forked from josch/mmdebstrap
Compare commits
10 commits
444b3b6fec
...
e4e10b670c
Author | SHA1 | Date | |
---|---|---|---|
e4e10b670c | |||
c4a43ea0f9 | |||
60d69f6f78 | |||
122952a9b0 | |||
b1f1d7fbdd | |||
64a7ac5ceb | |||
3b2a681cc6 | |||
4da43ec72e | |||
3b41fe6805 | |||
|
c61e81a244 |
3 changed files with 151 additions and 368 deletions
123
coverage.sh
123
coverage.sh
|
@ -127,7 +127,7 @@ if [ ! -e shared/hooks/eatmydata/customize.sh ] || [ hooks/eatmydata/customize.s
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
starttime=
|
starttime=
|
||||||
total=213
|
total=177
|
||||||
skipped=0
|
skipped=0
|
||||||
runtests=0
|
runtests=0
|
||||||
i=1
|
i=1
|
||||||
|
@ -2141,6 +2141,10 @@ tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort > tar2.txt
|
||||||
ppc64el)
|
ppc64el)
|
||||||
echo ./lib64;
|
echo ./lib64;
|
||||||
;;
|
;;
|
||||||
|
s390x)
|
||||||
|
echo ./lib32;
|
||||||
|
echo ./usr/lib32/;
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
} | sort -u | diff -u - tar2.txt
|
} | sort -u | diff -u - tar2.txt
|
||||||
rm -r /tmp/debian-chroot
|
rm -r /tmp/debian-chroot
|
||||||
|
@ -3076,123 +3080,6 @@ END
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
# test all variants
|
|
||||||
|
|
||||||
for variant in essential apt required minbase buildd important debootstrap - standard; do
|
|
||||||
print_header "mode=root,variant=$variant: create tarball"
|
|
||||||
cat << END > shared/test.sh
|
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
$CMD --mode=root --variant=$variant $DEFAULT_DIST /tmp/debian-chroot.tar $mirror
|
|
||||||
tar -tf /tmp/debian-chroot.tar | sort > "$variant.txt"
|
|
||||||
rm /tmp/debian-chroot.tar
|
|
||||||
END
|
|
||||||
if [ "$HAVE_QEMU" = "yes" ]; then
|
|
||||||
./run_qemu.sh
|
|
||||||
runtests=$((runtests+1))
|
|
||||||
else
|
|
||||||
./run_null.sh SUDO
|
|
||||||
runtests=$((runtests+1))
|
|
||||||
fi
|
|
||||||
# check if the other modes produce the same result in each variant
|
|
||||||
for mode in unshare fakechroot proot; do
|
|
||||||
print_header "mode=$mode,variant=$variant: create tarball"
|
|
||||||
# fontconfig doesn't install reproducibly because differences
|
|
||||||
# in /var/cache/fontconfig/. See
|
|
||||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=864082
|
|
||||||
if [ "$variant" = standard ]; then
|
|
||||||
echo "skipping test because of #864082" >&2
|
|
||||||
skipped=$((skipped+1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [ "$mode" = "unshare" ] && [ "$HAVE_UNSHARE" != "yes" ]; then
|
|
||||||
echo "HAVE_UNSHARE != yes -- Skipping test..." >&2
|
|
||||||
skipped=$((skipped+1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [ "$mode" = "proot" ] && [ "$HAVE_PROOT" != "yes" ]; then
|
|
||||||
echo "HAVE_PROOT != yes -- Skipping test..." >&2
|
|
||||||
skipped=$((skipped+1))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
cat << END > shared/test.sh
|
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
if [ "\$(id -u)" -eq 0 ] && ! id -u user > /dev/null 2>&1; then
|
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
adduser --gecos user --disabled-password user
|
|
||||||
fi
|
|
||||||
if [ "$mode" = unshare ]; then
|
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
sysctl -w kernel.unprivileged_userns_clone=1
|
|
||||||
fi
|
|
||||||
prefix=
|
|
||||||
[ "\$(id -u)" -eq 0 ] && prefix="runuser -u user --"
|
|
||||||
\$prefix $CMD --mode=$mode --variant=$variant $DEFAULT_DIST /tmp/debian-chroot.tar $mirror
|
|
||||||
tar -tf /tmp/debian-chroot.tar | sort | diff -u "./$variant.txt" -
|
|
||||||
rm /tmp/debian-chroot.tar
|
|
||||||
END
|
|
||||||
if [ "$HAVE_QEMU" = "yes" ]; then
|
|
||||||
./run_qemu.sh
|
|
||||||
runtests=$((runtests+1))
|
|
||||||
else
|
|
||||||
./run_null.sh
|
|
||||||
runtests=$((runtests+1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
# some variants are equal and some are strict superset of the last
|
|
||||||
# special case of the buildd variant: nothing is a superset of it
|
|
||||||
case "$variant" in
|
|
||||||
essential) ;; # nothing to compare it to
|
|
||||||
apt)
|
|
||||||
[ $(comm -23 shared/essential.txt shared/apt.txt | wc -l) -eq 0 ]
|
|
||||||
[ $(comm -13 shared/essential.txt shared/apt.txt | wc -l) -gt 0 ]
|
|
||||||
rm shared/essential.txt
|
|
||||||
;;
|
|
||||||
required)
|
|
||||||
[ $(comm -23 shared/apt.txt shared/required.txt | wc -l) -eq 0 ]
|
|
||||||
[ $(comm -13 shared/apt.txt shared/required.txt | wc -l) -gt 0 ]
|
|
||||||
rm shared/apt.txt
|
|
||||||
;;
|
|
||||||
minbase) # equal to required
|
|
||||||
cmp shared/required.txt shared/minbase.txt
|
|
||||||
rm shared/required.txt
|
|
||||||
;;
|
|
||||||
buildd)
|
|
||||||
[ $(comm -23 shared/minbase.txt shared/buildd.txt | wc -l) -eq 0 ]
|
|
||||||
[ $(comm -13 shared/minbase.txt shared/buildd.txt | wc -l) -gt 0 ]
|
|
||||||
rm shared/buildd.txt # we need minbase.txt but not buildd.txt
|
|
||||||
;;
|
|
||||||
important)
|
|
||||||
[ $(comm -23 shared/minbase.txt shared/important.txt | wc -l) -eq 0 ]
|
|
||||||
[ $(comm -13 shared/minbase.txt shared/important.txt | wc -l) -gt 0 ]
|
|
||||||
rm shared/minbase.txt
|
|
||||||
;;
|
|
||||||
debootstrap) # equal to important
|
|
||||||
cmp shared/important.txt shared/debootstrap.txt
|
|
||||||
rm shared/important.txt
|
|
||||||
;;
|
|
||||||
-) # equal to debootstrap
|
|
||||||
cmp shared/debootstrap.txt shared/-.txt
|
|
||||||
rm shared/debootstrap.txt
|
|
||||||
;;
|
|
||||||
standard)
|
|
||||||
[ $(comm -23 shared/-.txt shared/standard.txt | wc -l) -eq 0 ]
|
|
||||||
[ $(comm -13 shared/-.txt shared/standard.txt | wc -l) -gt 0 ]
|
|
||||||
rm shared/-.txt shared/standard.txt
|
|
||||||
;;
|
|
||||||
*) exit 1;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# test extract variant also with chrootless mode
|
# test extract variant also with chrootless mode
|
||||||
for mode in root unshare fakechroot proot chrootless; do
|
for mode in root unshare fakechroot proot chrootless; do
|
||||||
print_header "mode=$mode,variant=extract: unpack doc-debian"
|
print_header "mode=$mode,variant=extract: unpack doc-debian"
|
||||||
|
|
|
@ -224,6 +224,9 @@ Apt::Get::Download-Only true;
|
||||||
Acquire::Languages "none";
|
Acquire::Languages "none";
|
||||||
Dir::Etc::Trusted "/etc/apt/trusted.gpg";
|
Dir::Etc::Trusted "/etc/apt/trusted.gpg";
|
||||||
Dir::Etc::TrustedParts "/etc/apt/trusted.gpg.d";
|
Dir::Etc::TrustedParts "/etc/apt/trusted.gpg.d";
|
||||||
|
Acquire::http::Dl-Limit "1000";
|
||||||
|
Acquire::https::Dl-Limit "1000";
|
||||||
|
Acquire::Retries "5";
|
||||||
END
|
END
|
||||||
|
|
||||||
> "$rootdir/var/lib/dpkg/status"
|
> "$rootdir/var/lib/dpkg/status"
|
||||||
|
@ -466,6 +469,17 @@ cleanuptmpdir() {
|
||||||
export SOURCE_DATE_EPOCH=$(date --date="$(grep-dctrl -s Date -n '' "$newmirrordir/dists/$DEFAULT_DIST/Release")" +%s)
|
export SOURCE_DATE_EPOCH=$(date --date="$(grep-dctrl -s Date -n '' "$newmirrordir/dists/$DEFAULT_DIST/Release")" +%s)
|
||||||
|
|
||||||
if [ "$HAVE_QEMU" = "yes" ]; then
|
if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
|
case "$HOSTARCH" in
|
||||||
|
amd64|i386)
|
||||||
|
# okay
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "qemu support is only available on amd64 and i386" >&2
|
||||||
|
echo "because syslinux is only available on those arches" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
# We must not use any --dpkgopt here because any dpkg options still
|
# We must not use any --dpkgopt here because any dpkg options still
|
||||||
# leak into the chroot with chrootless mode.
|
# leak into the chroot with chrootless mode.
|
||||||
# We do not use our own package cache here because
|
# We do not use our own package cache here because
|
||||||
|
@ -507,6 +521,9 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
arches=$HOSTARCH
|
arches=$HOSTARCH
|
||||||
fi
|
fi
|
||||||
$CMD --variant=apt --architectures=$arches --include="$pkgs" \
|
$CMD --variant=apt --architectures=$arches --include="$pkgs" \
|
||||||
|
--aptopt='Acquire::http::Dl-Limit "1000"' \
|
||||||
|
--aptopt='Acquire::https::Dl-Limit "1000"' \
|
||||||
|
--aptopt='Acquire::Retries "5"' \
|
||||||
$DEFAULT_DIST - "$mirror" > "$tmpdir/debian-chroot.tar"
|
$DEFAULT_DIST - "$mirror" > "$tmpdir/debian-chroot.tar"
|
||||||
|
|
||||||
cat << END > "$tmpdir/extlinux.conf"
|
cat << END > "$tmpdir/extlinux.conf"
|
||||||
|
@ -540,7 +557,7 @@ END
|
||||||
cat << 'END' > "$tmpdir/worker.sh"
|
cat << 'END' > "$tmpdir/worker.sh"
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
echo 'root:root' | chpasswd
|
echo 'root:root' | chpasswd
|
||||||
mount -t 9p -o trans=virtio,access=any mmdebstrap /mnt
|
mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt
|
||||||
# need to restart mini-httpd because we mounted different content into www-root
|
# need to restart mini-httpd because we mounted different content into www-root
|
||||||
systemctl restart mini-httpd
|
systemctl restart mini-httpd
|
||||||
|
|
||||||
|
|
369
mmdebstrap
369
mmdebstrap
|
@ -1290,7 +1290,7 @@ sub run_chroot {
|
||||||
}
|
}
|
||||||
|
|
||||||
# the file might not exist if it was removed in a hook
|
# the file might not exist if it was removed in a hook
|
||||||
if (-e "$options->{root}/sbin/start-stop-daemon") {
|
if (-f "$options->{root}/sbin/start-stop-daemon") {
|
||||||
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
if (-e "$options->{root}/sbin/start-stop-daemon.REAL") {
|
||||||
error "$options->{root}/sbin/start-stop-daemon.REAL already"
|
error "$options->{root}/sbin/start-stop-daemon.REAL already"
|
||||||
. " exists";
|
. " exists";
|
||||||
|
@ -1318,7 +1318,7 @@ sub run_chroot {
|
||||||
"$options->{root}/sbin/start-stop-daemon"
|
"$options->{root}/sbin/start-stop-daemon"
|
||||||
) or error "cannot move start-stop-daemon: $!";
|
) or error "cannot move start-stop-daemon: $!";
|
||||||
}
|
}
|
||||||
if (-e "$options->{root}/usr/sbin/policy-rc.d") {
|
if (-f "$options->{root}/usr/sbin/policy-rc.d") {
|
||||||
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
unlink "$options->{root}/usr/sbin/policy-rc.d"
|
||||||
or error "cannot unlink policy-rc.d: $!";
|
or error "cannot unlink policy-rc.d: $!";
|
||||||
}
|
}
|
||||||
|
@ -1510,8 +1510,7 @@ sub setup {
|
||||||
run_update($options);
|
run_update($options);
|
||||||
}
|
}
|
||||||
|
|
||||||
(my $pkgs_to_install, my $essential_pkgs, my $cached_debs)
|
(my $essential_pkgs, my $cached_debs) = run_download($options);
|
||||||
= run_download($options);
|
|
||||||
|
|
||||||
# in theory, we don't have to extract the packages in chrootless mode
|
# in theory, we don't have to extract the packages in chrootless mode
|
||||||
# but we do it anyways because otherwise directory creation timestamps
|
# but we do it anyways because otherwise directory creation timestamps
|
||||||
|
@ -1533,7 +1532,7 @@ sub setup {
|
||||||
|
|
||||||
run_hooks('essential', $options);
|
run_hooks('essential', $options);
|
||||||
|
|
||||||
run_install($options, $pkgs_to_install, $chrootcmd);
|
run_install($options, $chrootcmd);
|
||||||
|
|
||||||
run_hooks('customize', $options);
|
run_hooks('customize', $options);
|
||||||
}
|
}
|
||||||
|
@ -1992,22 +1991,6 @@ sub run_update() {
|
||||||
sub run_download() {
|
sub run_download() {
|
||||||
my $options = shift;
|
my $options = shift;
|
||||||
|
|
||||||
my %pkgs_to_install;
|
|
||||||
for my $incl (@{ $options->{include} }) {
|
|
||||||
for my $pkg (split /[,\s]+/, $incl) {
|
|
||||||
# strip leading and trailing whitespace
|
|
||||||
$pkg =~ s/^\s+|\s+$//g;
|
|
||||||
# skip if the remainder is an empty string
|
|
||||||
if ($pkg eq '') {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
$pkgs_to_install{$pkg} = ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($options->{variant} eq 'buildd') {
|
|
||||||
$pkgs_to_install{'build-essential'} = ();
|
|
||||||
}
|
|
||||||
|
|
||||||
# We use /var/cache/apt/archives/ to figure out which packages apt chooses
|
# We use /var/cache/apt/archives/ to figure out which packages apt chooses
|
||||||
# to install. That's why the directory must be empty if:
|
# to install. That's why the directory must be empty if:
|
||||||
# - /var/cache/apt/archives exists, and
|
# - /var/cache/apt/archives exists, and
|
||||||
|
@ -2031,7 +2014,7 @@ sub run_download() {
|
||||||
if (
|
if (
|
||||||
!$options->{dryrun}
|
!$options->{dryrun}
|
||||||
&& ((none { $_ eq $options->{variant} } ('extract', 'custom'))
|
&& ((none { $_ eq $options->{variant} } ('extract', 'custom'))
|
||||||
|| scalar keys %pkgs_to_install != 0)
|
|| scalar @{ $options->{include} } != 0)
|
||||||
&& -d "$options->{root}/var/cache/apt/archives/"
|
&& -d "$options->{root}/var/cache/apt/archives/"
|
||||||
) {
|
) {
|
||||||
my $apt_archives = "/var/cache/apt/archives/";
|
my $apt_archives = "/var/cache/apt/archives/";
|
||||||
|
@ -2064,10 +2047,22 @@ sub run_download() {
|
||||||
# (essential variant) then we have to compute the package set ourselves.
|
# (essential variant) then we have to compute the package set ourselves.
|
||||||
# Same if we want to install priority based variants.
|
# Same if we want to install priority based variants.
|
||||||
if (any { $_ eq $options->{variant} } ('extract', 'custom')) {
|
if (any { $_ eq $options->{variant} } ('extract', 'custom')) {
|
||||||
if (scalar keys %pkgs_to_install == 0) {
|
if (scalar @{ $options->{include} } == 0) {
|
||||||
info "nothing to download -- skipping...";
|
info "nothing to download -- skipping...";
|
||||||
return ([], []);
|
return ([], []);
|
||||||
}
|
}
|
||||||
|
my %pkgs_to_install;
|
||||||
|
for my $incl (@{ $options->{include} }) {
|
||||||
|
for my $pkg (split /[,\s]+/, $incl) {
|
||||||
|
# strip leading and trailing whitespace
|
||||||
|
$pkg =~ s/^\s+|\s+$//g;
|
||||||
|
# skip if the remainder is an empty string
|
||||||
|
if ($pkg eq '') {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$pkgs_to_install{$pkg} = ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
my %result = ();
|
my %result = ();
|
||||||
if ($options->{dryrun}) {
|
if ($options->{dryrun}) {
|
||||||
|
@ -2126,7 +2121,10 @@ sub run_download() {
|
||||||
],
|
],
|
||||||
%result
|
%result
|
||||||
});
|
});
|
||||||
} elsif ($options->{variant} eq 'essential') {
|
} elsif (
|
||||||
|
any { $_ eq $options->{variant} }
|
||||||
|
('essential', 'standard', 'important', 'required', 'buildd')
|
||||||
|
) {
|
||||||
# 2021-06-07, #debian-apt on OFTC, times in UTC+2
|
# 2021-06-07, #debian-apt on OFTC, times in UTC+2
|
||||||
# 17:27 < DonKult> (?essential includes 'apt' through)
|
# 17:27 < DonKult> (?essential includes 'apt' through)
|
||||||
# 17:30 < josch> DonKult: no, because pkgCacheGen::ForceEssential ",";
|
# 17:30 < josch> DonKult: no, because pkgCacheGen::ForceEssential ",";
|
||||||
|
@ -2151,7 +2149,7 @@ sub run_download() {
|
||||||
'install',
|
'install',
|
||||||
'?narrow('
|
'?narrow('
|
||||||
. (
|
. (
|
||||||
defined($options->{suite})
|
length($options->{suite})
|
||||||
? '?archive(' . $options->{suite} . '),'
|
? '?archive(' . $options->{suite} . '),'
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
|
@ -2161,209 +2159,6 @@ sub run_download() {
|
||||||
],
|
],
|
||||||
%result
|
%result
|
||||||
});
|
});
|
||||||
} elsif (
|
|
||||||
any { $_ eq $options->{variant} }
|
|
||||||
('standard', 'important', 'required', 'minbase', 'buildd')
|
|
||||||
) {
|
|
||||||
# In the future, after bug https://bugs.debian.org/989558 is fixed, we
|
|
||||||
# want to use apt patterns to select the packages to install:
|
|
||||||
#
|
|
||||||
# ?narrow(?archive(unstable),?architecture(amd64),?priority(important))
|
|
||||||
#
|
|
||||||
# Once this is possible, we can append above statement to the apt-get
|
|
||||||
# install call in run_download() instead of assembling the package list
|
|
||||||
# here and passing it through all the way. Then this function only
|
|
||||||
# takes care of retrieving the essential packages.
|
|
||||||
#
|
|
||||||
# https://salsa.debian.org/apt-team/apt/-/merge_requests/185
|
|
||||||
my %ess_pkgs;
|
|
||||||
my %ess_pkgs_target;
|
|
||||||
my %pkgs_to_install_target = %pkgs_to_install;
|
|
||||||
my $num_suite_matches = 0;
|
|
||||||
my $num_suite_mismatch = 0;
|
|
||||||
open(
|
|
||||||
my $pipe_apt,
|
|
||||||
'-|',
|
|
||||||
'apt-get',
|
|
||||||
'indextargets',
|
|
||||||
'--format',
|
|
||||||
('$(CODENAME)' . "\t" . '$(SUITE)' . "\t" . '$(FILENAME)'),
|
|
||||||
'Created-By: Packages'
|
|
||||||
) or error "cannot start apt-get indextargets: $!";
|
|
||||||
while (my $line = <$pipe_apt>) {
|
|
||||||
chomp $line;
|
|
||||||
my ($codename, $suite, $fname) = split /\t/, $line, 3;
|
|
||||||
debug "processing indextarget output for $codename $suite $fname";
|
|
||||||
my $suite_matches = 0;
|
|
||||||
if (
|
|
||||||
defined $options->{suite}
|
|
||||||
and
|
|
||||||
($options->{suite} eq $codename or $options->{suite} eq $suite)
|
|
||||||
) {
|
|
||||||
$suite_matches = 1;
|
|
||||||
$num_suite_matches++;
|
|
||||||
} else {
|
|
||||||
$num_suite_mismatch++;
|
|
||||||
}
|
|
||||||
open(my $pipe_cat, '-|', '/usr/lib/apt/apt-helper', 'cat-file',
|
|
||||||
$fname)
|
|
||||||
or error "cannot start apt-helper cat-file: $!";
|
|
||||||
|
|
||||||
my $pkgname;
|
|
||||||
my $ess = '';
|
|
||||||
my $prio = 'optional';
|
|
||||||
my $arch = '';
|
|
||||||
while (my $line = <$pipe_cat>) {
|
|
||||||
chomp $line;
|
|
||||||
# Dpkg::Index takes 10 seconds to parse a typical Packages
|
|
||||||
# file. Thus we instead use a simple parser that just retrieve
|
|
||||||
# the information we need.
|
|
||||||
if ($line ne "") {
|
|
||||||
if ($line =~ /^Package: (.*)/) {
|
|
||||||
$pkgname = $1;
|
|
||||||
} elsif ($line =~ /^Essential: yes$/) {
|
|
||||||
$ess = 'yes';
|
|
||||||
} elsif ($line =~ /^Priority: (.*)/) {
|
|
||||||
$prio = $1;
|
|
||||||
} elsif ($line =~ /^Architecture: (.*)/) {
|
|
||||||
$arch = $1;
|
|
||||||
}
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
# we are only interested of packages of native architecture or
|
|
||||||
# Architecture:all
|
|
||||||
if ($arch eq $options->{nativearch} or $arch eq 'all') {
|
|
||||||
# the line is empty, thus a package stanza just finished
|
|
||||||
# processing and we can handle it now
|
|
||||||
if ($ess eq 'yes') {
|
|
||||||
$ess_pkgs{$pkgname} = ();
|
|
||||||
if ($suite_matches) {
|
|
||||||
$ess_pkgs_target{$pkgname} = ();
|
|
||||||
}
|
|
||||||
} elsif ($options->{variant} eq 'essential') {
|
|
||||||
# for this variant we are only interested in the
|
|
||||||
# essential packages
|
|
||||||
} elsif (
|
|
||||||
any { $_ eq $options->{variant} } (
|
|
||||||
'standard', 'important', 'required', 'buildd',
|
|
||||||
'minbase'
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if ($prio eq 'optional' or $prio eq 'extra') {
|
|
||||||
# always ignore packages of priority optional and
|
|
||||||
# extra
|
|
||||||
} elsif ($prio eq 'standard') {
|
|
||||||
if (
|
|
||||||
none { $_ eq $options->{variant} }
|
|
||||||
('important', 'required', 'buildd', 'minbase')
|
|
||||||
) {
|
|
||||||
$pkgs_to_install{$pkgname} = ();
|
|
||||||
if ($suite_matches) {
|
|
||||||
$pkgs_to_install_target{$pkgname} = ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elsif ($prio eq 'important') {
|
|
||||||
if (
|
|
||||||
none { $_ eq $options->{variant} }
|
|
||||||
('required', 'buildd', 'minbase')
|
|
||||||
) {
|
|
||||||
$pkgs_to_install{$pkgname} = ();
|
|
||||||
if ($suite_matches) {
|
|
||||||
$pkgs_to_install_target{$pkgname} = ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elsif ($prio eq 'required') {
|
|
||||||
# required packages are part of all sets except
|
|
||||||
# essential and apt
|
|
||||||
$pkgs_to_install{$pkgname} = ();
|
|
||||||
if ($suite_matches) {
|
|
||||||
$pkgs_to_install_target{$pkgname} = ();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error "unknown priority: $prio";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
error "unknown variant: $options->{variant}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# reset values
|
|
||||||
undef $pkgname;
|
|
||||||
$ess = '';
|
|
||||||
$prio = 'optional';
|
|
||||||
$arch = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
close $pipe_cat;
|
|
||||||
$? == 0 or error "apt-helper cat-file failed: $?";
|
|
||||||
}
|
|
||||||
close $pipe_apt;
|
|
||||||
$? == 0 or error "apt-get indextargets failed: $?";
|
|
||||||
|
|
||||||
# We now have two package sets, %pkgs_to_install and
|
|
||||||
# %pkgs_to_install_target, where the latter was only filled if the
|
|
||||||
# suite matched the codename or the suite name of one of the given
|
|
||||||
# apt indices.
|
|
||||||
# We only need to bother with this distinction if one or more of the
|
|
||||||
# indices matched and one or more of the indices mismatched. If either
|
|
||||||
# nothing matched or all matched, then we can just use %pkgs_to_install
|
|
||||||
if ( defined $options->{suite}
|
|
||||||
and $num_suite_matches > 0
|
|
||||||
and $num_suite_mismatch > 0) {
|
|
||||||
# Now we know that some matched and some didn't. But we only
|
|
||||||
# replace the results from all indices with the results from those
|
|
||||||
# indices that matched if the results are actually different and
|
|
||||||
# if there is more than zero packages from the indices that matched
|
|
||||||
if (scalar keys %ess_pkgs_target > 0
|
|
||||||
and keys %ess_pkgs != %ess_pkgs_target) {
|
|
||||||
info( "multiple sources defined, using those matching "
|
|
||||||
. "'$options->{suite}' to find essential packages");
|
|
||||||
%ess_pkgs = %ess_pkgs_target;
|
|
||||||
}
|
|
||||||
if (scalar keys %pkgs_to_install_target > 0
|
|
||||||
and keys %pkgs_to_install != keys %pkgs_to_install_target) {
|
|
||||||
if ($options->{variant} eq 'essential') {
|
|
||||||
error "logic error";
|
|
||||||
} elsif (
|
|
||||||
any { $_ eq $options->{variant} }
|
|
||||||
('standard', 'important', 'required', 'buildd', 'minbase')
|
|
||||||
) {
|
|
||||||
info( "multiple sources defined -- using those matching "
|
|
||||||
. "'$options->{suite}' to find packages for variant "
|
|
||||||
. "'$options->{variant}'");
|
|
||||||
%pkgs_to_install = %pkgs_to_install_target;
|
|
||||||
} else {
|
|
||||||
error "unknown variant: $options->{variant}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug "Identified the following Essential:yes packages:";
|
|
||||||
foreach my $pkg (sort keys %ess_pkgs) {
|
|
||||||
debug " $pkg";
|
|
||||||
}
|
|
||||||
|
|
||||||
my %result = ();
|
|
||||||
if ($options->{dryrun}) {
|
|
||||||
info "simulate downloading packages with apt...";
|
|
||||||
} else {
|
|
||||||
# if there are already packages in /var/cache/apt/archives/, we
|
|
||||||
# need to use our proxysolver to obtain the solution chosen by apt
|
|
||||||
if (scalar @cached_debs > 0) {
|
|
||||||
$result{EDSP_RES} = \@dl_debs;
|
|
||||||
}
|
|
||||||
info "downloading packages with apt...";
|
|
||||||
}
|
|
||||||
run_apt_progress({
|
|
||||||
ARGV => [
|
|
||||||
'apt-get',
|
|
||||||
'--yes',
|
|
||||||
'-oApt::Get::Download-Only=true',
|
|
||||||
$options->{dryrun} ? '-oAPT::Get::Simulate=true' : (),
|
|
||||||
'install'
|
|
||||||
],
|
|
||||||
PKGS => [keys %ess_pkgs],
|
|
||||||
%result
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
error "unknown variant: $options->{variant}";
|
error "unknown variant: $options->{variant}";
|
||||||
}
|
}
|
||||||
|
@ -2433,7 +2228,7 @@ sub run_download() {
|
||||||
# list before returning it.
|
# list before returning it.
|
||||||
@essential_pkgs = sort @essential_pkgs;
|
@essential_pkgs = sort @essential_pkgs;
|
||||||
|
|
||||||
return ([keys %pkgs_to_install], \@essential_pkgs, \@cached_debs);
|
return (\@essential_pkgs, \@cached_debs);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub run_extract() {
|
sub run_extract() {
|
||||||
|
@ -2876,11 +2671,50 @@ sub run_essential() {
|
||||||
|
|
||||||
sub run_install() {
|
sub run_install() {
|
||||||
my $options = shift;
|
my $options = shift;
|
||||||
my $pkgs_to_install = shift;
|
|
||||||
my $chrootcmd = shift;
|
my $chrootcmd = shift;
|
||||||
|
|
||||||
|
my %pkgs_to_install;
|
||||||
|
for my $incl (@{ $options->{include} }) {
|
||||||
|
for my $pkg (split /[,\s]+/, $incl) {
|
||||||
|
# strip leading and trailing whitespace
|
||||||
|
$pkg =~ s/^\s+|\s+$//g;
|
||||||
|
# skip if the remainder is an empty string
|
||||||
|
if ($pkg eq '') {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$pkgs_to_install{$pkg} = ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($options->{variant} eq 'buildd') {
|
||||||
|
$pkgs_to_install{'build-essential'} = ();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
any { $_ eq $options->{variant} }
|
||||||
|
('required', 'important', 'standard', 'buildd')
|
||||||
|
) {
|
||||||
|
my $priority;
|
||||||
|
if (any { $_ eq $options->{variant} } ('required', 'buildd')) {
|
||||||
|
$priority = '?priority(required)';
|
||||||
|
} elsif ($options->{variant} eq 'important') {
|
||||||
|
$priority = '?or(?priority(required),?priority(important))';
|
||||||
|
} elsif ($options->{variant} eq 'standard') {
|
||||||
|
$priority = '?or(~prequired,~pimportant,~pstandard)';
|
||||||
|
}
|
||||||
|
$pkgs_to_install{
|
||||||
|
"?narrow("
|
||||||
|
. (
|
||||||
|
length($options->{suite})
|
||||||
|
? '?archive(' . $options->{suite} . '),'
|
||||||
|
: ''
|
||||||
|
)
|
||||||
|
. "?architecture($options->{nativearch}),"
|
||||||
|
. "$priority)"
|
||||||
|
} = ();
|
||||||
|
}
|
||||||
|
my @pkgs_to_install = keys %pkgs_to_install;
|
||||||
|
|
||||||
if ($options->{mode} eq 'chrootless') {
|
if ($options->{mode} eq 'chrootless') {
|
||||||
if (scalar @{$pkgs_to_install} > 0) {
|
if (scalar @pkgs_to_install > 0) {
|
||||||
my @chrootless_opts = (
|
my @chrootless_opts = (
|
||||||
'-oDPkg::Options::=--force-not-root',
|
'-oDPkg::Options::=--force-not-root',
|
||||||
'-oDPkg::Options::=--force-script-chrootless',
|
'-oDPkg::Options::=--force-script-chrootless',
|
||||||
|
@ -2891,7 +2725,7 @@ sub run_install() {
|
||||||
);
|
);
|
||||||
run_apt_progress({
|
run_apt_progress({
|
||||||
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||||
PKGS => $pkgs_to_install,
|
PKGS => [@pkgs_to_install],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} elsif (
|
} elsif (
|
||||||
|
@ -2899,7 +2733,7 @@ sub run_install() {
|
||||||
('root', 'unshare', 'fakechroot', 'proot')
|
('root', 'unshare', 'fakechroot', 'proot')
|
||||||
) {
|
) {
|
||||||
if ($options->{variant} ne 'custom'
|
if ($options->{variant} ne 'custom'
|
||||||
and scalar @{$pkgs_to_install} > 0) {
|
and scalar @pkgs_to_install > 0) {
|
||||||
# Advantage of running apt on the outside instead of inside the
|
# Advantage of running apt on the outside instead of inside the
|
||||||
# chroot:
|
# chroot:
|
||||||
#
|
#
|
||||||
|
@ -2945,7 +2779,7 @@ sub run_install() {
|
||||||
'--yes',
|
'--yes',
|
||||||
'install'
|
'install'
|
||||||
],
|
],
|
||||||
PKGS => $pkgs_to_install,
|
PKGS => [@pkgs_to_install],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
$options
|
$options
|
||||||
|
@ -2958,7 +2792,7 @@ sub run_install() {
|
||||||
'apt-get', '--yes',
|
'apt-get', '--yes',
|
||||||
'-oAPT::Get::Simulate=true', 'install'
|
'-oAPT::Get::Simulate=true', 'install'
|
||||||
],
|
],
|
||||||
PKGS => $pkgs_to_install,
|
PKGS => [@pkgs_to_install],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3960,6 +3794,9 @@ sub get_keyring_by_suite {
|
||||||
|
|
||||||
my $debianvendor;
|
my $debianvendor;
|
||||||
my $ubuntuvendor;
|
my $ubuntuvendor;
|
||||||
|
# make $@ local, so we don't print "Can't locate Dpkg/Vendor/Debian.pm"
|
||||||
|
# in other parts where we evaluate $@
|
||||||
|
local $@ = '';
|
||||||
eval {
|
eval {
|
||||||
require Dpkg::Vendor::Debian;
|
require Dpkg::Vendor::Debian;
|
||||||
require Dpkg::Vendor::Ubuntu;
|
require Dpkg::Vendor::Ubuntu;
|
||||||
|
@ -4079,6 +3916,9 @@ sub get_sourceslist_by_suite {
|
||||||
# https://lists.debian.org/87r26wqr2a.fsf@43-1.org
|
# https://lists.debian.org/87r26wqr2a.fsf@43-1.org
|
||||||
my $bullseye_or_later = 0;
|
my $bullseye_or_later = 0;
|
||||||
my $distro_info = '/usr/share/distro-info/debian.csv';
|
my $distro_info = '/usr/share/distro-info/debian.csv';
|
||||||
|
# make $@ local, so we don't print "Can't locate Debian/DistroInfo.pm"
|
||||||
|
# in other parts where we evaluate $@
|
||||||
|
local $@ = '';
|
||||||
eval { require Debian::DistroInfo; };
|
eval { require Debian::DistroInfo; };
|
||||||
if (!$@) {
|
if (!$@) {
|
||||||
# libdistro-info-perl is installed
|
# libdistro-info-perl is installed
|
||||||
|
@ -4307,7 +4147,18 @@ sub main() {
|
||||||
'version' => sub { print STDOUT "mmdebstrap $VERSION\n"; exit 0; },
|
'version' => sub { print STDOUT "mmdebstrap $VERSION\n"; exit 0; },
|
||||||
'components=s@' => \$options->{components},
|
'components=s@' => \$options->{components},
|
||||||
'variant=s' => \$options->{variant},
|
'variant=s' => \$options->{variant},
|
||||||
'include=s@' => \$options->{include},
|
'include=s' => sub {
|
||||||
|
my ($opt_name, $opt_value) = @_;
|
||||||
|
for my $pkg (split /[,\s]+/, $opt_value) {
|
||||||
|
# strip leading and trailing whitespace
|
||||||
|
$pkg =~ s/^\s+|\s+$//g;
|
||||||
|
# skip if the remainder is an empty string
|
||||||
|
if ($pkg eq '') {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
push @{ $options->{include} }, $pkg;
|
||||||
|
}
|
||||||
|
},
|
||||||
'architectures=s@' => \$options->{architectures},
|
'architectures=s@' => \$options->{architectures},
|
||||||
'mode=s' => \$options->{mode},
|
'mode=s' => \$options->{mode},
|
||||||
'dpkgopt=s@' => \$options->{dpkgopts},
|
'dpkgopt=s@' => \$options->{dpkgopts},
|
||||||
|
@ -4430,6 +4281,10 @@ sub main() {
|
||||||
if (any { $_ eq $options->{variant} } ('-', 'debootstrap')) {
|
if (any { $_ eq $options->{variant} } ('-', 'debootstrap')) {
|
||||||
$options->{variant} = 'important';
|
$options->{variant} = 'important';
|
||||||
}
|
}
|
||||||
|
# minbase is an alias for required
|
||||||
|
if ($options->{variant} eq 'minbase') {
|
||||||
|
$options->{variant} = 'required';
|
||||||
|
}
|
||||||
|
|
||||||
# fakeroot is an alias for fakechroot
|
# fakeroot is an alias for fakechroot
|
||||||
if ($options->{mode} eq 'fakeroot') {
|
if ($options->{mode} eq 'fakeroot') {
|
||||||
|
@ -4498,7 +4353,7 @@ sub main() {
|
||||||
# the --robot option was introduced in 1.20.0 but until 1.20.2 the
|
# the --robot option was introduced in 1.20.0 but until 1.20.2 the
|
||||||
# output contained a string after the version, separated by a
|
# output contained a string after the version, separated by a
|
||||||
# whitespace -- since then, it's only the version
|
# whitespace -- since then, it's only the version
|
||||||
if ($? == 0 and $content =~ /^([0-9.]+)( .*)?$/) {
|
if ($? == 0 and $content =~ /^([0-9.]+).*$/) {
|
||||||
# dpkg is new enough for the --robot option
|
# dpkg is new enough for the --robot option
|
||||||
$dpkgversion = version->new($1);
|
$dpkgversion = version->new($1);
|
||||||
}
|
}
|
||||||
|
@ -4519,8 +4374,8 @@ sub main() {
|
||||||
and $content =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/m) {
|
and $content =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/m) {
|
||||||
$aptversion = version->new($1);
|
$aptversion = version->new($1);
|
||||||
}
|
}
|
||||||
if ($aptversion < "2.3.7") {
|
if ($aptversion < "2.3.10") {
|
||||||
error "need apt >= 2.3.7 but have $aptversion";
|
error "need apt >= 2.3.10 but have $aptversion";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6152,9 +6007,9 @@ option depends on the selected variant. The B<extract> and B<custom> variants
|
||||||
install no packages by default, so for these variants, the packages specified
|
install no packages by default, so for these variants, the packages specified
|
||||||
by this option will be the only ones that get either extracted or installed by
|
by this option will be the only ones that get either extracted or installed by
|
||||||
dpkg, respectively. For all other variants, apt is used to install the
|
dpkg, respectively. For all other variants, apt is used to install the
|
||||||
additional packages. Package names are directly passed to
|
additional packages. Package names are directly passed to apt and thus, you
|
||||||
apt and thus, you can use apt features like C<pkg/suite>, C<pkg=version>,
|
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
||||||
C<pkg-> or use a glob or regex for C<pkg>. See apt(8) for the supported
|
regex for C<pkg> or use apt patterns. See apt(8) for the supported
|
||||||
syntax. The option can be specified multiple times and the packages are
|
syntax. The option can be specified multiple times and the packages are
|
||||||
concatenated in the order in which they are given on the command line. If
|
concatenated in the order in which they are given on the command line. If
|
||||||
later list items are repeated, then they get dropped so that the resulting
|
later list items are repeated, then they get dropped so that the resulting
|
||||||
|
@ -6461,8 +6316,10 @@ All package sets also include the direct and indirect hard dependencies (but
|
||||||
not recommends) of the selected package sets. The variants B<minbase>,
|
not recommends) of the selected package sets. The variants B<minbase>,
|
||||||
B<buildd> and B<->, resemble the package sets that debootstrap would install
|
B<buildd> and B<->, resemble the package sets that debootstrap would install
|
||||||
with the same I<--variant> argument. The release with a name matching the
|
with the same I<--variant> argument. The release with a name matching the
|
||||||
I<SUITE> argument will be used to determine the C<Essential:yes> and priority
|
I<SUITE> argument as well as the native architecture will be used to determine
|
||||||
values.
|
the C<Essential:yes> and priority values. To select packages with matching
|
||||||
|
priority from any suite, specify the empty string for I<SUITE>. The default
|
||||||
|
variant is B<debootstrap>.
|
||||||
|
|
||||||
=over 8
|
=over 8
|
||||||
|
|
||||||
|
@ -6489,19 +6346,30 @@ The B<essential> set plus apt.
|
||||||
=item B<required>, B<minbase>
|
=item B<required>, B<minbase>
|
||||||
|
|
||||||
The B<essential> set plus all packages with Priority:required and apt.
|
The B<essential> set plus all packages with Priority:required and apt.
|
||||||
|
It is roughly equivalent to running mmdebstrap with
|
||||||
|
|
||||||
|
--variant=essential --include="?priority(required)"
|
||||||
|
|
||||||
=item B<buildd>
|
=item B<buildd>
|
||||||
|
|
||||||
The B<minbase> set plus build-essential.
|
The B<minbase> set plus build-essential.
|
||||||
|
It is roughly equivalent to running mmdebstrap with
|
||||||
|
|
||||||
|
--variant=essential --include="?priority(required),build-essential"
|
||||||
|
|
||||||
=item B<important>, B<debootstrap>, B<->
|
=item B<important>, B<debootstrap>, B<->
|
||||||
|
|
||||||
The B<required> set plus all packages with Priority:important. This is the
|
The B<required> set plus all packages with Priority:important. This is the
|
||||||
default of debootstrap.
|
default of debootstrap. It is roughly equivalent to running mmdebstrap with
|
||||||
|
|
||||||
|
--variant=essential --include="~prequired|~pimportant"
|
||||||
|
|
||||||
=item B<standard>
|
=item B<standard>
|
||||||
|
|
||||||
The B<important> set plus all packages with Priority:standard.
|
The B<important> set plus all packages with Priority:standard.
|
||||||
|
It is roughly equivalent to running mmdebstrap with
|
||||||
|
|
||||||
|
--variant=essential --include="~prequired|~pimportant|~pstandard"
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
@ -6979,6 +6847,17 @@ Create a system that can be used with podman:
|
||||||
root
|
root
|
||||||
$ podman rmi debian
|
$ podman rmi debian
|
||||||
|
|
||||||
|
As a docker/podman replacement:
|
||||||
|
|
||||||
|
$ mmdebstrap unstable | mmtarfilter --path-exclude='/dev/*' > chroot.tar
|
||||||
|
[...]
|
||||||
|
$ mmdebstrap --variant=custom --skip=update \
|
||||||
|
--setup-hook='tar-in chroot.tar /' \
|
||||||
|
--customize-hook='chroot "$1" whoami' unstable /dev/null
|
||||||
|
[...]
|
||||||
|
root
|
||||||
|
$ rm chroot.tar
|
||||||
|
|
||||||
=head1 ENVIRONMENT VARIABLES
|
=head1 ENVIRONMENT VARIABLES
|
||||||
|
|
||||||
=over 8
|
=over 8
|
||||||
|
|
Loading…
Reference in a new issue