Aluode/PerceptionLabPortable
0
1from __future__ import annotations2 3import os4from typing import ClassVar5 6from .. import Command, _shutil7 8from distutils import log9from distutils.errors import DistutilsOptionError10from distutils.util import convert_path11 12 13class rotate(Command):14 """Delete older distributions"""15 16 description = "delete older distributions, keeping N newest files"17 user_options = [18 ('match=', 'm', "patterns to match (required)"),19 ('dist-dir=', 'd', "directory where the distributions are"),20 ('keep=', 'k', "number of matching distributions to keep"),21 ]22 23 boolean_options: ClassVar[list[str]] = []24 25 def initialize_options(self):26 self.match = None27 self.dist_dir = None28 self.keep = None29 30 def finalize_options(self) -> None:31 if self.match is None:32 raise DistutilsOptionError(33 "Must specify one or more (comma-separated) match patterns "34 "(e.g. '.zip' or '.egg')"35 )36 if self.keep is None:37 raise DistutilsOptionError("Must specify number of files to keep")38 try:39 self.keep = int(self.keep)40 except ValueError as e:41 raise DistutilsOptionError("--keep must be an integer") from e42 if isinstance(self.match, str):43 self.match = [convert_path(p.strip()) for p in self.match.split(',')]44 self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))45 46 def run(self) -> None:47 self.run_command("egg_info")48 from glob import glob49 50 for pattern in self.match:51 pattern = self.distribution.get_name() + '*' + pattern52 files = glob(os.path.join(self.dist_dir, pattern))53 files = [(os.path.getmtime(f), f) for f in files]54 files.sort()55 files.reverse()56 57 log.info("%d file(s) matching %s", len(files), pattern)58 files = files[self.keep :]59 for t, f in files:60 log.info("Deleting %s", f)61 if not self.dry_run:62 if os.path.isdir(f):63 _shutil.rmtree(f)64 else:65 os.unlink(f)66 