summaryrefslogtreecommitdiffstats
path: root/modules/git/commit.go
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2021-07-02 20:23:37 +0100
committerGitHub <noreply@github.com>2021-07-02 21:23:37 +0200
commit62c278e4ab66090f48b7937717b28a657cab8688 (patch)
tree240da3c53d43d306f68ed2fe69d59c11dd6f32a7 /modules/git/commit.go
parent836884429ae6d08909f4f96fbe0f1ea288e7af12 (diff)
downloadgitea-62c278e4ab66090f48b7937717b28a657cab8688.tar.gz
gitea-62c278e4ab66090f48b7937717b28a657cab8688.zip
Fix modified files list in webhooks when there is a space (#16288)
* Fix modified files list in webhooks when there is a space There is an unfortunate bug with GetCommitFileStatus where files with spaces are misparsed and split at the space. There is a second bug because modern gits detect renames meaning that this function no longer works correctly. There is a third bug in that merge commits don't have their modified files detected correctly. Fix #15865 Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'modules/git/commit.go')
-rw-r--r--modules/git/commit.go64
1 files changed, 46 insertions, 18 deletions
diff --git a/modules/git/commit.go b/modules/git/commit.go
index f4d6075fe2..3ce2b03886 100644
--- a/modules/git/commit.go
+++ b/modules/git/commit.go
@@ -15,6 +15,8 @@ import (
"os/exec"
"strconv"
"strings"
+
+ "code.gitea.io/gitea/modules/log"
)
// Commit represents a git commit.
@@ -432,33 +434,59 @@ func NewCommitFileStatus() *CommitFileStatus {
}
}
+func parseCommitFileStatus(fileStatus *CommitFileStatus, stdout io.Reader) {
+ rd := bufio.NewReader(stdout)
+ peek, err := rd.Peek(1)
+ if err != nil {
+ if err != io.EOF {
+ log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err)
+ }
+ return
+ }
+ if peek[0] == '\n' || peek[0] == '\x00' {
+ _, _ = rd.Discard(1)
+ }
+ for {
+ modifier, err := rd.ReadSlice('\x00')
+ if err != nil {
+ if err != io.EOF {
+ log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err)
+ }
+ return
+ }
+ file, err := rd.ReadString('\x00')
+ if err != nil {
+ if err != io.EOF {
+ log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err)
+ }
+ return
+ }
+ file = file[:len(file)-1]
+ switch modifier[0] {
+ case 'A':
+ fileStatus.Added = append(fileStatus.Added, file)
+ case 'D':
+ fileStatus.Removed = append(fileStatus.Removed, file)
+ case 'M':
+ fileStatus.Modified = append(fileStatus.Modified, file)
+ }
+ }
+}
+
// GetCommitFileStatus returns file status of commit in given repository.
func GetCommitFileStatus(repoPath, commitID string) (*CommitFileStatus, error) {
stdout, w := io.Pipe()
done := make(chan struct{})
fileStatus := NewCommitFileStatus()
go func() {
- scanner := bufio.NewScanner(stdout)
- for scanner.Scan() {
- fields := strings.Fields(scanner.Text())
- if len(fields) < 2 {
- continue
- }
-
- switch fields[0][0] {
- case 'A':
- fileStatus.Added = append(fileStatus.Added, fields[1])
- case 'D':
- fileStatus.Removed = append(fileStatus.Removed, fields[1])
- case 'M':
- fileStatus.Modified = append(fileStatus.Modified, fields[1])
- }
- }
- done <- struct{}{}
+ parseCommitFileStatus(fileStatus, stdout)
+ close(done)
}()
stderr := new(bytes.Buffer)
- err := NewCommand("show", "--name-status", "--pretty=format:''", commitID).RunInDirPipeline(repoPath, w, stderr)
+ args := []string{"log", "--name-status", "-c", "--pretty=format:", "--parents", "--no-renames", "-z", "-1", commitID}
+
+ err := NewCommand(args...).RunInDirPipeline(repoPath, w, stderr)
w.Close() // Close writer to exit parsing goroutine
if err != nil {
return nil, ConcatenateError(err, stderr.String())