Skip to content

Commit a60a77d

Browse files
committed
WIP
1 parent 415a80c commit a60a77d

File tree

2 files changed

+40
-51
lines changed

2 files changed

+40
-51
lines changed

commands/command_fetch.go

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var (
1919
fetchRecentArg bool
2020
fetchAllArg bool
2121
fetchPruneArg bool
22+
fetchDryRunArg bool
2223
)
2324

2425
func getIncludeExcludeArgs(cmd *cobra.Command) (include, exclude *string) {
@@ -106,7 +107,7 @@ func fetchCommand(cmd *cobra.Command, args []string) {
106107
verifyUnreachable := fetchPruneCfg.PruneVerifyUnreachableAlways
107108

108109
// assume false for non available options in fetch
109-
prune(fetchPruneCfg, verify, verifyUnreachable, false, false, false)
110+
prune(fetchPruneCfg, verify, verifyUnreachable, false, fetchDryRunArg, fetchDryRunArg)
110111
}
111112

112113
if !success {
@@ -147,7 +148,7 @@ func fetchRef(ref string, filter *filepathfilter.Filter) bool {
147148
if err != nil {
148149
Panic(err, tr.Tr.Get("Could not scan for Git LFS files"))
149150
}
150-
return fetchAndReportToChan(pointers, filter, nil)
151+
return fetch(pointers)
151152
}
152153

153154
func pointersToFetchForRefs(refs []string) ([]*lfs.WrappedPointer, error) {
@@ -189,7 +190,7 @@ func fetchRefs(refs []string) bool {
189190
if err != nil {
190191
Panic(err, tr.Tr.Get("Could not scan for Git LFS files"))
191192
}
192-
return fetchAndReportToChan(pointers, nil, nil)
193+
return fetch(pointers)
193194
}
194195

195196
// Fetch all previous versions of objects from since to ref (not including final state at ref)
@@ -212,7 +213,7 @@ func fetchPreviousVersions(ref string, since time.Time, filter *filepathfilter.F
212213
ExitWithError(err)
213214
}
214215

215-
return fetchAndReportToChan(pointers, filter, nil)
216+
return fetch(pointers)
216217
}
217218

218219
// Fetch recent objects based on config
@@ -282,7 +283,7 @@ func fetchRecent(fetchconf lfs.FetchPruneConfig, alreadyFetchedRefs []*git.Ref,
282283
func fetchAll() bool {
283284
pointers := scanAll()
284285
Print("fetch: %s", tr.Tr.Get("Fetching all references..."))
285-
return fetchAndReportToChan(pointers, nil, nil)
286+
return fetch(pointers)
286287
}
287288

288289
func scanAll() []*lfs.WrappedPointer {
@@ -323,44 +324,23 @@ func scanAll() []*lfs.WrappedPointer {
323324
return pointers
324325
}
325326

326-
// Fetch and report completion of each OID to a channel (optional, pass nil to skip)
327+
func printTransfers(out <-chan *tq.Transfer) {
328+
for p := range out {
329+
Print("%s %s => %s", tr.Tr.Get("fetch"), p.Oid, p.Name)
330+
}
331+
}
332+
333+
// Fetch
327334
// Returns true if all completed with no errors, false if errors were written to stderr/log
328-
func fetchAndReportToChan(allpointers []*lfs.WrappedPointer, filter *filepathfilter.Filter, out chan<- *lfs.WrappedPointer) bool {
329-
ready, pointers, meter := readyAndMissingPointers(allpointers, filter)
335+
func fetch(allpointers []*lfs.WrappedPointer) bool {
336+
pointers, meter := missingPointers(allpointers)
330337
q := newDownloadQueue(
331338
getTransferManifestOperationRemote("download", cfg.Remote()),
332-
cfg.Remote(), tq.WithProgress(meter),
339+
cfg.Remote(), tq.WithProgress(meter), tq.DryRun(fetchDryRunArg),
333340
)
334341

335-
if out != nil {
336-
// If we already have it, or it won't be fetched
337-
// report it to chan immediately to support pull/checkout
338-
for _, p := range ready {
339-
out <- p
340-
}
341-
342-
dlwatch := q.Watch()
343-
344-
go func() {
345-
// fetch only reports single OID, but OID *might* be referenced by multiple
346-
// WrappedPointers if same content is at multiple paths, so map oid->slice
347-
oidToPointers := make(map[string][]*lfs.WrappedPointer, len(pointers))
348-
for _, pointer := range pointers {
349-
plist := oidToPointers[pointer.Oid]
350-
oidToPointers[pointer.Oid] = append(plist, pointer)
351-
}
352-
353-
for t := range dlwatch {
354-
plist, ok := oidToPointers[t.Oid]
355-
if !ok {
356-
continue
357-
}
358-
for _, p := range plist {
359-
out <- p
360-
}
361-
}
362-
close(out)
363-
}()
342+
if fetchDryRunArg {
343+
go printTransfers(q.Watch())
364344
}
365345

366346
for _, p := range pointers {
@@ -381,37 +361,27 @@ func fetchAndReportToChan(allpointers []*lfs.WrappedPointer, filter *filepathfil
381361
return ok
382362
}
383363

384-
func readyAndMissingPointers(allpointers []*lfs.WrappedPointer, filter *filepathfilter.Filter) ([]*lfs.WrappedPointer, []*lfs.WrappedPointer, *tq.Meter) {
364+
func missingPointers(allpointers []*lfs.WrappedPointer) ([]*lfs.WrappedPointer, *tq.Meter) {
385365
logger := tasklog.NewLogger(os.Stdout,
386366
tasklog.ForceProgress(cfg.ForceProgress()),
387367
)
388-
meter := buildProgressMeter(false, tq.Download)
368+
meter := buildProgressMeter(fetchDryRunArg, tq.Download)
389369
logger.Enqueue(meter)
390370

391-
seen := make(map[string]bool, len(allpointers))
392371
missing := make([]*lfs.WrappedPointer, 0, len(allpointers))
393-
ready := make([]*lfs.WrappedPointer, 0, len(allpointers))
394372

395373
for _, p := range allpointers {
396-
// no need to download the same object multiple times
397-
if seen[p.Oid] {
398-
continue
399-
}
400-
401-
seen[p.Oid] = true
402-
403374
// no need to download objects that exist locally already
404375
lfs.LinkOrCopyFromReference(cfg, p.Oid, p.Size)
405376
if cfg.LFSObjectExists(p.Oid, p.Size) {
406-
ready = append(ready, p)
407377
continue
408378
}
409379

410380
missing = append(missing, p)
411381
meter.Add(p.Size)
412382
}
413383

414-
return ready, missing, meter
384+
return missing, meter
415385
}
416386

417387
func init() {
@@ -421,5 +391,6 @@ func init() {
421391
cmd.Flags().BoolVarP(&fetchRecentArg, "recent", "r", false, "Fetch recent refs & commits")
422392
cmd.Flags().BoolVarP(&fetchAllArg, "all", "a", false, "Fetch all LFS files ever referenced")
423393
cmd.Flags().BoolVarP(&fetchPruneArg, "prune", "p", false, "After fetching, prune old data")
394+
cmd.Flags().BoolVarP(&fetchDryRunArg, "dry-run", "d", false, "Do not fetch, only show what would be fetched")
424395
})
425396
}

t/t-fetch.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,19 @@ begin_test "fetch"
6363
cd clone
6464
rm -rf .git/lfs/objects
6565

66+
git lfs fetch --dry-run 2>&1 | tee fetch.log
67+
grep "fetch $contents_oid => a\.dat" fetch.log
68+
refute_local_object "$contents_oid"
69+
6670
git lfs fetch
6771
assert_local_object "$contents_oid" 1
6872

6973
git lfs fsck 2>&1 | tee fsck.log
7074
grep "Git LFS fsck OK" fsck.log
75+
76+
git lfs fetch --dry-run 2>&1 | tee fetch.log
77+
grep "fetch .* => a\.dat" fetch.log && exit 1
78+
true
7179
)
7280
end_test
7381

@@ -128,12 +136,22 @@ begin_test "fetch with remote and branches"
128136

129137
rm -rf .git/lfs/objects
130138

139+
git lfs fetch origin main newbranch --dry-run | tee fetch.log
140+
grep "fetch $contents_oid => a\.dat" fetch.log
141+
grep "fetch $b_oid => b\.dat" fetch.log
142+
refute_local_object "$contents_oid"
143+
refute_local_object "$b_oid"
144+
131145
git lfs fetch origin main newbranch
132146
assert_local_object "$contents_oid" 1
133147
assert_local_object "$b_oid" 1
134148

135149
git lfs fsck 2>&1 | tee fsck.log
136150
grep "Git LFS fsck OK" fsck.log
151+
152+
git lfs fetch origin main newbranch --dry-run | tee fetch.log
153+
grep "fetch .* => [ab]\.dat" fetch.log && exit 1
154+
true
137155
)
138156
end_test
139157

0 commit comments

Comments
 (0)