diff options
author | Christopher Haster <geky@geky.net> | 2022-11-16 19:46:26 +0300 |
---|---|---|
committer | Christopher Haster <geky@geky.net> | 2022-11-16 19:46:26 +0300 |
commit | e35e078943274ab516636cb104b8addd0e118fd0 (patch) | |
tree | fd9b37510e098eb0e325d0ae18636df52eee0fe6 | |
parent | 1a07c2ce0d4613094b6b72d1416f3d6034933cba (diff) |
Renamed prefix.py -> changeprefix.py and updated to use argparse
Added a couple flags to make the script a bit more flexible, and removed
littlefs-specific default in line with the other scripts which aren't
really littlefs-specific. (These defaults can be moved to the
littlefs-specific Makefile easily enough).
The original behavior can be reproduced like so:
./script/changeprefix.py lfs lfs2 --git
-rwxr-xr-x | scripts/changeprefix.py | 177 | ||||
-rwxr-xr-x | scripts/prefix.py | 61 |
2 files changed, 177 insertions, 61 deletions
diff --git a/scripts/changeprefix.py b/scripts/changeprefix.py new file mode 100755 index 0000000..9951e5c --- /dev/null +++ b/scripts/changeprefix.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +# +# Change prefixes in files/filenames. Useful for creating different versions +# of a codebase that don't conflict at compile time. +# +# Example: +# $ ./scripts/changeprefix.py lfs lfs3 +# +# Copyright (c) 2022, The littlefs authors. +# Copyright (c) 2019, Arm Limited. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause +# + +import glob +import itertools +import os +import os.path +import re +import shlex +import shutil +import subprocess +import tempfile + +GIT_TOOL = ['git'] + + +def openio(path, mode='r', buffering=-1): + # allow '-' for stdin/stdout + if path == '-': + if mode == 'r': + return os.fdopen(os.dup(sys.stdin.fileno()), mode, buffering) + else: + return os.fdopen(os.dup(sys.stdout.fileno()), mode, buffering) + else: + return open(path, mode, buffering) + +def changeprefix(from_prefix, to_prefix, line): + line, count1 = re.subn( + '\\b'+from_prefix, + to_prefix, + line) + line, count2 = re.subn( + '\\b'+from_prefix.upper(), + to_prefix.upper(), + line) + line, count3 = re.subn( + '\\B-D'+from_prefix.upper(), + '-D'+to_prefix.upper(), + line) + return line, count1+count2+count3 + +def changefile(from_prefix, to_prefix, from_path, to_path, *, + no_replacements=False): + # rename any prefixes in file + count = 0 + + # create a temporary file to avoid overwriting ourself + if from_path == to_path and to_path != '-': + to_path_temp = tempfile.NamedTemporaryFile('w', delete=False) + to_path = to_path_temp.name + else: + to_path_temp = None + + with openio(from_path) as from_f: + with openio(to_path, 'w') as to_f: + for line in from_f: + if not no_replacements: + line, n = changeprefix(from_prefix, to_prefix, line) + count += n + to_f.write(line) + + if from_path != '-' and to_path != '-': + shutil.copystat(from_path, to_path) + + if to_path_temp: + os.rename(to_path, from_path) + elif from_path != '-': + os.remove(from_path) + + # Summary + print('%s: %d replacements' % ( + '%s -> %s' % (from_path, to_path) if not to_path_temp else from_path, + count)) + +def main(from_prefix, to_prefix, paths=[], *, + verbose=False, + output=None, + no_replacements=False, + no_renames=False, + git=False, + no_stage=False, + git_tool=GIT_TOOL): + if not paths: + if git: + cmd = git_tool + ['ls-tree', '-r', '--name-only', 'HEAD'] + if verbose: + print(' '.join(shlex.quote(c) for c in cmd)) + paths = subprocess.check_output(cmd, encoding='utf8').split() + else: + print('no paths?', file=sys.stderr) + sys.exit(1) + + for from_path in paths: + # rename filename? + if output: + to_path = output + elif no_renames: + to_path = from_path + else: + to_path, _ = changeprefix(from_prefix, to_prefix, from_path) + + # rename contents + changefile(from_prefix, to_prefix, from_path, to_path, + no_replacements=no_replacements) + + # stage? + if git and not no_stage: + if from_path != to_path: + cmd = git_tool + ['rm', '-q', from_path] + if verbose: + print(' '.join(shlex.quote(c) for c in cmd)) + subprocess.check_call(cmd) + cmd = git_tool + ['add', to_path] + if verbose: + print(' '.join(shlex.quote(c) for c in cmd)) + subprocess.check_call(cmd) + + +if __name__ == "__main__": + import argparse + import sys + parser = argparse.ArgumentParser( + description="Change prefixes in files/filenames. Useful for creating " + "different versions of a codebase that don't conflict at compile " + "time.", + allow_abbrev=False) + parser.add_argument( + 'from_prefix', + help="Prefix to replace.") + parser.add_argument( + 'to_prefix', + help="Prefix to replace with.") + parser.add_argument( + 'paths', + nargs='*', + help="Files to operate on.") + parser.add_argument( + '-v', '--verbose', + action='store_true', + help="Output commands that run behind the scenes.") + parser.add_argument( + '-o', '--output', + help="Output file.") + parser.add_argument( + '-N', '--no-replacements', + action='store_true', + help="Don't change prefixes in files") + parser.add_argument( + '-R', '--no-renames', + action='store_true', + help="Don't rename files") + parser.add_argument( + '--git', + action='store_true', + help="Use git to find/update files.") + parser.add_argument( + '--no-stage', + action='store_true', + help="Don't stage changes with git.") + parser.add_argument( + '--git-tool', + type=lambda x: x.split(), + default=GIT_TOOL, + help="Path to git tool to use. Defaults to %r." % GIT_TOOL) + sys.exit(main(**{k: v + for k, v in vars(parser.parse_intermixed_args()).items() + if v is not None})) diff --git a/scripts/prefix.py b/scripts/prefix.py deleted file mode 100755 index 4c33ad4..0000000 --- a/scripts/prefix.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python2 - -# This script replaces prefixes of files, and symbols in that file. -# Useful for creating different versions of the codebase that don't -# conflict at compile time. -# -# example: -# $ ./scripts/prefix.py lfs2 - -import os -import os.path -import re -import glob -import itertools -import tempfile -import shutil -import subprocess - -DEFAULT_PREFIX = "lfs" - -def subn(from_prefix, to_prefix, name): - name, count1 = re.subn('\\b'+from_prefix, to_prefix, name) - name, count2 = re.subn('\\b'+from_prefix.upper(), to_prefix.upper(), name) - name, count3 = re.subn('\\B-D'+from_prefix.upper(), - '-D'+to_prefix.upper(), name) - return name, count1+count2+count3 - -def main(from_prefix, to_prefix=None, files=None): - if not to_prefix: - from_prefix, to_prefix = DEFAULT_PREFIX, from_prefix - - if not files: - files = subprocess.check_output([ - 'git', 'ls-tree', '-r', '--name-only', 'HEAD']).split() - - for oldname in files: - # Rename any matching file names - newname, namecount = subn(from_prefix, to_prefix, oldname) - if namecount: - subprocess.check_call(['git', 'mv', oldname, newname]) - - # Rename any prefixes in file - count = 0 - with open(newname+'~', 'w') as tempf: - with open(newname) as newf: - for line in newf: - line, n = subn(from_prefix, to_prefix, line) - count += n - tempf.write(line) - shutil.copystat(newname, newname+'~') - os.rename(newname+'~', newname) - subprocess.check_call(['git', 'add', newname]) - - # Summary - print '%s: %d replacements' % ( - '%s -> %s' % (oldname, newname) if namecount else oldname, - count) - -if __name__ == "__main__": - import sys - sys.exit(main(*sys.argv[1:])) |