diff options
author | Jimmy Praet <jimmy.praet@telenet.be> | 2021-09-11 16:21:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-11 16:21:17 +0200 |
commit | 3d6cb25e315c0d4249c5c749a2eb8c64ec463aad (patch) | |
tree | bf9ba30a34e0e97b6a52584caffa1d3d9fe2506d /services | |
parent | eb03e819d323f6374d0a99a5b80d4674a18fa957 (diff) | |
download | gitea-3d6cb25e315c0d4249c5c749a2eb8c64ec463aad.tar.gz gitea-3d6cb25e315c0d4249c5c749a2eb8c64ec463aad.zip |
Support unprotected file patterns (#16395)
Fixes #16381
Note that changes to unprotected files via the web editor still cannot be pushed directly to the protected branch. I could easily add such support for edits and deletes if needed. But for adding, uploading or renaming unprotected files, it is not trivial.
* Extract & Move GetAffectedFiles to modules/git
Diffstat (limited to 'services')
-rw-r--r-- | services/forms/repo_form.go | 1 | ||||
-rw-r--r-- | services/pull/patch.go | 95 |
2 files changed, 43 insertions, 53 deletions
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index c1c146f234..1210d5dfc5 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -199,6 +199,7 @@ type ProtectBranchForm struct { DismissStaleApprovals bool RequireSignedCommits bool ProtectedFilePatterns string + UnprotectedFilePatterns string } // Validate validates the fields diff --git a/services/pull/patch.go b/services/pull/patch.go index 72b459bf2c..73b979f647 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -245,70 +245,59 @@ func checkConflicts(pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath // CheckFileProtection check file Protection func CheckFileProtection(oldCommitID, newCommitID string, patterns []glob.Glob, limit int, env []string, repo *git.Repository) ([]string, error) { - // 1. If there are no patterns short-circuit and just return nil if len(patterns) == 0 { return nil, nil } - - // 2. Prep the pipe - stdoutReader, stdoutWriter, err := os.Pipe() + affectedFiles, err := git.GetAffectedFiles(oldCommitID, newCommitID, env, repo) if err != nil { - log.Error("Unable to create os.Pipe for %s", repo.Path) return nil, err } - defer func() { - _ = stdoutReader.Close() - _ = stdoutWriter.Close() - }() - changedProtectedFiles := make([]string, 0, limit) - - // 3. Run `git diff --name-only` to get the names of the changed files - err = git.NewCommand("diff", "--name-only", oldCommitID, newCommitID). - RunInDirTimeoutEnvFullPipelineFunc(env, -1, repo.Path, - stdoutWriter, nil, nil, - func(ctx context.Context, cancel context.CancelFunc) error { - // Close the writer end of the pipe to begin processing - _ = stdoutWriter.Close() - defer func() { - // Close the reader on return to terminate the git command if necessary - _ = stdoutReader.Close() - }() - - // Now scan the output from the command - scanner := bufio.NewScanner(stdoutReader) - for scanner.Scan() { - path := strings.TrimSpace(scanner.Text()) - if len(path) == 0 { - continue - } - lpath := strings.ToLower(path) - for _, pat := range patterns { - if pat.Match(lpath) { - changedProtectedFiles = append(changedProtectedFiles, path) - break - } - } - if len(changedProtectedFiles) >= limit { - break - } - } - - if len(changedProtectedFiles) > 0 { - return models.ErrFilePathProtected{ - Path: changedProtectedFiles[0], - } - } - return scanner.Err() - }) - // 4. log real errors if there are any... - if err != nil && !models.IsErrFilePathProtected(err) { - log.Error("Unable to check file protection for commits from %s to %s in %s: %v", oldCommitID, newCommitID, repo.Path, err) + for _, affectedFile := range affectedFiles { + lpath := strings.ToLower(affectedFile) + for _, pat := range patterns { + if pat.Match(lpath) { + changedProtectedFiles = append(changedProtectedFiles, lpath) + break + } + } + if len(changedProtectedFiles) >= limit { + break + } + } + if len(changedProtectedFiles) > 0 { + err = models.ErrFilePathProtected{ + Path: changedProtectedFiles[0], + } } - return changedProtectedFiles, err } +// CheckUnprotectedFiles check if the commit only touches unprotected files +func CheckUnprotectedFiles(oldCommitID, newCommitID string, patterns []glob.Glob, env []string, repo *git.Repository) (bool, error) { + if len(patterns) == 0 { + return false, nil + } + affectedFiles, err := git.GetAffectedFiles(oldCommitID, newCommitID, env, repo) + if err != nil { + return false, err + } + for _, affectedFile := range affectedFiles { + lpath := strings.ToLower(affectedFile) + unprotected := false + for _, pat := range patterns { + if pat.Match(lpath) { + unprotected = true + break + } + } + if !unprotected { + return false, nil + } + } + return true, nil +} + // checkPullFilesProtection check if pr changed protected files and save results func checkPullFilesProtection(pr *models.PullRequest, gitRepo *git.Repository) error { if err := pr.LoadProtectedBranch(); err != nil { |