[reprozip] 01/02: Initial debianisation

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Tue May 2 08:12:28 UTC 2017


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

ghisvail-guest pushed a commit to branch master
in repository reprozip.

commit 6079cb1be1d178f2941dbc2312735afb61cd4e8d
Author: Ghislain Antony Vaillant <ghisvail at gmail.com>
Date:   Fri Apr 21 08:28:29 2017 +0100

    Initial debianisation
---
 debian/changelog                  |   5 +
 debian/compat                     |   1 +
 debian/control                    |  82 +++++++
 debian/copyright                  |  39 ++++
 debian/gbp.conf                   |   7 +
 debian/reprozip.lintian-overrides |   2 +
 debian/rules                      |  22 ++
 debian/source/format              |   1 +
 debian/source/local-options       |   1 +
 debian/tests/control              |   9 +
 debian/tests/test_reprozip.py     | 446 ++++++++++++++++++++++++++++++++++++++
 debian/watch                      |   3 +
 12 files changed, 618 insertions(+)

diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..8cc9b36
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+reprozip (1.0.9-1) UNRELEASED; urgency=low
+
+  * Initial release. (Closes: #860531)
+
+ -- Ghislain Antony Vaillant <ghisvail at gmail.com>  Fri, 21 Apr 2017 08:27:46 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..f599e28
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+10
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..de5475d
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,82 @@
+Source: reprozip
+Maintainer: Debian Science Maintainers <debian-science-maintainers at lists.alioth.debian.org>
+Uploaders: Ghislain Antony Vaillant <ghisvail at gmail.com>
+Section: science
+Priority: optional
+Build-Depends: debhelper (>= 10),
+               dh-python,
+               libsqlite3-dev,
+               python3-all-dbg,
+               python3-all-dev,
+               python3-requests,
+               python3-rpaths,
+               python3-setuptools,
+               python3-usagestats,
+               python3-yaml
+Standards-Version: 3.9.8
+Vcs-Browser: https://anonscm.debian.org/git/debian-science/packages/reprozip.git
+Vcs-Git: https://anonscm.debian.org/git/debian-science/packages/reprozip.git
+Homepage: https://www.reprozip.org
+X-Python3-Version: >= 3.3
+
+Package: reprozip
+Architecture: all
+Multi-Arch: foreign
+Section: utils
+Depends: ${misc:Depends},
+         ${python3:Depends},
+         python3-reprozip
+Description: Linux tools for reproducible experiments (packer)
+ ReproZip is a tool aimed at simplifying the process of creating
+ reproducible experiments from command-line executions, a frequently-used
+ common denominator in computational science.
+ .
+ It tracks operating system calls and creates a package that contains
+ all the binaries, files and dependencies required to run a given
+ command on the author’s computational environment (packing step). A
+ reviewer can then extract the experiment in his environment to
+ reproduce the results (unpacking step).
+ .
+ This package provides the ReproZip packer.
+
+Package: python3-reprozip
+Architecture: linux-any
+Multi-Arch: same
+Section: python
+Depends: ${misc:Depends},
+         ${python3:Depends},
+         ${shlibs:Depends}
+Description: modules for the ReproZip packer
+ ReproZip is a tool aimed at simplifying the process of creating
+ reproducible experiments from command-line executions, a frequently-used
+ common denominator in computational science.
+ .
+ It tracks operating system calls and creates a package that contains
+ all the binaries, files and dependencies required to run a given
+ command on the author’s computational environment (packing step). A
+ reviewer can then extract the experiment in his environment to
+ reproduce the results (unpacking step).
+ .
+ This package provides the modules for Python 3.
+
+Package: python3-reprozip-dbg
+Architecture: linux-any
+Multi-Arch: same
+Section: debug
+Priority: extra
+Depends: ${misc:Depends},
+         ${python3:Depends},
+         ${shlibs:Depends},
+         python3-reprozip (= ${binary:Version})
+Description: debug extensions for the ReproZip packer
+ ReproZip is a tool aimed at simplifying the process of creating
+ reproducible experiments from command-line executions, a frequently-used
+ common denominator in computational science.
+ .
+ It tracks operating system calls and creates a package that contains
+ all the binaries, files and dependencies required to run a given
+ command on the author’s computational environment (packing step). A
+ reviewer can then extract the experiment in his environment to
+ reproduce the results (unpacking step).
+ .
+ This package provides the debug extensions for Python 3.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..be416c4
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,39 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: reprozip
+Source: https://pypi.python.org/pypi/reprozip
+
+Files: *
+Copyright: 2014-2017 New York University
+License: BSD-3-Clause
+
+Files: debian/*
+Copyright: 2017 Ghislain Antony Vaillant
+License: BSD-3-Clause
+
+License: BSD-3-Clause
+  BSD 3-Clause License
+  .
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+  .
+  * Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+  .
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+  .
+  * Neither the name of the copyright holder nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+  .
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..f53906f
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,7 @@
+[DEFAULT]
+upstream-branch = upstream
+debian-branch = master
+upstream-tag = upstream/%(version)s
+debian-tag = debian/%(version)s
+sign-tags = True
+pristine-tar = True
diff --git a/debian/reprozip.lintian-overrides b/debian/reprozip.lintian-overrides
new file mode 100644
index 0000000..703ed68
--- /dev/null
+++ b/debian/reprozip.lintian-overrides
@@ -0,0 +1,2 @@
+# Upstream does not provide manpages for the command-line tools yet.
+binary-without-manpage
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..f87797f
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,22 @@
+#!/usr/bin/make -f
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE = 1
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+export PYBUILD_NAME = reprozip
+export PYBUILD_TEST_ARGS = {dir}/debian/tests
+export PYBUILD_AFTER_INSTALL_python3-dbg = rm -rf {destdir}/usr/bin
+
+%:
+	dh $@ --with python3 --buildsystem=pybuild
+
+override_dh_auto_install:
+	dh_auto_install
+	dh_movefiles --package=$(PYBUILD_NAME) \
+		--sourcedir=debian/python3-$(PYBUILD_NAME) usr/bin
+
+override_dh_strip:
+	dh_strip --package=python3-$(PYBUILD_NAME) \
+		--dbg-package=python3-$(PYBUILD_NAME)-dbg
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/local-options b/debian/source/local-options
new file mode 100644
index 0000000..b2b7b88
--- /dev/null
+++ b/debian/source/local-options
@@ -0,0 +1 @@
+extend-diff-ignore="^[^/]+\.egg-info/"
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..fd4ecd4
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,9 @@
+Test-Command: set -e
+ ; cd "$AUTOPKGTEST_TMP"
+ ; HOME=/tmp
+ ; reprozip usage_report --disable
+ ; reprozip testrun /bin/echo
+ ; reprozip -v trace /bin/echo
+ ; reprozip -v pack echo.rpz
+Depends: reprozip
+Restrictions: allow-stderr
diff --git a/debian/tests/test_reprozip.py b/debian/tests/test_reprozip.py
new file mode 100644
index 0000000..d2d46b2
--- /dev/null
+++ b/debian/tests/test_reprozip.py
@@ -0,0 +1,446 @@
+# Copyright (C) 2014-2017 New York University
+# This file is part of ReproZip which is released under the Revised BSD License
+# See file LICENSE for full license details.
+
+from __future__ import print_function, unicode_literals
+
+import os
+
+import sqlite3
+from rpaths import AbstractPath, Path
+import sys
+import unittest
+
+from reprozip.common import FILE_READ, FILE_WRITE, FILE_WDIR, InputOutputFile
+from reprozip.tracer.trace import get_files, compile_inputs_outputs
+from reprozip import traceutils
+from reprozip.utils import PY3, unicode_, UniqueNames, make_dir_writable
+
+
+def make_database(insert, path=None):
+    if path is not None:
+        path = Path(path)
+        if PY3:
+            # On PY3, connect() only accepts unicode
+            conn = sqlite3.connect(str(path))
+        else:
+            conn = sqlite3.connect(path.path)
+    else:
+        conn = sqlite3.connect('')
+    conn.row_factory = sqlite3.Row
+
+    conn.execute(
+        '''
+        CREATE TABLE processes(
+            id INTEGER NOT NULL PRIMARY KEY,
+            run_id INTEGER NOT NULL,
+            parent INTEGER,
+            timestamp INTEGER NOT NULL,
+            is_thread BOOLEAN NOT NULL,
+            exitcode INTEGER
+            );
+        ''')
+    conn.execute(
+        '''
+        CREATE INDEX proc_parent_idx ON processes(parent);
+        ''')
+    conn.execute(
+        '''
+        CREATE TABLE opened_files(
+            id INTEGER NOT NULL PRIMARY KEY,
+            run_id INTEGER NOT NULL,
+            name TEXT NOT NULL,
+            timestamp INTEGER NOT NULL,
+            mode INTEGER NOT NULL,
+            is_directory BOOLEAN NOT NULL,
+            process INTEGER NOT NULL
+            );
+        ''')
+    conn.execute(
+        '''
+        CREATE INDEX open_proc_idx ON opened_files(process);
+        ''')
+    conn.execute(
+        '''
+        CREATE TABLE executed_files(
+            id INTEGER NOT NULL PRIMARY KEY,
+            name TEXT NOT NULL,
+            run_id INTEGER NOT NULL,
+            timestamp INTEGER NOT NULL,
+            process INTEGER NOT NULL,
+            argv TEXT NOT NULL,
+            envp TEXT NOT NULL,
+            workingdir TEXT NOT NULL
+            );
+        ''')
+    conn.execute(
+        '''
+        CREATE INDEX exec_proc_idx ON executed_files(process);
+        ''')
+
+    for timestamp, l in enumerate(insert):
+        if l[0] == 'proc':
+            ident, parent, is_thread = l[1:]
+            conn.execute(
+                '''
+                INSERT INTO processes(id, run_id, parent, timestamp,
+                                      is_thread, exitcode)
+                VALUES(?, 0, ?, ?, ?, 0);
+                ''',
+                (ident, parent, timestamp, is_thread))
+        elif l[0] == 'open':
+            process, name, is_dir, mode = l[1:]
+            conn.execute(
+                '''
+                INSERT INTO opened_files(run_id, name, timestamp, mode,
+                                         is_directory, process)
+                VALUES(0, ?, ?, ?, ?, ?);
+                ''',
+                (name, timestamp, mode, is_dir, process))
+        elif l[0] == 'exec':
+            process, name, wdir, argv = l[1:]
+            conn.execute(
+                '''
+                INSERT INTO executed_files(run_id, name, timestamp,
+                                           process, argv, envp,
+                                           workingdir)
+                VALUES(0, ?, ?, ?, ?, "", ?);
+                ''',
+                (name, timestamp, process, argv, wdir))
+        else:
+            assert False
+
+    conn.commit()
+    return conn
+
+
+class TestReprozip(unittest.TestCase):
+    @unittest.skipUnless(hasattr(os, 'chown'), "No POSIX file permissions")
+    def test_make_dir_writable(self):
+        """Tests make_dir_writable with read-only dir."""
+        def check_mode(mod, path):
+            self.assertEqual(oct((path.stat().st_mode & 0o0700) >> 6),
+                             oct(mod))
+
+        tmp = Path.tempdir()
+        try:
+            (tmp / 'some' / 'path').mkdir(parents=True)
+            (tmp / 'some' / 'path').chmod(0o555)
+            with make_dir_writable(tmp / 'some' / 'path'):
+                check_mode(7, tmp / 'some')
+                check_mode(7, tmp / 'some' / 'path')
+            check_mode(7, tmp / 'some')
+            check_mode(5, tmp / 'some' / 'path')
+        finally:
+            (tmp / 'some').chmod(0o755)
+            (tmp / 'some' / 'path').chmod(0o755)
+            tmp.rmtree()
+
+    @unittest.skipUnless(hasattr(os, 'chown'), "No POSIX file permissions")
+    def test_make_dir_writable2(self):
+        """Tests make_dir_writable with read-only and no-executable dirs."""
+        def check_mode(mod, path):
+            self.assertEqual(oct((path.stat().st_mode & 0o0700) >> 6),
+                             oct(mod))
+
+        tmp = Path.tempdir()
+        try:
+            (tmp / 'some' / 'complete' / 'path').mkdir(parents=True)
+            (tmp / 'some' / 'complete' / 'path').chmod(0o555)
+            (tmp / 'some' / 'complete').chmod(0o444)
+            with make_dir_writable(tmp / 'some' / 'complete' / 'path'):
+                check_mode(7, tmp / 'some')
+                check_mode(7, tmp / 'some' / 'complete')
+                check_mode(7, tmp / 'some' / 'complete' / 'path')
+            check_mode(7, tmp / 'some')
+            check_mode(4, tmp / 'some' / 'complete')
+            (tmp / 'some' / 'complete').chmod(0o755)
+            check_mode(5, tmp / 'some' / 'complete' / 'path')
+        finally:
+            (tmp / 'some').chmod(0o755)
+            (tmp / 'some' / 'complete').chmod(0o755)
+            (tmp / 'some' / 'complete' / 'path').chmod(0o755)
+            tmp.rmtree()
+
+    @unittest.skipIf(sys.version_info < (2, 7, 3),
+                     "Python version not supported by reprozip")
+    def test_argparse(self):
+        """Tests argument parsing"""
+        calls = []
+
+        def testrun(args):
+            calls.append(('t', args.verbosity))
+
+        def setup_logging(tag, verbosity):
+            calls.append(('l', verbosity))
+
+        import reprozip.main
+
+        old_funcs = reprozip.main.testrun, reprozip.main.setup_logging
+        reprozip.main.testrun = testrun
+        reprozip.main.setup_logging = setup_logging
+        old_argv = sys.argv
+        print("<<<<< argparse tests for reprozip (disregard usage warnings)",
+              file=sys.stderr)
+        try:
+            for a, c, v in [('reprozip', 2, -1),
+                            ('reprozip -v', 2, -1),
+                            ('reprozip testrun true', 0, 1),
+                            ('reprozip testrun -v true', 2, -1),
+                            ('reprozip -v testrun true', 0, 2),
+                            ('reprozip -v -v testrun true', 0, 3)]:
+                sys.argv = a.split()
+                with self.assertRaises(SystemExit) as cm:
+                    reprozip.main.main()
+                self.assertEqual(cm.exception.code, c)
+                if c == 0:
+                    self.assertEqual(calls, [('l', v), ('t', v)])
+                calls = []
+        finally:
+            print(">>>>> argparse tests", file=sys.stderr)
+            sys.argv = old_argv
+            reprozip.main.testrun, reprozip.main.setup_logging = old_funcs
+
+
+class TestNames(unittest.TestCase):
+    def test_uniquenames(self):
+        """Tests UniqueNames."""
+        u = UniqueNames()
+        self.assertEqual(u('test'), 'test')
+        self.assertEqual(u('test'), 'test_2')
+        self.assertEqual(u('test'), 'test_3')
+        self.assertEqual(u('test_2'), 'test_2_2')
+        self.assertEqual(u('test_'), 'test_')
+        self.assertEqual(u('test_'), 'test__2')
+
+    def test_label_files(self):
+        """Tests input/output file labelling."""
+        wd = Path('/fakeworkingdir')
+        self.assertEqual(
+            compile_inputs_outputs(
+                [{'argv': ['aa', 'bb.txt'], 'workingdir': wd}],
+                [[wd / 'aa', Path('/other/cc.bin'), wd / 'bb.txt']],
+                [[]]),
+            {'arg0': InputOutputFile(wd / 'aa', [0], []),
+             'cc.bin': InputOutputFile(Path('/other/cc.bin'), [0], []),
+             'arg1': InputOutputFile(wd / 'bb.txt', [0], [])})
+
+
+class TestFiles(unittest.TestCase):
+    def do_test(self, insert):
+        conn = make_database(insert)
+
+        try:
+            files, inputs, outputs = get_files(conn)
+            files = set(fi for fi in files
+                        if not fi.path.path.startswith(b'/lib'))
+            return files, inputs, outputs
+        finally:
+            conn.close()
+
+    @classmethod
+    def make_paths(cls, obj):
+        if isinstance(obj, set):
+            return set(cls.make_paths(e) for e in obj)
+        elif isinstance(obj, list):
+            return [cls.make_paths(e) for e in obj]
+        elif isinstance(obj, AbstractPath):
+            return obj
+        elif isinstance(obj, (bytes, unicode_)):
+            return Path(obj)
+        else:
+            assert False
+
+    def assertEqualPaths(self, objs, second):
+        self.assertEqual(self.make_paths(objs), second)
+
+    def test_get_files(self):
+        files, inputs, outputs = self.do_test([
+            ('proc', 0, None, False),
+            ('open', 0, "/some/dir", True, FILE_WDIR),
+            ('exec', 0, "/some/dir/ls", "/some/dir", "ls\0"),
+            ('open', 0, "/some/otherdir/in", False, FILE_READ),
+            ('open', 0, "/some/thing/created", True, FILE_WRITE),
+            ('proc', 1, 0, False),
+            ('open', 1, "/some/thing/created/file", False, FILE_WRITE),
+            ('open', 1, "/some/thing/created/file", False, FILE_READ),
+            ('open', 1, "/some/thing/created", True, FILE_WDIR),
+            ('exec', 0, "/some/thing/created/file", "/some/thing/created",
+             "created\0"),
+        ])
+        expected = set([
+            '/some/dir',
+            '/some/dir/ls',
+            '/some/otherdir/in',
+            '/some/thing',
+        ])
+        self.assertEqualPaths(expected,
+                              set(fi.path for fi in files))
+
+    def test_multiple_runs(self):
+        def fail(s):
+            assert False, "Shouldn't be called?"
+        old = Path.is_file, Path.stat
+        Path.is_file = lambda s: True
+        Path.stat = fail
+        try:
+            files, inputs, outputs = self.do_test([
+                ('proc', 0, None, False),
+                ('open', 0, "/some/dir", True, FILE_WDIR),
+                ('exec', 0, "/some/dir/ls", "/some/dir", b'ls\0/some/cli\0'),
+                ('open', 0, "/some/cli", False, FILE_WRITE),
+                ('open', 0, "/some/r", False, FILE_READ),
+                ('open', 0, "/some/rw", False, FILE_READ),
+                ('proc', 1, None, False),
+                ('open', 1, "/some/dir", True, FILE_WDIR),
+                ('exec', 1, "/some/dir/ls", "/some/dir", b'ls\0'),
+                ('open', 1, "/some/cli", False, FILE_READ),
+                ('proc', 2, 1, True),
+                ('open', 2, "/some/r", False, FILE_READ),
+                ('open', 1, "/some/rw", False, FILE_WRITE),
+            ])
+            expected = set([
+                '/some',
+                '/some/dir',
+                '/some/dir/ls',
+                '/some/r',
+                '/some/rw',
+            ])
+            self.assertEqualPaths(expected,
+                                  set(fi.path for fi in files))
+            self.assertEqualPaths([set(["/some/r", "/some/rw"]),
+                                   set(["/some/cli", "/some/r"])],
+                                  [set(l) for l in inputs])
+            self.assertEqualPaths([set(["/some/cli"]), set(["/some/rw"])],
+                                  [set(l) for l in outputs])
+        finally:
+            Path.is_file, Path.stat = old
+
+
+class TestCombine(unittest.TestCase):
+    def setUp(self):
+        self.tmpdir = Path.tempdir()
+
+    def tearDown(self):
+        self.tmpdir.rmtree()
+
+    def test_combine(self):
+        traces = []
+        schema = '''
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE processes(
+    id INTEGER NOT NULL PRIMARY KEY,
+    run_id INTEGER NOT NULL,
+    parent INTEGER,
+    timestamp INTEGER NOT NULL,
+    is_thread BOOLEAN NOT NULL,
+    exitcode INTEGER
+    );
+CREATE TABLE opened_files(
+    id INTEGER NOT NULL PRIMARY KEY,
+    run_id INTEGER NOT NULL,
+    name TEXT NOT NULL,
+    timestamp INTEGER NOT NULL,
+    mode INTEGER NOT NULL,
+    is_directory BOOLEAN NOT NULL,
+    process INTEGER NOT NULL
+    );
+CREATE TABLE executed_files(
+    id INTEGER NOT NULL PRIMARY KEY,
+    name TEXT NOT NULL,
+    run_id INTEGER NOT NULL,
+    timestamp INTEGER NOT NULL,
+    process INTEGER NOT NULL,
+    argv TEXT NOT NULL,
+    envp TEXT NOT NULL,
+    workingdir TEXT NOT NULL
+    );
+CREATE INDEX proc_parent_idx ON processes(parent);
+CREATE INDEX open_proc_idx ON opened_files(process);
+CREATE INDEX exec_proc_idx ON executed_files(process);
+        '''
+        sql_data = [
+            schema + '''
+INSERT INTO "processes" VALUES(1,0,NULL,12345678901001,0,0);
+INSERT INTO "opened_files" VALUES(1,0,'/home/vagrant',12345678901001,4,1,1);
+INSERT INTO "opened_files" VALUES(2,0,'/lib/ld.so',12345678901003,1,0,1);
+INSERT INTO "executed_files" VALUES(1,'/usr/bin/id',0,12345678901002,1,'id',
+    'RUN=first','/home/vagrant');
+            ''',
+            schema + '''
+INSERT INTO "processes" VALUES(1,0,NULL,12345678902001,0,0);
+INSERT INTO "processes" VALUES(2,0,1,12345678902002,1,0);
+INSERT INTO "processes" VALUES(3,1,NULL,12345678902004,0,0);
+INSERT INTO "processes" VALUES(4,1,3,12345678902005,0,1);
+INSERT INTO "opened_files" VALUES(1,0,'/usr',12345678902001,4,1,1);
+INSERT INTO "opened_files" VALUES(2,0,'/lib/ld.so',12345678902003,1,0,2);
+INSERT INTO "opened_files" VALUES(3,1,'/usr/bin',12345678902004,4,1,3);
+INSERT INTO "executed_files" VALUES(1,'/usr/bin/id',1,12345678902006,4,'id',
+    'RUN=third','/home/vagrant');
+            ''',
+            schema + '''
+INSERT INTO "processes" VALUES(0,0,NULL,12345678903001,0,1);
+INSERT INTO "opened_files" VALUES(0,0,'/home',12345678903001,4,1,0);
+INSERT INTO "executed_files" VALUES(1,'/bin/false',0,12345678903002,0,'false',
+    'RUN=fourth','/home');
+            ''']
+
+        for i, dat in enumerate(sql_data):
+            trace = self.tmpdir / ('trace%d.sqlite3' % i)
+            if PY3:
+                conn = sqlite3.connect(str(trace))
+            else:
+                conn = sqlite3.connect(trace.path)
+            conn.row_factory = sqlite3.Row
+            conn.executescript(dat + 'COMMIT;')
+            conn.commit()
+            conn.close()
+
+            traces.append(trace)
+
+        target = self.tmpdir / 'target'
+        traceutils.combine_traces(traces, target)
+        target = target / 'trace.sqlite3'
+
+        if PY3:
+            conn = sqlite3.connect(str(target))
+        else:
+            conn = sqlite3.connect(target.path)
+        conn.row_factory = None
+        processes = list(conn.execute(
+            '''
+            SELECT * FROM processes;
+            '''))
+        opened_files = list(conn.execute(
+            '''
+            SELECT * FROM opened_files;
+            '''))
+        executed_files = list(conn.execute(
+            '''
+            SELECT * FROM executed_files;
+            '''))
+
+        self.assertEqual([processes, opened_files, executed_files], [
+            [(1, 1, None, 12345678901001, 0, 0),
+             (2, 2, None, 12345678902001, 0, 0),
+             (3, 2, 1, 12345678902002, 1, 0),
+             (4, 3, None, 12345678902004, 0, 0),
+             (5, 3, 3, 12345678902005, 0, 1),
+             (6, 4, None, 12345678903001, 0, 1)],
+
+            [(1, 1, '/home/vagrant', 12345678901001, 4, 1, 1),
+             (2, 1, '/lib/ld.so', 12345678901003, 1, 0, 1),
+             (3, 2, '/usr', 12345678902001, 4, 1, 2),
+             (4, 2, '/lib/ld.so', 12345678902003, 1, 0, 3),
+             (5, 3, '/usr/bin', 12345678902004, 4, 1, 4),
+             (6, 4, '/home', 12345678903001, 4, 1, 6)],
+
+            [(1, '/usr/bin/id', 1, 12345678901002, 1, 'id',
+              'RUN=first', '/home/vagrant'),
+             (2, '/usr/bin/id', 3, 12345678902006, 5, 'id',
+              'RUN=third', '/home/vagrant'),
+             (3, '/bin/false', 4, 12345678903002, 6, 'false',
+              'RUN=fourth', '/home')],
+        ])
+
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..a6c45d4
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,3 @@
+version=4
+opts=uversionmangle=s/(rc|a|b|c)/~$1/ \
+https://pypi.debian.net/reprozip/reprozip@ANY_VERSION@@ARCHIVE_EXT@

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/reprozip.git



More information about the debian-science-commits mailing list