Apply formatting
This commit is contained in:
parent
8b943a903a
commit
98040d8a31
10 changed files with 375 additions and 232 deletions
15
boot.py
15
boot.py
|
@ -1,11 +1,10 @@
|
|||
import os
|
||||
import urllib.request
|
||||
from image import get_device_and_flavour, get_image_name
|
||||
from logger import *
|
||||
from logger import logging, setup_logging, verbose_option
|
||||
import click
|
||||
import subprocess
|
||||
|
||||
|
||||
FASTBOOT = 'fastboot'
|
||||
|
||||
JUMPDRIVE = 'jumpdrive'
|
||||
|
@ -20,9 +19,12 @@ boot_strategies = {
|
|||
|
||||
def dump_bootimg(image_name: str) -> str:
|
||||
path = '/tmp/boot.img'
|
||||
result = subprocess.run(['debugfs',
|
||||
image_name,
|
||||
'-R', f'dump /boot/boot.img {path}'])
|
||||
result = subprocess.run([
|
||||
'debugfs',
|
||||
image_name,
|
||||
'-R',
|
||||
f'dump /boot/boot.img {path}',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Faild to dump boot.img')
|
||||
exit(1)
|
||||
|
@ -43,8 +45,7 @@ def cmd_boot(verbose, type):
|
|||
if type == JUMPDRIVE:
|
||||
file = f'boot-{device}.img'
|
||||
path = os.path.join('/var/cache/jumpdrive', file)
|
||||
urllib.request.urlretrieve(
|
||||
f'https://github.com/dreemurrs-embedded/Jumpdrive/releases/download/{jumpdrive_version}/{file}', path)
|
||||
urllib.request.urlretrieve(f'https://github.com/dreemurrs-embedded/Jumpdrive/releases/download/{jumpdrive_version}/{file}', path)
|
||||
else:
|
||||
path = dump_bootimg(image_name)
|
||||
|
||||
|
|
2
cache.py
2
cache.py
|
@ -1,5 +1,5 @@
|
|||
import shutil
|
||||
from logger import *
|
||||
from logger import setup_logging, verbose_option
|
||||
import click
|
||||
import os
|
||||
|
||||
|
|
42
chroot.py
42
chroot.py
|
@ -4,27 +4,30 @@ import os
|
|||
import shutil
|
||||
|
||||
|
||||
def create_chroot(chroot_path, packages=['base'], pacman_conf='/app/local/etc/pacman.conf', chroot_base_path='/chroot', extra_repos={}):
|
||||
pacman_conf_target = chroot_path+'/etc/pacman.conf'
|
||||
def create_chroot(
|
||||
chroot_path,
|
||||
packages=['base'],
|
||||
pacman_conf='/app/local/etc/pacman.conf',
|
||||
chroot_base_path='/chroot',
|
||||
extra_repos={},
|
||||
):
|
||||
pacman_conf_target = chroot_path + '/etc/pacman.conf'
|
||||
|
||||
os.makedirs(chroot_path+'/etc', exist_ok=True)
|
||||
os.makedirs(chroot_path + '/etc', exist_ok=True)
|
||||
shutil.copyfile(pacman_conf, pacman_conf_target)
|
||||
|
||||
extra_conf = ''
|
||||
for repo_name, repo_options in extra_repos.items():
|
||||
extra_conf += f'\n\n[{repo_name}]\n'
|
||||
extra_conf += '\n'.join(['%s = %s' % (name, value)
|
||||
for name, value in repo_options.items()])
|
||||
extra_conf += '\n'.join(['%s = %s' % (name, value) for name, value in repo_options.items()])
|
||||
with open(pacman_conf_target, 'a') as file:
|
||||
file.write(extra_conf)
|
||||
|
||||
result = subprocess.run(['pacstrap',
|
||||
'-C', pacman_conf_target,
|
||||
'-c',
|
||||
'-G',
|
||||
chroot_path]
|
||||
+ packages
|
||||
+ ['--needed', '--overwrite=*', '-yyuu'])
|
||||
result = subprocess.run(['pacstrap', '-C', pacman_conf_target, '-c', '-G', chroot_path] + packages + [
|
||||
'--needed',
|
||||
'--overwrite=*',
|
||||
'-yyuu',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to install system')
|
||||
exit(1)
|
||||
|
@ -33,8 +36,7 @@ def create_chroot(chroot_path, packages=['base'], pacman_conf='/app/local/etc/pa
|
|||
def create_chroot_user(chroot_path):
|
||||
user = 'kupfer'
|
||||
password = '123456'
|
||||
groups = ['network', 'video', 'audio', 'optical', 'storage',
|
||||
'input', 'scanner', 'games', 'lp', 'rfkill', 'wheel']
|
||||
groups = ['network', 'video', 'audio', 'optical', 'storage', 'input', 'scanner', 'games', 'lp', 'rfkill', 'wheel']
|
||||
install_script = '\n'.join([
|
||||
f'if ! id -u "{user}" >/dev/null 2>&1; then',
|
||||
f' useradd -m {user}',
|
||||
|
@ -43,11 +45,13 @@ def create_chroot_user(chroot_path):
|
|||
f'echo "{user}:{password}" | chpasswd',
|
||||
f'chown {user}:{user} /home/{user} -R',
|
||||
])
|
||||
result = subprocess.run(['arch-chroot',
|
||||
chroot_path,
|
||||
'/bin/bash',
|
||||
'-c',
|
||||
install_script])
|
||||
result = subprocess.run([
|
||||
'arch-chroot',
|
||||
chroot_path,
|
||||
'/bin/bash',
|
||||
'-c',
|
||||
install_script,
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to setup user')
|
||||
exit(1)
|
||||
|
|
42
flash.py
42
flash.py
|
@ -3,7 +3,7 @@ from boot import dump_bootimg
|
|||
import os
|
||||
import subprocess
|
||||
import click
|
||||
from logger import *
|
||||
from logger import logging, setup_logging, verbose_option
|
||||
|
||||
ROOTFS = 'rootfs'
|
||||
BOOTIMG = 'bootimg'
|
||||
|
@ -29,8 +29,7 @@ def cmd_flash(verbose, what, location):
|
|||
logging.info(f'You need to specify a location to flash {what} to')
|
||||
exit(1)
|
||||
if location not in locations:
|
||||
logging.info(
|
||||
f'Invalid location {location}. Choose one of {", ".join(locations)} for location')
|
||||
logging.info(f'Invalid location {location}. Choose one of {", ".join(locations)} for location')
|
||||
exit(1)
|
||||
|
||||
dir = '/dev/disk/by-id'
|
||||
|
@ -38,41 +37,50 @@ def cmd_flash(verbose, what, location):
|
|||
sanitized_file = file.replace('-', '').replace('_', '').lower()
|
||||
if f'jumpdrive{location.split("-")[0]}' in sanitized_file:
|
||||
path = os.path.realpath(os.path.join(dir, file))
|
||||
result = subprocess.run(['lsblk',
|
||||
path,
|
||||
'-o', 'SIZE'],
|
||||
capture_output=True)
|
||||
result = subprocess.run(['lsblk', path, '-o', 'SIZE'], capture_output=True)
|
||||
if result.returncode != 0:
|
||||
logging.info(f'Failed to lsblk {path}')
|
||||
exit(1)
|
||||
if result.stdout == b'SIZE\n 0B\n':
|
||||
logging.info(
|
||||
f'Disk {path} has a size of 0B. That probably means it is not available (e.g. no microSD inserted or no microSD card slot installed in the device) or corrupt or defect')
|
||||
f'Disk {path} has a size of 0B. That probably means it is not available (e.g. no microSD inserted or no microSD card slot installed in the device) or corrupt or defect'
|
||||
)
|
||||
exit(1)
|
||||
|
||||
if location.endswith('-file'):
|
||||
logging.fatal('Not implemented yet')
|
||||
exit()
|
||||
else:
|
||||
result = subprocess.run(['dd',
|
||||
f'if={image_name}',
|
||||
f'of={path}',
|
||||
'bs=20M',
|
||||
'iflag=direct',
|
||||
'oflag=direct',
|
||||
'status=progress'])
|
||||
result = subprocess.run([
|
||||
'dd',
|
||||
f'if={image_name}',
|
||||
f'of={path}',
|
||||
'bs=20M',
|
||||
'iflag=direct',
|
||||
'oflag=direct',
|
||||
'status=progress',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.info(f'Failed to flash {image_name} to {path}')
|
||||
exit(1)
|
||||
|
||||
elif what == BOOTIMG:
|
||||
result = subprocess.run(['fastboot', 'erase', 'dtbo'])
|
||||
result = subprocess.run([
|
||||
'fastboot',
|
||||
'erase',
|
||||
'dtbo',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.info(f'Failed to erase dtbo')
|
||||
exit(1)
|
||||
|
||||
path = dump_bootimg(image_name)
|
||||
result = subprocess.run(['fastboot', 'flash', 'boot', path])
|
||||
result = subprocess.run([
|
||||
'fastboot',
|
||||
'flash',
|
||||
'boot',
|
||||
path,
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.info(f'Failed to flash boot.img')
|
||||
exit(1)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import click
|
||||
import subprocess
|
||||
from logger import *
|
||||
from logger import logging, setup_logging, verbose_option
|
||||
|
||||
|
||||
@click.command(name='forwarding')
|
||||
|
@ -8,31 +8,51 @@ from logger import *
|
|||
def cmd_forwarding(verbose):
|
||||
setup_logging(verbose)
|
||||
|
||||
result = subprocess.run(['sysctl', 'net.ipv4.ip_forward=1'])
|
||||
result = subprocess.run([
|
||||
'sysctl',
|
||||
'net.ipv4.ip_forward=1',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to enable ipv4 forward via sysctl')
|
||||
exit(1)
|
||||
|
||||
result = subprocess.run(['iptables', '-P', 'FORWARD', 'ACCEPT'])
|
||||
result = subprocess.run([
|
||||
'iptables',
|
||||
'-P',
|
||||
'FORWARD',
|
||||
'ACCEPT',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed set iptables rule')
|
||||
exit(1)
|
||||
|
||||
result = subprocess.run(['iptables',
|
||||
'-A', 'POSTROUTING',
|
||||
'-t', 'nat',
|
||||
'-j', 'MASQUERADE',
|
||||
'-s', '172.16.42.0/24'])
|
||||
result = subprocess.run([
|
||||
'iptables',
|
||||
'-A',
|
||||
'POSTROUTING',
|
||||
'-t',
|
||||
'nat',
|
||||
'-j',
|
||||
'MASQUERADE',
|
||||
'-s',
|
||||
'172.16.42.0/24',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed set iptables rule')
|
||||
exit(1)
|
||||
|
||||
result = subprocess.run(['ssh',
|
||||
'-o', 'GlobalKnownHostsFile=/dev/null',
|
||||
'-o', 'UserKnownHostsFile=/dev/null',
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'-t', 'kupfer@172.16.42.1',
|
||||
'sudo route add default gw 172.16.42.2'])
|
||||
result = subprocess.run([
|
||||
'ssh',
|
||||
'-o',
|
||||
'GlobalKnownHostsFile=/dev/null',
|
||||
'-o',
|
||||
'UserKnownHostsFile=/dev/null',
|
||||
'-o',
|
||||
'StrictHostKeyChecking=no',
|
||||
'-t',
|
||||
'kupfer@172.16.42.1',
|
||||
'sudo route add default gw 172.16.42.2',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to add gateway over ssh')
|
||||
exit(1)
|
||||
|
|
74
image.py
74
image.py
|
@ -1,12 +1,8 @@
|
|||
import atexit
|
||||
from logging import root
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import time
|
||||
import click
|
||||
from logger import *
|
||||
from logger import logging, setup_logging, verbose_option
|
||||
from chroot import create_chroot, create_chroot_user
|
||||
|
||||
devices = {
|
||||
|
@ -24,12 +20,10 @@ flavours = {
|
|||
|
||||
def get_device_and_flavour() -> tuple[str, str]:
|
||||
if not os.path.exists('.device'):
|
||||
logging.fatal(
|
||||
f'Please set the device using \'kupferbootstrap image device ...\'')
|
||||
logging.fatal(f'Please set the device using \'kupferbootstrap image device ...\'')
|
||||
exit(1)
|
||||
if not os.path.exists('.flavour'):
|
||||
logging.fatal(
|
||||
f'Please set the flavour using \'kupferbootstrap image flavour ...\'')
|
||||
logging.fatal(f'Please set the flavour using \'kupferbootstrap image flavour ...\'')
|
||||
exit(1)
|
||||
|
||||
with open('.device', 'r') as file:
|
||||
|
@ -50,14 +44,24 @@ def mount_rootfs_image(path):
|
|||
os.makedirs(rootfs_mount)
|
||||
|
||||
def umount():
|
||||
subprocess.run(['umount', '-lc', rootfs_mount],
|
||||
stderr=subprocess.DEVNULL)
|
||||
subprocess.run(
|
||||
[
|
||||
'umount',
|
||||
'-lc',
|
||||
rootfs_mount,
|
||||
],
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
atexit.register(umount)
|
||||
|
||||
result = subprocess.run(['mount',
|
||||
'-o', 'loop',
|
||||
path,
|
||||
rootfs_mount])
|
||||
result = subprocess.run([
|
||||
'mount',
|
||||
'-o',
|
||||
'loop',
|
||||
path,
|
||||
rootfs_mount,
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to loop mount {path} to {rootfs_mount}')
|
||||
exit(1)
|
||||
|
@ -82,8 +86,7 @@ def cmd_device(verbose, device):
|
|||
break
|
||||
|
||||
if device not in devices:
|
||||
logging.fatal(
|
||||
f'Unknown device {device}. Pick one from:\n{", ".join(devices.keys())}')
|
||||
logging.fatal(f'Unknown device {device}. Pick one from:\n{", ".join(devices.keys())}')
|
||||
exit(1)
|
||||
|
||||
logging.info(f'Setting device to {device}')
|
||||
|
@ -99,8 +102,7 @@ def cmd_flavour(verbose, flavour):
|
|||
setup_logging(verbose)
|
||||
|
||||
if flavour not in flavours:
|
||||
logging.fatal(
|
||||
f'Unknown flavour {flavour}. Pick one from:\n{", ".join(flavours.keys())}')
|
||||
logging.fatal(f'Unknown flavour {flavour}. Pick one from:\n{", ".join(flavours.keys())}')
|
||||
exit(1)
|
||||
|
||||
logging.info(f'Setting flavour to {flavour}')
|
||||
|
@ -118,31 +120,47 @@ def cmd_build(verbose):
|
|||
image_name = get_image_name(device, flavour)
|
||||
|
||||
if not os.path.exists(image_name):
|
||||
result = subprocess.run(['fallocate',
|
||||
'-l', '4G',
|
||||
image_name])
|
||||
result = subprocess.run([
|
||||
'fallocate',
|
||||
'-l',
|
||||
'4G',
|
||||
image_name,
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to allocate {image_name}')
|
||||
exit(1)
|
||||
|
||||
result = subprocess.run(['mkfs.ext4',
|
||||
'-L', 'kupfer',
|
||||
image_name])
|
||||
result = subprocess.run([
|
||||
'mkfs.ext4',
|
||||
'-L',
|
||||
'kupfer',
|
||||
image_name,
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to create ext4 filesystem on {image_name}')
|
||||
exit(1)
|
||||
|
||||
rootfs_mount = mount_rootfs_image(image_name)
|
||||
|
||||
create_chroot(rootfs_mount, packages=(['base', 'base-kupfer'] + devices[device] + flavours[flavour]), pacman_conf='/app/local/etc/pacman.conf', extra_repos={'main': {
|
||||
'Server': 'https://gitlab.com/kupfer/packages/prebuilts/-/raw/main/$repo'}, 'device': {'Server': 'https://gitlab.com/kupfer/packages/prebuilts/-/raw/main/$repo'}})
|
||||
create_chroot(
|
||||
rootfs_mount,
|
||||
packages=(['base', 'base-kupfer'] + devices[device] + flavours[flavour]),
|
||||
pacman_conf='/app/local/etc/pacman.conf',
|
||||
extra_repos={
|
||||
'main': {
|
||||
'Server': 'https://gitlab.com/kupfer/packages/prebuilts/-/raw/main/$repo',
|
||||
},
|
||||
'device': {
|
||||
'Server': 'https://gitlab.com/kupfer/packages/prebuilts/-/raw/main/$repo',
|
||||
},
|
||||
},
|
||||
)
|
||||
create_chroot_user(rootfs_mount)
|
||||
|
||||
|
||||
"""
|
||||
This doesn't work, because the mount isn't passed through to the real host
|
||||
"""
|
||||
|
||||
"""
|
||||
@click.command(name='inspect')
|
||||
@verbose_option
|
||||
|
|
|
@ -11,7 +11,7 @@ def setup_logging(verbose: bool):
|
|||
stream=sys.stdout,
|
||||
format='%(asctime)s %(levelname)s: %(message)s',
|
||||
datefmt='%m/%d/%Y %H:%M:%S',
|
||||
level=level
|
||||
level=level,
|
||||
)
|
||||
|
||||
|
||||
|
@ -19,5 +19,5 @@ verbose_option = click.option(
|
|||
'-v',
|
||||
'--verbose',
|
||||
is_flag=True,
|
||||
help='Enables verbose logging'
|
||||
help='Enables verbose logging',
|
||||
)
|
||||
|
|
274
packages.py
274
packages.py
|
@ -1,5 +1,4 @@
|
|||
from cmath import log
|
||||
from logger import *
|
||||
from logger import setup_logging, verbose_option
|
||||
import atexit
|
||||
import click
|
||||
import logging
|
||||
|
@ -15,21 +14,24 @@ makepkg_env = os.environ.copy() | {
|
|||
'MAKEFLAGS': f'-j{multiprocessing.cpu_count()}',
|
||||
}
|
||||
|
||||
makepkg_cross_env = makepkg_env | {
|
||||
'PACMAN': '/app/local/bin/pacman_aarch64'
|
||||
}
|
||||
makepkg_cross_env = makepkg_env | {'PACMAN': '/app/local/bin/pacman_aarch64'}
|
||||
|
||||
makepkg_cmd = ['makepkg',
|
||||
'--config', '/app/local/etc/makepkg.conf',
|
||||
'--noconfirm',
|
||||
'--ignorearch',
|
||||
'--needed']
|
||||
makepkg_cmd = [
|
||||
'makepkg',
|
||||
'--config',
|
||||
'/app/local/etc/makepkg.conf',
|
||||
'--noconfirm',
|
||||
'--ignorearch',
|
||||
'--needed',
|
||||
]
|
||||
|
||||
pacman_cmd = ['pacman',
|
||||
'-Syuu',
|
||||
'--noconfirm',
|
||||
'--overwrite=*',
|
||||
'--needed', ]
|
||||
pacman_cmd = [
|
||||
'pacman',
|
||||
'-Syuu',
|
||||
'--noconfirm',
|
||||
'--overwrite=*',
|
||||
'--needed',
|
||||
]
|
||||
|
||||
|
||||
class Package:
|
||||
|
@ -46,9 +48,11 @@ class Package:
|
|||
self._loadinfo()
|
||||
|
||||
def _loadinfo(self):
|
||||
result = subprocess.run(makepkg_cmd+['--printsrcinfo'],
|
||||
cwd=self.path,
|
||||
stdout=subprocess.PIPE)
|
||||
result = subprocess.run(
|
||||
makepkg_cmd + ['--printsrcinfo'],
|
||||
cwd=self.path,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
lines = result.stdout.decode('utf-8').split('\n')
|
||||
names = []
|
||||
depends = []
|
||||
|
@ -73,8 +77,7 @@ class Package:
|
|||
mode = line.split('=')[1]
|
||||
break
|
||||
if mode not in ['host', 'cross']:
|
||||
logging.fatal(
|
||||
f'Package {self.path} has an invalid mode configured: \'{mode}\'')
|
||||
logging.fatal(f'Package {self.path} has an invalid mode configured: \'{mode}\'')
|
||||
exit(1)
|
||||
self.mode = mode
|
||||
|
||||
|
@ -96,11 +99,16 @@ def check_prebuilts():
|
|||
for ext1 in ['db', 'files']:
|
||||
for ext2 in ['', '.tar.xz']:
|
||||
if not os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext1}{ext2}')):
|
||||
result = subprocess.run(['tar',
|
||||
'-czf',
|
||||
f'{repo}.{ext1}{ext2}',
|
||||
'-T', '/dev/null'],
|
||||
cwd=os.path.join('prebuilts', repo))
|
||||
result = subprocess.run(
|
||||
[
|
||||
'tar',
|
||||
'-czf',
|
||||
f'{repo}.{ext1}{ext2}',
|
||||
'-T',
|
||||
'/dev/null',
|
||||
],
|
||||
cwd=os.path.join('prebuilts', repo),
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed create prebuilt repos')
|
||||
exit(1)
|
||||
|
@ -108,14 +116,29 @@ def check_prebuilts():
|
|||
|
||||
def setup_chroot(chroot_path='/chroot/root'):
|
||||
logging.info('Initializing root chroot')
|
||||
create_chroot(chroot_path, packages=['base-devel'], pacman_conf='/app/local/etc/pacman.conf', extra_repos={
|
||||
'main': {'Server': 'file:///src/prebuilts/main'}, 'device': {'Server': 'file:///src/prebuilts/device'}})
|
||||
create_chroot(
|
||||
chroot_path,
|
||||
packages=['base-devel'],
|
||||
pacman_conf='/app/local/etc/pacman.conf',
|
||||
extra_repos={
|
||||
'main': {
|
||||
'Server': 'file:///src/prebuilts/main',
|
||||
},
|
||||
'device': {
|
||||
'Server': 'file:///src/prebuilts/device',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
logging.info('Updating root chroot')
|
||||
result = subprocess.run(pacman_cmd +
|
||||
['--root', chroot_path,
|
||||
'--arch', 'aarch64',
|
||||
'--config', chroot_path+'/etc/pacman.conf'])
|
||||
result = subprocess.run(pacman_cmd + [
|
||||
'--root',
|
||||
chroot_path,
|
||||
'--arch',
|
||||
'aarch64',
|
||||
'--config',
|
||||
chroot_path + '/etc/pacman.conf',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to update root chroot')
|
||||
exit(1)
|
||||
|
@ -134,8 +157,16 @@ def setup_chroot(chroot_path='/chroot/root'):
|
|||
file.write(data)
|
||||
|
||||
logging.info('Syncing chroot copy')
|
||||
result = subprocess.run(
|
||||
['rsync', '-a', '--delete', '-q', '-W', '-x', '/chroot/root/', '/chroot/copy'])
|
||||
result = subprocess.run([
|
||||
'rsync',
|
||||
'-a',
|
||||
'--delete',
|
||||
'-q',
|
||||
'-W',
|
||||
'-x',
|
||||
'/chroot/root/',
|
||||
'/chroot/copy',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to sync chroot copy')
|
||||
exit(1)
|
||||
|
@ -151,8 +182,7 @@ def discover_packages(path: str) -> dict[str, Package]:
|
|||
for dir2 in os.listdir(os.path.join('device', dir1)):
|
||||
paths.append(os.path.join('device', dir1, dir2))
|
||||
|
||||
results = Parallel(n_jobs=multiprocessing.cpu_count()*4)(
|
||||
delayed(Package)(path) for path in paths)
|
||||
results = Parallel(n_jobs=multiprocessing.cpu_count() * 4)(delayed(Package)(path) for path in paths)
|
||||
for package in results:
|
||||
packages[package.name] = package
|
||||
|
||||
|
@ -189,8 +219,7 @@ def discover_packages(path: str) -> dict[str, Package]:
|
|||
if found:
|
||||
break
|
||||
if not found:
|
||||
logging.fatal(
|
||||
f'Could not find package for "{dep}"')
|
||||
logging.fatal(f'Could not find package for "{dep}"')
|
||||
exit(1)
|
||||
selection = list(set(selection))
|
||||
packages = {package.name: package for package in selection}
|
||||
|
@ -201,7 +230,6 @@ def discover_packages(path: str) -> dict[str, Package]:
|
|||
def generate_package_order(packages: list[Package]) -> list[Package]:
|
||||
unsorted = packages.copy()
|
||||
sorted = []
|
||||
|
||||
"""
|
||||
It goes through all unsorted packages and checks if the dependencies have already been sorted.
|
||||
If that is true, the package itself is added to the sorted packages
|
||||
|
@ -227,13 +255,20 @@ def update_package_version_and_sources(package: Package):
|
|||
It is done here already, because doing it while host-compiling takes longer.
|
||||
We decided to even pin the commit of every -git package so this won't update any version, but it would if possible.
|
||||
"""
|
||||
cmd = makepkg_cmd+['--nobuild', '--noprepare', '--nodeps', '--skipinteg']
|
||||
cmd = makepkg_cmd + [
|
||||
'--nobuild',
|
||||
'--noprepare',
|
||||
'--nodeps',
|
||||
'--skipinteg',
|
||||
]
|
||||
if not package.has_pkgver:
|
||||
cmd.append('--noextract')
|
||||
logging.info(f'Updating package version for {package.path}')
|
||||
result = subprocess.run(cmd,
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path)
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to update package version for {package.path}')
|
||||
exit(1)
|
||||
|
@ -242,13 +277,16 @@ def update_package_version_and_sources(package: Package):
|
|||
def check_package_version_built(package: Package) -> bool:
|
||||
built = True
|
||||
|
||||
result = subprocess.run(makepkg_cmd +
|
||||
['--nobuild',
|
||||
'--noprepare',
|
||||
'--packagelist'],
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path,
|
||||
capture_output=True)
|
||||
result = subprocess.run(
|
||||
makepkg_cmd + [
|
||||
'--nobuild',
|
||||
'--noprepare',
|
||||
'--packagelist',
|
||||
],
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path,
|
||||
capture_output=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to get package list for {package.path}')
|
||||
exit(1)
|
||||
|
@ -264,7 +302,6 @@ def check_package_version_built(package: Package) -> bool:
|
|||
|
||||
def setup_dependencies_and_sources(package: Package):
|
||||
logging.info(f'Setting up dependencies and sources for {package.path}')
|
||||
|
||||
"""
|
||||
To make cross-compilation work for almost every package, the host needs to have the dependencies installed
|
||||
so that the build tools can be used
|
||||
|
@ -276,63 +313,89 @@ def setup_dependencies_and_sources(package: Package):
|
|||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal(
|
||||
f'Failed to setup dependencies for {package.path}')
|
||||
logging.fatal(f'Failed to setup dependencies for {package.path}')
|
||||
exit(1)
|
||||
|
||||
result = subprocess.run(makepkg_cmd +
|
||||
['--nobuild',
|
||||
'--holdver',
|
||||
'--syncdeps'],
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path)
|
||||
result = subprocess.run(
|
||||
makepkg_cmd + [
|
||||
'--nobuild',
|
||||
'--holdver',
|
||||
'--syncdeps',
|
||||
],
|
||||
env=makepkg_cross_env,
|
||||
cwd=package.path,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal(
|
||||
f'Failed to check sources for {package.path}')
|
||||
logging.fatal(f'Failed to check sources for {package.path}')
|
||||
exit(1)
|
||||
|
||||
|
||||
def build_package(package: Package):
|
||||
makepkg_compile_opts = ['--noextract',
|
||||
'--skipinteg',
|
||||
'--holdver',
|
||||
'--nodeps']
|
||||
makepkg_compile_opts = [
|
||||
'--noextract',
|
||||
'--skipinteg',
|
||||
'--holdver',
|
||||
'--nodeps',
|
||||
]
|
||||
|
||||
if package.mode == 'cross':
|
||||
logging.info(f'Cross-compiling {package.path}')
|
||||
result = subprocess.run(makepkg_cmd+makepkg_compile_opts,
|
||||
env=makepkg_cross_env | {
|
||||
'QEMU_LD_PREFIX': '/usr/aarch64-linux-gnu'},
|
||||
cwd=package.path)
|
||||
result = subprocess.run(
|
||||
makepkg_cmd + makepkg_compile_opts,
|
||||
env=makepkg_cross_env | {'QEMU_LD_PREFIX': '/usr/aarch64-linux-gnu'},
|
||||
cwd=package.path,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
logging.fatal(
|
||||
f'Failed to cross-compile package {package.path}')
|
||||
logging.fatal(f'Failed to cross-compile package {package.path}')
|
||||
exit(1)
|
||||
else:
|
||||
logging.info(f'Host-compiling {package.path}')
|
||||
|
||||
def umount():
|
||||
subprocess.run(['umount', '-lc', '/chroot/copy'],
|
||||
stderr=subprocess.DEVNULL)
|
||||
subprocess.run(
|
||||
[
|
||||
'umount',
|
||||
'-lc',
|
||||
'/chroot/copy',
|
||||
],
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
atexit.register(umount)
|
||||
|
||||
result = subprocess.run(
|
||||
['mount', '-o', 'bind', '/chroot/copy', '/chroot/copy'])
|
||||
result = subprocess.run([
|
||||
'mount',
|
||||
'-o',
|
||||
'bind',
|
||||
'/chroot/copy',
|
||||
'/chroot/copy',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal('Failed to bind mount chroot to itself')
|
||||
exit(1)
|
||||
|
||||
os.makedirs('/chroot/copy/src')
|
||||
result = subprocess.run(
|
||||
['mount', '-o', 'bind', '.', '/chroot/copy/src'])
|
||||
result = subprocess.run([
|
||||
'mount',
|
||||
'-o',
|
||||
'bind',
|
||||
'.',
|
||||
'/chroot/copy/src',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(
|
||||
f'Failed to bind mount folder to chroot')
|
||||
logging.fatal(f'Failed to bind mount folder to chroot')
|
||||
exit(1)
|
||||
|
||||
env = [f'{key}={value}' for key, value in makepkg_env.items()]
|
||||
result = subprocess.run(
|
||||
['arch-chroot', '/chroot/copy', '/usr/bin/env'] + env + ['/bin/bash', '-c', f'cd /src/{package.path} && makepkg --noconfirm --ignorearch {" ".join(makepkg_compile_opts)}'])
|
||||
result = subprocess.run([
|
||||
'arch-chroot',
|
||||
'/chroot/copy',
|
||||
'/usr/bin/env',
|
||||
] + env + [
|
||||
'/bin/bash',
|
||||
'-c',
|
||||
f'cd /src/{package.path} && makepkg --noconfirm --ignorearch {" ".join(makepkg_compile_opts)}',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to host-compile package {package.path}')
|
||||
exit(1)
|
||||
|
@ -353,17 +416,18 @@ def add_package_to_repo(package: Package):
|
|||
os.path.join(package.path, file),
|
||||
os.path.join(dir, file),
|
||||
)
|
||||
result = subprocess.run(['repo-add',
|
||||
'--remove',
|
||||
'--new',
|
||||
'--prevent-downgrade',
|
||||
os.path.join(
|
||||
'prebuilts',
|
||||
package.repo,
|
||||
f'{package.repo}.db.tar.xz',
|
||||
),
|
||||
os.path.join(dir, file),
|
||||
])
|
||||
result = subprocess.run([
|
||||
'repo-add',
|
||||
'--remove',
|
||||
'--new',
|
||||
'--prevent-downgrade',
|
||||
os.path.join(
|
||||
'prebuilts',
|
||||
package.repo,
|
||||
f'{package.repo}.db.tar.xz',
|
||||
),
|
||||
os.path.join(dir, file),
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed add package {package.path} to repo')
|
||||
exit(1)
|
||||
|
@ -371,13 +435,9 @@ def add_package_to_repo(package: Package):
|
|||
for ext in ['db', 'files']:
|
||||
if os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz')):
|
||||
os.unlink(os.path.join('prebuilts', repo, f'{repo}.{ext}'))
|
||||
shutil.copyfile(
|
||||
os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz'),
|
||||
os.path.join('prebuilts', repo, f'{repo}.{ext}')
|
||||
)
|
||||
shutil.copyfile(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz'), os.path.join('prebuilts', repo, f'{repo}.{ext}'))
|
||||
if os.path.exists(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz.old')):
|
||||
os.unlink(os.path.join('prebuilts', repo,
|
||||
f'{repo}.{ext}.tar.xz.old'))
|
||||
os.unlink(os.path.join('prebuilts', repo, f'{repo}.{ext}.tar.xz.old'))
|
||||
|
||||
|
||||
@click.group(name='packages')
|
||||
|
@ -405,11 +465,9 @@ def cmd_build(verbose, path):
|
|||
if len(need_build) == 0:
|
||||
logging.info('Everything built already')
|
||||
return
|
||||
logging.info('Building %s', ', '.join(
|
||||
map(lambda x: x.path, need_build)))
|
||||
logging.info('Building %s', ', '.join(map(lambda x: x.path, need_build)))
|
||||
with open('.last_built', 'w') as file:
|
||||
file.write('\n'.join(
|
||||
map(lambda x: x.path, need_build)))
|
||||
file.write('\n'.join(map(lambda x: x.path, need_build)))
|
||||
|
||||
for package in need_build:
|
||||
setup_chroot()
|
||||
|
@ -422,10 +480,13 @@ def cmd_build(verbose, path):
|
|||
@verbose_option
|
||||
def cmd_clean(verbose):
|
||||
setup_logging(verbose)
|
||||
result = subprocess.run(['git',
|
||||
'clean',
|
||||
'-dffX',
|
||||
'main', 'device'])
|
||||
result = subprocess.run([
|
||||
'git',
|
||||
'clean',
|
||||
'-dffX',
|
||||
'main',
|
||||
'device',
|
||||
])
|
||||
if result.returncode != 0:
|
||||
logging.fatal(f'Failed to git clean')
|
||||
exit(1)
|
||||
|
@ -546,8 +607,7 @@ def cmd_check(verbose, path):
|
|||
reason = f'Expected to find "{key}"'
|
||||
|
||||
if not formatted:
|
||||
logging.fatal(
|
||||
f'Line {line_index+1} in {os.path.join(package.path, "PKGBUILD")} is not formatted correctly: "{line}"')
|
||||
logging.fatal(f'Line {line_index+1} in {os.path.join(package.path, "PKGBUILD")} is not formatted correctly: "{line}"')
|
||||
if reason != "":
|
||||
logging.fatal(reason)
|
||||
exit(1)
|
||||
|
|
17
ssh.py
17
ssh.py
|
@ -1,6 +1,6 @@
|
|||
import subprocess
|
||||
import click
|
||||
from logger import *
|
||||
from logger import setup_logging, verbose_option
|
||||
|
||||
|
||||
@click.command(name='ssh')
|
||||
|
@ -8,8 +8,13 @@ from logger import *
|
|||
def cmd_ssh(verbose):
|
||||
setup_logging(verbose)
|
||||
|
||||
subprocess.run(['ssh',
|
||||
'-o', 'GlobalKnownHostsFile=/dev/null',
|
||||
'-o', 'UserKnownHostsFile=/dev/null',
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'kupfer@172.16.42.1'])
|
||||
subprocess.run([
|
||||
'ssh',
|
||||
'-o',
|
||||
'GlobalKnownHostsFile=/dev/null',
|
||||
'-o',
|
||||
'UserKnownHostsFile=/dev/null',
|
||||
'-o',
|
||||
'StrictHostKeyChecking=no',
|
||||
'kupfer@172.16.42.1',
|
||||
])
|
||||
|
|
89
wrapper.py
89
wrapper.py
|
@ -13,46 +13,73 @@ else:
|
|||
version = version_file.read().replace('\n', '')
|
||||
tag = f'registry.gitlab.com/kupfer/kupferbootstrap:{version}'
|
||||
if version == 'dev':
|
||||
result = subprocess.run([
|
||||
'docker',
|
||||
'build',
|
||||
'.',
|
||||
'-t', tag
|
||||
], cwd=script_path)
|
||||
result = subprocess.run(
|
||||
[
|
||||
'docker',
|
||||
'build',
|
||||
'.',
|
||||
'-t',
|
||||
tag,
|
||||
],
|
||||
cwd=script_path,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print(f'Failed to build kupferbootstrap docker image')
|
||||
exit(1)
|
||||
else:
|
||||
# Check if the image for the version already exists
|
||||
result = subprocess.run(['docker', 'images', '-q', tag],
|
||||
capture_output=True)
|
||||
result = subprocess.run(
|
||||
[
|
||||
'docker',
|
||||
'images',
|
||||
'-q',
|
||||
tag,
|
||||
],
|
||||
capture_output=True,
|
||||
)
|
||||
if result.stdout == b'':
|
||||
print(
|
||||
f'Pulling kupferbootstrap docker image version \'{version}\'')
|
||||
subprocess.run(['docker', 'pull', tag])
|
||||
print(f'Pulling kupferbootstrap docker image version \'{version}\'')
|
||||
subprocess.run([
|
||||
'docker',
|
||||
'pull',
|
||||
tag,
|
||||
])
|
||||
|
||||
def at_exit():
|
||||
subprocess.run(['docker', 'kill', 'kupferbootstrap'],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,)
|
||||
subprocess.run(
|
||||
[
|
||||
'docker',
|
||||
'kill',
|
||||
'kupferbootstrap',
|
||||
],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
atexit.register(at_exit)
|
||||
|
||||
# TODO: Remove the mount of /usr/share/i18n/locales. It's a trick so we don't need to generate the locales in the chroot.
|
||||
# Something like a prebuilt docker image as base or copying the files from it would be good.
|
||||
subprocess.run(['docker',
|
||||
'run',
|
||||
'--name', 'kupferbootstrap',
|
||||
'--rm',
|
||||
'--interactive',
|
||||
'--tty',
|
||||
'--privileged',
|
||||
'-v', f'{os.getcwd()}:/src:z',
|
||||
'-v', f'{os.path.join(appdirs.user_cache_dir("kupfer"),"chroot")}:/chroot:z',
|
||||
'-v', f'{os.path.join(appdirs.user_cache_dir("kupfer"),"pacman")}:/var/cache/pacman/pkg:z',
|
||||
'-v', f'{os.path.join(appdirs.user_cache_dir("kupfer"),"jumpdrive")}:/var/cache/jumpdrive:z',
|
||||
'-v', '/dev:/dev',
|
||||
#'-v', '/mnt/kupfer:/mnt/kupfer:z',
|
||||
'-v', '/usr/share/i18n/locales:/usr/share/i18n/locales:ro'] +
|
||||
[tag,
|
||||
'kupferbootstrap']
|
||||
+ sys.argv[1:])
|
||||
subprocess.run([
|
||||
'docker',
|
||||
'run',
|
||||
'--name',
|
||||
'kupferbootstrap',
|
||||
'--rm',
|
||||
'--interactive',
|
||||
'--tty',
|
||||
'--privileged',
|
||||
'-v',
|
||||
f'{os.getcwd()}:/src:z',
|
||||
'-v',
|
||||
f'{os.path.join(appdirs.user_cache_dir("kupfer"),"chroot")}:/chroot:z',
|
||||
'-v',
|
||||
f'{os.path.join(appdirs.user_cache_dir("kupfer"),"pacman")}:/var/cache/pacman/pkg:z',
|
||||
'-v',
|
||||
f'{os.path.join(appdirs.user_cache_dir("kupfer"),"jumpdrive")}:/var/cache/jumpdrive:z',
|
||||
'-v',
|
||||
'/dev:/dev',
|
||||
#'-v', '/mnt/kupfer:/mnt/kupfer:z',
|
||||
'-v',
|
||||
'/usr/share/i18n/locales:/usr/share/i18n/locales:ro'
|
||||
] + [tag, 'kupferbootstrap'] + sys.argv[1:])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue