forked from josch/mmdebstrap
Instead of Dpkg::Index use a primitive deb822 parser and shave off another 10 seconds
This commit is contained in:
parent
16d9b413f7
commit
1e9817574c
2 changed files with 36 additions and 30 deletions
10
README.md
10
README.md
|
@ -26,7 +26,7 @@ Summary:
|
||||||
|
|
||||||
- more than one mirror possible
|
- more than one mirror possible
|
||||||
- security and updates mirror included for Debian stable chroots
|
- security and updates mirror included for Debian stable chroots
|
||||||
- 2-3 times faster
|
- 3-6 times faster
|
||||||
- chroot with apt in 11 seconds
|
- chroot with apt in 11 seconds
|
||||||
- gzipped tarball with apt is 27M small
|
- gzipped tarball with apt is 27M small
|
||||||
- bit-by-bit reproducible output
|
- bit-by-bit reproducible output
|
||||||
|
@ -40,14 +40,14 @@ with debootstrap since 2009 (See #543819 and #762222). Since mmdebstrap uses
|
||||||
apt internally, support for multiple mirrors comes for free and stable or
|
apt internally, support for multiple mirrors comes for free and stable or
|
||||||
oldstable **chroots will include security and updates mirrors**.
|
oldstable **chroots will include security and updates mirrors**.
|
||||||
|
|
||||||
A side-effect of using apt is being **2-3 times faster** than debootstrap. The
|
A side-effect of using apt is being **3-6 times faster** than debootstrap. The
|
||||||
timings were carried out on a laptop with an Intel Core i5-5200U.
|
timings were carried out on a laptop with an Intel Core i5-5200U.
|
||||||
|
|
||||||
| variant | mmdebstrap | debootstrap |
|
| variant | mmdebstrap | debootstrap |
|
||||||
| ------- | ---------- | ------------ |
|
| ------- | ---------- | ------------ |
|
||||||
| minbase | 25.25 s | 51.47 s |
|
| minbase | 14.18 s | 51.47 s |
|
||||||
| buildd | 30.99 s | 59.38 s |
|
| buildd | 20.55 s | 59.38 s |
|
||||||
| - | 29.85 s | 127.18 s |
|
| - | 18.98 s | 127.18 s |
|
||||||
|
|
||||||
Apt considers itself an `Essential: yes` package. This feature allows one to
|
Apt considers itself an `Essential: yes` package. This feature allows one to
|
||||||
create a chroot containing just the `Essential: yes` packages and apt (and
|
create a chroot containing just the `Essential: yes` packages and apt (and
|
||||||
|
|
56
mmdebstrap
56
mmdebstrap
|
@ -22,7 +22,6 @@ use File::Copy;
|
||||||
use File::Path qw(make_path remove_tree);
|
use File::Path qw(make_path remove_tree);
|
||||||
use File::Temp qw(tempfile tempdir);
|
use File::Temp qw(tempfile tempdir);
|
||||||
use Cwd qw(abs_path);
|
use Cwd qw(abs_path);
|
||||||
use Dpkg::Index;
|
|
||||||
require "syscall.ph";
|
require "syscall.ph";
|
||||||
use Fcntl qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD);
|
use Fcntl qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD);
|
||||||
use List::Util qw(any none);
|
use List::Util qw(any none);
|
||||||
|
@ -732,49 +731,56 @@ sub setup {
|
||||||
chomp $fname;
|
chomp $fname;
|
||||||
open (my $pipe_cat, '-|', '/usr/lib/apt/apt-helper', 'cat-file', $fname) or die "cannot start apt-helper cat-file: $!";
|
open (my $pipe_cat, '-|', '/usr/lib/apt/apt-helper', 'cat-file', $fname) or die "cannot start apt-helper cat-file: $!";
|
||||||
|
|
||||||
my $key_func = sub {
|
my $pkgname;
|
||||||
return $_[0]->{Package} . ' ' . $_[0]->{Version} . ' ' . $_[0]->{Architecture};
|
my $ess = '';
|
||||||
};
|
my $prio = 'optional';
|
||||||
|
while (my $line = <$pipe_cat>) {
|
||||||
my $index = Dpkg::Index->new(get_key_func=>$key_func);
|
chomp $line;
|
||||||
|
# Dpkg::Index takes 10 seconds to parse a typical Packages
|
||||||
$index->parse($pipe_cat, 'apt-helper cat-file') or die "failed to parse";
|
# file. Thus we instead use a simple parser that just retrieve
|
||||||
|
# the information we need.
|
||||||
foreach my $key ($index->get_keys()) {
|
if ($line ne "") {
|
||||||
my $cdata = $index->get_by_key($key);
|
if ($line =~ /^Package: (.*)/) {
|
||||||
my $pkgname = $cdata->{Package};
|
$pkgname = $1;
|
||||||
my $arch = $cdata->{Architecture} // '';
|
} elsif ($line =~ /^Essential: yes$/) {
|
||||||
my $ess = $cdata->{Essential} // '';
|
$ess = 'yes'
|
||||||
|
} elsif ($line =~ /^Priority: (.*)/) {
|
||||||
|
$prio = $1;
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
# the line is empty, thus a package stanza just finished
|
||||||
|
# processing and we can handle it now
|
||||||
if ($ess eq 'yes') {
|
if ($ess eq 'yes') {
|
||||||
$ess_pkgs{$pkgname} = ();
|
$ess_pkgs{$pkgname} = ();
|
||||||
}
|
} elsif ($options->{variant} eq 'essential') {
|
||||||
my $prio = $cdata->{Priority} // 'optional';
|
|
||||||
if ($options->{variant} eq 'essential') {
|
|
||||||
# for this variant we are only interested in the
|
# for this variant we are only interested in the
|
||||||
# essential packages
|
# essential packages
|
||||||
next;
|
|
||||||
} elsif (any { $_ eq $options->{variant} } ('standard', 'important', 'required', 'buildd', 'minbase')) {
|
} elsif (any { $_ eq $options->{variant} } ('standard', 'important', 'required', 'buildd', 'minbase')) {
|
||||||
if ($prio eq 'optional' or $prio eq 'extra') {
|
if ($prio eq 'optional' or $prio eq 'extra') {
|
||||||
# always ignore packages of priority optional and extra
|
# always ignore packages of priority optional and extra
|
||||||
next;
|
|
||||||
} elsif ($prio eq 'standard') {
|
} elsif ($prio eq 'standard') {
|
||||||
if (any { $_ eq $options->{variant} } ('important', 'required', 'buildd', 'minbase')) {
|
if (none { $_ eq $options->{variant} } ('important', 'required', 'buildd', 'minbase')) {
|
||||||
next;
|
$pkgs_to_install{$pkgname} = ();
|
||||||
}
|
}
|
||||||
} elsif ($prio eq 'important') {
|
} elsif ($prio eq 'important') {
|
||||||
if (any { $_ eq $options->{variant} } ('required', 'buildd', 'minbase')) {
|
if (none { $_ eq $options->{variant} } ('required', 'buildd', 'minbase')) {
|
||||||
next;
|
$pkgs_to_install{$pkgname} = ();
|
||||||
}
|
}
|
||||||
} elsif ($prio eq 'required') {
|
} elsif ($prio eq 'required') {
|
||||||
# required packages are part of all sets except
|
# required packages are part of all sets except
|
||||||
# essential and apt
|
# essential and apt
|
||||||
|
$pkgs_to_install{$pkgname} = ();
|
||||||
} else {
|
} else {
|
||||||
die "unknown priority: $prio";
|
die "unknown priority: $prio";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
die "unknown variant: $options->{variant}";
|
die "unknown variant: $options->{variant}";
|
||||||
}
|
}
|
||||||
$pkgs_to_install{$pkgname} = ();
|
# reset values
|
||||||
|
undef $pkgname;
|
||||||
|
$ess = '';
|
||||||
|
$prio = 'optional';
|
||||||
}
|
}
|
||||||
|
|
||||||
close $pipe_cat;
|
close $pipe_cat;
|
||||||
|
@ -1805,7 +1811,7 @@ This section lists some differences to debootstrap.
|
||||||
|
|
||||||
=item * Multiple ways to operate as non-root: fakechroot, proot, unshare
|
=item * Multiple ways to operate as non-root: fakechroot, proot, unshare
|
||||||
|
|
||||||
=item * 2-3 times faster
|
=item * 3-6 times faster
|
||||||
|
|
||||||
=item * Can create a chroot with only Essential:yes packages and their dependencies
|
=item * Can create a chroot with only Essential:yes packages and their dependencies
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue