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
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 now_date = datetime.now()
72 delete_date = now_date - timedelta(seconds=int(Options["Days"]) * 84600)
74 morguedir = cnf.get("Dir::Morgue", os.path.join("Dir::Pool", 'morgue'))
75 morguesubdir = cnf.get("Clean-Queues::MorgueSubDir", 'queue')
77 # Build directory as morguedir/morguesubdir/year/month/day
78 del_dir = os.path.join(morguedir,
81 '%.2d' % now_date.month,
82 '%.2d' % now_date.day)
84 # Ensure a directory exists to remove files to
85 if not Options["No-Action"]:
86 if not os.path.exists(del_dir):
87 os.makedirs(del_dir, 02775)
88 if not os.path.isdir(del_dir):
89 utils.fubar("%s must be a directory." % (del_dir))
91 # Move to the directory to clean
92 incoming = Options["Incoming"]
94 incoming_queue = get_policy_queue('unchecked')
95 if not incoming_queue:
96 utils.fubar("Cannot find 'unchecked' queue")
97 incoming = incoming_queue.path
102 utils.fubar("Cannot chdir to %s" % incoming)
104 # Remove a file to the morgue
105 def remove (from_dir, f):
106 fname = os.path.basename(f)
107 if os.access(f, os.R_OK):
108 Logger.log(["move file to morgue", from_dir, fname, del_dir])
109 if Options["Verbose"]:
110 print "Removing '%s' (to '%s')." % (fname, del_dir)
111 if Options["No-Action"]:
114 dest_filename = os.path.join(del_dir, fname)
115 # If the destination file exists; try to find another filename to use
116 if os.path.exists(dest_filename):
117 dest_filename = utils.find_next_free(dest_filename, 10)
118 Logger.log(["change destination file name", os.path.basename(dest_filename)])
119 utils.move(f, dest_filename, 0660)
121 Logger.log(["skipping file because of permission problem", fname])
122 utils.warn("skipping '%s', permission denied." % fname)
124 # Removes any old files.
125 # [Used for Incoming/REJECT]
128 Logger.log(["check Incoming/REJECT for old files", os.getcwd()])
129 for f in os.listdir('.'):
130 if os.path.isfile(f):
131 if os.stat(f)[stat.ST_MTIME] < delete_date:
132 remove('Incoming/REJECT', f)
134 if Options["Verbose"]:
135 print "Skipping, too new, '%s'." % (os.path.basename(f))
137 # Removes any files which are old orphans (not associated with a valid .changes file).
138 # [Used for Incoming]
140 def flush_orphans ():
144 Logger.log(["check Incoming for old orphaned files", os.getcwd()])
145 # Build up the list of all files in the directory
146 for i in os.listdir('.'):
147 if os.path.isfile(i):
149 if i.endswith(".changes"):
150 changes_files.append(i)
152 # Proces all .changes and .dsc files.
153 for changes_filename in changes_files:
155 changes = utils.parse_changes(changes_filename)
156 files = utils.build_file_list(changes)
158 utils.warn("error processing '%s'; skipping it. [Got %s]" % (changes_filename, sys.exc_type))
162 for f in files.keys():
163 if f.endswith(".dsc"):
165 dsc = utils.parse_changes(f, dsc_file=1)
166 dsc_files = utils.build_file_list(dsc, is_a_dsc=1)
168 utils.warn("error processing '%s'; skipping it. [Got %s]" % (f, sys.exc_type))
171 # Ensure all the files we've seen aren't deleted
173 for i in (files.keys(), dsc_files.keys(), [changes_filename]):
176 if all_files.has_key(key):
177 if Options["Verbose"]:
178 print "Skipping, has parents, '%s'." % (key)
181 # Anthing left at this stage is not referenced by a .changes (or
182 # a .dsc) and should be deleted if old enough.
183 for f in all_files.keys():
184 if os.stat(f)[stat.ST_MTIME] < delete_date:
185 remove('Incoming', f)
187 if Options["Verbose"]:
188 print "Skipping, too new, '%s'." % (os.path.basename(f))
190 ################################################################################
193 global Options, Logger
197 for i in ["Help", "Incoming", "No-Action", "Verbose" ]:
198 if not cnf.has_key("Clean-Queues::Options::%s" % (i)):
199 cnf["Clean-Queues::Options::%s" % (i)] = ""
200 if not cnf.has_key("Clean-Queues::Options::Days"):
201 cnf["Clean-Queues::Options::Days"] = "14"
203 Arguments = [('h',"help","Clean-Queues::Options::Help"),
204 ('d',"days","Clean-Queues::Options::Days", "IntLevel"),
205 ('i',"incoming","Clean-Queues::Options::Incoming", "HasArg"),
206 ('n',"no-action","Clean-Queues::Options::No-Action"),
207 ('v',"verbose","Clean-Queues::Options::Verbose")]
209 apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
210 Options = cnf.SubTree("Clean-Queues::Options")
215 Logger = daklog.Logger('clean-queues', Options['No-Action'])
219 if Options["Verbose"]:
220 print "Processing incoming..."
223 reject = cnf["Dir::Reject"]
224 if os.path.exists(reject) and os.path.isdir(reject):
225 if Options["Verbose"]:
226 print "Processing reject directory..."
232 #######################################################################################
234 if __name__ == '__main__':