commands/command_pointer.go: introduce --check option

We have used the 'git-lfs-pointer(1)' command historically to compare
varying implementation of the Git LFS protocol. This has been done by
passing both `--file` and `--stdin` to the command, which will in turn
compare the contents of both handles and return appropriately whether
they are the same or different.

One use case that Git LFS pointer does not yet support directly is
_checking_ to see whether a given file is a valid Git LFS pointer. This
is a different use-case than before, since we aren't doing any
comparison, we're simply checking whether the official implementation of
Git LFS can parse a given stream as a pointer.

As an aside, one way to do this today is the following:

  $ git lfs clean < a.txt | git lfs pointer --stdin --file my.ptr

Where we first generate a pointer of the file 'a.txt' (via
`git-lfs-clean(1)`), and then redirect that to `git-lfs-pointer(1)`
against our own file.

Let's make this above incantation easier to execute by providing a
functionally equivalent `--check` option. Running `git lfs pointer
--check` (and passing either `--file`, or `--stdin`) will return either
1 or 0 depending on whether or not the given pointer file was invalid or
not.
This commit is contained in:
Taylor Blau 2019-01-29 14:39:09 -08:00
parent 3473b85482
commit c5bfafb83d
3 changed files with 96 additions and 3 deletions

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"github.com/git-lfs/git-lfs/git"
@ -18,6 +19,7 @@ var (
pointerFile string
pointerCompare string
pointerStdin bool
pointerCheck bool
)
func pointerCommand(cmd *cobra.Command, args []string) {
@ -26,6 +28,36 @@ func pointerCommand(cmd *cobra.Command, args []string) {
buildOid := ""
compareOid := ""
if pointerCheck {
var r io.ReadCloser
var err error
if len(pointerCompare) > 0 {
ExitWithError(fmt.Errorf("fatal: cannot combine --check with --compare"))
}
if len(pointerFile) > 0 {
if pointerStdin {
ExitWithError(fmt.Errorf("fatal: with --check, --file cannot be combined with --stdin"))
}
r, err = os.Open(pointerFile)
if err != nil {
ExitWithError(err)
}
} else if pointerStdin {
r = ioutil.NopCloser(os.Stdin)
} else {
ExitWithError(fmt.Errorf("fatal: must specify either --file or --stdin with --compare"))
}
_, err = lfs.DecodePointer(r)
if err != nil {
os.Exit(1)
}
r.Close()
return
}
if len(pointerCompare) > 0 || pointerStdin {
comparing = true
}
@ -129,5 +161,6 @@ func init() {
cmd.Flags().StringVarP(&pointerFile, "file", "f", "", "Path to a local file to generate the pointer from.")
cmd.Flags().StringVarP(&pointerCompare, "pointer", "p", "", "Path to a local file containing a pointer built by another Git LFS implementation.")
cmd.Flags().BoolVarP(&pointerStdin, "stdin", "", false, "Read a pointer built by another Git LFS implementation through STDIN.")
cmd.Flags().BoolVarP(&pointerCheck, "check", "", false, "Check whether the given file is a Git LFS pointer.")
})
}

@ -1,11 +1,12 @@
git-lfs-pointer(1) -- Build and compare pointers
================================================
git-lfs-pointer(1) -- Build, compare, and check pointers
========================================================
## SYNOPSIS
`git lfs pointer --file=path/to/file`<br>
`git lfs pointer --file=path/to/file --pointer=path/to/pointer`<br>
`git lfs pointer --file=path/to/file --stdin`
`git lfs pointer --check --file=path/to/file`
## Description
@ -25,6 +26,12 @@ between different Git LFS implementations.
Reads the pointer from STDIN to compare with the pointer generated from
`--file`.
* `--check`:
Reads the pointer from STDIN (if `--stdin` is given) or the filepath (if
`--file`) is given. If neither or both of `--stdin` and `--file` are given,
the invocation is invalid. Exits 0 if the data read is a valid Git LFS
pointer. Exits 1 otherwise.
## SEE ALSO
Part of the git-lfs(1) suite.

@ -2,7 +2,6 @@
. "$(dirname "$0")/testlib.sh"
begin_test "pointer --file --stdin"
(
set -e
@ -302,3 +301,57 @@ begin_test "pointer to console"
grep "oid sha256:e96ec1bd71eea8df78b24c64a7ab9d42dd7f821c4e503f0e2288273b9bff6c16" pointer.txt
)
end_test
begin_test "pointer --check (with valid pointer)"
(
set -e
reponame="pointer---check-valid-pointer"
git init "$reponame"
cd "$reponame"
echo "contents" > good.txt
git lfs pointer --file good.txt > good.ptr
cat good.ptr
git lfs pointer --check --file good.ptr
git lfs pointer --check --stdin < good.ptr
)
end_test
begin_test "pointer --check (with invalid pointer)"
(
set -e
reponame="pointer---check-invalid-pointer"
git init "$reponame"
cd "$reponame"
echo "not-a-pointer" > bad.ptr
! git lfs pointer --check --file bad.ptr
! git lfs pointer --check --stdin < bad.ptr
)
end_test
begin_test "pointer --check (with invalid arguments)"
(
set -e
reponame="pointer---check-invalid-pointer"
git init "$reponame"
cd "$reponame"
touch a.txt
# git-lfs-pointer(1) --check with invalid combination --compare
! git lfs pointer --check --compare
# git-lfs-pointer(1) --check without --file or --stdin
! git lfs pointer --check
# git-lfs-pointer(1) --check with --file and --stdin
! git lfs pointer --check --file a.txt --stdin
)
end_test