mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 11:18:33 +00:00 
			
		
		
		
	Allow to merge if file path contains " or \ (#8629)
* 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>
This commit is contained in:
		| @@ -12,6 +12,7 @@ import ( | |||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"regexp" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| @@ -374,16 +375,31 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var escapedSymbols = regexp.MustCompile(`([*[?! \\])`) | ||||||
|  |  | ||||||
| func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) { | func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) { | ||||||
| 	getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) { | 	getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) { | ||||||
| 		var outbuf, errbuf strings.Builder | 		var outbuf, errbuf strings.Builder | ||||||
| 		// Compute the diff-tree for sparse-checkout | 		// 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 "", fmt.Errorf("git diff-tree [%s base:%s head:%s]: %s", repoPath, baseBranch, headBranch, errbuf.String()) | ||||||
| 		} | 		} | ||||||
| 		return outbuf.String(), nil | 		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) | 	list, err := getDiffTreeFromBranch(repoPath, baseBranch, headBranch) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		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. | 	// Prefixing '/' for each entry, otherwise all files with the same name in subdirectories would be matched. | ||||||
| 	out := bytes.Buffer{} | 	out := bytes.Buffer{} | ||||||
| 	scanner := bufio.NewScanner(strings.NewReader(list)) | 	scanner := bufio.NewScanner(strings.NewReader(list)) | ||||||
|  | 	scanner.Split(scanNullTerminatedStrings) | ||||||
| 	for scanner.Scan() { | 	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 | 	return out.String(), nil | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user