2 # vim: set ts=4 sts=4 sw=4 textwidth=112 :
7 import os, sys, optparse
9 import RarslaveDetector
10 import RarslaveGlobals
11 from RarslaveCommon import *
13 # Global options from the RarslaveGlobals class
14 options = RarslaveGlobals.options
15 config = RarslaveGlobals.config
16 logger = RarslaveGlobals.logger
18 # A tiny class used to find unique PAR2 sets
19 class CompareSet (object):
21 def __init__ (self, dir, p2file):
25 self.basename = get_basename (self.p2file)
26 self.name_matches = find_name_matches (self.dir, self.basename)
28 def __eq__ (self, rhs):
29 return (self.dir == rhs.dir) \
30 and (self.basename == rhs.basename) \
31 and list_eq (self.name_matches, rhs.name_matches)
34 def find_all_par2_files (dir):
35 """Finds all par2 files in a directory"""
36 # NOTE: does NOT return absolute paths
38 if not os.path.isdir (os.path.abspath (dir)):
39 raise ValueError # bad directory given
41 dir = os.path.abspath (dir)
42 files = os.listdir (dir)
44 return find_par2_files (files)
46 def generate_all_parsets (dir):
47 # Generate all parsets in the given directory.
49 assert os.path.isdir (dir) # Directory MUST be valid
52 p2files = find_all_par2_files (dir)
55 p = CompareSet (dir, f)
59 return [(p.dir, p.p2file) for p in parsets]
61 def check_required_progs():
62 """Check if the required programs are installed"""
64 shell_not_found = 32512
67 if run_command ('par2repair --help > /dev/null 2>&1') == shell_not_found:
68 needed.append ('par2repair')
70 if run_command ('unrar --help > /dev/null 2>&1') == shell_not_found:
71 needed.append ('unrar')
73 if run_command ('unzip --help > /dev/null 2>&1') == shell_not_found:
74 needed.append ('unzip')
78 print 'Needed program "%s" not found in $PATH' % (n, )
82 def run_options (options):
85 options.work_dir = full_abspath (options.work_dir)
87 # Make sure that the directory is valid
88 if not os.path.isdir (options.work_dir):
89 sys.stderr.write ('\"%s\" is not a valid directory. Use the \"-d\"\n' % options.work_dir)
90 sys.stderr.write ('option to override the working directory temporarily, or edit the\n')
91 sys.stderr.write ('configuration file to override the working directory permanently.\n')
94 if options.extract_dir != None:
95 options.extract_dir = full_abspath (options.extract_dir)
98 print PROGRAM + ' - ' + VERSION
100 print 'Copyright (c) 2005,2006 Ira W. Snyder (devel@irasnyder.com)'
102 print 'This program comes with ABSOLUTELY NO WARRANTY.'
103 print 'This is free software, and you are welcome to redistribute it'
104 print 'under certain conditions. See the file COPYING for details.'
107 if options.check_progs:
108 check_required_progs ()
110 if options.write_def_config:
111 config.write_config (default=True)
113 if options.write_config:
114 config.write_config ()
116 def find_loglevel (options):
118 loglevel = options.verbose - options.quiet
120 if loglevel < RarslaveLogger.MessageType.Fatal:
121 loglevel = RarslaveLogger.MessageType.Fatal
123 if loglevel > RarslaveLogger.MessageType.Debug:
124 loglevel = RarslaveLogger.MessageType.Debug
128 def printMessageTable (loglevel):
130 if logger.hasFatalMessages ():
131 print '\nFatal Messages\n' + '=' * 80
132 logger.printLoglevel (RarslaveLogger.MessageType.Fatal)
134 if loglevel == RarslaveLogger.MessageType.Fatal:
137 if logger.hasNormalMessages ():
138 print '\nNormal Messages\n' + '=' * 80
139 logger.printLoglevel (RarslaveLogger.MessageType.Normal)
141 if loglevel == RarslaveLogger.MessageType.Normal:
144 if logger.hasVerboseMessages ():
145 print '\nVerbose Messages\n' + '=' * 80
146 logger.printLoglevel (RarslaveLogger.MessageType.Verbose)
148 if loglevel == RarslaveLogger.MessageType.Verbose:
151 if logger.hasDebugMessages ():
152 print '\nDebug Messages\n' + '=' * 80
153 logger.printLoglevel (RarslaveLogger.MessageType.Debug)
159 # Build the OptionParser
160 parser = optparse.OptionParser()
161 parser.add_option('-n', '--not-recursive',
162 action='store_false', dest='recursive',
163 default=config_get_value('options', 'recursive'),
164 help="Don't run recursively")
166 parser.add_option('-d', '--work-dir',
167 dest='work_dir', type='string',
168 default=config_get_value('directories', 'working_directory'),
169 help="Start running at DIR", metavar='DIR')
171 parser.add_option('-e', '--extract-dir',
172 dest='extract_dir', type='string',
173 default=config_get_value('directories', 'extract_directory'),
174 help="Extract to DIR", metavar='DIR')
176 parser.add_option('-p', '--check-required-programs',
177 action='store_true', dest='check_progs',
179 help="Check for required programs")
181 parser.add_option('-f', '--write-default-config',
182 action='store_true', dest='write_def_config',
183 default=False, help="Write out a new default config")
185 parser.add_option('-c', '--write-new-config',
186 action='store_true', dest='write_config',
187 default=False, help="Write out the current config")
189 parser.add_option('-i', '--interactive', dest='interactive', action='store_true',
190 default=config_get_value('options', 'interactive'),
191 help="Confirm before removing files")
193 parser.add_option('-q', '--quiet', dest='quiet', action='count',
194 default=0, help="Output fatal messages only")
196 parser.add_option('-v', '--verbose', dest='verbose', action='count',
197 default=0, help="Output extra information")
199 parser.add_option('-V', '--version', dest='version', action='store_true',
200 default=False, help="Output version information")
202 parser.version = VERSION
204 # Parse the given options
206 (RarslaveGlobals.options, args) = parser.parse_args()
207 options = RarslaveGlobals.options
209 # Run any special actions that are needed on these options
210 run_options (options)
212 # Find the loglevel using the options given
213 loglevel = find_loglevel (options)
216 if options.recursive:
217 for (dir, subdirs, files) in os.walk (options.work_dir):
218 parsets = generate_all_parsets (dir)
219 for (p2dir, p2file) in parsets:
220 detector = RarslaveDetector.RarslaveDetector (p2dir, p2file)
221 ret = detector.runMatchingTypes ()
225 parsets = generate_all_parsets (options.work_dir)
226 for (p2dir, p2file) in parsets:
227 detector = RarslaveDetector.RarslaveDetector (p2dir, p2file)
228 ret = detector.runMatchingTypes ()
231 printMessageTable (loglevel)
236 if __name__ == '__main__':