diff options
author | Daniel Baumann <daniel@debian.org> | 2024-10-18 20:33:49 +0200 |
---|---|---|
committer | Daniel Baumann <daniel@debian.org> | 2024-12-12 23:57:56 +0100 |
commit | e68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch) | |
tree | 97775d6c13b0f416af55314eb6a89ef792474615 /services/convert/repository.go | |
parent | Initial commit. (diff) | |
download | forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip |
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'services/convert/repository.go')
-rw-r--r-- | services/convert/repository.go | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/services/convert/repository.go b/services/convert/repository.go new file mode 100644 index 0000000..2fb6f6d --- /dev/null +++ b/services/convert/repository.go @@ -0,0 +1,254 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package convert + +import ( + "context" + "time" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + repo_model "code.gitea.io/gitea/models/repo" + unit_model "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" +) + +// ToRepo converts a Repository to api.Repository +func ToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission) *api.Repository { + return innerToRepo(ctx, repo, permissionInRepo, false) +} + +func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission, isParent bool) *api.Repository { + var parent *api.Repository + + if permissionInRepo.Units == nil && permissionInRepo.UnitsMode == nil { + // If Units and UnitsMode are both nil, it means that it's a hard coded permission, + // like access_model.Permission{AccessMode: perm.AccessModeAdmin}. + // So we need to load units for the repo, or UnitAccessMode will always return perm.AccessModeNone. + _ = repo.LoadUnits(ctx) // the error is not important, so ignore it + permissionInRepo.Units = repo.Units + } + + cloneLink := repo.CloneLink() + permission := &api.Permission{ + Admin: permissionInRepo.AccessMode >= perm.AccessModeAdmin, + Push: permissionInRepo.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeWrite, + Pull: permissionInRepo.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeRead, + } + if !isParent { + err := repo.GetBaseRepo(ctx) + if err != nil { + return nil + } + if repo.BaseRepo != nil { + // FIXME: The permission of the parent repo is not correct. + // It's the permission of the current repo, so it's probably different from the parent repo. + // But there isn't a good way to get the permission of the parent repo, because the doer is not passed in. + // Use the permission of the current repo to keep the behavior consistent with the old API. + // Maybe the right way is setting the permission of the parent repo to nil, empty is better than wrong. + parent = innerToRepo(ctx, repo.BaseRepo, permissionInRepo, true) + } + } + + // check enabled/disabled units + hasIssues := false + var externalTracker *api.ExternalTracker + var internalTracker *api.InternalTracker + if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err == nil { + config := unit.IssuesConfig() + hasIssues = true + internalTracker = &api.InternalTracker{ + EnableTimeTracker: config.EnableTimetracker, + AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, + EnableIssueDependencies: config.EnableDependencies, + } + } else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalTracker); err == nil { + config := unit.ExternalTrackerConfig() + hasIssues = true + externalTracker = &api.ExternalTracker{ + ExternalTrackerURL: config.ExternalTrackerURL, + ExternalTrackerFormat: config.ExternalTrackerFormat, + ExternalTrackerStyle: config.ExternalTrackerStyle, + ExternalTrackerRegexpPattern: config.ExternalTrackerRegexpPattern, + } + } + hasWiki := false + globallyEditableWiki := false + var externalWiki *api.ExternalWiki + if wikiUnit, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil { + hasWiki = true + if wikiUnit.DefaultPermissions == repo_model.UnitAccessModeWrite { + globallyEditableWiki = true + } + } else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil { + hasWiki = true + config := unit.ExternalWikiConfig() + externalWiki = &api.ExternalWiki{ + ExternalWikiURL: config.ExternalWikiURL, + } + } + hasPullRequests := false + ignoreWhitespaceConflicts := false + allowMerge := false + allowRebase := false + allowRebaseMerge := false + allowSquash := false + allowFastForwardOnly := false + allowRebaseUpdate := false + defaultDeleteBranchAfterMerge := false + defaultMergeStyle := repo_model.MergeStyleMerge + defaultAllowMaintainerEdit := false + if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil { + config := unit.PullRequestsConfig() + hasPullRequests = true + ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts + allowMerge = config.AllowMerge + allowRebase = config.AllowRebase + allowRebaseMerge = config.AllowRebaseMerge + allowSquash = config.AllowSquash + allowFastForwardOnly = config.AllowFastForwardOnly + allowRebaseUpdate = config.AllowRebaseUpdate + defaultDeleteBranchAfterMerge = config.DefaultDeleteBranchAfterMerge + defaultMergeStyle = config.GetDefaultMergeStyle() + defaultAllowMaintainerEdit = config.DefaultAllowMaintainerEdit + } + hasProjects := false + if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil { + hasProjects = true + } + + hasReleases := false + if _, err := repo.GetUnit(ctx, unit_model.TypeReleases); err == nil { + hasReleases = true + } + + hasPackages := false + if _, err := repo.GetUnit(ctx, unit_model.TypePackages); err == nil { + hasPackages = true + } + + hasActions := false + if _, err := repo.GetUnit(ctx, unit_model.TypeActions); err == nil { + hasActions = true + } + + if err := repo.LoadOwner(ctx); err != nil { + return nil + } + + numReleases, _ := db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{ + IncludeDrafts: false, + IncludeTags: false, + RepoID: repo.ID, + }) + + mirrorInterval := "" + var mirrorUpdated time.Time + if repo.IsMirror { + pullMirror, err := repo_model.GetMirrorByRepoID(ctx, repo.ID) + if err == nil { + mirrorInterval = pullMirror.Interval.String() + mirrorUpdated = pullMirror.UpdatedUnix.AsTime() + } + } + + var transfer *api.RepoTransfer + if repo.Status == repo_model.RepositoryPendingTransfer { + t, err := models.GetPendingRepositoryTransfer(ctx, repo) + if err != nil && !models.IsErrNoPendingTransfer(err) { + log.Warn("GetPendingRepositoryTransfer: %v", err) + } else { + if err := t.LoadAttributes(ctx); err != nil { + log.Warn("LoadAttributes of RepoTransfer: %v", err) + } else { + transfer = ToRepoTransfer(ctx, t) + } + } + } + + var language string + if repo.PrimaryLanguage != nil { + language = repo.PrimaryLanguage.Language + } + + repoAPIURL := repo.APIURL() + + return &api.Repository{ + ID: repo.ID, + Owner: ToUserWithAccessMode(ctx, repo.Owner, permissionInRepo.AccessMode), + Name: repo.Name, + FullName: repo.FullName(), + Description: repo.Description, + Private: repo.IsPrivate, + Template: repo.IsTemplate, + Empty: repo.IsEmpty, + Archived: repo.IsArchived, + Size: int(repo.Size / 1024), + Fork: repo.IsFork, + Parent: parent, + Mirror: repo.IsMirror, + HTMLURL: repo.HTMLURL(), + URL: repoAPIURL, + SSHURL: cloneLink.SSH, + CloneURL: cloneLink.HTTPS, + OriginalURL: repo.SanitizedOriginalURL(), + Website: repo.Website, + Language: language, + LanguagesURL: repoAPIURL + "/languages", + Stars: repo.NumStars, + Forks: repo.NumForks, + Watchers: repo.NumWatches, + OpenIssues: repo.NumOpenIssues, + OpenPulls: repo.NumOpenPulls, + Releases: int(numReleases), + DefaultBranch: repo.DefaultBranch, + Created: repo.CreatedUnix.AsTime(), + Updated: repo.UpdatedUnix.AsTime(), + ArchivedAt: repo.ArchivedUnix.AsTime(), + Permissions: permission, + HasIssues: hasIssues, + ExternalTracker: externalTracker, + InternalTracker: internalTracker, + HasWiki: hasWiki, + WikiBranch: repo.WikiBranch, + GloballyEditableWiki: globallyEditableWiki, + HasProjects: hasProjects, + HasReleases: hasReleases, + HasPackages: hasPackages, + HasActions: hasActions, + ExternalWiki: externalWiki, + HasPullRequests: hasPullRequests, + IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, + AllowMerge: allowMerge, + AllowRebase: allowRebase, + AllowRebaseMerge: allowRebaseMerge, + AllowSquash: allowSquash, + AllowFastForwardOnly: allowFastForwardOnly, + AllowRebaseUpdate: allowRebaseUpdate, + DefaultDeleteBranchAfterMerge: defaultDeleteBranchAfterMerge, + DefaultMergeStyle: string(defaultMergeStyle), + DefaultAllowMaintainerEdit: defaultAllowMaintainerEdit, + AvatarURL: repo.AvatarLink(ctx), + Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate, + MirrorInterval: mirrorInterval, + MirrorUpdated: mirrorUpdated, + RepoTransfer: transfer, + Topics: repo.Topics, + ObjectFormatName: repo.ObjectFormatName, + } +} + +// ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer +func ToRepoTransfer(ctx context.Context, t *models.RepoTransfer) *api.RepoTransfer { + teams, _ := ToTeams(ctx, t.Teams, false) + + return &api.RepoTransfer{ + Doer: ToUser(ctx, t.Doer, nil), + Recipient: ToUser(ctx, t.Recipient, nil), + Teams: teams, + } +} |