3 """ Clean incoming of old unused files """
4 # Copyright (C) 2000, 2001, 2002, 2006 James Troup <james@nocrew.org>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 ################################################################################
22 # <aj> Bdale, a ham-er, and the leader,
23 # <aj> Willy, a GCC maintainer,
24 # <aj> Lamont-work, 'cause he's the top uploader....
25 # <aj> Penguin Puff' save the day!
26 # <aj> Porting code, trying to build the world,
27 # <aj> Here they come just in time...
28 # <aj> The Penguin Puff' Guys!
31 # <aj> willy: btw, if you don't maintain gcc you need to start, since
32 # the lyrics fit really well that way
34 ################################################################################
36 import os, os.path, stat, sys, time
37 from datetime import datetime, timedelta
39 from daklib import utils
40 from daklib import daklog
41 from daklib.config import Config
42 from daklib.dbconn import get_policy_queue
44 ################################################################################
51 ################################################################################
53 def usage (exit_code=0):
54 print """Usage: dak clean-queues [OPTIONS]
55 Clean out incoming directories.
57 -d, --days=DAYS remove anything older than DAYS old
58 -i, --incoming=INCOMING the incoming directory to clean
59 -n, --no-action don't do anything
60 -v, --verbose explain what is being done
61 -h, --help show this help and exit"""
65 ################################################################################
68 global delete_date, del_dir
70 # Used for directory naming
71 now_date = datetime.now()
73 # Used for working out times
74 delete_date = int(time.time())-(int(Options["Days"])*84600)
76 morguedir = cnf.get("Dir::Morgue", os.path.join("Dir::Pool", 'morgue'))
77 morguesubdir = cnf.get("Clean-Queues::MorgueSubDir", 'queue')
79 # Build directory as morguedir/morguesubdir/year/month/day
80 del_dir = os.path.join(morguedir,
83 '%.2d' % now_date.month,
84 '%.2d' % now_date.day)
86 # Ensure a directory exists to remove files to
87 if not Options["No-Action"]:
88 if not os.path.exists(del_dir):
89 os.makedirs(del_dir, 0o2775)
90 if not os.path.isdir(del_dir):
91 utils.fubar("%s must be a directory." % (del_dir))
93 # Move to the directory to clean
94 incoming = Options.get("Incoming")
96 incoming = cnf.get('Dir::Unchecked')
98 utils.fubar("Cannot find 'unchecked' directory")
103 utils.fubar("Cannot chdir to %s" % incoming)
105 # Remove a file to the morgue
106 def remove (from_dir, f):
107 fname = os.path.basename(f)
108 if os.access(f, os.R_OK):
109 Logger.log(["move file to morgue", from_dir, fname, del_dir])
110 if Options["Verbose"]:
111 print "Removing '%s' (to '%s')." % (fname, del_dir)
112 if Options["No-Action"]:
115 dest_filename = os.path.join(del_dir, fname)
116 # If the destination file exists; try to find another filename to use
117 if os.path.exists(dest_filename):
118 dest_filename = utils.find_next_free(dest_filename, 10)
119 Logger.log(["change destination file name", os.path.basename(dest_filename)])
120 utils.move(f, dest_filename, 0o660)
122 Logger.log(["skipping file because of permission problem", fname])
123 utils.warn("skipping '%s', permission denied." % fname)
125 # Removes any old files.
126 # [Used for Incoming/REJECT]
129 Logger.log(["check Incoming/REJECT for old files", os.getcwd()])
130 for f in os.listdir('.'):
131 if os.path.isfile(f):
132 if os.stat(f)[stat.ST_MTIME] < delete_date:
133 remove('Incoming/REJECT', f)
135 if Options["Verbose"]:
136 print "Skipping, too new, '%s'." % (os.path.basename(f))
138 # Removes any files which are old orphans (not associated with a valid .changes file).
139 # [Used for Incoming]
141 def flush_orphans ():
145 Logger.log(["check Incoming for old orphaned files", os.getcwd()])
146 # Build up the list of all files in the directory
147 for i in os.listdir('.'):
148 if os.path.isfile(i):
150 if i.endswith(".changes"):
151 changes_files.append(i)
153 # Proces all .changes and .dsc files.
154 for changes_filename in changes_files:
156 changes = utils.parse_changes(changes_filename)
157 files = utils.build_file_list(changes)
159 utils.warn("error processing '%s'; skipping it. [Got %s]" % (changes_filename, sys.exc_info()[0]))
163 for f in files.keys():
164 if f.endswith(".dsc"):
166 dsc = utils.parse_changes(f, dsc_file=1)
167 dsc_files = utils.build_file_list(dsc, is_a_dsc=1)
169 utils.warn("error processing '%s'; skipping it. [Got %s]" % (f, sys.exc_info()[0]))
172 # Ensure all the files we've seen aren't deleted
174 for i in (files.keys(), dsc_files.keys(), [changes_filename]):
177 if all_files.has_key(key):
178 if Options["Verbose"]:
179 print "Skipping, has parents, '%s'." % (key)
182 # Anthing left at this stage is not referenced by a .changes (or
183 # a .dsc) and should be deleted if old enough.
184 for f in all_files.keys():
185 if os.stat(f)[stat.ST_MTIME] < delete_date:
186 remove('Incoming', f)
188 if Options["Verbose"]:
189 print "Skipping, too new, '%s'." % (os.path.basename(f))
191 ################################################################################
194 global Options, Logger
198 for i in ["Help", "Incoming", "No-Action", "Verbose" ]:
199 if not cnf.has_key("Clean-Queues::Options::%s" % (i)):
200 cnf["Clean-Queues::Options::%s" % (i)] = ""
201 if not cnf.has_key("Clean-Queues::Options::Days"):
202 cnf["Clean-Queues::Options::Days"] = "14"
204 Arguments = [('h',"help","Clean-Queues::Options::Help"),
205 ('d',"days","Clean-Queues::Options::Days", "IntLevel"),
206 ('i',"incoming","Clean-Queues::Options::Incoming", "HasArg"),
207 ('n',"no-action","Clean-Queues::Options::No-Action"),
208 ('v',"verbose","Clean-Queues::Options::Verbose")]
210 apt_pkg.parse_commandline(cnf.Cnf,Arguments,sys.argv)
211 Options = cnf.subtree("Clean-Queues::Options")
216 Logger = daklog.Logger('clean-queues', Options['No-Action'])
220 if Options["Verbose"]:
221 print "Processing incoming..."
224 reject = cnf["Dir::Reject"]
225 if os.path.exists(reject) and os.path.isdir(reject):
226 if Options["Verbose"]:
227 print "Processing reject directory..."
233 #######################################################################################
235 if __name__ == '__main__':