[calm - Cygwin server-side packaging maintenance script] branch master, updated. 20230209-89-g79e8308

Jon Turney jturney@sourceware.org
Thu Apr 11 14:21:26 GMT 2024




https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=79e8308164e5b6d8dfcef05c68e492311552dc31

commit 79e8308164e5b6d8dfcef05c68e492311552dc31
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Tue Apr 9 21:16:58 2024 +0100

    Add some more old-style obsoletion upgrade information
    
    These packages weren't being noticed before as being "obsolete, but no
    replacement" due to the way split() can produce a list containing an
    empty string, rather than an empty list.

https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=ee039db724d8b555b2748bb9295e4ad0106babe4

commit ee039db724d8b555b2748bb9295e4ad0106babe4
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Tue Apr 9 19:43:08 2024 +0100

    Convert package lists in hints to actual lists
    
    Convert package lists in hints to actual lists in one place, rather than
    doing it every time we need to use the value.
    
    This fixes the bug that build-requires wasn't written to JSON as a list.
    
    Update test data appropriately.
    
    Future work: Factor out "strip out version constraints from a package
    list" into a utility function.

https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=b768c25a36de53156cb11b129a0bac57bc5cac46

commit b768c25a36de53156cb11b129a0bac57bc5cac46
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Mon Apr 8 16:34:04 2024 +0100

    Add repr for RepoPath objects to aid debugging


Diff:
---
 calm/package.py                                   | 81 +++++++++++++----------
 calm/past_mistakes.py                             |  7 ++
 calm/pkg2html.py                                  |  8 +--
 calm/reports.py                                   | 14 ++--
 calm/utils.py                                     |  7 +-
 test/testdata/process_arch/packages.json.expected |  4 +-
 test/testdata/uploads/pkglist.expected            | 14 ++--
 7 files changed, 74 insertions(+), 61 deletions(-)

diff --git a/calm/package.py b/calm/package.py
index efc01c4..abaec1b 100755
--- a/calm/package.py
+++ b/calm/package.py
@@ -84,6 +84,9 @@ class RepoPath():
     def move(self):
         return (os.path.join(self.arch, 'release', self.path), self.fn)
 
+    def __repr__(self):
+        return "RepoPath(%s, %s, %s)" % (self.arch, self.path, self.fn)
+
 
 # information we keep about a package
 class Package(object):
@@ -265,13 +268,30 @@ def read_hints(p, fn, kind, strict=False):
         for l in hints['parse-warnings']:
             logging.info("package '%s': %s" % (p, l))
 
-    # generate depends: from requires:
-    # XXX: store this as a list, rather than splitting it into one everywhere we
-    # use it
-    hints['depends'] = ', '.join(process_package_constraint_list(hints.get('requires', '')))
-    # erase requires:, to ensure there is nothing using it
+    # convert hint keys which have a value which is a list to an actual list (to
+    # avoid doing the splitting and whitespace handling everywhere)
+    #
+    # XXX: guarantee they exist and are an empty list if empty, so we don't need
+    # to check if they exist everywhere?)
+    for k in ['obsoletes', 'provides', 'conflicts', 'build-depends']:
+        if k in hints:
+            v = hints[k].strip()
+            if not v:
+                v = []
+            else:
+                # split on comma, remove any extraneous whitespace
+                v = [i.strip() for i in v.split(',')]
+            hints[k] = v
+
+    # 'depends' is special, generated from from requires:
+    hints['depends'] = process_package_constraint_list(hints.get('requires', ''))
+    # erase requires:, to ensure there is nothing still using it
     hints.pop('requires', None)
 
+    # disable check is just whitespace separated
+    if 'disable-check' in hints:
+        hints['disable-check'] = hints['disable-check'].split()
+
     return hints
 
 
@@ -624,7 +644,7 @@ def upgrade_oldstyle_obsoletes(packages, missing_obsolete):
                     continue
                 logging.debug("_obsolete package '%s' version '%s' mtime '%s' is over cut-off age" % (p, vr, time.strftime("%F %T %Z", time.localtime(mtime))))
 
-                requires = packages[p].version_hints[vr].get('depends', '').split(', ')
+                requires = packages[p].version_hints[vr].get('depends', [])
                 requires = [re.sub(r'(.*) +\(.*\)', r'\1', r) for r in requires]
 
                 o = None
@@ -642,7 +662,7 @@ def upgrade_oldstyle_obsoletes(packages, missing_obsolete):
 
                 else:
                     # ignore self-destruct packages
-                    provides = packages[p].version_hints[vr].get('provides', '')
+                    provides = packages[p].version_hints[vr].get('provides', [])
                     if '_self-destruct' in provides:
                         continue
 
@@ -690,7 +710,7 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
     for p in packages:
         valid_requires.add(p)
         for hints in packages[p].version_hints.values():
-            valid_requires.update(hints.get('provides', '').split())
+            valid_requires.update(hints.get('provides', []))
 
             # reset computed package state
             packages[p].has_requires = False
@@ -715,10 +735,7 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
             ]:
                 # if c is in hints, and not the empty string
                 if hints.get(c, ''):
-                    for r in hints[c].split(','):
-                        # remove any extraneous whitespace
-                        r = r.strip()
-
+                    for r in hints[c]:
                         # strip off any version relation enclosed in '()'
                         # following the package name
                         r = re.sub(r'(.*) +\(.*\)', r'\1', r)
@@ -764,15 +781,13 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
             if p in packages:
                 for v in packages[p].version_hints:
 
-                    obsoletes = packages[p].version_hints[v].get('obsoletes', '').split(',')
-                    obsoletes = [o.strip() for o in obsoletes]
-                    obsoletes = [o for o in obsoletes if o]
+                    obsoletes = packages[p].version_hints[v].get('obsoletes', [])
 
                     def add_needed_obsoletes(needed):
                         for n in sorted(needed):
                             if n not in obsoletes:
                                 obsoletes.append(n)
-                                packages[p].version_hints[v]['obsoletes'] = ', '.join(obsoletes)
+                                packages[p].version_hints[v]['obsoletes'] = obsoletes
                                 logging.info("added 'obsoletes: %s' to package '%s' version '%s'" % (n, p, v))
 
                             # recurse so we don't drop transitive missing obsoletes
@@ -791,10 +806,9 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
         # in read_hints(), so fix that up here.
     for p in sorted(packages):
         for hints in packages[p].version_hints.values():
-            obsoletes = hints.get('obsoletes', '')
+            obsoletes = hints.get('obsoletes', [])
             if obsoletes:
-                for o in obsoletes.split(','):
-                    o = o.strip()
+                for o in obsoletes:
                     o = re.sub(r'(.*) +\(.*\)', r'\1', o)
 
                     if o in packages:
@@ -802,10 +816,10 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
 
                         for (ov, ohints) in packages[o].version_hints.items():
                             if 'depends' in ohints:
-                                depends = ohints['depends'].split(', ')
+                                depends = ohints['depends']
                                 if p in depends:
                                     depends = [d for d in depends if d != p]
-                                    packages[o].version_hints[ov]['depends'] = ', '.join(depends)
+                                    packages[o].version_hints[ov]['depends'] = depends
                                     logging.debug("removed obsoleting '%s' from the depends: of package '%s'" % (p, o))
                     else:
                         logging.debug("can't ensure package '%s' doesn't depends: on obsoleting '%s'" % (o, p))
@@ -907,7 +921,7 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
                 if packages[p].tar(vr).is_empty:
                     # this classification relies on obsoleting packages
                     # not being present in depends
-                    if packages[p].version_hints[vr].get('depends', ''):
+                    if packages[p].version_hints[vr].get('depends', []):
                         # also allow '_obsolete' because old obsoletion
                         # packages depend on their replacement, but are not
                         # obsoleted by it
@@ -947,9 +961,7 @@ def validate_packages(args, packages, valid_provides_extra=None, missing_obsolet
                     ('obsoletes', 'obsoleted_by'),
             ]:
                 if k in hints:
-                    dpl = hints[k].split(',')
-                    for dp in dpl:
-                        dp = dp.strip()
+                    for dp in hints[k]:
                         dp = re.sub(r'(.*)\s+\(.*\)', r'\1', dp)
                         if dp in packages:
                             getattr(packages[dp], a).add(p)
@@ -1101,7 +1113,7 @@ def assign_importance(packages):
     # recursively give dependencies of base packages the basedep importance
     def recursive_basedep(p):
         bv = p.best_version
-        requires = p.version_hints[bv].get('depends', '').split(', ')
+        requires = p.version_hints[bv].get('depends', [])
         requires = [re.sub(r'(.*) +\(.*\)', r'\1', r) for r in requires]
         for r in requires:
             if r in packages:
@@ -1351,27 +1363,26 @@ def write_setup_ini(args, packages, arch):
 
                 if version in po.versions():
                     if hints.get('depends', ''):
-                        print("depends2: %s" % hints.get('depends', ''), file=f)
+                        print("depends2: %s" % ', '.join(hints.get('depends', [])), file=f)
 
                     if hints.get('obsoletes', ''):
-                        print("obsoletes: %s" % hints['obsoletes'], file=f)
+                        print("obsoletes: %s" % ', '.join(hints['obsoletes']), file=f)
 
                     if hints.get('provides', ''):
-                        print("provides: %s" % hints['provides'], file=f)
+                        print("provides: %s" % ', '.join(hints['provides']), file=f)
 
                     if hints.get('conflicts', ''):
-                        print("conflicts: %s" % hints['conflicts'], file=f)
+                        print("conflicts: %s" % ','.join(hints['conflicts']), file=f)
 
                 if s:
                     src_hints = packages[s].version_hints.get(version, {})
-                    bd = src_hints.get('build-depends', '')
+                    bd = src_hints.get('build-depends', [])
 
                     # Ideally, we'd transform dependency atoms which aren't
                     # cygwin package names into package names. For the moment,
                     # we don't have the information to do that, so filter them
                     # all out.
-                    if bd:
-                        bd = [atom for atom in bd.split(', ') if '(' not in atom]
+                    bd = [atom for atom in bd if '(' not in atom]
 
                     if bd:
                         print("build-depends: %s" % ', '.join(bd), file=f)
@@ -1457,7 +1468,7 @@ def write_repo_json(args, packages, f):
             sp = {'name': sp, 'categories': hints.get('category', '').split()}
             for k in ['depends', 'provides', 'obsoletes']:
                 if hints.get(k, None):
-                    sp[k] = [d.strip() for d in hints[k].split(',')]
+                    sp[k] = hints[k]
             spl.append(sp)
         d['subpackages'] = spl
 
@@ -1642,7 +1653,7 @@ def mark_fn(packages, po, v, certain_age, vault_requests):
 
     # - if package depends on anything in expired_provides
     #
-    requires = po.version_hints[v].get('depends', '').split(', ')
+    requires = po.version_hints[v].get('depends', [])
     if any(ep in requires for ep in past_mistakes.expired_provides):
         logging.debug("package '%s' version '%s' not retained as it requires a provide known to be expired" % (pn, v))
         return Freshness.conditional
diff --git a/calm/past_mistakes.py b/calm/past_mistakes.py
index 4ab53c0..b9ffec9 100644
--- a/calm/past_mistakes.py
+++ b/calm/past_mistakes.py
@@ -277,6 +277,8 @@ old_style_obsolete_by = {
     'at-spi2-atk': 'libatk-bridge2.0_0',
     'idle3': 'idle39',
     'lighttpd-mod_trigger_b4_dl': 'lighttpd',
+    'python-gi-common': 'python3-gi',
+    'python-pyatspi-common': 'python3-pyatspi',
     'qt-gstreamer': 'libQtGStreamer1_0_0',
     # these are odd and only exist to record an optional dependency on the
     # language runtime (dynamically loaded at runtime), which is also noted in
@@ -291,6 +293,11 @@ old_style_obsolete_by = {
     'python3-.*': '',
     # these packages probably should be marked as self-destruct?
     'mate-utils': '',
+    'octave-octcdf': '',
+    'python-twisted-debuginfo': '',
     'texlive-collection-htmlxml': '',
+    'vte2.91': '',
     'w32api': '',
+    # self-destruct, or need to start to exist
+    'cron-debuginfo': '',
 }
diff --git a/calm/pkg2html.py b/calm/pkg2html.py
index 70b0aeb..c619bb9 100755
--- a/calm/pkg2html.py
+++ b/calm/pkg2html.py
@@ -248,12 +248,8 @@ def update_package_listings(args, packages):
                             if details[key].is_attr:
                                 value[arch] = getattr(pos[arch], key, set())
                             else:
-                                t = pos[arch].version_hints[pos[arch].best_version].get(key, None)
-
-                                if t:
-                                    value[arch] = set(t.split(', '))
-                                else:
-                                    value[arch] = set()
+                                t = pos[arch].version_hints[pos[arch].best_version].get(key, [])
+                                value[arch] = set(t)
                             values.update(value[arch])
 
                         if values:
diff --git a/calm/reports.py b/calm/reports.py
index eb1078b..0ff0b11 100644
--- a/calm/reports.py
+++ b/calm/reports.py
@@ -295,15 +295,15 @@ def provides_rebuild(args, packages, fn, provide_package, reportlist):
 
     if pp_package:
         pp_bv = pp_package.best_version
-        pp_provide = pp_package.version_hints[pp_bv]['provides']
+        pp_provide = pp_package.version_hints[pp_bv]['provides'][0]
         pp_provide_base = re.sub(r'\d+$', '', pp_provide)
 
         for p in packages[arch]:
             po = packages[arch][p]
             bv = po.best_version
 
-            depends = packages[arch][p].version_hints[bv]['depends'].split(', ')
-            depends = [re.sub(r'(.*) +\(.*\)', r'\1', r) for r in depends]
+            depends = packages[arch][p].version_hints[bv]['depends']
+            depends = utils.deplist_without_verrel(depends)
 
             for d in depends:
                 if not d.startswith(pp_provide_base):
@@ -350,12 +350,12 @@ def python_rebuild(args, packages, fn, reportlist):
     # XXX: look into how we can change this, after x86 is dropped
     arch = 'x86_64'
 
-    # assume that python3 depends on the latest python3n package
+    # assume that python3 depends only on the latest python3n package
     py_package = packages[arch].get('python3', None)
     if not py_package:
         return
 
-    latest_py = py_package.version_hints[py_package.best_version]['depends'].split(', ')[0]
+    latest_py = py_package.version_hints[py_package.best_version]['depends'][0]
 
     modules = {}
 
@@ -366,8 +366,8 @@ def python_rebuild(args, packages, fn, reportlist):
         if po.obsoleted_by:
             continue
 
-        depends = packages[arch][p].version_hints[bv]['depends'].split(', ')
-        depends = [re.sub(r'(.*) +\(.*\)', r'\1', r) for r in depends]
+        depends = packages[arch][p].version_hints[bv]['depends']
+        depends = utils.deplist_without_verrel(depends)
 
         for d in depends:
             # scan for a 'pythonnn' dependency
diff --git a/calm/utils.py b/calm/utils.py
index f6679fb..af2f5cb 100644
--- a/calm/utils.py
+++ b/calm/utils.py
@@ -204,8 +204,5 @@ def sendmail(hdr, msg):
 #
 # remove version-constrains from a list of dependencies
 #
-def deplist_without_verrel(dl):
-    dpl = dl.split(',')
-    dpl = [dp.strip() for dp in dpl]
-    dpl = [re.sub(r'(.*)\s+\(.*\)', r'\1', dp) for dp in dpl]
-    return dpl
+def deplist_without_verrel(dpl):
+    return [re.sub(r'(.*)\s+\(.*\)', r'\1', dp) for dp in dpl]
diff --git a/test/testdata/process_arch/packages.json.expected b/test/testdata/process_arch/packages.json.expected
index 2c41b14..bc50d46 100644
--- a/test/testdata/process_arch/packages.json.expected
+++ b/test/testdata/process_arch/packages.json.expected
@@ -411,7 +411,9 @@
  '            "arches": [\n'
  '                "x86_64"\n'
  '            ],\n'
- '            "build-depends": "cygwin-devel",\n'
+ '            "build-depends": [\n'
+ '                "cygwin-devel"\n'
+ '            ],\n'
  '            "name": "test-e",\n'
  '            "subpackages": [\n'
  '                {\n'
diff --git a/test/testdata/uploads/pkglist.expected b/test/testdata/uploads/pkglist.expected
index 72489ac..224e4bf 100644
--- a/test/testdata/uploads/pkglist.expected
+++ b/test/testdata/uploads/pkglist.expected
@@ -4,7 +4,7 @@
                     'Like it’s you’re Markup Language™ Nokogiri’s tool―that '
                     'Bézier."',
            'category': 'Devel',
-           'depends': 'cygwin'}}, {}, False),
+           'depends': ['cygwin']}}, {}, False),
  'testpackage-src': Package('testpackage', {'1.0-1': Tar('testpackage-1.0-1-src.tar.bz2', 'x86_64/release/testpackage', 'acfd77df3347e6432ccf29c12989964bc680a158d574f85dfa7ef222759f411006c7bd2773e37c5abdee628bea769b2da9aae213db615cd91402fd385373933d', 266, False)}, {'1.0-1': {'sdesc': '"A test package"',
            'ldesc': '"A test package\n'
                     "It's description might contains some unicode junk\n"
@@ -13,25 +13,25 @@
            'category': 'Devel',
            'homepage': 'http://homepage.url',
            'parse-warnings': ["key 'license' missing"],
-           'depends': ''}}, {}, False),
+           'depends': []}}, {}, False),
  'testpackage-subpackage': Package('testpackage/testpackage-subpackage', {'1.0-1': Tar('testpackage-subpackage-1.0-1.tar.bz2', 'x86_64/release/testpackage/testpackage-subpackage', 'aff488008bee3486e25b539fe6ccd1397bd3c5c0ba2ee2cf34af279554baa195af7493ee51d6f8510735c9a2ea54436d776a71e768165716762aec286abbbf83', 195, False)}, {'1.0-1': {'sdesc': '"A test subpackage"',
            'ldesc': '"A test subpackage"',
            'category': 'Devel',
            'external-source': 'testpackage-src',
-           'depends': ''}}, {}, False),
+           'depends': []}}, {}, False),
  'testpackage-zstd': Package('testpackage-zstd', {'1.0-1': Tar('testpackage-zstd-1.0-1.tar.zst', 'x86_64/release/testpackage-zstd', '044066c54c036190f9b0496ccf31f74748d209cce961352e19631876d5abd79ef6d2b34edfb955b8d1a7a781294ee0636bb1305afe410b34562367a2cb77988d', 98, False)}, {'1.0-1': {'category': 'Base',
            'sdesc': '"test package (zstd compressed)"',
            'ldesc': '"test package (zstd compressed)"',
-           'depends': ''}}, {}, False),
+           'depends': []}}, {}, False),
  'testpackage-zstd-src': Package('testpackage-zstd', {'1.0-1': Tar('testpackage-zstd-1.0-1-src.tar.zst', 'x86_64/release/testpackage-zstd', '90561ec4dad76268773856cbdda891b0e7b53f26492777f1ff76757844cb47124396feb76f1e30bc1baa680f1d788de21d89e612faeb30b5039b210ca9186434', 313, False)}, {'1.0-1': {'category': 'Base',
-           'build-depends': 'cygport',
+           'build-depends': ['cygport'],
            'sdesc': '"test package (zstd compressed)"',
            'ldesc': '"test package (zstd compressed)"',
            'homepage': 'http://zstd.testpkg.invalid',
            'skip': '',
            'parse-warnings': ["key 'license' missing"],
-           'depends': ''}}, {}, False),
+           'depends': []}}, {}, False),
  'testpackage2-subpackage': Package('testpackage2/testpackage2-subpackage', {'1.0-1': Tar('testpackage2-subpackage-1.0-1.tar.bz2', 'x86_64/release/testpackage2/testpackage2-subpackage', 'c4bf8e28d71b532e2b741e2931906dec0f0a70d4d051c0503476f864a5228f43765ae3342aafcebfd5a1738073537726b2bfbbd89c6da939a5f46d95aca3feaf', 46, True)}, {'1.0-1': {'sdesc': '"A test subpackage 2"',
            'ldesc': '"A test subpackage 2"',
            'category': 'Devel',
-           'depends': ''}}, {}, False)}
+           'depends': []}}, {}, False)}



More information about the Cygwin-apps-cvs mailing list