9b4ea4651f0bd7c7cd5c34a411a27de1b5559aa7
[rarslave2.git] / PAR2Set / NoExtract.py
1 #!/usr/bin/env python
2 # vim: set ts=4 sts=4 sw=4 textwidth=92:
3
4 """
5 Holds the NoExtract class.
6
7 This module works with sets that only need to repair and delete, and do
8 not need any extraction.
9
10 It will detect sets like the following:
11 X.par2
12 X.vol0+1.par2
13 ...
14
15 01.mp3
16 02.mp3
17 ...
18
19 Where the PAR2 files protect the mp3 files directly.
20
21 NOTE: It doesn't just detect mp3's, it will detect any set that does not
22 NOTE: have any extractable elements in it.
23 """
24
25 __author__    = "Ira W. Snyder (devel@irasnyder.com)"
26 __copyright__ = "Copyright (c) 2006,2007 Ira W. Snyder (devel@irasnyder.com)"
27 __license__   = "GNU GPL v2 (or, at your option, any later version)"
28
29 #    NoExtract.py
30 #
31 #    Copyright (C) 2006,2007  Ira W. Snyder (devel@irasnyder.com)
32 #
33 #    This program is free software; you can redistribute it and/or modify
34 #    it under the terms of the GNU General Public License as published by
35 #    the Free Software Foundation; either version 2 of the License, or
36 #    (at your option) any later version.
37 #
38 #    This program is distributed in the hope that it will be useful,
39 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
40 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
41 #    GNU General Public License for more details.
42 #
43 #    You should have received a copy of the GNU General Public License
44 #    along with this program; if not, write to the Free Software
45 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
46
47 import logging
48 import PAR2Set.Base
49 import rsutil.common
50
51
52 def detector (name_files, prot_files):
53         """Detector for the NoExtract type"""
54
55         EXTRACT_REGEX = rsutil.common.config_get_value ('regular expressions', 'extractable_regex')
56         return not rsutil.common.has_a_match (EXTRACT_REGEX, prot_files)
57
58
59 class NoExtract (PAR2Set.Base.Base):
60
61         """Class for sets that do not need to be extracted. Note that this is not a
62            base class, this is a working class."""
63
64         def __repr__ (self):
65                 return 'NoExtract'
66
67         def update_matches (self):
68                 """Updates the contents of instance variables with the current in-filesystem state.
69                    This should be run after any operation which can create or delete files."""
70
71                 # A NoExtract set is very different from the other sets in this regard. Since we
72                 # don't really have a single file that is protected, it's not likely that "normal"
73                 # name matching will work as expected.
74                 #
75                 # Because of this, we will try to find name matches for every single name that is
76                 # protected by this set. This will help to detect .1 files that are produced when
77                 # repairing this kind of set.
78
79                 # Find "normal" name matched files
80                 self.name_matched_files = rsutil.common.find_name_matches (self.dir, self.basename)
81
82                 # Find "extra" name matched files
83                 for f in self.prot_matched_files:
84                         f_basename = rsutil.common.get_basename (f)
85                         f_matches = rsutil.common.find_name_matches (self.dir, f_basename)
86
87                         self.name_matched_files = rsutil.common.no_duplicates (self.name_matched_files +
88                                         f_matches)
89
90                 # Update the all_files part now
91                 self.all_files = rsutil.common.no_duplicates (self.name_matched_files + self.prot_matched_files)
92
93         def runAll (self):
94                 """Run the Repair and Deletion stages, omitting the Extraction stage"""
95
96                 # Repair Stage
97                 try:
98                         self.runVerifyAndRepair()
99                 except (RuntimeError, OSError):
100                         logging.critical('Repair stage failed for: %s' % self.p2file)
101                         raise
102
103                 self.update_matches ()
104
105                 # Deletion Stage
106                 try:
107                         self.runDelete()
108                 except (RuntimeError, OSError):
109                         logging.critical('Delete stage failed for: %s' % self.p2file)
110                         raise
111
112                 logging.info ('Successfully completed: %s' % self.p2file)
113