@@ -275,31 +275,45 @@ def fetch(self):
275275 It returns a dict structure associating each (remote, ref) to their
276276 SHA in local repository.
277277 """
278- merges_requested = [(m ["remote" ], m ["ref" ])
279- for m in self .merges ]
280278 basecmd = ("git" , "fetch" )
281279 logger .info ("Fetching required remotes" )
282280 fetch_heads = {}
283281 ls_remote_refs = collections .defaultdict (list ) # to ls-query
284- while merges_requested :
285- remote , ref = merges_requested [0 ]
286- merges_requested = merges_requested [1 :]
282+ for merge in self .merges :
283+ remote = merge ["remote" ]
284+ ref = merge ["ref" ]
285+ pin = merge .get ("pin" )
287286 cmd = (
288287 basecmd +
289288 self ._fetch_options ({"remote" : remote , "ref" : ref }) +
290289 (remote ,))
291290 if remote not in self .fetch_all :
292291 cmd += (ref , )
293292 else :
293+ if pin :
294+ # Probably solvable, but a little too tricky for me to
295+ # figure out right now
296+ raise GitAggregatorException (
297+ "Cannot use fetch_all with pin"
298+ )
294299 ls_remote_refs [remote ].append (ref )
295300 self .log_call (cmd , cwd = self .cwd )
296- with open (os .path .join (self .cwd , ".git" , "FETCH_HEAD" ), "r" ) as f :
297- for line in f :
298- fetch_head , for_merge , _ = line .split ("\t " )
299- if for_merge == "not-for-merge" :
300- continue
301- break
302- fetch_heads [(remote , ref )] = fetch_head
301+ if pin :
302+ try :
303+ fetch_heads [(remote , ref )] = self .rev_parse (pin )
304+ except Exception :
305+ logger .error (
306+ "Could not find pin %r after fetching %r" , pin , ref
307+ )
308+ raise
309+ else :
310+ with open (os .path .join (self .cwd , ".git" , "FETCH_HEAD" )) as f :
311+ for line in f :
312+ fetch_head , for_merge , _ = line .split ("\t " )
313+ if for_merge == "not-for-merge" :
314+ continue
315+ break
316+ fetch_heads [(remote , ref )] = fetch_head
303317 if self .fetch_all :
304318 if self .fetch_all is True :
305319 remotes = self .remotes
@@ -311,31 +325,16 @@ def fetch(self):
311325 remote ["url" ],
312326 ls_remote_refs [remote ["name" ]])
313327 for _ , ref , sha in refs :
314- if (remote ["name" ], ref ) in merges_requested :
315- merges_requested .remove ((remote ["name" ], ref ))
316328 fetch_heads [(remote ["name" ], ref )] = sha
317- if len (merges_requested ):
318- # Last case: our ref is a sha and remote git repository does
319- # not support querying commit directly by SHA. In this case
320- # we need just to check if ref is actually SHA, and if we have
321- # this SHA locally.
322- for remote , ref in merges_requested :
323- if not re .search ("[0-9a-f]{4,}" , ref ):
324- raise ValueError ("Could not resolv ref %r on remote %r"
325- % (ref , remote ))
326- valid_local_shas = self .log_call (
327- ['git' , 'rev-parse' , '-v' ] + [sha
328- for _r , sha in merges_requested ],
329- cwd = self .cwd , callwith = subprocess .check_output
330- ).strip ().splitlines ()
331- for remote , sha in merges_requested :
332- if sha not in valid_local_shas :
333- raise ValueError (
334- "Could not find SHA ref %r after fetch on remote %r"
335- % (ref , remote ))
336- fetch_heads [(remote ["name" ], sha )] = sha
337329 return fetch_heads
338330
331+ def rev_parse (self , ref ):
332+ return self .log_call (
333+ ["git" , "rev-parse" , "--verify" , ref ],
334+ callwith = subprocess .check_output ,
335+ cwd = self .cwd ,
336+ ).strip ()
337+
339338 def push (self ):
340339 remote = self .target ['remote' ]
341340 branch = self .target ['branch' ]
@@ -384,11 +383,7 @@ def _switch_to_branch(self, branch_name, ref=None):
384383 logger .info ("Switch to branch %s" , branch_name )
385384 cmd = ['git' , 'checkout' , '-B' , branch_name ]
386385 if ref is not None :
387- sha1 = self .log_call (
388- ['git' , 'rev-parse' , ref ],
389- callwith = subprocess .check_output ,
390- cwd = self .cwd ).strip ()
391- cmd .append (sha1 )
386+ cmd .append (self .rev_parse (ref ))
392387 self .log_call (cmd , cwd = self .cwd )
393388
394389 def _execute_shell_command_after (self ):
0 commit comments