1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16  import os 
 17   
 18  from twisted.internet import defer 
 19   
 20  from buildslave.commands.base import SourceBaseCommand 
 21  from buildslave import runprocess 
 22  from buildslave.commands.base import AbandonChain 
 23   
 24   
 25 -class Git(SourceBaseCommand): 
  26      """Git specific VC operation. In addition to the arguments 
 27      handled by SourceBaseCommand, this command reads the following keys: 
 28   
 29      ['repourl'] (required):        the upstream GIT repository string 
 30      ['branch'] (optional):         which version (i.e. branch or tag) 
 31                                     to retrieve. Default: "master". 
 32      ['submodules'] (optional):     whether to initialize and update 
 33                                     submodules. Default: False. 
 34      ['ignore_ignores'] (optional): ignore ignores when purging changes 
 35                                     (default true) 
 36      ['reference'] (optional):      use this reference repository 
 37                                     to fetch objects. 
 38      ['gerrit_branch'] (optional):  which virtual branch to retrieve. 
 39      ['progress'] (optional):       have git output progress markers, 
 40                                     avoiding timeouts for long fetches; 
 41                                     requires Git 1.7.2 or later. 
 42      ['shallow'] (optional):        if true, use shallow clones that do not 
 43                                     also fetch history 
 44      """ 
 45   
 46      header = "git operation" 
 47   
 49          SourceBaseCommand.setup(self, args) 
 50          self.repourl = args['repourl'] 
 51          self.branch = args.get('branch') 
 52          if not self.branch: 
 53              self.branch = "master" 
 54          self.sourcedata = "%s %s\n" % (self.repourl, self.branch) 
 55          self.submodules = args.get('submodules') 
 56          self.ignore_ignores = args.get('ignore_ignores', True) 
 57          self.reference = args.get('reference', None) 
 58          self.gerrit_branch = args.get('gerrit_branch', None) 
  59   
 62   
 64          return os.path.isdir(os.path.join(self._fullSrcdir(), ".git")) 
  65   
 66 -    def _dovccmd(self, command, cb=None, stopOnFail=True, **kwargs): 
  79   
 81           
 82           
 83           
 84           
 85           
 86          try: 
 87              self.readSourcedata() 
 88          except IOError: 
 89              return False 
 90          return True 
  91   
 93          command = ['submodule', 'foreach', 'git', 'clean', '-f', '-d'] 
 94          if self.ignore_ignores: 
 95              command.append('-x') 
 96          return self._dovccmd(command) 
  97   
 99          return self._dovccmd(['submodule', 'update'], self._cleanSubmodules) 
 100   
102          if self.submodules: 
103              return self._dovccmd(['submodule', 'init'], self._updateSubmodules) 
104          else: 
105              return defer.succeed(0) 
 106   
108           
109           
110          command = ['branch', '-M', self.branch] 
111          return self._dovccmd(command, self._initSubmodules, False) 
 112           
114          if self.revision: 
115              head = self.revision 
116          else: 
117              head = 'FETCH_HEAD' 
118   
119           
120           
121          command = ['reset', '--hard', head] 
122          return self._dovccmd(command, self._didHeadCheckout) 
 123   
125           
126           
127          if hasattr(self.command, 'stderr'): 
128              if "Couldn't find remote ref" in self.command.stderr: 
129                  raise AbandonChain(-1) 
 130   
131       
132       
133       
134       
147   
149           
150           
151          command = ['fetch', '-t', self.repourl, '+%s' % branch] 
152           
153           
154           
155           
156          if self.args.get('progress'): 
157              command.append('--progress') 
158          self.sendStatus({"header": "fetching branch %s from %s\n" 
159                                          % (branch, self.repourl)}) 
160          return self._dovccmd(command, self._didFetch, keepStderr=True) 
 161   
163          branch = self.gerrit_branch or self.branch 
164   
165           
166          if self.revision: 
167               
168              d = self._dovccmd(['reset', '--hard', self.revision], 
169                                self._initSubmodules) 
170               
171               
172              d.addErrback(self._doFetch, branch) 
173              return d 
174          else: 
175               
176              return self._doFetch(None, branch) 
 177   
179           
180           
181          if self.reference: 
182              git_alts_path = os.path.join(self._fullSrcdir(), '.git', 'objects', 'info', 'alternates') 
183              git_alts_content = os.path.join(self.reference, 'objects') 
184              self.setFileContents(git_alts_path, git_alts_content) 
185          return self.doVCUpdate() 
 186   
188          git = self.getCommand("git") 
189   
190           
191           
192          if not self.args.get('revision') and self.args.get('shallow'): 
193              cmd = [git, 'clone', '--depth', '1'] 
194               
195              if self.reference: 
196                  cmd.extend(['--reference', self.reference]) 
197              cmd.extend([self.repourl, self._fullSrcdir()]) 
198              c = runprocess.RunProcess(self.builder, cmd, self.builder.basedir, 
199                               sendRC=False, timeout=self.timeout, 
200                               maxTime=self.maxTime, logEnviron=self.logEnviron, 
201                               usePTY=False) 
202              self.command = c 
203              cmdexec = c.start() 
204              cmdexec.addCallback(self._didInit) 
205              return cmdexec 
206          else: 
207              os.makedirs(self._fullSrcdir()) 
208              return self._dovccmd(['init'], self._didInit) 
 209   
211          command = ['rev-parse', 'HEAD'] 
212          def _parse(res): 
213              hash = self.command.stdout.strip() 
214              if len(hash) != 40: 
215                  return None 
216              return hash 
 217          return self._dovccmd(command, _parse, keepStdout=True) 
 218