Pull in all upstream patches since 5.1.13.

- Choose providers better (RHBZ#1266918).
- Use autopatch.
This commit is contained in:
Richard W.M. Jones 2015-10-13 16:11:35 +01:00
parent 1287017bff
commit 22a6b3ebe7
8 changed files with 762 additions and 1 deletions

View File

@ -0,0 +1,53 @@
From b6cf15d8f38270d6d6c9df2c8589829c9a3ad176 Mon Sep 17 00:00:00 2001
From: Pino Toscano <ptoscano@redhat.com>
Date: Mon, 13 Jul 2015 17:32:33 +0200
Subject: [PATCH 1/7] utils: import parse_size from libguestfs
---
src/utils.ml | 21 +++++++++++++++++++++
src/utils.mli | 3 +++
2 files changed, 24 insertions(+)
diff --git a/src/utils.ml b/src/utils.ml
index 3e81c21..7ae24bd 100644
--- a/src/utils.ml
+++ b/src/utils.ml
@@ -204,3 +204,24 @@ let compare_architecture a1 a2 =
exit 1
in
compare (index_of_architecture a1) (index_of_architecture a2)
+
+(* Parse a size field, eg. "10G". *)
+let parse_size =
+ let const_re = Str.regexp "^\\([.0-9]+\\)\\([bKMG]\\)$" in
+ fun field ->
+ let matches rex = Str.string_match rex field 0 in
+ let sub i = Str.matched_group i field in
+ let size_scaled f = function
+ | "b" -> Int64.of_float f
+ | "K" -> Int64.of_float (f *. 1024.)
+ | "M" -> Int64.of_float (f *. 1024. *. 1024.)
+ | "G" -> Int64.of_float (f *. 1024. *. 1024. *. 1024.)
+ | _ -> assert false
+ in
+
+ if matches const_re then (
+ size_scaled (float_of_string (sub 1)) (sub 2)
+ ) else (
+ eprintf "supermin: cannot parse size field '%s'\n" field;
+ exit 1
+ )
diff --git a/src/utils.mli b/src/utils.mli
index 5de940d..7896e34 100644
--- a/src/utils.mli
+++ b/src/utils.mli
@@ -90,3 +90,6 @@ val compare_version : string -> string -> int
val compare_architecture : string -> string -> int
(** Compare two architecture strings. *)
+
+val parse_size : string -> int64
+(** Parse a size field, eg. [10G] *)
--
2.5.0

View File

@ -0,0 +1,184 @@
From 92bc55b54a17d368b43241394ace1d862899f9d7 Mon Sep 17 00:00:00 2001
From: Pino Toscano <ptoscano@redhat.com>
Date: Mon, 13 Jul 2015 17:33:34 +0200
Subject: [PATCH 2/7] Add --size for ext2 filesystem
Add a --size option to setting the size of the ext2 filesystem,
so it is possible to create ext2 appliances with smaller disk images.
The default is like the previously hardcoded value of 4GB.
---
src/build.ml | 4 ++--
src/ext2.ml | 19 ++++++++++---------
src/prepare.ml | 2 +-
src/supermin.ml | 9 +++++++--
src/supermin.pod | 15 +++++++++++++++
5 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/src/build.ml b/src/build.ml
index d7d0781..fb2e6d3 100644
--- a/src/build.ml
+++ b/src/build.ml
@@ -59,7 +59,7 @@ and string_of_file_content = function
let rec build debug
(copy_kernel, dtb_wildcard, format, host_cpu,
- packager_config, tmpdir, use_installed)
+ packager_config, tmpdir, use_installed, size)
inputs outputdir =
if debug >= 1 then
printf "supermin: build: %s\n%!" (String.concat " " inputs);
@@ -210,7 +210,7 @@ let rec build debug
and initrd = outputdir // "initrd" in
let kernel_version, modpath =
Kernel.build_kernel debug host_cpu dtb_wildcard copy_kernel kernel dtb in
- Ext2.build_ext2 debug basedir files modpath kernel_version appliance;
+ Ext2.build_ext2 debug basedir files modpath kernel_version appliance size;
Ext2_initrd.build_initrd debug tmpdir modpath initrd
and read_appliance debug basedir appliance = function
diff --git a/src/ext2.ml b/src/ext2.ml
index d5c26a7..79539a3 100644
--- a/src/ext2.ml
+++ b/src/ext2.ml
@@ -23,26 +23,27 @@ open Utils
open Ext2fs
open Package_handler
-(* The ext2 image that we build always has a fixed size, and we 'hope'
- * that the files fit in (otherwise we'll get an error). Note that
- * the file is sparsely allocated.
+(* The ext2 image that we build has a size of 4GB if not specified,
+ * and we 'hope' that the files fit in (otherwise we'll get an error).
+ * Note that the file is sparsely allocated.
*
* The downside of allocating a very large initial disk is that the
* fixed overhead of ext2 is larger (since ext2 calculates it based on
* the size of the disk). For a 4GB disk the overhead is
* approximately 66MB.
- *
- * In future, make this configurable, or determine it from the input
- * files (XXX).
*)
-let appliance_size = 4L *^ 1024L *^ 1024L *^ 1024L
+let default_appliance_size = 4L *^ 1024L *^ 1024L *^ 1024L
-let build_ext2 debug basedir files modpath kernel_version appliance =
+let build_ext2 debug basedir files modpath kernel_version appliance size =
if debug >= 1 then
printf "supermin: ext2: creating empty ext2 filesystem '%s'\n%!" appliance;
let fd = openfile appliance [O_WRONLY;O_CREAT;O_TRUNC;O_NOCTTY] 0o644 in
- LargeFile.ftruncate fd appliance_size;
+ let size =
+ match size with
+ | None -> default_appliance_size
+ | Some s -> s in
+ LargeFile.ftruncate fd size;
close fd;
let cmd =
diff --git a/src/prepare.ml b/src/prepare.ml
index 75f21dc..7e522e9 100644
--- a/src/prepare.ml
+++ b/src/prepare.ml
@@ -22,7 +22,7 @@ open Package_handler
open Utils
let prepare debug (copy_kernel, dtb_wildcard, format, host_cpu,
- packager_config, tmpdir, use_installed)
+ packager_config, tmpdir, use_installed, size)
inputs outputdir =
if debug >= 1 then
printf "supermin: prepare: %s\n%!" (String.concat " " inputs);
diff --git a/src/supermin.ml b/src/supermin.ml
index 14261d6..9623229 100644
--- a/src/supermin.ml
+++ b/src/supermin.ml
@@ -94,6 +94,7 @@ let main () =
let outputdir = ref "" in
let packager_config = ref "" in
let use_installed = ref false in
+ let size = ref None in
let set_debug () = incr debug in
@@ -118,6 +119,8 @@ let main () =
exit 1
in
+ let set_size arg = size := Some (parse_size arg) in
+
let error_supermin_5 () =
eprintf "supermin: *** error: This is supermin version 5.\n";
eprintf "supermin: *** It looks like you are looking for supermin version 4.\n";
@@ -143,6 +146,7 @@ let main () =
"-o", Arg.Set_string outputdir, "OUTPUTDIR Set output directory";
"--packager-config", Arg.Set_string packager_config, "CONFIGFILE Set packager config file";
"--prepare", Arg.Unit set_prepare_mode, " Prepare a supermin appliance";
+ "--size", Arg.String set_size, " Set the size of the ext2 filesystem";
"--use-installed", Arg.Set use_installed, " Use installed files instead of accessing network";
"-v", Arg.Unit set_debug, " Enable debugging messages";
"--verbose", Arg.Unit set_debug, ditto;
@@ -165,6 +169,7 @@ let main () =
let packager_config =
match !packager_config with "" -> None | s -> Some s in
let use_installed = !use_installed in
+ let size = !size in
let format =
match mode, !format with
@@ -184,7 +189,7 @@ let main () =
debug, mode, if_newer, inputs, lockfile, outputdir,
(copy_kernel, dtb_wildcard, format, host_cpu,
- packager_config, tmpdir, use_installed) in
+ packager_config, tmpdir, use_installed, size) in
if debug >= 1 then printf "supermin: version: %s\n" Config.package_version;
@@ -192,7 +197,7 @@ let main () =
* This fails with an error if one could not be located.
*)
let () =
- let (_, _, _, _, packager_config, tmpdir, _) = args in
+ let (_, _, _, _, packager_config, tmpdir, _, _) = args in
let settings = {
debug = debug;
tmpdir = tmpdir;
diff --git a/src/supermin.pod b/src/supermin.pod
index f2e8446..f9b7395 100644
--- a/src/supermin.pod
+++ b/src/supermin.pod
@@ -189,6 +189,9 @@ appliance to C<OUTPUTDIR/initrd>, and the ext2 filesystem image to
C<OUTPUTDIR/root>. (Where C<OUTPUTDIR> is specified by the I<-o>
option).
+The filesystem (C<OUTPUTDIR/root>) has a default size of 4 GB
+(see also the I<--size> option).
+
=back
=item B<--host-cpu> CPU
@@ -283,6 +286,18 @@ However this option is useful in some controlled situations: for
example when using supermin inside a freshly installed chroot, or if
you have no network access during the build.
+=item B<--size> SIZE
+
+(I<--build> mode only)
+
+Select the size of the output ext2 filesystem, where the size can be
+specified using common names such as C<32G> (32 gigabytes) etc.
+
+If the size is not specified, a default size of 4 GB is used.
+
+To specify size in bytes, the number must be followed by the lowercase
+letter I<b>, eg: S<C<--size 10737418240b>>.
+
=item B<-v>
=item B<--verbose>
--
2.5.0

View File

@ -0,0 +1,217 @@
From d4615d38b2ccbf47642457887d2f4b1a514ee456 Mon Sep 17 00:00:00 2001
From: Pino Toscano <ptoscano@redhat.com>
Date: Tue, 14 Jul 2015 08:57:44 +0200
Subject: [PATCH 3/7] docs: Use F<> for filenames instead of C<>
---
src/supermin.pod | 60 ++++++++++++++++++++++++++++----------------------------
1 file changed, 30 insertions(+), 30 deletions(-)
diff --git a/src/supermin.pod b/src/supermin.pod
index f9b7395..53d1b11 100644
--- a/src/supermin.pod
+++ b/src/supermin.pod
@@ -46,7 +46,7 @@ For example:
creates a supermin appliance containing the packages C<bash> and
C<coreutils>. Specifically, it creates some files in directory
-C<supermin.d>. This directory I<is> the supermin appliance. (See
+F<supermin.d>. This directory I<is> the supermin appliance. (See
L</SUPERMIN APPLIANCES> below).
It is intended that the I<--prepare> step is done on a central build
@@ -60,8 +60,8 @@ builds the full appliance from the supermin appliance:
supermin --build --format ext2 supermin.d -o appliance.d
-This will create files called C<appliance.d/kernel>,
-C<appliance.d/root> etc, which is the full sized bootable appliance.
+This will create files called F<appliance.d/kernel>,
+F<appliance.d/root> etc, which is the full sized bootable appliance.
It is intended that the I<--build> step is done on the end user's
machine at the last second before the appliance is needed. The
@@ -112,7 +112,7 @@ a separate program called C<supermin-helper>.
(I<--build> mode only)
Copy the kernel (and device tree, if created) instead of symlinking to
-the kernel in C</boot>.
+the kernel in F</boot>.
This is fractionally slower, but is necessary if you want to change
the permissions or SELinux label on the kernel or device tree.
@@ -124,7 +124,7 @@ the permissions or SELinux label on the kernel or device tree.
If specified, search for a device tree which is compatible with the
selected kernel and the name of which matches the given wildcard. You
can use a wildcard such as C<vexpress-*a9*.dtb> which would match
-C<vexpress-v2p-ca9.dtb>.
+F<vexpress-v2p-ca9.dtb>.
Notes:
@@ -170,7 +170,7 @@ Possible formats are:
A directory tree in the host filesystem.
-The filesystem tree is written to C<OUTPUTDIR> (ie. the I<-o> option).
+The filesystem tree is written to F<OUTPUTDIR> (ie. the I<-o> option).
This is called a C<chroot> because you could literally L<chroot(1)>
into this directory afterwards, although it's a better idea to use a
@@ -183,13 +183,13 @@ assumed that you will be running the appliance using the host kernel.
An ext2 filesystem disk image.
-The output kernel is written to C<OUTPUTDIR/kernel>, the device tree
-(if using) to C<OUTPUTDIR/dtb>, a small initramfs which can mount the
-appliance to C<OUTPUTDIR/initrd>, and the ext2 filesystem image to
-C<OUTPUTDIR/root>. (Where C<OUTPUTDIR> is specified by the I<-o>
+The output kernel is written to F<OUTPUTDIR/kernel>, the device tree
+(if using) to F<OUTPUTDIR/dtb>, a small initramfs which can mount the
+appliance to F<OUTPUTDIR/initrd>, and the ext2 filesystem image to
+F<OUTPUTDIR/root>. (Where F<OUTPUTDIR> is specified by the I<-o>
option).
-The filesystem (C<OUTPUTDIR/root>) has a default size of 4 GB
+The filesystem (F<OUTPUTDIR/root>) has a default size of 4 GB
(see also the I<--size> option).
=back
@@ -210,7 +210,7 @@ The output directory is checked and it is I<not> rebuilt unless it
needs to be.
This is done by consulting the dates of the host package database
-(C</var/lib/rpm> etc), the input supermin files, and the output
+(F</var/lib/rpm> etc), the input supermin files, and the output
directory. The operation is only carried out if either the host
package database or the input supermin files are newer than the output
directory.
@@ -248,9 +248,9 @@ B<Any previous contents of the output directory are deleted>, and a
new output directory is created.
The output directory is created (nearly) atomically by constructing a
-temporary directory called something like C<OUTPUTDIR.abc543>, then
+temporary directory called something like F<OUTPUTDIR.abc543>, then
renaming the old output directory (if present) and deleting it, and
-then renaming the temporary directory to C<OUTPUTDIR>. By combining
+then renaming the temporary directory to F<OUTPUTDIR>. By combining
this option with I<--lock> you can ensure that multiple parallel runs
of supermin do not conflict with each other.
@@ -262,10 +262,10 @@ Set the configuration file for the package manager. This allows you
to specify alternate software repositories.
For ArchLinux, this sets the pacman configuration file (default
-C</etc/pacman.conf>). See L<pacman.conf(5)>.
+F</etc/pacman.conf>). See L<pacman.conf(5)>.
For Yum/RPM distributions, this sets the yum configuration file
-(default C</etc/yum.conf>). See L<yum.conf(5)>.
+(default F</etc/yum.conf>). See L<yum.conf(5)>.
=item B<--prepare>
@@ -336,8 +336,8 @@ Print the package name and version number, and exit.
Supermin appliances consist of just enough information to be able to
build an appliance containing the same operating system (Linux
version, distro, release etc) as the host OS. Since the host and
-appliance share many common files such as C</bin/bash> and
-C</lib/libc.so> there is no reason to ship these files in the
+appliance share many common files such as F</bin/bash> and
+F</lib/libc.so> there is no reason to ship these files in the
appliance. They can simply be read from the host on demand when the
appliance is launched. Therefore to save space we just store the
names of the packages we want from the host, and copy those in (plus
@@ -350,20 +350,20 @@ skeleton base image which contains these files and the outline
directory structure.
Therefore the supermin appliance normally consists of at least two
-control files (C<packages> and C<base.tar.gz>).
+control files (F<packages> and F<base.tar.gz>).
=over 4
-=item B<packages>
+=item F<packages>
The list of packages to be copied from the host. Dependencies are
resolved automatically.
The file is plain text, one package name per line.
-=item B<base.tar>
+=item F<base.tar>
-=item B<base.tar.gz>
+=item F<base.tar.gz>
This tar file (which may be compressed) contains the skeleton
filesystem. Mostly it contains directories and a few configuration
@@ -372,7 +372,7 @@ files.
All paths in the tar file should be relative to the root directory of
the appliance.
-=item B<hostfiles>
+=item F<hostfiles>
Any other files that are to be copied from the host. This is a plain
text file with one pathname per line.
@@ -382,7 +382,7 @@ is created, eg:
/etc/yum.repos.d/*.repo
-would copy all of the C<*.repo> files into the appliance.
+would copy all of the F<*.repo> files into the appliance.
Each pathname in the file should start with a C</> character.
@@ -392,7 +392,7 @@ However you may drop one or more of these files into the supermin
appliance directory if you want to copy random unpackaged files into
the full appliance.
-=item B<excludefiles>
+=item F<excludefiles>
A list of filenames, directory names, or wildcards prefixed by C<->
which are excluded from the final appliance.
@@ -427,9 +427,9 @@ directories passed to it. A common layout could look like this:
supermin.d/zz-hostfiles
In this way extra files can be added to the appliance just by creating
-another tar file (C<extra.tar.gz> in the example above) and dropping
+another tar file (F<extra.tar.gz> in the example above) and dropping
it into the directory, and additional host files can be added
-(C<zz-hostfiles> in the example above). When the appliance is
+(F<zz-hostfiles> in the example above). When the appliance is
constructed, the extra files will appear in the appliance.
=head2 MINIMIZING THE SUPERMIN APPLIANCE
@@ -481,7 +481,7 @@ then you should do something like this:
=head2 ENFORCING AVAILABILITY OF PACKAGES
Supermin builds the appliance by copying in the packages listed in
-C<packages>. For this to work those packages must be available. We
+F<packages>. For this to work those packages must be available. We
usually enforce this by adding requirements (eg. RPM C<Requires:>
lines) on the package that uses the supermin appliance, so that
package cannot be installed without pulling in the dependent packages
@@ -497,14 +497,14 @@ If this environment variable is set, then automatic selection of the
kernel is bypassed and this kernel is used.
The environment variable should point to a kernel file,
-eg. C</boot/vmlinuz-3.0.x86_64>
+eg. F</boot/vmlinuz-3.0.x86_64>
=item SUPERMIN_MODULES
This specifies the kernel modules directory to use.
The environment variable should point to a module directory,
-eg. C</lib/modules/3.0.x86_64/>
+eg. F</lib/modules/3.0.x86_64/>
=item SUPERMIN_DTB
--
2.5.0

View File

@ -0,0 +1,25 @@
From f7707b743152b96af204e7ef55b33fca7d91bab0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 Oct 2015 12:42:05 +0100
Subject: [PATCH 4/7] rpm: rpm_is_available function can be "noalloc".
---
src/librpm.ml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/librpm.ml b/src/librpm.ml
index dc80286..4eeba77 100644
--- a/src/librpm.ml
+++ b/src/librpm.ml
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
-external rpm_is_available : unit -> bool = "supermin_rpm_is_available"
+external rpm_is_available : unit -> bool = "supermin_rpm_is_available" "noalloc"
external rpm_version : unit -> string = "supermin_rpm_version"
external rpm_vercmp : string -> string -> int = "supermin_rpm_vercmp" "noalloc"
--
2.5.0

View File

@ -0,0 +1,62 @@
From 9515c554ca9e725c4094cbbcd9f37bb316a2529f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 Oct 2015 12:48:03 +0100
Subject: [PATCH 5/7] rpm: Add some documentation to librpm.mli.
---
src/librpm.mli | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/librpm.mli b/src/librpm.mli
index da73911..5229be6 100644
--- a/src/librpm.mli
+++ b/src/librpm.mli
@@ -16,17 +16,28 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)
+(** Wrappers around [librpm] functions. *)
+
val rpm_is_available : unit -> bool
+(** Returns [true] iff librpm is supported. If this returns [false],
+ then all other functions will abort. *)
val rpm_version : unit -> string
+(** The linked version of librpm. *)
+
val rpm_vercmp : string -> string -> int
+(** Compare two RPM version strings using RPM version compare rules. *)
type t
+(** The librpm handle. *)
exception Multiple_matches of int
val rpm_open : ?debug:int -> t
+(** Open the librpm (transaction set) handle. *)
val rpm_close : t -> unit
+(** Explicitly close the handle. The handle can also be closed by
+ the garbage collector if it becomes unreachable. *)
type rpm_t = {
name : string;
@@ -44,6 +55,16 @@ type rpmfile_t = {
| FileConfig
val rpm_installed : t -> string -> rpm_t array
+(** Return the list of packages matching the name
+ (similar to [rpm -q name]). *)
+
val rpm_pkg_requires : t -> string -> string array
+(** Return the requires of a package (similar to [rpm -qR]). *)
+
val rpm_pkg_whatprovides : t -> string -> string array
+(** Return what package(s) provide a particular requirement
+ (similar to [rpm -q --whatprovides]). *)
+
val rpm_pkg_filelist : t -> string -> rpmfile_t array
+(** Return the list of files contained in a package, and attributes of
+ those files (similar to [rpm -ql]). *)
--
2.5.0

View File

@ -0,0 +1,82 @@
From a843495409d2d1cf1cd966470b57d336d7ad04d4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 Oct 2015 13:40:56 +0100
Subject: [PATCH 6/7] rpm: Flush debugging messages in C code.
Because C and OCaml use different implementations of stdio, and
because C stdout is not line-buffered, we can get mixed up debugging
messages.
Partially fix this by using fflush (stdout) after printing C debugging
messages (this doesn't completely fix it because we'd have to do the
same in OCaml code too).
This slows down debugging output, but it's only used when debugging so
we don't care about that.
---
src/librpm-c.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/librpm-c.c b/src/librpm-c.c
index fc847d6..3bd25a2 100644
--- a/src/librpm-c.c
+++ b/src/librpm-c.c
@@ -202,8 +202,11 @@ supermin_rpm_installed (value rpmv, value pkgv)
caml_raise_not_found ();
count = rpmdbGetIteratorCount (iter);
- if (data.debug >= 2)
- printf ("supermin: rpm: installed: %d occurrences for '%s'\n", count, String_val (pkgv));
+ if (data.debug >= 2) {
+ printf ("supermin: rpm: installed: %d occurrences for '%s'\n",
+ count, String_val (pkgv));
+ fflush (stdout);
+ }
rv = caml_alloc (count, 0);
i = 0;
@@ -287,8 +290,11 @@ supermin_rpm_pkg_requires (value rpmv, value pkgv)
caml_raise_not_found ();
count = rpmdbGetIteratorCount (iter);
- if (data.debug >= 2)
- printf ("supermin: rpm: pkg_requires: %d occurrences for '%s'\n", count, String_val (pkgv));
+ if (data.debug >= 2) {
+ printf ("supermin: rpm: pkg_requires: %d occurrences for '%s'\n",
+ count, String_val (pkgv));
+ fflush (stdout);
+ }
if (count != 1)
librpm_raise_multiple_matches (count);
@@ -351,8 +357,11 @@ supermin_rpm_pkg_whatprovides (value rpmv, value pkgv)
caml_raise_not_found ();
count = rpmdbGetIteratorCount (iter);
- if (data.debug >= 2)
- printf ("supermin: rpm: pkg_whatprovides: %d occurrences for '%s'\n", count, String_val (pkgv));
+ if (data.debug >= 2) {
+ printf ("supermin: rpm: pkg_whatprovides: %d occurrences for '%s'\n",
+ count, String_val (pkgv));
+ fflush (stdout);
+ }
rv = caml_alloc (count, 0);
i = 0;
@@ -398,8 +407,11 @@ supermin_rpm_pkg_filelist (value rpmv, value pkgv)
caml_raise_not_found ();
count = rpmdbGetIteratorCount (iter);
- if (data.debug >= 2)
- printf ("supermin: rpm: pkg_filelist: %d occurrences for '%s'\n", count, String_val (pkgv));
+ if (data.debug >= 2) {
+ printf ("supermin: rpm: pkg_filelist: %d occurrences for '%s'\n",
+ count, String_val (pkgv));
+ fflush (stdout);
+ }
if (count != 1)
librpm_raise_multiple_matches (count);
--
2.5.0

View File

@ -0,0 +1,123 @@
From 17b724b5d345f5e9d622bcadf27c57baa102bbba Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 Oct 2015 13:42:57 +0100
Subject: [PATCH 7/7] rpm: Choose providers better (RHBZ#1266918).
In the referenced bug, a customer had installed a web browser called
'palemoon'. The RPM of this web browser provides and requires various
core libraries, such as:
Provides: libnss3.so()(64bit) # normally provided by 'nss'
Requires: libxul.so()(64bit) # normally provided by 'firefox'
Our previous algorithm -- inherited from the days when we used to run
'rpm' commands -- takes every provider of a particular requirement and
adds it to a big list, so if any other package requires
'libnss3.so()(64bit)', then both 'nss' and 'palemoon' are added to the
package list.
Yum used to handle this differently - it used to only pick the package
with the shortest name. Later on, before yum was retired, it had a
more complex decision algorithm described here:
http://yum.baseurl.org/wiki/CompareProviders
This change makes supermin use the shortest name algorithm, so in the
case above, it always picks 'nss' over 'palemoon'.
There is a second possible problem which is not fixed by the current
patch set: If a package both provides and requires the same
dependency, we should ignore that dependency. For example, 'palemoon'
both Provides and Requires 'libxul.so()(64bit)', so if 'palemoon' is
pulled in, then 'firefox' would not be an additional requirement.
Because we store all the packages in a big list, we lose track of
where a dependency originates from, so it is not easy to implement
this second change.
---
src/rpm.ml | 64 ++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 48 insertions(+), 16 deletions(-)
diff --git a/src/rpm.ml b/src/rpm.ml
index 4d31472..1db47b6 100644
--- a/src/rpm.ml
+++ b/src/rpm.ml
@@ -210,8 +210,51 @@ let rpm_package_name pkg =
let rpm_get_package_database_mtime () =
(lstat "/var/lib/rpm/Packages").st_mtime
-(* Memo of resolved provides. *)
-let rpm_providers = Hashtbl.create 13
+(* Return the best provider of a particular RPM requirement.
+ *
+ * There may be multiple, or no providers. In case there are multiple,
+ * choose the one with the shortest name (as yum used to).
+ *
+ * We could do better here: http://yum.baseurl.org/wiki/CompareProviders
+ *)
+let provider =
+ (* Memo of resolved provides. *)
+ let rpm_providers = Hashtbl.create 13 in
+ fun req ->
+ try Hashtbl.find rpm_providers req
+ with Not_found ->
+ let ret =
+ try
+ (* 'providers' here is an array of just package names. *)
+ let providers = rpm_pkg_whatprovides (get_rpm ()) req in
+ let providers = Array.to_list providers in
+ (* --whatprovides will return duplicate identical packages, so: *)
+ let providers = sort_uniq providers in
+ (* Only packages which are actually installed: *)
+ let providers =
+ List.filter (fun name -> rpm_package_of_string name <> None)
+ providers in
+
+ match providers with
+ | [] -> None
+ | [name] ->
+ Some name
+ | names ->
+ if !settings.debug >= 2 then
+ printf "supermin: rpm: multiple providers: requirement %s: providers: %s\n"
+ req (String.concat " " names);
+ let cmp name1 name2 =
+ let len1 = String.length name1 and len2 = String.length name2 in
+ if len1 <> len2 then compare len1 len2
+ else compare name1 name2 in
+ let names = List.sort cmp names in
+ let best_name = List.hd names in
+ if !settings.debug >= 2 then
+ printf "supermin: rpm: multiple providers: picked %s\n" best_name;
+ Some best_name
+ with Not_found -> None in
+ Hashtbl.add rpm_providers req ret;
+ ret
let rpm_get_all_requires pkgs =
let get pkg =
@@ -226,20 +269,9 @@ let rpm_get_all_requires pkgs =
rpm_pkg_requires (get_rpm ()) (rpm_package_to_string pkg) in
let pkgs' = Array.fold_left (
fun set x ->
- try
- let provides =
- try Hashtbl.find rpm_providers x
- with Not_found ->
- let p = rpm_pkg_whatprovides (get_rpm ()) x in
- Hashtbl.add rpm_providers x p;
- p in
- Array.fold_left (
- fun newset p ->
- match rpm_package_of_string p with
- | None -> newset
- | Some x -> StringSet.add p newset
- ) set provides
- with Not_found -> set
+ match provider x with
+ | None -> set
+ | Some p -> StringSet.add p set
) StringSet.empty reqs in
pkgs'
in
--
2.5.0

View File

@ -6,7 +6,7 @@
Summary: Tool for creating supermin appliances
Name: supermin
Version: 5.1.13
Release: 3%{?dist}
Release: 4%{?dist}
License: GPLv2+
%if 0%{?rhel} >= 7
@ -16,6 +16,15 @@ ExclusiveArch: x86_64
URL: http://people.redhat.com/~rjones/supermin/
Source0: http://libguestfs.org/download/supermin/%{name}-%{version}.tar.gz
# All upstream patches since 5.1.13.
Patch0001: 0001-utils-import-parse_size-from-libguestfs.patch
Patch0002: 0002-Add-size-for-ext2-filesystem.patch
Patch0003: 0003-docs-Use-F-for-filenames-instead-of-C.patch
Patch0004: 0004-rpm-rpm_is_available-function-can-be-noalloc.patch
Patch0005: 0005-rpm-Add-some-documentation-to-librpm.mli.patch
Patch0006: 0006-rpm-Flush-debugging-messages-in-C-code.patch
Patch0007: 0007-rpm-Choose-providers-better-RHBZ-1266918.patch
BuildRequires: /usr/bin/pod2man
BuildRequires: rpm
BuildRequires: rpm-devel
@ -85,6 +94,7 @@ from supermin appliances.
%prep
%setup -q
%autopatch -p1
%build
@ -128,6 +138,11 @@ make check || {
%changelog
* Tue Oct 13 2015 Richard W.M. Jones <rjones@redhat.com> - 5.1.13-4
- Pull in all upstream patches since 5.1.13.
- Choose providers better (RHBZ#1266918).
- Use autopatch.
* Mon Jul 27 2015 Richard W.M. Jones <rjones@redhat.com> - 5.1.13-3
- Bump version to rebuild against new RPM in Rawhide.