Hello community, here is the log from the commit of package osc for openSUSE:Factory checked in at 2017-09-23 21:36:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/osc (Old) and /work/SRC/openSUSE:Factory/.osc.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "osc" Sat Sep 23 21:36:21 2017 rev:121 rq:528240 version:0.160.0 Changes: -------- --- /work/SRC/openSUSE:Factory/osc/osc.changes 2017-08-23 11:54:11.526968365 +0200 +++ /work/SRC/openSUSE:Factory/.osc.new/osc.changes 2017-09-23 21:36:30.503068050 +0200 @@ -1,0 +2,12 @@ +Fri Sep 22 07:07:33 UTC 2017 - [email protected] + +- 0.160 + - support fissile build type + - Container support for the package cache + - Remove all untracked files during "osc clean" + - Support the commit of a deleted, but non-existent package + - triggerreason --multibuild-package option + - improved status display + - improved request listing filters + +------------------------------------------------------------------- Old: ---- osc-0.159.0.tar.gz New: ---- osc-0.160.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ osc.spec ++++++ --- /var/tmp/diff_new_pack.Q6hU6I/_old 2017-09-23 21:36:35.810321662 +0200 +++ /var/tmp/diff_new_pack.Q6hU6I/_new 2017-09-23 21:36:35.814321098 +0200 @@ -16,12 +16,12 @@ # -%define version_unconverted 0.159.0 +%define version_unconverted 0.160.0 %define osc_plugin_dir %{_prefix}/lib/osc-plugins %define macros_file macros.osc Name: osc -Version: 0.159.0 +Version: 0.160.0 Release: 0 Summary: Open Build Service Commander License: GPL-2.0+ ++++++ PKGBUILD ++++++ --- /var/tmp/diff_new_pack.Q6hU6I/_old 2017-09-23 21:36:35.846316599 +0200 +++ /var/tmp/diff_new_pack.Q6hU6I/_new 2017-09-23 21:36:35.846316599 +0200 @@ -1,5 +1,5 @@ pkgname=osc -pkgver=0.159.0 +pkgver=0.160.0 pkgrel=0 pkgdesc="Open Build Service client" arch=('i686' 'x86_64') ++++++ _service ++++++ --- /var/tmp/diff_new_pack.Q6hU6I/_old 2017-09-23 21:36:35.866313787 +0200 +++ /var/tmp/diff_new_pack.Q6hU6I/_new 2017-09-23 21:36:35.866313787 +0200 @@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> - <param name="version">0.159.0</param> - <param name="revision">0.159.0</param> + <param name="version">0.160.0</param> + <param name="revision">0.160.0</param> <param name="url">git://github.com/openSUSE/osc.git</param> <param name="scm">git</param> </service> ++++++ debian.changelog ++++++ --- /var/tmp/diff_new_pack.Q6hU6I/_old 2017-09-23 21:36:35.906308162 +0200 +++ /var/tmp/diff_new_pack.Q6hU6I/_new 2017-09-23 21:36:35.906308162 +0200 @@ -1,4 +1,4 @@ -osc (0.159.0-0) unstable; urgency=low +osc (0.160.0-0) unstable; urgency=low - Install bash completion -- Nick Brown <[email protected]> Wed, 26 Oct 2016 10:00:00 +0200 ++++++ osc-0.159.0.tar.gz -> osc-0.160.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/NEWS new/osc-0.160.0/NEWS --- old/osc-0.159.0/NEWS 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/NEWS 2017-09-22 09:06:18.000000000 +0200 @@ -1,3 +1,12 @@ +0.160 + - support fissile build type + - Container support for the package cache + - Remove all untracked files during "osc clean" + - Support the commit of a deleted, but non-existent package + - triggerreason --multibuild-package option + - improved status display + - improved request listing filters + 0.159 - "osc buildhistory": show build duration - Support builds using native Docker build descriptions diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/osc/build.py new/osc-0.160.0/osc/build.py --- old/osc-0.159.0/osc/build.py 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/osc/build.py 2017-09-22 09:06:18.000000000 +0200 @@ -349,6 +349,11 @@ '-type', 'f'], stdout=subprocess.PIPE).stdout.read().strip() s_built = '' + elif buildtype == 'fissile': + b_built = subprocess.Popen(['find', os.path.join(pacdir, 'FISSILE'), + '-type', 'f'], + stdout=subprocess.PIPE).stdout.read().strip() + s_built = '' elif buildtype == 'dsc' or buildtype == 'collax': b_built = subprocess.Popen(['find', os.path.join(pacdir, 'DEBS'), '-name', '*.deb'], @@ -520,7 +525,9 @@ build_type = 'snapcraft' if os.path.basename(build_descr) == 'Dockerfile': build_type = 'docker' - if build_type not in ['spec', 'dsc', 'kiwi', 'arch', 'collax', 'livebuild', 'snapcraft', 'appimage', 'docker']: + if os.path.basename(build_descr) == 'fissile.yml': + build_type = 'fissile' + if build_type not in ['spec', 'dsc', 'kiwi', 'arch', 'collax', 'livebuild', 'snapcraft', 'appimage', 'docker', 'fissile']: raise oscerr.WrongArgs( 'Unknown build type: \'%s\'. Build description should end in .spec, .dsc, .kiwi, or .livebuild. Or being named PKGBUILD, build.collax, appimage.yml, snapcraft.yaml or Dockerfile' \ % build_type) @@ -961,8 +968,8 @@ if old_pkg_dir != None: buildargs.append('--oldpackages=%s' % old_pkg_dir) - # Make packages from buildinfo available as repos for kiwi/docker - if build_type == 'kiwi' or build_type == 'docker': + # Make packages from buildinfo available as repos for kiwi/docker/fissile + if build_type == 'kiwi' or build_type == 'docker' or build_type == 'fissile': if os.path.exists('repos'): shutil.rmtree('repos') if os.path.exists('containers'): @@ -1105,7 +1112,7 @@ print('Writing build configuration') - if build_type == 'kiwi' or build_type == 'docker': + if build_type == 'kiwi' or build_type == 'docker' or build_type == 'fissile': rpmlist = [ '%s %s\n' % (i.name, i.fullfilename) for i in bi.deps if not i.noinstall ] else: rpmlist = [ '%s %s\n' % (i.name, i.fullfilename) for i in bi.deps ] @@ -1121,10 +1128,11 @@ rpmlist.append('preinstall: ' + ' '.join(bi.preinstall_list) + '\n') rpmlist.append('vminstall: ' + ' '.join(bi.vminstall_list) + '\n') rpmlist.append('runscripts: ' + ' '.join(bi.runscripts_list) + '\n') - if build_type != 'kiwi' and build_type != 'docker' and bi.noinstall_list: - rpmlist.append('noinstall: ' + ' '.join(bi.noinstall_list) + '\n') - if build_type != 'kiwi' and build_type != 'docker' and bi.installonly_list: - rpmlist.append('installonly: ' + ' '.join(bi.installonly_list) + '\n') + if build_type != 'kiwi' and build_type != 'docker' and build_type != 'fissile': + if bi.noinstall_list: + rpmlist.append('noinstall: ' + ' '.join(bi.noinstall_list) + '\n') + if bi.installonly_list: + rpmlist.append('installonly: ' + ' '.join(bi.installonly_list) + '\n') rpmlist_file = NamedTemporaryFile(prefix='rpmlist.') rpmlist_filename = rpmlist_file.name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/osc/commandline.py new/osc-0.160.0/osc/commandline.py --- old/osc-0.159.0/osc/commandline.py 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/osc/commandline.py 2017-09-22 09:06:18.000000000 +0200 @@ -9,6 +9,7 @@ from . import conf from . import oscerr import sys +import signal import time import imp import inspect @@ -773,6 +774,7 @@ prjconf denotes the (build) configuration of a project. pkg denotes metadata of a buildservice package. user denotes the metadata of a user. + group denotes the metadata of a group. pattern denotes installation patterns defined for a project. To list patterns, use 'osc meta pattern PRJ'. An additional argument @@ -796,9 +798,9 @@ Usage: osc meta <prj|prjconf> [-r|--revision REV] ARGS... - osc meta <prj|pkg|prjconf|user|pattern> ARGS... - osc meta <prj|pkg|prjconf|user|pattern> [-m|--message TEXT] -e|--edit ARGS... - osc meta <prj|pkg|prjconf|user|pattern> [-m|--message TEXT] -F|--file ARGS... + osc meta <prj|pkg|prjconf|user|group|pattern> ARGS... + osc meta <prj|pkg|prjconf|user|group|pattern> [-m|--message TEXT] -e|--edit ARGS... + osc meta <prj|pkg|prjconf|user|group|pattern> [-m|--message TEXT] -F|--file ARGS... osc meta pattern --delete PRJ PATTERN osc meta attribute PRJ [PKG [SUBPACKAGE]] [--attribute ATTRIBUTE] [--create|--delete|--set [value_list]] ${cmd_option_list} @@ -876,6 +878,8 @@ attributepath.append('_attribute') elif cmd == 'user': user = args[0] + elif cmd == 'group': + group = args[0] elif cmd == 'pattern': project = args[0] if len(args) > 1: @@ -904,6 +908,10 @@ r = get_user_meta(apiurl, user) if r: sys.stdout.write(''.join(r)) + elif cmd == 'group': + r = get_group_meta(apiurl, group) + if r: + sys.stdout.write(''.join(r)) elif cmd == 'pattern': if pattern: r = show_pattern_meta(apiurl, project, pattern) @@ -948,6 +956,12 @@ path_args=(quote_plus(user)), apiurl=apiurl, template_args=({'user': user})) + elif cmd == 'group': + edit_meta(metatype='group', + edit=True, + path_args=(quote_plus(group)), + apiurl=apiurl, + template_args=({'group': group})) elif cmd == 'pattern': edit_meta(metatype='pattern', edit=True, @@ -1011,6 +1025,12 @@ edit=opts.edit, apiurl=apiurl, path_args=(quote_plus(user))) + elif cmd == 'group': + edit_meta(metatype='group', + data=f, + edit=opts.edit, + apiurl=apiurl, + path_args=(quote_plus(group))) elif cmd == 'pattern': edit_meta(metatype='pattern', data=f, @@ -1208,7 +1228,7 @@ sr_ids.append(result) else: s = """<action type="submit"> <source project="%s" package="%s" /> <target project="%s" package="%s" /> %s </action>""" % \ - (project, p, t, p, options_block) + (project, p, target_project, p, options_block) actionxml += s if actionxml != "": @@ -1639,7 +1659,7 @@ actionxml = """ <action type="add_role"> <target project="%s" package="%s" /> <group name="%s" role="%s" /> </action> """ % \ (project, package, group, role) - if get_group(apiurl, group) == None: + if get_group_meta(apiurl, group) == None: raise oscerr.WrongArgs('osc: an error occured.') return actionxml @@ -1662,7 +1682,7 @@ group = user.replace('group:', '') actionxml = """ <action type="set_bugowner"> <target project="%s" %s /> <group name="%s" /> </action> """ % \ (project, package, group) - if get_group(apiurl, group) == None: + if get_group_meta(apiurl, group) == None: raise oscerr.WrongArgs('osc: an error occured.') else: actionxml = """ <action type="set_bugowner"> <target project="%s" %s /> <person name="%s" /> </action> """ % \ @@ -1993,7 +2013,7 @@ @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.option('-t', '--type', metavar='TYPE', - help='limit to requests which contain a given action type (submit/delete/change_devel)') + help='limit to requests which contain a given action type (submit/delete/change_devel/add_role/set_bugowner/maintenance_incident/maintenance_release)') @cmdln.option('-a', '--all', action='store_true', help='all states. Same as\'-s all\'') @cmdln.option('-f', '--force', action='store_true', @@ -2028,6 +2048,8 @@ help='exclude target project from request list') @cmdln.option('--involved-projects', action='store_true', help='show all requests for project/packages where USER is involved') + @cmdln.option('--target-package-filter', metavar='TARGET_PACKAGE_FILTER', + help='only list requests for the packages matching the package filter. A (python) regular expression is expected.') @cmdln.option('--source-buildstatus', action='store_true', help='print the buildstatus of the source package (only works with "show" and the interactive review)') @cmdln.alias("rq") @@ -2261,7 +2283,8 @@ if subcmd == 'review': # FIXME: do the review list for the user and for all groups he belong to - results = get_review_list(apiurl, project, package, who, opts.group, opts.project, opts.package, state_list) + results = get_review_list(apiurl, project, package, who, opts.group, opts.project, opts.package, state_list, + opts.type) else: if opts.involved_projects: who = who or conf.get_apiurl_usr(apiurl) @@ -2311,17 +2334,29 @@ ## Workaround: fetch all, and filter on client side. ## FIXME: date filtering should become implemented on server side + + + if opts.target_package_filter: + filter_pattern = re.compile(opts.target_package_filter) for result in results: - if days == 0 or result.state.when > since or result.state.name == 'new': - if (opts.interactive or conf.config['request_show_interactive']) and not opts.non_interactive: - ignore_reviews = subcmd != 'review' - request_interactive_review(apiurl, result, group=opts.group, - ignore_reviews=ignore_reviews, - source_buildstatus=source_buildstatus) + filtered = False + for action in result.actions: + if action.type == 'group' or not opts.target_package_filter: + continue + if not filter_pattern.match(action.tgt_package): + filtered = True + break + if not filtered: + if days == 0 or result.state.when > since or result.state.name == 'new': + if (opts.interactive or conf.config['request_show_interactive']) and not opts.non_interactive: + ignore_reviews = subcmd != 'review' + request_interactive_review(apiurl, result, group=opts.group, + ignore_reviews=ignore_reviews, + source_buildstatus=source_buildstatus) + else: + print(result.list_view(), '\n') else: - print(result.list_view(), '\n') - else: - skipped += 1 + skipped += 1 if skipped: print("There are %d requests older than %s days.\n" % (skipped, days)) @@ -4620,9 +4655,9 @@ prj.commit(msg=msg, skip_local_service_run=skip_local_service_run, verbose=opts.verbose, can_branch=can_branch) args.remove(arg) - pacs = findpacs(args) + pacs, no_pacs = findpacs(args, fatal=False) - if conf.config['do_package_tracking'] and len(pacs) > 0: + if conf.config['do_package_tracking'] and (pacs or no_pacs): prj_paths = {} single_paths = [] files = {} @@ -4633,15 +4668,33 @@ for pac in pacs: path = os.path.normpath(os.path.join(pac.dir, os.pardir)) if is_project_dir(path): - pac_path = os.path.basename(os.path.normpath(pac.absdir)) - prj_paths.setdefault(path, []).append(pac_path) + # use this path construction for computing "pac_name", + # because it is possible that pac.name != pac_name (e.g. + # for an external package wc) + pac_name = os.path.basename(os.path.normpath(pac.absdir)) + prj_paths.setdefault(path, []).append(pac_name) pac_objs.setdefault(path, []).append(pac) - files[pac_path] = pac.todo + files.setdefault(path, {})[pac_name] = pac.todo else: single_paths.append(pac.dir) if not pac.todo: pac.todo = pac.filenamelist + pac.filenamelist_unvers pac.todo.sort() + for pac in no_pacs: + if os.path.exists(pac): + # fail with an appropriate error message + store_read_apiurl(pac, defaulturl=False) + path = os.path.normpath(os.path.join(pac, os.pardir)) + if is_project_dir(path): + pac_name = os.path.basename(os.path.normpath(os.path.abspath(pac))) + prj_paths.setdefault(path, []).append(pac_name) + pac_objs.setdefault(path, []) + # wrt. the current implementation of Project.commit, this + # actually not needed + files.setdefault(path, {})[pac_name] = [] + else: + # fail with an appropriate error message + store_read_apiurl(pac, defaulturl=False) for prj_path, packages in prj_paths.items(): prj = Project(prj_path) if not msg and not opts.no_message: @@ -4655,7 +4708,8 @@ if repl in('y', 'Y'): can_branch = True - prj.commit(packages, msg=msg, files=files, skip_local_service_run=skip_local_service_run, verbose=opts.verbose, can_branch=can_branch, force=opts.force) + prj_files = files[prj_path] + prj.commit(packages, msg=msg, files=prj_files, skip_local_service_run=skip_local_service_run, verbose=opts.verbose, can_branch=can_branch, force=opts.force) store_unlink_file(prj.absdir, '_commit_msg') for pac in single_paths: p = Package(pac) @@ -4663,6 +4717,9 @@ msg = get_commit_msg(p.absdir, [p]) p.commit(msg, skip_local_service_run=skip_local_service_run, verbose=opts.verbose, force=opts.force) store_unlink_file(p.absdir, '_commit_msg') + elif no_pacs: + # fail with an appropriate error message + store_read_apiurl(no_pacs[0], defaulturl=False) else: for p in pacs: if not p.todo: @@ -5155,6 +5212,27 @@ print("See 'osc help prjresults'.", file=sys.stderr) return 2 + @cmdln.alias('rpmlint') + @cmdln.alias('lint') + def do_rpmlintlog(self, subcmd, opts, *args): + """${cmd_name}: Shows the rpmlint logfile + + Shows the rpmlint logfile to analyse if there are any problems + with the spec file and the built binaries. + + usage: + osc rpmlintlog project package repository arch + """ + apiurl = self.get_api_url() + args = slash_split(args) + + if len(args) == 4: + project, package, repository, arch = args + else: + raise oscerr.WrongArgs('please provide project package repository arch.') + + print(get_rpmlint_log(apiurl, project, package, repository, arch)) + @cmdln.alias('bl') @cmdln.alias('blt') @cmdln.alias('buildlogtail') @@ -5393,6 +5471,8 @@ data = f.read(BUFSIZE) f.close() + @cmdln.option('-M', '--multibuild-package', metavar='MPAC', + help='get triggerreason of the specified multibuild package') @cmdln.alias('tr') def do_triggerreason(self, subcmd, opts, *args): """${cmd_name}: Show reason why a package got triggered to build @@ -5408,8 +5488,8 @@ - rebuild count sync (In case that it is configured to sync release numbers) usage in package or project directory: - osc reason REPOSITORY ARCH - osc reason PROJECT PACKAGE REPOSITORY ARCH + osc triggerreason REPOSITORY ARCH + osc triggerreason PROJECT PACKAGE REPOSITORY ARCH ${cmd_option_list} """ @@ -5438,11 +5518,15 @@ else: raise oscerr.WrongArgs('Too many arguments.') + if opts.multibuild_package: + package = package + ":" + opts.multibuild_package + print(apiurl, project, package, repository, arch) xml = show_package_trigger_reason(apiurl, project, package, repository, arch) root = ET.fromstring(xml) reason = root.find('explain').text - print(reason) + triggertime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(int(root.find('time').text))) + print("%s (at %s)" % (reason, triggertime)) if reason == "meta change": print("changed keys:") for package in root.findall('packagechange'): @@ -5789,7 +5873,7 @@ for subarch in osc.build.can_also_build.get(mainarch): all_archs.append(subarch) for arg in args: - if arg.endswith('.spec') or arg.endswith('.dsc') or arg.endswith('.kiwi') or arg.endswith('.livebuild') or arg == 'PKGBUILD' or arg == 'build.collax' or arg == 'Dockerfile': + if arg.endswith('.spec') or arg.endswith('.dsc') or arg.endswith('.kiwi') or arg.endswith('.livebuild') or arg == 'PKGBUILD' or arg == 'build.collax' or arg == 'Dockerfile' or arg == 'fissile.yml': arg_descr = arg else: if (arg == osc.build.hostarch or arg in all_archs) and arg_arch is None: @@ -5851,7 +5935,7 @@ # reduce(lambda x, y: x + y, (glob.glob(x) for x in ('*.spec', '*.dsc', '*.kiwi'))) # but be a bit more readable :) descr = glob.glob('*.spec') + glob.glob('*.dsc') + glob.glob('*.kiwi') + glob.glob('*.livebuild') \ - + glob.glob('PKGBUILD') + glob.glob('build.collax') + glob.glob('Dockerfile') + + glob.glob('PKGBUILD') + glob.glob('build.collax') + glob.glob('Dockerfile') + glob.glob('fissile.yml') # FIXME: # * request repos from server and select by build type. @@ -6283,6 +6367,7 @@ osc chroot [OPTS] (REPOSITORY = build_repository (config option), ARCH = hostarch, BUILD_DESCR is detected automatically) ${cmd_option_list} """ + if len(args) > 3: raise oscerr.WrongArgs('Too many arguments') if conf.config['build-type'] and conf.config['build-type'] != "lxc": @@ -6336,13 +6421,38 @@ sucmd = suwrapper.split()[0] suargs = ' '.join(suwrapper.split()[1:]) if suwrapper.startswith('su '): + mntproc = [sucmd, '%s mount -n -tproc none %s/proc' % (suargs, buildroot)] + umntproc = [sucmd, '%s umount %s/proc' % (suargs, buildroot)] cmd = [sucmd, '%s chroot "%s" su - %s' % (suargs, buildroot, user)] else: + mntproc = [sucmd, 'mount', '-n', '-tproc' , 'none', '%s/proc' % buildroot] + umntproc = [sucmd, 'umount', '%s/proc' % buildroot] cmd = [sucmd, 'chroot', buildroot, 'su', '-', user] if suargs: + mntproc[1:1] = suargs.split() + umntproc[1:1] = suargs.split() cmd[1:1] = suargs.split() + + #signal handler for chroot procfs umount + def umount_proc(signum = None, frame = None, ret=1): + subprocess.call(umntproc) + sys.exit(ret) + for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]: + signal.signal(sig, umount_proc) + + print('mounting proc: %s' % ' '.join(mntproc)) + mount_err = -1 + mount_err = subprocess.call(mntproc) + if mount_err > 0: + print('There was an error mounting proc. Please check mountpoints in chroot') print('running: %s' % ' '.join(cmd)) - os.execvp(sucmd, cmd) + retval = 0 + try: + retval = subprocess.call(cmd) + finally: + if not mount_err or mount_err == 32: + print('unmounting %s/proc ...' % buildroot) + umount_proc(ret=retval) @cmdln.option('', '--csv', action='store_true', @@ -8786,7 +8896,13 @@ for pdir in pacs: p = Package(pdir) pdir = getTransActPath(pdir) - for filename in (fname for st, fname in p.get_status() if st == '?'): + todo = [fname for st, fname in p.get_status() if st == '?'] + for fname in p.excluded: + # there might be some rare cases, where an excluded file has + # not state '?' + if os.path.isfile(fname) and p.status(fname) == '?': + todo.append(fname) + for filename in todo: print('Removing: %s' % os.path.join(pdir, filename)) if not opts.dry_run: os.unlink(os.path.join(p.absdir, filename)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/osc/conf.py new/osc-0.160.0/osc/conf.py --- old/osc-0.159.0/osc/conf.py 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/osc/conf.py 2017-09-22 09:06:18.000000000 +0200 @@ -180,7 +180,10 @@ 'maintained_update_project_attribute': 'OBS:UpdateProject', 'show_download_progress': '0', # path to the vc script - 'vc-cmd': '/usr/lib/build/vc' + 'vc-cmd': '/usr/lib/build/vc', + + # heuristic to speedup Package.status + 'status_mtime_heuristic': '0' } # some distros like Debian rename and move build to obs-build @@ -196,7 +199,8 @@ boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback', 'check_filelist', 'plaintext_passwd', 'checkout_no_colon', 'checkout_rooted', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive', 'request_show_source_buildstatus', 'review_inherit_group', 'use_keyring', 'gnome_keyring', 'no_verify', 'builtin_signature_check', - 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time', 'no_preinstallimage'] + 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time', 'no_preinstallimage', + 'status_mtime_heuristic'] api_host_options = ['user', 'pass', 'passx', 'aliases', 'http_headers', 'email', 'sslcertck', 'cafile', 'capath', 'trusted_prj'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/osc/core.py new/osc-0.160.0/osc/core.py --- old/osc-0.159.0/osc/core.py 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/osc/core.py 2017-09-22 09:06:18.000000000 +0200 @@ -5,7 +5,7 @@ from __future__ import print_function -__version__ = '0.159' +__version__ = '0.160.0' # __store_version__ is to be incremented when the format of the working copy # "store" changes in an incompatible way. Please add any needed migration @@ -179,6 +179,15 @@ </person> """ +new_group_template = """\ +<group> + <title>%(group)s</title> + <person> + <person userid=""/> + </person> +</group> +""" + info_templ = """\ Project name: %s Package name: %s @@ -1040,6 +1049,8 @@ pass except OSError: pac_dir = os.path.join(self.dir, pac) + except (oscerr.NoWorkingCopy, oscerr.WorkingCopyOutdated, oscerr.PackageError): + pass #print statfrmt('Deleting', getTransActPath(os.path.join(self.dir, pac))) print(statfrmt('Deleting', getTransActPath(pac_dir))) delete_package(self.apiurl, self.name, pac) @@ -1844,9 +1855,10 @@ known_by_meta = False exists = False exists_in_store = False + localfile = os.path.join(self.absdir, n) if n in self.filenamelist: known_by_meta = True - if os.path.exists(os.path.join(self.absdir, n)): + if os.path.exists(localfile): exists = True if os.path.exists(os.path.join(self.storedir, n)): exists_in_store = True @@ -1862,10 +1874,13 @@ elif n in self.to_be_added and exists: state = 'A' elif exists and exists_in_store and known_by_meta: - if dgst(os.path.join(self.absdir, n)) != self.findfilebyname(n).md5: + filemeta = self.findfilebyname(n) + state = ' ' + if conf.config['status_mtime_heuristic']: + if os.path.getmtime(localfile) != filemeta.mtime and dgst(localfile) != filemeta.md5: + state = 'M' + elif dgst(localfile) != filemeta.md5: state = 'M' - else: - state = ' ' elif n in self.to_be_added and not exists: state = '!' elif not exists and exists_in_store and known_by_meta and not n in self.to_be_deleted: @@ -1880,7 +1895,7 @@ 'This might be caused by an old wc format. Please backup your current\n' 'wc and checkout the package again. Afterwards copy all files (except the\n' '.osc/ dir) into the new package wc.' % n) - elif os.path.islink(os.path.join(self.absdir, n)): + elif os.path.islink(localfile): # dangling symlink, whose name is _not_ tracked: treat it # as unversioned state = '?' @@ -3108,7 +3123,7 @@ continue known = None for i in pacs: - if i.name == p.name: + if i.name == p.name and i.prjname == p.prjname: known = i break if known: @@ -3646,6 +3661,10 @@ 'template': new_user_template, 'file_ext': '.xml' }, + 'group': { 'path': 'group/%s', + 'template': new_group_template, + 'file_ext': '.xml' + }, 'pattern': { 'path': 'source/%s/_pattern/%s', 'template': new_pattern_template, 'file_ext': '.xml' @@ -4208,7 +4227,8 @@ print('error: cannot interpolate \'%s\' in \'%s\'' % (e.args[0], tmpl_name), file=sys.stderr) return '' -def get_review_list(apiurl, project='', package='', byuser='', bygroup='', byproject='', bypackage='', states=()): +def get_review_list(apiurl, project='', package='', byuser='', bygroup='', byproject='', bypackage='', states=(), + req_type=''): # this is so ugly... def build_by(xpath, val): if 'all' in states: @@ -4238,6 +4258,9 @@ elif byproject: xpath = build_by(xpath, '@by_project=\'%s\'' % byproject) + if req_type: + xpath = xpath_join(xpath, 'action/@type=\'%s\'' % req_type, op='and') + # XXX: we cannot use the '|' in the xpath expression because it is not supported # in the backend todo = {} @@ -4318,7 +4341,8 @@ requests.append(r) return requests -def get_request_list(apiurl, project='', package='', req_who='', req_state=('new', 'review', 'declined'), req_type=None, exclude_target_projects=[]): +def get_request_list(apiurl, project='', package='', req_who='', req_state=('new', 'review', 'declined'), req_type=None, exclude_target_projects=[], + withfullhistory=False): xpath = '' if not 'all' in req_state: for state in req_state: @@ -4350,7 +4374,10 @@ if conf.config['verbose'] > 1: print('[ %s ]' % xpath) - res = search(apiurl, request=xpath) + queries = {} + if withfullhistory: + queries['request'] = {'withfullhistory': '1'} + res = search(apiurl, queries=queries, request=xpath) collection = res['request'] requests = [] for root in collection.findall('request'): @@ -4455,7 +4482,12 @@ raise oscerr.UserAbort() return repl == 'y', reqs +# old function for compat reasons. Some plugins may call this function. +# and we do not want to break the plugins. def get_group(apiurl, group): + return get_group_meta(apiurl, group) + +def get_group_meta(apiurl, group): u = makeurl(apiurl, ['group', quote_plus(group)]) try: f = http_GET(u) @@ -4473,7 +4505,6 @@ print('user \'%s\' not found' % user) return None - def _get_xml_data(meta, *tags): data = [] if meta != None: @@ -4494,7 +4525,7 @@ def get_group_data(apiurl, group, *tags): - meta = get_group(apiurl, group) + meta = get_group_meta(apiurl, group) return _get_xml_data(meta, *tags) @@ -6504,19 +6535,28 @@ new_expr = '(%s)' % new_expr return '%s %s %s' % (expr, op, new_expr) -def search(apiurl, **kwargs): +def search(apiurl, queries=None, **kwargs): """ Perform a search request. The requests are constructed as follows: kwargs = {'kind1' => xpath1, 'kind2' => xpath2, ..., 'kindN' => xpathN} GET /search/kind1?match=xpath1 ... GET /search/kindN?match=xpathN + + queries is a dict of optional http query parameters, which are passed + to the makeurl call, of the form + {kindI1: dict_or_list, ..., kindIL: dict_or_list}, + where kind_i1 to kind_iL are keys of kwargs. """ + if queries is None: + queries = {} res = {} for urlpath, xpath in kwargs.items(): path = [ 'search' ] path += urlpath.split('_') # FIXME: take underscores as path seperators. I see no other way atm to fix OBS api calls and not breaking osc api - u = makeurl(apiurl, path, ['match=%s' % quote_plus(xpath)]) + query = queries.get(urlpath, {}) + query['match'] = xpath + u = makeurl(apiurl, path, query) f = http_GET(u) res[urlpath] = ET.parse(f).getroot() return res @@ -7102,6 +7142,7 @@ print('unable to retrieve the buildstatus: %s' % e) print_request(request) + print_comments(apiurl, 'request', request.reqid) try: prompt = '(a)ccept/(d)ecline/(r)evoke/c(l)one/co(m)ment/(s)kip/(c)ancel > ' editable_actions = request.get_actions('submit', 'maintenance_incident') @@ -7144,6 +7185,7 @@ tmpfile.flush() run_editor(tmpfile.name) print_request(request) + print_comments(apiurl, 'request', request.reqid) elif repl == 's': print('skipping: #%s' % request.reqid, file=sys.stderr) break @@ -7517,4 +7559,9 @@ ret = ET.fromstring(f.read()).find('summary') return ret.text +def get_rpmlint_log(apiurl, proj, pkg, repo, arch): + u = makeurl(apiurl, ['build', proj, repo, arch, pkg, 'rpmlint.log']) + f = http_GET(u) + return f.read() + # vim: sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-0.159.0/osc/fetch.py new/osc-0.160.0/osc/fetch.py --- old/osc-0.159.0/osc/fetch.py 2017-07-19 00:48:15.000000000 +0200 +++ new/osc-0.160.0/osc/fetch.py 2017-09-22 09:06:18.000000000 +0200 @@ -246,6 +246,13 @@ all = len(buildinfo.deps) for i in buildinfo.deps: i.makeurls(self.cachedir, self.urllist) + # find container extension by looking in the cache + if i.name.startswith('container:') and i.fullfilename.endswith('.tar.xz'): + for ext in ['.tar.xz', '.tar.gz', '.tar']: + if os.path.exists(i.fullfilename[:-7] + ext): + i.canonname = i.canonname[:-7] + ext + i.makeurls(self.cachedir, self.urllist) + if os.path.exists(i.fullfilename): cached += 1 if i.hdrmd5: ++++++ osc.dsc ++++++ --- /var/tmp/diff_new_pack.Q6hU6I/_old 2017-09-23 21:36:36.302252479 +0200 +++ /var/tmp/diff_new_pack.Q6hU6I/_new 2017-09-23 21:36:36.302252479 +0200 @@ -1,6 +1,6 @@ Format: 1.0 Source: osc -Version: 0.159.0-0 +Version: 0.160.0-0 Binary: osc Maintainer: Adrian Schroeter <[email protected]> Architecture: any
