Skip to content

Commit

Permalink
Renamed prefix.py -> changeprefix.py and updated to use argparse
Browse files Browse the repository at this point in the history
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
  • Loading branch information
geky committed Nov 16, 2022
1 parent 1a07c2c commit e35e078
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 61 deletions.
177 changes: 177 additions & 0 deletions scripts/changeprefix.py
Original file line number Diff line number Diff line change
@@ -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}))
61 changes: 0 additions & 61 deletions scripts/prefix.py

This file was deleted.

0 comments on commit e35e078

Please sign in to comment.