]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
arch: better package selection 223/head
authorGeorges Discry <georges@discry.be>
Tue, 23 Jan 2018 23:52:41 +0000 (00:52 +0100)
committerGeorges Discry <georges@discry.be>
Sat, 10 Feb 2018 11:17:32 +0000 (12:17 +0100)
The package selection for Arch Linux is not optimal, especially when the
image is not bootable. The main issue is that a kernel is still
installed when the image is not bootable.

Optional packages from the `base` group that are required under specific
configurations are first deleted from the package selection and
explicitly re-added when required. For example, the `cryptsetup` and
`device-mapper` packages are included only if the image is bootable and
encrypted.  Similarly, a kernel is included only if the image is
bootable or if the user selected one explicitly.

Sets are now better used in the package selection. The appropriate
operators and methods are directly used instead of relying on
intermediary sets.

The installation of the packages is split into two operations. The first
only installs the packages from the `base` group and the second installs
the packages selected by the user. This is necessary because some
packages (e.g. `git`) have an install script that depends on the `base`
group without listing those in their dependencies. If they are installed
before their implicit dependency, their install script will most likely
fail.

mkosi

diff --git a/mkosi b/mkosi
index 9a01832a796abf947237a47142221fb8bb1386e7..99567c5466c54ebacd13bd6a9ce7a88b66585e7e 100755 (executable)
--- a/mkosi
+++ b/mkosi
@@ -1394,53 +1394,60 @@ SigLevel    = Required DatabaseOptional
 
     run_pacman(["-Sy"])
     # determine base packages list from base group
-    c = run_pacman(["-Sg", "base"], stdout=PIPE, universal_newlines=True)
+    c = run_pacman(["-Sqg", "base"], stdout=PIPE, universal_newlines=True)
     packages = set(c.stdout.split())
-    packages.remove("base")
+    packages -= {
+        "cryptsetup",
+        "device-mapper",
+        "dhcpcd",
+        "e2fsprogs",
+        "jfsutils",
+        "linux",
+        "lvm2",
+        "man-db",
+        "man-pages",
+        "mdadm",
+        "netctl",
+        "pcmciautils",
+        "reiserfsprogs",
+        "xfsprogs",
+    }
 
-    official_kernel_packages = [
+    official_kernel_packages = {
         "linux",
         "linux-lts",
         "linux-hardened",
-        "linux-zen"
-    ]
-
-    kernel_packages = {"linux"}
-    if args.packages:
-        kernel_packages = set.intersection(set(args.packages), set(official_kernel_packages))
-        # prefer user-specified packages over implicit base kernel
-        if kernel_packages and "linux" not in kernel_packages:
-            packages.remove("linux")
-        if len(kernel_packages) > 1:
-            warn('More than one kernel will be installed: {}', ' '.join(kernel_packages))
-
-    packages -= {"device-mapper",
-                 "dhcpcd",
-                 "e2fsprogs",
-                 "jfsutils",
-                 "lvm2",
-                 "man-db",
-                 "man-pages",
-                 "mdadm",
-                 "netctl",
-                 "pcmciautils",
-                 "reiserfsprogs",
-                 "xfsprogs"}
+        "linux-zen",
+    }
+    kernel_packages = official_kernel_packages.intersection(args.packages)
+    packages |= kernel_packages
+    if len(kernel_packages) > 1:
+        warn('More than one kernel will be installed: {}', ' '.join(kernel_packages))
 
     if args.bootable:
         if args.output_format == OutputFormat.raw_gpt:
             packages.add("e2fsprogs")
         elif args.output_format == OutputFormat.raw_btrfs:
             packages.add("btrfs-progs")
-    else:
-        packages -= kernel_packages
-
-    packages |= set(args.packages)
+        if args.encrypt:
+            packages.add("cryptsetup")
+            packages.add("device-mapper")
+        if not kernel_packages:
+            # No user-specified kernel
+            packages.add("linux")
+
+    # Set up system with packages from the base group
+    run_pacstrap(packages)
 
+    # Install the user-specified packages
+    packages = set(args.packages)
     if run_build_script:
-        packages |= set(args.build_packages)
-
-    run_pacstrap(packages)
+        packages.update(args.build_packages)
+    # Remove already installed packages
+    c = run_pacman(['-Qq'], stdout=PIPE, universal_newlines=True)
+    packages.difference_update(c.stdout.split())
+    if packages:
+        run_pacstrap(packages)
 
     # Kill the gpg-agent used by pacman and pacman-key
     run(['gpg-connect-agent', '--homedir', os.path.join(root, 'etc/pacman.d/gnupg'), 'KILLAGENT', '/bye'])