import re, os, sys
import par2parser
+import RarslaveConfig
# Global Variables
(TYPE_OLDRAR, TYPE_NEWRAR, TYPE_ZIP, TYPE_NOEXTRACT) = range (4)
+(ECHECK, EEXTRACT, EDELETE) = range(1,4)
+config = RarslaveConfig.RarslaveConfig()
class RarslaveExtractor (object):
self.heads.append (os.path.join (dir, head))
- def extract (self, todir):
+ def extract (self, todir=None):
# Extract all heads of this set
# Create the directory $todir if it doesn't exist
- if not os.path.isdir (todir):
+ if todir != None and not os.path.isdir (todir):
# TODO: LOGGER
try:
os.makedirs (todir)
except OSError:
# TODO: LOGGER
- # Failed mkdir -p, clean up time ...
- pass # FIXME: temporary for syntax
+ return -EEXTRACT
# Extract all heads
extraction_func = \
# Call the extraction function on each head
for h in self.heads:
- extraction_func (h, todir)
+ if todir == None:
+ # Run in the head's directory
+ extraction_func (h, os.path.dirname (h))
+ else:
+ extraction_func (h, todir)
def __extract_rar (self, file, todir):
assert os.path.isfile (file)
assert os.path.isdir (todir)
- RAR_CMD = 'unrar x -o+ -- '
-
- #file = full_abspath (file)
- #todir = full_abspath (todir)
+ RAR_CMD = config.get_value ('commands', 'unrar')
cmd = '%s \"%s\"' % (RAR_CMD, file)
ret = run_command (cmd, todir)
+ # Check error code
+ if ret != 0:
+ return -EEXTRACT
+
def __extract_zip (self, file, todir):
- ZIP_CMD = 'unzip \"%s\" -d \"%s\"'
+ ZIP_CMD = config.get_value ('commands', 'unzip')
cmd = ZIP_CMD % (file, todir)
ret = run_command (cmd)
+ # Check error code
+ if ret != 0:
+ return -EEXTRACT
+
def __extract_noextract (self, file, todir):
# Just move this file to the $todir, since no extraction is needed
# FIXME: NOTE: mv will fail by itself if you're moving to the same dir!
- cmd = 'mv \"%s\" \"%s\"' % (file, todir)
+ NOEXTRACT_CMD = config.get_value ('commands', 'noextract')
+
+ cmd = NOEXTRACT_CMD % (file, todir)
ret = run_command (cmd)
+ # Check error code
+ if ret != 0:
+ return -EEXTRACT
+
class RarslaveRepairer (object):
def checkAndRepair (self):
# Form the command:
# par2repair -- PAR2 PAR2_EXTRA [JOIN_FILES]
- PAR2_CMD = 'par2repair -- '
+ PAR2_CMD = config.get_value ('commands', 'par2repair')
# Get set up
basename = get_basename (self.file)
# run the command
ret = run_command (command, self.dir)
+ # check the result
+ if ret != 0:
+ # TODO: logger
+ print 'error during checkAndRepair()'
+ return -ECHECK
+
def run_command (cmd, indir=None):
# Runs the specified command-line in the directory given (or, in the current directory
# if none is given). It returns the status code given by the application.
if indir != None:
assert os.path.isdir (indir) # MUST be a directory!
- os.chdir (pwd)
+ os.chdir (indir)
# FIXME: re-enable this after testing
print 'RUNNING (%s): %s' % (indir, cmd)
+ return 0
+
# return os.system (cmd)
def get_basename (name):
"""Strips most kinds of endings from a filename"""
- regex = '^(.+)\.(par2|vol\d+\+\d+|\d\d\d|part\d+|rar|zip|avi|mp4|mkv|ogm)$'
+ regex = config.get_value ('regular expressions', 'basename_regex')
r = re.compile (regex, re.IGNORECASE)
done = False
def find_par2_files (files):
"""Find all par2 files in the list $files"""
- regex = re.compile ('^.*\.par2$', re.IGNORECASE)
+ PAR2_REGEX = config.get_value ('regular expressions', 'par2_regex')
+ regex = re.compile (PAR2_REGEX, re.IGNORECASE)
return [f for f in files if regex.match (f)]
def find_all_par2_files (dir):
def find_deleteable_files (files):
# Deleteable types regex should come from the config
dfiles = []
- dregex = re.compile ('^.*\.(par2|\d|\d\d\d|rar|r\d\d|zip)$', re.IGNORECASE)
+ 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)]
def __eq__ (self, rhs):
return self.__list_eq (self.likely_files, rhs.likely_files)
+ def run_all (self):
+ par2files = find_par2_files (self.likely_files)
+ par2head = par2files[0]
+
+ join = is_noextract (self.likely_files)
+
+ # Repair Stage
+ repairer = RarslaveRepairer (self.dir, par2head, join)
+ ret = repairer.checkAndRepair () # FIXME: Check return value
+
+ if ret: # FAILURE
+ return -ECHECK
+
+ # Extraction Stage
+ EXTRACT_DIR = config.get_value ('directories', 'extract_directory')
+ extractor = find_extraction_heads (self.dir, self.likely_files)
+ ret = extractor.extract (EXTRACT_DIR)
+
+ if ret: # FAILURE
+ return -EEXTRACT
+
+ # Deletion Stage
+ DELETE_INTERACTIVE = config.get_value ('options', 'interactive')
+ deleteable_files = find_deleteable_files (self.likely_files)
+ ret = delete_list (deleteable_files, DELETE_INTERACTIVE)
+
+ if ret: # FAILURE
+ return -EDELETE
+
+ return 0
+
+def delete_list (files, interactive=False):
+ # Delete a list of files
+ # TODO: Add the ability to confirm deletion, like in the original rarslave
+
+ if interactive:
+ # TODO: prompt here
+ # prompt -> OK_TO_DELETE -> do nothing, fall through
+ # prompt -> NOT_OK -> return immediately
+ pass
+
+ for f in files:
+ # FIXME: re-enable this in production
+ # os.remove (f)
+ print 'rm', f
+
+ return 0
+
+
def generate_all_parsets (dir):
# Generate all parsets in the given directory.
return parsets
def main ():
- # Setup stage
- print '\nSETUP STAGE'
- DIR = os.path.abspath ('test_material/01/')
- p2files = find_all_par2_files (DIR)
- p2file = p2files[0]
-
- # Repair stage
- print '\nREPAIR STAGE'
- repairer = RarslaveRepairer (DIR, p2file)
- repairer.checkAndRepair ()
-
- # Extraction stage
- print '\nEXTRACTION STAGE'
- files = find_likely_files (get_basename (p2file), DIR)
- extractor = find_extraction_heads (DIR, files)
- extractor.extract('extract_dir')
-
- # Deletion stage
- print '\nDELETION STAGE'
- printlist ( find_deleteable_files (files) )
-
- print '\n\n'
-
- # Setup stage
- print '\nSETUP STAGE'
- DIR = os.path.abspath ('test_material/13/')
- p2files = find_all_par2_files (DIR)
- p2file = p2files[0]
-
- # Repair stage
- print '\nREPAIR STAGE'
- RarslaveRepairer (DIR, p2file, join=True).checkAndRepair ()
-
- # Extraction stage
- print '\nEXTRACTION STAGE'
- files = find_likely_files (get_basename (p2file), DIR)
- find_extraction_heads (DIR, files).extract ('extract_dir')
-
- # Deletion stage
- print '\nDELETION STAGE'
- printlist ( find_deleteable_files (files) )
-
- print '\n\n'
-
- # Setup stage
- print '\nSETUP STAGE'
- DIR = os.path.abspath ('test_material/14/')
- p2files = find_all_par2_files (DIR)
- p2file = p2files[0]
-
- # Repair stage
- print '\nREPAIR STAGE'
- RarslaveRepairer (DIR, p2file, join=True).checkAndRepair ()
-
- # Extraction stage
- print '\nEXTRACTION STAGE'
- files = find_likely_files (get_basename (p2file), DIR)
- find_extraction_heads (DIR, files).extract ('extract_dir')
-
- # Deletion stage
- print '\nDELETEION STAGE'
- printlist ( find_deleteable_files (files) )
-
- #### TESTING ####
- parsets = generate_all_parsets ('test_material/02/')
- print '\n\nPARSETS LEN:', len(parsets)
- for p in parsets:
- print p.likely_files[0]
+ TOPDIR = os.path.abspath ('test_material')
+ for (dir, subdirs, files) in os.walk (TOPDIR):
+ print 'DEBUG: IN DIRECTORY:', dir
+ parsets = generate_all_parsets (dir)
+ for p in parsets:
+ p.run_all ()
if __name__ == '__main__':
main ()