From ab2b92bf6743790902c68e764b7e28b4aa0a681a Mon Sep 17 00:00:00 2001
From: Britney Fransen <brfransen@gmail.com>
Date: Sat, 14 Apr 2012 15:44:45 -0500
Subject: LinHES-system: add cacheclean and cron job to keep 3 newest pkgs in
 pacman cache.

---
 abs/core/LinHES-system/PKGBUILD        |  13 ++--
 abs/core/LinHES-system/cacheclean      | 134 +++++++++++++++++++++++++++++++++
 abs/core/LinHES-system/cacheclean.cron |   2 +
 3 files changed, 144 insertions(+), 5 deletions(-)
 create mode 100755 abs/core/LinHES-system/cacheclean
 create mode 100644 abs/core/LinHES-system/cacheclean.cron

diff --git a/abs/core/LinHES-system/PKGBUILD b/abs/core/LinHES-system/PKGBUILD
index f8baeaf..94f592d 100644
--- a/abs/core/LinHES-system/PKGBUILD
+++ b/abs/core/LinHES-system/PKGBUILD
@@ -1,6 +1,6 @@
 pkgname=LinHES-system
 pkgver=2
-pkgrel=41
+pkgrel=42
 arch=('i686')
 MVDIR=$startdir/pkg/usr/LH
 BINDIR=$startdir/pkg/usr/bin
@@ -20,11 +20,11 @@ binfiles="LinHES-start optimize_mythdb.py
  lh_system_host_update
  lh_system_all_host_update
  add_storage.py
- diskspace.sh"
+ diskspace.sh
+ cacheclean"
 
 source=(LinHES-session LinHES-profile.sh $binfiles alsa-base myth_mtc.lr 
- diskspace smolt.cron)
-
+ diskspace smolt.cron cacheclean.cron)
 build() {
         cd $startdir/src
         install -m755 -D LinHES-session $startdir/pkg/etc/X11/Sessions/LinHES
@@ -47,6 +47,7 @@ build() {
 
         install -m644 -D $startdir/src/alsa-base $startdir/pkg/etc/modprobe.d/alsa-base.conf
         install -m755 -D $startdir/src/smolt.cron $startdir/pkg/etc/cron.weekly/smolt.cron
+        install -m755 -D $startdir/src/cacheclean.cron $startdir/pkg/etc/cron.weekly/cacheclean.cron
         install -m755 -D $startdir/src/diskspace $startdir/pkg/etc/cron.tenminutes/diskspace
         mkdir $startdir/pkg/etc/logrotate.d
         cp $startdir/myth_mtc.lr $startdir/pkg/etc/logrotate.d
@@ -74,7 +75,9 @@ md5sums=('d6a564f3286590875874573107940908'
          '47e093e8cfe4b5b96602358e1f540832'
          '6faeba0aeb38e772121f751cabda8683'
          '68e3e87571f3b0fa4a48a10df50dc220'
+         '9603b0ca6e090eff31e76482a3c335e7'
          'eb879fee9603a05d5420d4ce8ed9e450'
          'f1870a9522c79e6b248fcbf81dec3280'
          '84492954db16740f949d795b74383189'
-         'abe887472a170bd1a8e6da6a7b7e93e4')
+         'abe887472a170bd1a8e6da6a7b7e93e4'
+         '02c810c2f47b7c4495fdacaf54189473')
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."
diff --git a/abs/core/LinHES-system/cacheclean.cron b/abs/core/LinHES-system/cacheclean.cron
new file mode 100644
index 0000000..b47a3ef
--- /dev/null
+++ b/abs/core/LinHES-system/cacheclean.cron
@@ -0,0 +1,2 @@
+#!/bin/bash
+/usr/LH/bin/cacheclean 3
-- 
cgit v0.12

