Jelajahi Sumber

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
Christopher Haster 3 tahun lalu
induk
melakukan
e35e078943
2 mengubah file dengan 177 tambahan dan 61 penghapusan
  1. 177 0
      scripts/changeprefix.py
  2. 0 61
      scripts/prefix.py

+ 177 - 0
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}))

+ 0 - 61
scripts/prefix.py

@@ -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:]))