Hello community,

here is the log from the commit of package openSUSE-release-tools for 
openSUSE:Factory checked in at 2018-08-20 16:19:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openSUSE-release-tools (Old)
 and      /work/SRC/openSUSE:Factory/.openSUSE-release-tools.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openSUSE-release-tools"

Mon Aug 20 16:19:48 2018 rev:121 rq:630331 version:20180817.c11f78e

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/openSUSE-release-tools/openSUSE-release-tools.changes
    2018-08-18 00:03:47.331019087 +0200
+++ 
/work/SRC/openSUSE:Factory/.openSUSE-release-tools.new/openSUSE-release-tools.changes
       2018-08-20 16:19:53.144861856 +0200
@@ -1,0 +2,69 @@
+Fri Aug 17 16:25:00 UTC 2018 - [email protected]
+
+- Update to version 20180817.c11f78e:
+  * osclib/conf: remove staging default for generic projects.
+
+-------------------------------------------------------------------
+Fri Aug 17 15:58:11 UTC 2018 - [email protected]
+
+- Update to version 20180817.f0fadd6:
+  * osclib/conf: provide Leap:N:Update default settings.
+  * osclib/conf: exclude sub-projects from matching project patterns.
+
+-------------------------------------------------------------------
+Fri Aug 17 15:44:21 UTC 2018 - [email protected]
+
+- Update to version 20180817.8092671:
+  * ReviewBot: drop self.staging_config post switch to Config.get().
+  * repo_checker: use osclib.conf.str2bool() instead of bool().
+  * ReviewBots: utilize Config.get() instead of self.staging_config.
+  * osclib/conf: provide cached get() method to supersede ReviewBot cache.
+  * check_source: drop staging_group() for target_project_config().
+
+-------------------------------------------------------------------
+Fri Aug 17 15:07:36 UTC 2018 - [email protected]
+
+- Update to version 20180817.55116d3:
+  * osclib/stagingapi: utilize osclib.core.attribute_value_*() implementations.
+  * tests/obs: improve format of default Config attribute.
+  * osclib/conf: decouple from StagingAPI and always fetch remote config.
+  * osclib/conf: utilize osclib.core.attribute_value_load() instead of 
StagingAPI.
+  * osclib/conf: drop dashboard/config migration to attribute.
+  * osclib/core: provide attribute_value_(load|save) adapted from StagingAPI.
+
+-------------------------------------------------------------------
+Fri Aug 17 14:59:25 UTC 2018 - [email protected]
+
+- Update to version 20180817.93038db:
+  * osc-staging: add documentation for setprio command.
+  * osclib/prio: support non-important priority.
+
+-------------------------------------------------------------------
+Thu Aug 16 22:34:28 UTC 2018 - [email protected]
+
+- Update to version 20180816.fb3d580:
+  * osclib/core: maintainers_get(): rework to properly supports groups.
+  * osclib/core: provide groups_members() to expand muliple groups users.
+  * Utilize ET.fromstringlist() intead of joining strings.
+
+-------------------------------------------------------------------
+Thu Aug 16 22:24:31 UTC 2018 - [email protected]
+
+- Update to version 20180816.7b0f756:
+  * repo_checker: CreatePackageDescr: remove more unnecessary special cases.
+
+-------------------------------------------------------------------
+Wed Aug 15 22:34:26 UTC 2018 - [email protected]
+
+- Update to version 20180815.fa1f929:
+  * repo_checker: drop whitelist_clean sub-command.
+  * repo_checker: determine existing problems based on project_only output.
+
+-------------------------------------------------------------------
+Wed Aug 15 22:05:45 UTC 2018 - [email protected]
+
+- Update to version 20180815.eed6dde:
+  * repo_checker: support multi-layer projects during project_only run.
+  * repo_checker: properly support multi-layer projects during request mode.
+
+-------------------------------------------------------------------

Old:
----
  openSUSE-release-tools-20180815.cec5fa6.obscpio

New:
----
  openSUSE-release-tools-20180817.c11f78e.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ openSUSE-release-tools.spec ++++++
--- /var/tmp/diff_new_pack.Y0Whke/_old  2018-08-20 16:19:54.300863489 +0200
+++ /var/tmp/diff_new_pack.Y0Whke/_new  2018-08-20 16:19:54.304863494 +0200
@@ -20,7 +20,7 @@
 %define source_dir openSUSE-release-tools
 %define announcer_filename factory-package-news
 Name:           openSUSE-release-tools
-Version:        20180815.cec5fa6
+Version:        20180817.c11f78e
 Release:        0
 Summary:        Tools to aid in staging and release work for openSUSE/SUSE
 License:        GPL-2.0-or-later AND MIT

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.Y0Whke/_old  2018-08-20 16:19:54.356863567 +0200
+++ /var/tmp/diff_new_pack.Y0Whke/_new  2018-08-20 16:19:54.356863567 +0200
@@ -1,6 +1,6 @@
 <servicedata>
   <service name="tar_scm">
     <param 
name="url">https://github.com/openSUSE/openSUSE-release-tools.git</param>
-    <param 
name="changesrevision">07bc6c031a0783b17e5cfefd3e0c0db323ee6c3b</param>
+    <param 
name="changesrevision">c11f78eb83656c583cdba86c0c7537e8a46919f8</param>
   </service>
 </servicedata>

++++++ openSUSE-release-tools-20180815.cec5fa6.obscpio -> 
openSUSE-release-tools-20180817.c11f78e.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/CreatePackageDescr.pm 
new/openSUSE-release-tools-20180817.c11f78e/CreatePackageDescr.pm
--- old/openSUSE-release-tools-20180815.cec5fa6/CreatePackageDescr.pm   
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/CreatePackageDescr.pm   
2018-08-17 18:20:13.000000000 +0200
@@ -121,11 +121,8 @@
     $out .= "-Con:\n";
     $out .= "+Req:\n";
     foreach my $prv ( @{ $qq{1049} || [] } ) {
-        next if ( $prv =~ m/^rpmlib/ );
-        next
-          if ( $name eq "libqmmp0-plugin-mplayer"
-            && $prv eq "/usr/bin/mplayer" );
-        next if ( $prv eq "this-is-only-for-build-envs" );
+        # Completely disgusting, but maintainers have no interest in fixing,
+        # see #1153 for more details.
         next
           if ( $name =~ "^installation-images-debuginfodeps.*"
             && $prv =~ m/debuginfo.build/ );
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openSUSE-release-tools-20180815.cec5fa6/ReviewBot.py 
new/openSUSE-release-tools-20180817.c11f78e/ReviewBot.py
--- old/openSUSE-release-tools-20180815.cec5fa6/ReviewBot.py    2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/ReviewBot.py    2018-08-17 
18:20:13.000000000 +0200
@@ -141,12 +141,9 @@
 
     def staging_api(self, project):
         if project not in self.staging_apis:
-            config = Config(project)
+            Config(self.apiurl, project)
             self.staging_apis[project] = StagingAPI(self.apiurl, project)
 
-            config.apply_remote(self.staging_apis[project])
-            self.staging_config[project] = conf.config[project].copy()
-
         return self.staging_apis[project]
 
     @property
@@ -174,7 +171,6 @@
 
     def check_requests(self):
         self.staging_apis = {}
-        self.staging_config = {}
 
         # give implementations a chance to do something before single requests
         self.prepare_review()
@@ -203,8 +199,7 @@
     @memoize(session=True)
     def request_override_check_users(self, project):
         """Determine users allowed to override review in a comment command."""
-        self.staging_api(project)
-        config = self.staging_config[project]
+        config = Config.get(self.apiurl, project)
 
         users = []
         group = config.get('staging-group')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/check_source.py 
new/openSUSE-release-tools-20180817.c11f78e/check_source.py
--- old/openSUSE-release-tools-20180815.cec5fa6/check_source.py 2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/check_source.py 2018-08-17 
18:20:13.000000000 +0200
@@ -13,6 +13,7 @@
 
 import osc.conf
 import osc.core
+from osclib.conf import Config
 from osclib.core import devel_project_get
 from osclib.core import devel_project_fallback
 import urllib2
@@ -36,14 +37,14 @@
 
     def target_project_config(self, project):
         # Load project config and allow for remote entries.
-        self.staging_api(project)
-        config = self.staging_config[project]
+        config = Config.get(self.apiurl, project)
 
         self.single_action_require = 
str2bool(config.get('check-source-single-action-require', 'False'))
         self.ignore_devel = not str2bool(config.get('devel-project-enforce', 
'False'))
         self.in_air_rename_allow = 
str2bool(config.get('check-source-in-air-rename-allow', 'False'))
         self.add_review_team = 
str2bool(config.get('check-source-add-review-team', 'True'))
         self.review_team = config.get('review-team')
+        self.staging_group = config.get('staging-group')
         self.repo_checker = config.get('repo-checker')
         self.devel_whitelist = config.get('devel-whitelist', '').split()
 
@@ -175,25 +176,15 @@
 
             if self.only_changes():
                 self.logger.debug('only .changes modifications')
-                staging_group = self.staging_group(target_project)
-                if staging_group and not self.dryrun:
+                if self.staging_group and not self.dryrun:
                     osc.core.change_review_state(self.apiurl, 
str(self.request.reqid), 'accepted',
-                        by_group=staging_group,
+                        by_group=self.staging_group,
                         message='skipping the staging process since only 
.changes modifications')
             elif self.repo_checker is not None:
                 self.add_review(self.request, by_user=self.repo_checker, 
msg='Please review build success')
 
         return True
 
-    def staging_group(self, project):
-        try:
-            return self.staging_api(project).cstaging_group
-        except urllib2.HTTPError as e:
-            if e.code != 404:
-                raise e
-
-        return None
-
     def is_devel_project(self, source_project, target_project):
         if source_project in self.devel_whitelist:
             return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/devel-project.py 
new/openSUSE-release-tools-20180817.c11f78e/devel-project.py
--- old/openSUSE-release-tools-20180815.cec5fa6/devel-project.py        
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/devel-project.py        
2018-08-17 18:20:13.000000000 +0200
@@ -40,8 +40,9 @@
 osc.core.search = search
 
 def staging_api(args):
-    Config(args.project)
-    return StagingAPI(osc.conf.config['apiurl'], args.project)
+    apiurl = osc.conf.config['apiurl']
+    Config(apiurl, args.project)
+    return StagingAPI(apiurl, args.project)
 
 def devel_projects_get(apiurl, project):
     """
@@ -92,7 +93,7 @@
     apiurl = osc.conf.config['apiurl']
     devel_projects = devel_projects_load(args)
     for devel_project in devel_projects:
-        meta = ET.fromstring(''.join(show_project_meta(apiurl, devel_project)))
+        meta = ET.fromstringlist(show_project_meta(apiurl, devel_project))
         groups = meta.xpath('group[@role="maintainer"]/@groupid')
         intersection = set(groups).intersection(desired)
         if len(intersection) != len(desired):
@@ -116,7 +117,7 @@
                 maintainer_map.setdefault(userid, set())
                 maintainer_map[userid].add(devel_package_identifier)
 
-    Config(args.project) # Ensure mail-* options are loaded for mail_send().
+    Config(apiurl, args.project) # Ensure mail-* options are loaded for 
mail_send().
     subject = 'Packages you maintain are present in {}'.format(args.project)
     for userid, package_identifiers in maintainer_map.items():
         email = entity_email(apiurl, userid)
@@ -207,7 +208,7 @@
                 meta = show_project_meta(apiurl, project)
     else:
         meta = show_project_meta(apiurl, project)
-    meta = ET.fromstring(''.join(meta))
+    meta = ET.fromstringlist(meta)
 
     userids = []
     for person in meta.findall('person[@role="maintainer"]'):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/fcc_submitter.py 
new/openSUSE-release-tools-20180817.c11f78e/fcc_submitter.py
--- old/openSUSE-release-tools-20180815.cec5fa6/fcc_submitter.py        
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/fcc_submitter.py        
2018-08-17 18:20:13.000000000 +0200
@@ -187,7 +187,7 @@
         """
 
         f = osc.core.show_prj_results_meta(self.apiurl, project)
-        root = ET.fromstring(''.join(f))
+        root = ET.fromstringlist(f)
         #print ET.dump(root)
 
         failed_multibuild_pacs = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openSUSE-release-tools-20180815.cec5fa6/leaper.py 
new/openSUSE-release-tools-20180817.c11f78e/leaper.py
--- old/openSUSE-release-tools-20180815.cec5fa6/leaper.py       2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/leaper.py       2018-08-17 
18:20:13.000000000 +0200
@@ -33,8 +33,8 @@
 except ImportError:
     import cElementTree as ET
 
-import osc.conf
 import osc.core
+from osclib.conf import Config
 from osclib.core import devel_project_get
 import urllib2
 import yaml
@@ -468,8 +468,7 @@
         return False
 
     def check_one_request(self, req):
-        api = self.staging_api(req.actions[0].tgt_project)
-        config = self.staging_config[api.project]
+        config = Config.get(self.apiurl, req.actions[0].tgt_project)
         self.needs_legal_review = False
         self.needs_reviewteam = False
         self.needs_release_manager = False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/manager_42.py 
new/openSUSE-release-tools-20180817.c11f78e/manager_42.py
--- old/openSUSE-release-tools-20180815.cec5fa6/manager_42.py   2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/manager_42.py   2018-08-17 
18:20:13.000000000 +0200
@@ -197,8 +197,8 @@
         if (self.sle_workarounds and not self.sle_workarounds_sourced and
             package in self.packages[self.sle_workarounds]):
             # Determine how recently the package was updated.
-            root = ET.fromstring(''.join(
-                get_commitlog(self.apiurl, self.sle_workarounds, package, 
None, format='xml')))
+            root = ET.fromstringlist(
+                get_commitlog(self.apiurl, self.sle_workarounds, package, 
None, format='xml'))
             updated_last = date_parse(root.find('logentry/date').text)
             age = datetime.now() - updated_last
             if age.total_seconds() < 3600 * 24:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openSUSE-release-tools-20180815.cec5fa6/metrics.py 
new/openSUSE-release-tools-20180817.c11f78e/metrics.py
--- old/openSUSE-release-tools-20180815.cec5fa6/metrics.py      2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/metrics.py      2018-08-17 
18:20:13.000000000 +0200
@@ -355,8 +355,8 @@
         revision_index.index = {}
 
         try:
-            root = ET.fromstring(''.join(
-                get_commitlog(api.apiurl, api.cstaging, 'dashboard', None, 
format='xml')))
+            root = ET.fromstringlist(
+                get_commitlog(api.apiurl, api.cstaging, 'dashboard', None, 
format='xml'))
         except HTTPError as e:
             return revision_index.index
 
@@ -549,9 +549,9 @@
     Cache.PATTERNS['/source/[^/]+/dashboard/[^/]+\?rev=.*'] = sys.maxint
     Cache.init()
 
-    config = Config(args.project)
-    api = StagingAPI(osc.conf.config['apiurl'], args.project)
-    config.apply_remote(api)
+    apiurl = osc.conf.config['apiurl']
+    Config(apiurl, args.project)
+    api = StagingAPI(apiurl, args.project)
 
     print('dashboard: wrote {:,} points'.format(ingest_dashboard(api)))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/openqa-comments.py 
new/openSUSE-release-tools-20180817.c11f78e/openqa-comments.py
--- old/openSUSE-release-tools-20180815.cec5fa6/openqa-comments.py      
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/openqa-comments.py      
2018-08-17 18:20:13.000000000 +0200
@@ -211,9 +211,9 @@
     if args.force:
         MARGIN_HOURS = 0
 
-    config = Config(args.project)
-    api = StagingAPI(osc.conf.config['apiurl'], args.project)
-    config.apply_remote(api)
+    apiurl = osc.conf.config['apiurl']
+    Config(apiurl, args.project)
+    api = StagingAPI(apiurl, args.project)
     openQA = OpenQAReport(api)
 
     if args.staging:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osc-staging.py 
new/openSUSE-release-tools-20180817.c11f78e/osc-staging.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osc-staging.py  2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osc-staging.py  2018-08-17 
18:20:13.000000000 +0200
@@ -321,6 +321,11 @@
         If the force option is included the rebuild checks will be ignored and
         all packages failing to build will be triggered.
 
+    "setprio" will set priority of requests withing stagings
+        If no stagings are specified all stagings will be used.
+        The default priority is important, but the possible values are:
+          "critical", "important", "moderate" or "low".
+
     "supersede" will supersede requests were applicable.
         A request list can be used to limit what is superseded.
 
@@ -349,7 +354,7 @@
         osc staging unlock
         osc staging rebuild [--force] [STAGING...]
         osc staging repair [--cleanup] [REQUEST...]
-        osc staging setprio [STAGING...]
+        osc staging setprio [STAGING...] [priority]
         osc staging supersede [REQUEST...]
     """
     if opts.version:
@@ -407,7 +412,7 @@
     opts.project = self._full_project_name(opts.project)
     opts.apiurl = self.get_api_url()
     opts.verbose = False
-    config = Config(opts.project)
+    Config(opts.apiurl, opts.project)
 
     colorama.init(autoreset=True,
         strip=(opts.no_color or not bool(int(conf.config.get('staging.color', 
True)))))
@@ -423,8 +428,6 @@
         Cache.delete_all()
 
     api = StagingAPI(opts.apiurl, opts.project)
-    config.apply_remote(api)
-
     needed = lock_needed(cmd, opts)
     with OBSLock(opts.apiurl, opts.project, reason=cmd, needed=needed) as lock:
 
@@ -669,7 +672,17 @@
         elif cmd == 'repair':
             RepairCommand(api).perform(args[1:], opts.cleanup)
         elif cmd == 'setprio':
-            PrioCommand(api).perform(args[1:])
+            stagings = []
+            priority = None
+
+            priorities = ['critical', 'important', 'moderate', 'low']
+            for arg in args[1:]:
+                if arg in priorities:
+                    priority = arg
+                else:
+                    stagings.append(arg)
+
+            PrioCommand(api).perform(stagings, priority)
         elif cmd == 'supersede':
             SupersedeCommand(api).perform(args[1:])
         elif cmd == 'unlock':
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osclib/conf.py 
new/openSUSE-release-tools-20180817.c11f78e/osclib/conf.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osclib/conf.py  2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osclib/conf.py  2018-08-17 
18:20:13.000000000 +0200
@@ -24,6 +24,8 @@
 import re
 
 from osc import conf
+from osclib.core import attribute_value_load
+from osclib.memoize import memoize
 
 
 # Sane defatuls for openSUSE and SUSE.  The string interpolation rule
@@ -34,7 +36,7 @@
 #   the project.
 
 DEFAULT = {
-    r'openSUSE:(?P<project>Factory)': {
+    r'openSUSE:(?P<project>Factory(?::Ports)?)$': {
         'staging': 'openSUSE:%(project)s:Staging',
         'staging-group': 'factory-staging',
         'staging-archs': 'i586 x86_64',
@@ -62,7 +64,7 @@
         'mail-noreply': '[email protected]',
         'mail-release-list': '[email protected]',
     },
-    r'openSUSE:(?P<project>Leap:(?P<version>[\d.]+))': {
+    r'openSUSE:(?P<project>Leap:(?P<version>[\d.]+)(?::Ports)?)$': {
         'staging': 'openSUSE:%(project)s:Staging',
         'staging-group': 'factory-staging',
         'staging-archs': 'i586 x86_64',
@@ -108,7 +110,12 @@
         'mail-noreply': '[email protected]',
         'mail-release-list': '[email protected]',
     },
-    r'openSUSE:(?P<project>Backports:(?P<version>[^:]+))': {
+    r'openSUSE:(?P<project>Leap:(?P<version>[\d.]+):Update)$': {
+        'main-repo': 'standard',
+        'leaper-override-group': 'leap-reviewers',
+        'repo_checker-arch-whitelist': 'x86_64',
+    },
+    r'openSUSE:(?P<project>Backports:(?P<version>[^:]+))$': {
         'staging': 'openSUSE:%(project)s:Staging',
         'staging-group': 'factory-staging',
         'staging-archs': 'x86_64',
@@ -132,7 +139,7 @@
     # Allows devel projects to utilize tools that require config, but not
     # complete StagingAPI support.
     r'(?P<project>.*$)': {
-        'staging': '%(project)s', # Allows for dashboard/config if desired.
+        'staging': None,
         'staging-group': None,
         'staging-archs': '',
         'staging-dvd-archs': '',
@@ -170,22 +177,29 @@
 class Config(object):
     """Helper class to configuration file."""
 
-    def __init__(self, project):
+    def __init__(self, apiurl, project):
         self.project = project
+        self.remote_values = self.fetch_remote(apiurl)
 
         conf_file = conf.config.get('conffile', os.environ.get('OSC_CONFIG', 
'~/.oscrc'))
         self.conf_file = os.path.expanduser(conf_file)
-        self.remote_values = None
 
         # Populate the configuration dictionary
         self.populate_conf()
 
+    @staticmethod
+    @memoize(session=True) # Allow reset by memoize_session_reset() for 
ReviewBot.
+    def get(apiurl, project):
+        """Cached version for directly accessing project config."""
+        Config(apiurl, project)
+        return conf.config.get(project, [])
+
     @property
     def conf(self):
         return conf
 
     def populate_conf(self):
-        """Add sane default into the configuration."""
+        """Add sane default into the configuration and layer (defaults, 
remote, ~/.oscrc)."""
         defaults = {}
         default_ordered = OrderedDict(sorted(DEFAULT.items(), key=lambda i: 
int(i[1].get('_priority', 99))))
         for prj_pattern in default_ordered:
@@ -231,32 +245,12 @@
         else:
             return defaults
 
-    def _migrate_staging_config(self, api):
-        # first try staging project's dashboard. Can't rely on cstaging as it's
-        # defined by config
-        config = api.load_file_content(self.project + ':Staging', 'dashboard', 
'config')
-        if not config:
-            config = api.load_file_content(self.project, 'dashboard', 'config')
-        if not config:
-            return None
-
-        print("Found config in staging dashboard - migrate now [y/n] (y)? ", 
end='')
-        response = raw_input().lower()
-        if response != '' and response != 'y':
-            return config
-
-        api.attribute_value_save('Config', config)
-
-    def apply_remote(self, api):
-        """Fetch remote config and re-process (defaults, remote, .oscrc)."""
-
-        config = api.attribute_value_load('Config')
-        if not config:
-            # try the old way
-            config = self._migrate_staging_config(api)
+    def fetch_remote(self, apiurl):
+        config = attribute_value_load(apiurl, self.project, 'Config')
         if config:
             cp = ConfigParser()
             config = '[remote]\n' + config
             cp.readfp(io.BytesIO(config))
-            self.remote_values = dict(cp.items('remote'))
-            self.populate_conf()
+            return dict(cp.items('remote'))
+
+        return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osclib/core.py 
new/openSUSE-release-tools-20180817.c11f78e/osclib/core.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osclib/core.py  2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osclib/core.py  2018-08-17 
18:20:13.000000000 +0200
@@ -14,6 +14,7 @@
 from osc.core import get_binarylist
 from osc.core import get_dependson
 from osc.core import http_GET
+from osc.core import http_POST
 from osc.core import makeurl
 from osc.core import owner
 from osc.core import Request
@@ -35,6 +36,14 @@
 
     return root.xpath('person/person/@userid')
 
+def groups_members(apiurl, groups):
+    members = []
+
+    for group in groups:
+        members.extend(group_members(apiurl, group))
+
+    return members
+
 @memoize(session=True)
 def owner_fallback(apiurl, project, package):
     root = owner(apiurl, package, project=project)
@@ -47,14 +56,22 @@
 @memoize(session=True)
 def maintainers_get(apiurl, project, package=None):
     if package is None:
-        meta = ET.fromstring(''.join(show_project_meta(apiurl, project)))
-        return [p.get('userid') for p in meta.findall('.//person') if 
p.get('role') == 'maintainer']
+        meta = ETL.fromstringlist(show_project_meta(apiurl, project))
+        maintainers = meta.xpath('//person[@role="maintainer"]/@userid')
+
+        groups = meta.xpath('//group[@role="maintainer"]/@groupid')
+        maintainers.extend(groups_members(apiurl, groups))
+
+        return maintainers
 
+    # Ugly reparse, but real xpath makes the rest much cleaner.
     root = owner_fallback(apiurl, project, package)
-    maintainers = [p.get('name') for p in root.findall('.//person') if 
p.get('role') == 'maintainer']
-    if not maintainers:
-        for group in [p.get('name') for p in root.findall('.//group') if 
p.get('role') == 'maintainer']:
-            maintainers = maintainers + group_members(apiurl, group)
+    root = ETL.fromstringlist(ET.tostringlist(root))
+    maintainers = root.xpath('//person[@role="maintainer"]/@name')
+
+    groups = root.xpath('//group[@role="maintainer"]/@name')
+    maintainers.extend(groups_members(apiurl, groups))
+
     return maintainers
 
 @memoize(session=True)
@@ -71,7 +88,7 @@
 @memoize(session=True)
 def target_archs(apiurl, project):
     meta = show_project_meta(apiurl, project)
-    meta = ET.fromstring(''.join(meta))
+    meta = ET.fromstringlist(meta)
     archs = []
     for arch in meta.findall('repository[@name="standard"]/arch'):
         archs.append(arch.text)
@@ -167,7 +184,7 @@
 @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)))
+        meta = ET.fromstringlist(show_package_meta(apiurl, target_project, 
target_package))
         node = meta.find('devel')
         if node is not None:
             return node.get('project'), node.get('package')
@@ -262,3 +279,41 @@
     root = ETL.parse(http_GET(url)).getroot()
     return root.xpath(
         '//sourceinfo[not(./linked[@project="{}"]) and not(contains(@package, 
":"))]/@package'.format(project))
+
+def attribute_value_load(apiurl, project, name, namespace='OSRT'):
+    url = makeurl(apiurl, ['source', project, '_attribute', namespace + ':' + 
name])
+
+    try:
+        root = ETL.parse(http_GET(url)).getroot()
+    except HTTPError as e:
+        if e.code == 404:
+            return None
+
+        raise e
+
+    value = root.xpath(
+        './attribute[@namespace="{}" and 
@name="{}"]/value/text()'.format(namespace, name))
+    if not len(value):
+        return None
+
+    return value[0]
+
+# New attributes must be defined manually before they can be used. Example:
+#   `osc api /attribute/OSRT/IgnoredIssues/_meta outputs`
+#
+# The new attribute can be created via:
+#   `api -T $xml /attribute/OSRT/$NEWATTRIBUTE/_meta`
+#
+# Remember to create for both OBS and IBS as necessary.
+def attribute_value_save(apiurl, project, name, value, namespace='OSRT'):
+    root = ET.Element('attributes')
+
+    attribute = ET.SubElement(root, 'attribute')
+    attribute.set('namespace', namespace)
+    attribute.set('name', name)
+
+    ET.SubElement(attribute, 'value').text = value
+
+    # The OBS API of attributes is super strange, POST to update.
+    url = makeurl(apiurl, ['source', project, '_attribute'])
+    http_POST(url, data=ET.tostring(root))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osclib/prio_command.py 
new/openSUSE-release-tools-20180817.c11f78e/osclib/prio_command.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osclib/prio_command.py  
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osclib/prio_command.py  
2018-08-17 18:20:13.000000000 +0200
@@ -22,7 +22,7 @@
     def __init__(self, api):
         self.api = api
 
-    def _setprio(self, project):
+    def _setprio(self, project, priority):
         """
         Set prios for requests that are still in review
         :param project: project to check
@@ -35,9 +35,7 @@
         for r in project['missing_reviews']:
             reqid = str(r['request'])
             req = osc.core.get_request(self.api.apiurl, reqid)
-            priority = req.priority
-            if priority is None:
-                priority = 'important'
+            if req.priority != priority:
                 query = { 'cmd': 'setpriority', 'priority': priority }
                 url = osc.core.makeurl(self.api.apiurl, ['request', reqid], 
query)
                 print reqid, message
@@ -48,7 +46,7 @@
                     print e
 
 
-    def perform(self, projects=None):
+    def perform(self, projects=None, priority=None):
         """
         Set priority on specific stagings or all of them at once
         :param projects: projects on which to set priority, None for all
@@ -59,10 +57,13 @@
             aggregate = True
             projects = self.api.get_staging_projects()
 
+        if not priority:
+            priority = 'important'
+
         for project in projects:
             info = self.api.project_status(project, aggregate)
             if not info['selected_requests']:
                 continue
-            self._setprio(info)
+            self._setprio(info, priority)
 
         return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osclib/request_splitter.py 
new/openSUSE-release-tools-20180817.c11f78e/osclib/request_splitter.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osclib/request_splitter.py      
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osclib/request_splitter.py      
2018-08-17 18:20:13.000000000 +0200
@@ -483,7 +483,7 @@
         # Only allow reviews by whitelisted groups and users as all others will
         # be considered non-quick (like @by_group="legal-auto"). The allowed
         # groups are only those configured as reviewers on the target project.
-        meta = ET.fromstring(''.join(show_project_meta(splitter.api.apiurl, 
splitter.api.project)))
+        meta = ET.fromstringlist(show_project_meta(splitter.api.apiurl, 
splitter.api.project))
         allowed_groups = meta.xpath('group[@role="reviewer"]/@groupid')
         allowed_users = []
         if 'repo-checker' in splitter.config:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/osclib/stagingapi.py 
new/openSUSE-release-tools-20180817.c11f78e/osclib/stagingapi.py
--- old/openSUSE-release-tools-20180815.cec5fa6/osclib/stagingapi.py    
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/osclib/stagingapi.py    
2018-08-17 18:20:13.000000000 +0200
@@ -34,6 +34,8 @@
 
 from osc import conf
 from osc import oscerr
+from osclib.core import attribute_value_load
+from osclib.core import attribute_value_save
 from osc.core import show_package_meta
 from osc.core import buildlog_strip_time
 from osc.core import change_review_state
@@ -690,12 +692,12 @@
 
     def get_prj_meta_revision(self, project):
         log = get_commitlog(self.apiurl, project, '_project', None, 
format='xml', meta=True)
-        root = ET.fromstring(''.join(log))
+        root = ET.fromstringlist(log)
         return int(root.find('logentry').get('revision'))
 
     def get_prj_meta(self, project, revision=None):
         meta = show_project_meta(self.apiurl, project, rev=revision)
-        return ET.fromstring(''.join(meta))
+        return ET.fromstringlist(meta)
 
     def load_prj_pseudometa(self, description_text):
         try:
@@ -867,7 +869,7 @@
 
     def is_package_disabled(self, project, package, store=False):
         meta = show_package_meta(self.apiurl, project, package)
-        meta = ET.fromstring(''.join(meta))
+        meta = ET.fromstringlist(meta)
         disabled = len(meta.xpath('build/disable[not(@*)]')) > 0
         if store:
             self._package_disabled['/'.join([project, package])] = disabled
@@ -1513,35 +1515,11 @@
         if content != self.dashboard_content_load(filename):
             self.dashboard_content_save(filename, content, comment)
 
-    def attribute_value_load(self, attribute):
-        url = self.makeurl(['source', self.project, '_attribute', 'OSRT:' + 
attribute])
-        try:
-            f = self.retried_GET(url)
-        except HTTPError as e:
-            if e.code == 404:
-                return None
-            raise e
-        root = ET.parse(f).getroot()
-        root = root.xpath('./attribute[@namespace="OSRT" and 
@name="{}"]/value/text()'.format(attribute))
-        if not len(root):
-            return None
-        return root[0]
+    def attribute_value_load(self, name):
+        return attribute_value_load(self.apiurl, self.project, name)
 
-    # to create a new attribute 'type' you need to do some manual step
-    # create a xml file analoge to what
-    # osc api /attribute/OSRT/IgnoredIssues/_meta outputs
-    # you need to think about roles, groups and users that should be
-    # able to write the attribute
-    # after that osc api -T $xml /attribute/OSRT/$NEWATTRIBUTE/_meta
-    # (preferably do this right away for ibs and obs)
-    def attribute_value_save(self, attribute, text):
-        root = ET.fromstring('<attributes><attribute name="" 
namespace="OSRT">' +
-                             '<value/></attribute></attributes>')
-        root.find('./attribute').set('name', attribute)
-        root.find('./attribute/value').text = text
-        # the OBS API of attributes is super strange, you POST updates
-        url = self.makeurl(['source', self.project, '_attribute'])
-        self.retried_POST(url, data=ET.tostring(root))
+    def attribute_value_save(self, name, value):
+        return attribute_value_save(self.apiurl, self.project, name, value)
 
     def update_status_or_deactivate(self, project, command):
         meta = self.get_prj_pseudometa(project)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/pkglistgen.py 
new/openSUSE-release-tools-20180817.c11f78e/pkglistgen.py
--- old/openSUSE-release-tools-20180815.cec5fa6/pkglistgen.py   2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/pkglistgen.py   2018-08-17 
18:20:13.000000000 +0200
@@ -1159,10 +1159,9 @@
         # Store target project as opts.project will contain subprojects.
         target_project = opts.project
 
-        config = Config(target_project)
         apiurl = conf.config['apiurl']
+        config = Config(apiurl, target_project)
         api = StagingAPI(apiurl, target_project)
-        config.apply_remote(api)
 
         target_config = conf.config[target_project]
         if opts.scope == 'ports':
@@ -1387,7 +1386,7 @@
             project_family.extend(project_list_family(apiurl, family_include))
 
         for project in project_family:
-            config = Config(project)
+            config = Config(apiurl, project)
             project_config = conf.config[project]
 
             baseurl = project_config.get('download-baseurl')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/repo_checker.pl 
new/openSUSE-release-tools-20180817.c11f78e/repo_checker.pl
--- old/openSUSE-release-tools-20180815.cec5fa6/repo_checker.pl 2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/repo_checker.pl 2018-08-17 
18:20:13.000000000 +0200
@@ -20,8 +20,8 @@
 my $arch = shift @ARGV;
 my @directories = split(/\,/, shift @ARGV);
 my %toignore;
-my $repodir;
 my %whitelist;
+my $filter = 1;
 while (@ARGV) {
     my $switch = shift @ARGV;
     if ( $switch eq "-f" ) {
@@ -33,12 +33,12 @@
         }
         close(TOIGNORE);
     }
-    elsif ( $switch eq "-r" ) {
-        $repodir = shift @ARGV;
-    }
     elsif ( $switch eq "-w" ) {
         %whitelist = map { $_ => 1 } split(/\,/, shift @ARGV);
     }
+    elsif ( $switch eq "--no-filter" ) {
+        $filter = 0;
+    }
     else {
         print "read the source luke: $switch ? \n";
         exit(1);
@@ -47,9 +47,8 @@
 
 my %targets;
 
-sub write_package($$) {
-    my $ignore  = shift;
-    my $package = shift;
+sub write_package {
+    my ($package, $packages_fd, $written_names) = @_;
 
     my $name = basename($package);
     if ($name =~ m/^[a-z0-9]{32}-/) { # repo cache
@@ -58,44 +57,49 @@
        $name =~ s,^(.*)-[^-]+-[^-]+.rpm,$1,;
     }
 
-    if ( $ignore == 1 && defined $toignore{$name} ) {
+    if ( defined $written_names->{$name} ) {
         return;
     }
+    $written_names->{$name} = $package;
 
     my $out = CreatePackageDescr::package_snippet($package);
     if ($out eq "" || $out =~ m/=Pkg:    /) {
         print STDERR "ERROR: empty package snippet for: $name\n";
         exit(126);
     }
-    print PACKAGES $out;
+    print $packages_fd $out;
     return $name;
 }
 
 my @rpms;
 my $tmpdir = tempdir( "repochecker-XXXXXXX", TMPDIR => 1, CLEANUP => 1 );
 my $pfile = $tmpdir . "/packages";
-open( PACKAGES, ">", $pfile ) || die 'can not open';
-print PACKAGES "=Ver: 2.0\n";
+open( my $packages_fd, ">", $pfile ) || die 'can not open';
+print $packages_fd "=Ver: 2.0\n";
 
-# Allow $repodir to be empty indicating to only review $directories.
-if (length($repodir)) {
-    my @rpms = glob("$repodir/*.rpm");
-    foreach my $package (@rpms) {
-        write_package(1, $package);
-    }
-}
+my $written_names = {};
+my $first_layer = 1;
 
 foreach my $directory (@directories) {
     @rpms = glob("$directory/*.rpm");
     foreach my $package (@rpms) {
-        my $name = write_package( 0, $package );
-        if (!exists($whitelist{$name})) {
+        my $name = write_package( $package, $packages_fd, $written_names );
+        if ($first_layer && $name && !exists($whitelist{$name})) {
             $targets{$name} = 1;
         }
     }
+
+    if ($first_layer) {
+        foreach my $key (keys %toignore) {
+            if (!defined($written_names->{$key})) {
+                $written_names->{$key} = "simulate overridden";
+            }
+        }
+        $first_layer = 0;
+    }
 }
 
-close(PACKAGES);
+close($packages_fd);
 
 my $error_file = $tmpdir . "/error_file";
 open(INSTALL, "/usr/bin/installcheck $arch $pfile 2> $error_file |")
@@ -109,7 +113,7 @@
         $inc = 0;
     }
     if ( $_ =~ /^can't install (.*)-[^-]+-[^-]+:$/ ) {
-        if ( defined $targets{$1} ) {
+        if ( !$filter || defined $targets{$1} ) {
             $inc = 1;
             $ret = 1;
         }
@@ -138,7 +142,7 @@
         $inc = 0;
     }
     if ( $_ =~ /^found conflict of (.*)-[^-]+-[^-]+ with (.*)-[^-]+-[^-]+:$/ ) 
{
-        if ( defined $targets{$1} || defined $targets{$2} ) {
+        if ( !$filter || defined $targets{$1} || defined $targets{$2} ) {
             $inc = 1;
             $ret = 1;
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/repo_checker.py 
new/openSUSE-release-tools-20180817.c11f78e/repo_checker.py
--- old/openSUSE-release-tools-20180815.cec5fa6/repo_checker.py 2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/repo_checker.py 2018-08-17 
18:20:13.000000000 +0200
@@ -15,7 +15,10 @@
 import tempfile
 
 from osclib.comments import CommentAPI
+from osclib.conf import Config
+from osclib.conf import str2bool
 from osclib.core import binary_list
+from osclib.core import BINARY_REGEX
 from osclib.core import depends_on
 from osclib.core import devel_project_fallback
 from osclib.core import fileinfo_ext_all
@@ -24,6 +27,7 @@
 from osclib.core import target_archs
 from osclib.cycle import CycleDetector
 from osclib.memoize import CACHEDIR
+from osclib.memoize import memoize
 
 import ReviewBot
 
@@ -52,7 +56,6 @@
         return not len(root.xpath('result[@state!="published"]'))
 
     def project_only(self, project, post_comments=False):
-        # self.staging_config needed by target_archs().
         api = self.staging_api(project)
 
         if not self.force and not self.repository_published(project):
@@ -70,12 +73,17 @@
 
         comment = [build]
         for arch in self.target_archs(project):
-            directory_project = self.mirror(project, arch)
+            directories = []
+            repos = self.staging_api(project).expanded_repos('standard')
+            for layered_project, repo in repos:
+                if repo != 'standard':
+                    raise "We assume all is standard"
+                directories.append(self.mirror(layered_project, arch))
 
             parse = project if post_comments else False
             results = {
                 'cycle': CheckResult(True, None),
-                'install': self.install_check(project, [directory_project], 
arch, parse=parse),
+                'install': self.install_check(project, directories, arch, 
parse=parse, no_filter=True),
             }
 
             if not all(result.success for _, result in results.items()):
@@ -84,7 +92,6 @@
         text = '\n'.join(comment).strip()
         if not self.dryrun:
             api.dashboard_content_ensure('repo_checker', text + '\n', 
'project_only run')
-            self.whitelist_clean(project)
         else:
             print(text)
 
@@ -95,7 +102,7 @@
         self.logger.info('{} package 
comments'.format(len(self.package_results)))
 
         for package, sections in self.package_results.items():
-            if 
bool(self.staging_config[project].get('repo_checker-package-comment-devel', 
True)):
+            if str2bool(Config.get(self.apiurl, 
project).get('repo_checker-package-comment-devel', 'True')):
                 bot_name_suffix = project
                 comment_project, comment_package = 
devel_project_fallback(self.apiurl, project, package)
                 if comment_project is None or comment_package is None:
@@ -255,10 +262,10 @@
 
             # Only bother if staging can match arch, but layered first.
             repos = self.staging_api(project).expanded_repos('standard')
-            for layered_project, repo in reversed(repos):
+            for layered_project, repo in repos:
                 if repo != 'standard':
                     raise "We assume all is standard"
-                directories.insert(0, self.mirror(layered_project, arch))
+                directories.append(self.mirror(layered_project, arch))
 
             whitelist = self.binary_whitelist(project, arch, group)
 
@@ -296,7 +303,7 @@
 
         # Check for arch whitelist and use intersection.
         product = project.split(':Staging:', 1)[0]
-        whitelist = 
self.staging_config[product].get('repo_checker-arch-whitelist')
+        whitelist = Config.get(self.apiurl, 
product).get('repo_checker-arch-whitelist')
         if whitelist:
             archs = list(set(whitelist.split(' ')).intersection(set(archs)))
 
@@ -336,17 +343,36 @@
             if binary.package in packages:
                 yield binary.name
 
+    @memoize(session=True)
+    def binary_list_existing_problem(self, project):
+        """Determine which binaries are mentioned in repo_checker output."""
+        binaries = set()
+
+        api = self.staging_api(project)
+        content = api.dashboard_content_load('repo_checker')
+        if not content:
+            self.logger.warn('no project_only run from which to extract 
existing problems')
+            return binaries
+
+        sections = self.install_check_parse(content)
+        for section in sections:
+            for binary in section.binaries:
+                match = re.match(BINARY_REGEX, binary)
+                if match:
+                    binaries.add(match.group('name'))
+
+        return binaries
+
     def binary_whitelist(self, project, arch, group):
         additions = 
self.staging_api(project).get_prj_pseudometa(group).get('config', {})
+        whitelist = self.binary_list_existing_problem(project)
         prefix = 'repo_checker-binary-whitelist'
-        whitelist = set()
         for key in [prefix, '-'.join([prefix, arch])]:
-            whitelist.update(self.staging_config[project].get(key, '').split(' 
'))
             whitelist.update(additions.get(key, '').split(' '))
         whitelist = filter(None, whitelist)
         return whitelist
 
-    def install_check(self, project, directories, arch, ignore=[], 
whitelist=[], parse=False):
+    def install_check(self, project, directories, arch, ignore=[], 
whitelist=[], parse=False, no_filter=False):
         self.logger.info('install check: start')
 
         with tempfile.NamedTemporaryFile() as ignore_file:
@@ -355,14 +381,12 @@
                 ignore_file.write(item + '\n')
             ignore_file.flush()
 
-            directory_project = directories.pop(0) if len(directories) > 1 
else None
-
             # Invoke repo_checker.pl to perform an install check.
             script = os.path.join(SCRIPT_PATH, 'repo_checker.pl')
             parts = ['LC_ALL=C', 'perl', script, arch, ','.join(directories),
                      '-f', ignore_file.name, '-w', ','.join(whitelist)]
-            if directory_project:
-                parts.extend(['-r', directory_project])
+            if no_filter:
+                parts.append('--no-filter')
 
             parts = [pipes.quote(part) for part in parts]
             p = subprocess.Popen(' '.join(parts), shell=True,
@@ -527,83 +551,6 @@
         self.review_messages['accepted'] = 'delete request is safe'
         return True
 
-    def whitelist_clean(self, project, interactive=False):
-        from copy import copy
-        from difflib import unified_diff
-        from osclib.core import BINARY_REGEX
-
-        api = self.staging_api(project)
-
-        # Determine which binaries are mentioned in repo_checker output.
-        content = api.dashboard_content_load('repo_checker')
-        sections = self.install_check_parse(content)
-        binaries = set()
-        for section in sections:
-            for binary in section.binaries:
-                match = re.match(BINARY_REGEX, binary)
-                if match:
-                    binaries.add(match.group('name'))
-
-        # Find whitelist config entries and filter list to only those 
mentioned.
-        prefix = 'repo_checker-binary-whitelist'
-        binaries_common = None
-        whitelists = {}
-        whitelists_remaining = {}
-        for key, value in self.staging_config[project].items():
-            if not key.startswith(prefix):
-                continue
-
-            whitelists[key] = set(value.split())
-            whitelists_remaining[key] = whitelists[key].intersection(binaries)
-
-            if key != prefix:
-                if binaries_common is None:
-                    binaries_common = whitelists_remaining[key]
-                else:
-                    binaries_common = 
binaries_common.intersection(whitelists_remaining[key])
-
-        if binaries_common is not None and len(binaries_common):
-            # Remove entries common to all archs and place in common whitelist.
-            whitelists_remaining[prefix].update(binaries_common)
-
-            for key, value in whitelists_remaining.items():
-                if key == prefix:
-                    continue
-
-                whitelists_remaining[key] = whitelists_remaining[key] - 
binaries_common
-
-        # Update whitelist entries with new values.
-        config = api.attribute_value_load('Config').splitlines(True)
-        config_new = copy(config)
-        for key, value in whitelists_remaining.items():
-            if value != whitelists[key]:
-                self.whitelist_clean_set(config_new, key, ' 
'.join(sorted(value)))
-
-        if config == config_new:
-            print('No changes')
-            return
-
-        # Present diff and prompt to apply.
-        print(''.join(unified_diff(config, config_new, fromfile='config.orig', 
tofile='config.new')))
-        print('Apply config changes? [y/n] (y): ',  end='')
-        if interactive:
-            response = raw_input().lower()
-            if response != '' and response != 'y':
-                print('quit')
-                return
-        else:
-            print('y')
-
-        api.attribute_value_save('Config', ''.join(config_new))
-
-    def whitelist_clean_set(self, config, key, value):
-        # Unfortunately even OscConfigParser does not preserve empty lines.
-        for i, line in enumerate(config):
-            if line.startswith(key + ' ='):
-                config[i] = '{} = {}\n'.format(key, value) if value else '{} 
=\n'.format(key)
-
-        return config
-
 
 class CommandLineInterface(ReviewBot.CommandLineInterface):
 
@@ -636,10 +583,6 @@
         self.checker.check_requests() # Needed to properly init ReviewBot.
         self.checker.project_only(project, opts.post_comments)
 
-    def do_whitelist_clean(self, subcmd, opts, project):
-        self.checker.check_requests() # Needed to properly init ReviewBot.
-        self.checker.whitelist_clean(project, interactive=True)
-
 if __name__ == "__main__":
     app = CommandLineInterface()
     sys.exit(app.main())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/suppkg_rebuild.py 
new/openSUSE-release-tools-20180817.c11f78e/suppkg_rebuild.py
--- old/openSUSE-release-tools-20180815.cec5fa6/suppkg_rebuild.py       
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/suppkg_rebuild.py       
2018-08-17 18:20:13.000000000 +0200
@@ -47,7 +47,7 @@
     def __init__(self, project):
         self.project = project
         self.apiurl = osc.conf.config['apiurl']
-        Config(self.project)
+        Config(self.apiurl, self.project)
         self.api = StagingAPI(self.apiurl, self.project)
 
     def get_support_package_list(self, project, repository):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/accept_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/accept_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/accept_tests.py   
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/accept_tests.py   
2018-08-17 18:20:13.000000000 +0200
@@ -31,7 +31,7 @@
         Initialize the configuration
         """
         self.obs = OBS()
-        Config('openSUSE:Factory')
+        Config(APIURL, 'openSUSE:Factory')
         self.api = StagingAPI(APIURL, 'openSUSE:Factory')
 
     def test_accept_comments(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/api_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/api_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/api_tests.py      
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/api_tests.py      
2018-08-17 18:20:13.000000000 +0200
@@ -43,7 +43,7 @@
         """
 
         self.obs = OBS()
-        Config('openSUSE:Factory')
+        Config(APIURL, 'openSUSE:Factory')
         self.api = StagingAPI(APIURL, 'openSUSE:Factory')
 
     def tearDown(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/check_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/check_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/check_tests.py    
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/check_tests.py    
2018-08-17 18:20:13.000000000 +0200
@@ -63,7 +63,7 @@
         """Initialize the configuration."""
 
         self.obs = OBS()
-        Config('openSUSE:Factory')
+        Config(APIURL, 'openSUSE:Factory')
         self.stagingapi = StagingAPI(APIURL, 'openSUSE:Factory')
         self.checkcommand = CheckCommand(self.stagingapi)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/config_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/config_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/config_tests.py   
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/config_tests.py   
2018-08-17 18:20:13.000000000 +0200
@@ -2,6 +2,8 @@
 from osc import conf
 from osclib.conf import DEFAULT
 from osclib.conf import Config
+from osclib.core import attribute_value_save
+from osclib.memoize import memoize_session_reset
 from osclib.stagingapi import StagingAPI
 
 from obs import APIURL
@@ -12,31 +14,32 @@
 class TestConfig(unittest.TestCase):
     def setUp(self):
         self.obs = OBS()
-        self.config = Config(PROJECT)
+        self.load_config()
         self.api = StagingAPI(APIURL, PROJECT)
 
+    def load_config(self, project=PROJECT):
+        self.config = Config(APIURL, project)
+
     def test_basic(self):
         self.assertEqual('openSUSE', conf.config[PROJECT]['lock-ns'])
 
     def test_remote(self):
-        self.assertEqual('local', conf.config[PROJECT]['overridden-by-local'])
-        self.assertIsNone(conf.config[PROJECT].get('remote-only'))
-
-        self.config.apply_remote(self.api)
-
+        # Initial config present in fixtures/oscrc and obs.py attribute 
default.
+        # Local config fixture contains overridden-by-local and should win over
+        # the remote config value.
         self.assertEqual('local', conf.config[PROJECT]['overridden-by-local'])
         self.assertEqual('remote-indeed', conf.config[PROJECT]['remote-only'])
 
-        self.api.attribute_value_save('Config', 'remote-only = nope')
-        self.config.apply_remote(self.api)
+        # Change remote value.
+        attribute_value_save(APIURL, PROJECT, 'Config', 'remote-only = new 
value\n')
+        self.load_config()
 
         self.assertEqual('local', conf.config[PROJECT]['overridden-by-local'])
-        self.assertEqual('nope', conf.config[PROJECT]['remote-only'])
+        self.assertEqual('new value', conf.config[PROJECT]['remote-only'])
 
     def test_remote_none(self):
-        self.api.attribute_value_save('Config', '')
-        # don't crash
-        self.config.apply_remote(self.api)
+        self.load_config('not_real_project')
+        self.assertTrue(True) # Did not crash!
 
     def test_pattern_order(self):
         # Add pattern to defaults in order to identify which was matched.
@@ -47,6 +50,7 @@
         projects = (
             'openSUSE:Factory',
             'openSUSE:Leap:15.0',
+            'openSUSE:Leap:15.0:Update',
             'openSUSE:Backports:SLE-15',
             'SUSE:SLE-15:GA',
             'SUSE:SLE-12:GA',
@@ -56,7 +60,16 @@
         # Ensure each pattern is match instead of catch-all pattern.
         patterns = set()
         for project in projects:
-            config = Config(project)
+            config = Config(APIURL, project)
             patterns.add(conf.config[project]['pattern'])
 
         self.assertEqual(len(patterns), len(DEFAULT))
+
+    def test_get_memoize_reset(self):
+        """Ensure memoize_session_reset() properly forces re-fetch of 
config."""
+        self.assertEqual('remote-indeed', Config.get(APIURL, 
PROJECT)['remote-only'])
+
+        attribute_value_save(APIURL, PROJECT, 'Config', 'remote-only = new 
value\n')
+        memoize_session_reset()
+
+        self.assertEqual('new value', Config.get(APIURL, 
PROJECT)['remote-only'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/freeze_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/freeze_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/freeze_tests.py   
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/freeze_tests.py   
2018-08-17 18:20:13.000000000 +0200
@@ -33,7 +33,7 @@
         Initialize the configuration
         """
         self.obs = OBS()
-        Config('openSUSE:Factory')
+        Config(APIURL, 'openSUSE:Factory')
         self.api = StagingAPI(APIURL, 'openSUSE:Factory')
 
     def _get_fixture_path(self, filename):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openSUSE-release-tools-20180815.cec5fa6/tests/obs.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/obs.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/obs.py    2018-08-15 
22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/obs.py    2018-08-17 
18:20:13.000000000 +0200
@@ -274,7 +274,7 @@
             'openSUSE:Factory': {
                 'OSRT': {
                     'Config': 'overridden-by-local = remote-nope\n'
-                    'remote-only = remote-indeed'
+                              'remote-only = remote-indeed\n'
                 }
             }
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/obslock_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/obslock_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/obslock_tests.py  
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/obslock_tests.py  
2018-08-17 18:20:13.000000000 +0200
@@ -11,7 +11,7 @@
 class TestOBSLock(unittest.TestCase):
     def setUp(self):
         self.obs = OBS()
-        Config(PROJECT)
+        Config(APIURL, PROJECT)
 
     def obs_lock(self, reason='list'):
         return OBSLock(APIURL, PROJECT, reason=reason)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/select_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/select_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/select_tests.py   
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/select_tests.py   
2018-08-17 18:20:13.000000000 +0200
@@ -32,7 +32,7 @@
         Initialize the configuration
         """
         self.obs = OBS()
-        Config('openSUSE:Factory')
+        Config(APIURL, 'openSUSE:Factory')
         self.api = StagingAPI(APIURL, 'openSUSE:Factory')
 
     def test_old_frozen(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/tests/unselect_tests.py 
new/openSUSE-release-tools-20180817.c11f78e/tests/unselect_tests.py
--- old/openSUSE-release-tools-20180815.cec5fa6/tests/unselect_tests.py 
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/tests/unselect_tests.py 
2018-08-17 18:20:13.000000000 +0200
@@ -11,7 +11,7 @@
 class TestUnselect(unittest.TestCase):
     def setUp(self):
         self.obs = OBS()
-        Config(PROJECT)
+        Config(APIURL, PROJECT)
         self.api = StagingAPI(APIURL, PROJECT)
 
     def test_cleanup_filter(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/totest-manager.py 
new/openSUSE-release-tools-20180817.c11f78e/totest-manager.py
--- old/openSUSE-release-tools-20180815.cec5fa6/totest-manager.py       
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/totest-manager.py       
2018-08-17 18:20:13.000000000 +0200
@@ -1040,7 +1040,7 @@
         if not self.options.obs_api_url:
             self.options.obs_api_url = self.api_url[project_base]
 
-        Config(project)
+        Config(self.options.obs_api_url, project)
         if project not in self.totest_class:
             msg = 'Project %s not recognized. Possible values [%s]' % (
                 project, ', '.join(self.totest_class))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20180815.cec5fa6/update_crawler.py 
new/openSUSE-release-tools-20180817.c11f78e/update_crawler.py
--- old/openSUSE-release-tools-20180815.cec5fa6/update_crawler.py       
2018-08-15 22:56:03.000000000 +0200
+++ new/openSUSE-release-tools-20180817.c11f78e/update_crawler.py       
2018-08-17 18:20:13.000000000 +0200
@@ -329,7 +329,7 @@
     osc.conf.config['debug'] = args.osc_debug
 
     # initialize stagingapi config
-    Config(args.to_prj)
+    Config(osc.conf.config['apiurl'], args.to_prj)
 
     uc = UpdateCrawler(args.from_prj, args.to_prj)
     uc.caching = args.cache_requests

++++++ openSUSE-release-tools.obsinfo ++++++
--- /var/tmp/diff_new_pack.Y0Whke/_old  2018-08-20 16:19:54.980864449 +0200
+++ /var/tmp/diff_new_pack.Y0Whke/_new  2018-08-20 16:19:54.980864449 +0200
@@ -1,5 +1,5 @@
 name: openSUSE-release-tools
-version: 20180815.cec5fa6
-mtime: 1534366563
-commit: cec5fa69297b5c3221001e91a182f3e0a6ea2c66
+version: 20180817.c11f78e
+mtime: 1534522813
+commit: c11f78eb83656c583cdba86c0c7537e8a46919f8
 


Reply via email to