@@ -180,8 +180,10 @@ func (r Repo) fetchGitRepo(arch string, entry *manifest.Manifest2822Entry) (stri
180180 }
181181 }
182182
183- fetchString := entry .ArchGitFetch (arch ) + ":"
184- if entry .ArchGitCommit (arch ) == "FETCH_HEAD" {
183+ fetchStrings := []string {
184+ entry .ArchGitFetch (arch ) + ":" ,
185+ }
186+ if entryArchGitCommit := entry .ArchGitCommit (arch ); entryArchGitCommit == "FETCH_HEAD" {
185187 // fetch remote tag references to a local tag ref so that we can cache them and not re-fetch every time
186188 localRef := "refs/tags/" + gitNormalizeForTagUsage (cacheKey )
187189 commit , err := getGitCommit (localRef )
@@ -190,7 +192,7 @@ func (r Repo) fetchGitRepo(arch string, entry *manifest.Manifest2822Entry) (stri
190192 entry .SetGitCommit (arch , commit )
191193 return commit , nil
192194 }
193- fetchString += localRef
195+ fetchStrings [ 0 ] += localRef
194196 } else {
195197 // we create a temporary remote dir so that we can clean it up completely afterwards
196198 refBase := "refs/remotes"
@@ -210,10 +212,19 @@ func (r Repo) fetchGitRepo(arch string, entry *manifest.Manifest2822Entry) (stri
210212 tempRef := path .Join (refBase , filepath .Base (tempRefDir ))
211213 if entry .ArchGitFetch (arch ) == manifest .DefaultLineBasedFetch {
212214 // backwards compat (see manifest/line-based.go in go-dockerlibrary)
213- fetchString += tempRef + "/*"
215+ fetchStrings [ 0 ] += tempRef + "/*"
214216 } else {
215- fetchString += tempRef + "/temp"
217+ fetchStrings [ 0 ] += tempRef + "/temp"
216218 }
219+
220+ fetchStrings = append ([]string {
221+ // Git (and more recently, GitHub) support "git fetch"ing a specific commit directly!
222+ // (The "actions/checkout@v2" GitHub action uses this to fetch commits for running workflows even after branches are deleted!)
223+ // https://github.com/git/git/commit/f8edeaa05d8623a9f6dad408237496c51101aad8
224+ // https://github.com/go-git/go-git/pull/58
225+ // If that works, we want to prefer it (since it'll be much more efficient at getting us the commit we care about), so we prepend it to our list of "things to try fetching"
226+ entryArchGitCommit + ":" + tempRef + "/temp" ,
227+ }, fetchStrings ... )
217228 }
218229
219230 if strings .HasPrefix (entry .ArchGitRepo (arch ), "git://github.com/" ) {
@@ -229,27 +240,32 @@ func (r Repo) fetchGitRepo(arch string, entry *manifest.Manifest2822Entry) (stri
229240 return "" , err
230241 }
231242
232- err = gitRemote .Fetch (& goGit.FetchOptions {
233- RefSpecs : []goGitConfig.RefSpec {goGitConfig .RefSpec (fetchString )},
234- Tags : goGit .NoTags ,
243+ var commit string
244+ fetchErrors := []error {}
245+ for _ , fetchString := range fetchStrings {
246+ err := gitRemote .Fetch (& goGit.FetchOptions {
247+ RefSpecs : []goGitConfig.RefSpec {goGitConfig .RefSpec (fetchString )},
248+ Tags : goGit .NoTags ,
235249
236- //Progress: os.Stdout,
237- })
238- if err != nil {
239- if fetchErr := fetchGitCommit ( arch , entry , gitRemote . Config (). URLs [ 0 ], fetchString ); fetchErr != nil {
240- return "" , cli . NewMultiError ( err , fetchErr )
250+ //Progress: os.Stdout,
251+ })
252+ if err != nil {
253+ fetchErrors = append ( fetchErrors , err )
254+ continue
241255 }
242- }
243256
244- commit , err := getGitCommit (entry .ArchGitCommit (arch ))
245- if err != nil {
246- if fetchErr := fetchGitCommit (arch , entry , gitRemote .Config ().URLs [0 ], fetchString ); fetchErr != nil {
247- return "" , cli .NewMultiError (err , fetchErr )
248- }
249257 commit , err = getGitCommit (entry .ArchGitCommit (arch ))
250258 if err != nil {
251- return "" , err
259+ fetchErrors = append (fetchErrors , err )
260+ continue
252261 }
262+
263+ fetchErrors = nil
264+ break
265+ }
266+
267+ if len (fetchErrors ) > 0 {
268+ return "" , cli .NewMultiError (fetchErrors ... )
253269 }
254270
255271 gitTag := gitNormalizeForTagUsage (path .Join (arch , namespace , r .RepoName , entry .Tags [0 ]))
@@ -263,20 +279,3 @@ func (r Repo) fetchGitRepo(arch string, entry *manifest.Manifest2822Entry) (stri
263279 entry .SetGitCommit (arch , commit )
264280 return commit , nil
265281}
266-
267- // this is used as a fallback if using github.com/go-git/go-git/v5 to fetch the branch fails to find the commit
268- // Git (and more recently, GitHub) support "git fetch"ing a specific commit directly!
269- // (The "actions/checkout@v2" GitHub action uses this to fetch commits for running workflows even after branches are deleted!)
270- // https://github.com/git/git/commit/f8edeaa05d8623a9f6dad408237496c51101aad8
271- // (Unfortunately, github.com/go-git/go-git/v5 does not support fetching a commit like this from what I can figure [https://github.com/go-git/go-git/issues/56], so we have to shell out.)
272- func fetchGitCommit (arch string , entry * manifest.Manifest2822Entry , gitRemote , fetchString string ) error {
273- commit := entry .ArchGitCommit (arch )
274- if commit == "FETCH_HEAD" {
275- return fmt .Errorf ("cannot fetch line-based entry commit when fetching by tag" )
276- }
277-
278- fetchString = "+" + commit + ":" + strings .SplitN (fetchString , ":" , 2 )[1 ]
279-
280- _ , err := git (`fetch` , `--quiet` , gitRemote , fetchString )
281- return err
282- }
0 commit comments