public inbox for cygwin-apps-cvs@sourceware.org
help / color / mirror / Atom feed
* [calm - Cygwin server-side packaging maintenance script] branch master, updated. 20221205-2-g8579fcf
@ 2022-12-14 13:24 Jon TURNEY
  0 siblings, 0 replies; only message in thread
From: Jon TURNEY @ 2022-12-14 13:24 UTC (permalink / raw)
  To: cygwin-apps-cvs




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

commit 8579fcf737b93dd4b60cb42f2f1cb782a3886bd6
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Fri Sep 16 17:56:56 2022 +0100

    Treat sha512.sum as a cache for sha512 computation
    
    Rather than treating the sha512.sum file as (kind of) part of the
    package, just treat it as a cache for sha512 computation of files in
    the same directory.
    
    Also use the mtime_cache decorator to avoid parsing sha512.sum files
    which haven't changed.

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

commit 56f16534dd1a0a63f3a5069ca13fe5d5aa7df691
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Fri Dec 9 14:35:37 2022 +0000

    Add a simple wrapper for caching a parsed file until mtime changes


Diff:
---
 calm/package.py | 76 +++++++++++++++++++++++++++++++++------------------------
 calm/utils.py   | 33 +++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 32 deletions(-)

diff --git a/calm/package.py b/calm/package.py
index 43fc4cc..d3b5ab0 100755
--- a/calm/package.py
+++ b/calm/package.py
@@ -44,6 +44,7 @@ from . import common_constants
 from . import hint
 from . import maintainers
 from . import past_mistakes
+from . import utils
 from .movelist import MoveList
 from .version import SetupVersion
 
@@ -159,7 +160,7 @@ def read_packages(rel_area, arch):
 
 # helper function to compute sha512 for a particular file
 # (block_size should be some multiple of sha512 block size which can be efficiently read)
-def sha512_file(fn, block_size=256 * 128):
+def sha512_file_hash(fn, block_size=256 * 128):
     sha512 = hashlib.sha512()
 
     with open(fn, 'rb') as f:
@@ -169,6 +170,41 @@ def sha512_file(fn, block_size=256 * 128):
     return sha512.hexdigest()
 
 
+# helper function to parse a sha512.sum file
+@utils.mtime_cache
+def sha512sum_file_read(sum_fn):
+    sha512 = {}
+    with open(sum_fn) as fo:
+        for l in fo:
+            match = re.match(r'^(\S+)\s+(?:\*|)(\S+)$', l)
+            if match:
+                sha512[match.group(2)] = match.group(1)
+            else:
+                logging.warning("bad line '%s' in checksum file %s" % (l.strip(), sum_fn))
+
+    return sha512
+
+
+# helper function to determine sha512 for a particular file
+#
+# read sha512 checksum from a sha512.sum file, if present, otherwise compute it
+def sha512_file(fn):
+    (dirname, basename) = os.path.split(fn)
+    sum_fn = os.path.join(dirname, 'sha512.sum')
+    if os.path.exists(sum_fn):
+        sha512 = sha512sum_file_read(sum_fn)
+        if basename in sha512:
+            return sha512[basename]
+        else:
+            logging.debug("no line for file %s in checksum file %s" % (basename, sum_fn))
+    else:
+        logging.debug("no sha512.sum in %s" % dirname)
+
+    sha512 = sha512_file_hash(fn)
+    logging.debug("computed sha512 hash for %s is %s" % (basename, sha512))
+    return sha512
+
+
 # process a list of package version-constraints
 def process_package_constraint_list(pcl):
     # split, keeping optional version-relation, trim and sort
@@ -264,31 +300,27 @@ def read_package_dir(packages, basedir, dirpath, files, upload=False):
     # the package name is always the directory name
     p = os.path.basename(dirpath)
 
+    # ignore dotfiles, backup files and checksum files
+    for f in files[:]:
+        if f.startswith('.') or f.endswith('.bak') or f == 'sha512.sum':
+            files.remove(f)
+
     # no .hint files
     if not any([f.endswith('.hint') for f in files]):
         if (relpath.count(os.path.sep) > 1):
-            for s in ['sha512.sum']:
-                if s in files:
-                    files.remove(s)
-
             if len(files) > 0:
                 logging.error("no .hint files in %s but has files: %s" % (dirpath, ', '.join(files)))
                 return True
 
         return False
 
-    # ignore dotfiles and backup files
-    for f in files[:]:
-        if f.startswith('.') or f.endswith('.bak'):
-            files.remove(f)
-
     # classify files for which kind of package they belong to
     fl = {}
     for kind in list(Kind) + ['all']:
         fl[kind] = []
 
     for f in files[:]:
-        if f == 'sha512.sum' or f == 'override.hint':
+        if f == 'override.hint':
             fl['all'].append(f)
             files.remove(f)
         elif re.match(r'^' + re.escape(p) + r'.*\.hint$', f):
@@ -358,21 +390,6 @@ def read_one_package(packages, p, relpath, dirpath, files, kind, strict):
     else:
         override_hints = {}
 
-    # read sha512.sum
-    sha512 = {}
-    if 'sha512.sum' not in files:
-        logging.debug("no sha512.sum for package '%s'" % p)
-    else:
-        files.remove('sha512.sum')
-
-        with open(os.path.join(dirpath, 'sha512.sum')) as fo:
-            for l in fo:
-                match = re.match(r'^(\S+)\s+(?:\*|)(\S+)$', l)
-                if match:
-                    sha512[match.group(2)] = match.group(1)
-                else:
-                    logging.warning("bad line '%s' in sha512.sum for package '%s'" % (l.strip(), p))
-
     # build a list of version-releases (since replacement pvr.hint files are
     # allowed to be uploaded, we must consider both .tar and .hint files for
     # that), and collect the attributes for each tar file
@@ -437,12 +454,7 @@ def read_one_package(packages, p, relpath, dirpath, files, kind, strict):
             t.size = os.path.getsize(os.path.join(dirpath, f))
             t.is_empty = tarfile_is_empty(os.path.join(dirpath, f))
             t.mtime = os.path.getmtime(os.path.join(dirpath, f))
-
-            if f in sha512:
-                t.sha512 = sha512[f]
-            else:
-                t.sha512 = sha512_file(os.path.join(dirpath, f))
-                logging.debug("no sha512.sum line for file %s in package '%s', computed sha512 hash is %s" % (f, p, t.sha512))
+            t.sha512 = sha512_file(os.path.join(dirpath, f))
 
             tars[vr] = t
 
diff --git a/calm/utils.py b/calm/utils.py
index fb95cc6..9f75813 100644
--- a/calm/utils.py
+++ b/calm/utils.py
@@ -125,3 +125,36 @@ def system(args):
     else:
         for l in output.decode().splitlines():
             logging.info(l)
+
+
+#
+# This provides a simple wrapper around a function which takes a pathname as
+# it's only parameter.  The result is cached as long as the mtime of the
+# pathname is unchanged.
+#
+def mtime_cache(user_function):
+    sentinel = object()          # unique object used to signal cache misses
+    cache = {}
+
+    def wrapper(key):
+        # make sure path is absolute
+        key = os.path.abspath(key)
+
+        (result, mtime) = cache.get(key, (sentinel, 0))
+
+        new_mtime = os.path.getmtime(key)
+
+        # cache hit
+        if result is not sentinel:
+            # cache valid
+            if new_mtime == mtime:
+                return result
+            else:
+                logging.debug('%s cache invalidated by mtime change' % key)
+
+        # cache miss
+        result = user_function(key)
+        cache[key] = (result, new_mtime)
+        return result
+
+    return wrapper


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-14 13:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-14 13:24 [calm - Cygwin server-side packaging maintenance script] branch master, updated. 20221205-2-g8579fcf Jon TURNEY

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).