import os
import re
import shutil
import sys
def mapDirectory(dirmap, dname):
"""Return the new location of the input directory.""" mapped_dir = p = dname
while p and not p in dirmap:
p = os.path.dirname(p)
if p:
mapped_dir = os.path.join(dirmap[p],
dname[len(p) + 1:])
return mapped_dir
def mapFiles(logfp, dirmap, dname, files):
"""Return a dictionary mapping files in dir to their new locations."""
dname = os.path.normpath(dname)
new_dir = mapDirectory(dirmap, dname)
logfp.write("mapDirectory [%s] -> [%s]\n" % (dname, new_dir))
fm = {}
for f in files:
src = os.path.join(dname, f)
dst = os.path.join(new_dir, f)
logfp.write("\t[%s] -> [%s]\n" % (src, dst))
fm[src] = dst
return fm
def isSourceFile(file):
"""Return True if the input file is a C/C++ source file."""
src_re = re.compile(r'\.(c|h)(pp)?$',
re.IGNORECASE)
return src_re.search(file) is not None
def swapSlashes(str):
"""Return the imput string with backslashes swapped to forward slashes."""
back_to_fwd_re = re.compile(r'\\')
return back_to_fwd_re.sub('/', str)
def mapIncludeFile(logfp, inc, srcdst, files_map):
"""Determine the remapped include file path.""" if os.path.dirname(inc):
pass else: inc = os.path.join(os.path.dirname(srcdst[0]), inc)
inc = os.path.normpath(inc) try:
mapped_inc = files_map[inc]
except KeyError:
err_msg = ('\nFatal error: Failed to locate [%s] '
'(included by [%s]) '
'relative to source root.' % (inc, srcdst[0]))
logfp.write(err_msg)
sys.stderr.write(err_msg)
sys.exit(1)
if (os.path.dirname(mapped_inc) ==
os.path.dirname(srcdst[1])):
mapped_inc = os.path.basename(mapped_inc)
return mapped_inc
def processSourceLine(logfp, line, srcdst, files_map):
"""Process a line from a source file, correcting included file paths."""
include_re = re.compile(
r'^\s*#\s*include\s*"'
r'(?P<inc_file>\S+)'
'"')
match = include_re.match(line)
if match:
logfp.write(' [%s] -> ' % line.rstrip())
mapped_inc_file = mapIncludeFile(
logfp,
match.group('inc_file'),
srcdst,
files_map
)
line = line[:match.start('inc_file')] + \
mapped_inc_file + \
line[match.end('inc_file'):]
line = swapSlashes(line)
logfp.write('[%s]\n' % line.rstrip())
return line
def relocateSource(logfp, srcdst, dstfile, files_map):
"""Relocate a source file, correcting paths to included files."""
infp = open(srcdst[0], 'r')
outfp = open(dstfile, 'w')
logfp.write('Relocating source file [%s] -> [%s]\n' %
(srcdst[0], dstfile))
for line in infp:
outfp.write(
processSourceLine(
logfp, line, srcdst, files_map)
)
infp.close()
outfp.close()
def relocate(logfp, srcdst, dst_root, files_map):
"""Relocate a file, correcting internal file references."""
dst_file = os.path.join(dst_root, srcdst[1])
dst_dir = os.path.dirname(dst_file)
if not os.path.isdir(dst_dir):
os.makedirs(dst_dir)
if isSourceFile(dst_file):
relocateSource(logfp, srcdst, dst_file, files_map)
else:
logfp.write('Copying [%s] -> [%s]\n' %
(srcdst[0], dst_file))
shutil.copyfile(srcdst[0], dst_file)
def percent(num, denom):
"""Return num / denom expressed as an integer percentage."""
return int(num * 100 / denom)
def printSettings(fp, dmap, src, dst):
"""Output script settings to the input file."""
fp.write('Relocating source tree from [%s] to [%s]\n' %
(src, dst))
fp.write('Relocating directories:\n')
for d in dirmap:
fp.write(' [%s] -> [%s]\n' %
(d, dmap[d]))
fp.write('\n')np = os.path.normpath
dirmap = {
np('png') : np('graphics/thirdparty/png'),
np('jpeg') : np('graphics/thirdparty/jpeg'),
np('bitmap') : np('graphics/common/bitmap'),
np('UserIF') : np('ui'),
np('UserIF/Wgts') : np('ui/widgets'),
np('os') : np('platform/os'),
np('os/hpux') : np('platform/os/hpux10')
}
from_root = '.'
to_root = '../relocate'logfp = open('relocate.log', 'w')
printSettings(logfp, dirmap, from_root, to_root)
printSettings(sys.stdout, dirmap, from_root, to_root)files_map = {}sys.stdout.write('Preprocessing files. Please wait.\n')
for (subdir, dirs, files) in os.walk(from_root):
files_map.update(
mapFiles(logfp, dirmap, subdir, files)
)os.makedirs(to_root)count = len(files_map)
item = 0
sys.stdout.write('Relocating [%d] files.\n'
'Logfile at [%s]\n'
'Progress [%02d%%]' %
(count, logfp.name, percent(item, count))
)
for srcdst in files_map.items():
item += 1
sys.stdout.write('\b\b\b\b%02d%%]' %
percent(item, count))
relocate(logfp, srcdst, to_root, files_map)
logfp.close()
sys.stdout.write('\nRelocation completed successfully.\n')