Skip to content

Commit af8346e

Browse files
committed
Merge branch 'main' into drop-command-prefixes
2 parents c79822f + 2b8db3f commit af8346e

File tree

14 files changed

+110
-117
lines changed

14 files changed

+110
-117
lines changed

commands/command_fetch.go

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,28 @@ import (
1818
)
1919

2020
var (
21-
fetchRecentArg bool
22-
fetchAllArg bool
23-
fetchPruneArg bool
24-
fetchDryRunArg bool
25-
fetchJsonArg bool
21+
fetchRecentArg bool
22+
fetchAllArg bool
23+
fetchPruneArg bool
24+
fetchRefetchArg bool
25+
fetchDryRunArg bool
26+
fetchJsonArg bool
2627
)
2728

2829
type fetchWatcher struct {
29-
transfers []*tq.Transfer
30-
virtuallyFetched map[string]bool
31-
}
32-
33-
func newfetchWatcher() *fetchWatcher {
34-
ret := &fetchWatcher{}
35-
if fetchJsonArg {
36-
ret.transfers = make([]*tq.Transfer, 0)
37-
}
38-
if fetchDryRunArg {
39-
ret.virtuallyFetched = make(map[string]bool)
40-
}
41-
return ret
30+
transfers []*tq.Transfer
31+
observed map[string]bool
4232
}
4333

4434
func (d *fetchWatcher) registerTransfer(t *tq.Transfer) {
45-
if d.transfers != nil {
35+
if fetchJsonArg {
4636
d.transfers = append(d.transfers, t)
4737
}
48-
if d.virtuallyFetched != nil {
49-
d.virtuallyFetched[t.Oid] = true
38+
if fetchDryRunArg || fetchRefetchArg {
39+
if d.observed == nil {
40+
d.observed = make(map[string]bool)
41+
}
42+
d.observed[t.Oid] = true
5043
}
5144
if fetchDryRunArg {
5245
printProgress("%s %s => %s", tr.Tr.Get("fetch"), t.Oid, t.Name)
@@ -57,15 +50,18 @@ func (d *fetchWatcher) dumpJson() {
5750
data := struct {
5851
Transfers []*tq.Transfer `json:"transfers"`
5952
}{Transfers: d.transfers}
53+
if data.Transfers == nil {
54+
data.Transfers = []*tq.Transfer{}
55+
}
6056
encoder := json.NewEncoder(os.Stdout)
6157
encoder.SetIndent("", " ")
6258
if err := encoder.Encode(data); err != nil {
6359
ExitWithError(err)
6460
}
6561
}
6662

67-
func (d *fetchWatcher) hasVirtuallyFetched(oid string) bool {
68-
return d.virtuallyFetched[oid]
63+
func (d *fetchWatcher) hasObserved(oid string) bool {
64+
return d.observed[oid]
6965
}
7066

7167
func hasToPrintTransfers() bool {
@@ -126,7 +122,7 @@ func fetchCommand(cmd *cobra.Command, args []string) {
126122
include, exclude := getIncludeExcludeArgs(cmd)
127123
fetchPruneCfg := lfs.NewFetchPruneConfig(cfg.Git)
128124

129-
watcher := newfetchWatcher()
125+
watcher := &fetchWatcher{}
130126

131127
if fetchAllArg {
132128
if fetchRecentArg {
@@ -392,8 +388,8 @@ func scanAll() []*lfs.WrappedPointer {
392388

393389
// Fetch
394390
// Returns true if all completed with no errors, false if errors were written to stderr/log
395-
func fetch(allpointers []*lfs.WrappedPointer, watcher *fetchWatcher) bool {
396-
pointers, meter := missingPointers(allpointers, watcher)
391+
func fetch(allPointers []*lfs.WrappedPointer, watcher *fetchWatcher) bool {
392+
pointersToFetch, meter := pointersToFetch(allPointers, watcher)
397393
q := newDownloadQueue(
398394
getTransferManifestOperationRemote("download", cfg.Remote()),
399395
cfg.Remote(), tq.WithProgress(meter), tq.DryRun(fetchDryRunArg),
@@ -411,7 +407,7 @@ func fetch(allpointers []*lfs.WrappedPointer, watcher *fetchWatcher) bool {
411407
}()
412408
}
413409

414-
for _, p := range pointers {
410+
for _, p := range pointersToFetch {
415411
tracerx.Printf("fetch %v [%v]", p.Name, p.Oid)
416412

417413
q.Add(downloadTransfer(p))
@@ -432,31 +428,38 @@ func fetch(allpointers []*lfs.WrappedPointer, watcher *fetchWatcher) bool {
432428
return ok
433429
}
434430

435-
func missingPointers(allpointers []*lfs.WrappedPointer, watcher *fetchWatcher) ([]*lfs.WrappedPointer, *tq.Meter) {
431+
func pointersToFetch(allPointers []*lfs.WrappedPointer, watcher *fetchWatcher) ([]*lfs.WrappedPointer, *tq.Meter) {
436432
logger := tasklog.NewLogger(os.Stdout,
437433
tasklog.ForceProgress(cfg.ForceProgress()),
438434
)
439435
meter := buildProgressMeter(hasToPrintTransfers(), tq.Download)
440436
logger.Enqueue(meter)
441437

442-
missing := make([]*lfs.WrappedPointer, 0, len(allpointers))
438+
pointersToFetch := make([]*lfs.WrappedPointer, 0, len(allPointers))
443439

444-
for _, p := range allpointers {
445-
// no need to download objects that exist locally already
446-
lfs.LinkOrCopyFromReference(cfg, p.Oid, p.Size)
447-
if cfg.LFSObjectExists(p.Oid, p.Size) {
440+
for _, p := range allPointers {
441+
// if running with --dry-run or --refetch, skip objects that have already been virtually or
442+
// already forcefully fetched
443+
if watcher != nil && watcher.hasObserved(p.Oid) {
448444
continue
449445
}
450-
// also if running with --dry-run, skip objects that have already been virtually fetched
451-
if watcher != nil && watcher.hasVirtuallyFetched(p.Oid) {
446+
447+
// empty files are special, we always skip them in upload/download operations
448+
if p.Size == 0 {
449+
continue
450+
}
451+
452+
// no need to download objects that exist locally already, unless `--refetch` was provided
453+
lfs.LinkOrCopyFromReference(cfg, p.Oid, p.Size)
454+
if !fetchRefetchArg && cfg.LFSObjectExists(p.Oid, p.Size) {
452455
continue
453456
}
454457

455-
missing = append(missing, p)
458+
pointersToFetch = append(pointersToFetch, p)
456459
meter.Add(p.Size)
457460
}
458461

459-
return missing, meter
462+
return pointersToFetch, meter
460463
}
461464

462465
func init() {
@@ -466,6 +469,7 @@ func init() {
466469
cmd.Flags().BoolVarP(&fetchRecentArg, "recent", "r", false, "Fetch recent refs & commits")
467470
cmd.Flags().BoolVarP(&fetchAllArg, "all", "a", false, "Fetch all LFS files ever referenced")
468471
cmd.Flags().BoolVarP(&fetchPruneArg, "prune", "p", false, "After fetching, prune old data")
472+
cmd.Flags().BoolVar(&fetchRefetchArg, "refetch", false, "Also fetch objects that are already present locally")
469473
cmd.Flags().BoolVarP(&fetchDryRunArg, "dry-run", "d", false, "Do not fetch, only show what would be fetched")
470474
cmd.Flags().BoolVarP(&fetchJsonArg, "json", "j", false, "Give the output in a stable JSON format for scripts")
471475
})

commands/command_locks.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"github.com/git-lfs/git-lfs/v3/errors"
1010
"github.com/git-lfs/git-lfs/v3/git"
1111
"github.com/git-lfs/git-lfs/v3/locking"
12-
"github.com/git-lfs/git-lfs/v3/tools"
1312
"github.com/git-lfs/git-lfs/v3/tr"
1413
"github.com/spf13/cobra"
1514
)
@@ -96,9 +95,9 @@ func locksCommand(cmd *cobra.Command, args []string) {
9695
for _, lock := range locks {
9796
lockPaths = append(lockPaths, lock.Path)
9897
locksByPath[lock.Path] = lock
99-
maxPathLen = tools.MaxInt(maxPathLen, len(lock.Path))
98+
maxPathLen = max(maxPathLen, len(lock.Path))
10099
if lock.Owner != nil {
101-
maxNameLen = tools.MaxInt(maxNameLen, len(lock.Owner.Name))
100+
maxNameLen = max(maxNameLen, len(lock.Owner.Name))
102101
}
103102
}
104103

@@ -110,8 +109,8 @@ func locksCommand(cmd *cobra.Command, args []string) {
110109
ownerName = lock.Owner.Name
111110
}
112111

113-
pathPadding := tools.MaxInt(maxPathLen-len(lock.Path), 0)
114-
namePadding := tools.MaxInt(maxNameLen-len(ownerName), 0)
112+
pathPadding := max(maxPathLen-len(lock.Path), 0)
113+
namePadding := max(maxNameLen-len(ownerName), 0)
115114
kind := ""
116115
if locksOwned != nil {
117116
if locksOwned[lock] {

docs/man/git-lfs-checkout.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ $ git merge conflicting-branch
6969
CONFLICT (content): Merge conflict in path/to/conflicting/file.dat
7070
7171
# Checkout versions of the conflicting file into temp files
72-
$ git lfs checkout ours.dat --ours path/to/conflicting/file.dat
73-
$ git lfs checkout theirs.dat --theirs path/to/conflicting/file.dat
72+
$ git lfs checkout --to ours.dat --ours path/to/conflicting/file.dat
73+
$ git lfs checkout --to theirs.dat --theirs path/to/conflicting/file.dat
7474
7575
# Compare conflicting versions in ours.dat and theirs.dat,
7676
# then resolve conflict (e.g., by choosing one version over

docs/man/git-lfs-fetch.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ This does not update the working copy.
3939
`-p`::
4040
Prune old and unreferenced objects after fetching, equivalent to running `git
4141
lfs prune` afterwards. See git-lfs-prune(1) for more details.
42+
`--refetch`::
43+
Also fetch objects that are already present locally.
4244
`--dry-run`::
4345
`-d`::
4446
Print what would be fetched, without actually fetching anything.

git/githistory/ref_updater.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/git-lfs/git-lfs/v3/errors"
99
"github.com/git-lfs/git-lfs/v3/git"
1010
"github.com/git-lfs/git-lfs/v3/tasklog"
11-
"github.com/git-lfs/git-lfs/v3/tools"
1211
"github.com/git-lfs/git-lfs/v3/tr"
1312
"github.com/git-lfs/gitobj/v2"
1413
)
@@ -46,7 +45,7 @@ func (r *refUpdater) updateRefs() error {
4645

4746
var maxNameLen int
4847
for _, ref := range r.refs {
49-
maxNameLen = tools.MaxInt(maxNameLen, len(ref.Name))
48+
maxNameLen = max(maxNameLen, len(ref.Name))
5049
}
5150

5251
seen := make(map[string]struct{})
@@ -144,7 +143,7 @@ func (r *refUpdater) updateOneRef(list *tasklog.ListTask, maxNameLen int, seen m
144143
return err
145144
}
146145

147-
namePadding := tools.MaxInt(maxNameLen-len(ref.Name), 0)
146+
namePadding := max(maxNameLen-len(ref.Name), 0)
148147
list.Entry(fmt.Sprintf(" %s%s\t%s -> %x", ref.Name, strings.Repeat(" ", namePadding), ref.Sha, to))
149148
return nil
150149
}

lfshttp/client.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/git-lfs/git-lfs/v3/config"
2222
"github.com/git-lfs/git-lfs/v3/creds"
2323
"github.com/git-lfs/git-lfs/v3/errors"
24-
"github.com/git-lfs/git-lfs/v3/tools"
2524
"github.com/git-lfs/git-lfs/v3/tr"
2625
"github.com/rubyist/tracerx"
2726
"golang.org/x/net/http2"
@@ -215,7 +214,7 @@ func (c *Client) sshResolveWithRetries(e Endpoint, method string) (*sshAuthRespo
215214
return nil, errors.New("git-lfs-authenticate has been disabled by request")
216215
}
217216

218-
requests := tools.MaxInt(0, c.sshTries) + 1
217+
requests := max(0, c.sshTries) + 1
219218
for i := 0; i < requests; i++ {
220219
sshRes, err = c.SSH.Resolve(e, method)
221220
if err == nil {
@@ -293,7 +292,7 @@ func (c *Client) DoWithRedirect(cli *http.Client, req *http.Request, remote stri
293292

294293
var res *http.Response
295294

296-
requests := tools.MaxInt(0, retries) + 1
295+
requests := max(0, retries) + 1
297296
for i := 0; i < requests; i++ {
298297
res, err = cli.Do(req)
299298
if err == nil {

lfshttp/stats.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import (
1111
"sync"
1212
"sync/atomic"
1313
"time"
14-
15-
"github.com/git-lfs/git-lfs/v3/tools"
1614
)
1715

1816
type httpTransfer struct {
@@ -140,11 +138,11 @@ func (l *syncLogger) LogResponse(req *http.Request, status int, bodySize int64)
140138
fmt.Sprintf(" status=%d body=%d conntime=%d dnstime=%d tlstime=%d restime=%d time=%d",
141139
status,
142140
bodySize,
143-
tools.MaxInt64(t.ConnEnd-t.ConnStart, 0),
144-
tools.MaxInt64(t.DNSEnd-t.DNSStart, 0),
145-
tools.MaxInt64(t.TLSEnd-t.TLSStart, 0),
146-
tools.MaxInt64(now-t.ResponseStart, 0),
147-
tools.MaxInt64(now-t.Start, 0),
141+
max(t.ConnEnd-t.ConnStart, 0),
142+
max(t.DNSEnd-t.DNSStart, 0),
143+
max(t.TLSEnd-t.TLSStart, 0),
144+
max(now-t.ResponseStart, 0),
145+
max(now-t.Start, 0),
148146
))
149147
}
150148
}

t/t-fetch.sh

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ begin_test "init for fetch tests"
4141

4242
assert_server_object "$reponame" "$contents_oid"
4343

44+
# Add an empty file
45+
touch empty.dat
46+
git add empty.dat
47+
git commit -m 'empty'
48+
4449
# Add a file in a different branch
4550
git checkout -b newbranch
4651
printf "%s" "$b" > b.dat
@@ -118,17 +123,20 @@ EOF
118123
)
119124
end_test
120125

121-
begin_test "fetch (empty file)"
126+
begin_test "fetch --refetch"
122127
(
123128
set -e
124129
cd clone
125130
rm -rf .git/lfs/objects
126131

127-
touch empty.dat
128-
git add empty.dat
129-
git commit -m 'empty'
130-
131132
git lfs fetch
133+
assert_local_object "$contents_oid" 1
134+
135+
corrupt_local_object "$contents_oid"
136+
refute_local_object "$contents_oid" 1
137+
138+
git lfs fetch --refetch
139+
assert_local_object "$contents_oid" 1
132140

133141
git lfs fsck 2>&1 | tee fsck.log
134142
grep "Git LFS fsck OK" fsck.log
@@ -257,6 +265,36 @@ EOF
257265
)
258266
end_test
259267

268+
begin_test "fetch --refetch with remote and branches"
269+
(
270+
set -e
271+
cd clone
272+
273+
git checkout newbranch
274+
git checkout main
275+
276+
rm -rf .git/lfs/objects
277+
278+
git lfs fetch origin main newbranch
279+
assert_local_object "$contents_oid" 1
280+
assert_local_object "$b_oid" 1
281+
282+
corrupt_local_object "$contents_oid"
283+
corrupt_local_object "$b_oid"
284+
refute_local_object "$contents_oid" 1
285+
refute_local_object "$b_oid" 1
286+
287+
git lfs fetch --refetch --json origin main newbranch | tee fetch.json
288+
assert_local_object "$contents_oid" 1
289+
assert_local_object "$b_oid" 1
290+
291+
# check that we did not fetch a.dat twice
292+
[ 1 -eq $(grep -c '"name": "a.dat"' fetch.json) ]
293+
git lfs fsck 2>&1 | tee fsck.log
294+
grep "Git LFS fsck OK" fsck.log
295+
)
296+
end_test
297+
260298
begin_test "fetch with main commit sha1"
261299
(
262300
set -e

tasklog/log.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"sync"
99
"time"
1010

11-
"github.com/git-lfs/git-lfs/v3/tools"
1211
isatty "github.com/mattn/go-isatty"
1312
"github.com/olekukonko/ts"
1413
)
@@ -254,7 +253,7 @@ func (l *Logger) logTask(task Task) {
254253
// It returns the number of bytes "n" written to the sink and the error "err",
255254
// if one was encountered.
256255
func (l *Logger) logLine(str string) (n int, err error) {
257-
padding := strings.Repeat(" ", tools.MaxInt(0, l.widthFn()-len(str)))
256+
padding := strings.Repeat(" ", max(0, l.widthFn()-len(str)))
258257

259258
return l.log(str + padding + "\r")
260259
}

0 commit comments

Comments
 (0)