This commit is contained in:
commit
abe2d6a1b4
14 files changed
+232
-32
No files matched your search
+68
-5
@@ -13,6 +13,9 @@
|
||||
#
|
||||
# Usage: omarchy-iso-test [release/omarchy.iso] [options]
|
||||
#
|
||||
# --keyboard LABEL English (US/UK), Japanese, Japanese (US keyboard), Korean,
|
||||
# or Chinese (Simplified, Pinyin)/(Traditional, Zhuyin).
|
||||
# OMARCHY_PATH must be the source tree used to build the ISO.
|
||||
# --encrypt Drive the encrypted install flow (default: unencrypted)
|
||||
# --region REGION Pick global (default) or cn on the first screen
|
||||
# --provision Drive the deferred-provisioning install flow: no user during install, the
|
||||
@@ -49,12 +52,14 @@ NO_PREVIEW=false
|
||||
SYNC_DIR=""
|
||||
SYNC_ALL=false
|
||||
|
||||
KEYBOARD_LABEL="English (US)"
|
||||
GUEST_USER="omarchy"
|
||||
GUEST_PASSWORD="omarchy"
|
||||
GUEST_HOSTNAME="omarchy-test"
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--keyboard) KEYBOARD_LABEL="$2"; shift ;;
|
||||
--encrypt) ENCRYPT=true ;;
|
||||
--region) REGION="$2"; shift ;;
|
||||
--provision) PROVISION=true ;;
|
||||
@@ -91,6 +96,10 @@ if [[ $REGION != "global" && $REGION != "cn" ]]; then
|
||||
echo "--region must be global or cn, not $REGION" >&2
|
||||
exit 1
|
||||
fi
|
||||
case "$KEYBOARD_LABEL" in
|
||||
"English (US)" | "English (UK)" | "Japanese" | "Japanese (US keyboard)" | "Korean" | "Chinese (Simplified, Pinyin)" | "Chinese (Traditional, Zhuyin)") ;;
|
||||
*) echo "The VM harness cannot type credentials with keyboard: $KEYBOARD_LABEL" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
omarchy-pkg-add qemu-full edk2-ovmf socat imagemagick tesseract tesseract-data-eng tesseract-data-chi_sim
|
||||
|
||||
@@ -110,6 +119,9 @@ OVMF_CODE="/usr/share/edk2/x64/OVMF_CODE.4m.fd"
|
||||
OVMF_VARS_TEMPLATE="/usr/share/edk2/x64/OVMF_VARS.4m.fd"
|
||||
|
||||
BASE_NAME="$(basename "$ISO" .iso)"
|
||||
if [[ $KEYBOARD_LABEL != "English (US)" ]]; then
|
||||
BASE_NAME+="-$(printf '%s' "$KEYBOARD_LABEL" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g')"
|
||||
fi
|
||||
$ENCRYPT && BASE_NAME+="-encrypted"
|
||||
[[ $REGION == "cn" ]] && BASE_NAME+="-cn"
|
||||
$PROVISION && BASE_NAME+="-provision"
|
||||
@@ -637,6 +649,35 @@ audio-panel|meta_l-ctrl-a|omarchy-keyboard-panel|omarchy.audio'
|
||||
|
||||
# ----------------------------------------------------- driving the installer
|
||||
|
||||
select_keyboard() {
|
||||
local label="$1" index direction="down"
|
||||
# gum choose uses arrows, not a searchable text field. Read the same ordered
|
||||
# choices the ISO vendors from the runtime rather than hard-code row numbers.
|
||||
index=$(OMARCHY_TEST_KEYBOARD="$label" python - <<'PYTHON'
|
||||
import os, re
|
||||
from pathlib import Path
|
||||
source = Path(os.environ.get("OMARCHY_PATH", "")) / "install/provisioning/setup-form.sh"
|
||||
if not source.is_file():
|
||||
raise SystemExit("Set OMARCHY_PATH to the source tree used to build this ISO")
|
||||
text = source.read_text()
|
||||
rows = re.search(r"OMARCHY_KEYBOARD_LAYOUTS=\$'(.*?)'\n", text, re.S).group(1).splitlines()
|
||||
labels = [row.split("|")[0] for row in rows]
|
||||
label = os.environ["OMARCHY_TEST_KEYBOARD"]
|
||||
if label not in labels:
|
||||
raise SystemExit(f"Keyboard choice is absent from the ISO source: {label}")
|
||||
print(labels.index(label) - labels.index("English (US)"))
|
||||
PYTHON
|
||||
) || return 1
|
||||
if (( index < 0 )); then
|
||||
direction="up"
|
||||
index=$((-index))
|
||||
fi
|
||||
for (( i = 0; i < index; i++ )); do
|
||||
press "$direction"
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
drive_configurator() {
|
||||
log "Driving the installer wizard"
|
||||
|
||||
@@ -683,7 +724,11 @@ drive_configurator() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
press ret # English (US), or China, is preselected
|
||||
if [[ $KEYBOARD_LABEL != "English (US)" ]]; then
|
||||
select_keyboard "$KEYBOARD_LABEL"
|
||||
capture_console "success-installer-01-selected-keyboard"
|
||||
fi
|
||||
press ret
|
||||
|
||||
# Normal flow: user step comes before disk selection.
|
||||
wait_for_screen "$(region_text "Username" "用户名")" 120
|
||||
@@ -707,7 +752,15 @@ drive_configurator() {
|
||||
press ret
|
||||
|
||||
wait_for_screen "$(region_text "Email address" "邮箱")" 60
|
||||
type_text "test@omarchy.org"
|
||||
type_text "test"
|
||||
if [[ $KEYBOARD_LABEL == "Japanese" ]]; then
|
||||
press bracket_left
|
||||
elif [[ $KEYBOARD_LABEL == "English (UK)" ]]; then
|
||||
press shift-apostrophe
|
||||
else
|
||||
press shift-2
|
||||
fi
|
||||
type_text "omarchy.org"
|
||||
capture_console "success-installer-06-email"
|
||||
press ret
|
||||
|
||||
@@ -768,8 +821,12 @@ drive_provision_owner() {
|
||||
press ret
|
||||
|
||||
wait_for_screen "keyboard layout" 120
|
||||
press down
|
||||
capture_console "success-provision-01-keyboard-layout-uk"
|
||||
if [[ $KEYBOARD_LABEL == "English (US)" ]]; then
|
||||
press down # preserve the harness's default UK provisioning coverage
|
||||
else
|
||||
select_keyboard "$KEYBOARD_LABEL"
|
||||
fi
|
||||
capture_console "success-provision-01-keyboard-layout"
|
||||
press ret
|
||||
|
||||
wait_for_screen "Username" 120
|
||||
@@ -795,7 +852,13 @@ drive_provision_owner() {
|
||||
# Shift+2 as on US); send that keycode so the typed email is correct under
|
||||
# the new layout — itself further proof the deferred keymap took effect.
|
||||
type_text "test"
|
||||
press shift-apostrophe
|
||||
if [[ $KEYBOARD_LABEL == "English (US)" || $KEYBOARD_LABEL == "English (UK)" ]]; then
|
||||
press shift-apostrophe
|
||||
elif [[ $KEYBOARD_LABEL == "Japanese" ]]; then
|
||||
press bracket_left
|
||||
else
|
||||
press shift-2
|
||||
fi
|
||||
type_text "omarchy.org"
|
||||
capture_console "success-provision-04-email"
|
||||
press ret
|
||||
|
||||
@@ -46,11 +46,14 @@ pacman-key --lsign-key 40DFB630FF42BCFFB047046CF0134EE680CAC571
|
||||
pacman --config /configs/pacman-online-${OMARCHY_MIRROR}.conf --noconfirm -Sy omarchy-keyring
|
||||
pacman-key --populate omarchy
|
||||
|
||||
# Append the [omarchy] repo to the container's /etc/pacman.conf so subsequent
|
||||
# tools (notably makepkg in build-omarchy-packages.sh) can resolve omarchy-
|
||||
# only build deps like limine-snapper-sync and limine-mkinitcpio-hook.
|
||||
# Put OPR first in the container too so makepkg resolves the same overrides
|
||||
# as the online installer configuration.
|
||||
if ! grep -q '^\[omarchy\]' /etc/pacman.conf; then
|
||||
awk '/^\[omarchy\]/,/^$/' /configs/pacman-online-${OMARCHY_MIRROR}.conf >> /etc/pacman.conf
|
||||
opr_section=$(awk '/^\[omarchy\]/,/^$/' /configs/pacman-online-${OMARCHY_MIRROR}.conf)
|
||||
awk -v opr="$opr_section" '/^\[core\]/ { print opr; print "" } { print }' \
|
||||
/etc/pacman.conf >/tmp/pacman-opr-first.conf
|
||||
install -m 644 /tmp/pacman-opr-first.conf /etc/pacman.conf
|
||||
rm -f /tmp/pacman-opr-first.conf
|
||||
fi
|
||||
|
||||
# Build locations
|
||||
|
||||
@@ -904,6 +904,8 @@ run_partition_execute() {
|
||||
"bootloader_config": { "bootloader": "Limine", "uki": false, "removable": false },
|
||||
"custom_commands": [],
|
||||
"omarchy_install": {
|
||||
"input_method": "${keyboard_input_method:-none}",
|
||||
"input_xkb_layout": "${keyboard_xkb_layout:-}",
|
||||
"mode": "protected",
|
||||
"region": "$region",
|
||||
"target_mount": "/mnt",
|
||||
@@ -1167,6 +1169,8 @@ if $defer_provisioning; then
|
||||
# their real layout in the OOBE, which re-keys the console and, on encrypted
|
||||
# installs, rebuilds the initramfs so the LUKS prompt matches.
|
||||
keyboard="us"
|
||||
keyboard_input_method="none"
|
||||
keyboard_xkb_layout=""
|
||||
username=""
|
||||
password=""
|
||||
password_hash=""
|
||||
@@ -1249,6 +1253,8 @@ cat <<-_EOF_ >user_configuration.json
|
||||
"bootloader_config": { "bootloader": "Limine", "uki": false, "removable": false },
|
||||
"custom_commands": [],
|
||||
"omarchy_install": {
|
||||
"input_method": "${keyboard_input_method:-none}",
|
||||
"input_xkb_layout": "${keyboard_xkb_layout:-}",
|
||||
"mode": "full_disk",
|
||||
"region": "$region",
|
||||
"defer_provisioning": $defer_provisioning,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ONLY this module imports from archinstall. Everything else uses these helpers.
|
||||
If archinstall's API churns, the blast radius is contained here.
|
||||
|
||||
Tested against archinstall 4.5 (Python 3.14).
|
||||
Tested against archinstall 4.4 (Python 3.14).
|
||||
|
||||
The canonical call sequence (mirrored from archinstall.scripts.guided.py) is:
|
||||
|
||||
@@ -13,7 +13,7 @@ The canonical call sequence (mirrored from archinstall.scripts.guided.py) is:
|
||||
# configs do their own mounting before the Installer context opens.
|
||||
if disk_config.config_type != DiskLayoutType.Pre_mount:
|
||||
inst.mount_ordered_layout()
|
||||
inst.sanity_check(skip_ntp=, skip_wkd=)
|
||||
sanity_check(inst)
|
||||
inst.generate_key_files() # encrypted only
|
||||
inst.set_mirrors(handler, mirror_config, on_target=False)
|
||||
inst.minimal_installation(...) # base + linux pacstrap
|
||||
@@ -214,6 +214,14 @@ def _method_accepts(method, name: str) -> bool:
|
||||
return name in (*positional, *kwonly)
|
||||
|
||||
|
||||
def sanity_check(installer) -> None:
|
||||
"""Archinstall 4.5 removed offline; retain it for older releases."""
|
||||
options = {"skip_ntp": True, "skip_wkd": True}
|
||||
if _method_accepts(installer.sanity_check, "offline"):
|
||||
options["offline"] = True
|
||||
installer.sanity_check(**options)
|
||||
|
||||
|
||||
def _method_accepts_users(method) -> bool:
|
||||
return _method_accepts(method, "users")
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from .keyboard import validate_input_selection
|
||||
|
||||
|
||||
@dataclass
|
||||
class InstallContext:
|
||||
@@ -57,6 +59,8 @@ class InstallContext:
|
||||
kernel = (omarchy_install.get("storage") or {}).get("kernel") or _default_kernel()
|
||||
user_configuration["kernels"] = [kernel]
|
||||
|
||||
validate_input_selection(omarchy_install.get("input_method"), omarchy_install.get("input_xkb_layout", ""))
|
||||
|
||||
# Deferred provisioning: the whole system installs but user creation is deferred to
|
||||
# first boot. Selected by the configurator (omarchy_install.defer_provisioning) or by
|
||||
# an `defer-provisioning` marker file on an autoinstall drive, which also replaces the
|
||||
|
||||
@@ -16,21 +16,31 @@ from pathlib import Path
|
||||
from .command import capture
|
||||
|
||||
|
||||
def configure_keyboard(target: Path, language: str) -> bool:
|
||||
def configure_keyboard(target: Path, language: str, input_method: str | None = None, xkb_layout: str = "") -> bool:
|
||||
"""Write the console keymap into a mounted target without booting it.
|
||||
|
||||
Returns False for layouts localectl doesn't know, matching archinstall:
|
||||
warn and keep the default. Every layout the configurator offers is known;
|
||||
the guard is for the kb_layout an autoinstall drive can name freely.
|
||||
"""
|
||||
validate_input_selection(input_method, xkb_layout)
|
||||
if not language.strip():
|
||||
return True
|
||||
if input_method is None:
|
||||
return True
|
||||
language = "us"
|
||||
|
||||
# Input engines are separate from real console keymaps. The shared picker
|
||||
# uses US for Chinese/Korean and carries its preference in omarchy_install.
|
||||
if input_method is None:
|
||||
input_method = "mozc" if language == "jp106" else "none"
|
||||
|
||||
result = capture(["localectl", "--no-pager", "list-keymaps"])
|
||||
if result.returncode != 0:
|
||||
detail = result.stderr.strip() or "localectl returned an error"
|
||||
raise RuntimeError(f"Unable to list keyboard layouts: {detail}")
|
||||
if language.lower() not in {layout.lower() for layout in result.stdout.splitlines()}:
|
||||
if input_method != "none":
|
||||
raise ValueError(f"Unknown keyboard language: {language}")
|
||||
return False
|
||||
|
||||
# systemd-firstboot --force rewrites vconsole.conf wholesale, dropping the
|
||||
@@ -51,4 +61,15 @@ def configure_keyboard(target: Path, language: str) -> bool:
|
||||
if font:
|
||||
vconsole_path.write_text(vconsole_path.read_text() + font + "\n")
|
||||
|
||||
preference = target / "etc/omarchy/input-method"
|
||||
preference.parent.mkdir(parents=True, exist_ok=True)
|
||||
preference.write_text(f"INPUT_METHOD={input_method}\nXKB_LAYOUT={xkb_layout}\n")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def validate_input_selection(input_method: str | None, xkb_layout: str) -> None:
|
||||
if input_method is not None and input_method not in {"none", "mozc", "hangul", "pinyin", "chewing"}:
|
||||
raise ValueError(f"Unknown input method: {input_method}")
|
||||
if xkb_layout not in {"", "kr"}:
|
||||
raise ValueError(f"Unknown input keyboard layout: {xkb_layout}")
|
||||
@@ -261,10 +261,7 @@ def arch_install_system(ctx: InstallContext) -> None:
|
||||
if not pre_mounted:
|
||||
installer.mount_ordered_layout()
|
||||
|
||||
installer.sanity_check(
|
||||
skip_ntp=True,
|
||||
skip_wkd=True,
|
||||
)
|
||||
arch.sanity_check(installer)
|
||||
|
||||
if not pre_mounted and arch.is_encrypted(config):
|
||||
installer.generate_key_files()
|
||||
@@ -299,7 +296,11 @@ def arch_install_system(ctx: InstallContext) -> None:
|
||||
# use the target kernel instead of the live ISO's kernel.
|
||||
installer.add_additional_packages([f"{kernel}-headers" for kernel in config.kernels])
|
||||
|
||||
if not configure_keyboard(installer.target, kb_layout):
|
||||
if not configure_keyboard(
|
||||
installer.target, kb_layout,
|
||||
ctx.omarchy_install.get("input_method"),
|
||||
ctx.omarchy_install.get("input_xkb_layout", ""),
|
||||
):
|
||||
error(f"Invalid keyboard language specified: {kb_layout}")
|
||||
|
||||
if config.mirror_config:
|
||||
|
||||
@@ -13,6 +13,10 @@ ParallelDownloads = 5
|
||||
SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/edge/$arch
|
||||
|
||||
[core]
|
||||
Server = https://mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
@@ -25,10 +29,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
Server = https://mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/edge/$arch
|
||||
|
||||
[arch-mact2]
|
||||
Server = https://mirror.funami.tech/arch-mact2/os/x86_64
|
||||
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
|
||||
|
||||
@@ -13,6 +13,10 @@ ParallelDownloads = 5
|
||||
SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/rc/$arch
|
||||
|
||||
[core]
|
||||
Server = https://rc-mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
@@ -25,10 +29,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
Server = https://rc-mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/rc/$arch
|
||||
|
||||
[arch-mact2]
|
||||
Server = https://mirror.funami.tech/arch-mact2/os/x86_64
|
||||
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
|
||||
|
||||
@@ -13,6 +13,10 @@ ParallelDownloads = 5
|
||||
SigLevel = Required DatabaseOptional
|
||||
LocalFileSigLevel = Optional
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/stable/$arch
|
||||
|
||||
[core]
|
||||
Server = https://stable-mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
@@ -25,10 +29,6 @@ Include = /etc/pacman.d/mirrorlist
|
||||
Server = https://stable-mirror.omarchy.org/$repo/os/$arch
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://pkgs.omarchy.org/stable/$arch
|
||||
|
||||
[arch-mact2]
|
||||
Server = https://mirror.funami.tech/arch-mact2/os/x86_64
|
||||
Server = https://github.com/NoaHimesaka1873/arch-mact2-mirror/releases/download/release
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
mkdir -p "$work/install/provisioning"
|
||||
cat > "$work/install/provisioning/setup-form.sh" <<'FORM'
|
||||
OMARCHY_KEYBOARD_LAYOUTS=$'Chinese (Simplified, Pinyin)|us|pinyin
|
||||
English (US)|us
|
||||
Japanese|jp106|mozc'
|
||||
FORM
|
||||
export OMARCHY_PATH="$work"
|
||||
eval "$(sed -n '/^select_keyboard() {$/,/^}$/p' "$ROOT/bin/omarchy-iso-test")"
|
||||
press() { pressed+=("$1"); }
|
||||
sleep() { :; }
|
||||
|
||||
pressed=()
|
||||
select_keyboard "Japanese"
|
||||
[[ ${pressed[*]} == "down" ]]
|
||||
pressed=()
|
||||
select_keyboard "Chinese (Simplified, Pinyin)"
|
||||
[[ ${pressed[*]} == "up" ]]
|
||||
pressed=()
|
||||
select_keyboard "English (US)"
|
||||
(( ${#pressed[@]} == 0 ))
|
||||
if (set -e; select_keyboard "Missing") 2>"$work/error"; then
|
||||
echo "Unknown keyboard unexpectedly succeeded" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -q 'Keyboard choice is absent' "$work/error"
|
||||
echo "ok - VM keyboard choices are relative to the default and reject absent rows"
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Exercise the compatibility boundary without importing host archinstall."""
|
||||
import ast
|
||||
from pathlib import Path
|
||||
import types
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
source = ROOT / "configs/airootfs/usr/share/omarchy-iso/orchestrator/archinstall_adapter.py"
|
||||
tree = ast.parse(source.read_text())
|
||||
namespace = {}
|
||||
functions = [node for node in tree.body if isinstance(node, ast.FunctionDef) and node.name in {"_method_accepts", "sanity_check"}]
|
||||
exec(compile(ast.Module(body=functions, type_ignores=[]), str(source), "exec"), namespace)
|
||||
|
||||
|
||||
class SanityCheckTest(unittest.TestCase):
|
||||
def test_legacy_archinstall_stays_offline(self):
|
||||
calls = []
|
||||
def check(offline=False, skip_ntp=False, skip_wkd=False):
|
||||
calls.append((offline, skip_ntp, skip_wkd))
|
||||
namespace["sanity_check"](types.SimpleNamespace(sanity_check=check))
|
||||
self.assertEqual(calls, [(True, True, True)])
|
||||
|
||||
def test_archinstall_45_does_not_receive_removed_argument(self):
|
||||
calls = []
|
||||
class Installer:
|
||||
def sanity_check(self, skip_ntp=False, skip_wkd=False):
|
||||
calls.append((skip_ntp, skip_wkd))
|
||||
namespace["sanity_check"](Installer())
|
||||
self.assertEqual(calls, [(True, True)])
|
||||
@@ -108,7 +108,7 @@ class KernelSelectionTest(unittest.TestCase):
|
||||
)
|
||||
ctx = types.SimpleNamespace(
|
||||
state={"arch_config_handler": types.SimpleNamespace(config=config), "mirror_handler": None},
|
||||
target=Path("/unused"), tailscale_authkey_path=None,
|
||||
target=Path("/unused"), tailscale_authkey_path=None, omarchy_install={},
|
||||
)
|
||||
for name in ("_mount_offline_package_cache", "_mask_mkinitcpio_pacman_hooks",
|
||||
"_configure_limine_boot", "_write_pre_mounted_fstab"):
|
||||
@@ -121,6 +121,7 @@ class KernelSelectionTest(unittest.TestCase):
|
||||
stack.enter_context(mock.patch.object(phases_impl, "_runtime_package_list", return_value=["omarchy"]))
|
||||
stack.enter_context(mock.patch.object(phases_impl.arch, "is_pre_mount", return_value=True, create=True))
|
||||
stack.enter_context(mock.patch.object(phases_impl.arch, "root_user", return_value=None, create=True))
|
||||
stack.enter_context(mock.patch.object(phases_impl.arch, "sanity_check", create=True))
|
||||
opened = stack.enter_context(mock.patch.object(phases_impl.arch, "open_installer", create=True))
|
||||
opened.return_value.__enter__.return_value = installer
|
||||
if fail_headers:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
@@ -17,6 +18,7 @@ from orchestrator import keyboard as KEYBOARD # noqa: E402
|
||||
# wherever this checkout can see a runtime, and skip the coverage test rather
|
||||
# than fail when none is around (a bare CI checkout of just this repo).
|
||||
SETUP_FORM_CANDIDATES = (
|
||||
Path(os.environ.get("OMARCHY_PATH", "/nonexistent")) / "install/provisioning/setup-form.sh",
|
||||
Path("/omarchy-source/install/provisioning/setup-form.sh"),
|
||||
ROOT.parent / "omarchy/install/provisioning/setup-form.sh",
|
||||
Path("/usr/share/omarchy/install/provisioning/setup-form.sh"),
|
||||
@@ -31,7 +33,7 @@ def supported_keymaps():
|
||||
r"OMARCHY_KEYBOARD_LAYOUTS=\$'(.*?)'\n", candidate.read_text(), re.DOTALL
|
||||
)
|
||||
assert block, f"no layout list in {candidate}"
|
||||
return [line.split("|", 1)[1] for line in block.group(1).splitlines()]
|
||||
return [line.split("|")[1] for line in block.group(1).splitlines()]
|
||||
return None
|
||||
|
||||
|
||||
@@ -79,6 +81,36 @@ class KeyboardConfigurationTest(unittest.TestCase):
|
||||
"KEYMAP=us\nFONT=default8x16\n",
|
||||
)
|
||||
|
||||
def test_input_choice_survives_while_console_keymap_stays_real(self):
|
||||
for method, keymap, layout in (("mozc", "jp106", ""), ("mozc", "us", ""), ("hangul", "us", "kr"), ("pinyin", "us", ""), ("chewing", "us", "")):
|
||||
with self.subTest(method=method), tempfile.TemporaryDirectory() as directory:
|
||||
target = self.target(directory)
|
||||
self.assertTrue(KEYBOARD.configure_keyboard(target, keymap, method, layout))
|
||||
self.assertIn(f"KEYMAP={keymap}", (target / "etc/vconsole.conf").read_text())
|
||||
if keymap == "jp106":
|
||||
self.assertIn("XKBLAYOUT=jp", (target / "etc/vconsole.conf").read_text())
|
||||
self.assertEqual((target / "etc/omarchy/input-method").read_text(), f"INPUT_METHOD={method}\nXKB_LAYOUT={layout}\n")
|
||||
|
||||
def test_input_choice_with_no_console_map_defaults_to_us(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = self.target(directory)
|
||||
self.assertTrue(KEYBOARD.configure_keyboard(target, "", "pinyin"))
|
||||
self.assertIn("INPUT_METHOD=pinyin", (target / "etc/omarchy/input-method").read_text())
|
||||
|
||||
def test_unknown_keyboard_does_not_silently_drop_an_input_choice(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = self.target(directory)
|
||||
with self.assertRaises(ValueError):
|
||||
KEYBOARD.configure_keyboard(target, "unknown", "pinyin")
|
||||
|
||||
def test_invalid_input_preferences_are_rejected_without_writes(self):
|
||||
for method, layout in (("unknown", ""), ("hangul", "kr\nKEYMAP=ru")):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = self.target(directory)
|
||||
with self.assertRaises(ValueError):
|
||||
KEYBOARD.configure_keyboard(target, "us", method, layout)
|
||||
self.assertFalse((target / "etc/omarchy/input-method").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user