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