Showing preview only (2,869K chars total). Download the full file or copy to clipboard to get everything.
Repository: archlinux/archinstall
Branch: master
Commit: 1764b4971d8a
Files: 291
Total size: 2.7 MB
Directory structure:
gitextract_v4no44_h/
├── .editorconfig
├── .flake8
├── .github/
│ ├── CODEOWNERS
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 01_bug.yml
│ │ └── 02_feature.yml
│ └── workflows/
│ ├── bandit.yaml
│ ├── flake8.yaml
│ ├── github-pages.yml
│ ├── iso-build.yaml
│ ├── mypy.yaml
│ ├── pylint.yaml
│ ├── pytest.yaml
│ ├── python-build.yml
│ ├── python-publish.yml
│ ├── ruff-format.yaml
│ ├── ruff-lint.yaml
│ └── translation-check.yaml
├── .gitignore
├── .gitlab-ci.yml
├── .pre-commit-config.yaml
├── .pypirc
├── .readthedocs.yaml
├── CONTRIBUTING.md
├── LICENSE
├── PKGBUILD
├── README.md
├── archinstall/
│ ├── __init__.py
│ ├── __main__.py
│ ├── applications/
│ │ ├── audio.py
│ │ ├── bluetooth.py
│ │ ├── firewall.py
│ │ ├── power_management.py
│ │ └── print_service.py
│ ├── default_profiles/
│ │ ├── __init__.py
│ │ ├── desktop.py
│ │ ├── desktops/
│ │ │ ├── __init__.py
│ │ │ ├── awesome.py
│ │ │ ├── bspwm.py
│ │ │ ├── budgie.py
│ │ │ ├── cinnamon.py
│ │ │ ├── cosmic.py
│ │ │ ├── cutefish.py
│ │ │ ├── deepin.py
│ │ │ ├── enlightenment.py
│ │ │ ├── gnome.py
│ │ │ ├── hyprland.py
│ │ │ ├── i3.py
│ │ │ ├── labwc.py
│ │ │ ├── lxqt.py
│ │ │ ├── mate.py
│ │ │ ├── niri.py
│ │ │ ├── plasma.py
│ │ │ ├── qtile.py
│ │ │ ├── river.py
│ │ │ ├── sway.py
│ │ │ ├── xfce4.py
│ │ │ └── xmonad.py
│ │ ├── minimal.py
│ │ ├── profile.py
│ │ ├── server.py
│ │ ├── servers/
│ │ │ ├── __init__.py
│ │ │ ├── cockpit.py
│ │ │ ├── docker.py
│ │ │ ├── httpd.py
│ │ │ ├── lighttpd.py
│ │ │ ├── mariadb.py
│ │ │ ├── nginx.py
│ │ │ ├── postgresql.py
│ │ │ ├── sshd.py
│ │ │ └── tomcat.py
│ │ └── xorg.py
│ ├── lib/
│ │ ├── __init__.py
│ │ ├── applications/
│ │ │ ├── __init__.py
│ │ │ ├── application_handler.py
│ │ │ └── application_menu.py
│ │ ├── args.py
│ │ ├── authentication/
│ │ │ ├── __init__.py
│ │ │ ├── authentication_handler.py
│ │ │ └── authentication_menu.py
│ │ ├── boot.py
│ │ ├── bootloader/
│ │ │ ├── __init__.py
│ │ │ └── bootloader_menu.py
│ │ ├── command.py
│ │ ├── configuration.py
│ │ ├── crypt.py
│ │ ├── disk/
│ │ │ ├── __init__.py
│ │ │ ├── device_handler.py
│ │ │ ├── disk_menu.py
│ │ │ ├── encryption_menu.py
│ │ │ ├── fido.py
│ │ │ ├── filesystem.py
│ │ │ ├── lvm.py
│ │ │ ├── partitioning_menu.py
│ │ │ ├── subvolume_menu.py
│ │ │ └── utils.py
│ │ ├── exceptions.py
│ │ ├── global_menu.py
│ │ ├── hardware.py
│ │ ├── installer.py
│ │ ├── interactions/
│ │ │ ├── __init__.py
│ │ │ ├── disk_conf.py
│ │ │ ├── general_conf.py
│ │ │ └── system_conf.py
│ │ ├── locale/
│ │ │ ├── __init__.py
│ │ │ ├── locale_menu.py
│ │ │ └── utils.py
│ │ ├── luks.py
│ │ ├── menu/
│ │ │ ├── __init__.py
│ │ │ ├── abstract_menu.py
│ │ │ ├── helpers.py
│ │ │ ├── list_manager.py
│ │ │ ├── menu_helper.py
│ │ │ └── util.py
│ │ ├── mirror/
│ │ │ ├── __init__.py
│ │ │ ├── mirror_handler.py
│ │ │ └── mirror_menu.py
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ ├── application.py
│ │ │ ├── authentication.py
│ │ │ ├── bootloader.py
│ │ │ ├── device.py
│ │ │ ├── locale.py
│ │ │ ├── mirrors.py
│ │ │ ├── network.py
│ │ │ ├── packages.py
│ │ │ ├── profile.py
│ │ │ └── users.py
│ │ ├── network/
│ │ │ ├── __init__.py
│ │ │ ├── network_handler.py
│ │ │ ├── network_menu.py
│ │ │ ├── wifi_handler.py
│ │ │ └── wpa_supplicant.py
│ │ ├── networking.py
│ │ ├── output.py
│ │ ├── packages/
│ │ │ ├── __init__.py
│ │ │ ├── packages.py
│ │ │ └── util.py
│ │ ├── pacman/
│ │ │ ├── __init__.py
│ │ │ ├── config.py
│ │ │ └── pacman.py
│ │ ├── plugins.py
│ │ ├── profile/
│ │ │ ├── __init__.py
│ │ │ ├── profile_menu.py
│ │ │ └── profiles_handler.py
│ │ ├── translationhandler.py
│ │ ├── user/
│ │ │ ├── __init__.py
│ │ │ └── user_menu.py
│ │ ├── utils/
│ │ │ ├── __init__.py
│ │ │ ├── encoding.py
│ │ │ └── util.py
│ │ └── version.py
│ ├── locales/
│ │ ├── README.md
│ │ ├── ar/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── base.pot
│ │ ├── ca/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── cs/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── de/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── el/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── en/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── es/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── et/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── fi/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── fr/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ga/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── gl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── he/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── hi/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── hu/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── id/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── it/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ja/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ka/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ko/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ku/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── languages.json
│ │ ├── locales_generator.sh
│ │ ├── lt/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ne/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── nl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pt/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pt_BR/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ro/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ru/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── sv/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ta/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── tr/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── uk/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ur/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── uz/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── zh-CN/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ └── zh-TW/
│ │ └── LC_MESSAGES/
│ │ ├── base.mo
│ │ └── base.po
│ ├── main.py
│ ├── scripts/
│ │ ├── __init__.py
│ │ ├── guided.py
│ │ ├── minimal.py
│ │ └── only_hd.py
│ └── tui/
│ ├── __init__.py
│ ├── curses_menu.py
│ ├── help.py
│ ├── menu_item.py
│ ├── result.py
│ ├── types.py
│ └── ui/
│ ├── __init__.py
│ ├── components.py
│ ├── menu_item.py
│ └── result.py
├── docs/
│ ├── Makefile
│ ├── README.md
│ ├── _static/
│ │ ├── logo.pride.psd
│ │ ├── logo.psd
│ │ └── style.css
│ ├── _templates/
│ │ └── layout.html
│ ├── archinstall/
│ │ ├── Installer.rst
│ │ └── plugins.rst
│ ├── cli_parameters/
│ │ └── config/
│ │ ├── config_options.csv
│ │ ├── custom_commands.rst
│ │ ├── disk_config.rst
│ │ ├── disk_encryption.rst
│ │ └── manual_options.csv
│ ├── conf.py
│ ├── examples/
│ │ └── python.rst
│ ├── flowcharts/
│ │ └── DiskSelectionProcess.drawio
│ ├── help/
│ │ ├── discord.rst
│ │ ├── known_issues.rst
│ │ └── report_bug.rst
│ ├── index.rst
│ ├── installing/
│ │ ├── guided.rst
│ │ └── python.rst
│ └── pull_request_template.md
├── examples/
│ ├── auto_discovery_mounted.py
│ ├── config-sample.json
│ ├── creds-sample.json
│ ├── custom-command-sample.json
│ ├── disk_layouts-sample.json
│ └── full_automated_installation.py
├── pyproject.toml
└── tests/
├── __init__.py
├── conftest.py
├── data/
│ ├── __init__.py
│ ├── mirrorlists/
│ │ ├── test_multiple_countries
│ │ ├── test_no_country
│ │ └── test_with_country
│ ├── test_config.json
│ ├── test_creds.json
│ ├── test_deprecated_audio_config.json
│ ├── test_deprecated_creds_config.json
│ ├── test_deprecated_mirror_config.json
│ └── test_encrypted_creds.json
├── test_args.py
├── test_configuration_output.py
├── test_mirrorlist.py
└── test_password_strength.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
# See coding conventions in CONTRIBUTING.md
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.py]
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
================================================
FILE: .flake8
================================================
[flake8]
count = True
ignore = W191,W503,E704,E203
max-complexity = 40
max-line-length = 160
show-source = True
statistics = True
exclude = .git,__pycache__,build,docs,actions-runner
================================================
FILE: .github/CODEOWNERS
================================================
# As per https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#example-of-a-codeowners-file
* @Torxed
# Any PKGBUILD changes should tag grazzolini
/PKGBUILDs/ @grazzolini
/PKGBUILD @grazzolini
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [archlinux]
custom: ['https://archlinux.org/donate/']
================================================
FILE: .github/ISSUE_TEMPLATE/01_bug.yml
================================================
name: bug report
description: archinstall crashed or could not install properly?
body:
- type: markdown
attributes:
value: >
Please read the ~5 known issues first:
https://archinstall.archlinux.page/help/known_issues.html
- type: markdown
attributes:
value: >
**NOTE: Always try the latest official ISO**
- type: input
id: iso
attributes:
label: Which ISO version are you using?
description: 'Always use the latest ISO version'
placeholder: '"2024-12-01" or "Dec 1:st"'
validations:
required: true
- type: textarea
id: bug-report
attributes:
label: The installation log
description: 'note: located at `/var/log/archinstall/install.log`'
placeholder: |
Hardware model detected: Dell Inc. Precision 7670; UEFI mode: True
Processor model detected: 12th Gen Intel(R) Core(TM) i7-12850HX
Memory statistics: 31111048 available out of 32545396 total installed
Disk states before installing: {'blockdevices': ... }
Testing connectivity to the Arch Linux mirrors ...
...
render: json
validations:
required: true
- type: markdown
attributes:
value: >
**Note**: Assuming you have network connectivity,
you can easily post the installation log using the following command:
`curl -F'file=@/var/log/archinstall/install.log' https://0x0.st`
- type: textarea
id: freeform
attributes:
label: describe the problem
description: >
Please describe your issue as best as you can.
And please consider personal preferences vs what the recommended
steps/values are in https://wiki.archlinux.org/title/Installation_guide
as we try to abide by them as best we can.
value: |
#### Description of the issue
I was installing on X hardware ...
Then X Y Z happened and archinstall crashed ...
#### Virtual machine config:
```xml
<domain type="kvm">
<name>my-arch-machine</name>
...
</devices>
</domain>
```
```console
/usr/bin/qemu-system-x86_64 -name guest=my-arch-machine,debug-threads=on -object ...
```
validations:
required: true
- type: markdown
attributes:
value: >
**Note**: Feel free to modify the textarea above as you wish.
But it will grately help us in testing if we can generate the specific qemu command line,
for instance via:
`sudo virsh domxml-to-native qemu-argv --domain my-arch-machine`
================================================
FILE: .github/ISSUE_TEMPLATE/02_feature.yml
================================================
name: feature request
description: a new feature!
body:
- type: markdown
attributes:
value: >
Please read our short mission statement before requesting more features:
https://github.com/archlinux/archinstall?tab=readme-ov-file#mission-statement
- type: textarea
id: freeform
attributes:
label: describe the request
description: >
Feel free to write any feature you think others might benefit from:
validations:
required: true
================================================
FILE: .github/workflows/bandit.yaml
================================================
on: [ push, pull_request ]
name: Bandit security checkup
jobs:
bandit:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: pacman --noconfirm -Syu bandit
- name: Security checkup with Bandit
run: bandit -r archinstall || exit 0
================================================
FILE: .github/workflows/flake8.yaml
================================================
on: [ push, pull_request ]
name: flake8 linting
jobs:
flake8:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-pip python-pyparted pkgconfig gcc
- run: pip install --break-system-packages --upgrade pip
# this will install the exact version of flake8 that is in the pyproject.toml file
- name: Install archinstall dependencies
run: pip install --break-system-packages .[dev]
- run: python --version
- run: flake8 --version
- name: Lint with flake8
run: flake8
================================================
FILE: .github/workflows/github-pages.yml
================================================
name: documentation
on:
push:
paths:
- "docs/**"
pull_request:
paths:
- "docs/**"
workflow_dispatch:
permissions:
contents: write
jobs:
docs:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
options: --privileged
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
- name: Install pre-dependencies
run: |
pacman -Sy --noconfirm tree git python-pyparted python-setuptools python-sphinx python-sphinx_rtd_theme python-build python-installer python-wheel
- name: Sphinx build
run: |
sphinx-build docs _build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4
if: ${{ github.event_name != 'pull_request' }}
with:
publish_branch: gh-pages
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: _build/
force_orphan: true
enable_jekyll: false # This is required to preserve _static (and thus the theme)
cname: archinstall.archlinux.page
================================================
FILE: .github/workflows/iso-build.yaml
================================================
# This workflow will build an Arch Linux ISO file with the commit on it
name: Build Arch ISO with ArchInstall Commit
on:
push:
branches:
- master
- main # In case we adopt this convention in the future
pull_request:
paths-ignore:
- 'docs/**'
- '**.editorconfig'
- '**.gitignore'
- '**.md'
- 'LICENSE'
- 'PKGBUILD'
release:
types:
- created
jobs:
build:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
options: --privileged
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: pwd
- run: find .
- run: cat /etc/os-release
- run: pacman-key --init
- run: pacman --noconfirm -Sy archlinux-keyring
- run: ./build_iso.sh
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: Arch Live ISO
path: /tmp/archlive/out/*.iso
================================================
FILE: .github/workflows/mypy.yaml
================================================
on: [ push, pull_request ]
name: mypy type checking
jobs:
mypy:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-pip python-pyparted pkgconfig gcc
- run: pip install --break-system-packages --upgrade pip
# this will install the exact version of mypy that is in the pyproject.toml file
- name: Install archinstall dependencies
run: pip install --break-system-packages .[dev]
- run: python --version
- run: mypy --version
- name: run mypy
run: mypy --config-file pyproject.toml
================================================
FILE: .github/workflows/pylint.yaml
================================================
on: [ push, pull_request ]
name: Pylint linting
jobs:
pylint:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-pip python-pyparted pkgconfig gcc
- run: pip install --break-system-packages --upgrade pip
- name: Install Pylint
run: pip install --break-system-packages .[dev]
- run: python --version
- run: pylint --version
- name: Lint with Pylint
run: pylint .
================================================
FILE: .github/workflows/pytest.yaml
================================================
on: [ push, pull_request ]
name: pytest test validation
jobs:
pytest:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
options: --privileged
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-pip python-pyparted pkgconfig gcc
- run: pip install --break-system-packages --upgrade pip
- name: Install archinstall dependencies
run: pip install --break-system-packages .[dev]
- name: Test with pytest
run: pytest
================================================
FILE: .github/workflows/python-build.yml
================================================
# This workflow will build Python packages on every commit.
name: Build archinstall
on: [ push, pull_request ]
jobs:
deploy:
runs-on: ubuntu-latest
container:
image: archlinux/archlinux:latest
options: --privileged
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-uv python-setuptools python-pip
pacman --noconfirm -Sy python-pyparted python-pydantic python-textual
- name: Remove existing archinstall (if any)
run:
uv pip uninstall archinstall --break-system-packages --system
- name: Build archinstall
run: uv build --no-build-isolation --wheel
- name: Install archinstall
run: |
uv pip install dist/*.whl --break-system-packages --system --no-build --no-deps
- name: Run archinstall
run: |
python -V
archinstall --script guided -v
archinstall --script only_hd -v
archinstall --script minimal -v
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
with:
name: archinstall
path: dist/*
================================================
FILE: .github/workflows/python-publish.yml
================================================
# This workflow will upload a Python Package when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: Upload archinstall to PyPi
on:
release:
types: [ published ]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
# IMPORTANT: this permission is mandatory for Trusted Publishing
id-token: write
container:
image: archlinux/archlinux:latest
options: --privileged
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Prepare arch
run: |
pacman-key --init
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python python-uv python-setuptools python-pip python-pyparted python-pydantic python-textual
- name: Build archinstall
run: |
uv build --no-build-isolation --wheel
- name: Publish archinstall to PyPi
run: |
uv publish --trusted-publishing always
================================================
FILE: .github/workflows/ruff-format.yaml
================================================
on: [ push, pull_request ]
name: ruff check formatting
jobs:
ruff_format_check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
- run: ruff format --diff
================================================
FILE: .github/workflows/ruff-lint.yaml
================================================
on: [ push, pull_request ]
name: ruff check linting
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
================================================
FILE: .github/workflows/translation-check.yaml
================================================
#on:
# push:
# paths:
# - 'archinstall/locales/**'
# pull_request:
# paths:
# - 'archinstall/locales/**'
#name: Verify local_generate script was run on translation changes
#jobs:
# translation-check:
# runs-on: ubuntu-latest
# container:
# image: archlinux/archlinux:latest
# steps:
# - uses: actions/checkout@v4
# - run: pacman --noconfirm -Syu python git diffutils
# - name: Verify all translation scripts are up to date
# run: |
# cd ..
# cp -r archinstall archinstall_orig
# cd archinstall/archinstall/locales
# bash locales_generator.sh 1> /dev/null
# cd ../../..
# git diff \
# --quiet --no-index --name-only \
# archinstall_orig/archinstall/locales \
# archinstall/archinstall/locales \
# || (echo "Translation files have not been updated after translation, please run ./locales_generator.sh once more and commit" && exit 1)
================================================
FILE: .gitignore
================================================
**/**__pycache__
SAFETY_LOCK
**/**old.*
**/**.img
**/**pwfile
**/**build
**/**dist
**/**.egg*
**/**.sh
!archinstall/locales/locales_generator.sh
**/**.egg-info/
**/**build/
**/**src/
**/**pkg/
**/**dist/
**/**archinstall.build/
**/**archinstall-v*/
**/**.pkg.*.xz
**/**archinstall-*.tar.gz
**/**.zst
**/**.network
**/**.target
**/**.qcow2
**/**.log
**/**.fd
/test*.py
**/archiso
/guided.py
venv
.venv
.idea/**
**/install.log
.DS_Store
**/cmd_history.txt
**/*.*~
/*.sig
/*.json
requirements.txt
/.gitconfig
/actions-runner
/cmd_output.txt
node_modules/
uv.lock
================================================
FILE: .gitlab-ci.yml
================================================
# This file contains GitLab CI/CD configuration for the ArchInstall project.
# It defines several jobs that get run when a new commit is made, and is comparable to the GitHub workflows.
# There is an expectation that a runner exists that has the --privileged flag enabled for the build ISO job to run correctly.
# These jobs should leverage the same tag as that runner. If necessary, change the tag from 'docker' to the one it uses.
# All jobs will be run in the official archlinux container image, so we will declare that here.
image: archlinux/archlinux:latest
# This can be used to handle common actions. In this case, we do a pacman -Sy to make sure repos are ready to use.
before_script:
- pacman -Sy
stages:
- lint
- test
- build
- publish
mypy:
stage: lint
tags:
- docker
script:
- pacman --noconfirm -Syu python mypy
- mypy . --ignore-missing-imports || exit 0
flake8:
stage: lint
tags:
- docker
script:
- pacman --noconfirm -Syu python python-pip
- python -m pip install --upgrade pip
- pip install flake8
- flake8 . --count --select=E9,F63,F7 --show-source --statistics
- flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
# We currently do not have unit tests implemented but this stage is written in anticipation of their future usage.
# When a stage name is preceded with a '.' it's treated as "disabled" by GitLab and is not executed, so it's fine for it to be declared.
.pytest:
stage: test
tags:
- docker
script:
- pacman --noconfirm -Syu python python-pip
- python -m pip install --upgrade pip
- pip install pytest
- pytest
# This stage might fail with exit code 137 on a shared runner. This is probably due to the CPU/memory consumption needed to run the build.
build_iso:
stage: build
tags:
- docker
script:
- pwd
- find .
- cat /etc/os-release
- mkdir -p /tmp/archlive/airootfs/root/archinstall-git; cp -r . /tmp/archlive/airootfs/root/archinstall-git
- echo "pip uninstall archinstall -y; cd archinstall-git; python setup.py install" > /tmp/archlive/airootfs/root/.zprofile
- echo "echo \"This is an unofficial ISO for development and testing of archinstall. No support will be provided.\"" >> /tmp/archlive/airootfs/root/.zprofile
- echo "echo \"This ISO was built from Git SHA $CI_COMMIT_SHA\"" >> /tmp/archlive/airootfs/root/.zprofile
- echo "echo \"Type archinstall to launch the installer.\"" >> /tmp/archlive/airootfs/root/.zprofile
- cat /tmp/archlive/airootfs/root/.zprofile
- pacman --noconfirm -S git archiso
- cp -r /usr/share/archiso/configs/releng/* /tmp/archlive
- echo -e "git\npython\npython-pip\npython-setuptools" >> /tmp/archlive/packages.x86_64
- find /tmp/archlive
- cd /tmp/archlive; mkarchiso -v -w work/ -o out/ ./
artifacts:
name: "Arch Live ISO"
paths:
- /tmp/archlive/out/*.iso
expire_in: 1 week
## This job only runs when a tag is created on the master branch. This is because we do not want to try to publish to PyPi every time we commit.
## The following CI/CD variables need to be set to the PyPi username and password in the GitLab project's settings for this stage to work.
# * FLIT_USERNAME
# * FLIT_PASSWORD
publish_pypi:
stage: publish
tags:
- docker
script:
- pacman --noconfirm -S python python-pip
- python -m pip install --upgrade pip
- pip install setuptools wheel flit
- flit
only:
- tags
except:
- branches
================================================
FILE: .pre-commit-config.yaml
================================================
default_stages: ['pre-commit']
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.7
hooks:
# fix unused imports and sort them
- id: ruff
args: ["--extend-select", "I", "--fix"]
# format the code
- id: ruff-format
# run the linter
- id: ruff
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
# general hooks:
- id: check-added-large-files # Prevent giant files from being committed
args: ['--maxkb=5000']
- id: check-merge-conflict # Check for files that contain merge conflict strings
- id: check-symlinks # Checks for symlinks which do not point to anything
- id: check-yaml # Attempts to load all yaml files to verify syntax
- id: destroyed-symlinks # Detects symlinks which are changed to regular files
- id: detect-private-key # Checks for the existence of private keys
# Python specific hooks:
- id: check-ast # Simply check whether files parse as valid python
- id: check-docstring-first # Checks for a common error of placing code before the docstring
- repo: https://github.com/pycqa/flake8
rev: 7.3.0
hooks:
- id: flake8
args: [--config=.flake8]
fail_fast: true
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
hooks:
- id: mypy
args: [
'--config-file=pyproject.toml'
]
fail_fast: true
additional_dependencies:
- pydantic
- pytest
- cryptography
- textual
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
fail_fast: true
require_serial: true
================================================
FILE: .pypirc
================================================
[distutils]
index-servers =
pypi
[pypi]
repository = https://upload.pypi.org/legacy/
================================================
FILE: .readthedocs.yaml
================================================
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
sphinx:
builder: html
configuration: docs/conf.py
fail_on_warning: true
build:
os: "ubuntu-22.04"
tools:
python: "3.12"
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to archinstall
Any contributions through pull requests are welcome as this project aims to be a community based project to ease some Arch Linux installation steps.
Bear in mind that in the future this repo might be transferred to the official [GitLab repo under Arch Linux](http://gitlab.archlinux.org/archlinux/) *(if GitLab becomes open to the general public)*.
Therefore, guidelines and style changes to the code might come into effect as well as guidelines surrounding bug reporting and discussions.
## Branches
`master` is currently the default branch, and that's where all future feature work is being done, this means that `master` is a living entity and will most likely never be in a fully stable state.
For stable releases, please see the tagged commits.
Patch releases will be done against their own branches, branched from stable tagged releases and will be named according to the version it will become on release.
*(Patches to `v2.1.4` will be done on branch `v2.1.5` for instance)*.
## Discussions
Currently, questions, bugs and suggestions should be reported through [GitHub issue tracker](https://github.com/archlinux/archinstall/issues).<br>
For less formal discussions there is also an [archinstall Discord server](https://discord.gg/aDeMffrxNg).
## Coding convention
ArchInstall's goal is to follow [PEP8](https://www.python.org/dev/peps/pep-0008/) as best as it can with some minor exceptions.<br>
The exceptions to PEP8 are:
* Archinstall uses [tabs instead of spaces](https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces) simply to make it
easier for non-IDE developers to navigate the code *(Tab display-width should be equal to 4 spaces)*. Exception to the
rule are comments that need fine-tuned indentation for documentation purposes.
* [Line length](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) a maximum line length is enforced via flake8 with 160 characters
* Archinstall should always be saved with **Unix-formatted line endings** and no other platform-specific formats.
* [String quotes](https://www.python.org/dev/peps/pep-0008/#string-quotes) follow PEP8, the exception being when
creating formatted strings, double-quoted strings are *preferred* but not required on the outer edges *(
Example: `f"Welcome {name}"` rather than `f'Welcome {name}'`)*.
Most of these style guidelines have been put into place after the fact *(in an attempt to clean up the code)*.<br>
There might therefore be older code which does not follow the coding convention and the code is subject to change.
## Git hooks
`archinstall` ships pre-commit hooks that make it easier to run checks such as `mypy`, `ruff check`, and `flake8` locally.
The checks are listed in `.pre-commit-config.yaml` and can be installed via
```
pre-commit install
```
This will install the pre-commit hook and run it every time a `git commit` is executed.
## Documentation
If you'd like to contribute to the documentation, refer to [this guide](docs/README.md) on how to build the documentation locally.
## Submitting Changes
Archinstall uses GitHub's pull-request workflow and all contributions in terms of code should be done through pull requests.<br>
Anyone interested in archinstall may review your code. One of the core developers will merge your pull request when they
think it is ready. For every pull request, we aim to promptly either merge it or say why it is not yet ready; if you go
a few days without a reply, please feel free to ping the thread by adding a new comment.
To get your pull request merged sooner, you should explain why you are making the change. For example, you can point to
a code sample that is outdated in terms of Arch Linux command lines. It is also helpful to add links to online
documentation or to the implementation of the code you are changing.
Also, do not squash your commits after you have submitted a pull request, as this erases context during review. We will
squash commits when the pull request is merged.
Maintainer:
* Anton Hvornum ([@Torxed](https://github.com/Torxed))
[Contributors](https://github.com/archlinux/archinstall/graphs/contributors)
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
================================================
FILE: PKGBUILD
================================================
# Maintainer: David Runge <dvzrv@archlinux.org>
# Maintainer: Giancarlo Razzolini <grazzolini@archlinux.org>
# Maintainer: Anton Hvornum <torxed@archlinux.org>
# Contributor: Anton Hvornum <anton@hvornum.se>
# Contributor: demostanis worlds <demostanis@protonmail.com>
pkgname=archinstall
pkgver=3.0.15
pkgrel=1
pkgdesc="Just another guided/automated Arch Linux installer with a twist"
arch=(any)
url="https://github.com/archlinux/archinstall"
license=(GPL-3.0-only)
depends=(
'arch-install-scripts'
'btrfs-progs'
'coreutils'
'cryptsetup'
'dosfstools'
'e2fsprogs'
'glibc'
'kbd'
'libcrypt.so'
'libxcrypt'
'pciutils'
'procps-ng'
'python'
'python-cryptography'
'python-pydantic'
'python-pyparted'
'python-textual'
'python-markdown-it-py'
'python-linkify-it-py'
'systemd'
'util-linux'
'xfsprogs'
'lvm2'
'f2fs-tools'
'libfido2'
)
makedepends=(
'python-build'
'python-installer'
'python-setuptools'
'python-sphinx'
'python-wheel'
'python-sphinx_rtd_theme'
'python-pylint'
'ruff'
)
optdepends=(
'python-systemd: Adds journald logging'
)
provides=(python-archinstall archinstall)
conflicts=(python-archinstall archinstall-git)
replaces=(python-archinstall archinstall-git)
source=(
$pkgname-$pkgver.tar.gz::$url/archive/refs/tags/$pkgver.tar.gz
$pkgname-$pkgver.tar.gz.sig::$url/releases/download/$pkgver/$pkgname-$pkgver.tar.gz.sig
)
sha512sums=()
b2sums=()
validpgpkeys=('8AA2213C8464C82D879C8127D4B58E897A929F2E') # torxed@archlinux.org
check() {
cd $pkgname-$pkgver
ruff check
}
pkgver() {
cd $pkgname-$pkgver
awk '$1 ~ /^__version__/ {gsub("\"", ""); print $3}' archinstall/__init__.py
}
build() {
cd $pkgname-$pkgver
python -m build --wheel --no-isolation
PYTHONDONTWRITEBYTECODE=1 make man -C docs
}
package() {
cd "$pkgname-$pkgver"
python -m installer --destdir="$pkgdir" dist/*.whl
install -vDm 644 docs/_build/man/archinstall.1 -t "$pkgdir/usr/share/man/man1/"
}
================================================
FILE: README.md
================================================
<!-- <div align="center"> -->
<img src="https://github.com/archlinux/archinstall/raw/master/docs/logo.png" alt="drawing" width="200"/>
<!-- </div> -->
# Arch Installer
[](https://github.com/archlinux/archinstall/actions/workflows/flake8.yaml)
Just another guided/automated [Arch Linux](https://wiki.archlinux.org/index.php/Arch_Linux) installer with a twist.
The installer also doubles as a python library to install Arch Linux and manage services, packages, and other things inside the installed system *(Usually from a live medium or from an existing installation)*.
* archinstall [discord](https://discord.gg/aDeMffrxNg) server
* archinstall [#archinstall:matrix.org](https://matrix.to/#/#archinstall:matrix.org) Matrix channel
* archinstall [#archinstall@irc.libera.chat:6697](https://web.libera.chat/?channel=#archinstall)
* archinstall [documentation](https://archinstall.archlinux.page/)
# Installation & Usage
> [!TIP]
> In the ISO you are root by default. Use sudo if running from an existing system.
```shell
pacman-key --init
pacman -Sy archinstall
archinstall
```
Alternative ways to install are `git clone` the repository (and is better since you get the latest code regardless of [build date](https://archlinux.org/packages/?sort=&q=archinstall)) or `pip install --upgrade archinstall`.
## Upgrade `archinstall` on live Arch ISO image
Upgrading archinstall on the ISO needs to be done via a full system upgrade using
```shell
pacman -Syu
```
When booting from a live USB, the space on the ramdisk is limited and may not be sufficient to allow running a re-installation or upgrade of the installer.
In case one runs into this issue, any of the following can be used
* Resize the root partition https://wiki.archlinux.org/title/Archiso#Adjusting_the_size_of_the_root_file_system
* Specify the boot parameter copytoram=y (https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio-archiso/-/blob/master/docs/README.bootparams#L26) which will copy the root filesystem to tmpfs
## Running the [guided](https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py) installer
Assuming you are on an Arch Linux live-ISO or installed via `pip`, `archinstall` will use the `guided` script by default
```shell
archinstall
```
similar goes for running the [guided](https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py) installer using `git
```shell
git clone https://github.com/archlinux/archinstall
cd archinstall
python -m archinstall $@
```
To run alternative scripts using the `--script` parameter
```
archinstall --script <name>
```
#### Advanced
Some additional options that most users do not need are hidden behind the `--advanced` flag and all options/args can be consulted through `-h` or `--help`.
## Running from a declarative configuration file or URL
`archinstall` can be run with a JSON configuration file. There are 2 different configuration files to consider,
the `user_configuration.json` contains all general installation configuration, whereas the `user_credentials.json`
contains the sensitive user configuration such as user password, root password, and encryption password.
An example of the user configuration file can be found here
[configuration file](https://github.com/archlinux/archinstall/blob/master/examples/config-sample.json)
and an example of the credentials configuration here
[credentials file](https://github.com/archlinux/archinstall/blob/master/examples/creds-sample.json).
**HINT:** The configuration files can be auto-generated by starting `archinstall`, configuring all desired menu
points and then going to `Save configuration`.
To load the configuration file into `archinstall` run the following command
```shell
archinstall --config <path to user config file or URL> --creds <path to user credentials config file or URL>
```
### Credentials configuration file encryption
By default, all user account credentials are hashed with `yescrypt` and only the hash is stored in the saved `user_credentials.json` file.
This is not possible for disk encryption password which needs to be stored in plaintext to be able to apply it.
However, when selecting to save configuration files, `archinstall` will prompt for the option to encrypt the `user_credentials.json` file content.
A prompt will require to enter a encryption password to encrypt the file. When providing an encrypted `user_configuration.json` as a argument with `--creds <user_credentials.json>`
there are multiple ways to provide the decryption key:
* Provide the decryption key via the command line argument `--creds-decryption-key <password>`
* Store the encryption key in the environment variable `ARCHINSTALL_CREDS_DECRYPTION_KEY` which will be read automatically
* If none of the above is provided a prompt will be shown to enter the decryption key manually
# Help or Issues
If you come across any issues, kindly submit your issue here on GitHub or post your query in the
[discord](https://discord.gg/aDeMffrxNg) help channel.
When submitting an issue, please:
* Provide the stacktrace of the output if applicable
* Attach the `/var/log/archinstall/install.log` to the issue ticket. This helps us help you!
* To extract the log from the ISO image, one way is to use<br>
```shell
curl -F'file=@/var/log/archinstall/install.log' https://0x0.st
```
# Available Languages
Archinstall is available in different languages which have been contributed and are maintained by the community.
The language can be switched inside the installer (first menu entry). Bear in mind that not all languages provide
full translations as we rely on contributors to do the translations. Each language has an indicator that shows
how much has been translated.
Any contributions to the translations are more than welcome,
to get started please follow [the guide](https://github.com/archlinux/archinstall/blob/master/archinstall/locales/README.md)
## Fonts
The ISO does not ship with all fonts needed for different languages.
Fonts that use a different character set than Latin will not be displayed correctly. If those languages
want to be selected then a proper font has to be set manually in the console.
All available console fonts can be found in `/usr/share/kbd/consolefonts` and set with `setfont LatGrkCyr-8x16`.
# Scripting your own installation
## Scripting interactive installation
For an example of a fully scripted, interactive installation please refer to the example
[interactive_installation.py](https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py)
> **To create your own ISO with this script in it:** Follow [ArchISO](https://wiki.archlinux.org/index.php/archiso)'s guide on creating your own ISO.
## Script non-interactive automated installation
For an example of a fully scripted, automated installation please refer to the example
[full_automated_installation.py](https://github.com/archlinux/archinstall/blob/master/examples/full_automated_installation.py)
# Profiles
`archinstall` comes with a set of pre-configured profiles available for selection during the installation process.
- [Desktop](https://github.com/archlinux/archinstall/tree/master/archinstall/default_profiles/desktops)
- [Server](https://github.com/archlinux/archinstall/tree/master/archinstall/default_profiles/servers)
The profiles' definitions and the packages they will install can be directly viewed in the menu, or
[default profiles](https://github.com/archlinux/archinstall/tree/master/archinstall/default_profiles)
# Testing
## Using a Live ISO Image
If you want to test a commit, branch, or bleeding edge release from the repository using the standard Arch Linux Live ISO image,
replace the archinstall version with a newer one and execute the subsequent steps defined below.
1. You need a working network connection
2. Install the build requirements with `pacman -Sy; pacman -S git python-pip gcc pkgconf`
*(note that this may or may not work depending on your RAM and current state of the squashfs maximum filesystem free space)*
3. Uninstall the previous version of archinstall with `pip uninstall --break-system-packages archinstall`
4. Now clone the latest repository with `git clone https://github.com/archlinux/archinstall`
5. Enter the repository with `cd archinstall`
*At this stage, you can choose to check out a feature branch for instance with `git checkout v2.3.1-rc1`*
6. To run the source code, there are 2 different options:
- Run a specific branch version from source directly using `python -m archinstall`, in most cases this will work just fine, the
rare case it will not work is if the source has introduced any new dependencies that are not installed yet
- Installing the branch version with `pip install --break-system-packages .` and `archinstall`
## Without a Live ISO Image
To test this without a live ISO, the simplest approach is to use a local image and create a loop device.<br>
This can be done by installing `pacman -S arch-install-scripts util-linux` locally and doing the following:
# truncate -s 20G testimage.img
# losetup --partscan --show ./testimage.img
# pip install --upgrade archinstall
# python -m archinstall --script guided
# qemu-system-x86_64 -enable-kvm -machine q35,accel=kvm -device intel-iommu -cpu host -m 4096 -boot order=d -drive file=./testimage.img,format=raw -drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd -drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd
This will create a *20 GB* `testimage.img` and create a loop device which we can use to format and install to.<br>
`archinstall` is installed and executed in [guided mode](#docs-todo). Once the installation is complete, ~~you can use qemu/kvm to boot the test media.~~<br>
*(You'd actually need to do some EFI magic in order to point the EFI vars to the partition 0 in the test medium, so this won't work entirely out of the box, but that gives you a general idea of what we're going for here)*
There's also a [Building and Testing](https://github.com/archlinux/archinstall/wiki/Building-and-Testing) guide.<br>
It will go through everything from packaging, building and running *(with qemu)* the installer against a dev branch.
## Boot an Arch ISO image in a VM
You may want to boot an ISO image in a VM to test `archinstall` in there.
* Download the latest [Arch ISO](https://archlinux.org/download/)
* Use the the below command to boot the ISO in a VM
```
qemu-system-x86_64 -enable-kvm \
-machine q35,accel=kvm -device intel-iommu \
-cpu host -m 4096 -boot order=d \
-drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd \
-drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd \
-drive file=./archlinux-2025.12.01-x86_64.iso,format=raw
```
HINT: For espeakup support
```
qemu-system-x86_64 -enable-kvm \
-machine q35,accel=kvm -device intel-iommu \
-cpu host -m 4096 -boot order=d \
-drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd \
-drive if=pflash,format=raw,readonly,file=/usr/share/ovmf/x64/OVMF.4m.fd \
-drive file=./archlinux-2025.12.01-x86_64.iso,format=raw \
-device intel-hda -device hda-duplex,audiodev=snd0 \
-audiodev pa,id=snd0,server=/run/user/1000/pulse/native
```
# FAQ
## Keyring out-of-date
For a description of the problem see https://archinstall.archlinux.page/help/known_issues.html#keyring-is-out-of-date-2213 and discussion in issue https://github.com/archlinux/archinstall/issues/2213.
For a quick fix the below command will install the latest keyrings
```pacman -Sy archlinux-keyring```
## How to dual boot with Windows
To install Arch Linux alongside an existing Windows installation using `archinstall`, follow these steps:
1. Ensure some unallocated space is available for the Linux installation after the Windows installation.
2. Boot into the ISO and run `archinstall`.
3. Choose `Disk configuration` -> `Manual partitioning`.
4. Select the disk on which Windows resides.
5. Select `Create a new partition`.
6. Choose a filesystem type.
7. Determine the start and end sectors for the new partition location (values can be suffixed with various units).
8. Assign the mountpoint `/` to the new partition.
9. Assign the `Boot/ESP` partition the mountpoint `/boot` from the partitioning menu.
10. Confirm your settings and exit to the main menu by choosing `Confirm and exit`.
11. Modify any additional settings for your installation as necessary.
12. Start the installation upon completion of setup.
# Mission Statement
Archinstall promises to ship a [guided installer](https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py) that follows
the [Arch Linux Principles](https://wiki.archlinux.org/index.php/Arch_Linux#Principles) as well as a library to manage services, packages, and other Arch Linux aspects.
The guided installer ensures a user-friendly experience, offering optional selections throughout the process. Emphasizing its flexible nature, these options are never obligatory.
In addition, the decision to use the guided installer remains entirely with the user, reflecting the Linux philosophy of providing full freedom and flexibility.
---
Archinstall primarily functions as a flexible library for managing services, packages, and other elements within an Arch Linux system.
This core library is the backbone for the guided installer that Archinstall provides. It is also designed to be used by those who wish to script their own custom installations.
Therefore, Archinstall will try its best to not introduce any breaking changes except for major releases which may break backward compatibility after notifying about such changes.
# Contributing
Please see [CONTRIBUTING.md](https://github.com/archlinux/archinstall/blob/master/CONTRIBUTING.md)
================================================
FILE: archinstall/__init__.py
================================================
from archinstall.lib.plugins import plugin
__all__ = ['plugin']
================================================
FILE: archinstall/__main__.py
================================================
import sys
from archinstall.main import main
if __name__ == '__main__':
sys.exit(main())
================================================
FILE: archinstall/applications/audio.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.lib.hardware import SysInfo
from archinstall.lib.models.application import Audio, AudioConfiguration
from archinstall.lib.models.users import User
from archinstall.lib.output import debug
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class AudioApp:
@property
def pulseaudio_packages(self) -> list[str]:
return [
'pulseaudio',
]
@property
def pipewire_packages(self) -> list[str]:
return [
'pipewire',
'pipewire-alsa',
'pipewire-jack',
'pipewire-pulse',
'gst-plugin-pipewire',
'libpulse',
'wireplumber',
]
def _enable_pipewire(
self,
install_session: Installer,
users: list[User] | None = None,
) -> None:
if users is None:
return
for user in users:
# Create the full path for enabling the pipewire systemd items
service_dir = install_session.target / 'home' / user.username / '.config' / 'systemd' / 'user' / 'default.target.wants'
service_dir.mkdir(parents=True, exist_ok=True)
# Set ownership of the entire user catalogue
install_session.arch_chroot(f'chown -R {user.username}:{user.username} /home/{user.username}')
# symlink in the correct pipewire systemd items
install_session.arch_chroot(
f'ln -sf /usr/lib/systemd/user/pipewire-pulse.service /home/{user.username}/.config/systemd/user/default.target.wants/pipewire-pulse.service',
run_as=user.username,
)
install_session.arch_chroot(
f'ln -sf /usr/lib/systemd/user/pipewire-pulse.socket /home/{user.username}/.config/systemd/user/default.target.wants/pipewire-pulse.socket',
run_as=user.username,
)
def install(
self,
install_session: Installer,
audio_config: AudioConfiguration,
users: list[User] | None = None,
) -> None:
debug(f'Installing audio server: {audio_config.audio.value}')
if audio_config.audio == Audio.NO_AUDIO:
debug('No audio server selected, skipping installation.')
return
if SysInfo.requires_sof_fw():
install_session.add_additional_packages('sof-firmware')
if SysInfo.requires_alsa_fw():
install_session.add_additional_packages('alsa-firmware')
match audio_config.audio:
case Audio.PIPEWIRE:
install_session.add_additional_packages(self.pipewire_packages)
self._enable_pipewire(install_session, users)
case Audio.PULSEAUDIO:
install_session.add_additional_packages(self.pulseaudio_packages)
================================================
FILE: archinstall/applications/bluetooth.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.lib.output import debug
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class BluetoothApp:
@property
def packages(self) -> list[str]:
return [
'bluez',
'bluez-utils',
]
@property
def services(self) -> list[str]:
return [
'bluetooth.service',
]
def install(self, install_session: Installer) -> None:
debug('Installing Bluetooth')
install_session.add_additional_packages(self.packages)
install_session.enable_service(self.services)
================================================
FILE: archinstall/applications/firewall.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.lib.models.application import Firewall, FirewallConfiguration
from archinstall.lib.output import debug
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class FirewallApp:
@property
def ufw_packages(self) -> list[str]:
return [
'ufw',
]
@property
def fwd_packages(self) -> list[str]:
return [
'firewalld',
]
@property
def ufw_services(self) -> list[str]:
return [
'ufw.service',
]
@property
def fwd_services(self) -> list[str]:
return [
'firewalld.service',
]
def install(
self,
install_session: Installer,
firewall_config: FirewallConfiguration,
) -> None:
debug(f'Installing firewall: {firewall_config.firewall.value}')
match firewall_config.firewall:
case Firewall.UFW:
install_session.add_additional_packages(self.ufw_packages)
install_session.enable_service(self.ufw_services)
# write default conf file to enabled
ufw_conf = install_session.target / 'etc/ufw/ufw.conf'
ufw_conf.write_text(ufw_conf.read_text().replace('ENABLED=no', 'ENABLED=yes'))
case Firewall.FWD:
install_session.add_additional_packages(self.fwd_packages)
install_session.enable_service(self.fwd_services)
================================================
FILE: archinstall/applications/power_management.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.lib.models.application import PowerManagement, PowerManagementConfiguration
from archinstall.lib.output import debug
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class PowerManagementApp:
@property
def ppd_packages(self) -> list[str]:
return [
'power-profiles-daemon',
]
@property
def tuned_packages(self) -> list[str]:
return [
'tuned',
'tuned-ppd',
]
def install(
self,
install_session: Installer,
power_management_config: PowerManagementConfiguration,
) -> None:
debug(f'Installing power management daemon: {power_management_config.power_management.value}')
match power_management_config.power_management:
case PowerManagement.POWER_PROFILES_DAEMON:
install_session.add_additional_packages(self.ppd_packages)
case PowerManagement.TUNED:
install_session.add_additional_packages(self.tuned_packages)
================================================
FILE: archinstall/applications/print_service.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.lib.output import debug
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class PrintServiceApp:
@property
def packages(self) -> list[str]:
return ['cups', 'system-config-printer', 'cups-pk-helper']
@property
def services(self) -> list[str]:
return [
'cups.service',
]
def install(self, install_session: Installer) -> None:
debug('Installing print service')
install_session.add_additional_packages(self.packages)
install_session.enable_service(self.services)
================================================
FILE: archinstall/default_profiles/__init__.py
================================================
================================================
FILE: archinstall/default_profiles/desktop.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, Self, override
from archinstall.default_profiles.profile import GreeterType, Profile, ProfileType, SelectResult
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.output import info
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class DesktopProfile(Profile):
def __init__(self, current_selection: list[Self] = []) -> None:
super().__init__(
'Desktop',
ProfileType.Desktop,
current_selection=current_selection,
support_greeter=True,
)
@property
@override
def packages(self) -> list[str]:
return [
'nano',
'vim',
'openssh',
'htop',
'wget',
'smartmontools',
'xdg-utils',
]
@property
@override
def default_greeter_type(self) -> GreeterType | None:
combined_greeters: dict[GreeterType, int] = {}
for profile in self.current_selection:
if profile.default_greeter_type:
combined_greeters.setdefault(profile.default_greeter_type, 0)
combined_greeters[profile.default_greeter_type] += 1
if len(combined_greeters) >= 1:
return list(combined_greeters)[0]
return None
async def _do_on_select_profiles(self) -> None:
for profile in self.current_selection:
await profile.do_on_select()
@override
async def do_on_select(self) -> SelectResult:
items = [
MenuItem(
p.name,
value=p,
preview_action=lambda x: x.value.preview_text() if x.value else None,
)
for p in profile_handler.get_desktop_profiles()
]
group = MenuItemGroup(items, sort_items=True, sort_case_sensitive=False)
group.set_selected_by_value(self.current_selection)
result = await Selection[Self](
group,
multi=True,
allow_reset=True,
allow_skip=True,
preview_location='right',
).show()
match result.type_:
case ResultType.Selection:
self.current_selection = result.get_values()
await self._do_on_select_profiles()
return SelectResult.NewSelection
case ResultType.Skip:
return SelectResult.SameSelection
case ResultType.Reset:
return SelectResult.ResetCurrent
@override
def post_install(self, install_session: Installer) -> None:
for profile in self.current_selection:
profile.post_install(install_session)
@override
def install(self, install_session: Installer) -> None:
# Install common packages for all desktop environments
install_session.add_additional_packages(self.packages)
for profile in self.current_selection:
info(f'Installing profile {profile.name}...')
install_session.add_additional_packages(profile.packages)
install_session.enable_service(profile.services)
profile.install(install_session)
================================================
FILE: archinstall/default_profiles/desktops/__init__.py
================================================
from enum import Enum
class SeatAccess(Enum):
seatd = 'seatd'
polkit = 'polkit'
================================================
FILE: archinstall/default_profiles/desktops/awesome.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, override
from archinstall.default_profiles.profile import ProfileType
from archinstall.default_profiles.xorg import XorgProfile
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class AwesomeProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Awesome', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return super().packages + [
'awesome',
'alacritty',
'xorg-xinit',
'xorg-xrandr',
'xterm',
'feh',
'slock',
'terminus-font',
'gnu-free-fonts',
'ttf-liberation',
'xsel',
]
@override
def install(self, install_session: Installer) -> None:
super().install(install_session)
# TODO: Copy a full configuration to ~/.config/awesome/rc.lua instead.
with open(f'{install_session.target}/etc/xdg/awesome/rc.lua') as fh:
awesome_lua = fh.read()
# Replace xterm with alacritty for a smoother experience.
awesome_lua = awesome_lua.replace('"xterm"', '"alacritty"')
with open(f'{install_session.target}/etc/xdg/awesome/rc.lua', 'w') as fh:
fh.write(awesome_lua)
# TODO: Configure the right-click-menu to contain the above packages that were installed. (as a user config)
# TODO: check if we selected a greeter,
# but for now, awesome is intended to run without one.
with open(f'{install_session.target}/etc/X11/xinit/xinitrc') as xinitrc:
xinitrc_data = xinitrc.read()
for line in xinitrc_data.split('\n'):
if 'twm &' in line:
xinitrc_data = xinitrc_data.replace(line, f'# {line}')
if 'xclock' in line:
xinitrc_data = xinitrc_data.replace(line, f'# {line}')
if 'xterm' in line:
xinitrc_data = xinitrc_data.replace(line, f'# {line}')
xinitrc_data += '\n'
xinitrc_data += 'exec awesome\n'
with open(f'{install_session.target}/etc/X11/xinit/xinitrc', 'w') as xinitrc:
xinitrc.write(xinitrc_data)
================================================
FILE: archinstall/default_profiles/desktops/bspwm.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class BspwmProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Bspwm', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
# return super().packages + [
return [
'bspwm',
'sxhkd',
'dmenu',
'xdo',
'rxvt-unicode',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/budgie.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class BudgieProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Budgie', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'materia-gtk-theme',
'budgie',
'mate-terminal',
'nemo',
'papirus-icon-theme',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.LightdmSlick
================================================
FILE: archinstall/default_profiles/desktops/cinnamon.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class CinnamonProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Cinnamon', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'cinnamon',
'system-config-printer',
'gnome-keyring',
'gnome-terminal',
'engrampa',
'gnome-screenshot',
'gvfs-smb',
'xed',
'xdg-user-dirs-gtk',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/cosmic.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class CosmicProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Cosmic', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'cosmic',
'xdg-user-dirs',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.CosmicSession
================================================
FILE: archinstall/default_profiles/desktops/cutefish.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class CutefishProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Cutefish', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'cutefish',
'noto-fonts',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Sddm
================================================
FILE: archinstall/default_profiles/desktops/deepin.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class DeepinProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Deepin', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'deepin',
'deepin-terminal',
'deepin-editor',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/enlightenment.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class EnlightenmentProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Enlightenment', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return [
'enlightenment',
'terminology',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/gnome.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class GnomeProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('GNOME', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'gnome',
'gnome-tweaks',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Gdm
================================================
FILE: archinstall/default_profiles/desktops/hyprland.py
================================================
from typing import override
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class HyprlandProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Hyprland', ProfileType.DesktopEnv)
self.custom_settings = {'seat_access': None}
@property
@override
def packages(self) -> list[str]:
return [
'hyprland',
'dunst',
'kitty',
'uwsm',
'dolphin',
'wofi',
'xdg-desktop-portal-hyprland',
'qt5-wayland',
'qt6-wayland',
'polkit-kde-agent',
'grim',
'slurp',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Sddm
@property
@override
def services(self) -> list[str]:
if pref := self.custom_settings.get('seat_access', None):
return [pref]
return []
async def _select_seat_access(self) -> None:
# need to activate seat service and add to seat group
header = tr('Hyprland needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)')
header += '\n' + tr('Choose an option to give Hyprland access to your hardware') + '\n'
items = [MenuItem(s.value, value=s) for s in SeatAccess]
group = MenuItemGroup(items, sort_items=True)
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)
result = await Selection[SeatAccess](
group,
header=header,
allow_skip=False,
).show()
if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
@override
async def do_on_select(self) -> None:
await self._select_seat_access()
================================================
FILE: archinstall/default_profiles/desktops/i3.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class I3wmProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('i3-wm', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return [
'i3-wm',
'i3lock',
'i3status',
'i3blocks',
'xss-lock',
'xterm',
'lightdm-gtk-greeter',
'lightdm',
'dmenu',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/labwc.py
================================================
from typing import override
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class LabwcProfile(XorgProfile):
def __init__(self) -> None:
super().__init__(
'Labwc',
ProfileType.WindowMgr,
)
self.custom_settings = {'seat_access': None}
@property
@override
def packages(self) -> list[str]:
additional = []
if seat := self.custom_settings.get('seat_access', None):
additional = [seat]
return [
'alacritty',
'labwc',
] + additional
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
@property
@override
def services(self) -> list[str]:
if pref := self.custom_settings.get('seat_access', None):
return [pref]
return []
async def _select_seat_access(self) -> None:
# need to activate seat service and add to seat group
header = tr('labwc needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)')
header += '\n' + tr('Choose an option to give labwc access to your hardware') + '\n'
items = [MenuItem(s.value, value=s) for s in SeatAccess]
group = MenuItemGroup(items, sort_items=True)
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)
result = await Selection[SeatAccess](
group,
header=header,
allow_skip=False,
).show()
if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
@override
async def do_on_select(self) -> None:
await self._select_seat_access()
================================================
FILE: archinstall/default_profiles/desktops/lxqt.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class LxqtProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Lxqt', ProfileType.DesktopEnv)
# NOTE: SDDM is the only officially supported greeter for LXQt, so unlike other DEs, lightdm is not used here.
# LXQt works with lightdm, but since this is not supported, we will not default to this.
# https://github.com/lxqt/lxqt/issues/795
@property
@override
def packages(self) -> list[str]:
return [
'lxqt',
'breeze-icons',
'oxygen-icons',
'xdg-utils',
'ttf-freefont',
'l3afpad',
'slock',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Sddm
================================================
FILE: archinstall/default_profiles/desktops/mate.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class MateProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Mate', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'mate',
'mate-extra',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/niri.py
================================================
from typing import override
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class NiriProfile(XorgProfile):
def __init__(self) -> None:
super().__init__(
'Niri',
ProfileType.WindowMgr,
)
self.custom_settings = {'seat_access': None}
@property
@override
def packages(self) -> list[str]:
additional = []
if seat := self.custom_settings.get('seat_access', None):
additional = [seat]
return [
'niri',
'alacritty',
'fuzzel',
'mako',
'xorg-xwayland',
'waybar',
'swaybg',
'swayidle',
'swaylock',
'xdg-desktop-portal-gnome',
] + additional
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
@property
@override
def services(self) -> list[str]:
if pref := self.custom_settings.get('seat_access', None):
return [pref]
return []
async def _select_seat_access(self) -> None:
# need to activate seat service and add to seat group
header = tr('niri needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)')
header += '\n' + tr('Choose an option to give niri access to your hardware') + '\n'
items = [MenuItem(s.value, value=s) for s in SeatAccess]
group = MenuItemGroup(items, sort_items=True)
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)
result = await Selection[SeatAccess](
group,
header=header,
allow_skip=False,
).show()
if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
@override
async def do_on_select(self) -> None:
await self._select_seat_access()
================================================
FILE: archinstall/default_profiles/desktops/plasma.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class PlasmaProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('KDE Plasma', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'plasma-desktop',
'konsole',
'kate',
'dolphin',
'ark',
'plasma-workspace',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.PlasmaLoginManager
================================================
FILE: archinstall/default_profiles/desktops/qtile.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class QtileProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Qtile', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return [
'qtile',
'alacritty',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/river.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class RiverProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('River', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return [
'foot',
'xdg-desktop-portal-wlr',
'river',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/sway.py
================================================
from typing import override
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class SwayProfile(XorgProfile):
def __init__(self) -> None:
super().__init__(
'Sway',
ProfileType.WindowMgr,
)
self.custom_settings = {'seat_access': None}
@property
@override
def packages(self) -> list[str]:
additional = []
if seat := self.custom_settings.get('seat_access', None):
additional = [seat]
return [
'sway',
'swaybg',
'swaylock',
'swayidle',
'waybar',
'wmenu',
'brightnessctl',
'grim',
'slurp',
'pavucontrol',
'foot',
'xorg-xwayland',
] + additional
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
@property
@override
def services(self) -> list[str]:
if pref := self.custom_settings.get('seat_access', None):
return [pref]
return []
async def _select_seat_access(self) -> None:
# need to activate seat service and add to seat group
header = tr('Sway needs access to your seat (collection of hardware devices i.e. keyboard, mouse, etc)')
header += '\n' + tr('Choose an option to give Sway access to your hardware') + '\n'
items = [MenuItem(s.value, value=s) for s in SeatAccess]
group = MenuItemGroup(items, sort_items=True)
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)
result = await Selection[SeatAccess](
group,
header=header,
allow_skip=False,
).show()
if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
@override
async def do_on_select(self) -> None:
await self._select_seat_access()
================================================
FILE: archinstall/default_profiles/desktops/xfce4.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class Xfce4Profile(XorgProfile):
def __init__(self) -> None:
super().__init__('Xfce4', ProfileType.DesktopEnv)
@property
@override
def packages(self) -> list[str]:
return [
'xfce4',
'xfce4-goodies',
'pavucontrol',
'gvfs',
'xarchiver',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/desktops/xmonad.py
================================================
from typing import override
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
class XmonadProfile(XorgProfile):
def __init__(self) -> None:
super().__init__('Xmonad', ProfileType.WindowMgr)
@property
@override
def packages(self) -> list[str]:
return [
'xmonad',
'xmonad-contrib',
'xmonad-extras',
'xterm',
'dmenu',
]
@property
@override
def default_greeter_type(self) -> GreeterType:
return GreeterType.Lightdm
================================================
FILE: archinstall/default_profiles/minimal.py
================================================
from archinstall.default_profiles.profile import Profile, ProfileType
class MinimalProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Minimal',
ProfileType.Minimal,
)
================================================
FILE: archinstall/default_profiles/profile.py
================================================
from __future__ import annotations
from enum import Enum, auto
from typing import TYPE_CHECKING, Self
from archinstall.lib.translationhandler import tr
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
from archinstall.lib.models.users import User
class ProfileType(Enum):
# top level default_profiles
Server = 'Server'
Desktop = 'Desktop'
Xorg = 'Xorg'
Minimal = 'Minimal'
Custom = 'Custom'
# detailed selection default_profiles
ServerType = 'ServerType'
WindowMgr = 'Window Manager'
DesktopEnv = 'Desktop Environment'
CustomType = 'CustomType'
# special things
Application = 'Application'
class GreeterType(Enum):
Lightdm = 'lightdm-gtk-greeter'
LightdmSlick = 'lightdm-slick-greeter'
Sddm = 'sddm'
Gdm = 'gdm'
Ly = 'ly'
CosmicSession = 'cosmic-greeter'
PlasmaLoginManager = 'plasma-login-manager'
class SelectResult(Enum):
NewSelection = auto()
SameSelection = auto()
ResetCurrent = auto()
class Profile:
def __init__(
self,
name: str,
profile_type: ProfileType,
current_selection: list[Self] = [],
packages: list[str] = [],
services: list[str] = [],
support_gfx_driver: bool = False,
support_greeter: bool = False,
) -> None:
self.name = name
self.profile_type = profile_type
self.custom_settings: dict[str, str | None] = {}
self._support_gfx_driver = support_gfx_driver
self._support_greeter = support_greeter
# self.gfx_driver: str | None = None
self.current_selection = current_selection
self._packages = packages
self._services = services
# Only used for custom default_profiles
self.custom_enabled = False
@property
def packages(self) -> list[str]:
"""
Returns a list of packages that should be installed when
this profile is among the chosen ones
"""
return self._packages
@property
def services(self) -> list[str]:
"""
Returns a list of services that should be enabled when
this profile is among the chosen ones
"""
return self._services
@property
def default_greeter_type(self) -> GreeterType | None:
"""
Setting a default greeter type for a desktop profile
"""
return None
def install(self, install_session: Installer) -> None:
"""
Performs installation steps when this profile was selected
"""
def post_install(self, install_session: Installer) -> None:
"""
Hook that will be called when the installation process is
finished and custom installation steps for specific default_profiles
are needed
"""
def provision(self, install_session: Installer, users: list[User]) -> None:
"""
Hook that will be called when the installation process is
finished and user configuration for specific default_profiles
is needed
"""
def json(self) -> dict[str, str]:
"""
Returns a json representation of the profile
"""
return {}
async def do_on_select(self) -> SelectResult | None:
"""
Hook that will be called when a profile is selected
"""
return SelectResult.NewSelection
def set_custom_settings(self, settings: dict[str, str | None]) -> None:
"""
Set the custom settings for the profile.
This is also called when the settings are parsed from the config
and can be overridden to perform further actions based on the profile
"""
self.custom_settings = settings
def current_selection_names(self) -> list[str]:
if self.current_selection:
return [s.name for s in self.current_selection]
return []
def reset(self) -> None:
self.current_selection = []
def is_top_level_profile(self) -> bool:
top_levels = [ProfileType.Desktop, ProfileType.Server, ProfileType.Xorg, ProfileType.Minimal, ProfileType.Custom]
return self.profile_type in top_levels
def is_desktop_profile(self) -> bool:
return self.profile_type == ProfileType.Desktop
def is_server_type_profile(self) -> bool:
return self.profile_type == ProfileType.ServerType
def is_desktop_type_profile(self) -> bool:
return self.profile_type == ProfileType.DesktopEnv or self.profile_type == ProfileType.WindowMgr
def is_xorg_type_profile(self) -> bool:
return self.profile_type == ProfileType.Xorg
def is_custom_type_profile(self) -> bool:
return self.profile_type == ProfileType.CustomType
def is_graphic_driver_supported(self) -> bool:
if not self.current_selection:
return self._support_gfx_driver
else:
if any([p._support_gfx_driver for p in self.current_selection]):
return True
return False
def is_greeter_supported(self) -> bool:
return self._support_greeter
def preview_text(self) -> str:
"""
Override this method to provide a preview text for the profile
"""
return self.packages_text()
def packages_text(self, include_sub_packages: bool = False) -> str:
packages = set()
if self.packages:
packages = set(self.packages)
if include_sub_packages:
for sub_profile in self.current_selection:
if sub_profile.packages:
packages.update(sub_profile.packages)
text = tr('Installed packages') + ':\n'
for pkg in sorted(packages):
text += f'\t- {pkg}\n'
return text
================================================
FILE: archinstall/default_profiles/server.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, Self, override
from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.output import info
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
from archinstall.lib.models.users import User
class ServerProfile(Profile):
def __init__(self, current_value: list[Self] = []):
super().__init__(
'Server',
ProfileType.Server,
current_selection=current_value,
)
@override
async def do_on_select(self) -> SelectResult:
items = [
MenuItem(
p.name,
value=p,
preview_action=lambda x: x.value.preview_text() if x.value else None,
)
for p in profile_handler.get_server_profiles()
]
group = MenuItemGroup(items, sort_items=True)
group.set_selected_by_value(self.current_selection)
result = await Selection[Self](
group,
allow_reset=True,
allow_skip=True,
multi=True,
preview_location='right',
).show()
match result.type_:
case ResultType.Selection:
selections = result.get_values()
self.current_selection = selections
return SelectResult.NewSelection
case ResultType.Skip:
return SelectResult.SameSelection
case ResultType.Reset:
return SelectResult.ResetCurrent
@override
def provision(self, install_session: Installer, users: list[User]) -> None:
for profile in self.current_selection:
profile.provision(install_session, users)
@override
def post_install(self, install_session: Installer) -> None:
for profile in self.current_selection:
profile.post_install(install_session)
@override
def install(self, install_session: Installer) -> None:
server_info = self.current_selection_names()
details = ', '.join(server_info)
info(f'Now installing the selected servers: {details}')
for server in self.current_selection:
info(f'Installing {server.name}...')
install_session.add_additional_packages(server.packages)
install_session.enable_service(server.services)
server.install(install_session)
info('If your selections included multiple servers with the same port, you may have to reconfigure them.')
================================================
FILE: archinstall/default_profiles/servers/__init__.py
================================================
================================================
FILE: archinstall/default_profiles/servers/cockpit.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class CockpitProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Cockpit',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['cockpit', 'udisks2', 'packagekit']
@property
@override
def services(self) -> list[str]:
return ['cockpit.socket']
================================================
FILE: archinstall/default_profiles/servers/docker.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, override
from archinstall.default_profiles.profile import Profile, ProfileType
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
from archinstall.lib.models.users import User
class DockerProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Docker',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['docker']
@property
@override
def services(self) -> list[str]:
return ['docker']
@override
def provision(self, install_session: Installer, users: list[User]) -> None:
for user in users:
install_session.arch_chroot(f'usermod -a -G docker {user.username}')
================================================
FILE: archinstall/default_profiles/servers/httpd.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class HttpdProfile(Profile):
def __init__(self) -> None:
super().__init__(
'httpd',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['apache']
@property
@override
def services(self) -> list[str]:
return ['httpd']
================================================
FILE: archinstall/default_profiles/servers/lighttpd.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class LighttpdProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Lighttpd',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['lighttpd']
@property
@override
def services(self) -> list[str]:
return ['lighttpd']
================================================
FILE: archinstall/default_profiles/servers/mariadb.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, override
from archinstall.default_profiles.profile import Profile, ProfileType
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class MariadbProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Mariadb',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['mariadb']
@property
@override
def services(self) -> list[str]:
return ['mariadb']
@override
def post_install(self, install_session: Installer) -> None:
install_session.arch_chroot('mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql')
================================================
FILE: archinstall/default_profiles/servers/nginx.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class NginxProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Nginx',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['nginx']
@property
@override
def services(self) -> list[str]:
return ['nginx']
================================================
FILE: archinstall/default_profiles/servers/postgresql.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING, override
from archinstall.default_profiles.profile import Profile, ProfileType
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class PostgresqlProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Postgresql',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['postgresql']
@property
@override
def services(self) -> list[str]:
return ['postgresql']
@override
def post_install(self, install_session: Installer) -> None:
install_session.arch_chroot('initdb -D /var/lib/postgres/data', run_as='postgres')
================================================
FILE: archinstall/default_profiles/servers/sshd.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class SshdProfile(Profile):
def __init__(self) -> None:
super().__init__(
'sshd',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['openssh']
@property
@override
def services(self) -> list[str]:
return ['sshd']
================================================
FILE: archinstall/default_profiles/servers/tomcat.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
class TomcatProfile(Profile):
def __init__(self) -> None:
super().__init__(
'Tomcat',
ProfileType.ServerType,
)
@property
@override
def packages(self) -> list[str]:
return ['tomcat10']
@property
@override
def services(self) -> list[str]:
return ['tomcat10']
================================================
FILE: archinstall/default_profiles/xorg.py
================================================
from typing import override
from archinstall.default_profiles.profile import Profile, ProfileType
from archinstall.lib.translationhandler import tr
class XorgProfile(Profile):
def __init__(
self,
name: str = 'Xorg',
profile_type: ProfileType = ProfileType.Xorg,
):
super().__init__(
name,
profile_type,
support_gfx_driver=True,
)
@override
def preview_text(self) -> str:
text = tr('Environment type: {}').format(self.profile_type.value)
if packages := self.packages_text():
text += f'\n{packages}'
return text
@property
@override
def packages(self) -> list[str]:
return [
'xorg-server',
]
================================================
FILE: archinstall/lib/__init__.py
================================================
================================================
FILE: archinstall/lib/applications/__init__.py
================================================
================================================
FILE: archinstall/lib/applications/application_handler.py
================================================
from __future__ import annotations
from typing import TYPE_CHECKING
from archinstall.applications.audio import AudioApp
from archinstall.applications.bluetooth import BluetoothApp
from archinstall.applications.firewall import FirewallApp
from archinstall.applications.power_management import PowerManagementApp
from archinstall.applications.print_service import PrintServiceApp
from archinstall.lib.models import Audio
from archinstall.lib.models.application import ApplicationConfiguration
from archinstall.lib.models.users import User
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class ApplicationHandler:
def __init__(self) -> None:
pass
def install_applications(self, install_session: Installer, app_config: ApplicationConfiguration, users: list[User] | None = None) -> None:
if app_config.bluetooth_config and app_config.bluetooth_config.enabled:
BluetoothApp().install(install_session)
if app_config.audio_config and app_config.audio_config.audio != Audio.NO_AUDIO:
AudioApp().install(
install_session,
app_config.audio_config,
users,
)
if app_config.power_management_config:
PowerManagementApp().install(
install_session,
app_config.power_management_config,
)
if app_config.print_service_config and app_config.print_service_config.enabled:
PrintServiceApp().install(install_session)
if app_config.firewall_config:
FirewallApp().install(
install_session,
app_config.firewall_config,
)
================================================
FILE: archinstall/lib/applications/application_menu.py
================================================
from typing import override
from archinstall.lib.hardware import SysInfo
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.models.application import (
ApplicationConfiguration,
Audio,
AudioConfiguration,
BluetoothConfiguration,
Firewall,
FirewallConfiguration,
PowerManagement,
PowerManagementConfiguration,
PrintServiceConfiguration,
)
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class ApplicationMenu(AbstractSubMenu[ApplicationConfiguration]):
def __init__(
self,
preset: ApplicationConfiguration | None = None,
):
if preset:
self._app_config = preset
else:
self._app_config = ApplicationConfiguration()
menu_options = self._define_menu_options()
self._item_group = MenuItemGroup(menu_options, checkmarks=True)
super().__init__(
self._item_group,
config=self._app_config,
allow_reset=True,
)
@override
async def show(self) -> ApplicationConfiguration | None:
_ = await super().show()
return self._app_config
def _define_menu_options(self) -> list[MenuItem]:
return [
MenuItem(
text=tr('Bluetooth'),
action=select_bluetooth,
value=self._app_config.bluetooth_config,
preview_action=self._prev_bluetooth,
key='bluetooth_config',
),
MenuItem(
text=tr('Audio'),
action=select_audio,
preview_action=self._prev_audio,
key='audio_config',
),
MenuItem(
text=tr('Print service'),
action=select_print_service,
preview_action=self._prev_print_service,
key='print_service_config',
),
MenuItem(
text=tr('Power management'),
action=select_power_management,
preview_action=self._prev_power_management,
enabled=SysInfo.has_battery(),
key='power_management_config',
),
MenuItem(
text=tr('Firewall'),
action=select_firewall,
preview_action=self._prev_firewall,
key='firewall_config',
),
]
def _prev_power_management(self, item: MenuItem) -> str | None:
if item.value is not None:
config: PowerManagementConfiguration = item.value
return f'{tr("Power management")}: {config.power_management.value}'
return None
def _prev_bluetooth(self, item: MenuItem) -> str | None:
if item.value is not None:
bluetooth_config: BluetoothConfiguration = item.value
output = f'{tr("Bluetooth")}: '
output += tr('Enabled') if bluetooth_config.enabled else tr('Disabled')
return output
return None
def _prev_audio(self, item: MenuItem) -> str | None:
if item.value is not None:
config: AudioConfiguration = item.value
return f'{tr("Audio")}: {config.audio.value}'
return None
def _prev_print_service(self, item: MenuItem) -> str | None:
if item.value is not None:
print_service_config: PrintServiceConfiguration = item.value
output = f'{tr("Print service")}: '
output += tr('Enabled') if print_service_config.enabled else tr('Disabled')
return output
return None
def _prev_firewall(self, item: MenuItem) -> str | None:
if item.value is not None:
config: FirewallConfiguration = item.value
return f'{tr("Firewall")}: {config.firewall.value}'
return None
async def select_power_management(preset: PowerManagementConfiguration | None = None) -> PowerManagementConfiguration | None:
group = MenuItemGroup.from_enum(PowerManagement)
if preset:
group.set_focus_by_value(preset.power_management)
result = await Selection[PowerManagement](
group,
allow_skip=True,
allow_reset=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return PowerManagementConfiguration(power_management=result.get_value())
case ResultType.Reset:
return None
async def select_bluetooth(preset: BluetoothConfiguration | None) -> BluetoothConfiguration | None:
header = tr('Would you like to configure Bluetooth?') + '\n'
preset_val = preset.enabled if preset else False
result = await Confirmation(
header=header,
allow_skip=True,
preset=preset_val,
).show()
match result.type_:
case ResultType.Selection:
return BluetoothConfiguration(result.get_value())
case ResultType.Skip:
return preset
case _:
raise ValueError('Unhandled result type')
async def select_print_service(preset: PrintServiceConfiguration | None) -> PrintServiceConfiguration | None:
header = tr('Would you like to configure the print service?') + '\n'
preset_val = preset.enabled if preset else False
result = await Confirmation(
header=header,
allow_skip=True,
preset=preset_val,
).show()
match result.type_:
case ResultType.Selection:
result.get_value()
return PrintServiceConfiguration(result.get_value())
case ResultType.Skip:
return preset
case _:
raise ValueError('Unhandled result type')
async def select_audio(preset: AudioConfiguration | None = None) -> AudioConfiguration | None:
items = [MenuItem(a.value, value=a) for a in Audio]
group = MenuItemGroup(items)
if preset:
group.set_focus_by_value(preset.audio)
result = await Selection[Audio](
group,
header=tr('Select audio configuration'),
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return AudioConfiguration(audio=result.get_value())
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def select_firewall(preset: FirewallConfiguration | None = None) -> FirewallConfiguration | None:
group = MenuItemGroup.from_enum(Firewall)
if preset:
group.set_focus_by_value(preset.firewall)
result = await Selection[Firewall](
group,
allow_skip=True,
allow_reset=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return FirewallConfiguration(firewall=result.get_value())
case ResultType.Reset:
return None
================================================
FILE: archinstall/lib/args.py
================================================
import argparse
import json
import os
import sys
import urllib.error
import urllib.parse
from argparse import ArgumentParser, Namespace
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Self
from urllib.request import Request, urlopen
from pydantic.dataclasses import dataclass as p_dataclass
from archinstall.lib.crypt import decrypt
from archinstall.lib.menu.util import get_password
from archinstall.lib.models.application import ApplicationConfiguration, ZramConfiguration
from archinstall.lib.models.authentication import AuthenticationConfiguration
from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration
from archinstall.lib.models.device import DiskEncryption, DiskLayoutConfiguration
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import MirrorConfiguration
from archinstall.lib.models.network import NetworkConfiguration
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.models.users import Password, User, UserSerialization
from archinstall.lib.output import debug, error, logger, warn
from archinstall.lib.plugins import load_plugin
from archinstall.lib.translationhandler import Language, tr, translation_handler
from archinstall.lib.version import get_version
from archinstall.tui.ui.components import tui
@p_dataclass
class Arguments:
config: Path | None = None
config_url: str | None = None
creds: Path | None = None
creds_url: str | None = None
creds_decryption_key: str | None = None
silent: bool = False
dry_run: bool = False
script: str | None = None
mountpoint: Path = Path('/mnt')
skip_ntp: bool = False
skip_wkd: bool = False
skip_boot: bool = False
debug: bool = False
offline: bool = False
no_pkg_lookups: bool = False
plugin: str | None = None
skip_version_check: bool = False
skip_wifi_check: bool = False
advanced: bool = False
verbose: bool = False
@dataclass
class ArchConfig:
version: str | None = None
script: str | None = None
locale_config: LocaleConfiguration | None = None
archinstall_language: Language = field(default_factory=lambda: translation_handler.get_language_by_abbr('en'))
disk_config: DiskLayoutConfiguration | None = None
profile_config: ProfileConfiguration | None = None
mirror_config: MirrorConfiguration | None = None
network_config: NetworkConfiguration | None = None
bootloader_config: BootloaderConfiguration | None = None
app_config: ApplicationConfiguration | None = None
auth_config: AuthenticationConfiguration | None = None
swap: ZramConfiguration | None = None
hostname: str = 'archlinux'
kernels: list[str] = field(default_factory=lambda: ['linux'])
ntp: bool = True
packages: list[str] = field(default_factory=list)
parallel_downloads: int = 0
timezone: str = 'UTC'
services: list[str] = field(default_factory=list)
custom_commands: list[str] = field(default_factory=list)
def unsafe_config(self) -> dict[str, Any]:
config: dict[str, list[UserSerialization] | str | None] = {}
if self.auth_config:
if self.auth_config.users:
config['users'] = [user.json() for user in self.auth_config.users]
if self.auth_config.root_enc_password:
config['root_enc_password'] = self.auth_config.root_enc_password.enc_password
if self.disk_config:
disk_encryption = self.disk_config.disk_encryption
if disk_encryption and disk_encryption.encryption_password:
config['encryption_password'] = disk_encryption.encryption_password.plaintext
return config
def safe_config(self) -> dict[str, Any]:
config: Any = {
'version': self.version,
'script': self.script,
'archinstall-language': self.archinstall_language.json(),
'hostname': self.hostname,
'kernels': self.kernels,
'ntp': self.ntp,
'packages': self.packages,
'parallel_downloads': self.parallel_downloads,
'swap': self.swap,
'timezone': self.timezone,
'services': self.services,
'custom_commands': self.custom_commands,
'bootloader_config': self.bootloader_config.json() if self.bootloader_config else None,
'app_config': self.app_config.json() if self.app_config else None,
'auth_config': self.auth_config.json() if self.auth_config else None,
}
if self.locale_config:
config['locale_config'] = self.locale_config.json()
if self.disk_config:
config['disk_config'] = self.disk_config.json()
if self.profile_config:
config['profile_config'] = self.profile_config.json()
if self.mirror_config:
config['mirror_config'] = self.mirror_config.json()
if self.network_config:
config['network_config'] = self.network_config.json()
return config
@classmethod
def from_config(cls, args_config: dict[str, Any], args: Arguments) -> Self:
arch_config = cls()
arch_config.locale_config = LocaleConfiguration.parse_arg(args_config)
if script := args_config.get('script', None):
arch_config.script = script
if archinstall_lang := args_config.get('archinstall-language', None):
arch_config.archinstall_language = translation_handler.get_language_by_name(archinstall_lang)
if disk_config := args_config.get('disk_config', {}):
enc_password = args_config.get('encryption_password', '')
password = Password(plaintext=enc_password) if enc_password else None
arch_config.disk_config = DiskLayoutConfiguration.parse_arg(disk_config, password)
# DEPRECATED
# backwards compatibility for main level disk_encryption entry
disk_encryption: DiskEncryption | None = None
if args_config.get('disk_encryption', None) is not None and arch_config.disk_config is not None:
disk_encryption = DiskEncryption.parse_arg(
arch_config.disk_config,
args_config['disk_encryption'],
Password(plaintext=args_config.get('encryption_password', '')),
)
if disk_encryption:
arch_config.disk_config.disk_encryption = disk_encryption
if profile_config := args_config.get('profile_config', None):
arch_config.profile_config = ProfileConfiguration.parse_arg(profile_config)
if mirror_config := args_config.get('mirror_config', None):
backwards_compatible_repo = []
if additional_repositories := args_config.get('additional-repositories', []):
backwards_compatible_repo = [Repository(r) for r in additional_repositories]
arch_config.mirror_config = MirrorConfiguration.parse_args(
mirror_config,
backwards_compatible_repo,
)
if net_config := args_config.get('network_config', None):
arch_config.network_config = NetworkConfiguration.parse_arg(net_config)
if bootloader_config_dict := args_config.get('bootloader_config', None):
arch_config.bootloader_config = BootloaderConfiguration.parse_arg(bootloader_config_dict, args.skip_boot)
# DEPRECATED: separate bootloader and uki fields (backward compatibility)
elif bootloader_str := args_config.get('bootloader', None):
bootloader = Bootloader.from_arg(bootloader_str, args.skip_boot)
uki = args_config.get('uki', False)
if uki and not bootloader.has_uki_support():
uki = False
arch_config.bootloader_config = BootloaderConfiguration(bootloader=bootloader, uki=uki, removable=True)
# deprecated: backwards compatibility
audio_config_args = args_config.get('audio_config', None)
app_config_args = args_config.get('app_config', None)
if audio_config_args is not None or app_config_args is not None:
arch_config.app_config = ApplicationConfiguration.parse_arg(app_config_args, audio_config_args)
if auth_config_args := args_config.get('auth_config', None):
arch_config.auth_config = AuthenticationConfiguration.parse_arg(auth_config_args)
if hostname := args_config.get('hostname', ''):
arch_config.hostname = hostname
if kernels := args_config.get('kernels', []):
arch_config.kernels = kernels
arch_config.ntp = args_config.get('ntp', True)
if packages := args_config.get('packages', []):
arch_config.packages = packages
if parallel_downloads := args_config.get('parallel_downloads', 0):
arch_config.parallel_downloads = parallel_downloads
swap_arg = args_config.get('swap')
if swap_arg is not None:
arch_config.swap = ZramConfiguration.parse_arg(swap_arg)
if timezone := args_config.get('timezone', 'UTC'):
arch_config.timezone = timezone
if services := args_config.get('services', []):
arch_config.services = services
# DEPRECATED: backwards compatibility
root_password = None
if root_password := args_config.get('!root-password', None):
root_password = Password(plaintext=root_password)
if enc_password := args_config.get('root_enc_password', None):
root_password = Password(enc_password=enc_password)
if root_password is not None:
if arch_config.auth_config is None:
arch_config.auth_config = AuthenticationConfiguration()
arch_config.auth_config.root_enc_password = root_password
# DEPRECATED: backwards compatibility
users: list[User] = []
if args_users := args_config.get('!users', None):
users = User.parse_arguments(args_users)
if args_users := args_config.get('users', None):
users = User.parse_arguments(args_users)
if users:
if arch_config.auth_config is None:
arch_config.auth_config = AuthenticationConfiguration()
arch_config.auth_config.users = users
if custom_commands := args_config.get('custom_commands', []):
arch_config.custom_commands = custom_commands
return arch_config
class ArchConfigHandler:
def __init__(self) -> None:
self._parser: ArgumentParser = self._define_arguments()
args: Arguments = self._parse_args()
self._args = args
config = self._parse_config()
try:
self._config = ArchConfig.from_config(config, args)
self._config.version = get_version()
except ValueError as err:
warn(str(err))
sys.exit(1)
@property
def config(self) -> ArchConfig:
return self._config
@property
def args(self) -> Arguments:
return self._args
def get_script(self) -> str:
if script := self.args.script:
return script
if script := self.config.script:
return script
return 'guided'
def print_help(self) -> None:
self._parser.print_help()
def _define_arguments(self) -> ArgumentParser:
parser = ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'-v',
'--version',
action='version',
default=False,
version='%(prog)s ' + get_version(),
)
parser.add_argument(
'--config',
type=Path,
nargs='?',
default=None,
help='JSON configuration file',
)
parser.add_argument(
'--config-url',
type=str,
nargs='?',
default=None,
help='Url to a JSON configuration file',
)
parser.add_argument(
'--creds',
type=Path,
nargs='?',
default=None,
help='JSON credentials configuration file',
)
parser.add_argument(
'--creds-url',
type=str,
nargs='?',
default=None,
help='Url to a JSON credentials configuration file',
)
parser.add_argument(
'--creds-decryption-key',
type=str,
nargs='?',
default=None,
help='Decryption key for credentials file',
)
parser.add_argument(
'--silent',
action='store_true',
default=False,
help='WARNING: Disables all prompts for input and confirmation. If no configuration is provided, this is ignored',
)
parser.add_argument(
'--dry-run',
'--dry_run',
action='store_true',
default=False,
help='Generates a configuration file and then exits instead of performing an installation',
)
parser.add_argument(
'--script',
nargs='?',
help='Script to run for installation',
type=str,
)
parser.add_argument(
'--mountpoint',
type=Path,
nargs='?',
default=Path('/mnt'),
help='Define an alternate mount point for installation',
)
parser.add_argument(
'--skip-ntp',
action='store_true',
help='Disables NTP checks during installation',
default=False,
)
parser.add_argument(
'--skip-wkd',
action='store_true',
help='Disables checking if archlinux keyring wkd sync is complete.',
default=False,
)
parser.add_argument(
'--skip-boot',
action='store_true',
help='Disables installation of a boot loader (note: only use this when problems arise with the boot loader step).',
default=False,
)
parser.add_argument(
'--debug',
action='store_true',
default=False,
help='Adds debug info into the log',
)
parser.add_argument(
'--offline',
action='store_true',
default=False,
help='Disabled online upstream services such as package search and key-ring auto update.',
)
parser.add_argument(
'--no-pkg-lookups',
action='store_true',
default=False,
help='Disabled package validation specifically prior to starting installation.',
)
parser.add_argument(
'--plugin',
nargs='?',
type=str,
default=None,
help='File path to a plugin to load',
)
parser.add_argument(
'--skip-version-check',
action='store_true',
default=False,
help='Skip the version check when running archinstall',
)
parser.add_argument(
'--skip-wifi-check',
action='store_true',
default=False,
help='Skip wifi check when running archinstall',
)
parser.add_argument(
'--advanced',
action='store_true',
default=False,
help='Enabled advanced options',
)
parser.add_argument(
'--verbose',
action='store_true',
default=False,
help='Enabled verbose options',
)
return parser
def _parse_args(self) -> Arguments:
argparse_args = vars(self._parser.parse_args())
args: Arguments = Arguments(**argparse_args)
# amend the parameters (check internal consistency)
# Installation can't be silent if config is not passed
if args.config is None and args.config_url is None:
args.silent = False
if args.debug:
warn(f'Warning: --debug mode will write certain credentials to {logger.path}!')
if args.plugin:
plugin_path = Path(args.plugin)
load_plugin(plugin_path)
if args.creds_decryption_key is None:
if os.environ.get('ARCHINSTALL_CREDS_DECRYPTION_KEY'):
args.creds_decryption_key = os.environ.get('ARCHINSTALL_CREDS_DECRYPTION_KEY')
return args
def _parse_config(self) -> dict[str, Any]:
config: dict[str, Any] = {}
config_data: str | None = None
creds_data: str | None = None
if self._args.config is not None:
config_data = self._read_file(self._args.config)
elif self._args.config_url is not None:
config_data = self._fetch_from_url(self._args.config_url)
if config_data is not None:
config.update(json.loads(config_data))
if self._args.creds is not None:
creds_data = self._read_file(self._args.creds)
elif self._args.creds_url is not None:
creds_data = self._fetch_from_url(self._args.creds_url)
if creds_data is not None:
json_data = self._process_creds_data(creds_data)
if json_data is not None:
config.update(json_data)
config = self._cleanup_config(config)
return config
def _process_creds_data(self, creds_data: str) -> dict[str, Any] | None:
if creds_data.startswith('$'): # encrypted data
if self._args.creds_decryption_key is not None:
try:
creds_data = decrypt(creds_data, self._args.creds_decryption_key)
return json.loads(creds_data)
except ValueError as err:
if 'Invalid password' in str(err):
error(tr('Incorrect credentials file decryption password'))
sys.exit(1)
else:
debug(f'Error decrypting credentials file: {err}')
raise err from err
else:
header = tr('Enter credentials file decryption password')
wrong_pwd_text = tr('Incorrect password')
prompt = header
while True:
decryption_pwd: Password | None = tui.run(
lambda p=prompt: get_password( # type: ignore[misc]
header=p,
allow_skip=False,
no_confirmation=True,
)
)
if not decryption_pwd:
return None
try:
creds_data = decrypt(creds_data, decryption_pwd.plaintext)
break
except ValueError as err:
if 'Invalid password' in str(err):
debug('Incorrect credentials file decryption password')
prompt = f'{header}' + f'\n\n{wrong_pwd_text}'
else:
debug(f'Error decrypting credentials file: {err}')
raise err from err
return json.loads(creds_data)
def _fetch_from_url(self, url: str) -> str:
if urllib.parse.urlparse(url).scheme:
try:
req = Request(url, headers={'User-Agent': 'ArchInstall'})
with urlopen(req) as resp:
return resp.read().decode('utf-8')
except urllib.error.HTTPError as err:
error(f'Could not fetch JSON from {url}: {err}')
else:
error('Not a valid url')
sys.exit(1)
def _read_file(self, path: Path) -> str:
if not path.exists():
error(f'Could not find file {path}')
sys.exit(1)
return path.read_text()
def _cleanup_config(self, config: Namespace | dict[str, Any]) -> dict[str, Any]:
clean_args = {}
for key, val in config.items():
if isinstance(val, dict):
val = self._cleanup_config(val)
if val is not None:
clean_args[key] = val
return clean_args
================================================
FILE: archinstall/lib/authentication/__init__.py
================================================
================================================
FILE: archinstall/lib/authentication/authentication_handler.py
================================================
from __future__ import annotations
import getpass
from pathlib import Path
from typing import TYPE_CHECKING
from archinstall.lib.command import SysCommandWorker
from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod
from archinstall.lib.models.users import User
from archinstall.lib.output import debug, info
from archinstall.lib.translationhandler import tr
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
class AuthenticationHandler:
def setup_auth(
self,
install_session: Installer,
auth_config: AuthenticationConfiguration,
hostname: str,
) -> None:
if auth_config.u2f_config and auth_config.users is not None:
self._setup_u2f_login(install_session, auth_config.u2f_config, auth_config.users, hostname)
def _setup_u2f_login(self, install_session: Installer, u2f_config: U2FLoginConfiguration, users: list[User], hostname: str) -> None:
self._configure_u2f_mapping(install_session, u2f_config, users, hostname)
self._update_pam_config(install_session, u2f_config)
def _update_pam_config(
self,
install_session: Installer,
u2f_config: U2FLoginConfiguration,
) -> None:
match u2f_config.u2f_login_method:
case U2FLoginMethod.Passwordless:
config_entry = 'auth sufficient pam_u2f.so authfile=/etc/u2f_mappings cue'
case U2FLoginMethod.SecondFactor:
config_entry = 'auth required pam_u2f.so authfile=/etc/u2f_mappings cue'
case _:
raise ValueError(f'Unknown U2F login method: {u2f_config.u2f_login_method}')
debug(f'U2F PAM configuration: {config_entry}')
debug(f'Passwordless sudo enabled: {u2f_config.passwordless_sudo}')
sudo_config = install_session.target / 'etc/pam.d/sudo'
sys_login = install_session.target / 'etc/pam.d/system-login'
if u2f_config.passwordless_sudo:
self._add_u2f_entry(sudo_config, config_entry)
self._add_u2f_entry(sys_login, config_entry)
def _add_u2f_entry(self, file: Path, entry: str) -> None:
if not file.exists():
debug(f'File does not exist: {file}')
return None
content = file.read_text().splitlines()
# remove any existing u2f auth entry
content = [line for line in content if 'pam_u2f.so' not in line]
# add the u2f auth entry as the first one after comments
for i, line in enumerate(content):
if not line.startswith('#'):
content.insert(i, entry)
break
else:
content.append(entry)
file.write_text('\n'.join(content) + '\n')
def _configure_u2f_mapping(
self,
install_session: Installer,
u2f_config: U2FLoginConfiguration,
users: list[User],
hostname: str,
) -> None:
debug(f'Setting up U2F login: {u2f_config.u2f_login_method.value}')
install_session.pacman.strap('pam-u2f')
print(tr(f'Setting up U2F login: {u2f_config.u2f_login_method.value}'))
# https://developers.yubico.com/pam-u2f/
u2f_auth_file = install_session.target / 'etc/u2f_mappings'
u2f_auth_file.touch()
existing_keys = u2f_auth_file.read_text()
registered_keys: list[str] = []
for user in users:
print('')
info(tr('Setting up U2F device for user: {}').format(user.username))
info(tr('You may need to enter the PIN and then touch your U2F device to register it'))
cmd = ' '.join(
['arch-chroot', '-S', str(install_session.target), 'pamu2fcfg', '-u', user.username, '-o', f'pam://{hostname}', '-i', f'pam://{hostname}']
)
debug(f'Enrolling U2F device: {cmd}')
worker = SysCommandWorker(cmd, peek_output=True)
pin_inputted = False
while worker.is_alive():
if pin_inputted is False:
if bytes('enter pin for', 'UTF-8') in worker._trace_log.lower():
worker.write(bytes(getpass.getpass(''), 'UTF-8'))
pin_inputted = True
output = worker.decode().strip().splitlines()
debug(f'Output from pamu2fcfg: {output}')
key = output[-1].strip()
registered_keys.append(key)
all_keys = '\n'.join(registered_keys)
if existing_keys:
existing_keys += f'\n{all_keys}'
else:
existing_keys = all_keys
u2f_auth_file.write_text(existing_keys)
================================================
FILE: archinstall/lib/authentication/authentication_menu.py
================================================
from typing import override
from archinstall.lib.disk.fido import Fido2
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.menu.util import get_password
from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod
from archinstall.lib.models.users import Password, User
from archinstall.lib.output import FormattedOutput
from archinstall.lib.translationhandler import tr
from archinstall.lib.user.user_menu import select_users
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class AuthenticationMenu(AbstractSubMenu[AuthenticationConfiguration]):
def __init__(self, preset: AuthenticationConfiguration | None = None):
if preset:
self._auth_config = preset
else:
self._auth_config = AuthenticationConfiguration()
menu_options = self._define_menu_options()
self._item_group = MenuItemGroup(menu_options, checkmarks=True)
super().__init__(
self._item_group,
config=self._auth_config,
allow_reset=True,
)
@override
async def show(self) -> AuthenticationConfiguration | None:
return await super().show()
def _define_menu_options(self) -> list[MenuItem]:
return [
MenuItem(
text=tr('Root password'),
action=lambda x: select_root_password(),
preview_action=self._prev_root_pwd,
key='root_enc_password',
),
MenuItem(
text=tr('User account'),
action=self._create_user_account,
preview_action=self._prev_users,
key='users',
),
MenuItem(
text=tr('U2F login setup'),
action=select_u2f_login,
value=self._auth_config.u2f_config,
preview_action=self._prev_u2f_login,
key='u2f_config',
),
]
async def _create_user_account(self, preset: list[User] | None = None) -> list[User]:
preset = [] if preset is None else preset
users = await select_users(preset=preset)
return users
def _prev_users(self, item: MenuItem) -> str | None:
users: list[User] | None = item.value
if users:
return FormattedOutput.as_table(users)
return None
def _prev_root_pwd(self, item: MenuItem) -> str | None:
if item.value is not None:
password: Password = item.value
return f'{tr("Root password")}: {password.hidden()}'
return None
def _depends_on_u2f(self) -> bool:
devices = Fido2.get_fido2_devices()
if not devices:
return False
return True
def _prev_u2f_login(self, item: MenuItem) -> str | None:
if item.value is not None:
u2f_config: U2FLoginConfiguration = item.value
login_method = u2f_config.u2f_login_method.display_value()
output = tr('U2F login method: ') + login_method
output += '\n'
output += tr('Passwordless sudo: ') + (tr('Enabled') if u2f_config.passwordless_sudo else tr('Disabled'))
return output
devices = Fido2.get_fido2_devices()
if not devices:
return tr('No U2F devices found')
return None
async def select_root_password() -> Password | None:
password = await get_password(header=tr('Enter root password'), allow_skip=True)
return password
async def select_u2f_login(preset: U2FLoginConfiguration | None) -> U2FLoginConfiguration | None:
devices = Fido2.get_fido2_devices()
if not devices:
return None
items = []
for method in U2FLoginMethod:
items.append(MenuItem(method.display_value(), value=method))
group = MenuItemGroup(items)
if preset is not None:
group.set_selected_by_value(preset.u2f_login_method)
result = await Selection[U2FLoginMethod](
group,
allow_skip=True,
allow_reset=True,
).show()
match result.type_:
case ResultType.Selection:
u2f_method = result.get_value()
header = tr('Enable passwordless sudo?')
result_sudo = await Confirmation(
header=header,
allow_skip=True,
preset=False,
).show()
passwordless_sudo = result_sudo.item() == MenuItem.yes()
return U2FLoginConfiguration(
u2f_login_method=u2f_method,
passwordless_sudo=passwordless_sudo,
)
case ResultType.Skip:
return preset
case ResultType.Reset:
return None
================================================
FILE: archinstall/lib/boot.py
================================================
import time
from collections.abc import Iterator
from pathlib import Path
from types import TracebackType
from typing import ClassVar, Self
from archinstall.lib.command import SysCommand, SysCommandWorker, locate_binary
from archinstall.lib.exceptions import SysCallError
from archinstall.lib.output import error
class Boot:
_active_boot: ClassVar[Self | None] = None
def __init__(self, path: Path | str):
if isinstance(path, Path):
path = str(path)
self.path = path
self.container_name = 'archinstall'
self.session: SysCommandWorker | None = None
self.ready = False
def __enter__(self) -> Self:
if Boot._active_boot and Boot._active_boot.path != self.path:
raise KeyError('Archinstall only supports booting up one instance and another session is already active.')
if Boot._active_boot:
self.session = Boot._active_boot.session
self.ready = Boot._active_boot.ready
else:
# '-P' or --console=pipe could help us not having to do a bunch
# of os.write() calls, but instead use pipes (stdin, stdout and stderr) as usual.
self.session = SysCommandWorker(
[
'systemd-nspawn',
'-D',
self.path,
'--timezone=off',
'-b',
'--no-pager',
'--machine',
self.container_name,
]
)
if not self.ready and self.session:
while self.session.is_alive():
if b' login:' in self.session:
self.ready = True
break
Boot._active_boot = self
return self
def __exit__(self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None) -> None:
# b''.join(sys_command('sync')) # No need to, since the underlying fs() object will call sync.
# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager
if exc_type is not None:
error(
str(exc_value),
f'The error above occurred in a temporary boot-up of the installation {self.path!r}',
)
shutdown = None
shutdown_exit_code: int | None = -1
try:
shutdown = SysCommand(f'systemd-run --machine={self.container_name} --pty shutdown now')
except SysCallError as err:
shutdown_exit_code = err.exit_code
if self.session:
while self.session.is_alive():
time.sleep(0.25)
if shutdown and shutdown.exit_code:
shutdown_exit_code = shutdown.exit_code
if self.session and (self.session.exit_code == 0 or shutdown_exit_code == 0):
Boot._active_boot = None
else:
session_exit_code = self.session.exit_code if self.session else -1
raise SysCallError(
f'Could not shut down temporary boot of {self.path!r}: {session_exit_code}/{shutdown_exit_code}',
exit_code=next(filter(bool, [session_exit_code, shutdown_exit_code])),
)
def __iter__(self) -> Iterator[bytes]:
if self.session:
yield from self.session
def __contains__(self, key: bytes) -> bool:
if self.session is None:
return False
return key in self.session
def is_alive(self) -> bool:
if self.session is None:
return False
return self.session.is_alive()
def SysCommand(self, cmd: list[str], *args, **kwargs) -> SysCommand: # type: ignore[no-untyped-def]
if cmd[0][0] != '/' and cmd[0][:2] != './':
# This check is also done in SysCommand & SysCommandWorker.
# However, that check is done for `machinectl` and not for our chroot command.
# So this wrapper for SysCommand will do this additionally.
cmd[0] = locate_binary(cmd[0])
return SysCommand(['systemd-run', f'--machine={self.container_name}', '--pty', *cmd], *args, **kwargs)
def SysCommandWorker(self, cmd: list[str], *args, **kwargs) -> SysCommandWorker: # type: ignore[no-untyped-def]
if cmd[0][0] != '/' and cmd[0][:2] != './':
cmd[0] = locate_binary(cmd[0])
return SysCommandWorker(['systemd-run', f'--machine={self.container_name}', '--pty', *cmd], *args, **kwargs)
================================================
FILE: archinstall/lib/bootloader/__init__.py
================================================
================================================
FILE: archinstall/lib/bootloader/bootloader_menu.py
================================================
import textwrap
from typing import override
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
def __init__(
self,
bootloader_conf: BootloaderConfiguration,
uefi: bool,
skip_boot: bool = False,
):
self._bootloader_conf = bootloader_conf
self._skip_boot = skip_boot
self._uefi = uefi
menu_options = self._define_menu_options()
self._item_group = MenuItemGroup(menu_options, sort_items=False, checkmarks=True)
super().__init__(
self._item_group,
config=self._bootloader_conf,
allow_reset=False,
)
def _define_menu_options(self) -> list[MenuItem]:
bootloader = self._bootloader_conf.bootloader
# UKI availability
uki_enabled = self._uefi and bootloader.has_uki_support()
if not uki_enabled:
self._bootloader_conf.uki = False
# Removable availability
removable_enabled = self._uefi and bootloader.has_removable_support()
if not removable_enabled:
self._bootloader_conf.removable = False
return [
MenuItem(
text=tr('Bootloader'),
action=self._select_bootloader,
value=self._bootloader_conf.bootloader,
preview_action=self._prev_bootloader,
mandatory=True,
key='bootloader',
),
MenuItem(
text=tr('Unified kernel images'),
action=self._select_uki,
value=self._bootloader_conf.uki,
preview_action=self._prev_uki,
key='uki',
enabled=uki_enabled,
),
MenuItem(
text=tr('Install to removable location'),
action=self._select_removable,
value=self._bootloader_conf.removable,
preview_action=self._prev_removable,
key='removable',
enabled=removable_enabled,
),
]
def _prev_bootloader(self, item: MenuItem) -> str | None:
if item.value:
return f'{tr("Bootloader")}: {item.value.value}'
return None
def _prev_uki(self, item: MenuItem) -> str | None:
uki_text = f'{tr("Unified kernel images")}'
if item.value:
return f'{uki_text}: {tr("Enabled")}'
else:
return f'{uki_text}: {tr("Disabled")}'
def _prev_removable(self, item: MenuItem) -> str | None:
if item.value:
return tr('Will install to /EFI/BOOT/ (removable location, safe default)')
return tr('Will install to custom location with NVRAM entry')
@override
async def show(self) -> BootloaderConfiguration:
_ = await super().show()
return self._bootloader_conf
async def _select_bootloader(self, preset: Bootloader | None) -> Bootloader | None:
bootloader = await select_bootloader(preset, self._uefi, self._skip_boot)
if bootloader:
# Update UKI option based on bootloader
uki_item = self._menu_item_group.find_by_key('uki')
if not self._uefi or not bootloader.has_uki_support():
uki_item.enabled = False
uki_item.value = False
self._bootloader_conf.uki = False
else:
uki_item.enabled = True
# Update removable option based on bootloader
removable_item = self._menu_item_group.find_by_key('removable')
if not self._uefi or not bootloader.has_removable_support():
removable_item.enabled = False
removable_item.value = False
self._bootloader_conf.removable = False
else:
if not removable_item.enabled:
removable_item.value = True
self._bootloader_conf.removable = True
removable_item.enabled = True
return bootloader
async def _select_uki(self, preset: bool) -> bool:
prompt = tr('Would you like to use unified kernel images?') + '\n'
result = await Confirmation(header=prompt, allow_skip=True, preset=preset).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.item() == MenuItem.yes()
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def _select_removable(self, preset: bool) -> bool:
prompt = (
tr('Would you like to install the bootloader to the default removable media search location?')
+ '\n\n'
+ tr('This installs the bootloader to /EFI/BOOT/BOOTX64.EFI (or similar) which is useful for:')
+ '\n\n • '
+ tr('Firmware that does not properly support NVRAM boot entries like most MSI motherboards,')
+ '\n '
+ tr('most Apple Macs, many laptops...')
+ '\n • '
+ tr('USB drives or other portable external media.')
+ '\n • '
+ tr('Systems where you want the disk to be bootable on any computer.')
+ '\n\n'
+ tr(
textwrap.dedent(
"""\
If you do not know what this means, LEAVE THIS OPTION ENABLED, as it is the safe default.
It is suggested to disable this if none of the above apply, as it makes installing multiple
EFI bootloaders on the same disk easier, and it will not overwrite whatever bootloader
was previously installed at the default removable media search location, if any.
It may also make the installation more resilient in case of dual-booting with Windows,
as Windows is known to sometimes erase or replace the bootloader installed at the removable
location.
"""
)
)
+ '\n'
)
result = await Confirmation(
header=prompt,
allow_skip=True,
preset=preset,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.get_value()
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def select_bootloader(
preset: Bootloader | None,
uefi: bool,
skip_boot: bool = False,
) -> Bootloader | None:
options = []
hidden_options = []
header = tr('Select bootloader to install')
default = Bootloader.get_default(uefi, skip_boot)
if not skip_boot:
hidden_options += [Bootloader.NO_BOOTLOADER]
if not uefi:
options += [Bootloader.Grub, Bootloader.Limine]
header += '\n' + tr('UEFI is not detected and some options are disabled')
else:
options += [b for b in Bootloader if b not in hidden_options]
items = [MenuItem(o.value, value=o) for o in options]
group = MenuItemGroup(items)
group.set_default_by_value(default)
group.set_focus_by_value(preset)
result = await Selection[Bootloader](
group,
header=header,
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.get_value()
case ResultType.Reset:
raise ValueError('Unhandled result type')
================================================
FILE: archinstall/lib/command.py
================================================
import os
import shlex
import stat
import subprocess
import sys
import time
from collections.abc import Iterator
from select import EPOLLHUP, EPOLLIN, epoll
from shutil import which
from types import TracebackType
from typing import Any, Self, override
from archinstall.lib.exceptions import RequirementError, SysCallError
from archinstall.lib.output import debug, error, logger
from archinstall.lib.utils.encoding import clear_vt100_escape_codes
class SysCommandWorker:
def __init__(
self,
cmd: str | list[str],
peek_output: bool | None = False,
environment_vars: dict[str, str] | None = None,
working_directory: str = './',
remove_vt100_escape_codes_from_lines: bool = True,
):
if isinstance(cmd, str):
cmd = shlex.split(cmd)
if cmd and not cmd[0].startswith(('/', './')): # Path() does not work well
cmd[0] = locate_binary(cmd[0])
self.cmd = cmd
self.peek_output = peek_output
# define the standard locale for command outputs. For now the C ascii one. Can be overridden
self.environment_vars = {'LC_ALL': 'C'}
if environment_vars:
self.environment_vars.update(environment_vars)
self.working_directory = working_directory
self.exit_code: int | None = None
self._trace_log = b''
self._trace_log_pos = 0
self.poll_object = epoll()
self.child_fd: int | None = None
self.started: float | None = None
self.ended: float | None = None
self.remove_vt100_escape_codes_from_lines: bool = remove_vt100_escape_codes_from_lines
def __contains__(self, key: bytes) -> bool:
"""
Contains will also move the current buffert position forward.
This is to avoid re-checking the same data when looking for output.
"""
assert isinstance(key, bytes)
index = self._trace_log.find(key, self._trace_log_pos)
if index >= 0:
self._trace_log_pos += index + len(key)
return True
return False
def __iter__(self, *args: str, **kwargs: dict[str, Any]) -> Iterator[bytes]:
last_line = self._trace_log.rfind(b'\n')
lines = filter(None, self._trace_log[self._trace_log_pos : last_line].splitlines())
for line in lines:
if self.remove_vt100_escape_codes_from_lines:
line = clear_vt100_escape_codes(line)
yield line + b'\n'
self._trace_log_pos = last_line
@override
def __repr__(self) -> str:
self.make_sure_we_are_executing()
return str(self._trace_log)
@override
def __str__(self) -> str:
try:
return self._trace_log.decode('utf-8')
except UnicodeDecodeError:
return str(self._trace_log)
def __enter__(self) -> Self:
return self
def __exit__(self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None) -> None:
# b''.join(sys_command('sync')) # No need to, since the underlying fs() object will call sync.
# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager
if self.child_fd:
try:
os.close(self.child_fd)
except Exception:
pass
if self.peek_output:
# To make sure any peaked output didn't leave us hanging
# on the same line we were on.
sys.stdout.write('\n')
sys.stdout.flush()
if exc_type is not None:
debug(str(exc_value))
if self.exit_code != 0:
raise SysCallError(
f'{self.cmd} exited with abnormal exit code [{self.exit_code}]: {str(self)[-500:]}',
self.exit_code,
worker_log=self._trace_log,
)
def is_alive(self) -> bool:
self.poll()
if self.started and self.ended is None:
return True
return False
def write(self, data: bytes, line_ending: bool = True) -> int:
assert isinstance(data, bytes) # TODO: Maybe we can support str as well and encode it
self.make_sure_we_are_executing()
if self.child_fd:
return os.write(self.child_fd, data + (b'\n' if line_ending else b''))
return 0
def make_sure_we_are_executing(self) -> bool:
if not self.started:
return self.execute()
return True
def tell(self) -> int:
self.make_sure_we_are_executing()
return self._trace_log_pos
def seek(self, pos: int) -> None:
self.make_sure_we_are_executing()
# Safety check to ensure 0 < pos < len(tracelog)
self._trace_log_pos = min(max(0, pos), len(self._trace_log))
def peak(self, output: str | bytes) -> bool:
if self.peek_output:
if isinstance(output, bytes):
try:
output = output.decode('UTF-8')
except UnicodeDecodeError:
return False
_cmd_output(output)
sys.stdout.write(output)
sys.stdout.flush()
return True
def poll(self) -> None:
self.make_sure_we_are_executing()
if self.child_fd:
got_output = False
for _fileno, _event in self.poll_object.poll(0.1):
try:
output = os.read(self.child_fd, 8192)
got_output = True
self.peak(output)
self._trace_log += output
except OSError:
self.ended = time.time()
break
if self.ended or (not got_output and not _pid_exists(self.pid)):
self.ended = time.time()
try:
wait_status = os.waitpid(self.pid, 0)[1]
self.exit_code = os.waitstatus_to_exitcode(wait_status)
except ChildProcessError:
try:
wait_status = os.waitpid(self.child_fd, 0)[1]
self.exit_code = os.waitstatus_to_exitcode(wait_status)
except ChildProcessError:
self.exit_code = 1
def execute(self) -> bool:
import pty
if (old_dir := os.getcwd()) != self.working_directory:
os.chdir(str(self.working_directory))
# Note: If for any reason, we get a Python exception between here
# and until os.close(), the traceback will get locked inside
# stdout of the child_fd object. `os.read(self.child_fd, 8192)` is the
# only way to get the traceback without losing it.
self.pid, self.child_fd = pty.fork()
# https://stackoverflow.com/questions/4022600/python-pty-fork-how-does-it-work
if not self.pid:
_cmd_history(self.cmd)
try:
os.execve(self.cmd[0], list(self.cmd), {**os.environ, **self.environment_vars})
except FileNotFoundError:
error(f'{self.cmd[0]} does not exist.')
self.exit_code = 1
return False
else:
# Only parent process moves back to the original working directory
os.chdir(old_dir)
self.started = time.time()
self.poll_object.register(self.child_fd, EPOLLIN | EPOLLHUP)
return True
def decode(self, encoding: str = 'UTF-8') -> str:
return self._trace_log.decode(encoding)
class SysCommand:
def __init__(
self,
cmd: str | list[str],
peek_output: bool | None = False,
environment_vars: dict[str, str] | None = None,
working_directory: str = './',
remove_vt100_escape_codes_from_lines: bool = True,
):
self.cmd = cmd
self.peek_output = peek_output
self.environment_vars = environment_vars
self.working_directory = working_directory
self.remove_vt100_escape_codes_from_lines = remove_vt100_escape_codes_from_lines
self.session: SysCommandWorker | None = None
self.create_session()
def __enter__(self) -> SysCommandWorker | None:
return self.session
def __exit__(self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None) -> None:
# b''.join(sys_command('sync')) # No need to, since the underlying fs() object will call sync.
# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager
if exc_type is not None:
error(str(exc_value))
def __iter__(self, *args: list[Any], **kwargs: dict[str, Any]) -> Iterator[bytes]:
if self.session:
yield from self.session
def __getitem__(self, key: slice) -> bytes:
if not self.session:
raise KeyError('SysCommand() does not have an active session.')
elif type(key) is slice:
start = key.start or 0
end = key.stop or len(self.session._trace_log)
return self.session._trace_log[start:end]
else:
raise ValueError("SysCommand() doesn't have key & value pairs, only slices, SysCommand('ls')[:10] as an example.")
@override
def __repr__(self, *args: list[Any], **kwargs: dict[str, Any]) -> str:
return self.decode('UTF-8', errors='backslashreplace') or ''
def create_session(self) -> bool:
"""
Initiates a :ref:`SysCommandWorker` session in this class ``.session``.
It then proceeds to poll the process until it ends, after which it also
clears any printed output if ``.peek_output=True``.
"""
if self.session:
return True
with SysCommandWorker(
self.cmd,
peek_output=self.peek_output,
environment_vars=self.environment_vars,
remove_vt100_escape_codes_from_lines=self.remove_vt100_escape_codes_from_lines,
working_directory=self.working_directory,
) as session:
self.session = session
while not self.session.ended:
self.session.poll()
if self.peek_output:
sys.stdout.write('\n')
sys.stdout.flush()
return True
def decode(self, encoding: str = 'utf-8', errors: str = 'backslashreplace', strip: bool = True) -> str:
if not self.session:
raise ValueError('No session available to decode')
val = self.session._trace_log.decode(encoding, errors=errors)
if strip:
return val.strip()
return val
def output(self, remove_cr: bool = True) -> bytes:
if not self.session:
raise ValueError('No session available')
if remove_cr:
return self.session._trace_log.replace(b'\r\n', b'\n')
return self.session._trace_log
@property
def exit_code(self) -> int | None:
if self.session:
return self.session.exit_code
else:
return None
@property
def trace_log(self) -> bytes | None:
if self.session:
return self.session._trace_log
return None
def run(
cmd: list[str],
input_data: bytes | None = None,
) -> subprocess.CompletedProcess[bytes]:
_cmd_history(cmd)
return subprocess.run(
cmd,
input=input_data,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True,
)
def locate_binary(name: str) -> str:
if path := which(name):
return path
raise RequirementError(f'Binary {name} does not exist.')
def _pid_exists(pid: int) -> bool:
try:
return any(subprocess.check_output(['ps', '--no-headers', '-o', 'pid', '-p', str(pid)]).strip())
except subprocess.CalledProcessError:
return False
def _cmd_history(cmd: list[str]) -> None:
content = f'{time.time()} {cmd}\n'
_append_log('cmd_history.txt', content)
def _cmd_output(output: str) -> None:
_append_log('cmd_output.txt', output)
def _append_log(file: str, content: str) -> None:
path = logger.directory / file
change_perm = not path.exists()
try:
with path.open('a') as f:
f.write(content)
if change_perm:
path.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
except (PermissionError, FileNotFoundError):
# If the file does not exist, ignore the error
pass
================================================
FILE: archinstall/lib/configuration.py
================================================
import json
import readline
import stat
from pathlib import Path
from typing import Any
from pydantic import TypeAdapter
from archinstall.lib.args import ArchConfig
from archinstall.lib.crypt import encrypt
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.menu.util import get_password, prompt_dir
from archinstall.lib.output import debug, logger, warn
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class ConfigurationOutput:
def __init__(self, config: ArchConfig):
"""
Configuration output handler to parse the existing
configuration data structure and prepare for output on the
console and for saving it to configuration files
:param config: Archinstall configuration object
:type config: ArchConfig
"""
self._config = config
self._default_save_path = logger.directory
self._user_config_file = Path('user_configuration.json')
self._user_creds_file = Path('user_credentials.json')
@property
def user_configuration_file(self) -> Path:
return self._user_config_file
@property
def user_credentials_file(self) -> Path:
return self._user_creds_file
def user_config_to_json(self) -> str:
config = self._config.safe_config()
adapter = TypeAdapter(dict[str, Any])
python_dict = adapter.dump_python(config)
return json.dumps(python_dict, indent=4, sort_keys=True)
def user_credentials_to_json(self) -> str:
config = self._config.unsafe_config()
adapter = TypeAdapter(dict[str, Any])
python_dict = adapter.dump_python(config)
return json.dumps(python_dict, indent=4, sort_keys=True)
def write_debug(self) -> None:
debug(' -- Chosen configuration --')
debug(self.user_config_to_json())
async def confirm_config(self) -> bool:
header = f'{tr("The specified configuration will be applied")}. '
header += tr('Would you like to continue?') + '\n'
group = MenuItemGroup.yes_no()
group.set_preview_for_all(lambda x: self.user_config_to_json())
result = await Confirmation(
group=group,
header=header,
allow_skip=False,
preset=True,
preview_location='bottom',
preview_header=tr('Configuration preview'),
).show()
if not result.get_value():
return False
return True
def _is_valid_path(self, dest_path: Path) -> bool:
dest_path_ok = dest_path.exists() and dest_path.is_dir()
if not dest_path_ok:
warn(
f'Destination directory {dest_path.resolve()} does not exist or is not a directory\n.',
'Configuration files can not be saved',
)
return dest_path_ok
def save_user_config(self, dest_path: Path) -> None:
if self._is_valid_path(dest_path):
target = dest_path / self._user_config_file
target.write_text(self.user_config_to_json())
target.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
def save_user_creds(
self,
dest_path: Path,
password: str | None = None,
) -> None:
data = self.user_credentials_to_json()
if password:
data = encrypt(password, data)
if self._is_valid_path(dest_path):
target = dest_path / self._user_creds_file
target.write_text(data)
target.chmod(stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
def save(
self,
dest_path: Path | None = None,
creds: bool = False,
password: str | None = None,
) -> None:
save_path = dest_path or self._default_save_path
if self._is_valid_path(save_path):
self.save_user_config(save_path)
if creds:
self.save_user_creds(save_path, password=password)
async def save_config(config: ArchConfig) -> None:
def preview(item: MenuItem) -> str | None:
match item.value:
case 'user_config':
serialized = config_output.user_config_to_json()
return f'{config_output.user_configuration_file}\n{serialized}'
case 'user_creds':
if maybe_serial := config_output.user_credentials_to_json():
return f'{config_output.user_credentials_file}\n{maybe_serial}'
return tr('No configuration')
case 'all':
output = [str(config_output.user_configuration_file)]
config_output.user_credentials_to_json()
output.append(str(config_output.user_credentials_file))
return '\n'.join(output)
return None
config_output = ConfigurationOutput(config)
items = [
MenuItem(
tr('Save user configuration (including disk layout)'),
value='user_config',
preview_action=preview,
),
MenuItem(
tr('Save user credentials'),
value='user_creds',
preview_action=preview,
),
MenuItem(
tr('Save all'),
value='all',
preview_action=preview,
),
]
group = MenuItemGroup(items)
result = await Selection[str](
group,
allow_skip=True,
preview_location='right',
).show()
match result.type_:
case ResultType.Skip:
return
case ResultType.Selection:
save_option = result.get_value()
case _:
raise ValueError('Unhandled return type')
readline.set_completer_delims('\t\n=')
readline.parse_and_bind('tab: complete')
dest_path = await prompt_dir(
tr('Enter a directory for the configuration(s) to be saved') + '\n',
allow_skip=True,
)
if not dest_path:
return
header = tr('Do you want to save the configuration file(s) to {}?').format(dest_path)
save_result = await Confirmation(
header=header,
allow_skip=False,
preset=True,
).show()
match save_result.type_:
case ResultType.Selection:
if not save_result.get_value():
return
case _:
return
debug(f'Saving configuration files to {dest_path.absolute()}')
header = tr('Do you want to encrypt the user_credentials.json file?')
enc_result = await Confirmation(
header=header,
allow_skip=False,
preset=False,
).show()
enc_password: str | None = None
if enc_result.type_ == ResultType.Selection:
if enc_result.get_value():
password = await get_password(
header=tr('Credentials file encryption password'),
allow_skip=True,
)
if password:
enc_password = password.plaintext
match save_option:
case 'user_config':
config_output.save_user_config(dest_path)
case 'user_creds':
config_output.save_user_creds(dest_path, password=enc_password)
case 'all':
config_output.save(dest_path, creds=True, password=enc_password)
================================================
FILE: archinstall/lib/crypt.py
================================================
import base64
import ctypes
import os
from pathlib import Path
from cryptography.fernet import Fernet, InvalidToken
from cryptography.hazmat.primitives.kdf.argon2 import Argon2id
from archinstall.lib.output import debug
libcrypt = ctypes.CDLL('libcrypt.so')
libcrypt.crypt.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
libcrypt.crypt.restype = ctypes.c_char_p
libcrypt.crypt_gensalt.argtypes = [ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p, ctypes.c_int]
libcrypt.crypt_gensalt.restype = ctypes.c_char_p
LOGIN_DEFS = Path('/etc/login.defs')
def _search_login_defs(key: str) -> str | None:
defs = LOGIN_DEFS.read_text()
for line in defs.split('\n'):
line = line.strip()
if line.startswith('#'):
continue
if line.startswith(key):
value = line.split(' ')[1]
return value
return None
def crypt_gen_salt(prefix: str | bytes, rounds: int) -> bytes:
if isinstance(prefix, str):
prefix = prefix.encode('utf-8')
setting = libcrypt.crypt_gensalt(prefix, rounds, None, 0)
if setting is None:
raise ValueError(f'crypt_gensalt() returned NULL for prefix {prefix!r} and rounds {rounds}')
return setting
def crypt_yescrypt(plaintext: str) -> str:
"""
By default chpasswd in Arch uses PAM to hash the password with crypt_yescrypt
the PAM code https://github.com/linux-pam/linux-pam/blob/master/modules/pam_unix/support.c
shows that the hashing rounds are determined from YESCRYPT_COST_FACTOR in /etc/login.defs
If no value was specified (or commented out) a default of 5 is chosen
"""
value = _search_login_defs('YESCRYPT_COST_FACTOR')
if value is not None:
rounds = int(value)
if rounds < 3:
rounds = 3
elif rounds > 11:
rounds = 11
else:
rounds = 5
debug(f'Creating yescrypt hash with rounds {rounds}')
enc_plaintext = plaintext.encode('utf-8')
salt = crypt_gen_salt('$y$', rounds)
crypt_hash = libcrypt.crypt(enc_plaintext, salt)
if crypt_hash is None:
raise ValueError('crypt() returned NULL')
return crypt_hash.decode('utf-8')
def _get_fernet(salt: bytes, password: str) -> Fernet:
# https://cryptography.io/en/latest/hazmat/primitives/key-derivation-functions/#argon2id
kdf = Argon2id(
salt=salt,
length=32,
iterations=1,
lanes=4,
memory_cost=64 * 1024,
ad=None,
secret=None,
)
key = base64.urlsafe_b64encode(
kdf.derive(
password.encode('utf-8'),
),
)
return Fernet(key)
def encrypt(password: str, data: str) -> str:
salt = os.urandom(16)
f = _get_fernet(salt, password)
token = f.encrypt(data.encode('utf-8'))
encoded_token = base64.urlsafe_b64encode(token).decode('utf-8')
encoded_salt = base64.urlsafe_b64encode(salt).decode('utf-8')
return f'$argon2id${encoded_salt}${encoded_token}'
def decrypt(data: str, password: str) -> str:
_, algo, encoded_salt, encoded_token = data.split('$')
salt = base64.urlsafe_b64decode(encoded_salt)
token = base64.urlsafe_b64decode(encoded_token)
if algo != 'argon2id':
raise ValueError(f'Unsupported algorithm {algo!r}')
f = _get_fernet(salt, password)
try:
decrypted = f.decrypt(token)
except InvalidToken:
raise ValueError('Invalid password')
return decrypted.decode('utf-8')
================================================
FILE: archinstall/lib/disk/__init__.py
================================================
================================================
FILE: archinstall/lib/disk/device_handler.py
================================================
import logging
import os
from pathlib import Path
from parted import Device, Disk, DiskException, FileSystem, Geometry, IOException, Partition, PartitionException, freshDisk, getAllDevices, getDevice, newDisk
from archinstall.lib.command import SysCommand
from archinstall.lib.disk.utils import (
find_lsblk_info,
get_all_lsblk_info,
get_lsblk_info,
mount,
udev_sync,
umount,
)
from archinstall.lib.exceptions import DiskError, SysCallError, UnknownFilesystemFormat
from archinstall.lib.luks import Luks2, unlock_luks2_dev
from archinstall.lib.models.device import (
DEFAULT_ITER_TIME,
BDevice,
BtrfsMountOption,
DeviceModification,
DiskEncryption,
FilesystemType,
LsblkInfo,
ModificationStatus,
PartitionFlag,
PartitionGUID,
PartitionModification,
PartitionTable,
SubvolumeModification,
Unit,
_BtrfsSubvolumeInfo,
_DeviceInfo,
_PartitionInfo,
)
from archinstall.lib.models.users import Password
from archinstall.lib.output import debug, error, info, log
from archinstall.lib.utils.util import is_subpath
class DeviceHandler:
_TMP_BTRFS_MOUNT = Path('/mnt/arch_btrfs')
def __init__(self) -> None:
self._devices: dict[Path, BDevice] = {}
self._partition_table = PartitionTable.default()
self.load_devices()
@property
def devices(self) -> list[BDevice]:
return list(self._devices.values())
@property
def partition_table(self) -> PartitionTable:
return self._partition_table
def load_devices(self) -> None:
block_devices = {}
udev_sync()
all_lsblk_info = get_all_lsblk_info()
devices = getAllDevices()
devices.extend(self.get_loop_devices())
archiso_mountpoint = Path('/run/archiso/airootfs')
for device in devices:
dev_lsblk_info = find_lsblk_info(device.path, all_lsblk_info)
if not dev_lsblk_info:
debug(f'Device lsblk info not found: {device.path}')
continue
if dev_lsblk_info.type == 'rom':
continue
# exclude archiso loop device
if dev_lsblk_info.mountpoint == archiso_mountpoint:
continue
try:
if dev_lsblk_info.pttype:
disk = newDisk(device)
else:
disk = freshDisk(device, self.partition_table.value)
except DiskException as err:
debug(f'Unable to get disk from {device.path}: {err}')
continue
device_info = _DeviceInfo.from_disk(disk)
partition_infos = []
for partition in disk.partitions:
lsblk_info = find_lsblk_info(partition.path, dev_lsblk_info.children)
if not lsblk_info:
debug(f'Partition lsblk info not found: {partition.path}')
continue
fs_type = self._determine_fs_type(partition, lsblk_info)
subvol_infos = []
if fs_type == FilesystemType.Btrfs:
subvol_infos = self.get_btrfs_info(partition.path, lsblk_info)
partition_infos.append(
_PartitionInfo.from_partition(
partition,
lsblk_info,
fs_type,
subvol_infos,
),
)
block_device = BDevice(disk, device_info, partition_infos)
block_devices[block_device.device_info.path] = block_device
self._devices = block_devices
@staticmethod
def get_loop_devices() -> list[Device]:
devices = []
try:
loop_devices = SysCommand(['losetup', '-a'])
except SysCallError as err:
debug(f'Failed to get loop devices: {err}')
else:
for ld_info in str(loop_devices).splitlines():
try:
loop_device_path, _ = ld_info.split(':', maxsplit=1)
except ValueError:
continue
try:
loop_device = getDevice(loop_device_path)
except IOException as err:
debug(f'Failed to get loop device: {err}')
else:
devices.append(loop_device)
return devices
def _determine_fs_type(
self,
partition: Partition,
lsblk_info: LsblkInfo | None = None,
) -> FilesystemType | None:
try:
if partition.fileSystem:
if partition.fileSystem.type == FilesystemType.LinuxSwap.parted_value:
return FilesystemType.LinuxSwap
return FilesystemType(partition.fileSystem.type)
elif lsblk_info is not None:
return FilesystemType(lsblk_info.fstype) if lsblk_info.fstype else None
return None
except ValueError:
debug(f'Could not determine the filesystem: {partition.fileSystem}')
return None
def get_device(self, path: Path) -> BDevice | None:
return self._devices.get(path, None)
def get_device_by_partition_path(self, partition_path: Path) -> BDevice | None:
partition = self.find_partition(partition_path)
if partition:
device: Device = partition.disk.device
return self.get_device(Path(device.path))
return None
def find_partition(self, path: Path) -> _PartitionInfo | None:
for device in self._devices.values():
part = next(filter(lambda x: str(x.path) == str(path), device.partition_infos), None)
if part is not None:
return part
return None
def get_uuid_for_path(self, path: Path) -> str | None:
partition = self.find_partition(path)
return partition.partuuid if partition else None
def get_btrfs_info(
self,
dev_path: Path,
lsblk_info: LsblkInfo | None = None,
) -> list[_BtrfsSubvolumeInfo]:
if not lsblk_info:
lsblk_info = get_lsblk_info(dev_path)
subvol_infos: list[_BtrfsSubvolumeInfo] = []
if not lsblk_info.mountpoint:
mount(dev_path, self._TMP_BTRFS_MOUNT, create_target_mountpoint=True)
mountpoint = self._TMP_BTRFS_MOUNT
else:
# when multiple subvolumes are mounted then the lsblk output may look like
# "mountpoint": "/mnt/archinstall/var/log"
# "mountpoints": ["/mnt/archinstall/var/log", "/mnt/archinstall/home", ..]
# so we'll determine the minimum common path and assume that's the root
try:
common_path = os.path.commonpath(lsblk_info.mountpoints)
except ValueError:
return subvol_infos
mountpoint = Path(common_path)
try:
result = SysCommand(f'btrfs subvolume list {mountpoint}').decode()
except SysCallError as err:
debug(f'Failed to read btrfs subvolume information: {err}')
return subvol_infos
# It is assumed that lsblk will contain the fields as
# "mountpoints": ["/mnt/archinstall/log", "/mnt/archinstall/home", "/mnt/archinstall", ...]
# "fsroots": ["/@log", "/@home", "/@"...]
# we'll thereby map the fsroot, which are the mounted filesystem roots
# to the corresponding mountpoints
btrfs_subvol_info = dict(zip(lsblk_info.fsroots, lsblk_info.mountpoints))
# ID 256 gen 16 top level 5 path @
for line in result.splitlines():
# expected output format:
# ID 257 gen 8 top level 5 path @home
name = Path(line.split(' ')[-1])
sub_vol_mountpoint = btrfs_subvol_info.get('/' / name, None)
subvol_infos.append(_BtrfsSubvolumeInfo(name, sub_vol_mountpoint))
if not lsblk_info.mountpoint:
umount(dev_path)
return subvol_infos
def format(
self,
fs_type: FilesystemType,
path: Path,
additional_parted_options: list[str] = [],
) -> None:
mkfs_type = fs_type.value
command = None
options = []
match fs_type:
case FilesystemType.Btrfs | FilesystemType.Xfs:
# Force overwrite
options.append('-f')
case FilesystemType.F2fs:
options.append('-f')
options.extend(('-O', 'extra_attr'))
case FilesystemType.Ext2 | FilesystemType.Ext3 | FilesystemType.Ext4:
# Force create
options.append('-F')
case FilesystemType.Fat12 | FilesystemType.Fat16 | FilesystemType.Fat32:
mkfs_type = 'fat'
# Set FAT size
options.extend(('-F', fs_type.value.removeprefix(mkfs_type)))
case FilesystemType.LinuxSwap:
command = 'mkswap'
case _:
raise UnknownFilesystemFormat(f'Filetype "{fs_type.value}" is not supported')
if not command:
command = f'mkfs.{mkfs_type}'
cmd = [command, *options, *additional_parted_options, str(path)]
debug('Formatting filesystem:', ' '.join(cmd))
try:
SysCommand(cmd)
except SysCallError as err:
msg = f'Could not format {path} with {fs_type.value}: {err.message}'
error(msg)
raise DiskError(msg) from err
def encrypt(
self,
dev_path: Path,
mapper_name: str | None,
enc_password: Password | None,
lock_after_create: bool = True,
iter_time: int = DEFAULT_ITER_TIME,
) -> Luks2:
luks_handler = Luks2(
dev_path,
mapper_name=mapper_name,
password=enc_password,
)
key_file = luks_handler.encrypt(iter_time=iter_time)
udev_sync()
luks_handler.unlock(key_file=key_file)
if not luks_handler.mapper_dev:
raise DiskError('Failed to unlock luks device')
if lock_after_create:
debug(f'luks2 locking device: {dev_path}')
luks_handler.lock()
return luks_handler
def format_encrypted(
self,
dev_path: Path,
mapper_name: str | None,
fs_type: FilesystemType,
enc_conf: DiskEncryption,
) -> None:
if not enc_conf.encryption_password:
raise ValueError('No encryption password provided')
luks_handler = Luks2(
dev_path,
mapper_name=mapper_name,
password=enc_conf.encryption_password,
)
key_file = luks_handler.encrypt(iter_time=enc_conf.iter_ti
gitextract_v4no44_h/
├── .editorconfig
├── .flake8
├── .github/
│ ├── CODEOWNERS
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 01_bug.yml
│ │ └── 02_feature.yml
│ └── workflows/
│ ├── bandit.yaml
│ ├── flake8.yaml
│ ├── github-pages.yml
│ ├── iso-build.yaml
│ ├── mypy.yaml
│ ├── pylint.yaml
│ ├── pytest.yaml
│ ├── python-build.yml
│ ├── python-publish.yml
│ ├── ruff-format.yaml
│ ├── ruff-lint.yaml
│ └── translation-check.yaml
├── .gitignore
├── .gitlab-ci.yml
├── .pre-commit-config.yaml
├── .pypirc
├── .readthedocs.yaml
├── CONTRIBUTING.md
├── LICENSE
├── PKGBUILD
├── README.md
├── archinstall/
│ ├── __init__.py
│ ├── __main__.py
│ ├── applications/
│ │ ├── audio.py
│ │ ├── bluetooth.py
│ │ ├── firewall.py
│ │ ├── power_management.py
│ │ └── print_service.py
│ ├── default_profiles/
│ │ ├── __init__.py
│ │ ├── desktop.py
│ │ ├── desktops/
│ │ │ ├── __init__.py
│ │ │ ├── awesome.py
│ │ │ ├── bspwm.py
│ │ │ ├── budgie.py
│ │ │ ├── cinnamon.py
│ │ │ ├── cosmic.py
│ │ │ ├── cutefish.py
│ │ │ ├── deepin.py
│ │ │ ├── enlightenment.py
│ │ │ ├── gnome.py
│ │ │ ├── hyprland.py
│ │ │ ├── i3.py
│ │ │ ├── labwc.py
│ │ │ ├── lxqt.py
│ │ │ ├── mate.py
│ │ │ ├── niri.py
│ │ │ ├── plasma.py
│ │ │ ├── qtile.py
│ │ │ ├── river.py
│ │ │ ├── sway.py
│ │ │ ├── xfce4.py
│ │ │ └── xmonad.py
│ │ ├── minimal.py
│ │ ├── profile.py
│ │ ├── server.py
│ │ ├── servers/
│ │ │ ├── __init__.py
│ │ │ ├── cockpit.py
│ │ │ ├── docker.py
│ │ │ ├── httpd.py
│ │ │ ├── lighttpd.py
│ │ │ ├── mariadb.py
│ │ │ ├── nginx.py
│ │ │ ├── postgresql.py
│ │ │ ├── sshd.py
│ │ │ └── tomcat.py
│ │ └── xorg.py
│ ├── lib/
│ │ ├── __init__.py
│ │ ├── applications/
│ │ │ ├── __init__.py
│ │ │ ├── application_handler.py
│ │ │ └── application_menu.py
│ │ ├── args.py
│ │ ├── authentication/
│ │ │ ├── __init__.py
│ │ │ ├── authentication_handler.py
│ │ │ └── authentication_menu.py
│ │ ├── boot.py
│ │ ├── bootloader/
│ │ │ ├── __init__.py
│ │ │ └── bootloader_menu.py
│ │ ├── command.py
│ │ ├── configuration.py
│ │ ├── crypt.py
│ │ ├── disk/
│ │ │ ├── __init__.py
│ │ │ ├── device_handler.py
│ │ │ ├── disk_menu.py
│ │ │ ├── encryption_menu.py
│ │ │ ├── fido.py
│ │ │ ├── filesystem.py
│ │ │ ├── lvm.py
│ │ │ ├── partitioning_menu.py
│ │ │ ├── subvolume_menu.py
│ │ │ └── utils.py
│ │ ├── exceptions.py
│ │ ├── global_menu.py
│ │ ├── hardware.py
│ │ ├── installer.py
│ │ ├── interactions/
│ │ │ ├── __init__.py
│ │ │ ├── disk_conf.py
│ │ │ ├── general_conf.py
│ │ │ └── system_conf.py
│ │ ├── locale/
│ │ │ ├── __init__.py
│ │ │ ├── locale_menu.py
│ │ │ └── utils.py
│ │ ├── luks.py
│ │ ├── menu/
│ │ │ ├── __init__.py
│ │ │ ├── abstract_menu.py
│ │ │ ├── helpers.py
│ │ │ ├── list_manager.py
│ │ │ ├── menu_helper.py
│ │ │ └── util.py
│ │ ├── mirror/
│ │ │ ├── __init__.py
│ │ │ ├── mirror_handler.py
│ │ │ └── mirror_menu.py
│ │ ├── models/
│ │ │ ├── __init__.py
│ │ │ ├── application.py
│ │ │ ├── authentication.py
│ │ │ ├── bootloader.py
│ │ │ ├── device.py
│ │ │ ├── locale.py
│ │ │ ├── mirrors.py
│ │ │ ├── network.py
│ │ │ ├── packages.py
│ │ │ ├── profile.py
│ │ │ └── users.py
│ │ ├── network/
│ │ │ ├── __init__.py
│ │ │ ├── network_handler.py
│ │ │ ├── network_menu.py
│ │ │ ├── wifi_handler.py
│ │ │ └── wpa_supplicant.py
│ │ ├── networking.py
│ │ ├── output.py
│ │ ├── packages/
│ │ │ ├── __init__.py
│ │ │ ├── packages.py
│ │ │ └── util.py
│ │ ├── pacman/
│ │ │ ├── __init__.py
│ │ │ ├── config.py
│ │ │ └── pacman.py
│ │ ├── plugins.py
│ │ ├── profile/
│ │ │ ├── __init__.py
│ │ │ ├── profile_menu.py
│ │ │ └── profiles_handler.py
│ │ ├── translationhandler.py
│ │ ├── user/
│ │ │ ├── __init__.py
│ │ │ └── user_menu.py
│ │ ├── utils/
│ │ │ ├── __init__.py
│ │ │ ├── encoding.py
│ │ │ └── util.py
│ │ └── version.py
│ ├── locales/
│ │ ├── README.md
│ │ ├── ar/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── base.pot
│ │ ├── ca/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── cs/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── de/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── el/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── en/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── es/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── et/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── fi/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── fr/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ga/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── gl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── he/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── hi/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── hu/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── id/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── it/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ja/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ka/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ko/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ku/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── languages.json
│ │ ├── locales_generator.sh
│ │ ├── lt/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ne/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── nl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pl/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pt/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── pt_BR/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ro/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ru/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── sv/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ta/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── tr/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── uk/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── ur/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── uz/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ ├── zh-CN/
│ │ │ └── LC_MESSAGES/
│ │ │ ├── base.mo
│ │ │ └── base.po
│ │ └── zh-TW/
│ │ └── LC_MESSAGES/
│ │ ├── base.mo
│ │ └── base.po
│ ├── main.py
│ ├── scripts/
│ │ ├── __init__.py
│ │ ├── guided.py
│ │ ├── minimal.py
│ │ └── only_hd.py
│ └── tui/
│ ├── __init__.py
│ ├── curses_menu.py
│ ├── help.py
│ ├── menu_item.py
│ ├── result.py
│ ├── types.py
│ └── ui/
│ ├── __init__.py
│ ├── components.py
│ ├── menu_item.py
│ └── result.py
├── docs/
│ ├── Makefile
│ ├── README.md
│ ├── _static/
│ │ ├── logo.pride.psd
│ │ ├── logo.psd
│ │ └── style.css
│ ├── _templates/
│ │ └── layout.html
│ ├── archinstall/
│ │ ├── Installer.rst
│ │ └── plugins.rst
│ ├── cli_parameters/
│ │ └── config/
│ │ ├── config_options.csv
│ │ ├── custom_commands.rst
│ │ ├── disk_config.rst
│ │ ├── disk_encryption.rst
│ │ └── manual_options.csv
│ ├── conf.py
│ ├── examples/
│ │ └── python.rst
│ ├── flowcharts/
│ │ └── DiskSelectionProcess.drawio
│ ├── help/
│ │ ├── discord.rst
│ │ ├── known_issues.rst
│ │ └── report_bug.rst
│ ├── index.rst
│ ├── installing/
│ │ ├── guided.rst
│ │ └── python.rst
│ └── pull_request_template.md
├── examples/
│ ├── auto_discovery_mounted.py
│ ├── config-sample.json
│ ├── creds-sample.json
│ ├── custom-command-sample.json
│ ├── disk_layouts-sample.json
│ └── full_automated_installation.py
├── pyproject.toml
└── tests/
├── __init__.py
├── conftest.py
├── data/
│ ├── __init__.py
│ ├── mirrorlists/
│ │ ├── test_multiple_countries
│ │ ├── test_no_country
│ │ └── test_with_country
│ ├── test_config.json
│ ├── test_creds.json
│ ├── test_deprecated_audio_config.json
│ ├── test_deprecated_creds_config.json
│ ├── test_deprecated_mirror_config.json
│ └── test_encrypted_creds.json
├── test_args.py
├── test_configuration_output.py
├── test_mirrorlist.py
└── test_password_strength.py
SYMBOL INDEX (1638 symbols across 123 files)
FILE: archinstall/applications/audio.py
class AudioApp (line 14) | class AudioApp:
method pulseaudio_packages (line 16) | def pulseaudio_packages(self) -> list[str]:
method pipewire_packages (line 22) | def pipewire_packages(self) -> list[str]:
method _enable_pipewire (line 33) | def _enable_pipewire(
method install (line 59) | def install(
FILE: archinstall/applications/bluetooth.py
class BluetoothApp (line 11) | class BluetoothApp:
method packages (line 13) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
method install (line 25) | def install(self, install_session: Installer) -> None:
FILE: archinstall/applications/firewall.py
class FirewallApp (line 12) | class FirewallApp:
method ufw_packages (line 14) | def ufw_packages(self) -> list[str]:
method fwd_packages (line 20) | def fwd_packages(self) -> list[str]:
method ufw_services (line 26) | def ufw_services(self) -> list[str]:
method fwd_services (line 32) | def fwd_services(self) -> list[str]:
method install (line 37) | def install(
FILE: archinstall/applications/power_management.py
class PowerManagementApp (line 12) | class PowerManagementApp:
method ppd_packages (line 14) | def ppd_packages(self) -> list[str]:
method tuned_packages (line 20) | def tuned_packages(self) -> list[str]:
method install (line 26) | def install(
FILE: archinstall/applications/print_service.py
class PrintServiceApp (line 11) | class PrintServiceApp:
method packages (line 13) | def packages(self) -> list[str]:
method services (line 17) | def services(self) -> list[str]:
method install (line 22) | def install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/desktop.py
class DesktopProfile (line 16) | class DesktopProfile(Profile):
method __init__ (line 17) | def __init__(self, current_selection: list[Self] = []) -> None:
method packages (line 27) | def packages(self) -> list[str]:
method default_greeter_type (line 40) | def default_greeter_type(self) -> GreeterType | None:
method _do_on_select_profiles (line 52) | async def _do_on_select_profiles(self) -> None:
method do_on_select (line 57) | async def do_on_select(self) -> SelectResult:
method post_install (line 89) | def post_install(self, install_session: Installer) -> None:
method install (line 94) | def install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/desktops/__init__.py
class SeatAccess (line 4) | class SeatAccess(Enum):
FILE: archinstall/default_profiles/desktops/awesome.py
class AwesomeProfile (line 12) | class AwesomeProfile(XorgProfile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 18) | def packages(self) -> list[str]:
method install (line 34) | def install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/desktops/bspwm.py
class BspwmProfile (line 7) | class BspwmProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 25) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/budgie.py
class BudgieProfile (line 7) | class BudgieProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 24) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/cinnamon.py
class CinnamonProfile (line 7) | class CinnamonProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 28) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/cosmic.py
class CosmicProfile (line 7) | class CosmicProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/cutefish.py
class CutefishProfile (line 7) | class CutefishProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/deepin.py
class DeepinProfile (line 7) | class DeepinProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 22) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/enlightenment.py
class EnlightenmentProfile (line 7) | class EnlightenmentProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/gnome.py
class GnomeProfile (line 7) | class GnomeProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/hyprland.py
class HyprlandProfile (line 12) | class HyprlandProfile(XorgProfile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 20) | def packages(self) -> list[str]:
method default_greeter_type (line 38) | def default_greeter_type(self) -> GreeterType:
method services (line 43) | def services(self) -> list[str]:
method _select_seat_access (line 48) | async def _select_seat_access(self) -> None:
method do_on_select (line 69) | async def do_on_select(self) -> None:
FILE: archinstall/default_profiles/desktops/i3.py
class I3wmProfile (line 7) | class I3wmProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 28) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/labwc.py
class LabwcProfile (line 12) | class LabwcProfile(XorgProfile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 23) | def packages(self) -> list[str]:
method default_greeter_type (line 35) | def default_greeter_type(self) -> GreeterType:
method services (line 40) | def services(self) -> list[str]:
method _select_seat_access (line 45) | async def _select_seat_access(self) -> None:
method do_on_select (line 66) | async def do_on_select(self) -> None:
FILE: archinstall/default_profiles/desktops/lxqt.py
class LxqtProfile (line 7) | class LxqtProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 16) | def packages(self) -> list[str]:
method default_greeter_type (line 29) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/mate.py
class MateProfile (line 7) | class MateProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/niri.py
class NiriProfile (line 12) | class NiriProfile(XorgProfile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 23) | def packages(self) -> list[str]:
method default_greeter_type (line 43) | def default_greeter_type(self) -> GreeterType:
method services (line 48) | def services(self) -> list[str]:
method _select_seat_access (line 53) | async def _select_seat_access(self) -> None:
method do_on_select (line 74) | async def do_on_select(self) -> None:
FILE: archinstall/default_profiles/desktops/plasma.py
class PlasmaProfile (line 7) | class PlasmaProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 25) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/qtile.py
class QtileProfile (line 7) | class QtileProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 21) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/river.py
class RiverProfile (line 7) | class RiverProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 22) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/sway.py
class SwayProfile (line 12) | class SwayProfile(XorgProfile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 23) | def packages(self) -> list[str]:
method default_greeter_type (line 45) | def default_greeter_type(self) -> GreeterType:
method services (line 50) | def services(self) -> list[str]:
method _select_seat_access (line 55) | async def _select_seat_access(self) -> None:
method do_on_select (line 76) | async def do_on_select(self) -> None:
FILE: archinstall/default_profiles/desktops/xfce4.py
class Xfce4Profile (line 7) | class Xfce4Profile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 24) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/desktops/xmonad.py
class XmonadProfile (line 7) | class XmonadProfile(XorgProfile):
method __init__ (line 8) | def __init__(self) -> None:
method packages (line 13) | def packages(self) -> list[str]:
method default_greeter_type (line 24) | def default_greeter_type(self) -> GreeterType:
FILE: archinstall/default_profiles/minimal.py
class MinimalProfile (line 4) | class MinimalProfile(Profile):
method __init__ (line 5) | def __init__(self) -> None:
FILE: archinstall/default_profiles/profile.py
class ProfileType (line 13) | class ProfileType(Enum):
class GreeterType (line 29) | class GreeterType(Enum):
class SelectResult (line 39) | class SelectResult(Enum):
class Profile (line 45) | class Profile:
method __init__ (line 46) | def __init__(
method packages (line 73) | def packages(self) -> list[str]:
method services (line 81) | def services(self) -> list[str]:
method default_greeter_type (line 89) | def default_greeter_type(self) -> GreeterType | None:
method install (line 95) | def install(self, install_session: Installer) -> None:
method post_install (line 100) | def post_install(self, install_session: Installer) -> None:
method provision (line 107) | def provision(self, install_session: Installer, users: list[User]) -> ...
method json (line 114) | def json(self) -> dict[str, str]:
method do_on_select (line 120) | async def do_on_select(self) -> SelectResult | None:
method set_custom_settings (line 126) | def set_custom_settings(self, settings: dict[str, str | None]) -> None:
method current_selection_names (line 134) | def current_selection_names(self) -> list[str]:
method reset (line 139) | def reset(self) -> None:
method is_top_level_profile (line 142) | def is_top_level_profile(self) -> bool:
method is_desktop_profile (line 146) | def is_desktop_profile(self) -> bool:
method is_server_type_profile (line 149) | def is_server_type_profile(self) -> bool:
method is_desktop_type_profile (line 152) | def is_desktop_type_profile(self) -> bool:
method is_xorg_type_profile (line 155) | def is_xorg_type_profile(self) -> bool:
method is_custom_type_profile (line 158) | def is_custom_type_profile(self) -> bool:
method is_graphic_driver_supported (line 161) | def is_graphic_driver_supported(self) -> bool:
method is_greeter_supported (line 169) | def is_greeter_supported(self) -> bool:
method preview_text (line 172) | def preview_text(self) -> str:
method packages_text (line 178) | def packages_text(self, include_sub_packages: bool = False) -> str:
FILE: archinstall/default_profiles/server.py
class ServerProfile (line 17) | class ServerProfile(Profile):
method __init__ (line 18) | def __init__(self, current_value: list[Self] = []):
method do_on_select (line 26) | async def do_on_select(self) -> SelectResult:
method provision (line 58) | def provision(self, install_session: Installer, users: list[User]) -> ...
method post_install (line 63) | def post_install(self, install_session: Installer) -> None:
method install (line 68) | def install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/servers/cockpit.py
class CockpitProfile (line 6) | class CockpitProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/servers/docker.py
class DockerProfile (line 12) | class DockerProfile(Profile):
method __init__ (line 13) | def __init__(self) -> None:
method packages (line 21) | def packages(self) -> list[str]:
method services (line 26) | def services(self) -> list[str]:
method provision (line 30) | def provision(self, install_session: Installer, users: list[User]) -> ...
FILE: archinstall/default_profiles/servers/httpd.py
class HttpdProfile (line 6) | class HttpdProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/servers/lighttpd.py
class LighttpdProfile (line 6) | class LighttpdProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/servers/mariadb.py
class MariadbProfile (line 11) | class MariadbProfile(Profile):
method __init__ (line 12) | def __init__(self) -> None:
method packages (line 20) | def packages(self) -> list[str]:
method services (line 25) | def services(self) -> list[str]:
method post_install (line 29) | def post_install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/servers/nginx.py
class NginxProfile (line 6) | class NginxProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/servers/postgresql.py
class PostgresqlProfile (line 11) | class PostgresqlProfile(Profile):
method __init__ (line 12) | def __init__(self) -> None:
method packages (line 20) | def packages(self) -> list[str]:
method services (line 25) | def services(self) -> list[str]:
method post_install (line 29) | def post_install(self, install_session: Installer) -> None:
FILE: archinstall/default_profiles/servers/sshd.py
class SshdProfile (line 6) | class SshdProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/servers/tomcat.py
class TomcatProfile (line 6) | class TomcatProfile(Profile):
method __init__ (line 7) | def __init__(self) -> None:
method packages (line 15) | def packages(self) -> list[str]:
method services (line 20) | def services(self) -> list[str]:
FILE: archinstall/default_profiles/xorg.py
class XorgProfile (line 7) | class XorgProfile(Profile):
method __init__ (line 8) | def __init__(
method preview_text (line 20) | def preview_text(self) -> str:
method packages (line 29) | def packages(self) -> list[str]:
FILE: archinstall/lib/applications/application_handler.py
class ApplicationHandler (line 18) | class ApplicationHandler:
method __init__ (line 19) | def __init__(self) -> None:
method install_applications (line 22) | def install_applications(self, install_session: Installer, app_config:...
FILE: archinstall/lib/applications/application_menu.py
class ApplicationMenu (line 22) | class ApplicationMenu(AbstractSubMenu[ApplicationConfiguration]):
method __init__ (line 23) | def __init__(
method show (line 42) | async def show(self) -> ApplicationConfiguration | None:
method _define_menu_options (line 46) | def _define_menu_options(self) -> list[MenuItem]:
method _prev_power_management (line 82) | def _prev_power_management(self, item: MenuItem) -> str | None:
method _prev_bluetooth (line 88) | def _prev_bluetooth(self, item: MenuItem) -> str | None:
method _prev_audio (line 97) | def _prev_audio(self, item: MenuItem) -> str | None:
method _prev_print_service (line 103) | def _prev_print_service(self, item: MenuItem) -> str | None:
method _prev_firewall (line 112) | def _prev_firewall(self, item: MenuItem) -> str | None:
function select_power_management (line 119) | async def select_power_management(preset: PowerManagementConfiguration |...
function select_bluetooth (line 140) | async def select_bluetooth(preset: BluetoothConfiguration | None) -> Blu...
function select_print_service (line 159) | async def select_print_service(preset: PrintServiceConfiguration | None)...
function select_audio (line 179) | async def select_audio(preset: AudioConfiguration | None = None) -> Audi...
function select_firewall (line 201) | async def select_firewall(preset: FirewallConfiguration | None = None) -...
FILE: archinstall/lib/args.py
class Arguments (line 35) | class Arguments:
class ArchConfig (line 59) | class ArchConfig:
method unsafe_config (line 81) | def unsafe_config(self) -> dict[str, Any]:
method safe_config (line 98) | def safe_config(self) -> dict[str, Any]:
method from_config (line 135) | def from_config(cls, args_config: dict[str, Any], args: Arguments) -> ...
class ArchConfigHandler (line 257) | class ArchConfigHandler:
method __init__ (line 258) | def __init__(self) -> None:
method config (line 273) | def config(self) -> ArchConfig:
method args (line 277) | def args(self) -> Arguments:
method get_script (line 280) | def get_script(self) -> str:
method print_help (line 289) | def print_help(self) -> None:
method _define_arguments (line 292) | def _define_arguments(self) -> ArgumentParser:
method _parse_args (line 432) | def _parse_args(self) -> Arguments:
method _parse_config (line 454) | def _parse_config(self) -> dict[str, Any]:
method _process_creds_data (line 481) | def _process_creds_data(self, creds_data: str) -> dict[str, Any] | None:
method _fetch_from_url (line 524) | def _fetch_from_url(self, url: str) -> str:
method _read_file (line 537) | def _read_file(self, path: Path) -> str:
method _cleanup_config (line 544) | def _cleanup_config(self, config: Namespace | dict[str, Any]) -> dict[...
FILE: archinstall/lib/authentication/authentication_handler.py
class AuthenticationHandler (line 17) | class AuthenticationHandler:
method setup_auth (line 18) | def setup_auth(
method _setup_u2f_login (line 27) | def _setup_u2f_login(self, install_session: Installer, u2f_config: U2F...
method _update_pam_config (line 31) | def _update_pam_config(
method _add_u2f_entry (line 55) | def _add_u2f_entry(self, file: Path, entry: str) -> None:
method _configure_u2f_mapping (line 75) | def _configure_u2f_mapping(
FILE: archinstall/lib/authentication/authentication_menu.py
class AuthenticationMenu (line 16) | class AuthenticationMenu(AbstractSubMenu[AuthenticationConfiguration]):
method __init__ (line 17) | def __init__(self, preset: AuthenticationConfiguration | None = None):
method show (line 33) | async def show(self) -> AuthenticationConfiguration | None:
method _define_menu_options (line 36) | def _define_menu_options(self) -> list[MenuItem]:
method _create_user_account (line 59) | async def _create_user_account(self, preset: list[User] | None = None)...
method _prev_users (line 64) | def _prev_users(self, item: MenuItem) -> str | None:
method _prev_root_pwd (line 71) | def _prev_root_pwd(self, item: MenuItem) -> str | None:
method _depends_on_u2f (line 77) | def _depends_on_u2f(self) -> bool:
method _prev_u2f_login (line 83) | def _prev_u2f_login(self, item: MenuItem) -> str | None:
function select_root_password (line 102) | async def select_root_password() -> Password | None:
function select_u2f_login (line 107) | async def select_u2f_login(preset: U2FLoginConfiguration | None) -> U2FL...
FILE: archinstall/lib/boot.py
class Boot (line 12) | class Boot:
method __init__ (line 15) | def __init__(self, path: Path | str):
method __enter__ (line 24) | def __enter__(self) -> Self:
method __exit__ (line 56) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method __iter__ (line 91) | def __iter__(self) -> Iterator[bytes]:
method __contains__ (line 95) | def __contains__(self, key: bytes) -> bool:
method is_alive (line 101) | def is_alive(self) -> bool:
method SysCommand (line 107) | def SysCommand(self, cmd: list[str], *args, **kwargs) -> SysCommand: ...
method SysCommandWorker (line 117) | def SysCommandWorker(self, cmd: list[str], *args, **kwargs) -> SysComm...
FILE: archinstall/lib/bootloader/bootloader_menu.py
class BootloaderMenu (line 12) | class BootloaderMenu(AbstractSubMenu[BootloaderConfiguration]):
method __init__ (line 13) | def __init__(
method _define_menu_options (line 31) | def _define_menu_options(self) -> list[MenuItem]:
method _prev_bootloader (line 71) | def _prev_bootloader(self, item: MenuItem) -> str | None:
method _prev_uki (line 76) | def _prev_uki(self, item: MenuItem) -> str | None:
method _prev_removable (line 83) | def _prev_removable(self, item: MenuItem) -> str | None:
method show (line 89) | async def show(self) -> BootloaderConfiguration:
method _select_bootloader (line 93) | async def _select_bootloader(self, preset: Bootloader | None) -> Bootl...
method _select_uki (line 120) | async def _select_uki(self, preset: bool) -> bool:
method _select_removable (line 133) | async def _select_removable(self, preset: bool) -> bool:
function select_bootloader (line 180) | async def select_bootloader(
FILE: archinstall/lib/command.py
class SysCommandWorker (line 18) | class SysCommandWorker:
method __init__ (line 19) | def __init__(
method __contains__ (line 51) | def __contains__(self, key: bytes) -> bool:
method __iter__ (line 65) | def __iter__(self, *args: str, **kwargs: dict[str, Any]) -> Iterator[b...
method __repr__ (line 77) | def __repr__(self) -> str:
method __str__ (line 82) | def __str__(self) -> str:
method __enter__ (line 88) | def __enter__(self) -> Self:
method __exit__ (line 91) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method is_alive (line 117) | def is_alive(self) -> bool:
method write (line 125) | def write(self, data: bytes, line_ending: bool = True) -> int:
method make_sure_we_are_executing (line 135) | def make_sure_we_are_executing(self) -> bool:
method tell (line 140) | def tell(self) -> int:
method seek (line 144) | def seek(self, pos: int) -> None:
method peak (line 149) | def peak(self, output: str | bytes) -> bool:
method poll (line 164) | def poll(self) -> None:
method execute (line 191) | def execute(self) -> bool:
method decode (line 223) | def decode(self, encoding: str = 'UTF-8') -> str:
class SysCommand (line 227) | class SysCommand:
method __init__ (line 228) | def __init__(
method __enter__ (line 245) | def __enter__(self) -> SysCommandWorker | None:
method __exit__ (line 248) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method __iter__ (line 255) | def __iter__(self, *args: list[Any], **kwargs: dict[str, Any]) -> Iter...
method __getitem__ (line 259) | def __getitem__(self, key: slice) -> bytes:
method __repr__ (line 271) | def __repr__(self, *args: list[Any], **kwargs: dict[str, Any]) -> str:
method create_session (line 274) | def create_session(self) -> bool:
method decode (line 301) | def decode(self, encoding: str = 'utf-8', errors: str = 'backslashrepl...
method output (line 311) | def output(self, remove_cr: bool = True) -> bytes:
method exit_code (line 321) | def exit_code(self) -> int | None:
method trace_log (line 328) | def trace_log(self) -> bytes | None:
function run (line 334) | def run(
function locate_binary (line 349) | def locate_binary(name: str) -> str:
function _pid_exists (line 355) | def _pid_exists(pid: int) -> bool:
function _cmd_history (line 362) | def _cmd_history(cmd: list[str]) -> None:
function _cmd_output (line 367) | def _cmd_output(output: str) -> None:
function _append_log (line 371) | def _append_log(file: str, content: str) -> None:
FILE: archinstall/lib/configuration.py
class ConfigurationOutput (line 19) | class ConfigurationOutput:
method __init__ (line 20) | def __init__(self, config: ArchConfig):
method user_configuration_file (line 36) | def user_configuration_file(self) -> Path:
method user_credentials_file (line 40) | def user_credentials_file(self) -> Path:
method user_config_to_json (line 43) | def user_config_to_json(self) -> str:
method user_credentials_to_json (line 50) | def user_credentials_to_json(self) -> str:
method write_debug (line 57) | def write_debug(self) -> None:
method confirm_config (line 61) | async def confirm_config(self) -> bool:
method _is_valid_path (line 82) | def _is_valid_path(self, dest_path: Path) -> bool:
method save_user_config (line 91) | def save_user_config(self, dest_path: Path) -> None:
method save_user_creds (line 97) | def save_user_creds(
method save (line 112) | def save(
function save_config (line 126) | async def save_config(config: ArchConfig) -> None:
FILE: archinstall/lib/crypt.py
function _search_login_defs (line 22) | def _search_login_defs(key: str) -> str | None:
function crypt_gen_salt (line 37) | def crypt_gen_salt(prefix: str | bytes, rounds: int) -> bytes:
function crypt_yescrypt (line 49) | def crypt_yescrypt(plaintext: str) -> str:
function _get_fernet (line 79) | def _get_fernet(salt: bytes, password: str) -> Fernet:
function encrypt (line 100) | def encrypt(password: str, data: str) -> str:
function decrypt (line 111) | def decrypt(data: str, password: str) -> str:
FILE: archinstall/lib/disk/device_handler.py
class DeviceHandler (line 42) | class DeviceHandler:
method __init__ (line 45) | def __init__(self) -> None:
method devices (line 51) | def devices(self) -> list[BDevice]:
method partition_table (line 55) | def partition_table(self) -> PartitionTable:
method load_devices (line 58) | def load_devices(self) -> None:
method get_loop_devices (line 122) | def get_loop_devices() -> list[Device]:
method _determine_fs_type (line 145) | def _determine_fs_type(
method get_device (line 163) | def get_device(self, path: Path) -> BDevice | None:
method get_device_by_partition_path (line 166) | def get_device_by_partition_path(self, partition_path: Path) -> BDevic...
method find_partition (line 173) | def find_partition(self, path: Path) -> _PartitionInfo | None:
method get_uuid_for_path (line 180) | def get_uuid_for_path(self, path: Path) -> str | None:
method get_btrfs_info (line 184) | def get_btrfs_info(
method format (line 235) | def format(
method encrypt (line 278) | def encrypt(
method format_encrypted (line 307) | def format_encrypted(
method _setup_partition (line 338) | def _setup_partition(
method fetch_part_info (line 406) | def fetch_part_info(self, path: Path) -> LsblkInfo:
method create_lvm_btrfs_subvolumes (line 425) | def create_lvm_btrfs_subvolumes(
method create_btrfs_volumes (line 456) | def create_btrfs_volumes(
method umount_all_existing (line 501) | def umount_all_existing(self, device_path: Path) -> None:
method partition (line 515) | def partition(
method detect_pre_mounted_mods (line 560) | def detect_pre_mounted_mods(self, base_mountpoint: Path) -> list[Devic...
method partprobe (line 586) | def partprobe(self, path: Path | None = None) -> None:
method _wipe (line 601) | def _wipe(self, dev_path: Path) -> None:
method wipe_dev (line 610) | def wipe_dev(self, block_device: BDevice) -> None:
FILE: archinstall/lib/disk/disk_menu.py
class DiskMenuConfig (line 26) | class DiskMenuConfig:
class DiskLayoutConfigurationMenu (line 33) | class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskMenuConfig]):
method __init__ (line 34) | def __init__(self, disk_layout_config: DiskLayoutConfiguration | None):
method _define_menu_options (line 61) | def _define_menu_options(self) -> list[MenuItem]:
method show (line 96) | async def show(self) -> DiskLayoutConfiguration | None: # type: ignor...
method _check_dep_lvm (line 109) | def _check_dep_lvm(self) -> bool:
method _check_dep_btrfs (line 117) | def _check_dep_btrfs(self) -> bool:
method _select_disk_encryption (line 125) | async def _select_disk_encryption(self, preset: DiskEncryption | None)...
method _select_disk_layout_config (line 141) | async def _select_disk_layout_config(self, preset: DiskLayoutConfigura...
method _select_lvm_config (line 150) | async def _select_lvm_config(self, preset: LvmConfiguration | None) ->...
method _select_btrfs_snapshots (line 163) | async def _select_btrfs_snapshots(self, preset: SnapshotConfig | None)...
method _prev_disk_layouts (line 186) | def _prev_disk_layouts(self, item: MenuItem) -> str | None:
method _prev_lvm_config (line 221) | def _prev_lvm_config(self, item: MenuItem) -> str | None:
method _prev_btrfs_snapshots (line 242) | def _prev_btrfs_snapshots(self, item: MenuItem) -> str | None:
method _prev_disk_encryption (line 249) | def _prev_disk_encryption(self, item: MenuItem) -> str | None:
FILE: archinstall/lib/disk/encryption_menu.py
class DiskEncryptionMenu (line 26) | class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
method __init__ (line 27) | def __init__(
method _define_menu_options (line 50) | def _define_menu_options(self) -> list[MenuItem]:
method _select_lvm_vols (line 101) | async def _select_lvm_vols(self, preset: list[LvmVolume]) -> list[LvmV...
method _check_dep_enc_type (line 106) | def _check_dep_enc_type(self) -> bool:
method _check_dep_partitions (line 112) | def _check_dep_partitions(self) -> bool:
method _check_dep_lvm_vols (line 118) | def _check_dep_lvm_vols(self) -> bool:
method show (line 125) | async def show(self) -> DiskEncryption | None:
method _preview (line 158) | def _preview(self, item: MenuItem) -> str | None:
method _prev_type (line 184) | def _prev_type(self, item: MenuItem) -> str | None:
method _prev_password (line 193) | def _prev_password(self, item: MenuItem) -> str | None:
method _prev_partitions (line 199) | def _prev_partitions(self, item: MenuItem) -> str | None:
method _prev_lvm_vols (line 207) | def _prev_lvm_vols(self, item: MenuItem) -> str | None:
method _prev_hsm (line 215) | def _prev_hsm(self, item: MenuItem) -> str | None:
method _prev_iter_time (line 225) | def _prev_iter_time(self, item: MenuItem) -> str | None:
function select_encryption_type (line 236) | async def select_encryption_type(
function select_encrypted_password (line 272) | async def select_encrypted_password() -> Password | None:
function select_hsm (line 282) | async def select_hsm(preset: Fido2Device | None = None) -> Fido2Device |...
function select_partitions_to_encrypt (line 310) | async def select_partitions_to_encrypt(
function select_lvm_vols_to_encrypt (line 346) | async def select_lvm_vols_to_encrypt(
function select_iteration_time (line 375) | async def select_iteration_time(preset: int | None = None) -> int | None:
FILE: archinstall/lib/disk/fido.py
class Fido2 (line 13) | class Fido2:
method get_fido2_devices (line 20) | def get_fido2_devices(cls) -> list[Fido2Device]:
method get_cryptenroll_devices (line 49) | def get_cryptenroll_devices(cls, reload: bool = False) -> list[Fido2De...
method fido2_enroll (line 103) | def fido2_enroll(hsm_device: Fido2Device, dev_path: Path, password: Pa...
FILE: archinstall/lib/disk/filesystem.py
class FilesystemHandler (line 33) | class FilesystemHandler:
method __init__ (line 34) | def __init__(self, disk_config: DiskLayoutConfiguration):
method perform_filesystem_operations (line 38) | def perform_filesystem_operations(self) -> None:
method _format_partitions (line 76) | def _format_partitions(
method _validate_partitions (line 111) | def _validate_partitions(self, partitions: list[PartitionModification]...
method perform_lvm_operations (line 126) | def perform_lvm_operations(self) -> None:
method _setup_lvm_encrypted (line 141) | def _setup_lvm_encrypted(self, lvm_config: LvmConfiguration, enc_confi...
method _setup_lvm (line 161) | def _setup_lvm(
method _format_lvm_vols (line 216) | def _format_lvm_vols(
method _lvm_create_pvs (line 236) | def _lvm_create_pvs(
method _get_all_pv_dev_paths (line 248) | def _get_all_pv_dev_paths(
method _encrypt_lvm_vols (line 264) | def _encrypt_lvm_vols(
method _encrypt_partitions (line 286) | def _encrypt_partitions(
method _lvm_vol_handle_e2scrub (line 317) | def _lvm_vol_handle_e2scrub(self, vol_gp: LvmVolumeGroup) -> None:
FILE: archinstall/lib/disk/lvm.py
function _lvm_info (line 23) | def _lvm_info(
function _lvm_info_with_retry (line 66) | def _lvm_info_with_retry(cmd: str, info_type: Literal['lv']) -> LvmVolum...
function _lvm_info_with_retry (line 70) | def _lvm_info_with_retry(cmd: str, info_type: Literal['vg']) -> LvmGroup...
function _lvm_info_with_retry (line 74) | def _lvm_info_with_retry(cmd: str, info_type: Literal['pvseg']) -> LvmPV...
function _lvm_info_with_retry (line 77) | def _lvm_info_with_retry(
function lvm_vol_info (line 95) | def lvm_vol_info(lv_name: str) -> LvmVolumeInfo | None:
function lvm_group_info (line 101) | def lvm_group_info(vg_name: str) -> LvmGroupInfo | None:
function lvm_pvseg_info (line 107) | def lvm_pvseg_info(vg_name: str, lv_name: str) -> LvmPVInfo | None:
function lvm_vol_change (line 113) | def lvm_vol_change(vol: LvmVolume, activate: bool) -> None:
function lvm_export_vg (line 121) | def lvm_export_vg(vg: LvmVolumeGroup) -> None:
function lvm_import_vg (line 128) | def lvm_import_vg(vg: LvmVolumeGroup) -> None:
function lvm_vol_reduce (line 149) | def lvm_vol_reduce(vol_path: Path, amount: Size) -> None:
function lvm_pv_create (line 157) | def lvm_pv_create(pvs: Iterable[Path]) -> None:
function lvm_vg_create (line 169) | def lvm_vg_create(pvs: Iterable[Path], vg_name: str) -> None:
function lvm_vol_create (line 180) | def lvm_vol_create(vg_name: str, volume: LvmVolume, offset: Size | None ...
FILE: archinstall/lib/disk/partitioning_menu.py
class FreeSpace (line 28) | class FreeSpace:
method __init__ (line 29) | def __init__(self, start: Size, end: Size) -> None:
method length (line 34) | def length(self) -> Size:
method table_data (line 37) | def table_data(self) -> dict[str, str]:
class DiskSegment (line 48) | class DiskSegment:
method __init__ (line 49) | def __init__(self, segment: PartitionModification | FreeSpace) -> None:
method table_data (line 52) | def table_data(self) -> dict[str, str]:
class PartitioningList (line 70) | class PartitioningList(ListManager[DiskSegment]):
method __init__ (line 71) | def __init__(
method wipe_str (line 130) | def wipe_str(self) -> str:
method as_segments (line 133) | def as_segments(self, device_partitions: list[PartitionModification]) ...
method get_part_mods (line 189) | def get_part_mods(disk_segments: list[DiskSegment]) -> list[PartitionM...
method show (line 192) | async def show(self) -> DeviceModification | None:
method _run_actions_on_entry (line 202) | async def _run_actions_on_entry(self, entry: DiskSegment) -> None:
method selected_action_display (line 210) | def selected_action_display(self, selection: DiskSegment) -> str:
method filter_options (line 227) | def filter_options(self, selection: DiskSegment, options: list[str]) -...
method handle_action (line 270) | async def handle_action(
method _delete_partition (line 354) | def _delete_partition(
method _toggle_mount_option (line 367) | def _toggle_mount_option(
method _set_btrfs_subvolumes (line 382) | async def _set_btrfs_subvolumes(self, partition: PartitionModification...
method _prompt_formatting (line 391) | async def _prompt_formatting(self, partition: PartitionModification) -...
method _prompt_mountpoint (line 410) | async def _prompt_mountpoint(self) -> Path:
method _prompt_partition_fs_type (line 419) | async def _prompt_partition_fs_type(self, prompt: str | None = None) -...
method _validate_value (line 436) | def _validate_value(
method _prompt_size (line 468) | async def _prompt_size(self, free_space: FreeSpace) -> Size:
method _create_new_partition (line 519) | async def _create_new_partition(self, free_space: FreeSpace) -> Partit...
method _reset_confirmation (line 548) | async def _reset_confirmation(self) -> bool:
method _suggest_partition_layout (line 559) | async def _suggest_partition_layout(
function manual_partitioning (line 574) | async def manual_partitioning(
FILE: archinstall/lib/disk/subvolume_menu.py
class SubvolumeMenu (line 12) | class SubvolumeMenu(ListManager[SubvolumeModification]):
method __init__ (line 13) | def __init__(
method show (line 31) | async def show(self) -> list[SubvolumeModification] | None:
method selected_action_display (line 35) | def selected_action_display(self, selection: SubvolumeModification) ->...
method _add_subvolume (line 38) | async def _add_subvolume(self, preset: SubvolumeModification | None = ...
method handle_action (line 77) | async def handle_action(
FILE: archinstall/lib/disk/utils.py
class LsblkOutput (line 11) | class LsblkOutput(BaseModel):
function _fetch_lsblk_info (line 15) | def _fetch_lsblk_info(
function get_lsblk_info (line 47) | def get_lsblk_info(
function get_all_lsblk_info (line 60) | def get_all_lsblk_info() -> list[LsblkInfo]:
function get_lsblk_output (line 64) | def get_lsblk_output() -> LsblkOutput:
function find_lsblk_info (line 68) | def find_lsblk_info(
function get_lsblk_by_mountpoint (line 82) | def get_lsblk_by_mountpoint(mountpoint: Path, as_prefix: bool = False) -...
function disk_layouts (line 103) | def disk_layouts() -> str:
function get_parent_device_path (line 113) | def get_parent_device_path(dev_path: Path) -> Path:
function get_unique_path_for_device (line 118) | def get_unique_path_for_device(dev_path: Path) -> Path | None:
function udev_sync (line 132) | def udev_sync() -> None:
function mount (line 139) | def mount(
function umount (line 176) | def umount(mountpoint: Path, recursive: bool = False) -> None:
function swapon (line 194) | def swapon(path: Path) -> None:
FILE: archinstall/lib/exceptions.py
class RequirementError (line 1) | class RequirementError(Exception):
class DiskError (line 5) | class DiskError(Exception):
class UnknownFilesystemFormat (line 9) | class UnknownFilesystemFormat(Exception):
class SysCallError (line 13) | class SysCallError(Exception):
method __init__ (line 14) | def __init__(self, message: str, exit_code: int | None = None, worker_...
class HardwareIncompatibilityError (line 21) | class HardwareIncompatibilityError(Exception):
class ServiceException (line 25) | class ServiceException(Exception):
class PackageError (line 29) | class PackageError(Exception):
class Deprecated (line 33) | class Deprecated(Exception):
class DownloadTimeout (line 37) | class DownloadTimeout(Exception):
FILE: archinstall/lib/global_menu.py
class GlobalMenu (line 33) | class GlobalMenu(AbstractMenu[None]):
method __init__ (line 34) | def __init__(
method _get_menu_options (line 55) | def _get_menu_options(self) -> list[MenuItem]:
method _safe_config (line 188) | async def _safe_config(self) -> None:
method _missing_configs (line 197) | def _missing_configs(self) -> list[str]:
method is_config_valid (line 226) | def is_config_valid(self) -> bool:
method _select_archinstall_language (line 234) | async def _select_archinstall_language(self, preset: Language) -> Lang...
method _prev_archinstall_language (line 244) | def _prev_archinstall_language(self, item: MenuItem) -> str | None:
method _select_applications (line 251) | async def _select_applications(self, preset: ApplicationConfiguration ...
method _select_authentication (line 255) | async def _select_authentication(self, preset: AuthenticationConfigura...
method _update_lang_text (line 259) | def _update_lang_text(self) -> None:
method _locale_selection (line 270) | async def _locale_selection(self, preset: LocaleConfiguration) -> Loca...
method _prev_locale (line 274) | def _prev_locale(self, item: MenuItem) -> str | None:
method _prev_network_config (line 281) | def _prev_network_config(self, item: MenuItem) -> str | None:
method _prev_additional_pkgs (line 292) | def _prev_additional_pkgs(self, item: MenuItem) -> str | None:
method _prev_authentication (line 298) | def _prev_authentication(self, item: MenuItem) -> str | None:
method _prev_applications (line 321) | def _prev_applications(self, item: MenuItem) -> str | None:
method _prev_tz (line 355) | def _prev_tz(self, item: MenuItem) -> str | None:
method _prev_ntp (line 360) | def _prev_ntp(self, item: MenuItem) -> str | None:
method _prev_disk_config (line 367) | def _prev_disk_config(self, item: MenuItem) -> str | None:
method _prev_swap (line 391) | def _prev_swap(self, item: MenuItem) -> str | None:
method _prev_hostname (line 400) | def _prev_hostname(self, item: MenuItem) -> str | None:
method _prev_parallel_dw (line 405) | def _prev_parallel_dw(self, item: MenuItem) -> str | None:
method _prev_kernel (line 410) | def _prev_kernel(self, item: MenuItem) -> str | None:
method _prev_bootloader_config (line 416) | def _prev_bootloader_config(self, item: MenuItem) -> str | None:
method _validate_bootloader (line 422) | def _validate_bootloader(self) -> str | None:
method _prev_install_invalid_config (line 479) | def _prev_install_invalid_config(self, item: MenuItem) -> str | None:
method _prev_profile (line 491) | def _prev_profile(self, item: MenuItem) -> str | None:
method _select_disk_config (line 511) | async def _select_disk_config(
method _select_bootloader_config (line 518) | async def _select_bootloader_config(
method _select_profile (line 529) | async def _select_profile(self, current_profile: ProfileConfiguration ...
method _select_additional_packages (line 535) | async def _select_additional_packages(self, preset: list[str]) -> list...
method _mirror_configuration (line 549) | async def _mirror_configuration(self, preset: MirrorConfiguration | No...
method _prev_mirror_config (line 566) | def _prev_mirror_config(self, item: MenuItem) -> str | None:
FILE: archinstall/lib/hardware.py
class CpuVendor (line 14) | class CpuVendor(Enum):
method get_vendor (line 20) | def get_vendor(cls, name: str) -> Self:
method _has_microcode (line 27) | def _has_microcode(self) -> bool:
method get_ucode (line 34) | def get_ucode(self) -> Path | None:
class GfxPackage (line 40) | class GfxPackage(Enum):
class GfxDriver (line 59) | class GfxDriver(Enum):
method is_nvidia (line 68) | def is_nvidia(self) -> bool:
method packages_text (line 75) | def packages_text(self) -> str:
method gfx_packages (line 84) | def gfx_packages(self) -> list[GfxPackage]:
class _SysInfo (line 143) | class _SysInfo:
method __init__ (line 144) | def __init__(self) -> None:
method has_battery (line 148) | def has_battery(self) -> bool:
method cpu_info (line 160) | def cpu_info(self) -> dict[str, str]:
method mem_info (line 176) | def mem_info(self) -> dict[str, int]:
method mem_info_by_key (line 191) | def mem_info_by_key(self, key: str) -> int:
method loaded_modules (line 195) | def loaded_modules(self) -> list[str]:
method graphics_devices (line 210) | def graphics_devices(self) -> dict[str, str]:
class SysInfo (line 225) | class SysInfo:
method has_battery (line 227) | def has_battery() -> bool:
method has_wifi (line 231) | def has_wifi() -> bool:
method has_uefi (line 236) | def has_uefi() -> bool:
method _graphics_devices (line 240) | def _graphics_devices() -> dict[str, str]:
method has_nvidia_graphics (line 244) | def has_nvidia_graphics() -> bool:
method has_amd_graphics (line 248) | def has_amd_graphics() -> bool:
method has_intel_graphics (line 252) | def has_intel_graphics() -> bool:
method cpu_vendor (line 256) | def cpu_vendor() -> CpuVendor | None:
method cpu_model (line 262) | def cpu_model() -> str | None:
method sys_vendor (line 266) | def sys_vendor() -> str | None:
method product_name (line 274) | def product_name() -> str | None:
method mem_available (line 282) | def mem_available() -> int:
method mem_free (line 286) | def mem_free() -> int:
method mem_total (line 290) | def mem_total() -> int:
method virtualization (line 294) | def virtualization() -> str | None:
method is_vm (line 303) | def is_vm() -> bool:
method requires_sof_fw (line 313) | def requires_sof_fw() -> bool:
method requires_alsa_fw (line 317) | def requires_alsa_fw() -> bool:
FILE: archinstall/lib/installer.py
class Installer (line 68) | class Installer:
method __init__ (line 69) | def __init__(
method __enter__ (line 130) | def __enter__(self) -> Self:
method __exit__ (line 133) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method remove_mod (line 167) | def remove_mod(self, mod: str) -> None:
method append_mod (line 171) | def append_mod(self, mod: str) -> None:
method _verify_service_stop (line 175) | def _verify_service_stop(self, offline: bool, skip_ntp: bool, skip_wkd...
method _verify_boot_part (line 224) | def _verify_boot_part(self) -> None:
method sanity_check (line 242) | def sanity_check(
method mount_ordered_layout (line 251) | def mount_ordered_layout(self) -> None:
method _mount_partition_layout (line 274) | def _mount_partition_layout(self, luks_handlers: dict[Any, Luks2]) -> ...
method _mount_lvm_layout (line 305) | def _mount_lvm_layout(self, luks_handlers: dict[Any, Luks2] = {}) -> N...
method _prepare_luks_partitions (line 323) | def _prepare_luks_partitions(
method _import_lvm (line 337) | def _import_lvm(self) -> None:
method _prepare_luks_lvm (line 350) | def _prepare_luks_lvm(
method _mount_partition (line 364) | def _mount_partition(self, part_mod: PartitionModification) -> None:
method _mount_lvm_vol (line 384) | def _mount_lvm_vol(self, volume: LvmVolume) -> None:
method _mount_luks_partition (line 396) | def _mount_luks_partition(self, part_mod: PartitionModification, luks_...
method _mount_luks_volume (line 409) | def _mount_luks_volume(self, volume: LvmVolume, luks_handler: Luks2) -...
method _mount_btrfs_subvol (line 421) | def _mount_btrfs_subvol(
method generate_key_files (line 434) | def generate_key_files(self) -> None:
method _generate_key_files_partitions (line 446) | def _generate_key_files_partitions(self) -> None:
method _generate_key_file_lvm_volumes (line 469) | def _generate_key_file_lvm_volumes(self) -> None:
method sync_log_to_install_medium (line 492) | def sync_log_to_install_medium(self) -> bool:
method add_swapfile (line 505) | def add_swapfile(self, size: str = '4G', enable_resume: bool = True, f...
method post_install_check (line 534) | def post_install_check(self, *args: str, **kwargs: str) -> list[str]:
method set_mirrors (line 537) | def set_mirrors(
method genfstab (line 582) | def genfstab(self, flags: str = '-pU') -> None:
method set_hostname (line 606) | def set_hostname(self, hostname: str) -> None:
method set_locale (line 609) | def set_locale(self, locale_config: LocaleConfiguration) -> bool:
method set_timezone (line 658) | def set_timezone(self, zone: str) -> bool:
method activate_time_synchronization (line 679) | def activate_time_synchronization(self) -> None:
method enable_espeakup (line 683) | def enable_espeakup(self) -> None:
method enable_periodic_trim (line 687) | def enable_periodic_trim(self) -> None:
method enable_service (line 692) | def enable_service(self, services: str | list[str]) -> None:
method disable_service (line 708) | def disable_service(self, services_disable: str | list[str]) -> None:
method run_command (line 720) | def run_command(self, cmd: str, peek_output: bool = False) -> SysCommand:
method arch_chroot (line 723) | def arch_chroot(self, cmd: str, run_as: str | None = None, peek_output...
method drop_to_shell (line 729) | def drop_to_shell(self) -> None:
method configure_nic (line 732) | def configure_nic(self, nic: Nic) -> None:
method copy_iso_network_config (line 751) | def copy_iso_network_config(self, enable_services: bool = False) -> bool:
method mkinitcpio (line 808) | def mkinitcpio(self, flags: list[str]) -> bool:
method _get_microcode (line 842) | def _get_microcode(self) -> Path | None:
method _prepare_fs_type (line 848) | def _prepare_fs_type(
method _prepare_encrypt (line 860) | def _prepare_encrypt(self, before: str = 'filesystems') -> None:
method minimal_installation (line 871) | def minimal_installation(
method setup_btrfs_snapshot (line 958) | def setup_btrfs_snapshot(
method setup_swap (line 1007) | def setup_swap(self, algo: ZramAlgorithm = ZramAlgorithm.ZSTD) -> None:
method _get_efi_partition (line 1021) | def _get_efi_partition(self) -> PartitionModification | None:
method _get_boot_partition (line 1027) | def _get_boot_partition(self) -> PartitionModification | None:
method _get_root (line 1033) | def _get_root(self) -> PartitionModification | LvmVolume | None:
method _configure_grub_btrfsd (line 1042) | def _configure_grub_btrfsd(self, snapshot_type: SnapshotType) -> None:
method _get_luks_uuid_from_mapper_dev (line 1070) | def _get_luks_uuid_from_mapper_dev(self, mapper_dev_path: Path) -> str:
method _get_kernel_params_partition (line 1078) | def _get_kernel_params_partition(
method _get_kernel_params_lvm (line 1116) | def _get_kernel_params_lvm(
method _get_kernel_params (line 1155) | def _get_kernel_params(
method _create_bls_entries (line 1188) | def _create_bls_entries(
method _add_systemd_bootloader (line 1217) | def _add_systemd_bootloader(
method _add_grub_bootloader (line 1306) | def _add_grub_bootloader(
method _add_limine_bootloader (line 1428) | def _add_limine_bootloader(
method _add_efistub_bootloader (line 1586) | def _add_efistub_bootloader(
method _add_refind_bootloader (line 1641) | def _add_refind_bootloader(
method _config_uki (line 1740) | def _config_uki(
method add_bootloader (line 1790) | def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = F...
method add_additional_packages (line 1853) | def add_additional_packages(self, packages: str | list[str]) -> None:
method enable_sudo (line 1856) | def enable_sudo(self, user: User, group: bool = False) -> None:
method create_users (line 1886) | def create_users(self, users: User | list[User]) -> None:
method _create_user (line 1893) | def _create_user(self, user: User) -> None:
method set_user_password (line 1930) | def set_user_password(self, user: User) -> bool:
method user_set_shell (line 1949) | def user_set_shell(self, user: str, shell: str) -> bool:
method chown (line 1958) | def chown(self, owner: str, path: str, options: list[str] = []) -> bool:
method set_vconsole (line 1966) | def set_vconsole(self, locale_config: LocaleConfiguration) -> None:
method set_keyboard_language (line 1989) | def set_keyboard_language(self, language: str) -> bool:
method set_x11_keyboard_language (line 2013) | def set_x11_keyboard_language(self, language: str) -> bool:
method _service_started (line 2037) | def _service_started(self, service_name: str) -> str | None:
method _service_state (line 2055) | def _service_state(self, service_name: str) -> str:
function accessibility_tools_in_use (line 2065) | def accessibility_tools_in_use() -> bool:
function run_custom_user_commands (line 2069) | def run_custom_user_commands(commands: list[str], installation: Installe...
FILE: archinstall/lib/interactions/disk_conf.py
function select_devices (line 35) | async def select_devices(preset: list[BDevice] | None = []) -> list[BDev...
function get_default_partition_layout (line 89) | async def get_default_partition_layout(
function _manual_partitioning (line 106) | async def _manual_partitioning(
function select_disk_config (line 127) | async def select_disk_config(preset: DiskLayoutConfiguration | None = No...
function select_lvm_config (line 203) | async def select_lvm_config(
function _boot_partition (line 232) | def _boot_partition(sector_size: SectorSize, using_gpt: bool) -> Partiti...
function select_main_filesystem_format (line 251) | async def select_main_filesystem_format() -> FilesystemType:
function select_mount_options (line 273) | async def select_mount_options() -> list[str]:
function process_root_partition_size (line 299) | def process_root_partition_size(total_size: Size, sector_size: SectorSiz...
function get_default_btrfs_subvols (line 314) | def get_default_btrfs_subvols() -> list[SubvolumeModification]:
function suggest_single_disk_layout (line 326) | async def suggest_single_disk_layout(
function suggest_multi_disk_layout (line 432) | async def suggest_multi_disk_layout(
function suggest_lvm_layout (line 539) | async def suggest_lvm_layout(
FILE: archinstall/lib/interactions/general_conf.py
class PostInstallationAction (line 12) | class PostInstallationAction(Enum):
function select_ntp (line 18) | async def select_ntp(preset: bool = True) -> bool:
function select_hostname (line 42) | async def select_hostname(preset: str | None = None) -> str | None:
function select_timezone (line 61) | async def select_timezone(preset: str | None = None) -> str | None:
function select_language (line 87) | async def select_language(preset: str | None = None) -> str | None:
function select_archinstall_language (line 100) | async def select_archinstall_language(languages: list[Language], preset:...
function add_number_of_parallel_downloads (line 129) | async def add_number_of_parallel_downloads(preset: int = 1) -> int | None:
function select_post_installation (line 179) | async def select_post_installation(elapsed_time: float | None = None) ->...
FILE: archinstall/lib/interactions/system_conf.py
function select_kernel (line 11) | async def select_kernel(preset: list[str] = []) -> list[str]:
function select_uki (line 45) | async def select_uki(preset: bool = True) -> bool:
function select_driver (line 59) | async def select_driver(options: list[GfxDriver] = [], preset: GfxDriver...
function select_swap (line 110) | async def select_swap(preset: ZramConfiguration = ZramConfiguration(enab...
FILE: archinstall/lib/locale/locale_menu.py
class LocaleMenu (line 12) | class LocaleMenu(AbstractSubMenu[LocaleConfiguration]):
method __init__ (line 13) | def __init__(
method _define_menu_options (line 27) | def _define_menu_options(self) -> list[MenuItem]:
method show (line 53) | async def show(self) -> LocaleConfiguration | None:
method _select_kb_layout (line 61) | async def _select_kb_layout(self, preset: str | None) -> str | None:
function select_locale_lang (line 68) | async def select_locale_lang(preset: str | None = None) -> str | None:
function select_locale_enc (line 91) | async def select_locale_enc(preset: str | None = None) -> str | None:
function select_kb_layout (line 114) | async def select_kb_layout(preset: str | None = None) -> str | None:
FILE: archinstall/lib/locale/utils.py
function list_keyboard_languages (line 7) | def list_keyboard_languages() -> list[str]:
function list_locales (line 18) | def list_locales() -> list[str]:
function list_x11_keyboard_languages (line 29) | def list_x11_keyboard_languages() -> list[str]:
function verify_keyboard_layout (line 40) | def verify_keyboard_layout(layout: str) -> bool:
function verify_x11_keyboard_layout (line 47) | def verify_x11_keyboard_layout(layout: str) -> bool:
function get_kb_layout (line 54) | def get_kb_layout() -> str:
function set_kb_layout (line 82) | def set_kb_layout(locale: str) -> bool:
function list_timezones (line 103) | def list_timezones() -> list[str]:
FILE: archinstall/lib/luks.py
class Luks2 (line 17) | class Luks2:
method mapper_dev (line 25) | def mapper_dev(self) -> Path | None:
method isLuks (line 30) | def isLuks(self) -> bool:
method erase (line 37) | def erase(self) -> None:
method __enter__ (line 43) | def __enter__(self) -> None:
method __exit__ (line 46) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method _password_bytes (line 50) | def _password_bytes(self) -> bytes:
method _get_passphrase_args (line 59) | def _get_passphrase_args(
method encrypt (line 70) | def encrypt(
method _get_luks_uuid (line 115) | def _get_luks_uuid(self) -> str:
method is_unlocked (line 124) | def is_unlocked(self) -> bool:
method unlock (line 127) | def unlock(self, key_file: Path | None = None) -> None:
method lock (line 159) | def lock(self) -> None:
method create_keyfile (line 177) | def create_keyfile(self, target_path: Path, override: bool = False) ->...
method _add_key (line 207) | def _add_key(self, key_file: Path) -> None:
method _crypttab (line 222) | def _crypttab(
function unlock_luks2_dev (line 237) | def unlock_luks2_dev(
FILE: archinstall/lib/menu/abstract_menu.py
class SpecialMenuKey (line 16) | class SpecialMenuKey(Enum):
method matches (line 22) | def matches(key: str) -> bool:
class AbstractMenu (line 26) | class AbstractMenu[ValueT](InstanceRunnable[ValueT]):
method __init__ (line 27) | def __init__(
method __enter__ (line 47) | def __enter__(self, *args: Any, **kwargs: Any) -> Self:
method __exit__ (line 51) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method _sync_from_config (line 63) | def _sync_from_config(self) -> None:
method sync_all_to_config (line 70) | def sync_all_to_config(self) -> None:
method _sync (line 75) | def _sync(self, item: MenuItem) -> None:
method set_enabled (line 86) | def set_enabled(self, key: str, enabled: bool) -> None:
method disable_all (line 101) | def disable_all(self) -> None:
method is_config_valid (line 105) | def is_config_valid(self) -> bool:
method run (line 109) | async def run(self) -> ValueT | None:
method show (line 112) | async def show(self) -> ValueT | None:
class AbstractSubMenu (line 149) | class AbstractSubMenu[ValueT](AbstractMenu[ValueT]):
method __init__ (line 150) | def __init__(
FILE: archinstall/lib/menu/helpers.py
class Selection (line 12) | class Selection[ValueT]:
method __init__ (line 13) | def __init__(
method show (line 33) | async def show(self) -> Result[ValueT]:
class Confirmation (line 63) | class Confirmation:
method __init__ (line 64) | def __init__(
method show (line 87) | async def show(self) -> Result[bool]:
class Notify (line 106) | class Notify:
method __init__ (line 107) | def __init__(self, header: str):
method show (line 110) | async def show(self) -> Result[bool]:
class GenericValidator (line 115) | class GenericValidator(Validator):
method __init__ (line 116) | def __init__(self, validator_callback: Callable[[str], str | None]) ->...
method validate (line 122) | def validate(self, value: str) -> ValidationResult:
class Input (line 131) | class Input:
method __init__ (line 132) | def __init__(
method show (line 152) | async def show(self) -> Result[str]:
class Loading (line 175) | class Loading[ValueT]:
method __init__ (line 176) | def __init__(
method show (line 186) | async def show(self) -> Result[ValueT]:
class Table (line 201) | class Table[ValueT]:
method __init__ (line 202) | def __init__(
method show (line 229) | async def show(self) -> Result[ValueT]:
function _confirm_reset (line 251) | async def _confirm_reset() -> Result[bool]:
FILE: archinstall/lib/menu/list_manager.py
class ListManager (line 11) | class ListManager[ValueT]:
method __init__ (line 12) | def __init__(
method last_choice (line 48) | def last_choice(self) -> ValueT | str | None:
method is_last_choice_cancel (line 51) | def is_last_choice_cancel(self) -> bool:
method _run (line 56) | async def _run(self) -> list[ValueT] | None:
method _run_actions_on_entry (line 100) | async def _run_actions_on_entry(self, entry: ValueT) -> None:
method selected_action_display (line 124) | def selected_action_display(self, selection: ValueT) -> str:
method handle_action (line 131) | async def handle_action(self, action: str, entry: ValueT | None, data:...
method filter_options (line 138) | def filter_options(self, selection: ValueT, options: list[str]) -> lis...
FILE: archinstall/lib/menu/menu_helper.py
class MenuHelper (line 5) | class MenuHelper[ValueT]:
method __init__ (line 6) | def __init__(
method create_menu_group (line 15) | def create_menu_group(self) -> MenuItemGroup:
method _table_to_data_mapping (line 31) | def _table_to_data_mapping(self, data: list[ValueT]) -> dict[str, Valu...
FILE: archinstall/lib/menu/util.py
function get_password (line 12) | async def get_password(
function prompt_dir (line 78) | async def prompt_dir(
function confirm_abort (line 120) | async def confirm_abort() -> bool:
function delayed_warning (line 132) | def delayed_warning(message: str) -> bool:
FILE: archinstall/lib/mirror/mirror_handler.py
class MirrorListHandler (line 11) | class MirrorListHandler:
method __init__ (line 12) | def __init__(
method _mappings (line 24) | def _mappings(self) -> dict[str, list[MirrorStatusEntryV3]]:
method get_mirror_regions (line 31) | def get_mirror_regions(self) -> list[MirrorRegion]:
method load_mirrors (line 42) | def load_mirrors(self) -> None:
method load_remote_mirrors (line 52) | def load_remote_mirrors(self) -> bool:
method load_local_mirrors (line 68) | def load_local_mirrors(self) -> None:
method get_status_by_region (line 73) | def get_status_by_region(self, region: str, speed_sort: bool) -> list[...
method _parse_remote_mirror_list (line 87) | def _parse_remote_mirror_list(self, mirrorlist: str) -> dict[str, list...
method _parse_local_mirrors (line 122) | def _parse_local_mirrors(self, mirrorlist: str) -> dict[str, list[Mirr...
FILE: archinstall/lib/mirror/mirror_menu.py
class CustomMirrorRepositoriesList (line 22) | class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
method __init__ (line 23) | def __init__(self, custom_repositories: list[CustomRepository]):
method show (line 37) | async def show(self) -> list[CustomRepository] | None:
method selected_action_display (line 41) | def selected_action_display(self, selection: CustomRepository) -> str:
method handle_action (line 45) | async def handle_action(
method _add_custom_repository (line 66) | async def _add_custom_repository(self, preset: CustomRepository | None...
class CustomMirrorServersList (line 143) | class CustomMirrorServersList(ListManager[CustomServer]):
method __init__ (line 144) | def __init__(self, custom_servers: list[CustomServer]):
method show (line 158) | async def show(self) -> list[CustomServer] | None:
method selected_action_display (line 162) | def selected_action_display(self, selection: CustomServer) -> str:
method handle_action (line 166) | async def handle_action(
method _add_custom_server (line 187) | async def _add_custom_server(self, preset: CustomServer | None = None)...
class MirrorMenu (line 204) | class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
method __init__ (line 205) | def __init__(
method _define_menu_options (line 226) | def _define_menu_options(self) -> list[MenuItem]:
method _prev_regions (line 258) | def _prev_regions(self, item: MenuItem) -> str:
method _prev_additional_repos (line 272) | def _prev_additional_repos(self, item: MenuItem) -> str | None:
method _prev_custom_mirror (line 279) | def _prev_custom_mirror(self, item: MenuItem) -> str | None:
method _prev_custom_servers (line 287) | def _prev_custom_servers(self, item: MenuItem) -> str | None:
method show (line 296) | async def show(self) -> MirrorConfiguration | None:
function select_mirror_regions (line 300) | async def select_mirror_regions(
function add_custom_mirror_servers (line 340) | async def add_custom_mirror_servers(preset: list[CustomServer] = []) -> ...
function select_custom_mirror (line 349) | async def select_custom_mirror(preset: list[CustomRepository] = []) -> l...
function select_optional_repositories (line 358) | async def select_optional_repositories(preset: list[Repository]) -> list...
FILE: archinstall/lib/models/application.py
class PowerManagement (line 6) | class PowerManagement(StrEnum):
class PowerManagementConfigSerialization (line 11) | class PowerManagementConfigSerialization(TypedDict):
class BluetoothConfigSerialization (line 15) | class BluetoothConfigSerialization(TypedDict):
class Audio (line 19) | class Audio(StrEnum):
class AudioConfigSerialization (line 25) | class AudioConfigSerialization(TypedDict):
class PrintServiceConfigSerialization (line 29) | class PrintServiceConfigSerialization(TypedDict):
class Firewall (line 33) | class Firewall(StrEnum):
class FirewallConfigSerialization (line 38) | class FirewallConfigSerialization(TypedDict):
class ZramAlgorithm (line 42) | class ZramAlgorithm(StrEnum):
class ApplicationSerialization (line 50) | class ApplicationSerialization(TypedDict):
class AudioConfiguration (line 59) | class AudioConfiguration:
method json (line 62) | def json(self) -> AudioConfigSerialization:
method parse_arg (line 68) | def parse_arg(cls, arg: dict[str, Any]) -> Self:
class BluetoothConfiguration (line 75) | class BluetoothConfiguration:
method json (line 78) | def json(self) -> BluetoothConfigSerialization:
method parse_arg (line 82) | def parse_arg(cls, arg: BluetoothConfigSerialization) -> Self:
class PowerManagementConfiguration (line 87) | class PowerManagementConfiguration:
method json (line 90) | def json(self) -> PowerManagementConfigSerialization:
method parse_arg (line 96) | def parse_arg(cls, arg: PowerManagementConfigSerialization) -> Self:
class PrintServiceConfiguration (line 103) | class PrintServiceConfiguration:
method json (line 106) | def json(self) -> PrintServiceConfigSerialization:
method parse_arg (line 110) | def parse_arg(cls, arg: PrintServiceConfigSerialization) -> Self:
class FirewallConfiguration (line 115) | class FirewallConfiguration:
method json (line 118) | def json(self) -> FirewallConfigSerialization:
method parse_arg (line 124) | def parse_arg(cls, arg: dict[str, Any]) -> Self:
class ZramConfiguration (line 131) | class ZramConfiguration:
method parse_arg (line 136) | def parse_arg(cls, arg: bool | dict[str, Any]) -> Self:
class ApplicationConfiguration (line 146) | class ApplicationConfiguration:
method parse_arg (line 154) | def parse_arg(
method json (line 182) | def json(self) -> ApplicationSerialization:
FILE: archinstall/lib/models/authentication.py
class U2FLoginConfigSerialization (line 9) | class U2FLoginConfigSerialization(TypedDict):
class AuthenticationSerialization (line 14) | class AuthenticationSerialization(TypedDict):
class U2FLoginMethod (line 18) | class U2FLoginMethod(Enum):
method display_value (line 22) | def display_value(self) -> str:
class U2FLoginConfiguration (line 33) | class U2FLoginConfiguration:
method json (line 37) | def json(self) -> U2FLoginConfigSerialization:
method parse_arg (line 44) | def parse_arg(cls, args: U2FLoginConfigSerialization) -> Self | None:
class AuthenticationConfiguration (line 61) | class AuthenticationConfiguration:
method parse_arg (line 67) | def parse_arg(cls, args: dict[str, Any]) -> Self:
method json (line 78) | def json(self) -> AuthenticationSerialization:
FILE: archinstall/lib/models/bootloader.py
class Bootloader (line 10) | class Bootloader(Enum):
method has_uki_support (line 18) | def has_uki_support(self) -> bool:
method has_removable_support (line 21) | def has_removable_support(self) -> bool:
method json (line 28) | def json(self) -> str:
method get_default (line 32) | def get_default(cls, uefi: bool, skip_boot: bool = False) -> Self:
method from_arg (line 41) | def from_arg(cls, bootloader: str, skip_boot: bool) -> Self:
class BootloaderConfiguration (line 56) | class BootloaderConfiguration:
method json (line 61) | def json(self) -> dict[str, Any]:
method parse_arg (line 65) | def parse_arg(cls, config: dict[str, Any], skip_boot: bool) -> Self:
method get_default (line 72) | def get_default(cls, uefi: bool, skip_boot: bool = False) -> Self:
method preview (line 78) | def preview(self, uefi: bool) -> str:
FILE: archinstall/lib/models/device.py
class DiskLayoutType (line 25) | class DiskLayoutType(Enum):
method display_msg (line 30) | def display_msg(self) -> str:
class _DiskLayoutConfigurationSerialization (line 40) | class _DiskLayoutConfigurationSerialization(TypedDict):
class DiskLayoutConfiguration (line 50) | class DiskLayoutConfiguration:
method json (line 60) | def json(self) -> _DiskLayoutConfigurationSerialization:
method parse_arg (line 84) | def parse_arg(
method has_default_btrfs_vols (line 202) | def has_default_btrfs_vols(self) -> bool:
class PartitionTable (line 214) | class PartitionTable(Enum):
method is_gpt (line 218) | def is_gpt(self) -> bool:
method is_mbr (line 221) | def is_mbr(self) -> bool:
method default (line 225) | def default(cls) -> Self:
class Units (line 229) | class Units(Enum):
class Unit (line 234) | class Unit(Enum):
method get_all_units (line 257) | def get_all_units(cls) -> list[str]:
method get_si_units (line 261) | def get_si_units(cls) -> list[Self]:
method get_binary_units (line 265) | def get_binary_units(cls) -> list[Self]:
class _SectorSizeSerialization (line 269) | class _SectorSizeSerialization(TypedDict):
class SectorSize (line 275) | class SectorSize:
method __post_init__ (line 279) | def __post_init__(self) -> None:
method default (line 285) | def default(cls) -> Self:
method json (line 288) | def json(self) -> _SectorSizeSerialization:
method parse_args (line 295) | def parse_args(cls, arg: _SectorSizeSerialization) -> Self:
method normalize (line 301) | def normalize(self) -> int:
class _SizeSerialization (line 308) | class _SizeSerialization(TypedDict):
class Size (line 315) | class Size:
method json (line 320) | def json(self) -> _SizeSerialization:
method parse_args (line 328) | def parse_args(cls, size_arg: _SizeSerialization) -> Self:
method convert (line 337) | def convert(
method as_text (line 359) | def as_text(self) -> str:
method format_size (line 365) | def format_size(
method binary_unit_highest (line 377) | def binary_unit_highest(self, include_unit: bool = True) -> str:
method si_unit_highest (line 400) | def si_unit_highest(self, include_unit: bool = True) -> str:
method format_highest (line 414) | def format_highest(self, include_unit: bool = True, units: Units = Uni...
method is_valid_start (line 420) | def is_valid_start(self) -> bool:
method align (line 423) | def align(self) -> Size:
method gpt_end (line 428) | def gpt_end(self) -> Size:
method _normalize (line 431) | def _normalize(self) -> int:
method __sub__ (line 439) | def __sub__(self, other: Self) -> Size:
method __add__ (line 444) | def __add__(self, other: Self) -> Size:
method __lt__ (line 449) | def __lt__(self, other: Self) -> bool:
method __le__ (line 452) | def __le__(self, other: Self) -> bool:
method __eq__ (line 456) | def __eq__(self, other: object) -> bool:
method __ne__ (line 463) | def __ne__(self, other: object) -> bool:
method __gt__ (line 469) | def __gt__(self, other: Self) -> bool:
method __ge__ (line 472) | def __ge__(self, other: Self) -> bool:
class BtrfsMountOption (line 476) | class BtrfsMountOption(Enum):
class _BtrfsSubvolumeInfo (line 482) | class _BtrfsSubvolumeInfo:
class _PartitionInfo (line 488) | class _PartitionInfo:
method sector_size (line 505) | def sector_size(self) -> SectorSize:
method table_data (line 509) | def table_data(self) -> dict[str, str]:
method from_partition (line 529) | def from_partition(
class _DeviceInfo (line 570) | class _DeviceInfo:
method __hash__ (line 581) | def __hash__(self) -> int:
method table_data (line 584) | def table_data(self) -> dict[str, str | int | bool]:
method from_disk (line 597) | def from_disk(cls, disk: Disk) -> Self:
class _SubvolumeModificationSerialization (line 622) | class _SubvolumeModificationSerialization(TypedDict):
class SubvolumeModification (line 628) | class SubvolumeModification:
method from_existing_subvol_info (line 633) | def from_existing_subvol_info(cls, info: _BtrfsSubvolumeInfo) -> Self:
method parse_args (line 637) | def parse_args(cls, subvol_args: list[_SubvolumeModificationSerializat...
method relative_mountpoint (line 651) | def relative_mountpoint(self) -> Path:
method is_root (line 661) | def is_root(self) -> bool:
method is_default_root (line 666) | def is_default_root(self) -> bool:
method json (line 669) | def json(self) -> _SubvolumeModificationSerialization:
method table_data (line 672) | def table_data(self) -> _SubvolumeModificationSerialization:
class DeviceGeometry (line 676) | class DeviceGeometry:
method __init__ (line 677) | def __init__(self, geometry: Geometry, sector_size: SectorSize):
method start (line 682) | def start(self) -> int:
method end (line 686) | def end(self) -> int:
method get_length (line 689) | def get_length(self, unit: Unit = Unit.sectors) -> int:
method table_data (line 692) | def table_data(self) -> dict[str, str | int]:
class BDevice (line 710) | class BDevice:
method __hash__ (line 716) | def __hash__(self) -> int:
class PartitionType (line 720) | class PartitionType(Enum):
method get_type_from_code (line 726) | def get_type_from_code(cls, code: int) -> Self:
method get_partition_code (line 733) | def get_partition_code(self) -> int | None:
class PartitionFlagDataMixin (line 742) | class PartitionFlagDataMixin:
class PartitionFlag (line 747) | class PartitionFlag(PartitionFlagDataMixin, Enum):
method description (line 755) | def description(self) -> str:
method from_string (line 759) | def from_string(cls, s: str) -> Self | None:
class PartitionGUID (line 770) | class PartitionGUID(Enum):
method bytes (line 778) | def bytes(self) -> builtins.bytes:
class FilesystemType (line 782) | class FilesystemType(Enum):
method is_crypto (line 799) | def is_crypto(self) -> bool:
method parted_value (line 803) | def parted_value(self) -> str:
method installation_pkg (line 807) | def installation_pkg(self) -> str | None:
class ModificationStatus (line 819) | class ModificationStatus(Enum):
class _PartitionModificationSerialization (line 826) | class _PartitionModificationSerialization(TypedDict):
class PartitionModification (line 841) | class PartitionModification:
method __post_init__ (line 860) | def __post_init__(self) -> None:
method __hash__ (line 872) | def __hash__(self) -> int:
method end (line 876) | def end(self) -> Size:
method obj_id (line 880) | def obj_id(self) -> str:
method safe_dev_path (line 886) | def safe_dev_path(self) -> Path:
method safe_fs_type (line 892) | def safe_fs_type(self) -> FilesystemType:
method from_existing_partition (line 898) | def from_existing_partition(cls, partition_info: _PartitionInfo) -> Self:
method relative_mountpoint (line 926) | def relative_mountpoint(self) -> Path:
method is_efi (line 936) | def is_efi(self) -> bool:
method is_boot (line 939) | def is_boot(self) -> bool:
method is_root (line 942) | def is_root(self) -> bool:
method is_home (line 952) | def is_home(self) -> bool:
method is_swap (line 957) | def is_swap(self) -> bool:
method is_modify (line 960) | def is_modify(self) -> bool:
method is_delete (line 963) | def is_delete(self) -> bool:
method exists (line 966) | def exists(self) -> bool:
method is_exists_or_modify (line 969) | def is_exists_or_modify(self) -> bool:
method is_create_or_modify (line 976) | def is_create_or_modify(self) -> bool:
method mapper_name (line 980) | def mapper_name(self) -> str | None:
method set_flag (line 989) | def set_flag(self, flag: PartitionFlag) -> None:
method invert_flag (line 993) | def invert_flag(self, flag: PartitionFlag) -> None:
method json (line 999) | def json(self) -> _PartitionModificationSerialization:
method table_data (line 1017) | def table_data(self) -> dict[str, str]:
class LvmLayoutType (line 1040) | class LvmLayoutType(Enum):
method display_msg (line 1045) | def display_msg(self) -> str:
class _LvmVolumeGroupSerialization (line 1051) | class _LvmVolumeGroupSerialization(TypedDict):
class LvmVolumeGroup (line 1058) | class LvmVolumeGroup:
method json (line 1063) | def json(self) -> _LvmVolumeGroupSerialization:
method parse_arg (line 1071) | def parse_arg(cls, arg: _LvmVolumeGroupSerialization, disk_config: Dis...
method contains_lv (line 1084) | def contains_lv(self, lv: LvmVolume) -> bool:
class LvmVolumeStatus (line 1088) | class LvmVolumeStatus(Enum):
class _LvmVolumeSerialization (line 1095) | class _LvmVolumeSerialization(TypedDict):
class LvmVolume (line 1107) | class LvmVolume:
method __post_init__ (line 1123) | def __post_init__(self) -> None:
method __hash__ (line 1129) | def __hash__(self) -> int:
method obj_id (line 1133) | def obj_id(self) -> str:
method mapper_name (line 1139) | def mapper_name(self) -> str | None:
method mapper_path (line 1145) | def mapper_path(self) -> Path:
method safe_dev_path (line 1152) | def safe_dev_path(self) -> Path:
method safe_fs_type (line 1158) | def safe_fs_type(self) -> FilesystemType:
method relative_mountpoint (line 1164) | def relative_mountpoint(self) -> Path:
method parse_arg (line 1175) | def parse_arg(cls, arg: _LvmVolumeSerialization) -> Self:
method json (line 1190) | def json(self) -> _LvmVolumeSerialization:
method table_data (line 1202) | def table_data(self) -> dict[str, str]:
method is_modify (line 1214) | def is_modify(self) -> bool:
method exists (line 1217) | def exists(self) -> bool:
method is_exists_or_modify (line 1220) | def is_exists_or_modify(self) -> bool:
method is_root (line 1223) | def is_root(self) -> bool:
class LvmGroupInfo (line 1235) | class LvmGroupInfo:
class LvmVolumeInfo (line 1241) | class LvmVolumeInfo:
class LvmPVInfo (line 1248) | class LvmPVInfo:
class _LvmConfigurationSerialization (line 1254) | class _LvmConfigurationSerialization(TypedDict):
class LvmConfiguration (line 1260) | class LvmConfiguration:
method __post_init__ (line 1264) | def __post_init__(self) -> None:
method json (line 1273) | def json(self) -> _LvmConfigurationSerialization:
method parse_arg (line 1280) | def parse_arg(cls, arg: _LvmConfigurationSerialization, disk_config: D...
method get_all_pvs (line 1293) | def get_all_pvs(self) -> list[PartitionModification]:
method get_all_volumes (line 1300) | def get_all_volumes(self) -> list[LvmVolume]:
method get_root_volume (line 1308) | def get_root_volume(self) -> LvmVolume | None:
class _BtrfsOptionsSerialization (line 1317) | class _BtrfsOptionsSerialization(TypedDict):
class _SnapshotConfigSerialization (line 1321) | class _SnapshotConfigSerialization(TypedDict):
class SnapshotType (line 1325) | class SnapshotType(Enum):
class SnapshotConfig (line 1331) | class SnapshotConfig:
method json (line 1334) | def json(self) -> _SnapshotConfigSerialization:
method parse_args (line 1338) | def parse_args(cls, args: _SnapshotConfigSerialization) -> Self:
class BtrfsOptions (line 1343) | class BtrfsOptions:
method json (line 1346) | def json(self) -> _BtrfsOptionsSerialization:
method parse_arg (line 1350) | def parse_arg(cls, arg: _BtrfsOptionsSerialization) -> Self | None:
class _DeviceModificationSerialization (line 1359) | class _DeviceModificationSerialization(TypedDict):
class DeviceModification (line 1366) | class DeviceModification:
method device_path (line 1372) | def device_path(self) -> Path:
method using_gpt (line 1375) | def using_gpt(self, partition_table: PartitionTable) -> bool:
method add_partition (line 1381) | def add_partition(self, partition: PartitionModification) -> None:
method get_efi_partition (line 1384) | def get_efi_partition(self) -> PartitionModification | None:
method get_boot_partition (line 1388) | def get_boot_partition(self) -> PartitionModification | None:
method get_root_partition (line 1392) | def get_root_partition(self) -> PartitionModification | None:
method json (line 1396) | def json(self) -> _DeviceModificationSerialization:
class EncryptionType (line 1407) | class EncryptionType(Enum):
method _encryption_type_mapper (line 1414) | def _encryption_type_mapper(cls) -> dict[str, Self]:
method text_to_type (line 1423) | def text_to_type(cls, text: str) -> Self:
method type_to_text (line 1427) | def type_to_text(self) -> str:
class _DiskEncryptionSerialization (line 1433) | class _DiskEncryptionSerialization(TypedDict):
class DiskEncryption (line 1442) | class DiskEncryption:
method __post_init__ (line 1450) | def __post_init__(self) -> None:
method should_generate_encryption_file (line 1457) | def should_generate_encryption_file(self, dev: PartitionModification |...
method json (line 1463) | def json(self) -> _DiskEncryptionSerialization:
method validate_enc (line 1479) | def validate_enc(
method parse_arg (line 1496) | def parse_arg(
class _Fido2DeviceSerialization (line 1536) | class _Fido2DeviceSerialization(TypedDict):
class Fido2Device (line 1543) | class Fido2Device:
method json (line 1548) | def json(self) -> _Fido2DeviceSerialization:
method table_data (line 1555) | def table_data(self) -> dict[str, str]:
method parse_arg (line 1563) | def parse_arg(cls, arg: _Fido2DeviceSerialization) -> Self:
class LsblkInfo (line 1571) | class LsblkInfo(BaseModel):
method convert_size (line 1597) | def convert_size(cls, v: int, info: ValidationInfo) -> Size:
method remove_none (line 1603) | def remove_none(cls, v: list[Path | None]) -> list[Path]:
method serialize_size (line 1607) | def serialize_size(self, size: Size) -> str:
method fields (line 1611) | def fields(cls) -> list[str]:
FILE: archinstall/lib/models/locale.py
class LocaleConfiguration (line 9) | class LocaleConfiguration:
method default (line 15) | def default(cls) -> Self:
method json (line 21) | def json(self) -> dict[str, str]:
method preview (line 28) | def preview(self) -> str:
method _load_config (line 34) | def _load_config(self, args: dict[str, str]) -> None:
method parse_arg (line 43) | def parse_arg(cls, args: dict[str, Any]) -> Self:
FILE: archinstall/lib/models/mirrors.py
class MirrorStatusEntryV3 (line 22) | class MirrorStatusEntryV3(BaseModel):
method server_url (line 45) | def server_url(self) -> str:
method speed (line 49) | def speed(self) -> float:
method latency (line 88) | def latency(self) -> float | None:
method validate_score (line 104) | def validate_score(cls, value: float) -> int | None:
method debug_output (line 112) | def debug_output(self, info: ValidationInfo) -> Self:
class MirrorStatusListV3 (line 121) | class MirrorStatusListV3(BaseModel):
method check_model (line 130) | def check_model(
class MirrorRegion (line 141) | class MirrorRegion:
method json (line 145) | def json(self) -> dict[str, list[str]]:
method __eq__ (line 149) | def __eq__(self, other: object) -> bool:
class SignCheck (line 155) | class SignCheck(Enum):
class SignOption (line 161) | class SignOption(Enum):
class _CustomRepositorySerialization (line 166) | class _CustomRepositorySerialization(TypedDict):
class CustomRepository (line 174) | class CustomRepository:
method table_data (line 180) | def table_data(self) -> dict[str, str]:
method json (line 188) | def json(self) -> _CustomRepositorySerialization:
method parse_args (line 197) | def parse_args(cls, args: list[dict[str, str]]) -> list[Self]:
class CustomServer (line 213) | class CustomServer:
method table_data (line 216) | def table_data(self) -> dict[str, str]:
method json (line 219) | def json(self) -> dict[str, str]:
method parse_args (line 223) | def parse_args(cls, args: list[dict[str, str]]) -> list[Self]:
class _MirrorConfigurationSerialization (line 233) | class _MirrorConfigurationSerialization(TypedDict):
class MirrorConfiguration (line 241) | class MirrorConfiguration:
method region_names (line 248) | def region_names(self) -> str:
method custom_server_urls (line 252) | def custom_server_urls(self) -> str:
method json (line 255) | def json(self) -> _MirrorConfigurationSerialization:
method custom_servers_config (line 267) | def custom_servers_config(self) -> str:
method regions_config (line 277) | def regions_config(
method repositories_config (line 297) | def repositories_config(self) -> str:
method parse_args (line 308) | def parse_args(
FILE: archinstall/lib/models/network.py
class NicType (line 10) | class NicType(Enum):
method display_msg (line 16) | def display_msg(self) -> str:
class _NicSerialization (line 28) | class _NicSerialization(TypedDict):
class Nic (line 37) | class Nic:
method table_data (line 44) | def table_data(self) -> dict[str, str | bool | list[str]]:
method json (line 53) | def json(self) -> _NicSerialization:
method parse_arg (line 63) | def parse_arg(cls, arg: _NicSerialization) -> Self:
method as_systemd_config (line 72) | def as_systemd_config(self) -> str:
class _NetworkConfigurationSerialization (line 100) | class _NetworkConfigurationSerialization(TypedDict):
class NetworkConfiguration (line 106) | class NetworkConfiguration:
method json (line 110) | def json(self) -> _NetworkConfigurationSerialization:
method parse_arg (line 118) | def parse_arg(cls, config: _NetworkConfigurationSerialization) -> Self...
class WifiNetwork (line 138) | class WifiNetwork:
method __hash__ (line 146) | def __hash__(self) -> int:
method table_data (line 149) | def table_data(self) -> dict[str, str | int]:
method from_wpa (line 160) | def from_wpa(cls, results: str) -> list[Self]:
class WifiConfiguredNetwork (line 179) | class WifiConfiguredNetwork:
method from_wpa_cli_output (line 186) | def from_wpa_cli_output(cls, list_networks: str) -> list[Self]:
method _extract_flags (line 227) | def _extract_flags(flag_string: str) -> list[str]:
FILE: archinstall/lib/models/packages.py
class Repository (line 11) | class Repository(Enum):
class PackageSearchResult (line 22) | class PackageSearchResult:
method from_json (line 51) | def from_json(cls, data: dict[str, Any]) -> Self:
method pkg_version (line 55) | def pkg_version(self) -> str:
method __eq__ (line 59) | def __eq__(self, other: object) -> bool:
method __lt__ (line 65) | def __lt__(self, other: Self) -> bool:
class PackageSearch (line 70) | class PackageSearch:
method from_json (line 79) | def from_json(cls, data: dict[str, Any]) -> Self:
class LocalPackage (line 92) | class LocalPackage(BaseModel):
method __eq__ (line 102) | def __eq__(self, other: object) -> bool:
method __lt__ (line 108) | def __lt__(self, other: Self) -> bool:
class AvailablePackage (line 112) | class AvailablePackage(BaseModel):
method longest_key (line 132) | def longest_key(self) -> int:
method info (line 136) | def info(self) -> str:
class PackageGroup (line 147) | class PackageGroup:
method from_available_packages (line 152) | def from_available_packages(
method info (line 174) | def info(self) -> str:
FILE: archinstall/lib/models/profile.py
class _ProfileConfigurationSerialization (line 13) | class _ProfileConfigurationSerialization(TypedDict):
class ProfileConfiguration (line 20) | class ProfileConfiguration:
method json (line 25) | def json(self) -> _ProfileConfigurationSerialization:
method parse_arg (line 35) | def parse_arg(cls, arg: _ProfileConfigurationSerialization) -> Self:
FILE: archinstall/lib/models/users.py
class PasswordStrength (line 9) | class PasswordStrength(Enum):
method value (line 17) | def value(self) -> str: # pylint: disable=invalid-overridden-method
method color (line 28) | def color(self) -> str:
method strength (line 40) | def strength(cls, password: str) -> Self:
method _check_password_strength (line 48) | def _check_password_strength(
class Password (line 114) | class Password:
method __init__ (line 115) | def __init__(
method plaintext (line 130) | def plaintext(self) -> str:
method plaintext (line 134) | def plaintext(self, value: str) -> None:
method __eq__ (line 139) | def __eq__(self, other: object) -> bool:
method hidden (line 148) | def hidden(self) -> str:
class User (line 156) | class User:
method __str__ (line 163) | def __str__(self) -> str:
method table_data (line 167) | def table_data(self) -> dict[str, str | bool | list[str]]:
method json (line 175) | def json(self) -> UserSerialization:
method parse_arguments (line 184) | def parse_arguments(
FILE: archinstall/lib/network/network_handler.py
function install_network_config (line 6) | def install_network_config(
function _configure_nm_iwd (line 42) | def _configure_nm_iwd(installation: Installer) -> None:
FILE: archinstall/lib/network/network_menu.py
class ManualNetworkConfig (line 13) | class ManualNetworkConfig(ListManager[Nic]):
method __init__ (line 14) | def __init__(self, prompt: str, preset: list[Nic]):
method show (line 28) | async def show(self) -> list[Nic] | None:
method selected_action_display (line 32) | def selected_action_display(self, selection: Nic) -> str:
method handle_action (line 36) | async def handle_action(self, action: str, entry: Nic | None, data: li...
method _select_iface (line 53) | async def _select_iface(self, data: list[Nic]) -> str | None:
method _get_ip_address (line 81) | async def _get_ip_address(self, header: str, allow_skip: bool, multi: ...
method _edit_iface (line 117) | async def _edit_iface(self, edit_nic: Nic) -> Nic:
function select_network (line 169) | async def select_network(preset: NetworkConfiguration | None) -> Network...
FILE: archinstall/lib/network/wifi_handler.py
class WpaCliResult (line 18) | class WpaCliResult:
class WifiHandler (line 24) | class WifiHandler(InstanceRunnable[bool]):
method __init__ (line 25) | def __init__(self) -> None:
method run (line 29) | async def run(self) -> bool | None:
method _enable_supplicant (line 59) | async def _enable_supplicant(self, wifi_iface: str) -> bool:
method _find_wifi_interface (line 88) | def _find_wifi_interface(self) -> str | None:
method _setup_wifi (line 98) | async def _setup_wifi(self, wifi_iface: str) -> bool:
method _notify_failure (line 187) | async def _notify_failure(self) -> None:
method _wpa_cli (line 190) | def _wpa_cli(self, command: str, iface: str | None = None) -> WpaCliRe...
method _find_network_id (line 216) | def _find_network_id(self, ssid: str, iface: str) -> int | None:
method _prompt_psk (line 237) | async def _prompt_psk(self, existing: str | None = None) -> str | None:
method _get_scan_results (line 252) | def _get_scan_results(self, iface: str) -> list[WifiNetwork]:
FILE: archinstall/lib/network/wpa_supplicant.py
class WpaSupplicantNetwork (line 9) | class WpaSupplicantNetwork:
method psk (line 13) | def psk(self) -> str:
method ssid (line 17) | def ssid(self) -> str:
method to_config_entry (line 20) | def to_config_entry(self) -> str:
class WpaSupplicantConfig (line 34) | class WpaSupplicantConfig:
method __init__ (line 35) | def __init__(self) -> None:
method load_config (line 39) | def load_config(self) -> None:
method _config_header (line 59) | def _config_header(self) -> str:
method get_existing_network (line 62) | def get_existing_network(self, ssid: str) -> WpaSupplicantNetwork | None:
method set_network (line 71) | def set_network(self, network: WifiNetwork, psk: str) -> None:
method write_config (line 87) | def write_config(self) -> None:
method _create_config (line 98) | def _create_config(self) -> None:
method _parse_config (line 104) | def _parse_config(self) -> list[WpaSupplicantNetwork]:
FILE: archinstall/lib/networking.py
class DownloadTimer (line 20) | class DownloadTimer:
method __init__ (line 25) | def __init__(self, timeout: int = 5):
method raise_timeout (line 38) | def raise_timeout(self, signl: int, frame: FrameType | None) -> None:
method __enter__ (line 44) | def __enter__(self) -> Self:
method __exit__ (line 52) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
function get_hw_addr (line 71) | def get_hw_addr(ifname: str) -> str:
function list_interfaces (line 79) | def list_interfaces(skip_loopback: bool = True) -> dict[str, str]:
function update_keyring (line 92) | def update_keyring() -> bool:
function enrich_iface_types (line 104) | def enrich_iface_types(interfaces: list[str]) -> dict[str, str]:
function fetch_data_from_url (line 124) | def fetch_data_from_url(url: str, params: dict[str, str] | None = None, ...
function calc_checksum (line 145) | def calc_checksum(icmp_packet: bytes) -> int:
function build_icmp (line 157) | def build_icmp(payload: bytes) -> bytes:
function ping (line 166) | def ping(hostname: str, timeout: int = 5) -> int:
FILE: archinstall/lib/output.py
class FormattedOutput (line 17) | class FormattedOutput:
method _get_values (line 19) | def _get_values(
method as_table (line 50) | def as_table(
method as_columns (line 113) | def as_columns(entries: list[str], cols: int) -> str:
class Journald (line 130) | class Journald:
method log (line 132) | def log(message: str, level: int = logging.DEBUG) -> None:
class Logger (line 148) | class Logger:
method __init__ (line 149) | def __init__(self, path: Path = Path('/var/log/archinstall')) -> None:
method path (line 153) | def path(self) -> Path:
method directory (line 157) | def directory(self) -> Path:
method _check_permissions (line 160) | def _check_permissions(self) -> None:
method log (line 175) | def log(self, level: int, content: str) -> None:
function _supports_color (line 187) | def _supports_color() -> bool:
class Font (line 204) | class Font(Enum):
function _stylize_output (line 213) | def _stylize_output(
function info (line 266) | def info(
function _timestamp (line 277) | def _timestamp() -> str:
function debug (line 282) | def debug(
function error (line 293) | def error(
function warn (line 304) | def warn(
function log (line 315) | def log(
FILE: archinstall/lib/packages/packages.py
function installed_package (line 13) | def installed_package(package: str) -> LocalPackage | None:
function check_package_upgrade (line 27) | def check_package_upgrade(package: str) -> str | None:
function list_available_packages (line 38) | def list_available_packages(
function _normalize_key_name (line 68) | def _normalize_key_name(key: str) -> str:
function _parse_package_output (line 72) | def _parse_package_output[PackageType: (AvailablePackage, LocalPackage)](
function select_additional_packages (line 87) | async def select_additional_packages(
FILE: archinstall/lib/packages/util.py
function check_version_upgrade (line 8) | def check_version_upgrade() -> str | None:
FILE: archinstall/lib/pacman/config.py
class PacmanConfig (line 8) | class PacmanConfig:
method __init__ (line 9) | def __init__(self, target: Path | None):
method enable (line 18) | def enable(self, repo: Repository | list[Repository]) -> None:
method apply (line 24) | def apply(self) -> None:
method persist (line 53) | def persist(self) -> None:
FILE: archinstall/lib/pacman/pacman.py
class Pacman (line 13) | class Pacman:
method __init__ (line 14) | def __init__(self, target: Path, silent: bool = False):
method run (line 20) | def run(args: str, default_cmd: str = 'pacman') -> SysCommand:
method ask (line 41) | def ask(self, error_message: str, bail_message: str, func: Callable, *...
method sync (line 52) | def sync(self) -> None:
method strap (line 64) | def strap(self, packages: str | list[str]) -> None:
FILE: archinstall/lib/plugins.py
function plugin (line 33) | def plugin(f, *args, **kwargs) -> None: # type: ignore[no-untyped-def]
function _localize_path (line 37) | def _localize_path(path: Path) -> Path:
function _import_via_path (line 54) | def _import_via_path(path: Path, namespace: str | None = None) -> str:
function load_plugin (line 83) | def load_plugin(path: Path) -> None:
FILE: archinstall/lib/profile/profile_menu.py
class ProfileMenu (line 14) | class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
method __init__ (line 15) | def __init__(
method _define_menu_options (line 33) | def _define_menu_options(self) -> list[MenuItem]:
method show (line 63) | async def show(self) -> ProfileConfiguration | None:
method _select_profile (line 66) | async def _select_profile(self, preset: Profile | None) -> Profile | N...
method _select_gfx_driver (line 89) | async def _select_gfx_driver(self, preset: GfxDriver | None = None) ->...
method _prev_gfx (line 113) | def _prev_gfx(self, item: MenuItem) -> str | None:
method _prev_greeter (line 120) | def _prev_greeter(self, item: MenuItem) -> str | None:
method _preview_profile (line 125) | def _preview_profile(self, item: MenuItem) -> str | None:
function select_greeter (line 143) | async def select_greeter(
function select_profile (line 177) | async def select_profile(
FILE: archinstall/lib/profile/profiles_handler.py
class ProfileSerialization (line 23) | class ProfileSerialization(TypedDict):
class ProfileHandler (line 30) | class ProfileHandler:
method __init__ (line 31) | def __init__(self) -> None:
method to_json (line 39) | def to_json(self, profile: Profile | None) -> ProfileSerialization:
method parse_profile_config (line 57) | def parse_profile_config(self, profile_config: ProfileSerialization) -...
method profiles (line 137) | def profiles(self) -> list[Profile]:
method add_custom_profiles (line 144) | def add_custom_profiles(self, profiles: Profile | list[Profile]) -> None:
method remove_custom_profiles (line 153) | def remove_custom_profiles(self, profiles: Profile | list[Profile]) ->...
method get_profile_by_name (line 160) | def get_profile_by_name(self, name: str) -> Profile | None:
method get_top_level_profiles (line 163) | def get_top_level_profiles(self) -> list[Profile]:
method get_server_profiles (line 166) | def get_server_profiles(self) -> list[Profile]:
method get_desktop_profiles (line 169) | def get_desktop_profiles(self) -> list[Profile]:
method get_custom_profiles (line 172) | def get_custom_profiles(self) -> list[Profile]:
method install_greeter (line 175) | def install_greeter(self, install_session: Installer, greeter: Greeter...
method install_gfx_driver (line 222) | def install_gfx_driver(self, install_session: Installer, driver: GfxDr...
method install_profile_config (line 234) | def install_profile_config(self, install_session: Installer, profile_c...
method _import_profile_from_url (line 248) | def _import_profile_from_url(self, url: str) -> None:
method _load_profile_class (line 267) | def _load_profile_class(self, module: ModuleType) -> list[Profile]:
method _verify_unique_profile_names (line 286) | def _verify_unique_profile_names(self, profiles: list[Profile]) -> None:
method _is_legacy (line 299) | def _is_legacy(self, file: Path) -> bool:
method _process_profile_file (line 310) | def _process_profile_file(self, file: Path) -> list[Profile]:
method _find_available_profiles (line 336) | def _find_available_profiles(self) -> list[Profile]:
method reset_top_level_profiles (line 351) | def reset_top_level_profiles(self, exclude: list[Profile] = []) -> None:
FILE: archinstall/lib/translationhandler.py
class Language (line 11) | class Language:
method display_name (line 19) | def display_name(self) -> str:
method is_match (line 23) | def is_match(self, lang_or_translated_lang: str) -> bool:
method json (line 30) | def json(self) -> str:
class TranslationHandler (line 34) | class TranslationHandler:
method __init__ (line 35) | def __init__(self) -> None:
method translated_languages (line 43) | def translated_languages(self) -> list[Language]:
method _get_translations (line 46) | def _get_translations(self) -> list[Language]:
method _load_language_mappings (line 81) | def _load_language_mappings(self) -> list[dict[str, str]]:
method _get_catalog_size (line 91) | def _get_catalog_size(self, translation: gettext.NullTranslations) -> ...
method _get_total_active_messages (line 101) | def _get_total_active_messages(self) -> int:
method get_language_by_name (line 112) | def get_language_by_name(self, name: str) -> Language:
method get_language_by_abbr (line 121) | def get_language_by_abbr(self, abbr: str) -> Language:
method activate (line 130) | def activate(self, language: Language) -> None:
method _get_locales_dir (line 137) | def _get_locales_dir(self) -> Path:
method _provided_translations (line 145) | def _provided_translations(self) -> list[str]:
class _DeferredTranslation (line 160) | class _DeferredTranslation:
method __init__ (line 161) | def __init__(self, message: str):
method __str__ (line 165) | def __str__(self) -> str:
function tr (line 174) | def tr(message: str) -> str:
FILE: archinstall/lib/user/user_menu.py
class UserList (line 13) | class UserList(ListManager[User]):
method __init__ (line 14) | def __init__(self, prompt: str, lusers: list[User]):
method show (line 29) | async def show(self) -> list[User] | None:
method selected_action_display (line 33) | def selected_action_display(self, selection: User) -> str:
method handle_action (line 37) | async def handle_action(self, action: str, entry: User | None, data: l...
method _check_for_correct_username (line 61) | def _check_for_correct_username(self, username: str | None) -> str | N...
method _add_user (line 67) | async def _add_user(self) -> User | None:
function select_users (line 111) | async def select_users(prompt: str = '', preset: list[User] = []) -> lis...
FILE: archinstall/lib/utils/encoding.py
function clear_vt100_escape_codes (line 10) | def clear_vt100_escape_codes(data: bytes) -> bytes:
function clear_vt100_escape_codes_from_str (line 14) | def clear_vt100_escape_codes_from_str(data: str) -> str:
function _is_wide_character (line 19) | def _is_wide_character(char: str) -> bool:
function _count_wchars (line 23) | def _count_wchars(string: str) -> int:
function unicode_ljust (line 28) | def unicode_ljust(string: str, width: int, fillbyte: str = ' ') -> str:
function unicode_rjust (line 42) | def unicode_rjust(string: str, width: int, fillbyte: str = ' ') -> str:
FILE: archinstall/lib/utils/util.py
function running_from_iso (line 8) | def running_from_iso() -> bool:
function generate_password (line 18) | def generate_password(length: int = 64) -> str:
function is_subpath (line 23) | def is_subpath(first: Path, second: Path) -> bool:
function format_cols (line 34) | def format_cols(items: list[str], header: str | None = None) -> str:
FILE: archinstall/lib/version.py
function get_version (line 4) | def get_version() -> str:
FILE: archinstall/main.py
function _log_sys_info (line 24) | def _log_sys_info() -> None:
function _check_online (line 36) | def _check_online(wifi_handler: WifiHandler | None = None) -> bool:
function _fetch_arch_db (line 49) | def _fetch_arch_db() -> bool:
function _list_scripts (line 66) | def _list_scripts() -> str:
function run (line 76) | def run() -> int:
function _error_message (line 133) | def _error_message(exc: Exception) -> None:
function main (line 149) | def main() -> int:
FILE: archinstall/scripts/guided.py
function show_menu (line 27) | def show_menu(
function perform_installation (line 53) | def perform_installation(
function main (line 199) | def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
FILE: archinstall/scripts/minimal.py
function perform_installation (line 18) | def perform_installation(arch_config_handler: ArchConfigHandler) -> None:
function main (line 64) | async def main(arch_config_handler: ArchConfigHandler | None = None) -> ...
FILE: archinstall/scripts/only_hd.py
function show_menu (line 16) | def show_menu(arch_config_handler: ArchConfigHandler) -> None:
function perform_installation (line 30) | def perform_installation(arch_config_handler: ArchConfigHandler) -> None:
function main (line 65) | def main(arch_config_handler: ArchConfigHandler | None = None) -> None:
FILE: archinstall/tui/curses_menu.py
class AbstractCurses (line 33) | class AbstractCurses[ValueT](metaclass=ABCMeta):
method __init__ (line 34) | def __init__(self) -> None:
method resize_win (line 38) | def resize_win(self) -> None:
method kickoff (line 42) | def kickoff(self, win: curses.window) -> Result[ValueT]:
method clear_all (line 45) | def clear_all(self) -> None:
method clear_help_win (line 49) | def clear_help_win(self) -> None:
method _set_help_viewport (line 52) | def _set_help_viewport(self) -> Viewport:
method _confirm_interrupt (line 67) | def _confirm_interrupt(self, warning: str) -> bool:
method help_text (line 84) | def help_text(self) -> str:
method _show_help (line 87) | def _show_help(self) -> None:
method get_header_entries (line 95) | def get_header_entries(self, header: str) -> list[ViewportEntry]:
class AbstractViewport (line 105) | class AbstractViewport:
method __init__ (line 106) | def __init__(self) -> None:
method add_str (line 109) | def add_str(self, screen: curses.window, row: int, col: int, text: str...
method add_frame (line 116) | def add_frame(
method align_center (line 153) | def align_center(self, lines: list[ViewportEntry], width: int) -> int:
method _get_right_frame (line 158) | def _get_right_frame(
method _get_top (line 181) | def _get_top(
method _get_bottom (line 197) | def _get_bottom(
method _get_frame_dim (line 210) | def _get_frame_dim(
method _adjust_entries (line 242) | def _adjust_entries(
method _num_unique_rows (line 254) | def _num_unique_rows(self, entries: list[ViewportEntry]) -> int:
method _max_col (line 257) | def _max_col(self, entries: list[ViewportEntry]) -> int:
method _replace_str (line 263) | def _replace_str(self, text: str, index: int = 0, replacement: str = '...
method _assemble_entries (line 267) | def _assemble_entries(self, entries: list[ViewportEntry]) -> str:
class EditViewport (line 282) | class EditViewport(AbstractViewport):
method __init__ (line 283) | def __init__(
method _init_wins (line 315) | def _init_wins(self) -> None:
method update (line 330) | def update(self) -> None:
method textbox_value (line 358) | def textbox_value(self) -> str:
method erase (line 363) | def erase(self) -> None:
method edit (line 368) | def edit(self, default_text: str | None = None) -> None:
class Viewport (line 385) | class Viewport(AbstractViewport):
method __init__ (line 386) | def __init__(
method getch (line 408) | def getch(self) -> int:
method erase (line 411) | def erase(self) -> None:
method update (line 415) | def update(
class EditMenu (line 452) | class EditMenu(AbstractCurses[str]):
method __init__ (line 453) | def __init__(
method _init_viewports (line 507) | def _init_viewports(self) -> None:
method input (line 533) | def input(self) -> Result[str]:
method resize_win (line 542) | def resize_win(self) -> None:
method _clear_all (line 545) | def _clear_all(self) -> None:
method _get_input_text (line 555) | def _get_input_text(self) -> str | None:
method _draw (line 577) | def _draw(self) -> None:
method kickoff (line 595) | def kickoff(self, win: curses.window) -> Result[str]:
method _process_edit_key (line 620) | def _process_edit_key(self, key: int) -> int:
method _handle_interrupt (line 671) | def _handle_interrupt(self) -> bool:
class SelectMenu (line 681) | class SelectMenu[ValueT](AbstractCurses[ValueT]):
method __init__ (line 682) | def __init__(
method run (line 756) | def run(self) -> Result[ValueT]:
method kickoff (line 762) | def kickoff(self, win: curses.window) -> Result[ValueT]:
method resize_win (line 783) | def resize_win(self) -> None:
method _clear_all (line 786) | def _clear_all(self) -> None:
method _footer_entries (line 800) | def _footer_entries(self) -> list[ViewportEntry]:
method _init_viewports (line 807) | def _init_viewports(self, arg_prev_size: float | Literal['auto']) -> N...
method _determine_prev_size (line 903) | def _determine_prev_size(
method _draw (line 937) | def _draw(self) -> None:
method _update_viewport (line 967) | def _update_viewport(
method _get_col_widths (line 978) | def _get_col_widths(self, items: list[list[MenuItem]]) -> list[int]:
method _item_distance (line 982) | def _item_distance(self) -> int:
method _item_to_vp_entry (line 988) | def _item_to_vp_entry(self, items: list[list[MenuItem]]) -> list[Viewp...
method _calc_col_widths (line 1016) | def _calc_col_widths(self, rows: list[list[MenuItem]], columns: int) -...
method _menu_item_text (line 1030) | def _menu_item_text(self, item: MenuItem) -> str:
method _update_preview (line 1039) | def _update_preview(self) -> None:
method _get_scroll_pct (line 1067) | def _get_scroll_pct(
method _get_scroll_win_prev_entries (line 1087) | def _get_scroll_win_prev_entries(
method _calc_prev_scroll_pos (line 1113) | def _calc_prev_scroll_pos(
method _multi_prefix (line 1123) | def _multi_prefix(self, item: MenuItem) -> str:
method _handle_interrupt (line 1131) | def _handle_interrupt(self) -> bool:
method _process_input_key (line 1137) | def _process_input_key(self, key: int) -> Result[ValueT] | None:
method _focus_item (line 1226) | def _focus_item(self, direction: Literal['next', 'prev', 'first', 'las...
class Tui (line 1242) | class Tui:
method __enter__ (line 1245) | def __enter__(self) -> None:
method __exit__ (line 1250) | def __exit__(self, exc_type: type[BaseException] | None, exc_value: Ba...
method screen (line 1254) | def screen(self) -> curses.window:
method t (line 1258) | def t(cls) -> Self:
method shutdown (line 1263) | def shutdown() -> None:
method init (line 1269) | def init(self) -> Self:
method stop (line 1288) | def stop(self) -> None:
method print (line 1307) | def print(
method max_yx (line 1335) | def max_yx(self) -> tuple[int, int]:
method run (line 1339) | def run[ValueT](component: AbstractCurses[ValueT]) -> Result[ValueT]:
method _sig_win_resize (line 1351) | def _sig_win_resize(self, signum: int, frame: FrameType | None) -> None:
method _main_loop (line 1355) | def _main_loop[ValueT](self, component: AbstractCurses[ValueT]) -> Res...
method _reset_terminal (line 1359) | def _reset_terminal(self) -> None:
method _set_up_colors (line 1362) | def _set_up_colors(self) -> None:
method get_color (line 1370) | def get_color(self, color: STYLE) -> int:
FILE: archinstall/tui/help.py
class HelpTextGroupId (line 7) | class HelpTextGroupId(Enum):
class HelpText (line 15) | class HelpText:
class HelpGroup (line 21) | class HelpGroup:
method get_desc_width (line 25) | def get_desc_width(self) -> int:
method get_key_width (line 28) | def get_key_width(self) -> int:
class Help (line 32) | class Help:
method general (line 39) | def general() -> HelpGroup:
method navigation (line 49) | def navigation() -> HelpGroup:
method selection (line 64) | def selection() -> HelpGroup:
method search (line 78) | def search() -> HelpGroup:
method get_help_text (line 88) | def get_help_text() -> str:
FILE: archinstall/tui/menu_item.py
class MenuItem (line 12) | class MenuItem:
method __post_init__ (line 29) | def __post_init__(self) -> None:
method __hash__ (line 36) | def __hash__(self) -> int:
method get_id (line 39) | def get_id(self) -> str:
method get_value (line 42) | def get_value(self) -> Any:
method yes (line 47) | def yes(cls, action: Callable[[Any], Any] | None = None) -> Self:
method no (line 54) | def no(cls, action: Callable[[Any], Any] | None = None) -> Self:
method is_empty (line 60) | def is_empty(self) -> bool:
method has_value (line 63) | def has_value(self) -> bool:
method get_display_value (line 73) | def get_display_value(self) -> str | None:
class MenuItemGroup (line 80) | class MenuItemGroup:
method __init__ (line 81) | def __init__(
method add_item (line 113) | def add_item(self, item: MenuItem) -> None:
method find_by_id (line 117) | def find_by_id(self, item_id: str) -> MenuItem:
method find_by_key (line 124) | def find_by_key(self, key: str) -> MenuItem:
method get_enabled_items (line 131) | def get_enabled_items(self) -> list[MenuItem]:
method yes_no (line 135) | def yes_no(cls) -> Self:
method from_enum (line 142) | def from_enum(
method set_preview_for_all (line 156) | def set_preview_for_all(self, action: Callable[[Any], str | None]) -> ...
method set_focus_by_value (line 160) | def set_focus_by_value(self, value: Any) -> None:
method set_default_by_value (line 166) | def set_default_by_value(self, value: Any) -> None:
method set_selected_by_value (line 172) | def set_selected_by_value(self, values: Any | list[Any] | None) -> None:
method get_focused_index (line 186) | def get_focused_index(self) -> int | None:
method index_focus (line 201) | def index_focus(self) -> int | None:
method size (line 215) | def size(self) -> int:
method get_max_width (line 218) | def get_max_width(self) -> int:
method _max_items_text_width (line 224) | def _max_items_text_width(self) -> int:
method get_item_text (line 227) | def get_item_text(self, item: MenuItem) -> str:
method _default_suffix (line 255) | def _default_suffix(self, item: MenuItem) -> str:
method set_action_for_all (line 260) | def set_action_for_all(self, action: Callable[[Any], Any]) -> None:
method items (line 265) | def items(self) -> list[MenuItem]:
method _items_score (line 271) | def _items_score(self, item: MenuItem) -> int:
method filter_pattern (line 278) | def filter_pattern(self) -> str:
method has_filter (line 281) | def has_filter(self) -> bool:
method set_filter_pattern (line 284) | def set_filter_pattern(self, pattern: str) -> None:
method append_filter (line 289) | def append_filter(self, pattern: str) -> None:
method reduce_filter (line 294) | def reduce_filter(self) -> None:
method _reload_focus_item (line 299) | def _reload_focus_item(self) -> None:
method is_item_selected (line 306) | def is_item_selected(self, item: MenuItem) -> bool:
method select_current_item (line 309) | def select_current_item(self) -> None:
method focus_index (line 316) | def focus_index(self, index: int) -> None:
method focus_first (line 320) | def focus_first(self) -> None:
method focus_last (line 332) | def focus_last(self) -> None:
method focus_prev (line 344) | def focus_prev(self, skip_empty: bool = True) -> None:
method focus_next (line 354) | def focus_next(self, skip_not_enabled: bool = True) -> None:
method _find_next_selectable_item (line 364) | def _find_next_selectable_item(
method is_mandatory_fulfilled (line 382) | def is_mandatory_fulfilled(self) -> bool:
method max_item_width (line 388) | def max_item_width(self) -> int:
method _is_selectable (line 394) | def _is_selectable(self, item: MenuItem) -> bool:
method is_enabled (line 402) | def is_enabled(self, item: MenuItem) -> bool:
class MenuItemsState (line 422) | class MenuItemsState:
method __init__ (line 423) | def __init__(
method _determine_focus_row (line 438) | def _determine_focus_row(self) -> int | None:
method get_view_items (line 447) | def get_view_items(self) -> list[list[MenuItem]]:
method _get_view_items (line 492) | def _get_view_items(
method _max_visible_items (line 508) | def _max_visible_items(self) -> int:
method _remaining_next_spots (line 511) | def _remaining_next_spots(self) -> int:
method _remaining_prev_spots (line 514) | def _remaining_prev_spots(self) -> int:
FILE: archinstall/tui/result.py
class ResultType (line 7) | class ResultType(Enum):
class Result (line 14) | class Result[ValueT]:
method has_item (line 18) | def has_item(self) -> bool:
method get_value (line 21) | def get_value(self) -> ValueT:
method get_values (line 24) | def get_values(self) -> list[ValueT]:
method item (line 27) | def item(self) -> MenuItem:
method items (line 31) | def items(self) -> list[MenuItem]:
method text (line 35) | def text(self) -> str:
FILE: archinstall/tui/types.py
class STYLE (line 9) | class STYLE(Enum):
class MenuKeys (line 17) | class MenuKeys(Enum):
method from_ord (line 52) | def from_ord(cls, key: int) -> list[Self]:
method decode (line 62) | def decode(cls, key: int) -> str:
class FrameStyle (line 67) | class FrameStyle(Enum):
class FrameProperties (line 73) | class FrameProperties:
method max (line 79) | def max(cls, header: str) -> Self:
method min (line 87) | def min(cls, header: str) -> Self:
class Orientation (line 95) | class Orientation(Enum):
class PreviewStyle (line 100) | class PreviewStyle(Enum):
class Chars (line 109) | class Chars:
class ViewportEntry (line 125) | class ViewportEntry:
class Alignment (line 132) | class Alignment(Enum):
class FrameDim (line 138) | class FrameDim:
method x_delta (line 143) | def x_delta(self) -> int:
FILE: archinstall/tui/ui/components.py
class BaseScreen (line 30) | class BaseScreen(Screen[Result[ValueT]]):
method __init__ (line 36) | def __init__(self, allow_skip: bool = False, allow_reset: bool = False):
method action_cancel_operation (line 41) | def action_cancel_operation(self) -> None:
method action_reset_operation (line 45) | async def action_reset_operation(self) -> None:
class LoadingScreen (line 50) | class LoadingScreen(BaseScreen[ValueT]):
method __init__ (line 73) | def __init__(
method run (line 84) | async def run(self) -> Result[ValueT]:
method compose (line 89) | def compose(self) -> ComposeResult:
method on_mount (line 99) | def on_mount(self) -> None:
method _set_cursor (line 107) | def _set_cursor(self) -> None:
method _exec_callback (line 113) | def _exec_callback(self) -> None:
method action_pop_screen (line 118) | def action_pop_screen(self) -> None:
class _OptionList (line 122) | class _OptionList(OptionList):
class OptionListScreen (line 131) | class OptionListScreen(BaseScreen[ValueT]):
method __init__ (line 186) | def __init__(
method action_search (line 206) | def action_search(self) -> None:
method action_cancel_operation (line 212) | def action_cancel_operation(self) -> None:
method _handle_search_action (line 218) | def _handle_search_action(self) -> None:
method run (line 226) | async def run(self) -> Result[ValueT]:
method _get_options (line 230) | def _get_options(self) -> list[Option]:
method compose (line 240) | def compose(self) -> ComposeResult:
method on_mount (line 271) | def on_mount(self) -> None:
method on_input_changed (line 275) | def on_input_changed(self, event: Input.Changed) -> None:
method _update_options (line 281) | def _update_options(self, options: list[Option]) -> None:
method on_option_list_option_selected (line 291) | def on_option_list_option_selected(self, event: OptionList.OptionSelec...
method on_option_list_option_highlighted (line 297) | def on_option_list_option_highlighted(self, event: OptionList.OptionHi...
method _set_cursor (line 303) | def _set_cursor(self) -> None:
method _set_preview (line 327) | def _set_preview(self, item_id: str) -> None:
class _SelectionList (line 344) | class _SelectionList(SelectionList[ValueT]):
class SelectListScreen (line 353) | class SelectListScreen(BaseScreen[ValueT]):
method __init__ (line 409) | def __init__(
method action_search (line 428) | def action_search(self) -> None:
method action_cancel_operation (line 434) | def action_cancel_operation(self) -> None:
method _handle_search_action (line 440) | def _handle_search_action(self) -> None:
method run (line 448) | async def run(self) -> Result[ValueT]:
method _get_selections (line 452) | def _get_selections(self) -> list[Selection[MenuItem]]:
method compose (line 463) | def compose(self) -> ComposeResult:
method on_mount (line 491) | def on_mount(self) -> None:
method on_key (line 495) | def on_key(self, event: Key) -> None:
method on_input_changed (line 500) | def on_input_changed(self, event: Input.Changed) -> None:
method _update_options (line 506) | def _update_options(self, options: list[Selection[MenuItem]]) -> None:
method on_selection_list_selection_highlighted (line 518) | def on_selection_list_selection_highlighted(self, event: SelectionList...
method _set_cursor (line 525) | def _set_cursor(self) -> None:
method on_selection_list_selection_toggled (line 544) | def on_selection_list_selection_toggled(self, event: SelectionList.Sel...
method _set_preview (line 552) | def _set_preview(self, item: MenuItem) -> None:
class ConfirmationScreen (line 568) | class ConfirmationScreen(BaseScreen[ValueT]):
method __init__ (line 611) | def __init__(
method run (line 626) | async def run(self) -> Result[ValueT]:
method compose (line 631) | def compose(self) -> ComposeResult:
method on_mount (line 652) | def on_mount(self) -> None:
method action_focus_right (line 655) | def action_focus_right(self) -> None:
method action_focus_left (line 660) | def action_focus_left(self) -> None:
method _update_selection (line 665) | def _update_selection(self) -> None:
method _is_btn_focus (line 689) | def _is_btn_focus(self) -> bool:
method on_key (line 697) | def on_key(self, event: Key) -> None:
class NotifyScreen (line 706) | class NotifyScreen(ConfirmationScreen[ValueT]):
method __init__ (line 707) | def __init__(self, header: str):
class InputInfoType (line 712) | class InputInfoType(Enum):
class InputInfo (line 719) | class InputInfo:
class InputScreen (line 724) | class InputScreen(BaseScreen[str]):
method __init__ (line 763) | def __init__(
method run (line 784) | async def run(self) -> Result[str]:
method compose (line 789) | def compose(self) -> ComposeResult:
method on_mount (line 807) | def on_mount(self) -> None:
method on_input_submitted (line 811) | def on_input_submitted(self, event: Input.Submitted) -> None:
method on_input_changed (line 820) | def on_input_changed(self, event: Input.Changed) -> None:
class _DataTable (line 839) | class _DataTable(DataTable[ValueT]):
class TableSelectionScreen (line 848) | class TableSelectionScreen(BaseScreen[ValueT]):
method __init__ (line 908) | def __init__(
method run (line 935) | async def run(self) -> Result[ValueT]:
method compose (line 940) | def compose(self) -> ComposeResult:
method on_mount (line 966) | def on_mount(self) -> None:
method _load_data (line 977) | async def _load_data(self, table: DataTable[ValueT]) -> None:
method _display_header (line 982) | def _display_header(self, is_loading: bool) -> None:
method _put_data_to_table (line 991) | def _put_data_to_table(self, table: DataTable[ValueT], group: MenuItem...
method action_toggle_selection (line 1035) | def action_toggle_selection(self) -> None:
method on_data_table_row_highlighted (line 1052) | def on_data_table_row_highlighted(self, event: DataTable.RowHighlighte...
method _set_cursor (line 1070) | def _set_cursor(self, row_index: int) -> None:
method on_data_table_row_selected (line 1087) | def on_data_table_row_selected(self, event: DataTable.RowSelected) -> ...
class InstanceRunnable (line 1106) | class InstanceRunnable[ValueT](ABC):
method run (line 1108) | async def run(self) -> ValueT | None:
class _AppInstance (line 1112) | class _AppInstance(App[ValueT]):
method __init__ (line 1209) | def __init__(self, main: InstanceRunnable[ValueT] | Callable[[], Await...
method action_trigger_help (line 1213) | def action_trigger_help(self) -> None:
method on_mount (line 1221) | def on_mount(self) -> None:
method _run_worker (line 1225) | async def _run_worker(self) -> None:
method _show_async (line 1241) | async def _show_async(self, screen: Screen[Result[ValueT]]) -> Result[...
method show (line 1244) | async def show(self, screen: Screen[Result[ValueT]]) -> Result[ValueT]:
class TApp (line 1248) | class TApp:
method run (line 1251) | def run(self, main: InstanceRunnable[ValueT] | Callable[[], Awaitable[...
method exit (line 1264) | def exit(self, result: Any) -> None:
FILE: archinstall/tui/ui/menu_item.py
class MenuItem (line 13) | class MenuItem:
method __post_init__ (line 31) | def __post_init__(self) -> None:
method __hash__ (line 38) | def __hash__(self) -> int:
method get_id (line 41) | def get_id(self) -> str:
method get_value (line 44) | def get_value(self) -> Any:
method yes (line 49) | def yes(cls, action: Callable[[Any], Any] | None = None) -> Self:
method no (line 56) | def no(cls, action: Callable[[Any], Any] | None = None) -> Self:
method is_empty (line 62) | def is_empty(self) -> bool:
method has_value (line 65) | def has_value(self) -> bool:
method get_display_value (line 75) | def get_display_value(self) -> str | None:
class MenuItemGroup (line 82) | class MenuItemGroup:
method __init__ (line 83) | def __init__(
method from_objects (line 116) | def from_objects(cls, items: list[Any]) -> Self:
method add_item (line 120) | def add_item(self, item: MenuItem) -> None:
method find_by_id (line 124) | def find_by_id(self, item_id: str) -> MenuItem:
method find_by_key (line 131) | def find_by_key(self, key: str) -> MenuItem:
method get_enabled_items (line 138) | def get_enabled_items(self) -> list[MenuItem]:
method yes_no (line 142) | def yes_no(cls) -> Self:
method from_enum (line 149) | def from_enum(
method set_preview_for_all (line 163) | def set_preview_for_all(self, action: Callable[[Any], str | None]) -> ...
method set_focus_by_value (line 167) | def set_focus_by_value(self, value: Any) -> None:
method set_default_by_value (line 173) | def set_default_by_value(self, value: Any) -> None:
method set_selected_by_value (line 179) | def set_selected_by_value(self, values: Any | list[Any] | None) -> None:
method get_focused_index (line 193) | def get_focused_index(self) -> int | None:
method _max_items_text_width (line 209) | def _max_items_text_width(self) -> int:
method _default_suffix (line 212) | def _default_suffix(self, item: MenuItem) -> str:
method set_action_for_all (line 217) | def set_action_for_all(self, action: Callable[[Any], Any]) -> None:
method items (line 222) | def items(self) -> list[MenuItem]:
method _items_score (line 228) | def _items_score(self, item: MenuItem) -> int:
method set_filter_pattern (line 234) | def set_filter_pattern(self, pattern: str) -> None:
method focus_index (line 239) | def focus_index(self, index: int) -> None:
method focus_first (line 243) | def focus_first(self) -> None:
method focus_last (line 255) | def focus_last(self) -> None:
method focus_prev (line 267) | def focus_prev(self, skip_empty: bool = True) -> None:
method focus_next (line 277) | def focus_next(self, skip_not_enabled: bool = True) -> None:
method _find_next_selectable_item (line 287) | def _find_next_selectable_item(
method max_item_width (line 305) | def max_item_width(self) -> int:
method _is_selectable (line 311) | def _is_selectable(self, item: MenuItem) -> bool:
method is_enabled (line 319) | def is_enabled(self, item: MenuItem) -> bool:
FILE: archinstall/tui/ui/result.py
class ResultType (line 8) | class ResultType(Enum):
class Result (line 15) | class Result[ValueT]:
method true (line 21) | def true(cls) -> Self:
method false (line 25) | def false(cls) -> Self:
method reset (line 29) | def reset(cls) -> Self:
method selection (line 33) | def selection(cls, value: ValueT | list[ValueT] | None) -> Self:
method skip (line 37) | def skip(cls) -> Self:
method has_data (line 40) | def has_data(self) -> bool:
method has_value (line 43) | def has_value(self) -> bool:
method item (line 46) | def item(self) -> MenuItem:
method items (line 51) | def items(self) -> list[MenuItem]:
method get_value (line 57) | def get_value(self) -> ValueT:
method get_values (line 66) | def get_values(self) -> list[ValueT]:
FILE: docs/conf.py
function process_docstring (line 8) | def process_docstring(app, what, name, obj, options, lines) -> None: # ...
function setup (line 14) | def setup(app) -> None: # type: ignore[no-untyped-def]
FILE: tests/conftest.py
function config_fixture (line 7) | def config_fixture() -> Path:
function btrfs_config_fixture (line 12) | def btrfs_config_fixture() -> Path:
function creds_fixture (line 17) | def creds_fixture() -> Path:
function encrypted_creds_fixture (line 22) | def encrypted_creds_fixture() -> Path:
function deprecated_creds_config (line 27) | def deprecated_creds_config() -> Path:
function deprecated_mirror_config (line 32) | def deprecated_mirror_config() -> Path:
function deprecated_audio_config (line 37) | def deprecated_audio_config() -> Path:
function mirrorlist_no_country_fixture (line 42) | def mirrorlist_no_country_fixture() -> Path:
function mirrorlist_with_country_fixture (line 47) | def mirrorlist_with_country_fixture() -> Path:
function mirrorlist_multiple_countries_fixture (line 52) | def mirrorlist_multiple_countries_fixture() -> Path:
FILE: tests/test_args.py
function test_default_args (line 31) | def test_default_args(monkeypatch: MonkeyPatch) -> None:
function test_correct_parsing_args (line 57) | def test_correct_parsing_args(
function test_config_file_parsing (line 114) | def test_config_file_parsing(
function test_deprecated_mirror_config_parsing (line 242) | def test_deprecated_mirror_config_parsing(
function test_deprecated_creds_config_parsing (line 278) | def test_deprecated_creds_config_parsing(
function test_deprecated_audio_config_parsing (line 307) | def test_deprecated_audio_config_parsing(
function test_encrypted_creds_with_arg (line 328) | def test_encrypted_creds_with_arg(
function test_encrypted_creds_with_env_var (line 358) | def test_encrypted_creds_with_env_var(
FILE: tests/test_configuration_output.py
function test_user_config_roundtrip (line 10) | def test_user_config_roundtrip(
function test_creds_roundtrip (line 49) | def test_creds_roundtrip(
FILE: tests/test_mirrorlist.py
function test_mirrorlist_no_country (line 6) | def test_mirrorlist_no_country(mirrorlist_no_country_fixture: Path) -> N...
function test_mirrorlist_with_country (line 20) | def test_mirrorlist_with_country(mirrorlist_with_country_fixture: Path) ...
function test_mirrorlist_multiple_countries (line 34) | def test_mirrorlist_multiple_countries(mirrorlist_multiple_countries_fix...
FILE: tests/test_password_strength.py
function test_password_strength (line 18) | def test_password_strength(password: str, expected: PasswordStrength) ->...
Condensed preview — 291 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,091K chars).
[
{
"path": ".editorconfig",
"chars": 223,
"preview": "# http://editorconfig.org\n# See coding conventions in CONTRIBUTING.md\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\n"
},
{
"path": ".flake8",
"chars": 183,
"preview": "[flake8]\ncount = True\nignore = W191,W503,E704,E203\nmax-complexity = 40\nmax-line-length = 160\nshow-source = True\nstatisti"
},
{
"path": ".github/CODEOWNERS",
"chars": 237,
"preview": "# As per https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#example-of-a-co"
},
{
"path": ".github/FUNDING.yml",
"chars": 109,
"preview": "# These are supported funding model platforms\n\ngithub: [archlinux]\ncustom: ['https://archlinux.org/donate/']\n"
},
{
"path": ".github/ISSUE_TEMPLATE/01_bug.yml",
"chars": 2632,
"preview": "name: bug report\ndescription: archinstall crashed or could not install properly?\nbody:\n - type: markdown\n attributes"
},
{
"path": ".github/ISSUE_TEMPLATE/02_feature.yml",
"chars": 495,
"preview": "name: feature request\ndescription: a new feature!\nbody:\n - type: markdown\n attributes:\n value: >\n Please"
},
{
"path": ".github/workflows/bandit.yaml",
"chars": 419,
"preview": "on: [ push, pull_request ]\nname: Bandit security checkup\njobs:\n bandit:\n runs-on: ubuntu-latest\n contai"
},
{
"path": ".github/workflows/flake8.yaml",
"chars": 940,
"preview": "on: [ push, pull_request ]\nname: flake8 linting\njobs:\n flake8:\n runs-on: ubuntu-latest\n container:\n "
},
{
"path": ".github/workflows/github-pages.yml",
"chars": 1219,
"preview": "name: documentation\n\non:\n push:\n paths:\n - \"docs/**\"\n\n pull_request:\n paths:\n - \"docs/**\"\n\n workflow_"
},
{
"path": ".github/workflows/iso-build.yaml",
"chars": 979,
"preview": "# This workflow will build an Arch Linux ISO file with the commit on it\n\nname: Build Arch ISO with ArchInstall Commit\n\no"
},
{
"path": ".github/workflows/mypy.yaml",
"chars": 957,
"preview": "on: [ push, pull_request ]\nname: mypy type checking\njobs:\n mypy:\n runs-on: ubuntu-latest\n container:\n "
},
{
"path": ".github/workflows/pylint.yaml",
"chars": 829,
"preview": "on: [ push, pull_request ]\nname: Pylint linting\njobs:\n pylint:\n runs-on: ubuntu-latest\n container:\n "
},
{
"path": ".github/workflows/pytest.yaml",
"chars": 815,
"preview": "on: [ push, pull_request ]\nname: pytest test validation\njobs:\n pytest:\n runs-on: ubuntu-latest\n contain"
},
{
"path": ".github/workflows/python-build.yml",
"chars": 1334,
"preview": "# This workflow will build Python packages on every commit.\n\nname: Build archinstall\n\non: [ push, pull_request ]\n\njobs:\n"
},
{
"path": ".github/workflows/python-publish.yml",
"chars": 1114,
"preview": "# This workflow will upload a Python Package when a release is created\n# For more information see: https://help.github.c"
},
{
"path": ".github/workflows/ruff-format.yaml",
"chars": 316,
"preview": "on: [ push, pull_request ]\nname: ruff check formatting\njobs:\n ruff_format_check:\n runs-on: ubuntu-latest\n steps:\n"
},
{
"path": ".github/workflows/ruff-lint.yaml",
"chars": 290,
"preview": "on: [ push, pull_request ]\nname: ruff check linting\njobs:\n ruff:\n runs-on: ubuntu-latest\n steps:\n "
},
{
"path": ".github/workflows/translation-check.yaml",
"chars": 1105,
"preview": "#on:\n# push:\n# paths:\n# - 'archinstall/locales/**'\n# pull_request:\n# paths:\n# - 'archi"
},
{
"path": ".gitignore",
"chars": 560,
"preview": "**/**__pycache__\nSAFETY_LOCK\n**/**old.*\n**/**.img\n**/**pwfile\n**/**build\n**/**dist\n**/**.egg*\n**/**.sh\n!archinstall/loca"
},
{
"path": ".gitlab-ci.yml",
"chars": 3520,
"preview": "# This file contains GitLab CI/CD configuration for the ArchInstall project.\n# It defines several jobs that get run when"
},
{
"path": ".pre-commit-config.yaml",
"chars": 1743,
"preview": "default_stages: ['pre-commit']\nrepos:\n - repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v0.15.7\n hooks:"
},
{
"path": ".pypirc",
"chars": 89,
"preview": "[distutils]\nindex-servers =\n pypi\n\n[pypi]\nrepository = https://upload.pypi.org/legacy/\n"
},
{
"path": ".readthedocs.yaml",
"chars": 278,
"preview": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html fo"
},
{
"path": "CONTRIBUTING.md",
"chars": 4152,
"preview": "# Contributing to archinstall\n\nAny contributions through pull requests are welcome as this project aims to be a communit"
},
{
"path": "LICENSE",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "PKGBUILD",
"chars": 1966,
"preview": "# Maintainer: David Runge <dvzrv@archlinux.org>\n# Maintainer: Giancarlo Razzolini <grazzolini@archlinux.org>\n# Maintaine"
},
{
"path": "README.md",
"chars": 13959,
"preview": "<!-- <div align=\"center\"> -->\n<img src=\"https://github.com/archlinux/archinstall/raw/master/docs/logo.png\" alt=\"drawing\""
},
{
"path": "archinstall/__init__.py",
"chars": 65,
"preview": "from archinstall.lib.plugins import plugin\n\n__all__ = ['plugin']\n"
},
{
"path": "archinstall/__main__.py",
"chars": 92,
"preview": "import sys\n\nfrom archinstall.main import main\n\nif __name__ == '__main__':\n\tsys.exit(main())\n"
},
{
"path": "archinstall/applications/audio.py",
"chars": 2439,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.lib.hardware import SysInfo\nfrom "
},
{
"path": "archinstall/applications/bluetooth.py",
"chars": 570,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.lib.output import debug\n\nif TYPE_"
},
{
"path": "archinstall/applications/firewall.py",
"chars": 1276,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.lib.models.application import Fir"
},
{
"path": "archinstall/applications/power_management.py",
"chars": 963,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.lib.models.application import Pow"
},
{
"path": "archinstall/applications/print_service.py",
"chars": 588,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.lib.output import debug\n\nif TYPE_"
},
{
"path": "archinstall/default_profiles/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/default_profiles/desktop.py",
"chars": 2850,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Self, override\n\nfrom archinstall.default_profiles."
},
{
"path": "archinstall/default_profiles/desktops/__init__.py",
"chars": 84,
"preview": "from enum import Enum\n\n\nclass SeatAccess(Enum):\n\tseatd = 'seatd'\n\tpolkit = 'polkit'\n"
},
{
"path": "archinstall/default_profiles/desktops/awesome.py",
"chars": 1928,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, override\n\nfrom archinstall.default_profiles.profil"
},
{
"path": "archinstall/default_profiles/desktops/bspwm.py",
"chars": 545,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/budgie.py",
"chars": 549,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/cinnamon.py",
"chars": 626,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/cosmic.py",
"chars": 490,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/cutefish.py",
"chars": 484,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/deepin.py",
"chars": 506,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/enlightenment.py",
"chars": 502,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/gnome.py",
"chars": 476,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/hyprland.py",
"chars": 1919,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.desktops import SeatAccess\nfrom archinstall.default_profi"
},
{
"path": "archinstall/default_profiles/desktops/i3.py",
"chars": 581,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/labwc.py",
"chars": 1872,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.desktops import SeatAccess\nfrom archinstall.default_profi"
},
{
"path": "archinstall/default_profiles/desktops/lxqt.py",
"chars": 799,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/mate.py",
"chars": 475,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/niri.py",
"chars": 1998,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.desktops import SeatAccess\nfrom archinstall.default_profi"
},
{
"path": "archinstall/default_profiles/desktops/plasma.py",
"chars": 559,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/qtile.py",
"chars": 476,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/river.py",
"chars": 500,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/sway.py",
"chars": 2011,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.desktops import SeatAccess\nfrom archinstall.default_profi"
},
{
"path": "archinstall/default_profiles/desktops/xfce4.py",
"chars": 526,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/desktops/xmonad.py",
"chars": 528,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, ProfileType\nfrom archinstall."
},
{
"path": "archinstall/default_profiles/minimal.py",
"chars": 194,
"preview": "from archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass MinimalProfile(Profile):\n\tdef __init__(sel"
},
{
"path": "archinstall/default_profiles/profile.py",
"chars": 5016,
"preview": "from __future__ import annotations\n\nfrom enum import Enum, auto\nfrom typing import TYPE_CHECKING, Self\n\nfrom archinstall"
},
{
"path": "archinstall/default_profiles/server.py",
"chars": 2394,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, Self, override\n\nfrom archinstall.default_profiles."
},
{
"path": "archinstall/default_profiles/servers/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/default_profiles/servers/cockpit.py",
"chars": 414,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass CockpitProfil"
},
{
"path": "archinstall/default_profiles/servers/docker.py",
"chars": 726,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, override\n\nfrom archinstall.default_profiles.profil"
},
{
"path": "archinstall/default_profiles/servers/httpd.py",
"chars": 375,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass HttpdProfile("
},
{
"path": "archinstall/default_profiles/servers/lighttpd.py",
"chars": 386,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass LighttpdProfi"
},
{
"path": "archinstall/default_profiles/servers/mariadb.py",
"chars": 679,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, override\n\nfrom archinstall.default_profiles.profil"
},
{
"path": "archinstall/default_profiles/servers/nginx.py",
"chars": 374,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass NginxProfile("
},
{
"path": "archinstall/default_profiles/servers/postgresql.py",
"chars": 671,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING, override\n\nfrom archinstall.default_profiles.profil"
},
{
"path": "archinstall/default_profiles/servers/sshd.py",
"chars": 373,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass SshdProfile(P"
},
{
"path": "archinstall/default_profiles/servers/tomcat.py",
"chars": 382,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\n\n\nclass TomcatProfile"
},
{
"path": "archinstall/default_profiles/xorg.py",
"chars": 637,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import Profile, ProfileType\nfrom archinstall.lib."
},
{
"path": "archinstall/lib/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/applications/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/applications/application_handler.py",
"chars": 1489,
"preview": "from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nfrom archinstall.applications.audio import AudioAp"
},
{
"path": "archinstall/lib/applications/application_menu.py",
"chars": 5971,
"preview": "from typing import override\n\nfrom archinstall.lib.hardware import SysInfo\nfrom archinstall.lib.menu.abstract_menu import"
},
{
"path": "archinstall/lib/args.py",
"chars": 17048,
"preview": "import argparse\nimport json\nimport os\nimport sys\nimport urllib.error\nimport urllib.parse\nfrom argparse import ArgumentPa"
},
{
"path": "archinstall/lib/authentication/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/authentication/authentication_handler.py",
"chars": 4041,
"preview": "from __future__ import annotations\n\nimport getpass\nfrom pathlib import Path\nfrom typing import TYPE_CHECKING\n\nfrom archi"
},
{
"path": "archinstall/lib/authentication/authentication_menu.py",
"chars": 4123,
"preview": "from typing import override\n\nfrom archinstall.lib.disk.fido import Fido2\nfrom archinstall.lib.menu.abstract_menu import "
},
{
"path": "archinstall/lib/boot.py",
"chars": 3837,
"preview": "import time\nfrom collections.abc import Iterator\nfrom pathlib import Path\nfrom types import TracebackType\nfrom typing im"
},
{
"path": "archinstall/lib/bootloader/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/bootloader/bootloader_menu.py",
"chars": 6578,
"preview": "import textwrap\nfrom typing import override\n\nfrom archinstall.lib.menu.abstract_menu import AbstractSubMenu\nfrom archins"
},
{
"path": "archinstall/lib/command.py",
"chars": 10616,
"preview": "import os\nimport shlex\nimport stat\nimport subprocess\nimport sys\nimport time\nfrom collections.abc import Iterator\nfrom se"
},
{
"path": "archinstall/lib/configuration.py",
"chars": 6194,
"preview": "import json\nimport readline\nimport stat\nfrom pathlib import Path\nfrom typing import Any\n\nfrom pydantic import TypeAdapte"
},
{
"path": "archinstall/lib/crypt.py",
"chars": 3150,
"preview": "import base64\nimport ctypes\nimport os\nfrom pathlib import Path\n\nfrom cryptography.fernet import Fernet, InvalidToken\nfro"
},
{
"path": "archinstall/lib/disk/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/disk/device_handler.py",
"chars": 18579,
"preview": "import logging\nimport os\nfrom pathlib import Path\n\nfrom parted import Device, Disk, DiskException, FileSystem, Geometry,"
},
{
"path": "archinstall/lib/disk/disk_menu.py",
"chars": 8991,
"preview": "from dataclasses import dataclass\nfrom typing import override\n\nfrom archinstall.lib.disk.encryption_menu import DiskEncr"
},
{
"path": "archinstall/lib/disk/encryption_menu.py",
"chars": 11279,
"preview": "from pathlib import Path\nfrom typing import override\n\nfrom archinstall.lib.disk.fido import Fido2\nfrom archinstall.lib.m"
},
{
"path": "archinstall/lib/disk/fido.py",
"chars": 3843,
"preview": "import getpass\nfrom pathlib import Path\nfrom typing import ClassVar\n\nfrom archinstall.lib.command import SysCommand, Sys"
},
{
"path": "archinstall/lib/disk/filesystem.py",
"chars": 9913,
"preview": "import math\nimport time\nfrom pathlib import Path\n\nfrom archinstall.lib.disk.device_handler import device_handler\nfrom ar"
},
{
"path": "archinstall/lib/disk/lvm.py",
"chars": 5224,
"preview": "import json\nimport time\nfrom collections.abc import Iterable\nfrom pathlib import Path\nfrom typing import Literal, overlo"
},
{
"path": "archinstall/lib/disk/partitioning_menu.py",
"chars": 18900,
"preview": "import re\nfrom pathlib import Path\nfrom typing import override\n\nfrom archinstall.lib.disk.subvolume_menu import Subvolum"
},
{
"path": "archinstall/lib/disk/subvolume_menu.py",
"chars": 2808,
"preview": "from pathlib import Path\nfrom typing import assert_never, override\n\nfrom archinstall.lib.menu.helpers import Input\nfrom "
},
{
"path": "archinstall/lib/disk/utils.py",
"chars": 4830,
"preview": "from pathlib import Path\n\nfrom pydantic import BaseModel\n\nfrom archinstall.lib.command import SysCommand\nfrom archinstal"
},
{
"path": "archinstall/lib/exceptions.py",
"chars": 644,
"preview": "class RequirementError(Exception):\n\tpass\n\n\nclass DiskError(Exception):\n\tpass\n\n\nclass UnknownFilesystemFormat(Exception):"
},
{
"path": "archinstall/lib/global_menu.py",
"chars": 19149,
"preview": "from typing import override\n\nfrom archinstall.lib.applications.application_menu import ApplicationMenu\nfrom archinstall."
},
{
"path": "archinstall/lib/hardware.py",
"chars": 8298,
"preview": "import os\nfrom enum import Enum\nfrom functools import cached_property\nfrom pathlib import Path\nfrom typing import Self\n\n"
},
{
"path": "archinstall/lib/installer.py",
"chars": 69892,
"preview": "import glob\nimport os\nimport platform\nimport re\nimport shlex\nimport shutil\nimport stat\nimport subprocess\nimport textwrap"
},
{
"path": "archinstall/lib/interactions/__init__.py",
"chars": 841,
"preview": "from archinstall.lib.interactions.disk_conf import (\n\tget_default_partition_layout,\n\tselect_devices,\n\tselect_disk_config"
},
{
"path": "archinstall/lib/interactions/disk_conf.py",
"chars": 17781,
"preview": "from pathlib import Path\n\nfrom archinstall.lib.disk.device_handler import device_handler\nfrom archinstall.lib.disk.parti"
},
{
"path": "archinstall/lib/interactions/general_conf.py",
"chars": 5915,
"preview": "from enum import Enum\nfrom pathlib import Path\n\nfrom archinstall.lib.locale.utils import list_timezones\nfrom archinstall"
},
{
"path": "archinstall/lib/interactions/system_conf.py",
"chars": 4530,
"preview": "from typing import assert_never\n\nfrom archinstall.lib.hardware import GfxDriver, SysInfo\nfrom archinstall.lib.menu.helpe"
},
{
"path": "archinstall/lib/locale/__init__.py",
"chars": 390,
"preview": "from archinstall.lib.locale.utils import (\n\tlist_keyboard_languages,\n\tlist_locales,\n\tlist_timezones,\n\tlist_x11_keyboard_"
},
{
"path": "archinstall/lib/locale/locale_menu.py",
"chars": 3762,
"preview": "from typing import override\n\nfrom archinstall.lib.locale.utils import list_keyboard_languages, list_locales, set_kb_layo"
},
{
"path": "archinstall/lib/locale/utils.py",
"chars": 2325,
"preview": "from archinstall.lib.command import SysCommand\nfrom archinstall.lib.exceptions import ServiceException, SysCallError\nfro"
},
{
"path": "archinstall/lib/luks.py",
"chars": 6840,
"preview": "import shlex\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom subprocess import CalledProcessError\nfrom t"
},
{
"path": "archinstall/lib/menu/__init__.py",
"chars": 203,
"preview": "from archinstall.lib.menu.abstract_menu import AbstractMenu, AbstractSubMenu\nfrom archinstall.lib.menu.list_manager impo"
},
{
"path": "archinstall/lib/menu/abstract_menu.py",
"chars": 4449,
"preview": "from enum import Enum\nfrom types import TracebackType\nfrom typing import Any, Self, override\n\nfrom archinstall.lib.menu."
},
{
"path": "archinstall/lib/menu/helpers.py",
"chars": 6808,
"preview": "from collections.abc import Awaitable, Callable\nfrom typing import Any, Literal, override\n\nfrom textual.validation impor"
},
{
"path": "archinstall/lib/menu/list_manager.py",
"chars": 3948,
"preview": "import copy\nfrom typing import cast\n\nfrom archinstall.lib.menu.helpers import Selection\nfrom archinstall.lib.menu.menu_h"
},
{
"path": "archinstall/lib/menu/menu_helper.py",
"chars": 1251,
"preview": "from archinstall.lib.output import FormattedOutput\nfrom archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup\n\n\ncl"
},
{
"path": "archinstall/lib/menu/util.py",
"chars": 3517,
"preview": "import sys\nimport time\nfrom pathlib import Path\n\nfrom archinstall.lib.menu.helpers import Confirmation, Input\nfrom archi"
},
{
"path": "archinstall/lib/mirror/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/mirror/mirror_handler.py",
"chars": 5465,
"preview": "import time\nimport urllib\nfrom pathlib import Path\n\nfrom archinstall.lib.models import MirrorRegion\nfrom archinstall.lib"
},
{
"path": "archinstall/lib/mirror/mirror_menu.py",
"chars": 10466,
"preview": "from typing import override\n\nfrom archinstall.lib.menu.abstract_menu import AbstractSubMenu\nfrom archinstall.lib.menu.he"
},
{
"path": "archinstall/lib/models/__init__.py",
"chars": 1998,
"preview": "from archinstall.lib.models.application import ApplicationConfiguration, Audio, AudioConfiguration, BluetoothConfigurati"
},
{
"path": "archinstall/lib/models/application.py",
"chars": 5056,
"preview": "from dataclasses import dataclass\nfrom enum import StrEnum, auto\nfrom typing import Any, NotRequired, Self, TypedDict\n\n\n"
},
{
"path": "archinstall/lib/models/authentication.py",
"chars": 2232,
"preview": "from dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import Any, NotRequired, Self, TypedDict\n\nfro"
},
{
"path": "archinstall/lib/models/bootloader.py",
"chars": 2651,
"preview": "import sys\nfrom dataclasses import dataclass\nfrom enum import Enum\nfrom typing import Any, Self\n\nfrom archinstall.lib.ou"
},
{
"path": "archinstall/lib/models/device.py",
"chars": 42837,
"preview": "from __future__ import annotations\n\nimport builtins\nimport math\nimport uuid\nfrom dataclasses import dataclass, field\nfro"
},
{
"path": "archinstall/lib/models/locale.py",
"chars": 1255,
"preview": "from dataclasses import dataclass\nfrom typing import Any, Self\n\nfrom archinstall.lib.locale.utils import get_kb_layout\nf"
},
{
"path": "archinstall/lib/models/mirrors.py",
"chars": 8890,
"preview": "from __future__ import annotations\n\nimport datetime\nimport http.client\nimport urllib.error\nimport urllib.parse\nimport ur"
},
{
"path": "archinstall/lib/models/network.py",
"chars": 5116,
"preview": "import re\nfrom dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import NotRequired, Self, TypedDict"
},
{
"path": "archinstall/lib/models/packages.py",
"chars": 3551,
"preview": "from dataclasses import dataclass, field\nfrom enum import Enum\nfrom functools import cached_property\nfrom typing import "
},
{
"path": "archinstall/lib/models/profile.py",
"chars": 1363,
"preview": "from __future__ import annotations\n\nfrom dataclasses import dataclass\nfrom typing import TYPE_CHECKING, Self, TypedDict\n"
},
{
"path": "archinstall/lib/models/users.py",
"chars": 5097,
"preview": "from dataclasses import dataclass, field\nfrom enum import Enum\nfrom typing import NotRequired, Self, TypedDict, override"
},
{
"path": "archinstall/lib/network/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/network/network_handler.py",
"chars": 1592,
"preview": "from archinstall.lib.installer import Installer\nfrom archinstall.lib.models.network import NetworkConfiguration, NicType"
},
{
"path": "archinstall/lib/network/network_menu.py",
"chars": 5804,
"preview": "import ipaddress\nfrom typing import assert_never, override\n\nfrom archinstall.lib.menu.helpers import Input, Selection\nfr"
},
{
"path": "archinstall/lib/network/wifi_handler.py",
"chars": 7486,
"preview": "from asyncio import sleep\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typing import assert_never, ov"
},
{
"path": "archinstall/lib/network/wpa_supplicant.py",
"chars": 3348,
"preview": "from dataclasses import dataclass, field\nfrom pathlib import Path\n\nfrom archinstall.lib.models.network import WifiNetwor"
},
{
"path": "archinstall/lib/networking.py",
"chars": 5772,
"preview": "import os\nimport random\nimport select\nimport signal\nimport socket\nimport ssl\nimport struct\nimport time\nfrom types import"
},
{
"path": "archinstall/lib/output.py",
"chars": 8641,
"preview": "import logging\nimport os\nimport sys\nfrom collections.abc import Callable\nfrom dataclasses import asdict, is_dataclass\nfr"
},
{
"path": "archinstall/lib/packages/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/packages/packages.py",
"chars": 4632,
"preview": "from functools import lru_cache\n\nfrom archinstall.lib.exceptions import SysCallError\nfrom archinstall.lib.menu.helpers i"
},
{
"path": "archinstall/lib/packages/util.py",
"chars": 439,
"preview": "from functools import lru_cache\n\nfrom archinstall.lib.output import debug\nfrom archinstall.lib.packages.packages import "
},
{
"path": "archinstall/lib/pacman/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/pacman/config.py",
"chars": 1719,
"preview": "import re\nfrom pathlib import Path\nfrom shutil import copy2\n\nfrom archinstall.lib.models.packages import Repository\n\n\ncl"
},
{
"path": "archinstall/lib/pacman/pacman.py",
"chars": 2526,
"preview": "import sys\nimport time\nfrom collections.abc import Callable\nfrom pathlib import Path\n\nfrom archinstall.lib.command impor"
},
{
"path": "archinstall/lib/plugins.py",
"chars": 3625,
"preview": "import hashlib\nimport importlib.util\nimport os\nimport sys\nimport urllib.parse\nimport urllib.request\nfrom importlib impor"
},
{
"path": "archinstall/lib/profile/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/profile/profile_menu.py",
"chars": 6911,
"preview": "from typing import override\n\nfrom archinstall.default_profiles.profile import GreeterType, Profile\nfrom archinstall.lib."
},
{
"path": "archinstall/lib/profile/profiles_handler.py",
"chars": 11468,
"preview": "from __future__ import annotations\n\nimport importlib.util\nimport inspect\nimport sys\nfrom collections import Counter\nfrom"
},
{
"path": "archinstall/lib/translationhandler.py",
"chars": 5311,
"preview": "import builtins\nimport gettext\nimport json\nimport os\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typ"
},
{
"path": "archinstall/lib/user/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/user/user_menu.py",
"chars": 3368,
"preview": "import re\nfrom typing import override\n\nfrom archinstall.lib.menu.helpers import Confirmation, Input\nfrom archinstall.lib"
},
{
"path": "archinstall/lib/utils/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/lib/utils/encoding.py",
"chars": 1525,
"preview": "import re\nimport unicodedata\nfrom functools import lru_cache\n\n# https://stackoverflow.com/a/43627833/929999\n_VT100_ESCAP"
},
{
"path": "archinstall/lib/utils/util.py",
"chars": 1210,
"preview": "import secrets\nimport string\nfrom pathlib import Path\n\nfrom archinstall.lib.output import FormattedOutput\n\n\ndef running_"
},
{
"path": "archinstall/lib/version.py",
"chars": 165,
"preview": "from importlib.metadata import version\n\n\ndef get_version() -> str:\n\ttry:\n\t\treturn version('archinstall')\n\texcept Excepti"
},
{
"path": "archinstall/locales/README.md",
"chars": 3026,
"preview": "# Nationalization\n\nArchinstall supports multiple languages, which depend on translations coming from the community :)\n\n#"
},
{
"path": "archinstall/locales/ar/LC_MESSAGES/base.po",
"chars": 51835,
"preview": "# Header entry was created by Lokalize.\n#\n# zer0-x, 2022.\n# SPDX-FileCopyrightText: 2024 Omar TS <ots@duck.com>\nmsgid \"\""
},
{
"path": "archinstall/locales/base.pot",
"chars": 35340,
"preview": "msgid \"\"\nmsgstr \"\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\""
},
{
"path": "archinstall/locales/ca/LC_MESSAGES/base.po",
"chars": 57649,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/cs/LC_MESSAGES/base.po",
"chars": 55195,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Martin Kozá"
},
{
"path": "archinstall/locales/de/LC_MESSAGES/base.po",
"chars": 58798,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/el/LC_MESSAGES/base.po",
"chars": 54880,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/en/LC_MESSAGES/base.po",
"chars": 33135,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/es/LC_MESSAGES/base.po",
"chars": 61814,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: esbendev <b"
},
{
"path": "archinstall/locales/et/LC_MESSAGES/base.po",
"chars": 53873,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/fi/LC_MESSAGES/base.po",
"chars": 53404,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Aleksi Puha"
},
{
"path": "archinstall/locales/fr/LC_MESSAGES/base.po",
"chars": 59015,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: 2025-04-11 23:02+0200\\n\"\n\"Last-Tr"
},
{
"path": "archinstall/locales/ga/LC_MESSAGES/base.po",
"chars": 56245,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Aindriú Mac"
},
{
"path": "archinstall/locales/gl/LC_MESSAGES/base.po",
"chars": 61544,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: gaelgnz <ga"
},
{
"path": "archinstall/locales/he/LC_MESSAGES/base.po",
"chars": 49638,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Yaron Shahr"
},
{
"path": "archinstall/locales/hi/LC_MESSAGES/base.po",
"chars": 56540,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Atharv <ath"
},
{
"path": "archinstall/locales/hu/LC_MESSAGES/base.po",
"chars": 59087,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: summoner <s"
},
{
"path": "archinstall/locales/id/LC_MESSAGES/base.po",
"chars": 51747,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Ali Rohman "
},
{
"path": "archinstall/locales/it/LC_MESSAGES/base.po",
"chars": 60931,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: 2026-01-20 19:23+0100\\n\"\n\"Last-Tr"
},
{
"path": "archinstall/locales/ja/LC_MESSAGES/base.po",
"chars": 47663,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: UTUMI Hiros"
},
{
"path": "archinstall/locales/ka/LC_MESSAGES/base.po",
"chars": 55324,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: archinstall\\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: "
},
{
"path": "archinstall/locales/ko/LC_MESSAGES/base.po",
"chars": 43023,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: An Jaebeom "
},
{
"path": "archinstall/locales/ku/LC_MESSAGES/base.po",
"chars": 56428,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/languages.json",
"chars": 7714,
"preview": "[{\"abbr\": \"aa\", \"lang\": \"Afar\"},\n {\"abbr\": \"ab\", \"lang\": \"Abkhazian\"},\n {\"abbr\": \"af\", \"lang\": \"Afrikaans\"},\n {\"abbr\": \""
},
{
"path": "archinstall/locales/locales_generator.sh",
"chars": 1031,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\ncd $(dirname \"$0\")/..\n\nfunction update_lang() {\n\tfile=${1}\n\n\techo \"Updating: ${fi"
},
{
"path": "archinstall/locales/lt/LC_MESSAGES/base.po",
"chars": 36253,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Florijan De"
},
{
"path": "archinstall/locales/ne/LC_MESSAGES/base.po",
"chars": 48926,
"preview": "msgid \"\"\nmsgstr \"\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\""
},
{
"path": "archinstall/locales/nl/LC_MESSAGES/base.po",
"chars": 50378,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Heimen Stof"
},
{
"path": "archinstall/locales/pl/LC_MESSAGES/base.po",
"chars": 55882,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: acuteenvy\\n"
},
{
"path": "archinstall/locales/pt/LC_MESSAGES/base.po",
"chars": 57178,
"preview": "# Translators:\n# Hugo Carvalho <hugokarvalho@hotmail.com>\n# Luis Antonio <github.com/zaorinu>\nmsgid \"\"\nmsgstr \"\"\n\"Projec"
},
{
"path": "archinstall/locales/pt_BR/LC_MESSAGES/base.po",
"chars": 60956,
"preview": "# Translators:\n# @Cain-dev (cain-dev.github.io)\n# Rafael Fontenelle <rafaelff@gnome.org>\n# Jefferson Michael <github."
},
{
"path": "archinstall/locales/ro/LC_MESSAGES/base.po",
"chars": 55866,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: andrewKode "
},
{
"path": "archinstall/locales/ru/LC_MESSAGES/base.po",
"chars": 55873,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Aleksandr M"
},
{
"path": "archinstall/locales/sv/LC_MESSAGES/base.po",
"chars": 55945,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: \\n\"\n\"Langua"
},
{
"path": "archinstall/locales/ta/LC_MESSAGES/base.po",
"chars": 57714,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: K.B.Dharun "
},
{
"path": "archinstall/locales/tr/LC_MESSAGES/base.po",
"chars": 60604,
"preview": "# Please do not completely remove previous translator information from Language-Team.\n# If you are the last translator, "
},
{
"path": "archinstall/locales/uk/LC_MESSAGES/base.po",
"chars": 57065,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: TSEPLNK\\n\"\n"
},
{
"path": "archinstall/locales/ur/LC_MESSAGES/base.po",
"chars": 59041,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: Hannan Jave"
},
{
"path": "archinstall/locales/uz/LC_MESSAGES/base.po",
"chars": 54181,
"preview": "# O'zbek tili tarjimasi - Arch Install\n# Copyright (C) 2025 Arch Install Contributors\n# This file is distributed under t"
},
{
"path": "archinstall/locales/zh-CN/LC_MESSAGES/base.po",
"chars": 36791,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-Date: \\n\"\n\"PO-Revision-Date: \\n\"\n\"Last-Translator: clsty <cele"
},
{
"path": "archinstall/locales/zh-TW/LC_MESSAGES/base.po",
"chars": 38148,
"preview": "# SPDX-FileCopyrightText: 2025 neko0xff <chzang55@gmail.com>\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: \\n\"\n\"POT-Creation-D"
},
{
"path": "archinstall/main.py",
"chars": 4585,
"preview": "# Arch Linux installer - guided, templates etc.\n\nimport importlib\nimport os\nimport sys\nimport textwrap\nimport time\nimpor"
},
{
"path": "archinstall/scripts/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/scripts/guided.py",
"chars": 8229,
"preview": "import os\nimport sys\nimport time\n\nfrom archinstall.lib.applications.application_handler import ApplicationHandler\nfrom a"
},
{
"path": "archinstall/scripts/minimal.py",
"chars": 3342,
"preview": "from archinstall.default_profiles.minimal import MinimalProfile\nfrom archinstall.lib.args import ArchConfigHandler\nfrom "
},
{
"path": "archinstall/scripts/only_hd.py",
"chars": 3115,
"preview": "import sys\nfrom pathlib import Path\n\nfrom archinstall.lib.args import ArchConfig, ArchConfigHandler\nfrom archinstall.lib"
},
{
"path": "archinstall/tui/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "archinstall/tui/curses_menu.py",
"chars": 35158,
"preview": "from __future__ import annotations\n\nimport curses\nimport os\nimport signal\nimport sys\nfrom abc import ABCMeta, abstractme"
}
]
// ... and 91 more files (download for full content)
About this extraction
This page contains the full source code of the archlinux/archinstall GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 291 files (2.7 MB), approximately 719.1k tokens, and a symbol index with 1638 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.