status: update index before showing status

When running `git lfs status`, we perform a `git diff-index`.  However,
we don't update the index first, so any changes, such as permissions
changes due to locking, cause the file to be listed as modified.  Since
these changes don't represent actual changes that we're interested in,
refresh the index before running diff-index so that it doesn't produce
spurious output.
This commit is contained in:
brian m. carlson 2019-11-18 16:41:49 +00:00
parent a0030968ce
commit 228e31fb20
No known key found for this signature in database
GPG Key ID: 2D0C9BC12F82B3A1
5 changed files with 63 additions and 6 deletions

@ -170,12 +170,12 @@ func blobInfo(s *lfs.PointerScanner, blobSha, name string) (sha, from string, er
}
func scanIndex(ref string) (staged, unstaged []*lfs.DiffIndexEntry, err error) {
uncached, err := lfs.NewDiffIndexScanner(ref, false)
uncached, err := lfs.NewDiffIndexScanner(ref, false, true)
if err != nil {
return nil, nil, err
}
cached, err := lfs.NewDiffIndexScanner(ref, true)
cached, err := lfs.NewDiffIndexScanner(ref, true, false)
if err != nil {
return nil, nil, err
}

@ -178,7 +178,14 @@ func CatFile() (*subprocess.BufferedCmd, error) {
return gitNoLFSBuffered("cat-file", "--batch-check")
}
func DiffIndex(ref string, cached bool) (*bufio.Scanner, error) {
func DiffIndex(ref string, cached bool, refresh bool) (*bufio.Scanner, error) {
if refresh {
_, err := gitSimple("update-index", "-q", "--refresh")
if err != nil {
return nil, lfserrors.Wrap(err, "Failed to run git update-index")
}
}
args := []string{"diff-index", "-M"}
if cached {
args = append(args, "--cached")

@ -119,11 +119,16 @@ type DiffIndexScanner struct {
// scan for differences between the given ref and the currently checked out
// tree.
//
// If "refresh" is given, the DiffIndexScanner will refresh the index. This is
// probably what you want in all cases except fsck, where invoking a filtering
// operation would be undesirable due to the possibility of corruption. It can
// also be disabled where another operation will have refreshed the index.
//
// If any error was encountered in starting the command or closing its `stdin`,
// that error will be returned immediately. Otherwise, a `*DiffIndexScanner`
// will be returned with a `nil` error.
func NewDiffIndexScanner(ref string, cached bool) (*DiffIndexScanner, error) {
scanner, err := git.DiffIndex(ref, cached)
func NewDiffIndexScanner(ref string, cached bool, refresh bool) (*DiffIndexScanner, error) {
scanner, err := git.DiffIndex(ref, cached, refresh)
if err != nil {
return nil, err
}

@ -110,7 +110,7 @@ func scanIndex(cb GitScannerFoundPointer, ref string, f *filepathfilter.Filter,
// for in the indexf. It returns a channel from which sha1 strings can be read.
// The namMap will be filled indexFile pointers mapping sha1s to indexFiles.
func revListIndex(atRef string, cache bool, indexMap *indexFileMap) (*StringChannelWrapper, error) {
scanner, err := NewDiffIndexScanner(atRef, cache)
scanner, err := NewDiffIndexScanner(atRef, cache, false)
if err != nil {
return nil, err
}

@ -548,3 +548,48 @@ Git LFS objects not staged for commit:"
[ "$expected" = "$(git lfs status)" ]
)
end_test
begin_test "status: permission change"
(
set -e
# We're using chmod below.
if [ "$IS_WINDOWS" -eq 1 ]; then
exit 0
fi
reponame="status-permission-change"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
contents="contents"
git lfs track "*.dat"
git add .gitattributes
git commit -m "track *.dat"
printf "%s" "$contents" > a.dat
git add a.dat
git commit -m "add a.dat"
chmod 400 a.dat
# A permission change should not result in any output.
git lfs status 2>&1 | tee status.log
if [ "0" -ne "${PIPESTATUS[0]}" ]; then
echo >&2 "git lfs status should have succeeded, didn't ..."
exit 1
fi
expected="On branch master
Git LFS objects to be committed:
Git LFS objects not staged for commit:"
actual="$(cat status.log)"
[ "$expected" = "$actual" ]
)
end_test