mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-16 00:01:18 -04:00
Compare commits
No commits in common. "b48cf03717e99ff33d1e845c97e6f8c469cd2e6d" and "f5cd0d93192fc4d04966ba971c7aaaae7475926d" have entirely different histories.
b48cf03717
...
f5cd0d9319
@ -1145,7 +1145,7 @@ in this mapping or the filetype using heuristics.
|
|||||||
## Time (`time`)
|
## Time (`time`)
|
||||||
|
|
||||||
- `FORMAT`: Time format to display on UI. i.e. RFC1123 or 2006-01-02 15:04:05
|
- `FORMAT`: Time format to display on UI. i.e. RFC1123 or 2006-01-02 15:04:05
|
||||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia
|
||||||
|
|
||||||
## Task (`task`)
|
## Task (`task`)
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
@ -286,6 +288,102 @@ func (wr *nulSeparatedAttributeWriter) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type lineSeparatedAttributeWriter struct {
|
||||||
|
tmp []byte
|
||||||
|
attributes chan attributeTriple
|
||||||
|
closed chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wr *lineSeparatedAttributeWriter) Write(p []byte) (n int, err error) {
|
||||||
|
l := len(p)
|
||||||
|
|
||||||
|
nlIdx := bytes.IndexByte(p, '\n')
|
||||||
|
for nlIdx >= 0 {
|
||||||
|
wr.tmp = append(wr.tmp, p[:nlIdx]...)
|
||||||
|
|
||||||
|
if len(wr.tmp) == 0 {
|
||||||
|
// This should not happen
|
||||||
|
if len(p) > nlIdx+1 {
|
||||||
|
wr.tmp = wr.tmp[:0]
|
||||||
|
p = p[nlIdx+1:]
|
||||||
|
nlIdx = bytes.IndexByte(p, '\n')
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
working := attributeTriple{}
|
||||||
|
if wr.tmp[0] == '"' {
|
||||||
|
sb := new(strings.Builder)
|
||||||
|
remaining := string(wr.tmp[1:])
|
||||||
|
for len(remaining) > 0 {
|
||||||
|
rn, _, tail, err := strconv.UnquoteChar(remaining, '"')
|
||||||
|
if err != nil {
|
||||||
|
if len(remaining) > 2 && remaining[0] == '"' && remaining[1] == ':' && remaining[2] == ' ' {
|
||||||
|
working.Filename = sb.String()
|
||||||
|
wr.tmp = []byte(remaining[3:])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return l, fmt.Errorf("unexpected tail %s", remaining)
|
||||||
|
}
|
||||||
|
_, _ = sb.WriteRune(rn)
|
||||||
|
remaining = tail
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idx := bytes.IndexByte(wr.tmp, ':')
|
||||||
|
if idx < 0 {
|
||||||
|
return l, fmt.Errorf("unexpected input %s", string(wr.tmp))
|
||||||
|
}
|
||||||
|
working.Filename = string(wr.tmp[:idx])
|
||||||
|
if len(wr.tmp) < idx+2 {
|
||||||
|
return l, fmt.Errorf("unexpected input %s", string(wr.tmp))
|
||||||
|
}
|
||||||
|
wr.tmp = wr.tmp[idx+2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := bytes.IndexByte(wr.tmp, ':')
|
||||||
|
if idx < 0 {
|
||||||
|
return l, fmt.Errorf("unexpected input %s", string(wr.tmp))
|
||||||
|
}
|
||||||
|
|
||||||
|
working.Attribute = string(wr.tmp[:idx])
|
||||||
|
if len(wr.tmp) < idx+2 {
|
||||||
|
return l, fmt.Errorf("unexpected input %s", string(wr.tmp))
|
||||||
|
}
|
||||||
|
|
||||||
|
working.Value = string(wr.tmp[idx+2:])
|
||||||
|
|
||||||
|
wr.attributes <- working
|
||||||
|
wr.tmp = wr.tmp[:0]
|
||||||
|
if len(p) > nlIdx+1 {
|
||||||
|
p = p[nlIdx+1:]
|
||||||
|
nlIdx = bytes.IndexByte(p, '\n')
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wr.tmp = append(wr.tmp, p...)
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wr *lineSeparatedAttributeWriter) ReadAttribute() <-chan attributeTriple {
|
||||||
|
return wr.attributes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wr *lineSeparatedAttributeWriter) Close() error {
|
||||||
|
select {
|
||||||
|
case <-wr.closed:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
close(wr.attributes)
|
||||||
|
close(wr.closed)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Create a check attribute reader for the current repository and provided commit ID
|
// Create a check attribute reader for the current repository and provided commit ID
|
||||||
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) {
|
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) {
|
||||||
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
|
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
|
||||||
|
@ -95,3 +95,64 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
|||||||
Value: "unspecified",
|
Value: "unspecified",
|
||||||
}, attr)
|
}, attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_lineSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
|
||||||
|
wr := &lineSeparatedAttributeWriter{
|
||||||
|
attributes: make(chan attributeTriple, 5),
|
||||||
|
}
|
||||||
|
|
||||||
|
testStr := `".gitignore\"\n": linguist-vendored: unspecified
|
||||||
|
`
|
||||||
|
n, err := wr.Write([]byte(testStr))
|
||||||
|
|
||||||
|
assert.Equal(t, n, len(testStr))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case attr := <-wr.ReadAttribute():
|
||||||
|
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||||
|
assert.Equal(t, "linguist-vendored", attr.Attribute)
|
||||||
|
assert.Equal(t, "unspecified", attr.Value)
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
assert.Fail(t, "took too long to read an attribute from the list")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a second attribute again
|
||||||
|
n, err = wr.Write([]byte(testStr))
|
||||||
|
|
||||||
|
assert.Equal(t, n, len(testStr))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case attr := <-wr.ReadAttribute():
|
||||||
|
assert.Equal(t, ".gitignore\"\n", attr.Filename)
|
||||||
|
assert.Equal(t, "linguist-vendored", attr.Attribute)
|
||||||
|
assert.Equal(t, "unspecified", attr.Value)
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
assert.Fail(t, "took too long to read an attribute from the list")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a partial attribute
|
||||||
|
_, err = wr.Write([]byte("incomplete-file"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = wr.Write([]byte("name: "))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
select {
|
||||||
|
case <-wr.ReadAttribute():
|
||||||
|
assert.Fail(t, "There should not be an attribute ready to read")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
|
_, err = wr.Write([]byte("attribute: "))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
select {
|
||||||
|
case <-wr.ReadAttribute():
|
||||||
|
assert.Fail(t, "There should not be an attribute ready to read")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
|
_, err = wr.Write([]byte("value\n"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
attr := <-wr.ReadAttribute()
|
||||||
|
assert.Equal(t, "incomplete-filename", attr.Filename)
|
||||||
|
assert.Equal(t, "attribute", attr.Attribute)
|
||||||
|
assert.Equal(t, "value", attr.Value)
|
||||||
|
}
|
||||||
|
@ -289,3 +289,9 @@ func RenderRawString(ctx *markup.RenderContext, content string) (string, error)
|
|||||||
}
|
}
|
||||||
return buf.String(), nil
|
return buf.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMarkdownFile reports whether name looks like a Markdown file
|
||||||
|
// based on its extension.
|
||||||
|
func IsMarkdownFile(name string) bool {
|
||||||
|
return markup.IsMarkupFile(name, MarkupName)
|
||||||
|
}
|
||||||
|
@ -74,6 +74,28 @@ func TestRender_StandardLinks(t *testing.T) {
|
|||||||
`<p><a href="`+lnkWiki+`" rel="nofollow">WikiPage</a></p>`)
|
`<p><a href="`+lnkWiki+`" rel="nofollow">WikiPage</a></p>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMisc_IsMarkdownFile(t *testing.T) {
|
||||||
|
setting.Markdown.FileExtensions = []string{".md", ".markdown", ".mdown", ".mkd"}
|
||||||
|
trueTestCases := []string{
|
||||||
|
"test.md",
|
||||||
|
"wow.MARKDOWN",
|
||||||
|
"LOL.mDoWn",
|
||||||
|
}
|
||||||
|
falseTestCases := []string{
|
||||||
|
"test",
|
||||||
|
"abcdefg",
|
||||||
|
"abcdefghijklmnopqrstuvwxyz",
|
||||||
|
"test.md.test",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range trueTestCases {
|
||||||
|
assert.True(t, IsMarkdownFile(testCase))
|
||||||
|
}
|
||||||
|
for _, testCase := range falseTestCases {
|
||||||
|
assert.False(t, IsMarkdownFile(testCase))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRender_Images(t *testing.T) {
|
func TestRender_Images(t *testing.T) {
|
||||||
setting.AppURL = AppURL
|
setting.AppURL = AppURL
|
||||||
setting.AppSubURL = AppSubURL
|
setting.AppSubURL = AppSubURL
|
||||||
|
@ -230,10 +230,13 @@ func reqExploreSignIn() func(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reqBasicAuth() func(ctx *context.APIContext) {
|
func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
|
||||||
return func(ctx *context.APIContext) {
|
return func(ctx *context.APIContext) {
|
||||||
|
if ctx.IsSigned && setting.Service.EnableReverseProxyAuth && ctx.Data["AuthedMethod"].(string) == auth.ReverseProxyMethodName {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !ctx.Context.IsBasicAuth {
|
if !ctx.Context.IsBasicAuth {
|
||||||
ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required")
|
ctx.Error(http.StatusUnauthorized, "reqBasicOrRevProxyAuth", "auth required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.CheckForOTP()
|
ctx.CheckForOTP()
|
||||||
@ -595,6 +598,9 @@ func buildAuthGroup() *auth.Group {
|
|||||||
&auth.HTTPSign{},
|
&auth.HTTPSign{},
|
||||||
&auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API
|
&auth.Basic{}, // FIXME: this should be removed once we don't allow basic auth in API
|
||||||
)
|
)
|
||||||
|
if setting.Service.EnableReverseProxyAuth {
|
||||||
|
group.Add(&auth.ReverseProxy{})
|
||||||
|
}
|
||||||
specialAdd(group)
|
specialAdd(group)
|
||||||
|
|
||||||
return group
|
return group
|
||||||
@ -684,7 +690,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
|||||||
m.Combo("").Get(user.ListAccessTokens).
|
m.Combo("").Get(user.ListAccessTokens).
|
||||||
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
|
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
|
||||||
m.Combo("/{id}").Delete(user.DeleteAccessToken)
|
m.Combo("/{id}").Delete(user.DeleteAccessToken)
|
||||||
}, reqBasicAuth())
|
}, reqBasicOrRevProxyAuth())
|
||||||
}, context_service.UserAssignmentAPI())
|
}, context_service.UserAssignmentAPI())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user