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 self
.branch
= changes
[0].branch
41 def canBeMergedWith(self
, other
):
42 if other
.branch
!= self
.branch
:
43 return False # the builds are completely unrelated
45 if self
.changes
and other
.changes
:
46 # TODO: consider not merging these. It's a tradeoff between
47 # minimizing the number of builds and obtaining finer-grained
50 elif self
.changes
and not other
.changes
:
51 return False # we're using changes, they aren't
52 elif not self
.changes
and other
.changes
:
53 return False # they're using changes, we aren't
55 if self
.patch
or other
.patch
:
56 return False # you can't merge patched builds with anything
57 if self
.revision
== other
.revision
:
58 # both builds are using the same specific revision, so they can
59 # be merged. It might be the case that revision==None, so they're
65 def mergeWith(self
, others
):
66 """Generate a SourceStamp for the merger of me and all the other
67 BuildRequests. This is called by a Build when it starts, to figure
68 out what its sourceStamp should be."""
70 # either we're all building the same thing (changes==None), or we're
71 # all building changes (which can be merged)
73 changes
.extend(self
.changes
)
75 assert self
.canBeMergedWith(req
) # should have been checked already
76 changes
.extend(req
.changes
)
77 newsource
= SourceStamp(branch
=self
.branch
,
78 revision
=self
.revision
,
83 def getAbsoluteSourceStamp(self
, got_revision
):
84 return SourceStamp(branch
=self
.branch
, revision
=got_revision
, patch
=self
.patch
)
87 # TODO: this won't work for VC's with huge 'revision' strings
88 if self
.revision
is None:
90 text
= [ str(self
.revision
) ]
92 text
.append("in '%s'" % self
.branch
)
94 text
.append("[patch]")