Package buildslave :: Package commands :: Module p4
[frames] | no frames]

Source Code for Module buildslave.commands.p4

  1  import os, re 
  2   
  3  from twisted.python import log 
  4   
  5  from buildslave.commands.base import SourceBaseCommand 
  6  from buildslave import runprocess 
  7  from buildslave.commands import utils 
  8  from buildslave.util import Obfuscated 
  9   
 10   
11 -class P4Base(SourceBaseCommand):
12 """Base class for P4 source-updaters 13 14 ['p4port'] (required): host:port for server to access 15 ['p4user'] (optional): user to use for access 16 ['p4passwd'] (optional): passwd to try for the user 17 ['p4client'] (optional): client spec to use 18 """
19 - def setup(self, args):
20 SourceBaseCommand.setup(self, args) 21 self.p4port = args['p4port'] 22 self.p4client = args['p4client'] 23 self.p4user = args['p4user'] 24 self.p4passwd = args['p4passwd']
25
26 - def parseGotRevision(self):
27 # Executes a p4 command that will give us the latest changelist number 28 # of any file under the current (or default) client: 29 command = ['p4'] 30 if self.p4port: 31 command.extend(['-p', self.p4port]) 32 if self.p4user: 33 command.extend(['-u', self.p4user]) 34 if self.p4passwd: 35 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 36 if self.p4client: 37 command.extend(['-c', self.p4client]) 38 # add '-s submitted' for bug #626 39 command.extend(['changes', '-s', 'submitted', '-m', '1', '#have']) 40 c = runprocess.RunProcess(self.builder, command, self.builder.basedir, 41 environ=self.env, timeout=self.timeout, 42 maxTime=self.maxTime, sendStdout=True, 43 sendRC=False, keepStdout=True, 44 usePTY=False) 45 self.command = c 46 d = c.start() 47 48 def _parse(res): 49 # 'p4 -c clien-name change -m 1 "#have"' will produce an output like: 50 # "Change 28147 on 2008/04/07 by p4user@hostname..." 51 # The number after "Change" is the one we want. 52 m = re.match('Change\s+(\d+)\s+', c.stdout) 53 if m: 54 return m.group(1) 55 return None
56 d.addCallback(_parse) 57 return d
58 59
60 -class P4(P4Base):
61 """A P4 source-updater. 62 63 ['p4port'] (required): host:port for server to access 64 ['p4user'] (required): user to use for access 65 ['p4passwd'] (required): passwd to try for the user 66 ['p4client'] (required): client spec to use 67 ['p4extra_views'] (required): additional client views to use 68 ['p4base'] (required): view into the Perforce depot without branch name or trailing "..." 69 ['p4line_end'] (optional): value of the LineEnd client specification property 70 """ 71 72 header = "p4" 73
74 - def setup(self, args):
75 P4Base.setup(self, args) 76 self.p4base = args['p4base'] 77 self.p4extra_views = args['p4extra_views'] 78 self.p4line_end = args.get('p4line_end', None) 79 self.p4mode = args['mode'] 80 self.p4branch = args['branch'] 81 82 self.sourcedata = str([ 83 # Perforce server. 84 self.p4port, 85 86 # Client spec. 87 self.p4client, 88 89 # Depot side of view spec. 90 self.p4base, 91 self.p4branch, 92 self.p4extra_views, 93 self.p4line_end, 94 95 # Local side of view spec (srcdir is made from these). 96 self.builder.basedir, 97 self.mode, 98 self.workdir 99 ])
100 101
102 - def sourcedirIsUpdateable(self):
103 # We assume our client spec is still around. 104 # We just say we aren't updateable if the dir doesn't exist so we 105 # don't get ENOENT checking the sourcedata. 106 return (not self.sourcedirIsPatched() and 107 os.path.isdir(os.path.join(self.builder.basedir, 108 self.srcdir)))
109
110 - def doVCUpdate(self):
111 return self._doP4Sync(force=False)
112
113 - def _doP4Sync(self, force):
114 command = ['p4'] 115 116 if self.p4port: 117 command.extend(['-p', self.p4port]) 118 if self.p4user: 119 command.extend(['-u', self.p4user]) 120 if self.p4passwd: 121 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 122 if self.p4client: 123 command.extend(['-c', self.p4client]) 124 command.extend(['sync']) 125 if force: 126 command.extend(['-f']) 127 if self.revision: 128 command.extend(['@' + str(self.revision)]) 129 env = {} 130 c = runprocess.RunProcess(self.builder, command, self.builder.basedir, 131 environ=env, sendRC=False, timeout=self.timeout, 132 maxTime=self.maxTime, usePTY=False) 133 self.command = c 134 d = c.start() 135 d.addCallback(self._abandonOnFailure) 136 return d
137 138
139 - def doVCFull(self):
140 env = {} 141 command = ['p4'] 142 client_spec = '' 143 client_spec += "Client: %s\n\n" % self.p4client 144 client_spec += "Owner: %s\n\n" % self.p4user 145 client_spec += "Description:\n\tCreated by %s\n\n" % self.p4user 146 client_spec += "Root:\t%s\n\n" % self.builder.basedir 147 client_spec += "Options:\tallwrite rmdir\n\n" 148 if self.p4line_end: 149 client_spec += "LineEnd:\t%s\n\n" % self.p4line_end 150 else: 151 client_spec += "LineEnd:\tlocal\n\n" 152 153 # Setup a view 154 client_spec += "View:\n\t%s" % (self.p4base) 155 if self.p4branch: 156 client_spec += "%s/" % (self.p4branch) 157 client_spec += "... //%s/%s/...\n" % (self.p4client, self.srcdir) 158 if self.p4extra_views: 159 for k, v in self.p4extra_views: 160 client_spec += "\t%s/... //%s/%s%s/...\n" % (k, self.p4client, 161 self.srcdir, v) 162 if self.p4port: 163 command.extend(['-p', self.p4port]) 164 if self.p4user: 165 command.extend(['-u', self.p4user]) 166 if self.p4passwd: 167 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 168 command.extend(['client', '-i']) 169 log.msg(client_spec) 170 171 # from bdbaddog in github comments: 172 # I'm pretty sure the issue is that perforce client specs can't be 173 # non-ascii (unless you configure at initial config to be unicode). I 174 # floated a question to perforce mailing list. From reading the 175 # internationalization notes.. 176 # http://www.perforce.com/perforce/doc.092/user/i18nnotes.txt 177 # I'm 90% sure that's the case. 178 # (http://github.com/bdbaddog/buildbot/commit/8420149b2b804efcf5f81a13e18aa62da0424d21) 179 180 # Clean client spec to plain ascii 181 client_spec=client_spec.encode('ascii','ignore') 182 183 c = runprocess.RunProcess(self.builder, command, self.builder.basedir, 184 environ=env, sendRC=False, timeout=self.timeout, 185 maxTime=self.maxTime, initialStdin=client_spec, 186 usePTY=False) 187 self.command = c 188 d = c.start() 189 d.addCallback(self._abandonOnFailure) 190 d.addCallback(lambda _: self._doP4Sync(force=True)) 191 return d
192
193 - def parseGotRevision(self):
194 if self.revision: 195 return str(self.revision) 196 else: 197 return P4Base.parseGotRevision(self)
198 199
200 -class P4Sync(P4Base):
201 """A partial P4 source-updater. Requires manual setup of a per-slave P4 202 environment. The only thing which comes from the master is P4PORT. 203 'mode' is required to be 'copy'. 204 205 ['p4port'] (required): host:port for server to access 206 ['p4user'] (optional): user to use for access 207 ['p4passwd'] (optional): passwd to try for the user 208 ['p4client'] (optional): client spec to use 209 """ 210 211 header = "p4 sync" 212
213 - def setup(self, args):
214 P4Base.setup(self, args)
215
216 - def sourcedirIsUpdateable(self):
217 return True
218
219 - def _doVC(self, force):
220 d = os.path.join(self.builder.basedir, self.srcdir) 221 command = [self.getCommand('p4')] 222 if self.p4port: 223 command.extend(['-p', self.p4port]) 224 if self.p4user: 225 command.extend(['-u', self.p4user]) 226 if self.p4passwd: 227 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 228 if self.p4client: 229 command.extend(['-c', self.p4client]) 230 command.extend(['sync']) 231 if force: 232 command.extend(['-f']) 233 if self.revision: 234 command.extend(['@' + self.revision]) 235 env = {} 236 c = runprocess.RunProcess(self.builder, command, d, environ=env, 237 sendRC=False, timeout=self.timeout, 238 maxTime=self.maxTime, usePTY=False) 239 self.command = c 240 return c.start()
241
242 - def doVCUpdate(self):
243 return self._doVC(force=False)
244
245 - def doVCFull(self):
246 return self._doVC(force=True)
247
248 - def parseGotRevision(self):
249 if self.revision: 250 return str(self.revision) 251 else: 252 return P4Base.parseGotRevision(self)
253