Subversion Repositories programming

Rev

Rev 132 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 132 Rev 134
Line 17... Line 17...
17
# - Added the OptionParser to make this nice to run at the command line.
17
# - Added the OptionParser to make this nice to run at the command line.
18
# - Made recursiveness an option.
18
# - Made recursiveness an option.
19
# - Made start directory an option.
19
# - Made start directory an option.
20
# - Check for appropriate programs before starting.
20
# - Check for appropriate programs before starting.
21
#
21
#
-
 
22
# - 2005-10-17
-
 
23
# - Use a regular expression to handle the deletable types.
-
 
24
#
-
 
25
# - 2005-10-18
-
 
26
# - Use regular expressions to handle all finding of files, instead of
-
 
27
#   using the glob module.
-
 
28
# - Add a config class to handle all the default config stuff sanely.
-
 
29
#   This makes it easier to change some of the main parts of the program to
-
 
30
#   your specific configuration.
-
 
31
# - Move the docrcchecks variable inside the get_par2_filenames() function,
-
 
32
#   which is where it belongs anyway.
-
 
33
# - Added command-line option to check for required programs at start.
-
 
34
#
22
 
35
 
23
################################################################################
36
################################################################################
24
# REQUIREMENTS:
37
# REQUIREMENTS:
25
#
38
#
26
# This code requires the programs cfv, par2repair, lxsplit, and rar to be able
39
# This code requires the programs cfv, par2repair, lxsplit, and rar to be able
27
# to function properly. I will attempt to check that these are in your path.
40
# to function properly. I will attempt to check that these are in your path.
28
################################################################################
41
################################################################################
29
 
42
 
30
################################################################################
-
 
31
# Global Variables
43
class rarslave_config:
32
################################################################################
44
    """A simple class to hold the default configs for the whole program"""
-
 
45
 
33
WORK_DIR = '~/downloads/usenet'
46
    WORK_DIR               = '~/downloads/usenet'
-
 
47
    DELETEABLE_TYPES_REGEX = '^.*\.(rar|r\d\d)$'
-
 
48
    TEMP_REPAIR_REGEX      = '.*\.1$'
-
 
49
    PAR2_REGEX             = '.*\.(PAR|par)2$'
34
################################################################################
50
    VIDEO_FILE_REGEX       = '.*\.(AVI|avi|OGM|ogm|MKV|mkv)$'
-
 
51
    RECURSIVE              = True
-
 
52
    CHECK_REQ_PROGS        = False
35
 
53
 
-
 
54
    def __init__(self):
-
 
55
        pass
-
 
56
 
-
 
57
config = rarslave_config()
-
 
58
        
36
################################################################################
59
################################################################################
37
# The PAR2 Parser
60
# The PAR2 Parser
38
#
61
#
39
# This was stolen from cfv (see http://cfv.sourceforge.net/ for a copy)
62
# This was stolen from cfv (see http://cfv.sourceforge.net/ for a copy)
40
################################################################################
63
################################################################################
41
 
64
 
42
import struct, errno
65
import struct, errno
43
 
66
 
44
# We always want to do crc checks
-
 
45
docrcchecks = True
-
 
46
 
-
 
47
def chompnulls(line):
67
def chompnulls(line):
48
    p = line.find('\0')
68
    p = line.find('\0')
49
    if p < 0: return line
69
    if p < 0: return line
50
    else:     return line[:p]
70
    else:     return line[:p]
51
 
71
 
Line 57... Line 77...
57
        file = open(filename, 'rb')
77
        file = open(filename, 'rb')
58
    except:
78
    except:
59
        print 'Could not open %s' % (filename, )
79
        print 'Could not open %s' % (filename, )
60
        return []
80
        return []
61
 
81
 
-
 
82
    # We always want to do crc checks
-
 
83
    docrcchecks = True
-
 
84
 
62
    pkt_header_fmt = '< 8s Q 16s 16s 16s'
85
    pkt_header_fmt = '< 8s Q 16s 16s 16s'
63
    pkt_header_size = struct.calcsize(pkt_header_fmt)
86
    pkt_header_size = struct.calcsize(pkt_header_fmt)
64
    file_pkt_fmt = '< 16s 16s 16s Q'
87
    file_pkt_fmt = '< 16s 16s 16s Q'
65
    file_pkt_size = struct.calcsize(file_pkt_fmt)
88
    file_pkt_size = struct.calcsize(file_pkt_fmt)
66
    main_pkt_fmt = '< Q I'
89
    main_pkt_fmt = '< Q I'
Line 214... Line 237...
214
        self.used_parjoin = retval
237
        self.used_parjoin = retval
215
        self.verified = retval
238
        self.verified = retval
216
        return self.verified
239
        return self.verified
217
 
240
 
218
    def __has_video_file(self):
241
    def __has_video_file(self):
-
 
242
        regex = re.compile(config.VIDEO_FILE_REGEX)
-
 
243
    
219
        for f in self.files:
244
        for f in self.files:
220
            if os.path.splitext(f)[1] in ('.avi', '.ogm', '.mkv'):
245
            if regex.match(f):
221
                return True
246
                return True
222
 
247
 
223
        return False
248
        return False
224
 
249
 
225
    def __remove_currentset(self):
250
    def __remove_currentset(self):
Line 236... Line 261...
236
        # remove all of the extra pars
261
        # remove all of the extra pars
237
        for i in self.extra_pars:
262
        for i in self.extra_pars:
238
            os.remove(i)
263
            os.remove(i)
239
 
264
 
240
        # remove any rars that are associated (leave EVERYTHING else)
265
        # remove any rars that are associated (leave EVERYTHING else)
241
        # This regex matches both old and new style rar(s).
266
        # This regex matches both old and new style rar(s) by default.
242
        regex = re.compile('^.*\.(rar|r\d\d)$')
267
        regex = re.compile(config.DELETEABLE_TYPES_REGEX)
-
 
268
 
243
        for i in self.files:
269
        for i in self.files:
244
            if regex.match(i):
270
            if regex.match(i):
245
                os.remove(i)
271
                os.remove(i)
246
 
272
 
247
        # remove any .0?? files (from parjoin)
273
        # remove any .{001,002,...} files (from parjoin)
248
        if self.used_parjoin:
274
        if self.used_parjoin:
249
            for i in os.listdir(os.getcwd()):
275
            for i in os.listdir(os.getcwd()):
250
                if i != self.files[0] and self.files[0] in i:
276
                if i != self.files[0] and self.files[0] in i:
251
                    os.remove(i)
277
                    os.remove(i)
252
 
278
 
253
        # remove any temp repair files
279
        # remove any temp repair files
254
        for i in glob.glob('*.1'):
280
        regex = re.compile(config.TEMP_REPAIR_REGEX)
255
            os.remove(i)
281
        [os.remove(f) for f in os.listdir(os.getcwd()) if regex.match(f)]
256
 
282
 
257
    def __get_extract_file(self):
283
    def __get_extract_file(self):
258
        """Find the first extractable file"""
284
        """Find the first extractable file"""
259
        for i in self.files:
285
        for i in self.files:
260
            if os.path.splitext(i)[1] == '.rar':
286
            if os.path.splitext(i)[1] == '.rar':
Line 288... Line 314...
288
 
314
 
289
################################################################################
315
################################################################################
290
# The rarslave program itself
316
# The rarslave program itself
291
################################################################################
317
################################################################################
292
 
318
 
293
import os, sys, glob
319
import os, sys
294
from optparse import OptionParser
320
from optparse import OptionParser
295
 
321
 
296
def check_required_progs():
322
def check_required_progs():
297
    """Check if the required programs are installed"""
323
    """Check if the required programs are installed"""
298
 
324
 
Line 319... Line 345...
319
 
345
 
320
def get_parsets():
346
def get_parsets():
321
    """Get a representation of each parset in the current directory, and
347
    """Get a representation of each parset in the current directory, and
322
    return them as a list of parset instances"""
348
    return them as a list of parset instances"""
323
 
349
 
324
    par2files =  glob.glob('*.par2')
350
    regex = re.compile(config.PAR2_REGEX)
325
    par2files += glob.glob('*.PAR2')
351
    par2files = [f for f in os.listdir(os.getcwd()) if regex.match(f)]
326
 
352
 
327
    parsets = []
353
    parsets = []
328
 
354
 
329
    for i in par2files:
355
    for i in par2files:
330
        try:
356
        try:
Line 370... Line 396...
370
 
396
 
371
def main():
397
def main():
372
 
398
 
373
    # Build the OptionParser
399
    # Build the OptionParser
374
    parser = OptionParser()
400
    parser = OptionParser()
-
 
401
    parser.add_option('-n', '--not-recursive',
375
    parser.add_option('-n', '--not-recursive', action='store_false', dest='recursive',
402
                      action='store_false', dest='recursive',
376
                      default=True, help="don't run recursively")
403
                      default=config.RECURSIVE, help="Don't run recursively")
-
 
404
    
377
    parser.add_option('-d', '--start-dir', dest='work_dir', default=WORK_DIR,
405
    parser.add_option('-d', '--work-dir',
-
 
406
                      dest='work_dir', default=config.WORK_DIR,
378
                      help='start running at DIR', metavar='DIR')
407
                      help="Start running at DIR", metavar='DIR')
-
 
408
    
-
 
409
    parser.add_option('-p', '--check-required-programs',
-
 
410
                       action='store_true', dest='check_progs',
-
 
411
                       default=config.CHECK_REQ_PROGS, help="Don't check for required programs")
379
 
412
 
380
    # Parse the given options
413
    # Parse the given options
381
    (options, args) = parser.parse_args()
414
    (options, args) = parser.parse_args()
382
 
415
 
383
    # Fix up the working directory
416
    # Fix up the working directory
384
    options.work_dir = os.path.abspath(os.path.expanduser(options.work_dir))
417
    options.work_dir = os.path.abspath(os.path.expanduser(options.work_dir))
385
 
418
 
386
    # Check that we have the required programs installed
419
    # Check that we have the required programs installed
-
 
420
    if options.check_progs:
387
    check_required_progs()
421
        check_required_progs()
388
 
422
 
389
    # Run rarslave!
423
    # Run rarslave!
390
    if options.recursive:
424
    if options.recursive:
391
        for root, dirs, files in os.walk(options.work_dir):
425
        for root, dirs, files in os.walk(options.work_dir):
392
            directory_worker(root)
426
            directory_worker(root)