diff options
Diffstat (limited to 'abs/core/LinHES-system/cacheclean')
| -rwxr-xr-x | abs/core/LinHES-system/cacheclean | 134 | 
1 files changed, 134 insertions, 0 deletions
| diff --git a/abs/core/LinHES-system/cacheclean b/abs/core/LinHES-system/cacheclean new file mode 100755 index 0000000..d32d16b --- /dev/null +++ b/abs/core/LinHES-system/cacheclean @@ -0,0 +1,134 @@ +#!/usr/bin/env python +"""cacheclean - a simple python script to clean up the /data/var/cache/pacman/pkg directory. +More versatile than 'pacman -Sc' in that you can select how many old versions +to keep. +Usage: cacheclean {-p} {-v} <# of copies to keep> +    # of copies to keep - (required) how many generations of each package to keep +    -p - (optional) preview what would be deleted; forces verbose (-v) mode. +    -v - (optional) show deleted packages. +     +Adapted from https://github.com/graysky2/cacheclean for LinHES pacman cache directories +and python 2.6.""" + +# Note that the determination of package age is done by simply looking at the date-time +# modified stamp on the file. There is just enough variation in the way package version +# is done that I thought this would be simpler & just as good. +# Also note that you must be root to run this script. + +import getopt +import os +import re +import sys + +# helper function to get tuple of (file dtm, file name, file sz)     +def fn_stats(fn): +    s = os.stat(fn) +    return (s[8], fn, s[6]) + +# cleanup does the actual pkg file deletion +def cleanup(run_list): +    # strictly speaking only the first two of these globals need to be listed. +    global n_deleted, bytes_deleted, opt_verbose, opt_preview, n_to_keep +    # return if the run_list is too short +    #print run_list +    #return +    if len(run_list) <= n_to_keep: return +    # Build list of tuples (date-time file modified, file name, file size) +    dtm_list = [fn_stats(tfn) for tfn in run_list] +    # Sort the list by date-time +    dtm_list.sort() +    # Build list of the filenames to delete (all but last n_to_keep). +    # <showing_off> +    #kill_list = [tfn[1] for tfn in dtm_list[:-n_to_keep]] +    #bytes_deleted = sum(x[2] for x in dtm_list[:-n_to_keep]) +    # </showing_off> +    kill_list = [] +    for x in dtm_list[:-n_to_keep]: +        if os.path.isfile(x[1]): +            kill_list.append(x[1]) +            bytes_deleted += x[2] +    if opt_verbose and kill_list: print (kill_list) +    n_deleted += len(kill_list) +    # and finally delete (if not in preview mode) +    if not opt_preview: +        for dfn in kill_list: +            os.unlink(dfn) + +###################################################################### +# mainline processing + +# process command line options +try: +    opts, pargs = getopt.getopt(sys.argv[1:], 'vp') +    opt_dict = dict(opts) +    opt_preview = '-p' in opt_dict +    opt_verbose = '-v' in opt_dict +    if opt_preview: opt_verbose = True +    if len(pargs) == 1: +        n_to_keep = pargs[0] +    else: +        raise getopt.GetoptError("missing required argument.") +    try: +        n_to_keep = int(n_to_keep) +        if n_to_keep <= 0: raise ValueError +    except ValueError as e: +        raise getopt.GetoptError("# of copies to keep must be numeric > 0!") +except getopt.GetoptError as msg: +    print ("Error:",msg,"\n",__doc__) +    sys.exit(1) + +# change to the pkg directory & get a sorted list of its contents +os.chdir('/data/var/cache/pacman/pkg') +pkg_fns = os.listdir('.') +pkg_fns.sort() + +# Pattern to use to extract the package name from the tar file name: +# for pkg e.g. 'gnome-common-2.8.0-1-i686.pkg.tar.gz' group(1) is 'gnome-common'. + +bpat = re.compile(""" +^([^-/][^/]*?)-         # (1) package name +[^-/\s]+-               # (2) version +[^-/\s]+                # (3) release +(-i686|-x86_64|-any)?   # (4) architecture +\.pkg\.tar              # (5) extension +(?:\.(?:gz|bz2|xz|Z))?  # (6) compresssion extension +(?:\.aria2|.sig)?       # (7) other extension +(?:\.part)?$            # (8) partially-downloaded files' extension +""", re.X) + +n_deleted = 0 +bytes_deleted = 0 +pkg_base_nm = '' +# now look for "runs" of the same package name differing only in version info. +for run_end in range(len(pkg_fns)): +    fn = pkg_fns[run_end] + +    # make sure we skip directories +    if os.path.isfile(fn): +        mo = bpat.match(fn) # test for a match of the package name pattern +        if mo: +            # print ("Processing file '" + fn + "' " + str(mo.lastindex), file=sys.stdout) +            tbase = mo.group(1) # gets the 'base' package name +            # include the architecture in the name if it's present +            if mo.group(2) is not None: +                tbase += mo.group(2) +            # print ('tbase: ' + tbase + '  ' + str(mo.lastindex), file=sys.stdout) +            # is it a new base name, i.e. the start of a new run? +            if tbase != pkg_base_nm: # if so then process the prior run +                if pkg_base_nm != '': +                    cleanup(pkg_fns[run_start:run_end]) +                pkg_base_nm = tbase # & setup for the new run +                run_start = run_end +        else: +            print >>sys.stderr, "File '"+fn+"' doesn't match package pattern!" +    else: +        print >>sys.stdout, "skipping directory '"+fn+"'!" + +# catch the final run of the list +run_end += 1 +cleanup(pkg_fns[run_start:run_end]) + +if opt_verbose: +    if opt_preview: +        print ("Preview mode (no files deleted):"), +    print n_deleted,"files deleted,",bytes_deleted/(2**10),"kbytes /",bytes_deleted/(2**20),"MBytes /",bytes_deleted/(2**30), "GBytes." | 
