diff --git a/coverage.sh b/coverage.sh index a0cccd4..ad35545 100755 --- a/coverage.sh +++ b/coverage.sh @@ -52,7 +52,7 @@ if [ ! -e shared/mmdebstrap ] || [ mmdebstrap -nt shared/mmdebstrap ]; then fi starttime= -total=104 +total=105 i=1 print_header() { @@ -856,6 +856,42 @@ else echo "RUN_MA_SAME_TESTS != yes -- Skipping test..." fi +print_header "mode=root,variant=apt: test --include=libmagic-mgc:armhf with multiple --arch options" +cat << END > shared/test.sh +#!/bin/sh +set -eu +export LC_ALL=C.UTF-8 +$CMD --mode=root --variant=apt --architectures=amd64 --architectures=armhf --include=libmagic-mgc:armhf $DEFAULT_DIST /tmp/debian-chroot $mirror +{ echo "amd64"; echo "armhf"; } | cmp /tmp/debian-chroot/var/lib/dpkg/arch - +rm /tmp/debian-chroot/var/lib/dpkg/arch +rm /tmp/debian-chroot/var/log/apt/eipp.log.xz +rm /tmp/debian-chroot/var/lib/apt/extended_states +rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.list +rm /tmp/debian-chroot/var/lib/dpkg/info/libmagic-mgc.md5sums +rm /tmp/debian-chroot/usr/lib/file/magic.mgc +rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/README.Debian +rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.Debian.gz +rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/changelog.gz +rm /tmp/debian-chroot/usr/share/doc/libmagic-mgc/copyright +rm /tmp/debian-chroot/usr/share/file/magic.mgc +rm /tmp/debian-chroot/usr/share/misc/magic.mgc +rmdir /tmp/debian-chroot/usr/share/doc/libmagic-mgc/ +rmdir /tmp/debian-chroot/usr/share/file/magic/ +rmdir /tmp/debian-chroot/usr/share/file/ +rmdir /tmp/debian-chroot/usr/lib/file/ +tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt - +rm -r /tmp/debian-chroot +END +if [ "$RUN_MA_SAME_TESTS" = "yes" ]; then + if [ "$HAVE_QEMU" = "yes" ]; then + ./run_qemu.sh + else + ./run_null.sh SUDO + fi +else + echo "RUN_MA_SAME_TESTS != yes -- Skipping test..." +fi + print_header "mode=root,variant=apt: test --aptopt" cat << END > shared/test.sh #!/bin/sh diff --git a/mmdebstrap b/mmdebstrap index 8ba3740..05ffa99 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -1778,10 +1778,12 @@ sub main() { # copy ARGV because getopt modifies it my @ARGVORIG = @ARGV; + chomp (my $hostarch = `dpkg --print-architecture`); my $options = { components => ["main"], variant => "important", include => undef, + architectures => [$hostarch], mode => 'auto', dpkgopts => [], aptopts => [], @@ -1790,7 +1792,6 @@ sub main() { essential_hook => [], customize_hook => [], }; - chomp ($options->{architectures} = `dpkg --print-architecture`); my $logfile = undef; Getopt::Long::Configure ('default', 'bundling', 'auto_abbrev', 'ignore_case_always'); GetOptions( @@ -1799,7 +1800,7 @@ sub main() { 'components=s@' => \$options->{components}, 'variant=s' => \$options->{variant}, 'include=s' => \$options->{include}, - 'architectures=s' => \$options->{architectures}, + 'architectures=s@' => \$options->{architectures}, 'mode=s' => \$options->{mode}, 'dpkgopt=s@' => \$options->{dpkgopts}, 'aptopt=s@' => \$options->{aptopts}, @@ -1938,9 +1939,37 @@ sub main() { error "unknown mode: $options->{mode}"; } - my ($nativearch, @foreignarchs) = split /,/, $options->{architectures}; - $options->{nativearch} = $nativearch; - $options->{foreignarchs} = \@foreignarchs; + my @architectures = (); + foreach my $archs (@{$options->{architectures}}) { + foreach my $arch (split /[,\s]+/, $archs) { + # strip leading and trailing whitespace + $arch =~ s/^\s+|\s+$//g; + # skip if the remainder is an empty string + if ($arch eq '') { + next; + } + # do not append component if it's already in the list + if (any {$_ eq $arch} @architectures) { + next; + } + push @architectures, $arch; + } + } + + $options->{nativearch} = $hostarch; + $options->{foreignarchs} = []; + if (scalar @architectures == 0) { + warning "empty architecture list: falling back to native architecture $hostarch"; + } elsif (scalar @architectures == 1) { + $options->{nativearch} = $architectures[0]; + } else { + $options->{nativearch} = $architectures[0]; + push @{$options->{foreignarchs}}, @architectures[1..$#architectures]; + } + + debug "Native architecture (outside): $hostarch"; + debug "Native architecture (inside): $options->{nativearch}"; + debug ("Foreign architectures (inside): " . (join ', ', @{$options->{foreignarchs}})); { # FIXME: autogenerate this list @@ -1967,8 +1996,7 @@ sub main() { sparc => 'sparc', sparc64 => 'sparc64', }; - chomp (my $hostarch = `dpkg --print-architecture`); - if ($hostarch ne $nativearch) { + if ($hostarch ne $options->{nativearch}) { my $withemu = 0; my $noemu = 0; { @@ -1976,17 +2004,17 @@ sub main() { if ($pid == 0) { { no warnings; # don't print a warning if the following fails - exec 'arch-test', $nativearch; + exec 'arch-test', $options->{nativearch}; } # if exec didn't work (for example because the arch-test program is # missing) prepare for the worst and assume that the architecture # cannot be executed - print "$nativearch: not supported on this machine/kernel\n"; + print "$options->{nativearch}: not supported on this machine/kernel\n"; exit 1; } chomp (my $content = do { local $/; <$fh> }); close $fh; - if ($? == 0 and $content eq "$nativearch: ok") { + if ($? == 0 and $content eq "$options->{nativearch}: ok") { $withemu = 1; } } @@ -1995,17 +2023,17 @@ sub main() { if ($pid == 0) { { no warnings; # don't print a warning if the following fails - exec 'arch-test', '-n', $nativearch; + exec 'arch-test', '-n', $options->{nativearch}; } # if exec didn't work (for example because the arch-test program is # missing) prepare for the worst and assume that the architecture # cannot be executed - print "$nativearch: not supported on this machine/kernel\n"; + print "$options->{nativearch}: not supported on this machine/kernel\n"; exit 1; } chomp (my $content = do { local $/; <$fh> }); close $fh; - if ($? == 0 and $content eq "$nativearch: ok") { + if ($? == 0 and $content eq "$options->{nativearch}: ok") { $noemu = 1; } } @@ -2034,10 +2062,10 @@ sub main() { close $fh; } { - if (!exists $deb2qemu->{$nativearch}) { - warning "no mapping from $nativearch to qemu-user binary"; + if (!exists $deb2qemu->{$options->{nativearch}}) { + warning "no mapping from $options->{nativearch} to qemu-user binary"; } else { - my $binfmt_identifier = 'qemu-' . $deb2qemu->{$nativearch}; + my $binfmt_identifier = 'qemu-' . $deb2qemu->{$options->{nativearch}}; open my $fh, '-|', '/usr/sbin/update-binfmts', '--display', $binfmt_identifier // error "failed to fork(): $!"; chomp (my $binfmts = do { local $/; <$fh> }); close $fh; @@ -2046,22 +2074,22 @@ sub main() { } } } - error "$nativearch can neither be executed natively nor via qemu user emulation with binfmt_misc"; + error "$options->{nativearch} can neither be executed natively nor via qemu user emulation with binfmt_misc"; } elsif ($withemu == 0 and $noemu == 1) { error "arch-test succeeded without emu but not with emu"; } elsif ($withemu == 1 and $noemu == 0) { - info "$nativearch cannot be executed, falling back to qemu-user"; - if (!exists $deb2qemu->{$nativearch}) { - error "no mapping from $nativearch to qemu-user binary"; + info "$options->{nativearch} cannot be executed, falling back to qemu-user"; + if (!exists $deb2qemu->{$options->{nativearch}}) { + error "no mapping from $options->{nativearch} to qemu-user binary"; } - $options->{qemu} = $deb2qemu->{$nativearch}; + $options->{qemu} = $deb2qemu->{$options->{nativearch}}; } elsif ($withemu == 1 and $noemu == 1) { - info "$nativearch is different from $hostarch but can be executed natively"; + info "$options->{nativearch} is different from $hostarch but can be executed natively"; } else { error "logic error"; } } else { - info "chroot architecture $nativearch is equal to the host's architecture"; + info "chroot architecture $options->{nativearch} is equal to the host's architecture"; } } @@ -2750,11 +2778,18 @@ of duplicates. So the following are equivalent: =item B<--architectures>=I[,I,...] -Comma separated list of architectures. The first architecture is the I -architecture inside the chroot. The remaining architectures will be added to -the foreign dpkg architectures. Without this option, the I +Comma or whitespace separated list of architectures. The first architecture is +the I architecture inside the chroot. The remaining architectures will +be added to the foreign dpkg architectures. Without this option, the I architecture of the chroot defaults to the native architecture of the system -running B. +running B. The option can be specified multiple times and values +are concatenated. If later list items are repeated, then they get dropped so +that the resulting list is free of duplicates. So the following are +equivalent: + + --architectures="amd64 armhf mipsel" + --architectures=amd64,armhf,mipsel + --arch=amd64 --arch="armhf mipsel" --arch=armhf,mipsel =begin comment