Skip to content

Commit 24438cc

Browse files
committed
ls-files: add a --json option
We'd like to have a machine-readable option for ls-files in order to avoid ambiguity in parsing. Let's add a --json option to provide output in JSON format. Note that we use a JSON object with a single item here in order to allow us to emit more data in the future without breaking backward compatibility.
1 parent c9e2a13 commit 24438cc

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

commands/command_ls_files.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package commands
22

33
import (
4+
"encoding/json"
45
"os"
56
"strings"
67

@@ -18,9 +19,20 @@ var (
1819
lsFilesScanDeleted = false
1920
lsFilesShowSize = false
2021
lsFilesShowNameOnly = false
22+
lsFilesJSON = false
2123
debug = false
2224
)
2325

26+
type lsFilesObject struct {
27+
Name string `json:"name"`
28+
Size int64 `json:"size"`
29+
Checkout bool `json:"checkout"`
30+
Downloaded bool `json:"downloaded"`
31+
OidType string `json:"oid_type"`
32+
Oid string `json:"oid"`
33+
Version string `json:"version"`
34+
}
35+
2436
func lsFilesCommand(cmd *cobra.Command, args []string) {
2537
setupRepository()
2638

@@ -67,6 +79,7 @@ func lsFilesCommand(cmd *cobra.Command, args []string) {
6779
}
6880

6981
seen := make(map[string]struct{})
82+
var items []lsFilesObject
7083

7184
gitscanner := lfs.NewGitScanner(cfg, func(p *lfs.WrappedPointer, err error) {
7285
if err != nil {
@@ -96,6 +109,16 @@ func lsFilesCommand(cmd *cobra.Command, args []string) {
96109
p.OidType,
97110
p.Oid,
98111
p.Version))
112+
} else if lsFilesJSON {
113+
items = append(items, lsFilesObject{
114+
Name: p.Name,
115+
Size: p.Size,
116+
Checkout: fileExistsOfSize(p),
117+
Downloaded: cfg.LFSObjectExists(p.Oid, p.Size),
118+
OidType: p.OidType,
119+
Oid: p.Oid,
120+
Version: p.Version,
121+
})
99122
} else {
100123
msg := []string{p.Oid[:showOidLen], lsFilesMarker(p), p.Name}
101124
if lsFilesShowNameOnly {
@@ -144,6 +167,16 @@ func lsFilesCommand(cmd *cobra.Command, args []string) {
144167
Exit(tr.Tr.Get("Could not scan for Git LFS tree: %s", err))
145168
}
146169
}
170+
if lsFilesJSON {
171+
data := struct {
172+
Files []lsFilesObject `json:"files"`
173+
}{Files: items}
174+
encoder := json.NewEncoder(os.Stdout)
175+
encoder.SetIndent("", " ")
176+
if err := encoder.Encode(data); err != nil {
177+
ExitWithError(err)
178+
}
179+
}
147180
}
148181

149182
// Returns true if a pointer appears to be properly smudge on checkout
@@ -170,5 +203,6 @@ func init() {
170203
cmd.Flags().BoolVar(&lsFilesScanDeleted, "deleted", false, "")
171204
cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
172205
cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")
206+
cmd.Flags().BoolVarP(&lsFilesJSON, "json", "", false, "print output in JSON")
173207
})
174208
}

t/t-ls-files.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,60 @@ begin_test "ls-files: not affected by lfs.fetchexclude"
516516
[ "6bbd052ab0 * missing.dat" = "$(git lfs ls-files)" ]
517517
)
518518
end_test
519+
520+
begin_test "ls-files --json"
521+
(
522+
set -e
523+
524+
reponame="ls-files-json"
525+
git init "$reponame"
526+
cd "$reponame"
527+
528+
git lfs track "*.dat" | grep "Tracking \"\*.dat\""
529+
echo "some data" > some.dat
530+
echo "some text" > some.txt
531+
echo "missing" > missing.dat
532+
git add missing.dat
533+
git commit -m "add missing file"
534+
535+
git lfs ls-files --json > actual
536+
cat > expected <<-EOF
537+
{
538+
"files": [
539+
{
540+
"name": "missing.dat",
541+
"size": 8,
542+
"checkout": true,
543+
"downloaded": true,
544+
"oid_type": "sha256",
545+
"oid": "6bbd052ab054ef222c1c87be60cd191addedd24cc882d1f5f7f7be61dc61bb3a",
546+
"version": "https://git-lfs.github.com/spec/v1"
547+
}
548+
]
549+
}
550+
EOF
551+
diff -u actual expected
552+
553+
git rm missing.dat
554+
git add some.dat some.txt
555+
git commit -m "added some files, removed missing one"
556+
557+
git lfs ls-files --json > actual
558+
cat > expected <<-EOF
559+
{
560+
"files": [
561+
{
562+
"name": "some.dat",
563+
"size": 10,
564+
"checkout": true,
565+
"downloaded": true,
566+
"oid_type": "sha256",
567+
"oid": "5aa03f96c77536579166fba147929626cc3a97960e994057a9d80271a736d10f",
568+
"version": "https://git-lfs.github.com/spec/v1"
569+
}
570+
]
571+
}
572+
EOF
573+
diff -u actual expected
574+
)
575+
end_test

0 commit comments

Comments
 (0)