Compare commits

...

168 Commits

Author SHA1 Message Date
Johannes Schauer Marin Rodrigues 5fd96553f5
release 1.2.5 1 year ago
Johannes Schauer Marin Rodrigues b67d30cb86
mmdebstrap: bump copyright year 1 year ago
Johannes Schauer Marin Rodrigues d4eb268795
warn if hook directory contains no executable scripts 1 year ago
Johannes Schauer Marin Rodrigues 60186650cd
tests: tzdata gained lintian overrides and preinst prerm scripts 1 year ago
Johannes Schauer Marin Rodrigues 59ac33cebe
make shellcheck 0.9.0-1 more happy 1 year ago
Johannes Schauer Marin Rodrigues 847d8fe95b
make shellcheck 0.9.0-1 happy 1 year ago
Johannes Schauer Marin Rodrigues 4595d3df44
release 1.2.4 1 year ago
Johannes Schauer Marin Rodrigues 577f690540
README.md: update list of contributors 1 year ago
Johannes Schauer Marin Rodrigues 2b832e0128
add jessie-or-older extract hook 1 year ago
Johannes Schauer Marin Rodrigues a7b7e16033
move extract hook execution after run_prepare so that fakechroot works in it 1 year ago
Johannes Schauer Marin Rodrigues eb98dfbaee
apt also needs /var/lib to exist 1 year ago
Johannes Schauer Marin Rodrigues 6c5210a94f
error out early if setup fails and thus the ext2 block reader returns EOF 1 year ago
Johannes Schauer Marin Rodrigues a6a31e60eb
make sure that the unshared user has read access to the included package files 1 year ago
Johannes Schauer Marin Rodrigues 0dfd9adf2b
make sure absolute package paths start with a slash and are readable files 1 year ago
Johannes Schauer Marin Rodrigues 2fd3d768e8
avoid division by zero in progress computation 1 year ago
Johannes Schauer Marin Rodrigues ccd8919e67
add tests/unshare-include-deb 1 year ago
Johannes Schauer Marin Rodrigues b39713def5
remove last traces of proot 1 year ago
Johannes Schauer Marin Rodrigues 348c582866
coverage.py: error out if tests are missing from ./tests or from coverage.txt 1 year ago
Johannes Schauer Marin Rodrigues 67fbe118f3
tests/i386-which-can-be-executed-without-qemu: fixup spurious merged-/usr problem 1 year ago
Johannes Schauer Marin Rodrigues 5a263b5532
tests/file-mirror: wrap lines 1 year ago
Johannes Schauer Marin Rodrigues 830270840b
make sure genext2fs and genext2fs exist for the respective formats 1 year ago
Jochen Sprickerhof 374ae3dc99
use $username for subgid check
/etc/subgid contains a mapping of user names (not group names) to group
ids as defined in man subgid.
1 year ago
Johannes Schauer Marin Rodrigues 1f15194a6e
tests/pivot_root: use the mmdebstrap binary we copied into the chroot 1 year ago
Johannes Schauer Marin Rodrigues 117e4251a1
.mailmap: add Helmut Grohne and Benjamin Drung 1 year ago
Johannes Schauer Marin Rodrigues adf8f9399d
coverage.py: check that all files in ./tests appear in coverage.txt 1 year ago
Johannes Schauer Marin Rodrigues 543093eddc
README.md: update list of contributors 1 year ago
Johannes Schauer Marin Rodrigues 4dc1375840
run_qemu.sh: remove accidental qemu option from aavmf code filename 1 year ago
Johannes Schauer Marin Rodrigues c3aa679fec
run_qemu.sh: short-form boolean option 'read-only' deprecated, using read-only=on instead 1 year ago
Johannes Schauer Marin Rodrigues 7a057e37dd
release 1.2.3 1 year ago
Johannes Schauer Marin Rodrigues 5bd3da0aef
tests/create-tarball-dry-run: fix MODE->VARIANT 1 year ago
Johannes Schauer Marin Rodrigues d442f436de
shellcheck everything 1 year ago
Johannes Schauer Marin Rodrigues 889c02419e
update for perltidy 20220613 1 year ago
Johannes Schauer Marin Rodrigues a156d93314
run_qemu.sh: bump timeout to 40 minutes so that it works on an ARM Cortex-A53 at 1.5 GHz 1 year ago
Johannes Schauer Marin Rodrigues 4ccd799b50
tests/include-deb-file: create a dummy binary package to make sure apt doesn't download the package from the mirror 1 year ago
Johannes Schauer Marin Rodrigues 24c5a45202
make_mirror.sh: switch from extlinux to grub-efi to support arm64 1 year ago
Johannes Schauer Marin Rodrigues 2e8eaeb18b
mmdebstrap-autopkgtest-build-qemu: fix i386 grub target i386-efi -> i386-pc 1 year ago
Johannes Schauer Marin Rodrigues 420080648e
Revert "add another --dpkgopt example"
This reverts commit 40b6155967.

dpkg does not support the {foo,bar,baz} type of glob

Closes: #28
1 year ago
Johannes Schauer Marin Rodrigues be156e7a14
tests/chrootless: skip if libpam-runtime (<= 1.5.2-5) 1 year ago
Johannes Schauer Marin Rodrigues ea146ad108
add undocumented --chrooted-*-hook calling pivot_root in unshare mode 1 year ago
Johannes Schauer Marin Rodrigues 449fb248e2
Instead of mounting and unmounting for each run_chroot() call, do it once before the extract hook and unmount after the customize hooks 1 year ago
Johannes Schauer Marin Rodrigues eb54f6a23a
Instead of re-execing mmdebstrap under /bin/sh, use Text::ParseWords::shellwords
- saves a few PIDs
 - saves a bit of time because useless exec and fork is avoided
 - allows to run in pivoted chroots without mmdebstrap
1 year ago
Johannes Schauer Marin Rodrigues d2238c891b
coverage.py: add --skip option 1 year ago
Johannes Schauer Marin Rodrigues bf33a614c3
add mini-mmdebstrap in shell to the man page 1 year ago
Johannes Schauer Marin Rodrigues d15be6abbf
tests/check-against-debootstrap-dist: add more restrictions for remaining hacks 1 year ago
Johannes Schauer Marin Rodrigues 67902e06e9
tests/dev-ptmx: needs adduser inside the chroot 1 year ago
Johannes Schauer Marin Rodrigues d9ca7c21ff
make failure to remove /dev/ptmx a warning and not an error 1 year ago
Johannes Schauer Marin Rodrigues d29f9195d7
coverage.txt: add more requirements found by running tests on salsa ci and debci 1 year ago
Johannes Schauer Marin Rodrigues b454892ddd
release 1.2.2 1 year ago
Johannes Schauer Marin Rodrigues c2cd4a2a77
tests/check-against-debootstrap-dist: sort /etc/group for variant important 1 year ago
Johannes Schauer Marin Rodrigues 5ec6256461
tests/create-arm64-tarball: use regex instead of hardcoding the perl version 1 year ago
Johannes Schauer Marin Rodrigues 46f5889b54
make_mirror.sh: add console=tty0 to linux cmdline 1 year ago
Johannes Schauer Marin Rodrigues 822f8eafec
tests: test chrootless essential and systemd-sysv with fakeroot and foreign 1 year ago
Johannes Schauer Marin Rodrigues b5f6c7f08f
coverage.py: print failed options if more than one choices 1 year ago
Johannes Schauer Marin Rodrigues 43ba07e790
tests/check-against-debootstrap-dist: avoid code duplication by using a loop 1 year ago
Johannes Schauer Marin Rodrigues eb7cf54155
base-passwd now creates the _apt user 1 year ago
Johannes Schauer Marin Rodrigues 80ade97458
tests: put temporary files in /tmp and not into CWD 1 year ago
Johannes Schauer Marin Rodrigues e887a329ab
more changes for merged-/usr which is now default in testing and unstable 1 year ago
Johannes Schauer Marin Rodrigues fce852770b
tests/check-for-bit-by-bit-identical-format-output: add comment explaining why we cannot test chrootless mode here 1 year ago
Johannes Schauer Marin Rodrigues 07e3673161
tests/as-debootstrap-unshare-wrapper: systemd-sysusers before systemd 252 doesn't respect SOURCE_DATE_EPOCH when adding users to /etc/shadow 1 year ago
Johannes Schauer Marin Rodrigues 10c3d3e5f4
tests: output to stderr to prevent interleaving with set -x output 1 year ago
Johannes Schauer Marin Rodrigues 4048293be5
only print progress bars on interactive terminals that are wide enough 1 year ago
Johannes Schauer Marin Rodrigues 0903b3f6a7
tests/create-tarball-with-tmp-mounted-nodev: increase tmpfs size 1 year ago
Johannes Schauer Marin Rodrigues aac7157820
remove workarounds for #1010957 1 year ago
Johannes Schauer Marin Rodrigues bcb3fcdaf1
run_qemu.sh: add another example for how to connect to qemu via serial 1 year ago
Johannes Schauer Marin Rodrigues f0f211f383
coverage.py: only print dist, mode, variant and format for failed jobs if necessary 1 year ago
Johannes Schauer Marin Rodrigues 3a17a91b3c
hooks: do not require MMDEBSTRAP_VERBOSITY to be set
This allows running the hook from older mmdebstrap versions.
1 year ago
Johannes Schauer Marin Rodrigues fc5b60e038
adjust tests as /var/lib/dpkg/arch is now created unconditionally 1 year ago
Johannes Schauer Marin Rodrigues a207ac020b
remove test merged-usr-via-setup-hook as merged-/usr is now the default 1 year ago
Johannes Schauer Marin Rodrigues a16937e3e4
coverage.py: factor out coverage.txt parsing 1 year ago
Johannes Schauer Marin Rodrigues 8cb5b6e0ef
coverage.py: add --format option 1 year ago
Johannes Schauer Marin Rodrigues 91ca37706f
coverage.py: print default values in --help text 1 year ago
Johannes Schauer Marin Rodrigues d84a65b07f
coverage.py: do not allow 'default' in coverage.txt 1 year ago
Johannes Schauer Marin Rodrigues fbc3e5549d
coverage.py: improve output format of failed tests 1 year ago
Johannes Schauer Marin Rodrigues d4cb065639
Write an empty /etc/machine-id instead of writing 'uninitialized'.
Writing "uninitialized" instructs systemd to run units with
ConditionFirstBoot=yes which should only be done by tools that know how
to correctly set up such units.

Debian-Bug: #1021478
1 year ago
Jochen Sprickerhof adf62afcea
guestfish: move set-label after mkfs
Fixes:

libguestfs: error: set_label: don't know how to set the label for '' filesystems
1 year ago
Johannes Schauer Marin Rodrigues 3999212c48
always create /var/lib/dpkg/arch to make foreign architecture chrootless tarballs bit-by-bit identical 1 year ago
Johannes Schauer Marin Rodrigues c6c2baee6a
hooks/merged-usr/essential00.sh: avoid chroot in chrootless mode 1 year ago
Johannes Schauer Marin Rodrigues 6c68ab2e5e
also provide the info() function to debootstrap 2 years ago
Johannes Schauer Marin Rodrigues 2f27eccad4
allow /etc/apt/trusted.gpg.d/ not to exist 2 years ago
Johannes Schauer Marin Rodrigues 045b56bb4e
release 1.2.1 2 years ago
Johannes Schauer Marin Rodrigues 7123808b6c
do not clean up /run/lock as /var/lock is a symlink to it according to Debian policy §9.1.4 2 years ago
Johannes Schauer Marin Rodrigues 6416ce96c9
hooks/file-mirror-automount/setup00.sh: also parse MMDEBSTRAP_INCLUDE and make it available 2 years ago
Johannes Schauer Marin Rodrigues 410c5fcb24
fix --include option for files and add test case 2 years ago
Johannes Schauer Marin Rodrigues 9682e74385
release 1.2.0 2 years ago
Johannes Schauer Marin Rodrigues b0caeeef54
bump dates to 2022 2 years ago
Johannes Schauer Marin Rodrigues d209fb0c11
reformat with perltidy 2 years ago
Johannes Schauer Marin Rodrigues f4a3865c00
Remove support for proot.
The proot mode was broken from the start because in contrast to
fakechroot, no ownership information can be retained across multiple
invocations of proot. Since mmdebstrap started using apt from the
outside by setting DPkg::Chroot-Directory in mmdebstrap 0.8.0 proot mode
was finally completely broken because proot cannot wrap the chroot call
done by apt. Users of proot are recommended to run mmdebstrap in
fakechroot mode and then use proot with the resulting directory.
2 years ago
Johannes Schauer Marin Rodrigues 892e568496
coverage.sh: split up linting conditional 2 years ago
Johannes Schauer Marin Rodrigues b85df6b8f2
coverage.sh: idshift 2 years ago
Johannes Schauer Marin Rodrigues 7e8931578b
Store --include option values in MMDEBSTRAP_INCLUDE for hooks 2 years ago
Johannes Schauer Marin Rodrigues e1f0b0fa40
ensure operator precedence using more parenthesis 2 years ago
Johannes Schauer Marin Rodrigues 0ff2bef84c
tests/as-debootstrap-unshare-wrapper: redirect output of cmp and diff to stderr to preserve output order 2 years ago
Johannes Schauer Marin Rodrigues e875bca7fb
support apt patterns and paths with commas and whitespace for the --include option 2 years ago
Johannes Schauer Marin Rodrigues 0af22912f7
also delete everything in /run and add --skip=cleanup/run 2 years ago
Johannes Schauer Marin Rodrigues add9412a47
add --skip=chroot/mount and --skip=chroot/mount/dev, --skip=chroot/mount/proc, --skip=chroot/mount/sys 2 years ago
Johannes Schauer Marin Rodrigues e61e352f67
add --skip=chroot/start-stop-daemon and --skip=chroot/policy-rc.d 2 years ago
Johannes Schauer Marin Rodrigues 18c1e9bbc5
multiple skip options can be passed by separating them by comma or whitespace 2 years ago
Gioele Barabucci 7ce6db0ca7
mmdebstrap: Show APT's dependency trace when in debug mode
A dependency trace is a powerful tool to debug issues related to
APT's selection of packages, especially in custom mode.

Thus it makes sense to ask APT to output a dependency trace when
`mmdebstrap` is run with the `--debug` flag.
2 years ago
Johannes Schauer Marin Rodrigues 7d7d757f00
tarfilter: add --transform option 2 years ago
Johannes Schauer Marin Rodrigues 902bc55c4d
tarfilter --idshift now provides taridshift 2 years ago
Johannes Schauer Marin Rodrigues 226f86fea9
fix mmdebstrap hanging if apt in download step failed (closes: #1017795) 2 years ago
Johannes Schauer Marin Rodrigues df2226fb25
tests/check-against-debootstrap-dist: cmp outputs errors to stdout -- redirect to stderr to presereve output order with set +x 2 years ago
Johannes Schauer Marin Rodrigues 3fb97753ea
tests/check-against-debootstrap-dist: systemd started using systemd-sysusers instead of adduser 2 years ago
Johannes Schauer Marin Rodrigues 89a7e4c6ee
tests/custom-tmpdir: chown /home/user to 711 so that this test still works with adduser DIR_MODE=700 2 years ago
Johannes Schauer Marin Rodrigues f1d847e4ae
tests/dev-ptmx: we expect the grep calls to fail -- make sure they don't fail because /tmp/log doesn't exist 2 years ago
Johannes Schauer Marin Rodrigues c95632f963
coverage.py: add --variant option 2 years ago
Johannes Schauer Marin Rodrigues 5533b25255
tests/chrootless-essential: enable again now that glibc is fixed 2 years ago
Johannes Schauer Marin Rodrigues 34a9de929d
use standard character classes instead of bracketed character classes 2 years ago
Johannes Schauer Marin Rodrigues b385eb548a
only check first argument if we have one 2 years ago
Johannes Schauer Marin Rodrigues d82afec5de
error out if stdout is a tty 2 years ago
Johannes Schauer Marin Rodrigues 117a1591c5
coverage.py: also output failed to stderr 2 years ago
Johannes Schauer Marin Rodrigues 3fcb125e3c
release 1.1.0 2 years ago
Johannes Schauer Marin Rodrigues 35dc676394
relax apt version regex to allow devuan apt versions like 2.5.0devuan1 2 years ago
Johannes Schauer Marin Rodrigues 0ae0adde26
document mmdebstrap hanging forever instead of ENOSPC in qemu as a comment 2 years ago
Johannes Schauer Marin Rodrigues 5e22e0bfc8
adjust message about file-mirror-automount hook 2 years ago
Johannes Schauer Marin Rodrigues 2021f6f7cd
README.md: add an example for running coverage.py 2 years ago
Johannes Schauer Marin Rodrigues 432170c68e
tests/check-against-debootstrap-dist: account for ordering differences in /var/lib/dpkg/triggers/File 2 years ago
Johannes Schauer Marin Rodrigues 15c7de4a3b
tests/check-against-debootstrap-dist: static group ids for crontab, systemd-journal, systemd-network and systemd-resolve 2 years ago
Johannes Schauer Marin Rodrigues bf379f7e50
make_mirror.sh: bump DISK_SIZE to 10G because of gcc-defaults changing to gcc-12 2 years ago
Johannes Schauer Marin Rodrigues d91a18a350
Adjust merged-/usr as it's done by debootstrap
- implements the same as debootstrap in
   https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/71
 - builds a temporary usr-is-merged package and upgrades to the real one
 - create merged-/usr chroots for unstable and testing (which will
   become Debian 12 Bookworm)
 - add a dedicated merged-/usr section to the manual page
2 years ago
Johannes Schauer Marin Rodrigues 7cec147b9e
tests/arm64-without-qemu-support: removing qemu-user disables binfmt support again since src:systemd 251.2-4
Closes: #1012163
2 years ago
Johannes Schauer Marin Rodrigues 009089ee8a
Mount a new instance of /dev/pts in the chroot
Before, we bind-mounted /dev/ptmx and /dev/pts from the host into the
chroot. This will make posix_openpt() fail with 'No such file or
directory'.  The ability to create pseudo terminals is important for apt
(which will throw a warning otherwise) or running script(1) or source
package testsuites like for src:util-linux. This functionality is
restored by mounting a new devpts instance to /dev/pts and making
/dev/ptmx a symlink to /dev/pts/ptmx. Mounting with ptmxmode=666 is
required such that also non-root users in unshare mode are able to
create pseudo terminals. See also:

https://www.kernel.org/doc/Documentation/filesystems/devpts.txt
https://salsa.debian.org/debian/schroot/-/merge_requests/2
https://bugs.debian.org/856877
https://bugs.debian.org/817236
2 years ago
Johannes Schauer Marin Rodrigues 679f6cb2fc
coverage.py: allow passing tests by number 2 years ago
Johannes Schauer Marin Rodrigues e9e9cec884
coverage.py: remove unused variable 2 years ago
Johannes Schauer Marin Rodrigues b707676432
coverage.py: add --dist argument 2 years ago
Johannes Schauer Marin Rodrigues b51b5b9e2a
coverage.py: set sensible defaults for SOURCE_DATE_EPOCH and CMD 2 years ago
Johannes Schauer Marin Rodrigues 793d8bb561
add forgotten test create-directory-dry-run 2 years ago
Johannes Schauer Marin Rodrigues 9ca613da0a
coverage.py: instead of printing the length of the skipped dictionary, print the sum of the length of lists of tests it references 2 years ago
Johannes Schauer Marin Rodrigues 51ad1426c3
hooks/file-mirror-automount/setup00.sh: instead of grepping for Repo-URI, only output REPO_URI 2 years ago
Johannes Schauer Marin Rodrigues 153d1fa969
tests/arm64-without-qemu-support: disable binfmt not by uninstalling but by writing to /proc/sys/fs/binfmt_misc/qemu-aarch64
Since 1:7.0+dfsg-3, binfmt.d from systemd is used as preferred
alternative to binfmt-support. And systemd does not provide an official
way to trigger binfmt (de)registration besides a reboot.

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1012163

Since we also have binfmt-support installed, systemd and binfmt-support
work in parallel so this test becomes flaky and sometimes removing the
qemu packages would have the desired effect and sometimes not.

To make the test deterministic again, we explicitly disable emulation by
writing a 0 to /proc/sys/fs/binfmt_misc/qemu-aarch64
2 years ago
Johannes Schauer Marin Rodrigues c4962f9ab0
print value of SOURCE_DATE_EPOCH when creating and comparing debootstrap chroot to find bug only occurring when running autopkgtest around midnight 2 years ago
Johannes Schauer Marin Rodrigues c37e5e6059
tests/custom-tmpdir: try running mmdebstrap in a TMPDIR with special shell characters in its path 2 years ago
Johannes Schauer Marin Rodrigues 28122a8b5c
coverage.py: instead of killing (and leaving temporary files undeleted) just send SIGTERM and wait 2 years ago
Johannes Schauer Marin Rodrigues bf31355c62
run_qemu.sh: run timeout with --foreground so that qemu can receive sigint and quit immediately 2 years ago
Johannes Schauer Marin Rodrigues b46149b851
release 1.0.1 2 years ago
Johannes Schauer Marin Rodrigues 7198ad50f6
coverage.py: actually count number of successes to print the correct number when ctrl+c was pressed 2 years ago
Johannes Schauer Marin Rodrigues 5ea760920d
coverage.py: fix typo successully -> successfully 2 years ago
Johannes Schauer Marin Rodrigues 86f616996d
coverage.py: strip off fractional seconds of time left 2 years ago
Johannes Schauer Marin Rodrigues 1b5d87c7cf
coverage.py: add --mode to only run tests with given mode 2 years ago
Johannes Schauer Marin Rodrigues d96e85fddd
file-mirror-automount hook now supports modes that cannot mount (like fakechroot) by copying the repo into the chroot 2 years ago
Johannes Schauer Marin Rodrigues c1c6297db7
move copying files into shared directory from coverage.sh to coverage.py 2 years ago
Johannes Schauer Marin Rodrigues e4ef326b59
Only set up FAKECHROOT_CMD_SUBST for paths in PATH containing the original binary
If FAKECHROOT_CMD_SUBST sets up wrong substitutions, then binaries
cannot be found. For example if /usr/bin/chroot is listed in
FAKECHROOT_CMD_SUBST but /usr/sbin (the actual location of the chroot
binary) is not in PATH, the command fails
2 years ago
Johannes Schauer Marin Rodrigues 158956e213
release 1.0.0 2 years ago
Johannes Schauer Marin Rodrigues 4c3fddcd54
rewrite coverage.sh
- multiple individual shell scripts instead of one 3.5k line monster
 - tests driven by Python script allowing:
    * declarative test description in coverage.txt
    * collecting errors instead of aborting on first error
    * skipping tests
    * running specific tests
2 years ago
Johannes Schauer Marin Rodrigues e71676e15c
use warning() instead of warn() when unmounting /sys and /proc fails 2 years ago
Johannes Schauer Marin Rodrigues a238d90774
hooks/merged-usr: workaround not necessary anymore since debootstrap 1.0.125 2 years ago
Johannes Schauer Marin Rodrigues 790294ddca
hooks/merged-usr: acquire native architecture from apt-config
`dpkg --print-architecture` will be wrong when creating a foreign
architecture chroot and we cannot chroot() as the chroot directory is
still empty.
2 years ago
Johannes Schauer Marin Rodrigues cffd47e087
drop /usr/sbin prefixes from executables 2 years ago
Johannes Schauer Marin Rodrigues c6c9c27969
use DPkg::Path as default value for PATH 2 years ago
Johannes Schauer Marin Rodrigues 27926c75f9
unify checking if tools exist by running them with --version 2 years ago
Johannes Schauer Marin Rodrigues 0f9c6543c4
improve qemu-user
- rephrase info message to be less misleading
 - do not require qemu-$arch-static binary
 - check if /proc/sys/fs/binfmt_misc/qemu-$arch exists before reading it
2 years ago
Johannes Schauer Marin Rodrigues b99f1d53d5
add file-mirror-automount hook-dir 2 years ago
David Kalnischkies cc3150ef04
Rework download stage to allow file:// mirrors
- factor out package downloading function
 - replace -oApt::Get::Download-Only=true by -oDebug::pkgDpkgPm=1
 - remove guessing of package names in /var/cache/apt/archives/
 - drop edsp parsing with proxysolver/mmdebstrap-dump-solution to obtain
   downloaded filenames in favour of -oDpkg::Pre-Install-Pkgs::=cat
 - /var/cache/apt/archives/ is now allowed to contain packages
 - drop --skip=download/empty
 - file:// mirrors are now supported if their path is available inside
   the chroot
2 years ago
Johannes Schauer Marin Rodrigues c8835a6149
coverage.sh: make sure archives we copied into /var/cache/apt/archives are not deleted 2 years ago
Johannes Schauer Marin Rodrigues dc8b09ed50
fix pod formatting typo 2 years ago
Johannes Schauer Marin Rodrigues 21b23ebb9f
set MMDEBSTRAP_VERBOSITY in hooks 2 years ago
Johannes Schauer Marin Rodrigues 0664792cd5
manually push option arguments to array instead of using s@
By mixing s@ for --$foo-hook options and manual pushing in --hook-dir,
it can happen that options get lost. Consider the following test:

use Getopt::Long;
my $arr = [];
GetOptions(
    'A=s@' => \$arr,
    'B=s' => sub { push @{$arr}, $_[1]; }
);
foreach my $hook (@{$arr}) { print "hook: $hook\n"; }

This works fine:

    perl test.pl --A=a1 --B=b1 --A=a2 --B=b2
    hook: a1
    hook: b1
    hook: a2
    hook: b2

This misses b1:

    perl test.pl --B=b1 --A=a2 --B=b2
    hook: a2
    hook: b2
2 years ago
Johannes Schauer Marin Rodrigues 26af846d0a
fix that cached debs were not returned if there was nothing to download 2 years ago
Johannes Schauer Marin Rodrigues df6900ec4a
hooks/eatmydata/extract.sh: fix regex to also work on s390x 2 years ago
Johannes Schauer Marin Rodrigues 5c5f7de898
more documentation for TMPDIR 2 years ago
Johannes Schauer Marin Rodrigues 29b23bbcbc
document how to build on top of an existing tarball 2 years ago
Johannes Schauer Marin Rodrigues d10f320f5d
document how to build an sbuild unshare chroot mode tarball 2 years ago
Johannes Schauer Marin Rodrigues ce23e702e2
fixup comparison with debootstrap 2 years ago
Johannes Schauer Marin Rodrigues 2c155f7cc9
coverage.sh: only skip foreign arch if RUN_MA_SAME_TESTS==no and mode==fakechroot 2 years ago
Johannes Schauer Marin Rodrigues d7b39b6c97
coverage.sh: enable building variant=standard 2 years ago
Johannes Schauer Marin Rodrigues 6ec09c27ca
coverage.sh: mount tmpfs as workaround for #1010957 2 years ago
Johannes Schauer Marin Rodrigues 454121acb1
run_qemu.sh: use -cpu host as a workaround for #1011003 and because it's faster 2 years ago
Johannes Schauer Marin Rodrigues 09f1dd2ee6
Improve documentation of reproducibility of /etc/resolv.conf and /etc/hostname
Closes: #26
2 years ago

@ -1,2 +1,4 @@
Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
Johannes Schauer Marin Rodrigues <josch@mister-muffin.de> <j.schauer@email.de>
Helmut Grohne <helmut@subdivi.de> <helmut.grohne@intenta.de>
Benjamin Drung <benjamin.drung@ionos.com> <benjamin.drung@cloud.ionos.com>

@ -1,3 +1,71 @@
1.2.5 (2023-01-04)
------------------
- bugfix release
1.2.4 (2022-12-23)
------------------
- bugfix release
- add jessie-or-older extract hook
1.2.3 (2022-11-16)
------------------
- use Text::ParseWords::shellwords instead of spawning a new shell
- mount and unmount once, instead for each run_chroot() call
1.2.2 (2022-10-27)
------------------
- allow /etc/apt/trusted.gpg.d/ not to exist
- always create /var/lib/dpkg/arch to make foreign architecture chrootless
tarballs bit-by-bit identical
- write an empty /etc/machine-id instead of writing 'uninitialized'
- only print progress bars on interactive terminals that are wide enough
1.2.1 (2022-09-08)
------------------
- bugfix release
1.2.0 (2022-09-05)
------------------
- remove proot mode
- error out if stdout is an interactive terminal
- replace taridshift by tarfilter --idshift
- tarfilter: add --transform option
- multiple --skip options can be separated by comma or whitespace
- also cleanup the contents of /run
- support apt patterns and paths with commas and whitespace in --include
- hooks: store the values of the --include option in MMDEBSTRAP_INCLUDE
- add new --skip options: chroot/start-stop-daemon, chroot/policy-rc.d
chroot/mount, chroot/mount/dev, chroot/mount/proc, chroot/mount/sys,
cleanup/run
1.1.0 (2022-07-26)
----------------
- mount a new /dev/pts instance into the chroot to make posix_openpt work
- adjust merged-/usr hook to work the same way as debootstrap
- add no-merged-usr hook
1.0.1 (2022-05-29)
------------------
- bugfix release
1.0.0 (2022-05-28)
------------------
- all documented interfaces are now considered stable
- allow file:// mirrors
- /var/cache/apt/archives/ is now allowed to contain *.deb packages
- add file-mirror-automount hook-dir
- set $MMDEBSTRAP_VERBOSITY in hooks
- rewrite coverage with multiple individual and skippable shell scripts
0.8.6 (2022-03-25)
------------------

@ -34,7 +34,7 @@ Summary:
- chroot with apt in 11 seconds
- gzipped tarball with apt is 27M small
- bit-by-bit reproducible output
- unprivileged operation using Linux user namespaces, fakechroot or proot
- unprivileged operation using Linux user namespaces or fakechroot
- can operate on filesystems mounted with nodev
- foreign architecture chroots with qemu-user
- variant installing only Essential:yes packages and dependencies
@ -78,9 +78,9 @@ privileges to create a file (the chroot tarball) in one's home directory.
Thus, mmdebstrap provides multiple options to create a chroot tarball with the
right permissions **without superuser privileges**. This avoids a whole class
of bugs like #921815. Depending on what is available, it uses either Linux user
namespaces, fakechroot or proot. Debootstrap supports fakechroot but will not
namespaces or fakechroot. Debootstrap supports fakechroot but will not
create a tarball with the right permissions by itself. Support for Linux user
namespaces and proot is missing (see bugs #829134 and #698347, respectively).
namespaces is missing (see #829134).
When creating a chroot tarball with debootstrap, the temporary chroot directory
cannot be on a filesystem that has been mounted with nodev. In unprivileged
@ -137,6 +137,11 @@ By default, `coverage.sh` will skip running a single test which tries creating
a Ubuntu Focal chroot. To not skip that test, run `coverage.sh` with the
environment variable `ONLINE=yes`.
If a test fails you can run individual tests by executing `coverage.py` with
the test name and optionally limit it to a specific distribution like so:
CMD=./mmdebstrap ./coverage.py --dist unstable check-against-debootstrap-dist
Bugs
====
@ -147,11 +152,16 @@ Contributors
============
- Johannes Schauer Marin Rodrigues (main author)
- Gioele Barabucci
- Helmut Grohne
- Benjamin Drung
- Steve Dodd
- Jochen Sprickerhof
- Josh Triplett
- Konstantin Demin
- David Kalnischkies
- Joe Groocock
- Nicolas Vigier
- Raul Tambre
- Steve Dodd
- Trent W. Buck
- Vagrant Cascadian
- Gioele Barabucci

@ -0,0 +1,408 @@
#!/usr/bin/env python3
from debian.deb822 import Deb822, Release
import email.utils
import os
import sys
import shutil
import subprocess
import argparse
import time
from datetime import timedelta
from collections import defaultdict
from itertools import product
have_qemu = os.getenv("HAVE_QEMU", "yes") == "yes"
have_unshare = os.getenv("HAVE_UNSHARE", "yes") == "yes"
have_binfmt = os.getenv("HAVE_BINFMT", "yes") == "yes"
run_ma_same_tests = os.getenv("RUN_MA_SAME_TESTS", "yes") == "yes"
cmd = os.getenv("CMD", "./mmdebstrap")
default_dist = os.getenv("DEFAULT_DIST", "unstable")
all_dists = ["oldstable", "stable", "testing", "unstable"]
default_mode = "auto" if have_unshare else "root"
all_modes = ["auto", "root", "unshare", "fakechroot", "chrootless"]
default_variant = "apt"
all_variants = [
"extract",
"custom",
"essential",
"apt",
"minbase",
"buildd",
"-",
"standard",
]
default_format = "auto"
all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "null"]
mirror = os.getenv("mirror", "http://127.0.0.1/debian")
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
release_path = f"./shared/cache/debian/dists/{default_dist}/Release"
if not os.path.exists(release_path):
print("path doesn't exist:", release_path, file=sys.stderr)
print("run ./make_mirror.sh first", file=sys.stderr)
exit(1)
if os.getenv("SOURCE_DATE_EPOCH") is not None:
s_d_e = os.getenv("SOURCE_DATE_EPOCH")
else:
with open(release_path) as f:
rel = Release(f)
s_d_e = str(email.utils.mktime_tz(email.utils.parsedate_tz(rel["Date"])))
separator = (
"------------------------------------------------------------------------------"
)
def skip(condition, dist, mode, variant, fmt):
if not condition:
return ""
for line in condition.splitlines():
if not line:
continue
if eval(line):
return line.strip()
return ""
def parse_config(confname):
config_dict = defaultdict(dict)
config_order = list()
all_vals = {
"Dists": all_dists,
"Modes": all_modes,
"Variants": all_variants,
"Formats": all_formats,
}
with open(confname) as f:
for test in Deb822.iter_paragraphs(f):
if "Test" not in test.keys():
print("Test without name", file=sys.stderr)
exit(1)
name = test["Test"]
config_order.append(name)
for k in test.keys():
v = test[k]
if k not in [
"Test",
"Dists",
"Modes",
"Variants",
"Formats",
"Skip-If",
"Needs-QEMU",
"Needs-Root",
]:
print(f"Unknown field name {k} in test {name}")
exit(1)
if k in all_vals.keys():
if v == "default":
print(
f"Setting {k} to default in Test {name} is redundant",
file=sys.stderr,
)
exit(1)
if v == "any":
v = all_vals[k]
else:
# else, split the value by whitespace
v = v.split()
for i in v:
if i not in all_vals[k]:
print(
f"{i} is not a valid value for {k}", file=sys.stderr
)
exit(1)
config_dict[name][k] = v
return config_order, config_dict
def format_failed(num, total, name, dist, mode, variant, fmt, config_dict):
ret = f"({num}/{total}) {name}"
if len(config_dict[name].get("Dists", [])) > 1:
ret += f" --dist={dist}"
if len(config_dict[name].get("Modes", [])) > 1:
ret += f" --mode={mode}"
if len(config_dict[name].get("Variants", [])) > 1:
ret += f" --variant={variant}"
if len(config_dict[name].get("Formats", [])) > 1:
ret += f" --format={fmt}"
return ret
def main():
parser = argparse.ArgumentParser()
parser.add_argument("test", nargs="*", help="only run these tests")
parser.add_argument(
"-x",
"--exitfirst",
action="store_const",
dest="maxfail",
const=1,
help="exit instantly on first error or failed test.",
)
parser.add_argument(
"--maxfail",
metavar="num",
action="store",
type=int,
dest="maxfail",
default=0,
help="exit after first num failures or errors.",
)
parser.add_argument(
"--mode",
metavar="mode",
help=f"only run tests with this mode (Default = {default_mode})",
)
parser.add_argument(
"--dist",
metavar="dist",
help=f"only run tests with this dist (Default = {default_dist})",
)
parser.add_argument(
"--variant",
metavar="variant",
help=f"only run tests with this variant (Default = {default_variant})",
)
parser.add_argument(
"--format",
metavar="format",
help=f"only run tests with this format (Default = {default_format})",
)
parser.add_argument(
"--skip", metavar="test", action="append", help="skip this test"
)
args = parser.parse_args()
# copy over files from git or as distributed
for (git, dist, target) in [
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
(
"./proxysolver",
"/usr/lib/apt/solvers/mmdebstrap-dump-solution",
"proxysolver",
),
(
"./ldconfig.fakechroot",
"/usr/libexec/mmdebstrap/ldconfig.fakechroot",
"ldconfig.fakechroot",
),
]:
if os.path.exists(git):
shutil.copy(git, f"shared/{target}")
else:
shutil.copy(dist, f"shared/{target}")
# copy over hooks from git or as distributed
if os.path.exists("hooks"):
shutil.copytree("hooks", "shared/hooks", dirs_exist_ok=True)
else:
shutil.copytree(
"/usr/share/mmdebstrap/hooks", "shared/hooks", dirs_exist_ok=True
)
# parse coverage.txt
config_order, config_dict = parse_config("coverage.txt")
indirbutnotcovered = set(
[d for d in os.listdir("tests") if not d.startswith(".")]
) - set(config_order)
if indirbutnotcovered:
print(
"test(s) missing from coverage.txt: %s"
% (", ".join(sorted(indirbutnotcovered))),
file=sys.stderr,
)
exit(1)
coveredbutnotindir = set(config_order) - set(
[d for d in os.listdir("tests") if not d.startswith(".")]
)
if coveredbutnotindir:
print(
"test(s) missing from ./tests: %s"
% (", ".join(sorted(coveredbutnotindir))),
file=sys.stderr,
)
exit(1)
# produce the list of tests using the cartesian product of all allowed
# dists, modes, variants and formats of a given test
tests = []
for name in config_order:
test = config_dict[name]
for dist, mode, variant, fmt in product(
test.get("Dists", [default_dist]),
test.get("Modes", [default_mode]),
test.get("Variants", [default_variant]),
test.get("Formats", [default_format]),
):
skipreason = skip(test.get("Skip-If"), dist, mode, variant, fmt)
if skipreason:
tt = ("skip", skipreason)
elif have_qemu:
tt = "qemu"
elif test.get("Needs-QEMU", "false") == "true":
tt = ("skip", "test needs QEMU")
elif test.get("Needs-Root", "false") == "true":
tt = "sudo"
elif mode == "auto" and not have_unshare:
tt = "sudo"
elif mode == "root":
tt = "sudo"
elif mode == "unshare" and not have_unshare:
tt = ("skip", "test needs unshare")
else:
tt = "null"
tests.append((tt, name, dist, mode, variant, fmt))
torun = []
num_tests = len(tests)
if args.test:
# check if all given tests are either a valid name or a valid number
for test in args.test:
if test in [name for (_, name, _, _, _, _) in tests]:
continue
if not test.isdigit():
print(f"cannot find test named {test}", file=sys.stderr)
exit(1)
if int(test) >= len(tests) or int(test) <= 0 or str(int(test)) != test:
print(f"test number {test} doesn't exist", file=sys.stderr)
exit(1)
for i, (_, name, _, _, _, _) in enumerate(tests):
# if either the number or test name matches, then we use this test,
# otherwise we skip it
if name in args.test:
torun.append(i)
if str(i + 1) in args.test:
torun.append(i)
num_tests = len(torun)
starttime = time.time()
skipped = defaultdict(list)
failed = []
num_success = 0
num_finished = 0
for i, (test, name, dist, mode, variant, fmt) in enumerate(tests):
if torun and i not in torun:
continue
print(separator, file=sys.stderr)
print("(%d/%d) %s" % (i + 1, len(tests), name), file=sys.stderr)
print("dist: %s" % dist, file=sys.stderr)
print("mode: %s" % mode, file=sys.stderr)
print("variant: %s" % variant, file=sys.stderr)
print("format: %s" % fmt, file=sys.stderr)
if num_finished > 0:
currenttime = time.time()
timeleft = timedelta(
seconds=int(
(num_tests - num_finished)
* (currenttime - starttime)
/ num_finished
)
)
print("time left: %s" % timeleft, file=sys.stderr)
if failed:
print("failed: %d" % len(failed), file=sys.stderr)
num_finished += 1
with open("tests/" + name) as fin, open("shared/test.sh", "w") as fout:
for line in fin:
line = line.replace("{{ CMD }}", cmd)
line = line.replace("{{ SOURCE_DATE_EPOCH }}", s_d_e)
line = line.replace("{{ DIST }}", dist)
line = line.replace("{{ MIRROR }}", mirror)
line = line.replace("{{ MODE }}", mode)
line = line.replace("{{ VARIANT }}", variant)
line = line.replace("{{ FORMAT }}", fmt)
line = line.replace("{{ HOSTARCH }}", hostarch)
fout.write(line)
# ignore:
# SC2016 Expressions don't expand in single quotes, use double quotes for that.
# SC2050 This expression is constant. Did you forget the $ on a variable?
# SC2194 This word is constant. Did you forget the $ on a variable?
shellcheck = subprocess.run(
[
"shellcheck",
"--exclude=SC2050,SC2194,SC2016",
"-f",
"gcc",
"shared/test.sh",
],
check=False,
stdout=subprocess.PIPE,
).stdout.decode()
argv = None
match test:
case "qemu":
argv = ["./run_qemu.sh"]
case "sudo":
argv = ["./run_null.sh", "SUDO"]
case "null":
argv = ["./run_null.sh"]
case ("skip", reason):
skipped[reason].append(
("(%d/%d) %s" % (i + 1, len(tests), name), dist, mode, variant, fmt)
)
print(f"skipped because of {reason}", file=sys.stderr)
continue
print(separator, file=sys.stderr)
if args.skip and name in args.skip:
print(f"skipping because of --skip={name}", file=sys.stderr)
continue
if args.dist and args.dist != dist:
print(f"skipping because of --dist={args.dist}", file=sys.stderr)
continue
if args.mode and args.mode != mode:
print(f"skipping because of --mode={args.mode}", file=sys.stderr)
continue
if args.variant and args.variant != variant:
print(f"skipping because of --variant={args.variant}", file=sys.stderr)
continue
if args.format and args.format != fmt:
print(f"skipping because of --format={args.format}", file=sys.stderr)
continue
proc = subprocess.Popen(argv)
try:
proc.wait()
except KeyboardInterrupt:
proc.terminate()
proc.wait()
break
print(separator, file=sys.stderr)
if proc.returncode != 0 or shellcheck != "":
if shellcheck != "":
print(shellcheck)
failed.append(
format_failed(
i + 1, len(tests), name, dist, mode, variant, fmt, config_dict
)
)
print("result: FAILURE", file=sys.stderr)
else:
print("result: SUCCESS", file=sys.stderr)
num_success += 1
if args.maxfail and len(failed) >= args.maxfail:
break
print(
"successfully ran %d tests" % num_success,
file=sys.stderr,
)
if skipped:
print("skipped %d:" % sum([len(v) for v in skipped.values()]), file=sys.stderr)
for reason, l in skipped.items():
print(f"skipped because of {reason}:", file=sys.stderr)
for t in l:
print(f" {t}", file=sys.stderr)
if failed:
print("failed %d:" % len(failed), file=sys.stderr)
for f in failed:
print(f, file=sys.stderr)
exit(1)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,360 @@
Test: check-against-debootstrap-dist
Dists: any
Variants: minbase buildd -
Needs-Root: true
Test: as-debootstrap-unshare-wrapper
Needs-QEMU: true
Test: help
Test: man
Test: version
Test: create-directory
Needs-Root: true
Test: unshare-as-root-user
Needs-Root: true
Test: dist-using-codename
Dists: any
Test: fail-without-etc-subuid
Needs-QEMU: true
Test: fail-without-username-in-etc-subuid
Needs-QEMU: true
Test: unshare-as-root-user-inside-chroot
Needs-Root: true
Test: root-mode-inside-chroot
Needs-Root: true
Test: root-mode-inside-unshare-chroot
Needs-QEMU: true
Test: root-without-cap-sys-admin
Needs-Root: true
Test: mount-is-missing
Needs-QEMU: true
Test: check-for-bit-by-bit-identical-format-output
Needs-QEMU: true
Formats: tar squashfs ext2
Variants: essential apt minbase buildd - standard
Skip-If:
variant == "standard" and dist in ["oldstable", "stable"] # #864082, #1004557, #1004558
variant == "important" and dist == "oldstable" # /var/lib/systemd/catalog/database differs
fmt == "squashfs" and dist == "oldstable" # squashfs-tools-ng is not available
fmt == "ext2" and dist == "oldstable" # genext2fs does not support SOURCE_DATE_EPOCH
Test: tarfilter-idshift
Needs-QEMU: true
Skip-If: dist == "oldstable" # python3 tarfile module does not preserve xattrs
Test: progress-bars-on-fake-tty
Test: debug-output-on-fake-tty
Test: existing-empty-directory
Needs-Root: true
Test: existing-directory-with-lost-found
Needs-Root: true
Test: fail-installing-to-non-empty-lost-found
Test: fail-installing-to-non-empty-target-directory
Test: missing-device-nodes-outside-the-chroot
Needs-QEMU: true
Test: missing-dev-sys-proc-inside-the-chroot
Needs-QEMU: true
Test: chroot-directory-not-accessible-by-apt-user
Needs-Root: true
Test: cwd-directory-not-accessible-by-unshared-user
Needs-QEMU: true
Test: create-gzip-compressed-tarball
Needs-QEMU: true
Test: custom-tmpdir
Needs-QEMU: true
Test: xz-compressed-tarball
Test: directory-ending-in-tar
Modes: root
Needs-Root: true
Test: auto-mode-without-unshare-capabilities
Needs-QEMU: true
Test: fail-with-missing-lz4
Test: fail-with-path-with-quotes
Test: create-tarball-with-tmp-mounted-nodev
Needs-QEMU: true
Test: read-from-stdin-write-to-stdout
Test: supply-components-manually
Modes: root
Needs-Root: true
Test: stable-default-mirror
Needs-QEMU: true
Test: pass-distribution-but-implicitly-write-to-stdout
Needs-QEMU: true
Test: aspcud-apt-solver
Test: mirror-is-stdin
Test: copy-mirror
Needs-QEMU: true
Test: file-mirror
Needs-QEMU: true
Test: file-mirror-automount-hook
Modes: root unshare fakechroot
Needs-QEMU: true
Test: mirror-is-deb
Test: mirror-is-real-file
Test: deb822-1-2
Modes: root
Needs-Root: true
Test: deb822-2-2
Modes: root
Needs-Root: true
Test: automatic-mirror-from-suite
Needs-QEMU: true
Test: invalid-mirror
Test: fail-installing-to-root
Modes: root
Needs-Root: true
Test: fail-installing-to-existing-file
Modes: root
Needs-Root: true
Test: arm64-without-qemu-support
Needs-QEMU: true
Skip-If: hostarch != "amd64"
Test: i386-which-can-be-executed-without-qemu
Needs-QEMU: true
Skip-If:
hostarch != "amd64"
not run_ma_same_tests
Test: include-libmagic-mgc-arm64
Needs-Root: true
Skip-If:
hostarch != "amd64"
not run_ma_same_tests
Test: include-libmagic-mgc-arm64-with-multiple-arch-options
Needs-Root: true
Skip-If:
hostarch != "amd64"
not run_ma_same_tests
Test: aptopt
Needs-Root: true
Test: keyring
Needs-QEMU: true
Test: keyring-overwrites
Needs-Root: true
Test: signed-by-without-host-keys
Needs-QEMU: true
Test: ascii-armored-keys
Needs-QEMU: true
Test: signed-by-with-host-keys
Needs-Root: true
Test: dpkgopt
Needs-Root: true
Test: include
Needs-Root: true
Test: multiple-include
Needs-Root: true
Test: include-with-multiple-apt-sources
Needs-Root: true
Test: essential-hook
Needs-Root: true
Test: customize-hook
Needs-Root: true
Test: failing-customize-hook
Needs-Root: true
Test: sigint-during-customize-hook
Needs-Root: true
Test: hook-directory
Needs-Root: true
Test: eatmydata-via-hook-dir
Needs-Root: true
Test: special-hooks-using-helpers
Needs-Root: true
Test: special-hooks-using-helpers-and-env-vars
Needs-Root: true
Test: special-hooks-with-mode-mode
Modes: root unshare fakechroot
Needs-QEMU: true
Test: debootstrap-no-op-options
Needs-Root: true
Test: verbose
Needs-Root: true
Test: debug
Needs-Root: true
Test: quiet
Needs-Root: true
Test: logfile
Needs-Root: true
Test: without-etc-resolv-conf-and-etc-hostname
Needs-QEMU: true
Test: preserve-mode-of-etc-resolv-conf-and-etc-hostname
Modes: root
Needs-QEMU: true
Test: not-having-to-install-apt-in-include-because-a-hook-did-it-before
Test: remove-start-stop-daemon-and-policy-rc-d-in-hook
Test: skip-start-stop-daemon-policy-rc
Test: skip-mount
Modes: unshare
Test: compare-output-with-pre-seeded-var-cache-apt-archives
Needs-QEMU: true
Variants: any
Skip-If:
variant == "standard" and dist in ["oldstable", "stable"] # #864082, #1004557, #1004558
variant == "important" and dist == "oldstable" # /var/lib/systemd/catalog/database differs
Test: create-directory-dry-run
Test: create-tarball-dry-run
Variants: any
Modes: any
Test: unpack-doc-debian