[reprotest] 01/04: main, build: Support domain_host variation, add a --print-sudoers feature
Ximin Luo
infinity0 at debian.org
Thu Oct 26 22:01:04 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 9b34f0a3044b84c39bd897c47a426256cf0a88b1
Author: Ximin Luo <infinity0 at debian.org>
Date: Thu Oct 26 22:27:22 2017 +0200
main, build: Support domain_host variation, add a --print-sudoers feature
---
README.rst | 45 ++++++++----
debian/changelog | 2 +
debian/rules | 2 +-
debian/tests/control | 4 +-
reprotest/__init__.py | 25 +++++--
reprotest/build.py | 197 ++++++++++++++++++++++++++++++++++++++++----------
reprotest/presets.py | 4 +-
7 files changed, 212 insertions(+), 67 deletions(-)
diff --git a/README.rst b/README.rst
index eddc0c0..baff2d1 100644
--- a/README.rst
+++ b/README.rst
@@ -219,6 +219,11 @@ of names is given in the --help text for --variations.
Most variations do not have parameters, and for them only the + and - operators
are relevant. The variations that accept parameters are:
+domain_host.use_sudo
+ An integer, whether to use sudo(1) together with unshare(1) to change the
+ system hostname and domainname. 0 means don't use sudo; any non-zero value
+ means to use sudo. Default is 0, however this is not recommended and make
+ may your build fail, see "Varying the domain and host names" for details.
environment.variables
A semicolon-separated ordered set, specifying environment variables that
reprotest should try to vary. Default is "REPROTEST_CAPTURE_ENVIRONMENT".
@@ -269,6 +274,22 @@ means to vary home, time (the last given value for --variations), timezone, and
Varying the user or group
=========================
+Doing this without sudo *may* result in your build failing.
+
+Failure is likely if your build must do system-related things - as opposed to
+only processing bits and bytes. This is because it runs in a separate namespace
+where your non-privileged user looks like it is "root", but this prevents the
+filesystem from recognising files owned by the real "root" user, amongst other
+things. This is a limitation of unshare(1) and it is not possible work around
+this in reprotest without heavy effort.
+
+Therefore, it is recommended to run this variation with use_sudo=1. To avoid
+password prompts, see the section "Avoid sudo(1) password prompts" below.
+
+
+Varying the user or group
+=========================
+
If you also vary fileordering at the same time (this is the case by default),
each user you use needs to be in the "fuse" group. Do that by running `usermod
-aG fuse $OTHERUSER` as root.
@@ -280,22 +301,14 @@ There is currently no good way to do this. The following is a very brittle and
unclean solution. You will have to decide for yourself if it's worth it for
your use-case::
- $ OTHERUSER=(YOUR OTHER USER HERE)
- $ a="[a-zA-Z0-9]"
- $ cat <<EOF | sudo tee -a /etc/sudoers.d/local-reprotest
- $USER ALL = ($OTHERUSER) NOPASSWD: ALL
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$OTHERUSER $USER /tmp/autopkgtest.$a$a$a$a$a$a/const_build_path/
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$OTHERUSER $USER /tmp/autopkgtest.$a$a$a$a$a$a/build-experiment-[1-9]/
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$OTHERUSER $USER /tmp/autopkgtest.$a$a$a$a$a$a/build-experiment-[1-9]-before-disorderfs/
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$USER $OTHERUSER /tmp/autopkgtest.$a$a$a$a$a$a/const_build_path/
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$USER $OTHERUSER /tmp/autopkgtest.$a$a$a$a$a$a/build-experiment-[1-9]/
- $USER ALL = NOPASSWD: /bin/chown -h -R --from=$USER $OTHERUSER /tmp/autopkgtest.$a$a$a$a$a$a/build-experiment-[1-9]-before-disorderfs/
- EOF
-
-Repeat this for each user you'd like to use. Obviously, don't pick a privileged
-user for this purpose, such as root.
-
-(Simplifying the above using wildcards would open up passwordless access to
+ $ reprotest --print-sudoers \
+ --variations=user_group.available+=guest-builder,domain_host.use_sudo=1 \
+ | sudo EDITOR=tee visudo -f /etc/sudoers.d/local-reprotest
+
+Make sure you set the variations you actually want to use. Obviously, don't
+pick privileged users for this purpose, such as root.
+
+(Simplifying the output using wildcards, would open up passwordless access to
chown anything on your system, because wildcards here match whitespace. I don't
know what the sudo authors were thinking.)
diff --git a/debian/changelog b/debian/changelog
index 7917c7f..4099380 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,8 @@
reprotest (0.7.4) UNRELEASED; urgency=medium
* Hopefully fix the autopkgtest tests.
+ * Add a domain_host variation.
+ * Add a --print-sudoers feature.
-- Ximin Luo <infinity0 at debian.org> Fri, 20 Oct 2017 12:33:21 +0200
diff --git a/debian/rules b/debian/rules
index 604b183..6ee3062 100755
--- a/debian/rules
+++ b/debian/rules
@@ -11,7 +11,7 @@ export PYBUILD_NAME = reprotest
#
# To be user-friendly the user_group variation defaults to ON but is a no-op.
# This causes tests to fail since they expect something to be captured. So ignore it here
-export REPROTEST_TEST_DONTVARY = fileordering,user_group
+export REPROTEST_TEST_DONTVARY = fileordering,user_group,domain_host
override_dh_auto_configure:
test $$(python3 setup.py --version) = $$(dpkg-parsechangelog -SVersion)
diff --git a/debian/tests/control b/debian/tests/control
index 3e74024..f669c59 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -1,5 +1,5 @@
-Test-Command: env REPROTEST_TEST_DONTVARY=fileordering,user_group pytest-3 -m 'not need_builddeps'
+Test-Command: env REPROTEST_TEST_DONTVARY=fileordering,user_group,domain_host pytest-3 -m 'not need_builddeps'
Depends: @, python3-pytest, faketime, locales-all
-Test-Command: env REPROTEST_TEST_DONTVARY=fileordering,user_group pytest-3 -m 'need_builddeps'
+Test-Command: env REPROTEST_TEST_DONTVARY=fileordering,user_group,domain_host pytest-3 -m 'need_builddeps'
Depends: @builddeps@
diff --git a/reprotest/__init__.py b/reprotest/__init__.py
index 0bdf055..52dd1b8 100644
--- a/reprotest/__init__.py
+++ b/reprotest/__init__.py
@@ -605,6 +605,9 @@ def cli_parser():
'implemented very well and may leave cruft on your system.')
group3.add_argument('--dry-run', action='store_true', default=False,
help='Don\'t run the builds, just print what would happen.')
+ group3.add_argument('--print-sudoers', action='store_true', default=False,
+ help='Print a sudoers file for passwordless operation using the given '
+ '--variations, useful for user_group.available, domain_host.use_sudo.')
return parser
@@ -647,6 +650,14 @@ def command_line(parser, argv):
return args
+def get_main_spec(parsed_args):
+ variations = [parsed_args.variations] + parsed_args.vary
+ if parsed_args.dont_vary:
+ logging.warn("--dont-vary is deprecated; use --vary=-$variation instead")
+ variations += ["-%s" % a for x in parsed_args.dont_vary for a in x.split(",")]
+ return VariationSpec().extend(variations)
+
+
def run(argv, dry_run=None):
# Argparse exits with status code 2 if something goes wrong, which
# is already the right status exit code for reprotest.
@@ -655,12 +666,17 @@ def run(argv, dry_run=None):
config_args = config_to_args(parser, parsed_args.config_file)
# Command-line arguments override config file settings.
parsed_args = command_line(parser, config_args + argv)
+ dry_run = parsed_args.dry_run or dry_run
verbosity = parsed_args.verbosity
adtlog.verbosity = verbosity - 1
logging.basicConfig(level=30-10*verbosity)
logging.debug('%r', parsed_args)
+ if not dry_run and parsed_args.print_sudoers:
+ build.print_sudoers(get_main_spec(parsed_args))
+ return 0
+
# Decide which form of the CLI we're using
build_command, source_root = None, None
first_arg = parsed_args.__dict__['source_root|build_command']
@@ -729,12 +745,7 @@ def run(argv, dry_run=None):
source_pattern = values.source_pattern + (" " + source_pattern if source_pattern else "")
# Variations args
- variations = [parsed_args.variations] + parsed_args.vary
- if parsed_args.dont_vary:
- logging.warn("--dont-vary is deprecated; use --vary=-$variation instead")
- variations += ["-%s" % a for x in parsed_args.dont_vary for a in x.split(",")]
- spec = VariationSpec().extend(variations)
- specs = [spec]
+ specs = [get_main_spec(parsed_args)]
if parsed_args.auto_build:
check_func = check_auto
elif parsed_args.env_build:
@@ -776,7 +787,7 @@ def run(argv, dry_run=None):
source_pattern, no_clean_on_error, diffoscope_args)
check_args = (test_args, testbed_args, build_variations)
- if parsed_args.dry_run or dry_run:
+ if dry_run:
return check_args
else:
try:
diff --git a/reprotest/build.py b/reprotest/build.py
index 4f4fe99..17fa7bc 100644
--- a/reprotest/build.py
+++ b/reprotest/build.py
@@ -45,7 +45,7 @@ def basename(p):
return os.path.normpath(os.path.basename(os.path.normpath(p)))
-class Build(collections.namedtuple('_Build', 'build_command setup cleanup env tree')):
+class Build(collections.namedtuple('_Build', 'build_command setup cleanup env tree aux_tree')):
'''Holds the shell ASTs and various other data, used to execute each build.
Fields:
@@ -64,18 +64,26 @@ class Build(collections.namedtuple('_Build', 'build_command setup cleanup env tr
if no_clean_on_error is given and setup or build_command failed.
env (types.MappingProxyType): Immutable mapping of the environment.
tree (str): Path to the source root where the build should take place.
+ aux_tree (str): Path where auxilliary files are stored by reprotest.
+ When using cls.from_command(), this is automatically created and
+ cleaned up by the build script.
'''
@classmethod
def from_command(cls, build_command, env, tree):
- return cls(
+ aux_tree = os.path.join(dirname(tree), basename(tree) + '-aux')
+ _ = cls(
build_command = shell_syn.Command.make(
"sh", "-ec", shlex.quote(str(build_command))),
setup = shell_syn.AndList(),
cleanup = shell_syn.List(),
env = env,
tree = tree,
+ aux_tree = aux_tree,
)
+ _ = _.append_setup_exec('mkdir', '-p', aux_tree)
+ _ = _.prepend_cleanup_exec('rm', '-rf', aux_tree)
+ return _
def add_env(self, key, value):
'''Helper function for adding a key-value pair to an immutable mapping.'''
@@ -95,7 +103,7 @@ class Build(collections.namedtuple('_Build', 'build_command setup cleanup env tr
def prepend_to_build_command(self, *prefix):
'''Prepend a wrapper command onto the build_command.'''
new_command = shell_syn.Command(
- cmd_prefix=shell_syn.CmdPrefix(prefix),
+ cmd_prefix=shell_syn.CmdPrefix(map(shlex.quote, prefix)),
cmd_suffix=self.build_command)
return self._replace(build_command=new_command)
@@ -148,17 +156,21 @@ class Build(collections.namedtuple('_Build', 'build_command setup cleanup env tr
if self.cleanup:
cleanup = shell_syn.List.make("__c=0") + self.cleanup + \
shell_syn.List.make("exit $__c")
- main_script = "if ( run_build ); then ( cleanup ); "
- if no_clean_on_error:
- main_script += "fi"
- else:
- main_script += """\
-else
+ # TODO: the below can be extended with a custom command. shell
+ # doesn't work yet though; we need to hook into autopkgtest better.
+ whether_to_clean = '! ' + str(bool(no_clean_on_error)).lower()
+ main_script = """\
+trap '( cleanup )' HUP INT QUIT ABRT TERM PIPE # FIXME doesn't quite work reliably yet
+
+if ( run_build ); then ( cleanup ); else
__x=$?; # save the exit code of run_build
- if ( cleanup ); then :; else echo >&2 "cleanup failed with exit code $?"; fi;
+ if ( {0} ); then
+ if ( cleanup ); then :; else echo >&2 "cleanup failed with exit code $?"; fi;
+ fi
exit $__x
fi
-"""
+""".format(whether_to_clean)
+
return """\
run_build() {{
{0}
@@ -195,11 +207,48 @@ def environment(ctx, build, vary):
added += [(k, v)]
return build.modify_env(added, removed)
-# FIXME: this requires superuser privileges.
-# Probably need to couple with "namespace" UTS unshare when not running in a
-# virtual_server, see below for details
-# def domain_host(ctx, script, env, tree):
-# return script, env, tree
+def domain_host(ctx, build, vary):
+ if not vary:
+ return build
+ hostname = "reprotest-capture-hostname"
+ domainname = "reprotest-capture-domainname"
+ _ = build
+
+ # TODO: below only works on linux, of course..
+ if ctx.spec.domain_host.use_sudo:
+ ns_uts, ns_mnt = ('%s/ns-%s' % (build.aux_tree, ns) for ns in ("uts", "mnt"))
+ _ = _.append_setup_exec('touch', ns_mnt, ns_uts)
+ # make ns_mnt have propagation=private, required for --mount=$ns_mnt
+ _ = _.append_setup_exec('sudo', 'mount', '-B', ns_mnt, ns_mnt)
+ _ = _.append_setup_exec('sudo', 'mount', '--make-private', ns_mnt)
+ _ = _.prepend_cleanup_exec('sudo', 'umount', ns_mnt)
+ # create our unshare
+ ns_args = ['--mount=%s' % ns_mnt, '--uts=%s' % ns_uts]
+ _ = _.append_setup_exec('sudo', 'unshare', *ns_args, 'true')
+ _ = _.prepend_cleanup_exec('sudo', 'umount', ns_mnt)
+ _ = _.prepend_cleanup_exec('sudo', 'umount', ns_uts)
+ # configure our unshare
+ nsenter = ['sudo', 'nsenter'] + ns_args
+ _ = _.append_setup_exec(*nsenter, 'hostname', hostname)
+ _ = _.append_setup_exec(*nsenter, 'domainname', domainname)
+ # the mount -B hack suppresses spurious sudo(1) warnings about "unable to resolve host"
+ _ = _.append_setup_exec('sh', '-ec',
+ 'echo "127.0.0.1 {1}" > {0}/hosts && cat /etc/hosts >> {0}/hosts'.format(build.aux_tree, hostname))
+ _ = _.append_setup_exec(*nsenter, 'mount', '-B', '%s/hosts' % build.aux_tree, '/etc/hosts')
+ # wrap our build command
+ _ = _.prepend_to_build_command('sudo', '-E', 'nsenter', *ns_args, *make_sudo_command(*current_user_group()))
+ else:
+ logging.warn("Not using sudo for domain_host; it is recommended. Your build may fail.")
+ logging.warn("Be sure to `echo 1 > /proc/sys/kernel/unprivileged_userns_clone` if on a Debian system.")
+ if "user_group" in ctx.spec and ctx.spec.user_group.available:
+ logging.error("Incompatible variations: domain_host.use_sudo False, user_group.available non-empty.")
+ raise ValueError("Incompatible variations; check the log for details.")
+ _ = _.prepend_to_build_command(*"unshare -r --uts".split(),
+ "sh", "-ec", r"""
+ hostname {1}
+ domainname "{2}"
+ """.format(build.aux_tree, hostname, domainname) + '"$@"', "-")
+ return _
# Note: this has to go before fileordering because we can't move mountpoints
# TODO: this variation makes it impossible to parallelise the build, for most
@@ -324,6 +373,30 @@ def umask(ctx, build, vary):
else:
return build.append_setup_exec('umask', '0002')
+
+def current_user_group():
+ return getpass.getuser(), grp.getgrgid(os.getgid()).gr_name
+
+
+def make_sudo_command(user, group):
+ assert user or group
+ userarg = ['-u', user] if user else []
+ grouparg = ['-g', group] if group else []
+ return ['sudo', '-E'] + userarg + grouparg + ['env',
+ '-u', 'SUDO_COMMAND', '-u', 'SUDO_GID', '-u', 'SUDO_UID', '-u', 'SUDO_USER']
+
+def parse_user_group(user_group):
+ if not user_group or user_group == ':':
+ raise ValueError("user_group is empty: '%s'" % user_group)
+ if ":" in user_group:
+ user, group = user_group.split(":", 1)
+ if user:
+ return user, group
+ else:
+ return None, group
+ else:
+ return user_group, None
+
# Note: this needs to go before anything that might need to run setup commands
# as the other user (e.g. due to permissions).
@tool_required("sudo")
@@ -337,34 +410,26 @@ def user_group(ctx, build, vary):
"alternatively, suppress this warning with --variations=-user_group")
return build
- olduser = getpass.getuser()
- oldgroup = grp.getgrgid(os.getgid()).gr_name
+ olduser, oldgroup = current_user_group()
user_group = random.choice(list(set(ctx.spec.user_group.available) - set([(olduser, oldgroup)])))
- if ":" in user_group:
- user, group = user_group.split(":", 1)
- if user:
- sudo_command = ('sudo', '-E', '-u', user, '-g', group)
- else:
- user = olduser
- sudo_command = ('sudo', '-E', '-g', group)
- else:
- user = user_group # "user" is used below
- sudo_command = ('sudo', '-E', '-u', user)
+ user, group = parse_user_group(user_group)
+ sudo_command = make_sudo_command(user, group)
+ if not user:
+ user = olduser
binpath = os.path.join(dirname(build.tree), 'bin')
- _ = build.prepend_to_build_command(*sudo_command,
- *["env", "-u", "SUDO_COMMAND", "-u", "SUDO_GID", "-u", "SUDO_UID", "-u", "SUDO_USER"])
+ _ = build.prepend_to_build_command(*sudo_command)
# disorderfs needs to run as a different user.
# we prefer that to running it as root, principle of least-privilege.
_ = _.append_setup_exec('sh', '-ec', r'''
-mkdir -p "{0}"
-printf '#!/bin/sh\n{1} /usr/bin/disorderfs "$@"\n' > "{0}"/disorderfs
-chmod +x "{0}"/disorderfs
-printf '#!/bin/sh\n{1} /bin/mkdir "$@"\n' > "{0}"/mkdir
-chmod +x "{0}"/mkdir
-printf '#!/bin/sh\n{1} /bin/fusermount "$@"\n' > "{0}"/fusermount
-chmod +x "{0}"/fusermount
-'''.format(binpath, " ".join(map(shlex.quote, sudo_command))))
+ mkdir -p "{0}"
+ printf '#!/bin/sh\n{1} /usr/bin/disorderfs "$@"\n' > "{0}"/disorderfs
+ chmod +x "{0}"/disorderfs
+ printf '#!/bin/sh\n{1} /bin/mkdir "$@"\n' > "{0}"/mkdir
+ chmod +x "{0}"/mkdir
+ printf '#!/bin/sh\n{1} /bin/fusermount "$@"\n' > "{0}"/fusermount
+ chmod +x "{0}"/fusermount
+ '''.format(binpath, " ".join(map(shlex.quote, sudo_command))))
_ = _.prepend_cleanup_exec('sh', '-ec',
'cd "{0}" && rm -f disorderfs mkdir fusermount'.format(binpath))
_ = _.append_setup_exec_raw('export', 'PATH="%s:$PATH"' % binpath)
@@ -382,8 +447,8 @@ VARIATIONS = collections.OrderedDict([
('build_path', build_path),
('user_group', user_group),
# ('cpu', cpu),
- # ('domain_host', domain_host),
('fileordering', fileordering),
+ ('domain_host', domain_host), # needs to run after all other mounts have been set
('home', home),
('kernel', kernel),
('locales', locales),
@@ -435,6 +500,12 @@ class UserGroupVariation(collections.namedtuple('_UserGroupVariation', 'availabl
return cls(mdiffconf.strlist_set(";"))
+class DomainHostVariation(collections.namedtuple('_DomainHostVariation', 'use_sudo')):
+ @classmethod
+ def default(cls):
+ return cls(0)
+
+
class VariationSpec(mdiffconf.ImmutableNamespace):
@classmethod
def default(cls, variations=VARIATIONS):
@@ -442,6 +513,7 @@ class VariationSpec(mdiffconf.ImmutableNamespace):
"environment": EnvironmentVariation.default(),
"user_group": UserGroupVariation.default(),
"time": TimeVariation.default(),
+ "domain_host": DomainHostVariation.default(),
}
return cls(**{k: default_overrides.get(k, True) for k in variations})
@@ -492,6 +564,53 @@ class Variations(collections.namedtuple('_Variations', 'spec verbosity')):
return AttributeReplacer(self, [])
+def print_sudoers(spec):
+ logging.warn("This feature is EXPERIMENTAL, use at your own risk.")
+ logging.warn("The output may be out-of-date, please file bugs if it doesn't work...")
+
+ user, group = current_user_group()
+ a = "[a-zA-Z0-9]"
+ b = "/tmp/autopkgtest.{0}{0}{0}{0}{0}{0}".format(a)
+ bx = os.path.join(b, "build-experiment-[1-9]")
+ variables = {
+ "user": user,
+ "group": group,
+ "base": b,
+ "base_ex": bx,
+ }
+
+ if "user_group" in spec and spec.user_group.available:
+ user_groups = [parse_user_group(user_group) for user_group in spec.user_group.available]
+ users = sorted(set(user for user, group in user_groups if user))
+ for otheruser in users:
+ print("""\
+# Rules for varying user_group with user %(otheruser)s
+%(user)s ALL = (%(otheruser)s) NOPASSWD: ALL
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(otheruser)s %(user)s %(base)s/const_build_path/
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(otheruser)s %(user)s %(base_ex)s/
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(otheruser)s %(user)s %(base_ex)s-before-disorderfs/
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(user)s %(otheruser)s %(base)s/const_build_path/
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(user)s %(otheruser)s %(base_ex)s/
+%(user)s ALL = NOPASSWD: /bin/chown -h -R --from=%(user)s %(otheruser)s %(base_ex)s-before-disorderfs/
+""" % dict(**variables, **{
+ "otheruser": otheruser
+ }))
+
+ if "domain_host" in spec and spec.domain_host.use_sudo:
+ print("""\
+# Rules for varying domain_host
+%(user)s ALL = NOPASSWD: /bin/mount -B %(base_ex)s-aux/ns-mnt %(base_ex)s-aux/ns-mnt
+%(user)s ALL = NOPASSWD: /bin/mount --make-private %(base_ex)s-aux/ns-mnt
+%(user)s ALL = NOPASSWD: /usr/bin/unshare --mount=%(base_ex)s-aux/ns-mnt --uts=%(base_ex)s-aux/ns-uts true
+%(user)s ALL = NOPASSWD: /usr/bin/nsenter --mount=%(base_ex)s-aux/ns-mnt --uts=%(base_ex)s-aux/ns-uts hostname reprotest-*
+%(user)s ALL = NOPASSWD: /usr/bin/nsenter --mount=%(base_ex)s-aux/ns-mnt --uts=%(base_ex)s-aux/ns-uts domainname reprotest-*
+%(user)s ALL = NOPASSWD: /usr/bin/nsenter --mount=%(base_ex)s-aux/ns-mnt --uts=%(base_ex)s-aux/ns-uts mount -B %(base_ex)s-aux/hosts /etc/hosts
+%(user)s ALL = NOPASSWD:SETENV: /usr/bin/nsenter --mount=%(base_ex)s-aux/ns-mnt --uts=%(base_ex)s-aux/ns-uts sudo -E -u %(user)s -g %(group)s env *
+%(user)s ALL = NOPASSWD: /bin/umount %(base_ex)s-aux/ns-mnt
+%(user)s ALL = NOPASSWD: /bin/umount %(base_ex)s-aux/ns-uts
+""" % variables)
+
+
if __name__ == "__main__":
import sys
d = VariationSpec()
diff --git a/reprotest/presets.py b/reprotest/presets.py
index 413bae0..c588593 100644
--- a/reprotest/presets.py
+++ b/reprotest/presets.py
@@ -75,7 +75,7 @@ PRESET_DEB_DIR = ReprotestPreset(
def preset_deb_schroot(fn, preset):
return preset.re_replace.build_command("(.*)", lambda m: r"""
if [ "$(id -u)" = 0 ]; then
- sudo -E -u "$LOGNAME" sh -ec {0};
+ sudo -E -u "$SUDO_USER" env -u SUDO_USER sh -ec {0};
else
sh -ec {0};
fi
@@ -83,7 +83,7 @@ def preset_deb_schroot(fn, preset):
# schroot starts us off as root, we drop privs here to do the actual build
).set.testbed_init(
# need to symlink /etc/mtab to work around a fusermount(1) deficiency
- 'apt-get -y --no-install-recommends install disorderfs faketime locales-all sudo util-linux; \
+ 'apt-get -y --no-install-recommends install disorderfs fakeroot faketime locales-all sudo util-linux; \
test -c /dev/fuse || mknod -m 666 /dev/fuse c 10 229; \
test -f /etc/mtab || ln -s ../proc/self/mounts /etc/mtab'
).set.testbed_build_pre(
--
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