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["Incoming"]
96 incoming_queue = get_policy_queue('unchecked')
97 if not incoming_queue:
98 utils.fubar("Cannot find 'unchecked' queue")
99 incoming = incoming_queue.path
104 utils.fubar("Cannot chdir to %s" % incoming)
106 # Remove a file to the morgue
107 def remove (from_dir, f):
108 fname = os.path.basename(f)
109 if os.access(f, os.R_OK):
110 Logger.log(["move file to morgue", from_dir, fname, del_dir])
111 if Options["Verbose"]:
112 print "Removing '%s' (to '%s')." % (fname, del_dir)
113 if Options["No-Action"]:
116 dest_filename = os.path.join(del_dir, fname)
117 # If the destination file exists; try to find another filename to use
118 if os.path.exists(dest_filename):
119 dest_filename = utils.find_next_free(dest_filename, 10)
120 Logger.log(["change destination file name", os.path.basename(dest_filename)])
121 utils.move(f, dest_filename, 0o660)
123 Logger.log(["skipping file because of permission problem", fname])
124 utils.warn("skipping '%s', permission denied." % fname)
126 # Removes any old files.
127 # [Used for Incoming/REJECT]
130 Logger.log(["check Incoming/REJECT for old files", os.getcwd()])
131 for f in os.listdir('.'):
132 if os.path.isfile(f):
133 if os.stat(f)[stat.ST_MTIME] < delete_date:
134 remove('Incoming/REJECT', f)
136 if Options["Verbose"]:
137 print "Skipping, too new, '%s'." % (os.path.basename(f))
139 # Removes any files which are old orphans (not associated with a valid .changes file).
140 # [Used for Incoming]
142 def flush_orphans ():
146 Logger.log(["check Incoming for old orphaned files", os.getcwd()])
147 # Build up the list of all files in the directory
148 for i in os.listdir('.'):
149 if os.path.isfile(i):
151 if i.endswith(".changes"):
152 changes_files.append(i)
154 # Proces all .changes and .dsc files.
155 for changes_filename in changes_files:
157 changes = utils.parse_changes(changes_filename)
158 files = utils.build_file_list(changes)
160 utils.warn("error processing '%s'; skipping it. [Got %s]" % (changes_filename, sys.exc_info()[0]))
164 for f in files.keys():
165 if f.endswith(".dsc"):
167 dsc = utils.parse_changes(f, dsc_file=1)
168 dsc_files = utils.build_file_list(dsc, is_a_dsc=1)
170 utils.warn("error processing '%s'; skipping it. [Got %s]" % (f, sys.exc_info()[0]))
173 # Ensure all the files we've seen aren't deleted
175 for i in (files.keys(), dsc_files.keys(), [changes_filename]):
178 if all_files.has_key(key):
179 if Options["Verbose"]:
180 print "Skipping, has parents, '%s'." % (key)
183 # Anthing left at this stage is not referenced by a .changes (or
184 # a .dsc) and should be deleted if old enough.
185 for f in all_files.keys():
186 if os.stat(f)[stat.ST_MTIME] < delete_date:
187 remove('Incoming', f)
189 if Options["Verbose"]:
190 print "Skipping, too new, '%s'." % (os.path.basename(f))
192 ################################################################################
195 global Options, Logger
199 for i in ["Help", "Incoming", "No-Action", "Verbose" ]:
200 if not cnf.has_key("Clean-Queues::Options::%s" % (i)):
201 cnf["Clean-Queues::Options::%s" % (i)] = ""
202 if not cnf.has_key("Clean-Queues::Options::Days"):
203 cnf["Clean-Queues::Options::Days"] = "14"
205 Arguments = [('h',"help","Clean-Queues::Options::Help"),
206 ('d',"days","Clean-Queues::Options::Days", "IntLevel"),
207 ('i',"incoming","Clean-Queues::Options::Incoming", "HasArg"),
208 ('n',"no-action","Clean-Queues::Options::No-Action"),
209 ('v',"verbose","Clean-Queues::Options::Verbose")]
211 apt_pkg.ParseCommandLine(cnf.Cnf,Arguments,sys.argv)
212 Options = cnf.SubTree("Clean-Queues::Options")
217 Logger = daklog.Logger('clean-queues', Options['No-Action'])
221 if Options["Verbose"]:
222 print "Processing incoming..."
225 reject = cnf["Dir::Reject"]
226 if os.path.exists(reject) and os.path.isdir(reject):
227 if Options["Verbose"]:
228 print "Processing reject directory..."
234 #######################################################################################
236 if __name__ == '__main__':