diff --git a/osc-check_repo.py b/osc-check_repo.py index 36b5cb44..1393302e 100644 --- a/osc-check_repo.py +++ b/osc-check_repo.py @@ -109,7 +109,10 @@ def _check_repo_download(self, request): _errors_printed = set() -def _check_repo_group(self, id_, requests, debug=False): +def _check_repo_group(self, id_, requests, skip_cycle=None, debug=False): + if skip_cycle is None: + skip_cycle = [] + print '> Check group [%s]' % ', '.join(r.str_compact() for r in requests) # XXX TODO - If the requests comes from command line, the group is @@ -198,6 +201,14 @@ def _check_repo_group(self, id_, requests, debug=False): print print ' - New cycle detected:', sorted(cycle) print ' - New edges:', new_edges + + if skip_cycle: + print ' - Skiping this cycle and moving to the next check.' + continue + else: + print ' - If you want to skip this cycle, run manually the ' \ + 'check repo with -c / --skipcycle option.' + for request in requests: request.updated = True @@ -428,6 +439,7 @@ def _print_request_and_specs(self, request_and_specs): @cmdln.option('-p', '--project', dest='project', metavar='PROJECT', default='Factory', help='select a different project instead of openSUSE:Factory') @cmdln.option('-s', '--skip', action='store_true', help='skip review') +@cmdln.option('-c', '--skipcycle', action='store_true', help='skip cycle check') @cmdln.option('-n', '--dry', action='store_true', help='dry run, don\'t change review state') @cmdln.option('-v', '--verbose', action='store_true', help='verbose output') def do_check_repo(self, subcmd, opts, *args): @@ -542,7 +554,9 @@ def do_check_repo(self, subcmd, opts, *args): # projects also for id_, reqs in sorted(groups.items(), reverse=True): try: - self._check_repo_group(id_, reqs, debug=opts.verbose) + self._check_repo_group(id_, reqs, + skip_cycle=opts.skipcycle, + debug=opts.verbose) except Exception as e: print 'ERROR -- An exception happends while checking a group [%s]' % e if conf.config['debug']: diff --git a/osc-staging.py b/osc-staging.py index e154112c..086dce8e 100644 --- a/osc-staging.py +++ b/osc-staging.py @@ -57,7 +57,7 @@ def _full_project_name(self, project): return 'SUSE:%s' % project # If we can't guess, raise a Warning - warnings.warn('% project not recognized.' % project) + warnings.warn('%s project not recognized.' % project) return project diff --git a/osclib/accept_command.py b/osclib/accept_command.py index bfb7a059..b39c636d 100644 --- a/osclib/accept_command.py +++ b/osclib/accept_command.py @@ -1,4 +1,5 @@ import re +import urllib2 import warnings from xml.etree import cElementTree as ET @@ -33,7 +34,7 @@ class AcceptCommand(object): return rqs def perform(self, project): - """Accept the staging LETTER for review and submit to Factory / + """Accept the staging project for review and submit to Factory / openSUSE 13.2 ... Then disable the build to disabled @@ -57,15 +58,23 @@ class AcceptCommand(object): msg = 'Accepting staging review for {}'.format(req['package']) print(msg) - oldspecs = self.api.get_filelist_for_package(pkgname=req['package'], project=self.api.project, extension='spec') - change_request_state(self.api.apiurl, str(req['id']), 'accepted', message='Accept to %s' % self.api.project) + oldspecs = self.api.get_filelist_for_package(pkgname=req['package'], + project=self.api.project, + extension='spec') + change_request_state(self.api.apiurl, + str(req['id']), + 'accepted', + message='Accept to %s' % self.api.project) self.create_new_links(self.api.project, req['package'], oldspecs) # A single comment should be enough to notify everybody, since # they are already mentioned in the comments created by # select/unselect pkg_list = ", ".join(packages) - cmmt = 'Project "{}" accepted. The following packages have been submitted to {}: {}.'.format(project, self.api.project, pkg_list) + cmmt = 'Project "{}" accepted.' \ + ' The following packages have been submitted to {}: {}.'.format(project, + self.api.project, + pkg_list) self.comment.add_comment(project_name=project, comment=cmmt) # XXX CAUTION - AFAIK the 'accept' command is expected to clean the messages here. @@ -113,7 +122,7 @@ class AcceptCommand(object): # There is more than one .spec file in the package; link package containers as needed origmeta = self.api.load_file_content(project, pkgname, '_meta') for specfile in filelist: - package = specfile[:-5] # stripping .spec off the filename gives the packagename + package = specfile[:-5] # stripping .spec off the filename gives the packagename if package == pkgname: # This is the original package and does not need to be linked to itself continue @@ -121,10 +130,18 @@ class AcceptCommand(object): if not self.api.item_exists(project, package): print "Creating new package %s linked to %s" % (package, pkgname) # new package does not exist. Let's link it with new metadata - newmeta = re.sub(r'(\$',r''.format(pkgname), newmeta) - newmeta = re.sub(r'.*',r'', newmeta) - newmeta = re.sub(r'',r'{}'.format(pkgname), newmeta) + newmeta = re.sub(r'(\$', + r''.format(pkgname), + newmeta) + newmeta = re.sub(r'.*', + r'', + newmeta) + newmeta = re.sub(r'', + r'{}'.format(pkgname), + newmeta) self.api.save_file_content(project, package, '_meta', newmeta) link = "".format(pkgname) self.api.save_file_content(project, package, '_link', link) diff --git a/osclib/conf.py b/osclib/conf.py index cdff1b68..d7021391 100644 --- a/osclib/conf.py +++ b/osclib/conf.py @@ -51,7 +51,7 @@ DEFAULT = { 'openqa': None, 'lock': None, 'lock-ns': 'OBS', - } + }, } # diff --git a/osclib/cycle.py b/osclib/cycle.py index 99fea33b..deff4c6a 100644 --- a/osclib/cycle.py +++ b/osclib/cycle.py @@ -293,7 +293,7 @@ class CycleDetector(object): # # To do that, we store in `project_cycles_pkgs` all the # project (i.e Factory) cycles as a set of packages, so we can - # check in the new cycle (also as a set of package) is + # check if the new cycle (also as a set of packages) is # included here. project_cycles_pkgs = [set(cycle) for cycle in project_cycles] for cycle in current_graph.cycles(): diff --git a/osclib/obslock.py b/osclib/obslock.py index c5839149..ad6d623b 100644 --- a/osclib/obslock.py +++ b/osclib/obslock.py @@ -84,7 +84,7 @@ class OBSLock(object): now = datetime.utcnow() if now < ts: raise Exception('Lock acquired from the future [%s] by [%s]. Try later.' % (ts, user)) - if user != self.user and (now - ts).seconds < self.ttl: + if (now - ts).seconds < self.ttl: print 'Lock acquired by [%s]. Try later.' % user exit(-1) # raise Exception('Lock acquired by [%s]. Try later.' % user) diff --git a/osclib/stagingapi.py b/osclib/stagingapi.py index 0a1bbb18..1a7e13db 100644 --- a/osclib/stagingapi.py +++ b/osclib/stagingapi.py @@ -58,6 +58,7 @@ class StagingAPI(object): self.copenqa = conf.config[project]['openqa'] # If the project support rings, inititialize some variables. + self.ring_packages = {} if self.crings: self.rings = ( '{}:0-Bootstrap'.format(self.crings), diff --git a/tests/fixtures/source/openSUSE:Factory/apparmor-doc/_meta b/tests/fixtures/source/openSUSE:Factory/apparmor-doc/_meta new file mode 100644 index 00000000..c916413a --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory/apparmor-doc/_meta @@ -0,0 +1,11 @@ + + AppArmor userlevel parser utility + + The AppArmor Parser is a userlevel program that is used to load in + program profiles to the AppArmor Security kernel module. + + This package is part of a suite of tools that used to be named + SubDomain. + + + diff --git a/tests/fixtures/source/openSUSE:Factory/apparmor/_entry.xml b/tests/fixtures/source/openSUSE:Factory/apparmor/_entry.xml new file mode 100644 index 00000000..29b3c9f9 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory/apparmor/_entry.xml @@ -0,0 +1 @@ + diff --git a/tests/fixtures/source/openSUSE:Factory/apparmor/_meta b/tests/fixtures/source/openSUSE:Factory/apparmor/_meta new file mode 100644 index 00000000..63a3cc33 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory/apparmor/_meta @@ -0,0 +1,11 @@ + + AppArmor userlevel parser utility + + The AppArmor Parser is a userlevel program that is used to load in + program profiles to the AppArmor Security kernel module. + + This package is part of a suite of tools that used to be named + SubDomain. + + + diff --git a/tests/fixtures/source/openSUSE:Factory/apparmor/apparmor.xml b/tests/fixtures/source/openSUSE:Factory/apparmor/apparmor.xml new file mode 100644 index 00000000..a8c90ae6 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory/apparmor/apparmor.xml @@ -0,0 +1,3 @@ + + ${entries} + diff --git a/tests/fixtures/source/openSUSE:Factory/emacs b/tests/fixtures/source/openSUSE:Factory/emacs new file mode 100644 index 00000000..32bba972 --- /dev/null +++ b/tests/fixtures/source/openSUSE:Factory/emacs @@ -0,0 +1,3 @@ + + + diff --git a/tests/obs.py b/tests/obs.py index ad1b9b2c..12be1100 100644 --- a/tests/obs.py +++ b/tests/obs.py @@ -367,10 +367,20 @@ class OBS(object): 'openSUSE:Factory:Staging:J': [], } - # To track comments created during test execution, even if they have - # been deleted afterward + # To track comments created during test execution, even if + # they have been deleted afterward self.comment_bodies = [] + # Different spec files stored in some openSUSE:Factory + # projects + self.spec_list = { + 'openSUSE:Factory/apparmor': [ + { + 'spec': 'apparmor.spec', + } + ], + } + # # /request/ # @@ -560,6 +570,30 @@ class OBS(object): return response + @GET(re.compile(r'/source/openSUSE:Factory/apparmor$')) + def source_project_apparmor(self, request, uri, headers): + """Return apparmor spec list.""" + package = re.search(r'/source/([\w:]+/\w+)', uri).group(1) + response = (404, headers, 'Not found') + try: + template = string.Template(self._fixture(uri, filename='apparmor.xml')) + entry_template = string.Template(self._fixture(uri, filename='_entry.xml')) + entries = ''.join(entry_template.substitute(entry) for entry in self.spec_list[package]) + response = (200, headers, template.substitute({'entries': entries})) + + # The next call len() will be 2 + if len(self.spec_list[package]) == 1: + self.spec_list[package].append({'spec': 'apparmor-doc.spec'}) + + except Exception as e: + if DEBUG: + print uri, e + + if DEBUG: + print 'SOURCE APPARMOR', uri, response + + return response + @GET(re.compile(r'/source/home:Admin/\w+')) def source_project(self, request, uri, headers): """Return information of a source package."""