]> source.dussan.org Git - gitea.git/commitdiff
Allow to merge if file path contains " or \ (#8629)
authorIlya <ilux@cpan.org>
Fri, 1 Nov 2019 00:30:02 +0000 (03:30 +0300)
committerzeripath <art27@cantab.net>
Fri, 1 Nov 2019 00:30:02 +0000 (00:30 +0000)
* if a filename in a repository contains " or \ the owner can't merge pull request with this files
because "git diff-tree" adds double quotes to that filepath
example: filepath is ab"cd but "git diff-tree" returns "ab\"cd"

now, when the owner click "Merge Pull Request" button the server returns 500
this commit fix it

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* add -z option to getDiffTree
escape spec symbols for sparse-checkout

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* go fmt

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* typo

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* escape '\'
escape all spaces and '!'

* use regexp.ReplaceAllString()

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* strings.ReplaceAll was added in go 1.12

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
* add '\' to regexp.MustCompile

Signed-off-by: Ilya Pavlov <ilux@cpan.org>
services/pull/merge.go

index 5eb8eaa4d4701e4818cbdddb06880a9dd5b983fc..2e093eef86afd27f233685757a849ac64fe8f6dc 100644 (file)
@@ -12,6 +12,7 @@ import (
        "io/ioutil"
        "os"
        "path/filepath"
+       "regexp"
        "strings"
        "time"
 
@@ -374,16 +375,31 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
        return nil
 }
 
+var escapedSymbols = regexp.MustCompile(`([*[?! \\])`)
+
 func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) {
        getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) {
                var outbuf, errbuf strings.Builder
                // Compute the diff-tree for sparse-checkout
-               if err := git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "--root", baseBranch, headBranch, "--").RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
+               if err := git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root", baseBranch, headBranch, "--").RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
                        return "", fmt.Errorf("git diff-tree [%s base:%s head:%s]: %s", repoPath, baseBranch, headBranch, errbuf.String())
                }
                return outbuf.String(), nil
        }
 
+       scanNullTerminatedStrings := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+               if atEOF && len(data) == 0 {
+                       return 0, nil, nil
+               }
+               if i := bytes.IndexByte(data, '\x00'); i >= 0 {
+                       return i + 1, data[0:i], nil
+               }
+               if atEOF {
+                       return len(data), data, nil
+               }
+               return 0, nil, nil
+       }
+
        list, err := getDiffTreeFromBranch(repoPath, baseBranch, headBranch)
        if err != nil {
                return "", err
@@ -392,8 +408,14 @@ func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) {
        // Prefixing '/' for each entry, otherwise all files with the same name in subdirectories would be matched.
        out := bytes.Buffer{}
        scanner := bufio.NewScanner(strings.NewReader(list))
+       scanner.Split(scanNullTerminatedStrings)
        for scanner.Scan() {
-               fmt.Fprintf(&out, "/%s\n", scanner.Text())
+               filepath := scanner.Text()
+               // escape '*', '?', '[', spaces and '!' prefix
+               filepath = escapedSymbols.ReplaceAllString(filepath, `\$1`)
+               // no necessary to escape the first '#' symbol because the first symbol is '/'
+               fmt.Fprintf(&out, "/%s\n", filepath)
        }
+
        return out.String(), nil
 }