changeset 83:05e2bf4796fd

Add an option "--checklist-allow-distinfo" to allow FreeBSD "distinfo" formatted files as checkfiles. This effectively ignores SIZE() and TIMESTAMP = like lines instead of throwing errors. This allows to use a package's distinfo file directoy as checkfile.
author Franz Glasner <f.glasner@feldmann-mg.com>
date Thu, 10 Mar 2022 16:17:53 +0100
parents 7ddc249404d5
children 163de6dd6e05
files cutils/shasum.py
diffstat 1 files changed, 28 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/cutils/shasum.py	Tue Mar 01 09:26:38 2022 +0100
+++ b/cutils/shasum.py	Thu Mar 10 16:17:53 2022 +0100
@@ -79,6 +79,10 @@
         help="""Compare the checksum of each FILE against the checksums in
 the CHECKLIST. Any specified FILE that is not listed in the CHECKLIST will
 generate an error.""")
+    aparser.add_argument(
+        "--checklist-allow-distinfo", action="store_true",
+        dest="allow_distinfo",
+        help='Allow FreeBSD "distinfo" formatted checklists: ignore SIZE and TIMESTAMP lines.')
 
     aparser.add_argument(
         "--reverse", "-r", action="store_false", dest="bsd", default=False,
@@ -260,6 +264,9 @@
             if not checkline:
                 continue
             r, fn, tag = handle_checkline(opts, checkline)
+            if tag in ("SIZE", "TIMESTAMP"):
+                assert opts.allow_distinfo
+                continue
             print("{}: {}: {}".format(tag, fn, r.upper()), file=dest)
             if r != "ok" and exit_code == 0:
                 exit_code = 1
@@ -270,6 +277,9 @@
                     if not checkline:
                         continue
                     r, fn, tag = handle_checkline(opts, checkline)
+                    if tag in ("SIZE", "TIMESTAMP"):
+                        assert opts.allow_distinfo
+                        continue
                     print("{}: {}: {}".format(tag, fn, r.upper()), file=dest)
                     if r != "ok" and exit_code == 0:
                         exit_code = 1
@@ -288,6 +298,9 @@
         raise ValueError(
             "improperly formatted digest line: {}".format(line))
     tag, algo, fn, digest = parts
+    if tag in ("SIZE", "TIMESTAMP"):
+        assert opts.allow_distinfo
+        return (None, None, tag)
     try:
         d = compute_digest_file(algo, fn)
         if compare_digests_equal(d, digest, algo):
@@ -312,6 +325,9 @@
             if not parts:
                 raise ValueError(
                     "improperly formatted digest line: {}".format(checkline))
+            if parts[0] in ("SIZE", "TIMESTAMP"):
+                assert opts.allow_distinfo
+                continue
             fn = normalize_filename(parts[2], strip_leading_dot_slash=True)
             if fn in filenames:
                 return parts
@@ -322,6 +338,10 @@
 def parse_digest_line(opts, line):
     """Parse a `line` of a digest file and return its parts.
 
+    This is rather strict. But if `opts.allow_distinfo` is `True` then
+    some additional keywords ``SIZE`` and ``TIMESTAMP``are recignized
+    and returned. The caller is responsible to handle them.
+
     :return: a tuple of the normalized algorithm tag, the algorithm
              constructor, the filename and the hex digest;
              if `line` cannot be parsed successfully `None` is returned
@@ -335,11 +355,19 @@
     mo = re.search(r"\A(\S+)\s*\((.*)\)\s*=\s*(.+)\n?\Z", line)
     if mo:
         # (tag, algorithm, filename, digest)
+        if opts.allow_distinfo:
+            if mo.group(1) == "SIZE":
+                return ("SIZE", None, None, mo.group(3))
         return (mo.group(1),
                 algotag2algotype(mo.group(1)),
                 mo.group(2),
                 mo.group(3))
     else:
+        if opts.allow_distinfo:
+            mo = re.search(r"\ATIMESTAMP\s*=\s*([0-9]+)\s*\n\Z", line)
+            if mo:
+                return ("TIMESTAMP", None, None, mo.group(1))
+
         # coreutils?
         mo = re.search(r"([^\ ]+) [\*\ ]?(.+)\n?\Z", line)
         if mo: