git-lfs/git/ls_files.go
Chris Darroch ed3decf753 use backticks around commands in messages
A number of message strings contain embedded Git or Git LFS
commands, and while in many cases these are already delimited
with backticks, in other cases they are not.

We therefore rework the formatting of these messages to accord
with the general practice of using backticks to delimit "git"
and "git lfs" commands.

In one case for the "git lfs clone" command this requires us
to split a multi-line message into several parts, but that
also has the advantage that we can move some of the fixed
formatting and newlines out of the translatable message strings.

Note that some of these messages are not yet passed as translation
strings, but we will address that issue in a subsequent commit.
2022-01-29 22:35:10 -08:00

93 lines
1.9 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/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.Errorf("Error in `git %s`: %v %s",
strings.Join(args, " "), err, msg)
}
return rv, nil
}