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) 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 self.command = c 148 d = c.start() 149 d.addCallback(self._abandonOnFailure) 150 return d
151 152
153 - def doVCFull(self):
154 env = {} 155 command = ['p4'] 156 client_spec = '' 157 client_spec += "Client: %s\n\n" % self.p4client 158 client_spec += "Owner: %s\n\n" % self.p4user 159 client_spec += "Description:\n\tCreated by %s\n\n" % self.p4user 160 client_spec += "Root:\t%s\n\n" % self.builder.basedir 161 client_spec += "Options:\tallwrite rmdir\n\n" 162 if self.p4line_end: 163 client_spec += "LineEnd:\t%s\n\n" % self.p4line_end 164 else: 165 client_spec += "LineEnd:\tlocal\n\n" 166 167 # Setup a view 168 client_spec += "View:\n\t%s" % (self.p4base) 169 if self.p4branch: 170 client_spec += "%s/" % (self.p4branch) 171 client_spec += "... //%s/%s/...\n" % (self.p4client, self.srcdir) 172 if self.p4extra_views: 173 for k, v in self.p4extra_views: 174 client_spec += "\t%s/... //%s/%s%s/...\n" % (k, self.p4client, 175 self.srcdir, v) 176 if self.p4port: 177 command.extend(['-p', self.p4port]) 178 if self.p4user: 179 command.extend(['-u', self.p4user]) 180 if self.p4passwd: 181 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 182 command.extend(['client', '-i']) 183 log.msg(client_spec) 184 185 # from bdbaddog in github comments: 186 # I'm pretty sure the issue is that perforce client specs can't be 187 # non-ascii (unless you configure at initial config to be unicode). I 188 # floated a question to perforce mailing list. From reading the 189 # internationalization notes.. 190 # http://www.perforce.com/perforce/doc.092/user/i18nnotes.txt 191 # I'm 90% sure that's the case. 192 # (http://github.com/bdbaddog/buildbot/commit/8420149b2b804efcf5f81a13e18aa62da0424d21) 193 194 # Clean client spec to plain ascii 195 client_spec=client_spec.encode('ascii','ignore') 196 197 c = runprocess.RunProcess(self.builder, command, self.builder.basedir, 198 environ=env, sendRC=False, timeout=self.timeout, 199 maxTime=self.maxTime, initialStdin=client_spec, 200 usePTY=False) 201 self.command = c 202 d = c.start() 203 d.addCallback(self._abandonOnFailure) 204 d.addCallback(lambda _: self._doP4Sync(force=True)) 205 return d
206
207 - def parseGotRevision(self):
208 if self.revision: 209 return str(self.revision) 210 else: 211 return P4Base.parseGotRevision(self)
212 213
214 -class P4Sync(P4Base):
215 """A partial P4 source-updater. Requires manual setup of a per-slave P4 216 environment. The only thing which comes from the master is P4PORT. 217 'mode' is required to be 'copy'. 218 219 ['p4port'] (required): host:port for server to access 220 ['p4user'] (optional): user to use for access 221 ['p4passwd'] (optional): passwd to try for the user 222 ['p4client'] (optional): client spec to use 223 """ 224 225 header = "p4 sync" 226
227 - def setup(self, args):
228 P4Base.setup(self, args)
229
230 - def sourcedirIsUpdateable(self):
231 return True
232
233 - def _doVC(self, force):
234 d = os.path.join(self.builder.basedir, self.srcdir) 235 command = [self.getCommand('p4')] 236 if self.p4port: 237 command.extend(['-p', self.p4port]) 238 if self.p4user: 239 command.extend(['-u', self.p4user]) 240 if self.p4passwd: 241 command.extend(['-P', Obfuscated(self.p4passwd, "XXXXXXXX")]) 242 if self.p4client: 243 command.extend(['-c', self.p4client]) 244 command.extend(['sync']) 245 if force: 246 command.extend(['-f']) 247 if self.revision: 248 command.extend(['@' + self.revision]) 249 env = {} 250 c = runprocess.RunProcess(self.builder, command, d, environ=env, 251 sendRC=False, timeout=self.timeout, 252 maxTime=self.maxTime, usePTY=False) 253 self.command = c 254 return c.start()
255
256 - def doVCUpdate(self):
257 return self._doVC(force=False)
258
259 - def doVCFull(self):
260 return self._doVC(force=True)
261
262 - def parseGotRevision(self):
263 if self.revision: 264 return str(self.revision) 265 else: 266 return P4Base.parseGotRevision(self)
267