1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16  import os 
 17  import re 
 18   
 19  from twisted.internet import defer 
 20   
 21  from buildslave.commands.base import SourceBaseCommand 
 22  from buildslave import runprocess 
 23  from buildslave.commands.base import AbandonChain 
 24   
 25   
 26 -class Repo(SourceBaseCommand): 
  27      """Repo specific VC operation. In addition to the arguments 
 28      handled by SourceBaseCommand, this command reads the following keys: 
 29   
 30      ['manifest_url'] (required):    The manifests repo repository. 
 31      ['manifest_branch'] (optional): Which manifest repo version (i.e. branch or tag) 
 32                                      to retrieve. Default: "master". 
 33      ['manifest_file'] (optional):   Which manifest file to use. Default: "default.xml". 
 34      ['tarball'] (optional):         The tarball base to accelerate the fetch. 
 35      ['repo_downloads'] (optional):  Repo downloads to do. Computer from GerritChangeSource 
 36                                      and forced build properties. 
 37      """ 
 38   
 39      header = "repo operation" 
 40   
 42          SourceBaseCommand.setup(self, args) 
 43          self.manifest_url = args.get('manifest_url') 
 44          self.manifest_branch = args.get('manifest_branch') 
 45          self.manifest_file =  args.get('manifest_file') 
 46          self.tarball = args.get('tarball') 
 47          self.repo_downloads = args.get('repo_downloads') 
 48           
 49           
 50          self.repo_downloaded = "" 
 51   
 52          self.sourcedata = "%s %s %s" % (self.manifest_url, self.manifest_branch, self.manifest_file) 
 53          self.re_change = re.compile(".* refs/changes/\d\d/(\d+)/(\d+) -> FETCH_HEAD$") 
 54          self.re_head = re.compile("^HEAD is now at ([0-9a-f]+)...") 
  55   
 58   
 60          print os.path.join(self._fullSrcdir(), ".repo") 
 61          print os.path.isdir(os.path.join(self._fullSrcdir(), ".repo")) 
 62          return os.path.isdir(os.path.join(self._fullSrcdir(), ".repo")) 
  63   
 64 -    def _repoCmd(self, command, cb=None, abandonOnFailure=True, **kwargs): 
  77   
 88   
 89 -    def _gitCmd(self, subdir, cmds, callback): 
  99   
106   
108          os.makedirs(self._fullSrcdir()) 
109          if self.tarball and os.path.exists(self.tarball): 
110              return self._tarCmd(['-xvzf', self.tarball], self._doInit) 
111          else: 
112              return self._doInit(None) 
 113   
115           
116          if os.path.exists(os.path.join(self._fullSrcdir(), ".repo/project.list")): 
117              os.unlink(os.path.join(self._fullSrcdir(), ".repo/project.list")) 
118          return self._repoCmd(['init', '-u', self.manifest_url, '-b', self.manifest_branch, '-m', self.manifest_file], self._didInit) 
 119   
122   
124          command = ['forall', '-c', 'git', 'clean', '-f', '-d', '-x'] 
125          return self._repoCmd(command, self._doClean2, abandonOnFailure=False) 
 126   
128          command = ['forall', '-c', 'git', 'reset', '--hard', 'HEAD'] 
129          return self._repoCmd(command, self._doClean3, abandonOnFailure=False) 
 130   
132          command = ['clean', '-f', '-d', '-x'] 
133          return self._gitCmd(".repo/manifests",command, self._doSync) 
 134   
136          command = ['sync'] 
137          self.sendStatus({"header": "synching manifest %s from branch %s from %s\n" 
138                                     % (self.manifest_file, self.manifest_branch, self.manifest_url)}) 
139          return self._repoCmd(command, self._didSync) 
 140   
142          if self.tarball and not os.path.exists(self.tarball): 
143              return self._tarCmd(['-cvzf', self.tarball, ".repo"], self._doDownload) 
144          else: 
145              return self._doDownload(None) 
 146   
148          if hasattr(self.command, 'stderr') and self.command.stderr: 
149              if "Automatic cherry-pick failed" in self.command.stderr: 
150                  command = ['forall','-c' ,'git' ,'diff', 'HEAD'] 
151                  self.cherry_pick_failed = True 
152                  return self._repoCmd(command, self._DownloadAbandon, abandonOnFailure = False, keepStderr=True)  
153   
154              lines = self.command.stderr.split('\n') 
155              if len(lines) > 2: 
156                  match1 = self.re_change.match(lines[1]) 
157                  match2 = self.re_head.match(lines[-2]) 
158                  if match1 and match2: 
159                      self.repo_downloaded += "%s/%s %s " % (match1.group(1), match1.group(2), match2.group(1)) 
160   
161          if self.repo_downloads: 
162               
163              download = self.repo_downloads.pop(0) 
164              command = ['download'] + download.split(' ') 
165              self.sendStatus({"header": "downloading changeset %s\n" 
166                                         % (download)}) 
167              return self._repoCmd(command, self._doDownload, abandonOnFailure = False, keepStderr=True)  
168   
169          if self.repo_downloaded: 
170              self.sendStatus({"repo_downloaded": self.repo_downloaded[:-1]}) 
171          return defer.succeed(0) 
 172   
174           
175           
176          if hasattr(self.command, 'stderr'): 
177              if "Couldn't find remote ref" in self.command.stderr: 
178                  raise AbandonChain(-1) 
179              if hasattr(self, 'cherry_pick_failed') or "Automatic cherry-pick failed" in self.command.stderr: 
180                  raise AbandonChain(-1) 
  184