aboutsummaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJimmy Praet <jimmy.praet@telenet.be>2021-09-11 16:21:17 +0200
committerGitHub <noreply@github.com>2021-09-11 16:21:17 +0200
commit3d6cb25e315c0d4249c5c749a2eb8c64ec463aad (patch)
treebf9ba30a34e0e97b6a52584caffa1d3d9fe2506d /services
parenteb03e819d323f6374d0a99a5b80d4674a18fa957 (diff)
downloadgitea-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.go1
-rw-r--r--services/pull/patch.go95
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 {