X-Git-Url: https://www.irasnyder.com/gitweb/?p=rarslave2.git;a=blobdiff_plain;f=rarslave.py;h=6ffe57ffd8926bcb651c0c06422fa250fd7193b3;hp=1315f855e1dc2386f26ed1d72b211e2e7c94abb6;hb=ff34f5ee9df8449f200b68b9e62d302e87651cd3;hpb=cd3114227a2228eefc270ae7020a3abc99e6c9b4 diff --git a/rarslave.py b/rarslave.py index 1315f85..6ffe57f 100644 --- a/rarslave.py +++ b/rarslave.py @@ -5,7 +5,7 @@ VERSION="2.0.0" PROGRAM="rarslave2" import re, os, sys, optparse -import par2parser +import Par2Parser import RarslaveConfig import RarslaveLogger @@ -26,10 +26,7 @@ class RarslaveExtractor (object): def addHead (self, dir, head): assert os.path.isdir (dir) - # REQUIRES that the dir is valid, but not that the file is valid, so that - # we can move a file that doesn't exist yet. - # FIXME: probably CAN add this back, since we should be running this AFTER repair. - #assert os.path.isfile (os.path.join (dir, head)) + assert os.path.isfile (os.path.join (dir, head)) full_head = os.path.join (dir, head) logger.addMessage ('Adding extraction head: %s' % full_head, RarslaveLogger.MessageType.Debug) @@ -103,6 +100,10 @@ class RarslaveExtractor (object): # FIXME: NOTE: mv will fail by itself if you're moving to the same dir! NOEXTRACT_CMD = config.get_value ('commands', 'noextract') + # Make sure that both files are not the same file. If they are, don't run at all. + if os.path.samefile (file, os.path.join (todir, file)): + return SUCCESS + cmd = NOEXTRACT_CMD % (file, todir) ret = run_command (cmd) @@ -133,7 +134,7 @@ class RarslaveRepairer (object): # Get set up basename = get_basename (self.file) - all_files = find_likely_files (basename, self.dir) + all_files = find_likely_files (self.dir, self.file) all_files.sort () par2_files = find_par2_files (all_files) @@ -169,12 +170,9 @@ def run_command (cmd, indir=None): assert os.path.isdir (indir) # MUST be a directory! os.chdir (indir) - # FIXME: re-enable this after testing - print 'RUNNING (%s): %s' % (indir, cmd) - return SUCCESS - - # return os.system (cmd) - + ret = os.system (cmd) + os.chdir (pwd) + return ret def full_abspath (p): return os.path.abspath (os.path.expanduser (p)) @@ -196,18 +194,27 @@ def get_basename (name): return name -def find_likely_files (name, dir): +def find_likely_files (dir, p2file): """Finds files which are likely to be part of the set corresponding to $name in the directory $dir""" - if not os.path.isdir (os.path.abspath (dir)): - raise ValueError # bad directory given + assert os.path.isdir (dir) + assert os.path.isfile (os.path.join (dir, p2file)) + + basename = get_basename (p2file) dir = os.path.abspath (dir) - ename = re.escape (name) + ename = re.escape (basename) regex = re.compile ('^%s.*$' % (ename, )) - return [f for f in os.listdir (dir) if regex.match (f)] + name_matches = [f for f in os.listdir (dir) if regex.match (f)] + try: + parsed_matches = Par2Parser.get_protected_files (dir, p2file) + except (EnvironmentError, OSError, OverflowError): + parsed_matches = [] + logger.addMessage ('Bad par2 file: %s' % p2file, RarslaveLogger.MessageType.Fatal) + + return name_matches + parsed_matches def find_par2_files (files): """Find all par2 files in the list $files""" @@ -228,16 +235,6 @@ def find_all_par2_files (dir): return find_par2_files (files) -def has_extension (f, ext): - """Checks if f has the extension ext""" - - if ext[0] != '.': - ext = '.' + ext - - ext = re.escape (ext) - regex = re.compile ('^.*%s$' % (ext, ), re.IGNORECASE) - return regex.match (f) - def find_extraction_heads (dir, files): """Takes a list of possible files and finds likely heads of extraction.""" @@ -263,7 +260,7 @@ def find_extraction_heads (dir, files): if is_newrar (files): extractor = RarslaveExtractor (TYPE_NEWRAR) - regex = re.compile ('^.*\.part01.rar$', re.IGNORECASE) + regex = re.compile ('^.*\.part0*1.rar$', re.IGNORECASE) for f in files: if regex.match (f): extractor.addHead (dir, f) @@ -284,9 +281,9 @@ def find_extraction_heads (dir, files): for f in p2files: done = False try: - prot_files = par2parser.get_protected_files (dir, f) + prot_files = Par2Parser.get_protected_files (dir, f) done = True - except: #FIXME: add the actual exceptions + except (EnvironmentError, OverflowError, OSError): logger.addMessage ('Error parsing PAR2 file: %s', f) continue @@ -302,50 +299,50 @@ def find_extraction_heads (dir, files): # Make sure we found the type if extractor == None: logger.addMessage ('Not able to find an extractor for this type of set: %s' % p2files[0], - RarslaveLogger.MessageType.Fatal) + RarslaveLogger.MessageType.Verbose) # No-heads here, but it's better than failing completely extractor = RarslaveExtractor (TYPE_NOEXTRACT) return extractor -def is_oldrar (files): - for f in files: - if has_extension (f, '.r00'): - return True +def generic_matcher (files, regex, nocase=False): + """Run the regex over the files, and see if one matches or not. + NOTE: this does not return the matches, just if a match occurred.""" - return False + if nocase: + cregex = re.compile (regex, re.IGNORECASE) + else: + cregex = re.compile (regex) -def is_newrar (files): for f in files: - if has_extension (f, '.part01.rar'): + if cregex.match (f): return True return False -def is_zip (files): - for f in files: - if has_extension (f, '.zip'): - return True +def is_oldrar (files): + return generic_matcher (files, '^.*\.r00$') - return False +def is_newrar (files): + return generic_matcher (files, '^.*\.part0*1\.rar$') + +def is_zip (files): + return generic_matcher (files, '^.*\.zip$') def is_noextract (files): # Type that needs no extraction. # TODO: Add others ??? - for f in files: - if has_extension (f, '.001'): - return True - - return False + return generic_matcher (files, '^.*\.001$') -def find_deleteable_files (files): - # Deleteable types regex should come from the config - dfiles = [] +def find_deleteable_files (dir, p2file): + likely = find_likely_files (dir, p2file) DELETE_REGEX = config.get_value ('regular expressions', 'delete_regex') dregex = re.compile (DELETE_REGEX, re.IGNORECASE) - return [f for f in files if dregex.match (f)] + dfiles = [f for f in likely if dregex.match (f)] + dset = set(dfiles) # to eliminate dupes + return list(dset) def printlist (li): for f in li: @@ -365,7 +362,7 @@ class PAR2Set (object): self.file = file basename = get_basename (file) - self.likely_files = find_likely_files (basename, dir) + self.likely_files = find_likely_files (dir, file) def __list_eq (self, l1, l2): @@ -406,8 +403,8 @@ class PAR2Set (object): # Deletion Stage DELETE_INTERACTIVE = options.interactive - deleteable_files = find_deleteable_files (self.likely_files) - ret = delete_list (deleteable_files, DELETE_INTERACTIVE) + deleteable_files = find_deleteable_files (self.dir, par2head) + ret = delete_list (self.dir, deleteable_files, DELETE_INTERACTIVE) if ret != SUCCESS: logger.addMessage ('Deletion stage failed for: %s' % par2head, RarslaveLogger.MessageType.Fatal) @@ -416,16 +413,19 @@ class PAR2Set (object): logger.addMessage ('Successfully completed: %s' % par2head) return SUCCESS -def delete_list (files, interactive=False): +def delete_list (dir, files, interactive=False): # Delete a list of files + assert os.path.isdir (dir) + done = False valid_y = ['Y', 'YES'] - valid_n = ['N', 'NO'] + valid_n = ['N', 'NO', ''] if interactive: while not done: print 'Do you want to delete the following?:' + printlist (files) s = raw_input ('Delete [y/N]: ').upper() if s in valid_y + valid_n: @@ -435,9 +435,7 @@ def delete_list (files, interactive=False): return SUCCESS for f in files: - # FIXME: re-enable this in production - # os.remove (f) - print 'rm \"%s\"' % f + os.remove (os.path.join (dir, f)) return SUCCESS @@ -479,8 +477,17 @@ def check_required_progs(): sys.exit(1) def run_options (options): + + # Fix directories options.work_dir = full_abspath (options.work_dir) + # Make sure that the directory is valid + if not os.path.isdir (options.work_dir): + sys.stderr.write ('\"%s\" is not a valid directory. Use the \"-d\"\n' % options.work_dir) + sys.stderr.write ('option to override the working directory temporarily, or edit the\n') + sys.stderr.write ('configuration file to override the working directory permanently.\n') + sys.exit (1) + if options.extract_dir != None: options.extract_dir = full_abspath (options.extract_dir)