diff --git a/Makefile b/Makefile index 146abf5d08..8da85c7a81 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,25 @@ all: build include docker/Makefile +.PHONY: help +help: + @echo "Make Routines:" + @echo " - \"\" equivalent to \"build\"" + @echo " - build creates the entire project" + @echo " - clean delete integration files and build files but not css and js files" + @echo " - clean-all delete all generated files (integration test, build, css and js files)" + @echo " - css rebuild only css files" + @echo " - js rebuild only js files" + @echo " - generate run \"make css js\" and \"go generate\"" + @echo " - fmt format the code" + @echo " - generate-swagger generate the swagger spec from code comments" + @echo " - swagger-validate check if the swagger spec is valide" + @echo " - revive run code linter revive" + @echo " - misspell check if a word is written wrong" + @echo " - vet examines Go source code and reports suspicious constructs" + @echo " - test run unit test" + @echo " - test-sqlite run integration test for sqlite" + .PHONY: go-check go-check: $(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell go version | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?\s' | tr '.' ' ');)) diff --git a/go.mod b/go.mod index 5d22b82745..8af6890691 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( gitea.com/macaron/gzip v0.0.0-20191118033930-0c4c5566a0e5 gitea.com/macaron/i18n v0.0.0-20190822004228-474e714e2223 gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a - gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb + gitea.com/macaron/macaron v1.4.0 gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 github.com/PuerkitoBio/goquery v1.5.0 @@ -88,7 +88,7 @@ require ( github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect github.com/tstranex/u2f v1.0.0 github.com/unknwon/cae v0.0.0-20190822084630-55a0b64484a1 - github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e + github.com/unknwon/com v1.0.1 github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 github.com/urfave/cli v1.20.0 @@ -104,7 +104,7 @@ require ( gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df - gopkg.in/ini.v1 v1.48.0 + gopkg.in/ini.v1 v1.51.1 gopkg.in/ldap.v3 v3.0.2 gopkg.in/src-d/go-billy.v4 v4.3.2 gopkg.in/src-d/go-git.v4 v4.13.1 diff --git a/go.sum b/go.sum index 247630d47d..b945bb7edb 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a/go.mod h1:h6E4kLao1Y gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827/go.mod h1:/rvxMjIkOq4BM8uPUb+VHuU02ZfAO6R4+wD//tiCiRw= gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA= gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs= +gitea.com/macaron/macaron v1.4.0 h1:FY1QDGqyuUzs21K6ChkbYbRUfwL7v2aUrhNEJ0IgsAw= +gitea.com/macaron/macaron v1.4.0/go.mod h1:P7hfDbQjcW22lkYkXlxdRIfWOXxH2+K4EogN4Q0UlLY= gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 h1:mvkQGAlON1Z6Y8pqa/+FpYIskk54mazuECUfZK5oTg0= gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA= gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14mefLzGluqV7w2mGU3u+iZU+jCeWk= @@ -532,6 +534,8 @@ github.com/unknwon/cae v0.0.0-20190822084630-55a0b64484a1 h1:SpoCl3+Pta5/ubQyF+F github.com/unknwon/cae v0.0.0-20190822084630-55a0b64484a1/go.mod h1:QaSeRctcea9fK6piJpAMCCPKxzJ01+xFcr2k1m3WRPU= github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM= github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= +github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= +github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 h1:sRrkJEHtNoaSvyXMbRgofEOX4/3gMiraevQKJdIBhYE= github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6/go.mod h1:+5rDk6sDGpl3azws3O+f+GpFSyN9GVr0K8cvQLQM2ZQ= github.com/unknwon/paginater v0.0.0-20151104151617-7748a72e0141 h1:Z79lyIznnziKADUf0J7EP8Z4ZL7YJDiPuaazlfUBSy4= @@ -721,8 +725,8 @@ gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.44.2/go.mod h1:M3Cogqpuv0QCi3ExAY5V4uOt4qb/R3xZubo9m8lK5wg= gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.48.0 h1:URjZc+8ugRY5mL5uUeQH/a63JcHwdX9xZaWvmNWD7z8= -gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w= gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= diff --git a/models/repo_list.go b/models/repo_list.go index 34fac8b055..7b48834dba 100644 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -121,7 +121,8 @@ type SearchRepoOptions struct { StarredByID int64 Page int IsProfile bool - AllPublic bool // Include also all public repositories + AllPublic bool // Include also all public repositories of users and public organisations + AllLimited bool // Include also all public repositories of limited organisations PageSize int // Can be smaller than or equal to setting.ExplorePagingNum // None -> include collaborative AND non-collaborative // True -> include just collaborative @@ -228,7 +229,11 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { } if opts.AllPublic { - accessCond = accessCond.Or(builder.Eq{"is_private": false}) + accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})))) + } + + if opts.AllLimited { + accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})))) } cond = cond.And(accessCond) diff --git a/models/repo_list_test.go b/models/repo_list_test.go index a1eed18b83..07f84207e2 100644 --- a/models/repo_list_test.go +++ b/models/repo_list_test.go @@ -177,8 +177,8 @@ func TestSearchRepository(t *testing.T) { opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse}, count: 25}, {name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative", - opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true, Template: util.OptionalBoolFalse}, - count: 31}, + opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse}, + count: 30}, {name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName", opts: &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true}, count: 15}, diff --git a/models/repo_permission.go b/models/repo_permission.go index 782b195629..79d7dd012b 100644 --- a/models/repo_permission.go +++ b/models/repo_permission.go @@ -369,3 +369,23 @@ func hasAccess(e Engine, userID int64, repo *Repository) (bool, error) { func HasAccess(userID int64, repo *Repository) (bool, error) { return hasAccess(x, userID, repo) } + +// FilterOutRepoIdsWithoutUnitAccess filter out repos where user has no access to repositories +func FilterOutRepoIdsWithoutUnitAccess(u *User, repoIDs []int64, units ...UnitType) ([]int64, error) { + i := 0 + for _, rID := range repoIDs { + repo, err := GetRepositoryByID(rID) + if err != nil { + return nil, err + } + perm, err := GetUserRepoPermission(repo, u) + if err != nil { + return nil, err + } + if perm.CanReadAny(units...) { + repoIDs[i] = rID + i++ + } + } + return repoIDs[:i], nil +} diff --git a/models/user.go b/models/user.go index a8f2c6fd22..f2c0a1861e 100644 --- a/models/user.go +++ b/models/user.go @@ -638,19 +638,20 @@ func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) { func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) { var ids []int64 - sess := x.Table("repository"). + if err := x.Table("repository"). Cols("repository.id"). Join("INNER", "team_user", "repository.owner_id = team_user.org_id"). - Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true) - - if len(units) > 0 { - sess = sess.Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id") - sess = sess.In("team_unit.type", units) + Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true). + Where("team_user.uid = ?", u.ID). + GroupBy("repository.id").Find(&ids); err != nil { + return nil, err } - return ids, sess. - Where("team_user.uid = ?", u.ID). - GroupBy("repository.id").Find(&ids) + if len(units) > 0 { + return FilterOutRepoIdsWithoutUnitAccess(u, ids, units...) + } + + return ids, nil } // GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index fa3e3d8116..b9e783de97 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -10,6 +10,7 @@ link_account=Vincular conta register=Cadastrar website=Site version=Versão +powered_by=Desenvolvido por %s page=Página template=Template language=Idioma diff --git a/routers/home.go b/routers/home.go index d223054f4c..773e0f3d6b 100644 --- a/routers/home.go +++ b/routers/home.go @@ -142,6 +142,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { Keyword: keyword, OwnerID: opts.OwnerID, AllPublic: true, + AllLimited: true, TopicOnly: topicOnly, IncludeDescription: setting.UI.SearchRepoDescription, }) diff --git a/routers/repo/repo.go b/routers/repo/repo.go index d44812729f..d6d91f0843 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -180,6 +180,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { return } + var repo *models.Repository var err error if form.RepoTemplate > 0 { opts := models.GenerateRepoOptions{ @@ -209,14 +210,14 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { return } - repo, err := repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts) + repo, err = repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts) if err == nil { log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name) return } } else { - repo, err := repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ + repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ Name: form.RepoName, Description: form.Description, Gitignores: form.Gitignores, diff --git a/routers/user/home.go b/routers/user/home.go index f5e74b2406..512c60716d 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -188,9 +188,13 @@ func Milestones(ctx *context.Context) { ctx.ServerError("env.RepoIDs", err) return } + userRepoIDs, err = models.FilterOutRepoIdsWithoutUnitAccess(ctx.User, userRepoIDs, models.UnitTypeIssues, models.UnitTypePullRequests) + if err != nil { + ctx.ServerError("FilterOutRepoIdsWithoutUnitAccess", err) + return + } } else { - unitType := models.UnitTypeIssues - userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType) + userRepoIDs, err = ctxUser.GetAccessRepoIDs(models.UnitTypeIssues, models.UnitTypePullRequests) if err != nil { ctx.ServerError("ctxUser.GetAccessRepoIDs", err) return @@ -201,27 +205,30 @@ func Milestones(ctx *context.Context) { } var repoIDs []int64 - if issueReposQueryPattern.MatchString(reposQuery) { - // remove "[" and "]" from string - reposQuery = reposQuery[1 : len(reposQuery)-1] - //for each ID (delimiter ",") add to int to repoIDs - reposSet := false - for _, rID := range strings.Split(reposQuery, ",") { - // Ensure nonempty string entries - if rID != "" && rID != "0" { - reposSet = true - rIDint64, err := strconv.ParseInt(rID, 10, 64) - if err == nil && com.IsSliceContainsInt64(userRepoIDs, rIDint64) { - repoIDs = append(repoIDs, rIDint64) + if len(reposQuery) != 0 { + if issueReposQueryPattern.MatchString(reposQuery) { + // remove "[" and "]" from string + reposQuery = reposQuery[1 : len(reposQuery)-1] + //for each ID (delimiter ",") add to int to repoIDs + reposSet := false + for _, rID := range strings.Split(reposQuery, ",") { + // Ensure nonempty string entries + if rID != "" && rID != "0" { + reposSet = true + rIDint64, err := strconv.ParseInt(rID, 10, 64) + // If the repo id specified by query is not parseable or not accessible by user, just ignore it. + if err == nil && com.IsSliceContainsInt64(userRepoIDs, rIDint64) { + repoIDs = append(repoIDs, rIDint64) + } } } + if reposSet && len(repoIDs) == 0 { + // force an empty result + repoIDs = []int64{-1} + } + } else { + log.Warn("issueReposQueryPattern not match with query") } - if reposSet && len(repoIDs) == 0 { - // force an empty result - repoIDs = []int64{-1} - } - } else { - log.Error("issueReposQueryPattern not match with query") } if len(repoIDs) == 0 { @@ -256,26 +263,6 @@ func Milestones(ctx *context.Context) { } } showReposMap[rID] = repo - - // Check if user has access to given repository. - perm, err := models.GetUserRepoPermission(repo, ctxUser) - if err != nil { - ctx.ServerError("GetUserRepoPermission", fmt.Errorf("[%d]%v", rID, err)) - return - } - - if !perm.CanRead(models.UnitTypeIssues) { - if log.IsTrace() { - log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+ - "User in repo has Permissions: %-+v", - ctxUser, - models.UnitTypeIssues, - repo, - perm) - } - ctx.Status(404) - return - } } showRepos := models.RepositoryListOfMap(showReposMap) @@ -345,9 +332,11 @@ var issueReposQueryPattern = regexp.MustCompile(`^\[\d+(,\d+)*,?\]$`) // Issues render the user issues page func Issues(ctx *context.Context) { isPullList := ctx.Params(":type") == "pulls" + unitType := models.UnitTypeIssues if isPullList { ctx.Data["Title"] = ctx.Tr("pull_requests") ctx.Data["PageIsPulls"] = true + unitType = models.UnitTypePullRequests } else { ctx.Data["Title"] = ctx.Tr("issues") ctx.Data["PageIsIssues"] = true @@ -404,7 +393,7 @@ func Issues(ctx *context.Context) { } } } else { - log.Error("issueReposQueryPattern not match with query") + log.Warn("issueReposQueryPattern not match with query") } } @@ -424,11 +413,12 @@ func Issues(ctx *context.Context) { ctx.ServerError("env.RepoIDs", err) return } - } else { - unitType := models.UnitTypeIssues - if isPullList { - unitType = models.UnitTypePullRequests + userRepoIDs, err = models.FilterOutRepoIdsWithoutUnitAccess(ctx.User, userRepoIDs, unitType) + if err != nil { + ctx.ServerError("FilterOutRepoIdsWithoutUnitAccess", err) + return } + } else { userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType) if err != nil { ctx.ServerError("ctxUser.GetAccessRepoIDs", err) diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 9a9bb6b8d4..658494ac30 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -360,19 +360,21 @@
- {{.Poster.GetDisplayName}} -
- {{$.i18n.Tr "repo.issues.commented_at" .HashTag $createdSubStr | Safe}} -
-
-
- {{if .RenderedContent}} - {{.RenderedContent|Str2html}} - {{else}} - {{$.i18n.Tr "repo.issues.no_content"}} - {{end}} +
+ {{.Poster.GetDisplayName}} + +
+
+ {{if .RenderedContent}} + {{.RenderedContent|Str2html}} + {{else}} + {{$.i18n.Tr "repo.issues.no_content"}} + {{end}} +
+
{{.Content}}
-
{{.Content}}
diff --git a/vendor/gitea.com/macaron/macaron/go.mod b/vendor/gitea.com/macaron/macaron/go.mod index e256ae8f63..4741454ed4 100644 --- a/vendor/gitea.com/macaron/macaron/go.mod +++ b/vendor/gitea.com/macaron/macaron/go.mod @@ -3,9 +3,10 @@ module gitea.com/macaron/macaron go 1.11 require ( - gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 + gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a + github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 - github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e + github.com/unknwon/com v1.0.1 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 gopkg.in/ini.v1 v1.44.0 ) diff --git a/vendor/gitea.com/macaron/macaron/go.sum b/vendor/gitea.com/macaron/macaron/go.sum index 7dfc6ea74e..bd41a79152 100644 --- a/vendor/gitea.com/macaron/macaron/go.sum +++ b/vendor/gitea.com/macaron/macaron/go.sum @@ -1,19 +1,23 @@ -gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ= -gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM= +gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a h1:aOKEXkDTnh4euoH0so/THLXeHtQuqHmDPb1xEk6Ehok= +gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= +github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM= -github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= +github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= +github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/vendor/gitea.com/macaron/macaron/macaron.go b/vendor/gitea.com/macaron/macaron/macaron.go index 17b5783702..5326093dce 100644 --- a/vendor/gitea.com/macaron/macaron/macaron.go +++ b/vendor/gitea.com/macaron/macaron/macaron.go @@ -1,5 +1,3 @@ -// +build go1.3 - // Copyright 2014 The Macaron Authors // // Licensed under the Apache License, Version 2.0 (the "License"): you may @@ -283,6 +281,7 @@ var ( envLock sync.Mutex // Path of work directory. + // You must set this value yourself Root string // Flash applies to current request. @@ -310,12 +309,6 @@ func safeEnv() string { func init() { setENV(os.Getenv("MACARON_ENV")) - - var err error - Root, err = os.Getwd() - if err != nil { - panic("error getting work directory: " + err.Error()) - } } // SetConfig sets data sources for configuration. diff --git a/vendor/gopkg.in/ini.v1/.travis.yml b/vendor/gopkg.in/ini.v1/.travis.yml index 08682ef840..149b7249f6 100644 --- a/vendor/gopkg.in/ini.v1/.travis.yml +++ b/vendor/gopkg.in/ini.v1/.travis.yml @@ -8,6 +8,7 @@ go: - 1.10.x - 1.11.x - 1.12.x + - 1.13.x install: skip script: diff --git a/vendor/gopkg.in/ini.v1/README.md b/vendor/gopkg.in/ini.v1/README.md index 44e1fcddd8..3d6d3cfc07 100644 --- a/vendor/gopkg.in/ini.v1/README.md +++ b/vendor/gopkg.in/ini.v1/README.md @@ -1,5 +1,6 @@ -INI [![Build Status](https://travis-ci.org/go-ini/ini.svg?branch=master)](https://travis-ci.org/go-ini/ini) [![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg)](https://sourcegraph.com/github.com/go-ini/ini) -=== +# INI + +[![Build Status](https://img.shields.io/travis/go-ini/ini/master.svg?style=for-the-badge&logo=travis)](https://travis-ci.org/go-ini/ini) [![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-ini/ini) ![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200) diff --git a/vendor/gopkg.in/ini.v1/ini.go b/vendor/gopkg.in/ini.v1/ini.go index 9de6171c9b..428b71e34a 100644 --- a/vendor/gopkg.in/ini.v1/ini.go +++ b/vendor/gopkg.in/ini.v1/ini.go @@ -29,7 +29,7 @@ const ( // Maximum allowed depth when recursively substituing variable names. depthValues = 99 - version = "1.48.0" + version = "1.51.1" ) // Version returns current package version literal. @@ -111,8 +111,15 @@ type LoadOptions struct { KeyValueDelimiters string // PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes). PreserveSurroundedQuote bool + // DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values). + DebugFunc DebugFunc + // ReaderBufferSize is the buffer size of the reader in bytes. + ReaderBufferSize int } +// DebugFunc is the type of function called to log parse events. +type DebugFunc func(message string) + // LoadSources allows caller to apply customized options for loading from data source(s). func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) { sources := make([]dataSource, len(others)+1) diff --git a/vendor/gopkg.in/ini.v1/key.go b/vendor/gopkg.in/ini.v1/key.go index 62f9146990..3c197410fa 100644 --- a/vendor/gopkg.in/ini.v1/key.go +++ b/vendor/gopkg.in/ini.v1/key.go @@ -147,10 +147,15 @@ func (k *Key) transformValue(val string) string { noption := vr[2 : len(vr)-2] // Search in the same section. + // If not found or found the key itself, then search again in default section. nk, err := k.s.GetKey(noption) if err != nil || k == nk { - // Search again in default section. nk, _ = k.s.f.Section("").GetKey(noption) + if nk == nil { + // Stop when no results found in the default section, + // and returns the value as-is. + break + } } // Substitute by new value and take off leading '%(' and trailing ')s'. diff --git a/vendor/gopkg.in/ini.v1/parser.go b/vendor/gopkg.in/ini.v1/parser.go index 7c22a25c1a..53ab45c46f 100644 --- a/vendor/gopkg.in/ini.v1/parser.go +++ b/vendor/gopkg.in/ini.v1/parser.go @@ -25,7 +25,9 @@ import ( "unicode" ) -var pythonMultiline = regexp.MustCompile("^(\\s+)([^\n]+)") +const minReaderBufferSize = 4096 + +var pythonMultiline = regexp.MustCompile(`^([\t\f ]+)(.*)`) type parserOptions struct { IgnoreContinuation bool @@ -35,6 +37,8 @@ type parserOptions struct { UnescapeValueDoubleQuotes bool UnescapeValueCommentSymbols bool PreserveSurroundedQuote bool + DebugFunc DebugFunc + ReaderBufferSize int } type parser struct { @@ -46,9 +50,20 @@ type parser struct { comment *bytes.Buffer } +func (p *parser) debug(format string, args ...interface{}) { + if p.options.DebugFunc != nil { + p.options.DebugFunc(fmt.Sprintf(format, args...)) + } +} + func newParser(r io.Reader, opts parserOptions) *parser { + size := opts.ReaderBufferSize + if size < minReaderBufferSize { + size = minReaderBufferSize + } + return &parser{ - buf: bufio.NewReader(r), + buf: bufio.NewReaderSize(r, size), options: opts, count: 1, comment: &bytes.Buffer{}, @@ -285,33 +300,55 @@ func (p *parser) readPythonMultilines(line string, bufferSize int) (string, erro parserBufferPeekResult, _ := p.buf.Peek(bufferSize) peekBuffer := bytes.NewBuffer(parserBufferPeekResult) + indentSize := 0 for { peekData, peekErr := peekBuffer.ReadBytes('\n') if peekErr != nil { if peekErr == io.EOF { + p.debug("readPythonMultilines: io.EOF, peekData: %q, line: %q", string(peekData), line) return line, nil } + + p.debug("readPythonMultilines: failed to peek with error: %v", peekErr) return "", peekErr } + p.debug("readPythonMultilines: parsing %q", string(peekData)) + peekMatches := pythonMultiline.FindStringSubmatch(string(peekData)) + p.debug("readPythonMultilines: matched %d parts", len(peekMatches)) + for n, v := range peekMatches { + p.debug(" %d: %q", n, v) + } + + // Return if not a Python multiline value. if len(peekMatches) != 3 { + p.debug("readPythonMultilines: end of value, got: %q", line) return line, nil } - // NOTE: Return if not a python-ini multi-line value. - currentIdentSize := len(peekMatches[1]) - if currentIdentSize <= 0 { + // Determine indent size and line prefix. + currentIndentSize := len(peekMatches[1]) + if indentSize < 1 { + indentSize = currentIndentSize + p.debug("readPythonMultilines: indent size is %d", indentSize) + } + + // Make sure each line is indented at least as far as first line. + if currentIndentSize < indentSize { + p.debug("readPythonMultilines: end of value, current indent: %d, expected indent: %d, line: %q", currentIndentSize, indentSize, line) return line, nil } - // NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer. - _, err := p.readUntil('\n') + // Advance the parser reader (buffer) in-sync with the peek buffer. + _, err := p.buf.Discard(len(peekData)) if err != nil { + p.debug("readPythonMultilines: failed to skip to the end, returning error") return "", err } - line += fmt.Sprintf("\n%s", peekMatches[2]) + // Handle indented empty line. + line += "\n" + peekMatches[1][indentSize:] + peekMatches[2] } } @@ -325,6 +362,8 @@ func (f *File) parse(reader io.Reader) (err error) { UnescapeValueDoubleQuotes: f.options.UnescapeValueDoubleQuotes, UnescapeValueCommentSymbols: f.options.UnescapeValueCommentSymbols, PreserveSurroundedQuote: f.options.PreserveSurroundedQuote, + DebugFunc: f.options.DebugFunc, + ReaderBufferSize: f.options.ReaderBufferSize, }) if err = p.BOM(); err != nil { return fmt.Errorf("BOM: %v", err) @@ -348,8 +387,8 @@ func (f *File) parse(reader io.Reader) (err error) { // the size of the parser buffer is found. // TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`. parserBufferSize := 0 - // NOTE: Peek 1kb at a time. - currentPeekSize := 1024 + // NOTE: Peek 4kb at a time. + currentPeekSize := minReaderBufferSize if f.options.AllowPythonMultilineValues { for { diff --git a/vendor/gopkg.in/ini.v1/struct.go b/vendor/gopkg.in/ini.v1/struct.go index 2764534f31..d1cd2722fe 100644 --- a/vendor/gopkg.in/ini.v1/struct.go +++ b/vendor/gopkg.in/ini.v1/struct.go @@ -155,23 +155,45 @@ func wrapStrictError(err error, isStrict bool) error { // but it does not return error for failing parsing, // because we want to use default value that is already assigned to struct. func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error { - switch t.Kind() { + vt := t + isPtr := t.Kind() == reflect.Ptr + if isPtr { + vt = t.Elem() + } + switch vt.Kind() { case reflect.String: - if len(key.String()) == 0 { - return nil + stringVal := key.String() + if isPtr { + field.Set(reflect.ValueOf(&stringVal)) + } else if len(stringVal) > 0 { + field.SetString(key.String()) } - field.SetString(key.String()) case reflect.Bool: boolVal, err := key.Bool() if err != nil { return wrapStrictError(err, isStrict) } - field.SetBool(boolVal) + if isPtr { + field.Set(reflect.ValueOf(&boolVal)) + } else { + field.SetBool(boolVal) + } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - durationVal, err := key.Duration() - // Skip zero value - if err == nil && int64(durationVal) > 0 { - field.Set(reflect.ValueOf(durationVal)) + // ParseDuration will not return err for `0`, so check the type name + if vt.Name() == "Duration" { + durationVal, err := key.Duration() + if err != nil { + if intVal, err := key.Int64(); err == nil { + field.SetInt(intVal) + return nil + } + return wrapStrictError(err, isStrict) + } + if isPtr { + field.Set(reflect.ValueOf(&durationVal)) + } else if int64(durationVal) > 0 { + field.Set(reflect.ValueOf(durationVal)) + } return nil } @@ -179,13 +201,23 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri if err != nil { return wrapStrictError(err, isStrict) } - field.SetInt(intVal) + if isPtr { + pv := reflect.New(t.Elem()) + pv.Elem().SetInt(intVal) + field.Set(pv) + } else { + field.SetInt(intVal) + } // byte is an alias for uint8, so supporting uint8 breaks support for byte case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: durationVal, err := key.Duration() // Skip zero value if err == nil && uint64(durationVal) > 0 { - field.Set(reflect.ValueOf(durationVal)) + if isPtr { + field.Set(reflect.ValueOf(&durationVal)) + } else { + field.Set(reflect.ValueOf(durationVal)) + } return nil } @@ -193,33 +225,38 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri if err != nil { return wrapStrictError(err, isStrict) } - field.SetUint(uintVal) + if isPtr { + pv := reflect.New(t.Elem()) + pv.Elem().SetUint(uintVal) + field.Set(pv) + } else { + field.SetUint(uintVal) + } case reflect.Float32, reflect.Float64: floatVal, err := key.Float64() if err != nil { return wrapStrictError(err, isStrict) } - field.SetFloat(floatVal) + if isPtr { + pv := reflect.New(t.Elem()) + pv.Elem().SetFloat(floatVal) + field.Set(pv) + } else { + field.SetFloat(floatVal) + } case reflectTime: timeVal, err := key.Time() if err != nil { return wrapStrictError(err, isStrict) } - field.Set(reflect.ValueOf(timeVal)) + if isPtr { + field.Set(reflect.ValueOf(&timeVal)) + } else { + field.Set(reflect.ValueOf(timeVal)) + } case reflect.Slice: return setSliceWithProperType(key, field, delim, allowShadow, isStrict) - case reflect.Ptr: - switch t.Elem().Kind() { - case reflect.Bool: - boolVal, err := key.Bool() - if err != nil { - return wrapStrictError(err, isStrict) - } - field.Set(reflect.ValueOf(&boolVal)) - default: - return fmt.Errorf("unsupported type '%s'", t) - } default: return fmt.Errorf("unsupported type '%s'", t) } @@ -280,7 +317,6 @@ func (s *Section) mapTo(val reflect.Value, isStrict bool) error { continue } } - if key, err := s.GetKey(fieldName); err == nil { delim := parseDelim(tpField.Tag.Get("delim")) if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil { diff --git a/vendor/modules.txt b/vendor/modules.txt index e20a6bc410..5f2d44e691 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -20,7 +20,7 @@ gitea.com/macaron/gzip gitea.com/macaron/i18n # gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a gitea.com/macaron/inject -# gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb +# gitea.com/macaron/macaron v1.4.0 gitea.com/macaron/macaron # gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 gitea.com/macaron/session @@ -414,7 +414,7 @@ github.com/tstranex/u2f # github.com/unknwon/cae v0.0.0-20190822084630-55a0b64484a1 github.com/unknwon/cae github.com/unknwon/cae/zip -# github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e +# github.com/unknwon/com v1.0.1 github.com/unknwon/com # github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 github.com/unknwon/i18n @@ -547,7 +547,7 @@ gopkg.in/alexcesaro/quotedprintable.v3 gopkg.in/asn1-ber.v1 # gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 -# gopkg.in/ini.v1 v1.48.0 +# gopkg.in/ini.v1 v1.51.1 gopkg.in/ini.v1 # gopkg.in/ldap.v3 v3.0.2 gopkg.in/ldap.v3 diff --git a/web_src/js/index.js b/web_src/js/index.js index 3751c6d9e4..b8145fa439 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -2271,7 +2271,7 @@ function initTemplateSearch() { const checkTemplate = function () { const $templateUnits = $('#template_units'); const $nonTemplate = $('#non_template'); - if ($repoTemplate.val() !== '') { + if ($repoTemplate.val() !== '' && $repoTemplate.val() !== '0') { $templateUnits.show(); $nonTemplate.hide(); } else { diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 3da3ae6b99..5ed44c5881 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1178,3 +1178,9 @@ i.icon.centerlock { box-shadow: inset 0 0 0 1px #1678c2 !important; color: #1678c2 !important; } + +.ui.label > img { + width: auto !important; + vertical-align: middle; + height: 2.1666em !important; +} diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 6530bcf8e5..cd35b88f3b 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -850,6 +850,14 @@ box-shadow: 0 0 10px #8c8c8c; } + &:target > .content > .code-comment-content { + padding: 4px; + } + + &:target > .content > .code-comment-content > .text { + margin-bottom: 0; + } + .ui.form { .field:first-child { clear: none;