internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: archlinux/archinstall

Issue:
[master] Booting encrypted installation is missing `/sbin/init`.
![screenshot](https://user-images.githubusercontent.com/861439/170537967-88f66aaa-09a2-475e-8bd9-779b098455ae.png)



Discussion:
Works with un-encrypted.
`/sbin/init` is symlinked to `/lib/systemd/systemd` but that isn't available on the encrypted volume o0
Because `/dev/mapper/luksdev` is mounted to `/new_root` o0
![screenshot](https://user-images.githubusercontent.com/861439/170540608-0d6e2062-f913-4159-96c5-e0091cb2a051.png)

The reason is because the btrfs root volume `@/` doesn't get mounted, instead `<FS_TREE>` get mounted to `/` and under it is `@`. I'm looking in to it.

Resolving patch:
diff --git a/archinstall/lib/disk/btrfs/btrfs_helpers.py b/archinstall/lib/disk/btrfs/btrfs_helpers.py
--- a/archinstall/lib/disk/btrfs/btrfs_helpers.py
+++ b/archinstall/lib/disk/btrfs/btrfs_helpers.py
@@ -112,8 +112,8 @@ def subvolume_info_from_path(path :pathlib.Path) -> Optional[BtrfsSubvolume]:
 
 		return BtrfsSubvolume(**{'full_path' : path, 'name' : subvolume_name, **result})
 
-	except SysCallError:
-		pass
+	except SysCallError as error:
+		log(f"Could not retrieve subvolume information from {path}: {error}", level=logging.WARNING, fg="orange")
 
 	return None
 
diff --git a/archinstall/lib/disk/mapperdev.py b/archinstall/lib/disk/mapperdev.py
--- a/archinstall/lib/disk/mapperdev.py
+++ b/archinstall/lib/disk/mapperdev.py
@@ -77,7 +77,8 @@ def filesystem(self) -> Optional[str]:
 	@property
 	def subvolumes(self) -> Iterator['BtrfsSubvolume']:
 		from .btrfs import subvolume_info_from_path
-		
+
 		for mountpoint in self.mount_information:
-			if subvolume := subvolume_info_from_path(mountpoint):
-				yield subvolume
\ No newline at end of file
+			if target := mountpoint.get('target'):
+				if subvolume := subvolume_info_from_path(pathlib.Path(target)):
+					yield subvolume
\ No newline at end of file


Test patch:
Repository: archlinux/archinstall

Issue:
[critical] master installation failure: 'MapperDev' object has no attribute parent
installation video: https://www.youtube.com/watch?v=P-ZpZne7Pks

Installation: BIOS system on KVM, wiping whole drive, encryption on. Problem: /boot is errantly encrypted and is a mapper device. This causes bootloader installation to fail.

![image](https://user-images.githubusercontent.com/277927/170831869-aeda5d62-3e55-4d54-b9ee-2cdd4b496432.png)



Discussion:

Resolving patch:
diff --git a/archinstall/lib/menu/global_menu.py b/archinstall/lib/menu/global_menu.py
--- a/archinstall/lib/menu/global_menu.py
+++ b/archinstall/lib/menu/global_menu.py
@@ -206,8 +206,9 @@ def exit_callback(self):
 				for blockdevice in storage['arguments']['disk_layouts']:
 					if storage['arguments']['disk_layouts'][blockdevice].get('partitions'):
 						for partition_index in select_encrypted_partitions(
-								title="Select which partitions to encrypt:",
-								partitions=storage['arguments']['disk_layouts'][blockdevice]['partitions']
+								title=_('Select which partitions to encrypt:'),
+								partitions=storage['arguments']['disk_layouts'][blockdevice]['partitions'],
+								filter_=(lambda p: p['mountpoint'] != '/boot')
 							):
 
 							partition = storage['arguments']['disk_layouts'][blockdevice]['partitions'][partition_index]
diff --git a/archinstall/lib/user_interaction/partitioning_conf.py b/archinstall/lib/user_interaction/partitioning_conf.py
--- a/archinstall/lib/user_interaction/partitioning_conf.py
+++ b/archinstall/lib/user_interaction/partitioning_conf.py
@@ -376,7 +376,7 @@ def select_encrypted_partitions(
 
 	# show current partition layout:
 	if len(partitions):
-		title += current_partition_layout(partitions) + '\n'
+		title += current_partition_layout(partitions, with_idx=True) + '\n'
 
 	choice = Menu(title, partition_indexes, multi=multiple).run()
 


Test patch:
Repository: archlinux/archinstall

Issue:
Unknown device when using erofs 
archiso supports (and it's the default in the baseline profile) erofs fs type for the airrootfs (https://github.com/demostanis/demolinux/blob/e2800eed332fde1dbc4bccab4e9aa0668a9dd683/profiledef.sh#L14).
When using archinstall, this yields to the warning `Unknown device found by all_blockdevices(), ignoring: {'/dev/loop0': ...`
An additional check should be made at https://github.com/archlinux/archinstall/blob/33ce7dbd8baf5402a20e850f503390b9c229e698/archinstall/lib/disk/helpers.py#L247


Discussion:
Good catch, want to make a PR for it so you get credit?

Resolving patch:
diff --git a/archinstall/lib/disk/helpers.py b/archinstall/lib/disk/helpers.py
--- a/archinstall/lib/disk/helpers.py
+++ b/archinstall/lib/disk/helpers.py
@@ -244,7 +244,7 @@ def all_blockdevices(mappers=False, partitions=False, error=False) -> Dict[str,
 					instances[path] = Partition(path, block_device=BlockDevice(get_parent_of_partition(pathlib.Path(path))))
 			elif path_info.get('PTTYPE', False) is not False or path_info.get('TYPE') == 'loop':
 				instances[path] = BlockDevice(path, path_info)
-			elif path_info.get('TYPE') == 'squashfs':
+			elif path_info.get('TYPE') in ('squashfs', 'erofs'):
 				# We can ignore squashfs devices (usually /dev/loop0 on Arch ISO)
 				continue
 			else:


Test patch:
Repository: archlinux/archinstall

Issue:
Archinstall discover shop non-functional.
Hello,

I have installed Arch with archinstall twice now, selected the desktop option then KDE but I noticed that by default the "Discover" shop does not want to function I have to download the packagekit-qt5 package then it functions. Just wanted to let you know.


Archinstall discover shop non-functional.
Hello,

I have installed Arch with archinstall twice now, selected the desktop option then KDE but I noticed that by default the "Discover" shop does not want to function I have to download the packagekit-qt5 package then it functions. Just wanted to let you know.




Discussion:
thank you, i think we fixed this in master but ill double check :)
thank you, i think we fixed this in master but ill double check :)

Resolving patch:
diff --git a/profiles/kde.py b/profiles/kde.py
--- a/profiles/kde.py
+++ b/profiles/kde.py
@@ -13,6 +13,7 @@
 	"sddm",
 	"plasma-wayland-session",
 	"egl-wayland",
+	"packagekit-qt5",
 ]
 
 


Test patch:
Repository: archlinux/archinstall

Issue:
Please remove packagekit from GNOME profile
Speaking as the maintainer of GNOME on Arch, please remove packagekit from the `gnome` profile.

It's split out from the rest of gnome-software for a reason - packagekit is utterly unsupported. I've never seen it work reliably and it breaks our assumptions about user attention during upgrades.


Discussion:
You would know better than anyone else if it's okay to ship this package. https://archlinux.org/packages/extra/x86_64/gnome-software-packagekit-plugin/ I see you maintain it. It's a shame that without this the GNOME Software app doesn't work at all though, and users get the impression that their system is broken.
GNOME Software works just fine for installing from Flathub.
> GNOME Software works just fine for installing from Flathub.

I am aware that this works (assuming flatpak is installed and Flathub is configured as a source). However, a large collection of software is available in the Arch repos, and by not having it listed in gnome-software, the discoverability and ease of installation of this software is reduced.
I'd rather our users not break their systems by using packagekit.
> I'd rather our users not break their systems by using packagekit.

I had no idea it was that bad on Arch Linux. I will make a pull request to remove it and do the same for KDE as well

Resolving patch:
diff --git a/profiles/gnome.py b/profiles/gnome.py
--- a/profiles/gnome.py
+++ b/profiles/gnome.py
@@ -8,8 +8,7 @@
 __packages__ = [
 	"gnome",
 	"gnome-tweaks",
-	"gdm",
-	"gnome-software-packagekit-plugin",
+	"gdm"
 ]
 
 
diff --git a/profiles/kde.py b/profiles/kde.py
--- a/profiles/kde.py
+++ b/profiles/kde.py
@@ -12,8 +12,7 @@
 	"ark",
 	"sddm",
 	"plasma-wayland-session",
-	"egl-wayland",
-	"packagekit-qt5",
+	"egl-wayland"
 ]
 
 


Test patch:
Repository: archlinux/archinstall

Issue:
archinstall won't start due to TypeError
# Error
When I execute `archinstall` I get the following error:

```
...
File "/usr/lib/python3.10/site-packages/archinstall/lib/packages/packages.py", line 115, in installed_package
  return LocalPackage(**package_info)
TypeError: LocalPackage.__init__() got an unexpected keyword argument 'warning'
```
# What I tried
I looked at the code of `installed_package` and found it executes `pacman -Q --info {package}`, so I tried to execute that with archlinux-keyring to see what the output was like.

I executed `pacman -Q --info archlinux-keyring` and got the following output
```
warning: config file /etc/pacman.conf, line 19: directive 'SyncFirst' in section 'options' not recognized
Name 	: archlinux-keyring
Version : 20230225-1
...
```
# Why this seems to be happening
## Code
https://github.com/archlinux/archinstall/blob/8f6cc07062968b259bebd346521ef685c16f89dc/archinstall/lib/packages/packages.py#L105-L115
## Explanation 
Because the line `warning: config file /etc/pacman.conf, line 19: directive 'SyncFirst' in section 'options' not recognized` I get as part of the output of `pacman -Q --info {package}` has a colon it is being interpreted as a key value pair.

# Possible fix
Ignore all lines that start with 'warning'




Discussion:

Resolving patch:
diff --git a/archinstall/lib/packages/packages.py b/archinstall/lib/packages/packages.py
--- a/archinstall/lib/packages/packages.py
+++ b/archinstall/lib/packages/packages.py
@@ -1,3 +1,4 @@
+import dataclasses
 import json
 import ssl
 from typing import Dict, Any, Tuple, List
@@ -112,4 +113,4 @@ def installed_package(package :str) -> LocalPackage:
 	except SysCallError:
 		pass
 
-	return LocalPackage(**package_info)
+	return LocalPackage({field.name: package_info.get(field.name) for field in dataclasses.fields(LocalPackage)})


Test patch:
Repository: archlinux/archinstall

Issue:
Exit code of `SysCommand()` is exit status indication
The `exit_code` of a `SysCommand()` call is not an exit code but an exit status indication. [1] An exit status indication is "a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced." [2]

Below is an example of how to use `os.waitstatus_to_exitcode()` [3] to obtain the exit code. In the example, `grep` is executed without any arguments and so it returns an exit code of `2`. [4]

```python
import os
import pty

pid, fd = pty.fork()

if pid == 0:
    os.execv('/usr/bin/grep', ['grep'])
else:
    pid, wait_status = os.waitpid(pid, 0)
    exit_code = os.waitstatus_to_exitcode(wait_status)
    print(f'wait status: {wait_status}')
    print(f'exit code: {exit_code}')
```

**Output:**

```
wait status: 512
exit code: 2
```

### Findings

- Relevant lines of code in archinstall:

https://github.com/archlinux/archinstall/blob/f0a6adb96dd388d62b2f6683709a8e310e6727c8/archinstall/lib/general.py#L357-L361

- Exit code in archinstall error message:

```
>>> import archinstall
>>> archinstall.SysCommand('grep')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
...
archinstall.lib.exceptions.SysCallError: ['/usr/bin/grep'] exited with abnormal exit code [512]: b"Usage: grep [OPTION]... PATTERNS [FILE]...\r\nTry 'grep --help' for more information.\r\n"
```

- Exit code on the command line:

```
$ grep
Usage: grep [OPTION]... PATTERNS [FILE]...
Try 'grep --help' for more information.
$ echo $?
2
```

[1] https://docs.python.org/3/library/os.html#os.waitpid
[2] https://docs.python.org/3/library/os.html#os.wait
[3] https://docs.python.org/3/library/os.html#os.waitstatus_to_exitcode
[4] https://man.archlinux.org/man/grep.1#EXIT_STATUS


Discussion:
Good catch! This will be fixed asap!

Resolving patch:
diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py
--- a/archinstall/lib/general.py
+++ b/archinstall/lib/general.py
@@ -355,10 +355,12 @@ def poll(self) -> None:
 			if self.ended or (got_output is False and pid_exists(self.pid) is False):
 				self.ended = time.time()
 				try:
-					self.exit_code = os.waitpid(self.pid, 0)[1]
+					wait_status = os.waitpid(self.pid, 0)[1]
+					self.exit_code = os.waitstatus_to_exitcode(wait_status)
 				except ChildProcessError:
 					try:
-						self.exit_code = os.waitpid(self.child_fd, 0)[1]
+						wait_status = os.waitpid(self.child_fd, 0)[1]
+						self.exit_code = os.waitstatus_to_exitcode(wait_status)
 					except ChildProcessError:
 						self.exit_code = 1
 


Test patch:
Repository: archlinux/archinstall

Issue:
Installation guide change: Use `pacstrap -K`
Add `-K` option to `pacstrap` call.

### ArchWiki edit summary

> [→‎Install essential packages](https://wiki.archlinux.org/title/Installation_guide#Install_essential_packages): use pacstrap -K to generate a new pacman master key instead of copying it from the host, this avoids issues if the host's keyring was created when the time/timezone was incorrect and should generally be considered "safer"; see [Talk:Installation guide#Use pacstrap -K](https://wiki.archlinux.org/title/Talk:Installation_guide#Use_pacstrap_-K)

### ArchWiki diff

https://wiki.archlinux.org/index.php?title=Installation_guide&diff=750948&oldid=741457

### Relevant code

https://github.com/archlinux/archinstall/blob/126f56169d6faacd492b0b0f10c18762cf42a2ba/archinstall/lib/installer.py#L399


Discussion:
This has been implemented. 
> This has been implemented.

it has? oÔ
No it has not.

https://github.com/archlinux/archinstall/blob/79eb6bba627c4c70f24a265ac0b2ef9cbfbbd211/archinstall/lib/installer.py#L421

@Torxed, should this change be made?

> No it has not.
> 
> https://github.com/archlinux/archinstall/blob/79eb6bba627c4c70f24a265ac0b2ef9cbfbbd211/archinstall/lib/installer.py#L421
> 
> @Torxed, should this change be made?

Oh yeah! You're right. It hasn't been implemented. 
> No it has not.
> 
> https://github.com/archlinux/archinstall/blob/79eb6bba627c4c70f24a265ac0b2ef9cbfbbd211/archinstall/lib/installer.py#L421
> 
> @Torxed, should this change be made?

It looks like it's the recommended way, so let's do it and see how it behaves :)

Resolving patch:
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -418,7 +418,7 @@ def pacstrap(self, *packages :str, **kwargs :str) -> bool:
 			raise RequirementError(f'Could not sync mirrors: {error}', level=logging.ERROR, fg="red")
 
 		try:
-			return SysCommand(f'/usr/bin/pacstrap -C /etc/pacman.conf {self.target} {" ".join(packages)} --noconfirm', peek_output=True).exit_code == 0
+			return SysCommand(f'/usr/bin/pacstrap -C /etc/pacman.conf -K {self.target} {" ".join(packages)} --noconfirm', peek_output=True).exit_code == 0
 		except SysCallError as error:
 			self.log(f'Could not strap in packages: {error}', level=logging.ERROR, fg="red")
 


Test patch:
Repository: archlinux/archinstall

Issue:
Logic errors in `_fetch_lsblk_info()`
The for loop here will cause the `lsblk` command to be called as many times as specified by the retry parameter. It does not break out of the loop if there is a success. In addition, if all tries fail the last try does not need a sleep.

https://github.com/archlinux/archinstall/blob/00b0ae7ba439a5a420095175b3bedd52c569db51/archinstall/lib/disk/device_model.py#L979-L989

The `get_lsblk_info()` function calls `_fetch_lsblk_info()` without the retry argument.

https://github.com/archlinux/archinstall/blob/00b0ae7ba439a5a420095175b3bedd52c569db51/archinstall/lib/disk/device_model.py#L1004-L1008

The retry parameter will then default to 3.

https://github.com/archlinux/archinstall/blob/00b0ae7ba439a5a420095175b3bedd52c569db51/archinstall/lib/disk/device_model.py#L967

This means that when `get_lsblk_info()` is called, if the `lsblk` command is working fine (exit code of 0) then the command will be called unnecessarily 2 additional times.


Discussion:

Resolving patch:
diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py
--- a/archinstall/lib/disk/device_model.py
+++ b/archinstall/lib/disk/device_model.py
@@ -974,32 +974,33 @@ def _fetch_lsblk_info(dev_path: Optional[Union[Path, str]] = None, retry: int =
 	if retry == 0:
 		retry = 1
 
-	result = None
-
-	for i in range(retry):
+	for retry_attempt in range(retry):
 		try:
 			result = SysCommand(f'lsblk --json -b -o+{lsblk_fields} {dev_path}')
+			break
 		except SysCallError as error:
 			# Get the output minus the message/info from lsblk if it returns a non-zero exit code.
 			if error.worker:
 				err = error.worker.decode('UTF-8')
 				log(f'Error calling lsblk: {err}', level=logging.DEBUG)
-				time.sleep(1)
 			else:
 				raise error
 
-	if result and result.exit_code == 0:
-		try:
-			if decoded := result.decode('utf-8'):
-				block_devices = json.loads(decoded)
-				blockdevices = block_devices['blockdevices']
-				return [LsblkInfo.from_json(device) for device in blockdevices]
-		except json.decoder.JSONDecodeError as err:
-			log(f"Could not decode lsblk JSON: {result}", fg="red", level=logging.ERROR)
-			raise err
+			if retry_attempt == retry - 1:
+				raise error
 
-	raise DiskError(f'Failed to read disk "{dev_path}" with lsblk')
+			time.sleep(1)
+
+	try:
+		if decoded := result.decode('utf-8'):
+			block_devices = json.loads(decoded)
+			blockdevices = block_devices['blockdevices']
+			return [LsblkInfo.from_json(device) for device in blockdevices]
+	except json.decoder.JSONDecodeError as err:
+		log(f"Could not decode lsblk JSON: {result}", fg="red", level=logging.ERROR)
+		raise err
 
+	raise DiskError(f'Failed to read disk "{dev_path}" with lsblk')
 
 def get_lsblk_info(dev_path: Union[Path, str]) -> LsblkInfo:
 	if infos := _fetch_lsblk_info(dev_path):


Test patch:
Repository: archlinux/archinstall

Issue:
'Device' object has no attribute 'device_info'
Here is the traceback

```
[!] A log file has been created here: /var/log/archinstall/install.log
    Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues
Traceback (most recent call last):
  File "/usr/bin/archinstall", line 8, in <module>
    sys.exit(run_as_a_module())
             ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/archinstall/__init__.py", line 266, in run_as_a_module
    importlib.import_module(mod_name)
  File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1206, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1178, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1149, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/usr/lib/python3.11/site-packages/archinstall/scripts/guided.py", line 276, in <module>
    perform_installation(archinstall.storage.get('MOUNT_POINT', Path('/mnt')))
  File "/usr/lib/python3.11/site-packages/archinstall/scripts/guided.py", line 135, in perform_installation
    with Installer(
  File "/usr/lib/python3.11/site-packages/archinstall/lib/installer.py", line 137, in __exit__
    raise exc_val
  File "/usr/lib/python3.11/site-packages/archinstall/scripts/guided.py", line 173, in perform_installation
    installation.add_bootloader(archinstall.arguments["bootloader"])
  File "/usr/lib/python3.11/site-packages/archinstall/lib/installer.py", line 1069, in add_bootloader
    self._add_grub_bootloader(boot_partition, root_partition)
  File "/usr/lib/python3.11/site-packages/archinstall/lib/installer.py", line 958, in _add_grub_bootloader
    f' --recheck {device.device_info.path}'
                  ^^^^^^^^^^^^^^^^^^

```

Here's the [log](https://bpa.st/JS2K6)


Discussion:
Yep that's a bug, thanks for reporting

Resolving patch:
diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py
--- a/archinstall/lib/disk/device_handler.py
+++ b/archinstall/lib/disk/device_handler.py
@@ -10,7 +10,7 @@
 from parted import (  # type: ignore
 	Disk, Geometry, FileSystem,
 	PartitionException, DiskLabelException,
-	getAllDevices, freshDisk, Partition,
+	getAllDevices, freshDisk, Partition, Device
 )
 
 from .device_model import (
@@ -103,7 +103,8 @@ def get_device(self, path: Path) -> Optional[BDevice]:
 	def get_device_by_partition_path(self, partition_path: Path) -> Optional[BDevice]:
 		partition = self.find_partition(partition_path)
 		if partition:
-			return partition.disk.device
+			device: Device = partition.disk.device
+			return self.get_device(Path(device.path))
 		return None
 
 	def find_partition(self, path: Path) -> Optional[_PartitionInfo]:


Test patch:
Repository: archlinux/archinstall

Issue:
Incorrect paths used for steps in keyfile creation
From issue #1828 opened by @Reflux0301

### keyfile path

https://github.com/archlinux/archinstall/blob/bc4f80441f4c4c9ba084d4cba29cfaedf30b5490/archinstall/lib/luks.py#L190-L191

❌ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_/.key</code>
✔️ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_.key</code>

### mkdir

https://github.com/archlinux/archinstall/blob/bc4f80441f4c4c9ba084d4cba29cfaedf30b5490/archinstall/lib/luks.py#L201

❌ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_</code>
✔️ <code><i>target_path</i>/etc/cryptsetup-keys.d</code>
### chmod

https://github.com/archlinux/archinstall/blob/bc4f80441f4c4c9ba084d4cba29cfaedf30b5490/archinstall/lib/luks.py#L206

❌ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_</code>
✔️ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_.key</code>

### crypttab

https://github.com/archlinux/archinstall/blob/bc4f80441f4c4c9ba084d4cba29cfaedf30b5490/archinstall/lib/luks.py#L209

❌ <code><i>target_path</i>/etc/cryptsetup-keys.d/_name_/.key</code>
✔️ <code>/etc/cryptsetup-keys.d/_name_.key</code>

### References

- https://wiki.archlinux.org/title/Dm-crypt/System_configuration#Unlocking_with_a_keyfile
- https://wiki.archlinux.org/title/Dm-crypt/Device_encryption#passphrase


Discussion:

Resolving patch:
diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py
--- a/archinstall/lib/luks.py
+++ b/archinstall/lib/luks.py
@@ -187,8 +187,8 @@ def create_keyfile(self, target_path: Path, override: bool = False):
 
 		# Once we store the key as ../xyzloop.key systemd-cryptsetup can
 		# automatically load this key if we name the device to "xyzloop"
-		key_file_path = target_path / 'etc/cryptsetup-keys.d/' / self.mapper_name
-		key_file = key_file_path / '.key'
+		kf_path = Path(f'/etc/cryptsetup-keys.d/{self.mapper_name}.key')
+		key_file = target_path / kf_path.relative_to(kf_path.root)
 		crypttab_path = target_path / 'etc/crypttab'
 
 		if key_file.exists():
@@ -198,15 +198,15 @@ def create_keyfile(self, target_path: Path, override: bool = False):
 			else:
 				info(f'Key file {key_file} already exists, overriding')
 
-		key_file_path.mkdir(parents=True, exist_ok=True)
+		key_file.parent.mkdir(parents=True, exist_ok=True)
 
 		with open(key_file, "w") as keyfile:
 			keyfile.write(generate_password(length=512))
 
-		key_file_path.chmod(0o400)
+		key_file.chmod(0o400)
 
 		self._add_key(key_file)
-		self._crypttab(crypttab_path, key_file, options=["luks", "key-slot=1"])
+		self._crypttab(crypttab_path, kf_path, options=["luks", "key-slot=1"])
 
 	def _add_key(self, key_file: Path):
 		info(f'Adding additional key-file {key_file}')


Test patch: