* Populate URL field of API commits * fix orgmode_testtags/v1.21.12.1
| @@ -15,8 +15,8 @@ import ( | |||||
| "strings" | "strings" | ||||
| "code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
| "code.gitea.io/gitea/modules/log" | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
| "golang.org/x/net/html" | "golang.org/x/net/html" | ||||
| @@ -112,20 +112,6 @@ func cutoutVerbosePrefix(prefix string) string { | |||||
| return prefix | return prefix | ||||
| } | } | ||||
| // URLJoin joins url components, like path.Join, but preserving contents | |||||
| func URLJoin(base string, elems ...string) string { | |||||
| u, err := url.Parse(base) | |||||
| if err != nil { | |||||
| log.Error(4, "URLJoin: Invalid base URL %s", base) | |||||
| return "" | |||||
| } | |||||
| joinArgs := make([]string, 0, len(elems)+1) | |||||
| joinArgs = append(joinArgs, u.Path) | |||||
| joinArgs = append(joinArgs, elems...) | |||||
| u.Path = path.Join(joinArgs...) | |||||
| return u.String() | |||||
| } | |||||
| // RenderIssueIndexPatternOptions options for RenderIssueIndexPattern function | // RenderIssueIndexPatternOptions options for RenderIssueIndexPattern function | ||||
| type RenderIssueIndexPatternOptions struct { | type RenderIssueIndexPatternOptions struct { | ||||
| // url to which non-special formatting should be linked. If empty, | // url to which non-special formatting should be linked. If empty, | ||||
| @@ -177,7 +163,7 @@ func RenderIssueIndexPattern(rawBytes []byte, opts RenderIssueIndexPatternOption | |||||
| } | } | ||||
| if opts.Metas == nil { | if opts.Metas == nil { | ||||
| buf.WriteString(`<a href="`) | buf.WriteString(`<a href="`) | ||||
| buf.WriteString(URLJoin( | |||||
| buf.WriteString(util.URLJoin( | |||||
| opts.URLPrefix, "issues", string(remainder[startIndex+1:endIndex]))) | opts.URLPrefix, "issues", string(remainder[startIndex+1:endIndex]))) | ||||
| buf.WriteString(`">`) | buf.WriteString(`">`) | ||||
| buf.Write(remainder[startIndex:endIndex]) | buf.Write(remainder[startIndex:endIndex]) | ||||
| @@ -228,7 +214,7 @@ func renderFullSha1Pattern(rawBytes []byte, urlPrefix string) []byte { | |||||
| path := protocol + "://" + paths | path := protocol + "://" + paths | ||||
| author := string(m[3]) | author := string(m[3]) | ||||
| repoName := string(m[4]) | repoName := string(m[4]) | ||||
| path = URLJoin(path, author, repoName) | |||||
| path = util.URLJoin(path, author, repoName) | |||||
| ltype := "src" | ltype := "src" | ||||
| itemType := m[5] | itemType := m[5] | ||||
| if IsSameDomain(paths) { | if IsSameDomain(paths) { | ||||
| @@ -260,7 +246,7 @@ func renderFullSha1Pattern(rawBytes []byte, urlPrefix string) []byte { | |||||
| text += ")" | text += ")" | ||||
| } | } | ||||
| rawBytes = bytes.Replace(rawBytes, all, []byte(fmt.Sprintf( | rawBytes = bytes.Replace(rawBytes, all, []byte(fmt.Sprintf( | ||||
| `<a href="%s">%s</a>`, URLJoin(path, ltype, string(sha))+urlSuffix, text)), -1) | |||||
| `<a href="%s">%s</a>`, util.URLJoin(path, ltype, string(sha))+urlSuffix, text)), -1) | |||||
| } | } | ||||
| return rawBytes | return rawBytes | ||||
| } | } | ||||
| @@ -399,9 +385,9 @@ func RenderShortLinks(rawBytes []byte, urlPrefix string, noLink bool, isWikiMark | |||||
| urlPrefix = strings.Replace(urlPrefix, "/src/", "/raw/", 1) | urlPrefix = strings.Replace(urlPrefix, "/src/", "/raw/", 1) | ||||
| } | } | ||||
| if isWikiMarkdown { | if isWikiMarkdown { | ||||
| link = URLJoin("wiki", "raw", link) | |||||
| link = util.URLJoin("wiki", "raw", link) | |||||
| } | } | ||||
| link = URLJoin(urlPrefix, link) | |||||
| link = util.URLJoin(urlPrefix, link) | |||||
| } | } | ||||
| title := props["title"] | title := props["title"] | ||||
| if title == "" { | if title == "" { | ||||
| @@ -420,9 +406,9 @@ func RenderShortLinks(rawBytes []byte, urlPrefix string, noLink bool, isWikiMark | |||||
| name = fmt.Sprintf(`<img src="%s" %s title="%s" />`, link, alt, title) | name = fmt.Sprintf(`<img src="%s" %s title="%s" />`, link, alt, title) | ||||
| } else if !absoluteLink { | } else if !absoluteLink { | ||||
| if isWikiMarkdown { | if isWikiMarkdown { | ||||
| link = URLJoin("wiki", link) | |||||
| link = util.URLJoin("wiki", link) | |||||
| } | } | ||||
| link = URLJoin(urlPrefix, link) | |||||
| link = util.URLJoin(urlPrefix, link) | |||||
| } | } | ||||
| if noLink { | if noLink { | ||||
| rawBytes = bytes.Replace(rawBytes, orig, []byte(name), -1) | rawBytes = bytes.Replace(rawBytes, orig, []byte(name), -1) | ||||
| @@ -445,7 +431,7 @@ func RenderCrossReferenceIssueIndexPattern(rawBytes []byte, urlPrefix string, me | |||||
| repo := string(bytes.Split(m, []byte("#"))[0]) | repo := string(bytes.Split(m, []byte("#"))[0]) | ||||
| issue := string(bytes.Split(m, []byte("#"))[1]) | issue := string(bytes.Split(m, []byte("#"))[1]) | ||||
| link := fmt.Sprintf(`<a href="%s">%s</a>`, URLJoin(setting.AppURL, repo, "issues", issue), m) | |||||
| link := fmt.Sprintf(`<a href="%s">%s</a>`, util.URLJoin(setting.AppURL, repo, "issues", issue), m) | |||||
| rawBytes = bytes.Replace(rawBytes, m, []byte(link), 1) | rawBytes = bytes.Replace(rawBytes, m, []byte(link), 1) | ||||
| } | } | ||||
| return rawBytes | return rawBytes | ||||
| @@ -463,7 +449,7 @@ func renderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte { | |||||
| // Although unlikely, deadbeef and 1234567 are valid short forms of SHA1 hash | // Although unlikely, deadbeef and 1234567 are valid short forms of SHA1 hash | ||||
| // as used by git and github for linking and thus we have to do similar. | // as used by git and github for linking and thus we have to do similar. | ||||
| rawBytes = bytes.Replace(rawBytes, hash, []byte(fmt.Sprintf( | rawBytes = bytes.Replace(rawBytes, hash, []byte(fmt.Sprintf( | ||||
| `<a href="%s">%s</a>`, URLJoin(urlPrefix, "commit", string(hash)), base.ShortSha(string(hash)))), -1) | |||||
| `<a href="%s">%s</a>`, util.URLJoin(urlPrefix, "commit", string(hash)), base.ShortSha(string(hash)))), -1) | |||||
| } | } | ||||
| return rawBytes | return rawBytes | ||||
| } | } | ||||
| @@ -474,7 +460,7 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string, metas map[string]strin | |||||
| for _, m := range ms { | for _, m := range ms { | ||||
| m = m[bytes.Index(m, []byte("@")):] | m = m[bytes.Index(m, []byte("@")):] | ||||
| rawBytes = bytes.Replace(rawBytes, m, | rawBytes = bytes.Replace(rawBytes, m, | ||||
| []byte(fmt.Sprintf(`<a href="%s">%s</a>`, URLJoin(setting.AppURL, string(m[1:])), m)), -1) | |||||
| []byte(fmt.Sprintf(`<a href="%s">%s</a>`, util.URLJoin(setting.AppURL, string(m[1:])), m)), -1) | |||||
| } | } | ||||
| rawBytes = RenderFullIssuePattern(rawBytes) | rawBytes = RenderFullIssuePattern(rawBytes) | ||||
| @@ -13,6 +13,7 @@ import ( | |||||
| . "code.gitea.io/gitea/modules/markup" | . "code.gitea.io/gitea/modules/markup" | ||||
| _ "code.gitea.io/gitea/modules/markup/markdown" | _ "code.gitea.io/gitea/modules/markup/markdown" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
| ) | ) | ||||
| @@ -37,12 +38,12 @@ var alphanumericMetas = map[string]string{ | |||||
| // numericLink an HTML to a numeric-style issue | // numericLink an HTML to a numeric-style issue | ||||
| func numericIssueLink(baseURL string, index int) string { | func numericIssueLink(baseURL string, index int) string { | ||||
| return link(URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index)) | |||||
| return link(util.URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index)) | |||||
| } | } | ||||
| // alphanumLink an HTML link to an alphanumeric-style issue | // alphanumLink an HTML link to an alphanumeric-style issue | ||||
| func alphanumIssueLink(baseURL string, name string) string { | func alphanumIssueLink(baseURL string, name string) string { | ||||
| return link(URLJoin(baseURL, name), name) | |||||
| return link(util.URLJoin(baseURL, name), name) | |||||
| } | } | ||||
| // urlContentsLink an HTML link whose contents is the target URL | // urlContentsLink an HTML link whose contents is the target URL | ||||
| @@ -63,31 +64,6 @@ func testRenderIssueIndexPattern(t *testing.T, input, expected string, opts Rend | |||||
| assert.Equal(t, expected, actual) | assert.Equal(t, expected, actual) | ||||
| } | } | ||||
| func TestURLJoin(t *testing.T) { | |||||
| type test struct { | |||||
| Expected string | |||||
| Base string | |||||
| Elements []string | |||||
| } | |||||
| newTest := func(expected, base string, elements ...string) test { | |||||
| return test{Expected: expected, Base: base, Elements: elements} | |||||
| } | |||||
| for _, test := range []test{ | |||||
| newTest("https://try.gitea.io/a/b/c", | |||||
| "https://try.gitea.io", "a/b", "c"), | |||||
| newTest("https://try.gitea.io/a/b/c", | |||||
| "https://try.gitea.io/", "/a/b/", "/c/"), | |||||
| newTest("https://try.gitea.io/a/c", | |||||
| "https://try.gitea.io/", "/a/./b/", "../c/"), | |||||
| newTest("a/b/c", | |||||
| "a", "b/c/"), | |||||
| newTest("a/b/d", | |||||
| "a/", "b/c/", "/../d/"), | |||||
| } { | |||||
| assert.Equal(t, test.Expected, URLJoin(test.Base, test.Elements...)) | |||||
| } | |||||
| } | |||||
| func TestRender_IssueIndexPattern(t *testing.T) { | func TestRender_IssueIndexPattern(t *testing.T) { | ||||
| // numeric: render inputs without valid mentions | // numeric: render inputs without valid mentions | ||||
| test := func(s string) { | test := func(s string) { | ||||
| @@ -123,7 +99,7 @@ func TestRender_IssueIndexPattern2(t *testing.T) { | |||||
| test := func(s, expectedFmt string, indices ...int) { | test := func(s, expectedFmt string, indices ...int) { | ||||
| links := make([]interface{}, len(indices)) | links := make([]interface{}, len(indices)) | ||||
| for i, index := range indices { | for i, index := range indices { | ||||
| links[i] = numericIssueLink(URLJoin(setting.AppSubURL, "issues"), index) | |||||
| links[i] = numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), index) | |||||
| } | } | ||||
| expectedNil := fmt.Sprintf(expectedFmt, links...) | expectedNil := fmt.Sprintf(expectedFmt, links...) | ||||
| testRenderIssueIndexPattern(t, s, expectedNil, RenderIssueIndexPatternOptions{}) | testRenderIssueIndexPattern(t, s, expectedNil, RenderIssueIndexPatternOptions{}) | ||||
| @@ -228,8 +204,8 @@ func TestRender_AutoLink(t *testing.T) { | |||||
| } | } | ||||
| // render valid issue URLs | // render valid issue URLs | ||||
| test(URLJoin(setting.AppSubURL, "issues", "3333"), | |||||
| numericIssueLink(URLJoin(setting.AppSubURL, "issues"), 3333)) | |||||
| test(util.URLJoin(setting.AppSubURL, "issues", "3333"), | |||||
| numericIssueLink(util.URLJoin(setting.AppSubURL, "issues"), 3333)) | |||||
| // render external issue URLs | // render external issue URLs | ||||
| for _, externalURL := range []string{ | for _, externalURL := range []string{ | ||||
| @@ -240,7 +216,7 @@ func TestRender_AutoLink(t *testing.T) { | |||||
| } | } | ||||
| // render valid commit URLs | // render valid commit URLs | ||||
| tmp := URLJoin(AppSubURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae") | |||||
| tmp := util.URLJoin(AppSubURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae") | |||||
| test(tmp, "<a href=\""+tmp+"\">d8a994ef24</a>") | test(tmp, "<a href=\""+tmp+"\">d8a994ef24</a>") | ||||
| tmp += "#diff-2" | tmp += "#diff-2" | ||||
| test(tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>") | test(tmp, "<a href=\""+tmp+"\">d8a994ef24 (diff-2)</a>") | ||||
| @@ -260,8 +236,8 @@ func TestRender_Commits(t *testing.T) { | |||||
| } | } | ||||
| var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579" | var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579" | ||||
| var commit = URLJoin(AppSubURL, "commit", sha) | |||||
| var subtree = URLJoin(commit, "src") | |||||
| var commit = util.URLJoin(AppSubURL, "commit", sha) | |||||
| var subtree = util.URLJoin(commit, "src") | |||||
| var tree = strings.Replace(subtree, "/commit/", "/tree/", -1) | var tree = strings.Replace(subtree, "/commit/", "/tree/", -1) | ||||
| var src = strings.Replace(subtree, "/commit/", "/src/", -1) | var src = strings.Replace(subtree, "/commit/", "/src/", -1) | ||||
| @@ -284,10 +260,10 @@ func TestRender_CrossReferences(t *testing.T) { | |||||
| test( | test( | ||||
| "gogits/gogs#12345", | "gogits/gogs#12345", | ||||
| `<p><a href="`+URLJoin(AppURL, "gogits", "gogs", "issues", "12345")+`" rel="nofollow">gogits/gogs#12345</a></p>`) | |||||
| `<p><a href="`+util.URLJoin(AppURL, "gogits", "gogs", "issues", "12345")+`" rel="nofollow">gogits/gogs#12345</a></p>`) | |||||
| test( | test( | ||||
| "go-gitea/gitea#12345", | "go-gitea/gitea#12345", | ||||
| `<p><a href="`+URLJoin(AppURL, "go-gitea", "gitea", "issues", "12345")+`" rel="nofollow">go-gitea/gitea#12345</a></p>`) | |||||
| `<p><a href="`+util.URLJoin(AppURL, "go-gitea", "gitea", "issues", "12345")+`" rel="nofollow">go-gitea/gitea#12345</a></p>`) | |||||
| } | } | ||||
| func TestRender_FullIssueURLs(t *testing.T) { | func TestRender_FullIssueURLs(t *testing.T) { | ||||
| @@ -482,7 +458,7 @@ func TestMisc_IsSameDomain(t *testing.T) { | |||||
| setting.AppSubURL = AppSubURL | setting.AppSubURL = AppSubURL | ||||
| var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579" | var sha = "b6dd6210eaebc915fd5be5579c58cce4da2e2579" | ||||
| var commit = URLJoin(AppSubURL, "commit", sha) | |||||
| var commit = util.URLJoin(AppSubURL, "commit", sha) | |||||
| assert.True(t, IsSameDomain(commit)) | assert.True(t, IsSameDomain(commit)) | ||||
| assert.False(t, IsSameDomain("http://google.com/ncr")) | assert.False(t, IsSameDomain("http://google.com/ncr")) | ||||
| @@ -10,6 +10,7 @@ import ( | |||||
| "code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "github.com/russross/blackfriday" | "github.com/russross/blackfriday" | ||||
| ) | ) | ||||
| @@ -27,9 +28,9 @@ func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content [] | |||||
| if link[0] != '#' { | if link[0] != '#' { | ||||
| lnk := string(link) | lnk := string(link) | ||||
| if r.IsWiki { | if r.IsWiki { | ||||
| lnk = markup.URLJoin("wiki", lnk) | |||||
| lnk = util.URLJoin("wiki", lnk) | |||||
| } | } | ||||
| mLink := markup.URLJoin(r.URLPrefix, lnk) | |||||
| mLink := util.URLJoin(r.URLPrefix, lnk) | |||||
| link = []byte(mLink) | link = []byte(mLink) | ||||
| } | } | ||||
| } | } | ||||
| @@ -97,7 +98,7 @@ var ( | |||||
| func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { | func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { | ||||
| prefix := r.URLPrefix | prefix := r.URLPrefix | ||||
| if r.IsWiki { | if r.IsWiki { | ||||
| prefix = markup.URLJoin(prefix, "wiki", "src") | |||||
| prefix = util.URLJoin(prefix, "wiki", "src") | |||||
| } | } | ||||
| prefix = strings.Replace(prefix, "/src/", "/raw/", 1) | prefix = strings.Replace(prefix, "/src/", "/raw/", 1) | ||||
| if len(link) > 0 { | if len(link) > 0 { | ||||
| @@ -110,7 +111,7 @@ func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byt | |||||
| } | } | ||||
| } else { | } else { | ||||
| lnk := string(link) | lnk := string(link) | ||||
| lnk = markup.URLJoin(prefix, lnk) | |||||
| lnk = util.URLJoin(prefix, lnk) | |||||
| lnk = strings.Replace(lnk, " ", "+", -1) | lnk = strings.Replace(lnk, " ", "+", -1) | ||||
| link = []byte(lnk) | link = []byte(lnk) | ||||
| } | } | ||||
| @@ -11,6 +11,7 @@ import ( | |||||
| "code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
| . "code.gitea.io/gitea/modules/markup/markdown" | . "code.gitea.io/gitea/modules/markup/markdown" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
| ) | ) | ||||
| @@ -33,8 +34,8 @@ func TestRender_StandardLinks(t *testing.T) { | |||||
| googleRendered := `<p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p>` | googleRendered := `<p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p>` | ||||
| test("<https://google.com/>", googleRendered, googleRendered) | test("<https://google.com/>", googleRendered, googleRendered) | ||||
| lnk := markup.URLJoin(AppSubURL, "WikiPage") | |||||
| lnkWiki := markup.URLJoin(AppSubURL, "wiki", "WikiPage") | |||||
| lnk := util.URLJoin(AppSubURL, "WikiPage") | |||||
| lnkWiki := util.URLJoin(AppSubURL, "wiki", "WikiPage") | |||||
| test("[WikiPage](WikiPage)", | test("[WikiPage](WikiPage)", | ||||
| `<p><a href="`+lnk+`" rel="nofollow">WikiPage</a></p>`, | `<p><a href="`+lnk+`" rel="nofollow">WikiPage</a></p>`, | ||||
| `<p><a href="`+lnkWiki+`" rel="nofollow">WikiPage</a></p>`) | `<p><a href="`+lnkWiki+`" rel="nofollow">WikiPage</a></p>`) | ||||
| @@ -43,7 +44,7 @@ func TestRender_StandardLinks(t *testing.T) { | |||||
| func TestRender_ShortLinks(t *testing.T) { | func TestRender_ShortLinks(t *testing.T) { | ||||
| setting.AppURL = AppURL | setting.AppURL = AppURL | ||||
| setting.AppSubURL = AppSubURL | setting.AppSubURL = AppSubURL | ||||
| tree := markup.URLJoin(AppSubURL, "src", "master") | |||||
| tree := util.URLJoin(AppSubURL, "src", "master") | |||||
| test := func(input, expected, expectedWiki string) { | test := func(input, expected, expectedWiki string) { | ||||
| buffer := RenderString(input, tree, nil) | buffer := RenderString(input, tree, nil) | ||||
| @@ -52,13 +53,13 @@ func TestRender_ShortLinks(t *testing.T) { | |||||
| assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) | assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) | ||||
| } | } | ||||
| rawtree := markup.URLJoin(AppSubURL, "raw", "master") | |||||
| url := markup.URLJoin(tree, "Link") | |||||
| otherUrl := markup.URLJoin(tree, "OtherLink") | |||||
| imgurl := markup.URLJoin(rawtree, "Link.jpg") | |||||
| urlWiki := markup.URLJoin(AppSubURL, "wiki", "Link") | |||||
| otherUrlWiki := markup.URLJoin(AppSubURL, "wiki", "OtherLink") | |||||
| imgurlWiki := markup.URLJoin(AppSubURL, "wiki", "raw", "Link.jpg") | |||||
| rawtree := util.URLJoin(AppSubURL, "raw", "master") | |||||
| url := util.URLJoin(tree, "Link") | |||||
| otherUrl := util.URLJoin(tree, "OtherLink") | |||||
| imgurl := util.URLJoin(rawtree, "Link.jpg") | |||||
| urlWiki := util.URLJoin(AppSubURL, "wiki", "Link") | |||||
| otherUrlWiki := util.URLJoin(AppSubURL, "wiki", "OtherLink") | |||||
| imgurlWiki := util.URLJoin(AppSubURL, "wiki", "raw", "Link.jpg") | |||||
| favicon := "http://google.com/favicon.ico" | favicon := "http://google.com/favicon.ico" | ||||
| test( | test( | ||||
| @@ -136,7 +137,7 @@ func TestRender_Images(t *testing.T) { | |||||
| url := "../../.images/src/02/train.jpg" | url := "../../.images/src/02/train.jpg" | ||||
| title := "Train" | title := "Train" | ||||
| result := markup.URLJoin(AppSubURL, url) | |||||
| result := util.URLJoin(AppSubURL, url) | |||||
| test( | test( | ||||
| "", | "", | ||||
| @@ -259,7 +260,7 @@ Here are some links to the most important topics. You can find the full list of | |||||
| } | } | ||||
| func TestTotal_RenderWiki(t *testing.T) { | func TestTotal_RenderWiki(t *testing.T) { | ||||
| answers := testAnswers(markup.URLJoin(AppSubURL, "wiki/"), markup.URLJoin(AppSubURL, "wiki", "raw/")) | |||||
| answers := testAnswers(util.URLJoin(AppSubURL, "wiki/"), util.URLJoin(AppSubURL, "wiki", "raw/")) | |||||
| for i := 0; i < len(sameCases); i++ { | for i := 0; i < len(sameCases); i++ { | ||||
| line := RenderWiki([]byte(sameCases[i]), AppSubURL, nil) | line := RenderWiki([]byte(sameCases[i]), AppSubURL, nil) | ||||
| @@ -286,10 +287,10 @@ func TestTotal_RenderWiki(t *testing.T) { | |||||
| } | } | ||||
| func TestTotal_RenderString(t *testing.T) { | func TestTotal_RenderString(t *testing.T) { | ||||
| answers := testAnswers(markup.URLJoin(AppSubURL, "src", "master/"), markup.URLJoin(AppSubURL, "raw", "master/")) | |||||
| answers := testAnswers(util.URLJoin(AppSubURL, "src", "master/"), util.URLJoin(AppSubURL, "raw", "master/")) | |||||
| for i := 0; i < len(sameCases); i++ { | for i := 0; i < len(sameCases); i++ { | ||||
| line := RenderString(sameCases[i], markup.URLJoin(AppSubURL, "src", "master/"), nil) | |||||
| line := RenderString(sameCases[i], util.URLJoin(AppSubURL, "src", "master/"), nil) | |||||
| assert.Equal(t, answers[i], line) | assert.Equal(t, answers[i], line) | ||||
| } | } | ||||
| @@ -8,8 +8,8 @@ import ( | |||||
| "strings" | "strings" | ||||
| "testing" | "testing" | ||||
| "code.gitea.io/gitea/modules/markup" | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| "github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
| ) | ) | ||||
| @@ -30,7 +30,7 @@ func TestRender_StandardLinks(t *testing.T) { | |||||
| googleRendered := `<p><a href="https://google.com/" title="https://google.com/">https://google.com/</a></p>` | googleRendered := `<p><a href="https://google.com/" title="https://google.com/">https://google.com/</a></p>` | ||||
| test("[[https://google.com/]]", googleRendered) | test("[[https://google.com/]]", googleRendered) | ||||
| lnk := markup.URLJoin(AppSubURL, "WikiPage") | |||||
| lnk := util.URLJoin(AppSubURL, "WikiPage") | |||||
| test("[[WikiPage][WikiPage]]", | test("[[WikiPage][WikiPage]]", | ||||
| `<p><a href="`+lnk+`" title="WikiPage">WikiPage</a></p>`) | `<p><a href="`+lnk+`" title="WikiPage">WikiPage</a></p>`) | ||||
| } | } | ||||
| @@ -46,7 +46,7 @@ func TestRender_Images(t *testing.T) { | |||||
| url := "../../.images/src/02/train.jpg" | url := "../../.images/src/02/train.jpg" | ||||
| title := "Train" | title := "Train" | ||||
| result := markup.URLJoin(AppSubURL, url) | |||||
| result := util.URLJoin(AppSubURL, url) | |||||
| test( | test( | ||||
| "[[file:"+url+"]["+title+"]]", | "[[file:"+url+"]["+title+"]]", | ||||
| @@ -4,6 +4,13 @@ | |||||
| package util | package util | ||||
| import ( | |||||
| "net/url" | |||||
| "path" | |||||
| "code.gitea.io/gitea/modules/log" | |||||
| ) | |||||
| // OptionalBool a boolean that can be "null" | // OptionalBool a boolean that can be "null" | ||||
| type OptionalBool byte | type OptionalBool byte | ||||
| @@ -47,6 +54,20 @@ func Max(a, b int) int { | |||||
| return a | return a | ||||
| } | } | ||||
| // URLJoin joins url components, like path.Join, but preserving contents | |||||
| func URLJoin(base string, elems ...string) string { | |||||
| u, err := url.Parse(base) | |||||
| if err != nil { | |||||
| log.Error(4, "URLJoin: Invalid base URL %s", base) | |||||
| return "" | |||||
| } | |||||
| joinArgs := make([]string, 0, len(elems)+1) | |||||
| joinArgs = append(joinArgs, u.Path) | |||||
| joinArgs = append(joinArgs, elems...) | |||||
| u.Path = path.Join(joinArgs...) | |||||
| return u.String() | |||||
| } | |||||
| // Min min of two ints | // Min min of two ints | ||||
| func Min(a, b int) int { | func Min(a, b int) int { | ||||
| if a > b { | if a > b { | ||||
| @@ -0,0 +1,36 @@ | |||||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||||
| // Use of this source code is governed by a MIT-style | |||||
| // license that can be found in the LICENSE file. | |||||
| package util | |||||
| import ( | |||||
| "testing" | |||||
| "github.com/stretchr/testify/assert" | |||||
| ) | |||||
| func TestURLJoin(t *testing.T) { | |||||
| type test struct { | |||||
| Expected string | |||||
| Base string | |||||
| Elements []string | |||||
| } | |||||
| newTest := func(expected, base string, elements ...string) test { | |||||
| return test{Expected: expected, Base: base, Elements: elements} | |||||
| } | |||||
| for _, test := range []test{ | |||||
| newTest("https://try.gitea.io/a/b/c", | |||||
| "https://try.gitea.io", "a/b", "c"), | |||||
| newTest("https://try.gitea.io/a/b/c", | |||||
| "https://try.gitea.io/", "/a/b/", "/c/"), | |||||
| newTest("https://try.gitea.io/a/c", | |||||
| "https://try.gitea.io/", "/a/./b/", "../c/"), | |||||
| newTest("a/b/c", | |||||
| "a", "b/c/"), | |||||
| newTest("a/b/d", | |||||
| "a/", "b/c/", "/../d/"), | |||||
| } { | |||||
| assert.Equal(t, test.Expected, URLJoin(test.Base, test.Elements...)) | |||||
| } | |||||
| } | |||||
| @@ -13,6 +13,8 @@ import ( | |||||
| "code.gitea.io/git" | "code.gitea.io/git" | ||||
| "code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
| "code.gitea.io/gitea/modules/log" | |||||
| "code.gitea.io/gitea/modules/util" | |||||
| ) | ) | ||||
| // ToEmail convert models.EmailAddress to api.Email | // ToEmail convert models.EmailAddress to api.Email | ||||
| @@ -25,35 +27,40 @@ func ToEmail(email *models.EmailAddress) *api.Email { | |||||
| } | } | ||||
| // ToBranch convert a commit and branch to an api.Branch | // ToBranch convert a commit and branch to an api.Branch | ||||
| func ToBranch(b *models.Branch, c *git.Commit) *api.Branch { | |||||
| func ToBranch(repo *models.Repository, b *models.Branch, c *git.Commit) *api.Branch { | |||||
| return &api.Branch{ | return &api.Branch{ | ||||
| Name: b.Name, | Name: b.Name, | ||||
| Commit: ToCommit(c), | |||||
| Commit: ToCommit(repo, c), | |||||
| } | } | ||||
| } | } | ||||
| // ToCommit convert a commit to api.PayloadCommit | // ToCommit convert a commit to api.PayloadCommit | ||||
| func ToCommit(c *git.Commit) *api.PayloadCommit { | |||||
| func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit { | |||||
| authorUsername := "" | authorUsername := "" | ||||
| author, err := models.GetUserByEmail(c.Author.Email) | |||||
| if err == nil { | |||||
| if author, err := models.GetUserByEmail(c.Author.Email); err == nil { | |||||
| authorUsername = author.Name | authorUsername = author.Name | ||||
| } else if !models.IsErrUserNotExist(err) { | |||||
| log.Error(4, "GetUserByEmail: %v", err) | |||||
| } | } | ||||
| committerUsername := "" | committerUsername := "" | ||||
| committer, err := models.GetUserByEmail(c.Committer.Email) | |||||
| if err == nil { | |||||
| if committer, err := models.GetUserByEmail(c.Committer.Email); err == nil { | |||||
| committerUsername = committer.Name | committerUsername = committer.Name | ||||
| } else if !models.IsErrUserNotExist(err) { | |||||
| log.Error(4, "GetUserByEmail: %v", err) | |||||
| } | } | ||||
| verif := models.ParseCommitWithSignature(c) | verif := models.ParseCommitWithSignature(c) | ||||
| var signature, payload string | var signature, payload string | ||||
| if c.Signature != nil { | if c.Signature != nil { | ||||
| signature = c.Signature.Signature | signature = c.Signature.Signature | ||||
| payload = c.Signature.Payload | payload = c.Signature.Payload | ||||
| } | } | ||||
| return &api.PayloadCommit{ | return &api.PayloadCommit{ | ||||
| ID: c.ID.String(), | ID: c.ID.String(), | ||||
| Message: c.Message(), | Message: c.Message(), | ||||
| URL: "Not implemented", | |||||
| URL: util.URLJoin(repo.Link(), "commit", c.ID.String()), | |||||
| Author: &api.PayloadUser{ | Author: &api.PayloadUser{ | ||||
| Name: c.Author.Name, | Name: c.Author.Name, | ||||
| Email: c.Author.Email, | Email: c.Author.Email, | ||||
| @@ -8,9 +8,9 @@ import ( | |||||
| api "code.gitea.io/sdk/gitea" | api "code.gitea.io/sdk/gitea" | ||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/markup" | |||||
| "code.gitea.io/gitea/modules/markup/markdown" | "code.gitea.io/gitea/modules/markup/markdown" | ||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| ) | ) | ||||
| // Markdown render markdown document to HTML | // Markdown render markdown document to HTML | ||||
| @@ -45,7 +45,7 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { | |||||
| switch form.Mode { | switch form.Mode { | ||||
| case "gfm": | case "gfm": | ||||
| md := []byte(form.Text) | md := []byte(form.Text) | ||||
| context := markup.URLJoin(setting.AppURL, form.Context) | |||||
| context := util.URLJoin(setting.AppURL, form.Context) | |||||
| if form.Wiki { | if form.Wiki { | ||||
| ctx.Write([]byte(markdown.RenderWiki(md, context, nil))) | ctx.Write([]byte(markdown.RenderWiki(md, context, nil))) | ||||
| } else { | } else { | ||||
| @@ -9,8 +9,8 @@ import ( | |||||
| "testing" | "testing" | ||||
| "code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
| "code.gitea.io/gitea/modules/markup" | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| "code.gitea.io/gitea/modules/util" | |||||
| api "code.gitea.io/sdk/gitea" | api "code.gitea.io/sdk/gitea" | ||||
| "github.com/go-macaron/inject" | "github.com/go-macaron/inject" | ||||
| @@ -53,7 +53,7 @@ func TestAPI_RenderGFM(t *testing.T) { | |||||
| Context: Repo, | Context: Repo, | ||||
| Wiki: true, | Wiki: true, | ||||
| } | } | ||||
| requrl, _ := url.Parse(markup.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| req := &http.Request{ | req := &http.Request{ | ||||
| Method: "POST", | Method: "POST", | ||||
| URL: requrl, | URL: requrl, | ||||
| @@ -147,7 +147,7 @@ func TestAPI_RenderSimple(t *testing.T) { | |||||
| Text: "", | Text: "", | ||||
| Context: Repo, | Context: Repo, | ||||
| } | } | ||||
| requrl, _ := url.Parse(markup.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| req := &http.Request{ | req := &http.Request{ | ||||
| Method: "POST", | Method: "POST", | ||||
| URL: requrl, | URL: requrl, | ||||
| @@ -166,7 +166,7 @@ func TestAPI_RenderSimple(t *testing.T) { | |||||
| func TestAPI_RenderRaw(t *testing.T) { | func TestAPI_RenderRaw(t *testing.T) { | ||||
| setting.AppURL = AppURL | setting.AppURL = AppURL | ||||
| requrl, _ := url.Parse(markup.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown")) | |||||
| req := &http.Request{ | req := &http.Request{ | ||||
| Method: "POST", | Method: "POST", | ||||
| URL: requrl, | URL: requrl, | ||||
| @@ -61,7 +61,7 @@ func GetBranch(ctx *context.APIContext) { | |||||
| return | return | ||||
| } | } | ||||
| ctx.JSON(200, convert.ToBranch(branch, c)) | |||||
| ctx.JSON(200, convert.ToBranch(ctx.Repo.Repository, branch, c)) | |||||
| } | } | ||||
| // ListBranches list all the branches of a repository | // ListBranches list all the branches of a repository | ||||
| @@ -98,7 +98,7 @@ func ListBranches(ctx *context.APIContext) { | |||||
| ctx.Error(500, "GetCommit", err) | ctx.Error(500, "GetCommit", err) | ||||
| return | return | ||||
| } | } | ||||
| apiBranches[i] = convert.ToBranch(branches[i], c) | |||||
| apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c) | |||||
| } | } | ||||
| ctx.JSON(200, &apiBranches) | ctx.JSON(200, &apiBranches) | ||||