]> git.donarmstrong.com Git - wannabuild.git/blob - bin/expire_dumps
Auto-committed schema changes.
[wannabuild.git] / bin / expire_dumps
1 #!/usr/bin/python
2
3 # Copyright (C) 2007 Florian Reitmeir <florian@reitmeir.org>
4 # Copyright (C) 2008 Joerg Jaspert <joerg@debian.org>
5
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 # requires: python-dateutil
26
27 import glob, os, sys
28 import time, datetime
29 import re
30 from datetime import datetime
31 from datetime import timedelta
32 from optparse import OptionParser
33
34 RULES = [
35     {'days':14,   'interval':0},
36     {'days':31,   'interval':7},
37     {'days':365,  'interval':31},
38     {'days':3650, 'interval':365},
39
40     # keep 14 days, all each day
41     # keep 31 days, 1 each 7th day
42     # keep 365 days, 1 each 31th day
43     # keep 3650 days, 1 each 365th day
44 ]
45
46 TODAY = datetime.today()
47 VERBOSE = False
48 NOACTION = False
49 PRINT = False
50 PREFIX = ''
51 PATH = ''
52
53 def all_files(pattern, search_path, pathsep=os.pathsep):
54     """ Given a search path, yield all files matching the pattern. """
55     for path in search_path.split(pathsep):
56         for match in glob.glob(os.path.join(path, pattern)):
57             yield match
58
59 def parse_file_dates_pre(list):
60     out = []
61     # dump_2006.05.02-11:52:01.gz
62     p = re.compile('^\./dump_pre_([0-9]{4})\.([0-9]{2})\.([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2})(.gz)?$')
63     for file in list:
64         m = p.search(file)
65         if m:
66             d = datetime(int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)), int(m.group(5)), int(m.group(6)))
67             out.append({'name': file, 'date': d})
68     return out
69
70 def parse_file_dates_post(list):
71     out = []
72     # dump_2006.05.02-11:52:01.gz
73     p = re.compile('^\./dump_post_([0-9]{4})\.([0-9]{2})\.([0-9]{2})-([0-9]{2}):([0-9]{2}):([0-9]{2})(.gz)?$')
74     for file in list:
75         m = p.search(file)
76         if m:
77             d = datetime(int(m.group(1)), int(m.group(2)), int(m.group(3)), int(m.group(4)), int(m.group(5)), int(m.group(6)))
78             out.append({'name': file, 'date': d})
79     return out
80
81 def prepare_rules(rules):
82     out = []
83     for rule in rules:
84         out.append(
85             {
86             'days':timedelta(days=rule['days']),
87             'interval':timedelta(days=rule['interval'])}
88             )
89     return out
90
91 def expire(rules, list):
92     t_rules=prepare_rules(rules)
93     rule = t_rules.pop(0)
94     last = list.pop(0)
95
96     for file in list:
97         if VERBOSE:
98             print "current file to expire: " + file['name']
99             print file['date']
100
101         # check if rule applies
102         if (file['date'] < (TODAY-rule['days'])):
103             if VERBOSE:
104                 print "move to next rule"
105             if t_rules:
106                 rule = t_rules.pop(0)
107
108         if (last['date'] - file['date']) < rule['interval']:
109             if VERBOSE:
110                 print "unlink file:" + file['name']
111             if PRINT:
112                 print file['name']
113             if not NOACTION:
114                 os.unlink(file['name'])
115         else:
116             last = file
117             if VERBOSE:
118                 print "kept file:" + file['name']
119
120
121 parser = OptionParser()
122 parser.add_option("-d", "--directory", dest="directory",
123                   help="directory name", metavar="Name")
124 parser.add_option("-f", "--pattern", dest="pattern",
125                   help="Pattern maybe some glob", metavar="*.backup")
126 parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
127                   help="verbose")
128 parser.add_option("-n", "--no-action", action="store_true", dest="noaction", default=False,
129                   help="just prints what would be done, this implies verbose")
130 parser.add_option("-p", "--print", action="store_true", dest="printfiles", default=False,
131                   help="just print the filenames that should be deleted, this forbids verbose")
132
133 (options, args) = parser.parse_args()
134
135 if (not options.directory):
136     parser.error("no directory to check given")
137
138 if options.noaction:
139     VERBOSE=True
140     NOACTION=True
141
142 if options.verbose:
143     VERBOSE=True
144
145 if options.printfiles:
146     VERBOSE=False
147     PRINT=True
148
149 files = sorted( list(all_files(options.pattern,options.directory)), reverse=True );
150
151 if not files:
152     sys.exit(0)
153
154 files_dates =  parse_file_dates_pre(files);
155 expire(RULES, files_dates)
156
157 files_dates =  parse_file_dates_post(files);
158 expire(RULES, files_dates)