[reprotest] 01/01: Add a --store-dir option to save artifacts

Ximin Luo infinity0 at debian.org
Thu Jan 5 19:38:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository reprotest.

commit 3b062e0fdf8fae8bb6faf81c839ec6c0dd608426
Author: Ximin Luo <infinity0 at debian.org>
Date:   Thu Jan 5 20:13:44 2017 +0100

    Add a --store-dir option to save artifacts
---
 debian/changelog      |  1 +
 reprotest/__init__.py | 44 ++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 6135eba..b7c24fa 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -4,6 +4,7 @@ reprotest (0.5) UNRELEASED; urgency=medium
     That is: domain_host, shell, user_group.
   * Fix auto-presets in the case of a file in the current directory.
   * Allow disabling build-path variations. (Closes: #833284)
+  * Add a --store-dir option to save artifacts.
 
  -- Ximin Luo <infinity0 at debian.org>  Thu, 01 Dec 2016 19:31:55 +0100
 
diff --git a/reprotest/__init__.py b/reprotest/__init__.py
index e245360..7418300 100644
--- a/reprotest/__init__.py
+++ b/reprotest/__init__.py
@@ -386,12 +386,31 @@ def build(script, env, source_root_orig, source_root_build, dist_root, artifact_
         (dist_root, source_root_orig, dist_root, artifact_pattern, dist_root, dist_root)])
 
 
+def run_or_tee(progargs, filename, store_dir, *args, **kwargs):
+    if store_dir:
+        tee = subprocess.Popen(['tee', filename], stdin=subprocess.PIPE, cwd=store_dir)
+        r = subprocess.run(progargs, *args, stdout=tee.stdin, **kwargs)
+        tee.communicate()
+        return r
+    else:
+        return subprocess.run(progargs)
+
+
 def check(build_command, artifact_pattern, virtual_server_args, source_root,
-          no_clean_on_error=False, variations=VARIATIONS, diffoscope_args=[],
+          no_clean_on_error=False, variations=VARIATIONS,
+          store_dir=None, diffoscope_args=[],
           testbed_pre=None, testbed_init=None):
     # default argument [] is safe here because we never mutate it.
     if not source_root:
         raise ValueError("invalid source root: %s" % source_root)
+    if store_dir:
+        store_dir = str(store_dir)
+        if not os.path.exists(store_dir):
+            os.makedirs(store_dir, exist_ok=False)
+        elif os.listdir(store_dir):
+            raise ValueError("store_dir must be empty: %s" % store_dir)
+        store = Pair(os.path.join(store_dir, "control"),
+                     os.path.join(store_dir, "experiment"))
 
     # print(virtual_server_args)
     script = Pair.of(Script(build_command))
@@ -447,19 +466,30 @@ def check(build_command, artifact_pattern, virtual_server_args, source_root,
                 traceback.print_exc()
                 return 2
 
+        if store_dir:
+            shutil.copytree(result.control, store.control, symlinks=True)
+            shutil.copytree(result.experiment, store.experiment, symlinks=True)
+
         if diffoscope_args is None: # don't run diffoscope
             diffprogram = ['diff', '-ru', result.control, result.experiment]
             print("Running diff: ", diffprogram)
         else:
             diffprogram = ['diffoscope', result.control, result.experiment] + diffoscope_args
             print("Running diffoscope: ", diffprogram)
-        retcode = subprocess.call(diffprogram)
+
+        retcode = run_or_tee(diffprogram, 'diffoscope.out', store_dir).returncode
         if retcode == 0:
             print("=======================")
             print("Reproduction successful")
             print("=======================")
             print("No differences in %s" % artifact_pattern, flush=True)
-            subprocess.call(['find', '.', '-type', 'f', '-exec', 'sha256sum', '{}', ';'], cwd=result.control)
+            run_or_tee(['find', '.', '-type', 'f', '-exec', 'sha256sum', '{}', ';'],
+                'SHA256SUMS', store_dir,
+                cwd=result.control)
+
+            if store_dir:
+                shutil.rmtree(store.experiment)
+                os.symlink("control", store.experiment)
         else:
             # a slight hack, to trigger no_clean_on_error
             raise SystemExit(retcode)
@@ -498,6 +528,11 @@ COMMAND_LINE_OPTIONS = types.MappingProxyType(collections.OrderedDict([
         'dest': 'source_root', 'type': pathlib.Path,
         'help': 'Root of the source tree, if not the '
         'current working directory.'})),
+    ('--store-dir', types.MappingProxyType({
+        'default': None, 'type': pathlib.Path,
+        'help': 'Save the artifacts in this directory, which must be empty or '
+        'non-existent. Otherwise, the artifacts will be deleted and you only '
+        'see their hashes (if reproducible) or the diff output (if not).'})),
     ('--testbed-pre', types.MappingProxyType({
         'default': None, 'metavar': 'COMMANDS',
         'help': 'Shell commands to run before starting the test bed, in the '
@@ -655,6 +690,7 @@ def main():
     logging.basicConfig(
         format='%(message)s', level=30-10*verbosity, stream=sys.stdout)
 
+    store_dir = command_line_options.get("store_dir")
     testbed_pre = command_line_options.get("testbed_pre")
     testbed_init = command_line_options.get("testbed_init")
 
@@ -671,5 +707,5 @@ def main():
 
     # print(build_command, artifact, virtual_server_args)
     return check(build_command, artifact, virtual_server_args, source_root,
-                 no_clean_on_error, variations, diffoscope_args,
+                 no_clean_on_error, variations, store_dir, diffoscope_args,
                  testbed_pre, testbed_init)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/reprotest.git



More information about the Reproducible-commits mailing list