Use exceptions for error handling
[rarslave2.git] / rsutil / common.py
1 #!/usr/bin/env python
2 # vim: set ts=4 sts=4 sw=4 textwidth=92:
3
4 """
5 Module holding all of the common functions used throughout the rarslave project
6 """
7
8 __author__    = "Ira W. Snyder (devel@irasnyder.com)"
9 __copyright__ = "Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)"
10 __license__   = "GNU GPL v2 (or, at your option, any later version)"
11
12 #    common.py -- holds all of the common functions used throughout the rarslave project
13 #
14 #    Copyright (C) 2006,2007  Ira W. Snyder (devel@irasnyder.com)
15 #
16 #    This program is free software; you can redistribute it and/or modify
17 #    it under the terms of the GNU General Public License as published by
18 #    the Free Software Foundation; either version 2 of the License, or
19 #    (at your option) any later version.
20 #
21 #    This program is distributed in the hope that it will be useful,
22 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
23 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 #    GNU General Public License for more details.
25 #
26 #    You should have received a copy of the GNU General Public License
27 #    along with this program; if not, write to the Free Software
28
29 import os
30 import re
31 import logging
32 import subprocess
33 import exceptions
34
35 import rsutil.globals
36 import rsutil.par2parser
37
38 def find_matches (regex, li, ignorecase=True):
39
40         if ignorecase:
41                 cregex = re.compile (regex, re.IGNORECASE)
42         else:
43                 cregex = re.compile (regex)
44
45         return [e for e in li if cregex.match (e)]
46
47 def has_a_match (regex, li, ignorecase=True):
48
49         if ignorecase:
50                 cregex = re.compile (regex, re.IGNORECASE)
51         else:
52                 cregex = re.compile (regex)
53
54         for e in li:
55                 if cregex.match (e):
56                         return True
57
58         return False
59
60 def no_duplicates (li):
61         """Removes all duplicates from a list"""
62         return list(set(li))
63
64 def run_command (cmd, indir=None):
65         # Runs the specified command-line in the directory given (or, in the current directory
66         # if none is given). It returns the status code given by the application.
67
68         if indir == None:
69                 indir = os.getcwd()
70         else:
71                 assert os.path.isdir (indir) # MUST be a directory!
72
73         print 'RUNNING COMMAND'
74         print 'Directory: %s' % indir
75         print 'Command: %s' % cmd[0]
76         for f in cmd[1:]:
77                 print '-> %s' % f
78
79         ret = subprocess.Popen(cmd, cwd=indir).wait()
80
81         if ret != 0:
82                 raise RuntimeError
83
84         return ret
85
86 def full_abspath (p):
87         return os.path.abspath (os.path.expanduser (p))
88
89 def find_par2_files (files):
90         """Find all par2 files in the list $files"""
91
92         PAR2_REGEX = config_get_value ('regular expressions', 'par2_regex')
93         regex = re.compile (PAR2_REGEX, re.IGNORECASE)
94         return [f for f in files if regex.match (f)]
95
96 def find_name_matches (dir, basename):
97         """Finds files which are likely to be part of the set corresponding
98            to $name in the directory $dir"""
99
100         assert os.path.isdir (dir)
101
102         ename = re.escape (basename)
103         regex = re.compile ('^%s.*$' % (ename, ))
104
105         return [f for f in os.listdir (dir) if regex.match (f)]
106
107 def parse_all_par2 (dir, p2head, p2files):
108         """Searches though p2files and tries to parse at least one of them"""
109         done = False
110         files = []
111
112         for f in p2files:
113
114                 # Exit early if we've found a good file
115                 if done:
116                         break
117
118                 try:
119                         files = rsutil.par2parser.get_protected_files (dir, f)
120                         done = True
121                 except (EnvironmentError, OSError, OverflowError):
122                         logging.warning ('Corrupt PAR2 file: %s' % f)
123
124         # Now that we're out of the loop, check if we really finished
125         if not done:
126                 logging.critical ('All PAR2 files corrupt for: %s' % p2head)
127
128         # Return whatever we've got, empty or not
129         return files
130
131 def get_basename (name):
132         """Strips most kinds of endings from a filename"""
133
134         regex = config_get_value ('regular expressions', 'basename_regex')
135         r = re.compile (regex, re.IGNORECASE)
136         done = False
137
138         while not done:
139                 done = True
140
141                 if r.match (name):
142                         g = r.match (name).groups()
143                         name = g[0]
144                         done = False
145
146         return name
147
148 def list_eq (l1, l2):
149
150         if len(l1) != len(l2):
151                 return False
152
153         return set(l1) == set(l2)
154
155 # Convience functions for the config
156
157 def config_get_value (section, name):
158         return rsutil.globals.config.get_value (section, name)
159
160 # Convience functions for the options
161
162 def options_get_value (name):
163         return getattr (rsutil.globals.options, name)
164