Merge pull request #3080 from git-lfs/status-in-sub-directory

commands/status.go: relative paths outside of root
This commit is contained in:
Taylor Blau 2018-06-25 10:47:25 -05:00 committed by GitHub
commit df881bf23a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 4 deletions

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
@ -52,19 +53,29 @@ func statusCommand(cmd *cobra.Command, args []string) {
ExitWithError(err) ExitWithError(err)
} }
wd, _ := os.Getwd()
repo := cfg.LocalWorkingDir()
Print("\nGit LFS objects to be committed:\n") Print("\nGit LFS objects to be committed:\n")
for _, entry := range staged { for _, entry := range staged {
// Find a path from the current working directory to the
// absolute path of each side of the entry.
src := relativize(wd, filepath.Join(repo, entry.SrcName))
dst := relativize(wd, filepath.Join(repo, entry.DstName))
switch entry.Status { switch entry.Status {
case lfs.StatusRename, lfs.StatusCopy: case lfs.StatusRename, lfs.StatusCopy:
Print("\t%s -> %s (%s)", entry.SrcName, entry.DstName, formatBlobInfo(scanner, entry)) Print("\t%s -> %s (%s)", src, dst, formatBlobInfo(scanner, entry))
default: default:
Print("\t%s (%s)", entry.SrcName, formatBlobInfo(scanner, entry)) Print("\t%s (%s)", src, formatBlobInfo(scanner, entry))
} }
} }
Print("\nGit LFS objects not staged for commit:\n") Print("\nGit LFS objects not staged for commit:\n")
for _, entry := range unstaged { for _, entry := range unstaged {
Print("\t%s (%s)", entry.SrcName, formatBlobInfo(scanner, entry)) src := relativize(wd, filepath.Join(repo, entry.SrcName))
Print("\t%s (%s)", src, formatBlobInfo(scanner, entry))
} }
Print("") Print("")
@ -134,7 +145,7 @@ func blobInfo(s *lfs.PointerScanner, blobSha, name string) (sha, from string, er
return s.ContentsSha()[:7], from, nil return s.ContentsSha()[:7], from, nil
} }
f, err := os.Open(name) f, err := os.Open(filepath.Join(cfg.LocalWorkingDir(), name))
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -311,6 +322,39 @@ func porcelainStatusLine(entry *lfs.DiffIndexEntry) string {
return fmt.Sprintf("%s %s", entry.Status, entry.SrcName) return fmt.Sprintf("%s %s", entry.Status, entry.SrcName)
} }
// relativize relatives a path from "from" to "to". For instance, note that, for
// any paths "from" and "to", that:
//
// to == filepath.Clean(filepath.Join(from, relativize(from, to)))
func relativize(from, to string) string {
if len(from) == 0 {
return to
}
flist := strings.Split(filepath.ToSlash(from), "/")
tlist := strings.Split(filepath.ToSlash(to), "/")
var (
divergence int
min int
)
if lf, lt := len(flist), len(tlist); lf < lt {
min = lf
} else {
min = lt
}
for ; divergence < min; divergence++ {
if flist[divergence] != tlist[divergence] {
break
}
}
return strings.Repeat("../", len(flist)-divergence) +
strings.Join(tlist[divergence:], "/")
}
func init() { func init() {
RegisterCommand("status", statusCommand, func(cmd *cobra.Command) { RegisterCommand("status", statusCommand, func(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&porcelain, "porcelain", "p", false, "Give the output in an easy-to-parse format for scripts.") cmd.Flags().BoolVarP(&porcelain, "porcelain", "p", false, "Give the output in an easy-to-parse format for scripts.")

@ -119,6 +119,34 @@ begin_test "status --json"
) )
end_test end_test
begin_test "status in a sub-directory"
(
set -e
reponame="status-sub-directory"
git init "$reponame"
cd "$reponame"
git lfs track "*.dat"
printf "asdf" > file.dat
mkdir -p dir
git add .gitattributes file.dat
git commit -m "initial commit"
printf "ASDF" > file.dat
expected="On branch master
Git LFS objects to be committed:
Git LFS objects not staged for commit:
../file.dat (LFS: f0e4c2f -> File: 99b3bcf)"
[ "$expected" = "$(cd dir && git lfs status)" ]
)
end_test
begin_test "status: outside git repository" begin_test "status: outside git repository"
( (