mirror of https://github.com/go-gitea/gitea.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
2.3 KiB
93 lines
2.3 KiB
// Copyright 2025 The Gitea Authors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
|
|
package gitrepo |
|
|
|
import ( |
|
"bufio" |
|
"bytes" |
|
"context" |
|
"io" |
|
|
|
"code.gitea.io/gitea/modules/git/gitcmd" |
|
"code.gitea.io/gitea/modules/log" |
|
) |
|
|
|
// CommitFileStatus represents status of files in a commit. |
|
type CommitFileStatus struct { |
|
Added []string |
|
Removed []string |
|
Modified []string |
|
} |
|
|
|
// NewCommitFileStatus creates a CommitFileStatus |
|
func NewCommitFileStatus() *CommitFileStatus { |
|
return &CommitFileStatus{ |
|
[]string{}, []string{}, []string{}, |
|
} |
|
} |
|
|
|
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.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, 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(ctx context.Context, repo Repository, commitID string) (*CommitFileStatus, error) { |
|
stdout, w := io.Pipe() |
|
done := make(chan struct{}) |
|
fileStatus := NewCommitFileStatus() |
|
go func() { |
|
parseCommitFileStatus(fileStatus, stdout) |
|
close(done) |
|
}() |
|
|
|
stderr := new(bytes.Buffer) |
|
err := gitcmd.NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1"). |
|
AddDynamicArguments(commitID). |
|
WithDir(repoPath(repo)). |
|
WithStdout(w). |
|
WithStderr(stderr). |
|
Run(ctx) |
|
w.Close() // Close writer to exit parsing goroutine |
|
if err != nil { |
|
return nil, gitcmd.ConcatenateError(err, stderr.String()) |
|
} |
|
|
|
<-done |
|
return fileStatus, nil |
|
}
|
|
|