mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-20 14:31:19 +02:00
Fix merge conflict in migrations.go, v238.go, create v999.go and Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -310,7 +310,7 @@ Loop:
|
||||
return false, "", nil, &ErrWontSign{twofa}
|
||||
}
|
||||
case approved:
|
||||
protectedBranch, err := git_model.GetProtectedBranchBy(ctx, repo.ID, pr.BaseBranch)
|
||||
protectedBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ func ToBranch(repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *git
|
||||
}
|
||||
|
||||
if isRepoAdmin {
|
||||
branch.EffectiveBranchProtectionName = bp.BranchName
|
||||
branch.EffectiveBranchProtectionName = bp.RuleName
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
@@ -87,7 +87,8 @@ func ToBranch(repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *git
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branch.UserCanPush = bp.CanUserPush(db.DefaultContext, user.ID)
|
||||
bp.Repo = repo
|
||||
branch.UserCanPush = bp.CanUserPush(db.DefaultContext, user)
|
||||
branch.UserCanMerge = git_model.IsUserMergeWhitelisted(db.DefaultContext, bp, user.ID, permission)
|
||||
}
|
||||
|
||||
@@ -121,8 +122,14 @@ func ToBranchProtection(bp *git_model.ProtectedBranch) *api.BranchProtection {
|
||||
log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err)
|
||||
}
|
||||
|
||||
branchName := ""
|
||||
if !git_model.IsRuleNameSpecial(bp.RuleName) {
|
||||
branchName = bp.RuleName
|
||||
}
|
||||
|
||||
return &api.BranchProtection{
|
||||
BranchName: bp.BranchName,
|
||||
BranchName: branchName,
|
||||
RuleName: bp.RuleName,
|
||||
EnablePush: bp.CanPush,
|
||||
EnablePushWhitelist: bp.EnableWhitelist,
|
||||
PushWhitelistUsernames: pushWhitelistUsernames,
|
||||
|
||||
@@ -175,6 +175,48 @@ func registerDeleteOldSystemNotices() {
|
||||
})
|
||||
}
|
||||
|
||||
func registerGCLFS() {
|
||||
if !setting.LFS.StartServer {
|
||||
return
|
||||
}
|
||||
type GCLFSConfig struct {
|
||||
OlderThanConfig
|
||||
LastUpdatedMoreThanAgo time.Duration
|
||||
NumberToCheckPerRepo int64
|
||||
ProportionToCheckPerRepo float64
|
||||
}
|
||||
|
||||
RegisterTaskFatal("gc_lfs", &GCLFSConfig{
|
||||
OlderThanConfig: OlderThanConfig{
|
||||
BaseConfig: BaseConfig{
|
||||
Enabled: false,
|
||||
RunAtStart: false,
|
||||
Schedule: "@every 24h",
|
||||
},
|
||||
// Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload
|
||||
// and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby
|
||||
// an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid
|
||||
// changes in new branches that might lead to lfs objects becoming temporarily unassociated with git
|
||||
// objects.
|
||||
//
|
||||
// It is likely that a week is potentially excessive but it should definitely be enough that any
|
||||
// unassociated LFS object is genuinely unassociated.
|
||||
OlderThan: 24 * time.Hour * 7,
|
||||
},
|
||||
// Only GC things that haven't been looked at in the past 3 days
|
||||
LastUpdatedMoreThanAgo: 24 * time.Hour * 3,
|
||||
NumberToCheckPerRepo: 100,
|
||||
ProportionToCheckPerRepo: 0.6,
|
||||
}, func(ctx context.Context, _ *user_model.User, config Config) error {
|
||||
gcLFSConfig := config.(*GCLFSConfig)
|
||||
return repo_service.GarbageCollectLFSMetaObjects(ctx, repo_service.GarbageCollectLFSMetaObjectsOptions{
|
||||
AutoFix: true,
|
||||
OlderThan: time.Now().Add(-gcLFSConfig.OlderThan),
|
||||
UpdatedLessRecentlyThan: time.Now().Add(-gcLFSConfig.LastUpdatedMoreThanAgo),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func initExtendedTasks() {
|
||||
registerDeleteInactiveUsers()
|
||||
registerDeleteRepositoryArchives()
|
||||
@@ -188,4 +230,5 @@ func initExtendedTasks() {
|
||||
registerDeleteOldActions()
|
||||
registerUpdateGiteaChecker()
|
||||
registerDeleteOldSystemNotices()
|
||||
registerGCLFS()
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) bindi
|
||||
|
||||
// ProtectBranchForm form for changing protected branch settings
|
||||
type ProtectBranchForm struct {
|
||||
Protected bool
|
||||
RuleName string `binding:"Required"`
|
||||
EnablePush string
|
||||
WhitelistUsers string
|
||||
WhitelistTeams string
|
||||
|
||||
@@ -274,6 +274,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
|
||||
"ActionName": actName,
|
||||
"ReviewComments": reviewComments,
|
||||
"Language": locale.Language(),
|
||||
"CanReply": setting.IncomingEmail.Enabled && commentType != issues_model.CommentTypePullRequestPush,
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
|
||||
@@ -33,10 +33,14 @@ func (f *GitBucketDownloaderFactory) New(ctx context.Context, opts base.MigrateO
|
||||
return nil, err
|
||||
}
|
||||
|
||||
baseURL := u.Scheme + "://" + u.Host
|
||||
fields := strings.Split(u.Path, "/")
|
||||
oldOwner := fields[1]
|
||||
oldName := strings.TrimSuffix(fields[2], ".git")
|
||||
if len(fields) < 2 {
|
||||
return nil, fmt.Errorf("invalid path: %s", u.Path)
|
||||
}
|
||||
baseURL := u.Scheme + "://" + u.Host + strings.TrimSuffix(strings.Join(fields[:len(fields)-2], "/"), "/git")
|
||||
|
||||
oldOwner := fields[len(fields)-2]
|
||||
oldName := strings.TrimSuffix(fields[len(fields)-1], ".git")
|
||||
|
||||
log.Trace("Create GitBucket downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, oldOwner, oldName)
|
||||
return NewGitBucketDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil
|
||||
@@ -71,6 +75,7 @@ func (g *GitBucketDownloader) ColorFormat(s fmt.State) {
|
||||
func NewGitBucketDownloader(ctx context.Context, baseURL, userName, password, token, repoOwner, repoName string) *GitBucketDownloader {
|
||||
githubDownloader := NewGithubDownloaderV3(ctx, baseURL, userName, password, token, repoOwner, repoName)
|
||||
githubDownloader.SkipReactions = true
|
||||
githubDownloader.SkipReviews = true
|
||||
return &GitBucketDownloader{
|
||||
githubDownloader,
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ type GithubDownloaderV3 struct {
|
||||
curClientIdx int
|
||||
maxPerPage int
|
||||
SkipReactions bool
|
||||
SkipReviews bool
|
||||
}
|
||||
|
||||
// NewGithubDownloaderV3 creates a github Downloader via github v3 API
|
||||
@@ -809,6 +810,9 @@ func (g *GithubDownloaderV3) convertGithubReviewComments(cs []*github.PullReques
|
||||
// GetReviews returns pull requests review
|
||||
func (g *GithubDownloaderV3) GetReviews(reviewable base.Reviewable) ([]*base.Review, error) {
|
||||
allReviews := make([]*base.Review, 0, g.maxPerPage)
|
||||
if g.SkipReviews {
|
||||
return allReviews, nil
|
||||
}
|
||||
opt := &github.ListOptions{
|
||||
PerPage: g.maxPerPage,
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -126,11 +127,12 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
|
||||
|
||||
// isSignedIfRequired check if merge will be signed if required
|
||||
func isSignedIfRequired(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.User) (bool, error) {
|
||||
if err := pr.LoadProtectedBranch(ctx); err != nil {
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if pr.ProtectedBranch == nil || !pr.ProtectedBranch.RequireSignedCommits {
|
||||
if pb == nil || !pb.RequireSignedCommits {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -348,8 +350,8 @@ func testPR(id int64) {
|
||||
checkAndUpdateStatus(ctx, pr)
|
||||
}
|
||||
|
||||
// CheckPrsForBaseBranch check all pulls with bseBrannch
|
||||
func CheckPrsForBaseBranch(baseRepo *repo_model.Repository, baseBranchName string) error {
|
||||
// CheckPRsForBaseBranch check all pulls with baseBrannch
|
||||
func CheckPRsForBaseBranch(baseRepo *repo_model.Repository, baseBranchName string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(baseRepo.ID, baseBranchName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -83,10 +83,11 @@ func IsCommitStatusContextSuccess(commitStatuses []*git_model.CommitStatus, requ
|
||||
|
||||
// IsPullCommitStatusPass returns if all required status checks PASS
|
||||
func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) (bool, error) {
|
||||
if err := pr.LoadProtectedBranch(ctx); err != nil {
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "GetLatestCommitStatus")
|
||||
}
|
||||
if pr.ProtectedBranch == nil || !pr.ProtectedBranch.EnableStatusCheck {
|
||||
if pb == nil || !pb.EnableStatusCheck {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -137,12 +138,13 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR
|
||||
return "", errors.Wrap(err, "GetLatestCommitStatus")
|
||||
}
|
||||
|
||||
if err := pr.LoadProtectedBranch(ctx); err != nil {
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "LoadProtectedBranch")
|
||||
}
|
||||
var requiredContexts []string
|
||||
if pr.ProtectedBranch != nil {
|
||||
requiredContexts = pr.ProtectedBranch.StatusCheckContexts
|
||||
if pb != nil {
|
||||
requiredContexts = pb.StatusCheckContexts
|
||||
}
|
||||
|
||||
return MergeRequiredContextsCommitStatus(commitStatuses, requiredContexts), nil
|
||||
|
||||
+14
-10
@@ -760,12 +760,12 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a
|
||||
return false, nil
|
||||
}
|
||||
|
||||
err := pr.LoadProtectedBranch(ctx)
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if (p.CanWrite(unit.TypeCode) && pr.ProtectedBranch == nil) || (pr.ProtectedBranch != nil && git_model.IsUserMergeWhitelisted(ctx, pr.ProtectedBranch, user.ID, p)) {
|
||||
if (p.CanWrite(unit.TypeCode) && pb == nil) || (pb != nil && git_model.IsUserMergeWhitelisted(ctx, pb, user.ID, p)) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -778,10 +778,11 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
|
||||
return fmt.Errorf("LoadBaseRepo: %w", err)
|
||||
}
|
||||
|
||||
if err = pr.LoadProtectedBranch(ctx); err != nil {
|
||||
return fmt.Errorf("LoadProtectedBranch: %w", err)
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("LoadProtectedBranch: %v", err)
|
||||
}
|
||||
if pr.ProtectedBranch == nil {
|
||||
if pb == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -795,23 +796,23 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
|
||||
}
|
||||
}
|
||||
|
||||
if !issues_model.HasEnoughApprovals(ctx, pr.ProtectedBranch, pr) {
|
||||
if !issues_model.HasEnoughApprovals(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
Reason: "Does not have enough approvals",
|
||||
}
|
||||
}
|
||||
if issues_model.MergeBlockedByRejectedReview(ctx, pr.ProtectedBranch, pr) {
|
||||
if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
Reason: "There are requested changes",
|
||||
}
|
||||
}
|
||||
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pr.ProtectedBranch, pr) {
|
||||
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
Reason: "There are official review requests",
|
||||
}
|
||||
}
|
||||
|
||||
if issues_model.MergeBlockedByOutdatedBranch(pr.ProtectedBranch, pr) {
|
||||
if issues_model.MergeBlockedByOutdatedBranch(pb, pr) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
Reason: "The head branch is behind the base branch",
|
||||
}
|
||||
@@ -821,7 +822,7 @@ func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullReques
|
||||
return nil
|
||||
}
|
||||
|
||||
if pr.ProtectedBranch.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
|
||||
if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
|
||||
return models.ErrDisallowedToMerge{
|
||||
Reason: "Changed protected files",
|
||||
}
|
||||
@@ -836,6 +837,9 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit
|
||||
defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
|
||||
|
||||
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
@@ -106,8 +106,8 @@ func TestPatch(pr *issues_model.PullRequest) error {
|
||||
}
|
||||
|
||||
// 3. Check for protected files changes
|
||||
if err = checkPullFilesProtection(pr, gitRepo); err != nil {
|
||||
return fmt.Errorf("pr.CheckPullFilesProtection(): %w", err)
|
||||
if err = checkPullFilesProtection(ctx, pr, gitRepo); err != nil {
|
||||
return fmt.Errorf("pr.CheckPullFilesProtection(): %v", err)
|
||||
}
|
||||
|
||||
if len(pr.ChangedProtectedFiles) > 0 {
|
||||
@@ -544,23 +544,23 @@ func CheckUnprotectedFiles(repo *git.Repository, oldCommitID, newCommitID string
|
||||
}
|
||||
|
||||
// checkPullFilesProtection check if pr changed protected files and save results
|
||||
func checkPullFilesProtection(pr *issues_model.PullRequest, gitRepo *git.Repository) error {
|
||||
func checkPullFilesProtection(ctx context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) error {
|
||||
if pr.Status == issues_model.PullRequestStatusEmpty {
|
||||
pr.ChangedProtectedFiles = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := pr.LoadProtectedBranch(db.DefaultContext); err != nil {
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pr.ProtectedBranch == nil {
|
||||
if pb == nil {
|
||||
pr.ChangedProtectedFiles = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.MergeBase, "tracking", pr.ProtectedBranch.GetProtectedFilePatterns(), 10, os.Environ())
|
||||
pr.ChangedProtectedFiles, err = CheckFileProtection(gitRepo, pr.MergeBase, "tracking", pb.GetProtectedFilePatterns(), 10, os.Environ())
|
||||
if err != nil && !models.IsErrFilePathProtected(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
+17
-4
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -92,20 +93,29 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
if err := pull.LoadBaseRepo(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
pr := &issues_model.PullRequest{
|
||||
HeadRepoID: pull.BaseRepoID,
|
||||
HeadRepo: pull.BaseRepo,
|
||||
BaseRepoID: pull.HeadRepoID,
|
||||
BaseRepo: pull.HeadRepo,
|
||||
HeadBranch: pull.BaseBranch,
|
||||
BaseBranch: pull.HeadBranch,
|
||||
}
|
||||
|
||||
err = pr.LoadProtectedBranch(ctx)
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
// can't do rebase on protected branch because need force push
|
||||
if pr.ProtectedBranch == nil {
|
||||
if pb == nil {
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err)
|
||||
@@ -115,8 +125,11 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
|
||||
}
|
||||
|
||||
// Update function need push permission
|
||||
if pr.ProtectedBranch != nil && !pr.ProtectedBranch.CanUserPush(ctx, user.ID) {
|
||||
return false, false, nil
|
||||
if pb != nil {
|
||||
pb.Repo = pull.BaseRepo
|
||||
if !pb.CanUserPush(ctx, user) {
|
||||
return false, false, nil
|
||||
}
|
||||
}
|
||||
|
||||
baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, user)
|
||||
|
||||
@@ -303,14 +303,16 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
|
||||
|
||||
// We're going to iterate by pagesize.
|
||||
root := filepath.Clean(setting.RepoRootPath)
|
||||
if err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() || path == root {
|
||||
if !d.IsDir() || path == root {
|
||||
return nil
|
||||
}
|
||||
|
||||
name := d.Name()
|
||||
|
||||
if !strings.ContainsRune(path[len(root)+1:], filepath.Separator) {
|
||||
// Got a new user
|
||||
if err = checkUnadoptedRepositories(userName, repoNamesToCheck, unadopted); err != nil {
|
||||
@@ -318,16 +320,14 @@ func ListUnadoptedRepositories(query string, opts *db.ListOptions) ([]string, in
|
||||
}
|
||||
repoNamesToCheck = repoNamesToCheck[:0]
|
||||
|
||||
if !globUser.Match(info.Name()) {
|
||||
if !globUser.Match(name) {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
userName = info.Name()
|
||||
userName = name
|
||||
return nil
|
||||
}
|
||||
|
||||
name := info.Name()
|
||||
|
||||
if !strings.HasSuffix(name, ".git") {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
@@ -149,8 +149,7 @@ func RenameBranch(repo *repo_model.Repository, doer *user_model.User, gitRepo *g
|
||||
|
||||
// enmuerates all branch related errors
|
||||
var (
|
||||
ErrBranchIsDefault = errors.New("branch is default")
|
||||
ErrBranchIsProtected = errors.New("branch is protected")
|
||||
ErrBranchIsDefault = errors.New("branch is default")
|
||||
)
|
||||
|
||||
// DeleteBranch delete branch
|
||||
@@ -159,13 +158,12 @@ func DeleteBranch(doer *user_model.User, repo *repo_model.Repository, gitRepo *g
|
||||
return ErrBranchIsDefault
|
||||
}
|
||||
|
||||
isProtected, err := git_model.IsProtectedBranch(db.DefaultContext, repo.ID, branchName)
|
||||
isProtected, err := git_model.IsBranchProtected(db.DefaultContext, repo.ID, branchName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isProtected {
|
||||
return ErrBranchIsProtected
|
||||
return git_model.ErrBranchIsProtected
|
||||
}
|
||||
|
||||
commit, err := gitRepo.GetBranchCommit(branchName)
|
||||
|
||||
@@ -66,13 +66,16 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
protectedBranch, err := git_model.GetProtectedBranchBy(ctx, repo.ID, opts.OldBranch)
|
||||
protectedBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, opts.OldBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if protectedBranch != nil && !protectedBranch.CanUserPush(ctx, doer.ID) {
|
||||
return models.ErrUserCannotCommit{
|
||||
UserName: doer.LowerName,
|
||||
if protectedBranch != nil {
|
||||
protectedBranch.Repo = repo
|
||||
if !protectedBranch.CanUserPush(ctx, doer) {
|
||||
return models.ErrUserCannotCommit{
|
||||
UserName: doer.LowerName,
|
||||
}
|
||||
}
|
||||
}
|
||||
if protectedBranch != nil && protectedBranch.RequireSignedCommits {
|
||||
|
||||
@@ -463,17 +463,18 @@ func CreateOrUpdateRepoFile(ctx context.Context, repo *repo_model.Repository, do
|
||||
|
||||
// VerifyBranchProtection verify the branch protection for modifying the given treePath on the given branch
|
||||
func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, branchName, treePath string) error {
|
||||
protectedBranch, err := git_model.GetProtectedBranchBy(ctx, repo.ID, branchName)
|
||||
protectedBranch, err := git_model.GetFirstMatchProtectedBranchRule(ctx, repo.ID, branchName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if protectedBranch != nil {
|
||||
protectedBranch.Repo = repo
|
||||
isUnprotectedFile := false
|
||||
glob := protectedBranch.GetUnprotectedFilePatterns()
|
||||
if len(glob) != 0 {
|
||||
isUnprotectedFile = protectedBranch.IsUnprotectedFile(glob, treePath)
|
||||
}
|
||||
if !protectedBranch.CanUserPush(ctx, doer.ID) && !isUnprotectedFile {
|
||||
if !protectedBranch.CanUserPush(ctx, doer) && !isUnprotectedFile {
|
||||
return models.ErrUserCannotCommit{
|
||||
UserName: doer.LowerName,
|
||||
}
|
||||
|
||||
+66
-31
@@ -5,49 +5,67 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"xorm.io/builder"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func GarbageCollectLFSMetaObjects(ctx context.Context, logger log.Logger, autofix bool) error {
|
||||
log.Trace("Doing: GarbageCollectLFSMetaObjects")
|
||||
|
||||
if err := db.Iterate(
|
||||
ctx,
|
||||
builder.And(builder.Gt{"id": 0}),
|
||||
func(ctx context.Context, repo *repo_model.Repository) error {
|
||||
return GarbageCollectLFSMetaObjectsForRepo(ctx, repo, logger, autofix)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("Finished: GarbageCollectLFSMetaObjects")
|
||||
return nil
|
||||
// GarbageCollectLFSMetaObjectsOptions provides options for GarbageCollectLFSMetaObjects function
|
||||
type GarbageCollectLFSMetaObjectsOptions struct {
|
||||
Logger log.Logger
|
||||
AutoFix bool
|
||||
OlderThan time.Time
|
||||
UpdatedLessRecentlyThan time.Time
|
||||
NumberToCheckPerRepo int64
|
||||
ProportionToCheckPerRepo float64
|
||||
}
|
||||
|
||||
func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.Repository, logger log.Logger, autofix bool) error {
|
||||
if logger != nil {
|
||||
logger.Info("Checking %-v", repo)
|
||||
// GarbageCollectLFSMetaObjects garbage collects LFS objects for all repositories
|
||||
func GarbageCollectLFSMetaObjects(ctx context.Context, opts GarbageCollectLFSMetaObjectsOptions) error {
|
||||
log.Trace("Doing: GarbageCollectLFSMetaObjects")
|
||||
defer log.Trace("Finished: GarbageCollectLFSMetaObjects")
|
||||
|
||||
if !setting.LFS.StartServer {
|
||||
if opts.Logger != nil {
|
||||
opts.Logger.Info("LFS support is disabled")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
total, orphaned, collected, deleted := 0, 0, 0, 0
|
||||
if logger != nil {
|
||||
|
||||
return git_model.IterateRepositoryIDsWithLFSMetaObjects(ctx, func(ctx context.Context, repoID, count int64) error {
|
||||
repo, err := repo_model.GetRepositoryByID(ctx, repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if newMinimum := int64(float64(count) * opts.ProportionToCheckPerRepo); newMinimum > opts.NumberToCheckPerRepo && opts.NumberToCheckPerRepo != 0 {
|
||||
opts.NumberToCheckPerRepo = newMinimum
|
||||
}
|
||||
return GarbageCollectLFSMetaObjectsForRepo(ctx, repo, opts)
|
||||
})
|
||||
}
|
||||
|
||||
// GarbageCollectLFSMetaObjectsForRepo garbage collects LFS objects for a specific repository
|
||||
func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.Repository, opts GarbageCollectLFSMetaObjectsOptions) error {
|
||||
if opts.Logger != nil {
|
||||
opts.Logger.Info("Checking %-v", repo)
|
||||
}
|
||||
total, orphaned, collected, deleted := int64(0), 0, 0, 0
|
||||
if opts.Logger != nil {
|
||||
defer func() {
|
||||
if orphaned == 0 {
|
||||
logger.Info("Found %d total LFSMetaObjects in %-v", total, repo)
|
||||
} else if !autofix {
|
||||
logger.Info("Found %d/%d orphaned LFSMetaObjects in %-v", orphaned, total, repo)
|
||||
opts.Logger.Info("Found %d total LFSMetaObjects in %-v", total, repo)
|
||||
} else if !opts.AutoFix {
|
||||
opts.Logger.Info("Found %d/%d orphaned LFSMetaObjects in %-v", orphaned, total, repo)
|
||||
} else {
|
||||
logger.Info("Collected %d/%d orphaned/%d total LFSMetaObjects in %-v. %d removed from storage.", collected, orphaned, total, repo, deleted)
|
||||
opts.Logger.Info("Collected %d/%d orphaned/%d total LFSMetaObjects in %-v. %d removed from storage.", collected, orphaned, total, repo, deleted)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -60,17 +78,21 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R
|
||||
defer gitRepo.Close()
|
||||
|
||||
store := lfs.NewContentStore()
|
||||
errStop := errors.New("STOPERR")
|
||||
|
||||
return git_model.IterateLFSMetaObjectsForRepo(ctx, repo.ID, func(ctx context.Context, metaObject *git_model.LFSMetaObject, count int64) error {
|
||||
err = git_model.IterateLFSMetaObjectsForRepo(ctx, repo.ID, func(ctx context.Context, metaObject *git_model.LFSMetaObject, count int64) error {
|
||||
if opts.NumberToCheckPerRepo > 0 && total > opts.NumberToCheckPerRepo {
|
||||
return errStop
|
||||
}
|
||||
total++
|
||||
pointerSha := git.ComputeBlobHash([]byte(metaObject.Pointer.StringContent()))
|
||||
|
||||
if gitRepo.IsObjectExist(pointerSha.String()) {
|
||||
return nil
|
||||
return git_model.MarkLFSMetaObject(ctx, metaObject.ID)
|
||||
}
|
||||
orphaned++
|
||||
|
||||
if !autofix {
|
||||
if !opts.AutoFix {
|
||||
return nil
|
||||
}
|
||||
// Non-existent pointer file
|
||||
@@ -100,6 +122,19 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R
|
||||
//
|
||||
// It is likely that a week is potentially excessive but it should definitely be enough that any
|
||||
// unassociated LFS object is genuinely unassociated.
|
||||
OlderThan: time.Now().Add(-24 * 7 * time.Hour),
|
||||
OlderThan: opts.OlderThan,
|
||||
UpdatedLessRecentlyThan: opts.UpdatedLessRecentlyThan,
|
||||
OrderByUpdated: true,
|
||||
LoopFunctionAlwaysUpdates: true,
|
||||
})
|
||||
|
||||
if err == errStop {
|
||||
if opts.Logger != nil {
|
||||
opts.Logger.Info("Processing stopped at %d total LFSMetaObjects in %-v", total, repo)
|
||||
}
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user