Author SHA1 Message Date
alvinlollo 1bb6f8dddd ci: install archiso via private pacman config, not /etc/pacman.conf
Tests / tests (push) Successful in 4m8s
Writing stock core/extra over the host /etc/pacman.conf raced with the
tests workflow, which appends [cachyos]/[chaotic-aur] to the same file —
runs 132 and 133 ran concurrently on the runner, so either job could
corrupt the other's config mid-pacman.

Use 'pacman --config $(mktemp)' with stock core/extra instead: same
DNS-lookup reduction (only core/extra sync, no cachyos/chaotic), zero
writes to shared state. Verified on the runner: exit 0, only core/extra
synced, host /etc/pacman.conf mtime unchanged.
2026-10-07 11:22:12 +11:00
alvinlollo 0fbec83573 ci: retry pacman syncs and reset host pacman.conf before build
Tests / tests (push) Successful in 5m7s
Run 131 failed at 'pacman -Syu archiso jq' because the gateway
(192.168.1.1) intermittently drops UDP/53: cachyos.db and chaotic-aur.db
lookups hit libalpm's 10s resolve timeout while core/extra survived on
resolved's cache.

- build-iso: reset the host /etc/pacman.conf to stock core/extra first
  (tests.yaml leaves [cachyos]/[chaotic-aur] behind, and mkarchiso reads
  the profile's pacman.conf anyway), pre-warm mirror hostnames in the
  resolver cache, then retry pacman -Syu 5x with backoff.
- tests: wrap all three pacman -Syu calls in the same retry loop.

DNS-side redundancy was added on the runner separately (networkd drop-in
adds 1.1.1.1/8.8.8.8 next to the gateway).
2026-10-07 11:14:28 +11:00
alvinlollo a6c99b72d0 fix(ci): ensure /dev/fd symlinks exist for mkinitcpio and procsub
Tests / tests (push) Successful in 2m33s
The chroot's /dev only gains fd/stdin/stdout/stderr symlinks at boot, and
container executors often lack them, which breaks mkinitcpio's preset step
(pipes through /dev/stdin) and bash process substitution
("/dev/fd/63: No such file or directory").

- build-iso workflow: create the links in the executor's /dev, then mount a
  fresh devtmpfs and create them there too so the chroot tree is covered
  whether the executor's /dev is devtmpfs or a plain tmpfs
- customize_airootfs.sh: self-heal the same links inside the chroot
2026-10-06 14:53:16 +11:00
alvinlollo c64c64dc97 feat(installer): ask GitHub username first in git screen
Tests / tests (push) Successful in 2m14s
screen_git now prompts GitHub username before git name/email, and the
screen description plus installation summary list SSH before git to
match the new prompt order. Behavior unchanged - prompts are
independent and all assignment sites are read after the screen returns.
2026-10-05 17:42:15 +11:00
alvinlollo 319333e400 fix(packages): rename syncthingtray-qt6, ship neofetch from localrepo
Tests / tests (push) Successful in 2m23s
CI package check failed on main (400/402):

- syncthingtray-qt6 no longer exists in the AUR (RPC returns nothing);
  the qt6 build is now the official 'syncthingtray' package in extra/
  cachyos - rename it in packages.x86_64 and drop the dead
  AUR_MISSING entry from build-end4-deps.sh
- neofetch left the distro repos (only chaotic-neofetch-git remains);
  build the AUR package locally (7.1.0-2, PGP-verified against Dylan
  Araps' key) and commit it to localrepo/ with a reindexed local-aur
  db so both the CI check (file glob) and pacstrap ([local-aur]) work
- un-indent the package lists in build-end4-deps.sh: CI accepts
  repo-less packages via 'grep -qxF <name>' (exact whole-line match),
  which could never match indented names

Verified locally with an exact replica of the CI check: 402/402.
2026-10-05 17:32:23 +11:00
alvinlollo bb6f64e977 feat(installer): build-stamp motd, LUKS mode A/B, TPM2, unl0kr, login managers
Tests / tests (push) Failing after 2m33s
- profiledef.sh stages airootfs/root/.iso-build-stamp (git/CI gated, falls
  back to 'commit unknown'); customize_airootfs.sh installs it as
  /etc/alvin-build-stamp; install_motd appends it to the target /etc/motd
- alvin-install: skippable git/GitHub screens with ssh-import-id import
  (yay build + python-distro, curl .keys fallback), LUKS Mode A (systemd
  sd-encrypt + rd.luks.name) vs Mode B (unl0kr + cryptdevice), TPM2
  enrollment via $PASSWORD with rd.luks.options activation, unl0kr
  build/verify with Mode-A fallback, login manager none/greetd/sddm/gdm
  (enable DM before disabling getty@tty1), autologin per DM (forced off
  when TPM enrolled), build-stamp motd; includes the existing
  GRUB_DISABLE_BOOTNEXT grub tweak
- review fixes: greetd autologin TOML quoting, .ssh chowned before
  ssh-import-id, builtin-aware initramfs module verification across all
  installed kernels, curl exit-code split (fetch failure vs no keys),
  plain Hyprland on every login path
- add curl to packages.x86_64; document stamp flow and installer in
  AGENTS.md/README.md
2026-10-05 16:26:12 +11:00
alvinlollo 3b3764573e fix(installer): resolve owner in one chroot call, log ydotool link errors
Tests / tests (push) Failing after 2m28s
Two low-severity review findings on 8501a60:

- owner="$(id -u):$(id -g)" as two substitutions only propagates the
  last status, so a lone id -u failure would build ':1000' and abort at
  the chown with "invalid owner" under the wrong line. Run both ids in
  a single arch-chroot sh -c chained with && and join with paste -sd:;
  pipefail makes any failure abort at the owner= line. Verified both
  paths: existing user yields 1000:1000, missing user trips the ERR
  trap before owner is used.
- the ydotool symlink mkdir/ln wrote stderr to the terminal while the
  failure warn pointed at $LOG, which never recorded it; redirect both
  into the log, matching the bluetooth block.
2026-10-02 17:18:40 +10:00
alvinlollo 8501a60165 fix(installer): chown target files by numeric id, not live-medium name
The end-4 step's chowns ran on the live medium, whose /etc/passwd has
no $USERNAME (the user exists only inside /mnt), so 'chown -R
alvin:alvin' failed with "invalid user" and the ERR trap aborted the
install at line 543. Resolve uid/gid once via arch-chroot id and chown
by number; the three remaining name-based chowns (fork/fish/hypr
restores) would have hit the same wall later.

Replace those three mid-function chowns with one catch-all over the
target home after the last root-side write: sed -i on the presets
rewrites through a temp file, which leaves them root-owned with no
chown after it.

systemctl --user enable ydotool.service could never work inside the
chroot (no /run/user/UID/bus exists before boot; it only ever warned
with "Failed to connect to user scope bus", so ydotool never
autostarted). Write the symlink enable would write:
~/.config/systemd/user/default.target.wants/ydotool.service ->
/usr/lib/systemd/user/ydotool.service.
2026-10-02 17:05:19 +10:00
alvinlollo 7c601ca53d ci: log HTTP status and response body on ISO upload failure
Tests / tests (push) Failing after 2m30s
`curl -f` swallowed Gitea's error response, so the 3-attempt upload
failure on the 6330 MiB ISO reported nothing diagnosable. Capture the
status code via -w, print up to 2 KB of the response body for both
HTTP-level and transport-level failures, and clear upload.json at the
start of each attempt so a stale body cannot be misreported.
2026-09-27 18:33:04 +10:00
alvinlollo f3bd10cf0f fix(iso): sweep ii-builder leftovers via NSpid before userdel
Tests / tests (push) Successful in 2m19s
end-4's ./setup sudo keepalive orphans a `sleep 60` child as ii-builder;
userdel then exits 8 and aborts the ISO build (CI exit 8).

Sweep uid-matching processes inside the build chroot before userdel,
mirroring shadow's user_busy_processes() checks (real/effective/saved
uid + root device/inode). Because arch-chroot mounts proc before
`unshare --fork --pid`, /proc entry numbers are outer-namespace pids:
signal the last NSpid field instead, require matching NSpid depth, and
surface kill errors instead of swallowing them. userdel keeps its stderr
and, on final failure, dumps the leftover process list before aborting.
2026-09-27 14:03:47 +10:00
alvinlollo 83ed87f6a9 feat(iso): build end-4 deps in-image, ship end4-pC as default shell
Tests / tests (push) Successful in 2m35s
- customize_airootfs.sh stages dots-hyprland at /opt, runs ./setup
  install-deps as a throwaway builder, harvests the built packages into
  /opt/localrepo so pacstrap resolves them offline
- image ships its own [local-aur] (file:///opt/localrepo); CI and
  localrepo/update.sh keep that copy in sync; .gitignore covers work/,
  out/ and airootfs/opt/localrepo/
- alvin-install runs ./setup install --skip-alldeps on the target
- clone pctrade/end4-pC into /etc/skel/.config/quickshell, patch qsConfig
  ii -> end4-pC in the staged variables.lua (guarded + idempotent), and
  restore the fork after setup rsync --delete's ~/.config/quickshell
- ship user presets in skel, point fish `q` alias at end4-pC
- AGENTS.md: document the fourth package source and new gotchas
2026-09-27 10:31:49 +10:00
alvinlollo 5ffd5d0d82 ci: pin SOURCE_DATE_EPOCH, assert ISO uuid metadata, verify uploads
Tests / tests (push) Canceled after 1m42s
- Export SOURCE_DATE_EPOCH before mkarchiso so label, volume UUID,
  file mtimes and ext4 hash seed trace to one timestamp.
- Post-build step: assert blkid UUID of the ISO matches every
  /boot/<uuid>.uuid stem and archisosearchuuid= reference inside
  shipped boot configs, and that no %ARCHISO% placeholder remains.
- After upload: re-hash local ISOs, size-check API assets, download
  each back from the internal origin (bypasses traefik/Anubis) with
  percent-encoded filenames (iso_name contains a space), compare
  SHA-256. Definitive corruption (missing/size/sha mismatch) deletes
  the release; transport/API errors fail without deleting.
2026-09-23 22:32:08 +10:00
alvinlollo 8484bddcf2 fix(installer): parse pkglist name field, skip unresolvable pkgs, keymap confirm
pacstrap failed at line 382 because pkglist lines from pacman -Q are
'name version' and were passed whole as pacman targets (~400 'target
not found'). Parse only the first field, pre-filter against pacman -Slq
so packages missing from the live repos (local-aur) are skipped with a
warning, and fall back to an unfiltered list if pacman -Syy fails.
Keymap screen now offers a US-layout confirm before the gum filter.
2026-09-23 22:32:01 +10:00
alvinlollo 0755091721 ci: add 3-try retry loop and timeouts for ISO release upload
Tests / tests (push) Successful in 2m17s
2026-09-22 22:06:33 +10:00
alvinlollo c71168371d fix(ci): upload plain ISO directly, skip zstd compression
Tests / tests (push) Successful in 2m22s
Compression was 5.3 GiB -> 5.2 GiB (98.6%) — negligible savings for
the extra build time. Upload the .iso directly as a release asset.
2026-09-21 19:56:07 +10:00
alvinlollo 117b5e97aa Add alvin-install TUI installer, fix NetworkManager boot
Tests / tests (push) Successful in 2m23s
- New gum-based installer script (alvin-install) with LUKS encryption,
  nmtui networking, disk selector, user/git config, and CachyOS repo setup
- Replace NetworkManager full unit file with symlink for consistency
- Add alvin-install reference to MOTD
- Add file_permissions entry in profiledef.sh
- Fix localrepo path case in pacman.conf
2026-09-20 22:22:20 +10:00
alvinlollo 8a88921913 fix: use linux-cachyos kernel in all boot entries
Tests / tests (push) Successful in 2m16s
Boot configs referenced stock vmlinuz-linux/initramfs-linux.img but
only linux-cachyos is installed. This caused boot to fall through
to memtest86+ since the kernel file was not found.
2026-09-20 17:02:20 +10:00
alvinlollo 9614192416 fix(ci): replace git LFS with release asset uploads
Tests / tests (push) Successful in 2m34s
The GITEA_TOKEN lacks 'lfs' scope, causing the LFS batch API to reject
uploads. Upload .zst files directly as release assets via the Gitea API
instead. This eliminates git-lfs, the separate releases repo, and all
LFS-related plumbing.
2026-09-20 13:24:37 +10:00
alvinlollo 2f1ac8d052 fix(ci): remove stderr suppression on push to diagnose LFS upload failure
Tests / tests (push) Successful in 2m21s
2026-09-20 10:24:51 +10:00
alvinlollo fa7eff8517 fix(ci): skip LFS smudge on releases repo clone
Tests / tests (push) Successful in 2m17s
2026-09-19 21:47:53 +10:00
alvinlollo 24f3f0f399 fix(ci): keep latest 2 releases instead of 3, clean up .releases-repo in always step
Tests / tests (push) Successful in 2m13s
2026-09-19 21:39:53 +10:00
alvinlollo ac59de33c8 fix(ci): move releases clone out of /tmp and free disk after LFS push
Tests / tests (push) Successful in 2m18s
2026-09-19 21:34:21 +10:00
alvinlollo da0855d341 Add --rm to remove source ISO
Tests / tests (push) Successful in 2m32s
2026-09-18 12:49:33 +10:00
alvinlollo 50d49bbe38 fix(ci): add PreTransaction hook to ensure /dev/stdin exists inside pacstrap chroot
Tests / tests (push) Successful in 2m31s
2026-09-17 15:58:16 +10:00
alvinlollo 1090e3c75b fix(ci): ensure /dev/stdin exists for mkinitcpio and remove stock linux kernel
Tests / tests (push) Successful in 2m18s
- Add CI step to create /dev/stdin symlinks before ISO build
  (Docker/container environments may lack these, causing mkinitcpio to fail)
- Remove stock linux kernel from packages.x86_64 (linux-cachyos is the
  intended kernel; dual-kernel causes boot confusion and doubles build time)

Closes #X
2026-09-17 09:42:29 +10:00
alvinlollo 48b760d54e Update cleanup step name to match always() behavior
Tests / tests (push) Successful in 2m15s
2026-09-17 07:30:20 +10:00
alvinlollo 7f91c189db Mirror releases and seed README in AlvinArch-releases for discovery
Tests / tests (push) Successful in 2m22s
Create a matching git tag + release in alvinlollo/AlvinArch-releases next to
the main repo release, seed a short README there pointing back to
AlvinArch (workflow status badges on top), and extend release pruning to
the releases repo so both stay capped at 3.
2026-09-16 22:44:05 +10:00
alvinlollo 3816877b12 Fix ISO release uploads >3GB: zstd-compress and store via Git LFS in AlvinArch-releases
Release assets can no longer be attached directly (Gitea 500 on multi-GB
uploads). Compress each ISO with zstd, push the .zst into
alvinlollo/AlvinArch-releases (releases/<tag>/ on main) via Git LFS, verify
the LFS object server-side by OID, and create the release with a download
link plus SHA-256 checksums instead of a binary attachment.
2026-09-16 22:41:35 +10:00
alvinlollo c9cf5ead97 Remove conflicting os-release, move branding to profiledef.sh
Tests / tests (push) Successful in 2m30s
2026-09-16 17:13:07 +10:00
alvinlollo 01c7c4e1fa Harden ISO build workflow: verifiable upload, cleanup on cancel/exit
Tests / tests (push) Successful in 2m21s
2026-09-16 16:37:25 +10:00
alvinlollo d5356b772e Fix custom branding
Tests / tests (push) Successful in 4m18s
2026-09-16 15:44:38 +10:00
alvinlollo 75bc4b3f4c Fix ISO upload: use internal Gitea URL to bypass traefik timeout, add curl retries and 30min timeout
Tests / tests (push) Successful in 2m26s
2026-09-15 22:53:24 +10:00
alvinlollo 10198915a1 Remove airootfs files that conflict with package installs
Tests / tests (push) Successful in 2m21s
These files exist in the airootfs overlay but are owned by packages
in packages.x86_64, causing 'exists in filesystem' errors during
mkarchiso pacman install:

- usr/lib/os-release (filesystem)
- usr/share/pacman/keyrings/cachyos-* (cachyos-keyring)
- etc/clamav/certs/clamav.crt (clamav)
- etc/skel/.zshrc (grml-zsh-config)
2026-09-15 18:49:59 +10:00
alvinlollo 56c02781c2 Fix CI: drop incorrect -c flag, fix word splitting in tests
Tests / tests (push) Successful in 2m15s
build-iso:
- Remove -c flag (it takes a pacman.conf path, not a clean flag)
- Use absolute paths for mkarchiso with -- separator
- Copy local-aur.files* alongside local-aur.db*

tests:
- Fix word splitting: use 'while IFS= read -r' instead of
  'for f in ' for shell and YAML file loops
- Fix YAML find filter to use -not -path like shell find
2026-09-15 18:36:45 +10:00
alvinlollo 8e6e06155c Fix mkarchiso argument parsing in CI
Tests / tests (push) Successful in 2m15s
Use -- to separate flags from profile path, preventing mkarchiso
from misinterpreting the -w argument as the profile directory.
Also make rm -rf fail-safe with || true.
2026-09-15 18:23:24 +10:00
alvinlollo 22bae5f19b Use absolute paths for mkarchiso in CI
Tests / tests (push) Successful in 2m16s
mkarchiso requires absolute paths. Clean work dir explicitly and
pass PWD-based paths to -w, -o, and the profile directory.
2026-09-15 18:17:53 +10:00
alvinlollo 2dbbb3321d Use mkarchiso -c flag to clean work directory before build
Tests / tests (push) Successful in 2m32s
Replaces the separate rm step with the built-in -c flag which
forces mkarchiso to clean previous working directories first.
2026-09-15 18:11:35 +10:00
alvinlollo c4ce0b3534 Fix conflicting yq packages, add conflict check, rename workflow
Tests / tests (push) Successful in 2m22s
- Remove yq from packages.x86_64 (conflicts with go-yq)
- Add conflicting packages check step to tests workflow
- Rename 'Scheduled ArchISO Build' to 'Automated Arch ISO Build'
- Add --needed to all pacman install commands to suppress reinstalls
2026-09-15 17:49:28 +10:00
alvinlollo 3c592d1e84 Fix build-iso: copy localrepo to /tmp and patch pacman.conf for CI
Tests / tests (push) Successful in 2m23s
The local-aur repo in pacman.conf points to /home/alvin/alvinarch/localrepo
which only exists on the dev machine. In CI, copy the tracked .pkg.tar.zst
files to /tmp/localrepo and sed the path before building.
2026-09-15 17:43:05 +10:00
alvinlollo aad0ea2e03 Fix build-iso: use repo root as profile, not releng/
Tests / tests (push) Successful in 2m18s
The AlvinArch profile lives at the repo root, not in a releng/
subdirectory. The old path caused mkarchiso to fail with:
  ERROR: Profile '.../releng' does not exist!
2026-09-15 17:21:57 +10:00
alvinlollo 2eb1e9f61a Switch from systemd-networkd to NetworkManager, add AGENTS.md
Tests / tests (push) Successful in 2m22s
- Replace systemd-networkd/resolved symlinks with NetworkManager
- Remove unused networkd config files (ethernet, wlan, wwan)
- Add AGENTS.md for CI/agent guidance
- Update motd and packages.x86_64
2026-09-15 17:16:50 +10:00
alvinlollo 08e947c7ea Personalize README for AlvinArch
Rewrite README to accurately reflect the AlvinArch project:
- Update overview for Hyprland + end-4 dotfiles focus
- Replace inaccurate directory tree with actual project layout
- Document real skel configs (bat, fish, nvim, hypr/custom, starship)
- Add system services and networking documentation
- Add localrepo documentation (build scripts, end4-pkgbuilds)
- Replace DTOS/KyOS VirtualBox section with concise VM notes
- Remove irrelevant DTOS/KyOS rebranding section
- Add Planned Additions table (alacritty, gtk, fontconfig, dunst)
- Add Troubleshooting and Acknowledgements sections
- Update CI badge from checks.yaml to tests.yaml
2026-09-15 17:16:31 +10:00
alvinlollo 7f9cce549f Recognize localrepo and build-end4-deps.sh in package check 2026-09-15 15:37:44 +10:00
alvinlollo b76ff09624 Fix tests: check all repo matches for each package, not just first 2026-09-15 15:37:44 +10:00
alvinlollo 10d2c90c6f Fix tests: add core repo to allowed list, strip CR from pacman output 2026-09-15 15:37:44 +10:00
alvinlollo 8ea8699957 Fix tests: reset pacman.conf, correct CachyOS mirror URL format 2026-09-15 15:37:43 +10:00
alvinlollo 83f5dbae0d Fix tests: correct CachyOS and chaotic-aur mirror URLs, install keyrings properly 2026-09-15 15:37:43 +10:00
alvinlollo a4dbec69a1 Use archlinux runner natively - no Docker needed 2026-09-15 15:37:42 +10:00
alvinlollo 3b1ef02a40 Fix tests: remove all pacman-key calls (gpg-agent broken in Docker), TrustAll SigLevel 2026-09-15 15:37:42 +10:00
alvinlollo 8a61478b82 Fix tests: skip pacman-key lsign (gpg-agent broken in Docker), rely on SigLevel TrustAll 2026-09-15 15:37:42 +10:00
alvinlollo c6592dad04 Fix tests: proper CachyOS key import via pacman-key instead of broken URL 2026-09-15 15:37:41 +10:00
alvinlollo 8e0c7a96ce Fix tests: use default Arch mirrorlist, remove broken URL 2026-09-15 15:37:41 +10:00
alvinlollo fbb30d3e19 Fix package name: yamllint not python-yamllint on Arch 2026-09-15 15:37:40 +10:00
alvinlollo 843529d124 Fix tests: checkout on host, Arch work in docker run (Gitea runner Docker mode ENOTCONN bug) 2026-09-15 15:37:40 +10:00
alvinlollo 1c4e28c0c4 Fix formatting 2026-09-15 15:37:40 +10:00
alvinlollo 0794001d68 Rename Workflow from "Checks" to "Tests" 2026-09-15 15:37:39 +10:00
alvinlollo 04fcfb2dc6 Rename "Checks" to "Tests" 2026-09-15 15:37:39 +10:00
alvinlollo ffa528744e Update status test badge 2026-09-15 15:37:38 +10:00
alvinlollo b696731132 Combine check-packages and syntax-check into one workflow 2026-09-15 15:37:38 +10:00
alvinlollo 56041a26e1 Fix yamllint: also disable line-length and new-line-at-end-of-file rules 2026-09-15 15:37:38 +10:00
alvinlollo 52e402a932 Fix yamllint: disable document-start rule in relaxed config 2026-09-15 15:37:37 +10:00
alvinlollo 63a3d6539d Test RPi runner with multi-arch archlinux image 2026-09-15 15:37:37 +10:00
alvinlollo 12238a9d36 Add markdown statuses 2026-09-15 15:37:36 +10:00
alvinlollo 17987e3764 Fix script syntax 2026-09-15 15:37:36 +10:00
alvinlollo e00b4e00bf Make gitea actions run on push 2026-09-15 15:37:36 +10:00
alvinlollo df679c4377 Fix gitea workflows 2026-09-15 15:37:35 +10:00
alvinlollo 89e98b1fe3 Retry syntax-check with native host runner 2026-09-15 15:37:35 +10:00
alvinlollo d8c051d073 Retry syntax-check with host execution mode 2026-09-15 15:37:34 +10:00
alvinlollo 97ddfe0e5e Retry syntax-check with Docker-based runner 2026-09-15 15:37:34 +10:00
alvinlollo 78b55d9d13 Fix syntax-check: use ubuntu-latest without container for linting 2026-09-15 15:37:34 +10:00
alvinlollo 6d68160746 Fix checkout: install git+node in Arch container before checkout 2026-09-15 15:37:33 +10:00
alvinlollo f5f2c05c1a Fix syntax-check: remove commit count gate, use pacman for Arch 2026-09-15 15:37:33 +10:00
alvinlollo 589da72194 Change Runner os to archlinux 2026-09-15 15:37:33 +10:00
alvinlollo d30971f220 Add syntax checking for every 2 commits 2026-09-15 15:37:32 +10:00
alvinlollo 7d53298b9d Add monthly iso build workflow that can be triggered manually 2026-09-15 15:37:32 +10:00
alvinlollo effee71d38 Add package verification workflow 2026-09-15 15:37:31 +10:00
alvinlollo 2e51ff9226 Add dotfiles file structure 2026-09-15 15:37:31 +10:00
alvinlollo 7b7658732b Add missing aur packages not in packages.x86_64 2026-09-15 15:37:31 +10:00
alvinlollo df046dcba2 Add end-4 hyprland dependecies post-install 2026-09-15 15:37:30 +10:00
alvinlollo 94ce80a365 Add zsh config 2026-09-15 15:37:29 +10:00
alvinlollo 7d1a71569b Add starfish for fish 2026-09-15 15:37:28 +10:00
alvinlollo 861cfe8f77 Add end-4 dotfiles config 2026-09-15 15:37:28 +10:00
alvinlollo 2b27267ecf Add fish config 2026-09-15 15:37:27 +10:00
alvinlollo de7d5abe93 Add Bat config 2026-09-15 15:37:27 +10:00
alvinlollo 4006c15796 Add Lazyvim config 2026-09-15 15:37:27 +10:00
alvinlollo b2927a894f Update Packages 2026-09-15 15:37:26 +10:00
alvinlollo 0aa143fe75 Add CachyOS keyrings and AUR packages 2026-09-15 15:37:24 +10:00
alvinlollo 9afaf4f18a Add Australian Locales 2026-09-15 15:37:22 +10:00
alvinlollo a2eebba9a5 Add soft custom branding 2026-09-15 15:37:21 +10:00
alvinlollo ffee0ed8bc Add Packages and Clamav config 2026-09-15 15:37:21 +10:00
alvinlollo 05c5a33b0c Add to packages.x86_64 use sort -u -o packages.x86_64 packages.x86_64 2026-09-15 15:37:20 +10:00
alvinlollo 4a8b2b1b1d Add packages.x86_64 use sort -u -o packages.x86_64 packages.x86_64 2026-09-15 15:37:20 +10:00
alvinlollo c6df3c0a42 Add README.md guide to make a Arch Linux ISO 2026-09-15 15:37:20 +10:00
alvinlollo 437c7cefa7 Copied default archiso releng configuration 2026-09-15 15:37:19 +10:00
alvinlollo 771a26c9ce first commit 2026-09-15 15:37:19 +10:00
92 changed files with 9070 additions and 1053 deletions
+585
View File
@@ -0,0 +1,585 @@
name: Automated Arch ISO Build
on:
schedule:
- cron: "0 0 1 * *" # Runs monthly on the 1st day of the month
workflow_dispatch: # Allows manual triggers (multiple times a month)
concurrency:
group: iso-build
cancel-in-progress: false # Never kill a build that is mid-flight
jobs:
build:
runs-on: archlinux
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup local AUR repo
run: |
set -euo pipefail
shopt -s nullglob
mkdir -p /tmp/localrepo
cp localrepo/*.pkg.tar.zst localrepo/local-aur.db* localrepo/local-aur.files* /tmp/localrepo/
sed -i 's|file:///home/alvin/AlvinArch/localrepo|file:///tmp/localrepo|' pacman.conf
# The medium needs its own copy: the ISO's /etc/pacman.conf points
# [local-aur] at file:///opt/localrepo, which pacstrap reads at
# install time to resolve packages that are not in the official repos
# (built during the ISO build and harvested there by
# airootfs/root/customize_airootfs.sh).
mkdir -p airootfs/opt/localrepo
shipped=(localrepo/*.pkg.tar.zst localrepo/local-aur.db* localrepo/local-aur.files*)
if (( ${#shipped[@]} > 0 )); then
cp -L "${shipped[@]}" airootfs/opt/localrepo/
fi
echo "airootfs/opt/localrepo: $(ls airootfs/opt/localrepo | wc -l) file(s)"
- name: Install archiso and dependencies
run: |
set -euo pipefail
# Install with a *private* config instead of /etc/pacman.conf.
# The host config is shared mutable state: the tests workflow
# rewrites it and jobs overlap on this runner (runs 132 and 133
# ran concurrently), so writing it here could corrupt a concurrent
# tests run. It also carries [cachyos] and [chaotic-aur] leftovers
# from tests.yaml, and syncing those two repos means extra DNS
# lookups against a gateway that intermittently drops UDP/53 —
# that is what failed run 131 at this very step. The build only
# needs archiso/jq from extra; mkarchiso reads the *profile's*
# pacman.conf for everything that goes into the ISO.
BUILD_CONF=$(mktemp)
trap 'rm -f "$BUILD_CONF"' EXIT
cat > "$BUILD_CONF" << 'STOCKCONF'
[options]
DisableSandbox
HoldPkg = pacman glibc
Architecture = auto
CheckSpace
ParallelDownloads = 5
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
[core]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
STOCKCONF
sed -i 's/^ //' "$BUILD_CONF"
# Warm the resolver cache for the mirrors we are about to query.
# systemd-resolved serves later lookups from cache, so a gateway
# UDP/53 burst cannot hit them again. Failures here are not fatal —
# the retry loop below is the real safety net.
for host in mirror.aarnet.edu.au gsl-syd.mm.fcix.net au.arch.niranjan.co; do
for try in 1 2 3 4 5; do
if getent hosts "$host" >/dev/null 2>&1; then
break
fi
echo " ⏳ DNS for $host failed (try $try/5), retrying in $(( try * 3 ))s..."
sleep $(( try * 3 ))
done
done
# The gateway drops DNS queries in bursts; one burst must not fail
# the whole job, so retry with backoff before giving up.
synced=0
for try in 1 2 3 4 5; do
if pacman --config "$BUILD_CONF" -Syu --noconfirm --needed archiso jq; then
synced=1
break
fi
echo " ⚠️ pacman -Syu failed (attempt $try/5), retrying in $(( try * 15 ))s..." >&2
sleep $(( try * 15 ))
done
if [ "$synced" -ne 1 ]; then
echo "❌ pacman -Syu failed after 5 attempts — giving up" >&2
exit 1
fi
- name: Ensure /dev/fd symlinks exist for mkinitcpio and procsub
run: |
set -euo pipefail
# mkinitcpio's preset step pipes through /dev/stdin and bash process
# substitution (< <(...)) uses /dev/fd; both break if these symlinks
# are missing (they are normally created once at boot by mkinitcpio's
# init). Two places need them, so cover both:
# 1. the executor's own /dev: mkarchiso reads /dev/stdin on the host
# (machine-id, version, pkglist) and the workflow's own scripts use
# process substitution here. A no-op if the links already exist.
ln -sfn /proc/self/fd /dev/fd
ln -sfn /proc/self/fd/0 /dev/stdin
ln -sfn /proc/self/fd/1 /dev/stdout
ln -sfn /proc/self/fd/2 /dev/stderr
# 2. the chroot's /dev: devtmpfs is single-instance, so mounting it
# here yields the same tree that pacstrap/arch-chroot expose as
# <chroot>/dev. When the executor's /dev is itself devtmpfs (1)
# already fixed that tree; this pass is what makes it work when
# the executor's /dev is a plain tmpfs or directory instead.
d="$(mktemp -d)"
trap 'umount "$d" 2>/dev/null || true; rmdir "$d" 2>/dev/null || true' EXIT
mount -t devtmpfs devtmpfs "$d"
ln -sfn /proc/self/fd "$d/fd"
ln -sfn /proc/self/fd/0 "$d/stdin"
ln -sfn /proc/self/fd/1 "$d/stdout"
ln -sfn /proc/self/fd/2 "$d/stderr"
ls -l "$d/fd" "$d/stdin" "$d/stdout" "$d/stderr"
umount "$d"
rmdir "$d"
trap - EXIT
- name: Build Arch ISO
run: |
set -euo pipefail
# Pin one timestamp for the whole job: mkarchiso derives the ISO label,
# volume UUID, file mtimes, and ext4 hash seed from SOURCE_DATE_EPOCH.
# Exporting it explicitly makes every timestamp-derived value traceable
# (and lets later steps log the same value via $GITHUB_ENV).
SOURCE_DATE_EPOCH="$(date -u +%s)"
export SOURCE_DATE_EPOCH
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" >> "$GITHUB_ENV"
echo "Building with SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
# Clean up immediately even if this step is interrupted (cancel/exit):
# unmount leftovers first, then remove the multi-GB work dir.
trap 'umount -R "$PWD/work" 2>/dev/null || true; rm -rf "$PWD/work"' EXIT HUP INT TERM
rm -rf "$PWD/work"
# Always start from an empty out dir so stale ISOs are never re-uploaded
rm -rf "$PWD/out"
mkdir -p "$PWD/out"
mkarchiso -v -w "$PWD/work" -o "$PWD/out" -- "$PWD"
- name: Verify ISO search metadata
run: |
set -euo pipefail
shopt -s nullglob
isos=(out/*.iso)
if (( ${#isos[@]} != 1 )); then
echo "❌ Expected exactly 1 ISO in out/, found ${#isos[@]}" >&2
exit 1
fi
iso=${isos[0]}
# blkid exits non-zero when a field is missing; keep going so the
# explicit guard below can report a useful error.
vol_uuid=$(blkid -o value -s UUID "$iso" || true)
vol_label=$(blkid -o value -s LABEL "$iso" || true)
if [ -z "$vol_uuid" ]; then
echo "❌ blkid found no UUID for $iso — volume date chain broken?" >&2
exit 1
fi
echo "Volume UUID: $vol_uuid"
echo "Volume label: ${vol_label:-<none>}"
echo "SOURCE_DATE_EPOCH: ${SOURCE_DATE_EPOCH:-<unset>}"
fail() {
echo "❌ $1" >&2
echo " If you changed boot configs (efiboot/, syslinux/, grub/) on purpose," >&2
echo " update this 'Verify ISO search metadata' step to match." >&2
exit 1
}
# 1) /boot/<uuid>.uuid (the archisosearchfilename fallback key) must
# exist inside the ISO and its stem must equal the volume UUID.
uuid_refs=0
while IFS= read -r member; do
[ -z "$member" ] && continue
member=${member#/}
stem=$(basename "$member" .uuid)
if [ "$stem" != "$vol_uuid" ]; then
fail "$member: stem '$stem' != volume UUID '$vol_uuid'"
fi
echo " ✅ $member matches volume UUID"
uuid_refs=$((uuid_refs + 1))
done < <(bsdtar -tf "$iso" | grep -E '(^|/)boot/[0-9A-Za-z-]+\.uuid$' || true)
if (( uuid_refs == 0 )); then
fail "no /boot/<uuid>.uuid file found inside the ISO"
fi
# 2) Every archisosearchuuid= in shipped boot configs must equal the
# volume UUID; every %ARCHISO% placeholder must have been substituted.
search_refs=0
while IFS= read -r member; do
[ -z "$member" ] && continue
member=${member#/}
if ! content=$(bsdtar -xOf "$iso" "$member" 2>/dev/null); then
fail "could not extract $member from the ISO"
fi
if printf '%s\n' "$content" | grep -q '%ARCHISO'; then
fail "$member contains an unsubstituted %ARCHISO% placeholder"
fi
while IFS= read -r val; do
[ -z "$val" ] && continue
search_refs=$((search_refs + 1))
if [ "$val" != "$vol_uuid" ]; then
fail "$member: archisosearchuuid=$val != volume UUID '$vol_uuid'"
fi
echo " ✅ $member: archisosearchuuid=$val matches volume UUID"
done < <(printf '%s\n' "$content" | grep -o 'archisosearchuuid=[^[:space:]]*' | cut -d= -f2- || true)
done < <(bsdtar -tf "$iso" | grep -E '(^|/)(loader/entries/.*\.conf|boot/.*\.(cfg|conf))$' || true)
if (( search_refs == 0 )); then
fail "no archisosearchuuid= references found in shipped boot configs (params removed without updating this check?)"
fi
echo "✅ ISO search metadata consistent: $uuid_refs uuid file(s), $search_refs search reference(s)"
- name: Generate Unique Dynamic Tag
id: tag
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_API: http://192.168.1.168:3000/api/v1
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
test -n "$GITEA_TOKEN"
# Pre-flight: confirm the internal Gitea API is reachable so failures are clear
if ! curl -sfS -o /dev/null "$GITEA_API/version"; then
echo "❌ Cannot reach Gitea API at $GITEA_API" >&2
exit 1
fi
BASE_DATE=$(date -u +'%Y.%m.%d')
REVISION=1
TAG_NAME="iso-${BASE_DATE}-r${REVISION}"
# Check if the tag already exists via Gitea API, increment revision loop if it does
while curl -sf -o /dev/null -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/tags/$TAG_NAME"; do
REVISION=$((REVISION + 1))
TAG_NAME="iso-${BASE_DATE}-r${REVISION}"
done
echo "tag_name=${TAG_NAME}" >> "$GITHUB_OUTPUT"
echo "release_name=Arch Linux ISO (${BASE_DATE} Rev ${REVISION})" >> "$GITHUB_OUTPUT"
- name: Create Release and Upload ISO
id: release
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
# Use internal Gitea URL to bypass traefik proxy timeout on large uploads
GITEA_API: http://192.168.1.168:3000/api/v1
REPOSITORY: ${{ github.repository }}
TAG_NAME: ${{ steps.tag.outputs.tag_name }}
RELEASE_NAME: ${{ steps.tag.outputs.release_name }}
run: |
set -eu
shopt -s nullglob
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
if [ -z "$GITEA_TOKEN" ]; then
echo "❌ GITEA_TOKEN is empty" >&2
exit 1
fi
if [ -z "$TAG_NAME" ]; then
echo "❌ TAG_NAME is empty" >&2
exit 1
fi
if [ -z "$RELEASE_NAME" ]; then
echo "❌ RELEASE_NAME is empty" >&2
exit 1
fi
# Pre-flight: confirm the internal Gitea API is reachable so failures are clear
if ! curl -sfS -o /dev/null "$GITEA_API/version"; then
echo "❌ Cannot reach Gitea API at $GITEA_API" >&2
exit 1
fi
# Collect the ISOs produced by the build and record SHA-256
isos=(out/*.iso)
if (( ${#isos[@]} == 0 )); then
echo "❌ No ISO found in out/ — nothing to upload, aborting." >&2
exit 1
fi
sha256sums=()
for iso in "${isos[@]}"; do
fname=$(basename "$iso")
size=$(stat -c %s "$iso")
# Sanity check: a real ISO is multi-GB; anything tiny is the wrong file
if (( size < 100000000 )); then
echo "❌ '$iso' is only $size bytes — refusing to upload (not an ISO)." >&2
exit 1
fi
sha=$(sha256sum "$iso" | awk '{print $1}')
if [ -z "$sha" ]; then
echo "❌ Failed to compute SHA-256 for '$iso'" >&2
exit 1
fi
echo " ✅ $fname: $(( size / 1024 / 1024 )) MiB, sha256=$sha"
sha256sums+=("$sha")
done
# Build the release body with SHA-256 checksums
printf -v body 'Arch Linux live ISO %s\n\nChecksums (SHA-256):\n' "$RELEASE_NAME"
for i in "${!isos[@]}"; do
# Release body: markdown backticks are literal (printf format below)
# shellcheck disable=SC2016
printf -v line -- '- `%s`: sha256 `%s`\n' "$(basename "${isos[$i]}")" "${sha256sums[$i]}"
body+="$line"
done
# Create the release (curl result written to a file, checked with if)
payload=$(jq -nc --arg tag "$TAG_NAME" --arg name "$RELEASE_NAME" --arg body "$body" \
'{tag_name:$tag,name:$name,body:$body}')
if ! curl -sf -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$GITEA_API/repos/$REPOSITORY/releases" \
-d "$payload" -o "$tmpdir/release.json"; then
echo "❌ Failed to create release $TAG_NAME" >&2
exit 1
fi
if ! RELEASE_ID=$(jq -er '.id' "$tmpdir/release.json"); then
echo "❌ Release response contained no id" >&2
exit 1
fi
echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
echo " ✅ Created release $TAG_NAME (ID: $RELEASE_ID)"
# Upload each ISO as a release asset, up to 3 attempts per file
MAX_ATTEMPTS=3
for i in "${!isos[@]}"; do
iso=${isos[$i]}
fname=$(basename "$iso")
size=$(stat -c %s "$iso")
echo "Uploading $fname ($(( size / 1024 / 1024 )) MiB) to release $TAG_NAME..."
uploaded=0
attempt=1
while [ "$attempt" -le "$MAX_ATTEMPTS" ]; do
# Fresh output file each attempt: curl does not truncate -o on
# transport failure, so a stale body must not be misreported.
rm -f "$tmpdir/upload.json"
# A previous attempt may have saved the asset but lost the
# response; Gitea rejects duplicate names, so only after the
# first attempt check for and remove same-name leftovers
if [ "$attempt" -gt 1 ]; then
if curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID/assets" \
-o "$tmpdir/assets.json"; then
asset_ids=$(jq -r --arg name "$fname" \
'.[] | select(.name == $name) | .id' "$tmpdir/assets.json")
while read -r asset_id; do
if [ -n "$asset_id" ]; then
echo " ↻ Removing leftover asset id=$asset_id from a previous attempt"
if ! curl -sf -X DELETE -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID/assets/$asset_id" \
-o /dev/null; then
echo " ⚠️ Could not remove leftover asset id=$asset_id (continuing)" >&2
fi
fi
done <<< "$asset_ids"
fi
fi
# Capture HTTP status explicitly: `-f` would swallow the Gitea
# error body (e.g. attachment size-limit messages) and leave the
# failure reason unknown.
if http_code=$(curl -sS -X POST --max-time 600 \
-H "Authorization: token $GITEA_TOKEN" \
-F "attachment=@$iso" \
"$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID/assets" \
-o "$tmpdir/upload.json" -w '%{http_code}'); then
if [ "${http_code:0:1}" = "2" ] \
&& download_url=$(jq -er '.browser_download_url' "$tmpdir/upload.json"); then
echo " ✅ Uploaded $fname (attempt $attempt/$MAX_ATTEMPTS): $download_url"
uploaded=1
break
fi
echo " ⚠️ Upload of $fname: HTTP $http_code (attempt $attempt/$MAX_ATTEMPTS)" >&2
echo " Response: $(head -c 2000 "$tmpdir/upload.json" 2>/dev/null)" >&2
else
rc=$?
echo " ⚠️ Upload of $fname failed (attempt $attempt/$MAX_ATTEMPTS): curl exit $rc, HTTP ${http_code:-000}" >&2
if [ -s "$tmpdir/upload.json" ]; then
echo " Response: $(head -c 2000 "$tmpdir/upload.json")" >&2
fi
fi
if [ "$attempt" -lt "$MAX_ATTEMPTS" ]; then
sleep $(( attempt * 10 ))
fi
attempt=$(( attempt + 1 ))
done
if [ "$uploaded" -ne 1 ]; then
echo "❌ Failed to upload $fname after $MAX_ATTEMPTS attempts — aborting." >&2
exit 1
fi
done
echo "✅ All ISOs uploaded to release $TAG_NAME"
exit 0
- name: Verify uploaded ISO checksums
if: success()
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
# Internal origin bypasses traefik (and its Anubis bot wall) — the
# same host the upload step already uses.
GITEA_API: http://192.168.1.168:3000/api/v1
GITEA_ORIGIN: http://192.168.1.168:3000
REPOSITORY: ${{ github.repository }}
TAG_NAME: ${{ steps.tag.outputs.tag_name }}
RELEASE_ID: ${{ steps.release.outputs.release_id }}
run: |
set -euo pipefail
shopt -s nullglob
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
for var in GITEA_TOKEN TAG_NAME RELEASE_ID; do
if [ -z "${!var:-}" ]; then
echo "❌ $var is empty" >&2
exit 1
fi
done
case "$RELEASE_ID" in
''|*[!0-9]*) echo "❌ RELEASE_ID is not numeric: $RELEASE_ID" >&2; exit 1 ;;
esac
# fail_verify <reason...>: job fails but the release is kept — used
# for transport/API errors where the upload itself may be fine.
fail_verify() {
echo "❌ $1" >&2
echo " Release $TAG_NAME (ID $RELEASE_ID) left in place (not proven corrupt)." >&2
exit 1
}
# abort_release <reason...>: the asset is provably wrong — delete the
# release so a corrupt asset can never be published, then fail.
abort_release() {
echo "❌ $1" >&2
echo "Deleting release $TAG_NAME (ID $RELEASE_ID) so the bad upload cannot be used..." >&2
if ! curl -sf -X DELETE -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID" -o /dev/null; then
echo "⚠️ Could not delete release $RELEASE_ID — delete it manually!" >&2
fi
exit 1
}
isos=(out/*.iso)
if (( ${#isos[@]} == 0 )); then
echo "❌ No ISO in out/ to verify" >&2
exit 1
fi
# Recompute local checksums
declare -A local_sha local_size
for iso in "${isos[@]}"; do
fname=$(basename "$iso")
local_sha["$fname"]=$(sha256sum "$iso" | awk '{print $1}')
local_size["$fname"]=$(stat -c %s "$iso")
if [ -z "${local_sha[$fname]}" ]; then
echo "❌ Failed to compute SHA-256 for '$iso'" >&2
exit 1
fi
done
# List the release's assets as uploaded (API error = transient, no delete)
if ! curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/$RELEASE_ID/assets" \
-o "$tmpdir/assets.json"; then
fail_verify "Failed to list assets of release $RELEASE_ID (API/transport error)"
fi
for iso in "${isos[@]}"; do
fname=$(basename "$iso")
api_size=$(jq -er --arg name "$fname" \
'.[] | select(.name == $name) | .size' "$tmpdir/assets.json" 2>/dev/null) \
|| abort_release "Asset '$fname' missing from release $RELEASE_ID"
if [ "$api_size" != "${local_size[$fname]}" ]; then
abort_release "Asset '$fname' size mismatch: server=$api_size local=${local_size[$fname]}"
fi
# Download from the internal origin (traefik/Anubis bypassed).
# iso_name contains a space ("Alvin archlinux"), so the filename
# must be percent-encoded or curl rejects the URL outright.
enc_fname=$(jq -rn --arg v "$fname" '$v|@uri')
url="$GITEA_ORIGIN/$REPOSITORY/releases/download/$TAG_NAME/$enc_fname"
downloaded=0
for attempt in 1 2 3; do
# Try header auth, then ?token=, then anonymous (public repo).
if curl -sfL --max-time 600 -H "Authorization: token $GITEA_TOKEN" \
"$url" -o "$tmpdir/$fname"; then
downloaded=1
elif curl -sfL --max-time 600 "$url?token=$GITEA_TOKEN" \
-o "$tmpdir/$fname"; then
downloaded=1
elif curl -sfL --max-time 600 "$url" -o "$tmpdir/$fname"; then
downloaded=1
fi
[ "$downloaded" -eq 1 ] && break
echo " ⚠️ Download of $fname failed (attempt $attempt/3)" >&2
[ "$attempt" -lt 3 ] && sleep $(( attempt * 10 ))
done
if [ "$downloaded" -ne 1 ]; then
fail_verify "Could not download asset '$fname' back from release $RELEASE_ID (auth/transport error, not proven corrupt)"
fi
actual=$(sha256sum "$tmpdir/$fname" | awk '{print $1}')
expected=${local_sha[$fname]}
if [ "$actual" != "$expected" ]; then
abort_release "SHA-256 mismatch for '$fname': server=$actual local=$expected"
fi
echo " ✅ $fname: size and SHA-256 match"
rm -f "$tmpdir/$fname"
done
echo "✅ All uploaded assets verified against local ISO checksums"
exit 0
- name: Keep only latest 2 releases
if: success()
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_API: http://192.168.1.168:3000/api/v1
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
test -n "$GITEA_TOKEN"
echo "Pruning old releases in $REPOSITORY..."
readarray -t ids < <(curl -sf -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases" \
| jq -er 'sort_by(.created_at) | .[].id')
to_delete=$(( ${#ids[@]} - 2 ))
if (( to_delete > 0 )); then
for ((i = 0; i < to_delete; i++)); do
id=${ids[$i]}
echo "Deleting old release ID: $id"
curl -sf -X DELETE -H "Authorization: token $GITEA_TOKEN" \
"$GITEA_API/repos/$REPOSITORY/releases/$id"
done
fi
- name: Cleanup mkarchiso mounts and workdirs
if: always() # Runs on success, failure, or cancellation
run: |
set -eu
# Steps run as root (pacman is used directly); fall back to sudo if not
if [ "$(id -u)" -eq 0 ]; then
PRIV=""
else
PRIV="sudo"
fi
# Unmount any leftover loop devices or bind mounts in the work directory
$PRIV umount -R "$PWD/work" 2>/dev/null || true
# Clean up loop devices if any remain attached to the work dir
$PRIV losetup -D || true
# Remove working directories with proper permissions
$PRIV rm -rf "$PWD/work"
- name: Remove built ISO
if: always()
run: |
set -eu
rm -rf "$PWD/out"
+331
View File
@@ -0,0 +1,331 @@
name: Tests
on:
push:
pull_request:
workflow_dispatch:
jobs:
tests:
runs-on: archlinux
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Reset pacman.conf to stock
run: |
cat > /etc/pacman.conf << 'STOCKCONF'
[options]
DisableSandbox
HoldPkg = pacman glibc
Architecture = auto
CheckSpace
ParallelDownloads = 5
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
[core]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
STOCKCONF
sed -i 's/^ //' /etc/pacman.conf
# Remove stale sync databases for custom repos
rm -f /var/lib/pacman/sync/cachyos* /var/lib/pacman/sync/chaotic*
- name: Install prerequisites
run: |
# The gateway intermittently drops UDP/53 (it failed build run 131
# at the equivalent step); retry with backoff instead of dying on
# the first bad DNS burst.
synced=0
for try in 1 2 3 4 5; do
if pacman -Syu --noconfirm --needed shellcheck yamllint; then
synced=1
break
fi
echo "⚠️ pacman -Syu failed (attempt $try/5), retrying in $(( try * 15 ))s..." >&2
sleep $(( try * 15 ))
done
if [ "$synced" -ne 1 ]; then
echo "❌ pacman -Syu failed after 5 attempts — giving up" >&2
exit 1
fi
- name: Set up CachyOS repo
run: |
pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com
pacman-key --lsign-key F3B607488DB35A47
pacman -U --noconfirm \
'https://mirror.cachyos.org/repo/x86_64/cachyos/cachyos-keyring-20240331-1-any.pkg.tar.zst' \
'https://mirror.cachyos.org/repo/x86_64/cachyos/cachyos-mirrorlist-27-1-any.pkg.tar.zst'
# Fix the mirrorlist URL (pacnew has wrong format)
printf '%s\n' 'Server = https://mirror.cachyos.org/repo/$arch/$repo' \
> /etc/pacman.d/cachyos-mirrorlist
printf '\n[cachyos]\nInclude = /etc/pacman.d/cachyos-mirrorlist\n' \
>> /etc/pacman.conf
# Retry: gateway drops UDP/53 in bursts (see run 131)
synced=0
for try in 1 2 3 4 5; do
if pacman -Syu --noconfirm --needed; then
synced=1
break
fi
echo "⚠️ pacman -Syu failed (attempt $try/5), retrying in $(( try * 15 ))s..." >&2
sleep $(( try * 15 ))
done
if [ "$synced" -ne 1 ]; then
echo "❌ pacman -Syu failed after 5 attempts — giving up" >&2
exit 1
fi
- name: Set up chaotic-aur repo
run: |
pacman -U --noconfirm \
'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst' \
'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst'
printf '\n[chaotic-aur]\nInclude = /etc/pacman.d/chaotic-mirrorlist\n' \
>> /etc/pacman.conf
# Retry: gateway drops UDP/53 in bursts (see run 131)
synced=0
for try in 1 2 3 4 5; do
if pacman -Syu --noconfirm --needed; then
synced=1
break
fi
echo "⚠️ pacman -Syu failed (attempt $try/5), retrying in $(( try * 15 ))s..." >&2
sleep $(( try * 15 ))
done
if [ "$synced" -ne 1 ]; then
echo "❌ pacman -Syu failed after 5 attempts — giving up" >&2
exit 1
fi
- name: Lint shell scripts with ShellCheck
run: |
echo "═══════════════════════════════════════════════════════════════"
echo " Running ShellCheck on all .sh files"
echo "═══════════════════════════════════════════════════════════════"
SH_FILES=$(find . -name '*.sh' -not -path './.git/*')
if [ -z "$SH_FILES" ]; then
echo "No shell scripts found."
exit 0
fi
FAILED=0
while IFS= read -r f; do
echo ""
echo "── Checking: $f"
if shellcheck -x -s bash "$f"; then
echo " ✅ $f passed"
else
echo " ❌ $f failed"
FAILED=1
fi
done <<< "$SH_FILES"
if [ "$FAILED" -ne 0 ]; then
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ❌ One or more shell scripts have syntax issues"
echo "═══════════════════════════════════════════════════════════════"
exit 1
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ✅ All shell scripts passed ShellCheck"
echo "═══════════════════════════════════════════════════════════════"
- name: Lint YAML files with yamllint
run: |
echo "═══════════════════════════════════════════════════════════════"
echo " Running yamllint on all YAML files"
echo "═══════════════════════════════════════════════════════════════"
YAML_FILES=$(find . -not -path './.git/*' \( -name '*.yml' -o -name '*.yaml' \))
if [ -z "$YAML_FILES" ]; then
echo "No YAML files found."
exit 0
fi
FAILED=0
while IFS= read -r f; do
echo ""
echo "── Checking: $f"
if yamllint -d "{extends: relaxed, rules: {document-start: disable, line-length: disable, new-line-at-end-of-file: disable}}" "$f"; then
echo " ✅ $f passed"
else
echo " ❌ $f failed"
FAILED=1
fi
done <<< "$YAML_FILES"
if [ "$FAILED" -ne 0 ]; then
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ❌ One or more YAML files have syntax issues"
echo "═══════════════════════════════════════════════════════════════"
exit 1
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ✅ All YAML files passed yamllint"
echo "═══════════════════════════════════════════════════════════════"
- name: Validate packages.x86_64 syntax
run: |
echo "═══════════════════════════════════════════════════════════════"
echo " Validating packages.x86_64 format"
echo "═══════════════════════════════════════════════════════════════"
if [ ! -f packages.x86_64 ]; then
echo "packages.x86_64 not found, skipping."
exit 0
fi
FAILED=0
LINENUM=0
while IFS= read -r line; do
LINENUM=$((LINENUM + 1))
# Skip empty lines and comments
[[ -z "$line" || "$line" =~ ^# ]] && continue
# Check for invalid characters
if [[ ! "$line" =~ ^[a-zA-Z0-9._@+\-]+$ ]]; then
echo "❌ Line $LINENUM: invalid package name format: '$line'"
FAILED=1
fi
# Check for trailing whitespace
if [[ "$line" =~ [[:space:]]$ ]]; then
echo "⚠️ Line $LINENUM: trailing whitespace: '$line'"
FAILED=1
fi
done < packages.x86_64
if [ "$FAILED" -ne 0 ]; then
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ❌ packages.x86_64 has syntax issues"
echo "═══════════════════════════════════════════════════════════════"
exit 1
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ✅ packages.x86_64 syntax is valid"
echo "═══════════════════════════════════════════════════════════════"
- name: Check all packages
run: |
echo "═══════════════════════════════════════════════════════════════"
echo " Checking packages.x86_64 against repos"
echo " Allowed repos: cachyos, extra, multilib, chaotic-aur"
echo " Also accepted: localrepo/ pre-built packages"
echo " Also accepted: packages listed in build-end4-deps.sh"
echo "═══════════════════════════════════════════════════════════════"
ALLOWED_REPOS="^(core|extra|multilib|cachyos|chaotic-aur)$"
MISSING=()
FOUND=0
TOTAL=0
while IFS= read -r pkg; do
# Skip empty lines and comments
[[ -z "$pkg" || "$pkg" =~ ^# ]] && continue
TOTAL=$((TOTAL + 1))
# 1) Check allowed repos via pacman
repos=$(pacman -Si "$pkg" 2>/dev/null | grep "^Repository" | awk '{print $3}' | tr -d '\r')
MATCHED=0
for repo in $repos; do
if [[ "$repo" =~ $ALLOWED_REPOS ]]; then
MATCHED=1
FOUND=$((FOUND + 1))
break
fi
done
# 2) Check localrepo/ for a pre-built .pkg.tar.zst
if [[ $MATCHED -eq 0 ]] && compgen -G "localrepo/${pkg}-*.pkg.tar.zst" > /dev/null 2>&1; then
MATCHED=1
FOUND=$((FOUND + 1))
echo "📦 LOCAL: $pkg (pre-built in localrepo/)"
fi
# 3) Check build-end4-deps.sh for the package name
if [[ $MATCHED -eq 0 ]] && grep -qxF "${pkg}" localrepo/build-end4-deps.sh 2>/dev/null; then
MATCHED=1
FOUND=$((FOUND + 1))
echo "📦 BUILD: $pkg (listed in build-end4-deps.sh)"
fi
if [[ $MATCHED -eq 0 ]]; then
if [[ -z "$repos" ]]; then
echo "❌ MISSING: $pkg"
else
echo "⚠️ WRONG REPO: $pkg (found in: $repos)"
fi
MISSING+=("$pkg")
fi
done < packages.x86_64
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Results: $FOUND / $TOTAL packages found in allowed repos"
echo "═══════════════════════════════════════════════════════════════"
if [[ ${#MISSING[@]} -gt 0 ]]; then
echo ""
echo "⚠️ ${#MISSING[@]} package(s) NOT in allowed repos:"
for p in "${MISSING[@]}"; do
echo " • $p"
done
echo ""
echo "These packages must be in:"
echo " • cachyos, extra, multilib, or chaotic-aur"
echo " • OR pre-built in localrepo/"
echo " • OR added to build-end4-deps.sh"
exit 1
else
echo ""
echo "✅ All packages verified successfully!"
fi
- name: Check for conflicting packages
run: |
echo "═══════════════════════════════════════════════════════════════"
echo " Checking for conflicting packages in packages.x86_64"
echo "═══════════════════════════════════════════════════════════════"
# Collect all package names from the list
PKGS=()
while IFS= read -r pkg; do
[[ -z "$pkg" || "$pkg" =~ ^# ]] && continue
PKGS+=("$pkg")
done < packages.x86_64
# Use pacman -Sp --print to resolve the full install set and check for conflicts
# This catches "X and Y are in conflict" errors before the ISO build
PKG_LIST=$(printf '%s\n' "${PKGS[@]}")
if CONFLICTS=$(echo "$PKG_LIST" | pacman -Sp --needed - 2>&1); then
echo "✅ No package conflicts detected"
else
echo "$CONFLICTS" | grep -i "conflict" || true
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " ❌ Conflicting packages found — fix packages.x86_64"
echo "═══════════════════════════════════════════════════════════════"
exit 1
fi
+11
View File
@@ -0,0 +1,11 @@
# Multi-GB mkarchiso output (see AGENTS.md build command)
work/
out/
# In-image copy of localrepo/ — populated by localrepo/update.sh and
# .gitea/workflows/build-iso.yaml, shipped as /opt/localrepo on the ISO
airootfs/opt/localrepo/
# Build stamp staged by profiledef.sh at ISO build time (see AGENTS.md);
# consumed by customize_airootfs.sh, never committed
airootfs/root/.iso-build-stamp
+75
View File
@@ -0,0 +1,75 @@
# AGENTS.md
Arch Linux ISO profile (archiso). Builds a live ISO with Hyprland desktop, end-4 dots-hyprland, and curated packages. Hosted on Gitea.
## Build & Test Commands
```bash
# Build the ISO (repo root IS the profile directory)
sudo mkarchiso -v -w work -o out/ .
# Build AUR deps for end-4 (run locally before ISO build if localrepo/ is stale)
./localrepo/build-end4-deps.sh # build all
./localrepo/build-end4-deps.sh --quick # skip large AUR pkgs
# Refresh localrepo DB after adding/moving .pkg.tar.zst files
./localrepo/update.sh # re-indexes existing packages
./localrepo/update.sh pkg1.pkg.tar.zst # add files, then re-index
```
`update.sh` also refreshes `airootfs/opt/localrepo/` (the copy that ships on the
ISO), so run it after touching `localrepo/` before building.
## CI Checks (must pass before merge)
- **ShellCheck**: all `.sh` files checked with `shellcheck -x -s bash`
- **yamllint**: all `.yml`/`.yaml` files (relaxed config)
- **packages.x86_64 syntax**: one package per line, no trailing whitespace, `[a-zA-Z0-9._@+\-]+` only
- **Package repo check**: every package in `packages.x86_64` must be resolvable via `pacman -Si` in allowed repos (`cachyos`, `extra`, `multilib`, `chaotic-aur`), OR have a pre-built `.pkg.tar.zst` in `localrepo/`, OR appear in `localrepo/build-end4-deps.sh`
## Package Management
**Three sources** contribute packages to the ISO:
1. **`packages.x86_64`** — main list, installed by mkarchiso. Must be in an allowed repo.
2. **`localrepo/*.pkg.tar.zst`** — pre-built AUR packages. The `local-aur` repo is configured in `pacman.conf` and picked up by mkarchiso automatically.
3. **`build-end4-deps.sh`** — builds end-4 AUR deps at build time.
There is a **fourth source**: `customize_airootfs.sh` runs end-4's own
`./setup install-deps` inside the image (as a throwaway `ii-builder` account),
which resolves and compiles everything the dotfiles need (quickshell, MicroTeX,
theming, fonts, ...). Those packages are installed in the live system, land in
`pkglist.x86_64.txt`, and are harvested into `/opt/localrepo` so pacstrap can
install them into the target without the network.
**Important**: `localrepo/update.sh` auto-appends new package names to `packages.x86_64`. If you remove a package from `packages.x86_64` that exists in `localrepo/`, it will be re-added on the next `update.sh` run.
## Key Files
| File | Purpose |
|------|---------|
| `packages.x86_64` | Live ISO package list (~402 packages) |
| `profiledef.sh` | ISO metadata, compression, boot modes, build-stamp staging |
| `pacman.conf` | Repos: cachyos → core → extra → multilib → chaotic-aur → local-aur |
| `bootstrap_packages` | Minimal build-time packages (`base`, `arch-install-scripts`) |
| `airootfs/root/customize_airootfs.sh` | Runs inside chroot during build: keyrings, skel dotfiles (incl. end4-pC), qsConfig patch, end-4 `install-deps`, package harvest, uv/font pre-warm |
| `airootfs/root/.live-pacman.conf` | `/etc/pacman.conf` of the built image (adds `[local-aur]` = `file:///opt/localrepo`) |
| `airootfs/usr/local/bin/alvin-install` | Installer: partitions, pacstrap, LUKS (systemd initramfs **or** experimental unl0kr + optional TPM2 unlock), user, git identity + GitHub SSH keys, login manager (none/greetd/sddm/gdm) + autologin, end-4 dotfiles (`--skip-alldeps`), build-stamp motd, boot |
| `localrepo/build-end4-deps.sh` | Non-interactive AUR builds for end-4 dependencies |
| `localrepo/update.sh` | Regenerates localrepo DB, syncs names to packages.x86_64, syncs `airootfs/opt/localrepo/` |
## Gotchas
- The profile root is the **repo root** (not a `releng/` subdirectory). The CI build-iso workflow uses `mkarchiso -v -w work -o out/ releng` but this is a naming convention — the actual profile files live at the repo root.
- `customize_airootfs.sh` clones git repos (oh-my-zsh, lazy.nvim, plugins, end-4 dots) into `/etc/skel` and `/opt` during the ISO build. These require network access at build time but make the live ISO work offline.
- `customize_airootfs.sh` runs `./setup install-deps -f -s --skip-plasmaintg` as the throwaway user `ii-builder` (end-4's scripts refuse to run as root) and aborts the build if it fails. `--skip-plasmaintg` is deliberate: that optional Firefox widget pulls 410 packages / 526 MiB of KDE.
- The `[local-aur]` repo path in `pacman.conf` (`file:///home/alvin/alvinarch/localrepo`) is for local builds only. The CI does not use this path.
- The **image** ships its own `[local-aur]` at `file:///opt/localrepo` (see `.live-pacman.conf`). It holds `localrepo/` (copied by CI/`update.sh`) plus everything `install-deps` built. pacstrap runs without `-P`, so the target keeps the stock `/etc/pacman.conf`; `alvin-install` strips `[local-aur]` from it anyway as a safety net, because `/opt/localrepo` exists only on the medium.
- `alvin-install` runs end-4 with `--skip-alldeps` — dependencies must come from the ISO. It feeds `yes i` to end-4's failure prompt: inside the installer chroot the medium's `/run` is bind-mounted in, so end-4's `systemctl --machine=…@.host --user enable … --now` lines can never work (and `--now` would start services on the live medium). `install_end4_dots` re-applies the enable-only part (bluetooth, ydotool, i2c module) outside the chroot and reports every step end-4 had to skip. If the end-4 step reports "incomplete", check that `hyprctl`/`quickshell`/the venv were resolvable (harvest) before re-running anything.
- `/etc/skel/.cache/uv` + `/etc/skel/.local/share/uv/python` are pre-warmed by the build (~460 MB: CPython 3.12 and the pinned wheel cache) so end-4's `uv venv`/`uv pip install` at install time needs no network.
- **end4-pC** (`pctrade/end4-pC`) is the default quickshell config: cloned into `/etc/skel/.config/quickshell/end4-pC` at build time, selected by patching `hl.env("qsConfig", "ii")` → `"end4-pC"` in the **staged** `/opt/dots-hyprland/dots/.config/hypr/hyprland/variables.lua` (there is no `hypr/hyprland/` in this repo — `./setup install` copies it to the installed system). `alvin-install` re-copies end4-pC into the user's home *after* `./setup install`, because end-4's installer `rsync --delete`s all of `~/.config/quickshell`.
- `airootfs/etc/skel/.config/illogical-impulse/presets/` carries the user's presets (`Laptop.json`, `Personal-Performance.json`, `Personal-Performance.zip`). They embed `/home/alvin/...` paths, so wallpapers/screenshots need fixing up after install.
- End-4 metapackages are built from `localrepo/end4-pkgbuilds/` (quickshell-git, bibata-modern-classic-bin, microtex-git).
- `packages.x86_64` is sorted alphabetically. Keep it sorted when adding/removing entries.
- `airootfs/opt/localrepo/` is a build artifact (gitignored) — never commit it.
- **Build stamp flow**: `profiledef.sh` (sourced by mkarchiso) stages the gitignored `airootfs/root/.iso-build-stamp` when a `.git` dir exists **or** `CI`/`GITEA_ACTIONS` is set — line reads `AlvinArch build <date> | commit <date> | <4-char hash>` (falls back to `commit unknown` if `git -c safe.directory` can't read the repo; without `.git`/CI no file is staged). `customize_airootfs.sh` installs it as `/etc/alvin-build-stamp` on the live medium, and `alvin-install`'s `install_motd` copies the live `/etc/motd` banner to the target and appends the stamp. If the medium has no stamp, the installed system gets no motd from us.
+315 -857
View File
File diff suppressed because it is too large Load Diff
-32
View File
@@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFhTCCA22gAwIBAgIJBJPyuFHF1b7RMA0GCSqGSIb3DQEBDQUAMF8xDjAMBgNV
BAsTBUFyYm9yMQ4wDAYDVQQKEwVDaXNjbzE9MDsGA1UEAxM0Q2lzY28gU29mdHdh
cmUgSWRlbnRpdHkgUm9vdCBDQSBSU0EgNDA5NiBTSEE1MTIgMjA5OTAgFw0yNDAx
MjQxODQ1MjVaGA8yMDk5MDEyNDE4NDUyNVowXzEOMAwGA1UECxMFQXJib3IxDjAM
BgNVBAoTBUNpc2NvMT0wOwYDVQQDEzRDaXNjbyBTb2Z0d2FyZSBJZGVudGl0eSBS
b290IENBIFJTQSA0MDk2IFNIQTUxMiAyMDk5MIICIjANBgkqhkiG9w0BAQEFAAOC
Ag8AMIICCgKCAgEA14hoPbzqZxPr8Wqpq2H+tOib+DkQP80mUP6zAw3uu+eNygd+
jOBCenO6B7sp1sqCRT8QBQWQxNHVeVfMQN1vjMrqEMNh/eflVtOGy32UbkuQrVzj
2H+G1PtjeMQKa26LD8XPDUIOpj9rzPdjKFFfz13tm21gNIiVSTI34T5BS5BNEQj1
b+VQg+0kbANCOOTiTh+H/gxhpXRv8F3VNUrrPxA7a3WF5jhZZoPBns1LuBDW0fQ0
av6q/uEWtfxMdSNsAxYWVhO90Nx4khOISA1Fs1h1klGsee5XZkLKdUWedZQzbUz1
f7VPRxX+ddcK0Js2VPvxemMf2WaTbkrEi62y/cOaxqDs2xDTWEXrgOYYEfQ+RoeY
pbzBCaErqZvCeOgrnXFSHSyyd9+dTOxJuypBH+AWKtmkQMQQ7RQJSkGvrP9NgRxD
MXb1U4kpVn7kEEhv6telV9E8R635Zm4h/H9FQyc2LrLOuL5UPewMMWt8HqPbs2Xc
n1kTLvpEDciDJDRvu4XuBsjgQMA0rlt5BHAmZdGO5Dq4+ARWAYrzN9+M0dK+0phT
T9OOHItIL6wXcIiYLZBJlHfiemCByIcBBEYaRwdt3VP9tTl0F370StI2t1RMDPgt
xHcsYqN09QG/tWzwr/yNckFhVs/+UGQWslv2/W6eiKge5REUFuxT6i7V6oUCAwEA
AaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
FLd8Wz4X/JJ6Oi/+znsT0DTPuju8MA0GCSqGSIb3DQEBDQUAA4ICAQCZEut7iqp8
39u7CHD8zMrvOMmUKtJ7G1MrhkJfdyek8g7ArG74bgcxM3ptwDusdFgKh/mmCj/m
FU6TNjsufZ9hAyOE16ZtGflkOrRlihPQThDdGCxQjRsLVQa9S0IDkM1v1ZqvIMEc
PJOj3rhvkIJVjpHc0AZQP/TnaT/7dKD1wFOSNYwzdvE2HKVNA8XbeS9TNpHqYPvE
2gX6vQ7Pdn9DIF6YOmOuBobmaD1G7WbDz5Kvz5e3FdkzR+K3sGW4Qsr3OLt25dQS
H+x7X06fihUxhEgRJJp2cPKABSKVR2hoyzKNEbzgtV25gH7lr+EHA6CQYltkVpyM
4v1+PdX1EGY0+rAO+NsRwa6ndFteofJLh9PbvxHp0jGWnT1KF4lhmEyyka9JKbqT
yiyGzDsw/YA9NxiAsp/Ex8aYXX1/SeM/kb6dp7tytsHewwflns1jfGqRVyrXQ41x
CmmSioBvtZiry8BJTa8xIUWEsBL1pTl2RZrPDAw/qD10K2XJfh5HYFSkIppoIO+9
0wN8TYcXbyY+JnU/g32AvkmA3o8lotK6nbwuf7MAFdtPHMA4F8mPM3jADc1uGu9O
YweaA1c+P5KEOyr325cgsT04x4oeyvP3c3XMLpDpSgbzhfc9WyLYCf3R3jHlst1A
KaDwBk2xoE3knxihYjbcRfjaaYdUkWY4mg==
-----END CERTIFICATE-----
+3 -2
View File
@@ -1,7 +1,8 @@
To install Arch Linux follow the installation guide:
To install Arch Linux, follow the installation guide,
or run alvin-install for an automated setup.
https://wiki.archlinux.org/title/Installation_guide
For Wi-Fi, authenticate to the wireless network using the iwctl utility.
For Wi-Fi, run nmtui to configure a wireless network.
For mobile broadband (WWAN) modems, connect with the mmcli utility.
Ethernet, WLAN and WWAN interfaces using DHCP should work automatically.
@@ -0,0 +1,10 @@
[Trigger]
Type = Package
Operation = Install
Operation = Upgrade
Target = *
[Action]
Description = Ensuring /dev/stdin exists...
When = PreTransaction
Exec = /usr/bin/sh -c "[ -e /dev/stdin ] || ln -sf /proc/self/fd/0 /dev/stdin; [ -e /dev/stdout ] || ln -sf /proc/self/fd/1 /dev/stdout; [ -e /dev/stderr ] || ln -sf /proc/self/fd/2 /dev/stderr"
+6
View File
@@ -0,0 +1,6 @@
# Bat configuration
--theme="Catppuccin Mocha"
--style="numbers,changes,header"
--map-syntax="*.conf:INI"
--map-syntax=".gitconfig:Git Config"
--map-syntax=" Kitty:kitty"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
# Auto start Hyprland on tty1
if test -z "$DISPLAY" ;and test "$XDG_VTNR" -eq 1
mkdir -p ~/.cache
exec start-hyprland > ~/.cache/hyprland.log 2>&1
end
@@ -0,0 +1,7 @@
complete --command fisher --exclusive --long help --description "Print help"
complete --command fisher --exclusive --long version --description "Print version"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments install --description "Install plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments update --description "Update installed plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments remove --description "Remove installed plugins"
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments list --description "List installed plugins matching regex"
complete --command fisher --exclusive --condition "__fish_seen_subcommand_from update remove" --arguments "(fisher list)"
@@ -0,0 +1,21 @@
complete --command nvm --exclusive
complete --command nvm --exclusive --long version --description "Print version"
complete --command nvm --exclusive --long help --description "Print help"
complete --command nvm --long silent --description "Suppress standard output"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments install --description "Download and activate the specified Node version"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments use --description "Activate the specified Node version in the current shell"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments list --description "List installed Node versions"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments list-remote --description "List available Node versions to install"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments current --description "Print the currently-active Node version"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from install" --arguments "(
test -e $nvm_data && string split ' ' <$nvm_data/.index
)"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from use" --arguments "(_nvm_list | string split ' ')"
complete --command nvm --exclusive --condition __fish_use_subcommand --arguments uninstall --description "Uninstall the specified Node version"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from uninstall" --arguments "(
_nvm_list | string split ' ' | string replace system ''
)"
complete --command nvm --exclusive --condition "__fish_seen_subcommand_from use uninstall" --arguments "(
set --query nvm_default_version && echo default
)"
@@ -0,0 +1,14 @@
# This file was created by fish when upgrading to version 4.3, to migrate
# the 'fish_key_bindings' variable from its old default scope (universal)
# to its new default scope (global). We recommend you delete this file
# and configure key bindings in ~/.config/fish/config.fish if needed.
# set --global fish_key_bindings fish_default_key_bindings
# Prior to version 4.3, fish shipped an event handler that runs
# `set --universal fish_key_bindings fish_default_key_bindings`
# whenever the fish_key_bindings variable is erased.
# This means that as long as any fish < 4.3 is still running on this system,
# we cannot complete the migration.
# As a workaround, erase the universal variable at every shell startup.
set --erase --universal fish_key_bindings
@@ -0,0 +1,37 @@
# This file was created by fish when upgrading to version 4.3, to migrate
# theme variables from universal to global scope.
# Don't edit this file, as it will be written by the web-config tool (`fish_config`).
# To customize your theme, delete this file and see
# help interactive#syntax-highlighting
# or
# man fish-interactive | less +/^SYNTAX.HIGHLIGHTING
# for appropriate commands to add to ~/.config/fish/config.fish instead.
# See also the release notes for fish 4.3.0 (run `help relnotes`).
set --global fish_color_autosuggestion 555 brblack
set --global fish_color_cancel -r
set --global fish_color_command blue
set --global fish_color_comment red
set --global fish_color_cwd green
set --global fish_color_cwd_root red
set --global fish_color_end green
set --global fish_color_error brred
set --global fish_color_escape brcyan
set --global fish_color_history_current --bold
set --global fish_color_host normal
set --global fish_color_host_remote yellow
set --global fish_color_normal normal
set --global fish_color_operator brcyan
set --global fish_color_param cyan
set --global fish_color_quote yellow
set --global fish_color_redirection cyan --bold
set --global fish_color_search_match --background=111
set --global fish_color_selection white --bold --background=brblack
set --global fish_color_status red
set --global fish_color_user brgreen
set --global fish_color_valid_path --underline
set --global fish_pager_color_completion normal
set --global fish_pager_color_description B3A06D yellow -i
set --global fish_pager_color_prefix cyan --bold --underline
set --global fish_pager_color_progress brwhite --background=cyan
set --global fish_pager_color_selected_background -r
@@ -0,0 +1,28 @@
set --query XDG_DATA_HOME || set --local XDG_DATA_HOME ~/.local/share
set --query nvm_mirror || set --global nvm_mirror https://nodejs.org/dist
set --query nvm_data || set --global nvm_data $XDG_DATA_HOME/nvm
function _nvm_install --on-event nvm_install
test ! -d $nvm_data && command mkdir -p $nvm_data
echo "Downloading the Node distribution index..." 2>/dev/null
_nvm_index_update
end
function _nvm_update --on-event nvm_update
set --query --universal nvm_data && set --erase --universal nvm_data
set --query --universal nvm_mirror && set --erase --universal nvm_mirror
set --query nvm_mirror || set --global nvm_mirror https://nodejs.org/dist
end
function _nvm_uninstall --on-event nvm_uninstall
command rm -rf $nvm_data
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
set --names | string replace --filter --regex -- "^nvm" "set --erase nvm" | source
functions --erase (functions --all | string match --entire --regex -- "^_nvm_")
end
if status is-interactive && set --query nvm_default_version && ! set --query nvm_current_version
nvm use --silent $nvm_default_version
end
@@ -0,0 +1,33 @@
# Commands to run in interactive sessions can go here
if status is-interactive
# No greeting
set fish_greeting
# Use starship
function starship_transient_prompt_func
starship module character
end
if test "$TERM" != "linux"
starship init fish | source
enable_transience
end
# Colors
if test -f ~/.local/state/quickshell/user/generated/terminal/sequences.txt
cat ~/.local/state/quickshell/user/generated/terminal/sequences.txt
end
# Aliases
# kitty doesn't clear properly so we need to do this weird printing
alias clear "printf '\033[2J\033[3J\033[1;1H'"
alias celar "printf '\033[2J\033[3J\033[1;1H'"
alias claer "printf '\033[2J\033[3J\033[1;1H'"
alias pamcan pacman
alias q 'qs -c end4-pC'
if test "$TERM" != "linux"
alias ls 'eza --icons'
end
if test "$TERM" = "xterm-kitty"
alias ssh 'kitten ssh'
end
end
@@ -0,0 +1,2 @@
jorgebucaran/fisher
jorgebucaran/nvm.fish
@@ -0,0 +1,7 @@
# This file contains fish universal variable definitions.
# VERSION: 3.0
SETUVAR __fish_initialized:4300
SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fisher\x2efish\x1e\x7e/\x2econfig/fish/completions/fisher\x2efish
SETUVAR _fisher_jorgebucaran_2F_nvm_2E_fish_files:\x7e/\x2econfig/fish/functions/_nvm_index_update\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_list\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_version_activate\x2efish\x1e\x7e/\x2econfig/fish/functions/_nvm_version_deactivate\x2efish\x1e\x7e/\x2econfig/fish/functions/nvm\x2efish\x1e\x7e/\x2econfig/fish/conf\x2ed/nvm\x2efish\x1e\x7e/\x2econfig/fish/completions/nvm\x2efish
SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ejorgebucaran/nvm\x2efish
SETUVAR _fisher_upgraded_to_4_4:\x1d
@@ -0,0 +1,20 @@
function _nvm_index_update
test ! -d $nvm_data && command mkdir -p $nvm_data
set --local index $nvm_data/.index
if not command curl -q --location --silent $nvm_mirror/index.tab >$index.temp
command rm -f $index.temp
echo "nvm: Can't update index, host unavailable: \"$nvm_mirror\"" >&2
return 1
end
command awk -v OFS=\t '
/v0.9.12/ { exit } # Unsupported
NR > 1 {
print $1 (NR == 2 ? " latest" : $10 != "-" ? " lts/" tolower($10) : "")
}
' $index.temp >$index
command rm -f $index.temp
end
@@ -0,0 +1,14 @@
function _nvm_list
set --local versions $nvm_data/*
set --query versions[1] &&
string match --entire --regex -- (
string replace --all -- $nvm_data/ "" $versions |
string match --regex -- "v\d.+" |
string escape --style=regex |
string join "|"
) <$nvm_data/.index
command --all node |
string match --quiet --invert --regex -- "^$nvm_data" && echo system
end
@@ -0,0 +1,4 @@
function _nvm_version_activate --argument-names ver
set --global --export nvm_current_version $ver
set --prepend PATH $nvm_data/$ver/bin
end
@@ -0,0 +1,5 @@
function _nvm_version_deactivate --argument-names ver
test "$nvm_current_version" = "$ver" && set --erase nvm_current_version
set --local index (contains --index -- $nvm_data/$ver/bin $PATH) &&
set --erase PATH[$index]
end
@@ -0,0 +1,3 @@
function edit --wraps=nvim --description 'alias edit=nvim'
nvim $argv
end
@@ -0,0 +1,251 @@
function fisher --argument-names cmd --description "A plugin manager for Fish"
set --query fisher_path || set --local fisher_path $__fish_config_dir
set --local fisher_version 4.4.8
set --local fish_plugins $__fish_config_dir/fish_plugins
switch "$cmd"
case -v --version
echo "fisher, version $fisher_version"
case "" -h --help
echo "Usage: fisher install <plugins...> Install plugins"
echo " fisher remove <plugins...> Remove installed plugins"
echo " fisher uninstall <plugins...> Remove installed plugins (alias)"
echo " fisher update <plugins...> Update installed plugins"
echo " fisher update Update all installed plugins"
echo " fisher list [<regex>] List installed plugins matching regex"
echo "Options:"
echo " -v, --version Print version"
echo " -h, --help Print this help message"
echo "Variables:"
echo " \$fisher_path Plugin installation path. Default: $__fish_config_dir" | string replace --regex -- $HOME \~
case ls list
string match --entire --regex -- "$argv[2]" $_fisher_plugins
case install update remove uninstall
isatty || read --local --null --array stdin && set --append argv $stdin
test "$cmd" = uninstall && set cmd remove
set --local install_plugins
set --local update_plugins
set --local remove_plugins
set --local arg_plugins $argv[2..-1]
set --local old_plugins $_fisher_plugins
set --local new_plugins
test -e $fish_plugins && set --local file_plugins (string match --regex -- '^[^\s]+$' <$fish_plugins | string replace -- \~ ~)
if ! set --query argv[2]
if test "$cmd" != update
echo "fisher: Not enough arguments for command: \"$cmd\"" >&2 && return 1
else if ! set --query file_plugins
echo "fisher: \"$fish_plugins\" file not found: \"$cmd\"" >&2 && return 1
end
set arg_plugins $file_plugins
else if test "$cmd" = install && ! set --query old_plugins[1]
set --append arg_plugins $file_plugins
end
for plugin in $arg_plugins
set plugin (test -e "$plugin" && realpath $plugin || string lower -- $plugin)
contains -- "$plugin" $new_plugins || set --append new_plugins $plugin
end
if set --query argv[2]
for plugin in $new_plugins
if contains -- "$plugin" $old_plugins
test "$cmd" = remove &&
set --append remove_plugins $plugin ||
set --append update_plugins $plugin
else if test "$cmd" = install
set --append install_plugins $plugin
else
echo "fisher: Plugin not installed: \"$plugin\"" >&2 && return 1
end
end
else
for plugin in $new_plugins
contains -- "$plugin" $old_plugins &&
set --append update_plugins $plugin ||
set --append install_plugins $plugin
end
for plugin in $old_plugins
contains -- "$plugin" $new_plugins || set --append remove_plugins $plugin
end
end
set --local pid_list
set --local source_plugins
set --local fetch_plugins $update_plugins $install_plugins
set --local fish_path (status fish-path)
echo (set_color --bold)fisher $cmd version $fisher_version(set_color normal)
for plugin in $fetch_plugins
set --local source (command mktemp -d)
set --append source_plugins $source
command mkdir -p $source/{completions,conf.d,themes,functions}
$fish_path --command "
if test -e $plugin
command cp -Rf $plugin/* $source
else
set resp (command mktemp)
set temp (command mktemp -d)
set repo (string split -- \@ $plugin) || set repo[2] HEAD
if set path (string replace --regex -- '^(https://)?gitlab.com/' '' \$repo[1])
set name (string split -- / \$path)[-1]
set url https://gitlab.com/\$path/-/archive/\$repo[2]/\$name-\$repo[2].tar.gz
else
set url https://api.github.com/repos/\$repo[1]/tarball/\$repo[2]
end
echo Fetching (set_color --underline)\$url(set_color normal)
set http (command curl -q --silent -L -o \$resp -w %{http_code} \$url)
if test \"\$http\" = 200 && command tar -xzC \$temp -f \$resp 2>/dev/null
command cp -Rf \$temp/*/* $source
else if test \"\$http\" = 403
echo fisher: GitHub API rate limit exceeded \(HTTP 403\) >&2
command rm -rf $source
else
echo fisher: Invalid plugin name or host unavailable: \\\"$plugin\\\" >&2
command rm -rf $source
end
command rm -rf \$temp
end
set files $source/* && string match --quiet --regex -- .+\.fish\\\$ \$files
" &
set --append pid_list (jobs --last --pid)
end
wait $pid_list 2>/dev/null
for plugin in $fetch_plugins
if set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)] && test ! -e $source
if set --local index (contains --index -- "$plugin" $install_plugins)
set --erase install_plugins[$index]
else
set --erase update_plugins[(contains --index -- "$plugin" $update_plugins)]
end
end
end
for plugin in $update_plugins $remove_plugins
if set --local index (contains --index -- "$plugin" $_fisher_plugins)
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
if contains -- "$plugin" $remove_plugins
for name in (string replace --filter --regex -- '.+/conf\.d/([^/]+)\.fish$' '$1' $$plugin_files_var)
emit {$name}_uninstall
end
printf "%s\n" Removing\ (set_color red --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
set --erase _fisher_plugins[$index]
end
command rm -rf (string replace -- \~ ~ $$plugin_files_var)
functions --erase (string replace --filter --regex -- '.+/functions/([^/]+)\.fish$' '$1' $$plugin_files_var)
for name in (string replace --filter --regex -- '.+/completions/([^/]+)\.fish$' '$1' $$plugin_files_var)
complete --erase --command $name
end
set --erase $plugin_files_var
end
end
if set --query update_plugins[1] || set --query install_plugins[1]
command mkdir -p $fisher_path/{functions,themes,conf.d,completions}
end
for plugin in $update_plugins $install_plugins
set --local source $source_plugins[(contains --index -- "$plugin" $fetch_plugins)]
set --local files $source/{functions,themes,conf.d,completions}/*
if set --local index (contains --index -- $plugin $install_plugins)
set --local user_files $fisher_path/{functions,themes,conf.d,completions}/*
set --local conflict_files
for file in (string replace -- $source/ $fisher_path/ $files)
contains -- $file $user_files && set --append conflict_files $file
end
if set --query conflict_files[1] && set --erase install_plugins[$index]
echo -s "fisher: Cannot install \"$plugin\": please remove or move conflicting files first:" \n" "$conflict_files >&2
continue
end
end
for file in (string replace -- $source/ "" $files)
command cp -RLf $source/$file $fisher_path/$file
end
set --local plugin_files_var _fisher_(string escape --style=var -- $plugin)_files
set --query files[1] && set --universal $plugin_files_var (string replace -- $source $fisher_path $files | string replace -- ~ \~)
contains -- $plugin $_fisher_plugins || set --universal --append _fisher_plugins $plugin
contains -- $plugin $install_plugins && set --local event install || set --local event update
printf "%s\n" Installing\ (set_color --bold)$plugin(set_color normal) " "$$plugin_files_var | string replace -- \~ ~
for file in (string match --regex -- '.+/[^/]+\.fish$' $$plugin_files_var | string replace -- \~ ~)
source $file
if set --local name (string replace --regex -- '.+conf\.d/([^/]+)\.fish$' '$1' $file)
emit {$name}_$event
end
end
end
command rm -rf $source_plugins
if set --query _fisher_plugins[1]
set --local commit_plugins
for plugin in $file_plugins
contains -- (string lower -- $plugin) (string lower -- $_fisher_plugins) && set --append commit_plugins $plugin
end
for plugin in $_fisher_plugins
contains -- (string lower -- $plugin) (string lower -- $commit_plugins) || set --append commit_plugins $plugin
end
string replace --regex -- $HOME \~ $commit_plugins >$fish_plugins
else
set --erase _fisher_plugins
command rm -f $fish_plugins
end
set --local total (count $install_plugins) (count $update_plugins) (count $remove_plugins)
test "$total" != "0 0 0" && echo (string join ", " (
test $total[1] = 0 || echo "Installed $total[1]") (
test $total[2] = 0 || echo "Updated $total[2]") (
test $total[3] = 0 || echo "Removed $total[3]")
) plugin/s
case \*
echo "fisher: Unknown command: \"$cmd\"" >&2 && return 1
end
end
if ! set --query _fisher_upgraded_to_4_4
set --universal _fisher_upgraded_to_4_4
if functions --query _fisher_list
set --query XDG_DATA_HOME[1] || set --local XDG_DATA_HOME ~/.local/share
command rm -rf $XDG_DATA_HOME/fisher
functions --erase _fisher_{list,plugin_parse}
fisher update >/dev/null 2>/dev/null
else
for var in (set --names | string match --entire --regex '^_fisher_.+_files$')
set $var (string replace -- ~ \~ $$var)
end
functions --erase _fisher_fish_postexec
end
end
@@ -0,0 +1,3 @@
function lzd --wraps=lazydocker --description 'alias lzd=lazydocker'
lazydocker $argv
end
@@ -0,0 +1,237 @@
function nvm --description "Node version manager"
for silent in --silent -s
if set --local index (contains --index -- $silent $argv)
set --erase argv[$index] && break
end
set --erase silent
end
set --local cmd $argv[1]
set --local ver $argv[2]
if set --query silent && ! set --query cmd[1]
echo "nvm: Version number not specified (see nvm -h for usage)" >&2
return 1
end
if ! set --query ver[1] && contains -- "$cmd" install use
for file in .nvmrc .node-version
set file (_nvm_find_up $PWD $file) && read ver <$file && break
end
if ! set --query ver[1]
echo "nvm: Invalid version or missing \".nvmrc\" file" >&2
return 1
end
end
set --local their_version $ver
switch "$cmd"
case -v --version
echo "nvm, version 2.2.18"
case "" -h --help
echo "Usage: nvm install <version> Download and activate the specified Node version"
echo " nvm install Install the version specified in the nearest .nvmrc file"
echo " nvm use <version> Activate the specified Node version in the current shell"
echo " nvm use Activate the version specified in the nearest .nvmrc file"
echo " nvm list List installed Node versions"
echo " nvm list-remote List available Node versions to install"
echo " nvm list-remote <regex> List Node versions matching a given regex pattern"
echo " nvm current Print the currently-active Node version"
echo " nvm uninstall <version> Uninstall the specified Node version"
echo "Options:"
echo " -s, --silent Suppress standard output"
echo " -v, --version Print the version of nvm"
echo " -h, --help Print this help message"
echo "Variables:"
echo " nvm_arch Override architecture, e.g. x64-musl"
echo " nvm_mirror Use a mirror for downloading Node binaries"
echo " nvm_default_version Set the default version for new shells"
echo " nvm_default_packages Install a list of packages every time a Node version is installed"
echo " nvm_data Set a custom directory for storing nvm data"
echo "Examples:"
echo " nvm install latest Install the latest version of Node"
echo " nvm use 14.15.1 Use Node version 14.15.1"
echo " nvm use system Activate the system's Node version"
case install
_nvm_index_update
string match --entire --regex -- (_nvm_version_match $ver) <$nvm_data/.index | read ver alias
if ! set --query ver[1]
echo "nvm: Invalid version number or alias: \"$their_version\"" >&2
return 1
end
if test ! -e $nvm_data/$ver
set --local os (command uname -s | string lower)
set --local ext tar.gz
set --local arch (command uname -m)
set --local tarcmd tar
switch $os
case aix
set arch ppc64
case sunos
case linux
case darwin
case {msys_nt,mingw\*_nt}\*
set os win
set ext zip
set tarcmd bsdtar
case \*
echo "nvm: Unsupported operating system: \"$os\"" >&2
return 1
end
switch $arch
case i\*86
set arch x86
case x86_64
set arch x64
case arm64
string match --regex --quiet "v(?<major>\d+)" $ver
if test "$os" = darwin -a $major -lt 16
set arch x64
end
case armv6 armv6l
set arch armv6l
case armv7 armv7l
set arch armv7l
case armv8 armv8l aarch64
set arch arm64
end
set --query nvm_arch && set arch $nvm_arch
set --local dir "node-$ver-$os-$arch"
set --local url $nvm_mirror/$ver/$dir.$ext
command mkdir -p $nvm_data/$ver
if ! set --query silent
echo -e "Installing Node \x1b[1m$ver\x1b[22m $alias"
echo -e "Fetching \x1b[4m$url\x1b[24m\x1b[7m"
end
if ! command curl -q $silent --progress-bar --location $url |
command $tarcmd --extract --gzip --directory $nvm_data/$ver 2>/dev/null
command rm -rf $nvm_data/$ver
echo -e "\033[F\33[2K\x1b[0mnvm: Invalid mirror or host unavailable: \"$url\"" >&2
return 1
end
set --query silent || echo -en "\033[F\33[2K\x1b[0m"
if test "$os" = win
command mv $nvm_data/$ver/$dir $nvm_data/$ver/bin
else
command mv $nvm_data/$ver/$dir/* $nvm_data/$ver
command rm -rf $nvm_data/$ver/$dir
end
end
if test $ver != "$nvm_current_version"
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
_nvm_version_activate $ver
set --query nvm_default_packages[1] && npm install --global $silent $nvm_default_packages
end
set --query silent || printf "Now using Node %s (npm %s) %s\n" (_nvm_node_info)
case use
test $ver = default && set ver $nvm_default_version
_nvm_list | string match --entire --regex -- (_nvm_version_match $ver) | read ver __
if ! set --query ver[1]
echo "nvm: Can't use Node \"$their_version\", version must be installed first" >&2
return 1
end
if test $ver != "$nvm_current_version"
set --query nvm_current_version && _nvm_version_deactivate $nvm_current_version
test $ver != system && _nvm_version_activate $ver
end
set --query silent || printf "Now using Node %s (npm %s) %s\n" (_nvm_node_info)
case uninstall
if test -z "$ver"
echo "nvm: Not enough arguments for command: \"$cmd\"" >&2
return 1
end
test $ver = default && test ! -z "$nvm_default_version" && set ver $nvm_default_version
_nvm_list | string match --entire --regex -- (_nvm_version_match $ver) | read ver __
if ! set -q ver[1]
echo "nvm: Node version not installed or invalid: \"$their_version\"" >&2
return 1
end
set --query silent || printf "Uninstalling Node %s %s\n" $ver (string replace ~ \~ "$nvm_data/$ver/bin/node")
_nvm_version_deactivate $ver
command rm -rf $nvm_data/$ver
case current
_nvm_current
case ls list
_nvm_list | _nvm_list_format (_nvm_current) $argv[2]
case lsr {ls,list}-remote
_nvm_index_update || return
_nvm_list | command awk '
FILENAME == "-" && (is_local[$1] = FNR == NR) { next } {
print $0 (is_local[$1] ? " ✓" : "")
}
' - $nvm_data/.index | _nvm_list_format (_nvm_current) $argv[2]
case \*
echo "nvm: Unknown command or option: \"$cmd\" (see nvm -h for usage)" >&2
return 1
end
end
function _nvm_find_up --argument-names path file
test -e "$path/$file" && echo $path/$file || begin
test ! -z "$path" || return
_nvm_find_up (string replace --regex -- '/[^/]*$' "" $path) $file
end
end
function _nvm_version_match --argument-names ver
string replace --regex -- '^v?(\d+|\d+\.\d+)$' 'v$1.' $ver |
string replace --filter --regex -- '^v?(\d+)' 'v$1' |
string escape --style=regex || string lower '\b'$ver'(?:/\w+)?$'
end
function _nvm_list_format --argument-names current regex
command awk -v current="$current" -v regex="$regex" '
$0 ~ regex {
aliases[versions[i++] = $1] = $2 " " $3
pad = (n = length($1)) > pad ? n : pad
}
END {
if (!i) exit 1
while (i--)
printf((current == versions[i] ? " ▶ " : " ") "%"pad"s %s\n",
versions[i], aliases[versions[i]])
}
'
end
function _nvm_current
command --search --quiet node || return
set --query nvm_current_version && echo $nvm_current_version || echo system
end
function _nvm_node_info
set --local npm_path (string replace bin/npm-cli.js "" (realpath (command --search npm)))
test -f $npm_path/package.json || set --local npm_version_default (command npm --version)
command node --eval "
console.log(process.version)
console.log('$npm_version_default' ? '$npm_version_default': require('$npm_path/package.json').version)
console.log(process.execPath)
" | string replace -- ~ \~
end
@@ -0,0 +1,3 @@
function precmd --wraps="print -Pn '\\e]133;D;%?\\a\\e]133;A\\a'" --description "alias precmd=print -Pn '\\e]133;D;%?\\a\\e]133;A\\a'"
print -Pn '\e]133;D;%?\a\e]133;A\a' $argv
end
@@ -0,0 +1,3 @@
function preexec --wraps="print -Pn '\\e]133;B\\a\\e]133;C\\a'" --description "alias preexec=print -Pn '\\e]133;B\\a\\e]133;C\\a'"
print -Pn '\e]133;B\a\e]133;C\a' $argv
end
@@ -0,0 +1,41 @@
function update --description 'Automatically finds binarys and uses update commands'
if command -v pacman >/dev/null && command -v yay >/dev/null
echo "✅ 'pacman' and 'yay' found. Updating."
sudo pacman -Syu --noconfirm
yay -Syu --sudoloop --save --answerclean None --answerdiff None --noconfirm
else if command -v pacman >/dev/null
echo "✅ 'pacman' found. Updating."
sudo pacman -Syu --noconfirm
end
if command -v paru >/dev/null
echo "✅ 'paru' found. Updating."
paru -Syu
end
if command -v apt >/dev/null
echo "✅ 'apt' found. Updating."
sudo apt update && sudo apt full-upgrade -y
end
if command -v hyprpm >/dev/null
echo "✅ 'hyprpm' found. Updating."
hyprpm reload
sleep 2
hyprpm update
end
if command -v flatpak >/dev/null
echo "✅ 'flatpak' found. Updating."
flatpak update -y
end
if command -v npm >/dev/null
echo "✅ 'npm' found. Updating."
sudo npm install -g npm-check-updates
end
if command -v omz >/dev/null
omz update
end
end
@@ -0,0 +1,15 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
--
hl.env("XCURSOR_THEME", "Catppuccin Macchiato Dark")
hl.env("XCURSOR_SIZE", "24")
hl.env("HYPRCURSOR_THEME", "Catppuccin Macchiato Dark")
hl.env("HYPRCURSOR_SIZE", "24")
hl.env("WEBKIT_DISABLE_DMABUF_RENDERER", "1")
ecosystem = {
no_donation_nag = true,
no_update_news = false,
}
@@ -0,0 +1,8 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
hl.on("hyprland.start", function()
hl.exec_cmd("hyprctl setcursor 'Catppuccin Macchiato Dark' 24")
hl.exec_cmd("kdeconnectd &")
end)
@@ -0,0 +1,9 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
hl.config({
input = {
kb_options = "caps:escape",
},
})
@@ -0,0 +1,79 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
--##! Overrides
--# Unbind upstream binds we want to replace
hl.unbind("SUPER + B") -- sidebar toggle -> we use this for browser
hl.unbind("SUPER + T") -- terminal (we don't want this combo)
hl.unbind("CTRL + ALT + T") -- terminal (we don't want this combo)
hl.unbind("SUPER + W") -- browser (we use B instead)
hl.unbind("SUPER + ALT + Page_Up")
hl.unbind("SUPER + ALT + Page_Down")
hl.unbind("SUPER + SHIFT + Page_Up")
hl.unbind("SUPER + SHIFT + Page_Down")
hl.unbind("SUPER + O")
hl.unbind("SUPER + X")
--# Unbind workspace focus with named keys (we use code: keys)
for i = 0, 9 do
hl.unbind("SUPER + " .. i)
end
--# Rebind browser on B (previously sidebar toggle)
hl.bind("SUPER + B", hl.dsp.exec_cmd(browser), { description = "App: Browser" })
--# Rebind Obsidian
hl.bind(
"SUPER + X",
hl.dsp.exec_cmd("/home/alvin/.local/bin/Obsidian.AppImage --password-store=gnome-libsecret"),
{ description = "App: Obsidian" }
)
--##! Workspace
--# Switching with raw keycodes (layout-independent)
for i = 1, 10 do
local numberkey = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }
hl.bind("SUPER + code:" .. numberkey[i], function()
hl.dispatch(hl.dsp.focus({ workspace = workspace_in_group(i) }))
end)
end
--# keypad numbers
for i = 1, 10 do
local numpadkey = { 87, 88, 89, 83, 84, 85, 79, 80, 81, 90 }
hl.bind("SUPER + code:" .. numpadkey[i], function()
hl.dispatch(hl.dsp.focus({ workspace = workspace_in_group(i) }))
end)
end
--#/# bind = SUPER+CTRL, code:,, -- Send to workspace & switch
for i = 1, 10 do
local numberkey = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }
hl.bind("SUPER + CTRL + code:" .. numberkey[i], function()
hl.dispatch(hl.dsp.window.move({ workspace = workspace_in_group(i), follow = true }))
end)
end
--# keypad numbers
for i = 1, 10 do
local numpadkey = { 87, 88, 89, 83, 84, 85, 79, 80, 81, 90 }
hl.bind("SUPER + CTRL + code:" .. numpadkey[i], function()
hl.dispatch(hl.dsp.window.move({ workspace = workspace_in_group(i), follow = true }))
end)
end
--#/# bind = SUPER+ALT+SHIFT, Page_↑/↓,, -- Send to workspace left/right
for i = 1, 6 do
local key = { "SUPER + ALT + Page_", "SUPER + SHIFT + Page_", "CTRL + SUPER + SHIFT + " }
local keycombos =
{ key[1] .. "down", key[1] .. "up", key[2] .. "down", key[2] .. "up", key[3] .. "Right", key[3] .. "Left" }
local prefix = { "+", "-", "r+", "r-", "r+", "r-" }
hl.bind(keycombos[i], hl.dsp.window.move({ workspace = prefix[i] .. "1" })) -- # [hidden]
end
--##! Utilities
--#/# bind = SUPER+SHIFT+V, -- Paste as keystrokes
hl.bind(
"SUPER + SHIFT + V",
hl.dsp.exec_cmd("/home/alvin/.config/hypr/custom/scripts/paste-as-type.sh"),
{ description = "App: Browser Script" }
)
@@ -0,0 +1,3 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
@@ -0,0 +1,2 @@
#!/bin/bash
# The content of this script will be generated by switchwall.sh - Don't modify it by yourself.
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Grab text content from wayland clipboard
text=$(wl-paste --no-newline 2>/dev/null)
if [ -n "$text" ]; then
# Type out the clipboard string using ydotool
ydotool type -- "$text"
fi
@@ -0,0 +1,8 @@
-- This file will not be overwritten across dots-hyprland updates.
-- The file name is for the sake of organization and does not matter
-- See the corresponding files in ~/.config/hypr/hyprland for examples
terminal = "kitty"
browser = "zen-browser"
codeEditor = "nvim"
textEditor = "obsidian"
@@ -0,0 +1,677 @@
{
"appearance": {
"extraBackgroundTint": true,
"fakeScreenRounding": 0,
"fonts": {
"expressive": "Space Grotesk",
"iconNerd": "JetBrains Mono NF",
"main": "Google Sans Flex",
"monospace": "JetBrains Mono NF",
"numbers": "Google Sans Flex",
"reading": "Readex Pro",
"title": "Google Sans Flex"
},
"palette": {
"accentColor": "",
"type": "scheme-tonal-spot"
},
"transparency": {
"automatic": true,
"backgroundTransparency": 0.11,
"contentTransparency": 0.57,
"enable": false
},
"wallpaperTheming": {
"enableAppsAndShell": true,
"enableQtApps": true,
"enableTerminal": true,
"terminalGenerationProps": {
"forceDarkMode": false,
"harmonizeThreshold": 100,
"harmony": 0.5,
"termFgBoost": 0.35
}
}
},
"apps": {
"bluetooth": "kcmshell6 kcm_bluetooth",
"changePassword": "kitty -1 --hold=yes fish -i -c 'passwd'",
"manageUser": "kcmshell6 kcm_users",
"network": "kcmshell6 kcm_networkmanagement",
"networkEthernet": "kcmshell6 kcm_networkmanagement",
"taskManager": "plasma-systemmonitor --page-name Processes",
"terminal": "kitty -1",
"update": "kitty -1 --hold=yes fish -i -c 'pkexec pacman -Syu'",
"volumeMixer": "~/.config/hypr/hyprland/scripts/launch_first_available.sh \"pavucontrol-qt\" \"pavucontrol\""
},
"background": {
"blurRadius": 32,
"centeredWallpaper": false,
"centeredWallpaperColor": "primaryContainer",
"centeredWallpaperOnlyWhenLocked": false,
"centeredWallpaperShape": "Cookie7Sided",
"centeredWallpaperSize": 400,
"enableWallpaperPreview": false,
"hideWhenFullscreen": true,
"lockWall": "",
"parallax": {
"autoVertical": false,
"enableSidebar": true,
"enableWorkspace": true,
"vertical": false,
"widgetsFactor": 1.2,
"workspaceZoom": 1.07
},
"screenList": [],
"showBlur": true,
"showGrid": true,
"showSnapLines": true,
"splitRatio": "25",
"splitSide": "right",
"thumbnailPath": "",
"wallpaperAnimation": "random",
"wallpaperPath": "/home/alvin/Pictures/Wallpapers/Dynamic-Wallpapers/Dark/japan-street-Dark.png",
"widgets": {
"blurRadius": 32,
"blurWidgets": false,
"calendar": {
"enable": true,
"placementStrategy": "free",
"sizeMode": "2x2",
"x": 1596,
"y": 744,
"z": 4
},
"clock": {
"color": "",
"cookie": {
"aiStyling": false,
"constantlyRotate": false,
"dateInClock": true,
"dateStyle": "bubble",
"dialNumberStyle": "full",
"hourHandStyle": "hollow",
"hourMarks": false,
"minuteHandStyle": "medium",
"secondHandStyle": "line",
"sides": 12,
"timeIndicators": true,
"useSineCookie": false
},
"digital": {
"adaptiveAlignment": true,
"animateChange": true,
"font": {
"family": "Google Sans Flex",
"roundness": 1.1290989771359807,
"size": 129.49608904933814,
"weight": 595.725165314564,
"width": 99.44532190132371
},
"showDate": true,
"vertical": false
},
"enable": true,
"pixel": {
"orientation": "vertical"
},
"placementStrategy": "leastBusy",
"quote": {
"enable": true,
"followClock": false,
"text": "Kawaī neko o zenbu tabe chaimasu."
},
"showOnlyWhenLocked": false,
"style": "digital",
"styleLocked": "cookie",
"x": 1423,
"y": 383,
"z": 3
},
"customImage": {
"enable": true,
"path": "",
"placementStrategy": "free",
"shape": "Cookie4Sided",
"size": 200,
"x": 400,
"y": 100,
"z": 0
},
"customText": {
"alignment": "center",
"color": "",
"content": "Hello world",
"enable": true,
"fontFamily": "Caveat",
"fontSize": 72,
"placementStrategy": "free",
"shadow": true,
"x": 400,
"y": 300,
"z": 0
},
"images": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"media": {
"backgroundShape": "Cookie4Sided",
"enable": true,
"placementStrategy": "free",
"showControls": true,
"showLyrics": false,
"showTitles": true,
"sizeMode": "1x3",
"x": 744,
"y": 876,
"z": 1
},
"notes": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"resources": {
"enable": false,
"placementStrategy": "free",
"vertical": false,
"x": 400,
"y": 100,
"z": 0
},
"shadow": true,
"sticker": {
"enable": false,
"items": [],
"outlineColor": "#ffffff",
"outlineWidth": 8,
"path": "",
"placementStrategy": "free",
"rotation": 0,
"size": 200,
"x": 400,
"y": 100,
"z": 0
},
"timers": {
"enable": false,
"placementStrategy": "free",
"vertical": false,
"x": 400,
"y": 100,
"z": 0
},
"todo": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"userCard": {
"enable": false,
"placementStrategy": "free",
"sizeMode": "1x2",
"x": 400,
"y": 100,
"z": 0
},
"visualizer": {
"colorSource": "theme",
"enable": true,
"height": 343,
"placementStrategy": "free",
"ringSize": 380,
"sensitivity": 1.65,
"style": "mirror",
"x": 0,
"y": 0,
"z": -1000
},
"weather": {
"enable": false,
"expanded": false,
"placementStrategy": "mostBusy",
"sizeMode": "1x3",
"x": 400,
"y": 100,
"z": 0
},
"worldClock": {
"clockCount": 4,
"enable": false,
"placementStrategy": "free",
"sizeMode": "2x2",
"timezones": [
"Australia/Sydney",
"Asia/Tokyo",
"Europe/London",
"America/New_York"
],
"x": 400,
"y": 100,
"z": 0
}
},
"widgetsLocked": false
},
"bar": {
"autoHide": {
"enable": false,
"hoverRegionWidth": 2,
"pushWindows": false,
"showWhenPressingSuper": {
"delay": 140,
"enable": true
}
},
"borderless": "transparent",
"bottom": false,
"centerOnlyReserveFrame": false,
"cornerStyle": 3,
"divider": {
"spacing": 20,
"style": "rect"
},
"dynamicIsland": {
"leftWidget": "clockWidget",
"rightWidget": "systemIcons",
"showMediaControls": false,
"visualizerStyle": "wave"
},
"floatStyleShadow": true,
"followFrameColor": false,
"frameColor": "secondaryContainer",
"frameThickness": 4,
"groupColor": "layer1",
"indicators": {
"notifications": {
"showUnreadCount": true
}
},
"layouts": {
"leftLayout": [
"leftSidebarButton",
"activeWindow",
"resources"
],
"middleLayout": [
"media",
"clockWidget",
"workspaces",
"utilButtons",
"weatherBar",
"batteryIndicator"
],
"rightLayout": [
"sysTray",
"updatesCount",
"bluetooth",
"systemIcons"
]
},
"media": {
"alwaysVisible": false,
"maxWidth": 280,
"minWidth": 100,
"onlyTitle": false,
"preferredPlayer": "",
"showLyrics": false
},
"resources": {
"alwaysShowCpu": true,
"alwaysShowCpuTemp": true,
"alwaysShowDisk": false,
"alwaysShowRam": true,
"alwaysShowSwap": false,
"cpuWarningThreshold": 90,
"memoryWarningThreshold": 95,
"showValue": true,
"style": "outline",
"swapWarningThreshold": 85
},
"screenList": [],
"showBackground": true,
"showFrame": false,
"tooltips": {
"clickToShow": false,
"enable": true
},
"topLeftIcon": "spark",
"utilButtons": {
"isRecording": false,
"showColorPicker": false,
"showDarkModeToggle": false,
"showKeyboardToggle": true,
"showMicToggle": true,
"showPerformanceProfileToggle": true,
"showScreenRecord": false,
"showScreenSnip": false,
"showWallpaperToggle": false
},
"verbose": true,
"vertical": false,
"workspaces": {
"alwaysShowNumbers": true,
"indicatorStyle": "dot",
"monochromeIcons": true,
"numberMap": [],
"showAppIcons": true,
"showNumberDelay": 200,
"shown": 10,
"useNerdFont": false
}
},
"calendar": {
"locale": "en-GB"
},
"conflictKiller": {
"autoKillNotificationDaemons": true,
"autoKillTrays": true
},
"crosshair": {
"code": "0;P;d;1;0l;10;0o;2;1b;0"
},
"custom": {
"colorizeIcon": true,
"distroIcon": "google-gemini-symbolic"
},
"dock": {
"enable": true,
"height": 60,
"hoverRegionHeight": 2,
"hoverToReveal": true,
"ignoredAppRegexes": [],
"monochromeIcons": false,
"pinnedApps": [
"org.kde.dolphin",
"zen"
],
"pinnedOnStartup": false,
"showAppsButton": true,
"showBackground": true,
"showMedia": true,
"showPinButton": true
},
"hacks": {
"arbitraryRaceConditionDelay": 20
},
"hyprland": {
"animations": {
"animation": "normal",
"enable": true
},
"decoration": {
"activeOpacity": 1,
"blur": {
"enabled": false,
"passes": 3,
"size": 1
},
"inactiveOpacity": 0.95,
"rounding": 22,
"shadow": {
"enabled": true,
"range": 4
}
},
"general": {
"borderColor": {
"activeOpacity": 0.47,
"activeRole": "layer0Border",
"enable": false,
"inactiveOpacity": 0.2,
"inactiveRole": "layer0Border"
},
"borderSize": 1,
"gapsIn": 2,
"gapsOut": 5
},
"idle": {
"lock": 300,
"screenOff": 600,
"suspend": 10800
}
},
"interactions": {
"deadPixelWorkaround": {
"enable": false
},
"scrolling": {
"fasterTouchpadScroll": false,
"mouseScrollDeltaThreshold": 120,
"mouseScrollFactor": 120,
"touchpadScrollFactor": 450
}
},
"launcher": {
"pinnedApps": [
"org.kde.dolphin",
"kitty",
"cmake-gui"
]
},
"light": {
"antiFlashbang": {
"enable": false
},
"night": {
"automatic": false,
"colorTemperature": 5559,
"from": "19:00",
"to": "06:30"
}
},
"lock": {
"blur": {
"enable": false,
"extraZoom": 1.1,
"radius": 100,
"size": 20
},
"centerClock": true,
"launchOnStartup": false,
"materialShapeChars": true,
"security": {
"requirePasswordToPower": true,
"unlockKeyring": true
},
"showLockedText": true,
"showMedia": true,
"showToolbars": true,
"showWidgets": false,
"useHyprlock": false
},
"media": {
"filterDuplicatePlayers": true
},
"notifications": {
"position": "top_right",
"timeout": 7000
},
"osd": {
"timeout": 3000
},
"osk": {
"layout": "qwerty_full",
"pinnedOnStartup": false
},
"overlay": {
"clickthroughOpacity": 0.8,
"darkenScreen": false,
"floatingImage": {
"imageSource": "https://media.tenor.com/H5U5bJzj3oAAAAAi/kukuru.gif",
"scale": 0.5
},
"openingZoomAnimation": true
},
"overview": {
"centerIcons": true,
"columns": 5,
"enable": true,
"orderBottomUp": false,
"orderRightLeft": false,
"rows": 2,
"scale": 0.18,
"style": "default"
},
"panelFamily": "ii",
"policies": {
"ai": 1,
"weeb": 1
},
"profile": {
"avatarPath": "/home/alvin/Sync_Documents/",
"avatarPicture": "/home/alvin/Sync_Documents/Alvin logo original.png",
"descriptionText": "::uptime::",
"displayName": "",
"onlinePresets": true
},
"regionSelector": {
"annotation": {
"useSatty": false
},
"circle": {
"padding": 10,
"strokeWidth": 6
},
"rect": {
"showAimLines": true
},
"targetRegions": {
"content": true,
"contentRegionOpacity": 0.8,
"layers": true,
"opacity": 0.3,
"selectionPadding": 5,
"showLabel": false,
"windows": true
}
},
"resources": {
"historyLength": 60,
"updateInterval": 3100
},
"settings": {
"borderColor": "layer0Border",
"borderSize": 1,
"collapsedSections": [],
"style": "default"
},
"sidebar": {
"ai": {
"textFadeIn": false
},
"banner": true,
"bannerImage": "",
"booru": {
"allowNsfw": true,
"defaultProvider": "yandere",
"limit": 20,
"zerochan": {
"username": "theodorer61"
}
},
"bottomGroup": false,
"cornerOpen": {
"bottom": true,
"bottomLeftAction": "sidebarLeftOpen",
"bottomRightAction": "sidebarRightOpen",
"clickless": false,
"clicklessCornerEnd": true,
"clicklessCornerVerticalOffset": 1,
"cornerRegionHeight": 5,
"cornerRegionWidth": 250,
"enable": true,
"valueScroll": true,
"visualize": false
},
"keepRightSidebarLoaded": false,
"media": {
"artColors": false,
"artShape": "Oval",
"blurredBackground": false,
"enable": true,
"shapeArt": false,
"showLyrics": true
},
"mediaPlayer": false,
"quickSliders": {
"enable": true,
"showBrightness": true,
"showMic": true,
"showVolume": true
},
"quickToggles": {
"android": {
"columns": 6,
"toggles": [
{
"size": 2,
"type": "network"
},
{
"size": 2,
"type": "bluetooth"
},
{
"size": 2,
"type": "audio"
},
{
"size": 1,
"type": "idleInhibitor"
},
{
"size": 2,
"type": "mic"
},
{
"size": 1,
"type": "nightLight"
},
{
"size": 2,
"type": "powerProfile"
}
]
},
"style": "android"
},
"translator": {
"delay": 300,
"enable": true
}
},
"tray": {
"filterPassive": true,
"invertPinnedItems": true,
"monochromeIcons": false,
"pinnedItems": [
"Fcitx"
],
"showItemId": false
},
"wallpaperSelector": {
"changeInterval": 0,
"closeAfterSelection": true,
"columns": 4,
"liveWallpapersPath": "",
"showBlurBackground": false,
"showHomePath": true,
"showSearchbar": true,
"sortMode": "time",
"useSystemFileDialog": false,
"userPath": "/home/alvin/Pictures/Wallpapers/"
},
"windows": {
"centerTitle": true,
"showTitlebar": true
}
}
@@ -0,0 +1,676 @@
{
"appearance": {
"extraBackgroundTint": true,
"fakeScreenRounding": 0,
"fonts": {
"expressive": "Space Grotesk",
"iconNerd": "JetBrains Mono NF",
"main": "Google Sans Flex",
"monospace": "JetBrains Mono NF",
"numbers": "Google Sans Flex",
"reading": "Readex Pro",
"title": "Google Sans Flex"
},
"palette": {
"accentColor": "",
"type": "scheme-tonal-spot"
},
"transparency": {
"automatic": true,
"backgroundTransparency": 0.11,
"contentTransparency": 0.57,
"enable": false
},
"wallpaperTheming": {
"enableAppsAndShell": true,
"enableQtApps": true,
"enableTerminal": true,
"terminalGenerationProps": {
"forceDarkMode": false,
"harmonizeThreshold": 100,
"harmony": 0.5,
"termFgBoost": 0.35
}
}
},
"apps": {
"bluetooth": "kcmshell6 kcm_bluetooth",
"changePassword": "kitty -1 --hold=yes fish -i -c 'passwd'",
"manageUser": "kcmshell6 kcm_users",
"network": "kcmshell6 kcm_networkmanagement",
"networkEthernet": "kcmshell6 kcm_networkmanagement",
"taskManager": "plasma-systemmonitor --page-name Processes",
"terminal": "kitty -1",
"update": "kitty -1 --hold=yes fish -i -c 'pkexec pacman -Syu'",
"volumeMixer": "~/.config/hypr/hyprland/scripts/launch_first_available.sh \"pavucontrol-qt\" \"pavucontrol\""
},
"background": {
"blurRadius": 32,
"centeredWallpaper": false,
"centeredWallpaperColor": "primaryContainer",
"centeredWallpaperOnlyWhenLocked": false,
"centeredWallpaperShape": "Cookie7Sided",
"centeredWallpaperSize": 400,
"enableWallpaperPreview": false,
"hideWhenFullscreen": true,
"lockWall": "",
"parallax": {
"autoVertical": false,
"enableSidebar": true,
"enableWorkspace": true,
"vertical": false,
"widgetsFactor": 1.2,
"workspaceZoom": 1.07
},
"screenList": [],
"showBlur": true,
"showGrid": true,
"showSnapLines": true,
"splitRatio": "25",
"splitSide": "right",
"thumbnailPath": "",
"wallpaperAnimation": "random",
"wallpaperPath": "/home/alvin/Pictures/Wallpapers/Dynamic-Wallpapers/Dark/japan-street-Dark.png",
"widgets": {
"blurRadius": 32,
"blurWidgets": false,
"calendar": {
"enable": true,
"placementStrategy": "free",
"sizeMode": "2x2",
"x": 1596,
"y": 744,
"z": 4
},
"clock": {
"color": "",
"cookie": {
"aiStyling": false,
"constantlyRotate": false,
"dateInClock": true,
"dateStyle": "bubble",
"dialNumberStyle": "full",
"hourHandStyle": "hollow",
"hourMarks": false,
"minuteHandStyle": "medium",
"secondHandStyle": "line",
"sides": 12,
"timeIndicators": true,
"useSineCookie": false
},
"digital": {
"adaptiveAlignment": true,
"animateChange": true,
"font": {
"family": "Google Sans Flex",
"roundness": 1.1290989771359807,
"size": 129.49608904933814,
"weight": 350,
"width": 99.44532190132371
},
"showDate": true,
"vertical": false
},
"enable": true,
"pixel": {
"orientation": "vertical"
},
"placementStrategy": "leastBusy",
"quote": {
"enable": true,
"followClock": false,
"text": "Kawaī neko o zenbu tabe chaimasu."
},
"showOnlyWhenLocked": false,
"style": "digital",
"styleLocked": "cookie",
"x": 1423,
"y": 383,
"z": 3
},
"customImage": {
"enable": true,
"path": "",
"placementStrategy": "free",
"shape": "Cookie4Sided",
"size": 200,
"x": 400,
"y": 100,
"z": 0
},
"customText": {
"alignment": "center",
"color": "",
"content": "Hello world",
"enable": true,
"fontFamily": "Caveat",
"fontSize": 72,
"placementStrategy": "free",
"shadow": true,
"x": 400,
"y": 300,
"z": 0
},
"images": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"media": {
"backgroundShape": "Cookie4Sided",
"enable": true,
"placementStrategy": "free",
"showControls": true,
"showLyrics": false,
"showTitles": true,
"sizeMode": "1x3",
"x": 744,
"y": 876,
"z": 1
},
"notes": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"resources": {
"enable": false,
"placementStrategy": "free",
"vertical": false,
"x": 400,
"y": 100,
"z": 0
},
"shadow": true,
"sticker": {
"enable": false,
"items": [],
"outlineColor": "#ffffff",
"outlineWidth": 8,
"path": "",
"placementStrategy": "free",
"rotation": 0,
"size": 200,
"x": 400,
"y": 100,
"z": 0
},
"timers": {
"enable": false,
"placementStrategy": "free",
"vertical": false,
"x": 400,
"y": 100,
"z": 0
},
"todo": {
"enable": false,
"placementStrategy": "free",
"x": 400,
"y": 100,
"z": 0
},
"userCard": {
"enable": false,
"placementStrategy": "free",
"sizeMode": "1x2",
"x": 400,
"y": 100,
"z": 0
},
"visualizer": {
"colorSource": "theme",
"enable": true,
"height": 342,
"placementStrategy": "free",
"ringSize": 380,
"sensitivity": 1.65,
"style": "mirror",
"x": 0,
"y": 0,
"z": -1000
},
"weather": {
"enable": false,
"expanded": false,
"placementStrategy": "mostBusy",
"sizeMode": "1x3",
"x": 400,
"y": 100,
"z": 0
},
"worldClock": {
"clockCount": 4,
"enable": false,
"placementStrategy": "free",
"sizeMode": "2x2",
"timezones": [
"Australia/Sydney",
"Asia/Tokyo",
"Europe/London",
"America/New_York"
],
"x": 400,
"y": 100,
"z": 0
}
},
"widgetsLocked": false
},
"bar": {
"autoHide": {
"enable": false,
"hoverRegionWidth": 2,
"pushWindows": false,
"showWhenPressingSuper": {
"delay": 140,
"enable": true
}
},
"borderless": "transparent",
"bottom": false,
"centerOnlyReserveFrame": false,
"cornerStyle": 3,
"divider": {
"spacing": 20,
"style": "rect"
},
"dynamicIsland": {
"leftWidget": "clockWidget",
"rightWidget": "systemIcons",
"showMediaControls": false,
"visualizerStyle": "wave"
},
"floatStyleShadow": true,
"followFrameColor": false,
"frameColor": "secondaryContainer",
"frameThickness": 4,
"groupColor": "layer1",
"indicators": {
"notifications": {
"showUnreadCount": true
}
},
"layouts": {
"leftLayout": [
"leftSidebarButton",
"activeWindow",
"resources"
],
"middleLayout": [
"media",
"clockWidget",
"workspaces",
"utilButtons",
"weatherBar"
],
"rightLayout": [
"sysTray",
"updatesCount",
"bluetooth",
"systemIcons"
]
},
"media": {
"alwaysVisible": false,
"maxWidth": 280,
"minWidth": 100,
"onlyTitle": false,
"preferredPlayer": "",
"showLyrics": false
},
"resources": {
"alwaysShowCpu": true,
"alwaysShowCpuTemp": true,
"alwaysShowDisk": false,
"alwaysShowRam": true,
"alwaysShowSwap": false,
"cpuWarningThreshold": 90,
"memoryWarningThreshold": 95,
"showValue": true,
"style": "outline",
"swapWarningThreshold": 85
},
"screenList": [],
"showBackground": true,
"showFrame": false,
"tooltips": {
"clickToShow": false,
"enable": true
},
"topLeftIcon": "spark",
"utilButtons": {
"isRecording": false,
"showColorPicker": false,
"showDarkModeToggle": false,
"showKeyboardToggle": false,
"showMicToggle": true,
"showPerformanceProfileToggle": true,
"showScreenRecord": false,
"showScreenSnip": false,
"showWallpaperToggle": false
},
"verbose": true,
"vertical": false,
"workspaces": {
"alwaysShowNumbers": true,
"indicatorStyle": "dot",
"monochromeIcons": true,
"numberMap": [],
"showAppIcons": true,
"showNumberDelay": 200,
"shown": 10,
"useNerdFont": false
}
},
"calendar": {
"locale": "en-GB"
},
"conflictKiller": {
"autoKillNotificationDaemons": true,
"autoKillTrays": true
},
"crosshair": {
"code": "0;P;d;1;0l;10;0o;2;1b;0"
},
"custom": {
"colorizeIcon": true,
"distroIcon": "google-gemini-symbolic"
},
"dock": {
"enable": true,
"height": 60,
"hoverRegionHeight": 2,
"hoverToReveal": true,
"ignoredAppRegexes": [],
"monochromeIcons": false,
"pinnedApps": [
"org.kde.dolphin",
"zen"
],
"pinnedOnStartup": false,
"showAppsButton": true,
"showBackground": true,
"showMedia": true,
"showPinButton": true
},
"hacks": {
"arbitraryRaceConditionDelay": 20
},
"hyprland": {
"animations": {
"animation": "normal",
"enable": true
},
"decoration": {
"activeOpacity": 1,
"blur": {
"enabled": false,
"passes": 3,
"size": 1
},
"inactiveOpacity": 0.95,
"rounding": 22,
"shadow": {
"enabled": true,
"range": 4
}
},
"general": {
"borderColor": {
"activeOpacity": 0.47,
"activeRole": "layer0Border",
"enable": false,
"inactiveOpacity": 0.2,
"inactiveRole": "layer0Border"
},
"borderSize": 1,
"gapsIn": 2,
"gapsOut": 5
},
"idle": {
"lock": 300,
"screenOff": 600,
"suspend": 10800
}
},
"interactions": {
"deadPixelWorkaround": {
"enable": false
},
"scrolling": {
"fasterTouchpadScroll": false,
"mouseScrollDeltaThreshold": 120,
"mouseScrollFactor": 120,
"touchpadScrollFactor": 450
}
},
"launcher": {
"pinnedApps": [
"org.kde.dolphin",
"kitty",
"cmake-gui"
]
},
"light": {
"antiFlashbang": {
"enable": false
},
"night": {
"automatic": false,
"colorTemperature": 5559,
"from": "19:00",
"to": "06:30"
}
},
"lock": {
"blur": {
"enable": false,
"extraZoom": 1.1,
"radius": 100,
"size": 20
},
"centerClock": true,
"launchOnStartup": false,
"materialShapeChars": true,
"security": {
"requirePasswordToPower": true,
"unlockKeyring": true
},
"showLockedText": true,
"showMedia": true,
"showToolbars": true,
"showWidgets": false,
"useHyprlock": false
},
"media": {
"filterDuplicatePlayers": true
},
"notifications": {
"position": "top_right",
"timeout": 7000
},
"osd": {
"timeout": 3000
},
"osk": {
"layout": "qwerty_full",
"pinnedOnStartup": false
},
"overlay": {
"clickthroughOpacity": 0.8,
"darkenScreen": false,
"floatingImage": {
"imageSource": "https://media.tenor.com/H5U5bJzj3oAAAAAi/kukuru.gif",
"scale": 0.5
},
"openingZoomAnimation": true
},
"overview": {
"centerIcons": true,
"columns": 5,
"enable": true,
"orderBottomUp": false,
"orderRightLeft": false,
"rows": 2,
"scale": 0.18,
"style": "default"
},
"panelFamily": "ii",
"policies": {
"ai": 1,
"weeb": 1
},
"profile": {
"avatarPath": "",
"avatarPicture": "",
"descriptionText": "::uptime::",
"displayName": "",
"onlinePresets": false
},
"regionSelector": {
"annotation": {
"useSatty": false
},
"circle": {
"padding": 10,
"strokeWidth": 6
},
"rect": {
"showAimLines": true
},
"targetRegions": {
"content": true,
"contentRegionOpacity": 0.8,
"layers": true,
"opacity": 0.3,
"selectionPadding": 5,
"showLabel": false,
"windows": true
}
},
"resources": {
"historyLength": 60,
"updateInterval": 3100
},
"settings": {
"borderColor": "layer0Border",
"borderSize": 1,
"collapsedSections": [],
"style": "default"
},
"sidebar": {
"ai": {
"textFadeIn": false
},
"banner": true,
"bannerImage": "",
"booru": {
"allowNsfw": true,
"defaultProvider": "yandere",
"limit": 20,
"zerochan": {
"username": "theodorer61"
}
},
"bottomGroup": false,
"cornerOpen": {
"bottom": true,
"bottomLeftAction": "sidebarLeftOpen",
"bottomRightAction": "sidebarRightOpen",
"clickless": false,
"clicklessCornerEnd": true,
"clicklessCornerVerticalOffset": 1,
"cornerRegionHeight": 5,
"cornerRegionWidth": 250,
"enable": true,
"valueScroll": true,
"visualize": false
},
"keepRightSidebarLoaded": false,
"media": {
"artColors": false,
"artShape": "Oval",
"blurredBackground": false,
"enable": true,
"shapeArt": false,
"showLyrics": true
},
"mediaPlayer": false,
"quickSliders": {
"enable": true,
"showBrightness": true,
"showMic": true,
"showVolume": true
},
"quickToggles": {
"android": {
"columns": 6,
"toggles": [
{
"size": 2,
"type": "network"
},
{
"size": 2,
"type": "bluetooth"
},
{
"size": 2,
"type": "audio"
},
{
"size": 1,
"type": "idleInhibitor"
},
{
"size": 2,
"type": "mic"
},
{
"size": 1,
"type": "nightLight"
},
{
"size": 2,
"type": "powerProfile"
}
]
},
"style": "android"
},
"translator": {
"delay": 300,
"enable": true
}
},
"tray": {
"filterPassive": true,
"invertPinnedItems": true,
"monochromeIcons": false,
"pinnedItems": [
"Fcitx"
],
"showItemId": false
},
"wallpaperSelector": {
"changeInterval": 0,
"closeAfterSelection": true,
"columns": 4,
"liveWallpapersPath": "",
"showBlurBackground": false,
"showHomePath": true,
"showSearchbar": true,
"sortMode": "time",
"useSystemFileDialog": false,
"userPath": "/home/alvin/Pictures/Wallpapers/"
},
"windows": {
"centerTitle": true,
"showTitlebar": true
}
}
@@ -0,0 +1,9 @@
tt.*
.tests
doc/tags
debug
.repro
foo.*
*.log
data
.stfolder/
@@ -0,0 +1,15 @@
{
"neodev": {
"library": {
"enabled": true,
"plugins": true
}
},
"neoconf": {
"plugins": {
"lua_ls": {
"enabled": true
}
}
}
}
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+4
View File
@@ -0,0 +1,4 @@
# 💤 LazyVim
A starter template for [LazyVim](https://github.com/LazyVim/LazyVim).
Refer to the [documentation](https://lazyvim.github.io/installation) to get started.
+2
View File
@@ -0,0 +1,2 @@
-- bootstrap lazy.nvim, LazyVim and your plugins
require("config.lazy")
@@ -0,0 +1,54 @@
{
"Arduino-Nvim": { "branch": "main", "commit": "c9983b5ead3b2ce574d9bcb9708febad0f8ddbd7" },
"CopilotChat.nvim": { "branch": "main", "commit": "f0c2a23ab79dc295f5e0eef0d8b587a39020c852" },
"LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" },
"SchemaStore.nvim": { "branch": "main", "commit": "1f8835ba58a2ad341c9c1515316a3183596dbb60" },
"blink-copilot": { "branch": "main", "commit": "7ad8209b2f880a2840c94cdcd80ab4dc511d4f39" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"blink.compat": { "branch": "main", "commit": "2ed6d9a28b07fa6f3bface818470605f8896408c" },
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
"catppuccin": { "branch": "main", "commit": "058e83dc009e4dd62f30807054de9cc849699e27" },
"codeium.nvim": { "branch": "main", "commit": "821b570b526dbb05b57aa4ded578b709a704a38a" },
"conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" },
"copilot.lua": { "branch": "master", "commit": "2a849bc7bec4d175524c332c20d48ca9ece735df" },
"dial.nvim": { "branch": "master", "commit": "f2634758455cfa52a8acea6f142dcd6271a1bf57" },
"flash.nvim": { "branch": "main", "commit": "b6346946d10d07998efee029fb0f7a593806d0cd" },
"friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" },
"gitsigns.nvim": { "branch": "main", "commit": "31d6fb2d618bca1482b9f274751ead5f03461408" },
"grug-far.nvim": { "branch": "main", "commit": "1cc080f55706b38aabfa97d40acb6adf59ac4a5a" },
"inc-rename.nvim": { "branch": "main", "commit": "0074b551a17338ccdcd299bd86687cc651bcb33d" },
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
"lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" },
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
"markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "7adc933dabcc7c86ae6b07aff7ee68eac398491f" },
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
"mini.ai": { "branch": "main", "commit": "25248c6aa002391936a6200f12d1466015987133" },
"mini.hipatterns": { "branch": "main", "commit": "7c840c71d6a91f53d734cab2b6fe2290d285ec3b" },
"mini.icons": { "branch": "main", "commit": "98faae31e9be1cc054ae63485e58ceb185efcad0" },
"mini.pairs": { "branch": "main", "commit": "b1fd9df3bb4a41c8f45778a3859ee80ef6b367e3" },
"neotest": { "branch": "master", "commit": "4e2cd42c4252ee9d2435571d9adcdbc1d47931fe" },
"neotest-dart": { "branch": "main", "commit": "f10fc22a17559b3a7abb400e266db0a1201979e7" },
"neotest-golang": { "branch": "main", "commit": "61726ad54b6b94c73d130b65c33575d13a61fc11" },
"noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" },
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
"nvim-ansible": { "branch": "main", "commit": "c7f595d568b588942d4d0c37b5cd6cae3764a148" },
"nvim-lint": { "branch": "master", "commit": "a219b2c9e5b4765e5c845aba119dad55806fcaf1" },
"nvim-lspconfig": { "branch": "master", "commit": "e7ca2c95ba316a8b846d3f3546d407908c5c4ccb" },
"nvim-nio": { "branch": "master", "commit": "edcc181a875301dd21840189aa2f2f9ad69fc172" },
"nvim-treesitter": { "branch": "main", "commit": "7248feaca45e4d944591497964bc19afa89ad1c6" },
"nvim-treesitter-textobjects": { "branch": "main", "commit": "898ee307df58f854d11cd7edd06472574d48014e" },
"nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" },
"obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" },
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"render-markdown.nvim": { "branch": "main", "commit": "f422cb5c6855f150e2ddcfaf44e7157b98b34f6a" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
"telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
"ts-comments.nvim": { "branch": "main", "commit": "a59d6092213447450191122c9346f309161504cb" },
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" },
"yanky.nvim": { "branch": "main", "commit": "020c22d0cfa60358569e49d1d7b91630f175aef0" }
}
@@ -0,0 +1,29 @@
{
"extras": [
"lazyvim.plugins.extras.ai.codeium",
"lazyvim.plugins.extras.ai.copilot",
"lazyvim.plugins.extras.ai.copilot-chat",
"lazyvim.plugins.extras.coding.yanky",
"lazyvim.plugins.extras.editor.dial",
"lazyvim.plugins.extras.editor.inc-rename",
"lazyvim.plugins.extras.lang.ansible",
"lazyvim.plugins.extras.lang.dart",
"lazyvim.plugins.extras.lang.docker",
"lazyvim.plugins.extras.lang.git",
"lazyvim.plugins.extras.lang.go",
"lazyvim.plugins.extras.lang.json",
"lazyvim.plugins.extras.lang.markdown",
"lazyvim.plugins.extras.lang.toml",
"lazyvim.plugins.extras.lang.typescript",
"lazyvim.plugins.extras.lang.typescript.vtsls",
"lazyvim.plugins.extras.lang.yaml",
"lazyvim.plugins.extras.test.core",
"lazyvim.plugins.extras.util.dot",
"lazyvim.plugins.extras.util.mini-hipatterns"
],
"install_version": 8,
"news": {
"NEWS.md": "11866"
},
"version": 8
}
@@ -0,0 +1,8 @@
-- Autocmds are automatically loaded on the VeryLazy event
-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
--
-- Add any additional autocmds here
-- with `vim.api.nvim_create_autocmd`
--
-- Or remove existing autocmds by their group name (which is prefixed with `lazyvim_` for the defaults)
-- e.g. vim.api.nvim_del_augroup_by_name("lazyvim_wrap_spell")
@@ -0,0 +1,3 @@
-- Keymaps are automatically loaded on the VeryLazy event
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
-- Add any additional keymaps here
@@ -0,0 +1,53 @@
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
spec = {
-- add LazyVim and import its plugins
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
-- import/override with your plugins
{ import = "plugins" },
},
defaults = {
-- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
-- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
lazy = false,
-- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
-- have outdated releases, which may break your Neovim install.
version = false, -- always use the latest git commit
-- version = "*", -- try installing the latest stable version for plugins that support semver
},
install = { colorscheme = { "tokyonight", "habamax" } },
checker = {
enabled = true, -- check for plugin updates periodically
notify = false, -- notify on update
}, -- automatically check for plugin updates
performance = {
rtp = {
-- disable some rtp plugins
disabled_plugins = {
"gzip",
-- "matchit",
-- "matchparen",
-- "netrwPlugin",
"tarPlugin",
"tohtml",
"tutor",
"zipPlugin",
},
},
},
})
@@ -0,0 +1,27 @@
-- Options are automatically loaded before lazy.nvim startup
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here
-- SpellCheck
-- Filter diagnostics to hide warnings but keep errors, info, and hints
local function filter_warnings(diagnostic)
return diagnostic.severity ~= vim.diagnostic.severity.WARN
end
vim.diagnostic.config({
virtual_text = {
format = function(diagnostic)
if diagnostic.severity == vim.diagnostic.severity.WARN then
return ""
end
return diagnostic.message
end,
},
signs = {
filter = filter_warnings,
},
underline = {
filter = filter_warnings,
},
})
@@ -0,0 +1,23 @@
return {
"yuukiflow/Arduino-Nvim",
ft = "arduino",
opts = {
use_default_keymaps = false,
keymaps = {
{ mode = "n", key = "<Leader>mc", func = ":InoCheck<CR>" },
{ mode = "n", key = "<Leader>mu", func = ":InoUpload<CR>" },
{ mode = "n", key = "<Leader>ms", func = ":InoStatus<CR>" },
{ mode = "n", key = "<Leader>mg", func = ":InoGUI<CR>" },
{ mode = "n", key = "<Leader>mm", func = ":InoMonitor<CR>" },
{ mode = "n", key = "<Leader>ml", func = ":InoLib<CR>" },
{ mode = "n", key = "<Leader>mb", func = ":InoSelectBoard<CR>" },
{ mode = "n", key = "<Leader>mp", func = ":InoSelectPort<CR>" },
{ mode = "n", key = "<Leader>mr", func = ":InoUploadReset<CR>" },
},
},
dependencies = {
"nvim-telescope/telescope.nvim",
-- optional: remove if you use Neovim's built-in LSP (>= 0.11)
"neovim/nvim-lspconfig",
},
}
@@ -0,0 +1,197 @@
-- since this is just an example spec, don't actually load anything here and return an empty spec
-- stylua: ignore
if true then return {} end
-- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim
--
-- In your plugin files, you can:
-- * add extra plugins
-- * disable/enabled LazyVim plugins
-- * override the configuration of LazyVim plugins
return {
-- add gruvbox
{ "ellisonleao/gruvbox.nvim" },
-- Configure LazyVim to load gruvbox
{
"LazyVim/LazyVim",
opts = {
colorscheme = "gruvbox",
},
},
-- change trouble config
{
"folke/trouble.nvim",
-- opts will be merged with the parent spec
opts = { use_diagnostic_signs = true },
},
-- disable trouble
{ "folke/trouble.nvim", enabled = false },
-- override nvim-cmp and add cmp-emoji
{
"hrsh7th/nvim-cmp",
dependencies = { "hrsh7th/cmp-emoji" },
---@param opts cmp.ConfigSchema
opts = function(_, opts)
table.insert(opts.sources, { name = "emoji" })
end,
},
-- change some telescope options and a keymap to browse plugin files
{
"nvim-telescope/telescope.nvim",
keys = {
-- add a keymap to browse plugin files
-- stylua: ignore
{
"<leader>fp",
function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end,
desc = "Find Plugin File",
},
},
-- change some options
opts = {
defaults = {
layout_strategy = "horizontal",
layout_config = { prompt_position = "top" },
sorting_strategy = "ascending",
winblend = 0,
},
},
},
-- add pyright to lspconfig
{
"neovim/nvim-lspconfig",
---@class PluginLspOpts
opts = {
---@type lspconfig.options
servers = {
-- pyright will be automatically installed with mason and loaded with lspconfig
pyright = {},
},
},
},
-- add tsserver and setup with typescript.nvim instead of lspconfig
{
"neovim/nvim-lspconfig",
dependencies = {
"jose-elias-alvarez/typescript.nvim",
init = function()
require("lazyvim.util").lsp.on_attach(function(_, buffer)
-- stylua: ignore
vim.keymap.set( "n", "<leader>co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" })
vim.keymap.set("n", "<leader>cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer })
end)
end,
},
---@class PluginLspOpts
opts = {
---@type lspconfig.options
servers = {
-- tsserver will be automatically installed with mason and loaded with lspconfig
tsserver = {},
},
-- you can do any additional lsp server setup here
-- return true if you don't want this server to be setup with lspconfig
---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
setup = {
-- example to setup with typescript.nvim
tsserver = function(_, opts)
require("typescript").setup({ server = opts })
return true
end,
-- Specify * to use this function as a fallback for any server
-- ["*"] = function(server, opts) end,
},
},
},
-- for typescript, LazyVim also includes extra specs to properly setup lspconfig,
-- treesitter, mason and typescript.nvim. So instead of the above, you can use:
{ import = "lazyvim.plugins.extras.lang.typescript" },
-- add more treesitter parsers
{
"nvim-treesitter/nvim-treesitter",
opts = {
ensure_installed = {
"bash",
"html",
"javascript",
"json",
"lua",
"markdown",
"markdown_inline",
"python",
"query",
"regex",
"tsx",
"typescript",
"vim",
"yaml",
},
},
},
-- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above
-- would overwrite `ensure_installed` with the new value.
-- If you'd rather extend the default config, use the code below instead:
{
"nvim-treesitter/nvim-treesitter",
opts = function(_, opts)
-- add tsx and treesitter
vim.list_extend(opts.ensure_installed, {
"tsx",
"typescript",
})
end,
},
-- the opts function can also be used to change the default opts:
{
"nvim-lualine/lualine.nvim",
event = "VeryLazy",
opts = function(_, opts)
table.insert(opts.sections.lualine_x, {
function()
return "😄"
end,
})
end,
},
-- or you can return new options to override all the defaults
{
"nvim-lualine/lualine.nvim",
event = "VeryLazy",
opts = function()
return {
--[[add your custom lualine config here]]
}
end,
},
-- use mini.starter instead of alpha
{ import = "lazyvim.plugins.extras.ui.mini-starter" },
-- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc
{ import = "lazyvim.plugins.extras.lang.json" },
-- add any tools you want to have installed below
{
"williamboman/mason.nvim",
opts = {
ensure_installed = {
"stylua",
"shellcheck",
"shfmt",
"flake8",
},
},
},
}
@@ -0,0 +1,44 @@
return {
"neovim/nvim-lspconfig",
opts = {
servers = {
harper_ls = {
settings = {
["harper-ls"] = {
userDictPath = {
"~/.config/obsidian/Custom Dictionary.txt",
-- "/usr/share/dict/words",
-- "$HOME/.local/share/harper-ls/file_dictionaries",
},
workspaceDictPath = "",
fileDictPath = "",
linters = {
SpellCheck = true,
SpelledNumbers = false,
AnA = true,
SentenceCapitalization = true,
UnclosedQuotes = true,
WrongApostrophe = false,
LongSentences = true,
RepeatedWords = true,
Spaces = true,
CorrectNumberSuffix = true,
},
codeActions = {
ForceStable = false,
},
markdown = {
IgnoreLinkTitle = false,
},
diagnosticSeverity = "hint",
isolateEnglish = false,
dialect = "Australian",
maxFileLength = 120000,
ignoredLintsPath = "",
excludePatterns = {},
},
},
},
},
},
}
@@ -0,0 +1,53 @@
return {
"epwalsh/obsidian.nvim",
version = "*",
lazy = true,
ft = "markdown",
dependencies = {
"nvim-lua/plenary.nvim",
"hrsh7th/nvim-cmp",
"nvim-telescope/telescope.nvim",
"nvim-treesitter/nvim-treesitter",
},
opts = {
workspaces = {
{
name = "Personal",
path = "~/Obsidian/Personal/",
},
{
name = "School-Obsidian",
path = "~/Obsidian/School-Obsidian/",
},
},
log_level = vim.log.levels.INFO,
daily_notes = {
folder = "notes/dailies",
date_format = "%Y-%m-%d",
alias_format = "%B %-d, %Y",
default_tags = { "daily-notes" },
template = nil,
},
new_notes_location = "1Projects",
completion = {
nvim_cmp = true,
min_chars = 2,
},
mappings = {
-- Toggle check-boxes
["<leader>ch"] = {
action = function()
return require("obsidian").util.toggle_checkbox()
end,
opts = { buffer = true },
},
-- Smart action (smart enter)
["<cr>"] = {
action = function()
return require("obsidian").util.smart_action()
end,
opts = { buffer = true, expr = true },
},
},
},
}
@@ -0,0 +1,3 @@
indent_type = "Spaces"
indent_width = 2
column_width = 120
+103
View File
@@ -0,0 +1,103 @@
# Don't print a new line at the start of the prompt
add_newline = false
# Pipes ╰─ ╭─
# Powerline symbols                                   
# Wedges 🭧🭒 🭣🭧🭓
# Random noise 🬖🬥🬔🬗
# Cool stuff 󰜥   
# format = """
# $directory $fill $git_branch $cmd_duration
# $character"""
format = """
$cmd_duration $directory$git_branch
$character"""
[fill]
symbol = '-'
style = 'fg:245'
# Replace the "❯" symbol in the prompt with "➜"
[character] # The name of the module we are configuring is "character"
success_symbol = "[ ](bold fg:243)"
error_symbol = "[ ](bold fg:244)"
# Disable the package module, hiding it from the prompt completely
[package]
disabled = true
[git_branch]
style = "bg: 252"
symbol = "󰘬"
truncation_length = 12
truncation_symbol = ""
format = " 󰜥 [](bold fg:252)[$symbol $branch(:$remote_branch)](fg:235 bg:252)[ ](bold fg:252)"
[git_commit]
commit_hash_length = 4
tag_symbol = " "
[git_state]
format = '[\($state( $progress_current of $progress_total)\)]($style) '
cherry_pick = "[🍒 PICKING](bold red)"
[git_status]
conflicted = " 🏳 "
ahead = " 🏎💨 "
behind = " 😰 "
diverged = " 😵 "
untracked = " 🤷 ‍"
stashed = " 📦 "
modified = " 📝 "
staged = '[++\($count\)](green)'
renamed = " ✍️ "
deleted = " 🗑 "
[hostname]
ssh_only = false
format = "[•$hostname](bg:252 bold fg:235)[](bold fg:252)"
trim_at = ".companyname.com"
disabled = false
[line_break]
disabled = false
[memory_usage]
disabled = true
threshold = -1
symbol = " "
style = "bold dimmed green"
[time]
disabled = true
format = '🕙[\[ $time \]]($style) '
time_format = "%T"
[username]
style_user = "bold bg:252 fg:235"
style_root = "red bold"
format = "[](bold fg:252)[$user]($style)"
disabled = false
show_always = true
[directory]
home_symbol = " "
read_only = "  "
style = "bg:255 fg:240"
truncation_length = 2
truncation_symbol = ".../"
format = '[](bold fg:255)[󰉋 → $path]($style)[](bold fg:255)'
[directory.substitutions]
"Desktop" = "  "
"Documents" = "  "
"Downloads" = "  "
"Music" = " 󰎈 "
"Pictures" = "  "
"Videos" = "  "
"GitHub" = " 󰊤 "
[cmd_duration]
min_time = 0
format = '[](bold fg:252)[󰪢 $duration](bold bg:252 fg:235)[](bold fg:252)'
+36
View File
@@ -0,0 +1,36 @@
# Setup fzf
# ---------
if [[ ! "$PATH" == *${FZF_PATH}/bin* ]]; then
export PATH="$PATH:${FZF_PATH}/bin"
fi
function _fzf_settings_has() {
which "$@" > /dev/null 2>&1
}
if _fzf_settings_has brew; then
# If fzf was installed via brew, use the brew paths
if [[ -x "$(brew --prefix)/bin/fzf" ]]; then
if [[ -f "$(brew --prefix fzf)/shell/completion.zsh" ]]; then
source "$(brew --prefix fzf)/shell/completion.zsh" 2> /dev/null
fi
if [[ -f "$(brew --prefix fzf)/shell/key-bindings.zsh" ]]; then
source "$(brew --prefix fzf)/shell/key-bindings.zsh"
fi
fi
fi
# Auto-completion
# ---------------
if [[ -f "${FZF_PATH}/shell/completion.zsh" ]]; then
[[ $- == *i* ]] && source "${FZF_PATH}/shell/completion.zsh" 2> /dev/null
fi
# Key bindings
# ------------
if [[ -f "${FZF_PATH}/shell/key-bindings.zsh" ]]; then
source "${FZF_PATH}/shell/key-bindings.zsh"
fi
# Cleanup internal functions
unset -f _fzf_settings_has
@@ -1,22 +0,0 @@
[Match]
Type=ether
# Exclude virtual Ethernet interfaces
Kind=!*
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=100
[IPv6AcceptRA]
RouteMetric=100
@@ -1,20 +0,0 @@
[Match]
Type=wlan
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=600
[IPv6AcceptRA]
RouteMetric=600
@@ -1,19 +0,0 @@
[Match]
Type=wwan
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
# systemd-networkd does not set per-interface-type default route metrics
# https://github.com/systemd/systemd/issues/17698
# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband.
# Use values from NetworkManager. From nm_device_get_route_metric_default in
# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c
[DHCPv4]
RouteMetric=700
[IPv6AcceptRA]
RouteMetric=700
@@ -0,0 +1 @@
/usr/lib/systemd/system/NetworkManager.service
@@ -1 +0,0 @@
/usr/lib/systemd/system/systemd-networkd.service
@@ -1 +0,0 @@
/usr/lib/systemd/system/systemd-resolved.service
+10 -1
View File
@@ -48,4 +48,13 @@ Include = /etc/pacman.d/cachyos-mirrorlist
[chaotic-aur]
SigLevel = Required DatabaseOptional
Include = /etc/pacman.d/chaotic-mirrorlist
Include = /etc/pacman.d/chaotic-mirrorlist
[local-aur]
# Ships on the medium only: packages built at ISO build time (end-4
# dependencies, plus localrepo/). Keeps pacstrap from needing the network for
# anything that is not in the official repos. alvin-install strips this whole
# section from the target system's pacman.conf, because /opt/localrepo exists
# only on the live medium.
SigLevel = Optional TrustAll
Server = file:///opt/localrepo
+339 -1
View File
@@ -1,4 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
# The chroot's /dev is the kernel's single shared devtmpfs, which only gets the
# fd/stdin/stdout/stderr symlinks at boot (from mkinitcpio's init). If the
# runner environment lacks them, process substitution (< <(...)) and upstream
# tools (pacman-key) fail with "… /dev/fd/63: No such file or directory".
# Self-heal here; the CI build-iso workflow does the same before pacstrap so
# that mkinitcpio's hook (which pipes through /dev/stdin) works too.
for _link in "fd:/proc/self/fd" "stdin:/proc/self/fd/0" \
"stdout:/proc/self/fd/1" "stderr:/proc/self/fd/2"; do
[[ -e "/dev/${_link%%:*}" || -L "/dev/${_link%%:*}" ]] ||
ln -sfn "${_link#*:}" "/dev/${_link%%:*}"
done
unset _link
# Populate the keyring in the built root from the keyring bundles
# (/usr/share/pacman/keyrings, incl. the copied cachyos keyring).
# This mirrors the guide; it runs inside the image you are making.
@@ -10,4 +25,327 @@ pacman-key --populate archlinux cachyos chaotic
# 'pacman' package, which ships a stock /etc/pacman.conf and would otherwise
# overwrite this directory's configured version.
install -m 0644 /root/.live-pacman.conf /etc/pacman.conf
rm -f /root/.live-pacman.conf
rm -f /root/.live-pacman.conf
# Build stamp staged by profiledef.sh (absent for non-git, non-CI builds):
# keep it where alvin-install looks for it, drop the staging copy.
if [[ -f /root/.iso-build-stamp ]]; then
install -m 0644 /root/.iso-build-stamp /etc/alvin-build-stamp
rm -f /root/.iso-build-stamp
fi
# ============================================================================
# Pre-install dotfile dependencies into /etc/skel so new users get them
# instantly on first login (no network required).
# ============================================================================
SKEL="/etc/skel"
# ── Oh-My-Zsh ────────────────────────────────────────────────────────────────
if [[ ! -d "${SKEL}/.oh-my-zsh" ]]; then
echo "[customize] Cloning Oh-My-Zsh into skel..."
git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git "${SKEL}/.oh-my-zsh"
fi
# Oh-My-Zsh custom plugins
ZSH_CUSTOM="${SKEL}/.oh-my-zsh/custom"
mkdir -p "${ZSH_CUSTOM}/plugins"
declare -A OMZ_PLUGINS=(
[zsh-history-substring-search]="https://github.com/zsh-users/zsh-history-substring-search.git"
[zsh-autosuggestions]="https://github.com/zsh-users/zsh-autosuggestions.git"
[zsh-eza]="https://github.com/z-shell/zsh-eza.git"
[fzf-zsh-plugin]="https://github.com/unixorn/fzf-zsh-plugin.git"
[zsh-syntax-highlighting]="https://github.com/zsh-users/zsh-syntax-highlighting.git"
[zsh-autocomplete]="https://github.com/marlonrichert/zsh-autocomplete.git"
)
for plugin in "${!OMZ_PLUGINS[@]}"; do
target="${ZSH_CUSTOM}/plugins/${plugin}"
if [[ ! -d "${target}" ]]; then
echo "[customize] Cloning OMZ plugin: ${plugin}"
git clone --depth=1 "${OMZ_PLUGINS[${plugin}]}" "${target}"
fi
done
# ── LazyVim (lazy.nvim bootstraps on first launch, but pre-clone the plugin) ─
NVIM_DATA="${SKEL}/.local/share/nvim"
mkdir -p "${NVIM_DATA}"
if [[ ! -d "${NVIM_DATA}/lazy/lazy.nvim" ]]; then
echo "[customize] Pre-cloning lazy.nvim for LazyVim..."
git clone --filter=blob:none --branch=stable \
https://github.com/folke/lazy.nvim.git "${NVIM_DATA}/lazy/lazy.nvim"
fi
# ── end-4 dots-hyprland, staged for alvin-install (avoids a clone at install) ─
DOTS_REPO="/opt/dots-hyprland"
if [[ ! -d "${DOTS_REPO}/.git" ]]; then
echo "[customize] Cloning end-4 dots-hyprland..."
git clone --depth=1 https://github.com/end-4/dots-hyprland.git "${DOTS_REPO}"
git -C "${DOTS_REPO}" submodule update --init --depth=1
fi
# ── end4-pC: the default quickshell config, shipped in skel ──────────────────
# pctrade/end4-pC is a fork of the ii shell config. It lives next to ii in
# ~/.config/quickshell and does not modify it; which one runs is decided by
# qsConfig (patched just below). The repo has no submodules.
if [[ ! -d "${SKEL}/.config/quickshell/end4-pC" ]]; then
echo "[customize] Cloning end4-pC quickshell config into skel..."
git clone --depth=1 https://github.com/pctrade/end4-pC.git \
"${SKEL}/.config/quickshell/end4-pC"
fi
# ── Default quickshell config: ii -> end4-pC ─────────────────────────────────
# alvin-install copies this staged repo onto the target and runs `./setup
# install`, whose rsync writes hypr/hyprland/variables.lua into the user's
# home - so patching the staged copy is what sets qsConfig on the installed
# system. Re-running is a no-op; anything other than ii/end4-pC aborts.
VARIABLES_LUA="${DOTS_REPO}/dots/.config/hypr/hyprland/variables.lua"
if grep -Fq 'hl.env("qsConfig", "ii")' "${VARIABLES_LUA}"; then
echo "[customize] Setting qsConfig to end4-pC..."
sed -i 's|hl\.env("qsConfig", "ii")|hl.env("qsConfig", "end4-pC")|' "${VARIABLES_LUA}"
fi
if ! grep -Fq 'hl.env("qsConfig", "end4-pC")' "${VARIABLES_LUA}"; then
echo "[customize] qsConfig is neither ii nor end4-pC in ${VARIABLES_LUA}" >&2
exit 1
fi
# ============================================================================
# Pre-install end-4 dependencies into the image (network heavy, once per ISO)
# ============================================================================
# ./setup install-deps resolves and *builds* every AUR/source dependency the
# dotfiles need (quickshell, MicroTeX, theming, fonts, ...). Doing it here lets
# alvin-install run its end-4 step with --skip-alldeps, so an install only
# copies files - no AUR clones, no makepkg, no dependency resolution.
#
# The script refuses to run as root, hence the throwaway builder account.
# ============================================================================
BUILD_USER="ii-builder"
if ! id -u "${BUILD_USER}" &>/dev/null; then
useradd -m -u 1500 "${BUILD_USER}"
fi
echo "${BUILD_USER} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/99-ii-builder
chmod 440 /etc/sudoers.d/99-ii-builder
# makepkg writes src/, pkg/ and *.pkg.tar.zst into the PKGBUILD directories,
# so the tree must be owned by the account that runs it.
chown -R "${BUILD_USER}:${BUILD_USER}" "${DOTS_REPO}"
# -f: never prompt (ask=false); -s: skip "pacman -Syu";
# --skip-plasmaintg: optional Firefox widget that pulls 410 pkgs / 526 MiB of
# KDE packages onto a non-KDE system;
# stdin: answer end-4's x() failure prompt with "e", so a failed command
# aborts the build instead of blocking forever without a TTY.
# shellcheck disable=SC2024 # the redirect is meant for the child, not sudo
if ! sudo -u "${BUILD_USER}" env HOME="/home/${BUILD_USER}" \
GIT_TERMINAL_PROMPT=0 \
bash -c "cd ${DOTS_REPO} && ./setup install-deps -f -s --skip-plasmaintg" \
< <(yes e); then
echo "[customize] end-4 ./setup install-deps failed" >&2
exit 1
fi
# ── Harvest the packages install-deps just built into the in-image local repo ─
# The live /etc/pacman.conf points [local-aur] at /opt/localrepo; without the
# harvested copies pacstrap cannot resolve these packages at install time and
# would silently drop them from the target system.
mkdir -p /opt/localrepo
shopt -s nullglob
# <name> <version> from a package's embedded .PKGINFO (update.sh does the same)
pkg_meta() {
tar -xOf "$1" .PKGINFO 2>/dev/null |
awk -F' = ' '/^pkgname = /{n=$2} /^pkgver = /{v=$2} END{print n, v}'
}
mapfile -d '' -t built_pkgs < <(
find "${DOTS_REPO}" "/home/${BUILD_USER}/.cache/yay" \
-name '*.pkg.tar.zst' -print0 2>/dev/null
)
declare -A built_file=() built_ver=()
for p in "${built_pkgs[@]}"; do
read -r n v < <(pkg_meta "$p")
[[ -n "${n:-}" && -n "${v:-}" ]] || continue
built_file["$n"]="$p"
built_ver["$n"]="$v"
done
# One entry per package name, and the entry must be the version the image
# actually installed - a stale copy with the same name but another version
# would let pacstrap install something else than what was tested.
for existing in /opt/localrepo/*.pkg.tar.zst; do
[[ -e "$existing" ]] || continue
read -r n v < <(pkg_meta "$existing")
[[ -n "${n:-}" ]] || continue
if [[ -n "${built_ver[$n]:-}" ]]; then
echo "[customize] Replacing localrepo ${n} ${v} with built ${built_ver[$n]}"
rm -f "$existing"
fi
done
if ((${#built_file[@]} > 0)); then
echo "[customize] Harvesting ${#built_file[@]} package(s) into /opt/localrepo"
cp -f -- "${built_file[@]}" /opt/localrepo/
# makepkg -Afsi leaves its archives next to the PKGBUILD. They are already
# harvested (and installed in this image); keeping them in the dots tree
# would ship a second copy inside /opt/dots-hyprland, which alvin-install
# copies to ~/.dots-hyprland on every installed system.
find "${DOTS_REPO}" -type f -name '*.pkg.tar.zst' -delete
fi
# Rebuild the repo database (CI/update.sh ship a pre-built one alongside the
# packages) and refresh the live system's copy of it. No network needed: the
# remote repos were synced during pacstrap.
local_pkgs=(/opt/localrepo/*.pkg.tar.zst)
if ((${#local_pkgs[@]} > 0)); then
echo "[customize] Rebuilding local-aur db (${#local_pkgs[@]} packages)..."
repo-add -R /opt/localrepo/local-aur.db.tar.gz "${local_pkgs[@]}"
mkdir -p /var/lib/pacman/sync
cp -fL /opt/localrepo/local-aur.db /var/lib/pacman/sync/local-aur.db
if [[ -f /opt/localrepo/local-aur.files ]]; then
cp -fL /opt/localrepo/local-aur.files /var/lib/pacman/sync/local-aur.files
fi
fi
# ── makepkg leftovers + throwaway account do not belong in the ISO ──────────
if [[ -d "${DOTS_REPO}/sdata/dist-arch" ]]; then
find "${DOTS_REPO}/sdata/dist-arch" -mindepth 2 -maxdepth 2 -type d \
\( -name src -o -name pkg \) -prune -exec rm -rf {} +
fi
rm -f /etc/sudoers.d/99-ii-builder
# Processes still running as BUILD_USER make userdel exit 8 and abort the
# build. end-4's ./setup is the usual source: sudo_init_keepalive forks
# `(sleep 60; sudo true) &` and its EXIT trap kills only the subshell,
# orphaning the sleep child for up to a minute. Mirrors shadow's
# user_busy_processes(): match real/effective/saved uid AND require the
# process to live inside this build chroot - the runner shares our PID
# namespace, and a host process could carry the same uid.
#
# mkarchiso runs this script via arch-chroot, which mounts proc *before*
# `unshare --fork --pid`: /proc entry numbers belong to the outer pid
# namespace, while kill(2) resolves pids in our (nested) namespace. Use the
# last NSpid field - the pid in our own namespace - for signalling; keep the
# /proc entry number for logging, since that is what userdel reports.
nspid_fields() {
awk -F'\t' '/^NSpid:/{ $1=""; sub(/^ +/, ""); print; exit }' "$1"
}
builder_procs() {
local uid broot st p key real eff saved kpid cmd
local -a nsf self_nsf=()
uid=$(id -u "${BUILD_USER}") || return 0
broot=$(stat -Lc '%d:%i' /)
read -r -a self_nsf < <(nspid_fields /proc/self/status)
for st in /proc/[0-9]*/status; do
[[ -r "$st" ]] || continue
real=""; eff=""; saved=""
while read -r key real eff saved _; do
[[ $key == "Uid:" ]] && break
done < "$st" || continue
[[ $real == "$uid" || $eff == "$uid" || $saved == "$uid" ]] || continue
p=${st#/proc/}; p=${p%/status}
# Stat of /proc/<pid>/root needs CAP_SYS_PTRACE (or same-uid): exactly
# what shadow's userdel uses, so a process we cannot see here is one
# userdel cannot flag either. Compare by device+inode; skip on failure.
[[ $(stat -Lc '%d:%i' "/proc/$p/root" 2>/dev/null) == "$broot" ]] || continue
# NSpid chain length must equal ours, i.e. the process must live in our
# pid namespace - only then is its last field killable from here.
nsf=()
read -r -a nsf < <(nspid_fields "/proc/$p/status") || continue
if ((${#nsf[@]} > 0 && ${#nsf[@]} == ${#self_nsf[@]})); then
kpid=${nsf[${#nsf[@]} - 1]}
else
kpid="-"
fi
cmd=$(tr '\0' ' ' < "/proc/$p/cmdline" 2>/dev/null)
printf '%s\t%s\t%s\n' "$p" "$kpid" "$cmd"
done
return 0
}
sweep_builder_procs() {
local sig=$1 p kpid cmd kerr
local -a pids=()
while IFS=$'\t' read -r p kpid cmd; do
[[ -n $p ]] || continue
if [[ -z $kpid || $kpid == "-" ]]; then
echo "[customize] ${BUILD_USER} process outside our pid namespace (cannot signal): pid $p: $cmd"
continue
fi
echo "[customize] ${BUILD_USER} process ($sig): pid $p: $cmd"
pids+=("$kpid")
done < <(builder_procs)
if ((${#pids[@]} > 0)); then
# Surface signal failures (they used to be swallowed, hiding a
# pid-namespace mismatch as a silent no-op sweep).
if ! kerr=$(kill -"$sig" "${pids[@]}" 2>&1); then
[[ -n $kerr ]] && printf '[customize] kill -%s: %s\n' "$sig" "$kerr"
fi
fi
return 0
}
sweep_builder_procs TERM
sleep 2
sweep_builder_procs KILL
sleep 1
if ! userdel -r "${BUILD_USER}"; then
rm -rf "/home/${BUILD_USER:?}"
if ! userdel "${BUILD_USER}"; then
echo "[customize] FATAL: cannot remove user ${BUILD_USER}; leftover processes:" >&2
builder_procs >&2 || true
exit 1
fi
fi
chown -R root:root "${DOTS_REPO}"
# ── Google Sans Flex into skel: install_google_sans_flex() early-returns once
# fc-list sees the font, so the install step needs no network ──────────────
FONT_DIR="${SKEL}/.local/share/fonts/illogical-impulse-google-sans-flex"
if [[ ! -f "${FONT_DIR}/.git/HEAD" ]]; then
echo "[customize] Pre-installing Google Sans Flex into skel..."
rm -rf "${FONT_DIR}"
git clone --depth=1 --recurse-submodules --shallow-submodules \
https://github.com/end-4/google-sans-flex "${FONT_DIR}"
fi
# ── uv into skel: CPython 3.12 + the end-4 requirements wheel cache ──────────
# install-python-packages() runs `uv venv -p 3.12` and `uv pip install -r ...`
# during setup. Arch has no python312 package (uv would download one) and the
# pinned requirements are ~250 MiB of wheels, so warm both into skel: the venv
# is then created and filled straight from the image.
if command -v uv &>/dev/null; then
echo "[customize] Pre-warming uv (CPython 3.12 + requirements cache)..."
warm_venv="/tmp/uv-warm-venv"
rm -rf "${warm_venv}"
UV_CACHE_DIR="${SKEL}/.cache/uv" \
UV_PYTHON_INSTALL_DIR="${SKEL}/.local/share/uv/python" \
uv venv -p 3.12 "${warm_venv}"
UV_CACHE_DIR="${SKEL}/.cache/uv" \
UV_PYTHON_INSTALL_DIR="${SKEL}/.local/share/uv/python" \
uv pip install --python "${warm_venv}/bin/python" \
-r "${DOTS_REPO}/sdata/uv/requirements.txt"
rm -rf "${warm_venv}"
else
echo "[customize] uv not found - skipping python/wheel pre-warm."
fi
# ── Fish: ensure default shell is set for the live user ──────────────────────
# The live user (usually 'archlinux' or 'root') gets fish as default shell
if command -v fish &>/dev/null; then
echo "[customize] Setting fish as default shell for skel..."
chsh -s /usr/bin/fish root 2>/dev/null || true
fi
# ── Ensure skel directories have correct permissions ─────────────────────────
chmod 700 "${SKEL}/.config" 2>/dev/null || true
find "${SKEL}/.config" -type f -exec chmod 644 {} \; 2>/dev/null || true
find "${SKEL}/.config" -type d -exec chmod 755 {} \; 2>/dev/null || true
find "${SKEL}/.config" -name '*.sh' -exec chmod 755 {} \; 2>/dev/null || true
find "${SKEL}/.local" -type d -exec chmod 755 {} \; 2>/dev/null || true
echo "[customize] Dotfile pre-installation complete."
-12
View File
@@ -1,12 +0,0 @@
NAME="Alvin Arch Linux"
PRETTY_NAME="Arch Linux"
ID_LIKE=arch
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://gitlab.archlinux.org/groups/archlinux/-/issues"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
+1699
View File
File diff suppressed because it is too large Load Diff
@@ -1 +0,0 @@
882DCFE48E2051D48E2562ABF3B607488DB35A47:4:
@@ -1,41 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGNBGERxNwBDAD1aEVN8rdWBlV2sOwkiW1ddO44xKjdumwuGhoXP1pUzK4SkNUb
IrQ1cenckdxzZsS8cbXTvEteC4K8tTYxobZpgzAPhKZNECsyCyDf2DEYv7bS75gy
sdl0bh+mOXPjvOe9IK3eFPQWWFd0erYyf9SHjlZ0utOg3qZ2JuVupGOH8W3taKth
ijR98RzUqP5rPoMPKcrOdBUiIREHx0y6SwdyX0c2XKm52T3cP8O0MPsvZLbRwGU0
DTyr7knzuGhR9tLxsy4PqKz3tSUEGM7PhFcpEoRFvV/4Al8/OpRaPj3zRn6RbL1D
9ZAH9OblgHkQlK6MPnLOygoaAvjreMHK3ykjlRugUtnRBmQHhH+o3iXb8Ep5GXjZ
XJZazy5ZSTbuJ8+DcjuC/G459ePnQ658od2Sxz5OBRmK3a1taAtgszHio1EHb8Db
OZ+Za5E46VOHM/8sl8toGbK4JOqpgdQ3YqIH4R915WqCYnMvfTQbCiHLYzWHrgAA
awBu3kaV2MagPnkAEQEAAbQbQ2FjaHlPUyA8YWRtaW5AY2FjaHlvcy5vcmc+iQHO
BBMBCAA4AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEiC3P5I4gUdSOJWKr
87YHSI2zWkcFAmTUdqcACgkQ87YHSI2zWkc2ygwAknD+O2LQeHp1tEYwplF9Rthq
uPN64IxC/8nAc+L92fSOkVJKUfRh0PJcCCZgpTBAa7UV++GsT9SZ8jRtUPDfAy/R
0TSwKkEC6b1291xNdV3O83CtkSJRTP39nVCefXrBUpIwmkQJuytBF1qypTuw4jom
orcbmE40O7uNDe0FpZOJkUxT1sVJqj+y2h4mJsDuEAYKVQa4809yDwlQOYlLg6i3
wEBut7PPh8bEFWycNElKseh3dpQfvFVWMcUBafpQq7Q9zVFDW3nCUkFBMErcLb0y
VARQizrO3GqmWSU0zmgs8ruc3HnYjIfLIU68JRDsLdFgzIstEasnOskdUYywdvYw
BeGpCQX2ZFcTosLrZc1SRAk/XKioVXeHA92dcQacBClzKCmbat0CcNng5phu9fom
xGbNijvV5NWmQITw7j2sco0nLtfx2MiyRlR8s6pgrZ/VgfGq5K2gM306MgshgyMW
oIELm7aUTkbY+QH4v0y+U/KUNeHetDZhsMLwZq1DuQGNBGERxNwBDAC1RE2JFOjA
Mzqg3f5JsTa51WgApe2zlS/QjD+qr2LbC0CvQK3WO/MseqnEBfnXlUrL+tCzQXG7
9+kJk5xHsdaIbblTqdX3xNbT0/+sJkLsUWbfLh1lTgs+NnltsCtg1cIKm/eOBEWy
VfnrkKI+uTlQDDGcHW9XGaxLaIMi8FgaitMtrvH3AdajEpvpvdAAUbeIUL/hFs6V
TSs74xJRxy0J1eZYlZXo2YQ8EuZCAtyaQuvoDKijybxqj+FKPRiL920UI2emBYL0
cwMRq1XylZST7xXEzrEVgQ+xEUTBOUgmbRmIJVsSE/pDy7127dwPVpTglWiwfqnt
gdujrl6HM2b0a6lV5/ZoeYL5ucu6bku0ewbkoEKhqTe1JSVYWbStW5hwGFBxCFxG
pKQMMsDltmst8Z0Ic1Bhes00gd7LAC0AK8OkWFs4sIbHinNBVXQH/5MINF2ngm9t
P9kym17Nr5JterbxOOyNYl+ZOq6HFsrMXMZ1Cx+d4diqK2GnSeCZIvMAEQEAAYkB
vAQYAQgAJhYhBIgtz+SOIFHUjiViq/O2B0iNs1pHBQJhEcTcAhsMBQkDwmcAAAoJ
EPO2B0iNs1pHmFMMAOuyEJ93J4X5H+Jnf8/pXg2PFVvp0se7weCFha1d9umGSTrQ
Ejivm55z1X4R+Jt6D/cL3wN1WnayyNEtVzTD1CiuMDNO4a+qyBmE3/tJRWyIXoZ/
wdNu38rRNO/SdNbDWj0dCl6HCokLKSlfpP7996zymNeVX7yCw7T56jb2mTILTszy
E0xYPVAKb8cRZt9gUTivxQ3SPw5xVe1OXcF0Dkwx2EAAm7Alo6DMCZlqTii8Xc6K
YcaSRHNdlmkkW3RcTMkNja5mRFhzygklh9ViXqQs+9gZB+VHDqB2iNKbHJwO40aL
Ro/bta1h9P0HDD8q8mZWkZpGBlzul0x5UMedCeYudk9tOMwFCKRrhZeAyzMRn/+F
XUw7oFiWX6RX9ujq0O+Yna6WsWe+YN/vmT0KloTzRb0yqeDc37zc850+woYy+mNp
V2+Tq6hBDajk+BohvFyI7T4vvs45e+GwN2fTS6oqVsc9TfO7Q8JTi5y9UqByEbNC
bqY/IeIwaapRIqDYsg==
=bQDM
-----END PGP PUBLIC KEY BLOCK-----
+2 -2
View File
@@ -1,5 +1,5 @@
title Arch Linux install medium (%ARCH%, UEFI)
sort-key 01
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
@@ -1,5 +1,5 @@
title Arch Linux install medium (%ARCH%, UEFI) with speech
sort-key 02
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on
+4 -4
View File
@@ -46,14 +46,14 @@ timeout_style=menu
menuentry "Arch Linux install medium (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
}
menuentry "Arch Linux install medium with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
}
+4 -4
View File
@@ -23,14 +23,14 @@ timeout_style=menu
menuentry "Arch Linux install medium (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}"
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}"
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
}
menuentry "Arch Linux install medium with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' {
set gfxpayload=keep
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
}
+201
View File
@@ -0,0 +1,201 @@
#!/usr/bin/env bash
# ============================================================================
# build-end4-deps.sh — Build ALL end-4 (illogical-impulse) AUR dependencies
#
# This script builds every AUR package required by the end-4 dots-hyprland
# dotfiles that is NOT in the official Arch repos or chaotic-aur.
#
# It uses --noconfirm throughout so the entire run is non-interactive.
#
# Usage:
# ./localrepo/build-end4-deps.sh # build all
# ./localrepo/build-end4-deps.sh --quick # skip large AUR pkgs (use existing)
#
# After building, run ./localrepo/update.sh to refresh the repo database.
# ============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="${SCRIPT_DIR}"
WORK_DIR=$(mktemp -d /tmp/end4-build.XXXXXX)
SKIP_LARGE=false
for arg in "$@"; do
case "$arg" in
--quick) SKIP_LARGE=true ;;
esac
done
# ── colours ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
fail() { echo -e "${RED}[FAIL]${NC} $*"; }
# ── helper: build a single AUR package ───────────────────────────────────────
build_aur_pkg() {
local pkg="$1"
local src_url="https://aur.archlinux.org/cgit/aur.git/snapshot/${pkg}.tar.gz"
local pkg_dir="${WORK_DIR}/${pkg}"
info "Building AUR package: ${pkg}"
mkdir -p "${pkg_dir}"
if ! curl -fsSL "${src_url}" | tar xz -C "${WORK_DIR}"; then
fail "Failed to download ${pkg}"; return 1
fi
if ! (cd "${pkg_dir}" && makepkg -sfi --noconfirm --cleanbuild); then
fail "Failed to build ${pkg}"; return 1
fi
# Move built packages to localrepo
find "${pkg_dir}" -maxdepth 1 -name '*.pkg.tar.zst' -exec mv -f {} "${REPO_DIR}/" \;
ok "Built: ${pkg}"
return 0
}
# ── helper: build from a local PKGBUILD directory ────────────────────────────
build_local_pkgbuild() {
local pkg_dir="$1"
local pkg_name
pkg_name=$(basename "${pkg_dir}")
if ls "${REPO_DIR}"/illogical-impulse-"${pkg_name}"-*.pkg.tar.zst 1>/dev/null 2>&1; then
info "Package already exists in localrepo, skipping: ${pkg_name}"
return 0
fi
info "Building local PKGBUILD: ${pkg_name}"
if ! (cd "${pkg_dir}" && makepkg -sfi --noconfirm --cleanbuild); then
fail "Failed to build ${pkg_name}"; return 1
fi
find "${pkg_dir}" -maxdepth 1 -name '*.pkg.tar.zst' -exec mv -f {} "${REPO_DIR}/" \;
ok "Built: ${pkg_name}"
return 0
}
# ============================================================================
# 1. Build end-4 metapackages from local PKGBUILDs
# ============================================================================
info "═══ Step 1: Building end-4 metapackages ═══"
for pkg_dir in "${SCRIPT_DIR}"/end4-pkgbuilds/*/; do
build_local_pkgbuild "${pkg_dir}" || true
done
# ============================================================================
# 2. Build AUR dependencies required by end-4
# ============================================================================
info "═══ Step 2: Building AUR dependencies ═══"
# ── Theming & appearance ─────────────────────────────────────────────────────
# Entries in these lists must start at column 0: CI's package check accepts
# repo-less packages via `grep -qxF <pkg>` against this file (exact whole-line
# match), which silently never matched while the names were indented.
AUR_THEMING=(
adw-gtk-theme-git
darkly-bin
ttf-material-symbols-variable-git
ttf-readex-pro
ttf-rubik-vf
ttf-twemoji
otf-space-grotesk
kde-material-you-colors-git
)
# ── end-4 specific / build-from-source packages ──────────────────────────────
# matugen — material you color generation tool
# speech-dispatcher — may need AUR build on some setups
AUR_TOOLS=(
matugen
python-rpypostprocess
tts
)
# ── Packages not in any standard repo ────────────────────────────────────────
AUR_MISSING=(
asciinema-agg
davs2
varia
woeusb-ng
ttf-ms-fonts
)
# ── Large / complex builds (skipped with --quick) ────────────────────────────
AUR_LARGE=(
# quickshell is already built from end4-pkgbuilds above
)
# ── Run builds ───────────────────────────────────────────────────────────────
FAILED=()
for pkg in "${AUR_THEMING[@]}" "${AUR_TOOLS[@]}" "${AUR_MISSING[@]}"; do
build_aur_pkg "${pkg}" || FAILED+=("${pkg}")
done
if [[ "${SKIP_LARGE}" == false ]]; then
for pkg in "${AUR_LARGE[@]}"; do
build_aur_pkg "${pkg}" || FAILED+=("${pkg}")
done
fi
# ============================================================================
# 3. Build end-4 setup script dependencies (from dots-hyprland/setup)
# ============================================================================
info "═══ Step 3: Building end-4 setup helper packages ═══"
DOTS_DIR="${HOME}/dots-hyprland"
if [[ -d "${DOTS_DIR}" ]]; then
# Build any remaining metapackages from the dist-arch directory
for pkg_dir in "${DOTS_DIR}"/sdata/dist-arch/illogical-impulse-*/; do
pkg_name=$(basename "${pkg_dir}")
# Skip the ones we already built above
if ls "${REPO_DIR}"/illogical-impulse-"${pkg_name#illogical-impulse-}"-*.pkg.tar.zst 1>/dev/null 2>&1; then
info "Already built, skipping: ${pkg_name}"
continue
fi
# Only build packages that have a PKGBUILD (metapackages with depends=())
if [[ -f "${pkg_dir}/PKGBUILD" ]]; then
info "Building from dots-hyprland: ${pkg_name}"
(cd "${pkg_dir}" && makepkg -sfi --noconfirm --cleanbuild) || {
warn "Failed to build ${pkg_name} from dots-hyprland, skipping"
continue
}
find "${pkg_dir}" -maxdepth 1 -name '*.pkg.tar.zst' -exec mv -f {} "${REPO_DIR}/" \;
ok "Built: ${pkg_name}"
fi
done
else
warn "dots-hyprland not found at ${DOTS_DIR}, skipping dist-arch builds"
fi
# ============================================================================
# 4. Refresh local repository database
# ============================================================================
info "═══ Step 4: Refreshing local repository database ═══"
bash "${SCRIPT_DIR}/update.sh"
# ============================================================================
# 5. Cleanup & summary
# ============================================================================
rm -rf "${WORK_DIR}"
echo ""
echo "═══════════════════════════════════════════════════════════════"
if [[ ${#FAILED[@]} -gt 0 ]]; then
warn "Build completed with ${#FAILED[@]} failures:"
for f in "${FAILED[@]}"; do
echo " ✗ ${f}"
done
echo ""
echo "The following packages were built successfully into localrepo:"
else
ok "All builds completed successfully!"
fi
echo ""
echo "Packages in localrepo:"
for p in "${REPO_DIR}"/*.pkg.tar.zst; do
[[ -e "${p}" ]] || continue
echo " ✓ $(basename "${p}")"
done
echo "═══════════════════════════════════════════════════════════════"
@@ -0,0 +1,18 @@
groups=(illogical-impulse)
pkgname=illogical-impulse-bibata-modern-classic-bin
pkgver=2.0.6
pkgrel=2
pkgdesc="Material Based Cursor Theme, installed for illogical-impulse dotfiles"
arch=('any')
url="https://github.com/ful1e5/Bibata_Cursor"
license=('GPL-3.0-or-later')
conflicts=("bibata-cursor-theme" "bibata-cursor-theme-bin")
options=('!strip')
_variant=Bibata-Modern-Classic
source=("${pkgname%-bin}-$pkgver.tar.xz::$url/releases/download/v$pkgver/$_variant.tar.xz")
sha256sums=('SKIP')
package() {
install -dm755 "$pkgdir/usr/share/icons"
cp -dr --no-preserve=mode $_variant "$pkgdir/usr/share/icons"
}
@@ -0,0 +1,39 @@
groups=(illogical-impulse)
pkgname=illogical-impulse-microtex-git
_pkgname=MicroTeX
pkgver=r494.0e3707f
pkgrel=4
pkgdesc='MicroTeX for illogical-impulse dotfiles.'
#pkgdesc="A dynamic, cross-platform, and embeddable LaTeX rendering library"
arch=("x86_64")
#url="https://github.com/NanoMichael/${_pkgname}"
url="https://github.com/end-4/${_pkgname}"
license=('MIT')
depends=(
tinyxml2
gtkmm3
gtksourceviewmm
cairomm
)
makedepends=("git" "cmake")
source=("git+${url}.git")
sha256sums=("SKIP")
prepare() {
cd $_pkgname
sed -i 's/gtksourceviewmm-3.0/gtksourceviewmm-4.0/' CMakeLists.txt
sed -i 's/tinyxml2.so.10/tinyxml2.so.11/' CMakeLists.txt
}
build() {
cd $_pkgname
cmake -B build -S . -DCMAKE_BUILD_TYPE=None
cmake --build build
}
package() {
cd $_pkgname
install -Dm0755 -t "$pkgdir/opt/$_pkgname/" build/LaTeX
cp -r build/res "$pkgdir/opt/$_pkgname/"
install -Dm0644 -t "$pkgdir/usr/share/licenses/$pkgname/" LICENSE
}
@@ -0,0 +1,82 @@
_commit='7511545ee20664e3b8b8d3322c0ffe7567c56f7a'
# Useful links:
# https://git.outfoxxed.me/quickshell/quickshell/commits/branch/master
# https://aur.archlinux.org/packages/quickshell-git
groups=(illogical-impulse)
_prefix='illogical-impulse'
_pkgname=quickshell
pkgname="$_prefix-$_pkgname-git"
pkgver=0.1.0.r1
pkgrel=8
pkgdesc="$_pkgname-git pinned commit and extra deps for $_prefix"
arch=(x86_64 aarch64)
url='https://git.outfoxxed.me/quickshell/quickshell'
options=(!strip)
license=('LGPL-3.0-only')
depends=(
'cpptrace'
'jemalloc'
'mesa'
'qt6-declarative'
'qt6-base'
'qt6-svg'
'libdrm'
'libpipewire'
'libxcb'
'wayland'
# NOTE: Below are custom dependencies of illogical-impulse
qt6-5compat
qt6-avif-image-plugin
qt6-imageformats
qt6-multimedia
qt6-positioning
qt6-quicktimeline
qt6-sensors
qt6-svg
qt6-tools
qt6-translations
qt6-virtualkeyboard
qt6-wayland
kirigami
kdialog
syntax-highlighting
)
makedepends=(
'cli11'
'cmake'
'git'
'ninja'
'qt6-shadertools'
'spirv-tools'
'vulkan-headers'
'wayland'
'wayland-protocols'
)
provides=("$_pkgname" "$_pkgname-git")
conflicts=("$_pkgname" "$_pkgname-git")
_pkgsrc="$_pkgname"
source=("$_pkgsrc::git+$url.git#commit=$_commit"
quickshell-check.hook)
sha256sums=('SKIP'
'8543e21aeaaa5441b73a679160e7601a957f16c433e8d6bd9257e80bd0e94083')
build() {
cd "$_pkgname"
cmake -GNinja -B build \
-DCMAKE_BUILD_TYPE="RelWithDebInfo" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DDISTRIBUTOR="AUR (package: quickshell-git)" \
-DDISTRIBUTOR_DEBUGINFO_AVAILABLE=NO \
-DINSTALL_QML_PREFIX=lib/qt6/qml
cmake --build build
}
package() {
install -Dm644 "quickshell-check.hook" -t "$pkgdir/usr/share/libalpm/hooks"
cd "$_pkgname"
DESTDIR="$pkgdir" cmake --install build
install -Dm644 "LICENSE" -t "$pkgdir/usr/share/licenses/$_pkgname"
}
@@ -0,0 +1,10 @@
[Trigger]
Operation = Upgrade
Operation = Install
Type = Package
Target = qt6-base
Target = qt6-wayland
[Action]
Description = Querying Quickshell compatibility after Qt6 update...
When = PostTransaction
Exec = /usr/bin/quickshell --private-check-compat
Binary file not shown.
Binary file not shown.
Binary file not shown.
+15
View File
@@ -22,11 +22,26 @@ mapfile -t pkgs < <(find "${repo_dir}" -maxdepth 1 -name '*.pkg.tar.zst' -print
if [[ ${#pkgs[@]} -eq 0 ]]; then
echo "No .pkg.tar.zst files in ${repo_dir}" >&2
# keep the medium's copy honest too - an emptied localrepo/ must not
# leave the previous packages shipping on the next build
rm -rf "${profile_dir}/airootfs/opt/localrepo"
exit 0
fi
repo-add -R "${repo_dir}/${repo_name}.db.tar.gz" "${pkgs[@]}"
# Sync the medium's copy: the ISO ships its own [local-aur] at
# airootfs/opt/localrepo (pacman.conf on the live system points there, and
# pacstrap resolves these packages from it at install time).
img_repo="${profile_dir}/airootfs/opt/localrepo"
mkdir -p "${img_repo}"
rm -f "${img_repo}"/*.pkg.tar.zst "${img_repo}/${repo_name}".db \
"${img_repo}/${repo_name}".db.tar.gz "${img_repo}/${repo_name}".files \
"${img_repo}/${repo_name}".files.tar.gz
cp -f "${pkgs[@]}" "${img_repo}/"
cp -fL "${repo_dir}/${repo_name}".db* "${repo_dir}/${repo_name}".files* "${img_repo}/"
echo "Medium copy ready: ${img_repo}"
new_names=()
for p in "${pkgs[@]}"; do
name=$(tar -xOf "${p}" .PKGINFO | sed -n 's/^pkgname = //p' | head -1)
+65 -18
View File
@@ -14,19 +14,22 @@ base
base-devel
bash
bat
bc
bcachefs-tools
bind
blueman
bluez
bluez-uttils
bluez-utils
bolt
brightnessctl
brltty
btop
bullet
btrfs-progs
bully
cachyos-keyring
cachyos-mirrorlist
catppuccin-cursors-macchiato
cava
celt
chaotic-keyring
chaotic-mirrorlist
@@ -34,6 +37,8 @@ cifs-utils
clamav
clonezilla
cloud-init
cliphist
cmake
cmatrix
code
cowsay
@@ -41,6 +46,7 @@ cpio
cronie
cryptsetup
cups
curl
darkhttpd
davs2
dconf-editor
@@ -50,6 +56,7 @@ dialog
diffutils
dmidecode
dmraid
ddcutil
dnsmasq
dolphin-plugins
dosfstools
@@ -61,14 +68,14 @@ efibootmgr
electron
element-desktop
espeakup
eternalterminal
eternalterminal-client
eternalterminal-server
ethtool
exfatprogs
f2fs-tools
faac
faad2
fish
flac
fontconfig
fastfetch
fatresize
fcitx5
@@ -93,6 +100,7 @@ fzf
ghostty
ghostty-terminfo
git
geoclue
glib2-devel
gnome-disk-utility
gnome-font-viewer
@@ -100,11 +108,11 @@ gnome-online-accounts
gnome-power-manager
gpart
gparted
go-yq
gpm
gptfdisk
grml-zsh-config
grub
grub-customizer
gst-plugins-base
gst-plugins-ugly
gst-plugin-va
@@ -120,13 +128,20 @@ hcxtools
hdparm
htop
hyperv
hypridle
hyprlock
hyprpolkitagent
hyprpicker
hyprshot
hyprsunset
icu
intel-ucode
inxi
irssi
iw
iwd
jfsutils
jq
just
kdeconnect
kde-inotify-survey
@@ -134,6 +149,8 @@ kdenetwork-filesharing
kimageformats
kio-admin
kio-gdrive
kirigami
kitty
kitty-terminfo
kleopatra
kmscon-terminfo
@@ -146,13 +163,20 @@ kwalletmanager
lazygit
ldns
less
libass
libdbusmenu-gtk3
libdecor
libevdev
libportal
libportal-gtk4
libqalculate
libpipewire
lftp
libfido2
libfprint
libisoburn
libtorrent
libusb-compat
linux
linux-atm
linux-cachyos
linux-cachyos-headers
@@ -172,11 +196,12 @@ magic-wormhole
mako
man-db
man-pages
matugen
mc
mdadm
memtest86+
memtest86+-efi
meshy-git
meson
mkinitcpio
mkinitcpio-archiso
mkinitcpio-nfs-utils
@@ -188,12 +213,14 @@ mplayer
mpv-mpris
mtools
nano
ncurses
nbd
ndisc6
neofetch
neovim
net-tools
network-manager-applet
networkmanager
nfs-utils
nikto
nilfs-utils
@@ -221,7 +248,6 @@ openvpn
os-prober
otf-font-awesome
pacman-contrib
pacserve
pamixer
partclone
parted
@@ -231,8 +257,11 @@ pcsclite
perl-image-exiftool
piper
pipewire-alsa
pipewire-pulse
plasma-browser-integration
playerctl
plocate
polkit
power-profiles-daemon
ppp
pptpclient
@@ -246,15 +275,26 @@ python-pyquery
python-ufonormalizer
python-uv
python-virtualenv
python-aiohttp
python-packaging
qalculate-gtk
qemu-full
qemu-guest-agent
qt5-quickcontrols2
qt6ct
qt6-5compat
qt6-imageformats
qt6-multimedia
qt6-positioning
qt6-quicktimeline
qt6-sensors
qt6-tools
qt6-translations
qt6-virtualkeyboard
qt6-wayland
rclone
refind
reflector
rpi-imager-git
rsync
rxvt-unicode-terminfo
samba
@@ -272,18 +312,18 @@ shelly
shelly-flatpak-backend
shfmt
smartmontools
snapd
sof-firmware
sox
songrec
speech-dispatcher
squashfs-tools
sshfs
ssh-import-id
steam
starship
sudo
swaync
syncthing
syncthingtray-qt6
syncthingtray
syntax-highlighting
syslinux
systemd-resolvconf
tailscale
@@ -291,6 +331,8 @@ tcpdump
tea
terminus-font
termshark
tesseract
tesseract-data-eng
testdisk
texlive-bin
thunar
@@ -310,15 +352,18 @@ ttf-droid
ttf-fantasque-nerd
ttf-fira-code
ttf-jetbrains-mono
ttf-jetbrains-mono-nerd
ttf-material-symbols-variable-git
ttf-ms-fonts
ttf-victor-mono
ttf-readex-pro
ttf-twemoji
tty-clock
tumbler
udftools
uget
umockdev
unrar
upscayl-bin
upower
uriparser
usbguard
usb_modeswitch
@@ -332,7 +377,7 @@ vim
virt-manager
virtualbox-guest-utils-nox
vpnc
wallust
wayland-protocols
wine
winetricks
wireless-regdb
@@ -340,14 +385,16 @@ wireless_tools
woeusb-ng
wpa_supplicant
wvdial
wtype
xarchiver
xclip
xdg-utils
xdg-user-dirs
xdotool
xfsprogs
xl2tpd
xwaylandvideobridge
yay
ydotool
yt-dlp
zen-browser-bin
zram-generator
+1 -1
View File
@@ -103,7 +103,7 @@ Include = /etc/pacman.d/chaotic-mirrorlist
[local-aur]
SigLevel = Optional TrustAll
Server = file:///home/alvin/alvinarch/localrepo
Server = file:///home/alvin/AlvinArch/localrepo
# An example of a custom package repository. See the pacman manpage for
# tips on creating your own repositories.
+32 -2
View File
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
iso_name="archlinux"
iso_name="Alvin archlinux"
iso_label="AlvinArch_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)"
iso_publisher="Arch Linux <https://archlinux.org>"
iso_application="Arch Linux Live ISO"
iso_application="Alvin Arch Linux Live ISO"
iso_version="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y.%m.%d)"
install_dir="arch"
buildmodes=('iso')
@@ -20,6 +20,36 @@ file_permissions=(
["/root/.automated_script.sh"]="0:0:755"
["/root/.gnupg"]="0:0:700"
["/usr/local/bin/choose-mirror"]="0:0:755"
["/usr/local/bin/alvin-install"]="0:0:755"
["/usr/local/bin/Installation_guide"]="0:0:755"
["/usr/local/bin/livecd-sound"]="0:0:755"
)
# ── Build stamp (staged file, never committed) ────────────────────────────────
# airootfs/root/.iso-build-stamp lands at /root/.iso-build-stamp on the ISO;
# customize_airootfs.sh installs it as /etc/alvin-build-stamp, and alvin-install
# appends it to the installed system's /etc/motd. Only stamp builds from a git
# checkout or CI — a random source-tarball build would record a bogus commit.
# Sourced by mkarchiso under `set -eu`, hence every expansion is defaulted.
_stamp_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_stamp_file="${_stamp_dir}/airootfs/root/.iso-build-stamp"
rm -f "${_stamp_file}"
if [[ -e "${_stamp_dir}/.git" || -n "${CI:-}" || -n "${GITEA_ACTIONS:-}" ]]; then
_stamp_build="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y-%m-%d)"
# git ≥2.46 honours -c safe.directory even when mkarchiso runs as root
# over a user-owned checkout; older gits ignore it (protected-config
# scope) and fall through to the "unknown" line below instead of failing
# the build (`|| true` keeps set -e happy either way).
_stamp_commit="$(git -C "${_stamp_dir}" -c safe.directory="${_stamp_dir}" \
log -1 --format='%cs|%h' 2>/dev/null || true)"
if [[ -n "${_stamp_commit}" && "${_stamp_commit}" == *"|"* ]]; then
_stamp_hash="${_stamp_commit##*|}"
printf 'AlvinArch build %s | commit %s | %s\n' \
"${_stamp_build}" "${_stamp_commit%%|*}" "${_stamp_hash:0:4}" \
> "${_stamp_file}"
else
printf 'AlvinArch build %s | commit unknown\n' \
"${_stamp_build}" > "${_stamp_file}"
fi
fi
unset _stamp_dir _stamp_file _stamp_build _stamp_commit _stamp_hash
+6 -6
View File
@@ -4,8 +4,8 @@ Boot the Arch Linux install medium using NBD.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Arch Linux install medium (%ARCH%, NBD)
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% archiso_nbd_srv=${pxeserver} cms_verify=y
SYSAPPEND 3
@@ -15,8 +15,8 @@ Boot the Arch Linux live medium using NFS.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Arch Linux install medium (%ARCH%, NFS)
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
APPEND archisobasedir=%INSTALL_DIR% archiso_nfs_srv=${pxeserver}:/run/archiso/bootmnt cms_verify=y
SYSAPPEND 3
@@ -26,7 +26,7 @@ Boot the Arch Linux live medium using HTTP.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Arch Linux install medium (%ARCH%, HTTP)
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
LINUX ::/%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
INITRD ::/%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ cms_verify=y
SYSAPPEND 3
+4 -4
View File
@@ -4,8 +4,8 @@ Boot the Arch Linux install medium on BIOS.
It allows you to install Arch Linux or perform system maintenance.
ENDTEXT
MENU LABEL Arch Linux install medium (%ARCH%, BIOS)
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
# Accessibility boot option
@@ -15,6 +15,6 @@ Boot the Arch Linux install medium on BIOS with speakup screen reader.
It allows you to install Arch Linux or perform system maintenance with speech feedback.
ENDTEXT
MENU LABEL Arch Linux install medium (%ARCH%, BIOS) with ^speech
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on