Skip to content

Commit d7917d8

Browse files
authored
Merge pull request git-lfs#6252 from chrisd8088/fix-standalone-adapter-crash
Fix standalone adapter crash and ignore invalid custom adapter names
2 parents 1529d04 + af9e046 commit d7917d8

12 files changed

Lines changed: 436 additions & 37 deletions

commands/command_migrate_export.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func migrateExportCommand(cmd *cobra.Command, args []string) {
121121

122122
// If we have a valid remote, pre-download all objects using the Transfer Queue
123123
if remoteURL != "" {
124-
q := newDownloadQueue(getTransferManifestOperationRemote("Download", remote), remote)
124+
q := newDownloadQueue(getTransferManifestOperationRemote("download", remote), remote)
125125
gs := lfs.NewGitScanner(cfg, func(p *lfs.WrappedPointer, err error) {
126126
if err != nil {
127127
return

docs/custom-transfers.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ without querying the server, by using the following config option:
3737
configure a custom transfer agent for individual remotes.
3838
`lfs.standalonetransferagent` unconditionally configures a custom transfer
3939
agent for all remotes. The custom transfer agent must be specified in
40-
a `lfs.customtransfer.<name>` settings group.
40+
a `lfs.customtransfer.<name>` settings group, or else must be the internal
41+
`lfs-standalone-file` transfer adapter. Other values will be ignored.
4142

4243
## Defining a Custom Transfer Type
4344

docs/man/git-lfs-config.adoc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,13 @@ removed, and tus.io uploads will be available for all clients.
158158
+
159159
Allows the specified custom transfer agent to be used directly for
160160
transferring files, without asking the server how the transfers should
161-
be made. The custom transfer agent has to be defined in a
162-
`lfs.customtransfer.<name>` settings group.
161+
be made. The custom transfer agent must be defined in a
162+
`lfs.customtransfer.<name>` settings group, or else must be the internal
163+
`lfs-standalone-file` transfer adapter. Other values will be ignored.
164+
+
165+
See git-lfs-standalone-file(1) for details of the internal
166+
`lfs-standalone-file` custom transfer adapter, which is intended for
167+
use with local `file:///` URLs.
163168
* `lfs.customtransfer.<name>.path`
164169
+
165170
`lfs.customtransfer.<name>` is a settings group which defines a custom
@@ -169,13 +174,23 @@ should point to the process you wish to invoke. The protocol between the
169174
git-lfs client and the custom transfer process is documented at
170175
https://github.com/git-lfs/git-lfs/blob/main/docs/custom-transfers.md
171176
+
172-
The `<name>` must be a unique identifier that the LFS server understands. When
177+
The `<name>` must be a unique identifier that the LFS server understands
178+
and which does not conflict with the name of any pre-defined internal
179+
transfer adapter in the client such as "basic" or "ssh", as these will
180+
always override a custom transfer adapter with the same name. When
173181
calling the LFS API the client will include a list of supported transfer
174182
types. If the server also supports this named transfer type, it will
175183
select it and actions returned from the API will be in relation to that
176184
transfer type (may not be traditional URLs for example). Only if the
177185
server accepts as a transfer it supports will this custom transfer
178186
process be invoked.
187+
+
188+
If multiple `lfs.customtransfer.<name>` settings are defined, they
189+
must all be contained within the same configuration sub-section,
190+
meaning that the sub-section portion of their names must be identical.
191+
For instance, if `lfs.customTransfer.myAdapter.path` is defined,
192+
then `lfs.customTransfer.myAdapter.args` will be accepted, while
193+
`lfs.customtransfer.myadapter.args` will not.
179194
* `lfs.customtransfer.<name>.args`
180195
+
181196
If the custom transfer process requires any arguments, these can be
@@ -469,6 +484,6 @@ The set of keys allowed in this file is restricted for security reasons.
469484

470485
== SEE ALSO
471486

472-
git-config(1), git-lfs-install(1), gitattributes(5), gitignore(5).
487+
git-config(1), git-lfs-install(1), git-lfs-standalone-file(1), gitattributes(5), gitignore(5).
473488

474489
Part of the git-lfs(1) suite.

t/t-custom-transfers.sh

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,302 @@ begin_test "custom-transfer-standalone-urlmatch"
285285
git lfs fsck
286286
)
287287
end_test
288+
289+
begin_test "standalone agent without custom group (file transfers allowed)"
290+
(
291+
set -e
292+
293+
reponame="custom-transfer-standalone-valid-file"
294+
setup_remote_repo "$reponame"
295+
296+
# Clone directly, not through lfstest-gitserver.
297+
clone_repo_url "$REMOTEDIR/$reponame.git" "$reponame"
298+
299+
# When the remote has a file:// URL, we permit the standalone transfer
300+
# agent to be set to the internal "lfs-standalone-file" adapter without
301+
# any "lfs.customtransfer.*" settings.
302+
git config lfs.standaloneTransferAgent lfs-standalone-file
303+
304+
git lfs track "*.bin"
305+
306+
contents="a"
307+
contents_oid="$(calc_oid "$contents")"
308+
printf "%s" "$contents" >a.bin
309+
310+
git add .gitattributes a.bin
311+
git commit -m "initial commit"
312+
313+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
314+
[ 0 -eq "${PIPESTATUS[0]}" ]
315+
316+
assert_remote_object "$reponame" "$contents_oid" "${#contents}"
317+
318+
rm -rf .git/lfs/objects
319+
320+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
321+
[ 0 -eq "${PIPESTATUS[0]}" ]
322+
323+
[ 0 -eq "$(grep -c "not a registered custom transfer adapter" pull.log)" ]
324+
325+
assert_local_object "$contents_oid" "${#contents}"
326+
)
327+
end_test
328+
329+
begin_test "standalone agent without custom group (file transfers disallowed)"
330+
(
331+
set -e
332+
333+
reponame="custom-transfer-standalone-invalid-file"
334+
setup_remote_repo "$reponame"
335+
clone_repo "$reponame" "$reponame"
336+
337+
git lfs track "*.bin"
338+
339+
contents="a"
340+
contents_oid="$(calc_oid "$contents")"
341+
printf "%s" "$contents" >a.bin
342+
343+
git add .gitattributes a.bin
344+
git commit -m "initial commit"
345+
346+
git push origin main
347+
348+
# When the remote has an HTTP URL, we expect an error if the standalone
349+
# transfer agent is set to the internal "lfs-standalone-file" adapter.
350+
git config lfs.standaloneTransferAgent lfs-standalone-file
351+
352+
rm -rf .git/lfs/objects
353+
354+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
355+
[ 0 -ne "${PIPESTATUS[0]}" ]
356+
357+
grep "error initializing custom adapter \"lfs-standalone-file\"" pull.log
358+
grep "error creating handler: no valid file:// URLs found" pull.log
359+
grep "Failed to fetch some objects" pull.log
360+
361+
[ 0 -eq "$(grep -c "not a registered custom transfer adapter" pull.log)" ]
362+
363+
refute_local_object "$contents_oid"
364+
)
365+
end_test
366+
367+
begin_test "standalone agent without custom group ignored (basic transfers)"
368+
(
369+
set -e
370+
371+
reponame="custom-transfer-standalone-ignored-basic"
372+
setup_remote_repo "$reponame"
373+
clone_repo "$reponame" "$reponame"
374+
375+
# The standalone transfer agent should be ignored if it is set to the
376+
# internal "basic" adapter, regardless of whether that adapter is
377+
# actually used for HTTP requests to the Batch API.
378+
git config lfs.standaloneTransferAgent basic
379+
380+
git lfs track "*.bin"
381+
382+
contents="a"
383+
contents_oid="$(calc_oid "$contents")"
384+
printf "%s" "$contents" >a.bin
385+
386+
git add .gitattributes a.bin
387+
git commit -m "initial commit"
388+
389+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
390+
[ 0 -eq "${PIPESTATUS[0]}" ]
391+
392+
grep "standalone agent \"basic\" is not a registered custom transfer adapter; ignoring" push.log
393+
394+
assert_server_object "$reponame" "$contents_oid"
395+
396+
rm -rf .git/lfs/objects
397+
398+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
399+
[ 0 -eq "${PIPESTATUS[0]}" ]
400+
401+
grep "standalone agent \"basic\" is not a registered custom transfer adapter; ignoring" pull.log
402+
403+
assert_local_object "$contents_oid" "${#contents}"
404+
405+
# The standalone transfer agent should still be ignored even when
406+
# a custom transfer adapter is registered with the same name as the
407+
# internal "basic" adapter.
408+
git config lfs.customTransfer.basic.path path-to-nothing
409+
410+
contents="b"
411+
contents_oid="$(calc_oid "$contents")"
412+
printf "%s" "$contents" >b.bin
413+
414+
git add b.bin
415+
git commit -m "second commit"
416+
417+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
418+
[ 0 -eq "${PIPESTATUS[0]}" ]
419+
420+
grep "standalone agent \"basic\" is not a registered custom transfer adapter; ignoring" push.log
421+
grep "custom upload transfer adapter \"basic\" ignored due to conflict with standard adapter" push.log
422+
grep "custom download transfer adapter \"basic\" ignored due to conflict with standard adapter" push.log
423+
424+
assert_server_object "$reponame" "$contents_oid"
425+
426+
rm -rf .git/lfs/objects
427+
428+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
429+
[ 0 -eq "${PIPESTATUS[0]}" ]
430+
431+
grep "standalone agent \"basic\" is not a registered custom transfer adapter; ignoring" pull.log
432+
grep "custom upload transfer adapter \"basic\" ignored due to conflict with standard adapter" pull.log
433+
grep "custom download transfer adapter \"basic\" ignored due to conflict with standard adapter" pull.log
434+
435+
assert_local_object "$contents_oid" "${#contents}"
436+
)
437+
end_test
438+
439+
begin_test "standalone agent without custom group ignored (basic transfers not ssh)"
440+
(
441+
set -e
442+
443+
reponame="custom-transfer-standalone-ignored-basic-ssh"
444+
setup_remote_repo "$reponame"
445+
clone_repo "$reponame" "$reponame"
446+
447+
# The standalone transfer agent should be ignored if it is set to the
448+
# internal "ssh" adapter, regardless of whether the internal "basic"
449+
# adapter will actually be used for HTTP requests to the Batch API.
450+
git config lfs.standaloneTransferAgent ssh
451+
452+
git lfs track "*.bin"
453+
454+
contents="a"
455+
contents_oid="$(calc_oid "$contents")"
456+
printf "%s" "$contents" >a.bin
457+
458+
git add .gitattributes a.bin
459+
git commit -m "initial commit"
460+
461+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
462+
[ 0 -eq "${PIPESTATUS[0]}" ]
463+
464+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" push.log
465+
466+
assert_server_object "$reponame" "$contents_oid"
467+
468+
rm -rf .git/lfs/objects
469+
470+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
471+
[ 0 -eq "${PIPESTATUS[0]}" ]
472+
473+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" pull.log
474+
475+
assert_local_object "$contents_oid" "${#contents}"
476+
477+
# The standalone transfer agent should still be ignored even when
478+
# a custom transfer adapter is registered with the same name as the
479+
# internal "ssh" adapter.
480+
git config lfs.customTransfer.ssh.path path-to-nothing
481+
482+
contents="b"
483+
contents_oid="$(calc_oid "$contents")"
484+
printf "%s" "$contents" >b.bin
485+
486+
git add b.bin
487+
git commit -m "second commit"
488+
489+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
490+
[ 0 -eq "${PIPESTATUS[0]}" ]
491+
492+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" push.log
493+
grep "custom upload transfer adapter \"ssh\" ignored due to conflict with standard adapter" push.log
494+
grep "custom download transfer adapter \"ssh\" ignored due to conflict with standard adapter" push.log
495+
496+
assert_server_object "$reponame" "$contents_oid"
497+
498+
rm -rf .git/lfs/objects
499+
500+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
501+
[ 0 -eq "${PIPESTATUS[0]}" ]
502+
503+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" pull.log
504+
grep "custom upload transfer adapter \"ssh\" ignored due to conflict with standard adapter" pull.log
505+
grep "custom download transfer adapter \"ssh\" ignored due to conflict with standard adapter" pull.log
506+
507+
assert_local_object "$contents_oid" "${#contents}"
508+
)
509+
end_test
510+
511+
begin_test "standalone agent without custom group ignored (ssh transfers)"
512+
(
513+
set -e
514+
515+
setup_pure_ssh
516+
517+
reponame="custom-transfer-standalone-ignored-ssh"
518+
setup_remote_repo "$reponame"
519+
clone_repo "$reponame" "$reponame"
520+
521+
sshurl=$(ssh_remote "$reponame")
522+
git config lfs.url "$sshurl"
523+
524+
# The standalone transfer agent should be ignored if it is set to the
525+
# internal "ssh" adapter, regardless of whether that adapter is
526+
# actually used for SSH requests to the Batch API.
527+
git config lfs.standaloneTransferAgent ssh
528+
529+
git lfs track "*.bin"
530+
531+
contents="a"
532+
contents_oid="$(calc_oid "$contents")"
533+
printf "%s" "$contents" >a.bin
534+
535+
git add .gitattributes a.bin
536+
git commit -m "initial commit"
537+
538+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
539+
[ 0 -eq "${PIPESTATUS[0]}" ]
540+
541+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" push.log
542+
543+
assert_remote_object "$reponame" "$contents_oid" "${#contents}"
544+
545+
rm -rf .git/lfs/objects
546+
547+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
548+
[ 0 -eq "${PIPESTATUS[0]}" ]
549+
550+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" pull.log
551+
552+
assert_local_object "$contents_oid" "${#contents}"
553+
554+
# The standalone transfer agent should still be ignored even when
555+
# a custom transfer adapter is registered with the same name as the
556+
# internal "ssh" adapter.
557+
git config lfs.customTransfer.ssh.path path-to-nothing
558+
559+
contents="b"
560+
contents_oid="$(calc_oid "$contents")"
561+
printf "%s" "$contents" >b.bin
562+
563+
git add b.bin
564+
git commit -m "second commit"
565+
566+
GIT_TRACE=1 git push origin main 2>&1 | tee push.log
567+
[ 0 -eq "${PIPESTATUS[0]}" ]
568+
569+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" push.log
570+
grep "custom upload transfer adapter \"ssh\" ignored due to conflict with standard adapter" push.log
571+
grep "custom download transfer adapter \"ssh\" ignored due to conflict with standard adapter" push.log
572+
573+
assert_remote_object "$reponame" "$contents_oid" "${#contents}"
574+
575+
rm -rf .git/lfs/objects
576+
577+
GIT_TRACE=1 git lfs pull 2>&1 | tee pull.log
578+
[ 0 -eq "${PIPESTATUS[0]}" ]
579+
580+
grep "standalone agent \"ssh\" is not a registered custom transfer adapter; ignoring" pull.log
581+
grep "custom upload transfer adapter \"ssh\" ignored due to conflict with standard adapter" pull.log
582+
grep "custom download transfer adapter \"ssh\" ignored due to conflict with standard adapter" pull.log
583+
584+
assert_local_object "$contents_oid" "${#contents}"
585+
)
586+
end_test

tq/basic_download.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ func (a *basicDownloadAdapter) download(context *basicDownloadAdapterWorkerConte
327327
}
328328

329329
func configureBasicDownloadAdapter(m *concreteManifest) {
330-
m.RegisterNewAdapterFunc(BasicAdapterName, Download, func(name string, dir Direction) Adapter {
330+
m.RegisterNewAdapterFunc(BasicAdapterName, Download, false, func(name string, dir Direction) Adapter {
331331
switch dir {
332332
case Download:
333333
bd := &basicDownloadAdapter{newAdapterBase(m.fs, name, dir, nil)}

tq/basic_upload.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func newStartCallbackReader(r lfsapi.ReadSeekCloser, cb func() error) *startCall
211211
}
212212

213213
func configureBasicUploadAdapter(m *concreteManifest) {
214-
m.RegisterNewAdapterFunc(BasicAdapterName, Upload, func(name string, dir Direction) Adapter {
214+
m.RegisterNewAdapterFunc(BasicAdapterName, Upload, false, func(name string, dir Direction) Adapter {
215215
switch dir {
216216
case Upload:
217217
bu := &basicUploadAdapter{newAdapterBase(m.fs, name, dir, nil)}

0 commit comments

Comments
 (0)