-# Global options to be set / used later.
-options = None
-
-class RarslaveExtractor (object):
-
- # Instance Variables
- # ==========================================================================
- # dir -- The directory in which this set lives
- # p2files -- All PAR2 files in this set
- # name_matched_files -- Files in this set, matched by name only
- # prot_matched_files -- Files in this set, matched by parsing PAR2 files only
- # type -- This set's type
- # heads -- The heads to be extracted
-
- def __init__ (self, dir, p2files, name_files, prot_files):
-
- self.dir = dir
- self.p2files = p2files
- self.name_matched_files = name_files
- self.prot_matched_files = prot_files
-
- # Find the type
- self.type = self.__find_type ()
-
- logger.addMessage ('Detected set of type: %s' % self, RarslaveLogger.MessageType.Debug)
-
- # Find the heads
- self.heads = self.__find_heads ()
-
- for h in self.heads:
- logger.addMessage ('Adding extraction head: %s' % h, RarslaveLogger.MessageType.Debug)
-
- def __repr__ (self):
- return \
- { TYPE_OLDRAR : 'Old RAR',
- TYPE_NEWRAR : 'New RAR',
- TYPE_ZIP : 'Zip',
- TYPE_NOEXTRACT : 'No Extract',
- TYPE_UNKNOWN : 'Unknown' } [self.type]
-
- def __find_type (self):
-
- all_files = no_duplicates (self.name_matched_files + self.prot_matched_files)
-
- if self.is_oldrar (all_files):
- return TYPE_OLDRAR
- elif self.is_newrar (all_files):
- return TYPE_NEWRAR
- elif self.is_zip (all_files):
- return TYPE_ZIP
- elif self.is_noextract (all_files):
- return TYPE_NOEXTRACT
-
- return TYPE_UNKNOWN
-
- def __generic_find_heads (self, regex, ignorecase=True):
-
- heads = []
-
- if ignorecase:
- cregex = re.compile (regex, re.IGNORECASE)
- else:
- cregex = re.compile (regex)
-
- all_files = no_duplicates (self.name_matched_files + self.prot_matched_files)
-
- for f in all_files:
- if cregex.match (f):
- heads.append (f)
-
- return heads
-
- def __find_heads (self):
-
- if self.type == TYPE_OLDRAR:
- return self.__generic_find_heads ('^.*\.rar$')
- elif self.type == TYPE_NEWRAR:
- return self.__generic_find_heads ('^.*\.part0*1\.rar$')
- elif self.type == TYPE_ZIP:
- return self.__generic_find_heads ('^.*\.zip$')
- elif self.type == TYPE_NOEXTRACT:
- return self.prot_matched_files
-
- return []
-
- def __create_directory (self, dir):
- if dir == None:
- return SUCCESS
-
- if os.path.isdir (dir):
- return SUCCESS
-
- try:
- os.makedirs (dir)
- logger.addMessage ('Created directory: %s' % dir, RarslaveLogger.MessageType.Verbose)
- except OSError:
- logger.addMessage ('FAILED to create directory: %s' % dir, RarslaveLogger.MessageType.Fatal)
- return -EEXTRACT
-
- return SUCCESS
-
- def runExtract (self, todir=None):
- # Extract all heads of this set
-
- # Extract to the head's dir if we don't care where to extract
- if todir == None:
- todir = self.dir
-
- # Create the directory $todir if it doesn't exist
- ret = self.__create_directory (todir)
-
- if ret != SUCCESS:
- return -EEXTRACT
-
- # Extract all heads
- extraction_func = \
- { TYPE_OLDRAR : self.__extract_rar,
- TYPE_NEWRAR : self.__extract_rar,
- TYPE_ZIP : self.__extract_zip,
- TYPE_NOEXTRACT : self.__extract_noextract,
- TYPE_UNKNOWN : self.__extract_unknown }[self.type]
-
- # Call the extraction function on each head
- for h in self.heads:
- full_head = full_abspath (h)
- ret = extraction_func (full_head, todir)
- logger.addMessage ('Extraction Function returned: %d' % ret, RarslaveLogger.MessageType.Debug)
-
- # Check error code
- if ret != SUCCESS:
- logger.addMessage ('Failed extracting: %s' % h, RarslaveLogger.MessageType.Fatal)
- return -EEXTRACT
-
- return SUCCESS
-
- def __extract_rar (self, file, todir):
- assert os.path.isfile (file)
- assert os.path.isdir (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
-
- return SUCCESS
-
- def __extract_zip (self, file, todir):
- ZIP_CMD = config.get_value ('commands', 'unzip')
-
- cmd = ZIP_CMD % (file, todir)
- ret = run_command (cmd)
-
- # Check error code
- if ret != 0:
- return -EEXTRACT
-
- return SUCCESS
-
- 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!
- 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)
-
- # Check error code
- if ret != 0:
- return -EEXTRACT
-
- return SUCCESS
-
- def __extract_unknown (self, file, todir):
- return SUCCESS
-
- def __generic_matcher (self, 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."""
-
- if nocase:
- cregex = re.compile (regex, re.IGNORECASE)
- else:
- cregex = re.compile (regex)
-
- for f in files:
- if cregex.match (f):
- return True
-
- return False
-
- def is_oldrar (self, files):
- return self.__generic_matcher (files, '^.*\.r00$')
-
- def is_newrar (self, files):
- return self.__generic_matcher (files, '^.*\.part0*1\.rar$')
-
- def is_zip (self, files):
- return self.__generic_matcher (files, '^.*\.zip$')
-
- def is_noextract (self, files):
- # Type that needs no extraction.
- # TODO: Add others ???
- return self.__generic_matcher (files, '^.*\.001$')
-
-class PAR2Set (object):
-
- # Instance Variables
- # ==========================================================================
- # dir -- The directory this set lives in
- # p2file -- The starting PAR2 file
- # basename -- The basename of the set, guessed from the PAR2 file
- # all_p2files -- All PAR2 files of the set, guessed from the PAR2 file name only
- # name_matched_files -- Files in this set, guessed by name only
- # prot_matched_files -- Files in this set, guessed by parsing the PAR2 only