Hello community,

here is the log from the commit of package openSUSE-release-tools for 
openSUSE:Factory checked in at 2018-11-09 07:56:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openSUSE-release-tools (Old)
 and      /work/SRC/openSUSE:Factory/.openSUSE-release-tools.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "openSUSE-release-tools"

Fri Nov  9 07:56:12 2018 rev:142 rq:647383 version:20181108.4293b6b

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/openSUSE-release-tools/openSUSE-release-tools.changes
    2018-11-08 09:47:43.277154111 +0100
+++ 
/work/SRC/openSUSE:Factory/.openSUSE-release-tools.new/openSUSE-release-tools.changes
       2018-11-09 07:56:33.207564789 +0100
@@ -1,0 +2,78 @@
+Thu Nov 08 16:16:21 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181108.4293b6b:
+  * Avoid httppretty 0.9.6 for now
+
+-------------------------------------------------------------------
+Wed Nov 07 22:55:36 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181107.1fec88f:
+  * userscript/staging-move-drag-n-drop: provide initial version.
+
+-------------------------------------------------------------------
+Wed Nov 07 22:41:48 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181107.fc99800:
+  * check_source: check if member of staging group before attempting to skip.
+
+-------------------------------------------------------------------
+Wed Nov 07 08:53:17 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181107.c85f26e:
+  * Don't report that a package is ok if the resultlist is empty
+
+-------------------------------------------------------------------
+Mon Nov 05 11:54:37 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181105.1f8bf21:
+  * Fail rabbit-openqa and have systemd restart it
+
+-------------------------------------------------------------------
+Mon Nov 05 08:55:24 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181105.22b89d4:
+  * abichecker: fix for updated osc api
+
+-------------------------------------------------------------------
+Thu Nov 01 18:43:12 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181101.33a4a3b:
+  * osclib/request_splitter: provide stageable option and make default True.
+
+-------------------------------------------------------------------
+Thu Nov 01 14:05:12 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181101.9f21c86:
+  * devel-projects: remove workaround for OBS xpath bug during request search.
+
+-------------------------------------------------------------------
+Wed Oct 31 20:17:54 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181031.0d9cde5:
+  * osclib/core: repository_published() make x86_64 dependent on i586.
+
+-------------------------------------------------------------------
+Tue Oct 30 20:17:00 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181030.c7fd9ba:
+  * osclib/select: only check filter-from logic if argument was passed.
+
+-------------------------------------------------------------------
+Tue Oct 30 20:02:24 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181030.76bb32a:
+  * Fix indentation in is_snapshottable
+
+-------------------------------------------------------------------
+Fri Oct 26 14:54:27 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181026.9f82d01:
+  * leaper: block on pending factory submissions also for new packages
+
+-------------------------------------------------------------------
+Thu Oct 25 18:54:47 UTC 2018 - opensuse-releaset...@opensuse.org
+
+- Update to version 20181025.78a0172:
+  * osc-staging: handle None value for --filter-from.
+
+-------------------------------------------------------------------

Old:
----
  openSUSE-release-tools-20181025.5558473.obscpio

New:
----
  openSUSE-release-tools-20181108.4293b6b.obscpio

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

Other differences:
------------------
++++++ openSUSE-release-tools.spec ++++++
--- /var/tmp/diff_new_pack.ziblMR/_old  2018-11-09 07:56:36.255561313 +0100
+++ /var/tmp/diff_new_pack.ziblMR/_new  2018-11-09 07:56:36.295561267 +0100
@@ -20,7 +20,7 @@
 %define source_dir openSUSE-release-tools
 %define announcer_filename factory-package-news
 Name:           openSUSE-release-tools
-Version:        20181025.5558473
+Version:        20181108.4293b6b
 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.ziblMR/_old  2018-11-09 07:56:36.687560821 +0100
+++ /var/tmp/diff_new_pack.ziblMR/_new  2018-11-09 07:56:36.687560821 +0100
@@ -1,6 +1,6 @@
 <servicedata>
   <service name="tar_scm">
     <param 
name="url">https://github.com/openSUSE/openSUSE-release-tools.git</param>
-    <param 
name="changesrevision">55584739996331a3660216cb8ea4bcadca3bc60a</param>
+    <param 
name="changesrevision">824fab13fdeaac4f14ed10409c8ff7844eb3e07c</param>
   </service>
 </servicedata>

++++++ openSUSE-release-tools-20181025.5558473.obscpio -> 
openSUSE-release-tools-20181108.4293b6b.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/abichecker/abichecker.py 
new/openSUSE-release-tools-20181108.4293b6b/abichecker/abichecker.py
--- old/openSUSE-release-tools-20181025.5558473/abichecker/abichecker.py        
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/abichecker/abichecker.py        
2018-11-08 17:10:04.000000000 +0100
@@ -883,7 +883,7 @@
                 repository = [ mr.srcrepo for mr in matchrepos],
                 arch = [ mr.arch for mr in matchrepos])
         for result in results:
-            for res in osc.core.result_xml_to_dicts(result):
+            for res, _ in osc.core.result_xml_to_dicts(result):
                 if not 'package' in res or res['package'] != 
src_srcinfo.package:
                     continue
                 rmap[(res['repository'], res['arch'])] = res
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/check_source.py 
new/openSUSE-release-tools-20181108.4293b6b/check_source.py
--- old/openSUSE-release-tools-20181025.5558473/check_source.py 2018-10-25 
20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/check_source.py 2018-11-08 
17:10:04.000000000 +0100
@@ -16,6 +16,7 @@
 from osclib.conf import Config
 from osclib.core import devel_project_get
 from osclib.core import devel_project_fallback
+from osclib.core import group_members
 import urllib2
 import ReviewBot
 from osclib.conf import str2bool
@@ -174,10 +175,13 @@
 
             if self.only_changes():
                 self.logger.debug('only .changes modifications')
-                if self.staging_group and not self.dryrun:
-                    osc.core.change_review_state(self.apiurl, 
str(self.request.reqid), 'accepted',
-                        by_group=self.staging_group,
-                        message='skipping the staging process since only 
.changes modifications')
+                if self.staging_group and self.review_user in 
group_members(self.apiurl, self.staging_group):
+                    if not self.dryrun:
+                        osc.core.change_review_state(self.apiurl, 
str(self.request.reqid), 'accepted',
+                            by_group=self.staging_group,
+                            message='skipping the staging process since only 
.changes modifications')
+                else:
+                    self.logger.debug('unable to skip staging review since not 
a member of staging group')
             elif self.repo_checker is not None:
                 self.add_review(self.request, by_user=self.repo_checker, 
msg='Please review build success')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/devel-project.py 
new/openSUSE-release-tools-20181108.4293b6b/devel-project.py
--- old/openSUSE-release-tools-20181025.5558473/devel-project.py        
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/devel-project.py        
2018-11-08 17:10:04.000000000 +0100
@@ -146,12 +146,12 @@
     apiurl = osc.conf.config['apiurl']
     devel_projects = devel_projects_load(args)
 
+    # Disable including source project in get_request_list() query.
+    osc.conf.config['include_request_from_project'] = False
     for devel_project in devel_projects:
         requests = get_request_list(apiurl, devel_project,
                                     req_state=('new', 'review'),
                                     req_type='submit',
-                                    # Seems to work backwards, as it includes 
only.
-                                    exclude_target_projects=[devel_project],
                                     withfullhistory=True)
         for request in requests:
             action = request.actions[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/openSUSE-release-tools-20181025.5558473/leaper.py 
new/openSUSE-release-tools-20181108.4293b6b/leaper.py
--- old/openSUSE-release-tools-20181025.5558473/leaper.py       2018-10-25 
20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/leaper.py       2018-11-08 
17:10:04.000000000 +0100
@@ -149,20 +149,20 @@
 
             review_result = None
             prj = 'openSUSE.org:openSUSE:Factory'
-            if self.is_package_in_project(prj, package):
-                # True or None (open request) are acceptable for SLE.
-                in_factory = self._check_factory(package, src_srcinfo, prj)
-                if in_factory:
-                    review_result = True
-                    self.source_in_factory = True
-                elif in_factory is None:
-                    self.pending_factory_submission = True
+            # True or None (open request) are acceptable for SLE.
+            in_factory = self._check_factory(package, src_srcinfo, prj)
+            if in_factory:
+                review_result = True
+                self.source_in_factory = True
+            elif in_factory is None:
+                self.pending_factory_submission = True
+            else:
+                if self.is_package_in_project(prj, package):
+                    self.logger.info('the package is not in Factory, nor 
submitted there')
                 else:
                     self.logger.info('different sources in 
{}'.format(self.rdiff_link(src_project, src_package, src_rev, prj, package)))
-            else:
-                self.logger.info('the package is not in Factory, nor submitted 
there')
 
-            if review_result == None:
+            if review_result == None and not self.pending_factory_submission:
                 other_projects_to_check = []
                 m = re.match(r'SUSE:SLE-(\d+)(?:-SP(\d+)):', target_project)
                 if m:
@@ -205,7 +205,7 @@
 
                 self.logger.info('no matching sources found anywhere. Needs a 
human to decide whether that is ok. Please provide some justification to help 
that person.')
 
-            if not review_result:
+            if not review_result and origin is not None:
                 review_result = origin_same
                 if origin_same:
                     self.logger.info("ok, origin %s unchanged", origin)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/osc-staging.py 
new/openSUSE-release-tools-20181108.4293b6b/osc-staging.py
--- old/openSUSE-release-tools-20181025.5558473/osc-staging.py  2018-10-25 
20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/osc-staging.py  2018-11-08 
17:10:04.000000000 +0100
@@ -656,9 +656,10 @@
                 if opts.add:
                     api.mark_additional_packages(target_project, [opts.add])
                 else:
+                    filter_from = api.prj_from_short(opts.filter_from) if 
opts.filter_from else None
                     SelectCommand(api, target_project) \
                         .perform(requests, opts.move,
-                                 api.prj_from_short(opts.filter_from), 
opts.no_freeze)
+                                 filter_from, opts.no_freeze)
         elif cmd == 'cleanup_rings':
             CleanupRings(api).perform()
         elif cmd == 'ignore':
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/osclib/core.py 
new/openSUSE-release-tools-20181108.4293b6b/osclib/core.py
--- old/openSUSE-release-tools-20181025.5558473/osclib/core.py  2018-10-25 
20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/osclib/core.py  2018-11-08 
17:10:04.000000000 +0100
@@ -413,6 +413,19 @@
     return states
 
 def repository_published(apiurl, project, repository, archs=[]):
+    # In a perfect world this would check for the existence of imports from 
i586
+    # into x86_64, but in an even more perfect world OBS would show archs that
+    # depend on another arch for imports as not completed until the dependent
+    # arch completes. This is a simplified check that ensures x86_64 repos are
+    # not indicated as published when i586 has not finished which is primarily
+    # useful for repo_checker when only checking x86_64. The API treats archs 
as
+    # a filter on what to return and thus non-existent archs do not cause an
+    # issue nor alter the result.
+    if 'x86_64' in archs and 'i586' not in archs:
+        # Create a copy to avoid altering caller's list.
+        archs = list(archs)
+        archs.append('i586')
+
     root = ETL.fromstringlist(show_results_meta(
         apiurl, project, multibuild=True, repository=[repository], arch=archs))
     return not len(root.xpath('result[@state!="published" and 
@state!="unpublished"]'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/osclib/list_command.py 
new/openSUSE-release-tools-20181108.4293b6b/osclib/list_command.py
--- old/openSUSE-release-tools-20181025.5558473/osclib/list_command.py  
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/osclib/list_command.py  
2018-11-08 17:10:04.000000000 +0100
@@ -29,7 +29,6 @@
         if not len(requests): return
 
         splitter = RequestSplitter(self.api, requests, in_ring=True)
-        splitter.filter_add('./action[@type="submit" or @type="delete"]')
         splitter.group_by('./action/target/@devel_project')
         splitter.split()
 
@@ -68,6 +67,7 @@
             print 'Not in a ring:', ' '.join(sorted(non_ring_packages))
 
         # Print requests not handled by staging process to highlight them.
+        splitter.stageable = False
         for request_type in ('change_devel', 'set_bugowner'):
             splitter.reset()
             splitter.filter_add('./action[@type="{}"]'.format(request_type))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/osclib/request_splitter.py 
new/openSUSE-release-tools-20181108.4293b6b/osclib/request_splitter.py
--- old/openSUSE-release-tools-20181025.5558473/osclib/request_splitter.py      
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/osclib/request_splitter.py      
2018-11-08 17:10:04.000000000 +0100
@@ -9,10 +9,11 @@
 import re
 
 class RequestSplitter(object):
-    def __init__(self, api, requests, in_ring):
+    def __init__(self, api, requests, in_ring, stageable=True):
         self.api = api
         self.requests = requests
         self.in_ring = in_ring
+        self.stageable = stageable
         self.config = conf.config[self.api.project]
 
         # 55 minutes to avoid two staging bot loops of 30 minutes
@@ -38,6 +39,10 @@
         self.other = []
         self.grouped = {}
 
+        if self.stageable:
+            # Require requests to be stageable (submit or delete package).
+            self.filter_add('./action[@type="submit" or (@type="delete" and 
./target[@package])]')
+
     def strategy_set(self, name, **kwargs):
         self.reset()
 
@@ -393,7 +398,6 @@
 
 class StrategyNone(Strategy):
     def apply(self, splitter):
-        splitter.filter_add('./action[not(@type="add_role" or 
@type="change_devel")]')
         # All other strategies that inherit this are not restricted by age as
         # the age restriction is used to allow other strategies to be observed.
         if type(self) is StrategyNone:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/osclib/select_command.py 
new/openSUSE-release-tools-20181108.4293b6b/osclib/select_command.py
--- old/openSUSE-release-tools-20181025.5558473/osclib/select_command.py        
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/osclib/select_command.py        
2018-11-08 17:10:04.000000000 +0100
@@ -75,7 +75,7 @@
             # 'select' command becomes a 'move'
             # supersede = (new_rq, package, project)
             fprj = self.api.packages_staged[staged_requests[request]]['prj'] 
if not supersede else supersede[2]
-            if filter_from != fprj:
+            if filter_from and filter_from != fprj:
                 print('Ignoring "{}" in "{}" since not in 
"{}"'.format(request, fprj, filter_from))
                 return True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/rabbit-openqa.py 
new/openSUSE-release-tools-20181108.4293b6b/rabbit-openqa.py
--- old/openSUSE-release-tools-20181025.5558473/rabbit-openqa.py        
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/rabbit-openqa.py        
2018-11-08 17:10:04.000000000 +0100
@@ -32,6 +32,7 @@
         self.api = StagingAPI(apiurl, name)
         self.staging_projects = dict()
         self.listener = None
+        self.logger = logging.getLogger(__name__)
         self.replace_string = self.api.attribute_value_load('OpenQAMapping')
 
     def init(self):
@@ -104,7 +105,7 @@
             taken_names[name] = id
 
         for info in openqa_infos.values():
-            xml = self.openqa_check_xml(info['url'], info['state'], 
info['name'])
+            xml = self.openqa_check_xml(info['url'], info['state'], 'openqa:' 
+ info['name'])
             try:
                 http_POST(url, data=xml)
             except HTTPError:
@@ -262,11 +263,8 @@
     for entry in root.findall('project'):
         l.add(Project(entry.get('name')))
 
-    while True:
-        try:
-            l.run()
-        except KeyboardInterrupt:
-            l.stop()
-        except (HTTPError, URLError, ConnectionError, SSLError):
-            # OBS/openQA hickup
-            sleep(10)
+    try:
+        l.run()
+    except KeyboardInterrupt:
+        l.stop()
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/requirements.txt 
new/openSUSE-release-tools-20181108.4293b6b/requirements.txt
--- old/openSUSE-release-tools-20181025.5558473/requirements.txt        
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/requirements.txt        
2018-11-08 17:10:04.000000000 +0100
@@ -9,6 +9,6 @@
 git+https://github.com/openSUSE/osc
 
 # Dependencies for testing
-httpretty
+httpretty<0.9.6
 mock
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/systemd/osrt-rabbit-openqa.service 
new/openSUSE-release-tools-20181108.4293b6b/systemd/osrt-rabbit-openqa.service
--- 
old/openSUSE-release-tools-20181025.5558473/systemd/osrt-rabbit-openqa.service  
    2018-10-25 20:44:10.000000000 +0200
+++ 
new/openSUSE-release-tools-20181108.4293b6b/systemd/osrt-rabbit-openqa.service  
    2018-11-08 17:10:04.000000000 +0100
@@ -4,6 +4,7 @@
 [Service]
 User=osrt-rabbit-openqa
 ExecStart=/usr/bin/osrt-rabbit-openqa
+Restart=on-failure
 
 [Install]
 WantedBy=multi-user.target
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/totest-manager.py 
new/openSUSE-release-tools-20181108.4293b6b/totest-manager.py
--- old/openSUSE-release-tools-20181025.5558473/totest-manager.py       
2018-10-25 20:44:10.000000000 +0200
+++ new/openSUSE-release-tools-20181108.4293b6b/totest-manager.py       
2018-11-08 17:10:04.000000000 +0100
@@ -399,12 +399,18 @@
         url = self.api.makeurl(['build', project, '_result'], query)
         f = self.api.retried_GET(url)
         root = ET.parse(f).getroot()
-        for repo in root.findall('result'):
-            status = repo.find('status')
-            if status.get('code') != 'succeeded':
-                logger.info(
-                    '%s %s %s %s -> %s' % (project, package, repository, arch, 
status.get('code')))
-                return False
+        succeeded = root.findall('result/status[@code="succeeded"]')
+        # [@code!='succeeded'] is not supported by ET
+        failed = [status for status in root.findall("result/status") if 
status.get('code') != 'succeeded']
+
+        if len(failed) > 0:
+            logger.info(
+                '%s %s %s %s -> %s' % (project, package, repository, arch, 
failed[0].get('code')))
+            return False
+
+        if len(succeeded) == 0:
+            logger.info('No results for %s %s %s %s' % (project, package, 
repository, arch))
+            return False
 
         maxsize = self.maxsize_for_package(package)
         if not maxsize:
@@ -436,15 +442,14 @@
             if not self.package_ok(self.project, product, self.product_repo, 
self.product_arch):
                 return False
 
-            if len(self.livecd_products):
-
-                if not self.all_repos_done('%s:Live' % self.project):
-                    return False
+        if len(self.livecd_products):
+            if not self.all_repos_done('%s:Live' % self.project):
+                return False
 
-                for arch in self.livecd_archs:
-                    for product in self.livecd_products:
-                        if not self.package_ok('%s:Live' % self.project, 
product, self.livecd_repo, arch):
-                            return False
+            for arch in self.livecd_archs:
+                for product in self.livecd_products:
+                    if not self.package_ok('%s:Live' % self.project, product, 
self.livecd_repo, arch):
+                        return False
 
         return True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/userscript/README.md 
new/openSUSE-release-tools-20181108.4293b6b/userscript/README.md
--- old/openSUSE-release-tools-20181025.5558473/userscript/README.md    
1970-01-01 01:00:00.000000000 +0100
+++ new/openSUSE-release-tools-20181108.4293b6b/userscript/README.md    
2018-11-08 17:10:04.000000000 +0100
@@ -0,0 +1,5 @@
+# User Scripts
+
+The scripts may be installed in one's browser (using Greasemonkey or 
Tampermonkey) to provide additional features using OBS via the web.
+
+- [Staging Move 
Drag-n-Drop](https://github.com/openSUSE/openSUSE-release-tools/raw/master/userscript/staging-move-drag-n-drop.user.js)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/openSUSE-release-tools-20181025.5558473/userscript/staging-move-drag-n-drop.user.js
 
new/openSUSE-release-tools-20181108.4293b6b/userscript/staging-move-drag-n-drop.user.js
--- 
old/openSUSE-release-tools-20181025.5558473/userscript/staging-move-drag-n-drop.user.js
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/openSUSE-release-tools-20181108.4293b6b/userscript/staging-move-drag-n-drop.user.js
     2018-11-08 17:10:04.000000000 +0100
@@ -0,0 +1,620 @@
+// ==UserScript==
+// @name         OSRT Staging Move Drag-n-Drop
+// @namespace    openSUSE/openSUSE-release-tools
+// @version      0.1.0
+// @description  Provide staging request moving interface on staging dashboard.
+// @author       Jimmy Berry
+// @match        */project/staging_projects/*
+// @require      https://code.jquery.com/jquery-3.3.1.min.js
+// @require      
https://raw.githubusercontent.com/p34eu/selectables/master/selectables.js
+// @grant        none
+// ==/UserScript==
+
+// Uses a combination of two sources:
+// - https://www.sitepoint.com/accessible-drag-drop/ (modified slightly)
+// - https://github.com/p34eu/selectables (used directly with abuse of 
modifier key option)
+
+(function()
+{
+    // Add explanation of trigger shortcut to legend box.
+    var explanation = document.createElement('div');
+    explanation.id = 'osrt-explanation';
+    explanation.innerText = 'press ctrl+m to move requests';
+    document.querySelector('#legends').appendChild(explanation);
+
+    window.onkeyup = function(e) {
+        if (e.keyCode == 77 && e.ctrlKey) {
+            initMoveInterface();
+        }
+    }
+
+    // Include CSS immediately for explanation.
+    $('head').append(`<style>
+#osrt-explanation
+{
+    padding: 10px;
+    background-color: #d9b200;
+    color: white;
+}
+
+#osrt-summary
+{
+    position: sticky;
+    z-index: 10000;
+    bottom: 0;
+    left: 0;
+    width: 95%;
+    height: 100px;
+    padding: 10px;
+    background-color: black;
+    color: #18f018;
+    white-space: pre;
+    overflow: scroll;
+}
+
+/* drop target state */
+[data-draggable="target"][aria-dropeffect="move"]
+{
+    border-color: #68b;
+}
+
+[data-draggable="target"][aria-dropeffect="move"]:focus,
+[data-draggable="target"][aria-dropeffect="move"].dragover
+{
+    box-shadow:0 0 0 1px #fff, 0 0 0 3px #68b;
+}
+
+[data-draggable="item"]:focus
+{
+    box-shadow: 0 0 0 2px #68b, inset 0 0 0 1px #ddd;
+}
+
+[data-draggable="item"][aria-grabbed="true"],
+.color-legend .selected
+{
+    background: #8ad;
+    color: #fff;
+}
+
+.color-legend .moved,
+.osrt-moved
+{
+    background: repeating-linear-gradient(
+        45deg,
+        #606dbc,
+        #606dbc 10px,
+        #465298 10px,
+        #465298 20px
+    );
+}
+</style>`);
+
+})();
+
+var initMoveInterface = function(){
+    //exclude older browsers by the features we need them to support
+    //and legacy opera explicitly so we don't waste time on a dead browser
+    if
+    (
+        !document.querySelectorAll
+        ||
+        !('draggable' in document.createElement('span'))
+        ||
+        window.opera
+    )
+    { return; }
+
+    // Update explanation text and add new legend entries.
+    function addLegend(type)
+    {
+        var listItem = document.createElement('li');
+        var span = document.createElement('span');
+        span.classList.add(type.toLowerCase());
+        listItem.appendChild(span);
+        listItem.appendChild(document.createTextNode(type));
+        document.querySelector('ul.color-legend').appendChild(listItem);
+    }
+
+    addLegend('Moved');
+    addLegend('Selected');
+
+    document.querySelector('#osrt-explanation').innerText = 'move mode 
activated: drag box around requests or ctrl/shift+click requests to select and 
drag a request to another staging.';
+
+    // @resource will not work since served without proper MIME type.
+    
$.get('https://raw.githubusercontent.com/p34eu/selectables/master/selectables.css',
 function(data, status) {
+        $('head').append('<style>' + data + '</style>');
+    });
+
+    // Mark the drag targets and draggable items.
+    // Preferable to use the tr element as target, but mouse events not 
handled properly.
+    // Avoid making expand/collapse links selectable and avoid forcing them to 
be expanded.
+    // The pointer-events changes only seem to work properly from script.
+    $('table.staging-dashboard td').attr('data-draggable', 'target');
+    $('table.staging-dashboard ul.packages-list 
li.request:not(:has(a.staging_expand, 
a.staging_collapse))').attr('data-draggable', 'item').css('pointer-events', 
'all');
+
+    // Disable mouse events on the request links as that makes it nearly 
impossible to drag them.
+    $('table.staging-dashboard ul.packages-list 
li.request:not(:has(a.staging_expand, a.staging_collapse)) 
a').css('pointer-events', 'none');
+
+    // Configure selectables to play nice with drag-n-drop code.
+    new Selectables({
+        elements: 'ul.packages-list li[data-draggable="item"]',
+        zone: 'body',
+        start: function (e) {
+            e.osrtContinue = (e.target.getAttribute('data-draggable') != 
'item' &&
+                              e.target.tagName != 'A' &&
+                              e.target.tagName != 'LABEL' &&
+                              e.target.id != 'osrt-summary');
+        },
+        // Abuse key option by setting the value in start callback whic is run
+        // first and the value determines if drag selection is started.
+        key: 'osrtContinue',
+        onSelect: function (e) {
+            addSelection(e);
+        },
+        onDeselect: function (e) {
+            removeSelection(e);
+        }
+    });
+
+    function getStaging(item)
+    {
+        var parent;
+        if (item.tagName == 'TD') {
+            parent = item.parentElement;
+        } else {
+            parent = item.parentElement.parentElement.parentElement;
+        }
+        if (item.parentElement.classList.contains('staging_collapsible')) {
+            // An additional layer since in hidden container.
+            parent = parent.parentElement;
+        }
+        return parent.querySelector('div.letter a').innerText;
+    }
+
+    function updateSummary()
+    {
+        var summaryElement = document.querySelector('div#osrt-summary');
+        if (!summaryElement) {
+            summaryElement = document.createElement('div');
+            summaryElement.id = 'osrt-summary';
+            document.body.appendChild(summaryElement);
+        }
+
+        var elements = document.querySelectorAll('.osrt-moved');
+        var summary = {};
+        var staging;
+        for (var i = 0; i < elements.length; i++) {
+            staging = getStaging(elements[i]);
+            if (!(staging in summary)) {
+                summary[staging] = [];
+            }
+            summary[staging].push(elements[i].children[0].innerText.trim());
+        }
+
+        var summaryText = '';
+        var pathParts = window.location.pathname.split('/');
+        var project = pathParts[pathParts.length - 1];
+        for (var key in summary) {
+            staging = key;
+            if (!isNaN(key)) {
+                staging = 'adi:' + key;
+            }
+            summaryText += 'osc staging -p ' + project + ' select --move ' + 
staging + ' ' + summary[key].join(' ') + "\n";
+        }
+
+        summaryElement.innerText = summaryText;
+    }
+
+    //get the collection of draggable targets and add their draggable attribute
+    for(var
+        targets = document.querySelectorAll('[data-draggable="target"]'),
+        len = targets.length,
+        i = 0; i < len; i ++)
+    {
+        targets[i].setAttribute('aria-dropeffect', 'none');
+    }
+
+    //get the collection of draggable items and add their draggable attributes
+    for(var
+        items = document.querySelectorAll('[data-draggable="item"]'),
+        len = items.length,
+        i = 0; i < len; i ++)
+    {
+        items[i].setAttribute('draggable', 'true');
+        items[i].setAttribute('aria-grabbed', 'false');
+        items[i].setAttribute('tabindex', '0');
+
+        // OSRT modification: keep track of original staging.
+        items[i].setAttribute('data-staging-origin', getStaging(items[i]));
+    }
+
+    //dictionary for storing the selections data
+    //comprising an array of the currently selected items
+    //a reference to the selected items' owning container
+    //and a refernce to the current drop target container
+    var selections =
+    {
+        items      : [],
+        owner      : null,
+        droptarget : null
+    };
+
+    //function for selecting an item
+    function addSelection(item)
+    {
+        //if the owner reference is still null, set it to this item's parent
+        //so that further selection is only allowed within the same container
+        if(!selections.owner)
+        {
+            selections.owner = item.parentNode;
+        }
+
+        //or if that's already happened then compare it with this item's parent
+        //and if they're not the same container, return to prevent selection
+        else if(selections.owner != item.parentNode)
+        {
+            return;
+        }
+
+        //set this item's grabbed state
+        item.setAttribute('aria-grabbed', 'true');
+
+        //add it to the items array
+        selections.items.push(item);
+    }
+
+    //function for unselecting an item
+    function removeSelection(item)
+    {
+        //reset this item's grabbed state
+        item.setAttribute('aria-grabbed', 'false');
+
+        //then find and remove this item from the existing items array
+        for(var len = selections.items.length, i = 0; i < len; i ++)
+        {
+            if(selections.items[i] == item)
+            {
+                selections.items.splice(i, 1);
+                break;
+            }
+        }
+    }
+
+    //function for resetting all selections
+    function clearSelections()
+    {
+        //if we have any selected items
+        if(selections.items.length)
+        {
+            //reset the owner reference
+            selections.owner = null;
+
+            //reset the grabbed state on every selected item
+            for(var len = selections.items.length, i = 0; i < len; i ++)
+            {
+                selections.items[i].setAttribute('aria-grabbed', 'false');
+            }
+
+            //then reset the items array
+            selections.items = [];
+        }
+    }
+
+    //shorctut function for testing whether a selection modifier is pressed
+    function hasModifier(e)
+    {
+        return (e.ctrlKey || e.metaKey || e.shiftKey);
+    }
+
+    //function for applying dropeffect to the target containers
+    function addDropeffects()
+    {
+        //apply aria-dropeffect and tabindex to all targets apart from the 
owner
+        for(var len = targets.length, i = 0; i < len; i ++)
+        {
+            if
+            (
+                targets[i] != selections.owner
+                &&
+                targets[i].getAttribute('aria-dropeffect') == 'none'
+            )
+            {
+                targets[i].setAttribute('aria-dropeffect', 'move');
+                targets[i].setAttribute('tabindex', '0');
+            }
+        }
+
+        //remove aria-grabbed and tabindex from all items inside those 
containers
+        for(var len = items.length, i = 0; i < len; i ++)
+        {
+            if
+            (
+                items[i].parentNode != selections.owner
+                &&
+                items[i].getAttribute('aria-grabbed')
+            )
+            {
+                items[i].removeAttribute('aria-grabbed');
+                items[i].removeAttribute('tabindex');
+            }
+        }
+    }
+
+    //function for removing dropeffect from the target containers
+    function clearDropeffects()
+    {
+        //if we have any selected items
+        if(selections.items.length)
+        {
+            //reset aria-dropeffect and remove tabindex from all targets
+            for(var len = targets.length, i = 0; i < len; i ++)
+            {
+                if(targets[i].getAttribute('aria-dropeffect') != 'none')
+                {
+                    targets[i].setAttribute('aria-dropeffect', 'none');
+                    targets[i].removeAttribute('tabindex');
+                }
+            }
+
+            //restore aria-grabbed and tabindex to all selectable items
+            //without changing the grabbed value of any existing selected items
+            for(var len = items.length, i = 0; i < len; i ++)
+            {
+                if(!items[i].getAttribute('aria-grabbed'))
+                {
+                    items[i].setAttribute('aria-grabbed', 'false');
+                    items[i].setAttribute('tabindex', '0');
+                }
+                else if(items[i].getAttribute('aria-grabbed') == 'true')
+                {
+                    items[i].setAttribute('tabindex', '0');
+                }
+            }
+        }
+    }
+
+    //shortcut function for identifying an event element's target container
+    function getContainer(element)
+    {
+        do
+        {
+            if(element.nodeType == 1 && 
element.getAttribute('aria-dropeffect'))
+            {
+                return element;
+            }
+        }
+        while(element = element.parentNode);
+
+        return null;
+    }
+
+    //mousedown event to implement single selection
+    document.addEventListener('mousedown', function(e)
+    {
+        //if the element is a draggable item
+        if(e.target.getAttribute('draggable'))
+        {
+            //clear dropeffect from the target containers
+            clearDropeffects();
+
+            //if the multiple selection modifier is not pressed
+            //and the item's grabbed state is currently false
+            if
+            (
+                !hasModifier(e)
+                &&
+                e.target.getAttribute('aria-grabbed') == 'false'
+            )
+            {
+                //clear all existing selections
+                clearSelections();
+
+                //then add this new selection
+                addSelection(e.target);
+            }
+        }
+
+        //else [if the element is anything else]
+        //and the selection modifier is not pressed
+        else if(!hasModifier(e))
+        {
+            //clear dropeffect from the target containers
+            clearDropeffects();
+
+            //clear all existing selections
+            clearSelections();
+        }
+
+        //else [if the element is anything else and the modifier is pressed]
+        else
+        {
+            //clear dropeffect from the target containers
+            clearDropeffects();
+        }
+
+    }, false);
+
+    //mouseup event to implement multiple selection
+    document.addEventListener('mouseup', function(e)
+    {
+        //if the element is a draggable item
+        //and the multipler selection modifier is pressed
+        if(e.target.getAttribute('draggable') && hasModifier(e))
+        {
+            //if the item's grabbed state is currently true
+            if(e.target.getAttribute('aria-grabbed') == 'true')
+            {
+                //unselect this item
+                removeSelection(e.target);
+
+                //if that was the only selected item
+                //then reset the owner container reference
+                if(!selections.items.length)
+                {
+                    selections.owner = null;
+                }
+            }
+
+            //else [if the item's grabbed state is false]
+            else
+            {
+                //add this additional selection
+                addSelection(e.target);
+            }
+        }
+
+    }, false);
+
+    //dragstart event to initiate mouse dragging
+    document.addEventListener('dragstart', function(e)
+    {
+        //if the element's parent is not the owner, then block this event
+        if(selections.owner != e.target.parentNode)
+        {
+            e.preventDefault();
+            return;
+        }
+
+        //[else] if the multiple selection modifier is pressed
+        //and the item's grabbed state is currently false
+        if
+        (
+            hasModifier(e)
+            &&
+            e.target.getAttribute('aria-grabbed') == 'false'
+        )
+        {
+            //add this additional selection
+            addSelection(e.target);
+        }
+
+        //we don't need the transfer data, but we have to define something
+        //otherwise the drop action won't work at all in firefox
+        //most browsers support the proper mime-type syntax, eg. "text/plain"
+        //but we have to use this incorrect syntax for the benefit of IE10+
+        e.dataTransfer.setData('text', '');
+
+        //apply dropeffect to the target containers
+        addDropeffects();
+
+    }, false);
+
+    //related variable is needed to maintain a reference to the
+    //dragleave's relatedTarget, since it doesn't have e.relatedTarget
+    var related = null;
+
+    //dragenter event to set that variable
+    document.addEventListener('dragenter', function(e)
+    {
+        related = e.target;
+
+    }, false);
+
+    //dragleave event to maintain target highlighting using that variable
+    document.addEventListener('dragleave', function(e)
+    {
+        //get a drop target reference from the relatedTarget
+        var droptarget = getContainer(related);
+
+        //if the target is the owner then it's not a valid drop target
+        if(droptarget == selections.owner)
+        {
+            droptarget = null;
+        }
+
+        //if the drop target is different from the last stored reference
+        //(or we have one of those references but not the other one)
+        if(droptarget != selections.droptarget)
+        {
+            //if we have a saved reference, clear its existing dragover class
+            if(selections.droptarget)
+            {
+                selections.droptarget.className =
+                    selections.droptarget.className.replace(/ dragover/g, '');
+            }
+
+            //apply the dragover class to the new drop target reference
+            if(droptarget)
+            {
+                droptarget.className += ' dragover';
+            }
+
+            //then save that reference for next time
+            selections.droptarget = droptarget;
+        }
+
+    }, false);
+
+    //dragover event to allow the drag by preventing its default
+    document.addEventListener('dragover', function(e)
+    {
+        //if we have any selected items, allow them to be dragged
+        if(selections.items.length)
+        {
+            e.preventDefault();
+        }
+
+    }, false);
+
+    //dragend event to implement items being validly dropped into targets,
+    //or invalidly dropped elsewhere, and to clean-up the interface either way
+    document.addEventListener('dragend', function(e)
+    {
+        //if we have a valid drop target reference
+        //(which implies that we have some selected items)
+        if(selections.droptarget)
+        {
+            // OSRT modification: only move if location is changing.
+            if (getStaging(selections.droptarget) == 
getStaging(selections.items[0])) {
+                e.preventDefault();
+                return;
+            }
+
+            // OSRT modification: place requests back in package list.
+            var target = 
selections.droptarget.parentElement.querySelector('ul.packages-list');
+
+            //append the selected items to the end of the target container
+            for(var len = selections.items.length, i = 0; i < len; i ++)
+            {
+                // OSRT modification: place in package list and determine if 
moved from origin.
+                // selections.droptarget.appendChild(selections.items[i]);
+                target.appendChild(selections.items[i]);
+                if (getStaging(selections.items[i]) != 
selections.items[i].getAttribute('data-staging-origin'))
+                {
+                    selections.items[i].classList.add('osrt-moved');
+                }
+                else {
+                    selections.items[i].classList.remove('osrt-moved');
+                }
+            }
+
+            // OSRT modification: after drag update overall summary of moves.
+            updateSummary();
+
+            //prevent default to allow the action
+            e.preventDefault();
+        }
+
+        //if we have any selected items
+        if(selections.items.length)
+        {
+            //clear dropeffect from the target containers
+            clearDropeffects();
+
+            //if we have a valid drop target reference
+            if(selections.droptarget)
+            {
+                //reset the selections array
+                clearSelections();
+
+                //reset the target's dragover class
+                selections.droptarget.className =
+                    selections.droptarget.className.replace(/ dragover/g, '');
+
+                //reset the target reference
+                selections.droptarget = null;
+            }
+        }
+
+    }, false);
+};

++++++ openSUSE-release-tools.obsinfo ++++++
--- /var/tmp/diff_new_pack.ziblMR/_old  2018-11-09 07:56:40.311556688 +0100
+++ /var/tmp/diff_new_pack.ziblMR/_new  2018-11-09 07:56:40.311556688 +0100
@@ -1,5 +1,5 @@
 name: openSUSE-release-tools
-version: 20181025.5558473
-mtime: 1540493050
-commit: 55584739996331a3660216cb8ea4bcadca3bc60a
+version: 20181108.4293b6b
+mtime: 1541693404
+commit: 4293b6bce15bd3c6c0356d90ae80360a08d9b059
 


Reply via email to