1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16  import os 
 17   
 18  from twisted.python import log 
 19  from twisted.internet import defer 
 20   
 21  from buildslave.commands.base import SourceBaseCommand 
 22  from buildslave import runprocess 
 23   
 24   
 26      """Error class for this module.""" 
  27   
 28   
 30      """Monotone specific VC operation. In addition to the arguments 
 31      handled by SourceBaseCommand, this command reads the following keys: 
 32   
 33      ['repourl'] (required):     the Monotone repository string 
 34      ['branch'] (required):      which branch to retrieve. 
 35   
 36      ['revision'] (optional):    which revision (revision selector) 
 37                                  to retrieve. 
 38      ['progress'] (optional):       have mtn output progress markers, 
 39                                     avoiding timeouts for long fetches; 
 40      """ 
 41   
 42      header = "monotone operation" 
 43   
 60   
 65   
 66          d = self._checkDb(); 
 67          d.addCallback(cont) 
 68          return d 
  69   
 71          return self._dovccmd(self._update, True) 
  72   
 74          return self._dovccmd(self._checkout, True) 
  75   
 78   
 80          return os.path.isdir(os.path.join(self._fullSrcdir(), "_MTN")) 
  81   
 82 -    def _dovccmd(self, fn, dopull, cb=None, **kwargs): 
  83          if dopull: 
 84              command = [self.mtn, 'pull', self.sourcedata, 
 85                         '--db', self.database] 
 86              if self.progress: 
 87                  command.extend(['--ticker=dot']) 
 88              else: 
 89                  command.extend(['--ticker=none']) 
 90              c = runprocess.RunProcess(self.builder, command, 
 91                                        self.builder.basedir, 
 92                                        environ=self.env, sendRC=False, 
 93                                        timeout=self.timeout, 
 94                                        maxTime=self.maxTime, 
 95                                        keepStdout=True, usePTY=False, 
 96                                        logEnviron=self.logEnviron) 
 97              self.sendStatus({"header": "pulling %s from %s\n" 
 98                               % (self.branch, self.sourcedata)}) 
 99              self.command = c 
100              d = c.start() 
101              d.addCallback(self._abandonOnFailure) 
102              d.addCallback(fn) 
103          else: 
104              d = fn(None) 
105          if cb: 
106              d.addCallback(cb) 
107          return d 
 108   
110          command = [self.mtn, 'update', 
111                     '--db', self.database] 
112          if self.revision: 
113              command.extend(['--revision', self.revision]) 
114          else: 
115              command.extend(["-r", "h:" + self.branch]) 
116          command.extend(["-b", self.branch]) 
117          c = runprocess.RunProcess(self.builder, command, self._fullSrcdir(), 
118                                    environ=self.env, sendRC=False, 
119                                    timeout=self.timeout, maxTime=self.maxTime, 
120                                    keepStdout=True, usePTY=False, 
121                                    logEnviron=self.logEnviron) 
122          d = c.start() 
123          return d 
 124   
126          command = [self.mtn, 'checkout', self._fullSrcdir(), 
127                     '--db', self.database] 
128          if self.revision: 
129              command.extend(['--revision', self.revision]) 
130          command.extend(['--branch', self.branch]) 
131          c = runprocess.RunProcess(self.builder, command, self.builder.basedir, 
132                                    environ=self.env, sendRC=False, 
133                                    timeout=self.timeout, maxTime=self.maxTime, 
134                                    keepStdout=True, usePTY=False, 
135                                    logEnviron=self.logEnviron) 
136          d = c.start() 
137          return d 
 138   
140           
141           
142           
143          c = runprocess.RunProcess(self.builder, [self.mtn, 'db', 'info', 
144                                                   '--db', self.database], 
145                                    self.builder.basedir, 
146                                    environ=self.env, sendRC=False, 
147                                    keepStdout=True, sendStderr=False, 
148                                    usePTY=False, logEnviron=self.logEnviron) 
149          d = c.start() 
150          def afterCheckRepo(res, cdi): 
151              if type(res) is int and res != 0: 
152                  log.msg("No database found, creating it") 
153                   
154                   
155                   
156                  self._pull_timeout = max(self._pull_timeout, 3 * 60 * 60) 
157                  c = runprocess.RunProcess(self.builder, [self.mtn, 'db', 'init', 
158                                                           '--db', self.database], 
159                                            self.builder.basedir, 
160                                            environ=self.env,  
161                                            sendRC=False, usePTY=False, 
162                                            logEnviron=self.logEnviron) 
163                  self.command = c 
164                  return c.start() 
165              elif cdi.stdout.find("(migration needed)") > 0: 
166                  log.msg("Older format database found, migrating it") 
167                   
168                  c = runprocess.RunProcess(self.builder, [self.mtn, 
169                                                           'db', 'migrate', 
170                                                           '--db', self.database], 
171                                            self.builder.basedir, 
172                                            environ=self.env,  
173                                            sendRC=False, usePTY=False, 
174                                            logEnviron=self.logEnviron) 
175                  self.command = c 
176                  return c.start() 
177              elif cdi.stdout.find("(too new, cannot use)") > 0: 
178                  raise MonotoneError, "The database is of a newer format than mtn can handle...  Abort!" 
179              else: 
180                  return defer.succeed(res) 
 181          d.addCallback(afterCheckRepo, c) 
182          return d 
183   
185          def _parse(res): 
186              hash = self.command.stdout.strip() 
187              if len(hash) != 40: 
188                  return None 
189              return hash 
 190          return self._dovccmd(self._get_base_revision, False, _parse) 
191   
193          c = runprocess.RunProcess(self.builder, 
194                                    [self.mtn, 'automate', 'select', 'w:'], 
195                                    self._fullSrcdir(), 
196                                    sendRC=False, 
197                                    timeout=self.timeout, maxTime=self.maxTime, 
198                                    keepStdout=True, usePTY=False, 
199                                    logEnviron=self.logEnviron) 
200          d = c.start() 
201          d.addCallback(self._abandonOnFailure) 
202          return d 
 203