added ESP command line option

This commit is contained in:
Florian Schroegendorfer 2024-06-04 02:07:17 +02:00
parent 126e35a91e
commit 0e9d9f4727
Signed by: root
GPG Key ID: 17625E28D4D6E339
6 changed files with 140 additions and 74 deletions

View File

@ -27,7 +27,7 @@ The following variables will be used throughout this description:
`version` - new kernel's version string
### <p>configure<span style="float:right">`ekernel-configure`</span></p>
### `ekernel-configure`
Runs `make menuconfig` if the current config file is missing, or no other kernel is installed
@ -58,7 +58,7 @@ cd ${new}
make oldconfig || exit
```
### <p>build<span style="float:right">`ekernel-build`</span></p>
### `ekernel-build`
Build and install modules, using the given number of jobs.
@ -66,7 +66,7 @@ Build and install modules, using the given number of jobs.
make -j ${jobs} && make modules_install
```
### <p>install<span style="float:right">`ekernel-install`</span></p>
### `ekernel-install`
Update symlink ``/usr/src/linux`` to the new source directory.
@ -88,18 +88,7 @@ Rebuild external modules.
emerge @module-rebuild
```
### <p>commit<span style="float:right">`ekernel-commit`</span></p>
Commit the new kernel config with a detailed commit message.
```sh
git add -f /usr/src/linux/.config
git commit -S -m "${msg}"
```
The message will not only contain the version change, but also details about the newly added or removed options.
### <p>clean<span style="float:right">`ekernel-clean`</span></p>
### `ekernel-clean`
Remove unused kernel source directories, modules and boot images.
@ -113,9 +102,20 @@ rm -rf $(ls -1 ${esp} | sed -e '/${old}/d' -e '/${new}/d' -e '/bootx64/d')
The default is to keep the previous kernel version in case something goes
horribly wrong.
### `ekernel-commit`
Commit the new kernel config with a detailed commit message.
```sh
git add -f /usr/src/linux/.config
git commit -S -m "${msg}"
```
The message will not only contain the version change, but also details about the newly added or removed options.
## Installation
TODO: add ebuild `app-admin/ekernel`
You may use the ebuild `app-admin/ekernel` from my [personal repository](https://github.com/phlo/phlo-portage).
## Requirements

View File

@ -41,15 +41,12 @@ class Kernel:
# kernel source symlink
linux = src / "linux"
# EFI system partition
esp = pathlib.Path("/boot/EFI/Gentoo")
# boot image
bootx64 = esp / "bootx64.efi"
# module directory
modules = pathlib.Path("/lib/modules")
# EFI system partition
esp = pathlib.Path("/boot/EFI/Gentoo")
def __init__ (self, src):
"""Construct a Kernel based on a given source path."""
self.src = pathlib.Path(src)
@ -61,6 +58,7 @@ class Kernel:
raise ValueError(f"illegal source: {src}") from e
self.config = self.src / ".config"
self.bzImage = self.src / "arch/x86_64/boot/bzImage"
self.bootx64 = self.esp / "bootx64.efi"
self.efi = self.esp / f"gentoo-{self.version.base_version}.efi"
self.modules = self.modules / f"{self.version.base_version}-gentoo"
@ -76,8 +74,8 @@ class Kernel:
f"* src = {self.src}\n"
f"* config = {self.config}\n"
f"* bzImage = {self.bzImage}\n"
f"* efi = {self.efi}\n"
f"* modules = {self.modules}\n"
f"* efi = {self.efi}\n"
)
@classmethod
@ -211,9 +209,9 @@ def configure (argv):
parser.add_argument(
"-s",
metavar="<src>",
dest="kernel",
type=Kernel,
default=Kernel.latest(),
dest="src",
type=pathlib.Path,
default=Kernel.latest().src,
help="kernel source directory (default: latest)"
)
parser.add_argument(
@ -223,8 +221,9 @@ def configure (argv):
help="be quiet"
)
args = parser.parse_args(argv)
kernel = Kernel(args.src)
out.quiet = args.quiet
newoptions = args.kernel.src / ".newoptions"
newoptions = kernel.src / ".newoptions"
# check if current kernel config exists
try:
@ -233,18 +232,18 @@ def configure (argv):
oldconfig = Kernel.esp / "FILENOTFOUND"
# change to source directory
os.chdir(args.kernel.src)
os.chdir(kernel.src)
# delete config - reconfigure
if args.delete and args.kernel.config.exists():
out.einfo(f"deleting {args.kernel.config}")
args.kernel.config.unlink()
if args.delete and kernel.config.exists():
out.einfo(f"deleting {kernel.config}")
kernel.config.unlink()
# make oldconfig
if not args.kernel.config.exists() and oldconfig.exists():
if not kernel.config.exists() and oldconfig.exists():
# copy oldconfig
out.einfo(f"copying {out.hilite(oldconfig)}")
shutil.copy(oldconfig, args.kernel.config)
shutil.copy(oldconfig, kernel.config)
# store newly added options
out.einfo(f"running {out.hilite('make listnewconfig')}")
make = subprocess.run(["make", "listnewconfig"], capture_output=True)
@ -313,9 +312,9 @@ def build (argv):
parser.add_argument(
"-s",
metavar="<src>",
dest="kernel",
type=Kernel,
default=Kernel.latest(),
dest="src",
type=pathlib.Path,
default=Kernel.latest().src,
help="kernel source directory (default: latest)"
)
parser.add_argument(
@ -325,17 +324,18 @@ def build (argv):
help="be quiet"
)
args = parser.parse_args(argv)
kernel = Kernel(args.src)
out.quiet = args.quiet
# check if config exists
if not args.kernel.config.exists():
raise FileNotFoundError(f"missing config: {args.kernel.config}")
if not kernel.config.exists():
raise FileNotFoundError(f"missing config: {kernel.config}")
# change directory
os.chdir(args.kernel.src)
os.chdir(kernel.src)
# build and install modules
out.einfo(f"building {out.hilite(args.kernel.src.name)}")
out.einfo(f"building {out.hilite(kernel.src.name)}")
subprocess.run(["make", "-j", str(args.jobs)], check=True)
out.einfo("installing modules")
subprocess.run(["make", "modules_install"], check=True)
@ -353,6 +353,9 @@ def install (argv):
Command Line Arguments
----------------------
``-e <esp>``
EFI bootloader directory (default: ``/boot/EFI/Gentoo``)
``-s <src>``
kernel source directory (default: latest)
@ -379,12 +382,19 @@ def install (argv):
description="Install a kernel.",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"-e",
metavar="<esp>",
dest="esp",
type=pathlib.Path,
help="EFI bootloader directory (default: /boot/EFI/Gentoo)"
)
parser.add_argument(
"-s",
metavar="<src>",
dest="kernel",
type=Kernel,
default=Kernel.latest(),
dest="src",
type=pathlib.Path,
default=Kernel.latest().src,
help="kernel source directory (default: latest)"
)
parser.add_argument(
@ -394,29 +404,31 @@ def install (argv):
help="be quiet"
)
args = parser.parse_args(argv)
if args.esp: Kernel.esp = args.esp
kernel = Kernel(args.src)
out.quiet = args.quiet
# check if bzImage exists
if not args.kernel.bzImage.exists():
raise FileNotFoundError(f"missing bzImage {args.kernel.bzImage}")
if not kernel.bzImage.exists():
raise FileNotFoundError(f"missing bzImage {kernel.bzImage}")
# update symlink to the new source directory
out.einfo(
"updating symlink "
f"{out.hilite(args.kernel.linux)}{out.hilite(args.kernel.src)}"
f"{out.hilite(kernel.linux)}{out.hilite(kernel.src)}"
)
subprocess.run(
["eselect", "kernel", "set", args.kernel.src.name],
["eselect", "kernel", "set", kernel.src.name],
check=True
)
# copy boot image
out.einfo(f"creating boot image {out.hilite(args.kernel.bootx64)}")
shutil.copy(args.kernel.bzImage, args.kernel.bootx64)
out.einfo(f"creating boot image {out.hilite(kernel.bootx64)}")
shutil.copy(kernel.bzImage, kernel.bootx64)
# create backup
out.einfo(f"creating backup image {out.hilite(args.kernel.efi)}")
shutil.copy(args.kernel.bzImage, args.kernel.efi)
out.einfo(f"creating backup image {out.hilite(kernel.efi)}")
shutil.copy(kernel.bzImage, kernel.efi)
# rebuild external modules
out.einfo(f"rebuilding external kernel modules")
@ -437,6 +449,9 @@ def clean (argv):
Command Line Arguments
----------------------
``-e <esp>``
EFI bootloader directory (default: ``/boot/EFI/Gentoo``)
``-k <num>``
keep the previous ``<num>`` kernels (default: 1)
@ -452,6 +467,14 @@ def clean (argv):
description="Remove unused kernel leftovers.",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"-e",
metavar="<esp>",
dest="esp",
type=pathlib.Path,
default=Kernel.esp,
help="EFI bootloader directory (default: /boot/EFI/Gentoo)"
)
parser.add_argument(
"-k",
metavar="<keep>",
@ -473,6 +496,7 @@ def clean (argv):
help="be quiet"
)
args = parser.parse_args(argv)
if args.esp: Kernel.esp = args.esp
out.quiet = args.quiet
if args.keep < 0:
raise ValueError("invalid int value: must be greater equal zero")
@ -739,15 +763,20 @@ def update (argv):
metavar="<jobs>",
dest="jobs",
type=int,
default=int(jobs),
help=f"number of parallel make jobs (default: {jobs})"
)
parser.add_argument(
"-e",
metavar="<esp>",
dest="esp",
type=pathlib.Path,
help="EFI bootloader directory (default: /boot/EFI/Gentoo)"
)
parser.add_argument(
"-s",
metavar="<src>",
dest="kernel",
type=Kernel,
default=Kernel.latest(),
dest="src",
type=pathlib.Path,
help="kernel source directory (default: latest)"
)
parser.add_argument(
@ -755,7 +784,6 @@ def update (argv):
metavar="<keep>",
dest="keep",
type=int,
default=1,
help="keep the previous <num> bootable kernels (default: 1)"
)
parser.add_argument(
@ -763,7 +791,6 @@ def update (argv):
metavar="<msg>",
dest="msg",
type=str,
default="",
help="additional information for the commit message"
)
parser.add_argument(
@ -773,14 +800,15 @@ def update (argv):
help="be quiet"
)
args = parser.parse_args(argv)
args.jobs = ["-j", str(args.jobs)]
args.src = ["-s", str(args.kernel.src)]
args.keep = ["-k", str(args.keep)]
args.msg = ["-m", args.msg]
args.jobs = ["-j", str(args.jobs)] if args.jobs else []
args.esp = ["-e", str(args.esp)] if args.esp else []
args.src = ["-s", str(args.src)] if args.src else []
args.keep = ["-k", str(args.keep)] if args.keep is not None else []
args.msg = ["-m", args.msg] if args.msg else []
args.quiet = ["-q"] if args.quiet else []
configure(args.quiet + args.src)
build(args.quiet + args.jobs + args.src)
install(args.quiet + args.src)
clean(args.quiet + args.keep)
install(args.quiet + args.esp + args.src)
clean(args.quiet + args.esp + args.keep)
commit(args.quiet + args.msg)

View File

@ -24,13 +24,6 @@ esp = root / "boot/EFI/Gentoo"
# boot image
bootx64 = esp / "bootx64.efi"
# change Kernel class' root directory
Kernel.src = src
Kernel.linux = linux
Kernel.modules = modules
Kernel.esp = esp
Kernel.bootx64 = bootx64
# list of installed kernels
kernels = []
sources = [
@ -80,6 +73,13 @@ def setup ():
for p in root.glob("*"):
shutil.rmtree(p)
# change Kernel class' root directory
Kernel.src = src
Kernel.linux = linux
Kernel.modules = modules
Kernel.esp = esp
Kernel.bootx64 = bootx64
# create EFI system partition
esp.mkdir(parents=True)

View File

@ -93,6 +93,19 @@ class Tests (unittest.TestCase):
self.assertEqual(run("-q", "-k", "10"), 0)
self.check_clean(10)
def test_clean_esp (self):
esp = data.root / "boot/EFI/linux"
esp.mkdir(parents=True)
for k in data.kernels:
efi = esp / k.efi.name
if k.efi.exists():
efi.touch()
k.efi.unlink()
k.efi = efi
data.esp.rmdir()
self.assertEqual(run("-q", "-e", str(esp)), 0)
self.check_clean()
@colorless
@capture_stdout
def test_clean_dry_run (self):

View File

@ -24,6 +24,8 @@ class Tests (unittest.TestCase):
self.interceptor.start()
# setup test environment
data.setup()
self.kernel = Kernel.latest()
self.kernel.bzImage.touch()
def tearDown (self):
# stop interceptor
@ -55,19 +57,25 @@ class Tests (unittest.TestCase):
self.assertTrue(self.kernel.efi.exists())
def test_install (self):
self.kernel = Kernel.latest()
self.kernel.bzImage.touch()
self.assertEqual(run("-q"), 0)
self.check_install()
def test_install_version (self):
def test_install_esp (self):
esp = data.root / "boot/EFI/linux"
esp.mkdir(parents=True)
self.kernel.efi = esp / self.kernel.efi.name
self.kernel.bootx64 = esp / self.kernel.bootx64.name
self.assertEqual(run("-q", "-e", str(esp)), 0)
self.check_install()
def test_install_source (self):
self.kernel = Kernel.current()
self.assertEqual(run("-q", "-s", str(data.current)), 0)
self.check_install()
@capture_stderr
def test_install_missing_bzImage (self):
self.kernel = Kernel.latest()
self.kernel.bzImage.unlink()
with self.assertRaises(SystemExit):
self.assertEqual(run("-s", str(data.latest)), 1)
self.assertRegex(sys.stderr.getvalue(), r"missing.*bzImage")

View File

@ -81,6 +81,21 @@ class Tests (unittest.TestCase):
self.assertEqual(run("-q", "-j", "8"), 0)
self.check_update()
def test_update_esp (self):
esp = data.root / "boot/EFI/linux"
esp.mkdir(parents=True)
for k in data.kernels:
efi = esp / k.efi.name
if k.efi.exists():
efi.touch()
k.efi.unlink()
k.efi = efi
data.esp.rmdir()
self.latest.efi = esp / self.latest.efi.name
self.latest.bootx64 = esp / self.latest.bootx64.name
self.assertEqual(run("-q", "-e", str(esp)), 0)
self.check_update()
def test_update_source (self):
self.assertEqual(run("-q", "-s", str(data.latest)), 0)
self.check_update()
@ -90,6 +105,8 @@ class Tests (unittest.TestCase):
self.assertEqual(run("-q", "-k", "0"), 0)
self.check_update()
self.assertFalse(current.src.exists())
self.assertFalse(current.modules.exists())
self.assertFalse(current.efi.exists())
@capture_stdout
def test_update_message (self):