1
1
Fork 1
mirror of https://github.com/go-gitea/gitea.git synced 2024-05-29 16:46:18 +02:00

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>
This commit is contained in:
zeripath 2021-07-02 20:23:37 +01:00 committed by GitHub
parent 836884429a
commit 62c278e4ab
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 152 additions and 18 deletions

View File

@ -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())

File diff suppressed because one or more lines are too long