summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2019-11-01 17:50:59 +0000
committertechknowlogick <techknowlogick@gitea.io>2019-11-01 13:50:59 -0400
commit4dac8b2389a6d675eef4a43995cad6e0bbde6a3f (patch)
tree0f2f9f324ead0a2a4a3d7cdd8817bbc772743ef1 /services
parent3341aaf3f062e4bc3caa2f98705b6e26c26e638a (diff)
downloadgitea-4dac8b2389a6d675eef4a43995cad6e0bbde6a3f.tar.gz
gitea-4dac8b2389a6d675eef4a43995cad6e0bbde6a3f.zip
Allow to merge if file path contains " or \ (#8629) (#8771)
* 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>
Diffstat (limited to 'services')
-rw-r--r--services/pull/merge.go26
1 files changed, 24 insertions, 2 deletions
diff --git a/services/pull/merge.go b/services/pull/merge.go
index 6a1c30a63e..db071418da 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -12,6 +12,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "regexp"
"strings"
"code.gitea.io/gitea/models"
@@ -328,16 +329,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
@@ -346,8 +362,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
}