Populate URL field of API commits (#3546)

* Populate URL field of API commits

* fix orgmode_test
tokarchuk/v1.17
Ethan Koenig 7 years ago committed by Bo-Yi Wu
parent 7b297808ce
commit 7b104f0cd0
  1. 36
      modules/markup/html.go
  2. 48
      modules/markup/html_test.go
  3. 9
      modules/markup/markdown/markdown.go
  4. 29
      modules/markup/markdown/markdown_test.go
  5. 6
      modules/markup/orgmode/orgmode_test.go
  6. 21
      modules/util/util.go
  7. 36
      modules/util/util_test.go
  8. 23
      routers/api/v1/convert/convert.go
  9. 4
      routers/api/v1/misc/markdown.go
  10. 8
      routers/api/v1/misc/markdown_test.go
  11. 4
      routers/api/v1/repo/branch.go

@ -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"), test(util.URLJoin(setting.AppSubURL, "issues", "3333"),
numericIssueLink(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 commit = util.URLJoin(AppSubURL, "commit", sha)
var subtree = URLJoin(commit, "src") 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") lnk := util.URLJoin(AppSubURL, "WikiPage")
lnkWiki := markup.URLJoin(AppSubURL, "wiki", "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") rawtree := util.URLJoin(AppSubURL, "raw", "master")
url := markup.URLJoin(tree, "Link") url := util.URLJoin(tree, "Link")
otherUrl := markup.URLJoin(tree, "OtherLink") otherUrl := util.URLJoin(tree, "OtherLink")
imgurl := markup.URLJoin(rawtree, "Link.jpg") imgurl := util.URLJoin(rawtree, "Link.jpg")
urlWiki := markup.URLJoin(AppSubURL, "wiki", "Link") urlWiki := util.URLJoin(AppSubURL, "wiki", "Link")
otherUrlWiki := markup.URLJoin(AppSubURL, "wiki", "OtherLink") otherUrlWiki := util.URLJoin(AppSubURL, "wiki", "OtherLink")
imgurlWiki := markup.URLJoin(AppSubURL, "wiki", "raw", "Link.jpg") 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(
"!["+title+"]("+url+")", "!["+title+"]("+url+")",
@ -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 author, err := models.GetUserByEmail(c.Author.Email); err == nil {
if 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 committer, err := models.GetUserByEmail(c.Committer.Email); err == nil {
if 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)

Loading…
Cancel
Save