Start Kitty in Fish and fix boot and module restoration after QEMU checks
All checks were successful
Check and mirror to GitHub / checks (push) Successful in 20s
Check and mirror to GitHub / github-mirror (push) Successful in 7s

This commit is contained in:
Fi3w0 2026-10-04 19:34:31 +02:00
parent 52d4e90883
commit ba98cf48a7
15 changed files with 159 additions and 42 deletions

View file

@ -24,9 +24,9 @@ My personal Gentoo restoration kit, mainly for my own devices:
- Binaries preferred, with a small deliberate source-build list. - Binaries preferred, with a small deliberate source-build list.
- A Bubble Tea chooser with a final preview, conflict prompts and backups. - A Bubble Tea chooser with a final preview, conflict prompts and backups.
The Stock preset has been installed in a fresh Gentoo QEMU/KVM guest: packages, Stock and Fiw's Ryzen have been installed and checked in Gentoo QEMU/KVM.
config restoration and Plasma Login Manager login passed. Custom kernels, The full TUI restore, KDE presets, optional apps, GRUB/Limine and ext4/Btrfs
automatic bootloader deployment and optional setups still need full runtime checks. booting passed. See [tested scope and hardware limits](docs/setup.md#current-scope).
## Screenshots ## Screenshots

View file

@ -61,9 +61,10 @@
"label": "Kitty lavender profiles", "label": "Kitty lavender profiles",
"group": "fiw-apps", "group": "fiw-apps",
"packages": [ "packages": [
"x11-terms/kitty" "x11-terms/kitty",
"app-shells/fish"
], ],
"note": "Select fonts separately for the bundled JetBrainsMono Nerd Font." "note": "Both profiles start Fish. Select fonts separately for the bundled JetBrainsMono Nerd Font."
}, },
"neovim": { "neovim": {
"label": "Neovim transparent purple style", "label": "Neovim transparent purple style",

View file

@ -5,6 +5,7 @@ italic_font auto
bold_italic_font auto bold_italic_font auto
font_size 11.0 font_size 11.0
shell fish
linux_display_server auto linux_display_server auto
background_blur 32 background_blur 32
dynamic_background_opacity yes dynamic_background_opacity yes

View file

@ -43,6 +43,10 @@ packages again, including requirements of apps whose installation was skipped.
Fish, Kitty, Neovim and Fastfetch have no Plasma or KWin requirements. Fonts Fish, Kitty, Neovim and Fastfetch have no Plasma or KWin requirements. Fonts
have their own checkbox; Kitty can use its fallback font if those are omitted. have their own checkbox; Kitty can use its fallback font if those are omitted.
Both Kitty profiles start Fish explicitly, so the Kitty preset requires Fish
even when the optional Fish preferences are unchecked.
For Fish in TTY and SSH logins too, run `chsh -s "$(command -v fish)"` as your
regular user after installing Fish, then log in again.
Neovim's config includes a pinned Catppuccin runtime in its native package Neovim's config includes a pinned Catppuccin runtime in its native package
directory and loads it before the captured purple highlights. It needs no directory and loads it before the captured purple highlights. It needs no
plugin manager or runtime download. A built-in fallback remains available if plugin manager or runtime download. A built-in fallback remains available if

View file

@ -55,6 +55,11 @@ is generated before replacing it. If the previous menu was edited locally,
the new menu becomes a `.new` proposal. Existing `/etc/default/grub` settings the new menu becomes a `.new` proposal. Existing `/etc/default/grub` settings
are used by `grub-mkconfig`. are used by `grub-mkconfig`.
Explicit deployment asks before replacing a conflicting GRUB menu or Limine
managed block, with a backup. Keeping it writes a proposal and leaves firmware
registration and order unchanged. Automatic kernel refreshes preserve edits
without prompting; review their proposals before using the new entries.
## Kernel updates and backups ## Kernel updates and backups
Deployment installs a standalone refresh helper at Deployment installs a standalone refresh helper at
@ -72,9 +77,11 @@ live under `/var/lib/Fiw-Gentoo-Dots`. No existing disk partition is formatted.
Automatic deployment currently supports amd64 UEFI, GPT ESPs, plain ext4/Btrfs Automatic deployment currently supports amd64 UEFI, GPT ESPs, plain ext4/Btrfs
roots and unsigned boot. Encrypted, UKI-only, BIOS and signing workflows can roots and unsigned boot. Encrypted, UKI-only, BIOS and signing workflows can
keep their existing loader. Secure Boot being active stops unsigned deployment keep their existing loader. Secure Boot being active stops unsigned deployment
before changes. A fresh ext4 QEMU/KVM guest booted the binary kernel with a before changes. Automatic GRUB and Limine deployment and booting were checked
separately provisioned UEFI GRUB loader. The automatic deployment and kernel in Gentoo QEMU/KVM with ext4 and a Btrfs `@` root. The custom Ryzen kernel and
update hooks described here still need end-to-end boot checks. binary fallback booted, and addition/removal hooks and preservation of edited
menus were checked. Physical firmware and unsupported storage layouts still
need their own setup.
`optional/fiw-cachy-patch` refreshes the custom kernel patch; it does not select `optional/fiw-cachy-patch` refreshes the custom kernel patch; it does not select
a bootloader. See the [helper list](scripts.md) before using it. a bootloader. See the [helper list](scripts.md) before using it.

View file

@ -8,6 +8,7 @@ The report includes:
- Completed, partial, failed, cancelled and not attempted steps. - Completed, partial, failed, cancelled and not attempted steps.
- Confirmed present Portage packages and skipped or missing packages. - Confirmed present Portage packages and skipped or missing packages.
- NVIDIA module checks/builds for a selected custom kernel and binary fallback.
- Installed, existing, skipped or failed user Flatpaks. - Installed, existing, skipped or failed user Flatpaks.
- Enabled, missing or skipped service units. - Enabled, missing or skipped service units.
- Applied configs, preserved conflicts and pending `.new` proposals. - Applied configs, preserved conflicts and pending `.new` proposals.

View file

@ -69,6 +69,10 @@ Binary packages retain the binhost's USE settings; required dependency flags
are still checked. The preview includes dependency updates and replacements, are still checked. The preview includes dependency updates and replacements,
such as adding Steam's 32-bit libraries to a fresh multilib installation. such as adding Steam's 32-bit libraries to a fresh multilib installation.
Custom kernel installs with NVIDIA also check its modules against the selected
custom kernel and binary fallback. Missing or outdated modules are compiled
for each, and failures appear in the package report.
Read-only resolution and an export are available separately: Read-only resolution and an export are available separately:
```sh ```sh
@ -144,14 +148,19 @@ or Btrfs roots, and unsigned boot. See [boot setup](boot.md) for previews,
firmware choices and kernel update integration. Other layouts can keep their firmware choices and kernel update integration. Other layouts can keep their
existing loader. existing loader.
The optional [TideWM recipe](tidewm.md) follows the audited upstream master Gentoo QEMU/KVM checks covered a fresh Stock installation, Fiw's Ryzen custom
branch and uses the normal compile-or-skip prompt. The Stock package installation completed in a fresh ext4 Gentoo QEMU/KVM guest kernel and binary fallback, all package sections, the complete TUI restore,
(539 package steps, no missing selected packages). Config restoration, conflict all 16 config presets, capture filtering, preserved edits, proposals and backups.
handling, backups, the bundled chooser and Plasma Login Manager login were Plasma Login Manager, KDE/GTK styling, shortcuts, optional autostart, service
checked there, along with portable terminal configs and optional service enabling. enabling and both user Flatpaks were checked. GRUB and Limine booted ext4 and
The guest booted a binary kernel using a separately provisioned UEFI GRUB loader. a Btrfs `@` root; kernel addition/removal hooks and menu conflicts were checked.
Automatic bootloader deployment, custom Ryzen kernel builds, Btrfs, TideWM, The Btrfs guest used a converted copy of the installed ext4 guest.
optional Flatpak installation and physical GPU behaviour remain unverified.
App checks cover launches and local configuration, including MangoHud,
GameMode, FiwNode audio and Apdatifier. [TideWM](tidewm.md) compiled and ran
with virtual graphics. NVIDIA modules were built and checked for both selected
kernels. Physical NVIDIA rendering, Wi-Fi/Bluetooth devices, real audio hardware,
account sign-ins and gameplay still need checks on the target device.
Do not publish the private original fiw-gentoo archive. It has different Do not publish the private original fiw-gentoo archive. It has different
history and host-specific files. history and host-specific files.

View file

@ -19,8 +19,11 @@ is enabled by default, including the session-specific portal files.
This is a source build. The main installer shows it as an additional This is a source build. The main installer shows it as an additional
compile-or-skip choice; it is not part of the deliberately small source list. compile-or-skip choice; it is not part of the deliberately small source list.
A live recipe follows future upstream changes, while the current audit SHA A live recipe follows future upstream changes, while the current audit SHA
documents the version reviewed for this snapshot. Compilation of the documents the version reviewed for this snapshot. That commit compiled and
refreshed tree on a fresh device remains unverified. ran in the Gentoo QEMU/KVM guest, both nested inside Plasma and directly from
a TTY with virtual graphics. Kitty started Fish with the restored terminal
preferences in both sessions. Physical GPU and screencasting behaviour remain
device-specific checks.
After installation, choose **TideWM** at login. It creates its own default After installation, choose **TideWM** at login. It creates its own default
configuration on first launch. No existing TideWM settings are captured or configuration on first launch. No existing TideWM settings are captured or

View file

@ -10,6 +10,7 @@ import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
import tempfile
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
@ -229,7 +230,35 @@ def write(path, content, backups, mode=0o644):
tmp.replace(path) tmp.replace(path)
def refresh(saved, backups, exclude=None): def grub_config(output, images, exclude=None):
env = dict(os.environ, GRUB_TOP_LEVEL=images[0]['kernel'])
command = ['grub-mkconfig', '-o', str(output)]
if not exclude:
subprocess.run(command, env=env, check=True)
return
# Removal hooks can run before the kernel file disappears. Filter discovery
# through GRUB's library override, without moving installed boot artifacts.
library = Path('/usr/share/grub')
source = (library / 'grub-mkconfig_lib').read_text()
source, count = re.subn(r'\bgrub_file_is_not_garbage\s*\(\s*\)',
'fiw_dots_file_is_not_garbage ()', source, count=1)
if count != 1:
raise RuntimeError('Cannot filter this GRUB library; preserving the boot menu.')
paths = ['/boot/kernel-' + exclude] + [prefix + exclude for prefix in
('/boot/vmlinuz-', '/vmlinuz-', '/boot/vmlinux-', '/vmlinux-')]
source += '\ngrub_file_is_not_garbage () {\n case "$1" in\n ' + '|'.join(
shlex.quote(path) for path in paths) + ') return 1 ;;\n esac\n fiw_dots_file_is_not_garbage "$@"\n}\n'
with tempfile.TemporaryDirectory(prefix='fiw-dots-grub-') as directory:
root = Path(directory)
for path in library.iterdir():
if path.name != 'grub-mkconfig_lib':
(root / path.name).symlink_to(path)
(root / 'grub-mkconfig_lib').write_text(source)
subprocess.run(command, env=dict(env, pkgdatadir=directory), check=True)
def refresh(saved, backups, exclude=None, ask=None):
saved.pop('pending_config', None)
# Recheck the mount every time; never write into an unmounted ESP directory. # Recheck the mount every time; never write into an unmounted ESP directory.
target = discover_esp(Path(saved['esp'])) target = discover_esp(Path(saved['esp']))
images = kernel_images(exclude=exclude) images = kernel_images(exclude=exclude)
@ -246,7 +275,10 @@ def refresh(saved, backups, exclude=None):
config = GRUB_DIRECTORY / 'grub/grub.cfg' config = GRUB_DIRECTORY / 'grub/grub.cfg'
old_hash = file_hash(config) old_hash = file_hash(config)
output = config output = config
if old_hash and old_hash != saved.get('config_hash'): edited = old_hash and old_hash != saved.get('config_hash')
replace = edited and ask and ask('Existing GRUB menu differs from the saved version. Replace it with the generated menu?',
['replace', 'keep'], 'keep') == 'replace'
if edited and not replace:
output = config.with_name(config.name + '.new.' + datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ')) output = config.with_name(config.name + '.new.' + datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ'))
else: else:
backup(config, backups) backup(config, backups)
@ -264,12 +296,13 @@ def refresh(saved, backups, exclude=None):
shutil.copy2(source, dest) shutil.copy2(source, dest)
scratch = output.with_name('.' + output.name + '.tmp') scratch = output.with_name('.' + output.name + '.tmp')
try: try:
subprocess.run(['grub-mkconfig', '-o', str(scratch)], check=True) grub_config(scratch, images, exclude)
scratch.replace(output) scratch.replace(output)
finally: finally:
if scratch.exists(): if scratch.exists():
scratch.unlink() scratch.unlink()
if output != config: if output != config:
saved['pending_config'] = str(output)
print('Preserved edited GRUB config; review ' + str(output)) print('Preserved edited GRUB config; review ' + str(output))
else: else:
saved['config_hash'] = file_hash(config) saved['config_hash'] = file_hash(config)
@ -295,9 +328,13 @@ def refresh(saved, backups, exclude=None):
prior = managed_block(old) prior = managed_block(old)
block = render_limine(images, saved['cmdline']) block = render_limine(images, saved['cmdline'])
output = merge_limine(old, block) output = merge_limine(old, block)
if prior and block_hash(prior) != saved.get('block_hash'): edited = prior and block_hash(prior) != saved.get('block_hash')
replace = edited and ask and ask('Existing Limine entries differ from the saved version. Replace the managed entries?',
['replace', 'keep'], 'keep') == 'replace'
if edited and not replace:
proposal = config.with_name(config.name + '.new.' + datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ')) proposal = config.with_name(config.name + '.new.' + datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ'))
write(proposal, output, backups) write(proposal, output, backups)
saved['pending_config'] = str(proposal)
print('Preserved edited Limine entries; review ' + str(proposal)) print('Preserved edited Limine entries; review ' + str(proposal))
elif output != old: elif output != old:
write(config, output, backups) write(config, output, backups)
@ -381,7 +418,12 @@ def deploy(mode, esp=None, ask=confirm):
else: else:
subprocess.run(proposed['commands'][0], check=True) subprocess.run(proposed['commands'][0], check=True)
loader_path = '/EFI/Fiw-Gentoo/grubx64.efi' loader_path = '/EFI/Fiw-Gentoo/grubx64.efi'
saved = refresh(saved, backups) saved = refresh(saved, backups, ask=ask)
pending = saved.pop('pending_config', None)
if pending and firmware != 'keep':
commands = []
firmware = 'keep'
print('Kept the existing boot menu; firmware entries and order remain unchanged. Review ' + pending)
# Native installkernel provides versioned /boot kernel/initrd files; our # Native installkernel provides versioned /boot kernel/initrd files; our
# final hook refreshes only the chosen loader's own configuration. # final hook refreshes only the chosen loader's own configuration.
write(Path('/etc/kernel/install.conf'), proposed['installkernel_config'], backups) write(Path('/etc/kernel/install.conf'), proposed['installkernel_config'], backups)
@ -403,7 +445,8 @@ def deploy(mode, esp=None, ask=confirm):
report.write_text(json.dumps({'plan': proposed, 'firmware_choice': firmware, report.write_text(json.dumps({'plan': proposed, 'firmware_choice': firmware,
'backups': str(backups)}, indent=2) + '\n') 'backups': str(backups)}, indent=2) + '\n')
print('Boot deployment finished. Report: ' + str(report)) print('Boot deployment finished. Report: ' + str(report))
return {'status': 'completed', 'mode': mode, 'firmware_choice': firmware, return {'status': 'partial' if pending else 'completed', 'mode': mode, 'firmware_choice': firmware,
'review': [pending] if pending else [],
'report': str(report), 'backups': str(backups)} 'report': str(report), 'backups': str(backups)}
@ -422,6 +465,7 @@ def main():
stamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ') stamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S.%fZ')
backups = MANAGED / 'backups' / ('boot-refresh-' + stamp) backups = MANAGED / 'backups' / ('boot-refresh-' + stamp)
updated = refresh(saved, backups, args.exclude_version) updated = refresh(saved, backups, args.exclude_version)
updated.pop('pending_config', None)
write(STATE, json.dumps(updated, indent=2) + '\n', backups, 0o600) write(STATE, json.dumps(updated, indent=2) + '\n', backups, 0o600)

View file

@ -447,6 +447,37 @@ def resolve(stage, selection, packages, execute=False):
stderr=None if execute else subprocess.STDOUT) stderr=None if execute else subprocess.STDOUT)
def nvidia_modules():
"""Check both selected distribution kernels, not just /usr/src/linux."""
snapshot = json.loads((REPO / 'optional/kernel/snapshot.json').read_text())
driver = subprocess.check_output(['portageq', 'best_version', '/', 'x11-drivers/nvidia-drivers'], text=True).strip()
expected = re.sub(r'-r\d+$', '', driver.split('nvidia-drivers-', 1)[1])
result = {'checked': [], 'rebuilt': [], 'missing': []}
for atom in [snapshot['atom'], 'sys-kernel/gentoo-kernel-bin']:
cpv = subprocess.check_output(['portageq', 'best_version', '/', atom], text=True).strip()
contents = (Path('/var/db/pkg') / cpv / 'CONTENTS').read_text() if cpv else ''
versions = sorted(set(re.findall(r'/(?:usr/)?lib/modules/([^/ ]+)/', contents)))
if not versions:
result['missing'].append('NVIDIA kernel target: ' + atom)
for version in versions:
result['checked'].append(version)
def ready():
return all(subprocess.run(['modinfo', '-k', version, '-F', 'version', module],
text=True, capture_output=True).stdout.strip() == expected
for module in ['nvidia', 'nvidia_drm', 'nvidia_modeset', 'nvidia_uvm'])
if ready():
continue
build = Path('/lib/modules') / version / 'build'
print('Building NVIDIA modules for ' + version, flush=True)
command = ['emerge', '--oneshot', '--nodeps', '--usepkg=n', '--getbinpkg=n',
'--autounmask=n', '=' + driver]
if build.is_dir() and subprocess.run(command, env=dict(os.environ, KERNEL_DIR=str(build))).returncode == 0 and ready():
result['rebuilt'].append(version)
else:
result['missing'].append('NVIDIA modules for ' + version)
return result
def install_packages(selection): def install_packages(selection):
if os.geteuid() != 0: if os.geteuid() != 0:
raise RuntimeError('Package installation requires root. Run sudo ./install --install-packages --selection <file>.') raise RuntimeError('Package installation requires root. Run sudo ./install --install-packages --selection <file>.')
@ -504,6 +535,11 @@ def install_packages(selection):
if not accepted: if not accepted:
print('All requested packages were skipped; no live configuration applied.') print('All requested packages were skipped; no live configuration applied.')
return {'status': 'skipped', 'requested': requested, 'skipped': skipped, 'missing': requested} return {'status': 'skipped', 'requested': requested, 'skipped': skipped, 'missing': requested}
build_modules = (selection['kernel'] == 'custom' and 'system' in selection['groups']
and 'x11-drivers/nvidia-drivers' in accepted
and any(atom.startswith('=sys-kernel/gentoo-kernel-') for atom in accepted))
if build_modules:
print('NVIDIA modules will be checked and compiled when needed for the selected custom kernel and binary fallback.')
if ask('Apply the previewed Portage files and install the accepted packages?', ['apply', 'cancel'], 'cancel') != 'apply': if ask('Apply the previewed Portage files and install the accepted packages?', ['apply', 'cancel'], 'cancel') != 'apply':
return {'status': 'cancelled', 'requested': requested, 'skipped': skipped} return {'status': 'cancelled', 'requested': requested, 'skipped': skipped}
publish_repositories(fetched) publish_repositories(fetched)
@ -556,20 +592,24 @@ def install_packages(selection):
if final.returncode or ({cp_from_cpv(x) for x in source_builds(final.stdout)} - approved): if final.returncode or ({cp_from_cpv(x) for x in source_builds(final.stdout)} - approved):
raise RuntimeError('The final package plan changed. Review it before retrying; backups are at ' + str(backup_root)) raise RuntimeError('The final package plan changed. Review it before retrying; backups are at ' + str(backup_root))
result = resolve(Path('/'), selection, ['@fiw-dots-selected'], execute=True) result = resolve(Path('/'), selection, ['@fiw-dots-selected'], execute=True)
modules = nvidia_modules() if result.returncode == 0 and build_modules else {}
missing = [atom for atom in requested if subprocess.run( missing = [atom for atom in requested if subprocess.run(
['portageq', 'has_version', '/', atom], stdout=subprocess.DEVNULL, ['portageq', 'has_version', '/', atom], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL).returncode != 0] stderr=subprocess.DEVNULL).returncode != 0]
report = {'requested': requested, 'present': [atom for atom in accepted if atom not in missing], report = {'requested': requested, 'present': [atom for atom in accepted if atom not in missing],
'skipped': skipped, 'emerge_exit_code': result.returncode, 'skipped': skipped, 'emerge_exit_code': result.returncode,
'missing': missing, 'missing': missing,
'modules': modules, 'failed': modules.get('missing', []),
'pending': []} 'pending': []}
state = Path('/var/lib/Fiw-Gentoo-Dots') state = Path('/var/lib/Fiw-Gentoo-Dots')
state.mkdir(parents=True, exist_ok=True) state.mkdir(parents=True, exist_ok=True)
(state / ('packages-' + stamp + '.json')).write_text(json.dumps(report, indent=2) + '\n') (state / ('packages-' + stamp + '.json')).write_text(json.dumps(report, indent=2) + '\n')
print('Package report: ' + str(state / ('packages-' + stamp + '.json'))) print('Package report: ' + str(state / ('packages-' + stamp + '.json')))
print('Missing packages: ' + (', '.join(missing) or 'none')) print('Missing packages: ' + (', '.join(missing) or 'none'))
if result.returncode: if build_modules and result.returncode == 0:
error = RuntimeError('Some packages did not install; consult the package report and emerge output.') print('Missing NVIDIA modules: ' + (', '.join(modules.get('missing', [])) or 'none'))
if result.returncode or modules.get('missing'):
error = RuntimeError('Some packages or kernel modules did not install; consult the package report and emerge output.')
error.report = report error.report = report
raise error raise error
if 'kde' in selection['groups'] and 'kde-plasma/plasma-login-manager' not in missing: if 'kde' in selection['groups'] and 'kde-plasma/plasma-login-manager' not in missing:

View file

@ -15,9 +15,10 @@ trap 'rm -rf "$work"' EXIT
cd "$work" cd "$work"
# Newest CachyOS release for this kernel version (cachyos-7.2.8-1, -2, ...) # Newest CachyOS release for this kernel version (cachyos-7.2.8-1, -2, ...)
tag=$(curl -fsSL "https://api.github.com/repos/CachyOS/linux/releases?per_page=50" | releases=$(curl -fsSL "https://api.github.com/repos/CachyOS/linux/releases?per_page=50")
tag=$(printf '%s\n' "$releases" |
grep -oE "\"tag_name\": *\"cachyos-${ver//./\\.}-[0-9]+\"" | grep -oE "\"tag_name\": *\"cachyos-${ver//./\\.}-[0-9]+\"" |
grep -oE "cachyos-[0-9.]+-[0-9]+" | sort -V | tail -1) grep -oE "cachyos-[0-9.]+-[0-9]+" | sort -V | tail -1 || true)
[[ -n $tag ]] || { echo "CachyOS has no release for $ver yet" >&2; exit 1; } [[ -n $tag ]] || { echo "CachyOS has no release for $ver yet" >&2; exit 1; }
echo "Using $tag" echo "Using $tag"

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# SpotX-Bash + spicetify (Marketplace) on Gentoo's media-sound/spotify. # SpotX-Bash + spicetify (Marketplace) on Gentoo's media-sound/spotify.
# Run as your regular user after the first setup and after every Spotify update. # Run as your regular user after the first setup and after every Spotify update.
# Write access comes from an ACL (/etc/portage/env/media-sound/spotify). # Write access must be configured explicitly before opting in.
set -euo pipefail set -euo pipefail
client=/opt/spotify/spotify-client client=/opt/spotify/spotify-client
@ -9,7 +9,7 @@ spotx_url=https://raw.githubusercontent.com/SpotX-Official/SpotX-Bash/main/spotx
spicetify=$HOME/.spicetify/spicetify spicetify=$HOME/.spicetify/spicetify
[[ -w $client/Apps/xpui.spa && -w $client/spotify ]] || { [[ -w $client/Apps/xpui.spa && -w $client/spotify ]] || {
echo "No write access to $client. Run once as root: the optional Spotify ACL setup described in docs/spotify.md" >&2 echo "No write access to $client. Review docs/spotify.md and configure client write access explicitly before opting in." >&2
exit 1 exit 1
} }

View file

@ -1,8 +1,8 @@
llvm-core/llvm heavy.conf notmpfs.conf llvm-core/llvm fiw-dots-heavy.conf fiw-dots-notmpfs.conf
llvm-core/clang heavy.conf notmpfs.conf llvm-core/clang fiw-dots-heavy.conf fiw-dots-notmpfs.conf
dev-qt/qtwebengine heavy.conf notmpfs.conf dev-qt/qtwebengine fiw-dots-heavy.conf fiw-dots-notmpfs.conf
net-libs/nodejs heavy.conf net-libs/nodejs fiw-dots-heavy.conf
dev-lang/spidermonkey heavy.conf dev-lang/spidermonkey fiw-dots-heavy.conf
media-libs/embree heavy.conf notmpfs.conf media-libs/embree fiw-dots-heavy.conf fiw-dots-notmpfs.conf
media-gfx/blender heavy.conf notmpfs.conf media-gfx/blender fiw-dots-heavy.conf fiw-dots-notmpfs.conf
media-gfx/openvdb heavy.conf notmpfs.conf media-gfx/openvdb fiw-dots-heavy.conf fiw-dots-notmpfs.conf

View file

@ -1,2 +1,2 @@
sys-kernel/gentoo-kernel notmpfs.conf sys-kernel/gentoo-kernel fiw-dots-notmpfs.conf
sys-devel/gcc notmpfs.conf sys-devel/gcc fiw-dots-notmpfs.conf

View file

@ -183,10 +183,16 @@ def capture_fish():
def capture_kitty(): def capture_kitty():
def portable_profile(text, name):
text = re.sub(r'(?m)^linux_display_server\s+wayland\s*$',
'linux_display_server auto', text)
text = re.sub(r'(?m)^shell\s+.*\n?', '', text)
if name == 'kitty-common.conf':
text = text.rstrip() + '\n\nshell fish\n'
return text
for name in ['kitty.conf', 'kitty-main.conf', 'kitty-bright.conf', 'kitty-common.conf']: for name in ['kitty.conf', 'kitty-main.conf', 'kitty-bright.conf', 'kitty-common.conf']:
copy('kitty', '.config/kitty/' + name, copy('kitty', '.config/kitty/' + name,
lambda t: re.sub(r'(?m)^linux_display_server\s+wayland\s*$', lambda t: portable_profile(t, name))
'linux_display_server auto', t))
def capture_neovim(): def capture_neovim():