Package buildbot :: Module sourcestamp
[frames] | no frames]

Source Code for Module buildbot.sourcestamp

  1  # -*- test-case-name: buildbot.test.test_sourcestamp -*- 
  2   
  3  from zope.interface import implements 
  4  from twisted.persisted import styles 
  5  from buildbot import util, interfaces 
  6   
7 -class SourceStamp(util.ComparableMixin, styles.Versioned):
8 """This is a tuple of (branch, revision, patchspec, changes, project, repository). 9 10 C{branch} is always valid, although it may be None to let the Source 11 step use its default branch. There are three possibilities for the 12 remaining elements: 13 - (revision=REV, patchspec=None, changes=None): build REV. If REV is 14 None, build the HEAD revision from the given branch. Note that REV 15 must always be a string: SVN, Perforce, and other systems which use 16 integers should provide a string here, but the Source checkout step 17 will integerize it when making comparisons. 18 - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV, 19 then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}. 20 If REV is None, checkout HEAD and patch it. 21 - (revision=None, patchspec=None, changes=[CHANGES]): let the Source 22 step check out the latest revision indicated by the given Changes. 23 CHANGES is a tuple of L{buildbot.changes.changes.Change} instances, 24 and all must be on the same branch. 25 """ 26 27 persistenceVersion = 2 28 29 # all six of these are publically visible attributes 30 branch = None 31 revision = None 32 patch = None 33 changes = () 34 project = '' 35 repository = '' 36 ssid = None # filled in by db.get_sourcestampid() 37 38 compare_attrs = ('branch', 'revision', 'patch', 'changes', 'project', 'repository') 39 40 implements(interfaces.ISourceStamp) 41
42 - def __init__(self, branch=None, revision=None, patch=None, 43 changes=None, project='', repository=''):
44 if revision is not None: 45 if isinstance(revision, int): 46 revision = str(revision) 47 if patch is not None: 48 assert len(patch) == 2 49 assert int(patch[0]) != -1 50 self.branch = branch 51 self.revision = revision 52 self.patch = patch 53 self.project = project 54 self.repository = repository 55 if changes: 56 self.changes = tuple(changes) 57 # set branch and revision to most recent change 58 self.branch = changes[-1].branch 59 self.revision = str(changes[-1].revision) 60 if not self.project: 61 self.project = changes[-1].project 62 if not self.repository: 63 self.repository = changes[-1].repository
64
65 - def canBeMergedWith(self, other):
66 if other.repository != self.repository: 67 return False 68 if other.branch != self.branch: 69 return False # the builds are completely unrelated 70 if other.project != self.project: 71 return False 72 73 if self.changes and other.changes: 74 # TODO: consider not merging these. It's a tradeoff between 75 # minimizing the number of builds and obtaining finer-grained 76 # results. 77 return True 78 elif self.changes and not other.changes: 79 return False # we're using changes, they aren't 80 elif not self.changes and other.changes: 81 return False # they're using changes, we aren't 82 83 if self.patch or other.patch: 84 return False # you can't merge patched builds with anything 85 if self.revision == other.revision: 86 # both builds are using the same specific revision, so they can 87 # be merged. It might be the case that revision==None, so they're 88 # both building HEAD. 89 return True 90 91 return False
92
93 - def mergeWith(self, others):
94 """Generate a SourceStamp for the merger of me and all the other 95 BuildRequests. This is called by a Build when it starts, to figure 96 out what its sourceStamp should be.""" 97 98 # either we're all building the same thing (changes==None), or we're 99 # all building changes (which can be merged) 100 changes = [] 101 changes.extend(self.changes) 102 for req in others: 103 assert self.canBeMergedWith(req) # should have been checked already 104 changes.extend(req.changes) 105 newsource = SourceStamp(branch=self.branch, 106 revision=self.revision, 107 patch=self.patch, 108 project=self.project, 109 repository=self.repository, 110 changes=changes) 111 return newsource
112
113 - def getAbsoluteSourceStamp(self, got_revision):
114 return SourceStamp(branch=self.branch, revision=got_revision, 115 patch=self.patch, repository=self.repository, 116 project=self.project)
117
118 - def getText(self):
119 # note: this won't work for VC systems with huge 'revision' strings 120 text = [] 121 if self.project: 122 text.append("for %s" % self.project) 123 if self.repository: 124 text.append("in %s" % self.repository) 125 if self.revision is None: 126 return text + [ "latest" ] 127 text.append(str(self.revision)) 128 if self.branch: 129 text.append("in '%s'" % self.branch) 130 if self.patch: 131 text.append("[patch]") 132 return text
133
134 - def asDict(self):
135 result = {} 136 # Constant 137 result['revision'] = self.revision 138 # TODO(maruel): Make the patch content a suburl. 139 result['hasPatch'] = self.patch is not None 140 result['branch'] = self.branch 141 result['changes'] = [c.asDict() for c in getattr(self, 'changes', [])] 142 result['project'] = self.project 143 result['repository'] = self.repository 144 return result
145
146 - def upgradeToVersion1(self):
147 # version 0 was untyped; in version 1 and later, types matter. 148 if self.branch is not None and not isinstance(self.branch, str): 149 self.branch = str(self.branch) 150 if self.revision is not None and not isinstance(self.revision, str): 151 self.revision = str(self.revision) 152 if self.patch is not None: 153 self.patch = ( int(self.patch[0]), str(self.patch[1]) )
154
155 - def upgradeToVersion2(self):
156 # version 1 did not have project or repository; just set them to a default '' 157 self.project = '' 158 self.repository = ''
159 160 # vim: set ts=4 sts=4 sw=4 et: 161