git-lfs/git/ls_files.go
brian m. carlson cd1577af24
post-checkout: don't modify permissions of untracked files
Git doesn't know about untracked files, so we should avoid modifying
them when we adjust permissions in the post-checkout hook.  Add an
option to our invocation of git ls-files that controls the use of the
--others flag (which controls listing untracked files), and disable it
when we're looking for files to process with the post-checkout hook.
2021-12-06 13:44:33 +00: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
}