@@ -356,8 +356,25 @@ func testGitQueryString(t *testing.T, sb integration.Sandbox) {
356356 integration .SkipOnPlatform (t , "windows" )
357357 f := getFrontend (t , sb )
358358
359- gitDir , err := os .MkdirTemp ("" , "buildkit" )
359+ subModDir := t .TempDir ()
360+ defer os .RemoveAll (subModDir )
361+
362+ err := runShell (subModDir , []string {
363+ "git init" ,
364+ "git config --local user.email test" ,
365+ "git config --local user.name test" ,
366+ "echo 123 >file" ,
367+ "git add file" ,
368+ "git commit -m initial" ,
369+ "git update-server-info" ,
370+ }... )
360371 require .NoError (t , err )
372+
373+ subModServer := httptest .NewServer (http .FileServer (http .Dir (filepath .Clean (subModDir ))))
374+ defer subModServer .Close ()
375+ submodServerURL := subModServer .URL
376+
377+ gitDir := t .TempDir ()
361378 defer os .RemoveAll (gitDir )
362379 err = runShell (gitDir , []string {
363380 "git init" ,
@@ -368,13 +385,20 @@ func testGitQueryString(t *testing.T, sb integration.Sandbox) {
368385 require .NoError (t , err )
369386
370387 err = os .WriteFile (filepath .Join (gitDir , "Dockerfile" ), []byte (`
388+ FROM scratch AS withgit
389+ COPY .git/HEAD out
390+
391+ FROM scratch as withsubmod
392+ COPY submod/file out
393+
371394FROM scratch
372395COPY foo out
373396` ), 0600 )
374397 require .NoError (t , err )
375398
376399 err = runShell (gitDir , []string {
377- "git add Dockerfile foo" ,
400+ "git submodule add " + submodServerURL + "/.git submod" ,
401+ "git add Dockerfile foo submod" ,
378402 "git commit -m initial" ,
379403 "git tag v0.0.1" ,
380404 "git branch base" ,
@@ -426,6 +450,7 @@ COPY foo out
426450 type tcase struct {
427451 name string
428452 url string
453+ target string
429454 expectOut string
430455 expectErr string
431456 }
@@ -528,15 +553,73 @@ COPY foo out
528553 url : serverURL + "/.git?subdir=sub&ref=feature" ,
529554 expectOut : "subfeature\n " ,
530555 },
556+ {
557+ name : "withgit" ,
558+ url : serverURL + "/.git?keep-git-dir=true" ,
559+ expectOut : commitHashLatest + "\n " ,
560+ target : "withgit" ,
561+ },
562+ {
563+ name : "withgitandtag" ,
564+ url : serverURL + "/.git?tag=v0.0.2&keep-git-dir=true" ,
565+ expectOut : commitHashV2 + "\n " ,
566+ target : "withgit" ,
567+ },
568+ {
569+ name : "withgit-default" ,
570+ url : serverURL + "/.git" ,
571+ expectErr : ".git/HEAD\" : not found" ,
572+ target : "withgit" ,
573+ },
574+ {
575+ name : "withgit-valueless" ,
576+ url : serverURL + "/.git?keep-git-dir&submodules" ,
577+ expectOut : commitHashLatest + "\n " ,
578+ target : "withgit" ,
579+ },
580+ {
581+ name : "withgit-forbidden" ,
582+ url : serverURL + "/.git?keep-git-dir=false" ,
583+ expectErr : ".git/HEAD\" : not found" ,
584+ target : "withgit" ,
585+ },
586+ {
587+ name : "withsubmod" ,
588+ url : serverURL + "/.git" ,
589+ expectOut : "123\n " ,
590+ target : "withsubmod" ,
591+ },
592+ {
593+ name : "withsubmodset" ,
594+ url : serverURL + "/.git?submodules=true" ,
595+ expectOut : "123\n " ,
596+ target : "withsubmod" ,
597+ },
598+ {
599+ name : "withsubmodempty" ,
600+ url : serverURL + "/.git?submodules" ,
601+ expectOut : "123\n " ,
602+ target : "withsubmod" ,
603+ },
604+ {
605+ name : "withoutsubmod" ,
606+ url : serverURL + "/.git?submodules=false" ,
607+ expectErr : "submod/file\" : not found" ,
608+ target : "withsubmod" ,
609+ },
531610 }
532611
533612 for _ , tc := range tcases {
534613 t .Run ("context_" + tc .name , func (t * testing.T ) {
535614 dest := t .TempDir ()
615+ attrs := map [string ]string {
616+ "context" : tc .url ,
617+ }
618+ if tc .target != "" {
619+ attrs ["target" ] = tc .target
620+ }
536621 _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
537- FrontendAttrs : map [string ]string {
538- "context" : tc .url ,
539- },
622+ FrontendAttrs : attrs ,
540623 Exports : []client.ExportEntry {
541624 {
542625 Type : client .ExporterLocal ,
@@ -566,15 +649,28 @@ COPY foo out
566649
567650 for _ , tc := range tcases {
568651 dockerfile2 := fmt .Sprintf (`
569- FROM scratch
652+ FROM scratch AS main
570653ADD %s /repo/
654+
655+ FROM scratch as withsubmod
656+ COPY --from=main /repo/submod/file /repo/foo
657+
658+ FROM scratch AS withgit
659+ COPY --from=main /repo/.git/HEAD /repo/foo
660+
661+ FROM main
571662 ` , tc .url )
572663 inDir := integration .Tmpdir (t ,
573664 fstest .CreateFile ("Dockerfile" , []byte (dockerfile2 ), 0600 ),
574665 )
575666 t .Run ("add_" + tc .name , func (t * testing.T ) {
576667 dest := t .TempDir ()
668+ attrs := map [string ]string {}
669+ if tc .target != "" {
670+ attrs ["target" ] = tc .target
671+ }
577672 _ , err = f .Solve (sb .Context (), c , client.SolveOpt {
673+ FrontendAttrs : attrs ,
578674 Exports : []client.ExportEntry {
579675 {
580676 Type : client .ExporterLocal ,
0 commit comments