From e5d8d6b206c4204b7d3f4f406a931c135d0c8de8 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Thu, 15 Aug 2019 18:46:55 +0100
Subject: [PATCH] Install a script that builds the relocatable installation

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 .gitignore                   |   2 +
 .gitlab-ci.yml               |  11 +--
 README.md                    |   6 +-
 build-relocatable-install.in |   7 ++
 build-relocatable-install.py | 150 ++++++++++-------------------------
 ci/Jenkinsfile               |  11 +--
 copy-source-code.py          | 112 ++++++++++++++++++++++++++
 debian/rules                 |   1 +
 meson.build                  |  26 ++++++
 meson_options.txt            |   1 +
 10 files changed, 206 insertions(+), 121 deletions(-)
 create mode 100644 build-relocatable-install.in
 create mode 100644 copy-source-code.py

diff --git a/.gitignore b/.gitignore
index 2a3819ea9..329b876b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+.*.sw?
+/.mypy_cache
 /_build/
 /libcapsule/
 /libcapsule_*.dsc
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 32d343650..fd63f5ef6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,17 +45,18 @@ build:scout:
             meson \
             ${NULL+}
 
-            meson --prefix="$(pwd)/_build/prefix" -Dpython=python3.5 _build
+            meson \
+              --prefix="$(pwd)/_build/prefix" \
+              -Dpython=python3.5 \
+              -Dsrcdir=src \
+              _build
             ninja -C _build
             meson test --verbose -C _build
             ninja -C _build install
             rm -fr _build/relocatable-install
-            ./build-relocatable-install.py \
-              --srcdir . \
-              --builddir _build \
+            _build/prefix/bin/pressure-vessel-build-relocatable-install \
               --output _build/relocatable-install \
               --archive "$(pwd)/_build" \
-              --set-version "$(cat .tarball-version)" \
               ${NULL+}
             prove -v ./tests/relocatable-install.py :: \
               "$(pwd)/_build/relocatable-install"
diff --git a/README.md b/README.md
index e996ccdbd..59fa4850f 100644
--- a/README.md
+++ b/README.md
@@ -149,14 +149,12 @@ or available via apt-get. For example, you could do the build in a
 SteamRT 1 'scout' SDK Docker image that has those packages already.
 Then you can do:
 
-    meson --prefix="$(pwd)/_build/prefix" _build
+    meson --prefix="$(pwd)/_build/prefix" -Dsrcdir=src _build
     ninja -C _build
     meson test -v -C _build             # optional
     ninja -C _build install
     rm -fr _build/relocatable-install
-    ./build-relocatable-install.py \
-        --srcdir . \
-        --builddir _build \
+    _build/prefix/bin/pressure-vessel-build-relocatable-install \
         --output _build/relocatable-install \
         --archive .
     ./tests/relocatable-install.py _build/relocatable-install  # optional
diff --git a/build-relocatable-install.in b/build-relocatable-install.in
new file mode 100644
index 000000000..9395e4424
--- /dev/null
+++ b/build-relocatable-install.in
@@ -0,0 +1,7 @@
+#!@sh@
+exec "@python@" \
+"${DESTDIR}@prefix@/@srcdir@/build-relocatable-install.py" \
+--prefix "@prefix@" \
+--srcdir "@srcdir@" \
+--set-version "@version@" \
+"$@"
diff --git a/build-relocatable-install.py b/build-relocatable-install.py
index e74b7e80c..61a005c13 100755
--- a/build-relocatable-install.py
+++ b/build-relocatable-install.py
@@ -25,7 +25,6 @@
 
 import argparse
 import glob
-import json
 import os
 import re
 import shutil
@@ -135,42 +134,30 @@ def main():
     # type: () -> None
 
     parser = argparse.ArgumentParser()
-    parser.add_argument(
-        '--destdir', default=os.getenv('DESTDIR', ''))
-    parser.add_argument(
-        '--srcdir', default=os.getenv('MESON_SOURCE_ROOT', '.'))
-    parser.add_argument(
-        '--builddir', default=os.getenv('MESON_BUILD_ROOT', '_build'))
+    parser.add_argument('--destdir', default=os.getenv('DESTDIR'))
     parser.add_argument('--prefix', default=None)
+    parser.add_argument('--srcdir', default=None)
     parser.add_argument('--output', '-o', default=None)
     parser.add_argument('--archive', default=None)
-    parser.add_argument('--set-version', dest='version', default='unknown')
+    parser.add_argument('--set-version', dest='version', default=None)
     args = parser.parse_args()
 
-    if args.destdir:
-        args.destdir = os.path.abspath(args.destdir)
+    if args.srcdir is None:
+        args.srcdir = os.path.dirname(__file__)
 
-    args.srcdir = os.path.abspath(args.srcdir)
-    args.builddir = os.path.abspath(args.builddir)
+    if args.prefix is None:
+        args.prefix = '/usr/lib/pressure-vessel/relocatable'
 
-    if args.archive is None:
-        args.archive = args.builddir
-    else:
-        args.archive = os.path.abspath(args.archive)
+    if not os.path.isabs(args.srcdir):
+        args.srcdir = os.path.join(args.prefix, args.srcdir)
 
-    if args.prefix is None:
-        blob = subprocess.check_output([
-            'meson', 'introspect', args.builddir, '--buildoptions',
-        ], universal_newlines=True)
-        for opt in json.loads(blob):
-            if opt['name'] == 'prefix':
-                args.prefix = opt['value']
-                break
-        else:
-            raise RuntimeError(
-                'Unable to determine installation prefix from Meson, '
-                'please specify --prefix'
-            )
+    if args.destdir:
+        args.prefix = args.destdir + args.prefix
+        args.srcdir = args.destdir + args.srcdir
+
+    if args.version is None:
+        with open(os.path.join(args.srcdir, '.tarball-version')) as reader:
+            args.version = reader.read().strip()
 
     with tempfile.TemporaryDirectory(prefix='pressure-vessel-') as tmpdir:
         if args.output is None:
@@ -181,8 +168,6 @@ def main():
         if os.path.exists(installation):
             raise RuntimeError('--output directory must not already exist')
 
-        destdir_prefix = args.destdir + args.prefix
-
         os.makedirs(os.path.join(installation, 'bin'), exist_ok=True)
         os.makedirs(os.path.join(installation, 'metadata'), exist_ok=True)
 
@@ -194,13 +179,13 @@ def main():
 
         for script in SCRIPTS:
             install_exe(
-                os.path.join(destdir_prefix, 'bin', script),
+                os.path.join(args.prefix, 'bin', script),
                 os.path.join(installation, 'bin'),
             )
 
         for exe in EXECUTABLES:
             install_exe(
-                os.path.join(destdir_prefix, 'bin', exe),
+                os.path.join(args.prefix, 'bin', exe),
                 os.path.join(installation, 'bin'),
             )
 
@@ -430,82 +415,33 @@ def main():
             exist_ok=True,
         )
 
-        for src_tar in (
-            os.path.join(
-                args.srcdir,
-                '..',
-                'pressure-vessel_{}.orig.tar.xz'.format(args.version),
-            ),
-            os.path.join(
-                args.builddir,
-                'meson-dist/pressure-vessel-{}.tar.gz'.format(
-                    args.version,
-                ),
-            ),
-            os.path.join(
-                args.srcdir,
-                'pressure-vessel-{}.tar.xz'.format(args.version),
+        tar = subprocess.Popen([
+            'tar',
+            '-C', args.srcdir,
+            '--exclude=.*.sw?',
+            '--exclude=./.git',
+            '--exclude=./.mypy_cache',
+            '--exclude=./_build',
+            '--exclude=./debian',
+            '--exclude=./relocatable-install',
+            '-cf-',
+            '.',
+        ], stdout=subprocess.PIPE)
+        subprocess.check_call([
+            'tar',
+            '-C', os.path.join(
+                installation,
+                'sources',
+                'pressure-vessel',
             ),
-        ):
-            if os.path.exists(src_tar):
-                subprocess.check_call([
-                    'tar',
-                    '-C', os.path.join(
-                        installation,
-                        'sources',
-                        'pressure-vessel',
-                    ),
-                    '--strip-components=1',
-                    '-xvf', src_tar,
-                ])
-                break
-        else:
-            if os.path.exists('/usr/bin/git'):
-                git_archive = subprocess.Popen([
-                    'git', 'archive', '--format=tar', 'HEAD',
-                ], cwd=args.srcdir, stdout=subprocess.PIPE)
-                subprocess.check_call([
-                    'tar',
-                    '-C', os.path.join(
-                        installation,
-                        'sources',
-                        'pressure-vessel',
-                    ),
-                    '-xvf-',
-                ], stdin=git_archive.stdout)
-
-                if git_archive.wait() != 0:
-                    raise subprocess.CalledProcessError(
-                        returncode=git_archive.returncode,
-                        cmd=git_archive.args,
-                    )
-            else:
-                tar = subprocess.Popen([
-                    'tar',
-                    '-C', args.srcdir,
-                    '--exclude=./.git',
-                    '--exclude=./_build',
-                    '--exclude=./relocatable-install',
-                    '--exclude=./.mypy_cache',
-                    '--exclude=.*.swp',
-                    '-cf-',
-                    '.',
-                ], stdout=subprocess.PIPE)
-                subprocess.check_call([
-                    'tar',
-                    '-C', os.path.join(
-                        installation,
-                        'sources',
-                        'pressure-vessel',
-                    ),
-                    '-xvf-',
-                ], stdin=tar.stdout)
+            '-xvf-',
+        ], stdin=tar.stdout)
 
-                if tar.wait() != 0:
-                    raise subprocess.CalledProcessError(
-                        returncode=git_archive.returncode,
-                        cmd=git_archive.args,
-                    )
+        if tar.wait() != 0:
+            raise subprocess.CalledProcessError(
+                returncode=tar.returncode,
+                cmd=tar.args,
+            )
 
         with open(
             os.path.join(
diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile
index 06737163f..8b9153c1d 100644
--- a/ci/Jenkinsfile
+++ b/ci/Jenkinsfile
@@ -109,17 +109,18 @@ pipeline {
               sh '''
               set -eu
               cd src
-              meson --prefix="$(pwd)/_build/prefix" -Dpython=python3.5 _build
+              meson \
+                --prefix="$(pwd)/_build/prefix" \
+                -Dpython=python3.5 \
+                -Dsrcdir=src \
+                _build
               ninja -C _build
               meson test --verbose -C _build
               ninja -C _build install
               rm -fr ../relocatable-install
-              ./build-relocatable-install.py \
-                --srcdir . \
-                --builddir _build \
+              _build/prefix/bin/pressure-vessel-build-relocatable-install \
                 --output "${WORKSPACE}/relocatable-install" \
                 --archive "${WORKSPACE}" \
-                --set-version "$(cat .tarball-version)" \
                 ${NULL+}
               prove -v ./tests/relocatable-install.py :: \
                 "${WORKSPACE}/relocatable-install"
diff --git a/copy-source-code.py b/copy-source-code.py
new file mode 100644
index 000000000..c60187a75
--- /dev/null
+++ b/copy-source-code.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+
+# Copyright © 2017-2019 Collabora Ltd.
+#
+# SPDX-License-Identifier: MIT
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import argparse
+import os
+import subprocess
+
+try:
+    import typing
+except ImportError:
+    pass
+else:
+    typing      # silence pyflakes
+
+
+def v_check_call(command, **kwargs):
+    print('# {}'.format(command))
+    subprocess.check_call(command, **kwargs)
+
+
+def v_check_output(command, **kwargs):
+    print('# {}'.format(command))
+    return subprocess.check_output(command, **kwargs)
+
+
+def main():
+    # type: () -> None
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        '--destdir', default=os.getenv('DESTDIR', ''))
+    parser.add_argument(
+        '--srcdir', default=os.getenv('MESON_SOURCE_ROOT', '.'))
+    parser.add_argument('--set-version', default='0.0.0', dest='version')
+    parser.add_argument('--prefix', default='/usr')
+    parser.add_argument('output')
+    args = parser.parse_args()
+
+    args.srcdir = os.path.abspath(args.srcdir)
+    args.prefix = os.path.abspath(args.prefix)
+
+    if not os.path.isabs(args.output):
+        args.output = os.path.join(args.prefix, args.output)
+
+    if args.destdir:
+        args.destdir = os.path.abspath(args.destdir)
+        args.output = args.destdir + args.output
+
+    os.makedirs(os.path.join(args.output), exist_ok=True)
+
+    tar = subprocess.Popen([
+        'tar',
+        '-C', args.srcdir,
+        '--exclude=.*.sw?',
+        '--exclude=./.git',
+        '--exclude=./.mypy_cache',
+        '--exclude=./_build',
+        '--exclude=./debian',
+        '--exclude=./relocatable-install',
+        '-cf-',
+        '.',
+    ], stdout=subprocess.PIPE)
+    subprocess.check_call([
+        'tar',
+        '-C', os.path.join(
+            args.output,
+        ),
+        '-xvf-',
+    ], stdin=tar.stdout)
+
+    if tar.wait() != 0:
+        raise subprocess.CalledProcessError(
+            returncode=tar.returncode,
+            cmd=tar.args,
+        )
+
+    with open(
+        os.path.join(
+            args.output,
+            '.tarball-version',
+        ),
+        'w',
+    ) as writer:
+        writer.write('{}\n'.format(args.version))
+
+
+if __name__ == '__main__':
+    main()
+
+# vim:set sw=4 sts=4 et:
diff --git a/debian/rules b/debian/rules
index b3e17e206..8c670bcab 100755
--- a/debian/rules
+++ b/debian/rules
@@ -26,6 +26,7 @@ override_dh_auto_configure:
 	meson _build \
 		--prefix=/usr/lib/pressure-vessel/relocatable \
 		-Dpython=/usr/bin/$$python \
+		-Dsrcdir=src \
 		-Dversion=$(DEB_VERSION) \
 		$(NULL)
 
diff --git a/meson.build b/meson.build
index 02d71b653..90bb29a2c 100644
--- a/meson.build
+++ b/meson.build
@@ -179,4 +179,30 @@ executable(
   install_rpath : '${ORIGIN}/../' + get_option('libdir'),
 )
 
+if get_option('srcdir') != ''
+  conf_data = configuration_data()
+  conf_data.set('prefix', get_option('prefix'))
+  conf_data.set('python', python.path())
+  conf_data.set('sh', sh.path())
+  conf_data.set('srcdir', get_option('srcdir'))
+  conf_data.set('version', version)
+  install_data(
+    configure_file(
+      input : 'build-relocatable-install.in',
+      output : 'pressure-vessel-build-relocatable-install',
+      configuration : conf_data,
+    ),
+    install_dir : get_option('bindir'),
+    install_mode : 'rwxr-xr-x',
+  )
+  meson.add_install_script(
+    python.path(),
+    meson.current_source_dir() / 'copy-source-code.py',
+    '--srcdir', meson.current_source_dir(),
+    '--prefix', get_option('prefix'),
+    '--set-version', version,
+    get_option('srcdir'),
+  )
+endif
+
 # vim:set sw=2 sts=2 et:
diff --git a/meson_options.txt b/meson_options.txt
index cba6f7c59..fe6a3e81e 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,2 +1,3 @@
 option('python', type : 'string', value : 'python3')
+option('srcdir', type : 'string', value : '')
 option('version', type : 'string', value : 'auto')
-- 
GitLab