1
# -*- coding: utf-8 -*-
7
from stat import ST_MODE
8
from subprocess import Popen, PIPE, STDOUT
9
from distutils import log, file_util, dir_util
12
def execute(cmd, env=None):
13
"""Executes a command and returns its output."""
14
p = Popen(cmd, stdout=PIPE, stderr=STDOUT, close_fds=True, env=env)
15
return p.communicate()[0]
18
def less_than_version(vers1, vers2):
19
return version2tuple(vers1) < version2tuple(vers2)
22
def version2tuple(vers_string):
23
"""1.7.9alpha --> (1, 7, 9, 'alpha'), 1.8 --> (1, 8, 0, 'final')"""
24
tupl0 = vers_string.split('.')
27
m = re.search('(^[0-9]+)(.*)', v)
29
val.append(int(m.group(1)))
31
val.append(m.group(2).replace('-', '').replace('_', '').strip())
34
val.extend([0]*(3-len(val)))
35
if type(val[-1]) in (int, long):
40
def get_function(functions, vers):
41
"""Return the function to be used starting from version...
48
tv, func = functions[0]
49
for vi, fi in functions[1:]:
50
if less_than_version(vers, vi):
56
def prefix2etc(prefix):
60
return os.path.join(prefix, 'etc')
63
def move_tree(src, dirs_and_files, dest, preserve_symlinks=0, dry_run=0):
64
"""Moves dirs_and_files from src to dest
65
(put dirs first to create destination dirs for files).
67
dir_util.create_tree(dest, dirs_and_files, dry_run=dry_run)
68
for obj in dirs_and_files:
69
src_i = os.path.join(src, obj)
70
dst_i = os.path.join(dest, obj)
71
log.debug("move_tree %s to %s" , src_i, dst_i)
72
if not os.path.exists(src_i) and not os.path.islink(src_i):
73
log.info("not found: %s", src_i)
75
if os.path.islink(src_i):
76
link_dest = os.readlink(src_i)
77
log.info("linking %s -> %s", dst_i, link_dest)
79
os.symlink(link_dest, dst_i)
81
elif os.path.isdir(src_i):
82
dir_util.copy_tree(src_i, dst_i, preserve_symlinks=preserve_symlinks, dry_run=dry_run)
83
remove_tree(src_i, dry_run=dry_run)
85
file_util.move_file(src_i, dst_i, dry_run=dry_run)
88
def remove_tree(directory, verbose=0, dry_run=0, empty_dirs=0):
89
"""Same as dir_util.remove_tree + try to remove parent directories if they are empty."""
90
dir_util.remove_tree(directory, verbose, dry_run)
93
dsplit = directory.split(os.sep)
96
while len(dsplit) > 1:
98
full = os.path.join(*dsplit)
99
if os.path.exists(full):
102
log.debug("removed: %s", full)
108
def remove_empty_dirs(fromdir):
109
"""Removes all empty dirs"""
110
for base, dirs, files in os.walk(fromdir, topdown=False):
117
def re_search(filename, regexp, flags=0):
118
"""Search for regexp in the content of 'filename'."""
119
log.debug("search regular expression %r in %s", regexp, filename)
120
if not os.path.isfile(filename):
121
log.debug("not found: %s", filename)
123
expr = re.compile(regexp, flags)
124
content = open(filename, 'r').read()
125
res = expr.search(content)
129
def check_and_store(dico, match, lvar):
130
"""Check match.groups() and store them in dico[*var]."""
131
log.debug("check_var: variables=%r", lvar)
134
if type(lvar) not in (tuple, list):
136
inter = min(len(lvar), len(match.groups()))
137
log.debug(" values=%r", match.groups())
138
for i in range(inter):
139
var, value = lvar[i], match.group(i+1).strip()
140
if re.search('\?[A-Z_0-9]+\?', value):
141
log.info("%s is not configured (%r)", var, value)
146
# copy from asrun.utils
147
def read_rcfile(ficrc, destdict):
148
"""Read a ressource file and store variables to 'destdict'.
152
if not re.search('^[ ]*#', line):
153
mat = re.search('([-a-z_A-Z0-9]+) *: *(.*)', line.strip())
156
value = mat.group(2).strip()
157
# try to convert numbers and boolean values
164
if value in ('True', 'False'):
166
# repeatable ? (space separated)
167
if destdict.has_key(key) and key in ('vers', 'noeud'):
168
value = str(destdict[key])+' '+str(value)
169
destdict[key] = value
173
def replace_rcfile(ficrc, values):
174
"""Changes the values of fields of 'ficrc' using 'values' dict.
176
content = open(ficrc, 'r').read()
177
for field, value in values.items():
179
searched = '^%s *: *(.*)$' % field
180
replacement = '%s : %s' % (field, value)
181
# particular treatment for repeatable fields
182
if field == 'noeud': # only one occurrence in content, but may have more values
183
replacement = os.linesep.join(['%s : %s' % (field, vali) for vali in value.split()])
184
elif field == 'vers':
185
searched = '^%s$' % re.escape('#?vers : VVV?')
186
replacement = os.linesep.join(['#?vers : VVV?'] \
187
+ ['%s : %s' % (field, vali) for vali in value.split()])
188
regexp = re.compile(searched, re.MULTILINE)
189
content = regexp.sub(replacement, content, re.MULTILINE)
190
except: # skip invalid regexp (probably not a real field)
192
open(ficrc, 'w').write(content)
195
def print_diff(fromfile, tofile):
196
fromdate = time.ctime(os.stat(fromfile).st_mtime)
197
todate = time.ctime(os.stat(tofile).st_mtime)
198
fromlines = open(fromfile, 'U').readlines()
199
tolines = open(tofile, 'U').readlines()
201
diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile,
206
def backup_name(filename, ext, hidden=True):
207
"""From 'filename' + '.ext' returns '.ext-filename' if hidden is True, 'filename.ext' else."""
210
dirname, basename = os.path.split(filename)
212
basename = ext + '-' + basename
214
basename = basename + ext
215
return os.path.join(dirname, basename)
218
def chmod_scripts(files):
219
if type(files) not in (list, tuple):
221
for filename in files:
222
mode = ((os.stat(filename)[ST_MODE]) | 0555) & 07777
223
log.info("changing mode of %s to %o", filename, mode)
224
os.chmod(filename, mode)
228
def _test_get_function():
229
ff = ( ('0.0.0', 'func < 1.7.5'), ('1.7.5', 'func >= 1.7.5'), ('1.8.0', 'func >= 1.8.0') )
230
for v in ('1.2.3', '1.7.4', '1.7.5', '1.7.99', '1.8', '1.8.01', 'unknown'):
231
print v, '-->', get_function(ff, v)