summarylogtreecommitdiffstats
path: root/fixshebangs.py
diff options
context:
space:
mode:
authorAdrian Perez de Castro2015-07-23 12:46:03 +0300
committerAdrian Perez de Castro2015-07-23 12:46:03 +0300
commit5e24a9ca6ca8b396cde2c90ec907bd42fe452c0c (patch)
tree280290b3363239fd615b60c5cea233554fb76abb /fixshebangs.py
parentc8ce17cf6bb7923a9c13782b015881b2d41beb1f (diff)
downloadaur-5e24a9ca6ca8b396cde2c90ec907bd42fe452c0c.tar.gz
Add script to fix all Python script shebangs
Having a script to fix the Python shebangs (to make CLI tools use "python2") is more robust to upstream changes than to specify manually the list of files to fix. After this change, Python scripts which contain a shebang will all of them be changed to use "/usr/bin/env python2"; but still there is a manually defined list of scripts which use "exec python", that are passed through "sed" to fix that. These (shell) scripts do not change that often, and it may be better to keep the list to avoid potential damage when applygin the "sed" to all the files.
Diffstat (limited to 'fixshebangs.py')
-rwxr-xr-xfixshebangs.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/fixshebangs.py b/fixshebangs.py
new file mode 100755
index 000000000000..e2202c9a205f
--- /dev/null
+++ b/fixshebangs.py
@@ -0,0 +1,74 @@
+#! /usr/bin/env python2
+# -*- coding: utf-8 -*-
+# vim:fenc=utf-8
+#
+# Copyright © 2015 Adrian Perez <aperez@igalia.com>
+#
+# Distributed under terms of the MIT license.
+
+from os import path, unlink, fstat, utime, chmod
+
+
+VERBOSE = False
+def verbose(fmt, *arg):
+ if VERBOSE:
+ from sys import stdout
+ stdout.write(fmt % arg)
+
+
+def is_python_shebang(line):
+ return line.startswith("#!") and \
+ (line.split()[-1].startswith("python") or
+ line.split("/")[-1].startswith("python"))
+
+
+def add_shebang(fpath, fd, shebang=None):
+ if shebang is None:
+ shebang = "#! /usr/bin/env python2"
+
+ # Save metadata of the open file.
+ stat = fstat(fd.fileno())
+
+ # Unlink the original file name. The contents will be available
+ # for reading as long as we keep an open file descriptor to it.
+ unlink(fpath)
+
+ # Write new shebang as first line, then the original contents
+ with open(fpath, "w") as outfd:
+ outfd.write(shebang)
+ outfd.write("\n")
+ [outfd.write(chunk) for chunk in fd]
+
+ # Restore original file metadata.
+ utime(fpath, (stat.st_atime, stat.st_mtime))
+ chmod(fpath, stat.st_mode)
+
+
+def check_files(arg, dirname, fnames):
+ assert arg is None
+ for fname in fnames:
+ if fname.startswith("."):
+ continue
+ fpath = path.join(dirname, fname)
+ if not path.isfile(fpath):
+ continue
+ with open(fpath, "rU") as fd:
+ line = fd.readline().strip()
+ if is_python_shebang(line):
+ verbose("Fixing: %s\n", fpath)
+ add_shebang(fpath, fd)
+ else:
+ verbose("Skipped: %s\n", fpath)
+
+
+if __name__ == "__main__":
+ import sys
+ argv = sys.argv[1:]
+ if len(argv) > 0 and argv[0] in ("-v", "--verbose"):
+ VERBOSE = True
+ argv = argv[1:]
+
+ if len(argv) == 0:
+ argv.append(".")
+
+ [path.walk(top, check_files, None) for top in argv]