04abbd8436
Following on from the changes in PR #4781, we can make additional message strings translatable using the tr.Tr.Get() method. Because this method performs printf(3)-style format string parsing and interpolation, we can simplify some of the surrounding calls, e.g., from fmt.Errorf() to errors.New(), and from fmt.Fprintf() to fmt.Fprintln(). This ensures that if either the translated text or any interpolated arguments happen to contain character sequences that would be interpreted as Go format specifiers (e.g., "%s" or "%d"), these will not result in warnings such as "%!s(MISSING)" in the output text. Note also that we try to remove newlines from the message strings were possible and change the surrounding calls to append them instead, e.g., with fmt.Fprintln().
94 lines
2.0 KiB
Go
94 lines
2.0 KiB
Go
package git
|
|
|
|
import (
|
|
"bufio"
|
|
"io/ioutil"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/git-lfs/git-lfs/v3/errors"
|
|
"github.com/git-lfs/git-lfs/v3/tools"
|
|
"github.com/git-lfs/git-lfs/v3/tr"
|
|
"github.com/rubyist/tracerx"
|
|
)
|
|
|
|
type lsFileInfo struct {
|
|
BaseName string
|
|
FullPath string
|
|
}
|
|
type LsFiles struct {
|
|
Files map[string]*lsFileInfo
|
|
FilesByName map[string][]*lsFileInfo
|
|
}
|
|
|
|
func NewLsFiles(workingDir string, standardExclude bool, untracked bool) (*LsFiles, error) {
|
|
|
|
args := []string{
|
|
"ls-files",
|
|
"-z", // Use a NUL separator. This also disables the escaping of special characters.
|
|
"--cached",
|
|
}
|
|
|
|
if standardExclude {
|
|
args = append(args, "--exclude-standard")
|
|
}
|
|
if untracked {
|
|
args = append(args, "--others")
|
|
}
|
|
cmd := gitNoLFS(args...)
|
|
cmd.Dir = workingDir
|
|
|
|
tracerx.Printf("NewLsFiles: running in %s git %s",
|
|
workingDir, strings.Join(args, " "))
|
|
|
|
// Capture stdout and stderr
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
stderr, err := cmd.StderrPipe()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
scanner := bufio.NewScanner(stdout)
|
|
scanner.Split(tools.SplitOnNul)
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rv := &LsFiles{
|
|
Files: make(map[string]*lsFileInfo),
|
|
FilesByName: make(map[string][]*lsFileInfo),
|
|
}
|
|
|
|
// Setup a goroutine to drain stderr as large amounts of error output may cause
|
|
// the subprocess to block.
|
|
errorMessages := make(chan []byte)
|
|
go func() {
|
|
msg, _ := ioutil.ReadAll(stderr)
|
|
errorMessages <- msg
|
|
}()
|
|
|
|
// Read all files
|
|
for scanner.Scan() {
|
|
base := path.Base(scanner.Text())
|
|
finfo := &lsFileInfo{
|
|
BaseName: base,
|
|
FullPath: scanner.Text(),
|
|
}
|
|
rv.Files[scanner.Text()] = finfo
|
|
rv.FilesByName[base] = append(rv.FilesByName[base], finfo)
|
|
}
|
|
|
|
// Check the output of the subprocess, output stderr if the command failed.
|
|
msg := <-errorMessages
|
|
if err := cmd.Wait(); err != nil {
|
|
return nil, errors.New(tr.Tr.Get("Error in `git %s`: %v %s",
|
|
strings.Join(args, " "), err, msg))
|
|
}
|
|
|
|
return rv, nil
|
|
}
|