[Buildbot-commits] buildbot/buildbot/slave commands.py,1.44,1.45

Brian Warner warner at users.sourceforge.net
Mon Apr 24 06:45:39 UTC 2006


Update of /cvsroot/buildbot/buildbot/buildbot/slave
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25669/buildbot/slave

Modified Files:
	commands.py 
Log Message:
Revision: arch at buildbot.sf.net--2004/buildbot--dev--0--patch-506
Creator:  Brian Warner <warner at lothar.com>

add 'build properties', update test_vc

2006-04-23  Brian Warner  <warner at lothar.com>

	* buildbot/test/test_vc.py (VCBase.checkGotRevision): test
	'got_revision' build property for all VC systems that implement
	accurate ones: SVN, Darcs, Arch, Bazaar, Mercurial.

	* buildbot/slave/commands.py (SourceBase._handleGotRevision): try
	to determine which revision we actually obtained
	(CVS.parseGotRevision): implement this for CVS, which just means
	to grab a timestamp. Not ideal, and it depends upon the buildslave
	having a clock that is reasonably well syncronized with the server,
	but it's better than nothing.
	(SVN.parseGotRevision): implement it for SVN, which is accurate
	(Darcs.parseGotRevision): same
	(Arch.parseGotRevision): same
	(Bazaar.parseGotRevision): same
	(Mercurial.parseGotRevision): same

	* buildbot/process/step.py (LoggedRemoteCommand.remoteUpdate):
	keep a record of all non-stdout/stderr/header/rc status updates,
	for the benefit of RemoteCommands that send other useful things,
	like got_revision
	(Source.commandComplete): put any 'got_revision' status values
	into a build property of the same name

	* buildbot/process/step_twisted.py (Trial): update to deal with
	new ShellCommand refactoring

	* docs/buildbot.texinfo (Build Properties): document new feature
	that allows BuildSteps to get/set Build-wide properties like which
	revision was requested and/or checked out.

	* buildbot/interfaces.py (IBuildStatus.getProperty): new method
	* buildbot/status/builder.py (BuildStatus.getProperty): implement
	it. Note that this bumps the persistenceVersion of the saved Build
	object, so add the necessary upgrade-old-version logic to include
	an empty properties dict.

	* buildbot/process/base.py (Build.setProperty): implement it
	(Build.getProperty): same
	(Build.startBuild): change build startup to set 'branch',
	'revision', and 'slavename' properties at the right time

	* buildbot/process/step.py (BuildStep.__init__): change setup to
	require 'build' argument in a better way
	(LoggingBuildStep): split ShellCommand into two pieces, for better
	subclassing elsewhere. LoggingBuildStep is a BuildStep which runs
	a single RemoteCommand that sends stdout/stderr status text. It
	also provides the usual commandComplete / createSummary /
	evaluateCommand / getText methods to be overridden...
	(ShellCommand): .. whereas ShellCommand is specifically for
	running RemoteShellCommands. Other shell-like BuildSteps (like
	Source) can inherit from LoggingBuildStep instead of ShellCommand
	(WithProperties): marker class to do build-property interpolation
	(Source): inherit from LoggingBuildStep instead of ShellCommand
	(RemoteDummy): same

	* buildbot/test/test_properties.py: test new functionality

2006-04-21  Brian Warner  <warner at lothar.com>

	* buildbot/test/test_vc.py: rename testBranch to
	testCheckoutBranch to keep the tests in about the right
	alphabetical order


Index: commands.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/slave/commands.py,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- commands.py	17 Apr 2006 19:22:34 -0000	1.44
+++ commands.py	24 Apr 2006 06:45:37 -0000	1.45
@@ -1,6 +1,6 @@
 # -*- test-case-name: buildbot.test.test_slavecommand -*-
 
-import os, os.path, re, signal, shutil, types
+import os, os.path, re, signal, shutil, types, time
 
 from twisted.internet.protocol import ProcessProtocol
 from twisted.internet import reactor, defer
@@ -123,6 +123,14 @@
                  workdir, environ=None,
                  sendStdout=True, sendStderr=True, sendRC=True,
                  timeout=None, stdin=None, keepStdout=False):
+        """
+
+        @param keepStdout: if True, we keep a copy of all the stdout text
+                           that we've seen. This copy is available in
+                           self.stdout, which can be read after the command
+                           has finished.
+        """
+
         self.builder = builder
         self.command = command
         self.sendStdout = sendStdout
@@ -680,6 +688,7 @@
             d = self.doVCFull()
             d.addBoth(self.maybeDoVCRetry)
         d.addCallback(self._abandonOnFailure)
+        d.addCallback(self._handleGotRevision)
         d.addCallback(self.writeSourcedata)
         return d
 
@@ -692,6 +701,28 @@
             return False
         return True
 
+    def _handleGotRevision(self, res):
+        d = defer.maybeDeferred(self.parseGotRevision)
+        d.addCallback(lambda got_revision:
+                      self.sendStatus({'got_revision': got_revision}))
+        return d
+
+    def parseGotRevision(self):
+        """Override this in a subclass. It should return a string that
+        represents which revision was actually checked out, or a Deferred
+        that will fire with such a string. If, in a future build, you were to
+        pass this 'got_revision' string in as the 'revision' component of a
+        SourceStamp, you should wind up with the same source code as this
+        checkout just obtained.
+
+        It is probably most useful to scan self.command.stdout for a string
+        of some sort. Be sure to set keepStdout=True on the VC command that
+        you run, so that you'll have something available to look at.
+
+        If this information is unavailable, just return None."""
+
+        return None
+
     def writeSourcedata(self, res):
         open(self.sourcedatafile, "w").write(self.sourcedata)
         return res
@@ -910,6 +941,13 @@
         self.command = c
         return c.start()
 
+    def parseGotRevision(self):
+        # CVS does not have any kind of revision stamp to speak of. We return
+        # the current timestamp as a best-effort guess, but this depends upon
+        # the local system having a clock that is
+        # reasonably-well-synchronized with the repository.
+        return time.strftime("%Y-%m-%d %H:%M:%S %z", time.gmtime())
+
 registerSlaveCommand("cvs", CVS, cvs_ver)
 
 class SVN(SourceBase):
@@ -939,7 +977,8 @@
         d = os.path.join(self.builder.basedir, self.srcdir)
         command = ['svn', 'update', '--revision', str(revision)]
         c = ShellCommand(self.builder, command, d,
-                         sendRC=False, timeout=self.timeout)
+                         sendRC=False, timeout=self.timeout,
+                         keepStdout=True)
         self.command = c
         return c.start()
 
@@ -954,10 +993,22 @@
             command = ['svn', 'checkout', '--revision', str(revision),
                        self.svnurl, self.srcdir]
         c = ShellCommand(self.builder, command, d,
-                         sendRC=False, timeout=self.timeout)
+                         sendRC=False, timeout=self.timeout,
+                         keepStdout=True)
         self.command = c
         return c.start()
 
+    def parseGotRevision(self):
+        # svn checkout operations finish with 'Checked out revision 16657.'
+        # svn update operations finish the line 'At revision 16654.'
+        lines = self.command.stdout.rstrip().split("\n")
+        lastline = lines[-1]
+        r = re.search(r'revision (\d+)\.', lastline)
+        if r:
+            return int(r.group(1))
+        return None
+
+
 registerSlaveCommand("svn", SVN, cvs_ver)
 
 class Darcs(SourceBase):
@@ -1023,6 +1074,18 @@
         os.unlink(n)
         return res
 
+    def parseGotRevision(self):
+        # we use 'darcs context' to find out what we wound up with
+        command = ["darcs", "changes", "--context"]
+        c = ShellCommand(self.builder, command,
+                         os.path.join(self.builder.basedir, self.srcdir),
+                         sendStdout=False, sendStderr=False, sendRC=False,
+                         keepStdout=True)
+        c.usePTY = False
+        d = c.start()
+        d.addCallback(lambda res: c.stdout)
+        return d
+
 registerSlaveCommand("darcs", Darcs, cvs_ver)
 
 class Git(SourceBase):
@@ -1175,6 +1238,27 @@
         d.addCallback(self._abandonOnFailure)
         return d
 
+    def parseGotRevision(self):
+        # using code from tryclient.TlaExtractor
+        # 'tla logs --full' gives us ARCHIVE/BRANCH--REVISION
+        # 'tla logs' gives us REVISION
+        command = ["tla", "logs", "--full", "--reverse"]
+        c = ShellCommand(self.builder, command,
+                         os.path.join(self.builder.basedir, self.srcdir),
+                         sendStdout=False, sendStderr=False, sendRC=False,
+                         keepStdout=True)
+        c.usePTY = False
+        d = c.start()
+        def _parse(res):
+            tid = c.stdout.split("\n")[0].strip()
+            slash = tid.index("/")
+            dd = tid.rindex("--")
+            #branch = tid[slash+1:dd]
+            baserev = tid[dd+2:]
+            return baserev
+        d.addCallback(_parse)
+        return d
+
 registerSlaveCommand("arch", Arch, cvs_ver)
 
 class Bazaar(Arch):
@@ -1217,6 +1301,25 @@
             d.addCallback(self._didGet)
         return d
 
+    def parseGotRevision(self):
+        # using code from tryclient.BazExtractor
+        command = ["baz", "tree-id"]
+        c = ShellCommand(self.builder, command,
+                         os.path.join(self.builder.basedir, self.srcdir),
+                         sendStdout=False, sendStderr=False, sendRC=False,
+                         keepStdout=True)
+        c.usePTY = False
+        d = c.start()
+        def _parse(res):
+            tid = c.stdout.strip()
+            slash = tid.index("/")
+            dd = tid.rindex("--")
+            #branch = tid[slash+1:dd]
+            baserev = tid[dd+2:]
+            return baserev
+        d.addCallback(_parse)
+        return d
+
 registerSlaveCommand("bazaar", Bazaar, cvs_ver)
 
 
@@ -1281,6 +1384,20 @@
         self.command = c
         return c.start()
 
+    def parseGotRevision(self):
+        # we use 'hg identify' to find out what we wound up with
+        command = ["hg", "identify"]
+        c = ShellCommand(self.builder, command,
+                         os.path.join(self.builder.basedir, self.srcdir),
+                         sendStdout=False, sendStderr=False, sendRC=False,
+                         keepStdout=True)
+        d = c.start()
+        def _parse(res):
+            m = re.search(r'^(\w+)', c.stdout)
+            return m.group(1)
+        d.addCallback(_parse)
+        return d
+
 registerSlaveCommand("hg", Mercurial, cvs_ver)
 
 





More information about the Commits mailing list