pbuilder/multistrap : remove debootstrap code and do all the work in apt+dpkg. Improve native support and re-enable.

git-svn-id: http://emdebian.org/svn/current@5723 563faec7-e20c-0410-992a-a66f704d0ccd
This commit is contained in:
codehelp 2009-03-22 16:28:09 +00:00
parent 05bad91461
commit bb0ecacd94
3 changed files with 105 additions and 134 deletions

44
bash/multistrap Normal file
View file

@ -0,0 +1,44 @@
# bash completion support
#
# Copyright (C) 2009 Neil Williams <codehelp@debian.org>
#
# This package is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
_get_dpkg_cross_list()
{
grep Choices: /var/lib/dpkg/info/dpkg-cross.templates \
| cut -d':' -f2 | sed -e 's/None, //' | sed -e 's/,//g'
}
_em_multistrap()
{
local cur prev opts cmds help machine arch quiet
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
help="-h -? --help --version "
arch="-a --arch "
opts="-f --file"
machine=""
case "$prev" in
-@(a|-arch))
COMPREPLY=( $( _get_dpkg_cross_list $cur ) )
;;
*)
COMPREPLY=( $(compgen -W "${arch}${help}${opts}${machine}${cmds}" -- ${cur}) )
;;
esac
}
complete -F _em_multistrap -o default em_multistrap

View file

@ -22,12 +22,13 @@ use Parse::Debian::Packages;
use strict; use strict;
use vars qw/ $progname $ourversion %scripts $dstrap $script $extra use vars qw/ $progname $ourversion %scripts $dstrap $script $extra
@archives $deb $cachedir $config_str %packages $retval $str $retries @archives $deb $cachedir $config_str %packages $retval $str $retries
$dir $include $arch $foreign $suite $url $forceunpack $option %options $dir $include $arch $foreign $suite $url $unpack $option %options
@e $sourcesname $libdir $dpkgdir @debootstrap %suites $mirror $etcdir @e $sourcesname $libdir $dpkgdir @debootstrap %suites $mirror $etcdir
$repo @dirs @touch %sources $section %keys $host $key $value $type $repo @dirs @touch %sources $section %keys $host $key $value $type
$file $config $tidy /; $file $config $tidy /;
$progname = basename($0); $progname = basename($0);
$ourversion = "0.0.3"; $ourversion = "0.0.4";
$unpack = "true";
while( @ARGV ) { while( @ARGV ) {
$_= shift( @ARGV ); $_= shift( @ARGV );
@ -77,9 +78,13 @@ foreach $section (sort keys %keys)
if ($section eq "general") if ($section eq "general")
{ {
$arch = $keys{$section}{'arch'} if (not defined $arch); $arch = $keys{$section}{'arch'} if (not defined $arch);
$retries = $keys{$section}{'retries'};
$dir = $keys{$section}{'directory'} if (not defined $dir); $dir = $keys{$section}{'directory'} if (not defined $dir);
$forceunpack = lc($keys{$section}{'forceunpack'}); # support the original value but replace by new value.
$unpack = lc($keys{$section}{'unpack'})
if (defined $keys{$section}{'forceunpack'});
$unpack = lc($keys{$section}{'unpack'})
if (defined $keys{$section}{'unpack'});
$tidy++ if (defined $keys{$section}{'cleanup'});
@debootstrap = split(' ', lc($keys{$section}{'debootstrap'})); @debootstrap = split(' ', lc($keys{$section}{'debootstrap'}));
} }
else else
@ -88,16 +93,12 @@ foreach $section (sort keys %keys)
$packages{$section}=$keys{$section}{'packages'}; $packages{$section}=$keys{$section}{'packages'};
$suites{$section}=$keys{$section}{'suite'}; $suites{$section}=$keys{$section}{'suite'};
$scripts{$section}=$keys{$section}{'script'}; $scripts{$section}=$keys{$section}{'script'};
$options{$section}=$keys{$section}{'options'};
} }
} }
print "$progname $ourversion using $file\n"; print "$progname $ourversion using $file\n";
$host = `dpkg-architecture -qDEB_BUILD_ARCH`; $host = `dpkg-architecture -qDEB_BUILD_ARCH`;
chomp ($host); chomp ($host);
die ("$progname is not currently able to support native operation.\n") $foreign++ if ($host ne $arch);
if ($host eq $arch);
# don't let debootstrap do second-stage
$foreign = "--foreign"; # always set
$cachedir = "var/cache/apt/"; # archives $cachedir = "var/cache/apt/"; # archives
$libdir = "var/lib/apt/"; # lists $libdir = "var/lib/apt/"; # lists
$etcdir = "etc/apt/"; # sources $etcdir = "etc/apt/"; # sources
@ -179,38 +180,11 @@ $retval = system ("apt-get -y $config_str install $str");
die ("apt download failed. Exit value: ".($retval/256)."\n") die ("apt download failed. Exit value: ".($retval/256)."\n")
if ($retval != 0); if ($retval != 0);
foreach $dstrap (@debootstrap) &force_unpack if ($unpack eq "true");
{
$url = $sources{$dstrap};
$suite = $suites{$dstrap};
$script = $scripts{$dstrap};
$option = $options{$dstrap};
$extra = $packages{$dstrap};
$include = '';
if (($extra ne '') and ($option !~ /no-resolve-deps/))
{
@e = split(' ', $extra);
$include = "--include ";
$include .= join (',', @e);
}
&write_script ($dstrap);
$str = "/usr/sbin/debootstrap $option $include --arch $arch $foreign";
$str .= " --keep-debootstrap-dir $suite $dir $url $script";
print "$str\n";
$retval = system ($str);
while ($retval != 0 and $retries > 0)
{
print "Problem - trying again, $retries left. ".($retval/250)."\n$!\n";
sleep 1;
$retval = system ("$str");
$retries--;
}
}
&force_unpack if ($forceunpack eq "true");
system ("touch ${dir}${libdir}lists/lock"); system ("touch ${dir}${libdir}lists/lock");
(not defined $tidy) ? system ("apt-get $config_str update") : &tidy_apt; (not defined $tidy) ? system ("apt-get $config_str update") : &tidy_apt;
system ("rm -rf ${dir}debootstrap"); system ("rm -rf ${dir}debootstrap");
&native if (not defined ($foreign));
print "\nMultistrap system installed successfully in $dir.\n\n"; print "\nMultistrap system installed successfully in $dir.\n\n";
exit 0; exit 0;
@ -353,7 +327,7 @@ sub tidy_apt
next unless ($file =~ /\.bin$/); next unless ($file =~ /\.bin$/);
unlink ("${dir}${cachedir}$file"); unlink ("${dir}${cachedir}$file");
} }
if ($forceunpack eq "true") if ($unpack eq "true")
{ {
opendir (DEBS, "${dir}${cachedir}/archives/") opendir (DEBS, "${dir}${cachedir}/archives/")
or die ("Cannot read apt archives directory/.\n"); or die ("Cannot read apt archives directory/.\n");
@ -368,6 +342,13 @@ sub tidy_apt
} }
} }
# if native arch, do a few tasks just because we can and probably should.
sub native
{
print "I: Native mode - configuring unpacked packages . . .\n";
system ("sudo chroot $dir dpkg --configure -a");
}
sub get_required_debs sub get_required_debs
{ {
# emulate required="$(get_debs Priority: required)" # emulate required="$(get_debs Priority: required)"
@ -380,11 +361,8 @@ sub get_required_debs
or die ("Cannot open ${dir}${libdir}lists/ directory. $!\n"); or die ("Cannot open ${dir}${libdir}lists/ directory. $!\n");
my @lists=grep(/_Packages$/, readdir (PKGS)); my @lists=grep(/_Packages$/, readdir (PKGS));
closedir (PKGS); closedir (PKGS);
# only read Packages files from the debootstrap entries where
# options do not include --no-resolve-deps
foreach my $strap (@debootstrap) foreach my $strap (@debootstrap)
{ {
next if ($options{$strap} =~ /no-resolve-deps/);
my $s = lc($strap); my $s = lc($strap);
foreach my $l (@lists) foreach my $l (@lists)
{ {
@ -405,34 +383,6 @@ sub get_required_debs
return \@debs; return \@debs;
} }
sub write_script
{
($dstrap) = @_;
$extra = $packages{$dstrap};
$script = $scripts{$dstrap};
return if ($script eq '');
open (SCRIPT, ">$script") or die ("Cannot open $script. $!\n");
print SCRIPT<<END;
mirror_style release
download_style apt
finddebs_style hardcoded
variants - buildd fakechroot minbase
work_out_debs () {
required="$extra"
}
first_stage_install () {
extract \$required
}
second_stage_install () {
info BASESUCCESS "Base system installed successfully."
}
END
close (SCRIPT);
}
sub usageversion { sub usageversion {
print(STDERR <<END) print(STDERR <<END)
$progname version $ourversion $progname version $ourversion
@ -452,19 +402,15 @@ Options:
$progname extends debootstrap to provide support for multiple $progname extends debootstrap to provide support for multiple
repositories, using a configuration file to specify the relevant suites, repositories, using a configuration file to specify the relevant suites,
debootstrap options, architecture, extra packages and the mirror to use architecture, extra packages and the mirror to use for each repository.
for each repository.
Example configuration: Example configuration:
[General] [General]
arch=arm arch=armel
directory=/opt/multistrap/ directory=/opt/multistrap/
retries=5 # extract all downloaded archives (default is true)
# extract all downloaded archives as well as those unpack=true
# unpacked by debootstrap. # the order of sections is not important.
forceunpack=false
# the order of sections is important.
# debootstraps are unpacked in this sequence.
debootstrap=Debian debootstrap=Debian
[Debian] [Debian]
@ -472,41 +418,20 @@ packages=
source=http://ftp.uk.debian.org/debian source=http://ftp.uk.debian.org/debian
suite=lenny suite=lenny
script= script=
options=
This will result in a completely normal debootstrap of Debian lenny from This will result in a completely normal debootstrap of Debian lenny from
the specified mirror, for ARM in /opt/multistrap/. the specified mirror, for armel in /opt/multistrap/.
'Architecture' and 'directory' can be overridden on the command line. 'Architecture' and 'directory' can be overridden on the command line.
Specify a package to extend the debootstap to include that package and Specify a package to extend the debootstap to include that package and
all dependencies. all dependencies.
Specify a script only if the suite is not currently supported by
debootstrap (which in turn are based on Debian and Ubuntu suite names).
Useful options can include --no-resolve-deps if one of the repositories
contains packages that are also in any of the other repositories but at
a lower version. This prevents debootstrap unpacking the older version
of the duplicated package.
General settings: General settings:
The order of repositories specified in the debootstrap (under General),
determines which repository is unpacked first - this is important if one
repository is incomplete or contains older versions.
'directory' specifies the top level directory where the debootstrap 'directory' specifies the top level directory where the debootstrap
will be created - it is not packed into a .tgz once complete. will be created - it is not packed into a .tgz once complete.
'retries' determines how many times debootstrap should be allowed to
restart (the same value is used for all repositories) to allow for
temporary network issues.
If 'arch' does not match the build architecture (determined using
`dpkg-architecture -qDEB_BUILD_ARCH`, --foreign is passed to
each debootstrap.
END END
|| die "$progname: failed to write usage: $!\n"; || die "$progname: failed to write usage: $!\n";
} }
@ -532,14 +457,11 @@ for each repository.
Example configuration: Example configuration:
[General] [General]
arch=arm arch=armel
directory=/opt/multistrap/ directory=/opt/multistrap/
retries=5 # extract all downloaded archives (default is true)
# extract all downloaded archives as well as those unpack=true
# unpacked by debootstrap. # the order of sections is not important.
forceunpack=false
# the order of sections is important.
# debootstraps are unpacked in this sequence.
debootstrap=Debian debootstrap=Debian
[Debian] [Debian]
@ -550,40 +472,21 @@ Example configuration:
options= options=
This will result in a completely normal debootstrap of Debian lenny from This will result in a completely normal debootstrap of Debian lenny from
the specified mirror, for ARM in /opt/multistrap/. the specified mirror, for armel in /opt/multistrap/.
'Architecture' and 'directory' can be overridden on the command line. 'Architecture' and 'directory' can be overridden on the command line.
Section names are case-insensitive. Section names are case-insensitive.
Specify a package to extend the debootstap to include that package and Specify a package to extend the multistrap to include that package and
all dependencies. all dependencies.
Specify a script only if the suite is not currently supported by
debootstrap (which in turn are based on Debian and Ubuntu suite names).
Useful options can include --no-resolve-deps if one of the repositories
contains packages that are also in any of the other repositories but at
a lower version. This prevents debootstrap unpacking the older version
of the duplicated package.
=head1 General settings: =head1 General settings:
The order of repositories specified in the debootstrap (under General),
determines which repository is unpacked first - this is important if one
repository is incomplete or contains older versions.
'directory' specifies the top level directory where the debootstrap 'directory' specifies the top level directory where the debootstrap
will be created - it is not packed into a .tgz once complete. will be created - it is not packed into a .tgz once complete.
'retries' determines how many times debootstrap should be allowed to
restart (the same value is used for all repositories) to allow for
temporary network issues.
If 'arch' does not match the build architecture (determined using
`dpkg-architecture -qDEB_BUILD_ARCH`, --foreign is passed to
each debootstrap.
Note that em_multistrap deliberately turns off Install-Recommends. Note that em_multistrap deliberately turns off Install-Recommends.
As with debootstrap, em_multistrap will continue after errors although As with debootstrap, em_multistrap will continue after errors although
@ -591,18 +494,32 @@ you may want to purge $directory/var/cache/apt/archives from time to
time. time.
em_multistrap does not currently implement machine:variant support em_multistrap does not currently implement machine:variant support
but the build directory is not packed up at the end of the run so used in Emdebian but the build directory is not packed up at the
other scripts can be used to implement customisations. end of the run so other scripts can be used to implement customisations.
=head1 Native mode disabled =head1 State
em_multistrap is not intended for native support, it was developed for multistrap is stateless - if the directory exists, it will simply
proceed as normal and apt will try to pick up where it left off.
=head1 Native mode - multistrap
em_multistrap was not intended for native support, it was developed for
cross architeeture support. In order for multiple repositories to be cross architeeture support. In order for multiple repositories to be
used, em_multistrap sets the --foreign option with debootstrap even if used, em_multistrap sets the --foreign option with debootstrap even if
debootstrap would be able to complete the installation of each single debootstrap would be able to complete the installation of each single
repository. The reason for this is so that only the packages selected repository. The reason for this is so that only the packages selected
by apt are actually unpacked. by apt are actually unpacked.
Currently, em_multistrap disables native support. In native mode, various post-multistrap operations are likely to be
needed that debootstrap would do for you:
1. copy /etc/hosts into the chroot
2. clean the environment to unset LANGUAGE, LC_ALL and LANG
to silence nuisance perl warnings that obscure other errors
(An alternative to unset the localisation variables is to add
locales to your multistrap configuration file in the 'packages'
option.
=cut =cut

10
multistrap Executable file
View file

@ -0,0 +1,10 @@
#!/usr/bin/perl
use strict;
use warnings;
# Eventually, this will replace the em_ one or call em_ with
# --arch and take over native duties.
#debug
my $str = join(" ", @ARGV);
system ("sudo /opt/working/emdebian/svn/current/em_multistrap $str");