forked from josch/mmdebstrap
split up setup() into multiple functions
This commit is contained in:
parent
895c388ede
commit
1076e9a78d
1 changed files with 516 additions and 467 deletions
313
mmdebstrap
313
mmdebstrap
|
@ -1191,6 +1191,49 @@ sub setup {
|
|||
warning "cannot read $options->{apttrustedparts}";
|
||||
}
|
||||
|
||||
run_setup($options);
|
||||
|
||||
run_hooks('setup', $options);
|
||||
|
||||
run_update($options);
|
||||
|
||||
(my $pkgs_to_install, my $essential_pkgs) = run_download($options);
|
||||
|
||||
if ( $options->{mode} ne 'chrootless'
|
||||
or $options->{variant} eq 'extract') {
|
||||
# We have to extract the packages from @essential_pkgs either if we run
|
||||
# in chrootless mode and extract variant or in any other mode. In
|
||||
# other words, the only scenario in which the @essential_pkgs are not
|
||||
# extracted are in chrootless mode in any other than the extract
|
||||
# variant.
|
||||
run_extract($options, $essential_pkgs);
|
||||
}
|
||||
|
||||
run_hooks('extract', $options);
|
||||
|
||||
if ($options->{variant} ne 'extract') {
|
||||
my $chrootcmd = [];
|
||||
if ($options->{mode} ne 'chrootless') {
|
||||
$chrootcmd = run_prepare($options);
|
||||
}
|
||||
|
||||
run_essential($options, $essential_pkgs, $chrootcmd);
|
||||
|
||||
run_hooks('essential', $options);
|
||||
|
||||
run_install($options, $pkgs_to_install, $chrootcmd);
|
||||
|
||||
run_hooks('customize', $options);
|
||||
}
|
||||
|
||||
run_cleanup($options);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_setup() {
|
||||
my $options = shift;
|
||||
|
||||
{
|
||||
my @directories = (
|
||||
'/etc/apt/apt.conf.d', '/etc/apt/sources.list.d',
|
||||
|
@ -1580,8 +1623,11 @@ sub setup {
|
|||
$ENV{PATH} = "/usr/sbin:/usr/bin:/sbin:/bin";
|
||||
}
|
||||
|
||||
# run setup hooks
|
||||
run_hooks('setup', $options);
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_update() {
|
||||
my $options = shift;
|
||||
|
||||
info "running apt-get update...";
|
||||
run_apt_progress({
|
||||
|
@ -1607,6 +1653,12 @@ sub setup {
|
|||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_download() {
|
||||
my $options = shift;
|
||||
|
||||
my @pkgs_to_install;
|
||||
for my $incl (@{ $options->{include} }) {
|
||||
for my $pkg (split /[,\s]+/, $incl) {
|
||||
|
@ -1827,21 +1879,23 @@ sub setup {
|
|||
}
|
||||
}
|
||||
|
||||
# We have to extract the packages from @essential_pkgs either if we run in
|
||||
# chrootless mode and extract variant or in any other mode.
|
||||
# In other words, the only scenario in which the @essential_pkgs are not
|
||||
# extracted are in chrootless mode in any other than the extract variant.
|
||||
if ( $options->{mode} eq 'chrootless'
|
||||
and $options->{variant} ne 'extract') {
|
||||
# nothing to do
|
||||
} elsif ($options->{dryrun}) {
|
||||
return (\@pkgs_to_install, \@essential_pkgs);
|
||||
}
|
||||
|
||||
sub run_extract() {
|
||||
my $options = shift;
|
||||
my $essential_pkgs = shift;
|
||||
|
||||
if ($options->{dryrun}) {
|
||||
info "skip extracting packages because of --dry-run";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
info "extracting archives...";
|
||||
print_progress 0.0;
|
||||
my $counter = 0;
|
||||
my $total = scalar @essential_pkgs;
|
||||
foreach my $deb (@essential_pkgs) {
|
||||
my $total = scalar @{$essential_pkgs};
|
||||
foreach my $deb (@{$essential_pkgs}) {
|
||||
$counter += 1;
|
||||
# not using dpkg-deb --extract as that would replace the
|
||||
# merged-usr symlinks with plain directories
|
||||
|
@ -1869,81 +1923,13 @@ sub setup {
|
|||
print_progress($counter / $total * 100);
|
||||
}
|
||||
print_progress "done";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
run_hooks('extract', $options);
|
||||
sub run_prepare {
|
||||
my $options = shift;
|
||||
|
||||
if ($options->{mode} eq 'chrootless') {
|
||||
if ($options->{dryrun}) {
|
||||
info "simulate installing packages...";
|
||||
} else {
|
||||
info "installing packages...";
|
||||
}
|
||||
# FIXME: the dpkg config from the host is parsed before the command
|
||||
# line arguments are parsed and might break this mode
|
||||
# Example: if the host has --path-exclude set, then this will also
|
||||
# affect the chroot.
|
||||
my @chrootless_opts = (
|
||||
'-oDPkg::Options::=--force-not-root',
|
||||
'-oDPkg::Options::=--force-script-chrootless',
|
||||
'-oDPkg::Options::=--root=' . $options->{root},
|
||||
'-oDPkg::Options::=--log=' . "$options->{root}/var/log/dpkg.log",
|
||||
$options->{dryrun} ? '-oAPT::Get::Simulate=true' : (),
|
||||
);
|
||||
if (defined $options->{qemu}) {
|
||||
# The binfmt support on the outside is used, so qemu needs to know
|
||||
# where it has to look for shared libraries
|
||||
if (defined $ENV{QEMU_LD_PREFIX}
|
||||
&& $ENV{QEMU_LD_PREFIX} ne "") {
|
||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||
$ENV{QEMU_LD_PREFIX} = "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
||||
} else {
|
||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||
$ENV{QEMU_LD_PREFIX} = $options->{root};
|
||||
}
|
||||
}
|
||||
if ($options->{variant} eq 'extract') {
|
||||
# nothing to do
|
||||
} else {
|
||||
run_apt_progress({
|
||||
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||
PKGS => [map { "$options->{root}/$_" } @essential_pkgs],
|
||||
});
|
||||
}
|
||||
if (any { $_ eq $options->{variant} } ('extract', 'custom')) {
|
||||
# nothing to do
|
||||
} elsif (
|
||||
any { $_ eq $options->{variant} } (
|
||||
'essential', 'apt', 'standard', 'important',
|
||||
'required', 'buildd', 'minbase'
|
||||
)
|
||||
) {
|
||||
# run essential hooks
|
||||
run_hooks('essential', $options);
|
||||
|
||||
if (scalar @pkgs_to_install > 0) {
|
||||
run_apt_progress({
|
||||
ARGV =>
|
||||
['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||
PKGS => [@pkgs_to_install],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
error "unknown variant: $options->{variant}";
|
||||
}
|
||||
} elsif (
|
||||
any { $_ eq $options->{mode} }
|
||||
('root', 'unshare', 'fakechroot', 'proot')
|
||||
) {
|
||||
|
||||
if (any { $_ eq $options->{variant} } ('extract')) {
|
||||
# nothing to do
|
||||
} elsif (
|
||||
any { $_ eq $options->{variant} } (
|
||||
'custom', 'essential', 'apt', 'standard',
|
||||
'important', 'required', 'buildd', 'minbase'
|
||||
)
|
||||
) {
|
||||
if ($options->{mode} eq 'fakechroot') {
|
||||
# this borrows from and extends
|
||||
# /etc/fakechroot/debootstrap.env and
|
||||
|
@ -1951,18 +1937,15 @@ sub setup {
|
|||
{
|
||||
my @fakechrootsubst = ();
|
||||
foreach my $d ('/usr/sbin', '/usr/bin', '/sbin', '/bin') {
|
||||
push @fakechrootsubst,
|
||||
"$d/chroot=/usr/sbin/chroot.fakechroot";
|
||||
push @fakechrootsubst, "$d/chroot=/usr/sbin/chroot.fakechroot";
|
||||
push @fakechrootsubst, "$d/mkfifo=/bin/true";
|
||||
push @fakechrootsubst, "$d/ldconfig=/bin/true";
|
||||
push @fakechrootsubst,
|
||||
"$d/ldd=/usr/bin/ldd.fakechroot";
|
||||
push @fakechrootsubst, "$d/ldd=/usr/bin/ldd.fakechroot";
|
||||
push @fakechrootsubst, "$d/ischroot=/bin/true";
|
||||
}
|
||||
if (defined $ENV{FAKECHROOT_CMD_SUBST}
|
||||
&& $ENV{FAKECHROOT_CMD_SUBST} ne "") {
|
||||
push @fakechrootsubst, split /:/,
|
||||
$ENV{FAKECHROOT_CMD_SUBST};
|
||||
push @fakechrootsubst, split /:/, $ENV{FAKECHROOT_CMD_SUBST};
|
||||
}
|
||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||
$ENV{FAKECHROOT_CMD_SUBST} = join ':', @fakechrootsubst;
|
||||
|
@ -2054,15 +2037,13 @@ sub setup {
|
|||
if (($? != 0) or (!$deb_host_multiarch)) {
|
||||
error "dpkg-architecture failed: $?";
|
||||
}
|
||||
my $fakechrootdir
|
||||
= "/usr/lib/$deb_host_multiarch/fakechroot";
|
||||
my $fakechrootdir = "/usr/lib/$deb_host_multiarch/fakechroot";
|
||||
if (!-e "$fakechrootdir/libfakechroot.so") {
|
||||
error "$fakechrootdir/libfakechroot.so doesn't exist."
|
||||
. " Install libfakechroot:$options->{nativearch}"
|
||||
. " outside the chroot";
|
||||
}
|
||||
my $fakerootdir
|
||||
= "/usr/lib/$deb_host_multiarch/libfakeroot";
|
||||
my $fakerootdir = "/usr/lib/$deb_host_multiarch/libfakeroot";
|
||||
if (!-e "$fakerootdir/libfakeroot-sysv.so") {
|
||||
error "$fakerootdir/libfakeroot-sysv.so doesn't exist."
|
||||
. " Install libfakeroot:$options->{nativearch}"
|
||||
|
@ -2081,8 +2062,7 @@ sub setup {
|
|||
# to know where it has to look for shared libraries
|
||||
if (defined $ENV{QEMU_LD_PREFIX}
|
||||
&& $ENV{QEMU_LD_PREFIX} ne "") {
|
||||
$ENV{QEMU_LD_PREFIX}
|
||||
= "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
||||
$ENV{QEMU_LD_PREFIX} = "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
||||
} else {
|
||||
$ENV{QEMU_LD_PREFIX} = $options->{root};
|
||||
}
|
||||
|
@ -2120,19 +2100,16 @@ sub setup {
|
|||
. " work under proot";
|
||||
info "this is likely due to missing support for"
|
||||
. " renameat2 in proot";
|
||||
info
|
||||
"see https://github.com/proot-me/PRoot/issues/147";
|
||||
info "see https://github.com/proot-me/PRoot/issues/147";
|
||||
} else {
|
||||
info "the /bin/mv binary inside the chroot doesn't"
|
||||
. " work under fakechroot";
|
||||
info "with certain versions of coreutils and glibc,"
|
||||
. " this is due to missing support for renameat2 in"
|
||||
. " fakechroot";
|
||||
info
|
||||
"see https://github.com/dex4er/fakechroot/issues/60";
|
||||
info "see https://github.com/dex4er/fakechroot/issues/60";
|
||||
}
|
||||
info
|
||||
"expect package post installation scripts not to work";
|
||||
info "expect package post installation scripts not to work";
|
||||
rmdir "$options->{root}/000-move-me"
|
||||
or error "cannot rmdir: $!";
|
||||
} else {
|
||||
|
@ -2141,6 +2118,51 @@ sub setup {
|
|||
}
|
||||
}
|
||||
|
||||
return \@chrootcmd;
|
||||
}
|
||||
|
||||
sub run_essential() {
|
||||
my $options = shift;
|
||||
my $essential_pkgs = shift;
|
||||
my $chrootcmd = shift;
|
||||
|
||||
if ($options->{mode} eq 'chrootless') {
|
||||
if ($options->{dryrun}) {
|
||||
info "simulate installing packages...";
|
||||
} else {
|
||||
info "installing packages...";
|
||||
}
|
||||
# FIXME: the dpkg config from the host is parsed before the command
|
||||
# line arguments are parsed and might break this mode
|
||||
# Example: if the host has --path-exclude set, then this will also
|
||||
# affect the chroot.
|
||||
my @chrootless_opts = (
|
||||
'-oDPkg::Options::=--force-not-root',
|
||||
'-oDPkg::Options::=--force-script-chrootless',
|
||||
'-oDPkg::Options::=--root=' . $options->{root},
|
||||
'-oDPkg::Options::=--log=' . "$options->{root}/var/log/dpkg.log",
|
||||
$options->{dryrun} ? '-oAPT::Get::Simulate=true' : (),
|
||||
);
|
||||
if (defined $options->{qemu}) {
|
||||
# The binfmt support on the outside is used, so qemu needs to know
|
||||
# where it has to look for shared libraries
|
||||
if (defined $ENV{QEMU_LD_PREFIX}
|
||||
&& $ENV{QEMU_LD_PREFIX} ne "") {
|
||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||
$ENV{QEMU_LD_PREFIX} = "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
||||
} else {
|
||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||
$ENV{QEMU_LD_PREFIX} = $options->{root};
|
||||
}
|
||||
}
|
||||
run_apt_progress({
|
||||
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||
PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}],
|
||||
});
|
||||
} elsif (
|
||||
any { $_ eq $options->{mode} }
|
||||
('root', 'unshare', 'fakechroot', 'proot')
|
||||
) {
|
||||
# install the extracted packages properly
|
||||
# we need --force-depends because dpkg does not take Pre-Depends
|
||||
# into account and thus doesn't install them in the right order
|
||||
|
@ -2153,11 +2175,11 @@ sub setup {
|
|||
sub {
|
||||
run_dpkg_progress({
|
||||
ARGV => [
|
||||
@chrootcmd, 'env',
|
||||
@{$chrootcmd}, 'env',
|
||||
'--unset=TMPDIR', 'dpkg',
|
||||
'--install', '--force-depends'
|
||||
],
|
||||
PKGS => \@essential_pkgs,
|
||||
PKGS => $essential_pkgs,
|
||||
});
|
||||
},
|
||||
$options
|
||||
|
@ -2181,11 +2203,11 @@ sub setup {
|
|||
sub {
|
||||
run_dpkg_progress({
|
||||
ARGV => [
|
||||
@chrootcmd, 'env',
|
||||
@{$chrootcmd}, 'env',
|
||||
'--unset=TMPDIR', 'dpkg',
|
||||
'--install', '--force-depends'
|
||||
],
|
||||
PKGS => \@essential_pkgs,
|
||||
PKGS => $essential_pkgs,
|
||||
});
|
||||
},
|
||||
$options
|
||||
|
@ -2193,18 +2215,48 @@ sub setup {
|
|||
}
|
||||
}
|
||||
|
||||
foreach my $deb (@essential_pkgs) {
|
||||
} else {
|
||||
error "unknown mode: $options->{mode}";
|
||||
}
|
||||
|
||||
foreach my $deb (@{$essential_pkgs}) {
|
||||
unlink "$options->{root}/$deb"
|
||||
or error "cannot unlink $deb: $!";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_install() {
|
||||
my $options = shift;
|
||||
my $pkgs_to_install = shift;
|
||||
my $chrootcmd = shift;
|
||||
|
||||
if ($options->{mode} eq 'chrootless') {
|
||||
if (scalar @{$pkgs_to_install} > 0) {
|
||||
my @chrootless_opts = (
|
||||
'-oDPkg::Options::=--force-not-root',
|
||||
'-oDPkg::Options::=--force-script-chrootless',
|
||||
'-oDPkg::Options::=--root=' . $options->{root},
|
||||
'-oDPkg::Options::=--log='
|
||||
. "$options->{root}/var/log/dpkg.log",
|
||||
$options->{dryrun} ? '-oAPT::Get::Simulate=true' : (),
|
||||
);
|
||||
run_apt_progress({
|
||||
ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
}
|
||||
} elsif (
|
||||
any { $_ eq $options->{mode} }
|
||||
('root', 'unshare', 'fakechroot', 'proot')
|
||||
) {
|
||||
# run essential hooks
|
||||
if ($options->{variant} ne 'custom') {
|
||||
run_hooks('essential', $options);
|
||||
}
|
||||
|
||||
if ($options->{variant} ne 'custom'
|
||||
and scalar @pkgs_to_install > 0) {
|
||||
and scalar @{$pkgs_to_install} > 0) {
|
||||
# some packages have to be installed from the outside before
|
||||
# anything can be installed from the inside.
|
||||
#
|
||||
|
@ -2233,15 +2285,13 @@ sub setup {
|
|||
while (my $uri = <$pipe_apt>) {
|
||||
if ($uri =~ /^https:\/\//) {
|
||||
# FIXME: support for https is part of apt >= 1.5
|
||||
push @pkgs_to_install_from_outside,
|
||||
'apt-transport-https';
|
||||
push @pkgs_to_install_from_outside, 'apt-transport-https';
|
||||
push @pkgs_to_install_from_outside, 'ca-certificates';
|
||||
last;
|
||||
} elsif ($uri =~ /^tor(\+[a-z]+)*:\/\//) {
|
||||
# tor URIs can be tor+http://, tor+https:// or even
|
||||
# tor+mirror+file://
|
||||
push @pkgs_to_install_from_outside,
|
||||
'apt-transport-tor';
|
||||
push @pkgs_to_install_from_outside, 'apt-transport-tor';
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
@ -2288,19 +2338,17 @@ sub setup {
|
|||
}
|
||||
close $dh;
|
||||
if (scalar @debs_to_install == 0) {
|
||||
warning
|
||||
"nothing got downloaded -- maybe the packages"
|
||||
warning "nothing got downloaded -- maybe the packages"
|
||||
. " were already installed?";
|
||||
} else {
|
||||
# we need --force-depends because dpkg does not take
|
||||
# Pre-Depends into account and thus doesn't install
|
||||
# them in the right order
|
||||
info 'installing '
|
||||
. (join ', ', @pkgs_to_install_from_outside)
|
||||
. "...";
|
||||
. (join ', ', @pkgs_to_install_from_outside) . "...";
|
||||
run_dpkg_progress({
|
||||
ARGV => [
|
||||
@chrootcmd, 'env',
|
||||
@{$chrootcmd}, 'env',
|
||||
'--unset=TMPDIR', 'dpkg',
|
||||
'--install', '--force-depends'
|
||||
],
|
||||
|
@ -2321,15 +2369,12 @@ sub setup {
|
|||
. " chroot...";
|
||||
run_apt_progress({
|
||||
ARGV => [
|
||||
@chrootcmd,
|
||||
'env',
|
||||
'--unset=APT_CONFIG',
|
||||
'--unset=TMPDIR',
|
||||
'apt-get',
|
||||
'--yes',
|
||||
@{$chrootcmd}, 'env',
|
||||
'--unset=APT_CONFIG', '--unset=TMPDIR',
|
||||
'apt-get', '--yes',
|
||||
'install'
|
||||
],
|
||||
PKGS => [@pkgs_to_install],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
},
|
||||
$options
|
||||
|
@ -2342,18 +2387,19 @@ sub setup {
|
|||
'apt-get', '--yes',
|
||||
'-oAPT::Get::Simulate=true', 'install'
|
||||
],
|
||||
PKGS => [@pkgs_to_install],
|
||||
PKGS => $pkgs_to_install,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error "unknown variant: $options->{variant}";
|
||||
}
|
||||
} else {
|
||||
error "unknown mode: $options->{mode}";
|
||||
}
|
||||
|
||||
run_hooks('customize', $options);
|
||||
return;
|
||||
}
|
||||
|
||||
sub run_cleanup() {
|
||||
my $options = shift;
|
||||
|
||||
# clean up temporary configuration file
|
||||
unlink "$options->{root}/etc/apt/apt.conf.d/00mmdebstrap"
|
||||
|
@ -2369,7 +2415,10 @@ sub setup {
|
|||
});
|
||||
run_apt_progress(
|
||||
{ ARGV => ['apt-get', 'clean'], CHDIR => $options->{root} });
|
||||
unlink $tmpfile or error "failed to unlink $tmpfile: $!";
|
||||
if (defined $ENV{APT_CONFIG} && -e $ENV{APT_CONFIG}) {
|
||||
unlink $ENV{APT_CONFIG}
|
||||
or error "failed to unlink $ENV{APT_CONFIG}: $!";
|
||||
}
|
||||
|
||||
# apt since 1.6 creates the auxfiles directory. If apt inside the chroot
|
||||
# is older than that, then it will not know how to clean it.
|
||||
|
|
Loading…
Reference in a new issue