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

Source Code for Module buildslave.commands.p4

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