forked from josch/mmdebstrap
Compare commits
1 commit
e4e10b670c
...
444b3b6fec
Author | SHA1 | Date | |
---|---|---|---|
444b3b6fec |
3 changed files with 366 additions and 149 deletions
123
coverage.sh
123
coverage.sh
|
@ -127,7 +127,7 @@ if [ ! -e shared/hooks/eatmydata/customize.sh ] || [ hooks/eatmydata/customize.s
|
|||
fi
|
||||
fi
|
||||
starttime=
|
||||
total=177
|
||||
total=213
|
||||
skipped=0
|
||||
runtests=0
|
||||
i=1
|
||||
|
@ -2141,10 +2141,6 @@ tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort > tar2.txt
|
|||
ppc64el)
|
||||
echo ./lib64;
|
||||
;;
|
||||
s390x)
|
||||
echo ./lib32;
|
||||
echo ./usr/lib32/;
|
||||
;;
|
||||
esac
|
||||
} | sort -u | diff -u - tar2.txt
|
||||
rm -r /tmp/debian-chroot
|
||||
|
@ -3080,6 +3076,123 @@ END
|
|||
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
|
||||
for mode in root unshare fakechroot proot chrootless; do
|
||||
print_header "mode=$mode,variant=extract: unpack doc-debian"
|
||||
|
|
|
@ -224,9 +224,6 @@ Apt::Get::Download-Only true;
|
|||
Acquire::Languages "none";
|
||||
Dir::Etc::Trusted "/etc/apt/trusted.gpg";
|
||||
Dir::Etc::TrustedParts "/etc/apt/trusted.gpg.d";
|
||||
Acquire::http::Dl-Limit "1000";
|
||||
Acquire::https::Dl-Limit "1000";
|
||||
Acquire::Retries "5";
|
||||
END
|
||||
|
||||
> "$rootdir/var/lib/dpkg/status"
|
||||
|
@ -469,17 +466,6 @@ cleanuptmpdir() {
|
|||
export SOURCE_DATE_EPOCH=$(date --date="$(grep-dctrl -s Date -n '' "$newmirrordir/dists/$DEFAULT_DIST/Release")" +%s)
|
||||
|
||||
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
|
||||
# leak into the chroot with chrootless mode.
|
||||
# We do not use our own package cache here because
|
||||
|
@ -521,9 +507,6 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
|||
arches=$HOSTARCH
|
||||
fi
|
||||
$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"
|
||||
|
||||
cat << END > "$tmpdir/extlinux.conf"
|
||||
|
@ -557,7 +540,7 @@ END
|
|||
cat << 'END' > "$tmpdir/worker.sh"
|
||||
#!/bin/sh
|
||||
echo 'root:root' | chpasswd
|
||||
mount -t 9p -o trans=virtio,access=any,msize=128k mmdebstrap /mnt
|
||||
mount -t 9p -o trans=virtio,access=any mmdebstrap /mnt
|
||||
# need to restart mini-httpd because we mounted different content into www-root
|
||||
systemctl restart mini-httpd
|
||||
|
||||
|
|
373
mmdebstrap
373
mmdebstrap
|
@ -1510,7 +1510,8 @@ sub setup {
|
|||
run_update($options);
|
||||
}
|
||||
|
||||
(my $essential_pkgs, my $cached_debs) = run_download($options);
|
||||
(my $pkgs_to_install, my $essential_pkgs, my $cached_debs)
|
||||
= run_download($options);
|
||||
|
||||
# in theory, we don't have to extract the packages in chrootless mode
|
||||
# but we do it anyways because otherwise directory creation timestamps
|
||||
|
@ -1532,7 +1533,7 @@ sub setup {
|
|||
|
||||
run_hooks('essential', $options);
|
||||
|
||||
run_install($options, $chrootcmd);
|
||||
run_install($options, $pkgs_to_install, $chrootcmd);
|
||||
|
||||
run_hooks('customize', $options);
|
||||
}
|
||||
|
@ -1991,6 +1992,22 @@ sub run_update() {
|
|||
sub run_download() {
|
||||
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
|
||||
# to install. That's why the directory must be empty if:
|
||||
# - /var/cache/apt/archives exists, and
|
||||
|
@ -2014,7 +2031,7 @@ sub run_download() {
|
|||
if (
|
||||
!$options->{dryrun}
|
||||
&& ((none { $_ eq $options->{variant} } ('extract', 'custom'))
|
||||
|| scalar @{ $options->{include} } != 0)
|
||||
|| scalar keys %pkgs_to_install != 0)
|
||||
&& -d "$options->{root}/var/cache/apt/archives/"
|
||||
) {
|
||||
my $apt_archives = "/var/cache/apt/archives/";
|
||||
|
@ -2047,22 +2064,10 @@ sub run_download() {
|
|||
# (essential variant) then we have to compute the package set ourselves.
|
||||
# Same if we want to install priority based variants.
|
||||
if (any { $_ eq $options->{variant} } ('extract', 'custom')) {
|
||||
if (scalar @{ $options->{include} } == 0) {
|
||||
if (scalar keys %pkgs_to_install == 0) {
|
||||
info "nothing to download -- skipping...";
|
||||
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 = ();
|
||||
if ($options->{dryrun}) {
|
||||
|
@ -2121,10 +2126,7 @@ sub run_download() {
|
|||
],
|
||||
%result
|
||||
});
|
||||
} elsif (
|
||||
any { $_ eq $options->{variant} }
|
||||
('essential', 'standard', 'important', 'required', 'buildd')
|
||||
) {
|
||||
} elsif ($options->{variant} eq 'essential') {
|
||||
# 2021-06-07, #debian-apt on OFTC, times in UTC+2
|
||||
# 17:27 < DonKult> (?essential includes 'apt' through)
|
||||
# 17:30 < josch> DonKult: no, because pkgCacheGen::ForceEssential ",";
|
||||
|
@ -2149,7 +2151,7 @@ sub run_download() {
|
|||
'install',
|
||||
'?narrow('
|
||||
. (
|
||||
length($options->{suite})
|
||||
defined($options->{suite})
|
||||
? '?archive(' . $options->{suite} . '),'
|
||||
: ''
|
||||
)
|
||||
|
@ -2159,6 +2161,209 @@ sub run_download() {
|
|||
],
|
||||
%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 {
|
||||
error "unknown variant: $options->{variant}";
|
||||
}
|
||||
|
@ -2228,7 +2433,7 @@ sub run_download() {
|
|||
# list before returning it.
|
||||
@essential_pkgs = sort @essential_pkgs;
|
||||
|
||||
return (\@essential_pkgs, \@cached_debs);
|
||||
return ([keys %pkgs_to_install], \@essential_pkgs, \@cached_debs);
|
||||
}
|
||||
|
||||
sub run_extract() {
|
||||
|
@ -2670,51 +2875,12 @@ sub run_essential() {
|
|||
}
|
||||
|
||||
sub run_install() {
|
||||
my $options = 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;
|
||||
my $options = shift;
|
||||
my $pkgs_to_install = shift;
|
||||
my $chrootcmd = shift;
|
||||
|
||||
if ($options->{mode} eq 'chrootless') {
|
||||
if (scalar @pkgs_to_install > 0) {
|
||||
if (scalar @{$pkgs_to_install} > 0) {
|
||||
my @chrootless_opts = (
|
||||
'-oDPkg::Options::=--force-not-root',
|
||||
'-oDPkg::Options::=--force-script-chrootless',
|
||||
|
@ -2725,7 +2891,7 @@ sub run_install() {
|
|||
);
|
||||
run_apt_progress({
|
||||
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||
PKGS => [@pkgs_to_install],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
}
|
||||
} elsif (
|
||||
|
@ -2733,7 +2899,7 @@ sub run_install() {
|
|||
('root', 'unshare', 'fakechroot', 'proot')
|
||||
) {
|
||||
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
|
||||
# chroot:
|
||||
#
|
||||
|
@ -2779,7 +2945,7 @@ sub run_install() {
|
|||
'--yes',
|
||||
'install'
|
||||
],
|
||||
PKGS => [@pkgs_to_install],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
},
|
||||
$options
|
||||
|
@ -2792,7 +2958,7 @@ sub run_install() {
|
|||
'apt-get', '--yes',
|
||||
'-oAPT::Get::Simulate=true', 'install'
|
||||
],
|
||||
PKGS => [@pkgs_to_install],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3794,9 +3960,6 @@ sub get_keyring_by_suite {
|
|||
|
||||
my $debianvendor;
|
||||
my $ubuntuvendor;
|
||||
# make $@ local, so we don't print "Can't locate Dpkg/Vendor/Debian.pm"
|
||||
# in other parts where we evaluate $@
|
||||
local $@ = '';
|
||||
eval {
|
||||
require Dpkg::Vendor::Debian;
|
||||
require Dpkg::Vendor::Ubuntu;
|
||||
|
@ -3916,9 +4079,6 @@ sub get_sourceslist_by_suite {
|
|||
# https://lists.debian.org/87r26wqr2a.fsf@43-1.org
|
||||
my $bullseye_or_later = 0;
|
||||
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; };
|
||||
if (!$@) {
|
||||
# libdistro-info-perl is installed
|
||||
|
@ -4145,20 +4305,9 @@ sub main() {
|
|||
'h|help' => sub { pod2usage(-exitval => 0, -verbose => 1) },
|
||||
'man' => sub { pod2usage(-exitval => 0, -verbose => 2) },
|
||||
'version' => sub { print STDOUT "mmdebstrap $VERSION\n"; exit 0; },
|
||||
'components=s@' => \$options->{components},
|
||||
'variant=s' => \$options->{variant},
|
||||
'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;
|
||||
}
|
||||
},
|
||||
'components=s@' => \$options->{components},
|
||||
'variant=s' => \$options->{variant},
|
||||
'include=s@' => \$options->{include},
|
||||
'architectures=s@' => \$options->{architectures},
|
||||
'mode=s' => \$options->{mode},
|
||||
'dpkgopt=s@' => \$options->{dpkgopts},
|
||||
|
@ -4281,10 +4430,6 @@ sub main() {
|
|||
if (any { $_ eq $options->{variant} } ('-', 'debootstrap')) {
|
||||
$options->{variant} = 'important';
|
||||
}
|
||||
# minbase is an alias for required
|
||||
if ($options->{variant} eq 'minbase') {
|
||||
$options->{variant} = 'required';
|
||||
}
|
||||
|
||||
# fakeroot is an alias for fakechroot
|
||||
if ($options->{mode} eq 'fakeroot') {
|
||||
|
@ -4353,7 +4498,7 @@ sub main() {
|
|||
# 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
|
||||
# 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
|
||||
$dpkgversion = version->new($1);
|
||||
}
|
||||
|
@ -4374,8 +4519,8 @@ sub main() {
|
|||
and $content =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+) \([a-z0-9-]+\)$/m) {
|
||||
$aptversion = version->new($1);
|
||||
}
|
||||
if ($aptversion < "2.3.10") {
|
||||
error "need apt >= 2.3.10 but have $aptversion";
|
||||
if ($aptversion < "2.3.7") {
|
||||
error "need apt >= 2.3.7 but have $aptversion";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6007,9 +6152,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
|
||||
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
|
||||
additional packages. Package names are directly passed to apt and thus, you
|
||||
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
||||
regex for C<pkg> or use apt patterns. See apt(8) for the supported
|
||||
additional packages. Package names are directly passed to
|
||||
apt and thus, you can use apt features like C<pkg/suite>, C<pkg=version>,
|
||||
C<pkg-> or use a glob or regex for C<pkg>. See apt(8) for the supported
|
||||
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
|
||||
later list items are repeated, then they get dropped so that the resulting
|
||||
|
@ -6316,10 +6461,8 @@ All package sets also include the direct and indirect hard dependencies (but
|
|||
not recommends) of the selected package sets. The variants B<minbase>,
|
||||
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
|
||||
I<SUITE> argument as well as the native architecture will be used to determine
|
||||
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>.
|
||||
I<SUITE> argument will be used to determine the C<Essential:yes> and priority
|
||||
values.
|
||||
|
||||
=over 8
|
||||
|
||||
|
@ -6346,30 +6489,19 @@ The B<essential> set plus apt.
|
|||
=item B<required>, B<minbase>
|
||||
|
||||
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>
|
||||
|
||||
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<->
|
||||
|
||||
The B<required> set plus all packages with Priority:important. This is the
|
||||
default of debootstrap. It is roughly equivalent to running mmdebstrap with
|
||||
|
||||
--variant=essential --include="~prequired|~pimportant"
|
||||
default of debootstrap.
|
||||
|
||||
=item B<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
|
||||
|
||||
|
@ -6847,17 +6979,6 @@ Create a system that can be used with podman:
|
|||
root
|
||||
$ 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
|
||||
|
||||
=over 8
|
||||
|
|
Loading…
Reference in a new issue