git-lfs/commands/command_ls_files.go
Taylor Blau cc7b83a9b9 commands/command_ls_files: hide index with arguments
Since e2717688 (commands: scan repository index in git-lfs-ls-files(1),
2017-12-19), we have traversed the contents of the index when showing
files in 'git lfs ls-files'.

The purpose of this was to match behavior in 'git ls-files', where the
index is also shown by default.

However, when given an argument, 'git lfs ls-files' will traverse
starting from a specific revision, so showing the index unconditionally
causes a problem here. It does not make sense to show the current state
of the index when listing files when given a starting point explicitly.

So, let's skip calling into the gitscanner code when given an explicit
reference to start from (even if that reference is HEAD, since this
likely indicates that the user does not want to scan the index, too).
2018-09-05 10:33:27 -04:00

153 lines
3.6 KiB
Go

package commands
import (
"os"
"strings"
"github.com/git-lfs/git-lfs/git"
"github.com/git-lfs/git-lfs/lfs"
"github.com/git-lfs/git-lfs/tools/humanize"
"github.com/spf13/cobra"
)
var (
longOIDs = false
lsFilesScanAll = false
lsFilesScanDeleted = false
lsFilesShowSize = false
debug = false
)
func lsFilesCommand(cmd *cobra.Command, args []string) {
requireInRepo()
var ref string
if len(args) == 1 {
if lsFilesScanAll {
Exit("fatal: cannot use --all with explicit reference")
} else if args[0] == "--all" {
// Since --all is a valid argument to "git rev-parse",
// if we try to give it to git.ResolveRef below, we'll
// get an unexpected result.
//
// So, let's check early that the caller invoked the
// command correctly.
Exit("fatal: did you mean \"git lfs ls-files --all --\" ?")
}
ref = args[0]
} else {
fullref, err := git.CurrentRef()
if err != nil {
ref = git.RefBeforeFirstCommit
} else {
ref = fullref.Sha
}
}
showOidLen := 10
if longOIDs {
showOidLen = 64
}
seen := make(map[string]struct{})
gitscanner := lfs.NewGitScanner(func(p *lfs.WrappedPointer, err error) {
if err != nil {
Exit("Could not scan for Git LFS tree: %s", err)
return
}
if !lsFilesScanAll {
if _, ok := seen[p.Name]; ok {
return
}
}
if debug {
Print(
"filepath: %s\n"+
" size: %d\n"+
"checkout: %v\n"+
"download: %v\n"+
" oid: %s %s\n"+
" version: %s\n",
p.Name,
p.Size,
fileExistsOfSize(p),
cfg.LFSObjectExists(p.Oid, p.Size),
p.OidType,
p.Oid,
p.Version)
} else {
msg := []string{p.Oid[:showOidLen], lsFilesMarker(p), p.Name}
if lsFilesShowSize {
size := humanize.FormatBytes(uint64(p.Size))
msg = append(msg, "("+size+")")
}
Print(strings.Join(msg, " "))
}
seen[p.Name] = struct{}{}
})
defer gitscanner.Close()
includeArg, excludeArg := getIncludeExcludeArgs(cmd)
gitscanner.Filter = buildFilepathFilter(cfg, includeArg, excludeArg)
if len(args) == 0 {
// Only scan the index when "git lfs ls-files" was invoked with
// no arguments.
//
// Do so to avoid showing "mixed" results, e.g., ls-files output
// from a specific historical revision, and the index.
if err := gitscanner.ScanIndex(ref, nil); err != nil {
Exit("Could not scan for Git LFS index: %s", err)
}
}
if lsFilesScanAll {
if err := gitscanner.ScanAll(nil); err != nil {
Exit("Could not scan for Git LFS history: %s", err)
}
} else {
var err error
if lsFilesScanDeleted {
err = gitscanner.ScanRefWithDeleted(ref, nil)
} else {
err = gitscanner.ScanTree(ref)
}
if err != nil {
Exit("Could not scan for Git LFS tree: %s", err)
}
}
}
// Returns true if a pointer appears to be properly smudge on checkout
func fileExistsOfSize(p *lfs.WrappedPointer) bool {
path := cfg.Filesystem().DecodePathname(p.Name)
info, err := os.Stat(path)
return err == nil && info.Size() == p.Size
}
func lsFilesMarker(p *lfs.WrappedPointer) string {
if fileExistsOfSize(p) {
return "*"
}
return "-"
}
func init() {
RegisterCommand("ls-files", lsFilesCommand, func(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&longOIDs, "long", "l", false, "")
cmd.Flags().BoolVarP(&lsFilesShowSize, "size", "s", false, "")
cmd.Flags().BoolVarP(&debug, "debug", "d", false, "")
cmd.Flags().BoolVarP(&lsFilesScanAll, "all", "a", false, "")
cmd.Flags().BoolVar(&lsFilesScanDeleted, "deleted", false, "")
cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")
})
}