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

Source Code for Module buildbot.sourcestamp

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