|
# This file is part of Buildbot. Buildbot is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation, version 2. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Copyright Buildbot Team Members
# TODO: kill this class, or at least make it less significant """This is a tuple of (branch, revision, patchspec, changes, project, repository).
C{branch} is always valid, although it may be None to let the Source step use its default branch. There are three possibilities for the remaining elements: - (revision=REV, patchspec=None, changes=None): build REV. If REV is None, build the HEAD revision from the given branch. Note that REV must always be a string: SVN, Perforce, and other systems which use integers should provide a string here, but the Source checkout step will integerize it when making comparisons. - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV, then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}. If REV is None, checkout HEAD and patch it. - (revision=None, patchspec=None, changes=[CHANGES]): let the Source step check out the latest revision indicated by the given Changes. CHANGES is a tuple of L{buildbot.changes.changes.Change} instances, and all must be on the same branch.
@ivar ssid: sourcestamp ID, or None if this sourcestamp has not yet been added to the database
@ivar branch: branch name or None
@ivar revision: revision string or None
@ivar patch: tuple (patch level, patch body) or None
@ivar patch_info: tuple (patch author, patch comment) or None
@ivar changes: tuple of changes that went into this source stamp, sorted by number
@ivar project: project name
@ivar repository: repository URL """
# all seven of these are publicly visible attributes
def fromSsdict(cls, master, ssdict): """ Class method to create a L{SourceStamp} from a dictionary as returned by L{SourceStampConnectorComponent.getSourceStamp}.
@param master: build master instance @param ssdict: source stamp dictionary
@returns: L{SourceStamp} via Deferred """ # try to fetch from the cache, falling back to _make_ss if not # found
def _make_ss(cls, ssid, ssdict, master):
ssdict.get('patch_subdir')) ssdict['patch_comment'])
# sort the changeids in order, oldest to newest Change.fromChdict(master, chdict)) for id in sorted_changeids ]) else:
patch_info=None, changes=None, project='', repository='', codebase = '', _fromSsdict=False, _ignoreChanges=False):
# skip all this madness if we're being built from the database
assert 2 <= len(patch) <= 3 assert int(patch[0]) != -1 # set branch and revision to most recent change
revision = str(revision)
# this algorithm implements the "compatible" mergeRequests defined in # detail in cfg-buidlers.texinfo; change that documentation if the # algorithm changes! return False return False return False # you can't merge patched builds with anything
return True return False # we're using changes, they aren't return False # they're using changes, we aren't
# both builds are using the same specific revision, so they can # be merged. It might be the case that revision==None, so they're # both building HEAD.
return False
"""Generate a SourceStamp for the merger of me and all the other SourceStamps. This is called by a Build when it starts, to figure out what its sourceStamp should be."""
# either we're all building the same thing (changes==None), or we're # all building changes (which can be merged) branch=self.branch, revision=self.revision, patch=self.patch, patch_info=self.patch_info, project=self.project, repository=self.repository, codebase=self.codebase, changes=changes)
# Create an exact but identityless copy patch=self.patch, repository=self.repository, codebase=self.codebase, patch_info=self.patch_info, project=self.project, changes=self.changes, _ignoreChanges=True)
# note: this won't work for VC systems with huge 'revision' strings text = [] if self.project: text.append("for %s" % self.project) if self.repository: text.append("in %s" % self.repository) if self.codebase: text.append("(%s)" % self.codebase) if self.revision is None: return text + [ "latest" ] text.append(str(self.revision)) if self.branch: text.append("in '%s'" % self.branch) if self.patch: text.append("[patch]") return text
result = {} # Constant result['revision'] = self.revision # TODO(maruel): Make the patch content a suburl. result['hasPatch'] = self.patch is not None result['branch'] = self.branch result['changes'] = [c.asDict() for c in getattr(self, 'changes', [])] result['project'] = self.project result['repository'] = self.repository result['codebase'] = self.codebase return result
# version 0 was untyped; in version 1 and later, types matter. if self.branch is not None and not isinstance(self.branch, str): self.branch = str(self.branch) if self.revision is not None and not isinstance(self.revision, str): self.revision = str(self.revision) if self.patch is not None: self.patch = ( int(self.patch[0]), str(self.patch[1]) ) self.wasUpgraded = True
# version 1 did not have project or repository; just set them to a default '' self.project = '' self.repository = '' self.wasUpgraded = True
#The database has been upgraded where all existing sourcestamps got an #setid equal to its ssid #version 2 did not have codebase; set to ''
"temporary; do not use widely!" if self.sourcestampsetid: return defer.succeed(self.sourcestampsetid) else: return self.addSourceStampToDatabase(master)
# add it to the DB patch_body = None patch_level = None patch_subdir = None if self.patch: patch_level = self.patch[0] patch_body = self.patch[1] if len(self.patch) > 2: patch_subdir = self.patch[2]
patch_author = None patch_comment = None if self.patch_info: patch_author, patch_comment = self.patch_info
def get_setid(): if sourcestampsetid is not None: return defer.succeed( sourcestampsetid ) else: return master.db.sourcestampsets.addSourceStampSet()
def set_setid(setid): self.sourcestampsetid = setid return setid
def add_sourcestamp(setid): return master.db.sourcestamps.addSourceStamp( sourcestampsetid=setid, branch=self.branch, revision=self.revision, repository=self.repository, codebase=self.codebase, project=self.project, patch_body=patch_body, patch_level=patch_level, patch_author=patch_author, patch_comment=patch_comment, patch_subdir=patch_subdir, changeids=[c.number for c in self.changes])
def set_ssid(ssid): self.ssid = ssid return ssid
d = get_setid() d.addCallback(set_setid) d.addCallback(add_sourcestamp) d.addCallback(set_ssid) d.addCallback(lambda _ : self.sourcestampsetid) return d |