2 from zope
.interface
import implements
3 from buildbot
import util
, interfaces
5 class SourceStamp(util
.ComparableMixin
):
6 """This is a tuple of (branch, revision, patchspec, changes).
8 C{branch} is always valid, although it may be None to let the Source
9 step use its default branch. There are three possibilities for the
11 - (revision=REV, patchspec=None, changes=None): build REV. If REV is
12 None, build the HEAD revision from the given branch.
13 - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV,
14 then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}.
15 If REV is None, checkout HEAD and patch it.
16 - (revision=None, patchspec=None, changes=[CHANGES]): let the Source
17 step check out the latest revision indicated by the given Changes.
18 CHANGES is a tuple of L{buildbot.changes.changes.Change} instances,
19 and all must be on the same branch.
22 # all four of these are publically visible attributes
28 compare_attrs
= ('branch', 'revision', 'patch', 'changes')
30 implements(interfaces
.ISourceStamp
)
32 def __init__(self
, branch
=None, revision
=None, patch
=None,
35 self
.revision
= revision
38 self
.changes
= tuple(changes
)
39 # set branch and revision to most recent change
40 self
.branch
= changes
[-1].branch
41 self
.revision
= changes
[-1].revision
43 def canBeMergedWith(self
, other
):
44 if other
.branch
!= self
.branch
:
45 return False # the builds are completely unrelated
47 if self
.changes
and other
.changes
:
48 # TODO: consider not merging these. It's a tradeoff between
49 # minimizing the number of builds and obtaining finer-grained
52 elif self
.changes
and not other
.changes
:
53 return False # we're using changes, they aren't
54 elif not self
.changes
and other
.changes
:
55 return False # they're using changes, we aren't
57 if self
.patch
or other
.patch
:
58 return False # you can't merge patched builds with anything
59 if self
.revision
== other
.revision
:
60 # both builds are using the same specific revision, so they can
61 # be merged. It might be the case that revision==None, so they're
67 def mergeWith(self
, others
):
68 """Generate a SourceStamp for the merger of me and all the other
69 BuildRequests. This is called by a Build when it starts, to figure
70 out what its sourceStamp should be."""
72 # either we're all building the same thing (changes==None), or we're
73 # all building changes (which can be merged)
75 changes
.extend(self
.changes
)
77 assert self
.canBeMergedWith(req
) # should have been checked already
78 changes
.extend(req
.changes
)
79 newsource
= SourceStamp(branch
=self
.branch
,
80 revision
=self
.revision
,
85 def getAbsoluteSourceStamp(self
, got_revision
):
86 return SourceStamp(branch
=self
.branch
, revision
=got_revision
, patch
=self
.patch
)
89 # TODO: this won't work for VC's with huge 'revision' strings
90 if self
.revision
is None:
92 text
= [ str(self
.revision
) ]
94 text
.append("in '%s'" % self
.branch
)
96 text
.append("[patch]")