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


Reply via email to