Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/user_interaction/partitioning_conf.py
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2022-05-28 10:36:38 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2022-05-28 10:36:38 +0200
commitfaf925de1882be722d2994d697a802918282e509 (patch)
tree4856c76b10b36e94875ce3c9add961960bb23bf0 /archinstall/lib/user_interaction/partitioning_conf.py
parent3801bee921d22e23435c781c469d9ec0adfa00bd (diff)
parent78449f75bc44f0e2b03cb9d909b9b78e4f7ca4c8 (diff)
Merge branch 'upstreamMaster'
Diffstat (limited to 'archinstall/lib/user_interaction/partitioning_conf.py')
-rw-r--r--archinstall/lib/user_interaction/partitioning_conf.py171
1 files changed, 106 insertions, 65 deletions
diff --git a/archinstall/lib/user_interaction/partitioning_conf.py b/archinstall/lib/user_interaction/partitioning_conf.py
index af1d224f..bfff5705 100644
--- a/archinstall/lib/user_interaction/partitioning_conf.py
+++ b/archinstall/lib/user_interaction/partitioning_conf.py
@@ -1,12 +1,13 @@
from __future__ import annotations
-from typing import List, Any, Dict, Union, TYPE_CHECKING, Callable
+import copy
+from typing import List, Any, Dict, Union, TYPE_CHECKING, Callable, Optional
from ..menu import Menu
+from ..menu.menu import MenuSelectionType
from ..output import log
from ..disk.validators import fs_types
-from ..disk.helpers import has_mountpoint
if TYPE_CHECKING:
from ..disk import BlockDevice
@@ -19,9 +20,9 @@ def partition_overlap(partitions: list, start: str, end: str) -> bool:
return False
-def _current_partition_layout(partitions: List[Partition], with_idx: bool = False) -> str:
+def current_partition_layout(partitions: List[Dict[str, Any]], with_idx: bool = False, with_title: bool = True) -> str:
- def do_padding(name, max_len):
+ def do_padding(name: str, max_len: int):
spaces = abs(len(str(name)) - max_len) + 2
pad_left = int(spaces / 2)
pad_right = spaces - pad_left
@@ -61,39 +62,54 @@ def _current_partition_layout(partitions: List[Partition], with_idx: bool = Fals
current_layout += f'{row[:-1]}\n'
- title = str(_('Current partition layout'))
- return f'\n\n{title}:\n\n{current_layout}'
+ if with_title:
+ title = str(_('Current partition layout'))
+ return f'\n\n{title}:\n\n{current_layout}'
+ return current_layout
-def select_partition(title :str, partitions :List[Partition], multiple :bool = False, filter :Callable = None) -> Union[int, List[int], None]:
+
+def _get_partitions(partitions :List[Partition], filter_ :Callable = None) -> List[str]:
"""
filter allows to filter out the indexes once they are set. Should return True if element is to be included
"""
partition_indexes = []
for i in range(len(partitions)):
- if filter:
- if filter(partitions[i]):
+ if filter_:
+ if filter_(partitions[i]):
partition_indexes.append(str(i))
else:
partition_indexes.append(str(i))
+
+ return partition_indexes
+
+
+def select_partition(
+ title :str,
+ partitions :List[Partition],
+ multiple :bool = False,
+ filter_ :Callable = None
+) -> Optional[int, List[int]]:
+ partition_indexes = _get_partitions(partitions, filter_)
+
if len(partition_indexes) == 0:
return None
- # old code without filter
- # partition_indexes = list(map(str, range(len(partitions))))
- partition = Menu(title, partition_indexes, multi=multiple).run()
+ choice = Menu(title, partition_indexes, multi=multiple).run()
- if partition is not None:
- if isinstance(partition, list):
- return [int(p) for p in partition]
- else:
- return int(partition)
+ if choice.type_ == MenuSelectionType.Esc:
+ return None
- return None
+ if isinstance(choice.value, list):
+ return [int(p) for p in choice.value]
+ else:
+ return int(choice.value)
-def get_default_partition_layout(block_devices: Union['BlockDevice', List['BlockDevice']],
- advanced_options: bool = False) -> Dict[str, Any]:
+def get_default_partition_layout(
+ block_devices: Union['BlockDevice', List['BlockDevice']],
+ advanced_options: bool = False
+) -> Optional[Dict[str, Any]]:
from ..disk import suggest_single_disk_layout, suggest_multi_disk_layout
if len(block_devices) == 1:
@@ -107,14 +123,15 @@ def select_individual_blockdevice_usage(block_devices: list) -> Dict[str, Any]:
for device in block_devices:
layout = manage_new_and_existing_partitions(device)
-
result[device.path] = layout
return result
-def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str, Any]: # noqa: max-complexity: 50
+def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str, Any]: # noqa: max-complexity: 50
block_device_struct = {"partitions": [partition.__dump__() for partition in block_device.partitions.values()]}
+ original_layout = copy.deepcopy(block_device_struct)
+
# Test code: [part.__dump__() for part in block_device.partitions.values()]
# TODO: Squeeze in BTRFS subvolumes here
@@ -129,11 +146,13 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
mark_bootable = str(_('Mark/Unmark a partition as bootable (automatic for /boot)'))
set_filesystem_partition = str(_('Set desired filesystem for a partition'))
set_btrfs_subvolumes = str(_('Set desired subvolumes on a btrfs partition'))
+ save_and_exit = str(_('Save and exit'))
+ cancel = str(_('Cancel'))
while True:
modes = [new_partition, suggest_partition_layout]
- if len(block_device_struct['partitions']):
+ if len(block_device_struct['partitions']) > 0:
modes += [
delete_partition,
delete_all_partitions,
@@ -143,20 +162,31 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
mark_bootable,
mark_compressed,
set_filesystem_partition,
- set_btrfs_subvolumes,
]
+ indexes = _get_partitions(
+ block_device_struct["partitions"],
+ filter_=lambda x: True if x.get('filesystem', {}).get('format') == 'btrfs' else False
+ )
+
+ if len(indexes) > 0:
+ modes += [set_btrfs_subvolumes]
+
title = _('Select what to do with\n{}').format(block_device)
# show current partition layout:
if len(block_device_struct["partitions"]):
- title += _current_partition_layout(block_device_struct['partitions']) + '\n'
+ title += current_partition_layout(block_device_struct['partitions']) + '\n'
- task = Menu(title, modes, sort=False).run()
+ modes += [save_and_exit, cancel]
- if not task:
- break
+ task = Menu(title, modes, sort=False, skip=False).run()
+ task = task.value
+ if task == cancel:
+ return original_layout
+ elif task == save_and_exit:
+ break
if task == new_partition:
from ..disk import valid_parted_position
@@ -165,7 +195,10 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
# # https://www.gnu.org/software/parted/manual/html_node/mklabel.html
# name = input("Enter a desired name for the partition: ").strip()
- fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types(), skip=False).run()
+ fs_choice = Menu(_('Enter a desired filesystem type for the partition'), fs_types()).run()
+
+ if fs_choice.type_ == MenuSelectionType.Esc:
+ continue
prompt = _('Enter the start sector (percentage or block number, default: {}): ').format(
block_device.first_free_sector)
@@ -197,7 +230,7 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
"mountpoint": None,
"wipe": True,
"filesystem": {
- "format": fstype
+ "format": fs_choice.value
}
})
else:
@@ -208,18 +241,15 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
from ..disk import suggest_single_disk_layout
if len(block_device_struct["partitions"]):
- prompt = _('{} contains queued partitions, this will remove those, are you sure?').format(block_device)
- choice = Menu(prompt, ['yes', 'no'], default_option='no').run()
+ prompt = _('{}\ncontains queued partitions, this will remove those, are you sure?').format(block_device)
+ choice = Menu(prompt, Menu.yes_no(), default_option=Menu.no(), skip=False).run()
- if choice == 'no':
+ if choice.value == Menu.no():
continue
block_device_struct.update(suggest_single_disk_layout(block_device)[block_device.path])
-
- elif task is None:
- return block_device_struct
else:
- current_layout = _current_partition_layout(block_device_struct['partitions'], with_idx=True)
+ current_layout = current_partition_layout(block_device_struct['partitions'], with_idx=True)
if task == delete_partition:
title = _('{}\n\nSelect by index which partitions to delete').format(current_layout)
@@ -243,15 +273,14 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
block_device_struct["partitions"][partition]["filesystem"]["mount_options"].append("compress=zstd")
elif task == delete_all_partitions:
block_device_struct["partitions"] = []
+ block_device_struct["wipe"] = True
elif task == assign_mount_point:
title = _('{}\n\nSelect by index which partition to mount where').format(current_layout)
partition = select_partition(title, block_device_struct["partitions"])
if partition is not None:
- print(
- _(' * Partition mount-points are relative to inside the installation, the boot would be /boot as an example.'))
- mountpoint = input(
- _('Select where to mount partition (leave blank to remove mountpoint): ')).strip()
+ print(_(' * Partition mount-points are relative to inside the installation, the boot would be /boot as an example.'))
+ mountpoint = input(_('Select where to mount partition (leave blank to remove mountpoint): ')).strip()
if len(mountpoint):
block_device_struct["partitions"][partition]['mountpoint'] = mountpoint
@@ -273,14 +302,13 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
if not block_device_struct["partitions"][partition].get('filesystem', None):
block_device_struct["partitions"][partition]['filesystem'] = {}
- fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types(),
- skip=False).run()
+ fs_choice = Menu(_('Enter a desired filesystem type for the partition'), fs_types()).run()
- block_device_struct["partitions"][partition]['filesystem']['format'] = fstype
+ if fs_choice.type_ == MenuSelectionType.Selection:
+ block_device_struct["partitions"][partition]['filesystem']['format'] = fs_choice.value
# Negate the current wipe marking
- block_device_struct["partitions"][partition][
- 'wipe'] = not block_device_struct["partitions"][partition].get('wipe', False)
+ block_device_struct["partitions"][partition]['wipe'] = not block_device_struct["partitions"][partition].get('wipe', False)
elif task == mark_encrypted:
title = _('{}\n\nSelect which partition to mark as encrypted').format(current_layout)
@@ -288,16 +316,16 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
if partition is not None:
# Negate the current encryption marking
- block_device_struct["partitions"][partition][
- 'encrypted'] = not block_device_struct["partitions"][partition].get('encrypted', False)
+ block_device_struct["partitions"][partition]['encrypted'] = \
+ not block_device_struct["partitions"][partition].get('encrypted', False)
elif task == mark_bootable:
title = _('{}\n\nSelect which partition to mark as bootable').format(current_layout)
partition = select_partition(title, block_device_struct["partitions"])
if partition is not None:
- block_device_struct["partitions"][partition][
- 'boot'] = not block_device_struct["partitions"][partition].get('boot', False)
+ block_device_struct["partitions"][partition]['boot'] = \
+ not block_device_struct["partitions"][partition].get('boot', False)
elif task == set_filesystem_partition:
title = _('{}\n\nSelect which partition to set a filesystem on').format(current_layout)
@@ -308,16 +336,18 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
block_device_struct["partitions"][partition]['filesystem'] = {}
fstype_title = _('Enter a desired filesystem type for the partition: ')
- fstype = Menu(fstype_title, fs_types(), skip=False).run()
+ fs_choice = Menu(fstype_title, fs_types()).run()
- block_device_struct["partitions"][partition]['filesystem']['format'] = fstype
+ if fs_choice.type_ == MenuSelectionType.Selection:
+ block_device_struct["partitions"][partition]['filesystem']['format'] = fs_choice.value
elif task == set_btrfs_subvolumes:
from .subvolume_config import SubvolumeList
# TODO get preexisting partitions
title = _('{}\n\nSelect which partition to set subvolumes on').format(current_layout)
- partition = select_partition(title, block_device_struct["partitions"],filter=lambda x:True if x.get('filesystem',{}).get('format') == 'btrfs' else False)
+ partition = select_partition(title, block_device_struct["partitions"],filter_=lambda x:True if x.get('filesystem',{}).get('format') == 'btrfs' else False)
+
if partition is not None:
if not block_device_struct["partitions"][partition].get('btrfs', {}):
block_device_struct["partitions"][partition]['btrfs'] = {}
@@ -333,19 +363,30 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
return block_device_struct
+def select_encrypted_partitions(
+ title :str,
+ partitions :List[Partition],
+ multiple :bool = True,
+ filter_ :Callable = None
+) -> Optional[int, List[int]]:
+ partition_indexes = _get_partitions(partitions, filter_)
-def select_encrypted_partitions(block_devices: dict, password: str) -> dict:
- for device in block_devices:
- for partition in block_devices[device]['partitions']:
- if partition.get('mountpoint', None) != '/boot':
- partition['encrypted'] = True
- partition['!password'] = password
+ if len(partition_indexes) == 0:
+ return None
+
+ title = _('Select which partitions to mark for formatting:')
- if not has_mountpoint(partition,'/'):
- # Tell the upcoming steps to generate a key-file for non root mounts.
- partition['generate-encryption-key-file'] = True
+ # show current partition layout:
+ if len(partitions):
+ title += current_partition_layout(partitions) + '\n'
- return block_devices
+ choice = Menu(title, partition_indexes, multi=multiple).run()
- # TODO: Next version perhaps we can support mixed multiple encrypted partitions
- # Users might want to single out a partition for non-encryption to share between dualboot etc.
+ if choice.type_ == MenuSelectionType.Esc:
+ return None
+
+ if isinstance(choice.value, list):
+ for partition_index in choice.value:
+ yield int(partition_index)
+ else:
+ yield (partition_index)