cc7b83a9b9
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).
153 lines
3.6 KiB
Go
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")
|
|
})
|
|
}
|