diff --git a/ReviewBot.py b/ReviewBot.py index 9d254222..b373d7e2 100644 --- a/ReviewBot.py +++ b/ReviewBot.py @@ -361,17 +361,6 @@ class ReviewBot(object): return (None, None) - def get_devel_project(self, project, package): - try: - m = osc.core.show_package_meta(self.apiurl, project, package) - node = ET.fromstring(''.join(m)).find('devel') - if node is not None: - return node.get('project'), node.get('package', None) - except urllib2.HTTPError as e: - if e.code != 404: - raise e - return None, None - def can_accept_review(self, request_id): """return True if there is a new review for the specified reviewer""" states = set() diff --git a/check_source.py b/check_source.py index fbd69702..da47859a 100755 --- a/check_source.py +++ b/check_source.py @@ -12,6 +12,7 @@ except ImportError: import osc.conf import osc.core +from osclib.core import devel_project_get import urllib2 import ReviewBot from check_maintenance_incidents import MaintenanceChecker @@ -46,7 +47,7 @@ class CheckSource(ReviewBot.ReviewBot): if not self.ignore_devel: self.logger.info('checking if target package exists and has devel project') - devel_project, devel_package = self.get_devel_project(target_project, target_package) + devel_project, devel_package = devel_project_get(self.apiurl, target_project, target_package) if devel_project: if (source_project != devel_project or source_package != devel_package) and \ not(source_project == target_project and source_package == target_package): @@ -212,7 +213,8 @@ class CheckSource(ReviewBot.ReviewBot): message = 'Roles to packages are granted in the devel project, not in %s.' % action.tgt_project if action.tgt_package is not None: - message += ' Please send this request to %s/%s.' % self.get_devel_project(action.tgt_project, action.tgt_package) + project, package = devel_project_get(self.apiurl, action.tgt_project, action.tgt_package) + message += ' Send this request to {}/{}.'.format(project, package) self.review_messages['declined'] = message return False diff --git a/fcc_submitter.py b/fcc_submitter.py index e7d175d8..787a8ee9 100755 --- a/fcc_submitter.py +++ b/fcc_submitter.py @@ -30,6 +30,7 @@ from xml.etree import cElementTree as ET import osc.conf import osc.core +from osclib.core import devel_project_get from osc import oscerr from osclib.memoize import memoize @@ -223,14 +224,6 @@ class FccSubmitter(object): return True return False - def get_devel_project(self, package): - m = osc.core.show_package_meta(self.apiurl, self.factory, package) - node = ET.fromstring(''.join(m)).find('devel') - if node is None: - return None, None - else: - return node.get('project'), node.get('package', None) - def create_submitrequest(self, package): """Create a submit request using the osc.commandline.Osc class.""" src_project = self.factory # submit from Factory only @@ -376,7 +369,7 @@ class FccSubmitter(object): else: logging.info("%d - Preparing submit %s to %s"%(i, package, self.to_prj)) # get devel project - devel_prj, devel_pkg = self.get_devel_project(package) + devel_prj, devel_pkg = devel_project_get(self.apiurl, self.factory, package) # check devel project does not in the skip list if devel_prj in self.skip_devel_project_list: # check the except packages list diff --git a/leaper.py b/leaper.py index bb04bb5b..51718e8a 100755 --- a/leaper.py +++ b/leaper.py @@ -35,6 +35,7 @@ except ImportError: import osc.conf import osc.core +from osclib.core import devel_project_get import urllib2 import yaml import ReviewBot @@ -181,7 +182,7 @@ class Leaper(ReviewBot.ReviewBot): else: self.logger.info('different sources in {}'.format(self.rdiff_link(src_project, src_package, src_rev, prj, package))) - devel_project, devel_package = self.get_devel_project('openSUSE.org:openSUSE:Factory', package) + devel_project, devel_package = devel_project_get(self.apiurl, 'openSUSE.org:openSUSE:Factory', package) if devel_project is not None: # specifying devel package is optional if devel_package is None: diff --git a/osclib/core.py b/osclib/core.py index 75711299..813c705a 100644 --- a/osclib/core.py +++ b/osclib/core.py @@ -3,12 +3,14 @@ from datetime import datetime import dateutil.parser import re from xml.etree import cElementTree as ET +from urllib2 import HTTPError from osc.core import get_binarylist from osc.core import get_dependson from osc.core import http_GET from osc.core import makeurl from osc.core import owner +from osc.core import show_package_meta from osc.core import show_project_meta from osclib.memoize import memoize @@ -134,3 +136,31 @@ def package_binary_list(apiurl, project, repository, arch, package=None): binary_map[result.group('filename')] = package return package_binaries, binary_map + +@memoize(session=True) +def devel_project_get(apiurl, target_project, target_package): + try: + meta = ET.fromstring(''.join(show_package_meta(apiurl, target_project, target_package))) + node = meta.find('devel') + if node is not None: + return node.get('project'), node.get('package') + except HTTPError as e: + if e.code != 404: + raise e + + return None, None + +@memoize(session=True) +def devel_project_fallback(apiurl, target_project, target_package): + project, package = devel_project_get(apiurl, target_project, target_package) + if project is None and target_project != 'openSUSE:Factory': + if target_project.startswith('openSUSE:'): + project, package = devel_project_get(apiurl, 'openSUSE:Factory', target_package) + elif target_project.startswith('SUSE:'): + # For SLE (assume IBS), fallback to openSUSE:Factory devel projects. + project, package = devel_project_get(apiurl, 'openSUSE.org:openSUSE:Factory', target_package) + if project: + # Strip openSUSE.org: prefix since string since not used for lookup. + project = project.split(':', 1)[1] + + return project, package diff --git a/osclib/request_splitter.py b/osclib/request_splitter.py index b08d05ff..eea63cd4 100644 --- a/osclib/request_splitter.py +++ b/osclib/request_splitter.py @@ -4,6 +4,7 @@ import hashlib from lxml import etree as ET from osc import conf from osc.core import show_project_meta +from osclib.core import devel_project_fallback import re class RequestSplitter(object): @@ -113,7 +114,7 @@ class RequestSplitter(object): target = request.find('./action/target') target_project = target.get('project') target_package = target.get('package') - devel = self.devel_project_get(target_project, target_package) + devel, _ = devel_project_fallback(self.api.apiurl, target_project, target_package) if not devel and request_type == 'submit': devel = request.find('./action/source').get('project') if devel: @@ -146,18 +147,6 @@ class RequestSplitter(object): return self.api.project return None - def devel_project_get(self, target_project, target_package): - devel = self.api.get_devel_project(target_project, target_package) - if devel is None and self.api.project.startswith('openSUSE:'): - devel = self.api.get_devel_project('openSUSE:Factory', target_package) - if devel is None and self.api.project.startswith('SUSE:'): - # For SLE, fallback to openSUSE:Factory devel projects. - devel = self.api.get_devel_project('openSUSE.org:openSUSE:Factory', target_package) - if devel: - # Strip openSUSE.org: prefix since string since not used for lookup. - devel = devel.split(':', 1)[1] - return devel - def filter_check(self, request): for xpath in self.filters: if not xpath(request): diff --git a/osclib/stagingapi.py b/osclib/stagingapi.py index eac803b7..8eab905e 100644 --- a/osclib/stagingapi.py +++ b/osclib/stagingapi.py @@ -48,6 +48,7 @@ from osc.core import show_project_sourceinfo from osc.core import streamfile from osclib.cache import Cache +from osclib.core import devel_project_get from osclib.comments import CommentAPI from osclib.ignore_command import IgnoreCommand from osclib.memoize import memoize @@ -400,7 +401,7 @@ class StagingAPI(object): return None packages = root.findall('./frozenlink/package') # the first package's devel project is good enough - return self.get_devel_project(self.project, packages[0].get('name')) + return devel_project_get(self.apiurl, self.project, packages[0].get('name'))[0] def do_change_review_state(self, request_id, newstate, message=None, by_group=None, by_user=None, by_project=None): @@ -1794,17 +1795,6 @@ class StagingAPI(object): else: return False - def get_devel_project(self, project, package): - try: - m = show_package_meta(self.apiurl, project, package) - node = ET.fromstring(''.join(m)).find('devel') - if node is not None: - return node.get('project') - except urllib2.HTTPError as e: - if e.code == 404: - pass - return None - def staging_deactivate(self, project): """Cleanup staging after last request is removed and disable building.""" # Clear pseudometa since it no longer represents the staging. diff --git a/repo_checker.py b/repo_checker.py index 92710d92..f232f957 100755 --- a/repo_checker.py +++ b/repo_checker.py @@ -15,6 +15,7 @@ import tempfile from osclib.comments import CommentAPI from osclib.core import binary_list from osclib.core import depends_on +from osclib.core import devel_project_get from osclib.core import package_binary_list from osclib.core import request_staged from osclib.core import target_archs @@ -98,7 +99,7 @@ class RepoChecker(ReviewBot.ReviewBot): reference = hashlib.sha1(info).hexdigest()[:7] # Post comment on devel package in order to notifiy maintainers. - devel_project, devel_package = self.get_devel_project(project, package) + devel_project, devel_package = devel_project_get(self.apiurl, project, package) self.comment_write(state='seen', result=reference, project=devel_project, package=devel_package, message=message) diff --git a/update_crawler.py b/update_crawler.py index 928dc4e7..59260a96 100755 --- a/update_crawler.py +++ b/update_crawler.py @@ -38,6 +38,7 @@ from urllib import quote_plus from osclib.memoize import memoize from osclib.conf import Config +from osclib.core import devel_project_get from osclib.stagingapi import StagingAPI OPENSUSE = 'openSUSE:Leap:42.3' @@ -283,7 +284,7 @@ class UpdateCrawler(object): targetinfo = targets[package] # XXX: make more generic :-) - devel_prj = self.api.get_devel_project(FACTORY, package) + devel_prj = devel_project_get(self.apiurl, FACTORY, package) if devel_prj == 'devel:languages:haskell': logging.info('skipping haskell package %s' % package) continue