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, **kwargs): 
  78   
 80           
 81           
 82           
 83           
 84           
 85          try: 
 86              self.readSourcedata() 
 87          except IOError: 
 88              return False 
 89          return True 
  90   
 92          command = ['submodule', 'foreach', 'git', 'clean', '-f', '-d'] 
 93          if self.ignore_ignores: 
 94              command.append('-x') 
 95          return self._dovccmd(command) 
  96   
 98          return self._dovccmd(['submodule', 'update'], self._cleanSubmodules) 
  99   
101          if self.submodules: 
102              return self._dovccmd(['submodule', 'init'], self._updateSubmodules) 
103          else: 
104              return defer.succeed(0) 
 105   
107           
108           
109          command = ['branch', '-M', self.branch] 
110          return self._dovccmd(command, self._initSubmodules) 
 111           
113          if self.revision: 
114              head = self.revision 
115          else: 
116              head = 'FETCH_HEAD' 
117   
118           
119           
120          command = ['reset', '--hard', head] 
121          return self._dovccmd(command, self._didHeadCheckout) 
 122   
124           
125           
126          if hasattr(self.command, 'stderr'): 
127              if "Couldn't find remote ref" in self.command.stderr: 
128                  raise AbandonChain(-1) 
 129   
130       
131       
132       
133       
135          try: 
136               
137              diffbranch = self.sourcedata != self.readSourcedata() 
138          except IOError: 
139              diffbranch = False 
140          if diffbranch: 
141              command = ['clean', '-f', '-d'] 
142              if self.ignore_ignores: 
143                  command.append('-x') 
144              return self._dovccmd(command, self._didClean) 
145          return self._didClean(None) 
 146   
148           
149           
150          command = ['fetch', '-t', self.repourl, '+%s' % branch] 
151           
152           
153           
154           
155          if self.args.get('progress'): 
156              command.append('--progress') 
157          self.sendStatus({"header": "fetching branch %s from %s\n" 
158                                          % (branch, self.repourl)}) 
159          return self._dovccmd(command, self._didFetch, keepStderr=True) 
 160   
162          branch = self.gerrit_branch or self.branch 
163   
164           
165          if self.revision: 
166               
167              d = self._dovccmd(['reset', '--hard', self.revision], 
168                                self._initSubmodules) 
169               
170               
171              d.addErrback(self._doFetch, branch) 
172              return d 
173          else: 
174               
175              return self._doFetch(None, branch) 
 176   
178           
179           
180          if self.reference: 
181              git_alts_path = os.path.join(self._fullSrcdir(), '.git', 'objects', 'info', 'alternates') 
182              git_alts_content = os.path.join(self.reference, 'objects') 
183              self.setFileContents(git_alts_path, git_alts_content) 
184          return self.doVCUpdate() 
 185   
187          git = self.getCommand("git") 
188   
189           
190           
191          if not self.args.get('revision') and self.args.get('shallow'): 
192              cmd = [git, 'clone', '--depth', '1'] 
193               
194              if self.reference: 
195                  cmd.extend(['--reference', self.reference]) 
196              cmd.extend([self.repourl, self._fullSrcdir()]) 
197              c = runprocess.RunProcess(self.builder, cmd, self.builder.basedir, 
198                               sendRC=False, timeout=self.timeout, 
199                               maxTime=self.maxTime, logEnviron=self.logEnviron, 
200                               usePTY=False) 
201              self.command = c 
202              cmdexec = c.start() 
203              cmdexec.addCallback(self._didInit) 
204              return cmdexec 
205          else: 
206              os.makedirs(self._fullSrcdir()) 
207              return self._dovccmd(['init'], self._didInit) 
 208   
210          command = ['rev-parse', 'HEAD'] 
211          def _parse(res): 
212              hash = self.command.stdout.strip() 
213              if len(hash) != 40: 
214                  return None 
215              return hash 
 216          return self._dovccmd(command, _parse, keepStdout=True) 
 217