| 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 |