b764c499be11408fafaaadd88272221c7984fce7
[rarslave2.git] / PAR2Set / Join.py
1 #!/usr/bin/env python
2 # vim: set ts=4 sts=4 sw=4 textwidth=92:
3
4 """
5 Holds the Join class.
6
7 This module works with normal joined sets.
8
9 It will detect sets like the following:
10 X.par2
11 X.vol0+1.par2
12 ...
13
14 X.001
15 X.002
16 ...
17
18 Where the PAR2 files protect a file named X.avi, or similar other types.
19 It will not work where the PAR2 files are protecting the X.001, etc files
20 directly.
21 """
22
23 __author__    = "Ira W. Snyder (devel@irasnyder.com)"
24 __copyright__ = "Copyright (c) 2006,2007 Ira W. Snyder (devel@irasnyder.com)"
25 __license__   = "GNU GPL v2 (or, at your option, any later version)"
26
27 #    Join.py
28 #
29 #    Copyright (C) 2006,2007  Ira W. Snyder (devel@irasnyder.com)
30 #
31 #    This program is free software; you can redistribute it and/or modify
32 #    it under the terms of the GNU General Public License as published by
33 #    the Free Software Foundation; either version 2 of the License, or
34 #    (at your option) any later version.
35 #
36 #    This program is distributed in the hope that it will be useful,
37 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
38 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39 #    GNU General Public License for more details.
40 #
41 #    You should have received a copy of the GNU General Public License
42 #    along with this program; if not, write to the Free Software
43 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
44
45 import os
46 import logging
47 import PAR2Set.Base
48 import rsutil.common
49
50
51 def detector (name_files, prot_files):
52         """Detects a Join set"""
53
54         return rsutil.common.has_a_match ('^.*\.\d\d\d$', name_files) \
55                         and not rsutil.common.has_a_match ('^.*\.\d\d\d$', prot_files)
56
57
58 class Join (PAR2Set.Base.Base):
59
60         """Class for normal joined-file sets"""
61
62         def __repr__ (self):
63                 return 'JOIN'
64
65         def find_joinfiles (self):
66                 """Finds files which contain data to be joined together"""
67
68                 return rsutil.common.find_matches ('^.*\.\d\d\d$', self.name_matched_files)
69
70         def runVerifyAndRepair (self):
71                 """Verify and Repair a PAR2Set. This version extends the PAR2Set.Base.Base
72                    version by adding the datafiles to be joined at the end of the command
73                    line.
74
75                    This is done using the par2repair command by default"""
76
77                 PAR2_CMD = rsutil.common.config_get_value ('commands', 'par2repair')
78
79                 # assemble the command
80                 # par2repair -- PAR2 PAR2_EXTRA [JOIN_FILES]
81                 command = "%s \"%s\" " % (PAR2_CMD, self.p2file)
82
83                 for f in self.all_p2files:
84                         if f != self.p2file:
85                                 command += "\"%s\" " % os.path.split (f)[1]
86
87                 for f in self.find_joinfiles ():
88                         command += "\"%s\" " % os.path.split (f)[1]
89
90                 # run the command
91                 ret = rsutil.common.run_command (command, self.dir)
92
93                 # check the result
94                 if ret != 0:
95                         logging.critical ('PAR2 Check / Repair failed: %s' % self.p2file)
96                         return -rsutil.common.ECHECK
97
98                 return rsutil.common.SUCCESS
99
100         def find_extraction_heads (self):
101                 """Find the extraction heads. Since this should not be an extractable set,
102                    we return the files which are protected directly by the PAR2 files."""
103
104                 return self.prot_matched_files
105
106         def extraction_function (self, file, todir):
107                 """Extract a single file of the Join type.
108
109                    file -- the file to extract
110                    todir -- the directory to extract to
111
112                    This command ignores the extraction if file and todir+file are the same
113                    file. This keeps things like mv working smoothly."""
114
115                 NOEXTRACT_CMD = rsutil.common.config_get_value ('commands', 'noextract')
116
117                 # Make sure that both files are not the same file. If they are, don't run at all.
118                 if os.path.samefile (file, os.path.join (todir, file)):
119                         return rsutil.common.SUCCESS
120
121                 cmd = NOEXTRACT_CMD % (file, todir)
122                 ret = rsutil.common.run_command (cmd)
123
124                 # Check error code
125                 if ret != 0:
126                         return -rsutil.common.EEXTRACT
127
128                 return rsutil.common.SUCCESS
129