Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/buildbot/buildbot/sourcestamp.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildbot/buildbot/sourcestamp.py')
-rw-r--r--buildbot/buildbot/sourcestamp.py95
1 files changed, 95 insertions, 0 deletions
diff --git a/buildbot/buildbot/sourcestamp.py b/buildbot/buildbot/sourcestamp.py
new file mode 100644
index 0000000..e2162ca
--- /dev/null
+++ b/buildbot/buildbot/sourcestamp.py
@@ -0,0 +1,95 @@
+
+from zope.interface import implements
+from buildbot import util, interfaces
+
+class SourceStamp(util.ComparableMixin):
+ """This is a tuple of (branch, revision, patchspec, changes).
+
+ C{branch} is always valid, although it may be None to let the Source
+ step use its default branch. There are three possibilities for the
+ remaining elements:
+ - (revision=REV, patchspec=None, changes=None): build REV. If REV is
+ None, build the HEAD revision from the given branch.
+ - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV,
+ then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}.
+ If REV is None, checkout HEAD and patch it.
+ - (revision=None, patchspec=None, changes=[CHANGES]): let the Source
+ step check out the latest revision indicated by the given Changes.
+ CHANGES is a tuple of L{buildbot.changes.changes.Change} instances,
+ and all must be on the same branch.
+ """
+
+ # all four of these are publically visible attributes
+ branch = None
+ revision = None
+ patch = None
+ changes = ()
+
+ compare_attrs = ('branch', 'revision', 'patch', 'changes')
+
+ implements(interfaces.ISourceStamp)
+
+ def __init__(self, branch=None, revision=None, patch=None,
+ changes=None):
+ self.branch = branch
+ self.revision = revision
+ self.patch = patch
+ if changes:
+ self.changes = tuple(changes)
+ self.branch = changes[0].branch
+
+ def canBeMergedWith(self, other):
+ if other.branch != self.branch:
+ return False # the builds are completely unrelated
+
+ if self.changes and other.changes:
+ # TODO: consider not merging these. It's a tradeoff between
+ # minimizing the number of builds and obtaining finer-grained
+ # results.
+ return True
+ elif self.changes and not other.changes:
+ return False # we're using changes, they aren't
+ elif not self.changes and other.changes:
+ return False # they're using changes, we aren't
+
+ if self.patch or other.patch:
+ return False # you can't merge patched builds with anything
+ if self.revision == other.revision:
+ # both builds are using the same specific revision, so they can
+ # be merged. It might be the case that revision==None, so they're
+ # both building HEAD.
+ return True
+
+ return False
+
+ def mergeWith(self, others):
+ """Generate a SourceStamp for the merger of me and all the other
+ BuildRequests. This is called by a Build when it starts, to figure
+ out what its sourceStamp should be."""
+
+ # either we're all building the same thing (changes==None), or we're
+ # all building changes (which can be merged)
+ changes = []
+ changes.extend(self.changes)
+ for req in others:
+ assert self.canBeMergedWith(req) # should have been checked already
+ changes.extend(req.changes)
+ newsource = SourceStamp(branch=self.branch,
+ revision=self.revision,
+ patch=self.patch,
+ changes=changes)
+ return newsource
+
+ def getAbsoluteSourceStamp(self, got_revision):
+ return SourceStamp(branch=self.branch, revision=got_revision, patch=self.patch)
+
+ def getText(self):
+ # TODO: this won't work for VC's with huge 'revision' strings
+ if self.revision is None:
+ return [ "latest" ]
+ text = [ str(self.revision) ]
+ if self.branch:
+ text.append("in '%s'" % self.branch)
+ if self.patch:
+ text.append("[patch]")
+ return text