OLD | NEW |
| (Empty) |
1 # -*- test-case-name: buildbot.test.test_sourcestamp -*- | |
2 | |
3 from zope.interface import implements | |
4 from buildbot import util, interfaces | |
5 | |
6 class SourceStamp(util.ComparableMixin): | |
7 """This is a tuple of (branch, revision, patchspec, changes). | |
8 | |
9 C{branch} is always valid, although it may be None to let the Source | |
10 step use its default branch. There are three possibilities for the | |
11 remaining elements: | |
12 - (revision=REV, patchspec=None, changes=None): build REV. If REV is | |
13 None, build the HEAD revision from the given branch. | |
14 - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV, | |
15 then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}. | |
16 If REV is None, checkout HEAD and patch it. | |
17 - (revision=None, patchspec=None, changes=[CHANGES]): let the Source | |
18 step check out the latest revision indicated by the given Changes. | |
19 CHANGES is a tuple of L{buildbot.changes.changes.Change} instances, | |
20 and all must be on the same branch. | |
21 """ | |
22 | |
23 # all four of these are publically visible attributes | |
24 branch = None | |
25 revision = None | |
26 patch = None | |
27 changes = () | |
28 | |
29 compare_attrs = ('branch', 'revision', 'patch', 'changes') | |
30 | |
31 implements(interfaces.ISourceStamp) | |
32 | |
33 def __init__(self, branch=None, revision=None, patch=None, | |
34 changes=None): | |
35 self.branch = branch | |
36 self.revision = revision | |
37 self.patch = patch | |
38 if changes: | |
39 self.changes = tuple(changes) | |
40 # set branch and revision to most recent change | |
41 self.branch = changes[-1].branch | |
42 self.revision = changes[-1].revision | |
43 | |
44 def canBeMergedWith(self, other): | |
45 if other.branch != self.branch: | |
46 return False # the builds are completely unrelated | |
47 | |
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 | |
57 | |
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 | |
65 | |
66 return False | |
67 | |
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.""" | |
72 | |
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 | |
85 | |
86 def getAbsoluteSourceStamp(self, got_revision): | |
87 return SourceStamp(branch=self.branch, revision=got_revision, patch=self
.patch) | |
88 | |
89 def getText(self): | |
90 # TODO: this won't work for VC's with huge 'revision' strings | |
91 if self.revision is None: | |
92 return [ "latest" ] | |
93 text = [ str(self.revision) ] | |
94 if self.branch: | |
95 text.append("in '%s'" % self.branch) | |
96 if self.patch: | |
97 text.append("[patch]") | |
98 return text | |
99 | |
100 def asDict(self): | |
101 result = {} | |
102 # Constant | |
103 result['revision'] = self.revision | |
104 # TODO(maruel): Make the patch content a suburl. | |
105 result['hasPatch']= self.patch is not None | |
106 result['branch'] = self.branch | |
107 result['changes'] = [c.asDict() for c in getattr(self, 'changes', [])] | |
108 return result | |
109 | |
110 # vim: set ts=4 sts=4 sw=4 et: | |
OLD | NEW |