Mercurial > treepkg
comparison contrib/bin/delete-old-debs.py @ 535:fb7a900a649f
contrib: Added script to remove old deb files from directories.
author | Sascha Teichmann <teichmann@intevation.de> |
---|---|
date | Sat, 08 Jan 2011 12:57:07 +0000 |
parents | |
children | 8a61185a3357 |
comparison
equal
deleted
inserted
replaced
534:09fcac0bdc25 | 535:fb7a900a649f |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: UTF-8 -*- | |
3 # | |
4 # Copyright (C) 2011 by Intevation GmbH | |
5 # Authors: | |
6 # Sascha L. Teichmann <sascha.teichmann@intevation.de> | |
7 # | |
8 # This program is free software under the GPL (>=v2) | |
9 # Read the file COPYING coming with the software for details. | |
10 | |
11 import sys | |
12 import os | |
13 import re | |
14 | |
15 import subprocess | |
16 import logging | |
17 | |
18 from heapq import nsmallest | |
19 | |
20 from optparse import OptionParser | |
21 | |
22 log = logging.getLogger(__name__) | |
23 log.setLevel(logging.WARNING) | |
24 log.addHandler(logging.StreamHandler(sys.stderr)) | |
25 | |
26 DEFAULT_KEEP = 3 | |
27 | |
28 FIELD = re.compile("([a-zA-Z]+):\s*(.+)") | |
29 | |
30 # map rich comparison to 'dpkg --compare-versions' | |
31 # map == to !=, < to >= and so on to reverse order in heap. | |
32 RICH_CMP = dict([ | |
33 ("__%s__" % a, lambda se, ot: | |
34 subprocess.call([ | |
35 "dpkg", "--compare-versions", | |
36 se.version, b, ot.version]) == 0) | |
37 for a, b in (("eq", "ne"), ("ne", "eq"), | |
38 ("lt", "ge"), ("gt", "le"), | |
39 ("le", "gt"), ("ge", "lt"))]) | |
40 | |
41 | |
42 class DebCmp(object): | |
43 """Helper class to make deb files comparable | |
44 by there versions. | |
45 """ | |
46 | |
47 def __init__(self, version, path): | |
48 self.version = version | |
49 self.path = path | |
50 | |
51 self.__dict__.update(RICH_CMP) | |
52 | |
53 | |
54 def deb_info(deb, fields=["Package", "Version"]): | |
55 """Extract some meta info from a deb file.""" | |
56 po = subprocess.Popen( | |
57 ["dpkg-deb", "-f", deb] + fields, | |
58 stdout=subprocess.PIPE) | |
59 out = po.communicate()[0] | |
60 return dict([m.groups() | |
61 for m in map(FIELD.match, out.splitlines()) if m]) | |
62 | |
63 | |
64 def oldest_debs(deb_dir, keep=DEFAULT_KEEP): | |
65 """Given directory containing deb files this function | |
66 returns the files that are older than the youngest | |
67 keep-th per package. | |
68 """ | |
69 | |
70 log.info("scanning dir '%s'" % deb_dir) | |
71 | |
72 packages = {} | |
73 | |
74 num = 1 | |
75 for f in os.listdir(deb_dir): | |
76 if not f.endswith(".deb"): continue | |
77 deb = os.path.join(deb_dir, f) | |
78 if not os.path.isfile(deb): continue | |
79 info = deb_info(deb) | |
80 packages.setdefault(info['Package'], []).append( | |
81 DebCmp(info['Version'], deb)) | |
82 if (num % 10) == 0: | |
83 log.info("%d debs found" % (num-1)) | |
84 num += 1 | |
85 | |
86 if log.isEnabledFor(logging.INFO): | |
87 log.info("%d debs found" % (num-1)) | |
88 log.info("number packages: %s" % len(packages)) | |
89 | |
90 for package, debs in packages.iteritems(): | |
91 if len(debs) > keep: | |
92 # full sorting is not required | |
93 stay = frozenset([d.path for d in nsmallest(keep, debs)]) | |
94 | |
95 for deb in debs: | |
96 if deb.path not in stay: | |
97 yield deb.path | |
98 | |
99 | |
100 def main(): | |
101 usage = "usage: %prog [options] dir ..." | |
102 parser = OptionParser(usage=usage) | |
103 parser.add_option( | |
104 "-v", "--verbose", action="store_true", | |
105 dest="verbose", | |
106 help="verbose output") | |
107 parser.add_option( | |
108 "-d", "--dry-run", action="store_true", | |
109 dest="dry_run", | |
110 help="don't remove the old deb files") | |
111 parser.add_option( | |
112 "-k", "--keep", action="store", | |
113 dest="keep", type="int", default=DEFAULT_KEEP, | |
114 help="number of files to keep. Default: %d" % DEFAULT_KEEP) | |
115 | |
116 options, args = parser.parse_args() | |
117 | |
118 remove = options.dry_run and (lambda x: None) or os.remove | |
119 keep = max(1, options.keep) | |
120 if options.verbose: log.setLevel(logging.INFO) | |
121 | |
122 for deb_dir in args: | |
123 | |
124 if not os.path.isdir(deb_dir): | |
125 log.warn("'%s' is not a directory" % deb_dir) | |
126 continue | |
127 | |
128 for deb in oldest_debs(deb_dir, keep): | |
129 log.debug("remove '%s'" % deb) | |
130 remove(deb) | |
131 changes = deb.path[:-3] + "changes" | |
132 if os.path.isfile(changes): | |
133 log.debug("remove '%s'" % changes) | |
134 remove(changes) | |
135 | |
136 | |
137 if __name__ == "__main__": | |
138 main() |