diff options
author | Anthony Wang | 2023-02-20 22:21:24 +0000 |
---|---|---|
committer | Anthony Wang | 2023-02-20 22:21:24 +0000 |
commit | dc20c2832871f6462990751ea802e14b02bf41b0 (patch) | |
tree | 71bfef0694e6c0f8284438c290521d7297f24eab /routers | |
parent | 07df0a6b1c97be4b03d23d5dfa047a108de36592 (diff) | |
parent | ef11d41639dd1e89676e395068ee453312560adb (diff) |
Merge remote-tracking branch 'origin/main' into forgejo-federation
Diffstat (limited to 'routers')
82 files changed, 436 insertions, 307 deletions
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 9f77367d6..0e3d8b7a0 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -286,9 +286,18 @@ func CommonRoutes(ctx gocontext.Context) *web.Route { }, reqPackageAccess(perm.AccessModeWrite)) r.Get("/symbols/{filename}/{guid:[0-9a-fA-F]{32}[fF]{8}}/{filename2}", nuget.DownloadSymbolFile) r.Get("/Packages(Id='{id:[^']+}',Version='{version:[^']+}')", nuget.RegistrationLeafV2) - r.Get("/Packages()", nuget.SearchServiceV2) - r.Get("/FindPackagesById()", nuget.EnumeratePackageVersionsV2) - r.Get("/Search()", nuget.SearchServiceV2) + r.Group("/Packages()", func() { + r.Get("", nuget.SearchServiceV2) + r.Get("/$count", nuget.SearchServiceV2Count) + }) + r.Group("/FindPackagesById()", func() { + r.Get("", nuget.EnumeratePackageVersionsV2) + r.Get("/$count", nuget.EnumeratePackageVersionsV2Count) + }) + r.Group("/Search()", func() { + r.Get("", nuget.SearchServiceV2) + r.Get("/$count", nuget.SearchServiceV2Count) + }) }, reqPackageAccess(perm.AccessModeRead)) }) r.Group("/npm", func() { diff --git a/routers/api/packages/container/manifest.go b/routers/api/packages/container/manifest.go index 6167d00f3..e36c6a851 100644 --- a/routers/api/packages/container/manifest.go +++ b/routers/api/packages/container/manifest.go @@ -17,6 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" packages_module "code.gitea.io/gitea/modules/packages" container_module "code.gitea.io/gitea/modules/packages/container" "code.gitea.io/gitea/modules/util" @@ -71,11 +72,9 @@ func processManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffe } if isImageManifestMediaType(mci.MediaType) { - d, err := processImageManifest(mci, buf) - return d, err + return processImageManifest(mci, buf) } else if isImageIndexMediaType(mci.MediaType) { - d, err := processImageManifestIndex(mci, buf) - return d, err + return processImageManifestIndex(mci, buf) } return "", errManifestInvalid } @@ -182,6 +181,10 @@ func processImageManifest(mci *manifestCreationInfo, buf *packages_module.Hashed return err } + if err := notifyPackageCreate(mci.Creator, pv); err != nil { + return err + } + manifestDigest = digest return nil @@ -271,6 +274,10 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H return err } + if err := notifyPackageCreate(mci.Creator, pv); err != nil { + return err + } + manifestDigest = digest return nil @@ -282,6 +289,17 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H return manifestDigest, nil } +func notifyPackageCreate(doer *user_model.User, pv *packages_model.PackageVersion) error { + pd, err := packages_model.GetPackageDescriptor(db.DefaultContext, pv) + if err != nil { + return err + } + + notification.NotifyPackageCreate(db.DefaultContext, doer, pd) + + return nil +} + func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, metadata *container_module.Metadata) (*packages_model.PackageVersion, error) { created := true p := &packages_model.Package{ diff --git a/routers/api/packages/nuget/nuget.go b/routers/api/packages/nuget/nuget.go index 6423db7d3..3418bf995 100644 --- a/routers/api/packages/nuget/nuget.go +++ b/routers/api/packages/nuget/nuget.go @@ -10,6 +10,7 @@ import ( "io" "net/http" "regexp" + "strconv" "strings" "code.gitea.io/gitea/models/db" @@ -94,8 +95,7 @@ func FeedCapabilityResource(ctx *context.Context) { var searchTermExtract = regexp.MustCompile(`'([^']+)'`) -// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs -func SearchServiceV2(ctx *context.Context) { +func getSearchTerm(ctx *context.Context) string { searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'") if searchTerm == "" { // $filter contains a query like: @@ -106,7 +106,11 @@ func SearchServiceV2(ctx *context.Context) { searchTerm = strings.TrimSpace(match[1]) } } + return searchTerm +} +// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs +func SearchServiceV2(ctx *context.Context) { skip, take := ctx.FormInt("skip"), ctx.FormInt("take") if skip == 0 { skip = ctx.FormInt("$skip") @@ -116,9 +120,11 @@ func SearchServiceV2(ctx *context.Context) { } pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ - OwnerID: ctx.Package.Owner.ID, - Type: packages_model.TypeNuGet, - Name: packages_model.SearchValue{Value: searchTerm}, + OwnerID: ctx.Package.Owner.ID, + Type: packages_model.TypeNuGet, + Name: packages_model.SearchValue{ + Value: getSearchTerm(ctx), + }, IsInternal: util.OptionalBoolFalse, Paginator: db.NewAbsoluteListOptions( skip, @@ -145,6 +151,24 @@ func SearchServiceV2(ctx *context.Context) { xmlResponse(ctx, http.StatusOK, resp) } +// http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351 +func SearchServiceV2Count(ctx *context.Context) { + count, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{ + OwnerID: ctx.Package.Owner.ID, + Type: packages_model.TypeNuGet, + Name: packages_model.SearchValue{ + Value: getSearchTerm(ctx), + }, + IsInternal: util.OptionalBoolFalse, + }) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + ctx.PlainText(http.StatusOK, strconv.FormatInt(count, 10)) +} + // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-for-packages func SearchServiceV3(ctx *context.Context) { pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ @@ -288,6 +312,25 @@ func EnumeratePackageVersionsV2(ctx *context.Context) { xmlResponse(ctx, http.StatusOK, resp) } +// http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html#_Toc453752351 +func EnumeratePackageVersionsV2Count(ctx *context.Context) { + count, err := packages_model.CountVersions(ctx, &packages_model.PackageSearchOptions{ + OwnerID: ctx.Package.Owner.ID, + Type: packages_model.TypeNuGet, + Name: packages_model.SearchValue{ + ExactMatch: true, + Value: strings.Trim(ctx.FormTrim("id"), "'"), + }, + IsInternal: util.OptionalBoolFalse, + }) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + ctx.PlainText(http.StatusOK, strconv.FormatInt(count, 10)) +} + // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource#enumerate-package-versions func EnumeratePackageVersionsV3(ctx *context.Context) { packageName := ctx.Params("id") diff --git a/routers/api/v1/activitypub/person.go b/routers/api/v1/activitypub/person.go index 5d27674fa..04ce74c28 100644 --- a/routers/api/v1/activitypub/person.go +++ b/routers/api/v1/activitypub/person.go @@ -59,7 +59,7 @@ func Person(ctx *context.APIContext) { person.Icon = ap.Image{ Type: ap.ImageType, MediaType: "image/png", - URL: ap.IRI(ctx.ContextUser.AvatarFullLinkWithSize(2048)), + URL: ap.IRI(ctx.ContextUser.AvatarFullLinkWithSize(ctx, 2048)), } person.Inbox = ap.IRI(iri + "/inbox") diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go index ff6624418..6d50a1267 100644 --- a/routers/api/v1/admin/org.go +++ b/routers/api/v1/admin/org.go @@ -74,7 +74,7 @@ func CreateOrg(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToOrganization(org)) + ctx.JSON(http.StatusCreated, convert.ToOrganization(ctx, org)) } // GetAllOrgs API for getting information of all the organizations @@ -114,7 +114,7 @@ func GetAllOrgs(ctx *context.APIContext) { } orgs := make([]*api.Organization, len(users)) for i := range users { - orgs[i] = convert.ToOrganization(organization.OrgFromUser(users[i])) + orgs[i] = convert.ToOrganization(ctx, organization.OrgFromUser(users[i])) } ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 6b48ce4a9..1fbdab3e5 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -15,11 +15,12 @@ import ( "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/user" @@ -120,6 +121,14 @@ func CreateUser(ctx *context.APIContext) { overwriteDefault.Visibility = &visibility } + // Update the user creation timestamp. This can only be done after the user + // record has been inserted into the database; the insert intself will always + // set the creation timestamp to "now". + if form.Created != nil { + u.CreatedUnix = timeutil.TimeStamp(form.Created.Unix()) + u.UpdatedUnix = u.CreatedUnix + } + if err := user_model.CreateUser(u, overwriteDefault); err != nil { if user_model.IsErrUserAlreadyExist(err) || user_model.IsErrEmailAlreadyUsed(err) || @@ -140,7 +149,7 @@ func CreateUser(ctx *context.APIContext) { if form.SendNotify { mailer.SendRegisterNotifyMail(u) } - ctx.JSON(http.StatusCreated, convert.ToUser(u, ctx.Doer)) + ctx.JSON(http.StatusCreated, convert.ToUser(ctx, u, ctx.Doer)) } // EditUser api for modifying a user's information @@ -280,7 +289,7 @@ func EditUser(ctx *context.APIContext) { } log.Trace("Account profile updated by admin (%s): %s", ctx.Doer.Name, ctx.ContextUser.Name) - ctx.JSON(http.StatusOK, convert.ToUser(ctx.ContextUser, ctx.Doer)) + ctx.JSON(http.StatusOK, convert.ToUser(ctx, ctx.ContextUser, ctx.Doer)) } // DeleteUser api for deleting a user @@ -441,7 +450,7 @@ func GetAllUsers(ctx *context.APIContext) { results := make([]*api.User, len(users)) for i := range users { - results[i] = convert.ToUser(users[i], ctx.Doer) + results[i] = convert.ToUser(ctx, users[i], ctx.Doer) } ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) diff --git a/routers/api/v1/org/label.go b/routers/api/v1/org/label.go index 5d0455cdd..938fe79df 100644 --- a/routers/api/v1/org/label.go +++ b/routers/api/v1/org/label.go @@ -94,6 +94,7 @@ func CreateLabel(ctx *context.APIContext) { label := &issues_model.Label{ Name: form.Name, + Exclusive: form.Exclusive, Color: form.Color, OrgID: ctx.Org.Organization.ID, Description: form.Description, @@ -195,6 +196,9 @@ func EditLabel(ctx *context.APIContext) { if form.Name != nil { label.Name = *form.Name } + if form.Exclusive != nil { + label.Exclusive = *form.Exclusive + } if form.Color != nil { label.Color = strings.Trim(*form.Color, " ") if len(label.Color) == 6 { diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index 33c994497..e4afd7f3c 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -39,7 +39,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) { apiMembers := make([]*api.User, len(members)) for i, member := range members { - apiMembers[i] = convert.ToUser(member, ctx.Doer) + apiMembers[i] = convert.ToUser(ctx, member, ctx.Doer) } ctx.SetTotalCountHeader(count) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index a1b071d48..75420dcc4 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -42,7 +42,7 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { apiOrgs := make([]*api.Organization, len(orgs)) for i := range orgs { - apiOrgs[i] = convert.ToOrganization(orgs[i]) + apiOrgs[i] = convert.ToOrganization(ctx, orgs[i]) } ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) @@ -211,7 +211,7 @@ func GetAll(ctx *context.APIContext) { } orgs := make([]*api.Organization, len(publicOrgs)) for i := range publicOrgs { - orgs[i] = convert.ToOrganization(organization.OrgFromUser(publicOrgs[i])) + orgs[i] = convert.ToOrganization(ctx, organization.OrgFromUser(publicOrgs[i])) } ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) @@ -274,7 +274,7 @@ func Create(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToOrganization(org)) + ctx.JSON(http.StatusCreated, convert.ToOrganization(ctx, org)) } // Get get an organization @@ -298,7 +298,7 @@ func Get(ctx *context.APIContext) { ctx.NotFound("HasOrgOrUserVisible", nil) return } - ctx.JSON(http.StatusOK, convert.ToOrganization(ctx.Org.Organization)) + ctx.JSON(http.StatusOK, convert.ToOrganization(ctx, ctx.Org.Organization)) } // Edit change an organization's information @@ -344,7 +344,7 @@ func Edit(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToOrganization(org)) + ctx.JSON(http.StatusOK, convert.ToOrganization(ctx, org)) } // Delete an organization diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 8f87e8276..0c6926759 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -58,7 +58,7 @@ func ListTeams(ctx *context.APIContext) { return } - apiTeams, err := convert.ToTeams(teams, false) + apiTeams, err := convert.ToTeams(ctx, teams, false) if err != nil { ctx.Error(http.StatusInternalServerError, "ConvertToTeams", err) return @@ -97,7 +97,7 @@ func ListUserTeams(ctx *context.APIContext) { return } - apiTeams, err := convert.ToTeams(teams, true) + apiTeams, err := convert.ToTeams(ctx, teams, true) if err != nil { ctx.Error(http.StatusInternalServerError, "ConvertToTeams", err) return @@ -125,7 +125,7 @@ func GetTeam(ctx *context.APIContext) { // "200": // "$ref": "#/responses/Team" - apiTeam, err := convert.ToTeam(ctx.Org.Team) + apiTeam, err := convert.ToTeam(ctx, ctx.Org.Team) if err != nil { ctx.InternalServerError(err) return @@ -223,7 +223,7 @@ func CreateTeam(ctx *context.APIContext) { return } - apiTeam, err := convert.ToTeam(team) + apiTeam, err := convert.ToTeam(ctx, team) if err != nil { ctx.InternalServerError(err) return @@ -256,7 +256,7 @@ func EditTeam(ctx *context.APIContext) { form := web.GetForm(ctx).(*api.EditTeamOption) team := ctx.Org.Team - if err := team.GetUnits(); err != nil { + if err := team.LoadUnits(ctx); err != nil { ctx.InternalServerError(err) return } @@ -306,7 +306,7 @@ func EditTeam(ctx *context.APIContext) { return } - apiTeam, err := convert.ToTeam(team) + apiTeam, err := convert.ToTeam(ctx, team) if err != nil { ctx.InternalServerError(err) return @@ -383,7 +383,7 @@ func GetTeamMembers(ctx *context.APIContext) { members := make([]*api.User, len(teamMembers)) for i, member := range teamMembers { - members[i] = convert.ToUser(member, ctx.Doer) + members[i] = convert.ToUser(ctx, member, ctx.Doer) } ctx.SetTotalCountHeader(int64(ctx.Org.Team.NumMembers)) @@ -428,7 +428,7 @@ func GetTeamMember(ctx *context.APIContext) { ctx.NotFound() return } - ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.Doer)) + ctx.JSON(http.StatusOK, convert.ToUser(ctx, u, ctx.Doer)) } // AddTeamMember api for add a member to a team @@ -779,7 +779,7 @@ func SearchTeam(ctx *context.APIContext) { return } - apiTeams, err := convert.ToTeams(teams, false) + apiTeams, err := convert.ToTeams(ctx, teams, false) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index eacec6a60..8acaeaffb 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -76,7 +76,7 @@ func GetBranch(ctx *context.APIContext) { return } - br, err := convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) + br, err := convert.ToBranch(ctx, ctx.Repo.Repository, branch, c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return @@ -212,7 +212,7 @@ func CreateBranch(ctx *context.APIContext) { return } - br, err := convert.ToBranch(ctx.Repo.Repository, branch, commit, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) + br, err := convert.ToBranch(ctx, ctx.Repo.Repository, branch, commit, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return @@ -284,7 +284,7 @@ func ListBranches(ctx *context.APIContext) { } branchProtection := rules.GetFirstMatched(branches[i].Name) - apiBranch, err := convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) + apiBranch, err := convert.ToBranch(ctx, ctx.Repo.Repository, branches[i], c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin()) if err != nil { ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err) return diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 293778420..942d4c799 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -65,7 +65,7 @@ func ListCollaborators(ctx *context.APIContext) { users := make([]*api.User, len(collaborators)) for i, collaborator := range collaborators { - users[i] = convert.ToUser(collaborator.User, ctx.Doer) + users[i] = convert.ToUser(ctx, collaborator.User, ctx.Doer) } ctx.SetTotalCountHeader(count) @@ -287,7 +287,7 @@ func GetRepoPermissions(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToUserAndPermission(collaborator, ctx.ContextUser, permission.AccessMode)) + ctx.JSON(http.StatusOK, convert.ToUserAndPermission(ctx, collaborator, ctx.ContextUser, permission.AccessMode)) } // GetReviewers return all users that can be requested to review in this repo @@ -317,7 +317,7 @@ func GetReviewers(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) return } - ctx.JSON(http.StatusOK, convert.ToUsers(ctx.Doer, reviewers)) + ctx.JSON(http.StatusOK, convert.ToUsers(ctx, ctx.Doer, reviewers)) } // GetAssignees return all users that have write access and can be assigned to issues @@ -347,5 +347,5 @@ func GetAssignees(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) return } - ctx.JSON(http.StatusOK, convert.ToUsers(ctx.Doer, assignees)) + ctx.JSON(http.StatusOK, convert.ToUsers(ctx, ctx.Doer, assignees)) } diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index 68a92ca2a..22b013e7d 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -69,7 +69,7 @@ func getCommit(ctx *context.APIContext, identifier string) { return } - json, err := convert.ToCommit(ctx.Repo.Repository, ctx.Repo.GitRepo, commit, nil, true) + json, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, nil, true) if err != nil { ctx.Error(http.StatusInternalServerError, "toCommit", err) return @@ -217,7 +217,7 @@ func GetAllCommits(ctx *context.APIContext) { for i, commit := range commits { // Create json struct - apiCommits[i], err = convert.ToCommit(ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, stat) + apiCommits[i], err = convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, commit, userCache, stat) if err != nil { ctx.Error(http.StatusInternalServerError, "toCommit", err) return diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go index 100a28d7f..fd54d1f74 100644 --- a/routers/api/v1/repo/hook.go +++ b/routers/api/v1/repo/hook.go @@ -174,7 +174,7 @@ func TestHook(ctx *context.APIContext) { return } - commit := convert.ToPayloadCommit(ctx.Repo.Repository, ctx.Repo.Commit) + commit := convert.ToPayloadCommit(ctx, ctx.Repo.Repository, ctx.Repo.Commit) commitID := ctx.Repo.Commit.ID.String() if err := webhook_service.PrepareWebhook(ctx, hook, webhook_module.HookEventPush, &api.PushPayload{ @@ -186,8 +186,8 @@ func TestHook(ctx *context.APIContext) { TotalCommits: 1, HeadCommit: commit, Repo: convert.ToRepo(ctx, ctx.Repo.Repository, perm.AccessModeNone), - Pusher: convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone), - Sender: convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone), + Pusher: convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone), + Sender: convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone), }); err != nil { ctx.Error(http.StatusInternalServerError, "PrepareWebhook: ", err) return diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 40c92998d..3d14343d4 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -103,7 +103,7 @@ func ListIssueComments(ctx *context.APIContext) { apiComments := make([]*api.Comment, len(comments)) for i, comment := range comments { comment.Issue = issue - apiComments[i] = convert.ToComment(comments[i]) + apiComments[i] = convert.ToComment(ctx, comments[i]) } ctx.SetTotalCountHeader(totalCount) @@ -308,7 +308,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { return } for i := range comments { - apiComments[i] = convert.ToComment(comments[i]) + apiComments[i] = convert.ToComment(ctx, comments[i]) } ctx.SetTotalCountHeader(totalCount) @@ -368,7 +368,7 @@ func CreateIssueComment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusCreated, convert.ToComment(comment)) + ctx.JSON(http.StatusCreated, convert.ToComment(ctx, comment)) } // GetIssueComment Get a comment by ID @@ -436,7 +436,7 @@ func GetIssueComment(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToComment(comment)) + ctx.JSON(http.StatusOK, convert.ToComment(ctx, comment)) } // EditIssueComment modify a comment of an issue @@ -561,7 +561,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) return } - ctx.JSON(http.StatusOK, convert.ToComment(comment)) + ctx.JSON(http.StatusOK, convert.ToComment(ctx, comment)) } // DeleteIssueComment delete a comment from an issue diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index 1b998a535..921f6e53f 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -80,7 +80,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) { var result []api.Reaction for _, r := range reactions { result = append(result, api.Reaction{ - User: convert.ToUser(r.User, ctx.Doer), + User: convert.ToUser(ctx, r.User, ctx.Doer), Reaction: r.Type, Created: r.CreatedUnix.AsTime(), }) @@ -202,7 +202,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp ctx.Error(http.StatusForbidden, err.Error(), err) } else if issues_model.IsErrReactionAlreadyExist(err) { ctx.JSON(http.StatusOK, api.Reaction{ - User: convert.ToUser(ctx.Doer, ctx.Doer), + User: convert.ToUser(ctx, ctx.Doer, ctx.Doer), Reaction: reaction.Type, Created: reaction.CreatedUnix.AsTime(), }) @@ -213,7 +213,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp } ctx.JSON(http.StatusCreated, api.Reaction{ - User: convert.ToUser(ctx.Doer, ctx.Doer), + User: convert.ToUser(ctx, ctx.Doer, ctx.Doer), Reaction: reaction.Type, Created: reaction.CreatedUnix.AsTime(), }) @@ -298,7 +298,7 @@ func GetIssueReactions(ctx *context.APIContext) { var result []api.Reaction for _, r := range reactions { result = append(result, api.Reaction{ - User: convert.ToUser(r.User, ctx.Doer), + User: convert.ToUser(ctx, r.User, ctx.Doer), Reaction: r.Type, Created: r.CreatedUnix.AsTime(), }) @@ -412,7 +412,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i ctx.Error(http.StatusForbidden, err.Error(), err) } else if issues_model.IsErrReactionAlreadyExist(err) { ctx.JSON(http.StatusOK, api.Reaction{ - User: convert.ToUser(ctx.Doer, ctx.Doer), + User: convert.ToUser(ctx, ctx.Doer, ctx.Doer), Reaction: reaction.Type, Created: reaction.CreatedUnix.AsTime(), }) @@ -423,7 +423,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i } ctx.JSON(http.StatusCreated, api.Reaction{ - User: convert.ToUser(ctx.Doer, ctx.Doer), + User: convert.ToUser(ctx, ctx.Doer, ctx.Doer), Reaction: reaction.Type, Created: reaction.CreatedUnix.AsTime(), }) diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go index 6d22c8265..107119eb0 100644 --- a/routers/api/v1/repo/issue_subscription.go +++ b/routers/api/v1/repo/issue_subscription.go @@ -280,7 +280,7 @@ func GetIssueSubscribers(ctx *context.APIContext) { } apiUsers := make([]*api.User, 0, len(users)) for _, v := range users { - apiUsers = append(apiUsers, convert.ToUser(v, ctx.Doer)) + apiUsers = append(apiUsers, convert.ToUser(ctx, v, ctx.Doer)) } count, err := issues_model.CountIssueWatchers(ctx, issue.ID) diff --git a/routers/api/v1/repo/label.go b/routers/api/v1/repo/label.go index 411c0274e..a06d26e83 100644 --- a/routers/api/v1/repo/label.go +++ b/routers/api/v1/repo/label.go @@ -156,6 +156,7 @@ func CreateLabel(ctx *context.APIContext) { label := &issues_model.Label{ Name: form.Name, + Exclusive: form.Exclusive, Color: form.Color, RepoID: ctx.Repo.Repository.ID, Description: form.Description, @@ -218,6 +219,9 @@ func EditLabel(ctx *context.APIContext) { if form.Name != nil { label.Name = *form.Name } + if form.Exclusive != nil { + label.Exclusive = *form.Exclusive + } if form.Color != nil { label.Color = strings.Trim(*form.Color, " ") if len(label.Color) == 6 { diff --git a/routers/api/v1/repo/main_test.go b/routers/api/v1/repo/main_test.go index 543fb922d..c7466c493 100644 --- a/routers/api/v1/repo/main_test.go +++ b/routers/api/v1/repo/main_test.go @@ -13,8 +13,8 @@ import ( ) func TestMain(m *testing.M) { - setting.LoadForTest() - setting.NewQueueService() + setting.InitProviderAndLoadCommonSettingsForTest() + setting.LoadQueueSettings() unittest.MainTest(m, &unittest.TestOptions{ GiteaRootPath: filepath.Join("..", "..", "..", ".."), SetUp: webhook_service.Init, diff --git a/routers/api/v1/repo/notes.go b/routers/api/v1/repo/notes.go index 8eaa503ff..2d1f3291f 100644 --- a/routers/api/v1/repo/notes.go +++ b/routers/api/v1/repo/notes.go @@ -68,7 +68,7 @@ func getNote(ctx *context.APIContext, identifier string) { return } - cmt, err := convert.ToCommit(ctx.Repo.Repository, ctx.Repo.GitRepo, note.Commit, nil, true) + cmt, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, note.Commit, nil, true) if err != nil { ctx.Error(http.StatusInternalServerError, "ToCommit", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 8164b3869..7005725cf 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -1311,7 +1311,7 @@ func GetPullRequestCommits(ctx *context.APIContext) { apiCommits := make([]*api.Commit, 0, end-start) for i := start; i < end; i++ { - apiCommit, err := convert.ToCommit(ctx.Repo.Repository, baseGitRepo, commits[i], userCache, true) + apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, baseGitRepo, commits[i], userCache, true) if err != nil { ctx.ServerError("toCommit", err) return diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 96dc1fc2d..f6acaa780 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -673,7 +673,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions for _, r := range opts.Reviewers { var reviewer *user_model.User if strings.Contains(r, "@") { - reviewer, err = user_model.GetUserByEmail(r) + reviewer, err = user_model.GetUserByEmail(ctx, r) } else { reviewer, err = user_model.GetUserByName(ctx, r) } diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go index c01e66150..e9693dd05 100644 --- a/routers/api/v1/repo/release.go +++ b/routers/api/v1/repo/release.go @@ -64,7 +64,7 @@ func GetRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(release)) + ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) } // GetLatestRelease gets the most recent non-prerelease, non-draft release of a repository, sorted by created_at @@ -105,7 +105,7 @@ func GetLatestRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(release)) + ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) } // ListReleases list a repository's releases @@ -174,7 +174,7 @@ func ListReleases(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - rels[i] = convert.ToRelease(release) + rels[i] = convert.ToRelease(ctx, release) } filteredCount, err := repo_model.CountReleasesByRepoID(ctx.Repo.Repository.ID, opts) @@ -272,7 +272,7 @@ func CreateRelease(ctx *context.APIContext) { return } } - ctx.JSON(http.StatusCreated, convert.ToRelease(rel)) + ctx.JSON(http.StatusCreated, convert.ToRelease(ctx, rel)) } // EditRelease edit a release @@ -357,7 +357,7 @@ func EditRelease(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(rel)) + ctx.JSON(http.StatusOK, convert.ToRelease(ctx, rel)) } // DeleteRelease delete a release from a repository diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index 5aaea693c..597578aac 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -117,7 +117,7 @@ func ListReleaseAttachments(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(release).Attachments) + ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release).Attachments) } // CreateReleaseAttachment creates an attachment and saves the given file diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go index 7cc846fdc..051ee8f22 100644 --- a/routers/api/v1/repo/release_tags.go +++ b/routers/api/v1/repo/release_tags.go @@ -63,7 +63,7 @@ func GetReleaseByTag(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) return } - ctx.JSON(http.StatusOK, convert.ToRelease(release)) + ctx.JSON(http.StatusOK, convert.ToRelease(ctx, release)) } // DeleteReleaseByTag delete a release from a repository by tag name diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 1426d1dbc..0395198e2 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -201,7 +201,7 @@ func Search(ctx *context.APIContext) { results := make([]*api.Repository, len(repos)) for i, repo := range repos { - if err = repo.GetOwner(ctx); err != nil { + if err = repo.LoadOwner(ctx); err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false, Error: err.Error(), @@ -863,6 +863,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { AllowRebaseUpdate: true, DefaultDeleteBranchAfterMerge: false, DefaultMergeStyle: repo_model.MergeStyleMerge, + DefaultAllowMaintainerEdit: false, } } else { config = unit.PullRequestsConfig() @@ -898,6 +899,9 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if opts.DefaultMergeStyle != nil { config.DefaultMergeStyle = repo_model.MergeStyle(*opts.DefaultMergeStyle) } + if opts.DefaultAllowMaintainerEdit != nil { + config.DefaultAllowMaintainerEdit = *opts.DefaultAllowMaintainerEdit + } units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, diff --git a/routers/api/v1/repo/star.go b/routers/api/v1/repo/star.go index c7b2eb01f..e4cf0ffab 100644 --- a/routers/api/v1/repo/star.go +++ b/routers/api/v1/repo/star.go @@ -50,7 +50,7 @@ func ListStargazers(ctx *context.APIContext) { } users := make([]*api.User, len(stargazers)) for i, stargazer := range stargazers { - users[i] = convert.ToUser(stargazer, ctx.Doer) + users[i] = convert.ToUser(ctx, stargazer, ctx.Doer) } ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumStars)) diff --git a/routers/api/v1/repo/subscriber.go b/routers/api/v1/repo/subscriber.go index 6cd369898..613fbee40 100644 --- a/routers/api/v1/repo/subscriber.go +++ b/routers/api/v1/repo/subscriber.go @@ -50,7 +50,7 @@ func ListSubscribers(ctx *context.APIContext) { } users := make([]*api.User, len(subscribers)) for i, subscriber := range subscribers { - users[i] = convert.ToUser(subscriber, ctx.Doer) + users[i] = convert.ToUser(ctx, subscriber, ctx.Doer) } ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumWatches)) diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go index cb65e2b65..b28b6b0b9 100644 --- a/routers/api/v1/repo/tag.go +++ b/routers/api/v1/repo/tag.go @@ -107,7 +107,7 @@ func GetAnnotatedTag(ctx *context.APIContext) { if err != nil { ctx.Error(http.StatusBadRequest, "GetAnnotatedTag", err) } - ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx.Repo.Repository, tag, commit)) + ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx, ctx.Repo.Repository, tag, commit)) } } diff --git a/routers/api/v1/repo/teams.go b/routers/api/v1/repo/teams.go index eafe4236e..01292f18d 100644 --- a/routers/api/v1/repo/teams.go +++ b/routers/api/v1/repo/teams.go @@ -47,7 +47,7 @@ func ListTeams(ctx *context.APIContext) { return } - apiTeams, err := convert.ToTeams(teams, false) + apiTeams, err := convert.ToTeams(ctx, teams, false) if err != nil { ctx.InternalServerError(err) return @@ -98,7 +98,7 @@ func IsTeam(ctx *context.APIContext) { } if models.HasRepository(team, ctx.Repo.Repository.ID) { - apiTeam, err := convert.ToTeam(team) + apiTeam, err := convert.ToTeam(ctx, team) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go index aec398da7..ded8edd41 100644 --- a/routers/api/v1/repo/transfer.go +++ b/routers/api/v1/repo/transfer.go @@ -81,7 +81,7 @@ func Transfer(ctx *context.APIContext) { return } - org := convert.ToOrganization(organization.OrgFromUser(newOwner)) + org := convert.ToOrganization(ctx, organization.OrgFromUser(newOwner)) for _, tID := range *opts.TeamIDs { team, err := organization.GetTeamByID(ctx, tID) if err != nil { diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go index a05d5fc22..b7b8484a3 100644 --- a/routers/api/v1/user/follower.go +++ b/routers/api/v1/user/follower.go @@ -18,7 +18,7 @@ import ( func responseAPIUsers(ctx *context.APIContext, users []*user_model.User) { apiUsers := make([]*api.User, len(users)) for i := range users { - apiUsers[i] = convert.ToUser(users[i], ctx.Doer) + apiUsers[i] = convert.ToUser(ctx, users[i], ctx.Doer) } ctx.JSON(http.StatusOK, &apiUsers) } diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go index 8aad69884..f90c65817 100644 --- a/routers/api/v1/user/key.go +++ b/routers/api/v1/user/key.go @@ -4,6 +4,7 @@ package user import ( + std_ctx "context" "net/http" asymkey_model "code.gitea.io/gitea/models/asymkey" @@ -21,20 +22,20 @@ import ( ) // appendPrivateInformation appends the owner and key type information to api.PublicKey -func appendPrivateInformation(apiKey *api.PublicKey, key *asymkey_model.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) { +func appendPrivateInformation(ctx std_ctx.Context, apiKey *api.PublicKey, key *asymkey_model.PublicKey, defaultUser *user_model.User) (*api.PublicKey, error) { if key.Type == asymkey_model.KeyTypeDeploy { apiKey.KeyType = "deploy" } else if key.Type == asymkey_model.KeyTypeUser { apiKey.KeyType = "user" if defaultUser.ID == key.OwnerID { - apiKey.Owner = convert.ToUser(defaultUser, defaultUser) + apiKey.Owner = convert.ToUser(ctx, defaultUser, defaultUser) } else { user, err := user_model.GetUserByID(db.DefaultContext, key.OwnerID) if err != nil { return apiKey, err } - apiKey.Owner = convert.ToUser(user, user) + apiKey.Owner = convert.ToUser(ctx, user, user) } } else { apiKey.KeyType = "unknown" @@ -87,7 +88,7 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) { for i := range keys { apiKeys[i] = convert.ToPublicKey(apiLink, keys[i]) if ctx.Doer.IsAdmin || ctx.Doer.ID == keys[i].OwnerID { - apiKeys[i], _ = appendPrivateInformation(apiKeys[i], keys[i], user) + apiKeys[i], _ = appendPrivateInformation(ctx, apiKeys[i], keys[i], user) } } @@ -187,7 +188,7 @@ func GetPublicKey(ctx *context.APIContext) { apiLink := composePublicKeysAPILink() apiKey := convert.ToPublicKey(apiLink, key) if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID { - apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Doer) + apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer) } ctx.JSON(http.StatusOK, apiKey) } @@ -208,7 +209,7 @@ func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid apiLink := composePublicKeysAPILink() apiKey := convert.ToPublicKey(apiLink, key) if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID { - apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Doer) + apiKey, _ = appendPrivateInformation(ctx, apiKey, key, ctx.Doer) } ctx.JSON(http.StatusCreated, apiKey) } diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index d566c072f..dcb14780a 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -119,8 +119,8 @@ func ListMyRepos(ctx *context.APIContext) { results := make([]*api.Repository, len(repos)) for i, repo := range repos { - if err = repo.GetOwner(ctx); err != nil { - ctx.Error(http.StatusInternalServerError, "GetOwner", err) + if err = repo.LoadOwner(ctx); err != nil { + ctx.Error(http.StatusInternalServerError, "LoadOwner", err) return } accessMode, err := access_model.AccessLevel(ctx, ctx.Doer, repo) diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 55f3df40b..6fd4b3a95 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -74,7 +74,7 @@ func Search(ctx *context.APIContext) { ctx.JSON(http.StatusOK, map[string]interface{}{ "ok": true, - "data": convert.ToUsers(ctx.Doer, users), + "data": convert.ToUsers(ctx, ctx.Doer, users), }) } @@ -102,7 +102,7 @@ func GetInfo(ctx *context.APIContext) { ctx.NotFound("GetUserByName", user_model.ErrUserNotExist{Name: ctx.Params(":username")}) return } - ctx.JSON(http.StatusOK, convert.ToUser(ctx.ContextUser, ctx.Doer)) + ctx.JSON(http.StatusOK, convert.ToUser(ctx, ctx.ContextUser, ctx.Doer)) } // GetAuthenticatedUser get current user's information @@ -116,7 +116,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) { // "200": // "$ref": "#/responses/User" - ctx.JSON(http.StatusOK, convert.ToUser(ctx.Doer, ctx.Doer)) + ctx.JSON(http.StatusOK, convert.ToUser(ctx, ctx.Doer, ctx.Doer)) } // GetUserHeatmapData is the handler to get a users heatmap diff --git a/routers/common/middleware.go b/routers/common/middleware.go index 0c7838b0e..4f9d43c36 100644 --- a/routers/common/middleware.go +++ b/routers/common/middleware.go @@ -8,6 +8,7 @@ import ( "net/http" "strings" + "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -28,7 +29,7 @@ func Middlewares() []func(http.Handler) http.Handler { ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true) defer finished() - next.ServeHTTP(context.NewResponse(resp), req.WithContext(ctx)) + next.ServeHTTP(context.NewResponse(resp), req.WithContext(cache.WithCacheContext(ctx))) }) }, } @@ -49,11 +50,11 @@ func Middlewares() []func(http.Handler) http.Handler { handlers = append(handlers, middleware.StripSlashes) - if !setting.DisableRouterLog { + if !setting.Log.DisableRouterLog { handlers = append(handlers, routing.NewLoggerHandler()) } - if setting.EnableAccessLog { + if setting.Log.EnableAccessLog { handlers = append(handlers, context.AccessLogger()) } diff --git a/routers/init.go b/routers/init.go index ab2e2a0bb..6a51de669 100644 --- a/routers/init.go +++ b/routers/init.go @@ -73,7 +73,7 @@ func mustInitCtx(ctx context.Context, fn func(ctx context.Context) error) { // InitGitServices init new services for git, this is also called in `contrib/pr/checkout.go` func InitGitServices() { - setting.NewServices() + setting.LoadSettings() mustInit(storage.Init) mustInit(repo_service.Init) } @@ -119,7 +119,7 @@ func GlobalInitInstalled(ctx context.Context) { log.Info("AppPath: %s", setting.AppPath) log.Info("AppWorkPath: %s", setting.AppWorkPath) log.Info("Custom path: %s", setting.CustomPath) - log.Info("Log path: %s", setting.LogRootPath) + log.Info("Log path: %s", setting.Log.RootPath) log.Info("Configuration file: %s", setting.CustomConf) log.Info("Run Mode: %s", util.ToTitleCase(setting.RunMode)) log.Info("Gitea v%s%s", setting.AppVer, setting.AppBuiltWith) @@ -127,7 +127,7 @@ func GlobalInitInstalled(ctx context.Context) { // Setup i18n translation.InitLocales(ctx) - setting.NewServices() + setting.LoadSettings() mustInit(storage.Init) mailer.NewContext(ctx) diff --git a/routers/install/install.go b/routers/install/install.go index e9fa844a0..a3d64e5f7 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models/migrations" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password/hash" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/generate" @@ -79,7 +80,7 @@ func Init(ctx goctx.Context) func(next http.Handler) http.Handler { "AllLangs": translation.AllLangs(), "PageStartTime": startTime, - "PasswordHashAlgorithms": user_model.AvailableHashAlgorithms, + "PasswordHashAlgorithms": hash.RecommendedHashAlgorithms, }, } defer ctx.Close() @@ -133,7 +134,7 @@ func Install(ctx *context.Context) { form.SSHPort = setting.SSH.Port form.HTTPPort = setting.HTTPPort form.AppURL = setting.AppURL - form.LogRootPath = setting.LogRootPath + form.LogRootPath = setting.Log.RootPath // E-mail service settings if setting.MailService != nil { @@ -441,11 +442,11 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("server").Key("OFFLINE_MODE").SetValue(fmt.Sprint(form.OfflineMode)) // if you are reinstalling, this maybe not right because of missing version - if err := system_model.SetSettingNoVersion(system_model.KeyPictureDisableGravatar, strconv.FormatBool(form.DisableGravatar)); err != nil { + if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureDisableGravatar, strconv.FormatBool(form.DisableGravatar)); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form) return } - if err := system_model.SetSettingNoVersion(system_model.KeyPictureEnableFederatedAvatar, strconv.FormatBool(form.EnableFederatedAvatar)); err != nil { + if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureEnableFederatedAvatar, strconv.FormatBool(form.EnableFederatedAvatar)); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form) return } @@ -466,7 +467,7 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("session").Key("PROVIDER").SetValue("file") cfg.Section("log").Key("MODE").SetValue("console") - cfg.Section("log").Key("LEVEL").SetValue(setting.LogLevel.String()) + cfg.Section("log").Key("LEVEL").SetValue(setting.Log.Level.String()) cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath) cfg.Section("log").Key("ROUTER").SetValue("console") diff --git a/routers/install/setting.go b/routers/install/setting.go index b76219f45..68984f1e7 100644 --- a/routers/install/setting.go +++ b/routers/install/setting.go @@ -15,20 +15,21 @@ import ( // PreloadSettings preloads the configuration to check if we need to run install func PreloadSettings(ctx context.Context) bool { - setting.LoadAllowEmpty() + setting.InitProviderAllowEmpty() + setting.LoadCommonSettings() if !setting.InstallLock { log.Info("AppPath: %s", setting.AppPath) log.Info("AppWorkPath: %s", setting.AppWorkPath) log.Info("Custom path: %s", setting.CustomPath) - log.Info("Log path: %s", setting.LogRootPath) + log.Info("Log path: %s", setting.Log.RootPath) log.Info("Configuration file: %s", setting.CustomConf) log.Info("Prepare to run install page") translation.InitLocales(ctx) if setting.EnableSQLite3 { log.Info("SQLite3 is supported") } - setting.InitDBConfig() - setting.NewServicesForInstall() + + setting.LoadSettingsForInstall() svg.Init() } @@ -37,8 +38,9 @@ func PreloadSettings(ctx context.Context) bool { // reloadSettings reloads the existing settings and starts up the database func reloadSettings(ctx context.Context) { - setting.LoadFromExisting() - setting.InitDBConfig() + setting.InitProviderFromExistingFile() + setting.LoadCommonSettings() + setting.LoadDBSetting() if setting.InstallLock { if err := common.InitDBEngine(ctx); err == nil { log.Info("ORM engine initialization successful!") diff --git a/routers/private/hook_verification.go b/routers/private/hook_verification.go index 7b9550dfd..8ccde4f3d 100644 --- a/routers/private/hook_verification.go +++ b/routers/private/hook_verification.go @@ -101,7 +101,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error { if err != nil { return err } - verification := asymkey_model.ParseCommitWithSignature(commit) + verification := asymkey_model.ParseCommitWithSignature(ctx, commit) if !verification.Verified { cancel() return &errUnverifiedCommit{ diff --git a/routers/private/manager.go b/routers/private/manager.go index f15da298d..a56fe9d12 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -116,11 +116,11 @@ func AddLogger(ctx *context.PrivateContext) { } if _, ok := opts.Config["level"]; !ok { - opts.Config["level"] = setting.LogLevel + opts.Config["level"] = setting.Log.Level } if _, ok := opts.Config["stacktraceLevel"]; !ok { - opts.Config["stacktraceLevel"] = setting.StacktraceLogLevel + opts.Config["stacktraceLevel"] = setting.Log.StacktraceLogLevel } if opts.Mode == "file" { @@ -135,7 +135,7 @@ func AddLogger(ctx *context.PrivateContext) { } } - bufferLen := setting.Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000) + bufferLen := setting.Log.BufferLength byteConfig, err := json.Marshal(opts.Config) if err != nil { log.Error("Failed to marshal log configuration: %v %v", opts.Config, err) diff --git a/routers/private/ssh_log.go b/routers/private/ssh_log.go index 54604ad55..eacfa18f0 100644 --- a/routers/private/ssh_log.go +++ b/routers/private/ssh_log.go @@ -15,7 +15,7 @@ import ( // SSHLog hook to response ssh log func SSHLog(ctx *context.PrivateContext) { - if !setting.EnableSSHLog { + if !setting.Log.EnableSSHLog { ctx.Status(http.StatusOK) return } diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 1f71e8178..2566cbe42 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -117,7 +117,7 @@ func Config(ctx *context.Context) { ctx.Data["AppUrl"] = setting.AppURL ctx.Data["Domain"] = setting.Domain ctx.Data["OfflineMode"] = setting.OfflineMode - ctx.Data["DisableRouterLog"] = setting.DisableRouterLog + ctx.Data["DisableRouterLog"] = setting.Log.DisableRouterLog ctx.Data["RunUser"] = setting.RunUser ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode) ctx.Data["GitVersion"] = git.VersionInfo() @@ -125,7 +125,7 @@ func Config(ctx *context.Context) { ctx.Data["RepoRootPath"] = setting.RepoRootPath ctx.Data["CustomRootPath"] = setting.CustomPath ctx.Data["StaticRootPath"] = setting.StaticRootPath - ctx.Data["LogRootPath"] = setting.LogRootPath + ctx.Data["LogRootPath"] = setting.Log.RootPath ctx.Data["ScriptType"] = setting.ScriptType ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail @@ -183,10 +183,10 @@ func Config(ctx *context.Context) { ctx.Data["EnvVars"] = envVars ctx.Data["Loggers"] = setting.GetLogDescriptions() - ctx.Data["EnableAccessLog"] = setting.EnableAccessLog - ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate - ctx.Data["DisableRouterLog"] = setting.DisableRouterLog - ctx.Data["EnableXORMLog"] = setting.EnableXORMLog + ctx.Data["EnableAccessLog"] = setting.Log.EnableAccessLog + ctx.Data["AccessLogTemplate"] = setting.Log.AccessLogTemplate + ctx.Data["DisableRouterLog"] = setting.Log.DisableRouterLog + ctx.Data["EnableXORMLog"] = setting.Log.EnableXORMLog ctx.Data["LogSQL"] = setting.Database.LogSQL ctx.HTML(http.StatusOK, tplConfig) @@ -213,7 +213,7 @@ func ChangeConfig(ctx *context.Context) { } } - if err := system_model.SetSetting(&system_model.Setting{ + if err := system_model.SetSetting(ctx, &system_model.Setting{ SettingKey: key, SettingValue: value, Version: version, diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 38969dada..1bb9d0480 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -14,10 +14,10 @@ import ( "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go index 48b7dc686..5fba63281 100644 --- a/routers/web/auth/auth.go +++ b/routers/web/auth/auth.go @@ -13,11 +13,11 @@ import ( "code.gitea.io/gitea/models/auth" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/eventsource" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/session" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" diff --git a/routers/web/auth/linkaccount.go b/routers/web/auth/linkaccount.go index 47a0daa06..865bcca15 100644 --- a/routers/web/auth/linkaccount.go +++ b/routers/web/auth/linkaccount.go @@ -59,7 +59,7 @@ func LinkAccount(ctx *context.Context) { ctx.Data["email"] = email if len(email) != 0 { - u, err := user_model.GetUserByEmail(email) + u, err := user_model.GetUserByEmail(ctx, email) if err != nil && !user_model.IsErrUserNotExist(err) { ctx.ServerError("UserSignIn", err) return diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index a11417da1..7de63dbe9 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -225,7 +225,7 @@ func newAccessTokenResponse(ctx stdContext.Context, grant *auth.OAuth2Grant, ser idToken.Name = user.GetDisplayName() idToken.PreferredUsername = user.Name idToken.Profile = user.HTMLURL() - idToken.Picture = user.AvatarLink() + idToken.Picture = user.AvatarLink(ctx) idToken.Website = user.Website idToken.Locale = user.Language idToken.UpdatedAt = user.UpdatedUnix @@ -286,7 +286,7 @@ func InfoOAuth(ctx *context.Context) { Name: ctx.Doer.FullName, Username: ctx.Doer.Name, Email: ctx.Doer.Email, - Picture: ctx.Doer.AvatarLink(), + Picture: ctx.Doer.AvatarLink(ctx), } groups, err := getOAuthGroupsForUser(ctx.Doer) diff --git a/routers/web/auth/oauth_test.go b/routers/web/auth/oauth_test.go index 5116b4fc7..62f723600 100644 --- a/routers/web/auth/oauth_test.go +++ b/routers/web/auth/oauth_test.go @@ -69,7 +69,7 @@ func TestNewAccessTokenResponse_OIDCToken(t *testing.T) { assert.Equal(t, user.Name, oidcToken.Name) assert.Equal(t, user.Name, oidcToken.PreferredUsername) assert.Equal(t, user.HTMLURL(), oidcToken.Profile) - assert.Equal(t, user.AvatarLink(), oidcToken.Picture) + assert.Equal(t, user.AvatarLink(db.DefaultContext), oidcToken.Picture) assert.Equal(t, user.Website, oidcToken.Website) assert.Equal(t, user.UpdatedUnix, oidcToken.UpdatedAt) assert.Equal(t, user.Email, oidcToken.Email) @@ -87,7 +87,7 @@ func TestNewAccessTokenResponse_OIDCToken(t *testing.T) { assert.Equal(t, user.FullName, oidcToken.Name) assert.Equal(t, user.Name, oidcToken.PreferredUsername) assert.Equal(t, user.HTMLURL(), oidcToken.Profile) - assert.Equal(t, user.AvatarLink(), oidcToken.Picture) + assert.Equal(t, user.AvatarLink(db.DefaultContext), oidcToken.Picture) assert.Equal(t, user.Website, oidcToken.Website) assert.Equal(t, user.UpdatedUnix, oidcToken.UpdatedAt) assert.Equal(t, user.Email, oidcToken.Email) diff --git a/routers/web/auth/openid.go b/routers/web/auth/openid.go index f544b6535..aff2e5f78 100644 --- a/routers/web/auth/openid.go +++ b/routers/web/auth/openid.go @@ -197,7 +197,7 @@ func signInOpenIDVerify(ctx *context.Context) { log.Trace("User has email=%s and nickname=%s", email, nickname) if email != "" { - u, err = user_model.GetUserByEmail(email) + u, err = user_model.GetUserByEmail(ctx, email) if err != nil { if !user_model.IsErrUserNotExist(err) { ctx.RenderWithErr(err.Error(), tplSignInOpenID, &forms.SignInOpenIDForm{ diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go index e546c77bc..a5aa9c534 100644 --- a/routers/web/auth/password.go +++ b/routers/web/auth/password.go @@ -9,10 +9,10 @@ import ( "code.gitea.io/gitea/models/auth" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" @@ -59,7 +59,7 @@ func ForgotPasswdPost(ctx *context.Context) { email := ctx.FormString("email") ctx.Data["Email"] = email - u, err := user_model.GetUserByEmail(email) + u, err := user_model.GetUserByEmail(ctx, email) if err != nil { if user_model.IsErrUserNotExist(err) { ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale) diff --git a/routers/web/org/org_labels.go b/routers/web/org/org_labels.go index 1c910a93a..e96627762 100644 --- a/routers/web/org/org_labels.go +++ b/routers/web/org/org_labels.go @@ -45,6 +45,7 @@ func NewLabel(ctx *context.Context) { l := &issues_model.Label{ OrgID: ctx.Org.Organization.ID, Name: form.Title, + Exclusive: form.Exclusive, Description: form.Description, Color: form.Color, } @@ -70,6 +71,7 @@ func UpdateLabel(ctx *context.Context) { } l.Name = form.Title + l.Exclusive = form.Exclusive l.Description = form.Description l.Color = form.Color if err := issues_model.UpdateLabel(l); err != nil { diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 1ce44d486..6449d12de 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -121,7 +121,7 @@ func canWriteUnit(ctx *context.Context) bool { // NewProject render creating a project page func NewProject(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.Data["CanWriteProjects"] = canWriteUnit(ctx) ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink() shared_user.RenderUserHeader(ctx) @@ -137,7 +137,7 @@ func NewProjectPost(ctx *context.Context) { if ctx.HasError() { ctx.Data["CanWriteProjects"] = canWriteUnit(ctx) ctx.Data["PageIsViewProjects"] = true - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["BoardTypes"] = project_model.GetBoardConfig() ctx.HTML(http.StatusOK, tplProjectsNew) return } diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index d9754633b..1ed798014 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -401,7 +401,7 @@ func SearchTeam(ctx *context.Context) { return } - apiTeams, err := convert.ToTeams(teams, false) + apiTeams, err := convert.ToTeams(ctx, teams, false) if err != nil { log.Error("convert ToTeams failed: %v", err) ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 146bf27da..e5496676a 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -70,7 +70,7 @@ func List(ctx *context.Context) { } ctx.Data["workflows"] = workflows - ctx.Data["RepoLink"] = ctx.Repo.Repository.HTMLURL() + ctx.Data["RepoLink"] = ctx.Repo.Repository.Link() page := ctx.FormInt("page") if page <= 0 { diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index def7cfcad..3546334ed 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -199,7 +199,7 @@ func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[st } // populate commit email addresses to later look up avatars. - for _, c := range user_model.ValidateCommitsWithEmails(commits) { + for _, c := range user_model.ValidateCommitsWithEmails(ctx, commits) { commitNames[c.ID.String()] = c } @@ -262,9 +262,9 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m var avatar string if commit.User != nil { - avatar = string(templates.Avatar(commit.User, 18, "mr-3")) + avatar = string(templates.Avatar(ctx, commit.User, 18, "gt-mr-3")) } else { - avatar = string(templates.AvatarByEmail(commit.Author.Email, commit.Author.Name, 18, "mr-3")) + avatar = string(templates.AvatarByEmail(ctx, commit.Author.Email, commit.Author.Name, 18, "gt-mr-3")) } br.Avatar = gotemplate.HTML(avatar) diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 9f94159d0..843b1d8df 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -138,7 +138,7 @@ func Graph(ctx *context.Context) { return } - if err := graph.LoadAndProcessCommits(ctx.Repo.Repository, ctx.Repo.GitRepo); err != nil { + if err := graph.LoadAndProcessCommits(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo); err != nil { ctx.ServerError("LoadAndProcessCommits", err) return } @@ -343,9 +343,9 @@ func Diff(ctx *context.Context) { ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses) ctx.Data["CommitStatuses"] = statuses - verification := asymkey_model.ParseCommitWithSignature(commit) + verification := asymkey_model.ParseCommitWithSignature(ctx, commit) ctx.Data["Verification"] = verification - ctx.Data["Author"] = user_model.ValidateCommitWithEmail(commit) + ctx.Data["Author"] = user_model.ValidateCommitWithEmail(ctx, commit) ctx.Data["Parents"] = parents ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0 @@ -361,7 +361,7 @@ func Diff(ctx *context.Context) { if err == nil { ctx.Data["Note"] = string(charset.ToUTF8WithFallback(note.Message)) ctx.Data["NoteCommit"] = note.Commit - ctx.Data["NoteAuthor"] = user_model.ValidateCommitWithEmail(note.Commit) + ctx.Data["NoteAuthor"] = user_model.ValidateCommitWithEmail(ctx, note.Commit) } ctx.Data["BranchName"], err = commit.GetBranchName() diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index c4b8c814e..f21611c63 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -43,8 +43,8 @@ const ( ) // setCompareContext sets context data. -func setCompareContext(ctx *context.Context, base, head *git.Commit, headOwner, headName string) { - ctx.Data["BaseCommit"] = base +func setCompareContext(ctx *context.Context, before, head *git.Commit, headOwner, headName string) { + ctx.Data["BeforeCommit"] = before ctx.Data["HeadCommit"] = head ctx.Data["GetBlobByPathForCommit"] = func(commit *git.Commit, path string) *git.Blob { @@ -59,7 +59,7 @@ func setCompareContext(ctx *context.Context, base, head *git.Commit, headOwner, return blob } - setPathsCompareContext(ctx, base, head, headOwner, headName) + setPathsCompareContext(ctx, before, head, headOwner, headName) setImageCompareContext(ctx) setCsvCompareContext(ctx) } @@ -279,7 +279,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { } return nil } - if err := ci.HeadRepo.GetOwner(ctx); err != nil { + if err := ci.HeadRepo.LoadOwner(ctx); err != nil { if user_model.IsErrUserNotExist(err) { ctx.NotFound("GetUserByName", nil) } else { @@ -629,9 +629,8 @@ func PrepareCompareDiff( } baseGitRepo := ctx.Repo.GitRepo - baseCommitID := ci.CompareInfo.BaseCommitID - baseCommit, err := baseGitRepo.GetCommit(baseCommitID) + beforeCommit, err := baseGitRepo.GetCommit(beforeCommitID) if err != nil { ctx.ServerError("GetCommit", err) return false @@ -668,7 +667,7 @@ func PrepareCompareDiff( ctx.Data["Username"] = ci.HeadUser.Name ctx.Data["Reponame"] = ci.HeadRepo.Name - setCompareContext(ctx, baseCommit, headCommit, ci.HeadUser.Name, repo.Name) + setCompareContext(ctx, beforeCommit, headCommit, ci.HeadUser.Name, repo.Name) return false } @@ -820,6 +819,13 @@ func CompareDiff(ctx *context.Context) { ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWrite(unit.TypePullRequests) + if unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypePullRequests); err == nil { + config := unit.PullRequestsConfig() + ctx.Data["AllowMaintainerEdit"] = config.DefaultAllowMaintainerEdit + } else { + ctx.Data["AllowMaintainerEdit"] = false + } + ctx.HTML(http.StatusOK, tplCompare) } diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index e82b94b9e..9d4ffccc6 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -146,8 +146,8 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { // don't allow anonymous pulls if organization is not public if isPublicPull { - if err := repo.GetOwner(ctx); err != nil { - ctx.ServerError("GetOwner", err) + if err := repo.LoadOwner(ctx); err != nil { + ctx.ServerError("LoadOwner", err) return } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index e6a416234..d740b9344 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -100,7 +100,7 @@ func MustAllowUserComment(ctx *context.Context) { if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin { ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked")) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } } @@ -332,8 +332,24 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti labels = append(labels, orgLabels...) } + // Get the exclusive scope for every label ID + labelExclusiveScopes := make([]string, 0, len(labelIDs)) + for _, labelID := range labelIDs { + foundExclusiveScope := false + for _, label := range labels { + if label.ID == labelID || label.ID == -labelID { + labelExclusiveScopes = append(labelExclusiveScopes, label.ExclusiveScope()) + foundExclusiveScope = true + break + } + } + if !foundExclusiveScope { + labelExclusiveScopes = append(labelExclusiveScopes, "") + } + } + for _, l := range labels { - l.LoadSelectedLabelsAfterClick(labelIDs) + l.LoadSelectedLabelsAfterClick(labelIDs, labelExclusiveScopes) } ctx.Data["Labels"] = labels ctx.Data["NumLabels"] = len(labels) @@ -927,7 +943,7 @@ func NewIssueChooseTemplate(ctx *context.Context) { if len(issueTemplates) == 0 { // The "issues/new" and "issues/new/choose" share the same query parameters "project" and "milestone", if no template here, just redirect to the "issues/new" page with these parameters. - ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.HTMLURL(), ctx.Req.URL.RawQuery), http.StatusSeeOther) + ctx.Redirect(fmt.Sprintf("%s/issues/new?%s", ctx.Repo.Repository.Link(), ctx.Req.URL.RawQuery), http.StatusSeeOther) return } @@ -950,11 +966,11 @@ func DeleteIssue(ctx *context.Context) { } if issue.IsPull { - ctx.Redirect(fmt.Sprintf("%s/pulls", ctx.Repo.Repository.HTMLURL()), http.StatusSeeOther) + ctx.Redirect(fmt.Sprintf("%s/pulls", ctx.Repo.Repository.Link()), http.StatusSeeOther) return } - ctx.Redirect(fmt.Sprintf("%s/issues", ctx.Repo.Repository.HTMLURL()), http.StatusSeeOther) + ctx.Redirect(fmt.Sprintf("%s/issues", ctx.Repo.Repository.Link()), http.StatusSeeOther) } // ValidateRepoMetas check and returns repository's meta information @@ -1142,7 +1158,11 @@ func NewIssuePost(ctx *context.Context) { } // roleDescriptor returns the Role Descriptor for a comment in/with the given repo, poster and issue -func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *user_model.User, issue *issues_model.Issue) (issues_model.RoleDescriptor, error) { +func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *user_model.User, issue *issues_model.Issue, hasOriginalAuthor bool) (issues_model.RoleDescriptor, error) { + if hasOriginalAuthor { + return issues_model.RoleDescriptorNone, nil + } + perm, err := access_model.GetUserRepoPermission(ctx, repo, poster) if err != nil { return issues_model.RoleDescriptorNone, err @@ -1425,7 +1445,7 @@ func ViewIssue(ctx *context.Context) { return } // Add link to the issue of the already running stopwatch - ctx.Data["OtherStopwatchURL"] = otherIssue.HTMLURL() + ctx.Data["OtherStopwatchURL"] = otherIssue.Link() } } ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.Doer) @@ -1444,7 +1464,7 @@ func ViewIssue(ctx *context.Context) { // check if dependencies can be created across repositories ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies - if issue.ShowRole, err = roleDescriptor(ctx, repo, issue.Poster, issue); err != nil { + if issue.ShowRole, err = roleDescriptor(ctx, repo, issue.Poster, issue, issue.HasOriginalAuthor()); err != nil { ctx.ServerError("roleDescriptor", err) return } @@ -1483,7 +1503,7 @@ func ViewIssue(ctx *context.Context) { continue } - comment.ShowRole, err = roleDescriptor(ctx, repo, comment.Poster, issue) + comment.ShowRole, err = roleDescriptor(ctx, repo, comment.Poster, issue, comment.HasOriginalAuthor()) if err != nil { ctx.ServerError("roleDescriptor", err) return @@ -1582,7 +1602,7 @@ func ViewIssue(ctx *context.Context) { continue } - c.ShowRole, err = roleDescriptor(ctx, repo, c.Poster, issue) + c.ShowRole, err = roleDescriptor(ctx, repo, c.Poster, issue, c.HasOriginalAuthor()) if err != nil { ctx.ServerError("roleDescriptor", err) return @@ -2153,8 +2173,8 @@ func UpdatePullReviewRequest(ctx *context.Context) { } if reviewID < 0 { // negative reviewIDs represent team requests - if err := issue.Repo.GetOwner(ctx); err != nil { - ctx.ServerError("issue.Repo.GetOwner", err) + if err := issue.Repo.LoadOwner(ctx); err != nil { + ctx.ServerError("issue.Repo.LoadOwner", err) return } @@ -2658,7 +2678,7 @@ func NewComment(ctx *context.Context) { if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin { ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked")) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } @@ -2669,7 +2689,7 @@ func NewComment(ctx *context.Context) { if ctx.HasError() { ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } @@ -3272,5 +3292,5 @@ func handleTeamMentions(ctx *context.Context) { ctx.Data["MentionableTeams"] = teams ctx.Data["MentionableTeamsOrg"] = ctx.Repo.Owner.Name - ctx.Data["MentionableTeamsOrgAvatar"] = ctx.Repo.Owner.AvatarLink() + ctx.Data["MentionableTeamsOrgAvatar"] = ctx.Repo.Owner.AvatarLink(ctx) } diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go index 3e6b31f8f..7e5295e75 100644 --- a/routers/web/repo/issue_content_history.go +++ b/routers/web/repo/issue_content_history.go @@ -71,7 +71,7 @@ func GetContentHistoryList(ctx *context.Context) { } src := html.EscapeString(item.UserAvatarLink) - class := avatars.DefaultAvatarClass + " mr-3" + class := avatars.DefaultAvatarClass + " gt-mr-3" name := html.EscapeString(username) avatarHTML := string(templates.AvatarHTML(src, 28, class, username)) timeSinceText := string(timeutil.TimeSinceUnix(item.EditedUnix, ctx.Locale)) diff --git a/routers/web/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go index 41c127be9..365d9609d 100644 --- a/routers/web/repo/issue_dependency.go +++ b/routers/web/repo/issue_dependency.go @@ -34,7 +34,7 @@ func AddDependency(ctx *context.Context) { } // Redirect - defer ctx.Redirect(issue.HTMLURL()) + defer ctx.Redirect(issue.Link()) // Dependency dep, err := issues_model.GetIssueByID(ctx, depID) @@ -124,5 +124,5 @@ func RemoveDependency(ctx *context.Context) { } // Redirect - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) } diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 66e8920bd..d4fece9f0 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -113,6 +113,7 @@ func NewLabel(ctx *context.Context) { l := &issues_model.Label{ RepoID: ctx.Repo.Repository.ID, Name: form.Title, + Exclusive: form.Exclusive, Description: form.Description, Color: form.Color, } @@ -138,6 +139,7 @@ func UpdateLabel(ctx *context.Context) { } l.Name = form.Title + l.Exclusive = form.Exclusive l.Description = form.Description l.Color = form.Color if err := issues_model.UpdateLabel(l); err != nil { @@ -175,7 +177,7 @@ func UpdateIssueLabel(ctx *context.Context) { return } } - case "attach", "detach", "toggle": + case "attach", "detach", "toggle", "toggle-alt": label, err := issues_model.GetLabelByID(ctx, ctx.FormInt64("id")) if err != nil { if issues_model.IsErrRepoLabelNotExist(err) { @@ -189,12 +191,18 @@ func UpdateIssueLabel(ctx *context.Context) { if action == "toggle" { // detach if any issues already have label, otherwise attach action = "attach" - for _, issue := range issues { - if issues_model.HasIssueLabel(ctx, issue.ID, label.ID) { - action = "detach" - break + if label.ExclusiveScope() == "" { + for _, issue := range issues { + if issues_model.HasIssueLabel(ctx, issue.ID, label.ID) { + action = "detach" + break + } } } + } else if action == "toggle-alt" { + // always detach with alt key pressed, to be able to remove + // scoped labels + action = "detach" } if action == "attach" { diff --git a/routers/web/repo/issue_lock.go b/routers/web/repo/issue_lock.go index 10db968a2..08b76e555 100644 --- a/routers/web/repo/issue_lock.go +++ b/routers/web/repo/issue_lock.go @@ -21,13 +21,13 @@ func LockIssue(ctx *context.Context) { if issue.IsLocked { ctx.Flash.Error(ctx.Tr("repo.issues.lock_duplicate")) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } if !form.HasValidReason() { ctx.Flash.Error(ctx.Tr("repo.issues.lock.unknown_reason")) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } @@ -40,7 +40,7 @@ func LockIssue(ctx *context.Context) { return } - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) } // UnlockIssue unlocks a previously locked issue. @@ -52,7 +52,7 @@ func UnlockIssue(ctx *context.Context) { if !issue.IsLocked { ctx.Flash.Error(ctx.Tr("repo.issues.unlock_error")) - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) return } @@ -64,5 +64,5 @@ func UnlockIssue(ctx *context.Context) { return } - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) } diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go index d2a7a12a1..3d20b08b4 100644 --- a/routers/web/repo/issue_stopwatch.go +++ b/routers/web/repo/issue_stopwatch.go @@ -40,7 +40,7 @@ func IssueStopwatch(c *context.Context) { c.Flash.Success(c.Tr("repo.issues.tracker_auto_close")) } - url := issue.HTMLURL() + url := issue.Link() c.Redirect(url, http.StatusSeeOther) } @@ -72,7 +72,7 @@ func CancelStopwatch(c *context.Context) { }) } - url := issue.HTMLURL() + url := issue.Link() c.Redirect(url, http.StatusSeeOther) } diff --git a/routers/web/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go index 6e9d3673c..7dc7d0797 100644 --- a/routers/web/repo/issue_timetrack.go +++ b/routers/web/repo/issue_timetrack.go @@ -26,7 +26,7 @@ func AddTimeManually(c *context.Context) { c.NotFound("CanUseTimetracker", nil) return } - url := issue.HTMLURL() + url := issue.Link() if c.HasError() { c.Flash.Error(c.GetErrMsg()) @@ -83,5 +83,5 @@ func DeleteTime(c *context.Context) { } c.Flash.Success(c.Tr("repo.issues.del_time_history", util.SecToTime(t.Time))) - c.Redirect(issue.HTMLURL()) + c.Redirect(issue.Link()) } diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go index c23dbf062..1837c2b63 100644 --- a/routers/web/repo/issue_watch.go +++ b/routers/web/repo/issue_watch.go @@ -52,5 +52,5 @@ func IssueWatch(ctx *context.Context) { return } - ctx.Redirect(issue.HTMLURL()) + ctx.Redirect(issue.Link()) } diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index 3becf799c..967b81c60 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -13,6 +13,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" project_model "code.gitea.io/gitea/models/project" + attachment_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -123,7 +124,8 @@ func Projects(ctx *context.Context) { // NewProject render creating a project page func NewProject(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.new") - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["BoardTypes"] = project_model.GetBoardConfig() + ctx.Data["CardTypes"] = project_model.GetCardConfig() ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) ctx.HTML(http.StatusOK, tplProjectsNew) } @@ -135,7 +137,8 @@ func NewProjectPost(ctx *context.Context) { if ctx.HasError() { ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) - ctx.Data["ProjectTypes"] = project_model.GetProjectsConfig() + ctx.Data["BoardTypes"] = project_model.GetBoardConfig() + ctx.Data["CardTypes"] = project_model.GetCardConfig() ctx.HTML(http.StatusOK, tplProjectsNew) return } @@ -146,6 +149,7 @@ func NewProjectPost(ctx *context.Context) { Description: form.Content, CreatorID: ctx.Doer.ID, BoardType: form.BoardType, + CardType: form.CardType, Type: project_model.TypeRepository, }); err != nil { ctx.ServerError("NewProject", err) @@ -212,6 +216,7 @@ func EditProject(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CardTypes"] = project_model.GetCardConfig() p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id")) if err != nil { @@ -229,6 +234,7 @@ func EditProject(ctx *context.Context) { ctx.Data["title"] = p.Title ctx.Data["content"] = p.Description + ctx.Data["card_type"] = p.CardType ctx.HTML(http.StatusOK, tplProjectsNew) } @@ -239,6 +245,7 @@ func EditProjectPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.projects.edit") ctx.Data["PageIsEditProjects"] = true ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects) + ctx.Data["CardTypes"] = project_model.GetCardConfig() if ctx.HasError() { ctx.HTML(http.StatusOK, tplProjectsNew) @@ -261,6 +268,7 @@ func EditProjectPost(ctx *context.Context) { p.Title = form.Title p.Description = form.Content + p.CardType = form.CardType if err = project_model.UpdateProject(ctx, p); err != nil { ctx.ServerError("UpdateProjects", err) return @@ -302,6 +310,18 @@ func ViewProject(ctx *context.Context) { return } + if project.CardType != project_model.CardTypeTextOnly { + issuesAttachmentMap := make(map[int64][]*attachment_model.Attachment) + for _, issuesList := range issuesMap { + for _, issue := range issuesList { + if issueAttachment, err := attachment_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil { + issuesAttachmentMap[issue.ID] = issueAttachment + } + } + } + ctx.Data["issuesAttachmentMap"] = issuesAttachmentMap + } + linkedPrsMap := make(map[int64][]*issues_model.Issue) for _, issuesList := range issuesMap { for _, issue := range issuesList { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index ad17005d9..c7a59da8a 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -119,8 +119,8 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository { return nil } - if err := forkRepo.GetOwner(ctx); err != nil { - ctx.ServerError("GetOwner", err) + if err := forkRepo.LoadOwner(ctx); err != nil { + ctx.ServerError("LoadOwner", err) return nil } @@ -1315,8 +1315,8 @@ func CleanUpPullRequest(ctx *context.Context) { } else if err = pr.LoadBaseRepo(ctx); err != nil { ctx.ServerError("LoadBaseRepo", err) return - } else if err = pr.HeadRepo.GetOwner(ctx); err != nil { - ctx.ServerError("HeadRepo.GetOwner", err) + } else if err = pr.HeadRepo.LoadOwner(ctx); err != nil { + ctx.ServerError("HeadRepo.LoadOwner", err) return } diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index 9f4cdde86..d43a786c5 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -98,7 +98,7 @@ func CreateCodeComment(ctx *context.Context) { renderConversation(ctx, comment) return } - ctx.Redirect(comment.HTMLURL()) + ctx.Redirect(comment.Link()) } // UpdateResolveConversation add or remove an Conversation resolved mark diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 5204b5fd0..e969fdc5a 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -295,7 +295,7 @@ func LatestRelease(ctx *context.Context) { return } - ctx.Redirect(release.HTMLURL()) + ctx.Redirect(release.Link()) } // NewRelease render creating or edit release page diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 1b1887d65..aeac7cfa3 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -344,7 +344,7 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error { ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected")) } - ctx.Redirect(ctx.Repo.Repository.HTMLURL()) + ctx.Redirect(ctx.Repo.Repository.Link()) return nil } diff --git a/routers/web/repo/search.go b/routers/web/repo/search.go index 137f38d40..a04319847 100644 --- a/routers/web/repo/search.go +++ b/routers/web/repo/search.go @@ -54,7 +54,7 @@ func Search(ctx *context.Context) { ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable() } - ctx.Data["SourcePath"] = ctx.Repo.Repository.HTMLURL() + ctx.Data["SourcePath"] = ctx.Repo.Repository.Link() ctx.Data["SearchResults"] = searchResults ctx.Data["SearchResultLanguages"] = searchResultLanguages diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go index 5c30795f2..387a91741 100644 --- a/routers/web/repo/setting.go +++ b/routers/web/repo/setting.go @@ -529,6 +529,7 @@ func SettingsPost(ctx *context.Context) { AllowRebaseUpdate: form.PullsAllowRebaseUpdate, DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge, DefaultMergeStyle: repo_model.MergeStyle(form.PullsDefaultMergeStyle), + DefaultAllowMaintainerEdit: form.DefaultAllowMaintainerEdit, }, }) } else if !unit_model.TypePullRequests.UnitGlobalDisabled() { @@ -649,7 +650,7 @@ func SettingsPost(ctx *context.Context) { ctx.Error(http.StatusNotFound) return } - if err := repo.GetOwner(ctx); err != nil { + if err := repo.LoadOwner(ctx); err != nil { ctx.ServerError("Convert Fork", err) return } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index f31490237..e3c61fa40 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -56,18 +56,15 @@ type namedBlob struct { blob *git.Blob } +// locate a README for a tree in one of the supported paths. +// +// entries is passed to reduce calls to ListEntries(), so +// this has precondition: +// +// entries == ctx.Repo.Commit.SubTree(ctx.Repo.TreePath).ListEntries() +// // FIXME: There has to be a more efficient way of doing this -func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath string) (*namedBlob, error) { - tree, err := commit.SubTree(treePath) - if err != nil { - return nil, err - } - - entries, err := tree.ListEntries() - if err != nil { - return nil, err - } - +func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*namedBlob, error) { // Create a list of extensions in priority order // 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md // 2. Txt files - e.g. README.txt @@ -75,16 +72,38 @@ func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath st exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority extCount := len(exts) readmeFiles := make([]*namedBlob, extCount+1) + + docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/) for _, entry := range entries { if entry.IsDir() { + // as a special case for the top-level repo introduction README, + // fall back to subfolders, looking for e.g. docs/README.md, .gitea/README.zh-CN.txt, .github/README.txt, ... + // (note that docsEntries is ignored unless we are at the root) + lowerName := strings.ToLower(entry.Name()) + switch lowerName { + case "docs": + if entry.Name() == "docs" || docsEntries[0] == nil { + docsEntries[0] = entry + } + case ".gitea": + if entry.Name() == ".gitea" || docsEntries[1] == nil { + docsEntries[1] = entry + } + case ".github": + if entry.Name() == ".github" || docsEntries[2] == nil { + docsEntries[2] = entry + } + } continue } - if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok { + if i, ok := util.IsReadmeFileExtension(entry.Name(), exts...); ok { + log.Debug("Potential readme file: %s", entry.Name()) if readmeFiles[i] == nil || base.NaturalSortLess(readmeFiles[i].name, entry.Blob().Name()) { name := entry.Name() isSymlink := entry.IsLink() target := entry if isSymlink { + var err error target, err = entry.FollowLinks() if err != nil && !git.IsErrBadLink(err) { return nil, err @@ -107,6 +126,33 @@ func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath st break } } + + if ctx.Repo.TreePath == "" && readmeFile == nil { + for _, subTreeEntry := range docsEntries { + if subTreeEntry == nil { + continue + } + subTree := subTreeEntry.Tree() + if subTree == nil { + // this should be impossible; if subTreeEntry exists so should this. + continue + } + var err error + childEntries, err := subTree.ListEntries() + if err != nil { + return nil, err + } + readmeFile, err = findReadmeFileInEntries(ctx, childEntries) + if err != nil && !git.IsErrNotExist(err) { + return nil, err + } + if readmeFile != nil { + readmeFile.name = subTreeEntry.Name() + "/" + readmeFile.name + break + } + } + } + return readmeFile, nil } @@ -127,12 +173,20 @@ func renderDirectory(ctx *context.Context, treeLink string) { ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived } - readmeFile, readmeTreelink := findReadmeFile(ctx, entries, treeLink) - if ctx.Written() || readmeFile == nil { + if ctx.Written() { + return + } + + readmeFile, err := findReadmeFileInEntries(ctx, entries) + if err != nil { + ctx.ServerError("findReadmeFileInEntries", err) + return + } + if readmeFile == nil { return } - renderReadmeFile(ctx, readmeFile, readmeTreelink) + renderReadmeFile(ctx, readmeFile, treeLink) } // localizedExtensions prepends the provided language code with and without a @@ -157,89 +211,6 @@ func localizedExtensions(ext, languageCode string) (localizedExts []string) { return []string{lowerLangCode + ext, ext} } -func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) { - // Create a list of extensions in priority order - // 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md - // 2. Txt files - e.g. README.txt - // 3. No extension - e.g. README - exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority - extCount := len(exts) - readmeFiles := make([]*namedBlob, extCount+1) - - docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/) - for _, entry := range entries { - if entry.IsDir() { - lowerName := strings.ToLower(entry.Name()) - switch lowerName { - case "docs": - if entry.Name() == "docs" || docsEntries[0] == nil { - docsEntries[0] = entry - } - case ".gitea": - if entry.Name() == ".gitea" || docsEntries[1] == nil { - docsEntries[1] = entry - } - case ".github": - if entry.Name() == ".github" || docsEntries[2] == nil { - docsEntries[2] = entry - } - } - continue - } - - if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok { - log.Debug("Potential readme file: %s", entry.Name()) - name := entry.Name() - isSymlink := entry.IsLink() - target := entry - if isSymlink { - var err error - target, err = entry.FollowLinks() - if err != nil && !git.IsErrBadLink(err) { - ctx.ServerError("FollowLinks", err) - return nil, "" - } - } - if target != nil && (target.IsExecutable() || target.IsRegular()) { - readmeFiles[i] = &namedBlob{ - name, - isSymlink, - target.Blob(), - } - } - } - } - - var readmeFile *namedBlob - readmeTreelink := treeLink - for _, f := range readmeFiles { - if f != nil { - readmeFile = f - break - } - } - - if ctx.Repo.TreePath == "" && readmeFile == nil { - for _, entry := range docsEntries { - if entry == nil { - continue - } - var err error - readmeFile, err = getReadmeFileFromPath(ctx, ctx.Repo.Commit, entry.GetSubJumpablePathName()) - if err != nil { - ctx.ServerError("getReadmeFileFromPath", err) - return nil, "" - } - if readmeFile != nil { - readmeFile.name = entry.Name() + "/" + readmeFile.name - readmeTreelink = treeLink + "/" + util.PathEscapeSegments(entry.GetSubJumpablePathName()) - break - } - } - } - return readmeFile, readmeTreelink -} - type fileInfo struct { isTextFile bool isLFSFile bool @@ -318,7 +289,7 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin if fInfo.isLFSFile { filenameBase64 := base64.RawURLEncoding.EncodeToString([]byte(readmeFile.name)) - ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.HTMLURL(), url.PathEscape(fInfo.lfsMeta.Oid), url.PathEscape(filenameBase64)) + ctx.Data["RawFileLink"] = fmt.Sprintf("%s.git/info/lfs/objects/%s/%s", ctx.Repo.Repository.Link(), url.PathEscape(fInfo.lfsMeta.Oid), url.PathEscape(filenameBase64)) } if !fInfo.isTextFile { @@ -342,7 +313,7 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{ Ctx: ctx, RelativePath: path.Join(ctx.Repo.TreePath, readmeFile.name), // ctx.Repo.TreePath is the directory not the Readme so we must append the Readme filename (and path). - URLPrefix: readmeTreelink, + URLPrefix: path.Dir(readmeTreelink), Metas: ctx.Repo.Repository.ComposeDocumentMetas(), GitRepo: ctx.Repo.GitRepo, }, rd) @@ -452,7 +423,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc)) shouldRenderSource := ctx.FormString("display") == "source" - readmeExist := markup.IsReadmeFile(blob.Name()) + readmeExist := util.IsReadmeFileName(blob.Name()) ctx.Data["ReadmeExist"] = readmeExist markupType := markup.Type(blob.Name()) @@ -738,7 +709,7 @@ func Home(ctx *context.Context) { } ctx.Data["EnableFeed"] = true - ctx.Data["FeedURL"] = ctx.Repo.Repository.HTMLURL() + ctx.Data["FeedURL"] = ctx.Repo.Repository.Link() } checkHomeCodeViewable(ctx) @@ -840,7 +811,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri ctx.Data["LatestCommit"] = latestCommit if latestCommit != nil { - verification := asymkey_model.ParseCommitWithSignature(latestCommit) + verification := asymkey_model.ParseCommitWithSignature(ctx, latestCommit) if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) { return repo_model.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID) @@ -849,7 +820,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri return nil } ctx.Data["LatestCommitVerification"] = verification - ctx.Data["LatestCommitUser"] = user_model.ValidateCommitWithEmail(latestCommit) + ctx.Data["LatestCommitUser"] = user_model.ValidateCommitWithEmail(ctx, latestCommit) statuses, _, err := git_model.GetLatestCommitStatus(ctx, ctx.Repo.Repository.ID, latestCommit.ID.String(), db.ListOptions{}) if err != nil { @@ -1062,8 +1033,8 @@ func Forks(ctx *context.Context) { } for _, fork := range forks { - if err = fork.GetOwner(ctx); err != nil { - ctx.ServerError("GetOwner", err) + if err = fork.LoadOwner(ctx); err != nil { + ctx.ServerError("LoadOwner", err) return } } diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index d3826c3f3..d27d0f1bf 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -660,7 +660,7 @@ func TestWebhook(ctx *context.Context) { } } - apiUser := convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone) + apiUser := convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone) apiCommit := &api.PayloadCommit{ ID: commit.ID.String(), diff --git a/routers/web/user/avatar.go b/routers/web/user/avatar.go index 20c2ef3e4..2dba74822 100644 --- a/routers/web/user/avatar.go +++ b/routers/web/user/avatar.go @@ -41,7 +41,7 @@ func AvatarByUserName(ctx *context.Context) { user = user_model.NewGhostUser() } - cacheableRedirect(ctx, user.AvatarLinkWithSize(size)) + cacheableRedirect(ctx, user.AvatarLinkWithSize(ctx, size)) } // AvatarByEmailHash redirects the browser to the email avatar link @@ -53,5 +53,5 @@ func AvatarByEmailHash(ctx *context.Context) { return } size := ctx.FormInt("size") - cacheableRedirect(ctx, avatars.GenerateEmailAvatarFinalLink(email, size)) + cacheableRedirect(ctx, avatars.GenerateEmailAvatarFinalLink(ctx, email, size)) } diff --git a/routers/web/user/home.go b/routers/web/user/home.go index 36d9d4f01..4f45c1d5c 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -338,6 +338,11 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { filterMode int ) + // Default to recently updated, unlike repository issues list + if sortType == "" { + sortType = "recentupdate" + } + // -------------------------------------------------------------------------------- // Distinguish User from Organization. // Org: diff --git a/routers/web/user/package.go b/routers/web/user/package.go index ed4f0dd79..a9acc5281 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -376,7 +376,7 @@ func PackageSettingsPost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) } - ctx.Redirect(ctx.Package.Owner.HTMLURL() + "/-/packages") + ctx.Redirect(ctx.Package.Owner.HomeLink() + "/-/packages") return } } diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index f2a6f5b50..503562220 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -48,7 +48,7 @@ func Profile(ctx *context.Context) { } // advertise feed via meta tag - ctx.Data["FeedURL"] = ctx.ContextUser.HTMLURL() + ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink() // Show OpenID URIs openIDs, err := user_model.GetUserOpenIDs(ctx.ContextUser.ID) diff --git a/routers/web/user/search.go b/routers/web/user/search.go index f9b0e0735..c5c3aa75f 100644 --- a/routers/web/user/search.go +++ b/routers/web/user/search.go @@ -38,6 +38,6 @@ func Search(ctx *context.Context) { ctx.JSON(http.StatusOK, map[string]interface{}{ "ok": true, - "data": convert.ToUsers(ctx.Doer, users), + "data": convert.ToUsers(ctx, ctx.Doer, users), }) } diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go index dbaa8fd35..0e48013b0 100644 --- a/routers/web/user/setting/account.go +++ b/routers/web/user/setting/account.go @@ -11,10 +11,10 @@ import ( "code.gitea.io/gitea/models" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/password" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/web" diff --git a/routers/web/webfinger.go b/routers/web/webfinger.go index 13b93edae..c5ebce555 100644 --- a/routers/web/webfinger.go +++ b/routers/web/webfinger.go @@ -46,7 +46,7 @@ func WebfingerQuery(ctx *context.Context) { u, err = user_model.GetUserByName(ctx, parts[0]) case "mailto": - u, err = user_model.GetUserByEmailContext(ctx, resource.Opaque) + u, err = user_model.GetUserByEmail(ctx, resource.Opaque) if u != nil && u.KeepEmailPrivate { err = user_model.ErrUserNotExist{} } @@ -87,7 +87,7 @@ func WebfingerQuery(ctx *context.Context) { }, { Rel: "http://webfinger.net/rel/avatar", - Href: u.AvatarLink(), + Href: u.AvatarLink(ctx), }, { Rel: "self", |