Compare commits
10 commits
1c29f45a0b
...
ed115df979
Author | SHA1 | Date | |
---|---|---|---|
|
ed115df979 | ||
|
ac44379453 | ||
|
e2adf15f42 | ||
|
4057162e15 | ||
|
11b62648b1 | ||
|
5200aa1897 | ||
|
3175518459 | ||
|
a9dfa3c3fa | ||
|
c47b5ff316 | ||
|
bcf8abf874 |
2 changed files with 55 additions and 25 deletions
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# akshara
|
||||||
|
|
||||||
|
A simple system builder and immutability layer.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
To test a modified copy of `akshara`, run the following on a working blendOS install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
umount -l /usr && sudo mv ./akshara /usr/bin/akshara && sudo chmod +x /usr/bin/akshara
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `./akshara` with wherever your modified copy of `akshara` is.
|
||||||
|
|
||||||
|
⚠ **ANY CHANGES TO `/usr/bin/akshara` WILL BE REVERTED AFTER EVERY UPDATE!** ⚠
|
65
akshara
65
akshara
|
@ -19,15 +19,11 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
|
||||||
import yaml
|
import yaml
|
||||||
import shutil
|
|
||||||
import filecmp
|
import filecmp
|
||||||
import argparse
|
import argparse
|
||||||
import requests
|
import requests
|
||||||
import platform
|
|
||||||
import fasteners
|
import fasteners
|
||||||
from threading import Event
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
__version = '1.0.0'
|
__version = '1.0.0'
|
||||||
|
@ -137,33 +133,43 @@ def update_system():
|
||||||
blend_release = yaml.load(
|
blend_release = yaml.load(
|
||||||
blend_release_file, Loader=yaml.FullLoader)
|
blend_release_file, Loader=yaml.FullLoader)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Add check that all packages actually exist
|
||||||
|
|
||||||
info('downloading Arch tarball...')
|
info('downloading Arch tarball...')
|
||||||
|
|
||||||
|
# TODO: currently it errors if it doesn't have arch-repo anyways, so this doesn't need any extra checking, maybe add a check for that later though
|
||||||
|
# The mirror to use for downloading the bootstrap image
|
||||||
|
# For example, for the Arch mirror at mirrors.acm.wpi.edu, you'd use https://mirrors.acm.wpi.edu/archlinux
|
||||||
|
# Not sure why this wouldn't just use `arch-repo` but whatever
|
||||||
|
bootstrap_mirror = blend_release.get("arch-repo")
|
||||||
|
|
||||||
if not os.path.isfile('/.update.tar.zst'):
|
if not os.path.isfile('/.update.tar.zst'):
|
||||||
if exec('wget', '-q', '--show-progress', 'https://geo.mirror.pkgbuild.com/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
if exec('wget', '-q', '--show-progress', f'{bootstrap_mirror}/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
||||||
warn('failed download')
|
warn('failed download')
|
||||||
print()
|
print()
|
||||||
info('trying download again...')
|
info('trying download again...')
|
||||||
print()
|
print()
|
||||||
exec('rm', '-f', '/.update.tar.zst')
|
exec('rm', '-f', '/.update.tar.zst')
|
||||||
if exec('wget', '-q', '--show-progress', 'https://geo.mirror.pkgbuild.com/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
if exec('wget', '-q', '--show-progress', f'{bootstrap_mirror}/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
||||||
error('failed download')
|
error('failed download')
|
||||||
print()
|
print()
|
||||||
error('update failed')
|
error('update failed')
|
||||||
sys.exit(50)
|
sys.exit(50)
|
||||||
|
|
||||||
if exec('bash', '-c', 'sha256sum -c --ignore-missing <(wget -qO- https://geo.mirror.pkgbuild.com/iso/latest/sha256sums.txt | sed "s/archlinux-bootstrap-x86_64\\.tar\\.zst/.update.tar.zst/g") 2>/dev/null') != 0:
|
if exec('bash', '-c', f'sha256sum -c --ignore-missing <(wget -qO- {bootstrap_mirror}/iso/latest/sha256sums.txt | sed "s/archlinux-bootstrap-x86_64\\.tar\\.zst/.update.tar.zst/g") 2>/dev/null') != 0:
|
||||||
error('failed checksum verification')
|
error('failed checksum verification')
|
||||||
print()
|
print()
|
||||||
info('trying download again...')
|
info('trying download again...')
|
||||||
exec('rm', '-f', '/.update.tar.zst')
|
exec('rm', '-f', '/.update.tar.zst')
|
||||||
if exec('wget', '-q', '--show-progress', 'https://geo.mirror.pkgbuild.com/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
if exec('wget', '-q', '--show-progress', f'{bootstrap_mirror}/iso/latest/archlinux-bootstrap-x86_64.tar.zst', '-O', '/.update.tar.zst') != 0:
|
||||||
error('failed download')
|
error('failed download')
|
||||||
print()
|
print()
|
||||||
error('update failed')
|
error('update failed')
|
||||||
sys.exit(50)
|
sys.exit(50)
|
||||||
return
|
return
|
||||||
if exec('bash', '-c', 'sha256sum -c --ignore-missing <(wget -qO- https://geo.mirror.pkgbuild.com/iso/latest/sha256sums.txt | sed "s/archlinux-bootstrap-x86_64\\.tar\\.zst/.update.tar.zst/g") 2>/dev/null') != 0:
|
if exec('bash', '-c', f'sha256sum -c --ignore-missing <(wget -qO- {bootstrap_mirror}/iso/latest/sha256sums.txt | sed "s/archlinux-bootstrap-x86_64\\.tar\\.zst/.update.tar.zst/g") 2>/dev/null') != 0:
|
||||||
error('failed checksum verification')
|
error('failed checksum verification')
|
||||||
print()
|
print()
|
||||||
error('update failed')
|
error('update failed')
|
||||||
|
@ -196,9 +202,7 @@ def update_system():
|
||||||
'blend-files'
|
'blend-files'
|
||||||
]
|
]
|
||||||
|
|
||||||
keep = [
|
persistent_files = []
|
||||||
'/usr/share'
|
|
||||||
]
|
|
||||||
|
|
||||||
if (type(blend_release.get('impl')) == str and
|
if (type(blend_release.get('impl')) == str and
|
||||||
type(blend_release.get('track')) != 'custom'):
|
type(blend_release.get('track')) != 'custom'):
|
||||||
|
@ -224,6 +228,9 @@ def update_system():
|
||||||
if type(blend_release.get('user-services')) == list:
|
if type(blend_release.get('user-services')) == list:
|
||||||
user_services += blend_release.get('user-services')
|
user_services += blend_release.get('user-services')
|
||||||
|
|
||||||
|
if type(blend_release.get('persistent-files')) == list:
|
||||||
|
persistent_files += blend_release.get('persistent-files')
|
||||||
|
|
||||||
exec_chroot('rm', '-f', '/.new_rootfs/etc/resolv.conf')
|
exec_chroot('rm', '-f', '/.new_rootfs/etc/resolv.conf')
|
||||||
|
|
||||||
with open('/.new_rootfs/etc/resolv.conf', 'w') as pacman_mirrorlist_conf:
|
with open('/.new_rootfs/etc/resolv.conf', 'w') as pacman_mirrorlist_conf:
|
||||||
|
@ -233,7 +240,7 @@ def update_system():
|
||||||
if type(blend_release.get('arch-repo')) == str:
|
if type(blend_release.get('arch-repo')) == str:
|
||||||
pacman_mirrorlist_conf.write(f'Server = {blend_release.get("arch-repo")}/$repo/os/$arch\n')
|
pacman_mirrorlist_conf.write(f'Server = {blend_release.get("arch-repo")}/$repo/os/$arch\n')
|
||||||
else:
|
else:
|
||||||
pacman_mirrorlist_conf.write('Server = https://cloudflaremirrors.com/archlinux/$repo/os/$arch\n')
|
pacman_mirrorlist_conf.write('Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch\n')
|
||||||
|
|
||||||
exec_chroot('mkdir', '-p', '/var/cache/pacman/pkg')
|
exec_chroot('mkdir', '-p', '/var/cache/pacman/pkg')
|
||||||
exec_chroot('rm', '-rf', '/var/cache/pacman/pkg')
|
exec_chroot('rm', '-rf', '/var/cache/pacman/pkg')
|
||||||
|
@ -243,23 +250,15 @@ def update_system():
|
||||||
exec_chroot('pacman-key', '--init')
|
exec_chroot('pacman-key', '--init')
|
||||||
exec_chroot('pacman-key', '--populate')
|
exec_chroot('pacman-key', '--populate')
|
||||||
|
|
||||||
counter = 0
|
exec_chroot('sh', '-c', 'mkdir /tmp/rate-mirrors/; cd /tmp/rate-mirrors/; curl -LO $(curl -s https://api.github.com/repos/westandskif/rate-mirrors/releases/latest | grep "browser_download_url.*rate-mirrors-v.*-x86_64-unknown-linux-musl.tar.gz" | cut -d : -f 2,3 | tr -d \\")')
|
||||||
while True:
|
exec_chroot('bash', '-c', 'cd /tmp/rate-mirrors/; tar -xzf rate-mirrors*; cd $(find /tmp/rate-mirrors/ -mindepth 1 -maxdepth 1 -type d); ./rate_mirrors --disable-comments-in-file --entry-country=US --protocol=https arch --max-delay 7200 | sudo tee /etc/pacman.d/mirrorlist')
|
||||||
return_val = exec_chroot('pacman', '-Sy', '--ask=4', 'reflector')
|
|
||||||
counter += 1
|
|
||||||
if counter > 30:
|
|
||||||
error('failed to download packages')
|
|
||||||
exit(50)
|
|
||||||
if return_val == 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
exec_chroot('reflector', '--latest', '5', '--protocol', 'https', '--sort', 'rate', '--save', '/etc/pacman.d/mirrorlist')
|
|
||||||
|
|
||||||
#exec_chroot('sed', 's/#//g', '-i', '/etc/pacman.d/mirrorlist')
|
#exec_chroot('sed', 's/#//g', '-i', '/etc/pacman.d/mirrorlist')
|
||||||
#exec_chroot('bash', '-c', 'grep "^Server =" /etc/pacman.d/mirrorlist > /etc/pacman.d/mirrorlist.tmp; mv /etc/pacman.d/mirrorlist.tmp /etc/pacman.d/mirrorlist')
|
#exec_chroot('bash', '-c', 'grep "^Server =" /etc/pacman.d/mirrorlist > /etc/pacman.d/mirrorlist.tmp; mv /etc/pacman.d/mirrorlist.tmp /etc/pacman.d/mirrorlist')
|
||||||
|
|
||||||
with open('/.new_rootfs/etc/pacman.conf', 'r') as original: data = original.read()
|
with open('/.new_rootfs/etc/pacman.conf', 'r') as original: data = original.read()
|
||||||
with open('/.new_rootfs/etc/pacman.conf', 'w') as modified: modified.write(data.replace("[options]", "[options]\nParallelDownloads = 32\n"))
|
with open('/.new_rootfs/etc/pacman.conf', 'w') as modified: modified.write(data.replace("[options]", "[options]\nParallelDownloads = 32\n"))
|
||||||
|
with open('/.new_rootfs/etc/pacman.conf', 'w') as modified: modified.write(data.replace("#[multilib]\n#Include = /etc/pacman.d/mirrorlist", "[multilib]\nInclude = /etc/pacman.d/mirrorlist"))
|
||||||
|
|
||||||
with open('/.new_rootfs/etc/pacman.conf', 'a') as pacman_conf:
|
with open('/.new_rootfs/etc/pacman.conf', 'a') as pacman_conf:
|
||||||
pacman_conf.write(f'''
|
pacman_conf.write(f'''
|
||||||
|
@ -292,6 +291,7 @@ Server = {package_repo["repo-url"]}
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
while True:
|
while True:
|
||||||
|
print('running packages again')
|
||||||
return_val = exec_chroot('pacman', '-S', '--ask=4', *packages)
|
return_val = exec_chroot('pacman', '-S', '--ask=4', *packages)
|
||||||
counter += 1
|
counter += 1
|
||||||
if counter > 30:
|
if counter > 30:
|
||||||
|
@ -303,6 +303,7 @@ Server = {package_repo["repo-url"]}
|
||||||
counter = 0
|
counter = 0
|
||||||
if aur_packages != []:
|
if aur_packages != []:
|
||||||
while True:
|
while True:
|
||||||
|
print('running aur_packages again')
|
||||||
exec_chroot('useradd', '-m', '-G', 'wheel', '-s', '/bin/bash', 'aur')
|
exec_chroot('useradd', '-m', '-G', 'wheel', '-s', '/bin/bash', 'aur')
|
||||||
exec_chroot('bash', '-c', 'echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur')
|
exec_chroot('bash', '-c', 'echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur')
|
||||||
return_val = exec_chroot(
|
return_val = exec_chroot(
|
||||||
|
@ -326,6 +327,12 @@ Server = {package_repo["repo-url"]}
|
||||||
if type(user_service) is str:
|
if type(user_service) is str:
|
||||||
exec_chroot('systemctl', 'enable', '--global', user_service)
|
exec_chroot('systemctl', 'enable', '--global', user_service)
|
||||||
|
|
||||||
|
for persistent_file in persistent_files:
|
||||||
|
if type(persistent_file) is str:
|
||||||
|
if os.path.exists(persistent_file):
|
||||||
|
exec('mkdir', '-p', '/.new_rootfs/'+ os.path.dirname(persistent_file))
|
||||||
|
exec('cp', persistent_file, '/.new_rootfs/'+ persistent_file)
|
||||||
|
|
||||||
if type(blend_release.get('commands')) == list:
|
if type(blend_release.get('commands')) == list:
|
||||||
for command in blend_release.get('commands'):
|
for command in blend_release.get('commands'):
|
||||||
if type(command) == str:
|
if type(command) == str:
|
||||||
|
@ -402,7 +409,8 @@ Server = {package_repo["repo-url"]}
|
||||||
exec('cp', '-ax', '/.new_rootfs/var/lib/pacman', '/.new.var.lib/pacman')
|
exec('cp', '-ax', '/.new_rootfs/var/lib/pacman', '/.new.var.lib/pacman')
|
||||||
|
|
||||||
exec('mv', '.new_rootfs', '.update_rootfs')
|
exec('mv', '.new_rootfs', '.update_rootfs')
|
||||||
exec('cp', '-ax', '/.update_rootfs/etc', '/.update_rootfs/usr/etc')
|
# don't move /etc/shells to /usr/etc
|
||||||
|
exec('bash', '-c', 'shopt -s extglob; cd /.update_rootfs/etc; cp -ax !(shells) /.update_rootfs/usr/etc; cd -')
|
||||||
|
|
||||||
new_boot_files = []
|
new_boot_files = []
|
||||||
|
|
||||||
|
@ -491,3 +499,10 @@ try:
|
||||||
command()
|
command()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
error('aborting')
|
error('aborting')
|
||||||
|
# remove update and akshara stuff if the program is exited
|
||||||
|
exec('rm', '-rf', '/.new_rootfs/')
|
||||||
|
exec('rm', '-rf', '/.update_rootfs')
|
||||||
|
# it's basically impossible to ^C before akshara has exited but after it's created this file
|
||||||
|
# and i don't *think* that "update" would be destructive at all (unless it failed to run and would't boot), but i don't quite understand it soooo just to be on the safe side
|
||||||
|
exec('rm', '-f', '/.update')
|
||||||
|
# TODO: add similar handling for errors, and an option to not delete stuff on error/early exit
|
||||||
|
|
Loading…
Reference in a new issue