Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package osc for openSUSE:Factory checked in 
at 2022-07-29 16:48:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/osc (Old)
 and      /work/SRC/openSUSE:Factory/.osc.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "osc"

Fri Jul 29 16:48:20 2022 rev:164 rq:991675 version:0.181.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/osc/osc.changes  2022-06-25 10:24:51.170724349 
+0200
+++ /work/SRC/openSUSE:Factory/.osc.new.1533/osc.changes        2022-07-29 
16:48:25.962741777 +0200
@@ -1,0 +2,16 @@
+Tue Jul 26 19:37:46 UTC 2022 - Daniel Mach <daniel.m...@suse.com>
+
+- 0.181.0
+  - fix crash when 'pass' is not set in the config file
+  - add missing attributes to Package when scm_url is set
+  - fix failure to create config in current dir
+  - update list of considered file names for ssh key autodetection
+  - allow users to prefer ssh key over password auth
+  - ssh: recognize gpg keys (yubikey usage)
+  - fix operating on _project meta
+  - revert "interpretation of string literals in messages" that broke unicode 
handling
+  - fix product build rpm caching
+  - enable md5 revisions in osc log
+  - parseRevisionOption(): raise an exception on invalid revisions 
+
+-------------------------------------------------------------------

Old:
----
  osc-0.180.0.tar.gz

New:
----
  osc-0.181.0.tar.gz

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

Other differences:
------------------
++++++ osc.spec ++++++
--- /var/tmp/diff_new_pack.d2ztT7/_old  2022-07-29 16:48:26.782744057 +0200
+++ /var/tmp/diff_new_pack.d2ztT7/_new  2022-07-29 16:48:26.786744068 +0200
@@ -27,7 +27,7 @@
 %define use_python python
 %endif
 
-%define version_unconverted 0.180.0
+%define version_unconverted 0.181.0
 %define osc_plugin_dir %{_prefix}/lib/osc-plugins
 %define macros_file macros.osc
 %if ! %{defined _rpmmacrodir}
@@ -35,7 +35,7 @@
 %endif
 
 Name:           osc
-Version:        0.180.0
+Version:        0.181.0
 Release:        0
 Summary:        Open Build Service Commander
 License:        GPL-2.0-or-later

++++++ PKGBUILD ++++++
--- /var/tmp/diff_new_pack.d2ztT7/_old  2022-07-29 16:48:26.826744180 +0200
+++ /var/tmp/diff_new_pack.d2ztT7/_new  2022-07-29 16:48:26.830744191 +0200
@@ -1,5 +1,5 @@
 pkgname=osc
-pkgver=0.180.0
+pkgver=0.181.0
 pkgrel=0
 pkgdesc="Open Build Service client"
 arch=('x86_64')

++++++ _service ++++++
--- /var/tmp/diff_new_pack.d2ztT7/_old  2022-07-29 16:48:26.850744247 +0200
+++ /var/tmp/diff_new_pack.d2ztT7/_new  2022-07-29 16:48:26.866744291 +0200
@@ -1,7 +1,7 @@
 <services>
   <service name="tar_scm" mode="disabled">
-    <param name="version">0.180.0</param>
-    <param name="revision">0.180.0</param>
+    <param name="version">0.181.0</param>
+    <param name="revision">0.181.0</param>
     <param name="url">https://github.com/openSUSE/osc.git</param>
     <param name="scm">git</param>
   </service>

++++++ debian.changelog ++++++
--- /var/tmp/diff_new_pack.d2ztT7/_old  2022-07-29 16:48:26.906744402 +0200
+++ /var/tmp/diff_new_pack.d2ztT7/_new  2022-07-29 16:48:26.910744413 +0200
@@ -1,4 +1,4 @@
-osc (0.180.0-0) unstable; urgency=low
+osc (0.181.0-0) unstable; urgency=low
   - Update to 0.174.0:
     - fix password deletion via "osc config -d <apiurl> pass"
     - support changing the password store via "osc config <apiurl>

++++++ osc-0.180.0.tar.gz -> osc-0.181.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/NEWS new/osc-0.181.0/NEWS
--- old/osc-0.180.0/NEWS        2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/NEWS        2022-07-26 21:34:07.000000000 +0200
@@ -1,3 +1,16 @@
+0.181.0
+  - fix crash when 'pass' is not set in the config file
+  - add missing attributes to Package when scm_url is set
+  - fix failure to create config in current dir
+  - update list of considered file names for ssh key autodetection
+  - allow users to prefer ssh key over password auth
+  - ssh: recognize gpg keys (yubikey usage)
+  - fix operating on _project meta
+  - revert "interpretation of string literals in messages" that broke unicode 
handling
+  - fix product build rpm caching
+  - enable md5 revisions in osc log
+  - parseRevisionOption(): raise an exception on invalid revisions
+
 0.180.0
   - warn when trying to commit a prj/pac managed in scm
   - fix crash on "osc up" for git based package/projects
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/build.py new/osc-0.181.0/osc/build.py
--- old/osc-0.180.0/osc/build.py        2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/build.py        2022-07-26 21:34:07.000000000 +0200
@@ -293,7 +293,7 @@
 
 
     def makeurls(self, cachedir, urllist):
-        self.localdir = '%s/%s/%s/%s' % (cachedir, self.project, 
self.repository, self.arch)
+        self.localdir = '%s/%s/%s/%s' % (cachedir, self.project, 
self.repository, self.repoarch)
         self.fullfilename = os.path.join(self.localdir, self.canonname)
         self.urllist = [url % self.mp for url in urllist]
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/commandline.py 
new/osc-0.181.0/osc/commandline.py
--- old/osc-0.180.0/osc/commandline.py  2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/commandline.py  2022-07-26 21:34:07.000000000 +0200
@@ -983,10 +983,6 @@
         # If project or package arguments missing, assume to work
         # with project and/or package in current local directory.
         attributepath = []
-
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
-
         if cmd in ['prj', 'prjconf']:
             if len(args) < 1:
                 apiurl = store_read_apiurl(os.curdir)
@@ -1291,7 +1287,7 @@
             src_update = "noupdate"
 
         if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
+            pass
         elif opts.file:
             if opts.file == '-':
                 opts.message = sys.stdin.read()
@@ -1962,8 +1958,6 @@
 
         if not opts.message:
             opts.message = edit_message()
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         xml = """<request> %s <state name="new"/> 
<description>%s</description> </request> """ % \
               (actionsxml, _html_escape(opts.message or ""))
@@ -2041,8 +2035,6 @@
             raise oscerr.WrongOptions('invalid \'--role\': either specify 
\'maintainer\' or \'bugowner\'')
         if not opts.message:
             opts.message = edit_message()
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         r = Request()
         if user.startswith('group:'):
@@ -2121,8 +2113,6 @@
                 footer = textwrap.TextWrapper(width = 66).fill(
                          'please explain why you like to delete project %s' % 
project)
             opts.message = edit_message(footer)
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         r = Request()
         r.add_action('delete', tgt_project=project, tgt_package=package, 
tgt_repository=repository)
@@ -2170,8 +2160,6 @@
                      'please explain why you like to change the devel project 
of %s/%s to %s/%s'
                      % (project, package, devel_project, devel_package))
             opts.message = edit_message(footer)
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         r = Request()
         r.add_action('change_devel', src_project=devel_project, 
src_package=devel_package,
@@ -2341,9 +2329,6 @@
         if opts.incoming:
             conf.config['include_request_from_project'] = False
 
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
-
         if args[0] == 'help':
             return self.do_help(['help', 'request'])
 
@@ -2895,8 +2880,7 @@
             raise oscerr.WrongArgs('Too many arguments (required none or two)')
         else:
             raise oscerr.WrongArgs('Too few arguments (required none or two)')
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
+
         try:
             copy_pac(apiurl, project, package, apiurl, project, package, 
expand=True, comment=opts.message)
         except HTTPError as e:
@@ -3108,7 +3092,7 @@
         rev, dummy = parseRevisionOption(opts.revision)
 
         if opts.message:
-            comment = str(opts.message.encode().decode('unicode_escape'))
+            comment = opts.message
         else:
             if not rev:
                 rev = show_upstream_rev(src_apiurl, src_project, src_package)
@@ -3255,8 +3239,6 @@
 
         if not opts.message:
             opts.message = edit_message()
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         if 'kind' in root.attrib and root.attrib['kind'] == 
'maintenance_incident':
             r = create_release_request(apiurl, source_project, opts.message)
@@ -3300,8 +3282,6 @@
         maintenance_attribute = conf.config['maintenance_attribute']
         if opts.attribute:
             maintenance_attribute = opts.attribute
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         source_project = target_project = None
 
@@ -3440,8 +3420,6 @@
 
         if not opts.message:
             opts.message = edit_message()
-        else:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
 
         supersede_existing = False
         reqs = []
@@ -3665,9 +3643,6 @@
         if len(args) >= 4:
             tpackage = args[3]
 
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
-
         try:
             exists, targetprj, targetpkg, srcprj, srcpkg = \
                 branch_pkg(apiurl, args[0], args[1],
@@ -3761,7 +3736,7 @@
 
         msg = ''
         if opts.message:
-            msg = str(opts.message.encode().decode('unicode_escape'))
+            msg = opts.message
         else:
             msg = edit_message()
 
@@ -3808,7 +3783,7 @@
 
         msg = ''
         if opts.message:
-            msg = str(opts.message.encode().decode('unicode_escape'))
+            msg = opts.message
         else:
             msg = edit_message()
 
@@ -3854,8 +3829,6 @@
         ${cmd_option_list}
         """
         apiurl = self.get_api_url()
-        if opts.message:
-            opts.message = str(opts.message.encode().decode('unicode_escape'))
         kind = 'prj'
         path_args = (project,)
         if package is not None:
@@ -3896,7 +3869,7 @@
 
         msg = ''
         if opts.message:
-            msg = str(opts.message.encode().decode('unicode_escape'))
+            msg = opts.message
         else:
             msg = edit_message()
 
@@ -5003,7 +4976,7 @@
 
         msg = ''
         if opts.message:
-            msg = str(opts.message.encode().decode('unicode_escape'))
+            msg = opts.message
         elif opts.file:
             if opts.file == '-':
                 msg = sys.stdin.read()
@@ -7120,7 +7093,7 @@
             project = args[0]
             package = args[1]
 
-        rev, rev_upper = parseRevisionOption(opts.revision, allow_md5=False)
+        rev, rev_upper = parseRevisionOption(opts.revision)
         if rev and not checkRevision(project, package, rev, apiurl, opts.meta):
             print('Revision \'%s\' does not exist' % rev, file=sys.stderr)
             sys.exit(1)
@@ -8538,7 +8511,7 @@
 
             if requestactionsxml != "":
                 if opts.message:
-                    message = 
str(opts.message.encode().decode('unicode_escape'))
+                    message = opts.message
                 else:
                     message = edit_message()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/conf.py new/osc-0.181.0/osc/conf.py
--- old/osc-0.180.0/osc/conf.py 2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/conf.py 2022-07-26 21:34:07.000000000 +0200
@@ -540,14 +540,26 @@
             for authreq in headers.get_all('www-authenticate', []):
                 scheme = authreq.split()[0].lower()
                 authreqs[scheme] = authreq
-            if 'signature' in authreqs and self.signatureauthhandler and \
-                    (self.signatureauthhandler.sshkey_known() or 'basic' not 
in authreqs):
+
+            if 'signature' in authreqs \
+                and self.signatureauthhandler \
+                and (
+                    # sshkey explicitly set in the config file, use it instead 
of doing basic auth
+                    self.signatureauthhandler.sshkey_known()
+                    or (
+                        # can't fall-back to basic auth, because server 
doesn't support it
+                        'basic' not in authreqs
+                        # can't fall-back to basic auth, because there's no 
password provided
+                        or not self.passwd.find_user_password(None, apiurl)[1]
+                    )):
                 del headers['www-authenticate']
                 headers['www-authenticate'] = authreqs['signature']
                 return self.signatureauthhandler.http_error_401(req, fp, code, 
msg, headers)
+
             if 'basic' in authreqs:
                 del headers['www-authenticate']
                 headers['www-authenticate'] = authreqs['basic']
+
             response = super(self.__class__, self).http_error_401(req, fp, 
code, msg, headers)
             # workaround for http://bugs.python.org/issue9639
             if hasattr(self, 'retried'):
@@ -565,7 +577,7 @@
             proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
             stdout, _ = proc.communicate()
             if proc.returncode == 0 and stdout.strip():
-                return stdout.splitlines()
+                return [self.get_fingerprint(line) for line in 
stdout.splitlines()]
             else:
                 return []
 
@@ -584,21 +596,43 @@
                     return True
             return False
 
+        def is_ssh_public_keyfile(self, keyfile_path):
+            if not os.path.isfile(keyfile_path):
+                return False
+            return keyfile_path.endswith(".pub")
+
+        @staticmethod
+        def get_fingerprint(line):
+            parts = line.strip().split(b" ")
+            if len(parts) < 2:
+                raise ValueError("Unable to retrieve ssh key fingerprint from 
line: {}".format(line))
+            return parts[1]
+
         def list_ssh_dir_keys(self):
             sshdir = os.path.expanduser('~/.ssh')
             keys_in_home_ssh = {}
             for keyfile in os.listdir(sshdir):
-                if keyfile.endswith(".pub"):
+                if keyfile.startswith(("agent-", "authorized_keys", "config", 
"known_hosts")):
+                    # skip files that definitely don't contain keys
                     continue
+
                 keyfile_path = os.path.join(sshdir, keyfile)
-                if not self.is_ssh_private_keyfile(keyfile_path):
+                # public key alone may be sufficient because the private key
+                # can get loaded into ssh-agent from gpg (yubikey works this 
way)
+                is_public = self.is_ssh_public_keyfile(keyfile_path)
+                # skip private detection if we think the key is a public one 
already
+                is_private = False if is_public else 
self.is_ssh_private_keyfile(keyfile_path)
+
+                if not is_public and not is_private:
                     continue
+
                 cmd = ["ssh-keygen", "-lf", keyfile_path]
                 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
                 stdout, _ = proc.communicate()
                 if proc.returncode == 0:
-                    fingerprint = stdout.strip()
-                    if fingerprint:
+                    fingerprint = self.get_fingerprint(stdout)
+                    if fingerprint and (fingerprint not in keys_in_home_ssh or 
is_private):
+                        # prefer path to a private key
                         keys_in_home_ssh[fingerprint] = keyfile_path
             return keys_in_home_ssh
 
@@ -610,7 +644,7 @@
                     if fingerprint in keys_in_home_ssh:
                         return keys_in_home_ssh[fingerprint]
             sshdir = os.path.expanduser('~/.ssh')
-            keyfiles = ('id_ed25519', 'id_rsa')
+            keyfiles = ('id_ed25519', 'id_ed25519_sk', 'id_rsa', 'id_ecdsa', 
'id_ecdsa_sk', 'id_dsa')
             for keyfile in keyfiles:
                 keyfile_path = os.path.join(sshdir, keyfile)
                 if os.path.isfile(keyfile_path):
@@ -827,9 +861,10 @@
         fname = os.readlink(fname)
 
     # create directories to the config file (if they don't exist already)
-    if not os.path.exists(os.path.dirname(fname)):
+    fdir = os.path.dirname(fname)
+    if fdir:
         try:
-            os.makedirs(os.path.dirname(fname), mode=0o700)
+            os.makedirs(fdir, mode=0o700)
         except OSError as e:
             if e.errno != errno.EEXIST:
                 raise
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/core.py new/osc-0.181.0/osc/core.py
--- old/osc-0.180.0/osc/core.py 2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/core.py 2022-07-26 21:34:07.000000000 +0200
@@ -7,7 +7,7 @@
 
 
 from .util import git_version
-__version__ = git_version.get_version('0.180.0')
+__version__ = git_version.get_version('0.181.0')
 
 
 # __store_version__ is to be incremented when the format of the working copy
@@ -1800,6 +1800,10 @@
             self.srcmd5 = None
             self.linkinfo = None
             self.serviceinfo = None
+            self.size_limit = None
+            self.meta = None
+            self.excluded = []
+            self.filenamelist_unvers = []
             return
 
         files_tree = read_filemeta(self.dir)
@@ -3612,10 +3616,6 @@
         query['view'] = "blame"
         query['meta'] = 1
 
-    # The fake packages _project has no _meta file
-    if pac.startswith('_project'):
-        return ""
-
     url = makeurl(apiurl, ['source', prj, pac, '_meta'], query)
     try:
         f = http_GET(url)
@@ -6851,12 +6851,15 @@
     revisions = [None, None]
     if string:
         parts = string.split(':')
-        for i, revision in enumerate(parts[0:2], 0):
+
+        if len(parts) > 2:
+            raise oscerr.OscInvalidRevision(string)
+
+        for i, revision in enumerate(parts, 0):
             if revision.isdigit() or (allow_md5 and revision.isalnum() and 
len(revision) == 32):
                 revisions[i] = revision
             elif revision != '' and revision != 'latest':
-                print('your revision \'%s\' will be ignored' % string, 
file=sys.stderr)
-                return None, None
+                raise oscerr.OscInvalidRevision(string)
 
     return tuple(revisions)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/credentials.py 
new/osc-0.181.0/osc/credentials.py
--- old/osc-0.180.0/osc/credentials.py  2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/credentials.py  2022-07-26 21:34:07.000000000 +0200
@@ -166,6 +166,9 @@
 
     @classmethod
     def decode_password(cls, password):
+        if password is None:
+            # avoid crash on encoding None when 'pass' is not specified in the 
config
+            return None
         compressed_pw = base64.b64decode(password.encode("ascii"))
         return bz2.decompress(compressed_pw).decode("ascii")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/fetch.py new/osc-0.181.0/osc/fetch.py
--- old/osc-0.180.0/osc/fetch.py        2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/fetch.py        2022-07-26 21:34:07.000000000 +0200
@@ -265,8 +265,8 @@
                         if not hdrmd5 or hdrmd5 != i.hdrmd5:
                             print('%s/%s: attempting download from api, since 
the hdrmd5 did not match - %s != %s'
                                 % (i.project, i.name, hdrmd5, i.hdrmd5))
-                        os.unlink(i.fullfilename)
-                        self.__add_cpio(i)
+                            os.unlink(i.fullfilename)
+                            self.__add_cpio(i)
 
                 except KeyboardInterrupt:
                     print('Cancelled by user (ctrl-c)')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/oscerr.py 
new/osc-0.181.0/osc/oscerr.py
--- old/osc-0.180.0/osc/oscerr.py       2022-06-24 15:23:26.000000000 +0200
+++ new/osc-0.181.0/osc/oscerr.py       2022-07-26 21:34:07.000000000 +0200
@@ -121,6 +121,22 @@
         self.e = e
         self.msg = msg
 
+
+class OscValueError(OscBaseError):
+    """
+    Invalid argument value (of correct type).
+    """
+    pass
+
+
+class OscInvalidRevision(OscValueError):
+    """
+    Invalid revision value.
+    """
+    def __str__(self):
+        return "Invalid revision value: {}".format("".join(self.args))
+
+
 class PackageNotInstalled(OscBaseError):
     """
     Exception raised when a package is not installed on local system
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/osc/util/git_version.py 
new/osc-0.181.0/osc/util/git_version.py
--- old/osc-0.180.0/osc/util/git_version.py     2022-06-24 15:23:26.000000000 
+0200
+++ new/osc-0.181.0/osc/util/git_version.py     2022-07-26 21:34:07.000000000 
+0200
@@ -10,8 +10,9 @@
     # the `version` variable contents get substituted during `git archive`
     # it requires adding this to .gitattributes: <path to this file> 
export-subst
     version = "$Format:%(describe:tags=true)$"
-    if version.startswith("$"):
-        # version hasn't been substituted during `git archive`
+    if version.startswith(("$", "%")):
+        # "$": version hasn't been substituted during `git archive`
+        # "%": "Format:" and "$" characters get removed from the version 
string (a GitHub bug?)
         return None
     return version
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/osc-0.180.0/tests/test_core.py 
new/osc-0.181.0/tests/test_core.py
--- old/osc-0.180.0/tests/test_core.py  1970-01-01 01:00:00.000000000 +0100
+++ new/osc-0.181.0/tests/test_core.py  2022-07-26 21:34:07.000000000 +0200
@@ -0,0 +1,52 @@
+from osc.core import parseRevisionOption
+from osc.oscerr import OscInvalidRevision
+
+import unittest
+
+
+class TestParseRevisionOption(unittest.TestCase):
+    def test_empty(self):
+        expected = None, None
+        actual = parseRevisionOption("")
+        self.assertEqual(expected, actual)
+
+    def test_colon(self):
+        expected = None, None
+        actual = parseRevisionOption(":")
+        # your revision ':' will be ignored
+        self.assertEqual(expected, actual)
+
+    def test_invalid_multiple_colons(self):
+        self.assertRaises(OscInvalidRevision, parseRevisionOption, ":::::")
+
+    def test_one_number(self):
+        expected = ("1", None)
+        actual = parseRevisionOption("1")
+        self.assertEqual(expected, actual)
+
+    def test_two_numbers(self):
+        expected = ("1", "2")
+        actual = parseRevisionOption("1:2")
+        self.assertEqual(expected, actual)
+
+    def test_invalid_multiple_numbers(self):
+        self.assertRaises(OscInvalidRevision, parseRevisionOption, "1:2:3:4:5")
+
+    def test_one_hash(self):
+        expected = "c4ca4238a0b923820dcc509a6f75849b", None
+        actual = parseRevisionOption("c4ca4238a0b923820dcc509a6f75849b")
+        self.assertEqual(expected, actual)
+
+    def test_two_hashes(self):
+        expected = ("d41d8cd98f00b204e9800998ecf8427e", 
"c4ca4238a0b923820dcc509a6f75849b")
+        actual = 
parseRevisionOption("d41d8cd98f00b204e9800998ecf8427e:c4ca4238a0b923820dcc509a6f75849b")
+        self.assertEqual(expected, actual)
+
+    def test_invalid_multiple_hashes(self):
+        rev = 
"d41d8cd98f00b204e9800998ecf8427e:c4ca4238a0b923820dcc509a6f75849b:c81e728d9d4c2f636f067f89cc14862c"
+        self.assertRaises(OscInvalidRevision, parseRevisionOption, rev)
+
+
+if __name__ == "__main__":
+    import unittest
+    unittest.main()

++++++ osc.dsc ++++++
--- /var/tmp/diff_new_pack.d2ztT7/_old  2022-07-29 16:48:27.302745503 +0200
+++ /var/tmp/diff_new_pack.d2ztT7/_new  2022-07-29 16:48:27.306745514 +0200
@@ -1,6 +1,6 @@
 Format: 1.0
 Source: osc
-Version: 0.180.0-0
+Version: 0.181.0-0
 Binary: osc
 Maintainer: Adrian Schroeter <adr...@suse.de>
 Architecture: any

Reply via email to