Browse Source

Cache management

Valentin Niess 7 months ago
parent
commit
2f663acc32

+ 20 - 5
python_appimage/__main__.py

@@ -34,16 +34,31 @@ def main():
     parser.add_argument('-v', '--verbose', help='print extra information',
         dest='verbosity', action='store_const', const='DEBUG')
 
-    install_parser = subparsers.add_parser('install',
-        description='Install binary dependencies')
-    install_parser.add_argument('binary', nargs='+',
-        choices=binaries, help='one or more binary name')
-
     build_parser = subparsers.add_parser('build',
         description='Build a Python appimage')
     build_subparsers = build_parser.add_subparsers(title='type',
         help='Type of AppImage build', dest='sub_command')
 
+    cache_parser = subparsers.add_parser('cache',
+        description='Manage Python appimage cache')
+    cache_subparsers = cache_parser.add_subparsers(title='operation',
+        help='Type of cache operation', dest='sub_command')
+
+    cache_clean_parser = cache_subparsers.add_parser('clean',
+        description='Clean cached image(s)')
+    cache_clean_parser.add_argument('tags', nargs='*',
+        help='manylinux image tag(s) (e.g. 2014_x86_64)')
+    cache_clean_parser.add_argument('-a', '--all', action='store_true',
+        help='remove all image(s) data')
+
+    cache_list_parser = cache_subparsers.add_parser('list',
+        description='List cached image(s)')
+
+    install_parser = subparsers.add_parser('install',
+        description='Install binary dependencies')
+    install_parser.add_argument('binary', nargs='+',
+        choices=binaries, help='one or more binary name')
+
     build_local_parser = build_subparsers.add_parser('local',
         description='Bundle a local Python installation')
     build_local_parser.add_argument('-d', '--destination',

+ 0 - 0
python_appimage/commands/cache/__init__.py


+ 64 - 0
python_appimage/commands/cache/clean.py

@@ -0,0 +1,64 @@
+import glob
+import json
+import os
+from pathlib import Path
+import subprocess
+
+from ...utils.deps import CACHE_DIR
+from ...utils.fs import remove_file, remove_tree
+from ...utils.log import log
+
+
+__all__ = ['execute']
+
+
+def _unpack_args(args):
+    '''Unpack command line arguments
+    '''
+    return (args.tags, args.all)
+
+
+def execute(images, all_):
+    '''Clean cached image(s)
+    '''
+
+    cache = Path(CACHE_DIR)
+
+    if not images:
+        images = [image[9:] for image in sorted(os.listdir(cache /
+                                                         'share/images'))]
+
+    for image in images:
+        try:
+            image, tag = image.rsplit(':', 1)
+        except ValueError:
+            tag = None
+
+        if not image.replace('_', '').isalnum():
+            raise ValueError(f'bad image tag ({image})')
+
+        path = cache / f'share/images/manylinux{image}'
+        if not path.exists():
+            raise ValueError(f'no such image ({image})')
+
+        if tag is None:
+            if not all_:
+                path = path / 'extracted'
+            remove_tree(str(path))
+        else:
+            tag_file = path / f'tags/{tag}.json'
+            if not tag_file.exists():
+                raise ValueError(f'no such image ({image}:{tag})')
+
+            if all_:
+                with tag_file.open() as f:
+                    layers = json.load(f)["layers"]
+                for layer in layers:
+                    layer = path / f'layers/{layer}.tar.gz'
+                    if layer.exists():
+                        remove_file(str(layer))
+                remove_file(str(tag_file))
+            else:
+                path = cache / f'share/images/{image}/extracted/{tag}'
+                if path.exists():
+                    remove_tree(str(path))

+ 41 - 0
python_appimage/commands/cache/list.py

@@ -0,0 +1,41 @@
+import glob
+import os
+from pathlib import Path
+import subprocess
+
+from ...utils.deps import CACHE_DIR
+from ...utils.log import log
+
+
+__all__ = ['execute']
+
+
+def _unpack_args(args):
+    '''Unpack command line arguments
+    '''
+    return tuple()
+
+
+def execute():
+    '''List cached image(s)
+    '''
+
+    cache = Path(CACHE_DIR)
+
+    images = sorted(os.listdir(cache / 'share/images'))
+    for image in images:
+        tags = ', '.join((
+            tag[:-5] for tag in \
+                sorted(os.listdir(cache / f'share/images/{image}/tags'))
+        ))
+        if not tags:
+            continue
+        path = cache / f'share/images/{image}'
+        memory = _getsize(path)
+        log('LIST', f'{image} ({tags}) [{memory}]')
+
+
+def _getsize(path: Path):
+    r = subprocess.run(f'du -sh {path}', capture_output=True, check=True,
+                       shell=True)
+    return r.stdout.decode().split(None, 1)[0]

+ 2 - 2
python_appimage/manylinux/download.py

@@ -117,8 +117,8 @@ class Downloader:
         with tempfile.TemporaryDirectory() as tmpdir:
             workdir = Path(tmpdir)
             for i, hash_ in enumerate(missing):
-                log('DOWNLOAD', f'{self.image} ({tag}) '
-                                f'[{i + 1} / {len(missing)}]')
+                debug('DOWNLOAD', f'{self.image}:{tag} '
+                                  f'[{i + 1} / {len(missing)}]')
 
                 filename = f'{hash_}.tar.gz'
                 url = f'https://quay.io/v2/{repository}/blobs/sha256:{hash_}'