more NEWS items
[buildbot.git] / buildbot / sourcestamp.py
blob2c9e1ab6ef1e577e0d42d1ce9b31aa664c8a6be3
2 from buildbot import util, interfaces
3 from buildbot.twcompat import implements
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 four possibilities for the
10 remaining elements:
11 - (revision=REV, patchspec=None, changes=None): build REV
12 - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV,
13 then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}.
14 - (revision=None, patchspec=None, changes=[CHANGES]): let the Source
15 step check out the latest revision indicated by the given Changes.
16 CHANGES is a list of L{buildbot.changes.changes.Change} instances,
17 and all must be on the same branch.
18 - (revision=None, patchspec=None, changes=None): build the latest code
19 from the given branch.
20 """
22 # all four of these are publically visible attributes
23 branch = None
24 revision = None
25 patch = None
26 changes = []
28 compare_attrs = ('branch', 'revision', 'patch', 'changes')
30 if implements:
31 implements(interfaces.ISourceStamp)
32 else:
33 __implements__ = interfaces.ISourceStamp,
35 def __init__(self, branch=None, revision=None, patch=None,
36 changes=None):
37 self.branch = branch
38 self.revision = revision
39 self.patch = patch
40 if changes:
41 self.changes = changes
42 self.branch = changes[0].branch
44 def canBeMergedWith(self, other):
45 if other.branch != self.branch:
46 return False # the builds are completely unrelated
48 if self.changes and other.changes:
49 # TODO: consider not merging these. It's a tradeoff between
50 # minimizing the number of builds and obtaining finer-grained
51 # results.
52 return True
53 elif self.changes and not other.changes:
54 return False # we're using changes, they aren't
55 elif not self.changes and other.changes:
56 return False # they're using changes, we aren't
58 if self.patch or other.patch:
59 return False # you can't merge patched builds with anything
60 if self.revision == other.revision:
61 # both builds are using the same specific revision, so they can
62 # be merged. It might be the case that revision==None, so they're
63 # both building HEAD.
64 return True
66 return False
68 def mergeWith(self, others):
69 """Generate a SourceStamp for the merger of me and all the other
70 BuildRequests. This is called by a Build when it starts, to figure
71 out what its sourceStamp should be."""
73 # either we're all building the same thing (changes==None), or we're
74 # all building changes (which can be merged)
75 changes = []
76 changes.extend(self.changes)
77 for req in others:
78 assert self.canBeMergedWith(req) # should have been checked already
79 changes.extend(req.changes)
80 newsource = SourceStamp(branch=self.branch,
81 revision=self.revision,
82 patch=self.patch,
83 changes=changes)
84 return newsource