summaryrefslogtreecommitdiff
path: root/test/create-sys-script.py
diff options
context:
space:
mode:
authorDan Streetman <ddstreet@ieee.org>2017-02-10 15:27:18 -0500
committerDan Streetman <ddstreet@ieee.org>2017-02-10 15:27:18 -0500
commitd001ac2c01c9748182f686e1acfbe128126fc663 (patch)
tree790df618c6f027133d47a1e7cd9140baee64cc06 /test/create-sys-script.py
parent8367fea557cffaa6e870ccf1b94a063f560a922f (diff)
downloadsystemd-d001ac2c01c9748182f686e1acfbe128126fc663.tar.gz
test: add script to convert sys/ into sys-script.py
Instead of keeping all sys/ nodes in a tarball, use a script "sys-script.py" to create all the sys/ entries. This adds a script to create that initial "sys-script.py" script, using an existing sys/ directory, created from the sys.tar.xz contents. The "sys-script.py" can then be edited or recreated later, when any sys/ files are added or modified; the change will be only a patch to the "sys-script.py" script in git, instead of forcing git to store a new binary tarball.
Diffstat (limited to 'test/create-sys-script.py')
-rwxr-xr-xtest/create-sys-script.py183
1 files changed, 183 insertions, 0 deletions
diff --git a/test/create-sys-script.py b/test/create-sys-script.py
new file mode 100755
index 0000000000..4b7abd24ae
--- /dev/null
+++ b/test/create-sys-script.py
@@ -0,0 +1,183 @@
+#!/usr/bin/python3
+
+OUTFILE_HEADER = """#!/usr/bin/python3
+#
+# create-sys-script.py
+#
+# (C) 2017 Canonical Ltd.
+# Author: Dan Streetman <dan.streetman@canonical.com>
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# systemd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with systemd; If not, see <http://www.gnu.org/licenses/>.
+#
+"""
+
+# Use this only to (re-)create the test/sys-script.py script,
+# after adding or modifying anything in the test/sys/ directory
+
+
+import os, sys, stat, tempfile, filecmp
+
+
+OUTFILE = "sys-script.py"
+OUTFILE_MODE = 0o775
+
+OUTFILE_FUNCS = r"""
+import os, sys
+
+def d(path, mode):
+ os.mkdir(path, mode)
+
+def l(path, src):
+ os.symlink(src, path)
+
+def f(path, mode, contents):
+ with open(path, "wb") as f:
+ f.write(contents)
+ os.chmod(path, mode)
+
+"""
+
+OUTFILE_MAIN = """
+if len(sys.argv) < 2:
+ exit("Usage: {} <target dir>".format(sys.argv[0]))
+
+if not os.path.isdir(sys.argv[1]):
+ exit("Target dir {} not found".format(sys.argv[1]))
+
+os.chdir(sys.argv[1])
+
+"""
+
+
+def handle_dir(outfile, path):
+ m = os.lstat(path).st_mode & 0o777
+ outfile.write("d('{}', {:#o})\n".format(path, m))
+
+
+def handle_link(outfile, path):
+ src = os.readlink(path)
+ outfile.write("l('{}', '{}')\n".format(path, src))
+
+
+def escape_single_quotes(b):
+ # remove the b'' wrapping each line repr
+ r = repr(b)[2:-1]
+ # python escapes all ' only if there are ' and " in the string
+ if '"' not in r:
+ r = r.replace("'", r"\'")
+ # return line with all ' escaped
+ return r
+
+
+def handle_file(outfile, path):
+ m = os.lstat(path).st_mode & 0o777
+ with open(path, "rb") as f:
+ b = f.read()
+ if b.count(b"\n") > 1:
+ r = "\n".join([ escape_single_quotes(l) for l in b.split(b"\n") ])
+ r = "b'''{r}'''".format(r=r)
+ else:
+ r = repr(b)
+ outfile.write("f('{}', {:#o}, {})\n".format(path, m, r))
+
+
+def process_sysdir(outfile):
+ for (dirpath, dirnames, filenames) in os.walk("sys"):
+ handle_dir(outfile, dirpath)
+ for d in dirnames:
+ path = os.path.join(dirpath, d)
+ if stat.S_ISLNK(os.lstat(path).st_mode):
+ handle_link(outfile, path)
+ for f in filenames:
+ path = os.path.join(dirpath, f)
+ mode = os.lstat(path).st_mode
+ if stat.S_ISLNK(mode):
+ handle_link(outfile, path)
+ elif stat.S_ISREG(mode):
+ handle_file(outfile, path)
+
+
+def verify_dir(tmpd, path_a):
+ path_b = os.path.join(tmpd, path_a)
+ mode_a = os.lstat(path_a).st_mode
+ mode_b = os.lstat(path_b).st_mode
+ if not stat.S_ISDIR(mode_b):
+ raise Exception("Not directory")
+ if (mode_a & 0o777) != (mode_b & 0o777):
+ raise Exception("Permissions mismatch")
+
+
+def verify_link(tmpd, path_a):
+ path_b = os.path.join(tmpd, path_a)
+ if not stat.S_ISLNK(os.lstat(path_b).st_mode):
+ raise Exception("Not symlink")
+ if os.readlink(path_a) != os.readlink(path_b):
+ raise Exception("Symlink dest mismatch")
+
+
+def verify_file(tmpd, path_a):
+ path_b = os.path.join(tmpd, path_a)
+ mode_a = os.lstat(path_a).st_mode
+ mode_b = os.lstat(path_b).st_mode
+ if not stat.S_ISREG(mode_b):
+ raise Exception("Not file")
+ if (mode_a & 0o777) != (mode_b & 0o777):
+ raise Exception("Permissions mismatch")
+ if not filecmp.cmp(path_a, path_b, shallow=False):
+ raise Exception("File contents mismatch")
+
+
+def verify_script(tmpd):
+ for (dirpath, dirnames, filenames) in os.walk("sys"):
+ try:
+ path = dirpath
+ verify_dir(tmpd, path)
+ for d in dirnames:
+ path = os.path.join(dirpath, d)
+ if stat.S_ISLNK(os.lstat(path).st_mode):
+ verify_link(tmpd, path)
+ for f in filenames:
+ path = os.path.join(dirpath, f)
+ mode = os.lstat(path).st_mode
+ if stat.S_ISLNK(mode):
+ verify_link(tmpd, path)
+ elif stat.S_ISREG(mode):
+ verify_file(tmpd, path)
+ except Exception:
+ print("FAIL on '{}'".format(path), file=sys.stderr)
+ raise
+
+
+if __name__ == "__main__":
+ # Always operate in the dir where this script is
+ os.chdir(os.path.dirname(sys.argv[0]))
+
+ if not os.path.isdir("sys"):
+ exit("No sys/ directory; please create before running this")
+
+ print("Creating {} using contents of sys/".format(OUTFILE))
+
+ with open(OUTFILE, "w") as f:
+ os.chmod(OUTFILE, OUTFILE_MODE)
+ f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]), OUTFILE))
+ f.write(OUTFILE_FUNCS)
+ f.write(OUTFILE_MAIN)
+ process_sysdir(f)
+
+ with tempfile.TemporaryDirectory() as tmpd:
+ print("Recreating sys/ using {} at {}".format(OUTFILE, tmpd))
+ os.system("./{script} {tmpd}".format(script=OUTFILE, tmpd=tmpd))
+ verify_script(tmpd)
+
+ print("Verification successful, {} is correct".format(OUTFILE))