From elliot at rpath.com Mon Aug 29 13:43:35 2011 From: elliot at rpath.com (Elliot Peele) Date: Mon, 29 Aug 2011 17:43:35 +0000 Subject: mirrorball: Added tag mirrorball-pre-current for changeset ea13900299f4 Message-ID: <201108291743.p7THhZEP008848@scc.eng.rpath.com> changeset: 19a359fad4b0 user: Elliot Peele date: Mon, 29 Aug 2011 13:44:04 -0400 Added tag mirrorball-pre-current for changeset ea13900299f4 diff --git a/.hgtags b/.hgtags new file mode 100644 --- /dev/null +++ b/.hgtags @@ -0,0 +1,1 @@ +ea13900299f4da6f3d59074a4c2d742f77224269 mirrorball-pre-current From elliot at rpath.com Tue Aug 30 14:29:48 2011 From: elliot at rpath.com (Elliot Peele) Date: Tue, 30 Aug 2011 18:29:48 +0000 Subject: mirrorball: Add support for spliting package jobs when there are duplicates. Message-ID: <201108301829.p7UITmcb023012@scc.eng.rpath.com> changeset: 79fdd4de5fdf user: Elliot Peele date: Tue, 30 Aug 2011 14:29:46 -0400 Add support for spliting package jobs when there are duplicates. diff --git a/updatebot/errors.py b/updatebot/errors.py --- a/updatebot/errors.py +++ b/updatebot/errors.py @@ -317,6 +317,15 @@ _params = ['what'] _template = 'Failed to promote %(what)s' +class CanNotPromoteGroupsAndPackagesTogetherError(PromoteFailedError): + """ + CanNotPromoteGroupsAndPackagesTogetherError, raised when you try to promote + groups and packages at the same time, don't do that. + """ + + _params = ['trvs', ] + _template = 'You can not promote groups and packages at the same time.' + class PromoteMismatchError(PromoteFailedError): """ PromoteMismatchError, raised when the promote to the production label diff --git a/updatebot/update.py b/updatebot/update.py --- a/updatebot/update.py +++ b/updatebot/update.py @@ -34,6 +34,7 @@ from updatebot.errors import UpdateRemovesPackageError from updatebot.errors import ParentPlatformManifestInconsistencyError from updatebot.errors import RepositoryPackageSourceInconsistencyError +from updatebot.errors import CanNotPromoteGroupsAndPackagesTogetherError log = logging.getLogger('updatebot.update') @@ -979,6 +980,38 @@ return self._conaryhelper.getBuildRequires(pkgName) + def _orderPromoteJobList(self, trvLst): + """ + Filter trove list into separate jobs when attempting to promote two + versions of the same package. + """ + + data = {} + for n, v, f in trvLst: + if n.endswith(':source'): + continue + data.setdefault(n.split(':'), dict()).setdefault(v, set()).add(f) + + jobs = [] + + while data: + job = [] + toRemove = [] + for n, vs in data.iteritems(): + v = sorted(vs)[0] + for f in vs.pop(v): + job.append((n, v, f)) + + if not vs: + toRemove.append(n) + + for n in toRemove: + data.pop(n) + + jobs.append(job) + + return jobs + def publish(self, trvLst, expected, targetLabel, checkPackageList=True, extraExpectedPromoteTroves=None, enforceAllExpected=True): """ @@ -999,16 +1032,37 @@ where version and flavor may be None. """ - return self._conaryhelper.promote( - trvLst, - expected, - self._cfg.sourceLabel, - targetLabel, - checkPackageList=checkPackageList, - extraPromoteTroves=self._cfg.extraPromoteTroves, - extraExpectedPromoteTroves=extraExpectedPromoteTroves, - enforceAllExpected=enforceAllExpected, - ) + # Don't try to promote groups and packages together. + grps = [ x for x in trvLst if x[0].startswith('group-') ] + if grps and len(grps) != len(trvLst): + raise CanNotPromoteGroupsAndPackagesTogetherError(trvs=trvLst) + + if grps: + jobs = [ trvLst, ] + else: + # When promoting packages, we know what is being promoted, disable + # the sanity. + jobs = self._orderPromoteJobList(trvLst) + expected = set() + checkPackageList = False + + res = [] + for job in jobs: + res.append(self._conaryhelper.promote( + jobs, + expected, + self._cfg.sourceLabel, + targetLabel, + checkPackageList=checkPackageList, + extraPromoteTroves=self._cfg.extraPromoteTroves, + extraExpectedPromoteTroves=extraExpectedPromoteTroves, + enforceAllExpected=enforceAllExpected, + )) + + if grps: + return res[0] + + return res def mirror(self, fullTroveSync=False): """ From elliot at rpath.com Wed Aug 31 14:28:55 2011 From: elliot at rpath.com (Elliot Peele) Date: Wed, 31 Aug 2011 18:28:55 +0000 Subject: mirrorball: move splitting down into conaryhelper, this makes it easier for builder integration Message-ID: <201108311828.p7VIStpr031954@scc.eng.rpath.com> changeset: dc546ec55a75 user: Elliot Peele date: Tue, 30 Aug 2011 15:38:07 -0400 move splitting down into conaryhelper, this makes it easier for builder integration diff --git a/updatebot/conaryhelper.py b/updatebot/conaryhelper.py --- a/updatebot/conaryhelper.py +++ b/updatebot/conaryhelper.py @@ -46,6 +46,7 @@ from updatebot.errors import PromoteMismatchError from updatebot.errors import MirrorFailedError from updatebot.errors import BinariesNotFoundForSourceVersion +from updatebot.errors import CanNotPromoteGroupsAndPackagesTogetherError from updatebot.lib.findtroves import FindTrovesCache from updatebot.lib.conarycallbacks import UpdateBotCloneCallback @@ -1013,7 +1014,84 @@ return verMap - def promote(self, trvLst, expected, sourceLabels, targetLabel, + @staticmethod + def _iterPromoteJobList(trvLst): + """ + Filter trove list into separate jobs when attempting to promote two + versions of the same package. + """ + + data = {} + for n, v, f in trvLst: + # Skip sources, they come along for free with the underlying + # conary promote code. + if n.endswith(':source'): + continue + data.setdefault(n.split(':'), dict()).setdefault(v, set()).add(f) + + while data: + job = [] + toRemove = [] + for n, vs in data.iteritems(): + v = sorted(vs)[0] + for f in vs.pop(v): + job.append((n, v, f)) + + if not vs: + toRemove.append(n) + + for n in toRemove: + data.pop(n) + + yield job + + def promote(self, trvLst, expected, *args, **kwargs): + """ + Promote a group and its contents to a target label. + @param trvLst: list of troves to publish + @type trvLst: [(name, version, flavor), ... ] + @param expected: list of troves that are expected to be published. + @type expected: [(name, version, flavor), ...] + @param sourceLabels: list of labels that should be flattened onto the + targetLabel. + @type sourceLabels: [labelObject, ... ] + @param targetLabel: table to publish to + @type targetLabel: conary Label object + @param checkPackageList: verify the list of packages being promoted or + not. + @type checkPackageList: boolean + @param extraPromoteTroves: troves to promote in addition to the troves + that have been built. + @type extraPromoteTroves: list of trove specs. + @param extraExpectedPromoteTroves: list of trove nvfs that are expected + to be promoted, but are only filtered + by name, rather than version and + flavor. + @type extraExpectedPromoteTroves: list of name, version, flavor tuples + where version and flavor may be None. + @param commit: commit the promote changeset or just return it. + @type commit: boolean + """ + + # Make sure we are not trying to promote packages and groups together. + grps = [ x for x in trvLst if x[0].startswith('group-') ] + if grps and len(grps) != len(trvLst): + raise CanNotPromoteGroupsAndPackagesTogetherError(trvs=trvLst) + + # IF we are just dealing with a normal group promote, go ahead + # and do it. + if grps: + return self._promote(trvLst, expected, *args, **kwargs) + + # Otherwise we need to split up the job and deal with all of the + # packages. + results = [] + kwargs['checkPackageList'] = False + for job in self._iterPromoteJobList(trvLst): + results.append(self._promote(job, set(), *args, **kwargs)) + return results + + def _promote(self, trvLst, expected, sourceLabels, targetLabel, checkPackageList=True, extraPromoteTroves=None, extraExpectedPromoteTroves=None, commit=True, enforceAllExpected=True): diff --git a/updatebot/update.py b/updatebot/update.py --- a/updatebot/update.py +++ b/updatebot/update.py @@ -34,7 +34,6 @@ from updatebot.errors import UpdateRemovesPackageError from updatebot.errors import ParentPlatformManifestInconsistencyError from updatebot.errors import RepositoryPackageSourceInconsistencyError -from updatebot.errors import CanNotPromoteGroupsAndPackagesTogetherError log = logging.getLogger('updatebot.update') @@ -980,38 +979,6 @@ return self._conaryhelper.getBuildRequires(pkgName) - def _orderPromoteJobList(self, trvLst): - """ - Filter trove list into separate jobs when attempting to promote two - versions of the same package. - """ - - data = {} - for n, v, f in trvLst: - if n.endswith(':source'): - continue - data.setdefault(n.split(':'), dict()).setdefault(v, set()).add(f) - - jobs = [] - - while data: - job = [] - toRemove = [] - for n, vs in data.iteritems(): - v = sorted(vs)[0] - for f in vs.pop(v): - job.append((n, v, f)) - - if not vs: - toRemove.append(n) - - for n in toRemove: - data.pop(n) - - jobs.append(job) - - return jobs - def publish(self, trvLst, expected, targetLabel, checkPackageList=True, extraExpectedPromoteTroves=None, enforceAllExpected=True): """ @@ -1032,37 +999,16 @@ where version and flavor may be None. """ - # Don't try to promote groups and packages together. - grps = [ x for x in trvLst if x[0].startswith('group-') ] - if grps and len(grps) != len(trvLst): - raise CanNotPromoteGroupsAndPackagesTogetherError(trvs=trvLst) - - if grps: - jobs = [ trvLst, ] - else: - # When promoting packages, we know what is being promoted, disable - # the sanity. - jobs = self._orderPromoteJobList(trvLst) - expected = set() - checkPackageList = False - - res = [] - for job in jobs: - res.append(self._conaryhelper.promote( - jobs, - expected, - self._cfg.sourceLabel, - targetLabel, - checkPackageList=checkPackageList, - extraPromoteTroves=self._cfg.extraPromoteTroves, - extraExpectedPromoteTroves=extraExpectedPromoteTroves, - enforceAllExpected=enforceAllExpected, - )) - - if grps: - return res[0] - - return res + return self._conaryhelper.promote( + trvLst, + expected, + self._cfg.sourceLabel, + targetLabel, + checkPackageList=checkPackageList, + extraPromoteTroves=self._cfg.extraPromoteTroves, + extraExpectedPromoteTroves=extraExpectedPromoteTroves, + enforceAllExpected=enforceAllExpected, + ) def mirror(self, fullTroveSync=False): """ From elliot at rpath.com Wed Aug 31 14:28:56 2011 From: elliot at rpath.com (Elliot Peele) Date: Wed, 31 Aug 2011 18:28:56 +0000 Subject: mirrorball: begining of promote dispatcher Message-ID: <201108311828.p7VISuoF031985@scc.eng.rpath.com> changeset: cd7489350bee user: Elliot Peele date: Wed, 31 Aug 2011 14:28:36 -0400 begining of promote dispatcher diff --git a/updatebot/build/constants.py b/updatebot/build/constants.py --- a/updatebot/build/constants.py +++ b/updatebot/build/constants.py @@ -38,6 +38,7 @@ LOCAL_GROUP_BUILD = 3 LOCAL_CHANGESET_COMMIT = 4 REBUILD_START = 5 + PROMOTE = 6 names = { START: 'Start', @@ -46,6 +47,7 @@ LOCAL_GROUP_BUILD: 'Local Group Build', LOCAL_CHANGESET_COMMIT: 'Local Changeset Commit', REBUILD_START: 'Rebuild Start', + PROMOTE: 'Promote Troves', } @@ -63,3 +65,6 @@ JOB_COMMITTED = -7 JOB_FAILED = -8 JOB_STARTING = -9 + JOB_PROMOTING = -10 + JOB_PROMOTED = -11 + ERROR_PROMOTE_FAILURE = -12 diff --git a/updatebot/build/dispatcher.py b/updatebot/build/dispatcher.py --- a/updatebot/build/dispatcher.py +++ b/updatebot/build/dispatcher.py @@ -28,6 +28,7 @@ from updatebot.build.monitor import JobMonitor from updatebot.build.monitor import JobCommitter from updatebot.build.monitor import JobRebuildStarter +from updatebot.build.monitor import JobPromoter from updatebot.build.constants import JobStatus @@ -418,3 +419,64 @@ self._starter = self._starterClass((builder, useLatest, additionalResolveTroves)) + + +class PromoteDispatcher(Dispatcher): + """ + Dispatcher class that promotes the builds to the production label once they + are complete. + """ + + _completed = ( + JobStatus.ERROR_MONITOR_FAILURE, + JobStatus.ERROR_COMMITTER_FAILURE, + JobStatus.ERROR_PROMOTE_FAILURE, + buildjob.JOB_STATE_FAILED, + JobStatus.JOB_PROMOTED, + ) + + _slotdone = ( + buildjob.JOB_STATE_FAILED, + buildjob.JOB_STATE_BUILT + ) + + _promoterClass = JobPromoter + + def __init__(self, builder, maxSlots): + Dispatcher.__init__(self, builder, maxSlots) + + self._promoteSlots = util.BoundedCounter(0, 2, 2) + + self._promoter = self._promoterClass(self._builder._conaryhelper, + self._builder._cfg.targetLabel) + + def _jobDone(self): + # Override the job done method from the parent to hook into the + # build loop. This is kinda dirty, but I don't really have a + # better idea at the moment. + + done = Dispatcher._jobDone(self) + if done: + return done + + self._promoteJobs() + + return done + + def _promoteJobs(self): + """ + Handle the promote section of the build loop. + """ + + # Find jobs in the Committed state that need to be promoted + toPromote = [] + for jobId, (trove, state, result) in self._jobs.iteritems(): + # not ready to be promoted + if state != JobStatus.JOB_COMMITTED: + continue + + toPromote.append((jobId, result)) + + if self._promoteSlots and toPromote: + self._promoteSlots -= 1 + self._promoter.promoteJob(toPromote) diff --git a/updatebot/build/monitor.py b/updatebot/build/monitor.py --- a/updatebot/build/monitor.py +++ b/updatebot/build/monitor.py @@ -140,6 +140,31 @@ self.status.put((MessageTypes.DATA, (self.jobId, result))) +class PromoteWorker(AbstractWorker): + """ + Worker thread for promoting committed troves. + """ + + threadType = WorkerTypes.PROMOTE + + def __init__(self, status, (helper, targetLabel, trvLst)): + AbstractWorker.__init__(self, status) + + self.helper = helper + self.targetLabel = targetLabel + self.trvLst = trvLst + + def work(self): + """ + Promote the specified list of troves. + """ + + srcLabel = self.trvLst[0][1].trailingLabel() + result = self.helper.promote(self.trvLst, set(), srcLabel, + self.targetLabel, checkPackageList=False) + self.status.put((MessageTypes.DATA, (self.trvLst, result))) + + class JobStarter(AbstractStatusMonitor): """ Abstraction around threaded starter model. @@ -174,3 +199,12 @@ workerClass = CommitWorker commitJob = AbstractStatusMonitor.addJob + + +class JobPromoter(AbstractStatusMonitor): + """ + Abstraction around threaded promote model. + """ + + workerClass = PromoteWorker + promoteJob = AbstractStatusMonitor.addJob From elliot at rpath.com Wed Aug 31 14:28:56 2011 From: elliot at rpath.com (Elliot Peele) Date: Wed, 31 Aug 2011 18:28:56 +0000 Subject: mirrorball: branch merge Message-ID: <201108311828.p7VISuB1032012@scc.eng.rpath.com> changeset: 495215ab957a user: Elliot Peele date: Wed, 31 Aug 2011 14:28:53 -0400 branch merge diff --git a/updatebot/build/constants.py b/updatebot/build/constants.py --- a/updatebot/build/constants.py +++ b/updatebot/build/constants.py @@ -38,6 +38,7 @@ LOCAL_GROUP_BUILD = 3 LOCAL_CHANGESET_COMMIT = 4 REBUILD_START = 5 + PROMOTE = 6 names = { START: 'Start', @@ -46,6 +47,7 @@ LOCAL_GROUP_BUILD: 'Local Group Build', LOCAL_CHANGESET_COMMIT: 'Local Changeset Commit', REBUILD_START: 'Rebuild Start', + PROMOTE: 'Promote Troves', } @@ -63,3 +65,6 @@ JOB_COMMITTED = -7 JOB_FAILED = -8 JOB_STARTING = -9 + JOB_PROMOTING = -10 + JOB_PROMOTED = -11 + ERROR_PROMOTE_FAILURE = -12 diff --git a/updatebot/build/dispatcher.py b/updatebot/build/dispatcher.py --- a/updatebot/build/dispatcher.py +++ b/updatebot/build/dispatcher.py @@ -28,6 +28,7 @@ from updatebot.build.monitor import JobMonitor from updatebot.build.monitor import JobCommitter from updatebot.build.monitor import JobRebuildStarter +from updatebot.build.monitor import JobPromoter from updatebot.build.constants import JobStatus @@ -418,3 +419,64 @@ self._starter = self._starterClass((builder, useLatest, additionalResolveTroves)) + + +class PromoteDispatcher(Dispatcher): + """ + Dispatcher class that promotes the builds to the production label once they + are complete. + """ + + _completed = ( + JobStatus.ERROR_MONITOR_FAILURE, + JobStatus.ERROR_COMMITTER_FAILURE, + JobStatus.ERROR_PROMOTE_FAILURE, + buildjob.JOB_STATE_FAILED, + JobStatus.JOB_PROMOTED, + ) + + _slotdone = ( + buildjob.JOB_STATE_FAILED, + buildjob.JOB_STATE_BUILT + ) + + _promoterClass = JobPromoter + + def __init__(self, builder, maxSlots): + Dispatcher.__init__(self, builder, maxSlots) + + self._promoteSlots = util.BoundedCounter(0, 2, 2) + + self._promoter = self._promoterClass(self._builder._conaryhelper, + self._builder._cfg.targetLabel) + + def _jobDone(self): + # Override the job done method from the parent to hook into the + # build loop. This is kinda dirty, but I don't really have a + # better idea at the moment. + + done = Dispatcher._jobDone(self) + if done: + return done + + self._promoteJobs() + + return done + + def _promoteJobs(self): + """ + Handle the promote section of the build loop. + """ + + # Find jobs in the Committed state that need to be promoted + toPromote = [] + for jobId, (trove, state, result) in self._jobs.iteritems(): + # not ready to be promoted + if state != JobStatus.JOB_COMMITTED: + continue + + toPromote.append((jobId, result)) + + if self._promoteSlots and toPromote: + self._promoteSlots -= 1 + self._promoter.promoteJob(toPromote) diff --git a/updatebot/build/monitor.py b/updatebot/build/monitor.py --- a/updatebot/build/monitor.py +++ b/updatebot/build/monitor.py @@ -140,6 +140,31 @@ self.status.put((MessageTypes.DATA, (self.jobId, result))) +class PromoteWorker(AbstractWorker): + """ + Worker thread for promoting committed troves. + """ + + threadType = WorkerTypes.PROMOTE + + def __init__(self, status, (helper, targetLabel, trvLst)): + AbstractWorker.__init__(self, status) + + self.helper = helper + self.targetLabel = targetLabel + self.trvLst = trvLst + + def work(self): + """ + Promote the specified list of troves. + """ + + srcLabel = self.trvLst[0][1].trailingLabel() + result = self.helper.promote(self.trvLst, set(), srcLabel, + self.targetLabel, checkPackageList=False) + self.status.put((MessageTypes.DATA, (self.trvLst, result))) + + class JobStarter(AbstractStatusMonitor): """ Abstraction around threaded starter model. @@ -174,3 +199,12 @@ workerClass = CommitWorker commitJob = AbstractStatusMonitor.addJob + + +class JobPromoter(AbstractStatusMonitor): + """ + Abstraction around threaded promote model. + """ + + workerClass = PromoteWorker + promoteJob = AbstractStatusMonitor.addJob diff --git a/updatebot/conaryhelper.py b/updatebot/conaryhelper.py --- a/updatebot/conaryhelper.py +++ b/updatebot/conaryhelper.py @@ -46,6 +46,7 @@ from updatebot.errors import PromoteMismatchError from updatebot.errors import MirrorFailedError from updatebot.errors import BinariesNotFoundForSourceVersion +from updatebot.errors import CanNotPromoteGroupsAndPackagesTogetherError from updatebot.lib.findtroves import FindTrovesCache from updatebot.lib.conarycallbacks import UpdateBotCloneCallback @@ -1013,7 +1014,84 @@ return verMap - def promote(self, trvLst, expected, sourceLabels, targetLabel, + @staticmethod + def _iterPromoteJobList(trvLst): + """ + Filter trove list into separate jobs when attempting to promote two + versions of the same package. + """ + + data = {} + for n, v, f in trvLst: + # Skip sources, they come along for free with the underlying + # conary promote code. + if n.endswith(':source'): + continue + data.setdefault(n.split(':'), dict()).setdefault(v, set()).add(f) + + while data: + job = [] + toRemove = [] + for n, vs in data.iteritems(): + v = sorted(vs)[0] + for f in vs.pop(v): + job.append((n, v, f)) + + if not vs: + toRemove.append(n) + + for n in toRemove: + data.pop(n) + + yield job + + def promote(self, trvLst, expected, *args, **kwargs): + """ + Promote a group and its contents to a target label. + @param trvLst: list of troves to publish + @type trvLst: [(name, version, flavor), ... ] + @param expected: list of troves that are expected to be published. + @type expected: [(name, version, flavor), ...] + @param sourceLabels: list of labels that should be flattened onto the + targetLabel. + @type sourceLabels: [labelObject, ... ] + @param targetLabel: table to publish to + @type targetLabel: conary Label object + @param checkPackageList: verify the list of packages being promoted or + not. + @type checkPackageList: boolean + @param extraPromoteTroves: troves to promote in addition to the troves + that have been built. + @type extraPromoteTroves: list of trove specs. + @param extraExpectedPromoteTroves: list of trove nvfs that are expected + to be promoted, but are only filtered + by name, rather than version and + flavor. + @type extraExpectedPromoteTroves: list of name, version, flavor tuples + where version and flavor may be None. + @param commit: commit the promote changeset or just return it. + @type commit: boolean + """ + + # Make sure we are not trying to promote packages and groups together. + grps = [ x for x in trvLst if x[0].startswith('group-') ] + if grps and len(grps) != len(trvLst): + raise CanNotPromoteGroupsAndPackagesTogetherError(trvs=trvLst) + + # IF we are just dealing with a normal group promote, go ahead + # and do it. + if grps: + return self._promote(trvLst, expected, *args, **kwargs) + + # Otherwise we need to split up the job and deal with all of the + # packages. + results = [] + kwargs['checkPackageList'] = False + for job in self._iterPromoteJobList(trvLst): + results.append(self._promote(job, set(), *args, **kwargs)) + return results + + def _promote(self, trvLst, expected, sourceLabels, targetLabel, checkPackageList=True, extraPromoteTroves=None, extraExpectedPromoteTroves=None, commit=True, enforceAllExpected=True): diff --git a/updatebot/update.py b/updatebot/update.py --- a/updatebot/update.py +++ b/updatebot/update.py @@ -34,7 +34,6 @@ from updatebot.errors import UpdateRemovesPackageError from updatebot.errors import ParentPlatformManifestInconsistencyError from updatebot.errors import RepositoryPackageSourceInconsistencyError -from updatebot.errors import CanNotPromoteGroupsAndPackagesTogetherError log = logging.getLogger('updatebot.update') @@ -980,38 +979,6 @@ return self._conaryhelper.getBuildRequires(pkgName) - def _orderPromoteJobList(self, trvLst): - """ - Filter trove list into separate jobs when attempting to promote two - versions of the same package. - """ - - data = {} - for n, v, f in trvLst: - if n.endswith(':source'): - continue - data.setdefault(n.split(':'), dict()).setdefault(v, set()).add(f) - - jobs = [] - - while data: - job = [] - toRemove = [] - for n, vs in data.iteritems(): - v = sorted(vs)[0] - for f in vs.pop(v): - job.append((n, v, f)) - - if not vs: - toRemove.append(n) - - for n in toRemove: - data.pop(n) - - jobs.append(job) - - return jobs - def publish(self, trvLst, expected, targetLabel, checkPackageList=True, extraExpectedPromoteTroves=None, enforceAllExpected=True): """ @@ -1032,37 +999,16 @@ where version and flavor may be None. """ - # Don't try to promote groups and packages together. - grps = [ x for x in trvLst if x[0].startswith('group-') ] - if grps and len(grps) != len(trvLst): - raise CanNotPromoteGroupsAndPackagesTogetherError(trvs=trvLst) - - if grps: - jobs = [ trvLst, ] - else: - # When promoting packages, we know what is being promoted, disable - # the sanity. - jobs = self._orderPromoteJobList(trvLst) - expected = set() - checkPackageList = False - - res = [] - for job in jobs: - res.append(self._conaryhelper.promote( - jobs, - expected, - self._cfg.sourceLabel, - targetLabel, - checkPackageList=checkPackageList, - extraPromoteTroves=self._cfg.extraPromoteTroves, - extraExpectedPromoteTroves=extraExpectedPromoteTroves, - enforceAllExpected=enforceAllExpected, - )) - - if grps: - return res[0] - - return res + return self._conaryhelper.promote( + trvLst, + expected, + self._cfg.sourceLabel, + targetLabel, + checkPackageList=checkPackageList, + extraPromoteTroves=self._cfg.extraPromoteTroves, + extraExpectedPromoteTroves=extraExpectedPromoteTroves, + enforceAllExpected=enforceAllExpected, + ) def mirror(self, fullTroveSync=False): """