forked from Mirror/pmbootstrap
WIP: start ripping out args (MR 2252)
Cease merging pmbootstrap.cfg into args, implement a Context type to let us pull globals out of thin air (as an intermediate workaround) and rip args out of a lot of the codebase. This is just a first pass, after this we can split all the state that leaked over into Context into types with narrower scopes (like a BuildContext(), etc). Signed-off-by: Caleb Connolly <caleb@postmarketos.org>
This commit is contained in:
parent
bfea00e03a
commit
34dd9d42ba
129 changed files with 1393 additions and 1300 deletions
|
@ -63,13 +63,13 @@ they contain untrusted input):
|
||||||
|
|
||||||
```py
|
```py
|
||||||
# Does not work, the command does not run in a shell!
|
# Does not work, the command does not run in a shell!
|
||||||
pmb.chroot.root(args, ["echo", "test", ">", "/tmp/test"])
|
pmb.chroot.root(["echo", "test", ">", "/tmp/test"])
|
||||||
|
|
||||||
# Use this instead (assuming untrusted input for text, dest)
|
# Use this instead (assuming untrusted input for text, dest)
|
||||||
text = "test"
|
text = "test"
|
||||||
dest = "/tmp/test"
|
dest = "/tmp/test"
|
||||||
shell_cmd = f"echo {shutil.quote(text)} > {shutil.quote(dest)}"
|
shell_cmd = f"echo {shutil.quote(text)} > {shutil.quote(dest)}"
|
||||||
pmb.chroot.root(args, ["sh", "-c", shell_cmd])
|
pmb.chroot.root(["sh", "-c", shell_cmd])
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need to run many commands in a shell at once, write them into a
|
If you need to run many commands in a shell at once, write them into a
|
||||||
|
@ -83,7 +83,7 @@ the chroot. Use one of the following methods.
|
||||||
|
|
||||||
##### Short files
|
##### Short files
|
||||||
```py
|
```py
|
||||||
pmb.chroot.user(args, ["sh", "-c", f"echo {shlex.quote(hostname)}"
|
pmb.chroot.user(["sh", "-c", f"echo {shlex.quote(hostname)}"
|
||||||
" > /etc/hostname"], suffix)
|
" > /etc/hostname"], suffix)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ with open("tmp/somefile", "w") as handle:
|
||||||
handle.write("Some long file")
|
handle.write("Some long file")
|
||||||
handle.write("with multiple")
|
handle.write("with multiple")
|
||||||
handle.write("lines here")
|
handle.write("lines here")
|
||||||
pmb.chroot.root(args, ["mv", "/tmp/somefile", "/etc/somefile"])
|
pmb.chroot.root(["mv", "/tmp/somefile", "/etc/somefile"])
|
||||||
pmb.chroot.root(args, ["chown", "root:root", "/etc/somefile"], suffix)
|
pmb.chroot.root(["chown", "root:root", "/etc/somefile"], suffix)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manual testing
|
### Manual testing
|
||||||
|
|
|
@ -10,6 +10,7 @@ from pmb.helpers.exceptions import BuildFailedError, NonBugError
|
||||||
|
|
||||||
from . import config
|
from . import config
|
||||||
from . import parse
|
from . import parse
|
||||||
|
from . import types
|
||||||
from .config import init as config_init
|
from .config import init as config_init
|
||||||
from .helpers import frontend
|
from .helpers import frontend
|
||||||
from .helpers import logging
|
from .helpers import logging
|
||||||
|
@ -31,8 +32,8 @@ if version < (3, 9):
|
||||||
|
|
||||||
|
|
||||||
def print_log_hint() -> None:
|
def print_log_hint() -> None:
|
||||||
context = get_context()
|
context = get_context(allow_failure=True)
|
||||||
log = context.log
|
log = context.log if context else types.Config().work / "log.txt"
|
||||||
# Hints about the log file (print to stdout only)
|
# Hints about the log file (print to stdout only)
|
||||||
log_hint = "Run 'pmbootstrap log' for details."
|
log_hint = "Run 'pmbootstrap log' for details."
|
||||||
if not os.path.exists(log):
|
if not os.path.exists(log):
|
||||||
|
@ -50,6 +51,7 @@ def main() -> int:
|
||||||
try:
|
try:
|
||||||
# Parse arguments, set up logging
|
# Parse arguments, set up logging
|
||||||
args = parse.arguments()
|
args = parse.arguments()
|
||||||
|
context = get_context()
|
||||||
os.umask(0o22)
|
os.umask(0o22)
|
||||||
|
|
||||||
# Store script invocation command
|
# Store script invocation command
|
||||||
|
@ -66,7 +68,7 @@ def main() -> int:
|
||||||
elif not os.path.exists(args.config):
|
elif not os.path.exists(args.config):
|
||||||
raise RuntimeError("Please specify a config file, or run"
|
raise RuntimeError("Please specify a config file, or run"
|
||||||
" 'pmbootstrap init' to generate one.")
|
" 'pmbootstrap init' to generate one.")
|
||||||
elif not os.path.exists(config.work):
|
elif not os.path.exists(context.config.work):
|
||||||
raise RuntimeError("Work path not found, please run 'pmbootstrap"
|
raise RuntimeError("Work path not found, please run 'pmbootstrap"
|
||||||
" init' to create it.")
|
" init' to create it.")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import os
|
import os
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import pmb.aportgen.busybox_static
|
import pmb.aportgen.busybox_static
|
||||||
import pmb.aportgen.device
|
import pmb.aportgen.device
|
||||||
|
@ -9,7 +10,7 @@ import pmb.aportgen.linux
|
||||||
import pmb.aportgen.musl
|
import pmb.aportgen.musl
|
||||||
import pmb.aportgen.grub_efi
|
import pmb.aportgen.grub_efi
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +59,8 @@ def generate(args: PmbArgs, pkgname):
|
||||||
{"confirm_overwrite": True})
|
{"confirm_overwrite": True})
|
||||||
else:
|
else:
|
||||||
prefix, folder, options = properties(pkgname)
|
prefix, folder, options = properties(pkgname)
|
||||||
path_target = args.aports / folder / pkgname
|
config = get_context().config
|
||||||
|
path_target = config.aports / folder / pkgname
|
||||||
|
|
||||||
# Confirm overwrite
|
# Confirm overwrite
|
||||||
if options["confirm_overwrite"] and os.path.exists(path_target):
|
if options["confirm_overwrite"] and os.path.exists(path_target):
|
||||||
|
@ -67,7 +69,7 @@ def generate(args: PmbArgs, pkgname):
|
||||||
if not pmb.helpers.cli.confirm(args, "Continue and overwrite?"):
|
if not pmb.helpers.cli.confirm(args, "Continue and overwrite?"):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
aportgen = pmb.config.work / "aportgen"
|
aportgen = config.work / "aportgen"
|
||||||
|
|
||||||
if os.path.exists(aportgen):
|
if os.path.exists(aportgen):
|
||||||
pmb.helpers.run.user(["rm", "-r", aportgen])
|
pmb.helpers.run.user(["rm", "-r", aportgen])
|
||||||
|
@ -85,6 +87,6 @@ def generate(args: PmbArgs, pkgname):
|
||||||
if os.path.exists(path_target):
|
if os.path.exists(path_target):
|
||||||
pmb.helpers.run.user(["rm", "-r", path_target])
|
pmb.helpers.run.user(["rm", "-r", path_target])
|
||||||
pmb.helpers.run.user(
|
pmb.helpers.run.user(
|
||||||
args, ["mv", aportgen, path_target])
|
["mv", aportgen, path_target])
|
||||||
|
|
||||||
logging.info("*** pmaport generated: " + path_target)
|
logging.info("*** pmaport generated: " + path_target)
|
||||||
|
|
|
@ -5,30 +5,31 @@ import pmb.aportgen.core
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.apk_static
|
import pmb.chroot.apk_static
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(args: PmbArgs, pkgname):
|
||||||
arch = pkgname.split("-")[2]
|
arch = pkgname.split("-")[2]
|
||||||
|
context = get_context()
|
||||||
|
|
||||||
# Parse version from APKINDEX
|
# Parse version from APKINDEX
|
||||||
package_data = pmb.parse.apkindex.package(args, "busybox")
|
package_data = pmb.parse.apkindex.package("busybox")
|
||||||
version = package_data["version"]
|
version = package_data["version"]
|
||||||
pkgver = version.split("-r")[0]
|
pkgver = version.split("-r")[0]
|
||||||
pkgrel = version.split("-r")[1]
|
pkgrel = version.split("-r")[1]
|
||||||
|
|
||||||
# Prepare aportgen tempdir inside and outside of chroot
|
# Prepare aportgen tempdir inside and outside of chroot
|
||||||
tempdir = Path("/tmp/aportgen")
|
tempdir = Path("/tmp/aportgen")
|
||||||
aportgen = pmb.config.work / "aportgen"
|
aportgen = context.config.work / "aportgen"
|
||||||
pmb.chroot.root(args, ["rm", "-rf", tempdir])
|
pmb.chroot.root(["rm", "-rf", tempdir])
|
||||||
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
||||||
Chroot.native() / tempdir])
|
Chroot.native() / tempdir])
|
||||||
|
|
||||||
# Write the APKBUILD
|
# Write the APKBUILD
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir = channel_cfg["mirrordir_alpine"]
|
mirrordir = channel_cfg["mirrordir_alpine"]
|
||||||
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
||||||
apk_name = f"busybox-static-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"
|
apk_name = f"busybox-static-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"
|
||||||
|
@ -71,7 +72,7 @@ def generate(args: PmbArgs, pkgname):
|
||||||
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
# Generate checksums
|
# Generate checksums
|
||||||
pmb.build.init_abuild_minimal(args)
|
pmb.build.init_abuild_minimal()
|
||||||
pmb.chroot.root(args, ["chown", "-R", "pmos:pmos", tempdir])
|
pmb.chroot.root(["chown", "-R", "pmos:pmos", tempdir])
|
||||||
pmb.chroot.user(args, ["abuild", "checksum"], working_dir=tempdir)
|
pmb.chroot.user(["abuild", "checksum"], working_dir=tempdir)
|
||||||
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
import fnmatch
|
import fnmatch
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import re
|
import re
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
def indent_size(line):
|
def indent_size(line):
|
||||||
|
@ -48,7 +49,7 @@ def format_function(name, body, remove_indent=4):
|
||||||
return name + "() {\n" + ret + "}\n"
|
return name + "() {\n" + ret + "}\n"
|
||||||
|
|
||||||
|
|
||||||
def rewrite(args: PmbArgs, pkgname, path_original="", fields={}, replace_pkgname=None,
|
def rewrite(pkgname, path_original="", fields={}, replace_pkgname=None,
|
||||||
replace_functions={}, replace_simple={}, below_header="",
|
replace_functions={}, replace_simple={}, below_header="",
|
||||||
remove_indent=4):
|
remove_indent=4):
|
||||||
"""
|
"""
|
||||||
|
@ -93,7 +94,7 @@ def rewrite(args: PmbArgs, pkgname, path_original="", fields={}, replace_pkgname
|
||||||
lines_new += line.rstrip() + "\n"
|
lines_new += line.rstrip() + "\n"
|
||||||
|
|
||||||
# Copy/modify lines, skip Maintainer/Contributor
|
# Copy/modify lines, skip Maintainer/Contributor
|
||||||
path = pmb.config.work / "aportgen/APKBUILD"
|
path = get_context().config.work / "aportgen/APKBUILD"
|
||||||
with open(path, "r+", encoding="utf-8") as handle:
|
with open(path, "r+", encoding="utf-8") as handle:
|
||||||
skip_in_func = False
|
skip_in_func = False
|
||||||
for line in handle.readlines():
|
for line in handle.readlines():
|
||||||
|
@ -165,14 +166,14 @@ def get_upstream_aport(args: PmbArgs, pkgname, arch=None):
|
||||||
"""
|
"""
|
||||||
# APKBUILD
|
# APKBUILD
|
||||||
pmb.helpers.git.clone("aports_upstream")
|
pmb.helpers.git.clone("aports_upstream")
|
||||||
aports_upstream_path = pmb.config.work / "cache_git/aports_upstream"
|
aports_upstream_path = get_context().config.work / "cache_git/aports_upstream"
|
||||||
|
|
||||||
if getattr(args, "fork_alpine_retain_branch", False):
|
if getattr(args, "fork_alpine_retain_branch", False):
|
||||||
logging.info("Not changing aports branch as --fork-alpine-retain-branch was "
|
logging.info("Not changing aports branch as --fork-alpine-retain-branch was "
|
||||||
"used.")
|
"used.")
|
||||||
else:
|
else:
|
||||||
# Checkout branch
|
# Checkout branch
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
branch = channel_cfg["branch_aports"]
|
branch = channel_cfg["branch_aports"]
|
||||||
logging.info(f"Checkout aports.git branch: {branch}")
|
logging.info(f"Checkout aports.git branch: {branch}")
|
||||||
if pmb.helpers.run.user(["git", "checkout", branch],
|
if pmb.helpers.run.user(["git", "checkout", branch],
|
||||||
|
@ -202,8 +203,8 @@ def get_upstream_aport(args: PmbArgs, pkgname, arch=None):
|
||||||
split = aport_path.parts
|
split = aport_path.parts
|
||||||
repo = split[-2]
|
repo = split[-2]
|
||||||
pkgname = split[-1]
|
pkgname = split[-1]
|
||||||
index_path = pmb.helpers.repo.alpine_apkindex_path(args, repo, arch)
|
index_path = pmb.helpers.repo.alpine_apkindex_path(repo, arch)
|
||||||
package = pmb.parse.apkindex.package(args, pkgname, indexes=[index_path])
|
package = pmb.parse.apkindex.package(pkgname, indexes=[index_path])
|
||||||
|
|
||||||
# Compare version (return when equal)
|
# Compare version (return when equal)
|
||||||
compare = pmb.parse.version.compare(apkbuild_version, package["version"])
|
compare = pmb.parse.version.compare(apkbuild_version, package["version"])
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.aportgen.core
|
import pmb.aportgen.core
|
||||||
|
@ -237,8 +238,9 @@ def generate_deviceinfo(args: PmbArgs, pkgname, name, manufacturer, year, arch,
|
||||||
content += content_uuu
|
content += content_uuu
|
||||||
|
|
||||||
# Write to file
|
# Write to file
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "aportgen"])
|
work = get_context().config.work
|
||||||
path = pmb.config.work / "aportgen/deviceinfo"
|
pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"])
|
||||||
|
path = work / "aportgen/deviceinfo"
|
||||||
with open(path, "w", encoding="utf-8") as handle:
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
for line in content.rstrip().split("\n"):
|
for line in content.rstrip().split("\n"):
|
||||||
handle.write(line.lstrip() + "\n")
|
handle.write(line.lstrip() + "\n")
|
||||||
|
@ -258,8 +260,9 @@ def generate_modules_initfs(args: PmbArgs):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Write to file
|
# Write to file
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "aportgen"])
|
work = get_context().config.work
|
||||||
path = pmb.config.work / "aportgen/modules-initfs"
|
pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"])
|
||||||
|
path = work / "aportgen/modules-initfs"
|
||||||
with open(path, "w", encoding="utf-8") as handle:
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
for line in content.rstrip().split("\n"):
|
for line in content.rstrip().split("\n"):
|
||||||
handle.write(line.lstrip() + "\n")
|
handle.write(line.lstrip() + "\n")
|
||||||
|
@ -308,8 +311,9 @@ def generate_apkbuild(args: PmbArgs, pkgname, name, arch, flash_method):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Write the file
|
# Write the file
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "aportgen"])
|
work = get_context().config.work
|
||||||
path = pmb.config.work / "aportgen/APKBUILD"
|
pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"])
|
||||||
|
path = work / "aportgen/APKBUILD"
|
||||||
with open(path, "w", encoding="utf-8") as handle:
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
for line in content.rstrip().split("\n"):
|
for line in content.rstrip().split("\n"):
|
||||||
handle.write(line[8:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[8:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import pmb.aportgen.core
|
import pmb.aportgen.core
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.core import get_context
|
||||||
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
|
||||||
|
@ -10,19 +11,20 @@ def generate(args: PmbArgs, pkgname):
|
||||||
# Copy original aport
|
# Copy original aport
|
||||||
prefix = pkgname.split("-")[0]
|
prefix = pkgname.split("-")[0]
|
||||||
arch = pkgname.split("-")[1]
|
arch = pkgname.split("-")[1]
|
||||||
|
context = get_context()
|
||||||
if prefix == "gcc":
|
if prefix == "gcc":
|
||||||
upstream = pmb.aportgen.core.get_upstream_aport(args, "gcc", arch)
|
upstream = pmb.aportgen.core.get_upstream_aport(args, "gcc", arch)
|
||||||
based_on = "main/gcc (from Alpine)"
|
based_on = "main/gcc (from Alpine)"
|
||||||
elif prefix == "gcc4":
|
elif prefix == "gcc4":
|
||||||
upstream = f"{args.aports}/main/gcc4"
|
upstream = f"{context.config.aports}/main/gcc4"
|
||||||
based_on = "main/gcc4 (from postmarketOS)"
|
based_on = "main/gcc4 (from postmarketOS)"
|
||||||
elif prefix == "gcc6":
|
elif prefix == "gcc6":
|
||||||
upstream = f"{args.aports}/main/gcc6"
|
upstream = f"{context.config.aports}/main/gcc6"
|
||||||
based_on = "main/gcc6 (from postmarketOS)"
|
based_on = "main/gcc6 (from postmarketOS)"
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Invalid prefix '{prefix}', expected gcc, gcc4 or"
|
raise ValueError(f"Invalid prefix '{prefix}', expected gcc, gcc4 or"
|
||||||
" gcc6.")
|
" gcc6.")
|
||||||
pmb.helpers.run.user(["cp", "-r", upstream, pmb.config.work / "aportgen"])
|
pmb.helpers.run.user(["cp", "-r", upstream, context.config.work / "aportgen"])
|
||||||
|
|
||||||
# Rewrite APKBUILD
|
# Rewrite APKBUILD
|
||||||
fields = {
|
fields = {
|
||||||
|
@ -88,6 +90,6 @@ def generate(args: PmbArgs, pkgname):
|
||||||
'_libgcc=true*': '_libgcc=false',
|
'_libgcc=true*': '_libgcc=false',
|
||||||
}
|
}
|
||||||
|
|
||||||
pmb.aportgen.core.rewrite(args, pkgname, based_on, fields,
|
pmb.aportgen.core.rewrite(pkgname, based_on, fields,
|
||||||
replace_simple=replace_simple,
|
replace_simple=replace_simple,
|
||||||
below_header=below_header)
|
below_header=below_header)
|
||||||
|
|
|
@ -5,30 +5,31 @@ import pmb.aportgen.core
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.apk_static
|
import pmb.chroot.apk_static
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(args: PmbArgs, pkgname):
|
||||||
arch = "x86"
|
arch = "x86"
|
||||||
if pkgname != "grub-efi-x86":
|
if pkgname != "grub-efi-x86":
|
||||||
raise RuntimeError("only grub-efi-x86 is available")
|
raise RuntimeError("only grub-efi-x86 is available")
|
||||||
package_data = pmb.parse.apkindex.package(args, "grub")
|
package_data = pmb.parse.apkindex.package("grub")
|
||||||
version = package_data["version"]
|
version = package_data["version"]
|
||||||
pkgver = version.split("-r")[0]
|
pkgver = version.split("-r")[0]
|
||||||
pkgrel = version.split("-r")[1]
|
pkgrel = version.split("-r")[1]
|
||||||
|
|
||||||
# Prepare aportgen tempdir inside and outside of chroot
|
# Prepare aportgen tempdir inside and outside of chroot
|
||||||
|
context = get_context()
|
||||||
tempdir = Path("/tmp/aportgen")
|
tempdir = Path("/tmp/aportgen")
|
||||||
aportgen = pmb.config.work / "aportgen"
|
aportgen = context.config.work / "aportgen"
|
||||||
pmb.chroot.root(args, ["rm", "-rf", tempdir])
|
pmb.chroot.root(["rm", "-rf", tempdir])
|
||||||
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
||||||
Chroot.native() / tempdir])
|
Chroot.native() / tempdir])
|
||||||
|
|
||||||
# Write the APKBUILD
|
# Write the APKBUILD
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir = channel_cfg["mirrordir_alpine"]
|
mirrordir = channel_cfg["mirrordir_alpine"]
|
||||||
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
||||||
apk_name = f'"$srcdir/grub-efi-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"'
|
apk_name = f'"$srcdir/grub-efi-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"'
|
||||||
|
@ -61,7 +62,7 @@ def generate(args: PmbArgs, pkgname):
|
||||||
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
# Generate checksums
|
# Generate checksums
|
||||||
pmb.build.init_abuild_minimal(args)
|
pmb.build.init_abuild_minimal()
|
||||||
pmb.chroot.root(args, ["chown", "-R", "pmos:pmos", tempdir])
|
pmb.chroot.root(["chown", "-R", "pmos:pmos", tempdir])
|
||||||
pmb.chroot.user(args, ["abuild", "checksum"], working_dir=tempdir)
|
pmb.chroot.user(["abuild", "checksum"], working_dir=tempdir)
|
||||||
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.core import get_context
|
||||||
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.aportgen.core
|
import pmb.aportgen.core
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
|
@ -105,17 +106,18 @@ def generate_apkbuild(args: PmbArgs, pkgname, deviceinfo, patches):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Write the file
|
# Write the file
|
||||||
with (pmb.config.work / "aportgen/APKBUILD").open("w", encoding="utf-8") as hndl:
|
with (get_context().config.work / "aportgen/APKBUILD").open("w", encoding="utf-8") as hndl:
|
||||||
for line in content.rstrip().split("\n"):
|
for line in content.rstrip().split("\n"):
|
||||||
hndl.write(line[8:].replace(" " * 4, "\t") + "\n")
|
hndl.write(line[8:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(args: PmbArgs, pkgname):
|
||||||
device = "-".join(pkgname.split("-")[1:])
|
device = "-".join(pkgname.split("-")[1:])
|
||||||
deviceinfo = pmb.parse.deviceinfo(args, device)
|
deviceinfo = pmb.parse.deviceinfo(device)
|
||||||
|
work = get_context().config.work
|
||||||
|
|
||||||
# Symlink commonly used patches
|
# Symlink commonly used patches
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "aportgen"])
|
pmb.helpers.run.user(["mkdir", "-p", work / "aportgen"])
|
||||||
patches = [
|
patches = [
|
||||||
"gcc7-give-up-on-ilog2-const-optimizations.patch",
|
"gcc7-give-up-on-ilog2-const-optimizations.patch",
|
||||||
"gcc8-fix-put-user.patch",
|
"gcc8-fix-put-user.patch",
|
||||||
|
@ -125,6 +127,6 @@ def generate(args: PmbArgs, pkgname):
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
pmb.helpers.run.user(["ln", "-s",
|
pmb.helpers.run.user(["ln", "-s",
|
||||||
"../../.shared-patches/linux/" + patch,
|
"../../.shared-patches/linux/" + patch,
|
||||||
(pmb.config.work / "aportgen" / patch)])
|
(work / "aportgen" / patch)])
|
||||||
|
|
||||||
generate_apkbuild(args, pkgname, deviceinfo, patches)
|
generate_apkbuild(args, pkgname, deviceinfo, patches)
|
||||||
|
|
|
@ -5,30 +5,31 @@ import pmb.aportgen.core
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.apk_static
|
import pmb.chroot.apk_static
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, pkgname):
|
def generate(args: PmbArgs, pkgname):
|
||||||
arch = pkgname.split("-")[1]
|
arch = pkgname.split("-")[1]
|
||||||
|
|
||||||
# Parse musl version from APKINDEX
|
# Parse musl version from APKINDEX
|
||||||
package_data = pmb.parse.apkindex.package(args, "musl")
|
package_data = pmb.parse.apkindex.package("musl")
|
||||||
version = package_data["version"]
|
version = package_data["version"]
|
||||||
pkgver = version.split("-r")[0]
|
pkgver = version.split("-r")[0]
|
||||||
pkgrel = version.split("-r")[1]
|
pkgrel = version.split("-r")[1]
|
||||||
|
|
||||||
# Prepare aportgen tempdir inside and outside of chroot
|
# Prepare aportgen tempdir inside and outside of chroot
|
||||||
|
work = get_context().config.work
|
||||||
tempdir = Path("/tmp/aportgen")
|
tempdir = Path("/tmp/aportgen")
|
||||||
aportgen = pmb.config.work / "aportgen"
|
aportgen = work / "aportgen"
|
||||||
pmb.chroot.root(args, ["rm", "-rf", tempdir])
|
pmb.chroot.root(["rm", "-rf", tempdir])
|
||||||
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
pmb.helpers.run.user(["mkdir", "-p", aportgen,
|
||||||
Chroot.native() / tempdir])
|
Chroot.native() / tempdir])
|
||||||
|
|
||||||
# Write the APKBUILD
|
# Write the APKBUILD
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir = channel_cfg["mirrordir_alpine"]
|
mirrordir = channel_cfg["mirrordir_alpine"]
|
||||||
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
apkbuild_path = Chroot.native() / tempdir / "APKBUILD"
|
||||||
apk_name = f"$srcdir/musl-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"
|
apk_name = f"$srcdir/musl-$pkgver-r$pkgrel-$_arch-{mirrordir}.apk"
|
||||||
|
@ -97,7 +98,7 @@ def generate(args: PmbArgs, pkgname):
|
||||||
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[12:].replace(" " * 4, "\t") + "\n")
|
||||||
|
|
||||||
# Generate checksums
|
# Generate checksums
|
||||||
pmb.build.init_abuild_minimal(args)
|
pmb.build.init_abuild_minimal()
|
||||||
pmb.chroot.root(args, ["chown", "-R", "pmos:pmos", tempdir])
|
pmb.chroot.root(["chown", "-R", "pmos:pmos", tempdir])
|
||||||
pmb.chroot.user(args, ["abuild", "checksum"], working_dir=tempdir)
|
pmb.chroot.user(["abuild", "checksum"], working_dir=tempdir)
|
||||||
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
pmb.helpers.run.user(["cp", apkbuild_path, aportgen])
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import datetime
|
import datetime
|
||||||
import enum
|
import enum
|
||||||
|
from pmb.core.context import Context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ import pmb.build
|
||||||
import pmb.build.autodetect
|
import pmb.build.autodetect
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
|
@ -18,7 +19,7 @@ import pmb.parse.arch
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.helpers.exceptions import BuildFailedError
|
from pmb.helpers.exceptions import BuildFailedError
|
||||||
|
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
class BootstrapStage(enum.IntEnum):
|
class BootstrapStage(enum.IntEnum):
|
||||||
"""
|
"""
|
||||||
|
@ -48,7 +49,7 @@ def skip_already_built(pkgname, arch):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_apkbuild(args: PmbArgs, pkgname, arch):
|
def get_apkbuild(pkgname, arch):
|
||||||
"""Parse the APKBUILD path for pkgname.
|
"""Parse the APKBUILD path for pkgname.
|
||||||
|
|
||||||
When there is none, try to find it in the binary package APKINDEX files or raise an exception.
|
When there is none, try to find it in the binary package APKINDEX files or raise an exception.
|
||||||
|
@ -57,19 +58,19 @@ def get_apkbuild(args: PmbArgs, pkgname, arch):
|
||||||
:returns: None or parsed APKBUILD
|
:returns: None or parsed APKBUILD
|
||||||
"""
|
"""
|
||||||
# Get existing binary package indexes
|
# Get existing binary package indexes
|
||||||
pmb.helpers.repo.update(args, arch)
|
pmb.helpers.repo.update(arch)
|
||||||
|
|
||||||
# Get pmaport, skip upstream only packages
|
# Get pmaport, skip upstream only packages
|
||||||
pmaport = pmb.helpers.pmaports.get(args, pkgname, False)
|
pmaport = pmb.helpers.pmaports.get(pkgname, False)
|
||||||
if pmaport:
|
if pmaport:
|
||||||
return pmaport
|
return pmaport
|
||||||
if pmb.parse.apkindex.providers(args, pkgname, arch, False):
|
if pmb.parse.apkindex.providers(pkgname, arch, False):
|
||||||
return None
|
return None
|
||||||
raise RuntimeError("Package '" + pkgname + "': Could not find aport, and"
|
raise RuntimeError("Package '" + pkgname + "': Could not find aport, and"
|
||||||
" could not find this package in any APKINDEX!")
|
" could not find this package in any APKINDEX!")
|
||||||
|
|
||||||
|
|
||||||
def check_build_for_arch(args: PmbArgs, pkgname, arch):
|
def check_build_for_arch(pkgname, arch):
|
||||||
"""Check if pmaport can be built or exists as binary for a specific arch.
|
"""Check if pmaport can be built or exists as binary for a specific arch.
|
||||||
|
|
||||||
:returns: * True when it can be built
|
:returns: * True when it can be built
|
||||||
|
@ -78,14 +79,15 @@ def check_build_for_arch(args: PmbArgs, pkgname, arch):
|
||||||
:raises: RuntimeError if the package can't be built for the given arch and
|
:raises: RuntimeError if the package can't be built for the given arch and
|
||||||
does not exist as binary package.
|
does not exist as binary package.
|
||||||
"""
|
"""
|
||||||
|
context = get_context()
|
||||||
# Check for pmaport with arch
|
# Check for pmaport with arch
|
||||||
if pmb.helpers.package.check_arch(args, pkgname, arch, False):
|
if pmb.helpers.package.check_arch(pkgname, arch, False):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Check for binary package
|
# Check for binary package
|
||||||
binary = pmb.parse.apkindex.package(args, pkgname, arch, False)
|
binary = pmb.parse.apkindex.package(pkgname, arch, False)
|
||||||
if binary:
|
if binary:
|
||||||
pmaport = pmb.helpers.pmaports.get(args, pkgname)
|
pmaport = pmb.helpers.pmaports.get(pkgname)
|
||||||
pmaport_version = pmaport["pkgver"] + "-r" + pmaport["pkgrel"]
|
pmaport_version = pmaport["pkgver"] + "-r" + pmaport["pkgrel"]
|
||||||
logging.debug(pkgname + ": found pmaport (" + pmaport_version + ") and"
|
logging.debug(pkgname + ": found pmaport (" + pmaport_version + ") and"
|
||||||
" binary package (" + binary["version"] + ", from"
|
" binary package (" + binary["version"] + ", from"
|
||||||
|
@ -95,7 +97,7 @@ def check_build_for_arch(args: PmbArgs, pkgname, arch):
|
||||||
|
|
||||||
# No binary package exists and can't build it
|
# No binary package exists and can't build it
|
||||||
logging.info("NOTE: You can edit the 'arch=' line inside the APKBUILD")
|
logging.info("NOTE: You can edit the 'arch=' line inside the APKBUILD")
|
||||||
if args.action == "build":
|
if context.command == "build":
|
||||||
logging.info("NOTE: Alternatively, use --arch to build for another"
|
logging.info("NOTE: Alternatively, use --arch to build for another"
|
||||||
" architecture ('pmbootstrap build --arch=armhf " +
|
" architecture ('pmbootstrap build --arch=armhf " +
|
||||||
pkgname + "')")
|
pkgname + "')")
|
||||||
|
@ -103,7 +105,7 @@ def check_build_for_arch(args: PmbArgs, pkgname, arch):
|
||||||
arch)
|
arch)
|
||||||
|
|
||||||
|
|
||||||
def get_depends(args: PmbArgs, apkbuild):
|
def get_depends(context: Context, apkbuild):
|
||||||
"""Alpine's abuild always builds/installs the "depends" and "makedepends" of a package
|
"""Alpine's abuild always builds/installs the "depends" and "makedepends" of a package
|
||||||
before building it.
|
before building it.
|
||||||
|
|
||||||
|
@ -116,7 +118,7 @@ def get_depends(args: PmbArgs, apkbuild):
|
||||||
ret = list(apkbuild["makedepends"])
|
ret = list(apkbuild["makedepends"])
|
||||||
if "!check" not in apkbuild["options"]:
|
if "!check" not in apkbuild["options"]:
|
||||||
ret += apkbuild["checkdepends"]
|
ret += apkbuild["checkdepends"]
|
||||||
if "ignore_depends" not in args or not args.ignore_depends:
|
if not context.ignore_depends:
|
||||||
ret += apkbuild["depends"]
|
ret += apkbuild["depends"]
|
||||||
ret = sorted(set(ret))
|
ret = sorted(set(ret))
|
||||||
|
|
||||||
|
@ -130,35 +132,35 @@ def get_depends(args: PmbArgs, apkbuild):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def build_depends(args: PmbArgs, apkbuild, arch, strict):
|
def build_depends(context: Context, apkbuild, arch, strict):
|
||||||
"""Get and build dependencies with verbose logging messages.
|
"""Get and build dependencies with verbose logging messages.
|
||||||
|
|
||||||
:returns: (depends, depends_built)
|
:returns: (depends, depends_built)
|
||||||
"""
|
"""
|
||||||
# Get dependencies
|
# Get dependencies
|
||||||
pkgname = apkbuild["pkgname"]
|
pkgname = apkbuild["pkgname"]
|
||||||
depends = get_depends(args, apkbuild)
|
depends = get_depends(context, apkbuild)
|
||||||
logging.verbose(pkgname + ": build/install dependencies: " +
|
logging.verbose(pkgname + ": build/install dependencies: " +
|
||||||
", ".join(depends))
|
", ".join(depends))
|
||||||
|
|
||||||
# --no-depends: check for binary packages
|
# --no-depends: check for binary packages
|
||||||
depends_built = []
|
depends_built = []
|
||||||
if "no_depends" in args and args.no_depends:
|
if context.no_depends:
|
||||||
pmb.helpers.repo.update(args, arch)
|
pmb.helpers.repo.update(arch)
|
||||||
for depend in depends:
|
for depend in depends:
|
||||||
# Ignore conflicting dependencies
|
# Ignore conflicting dependencies
|
||||||
if depend.startswith("!"):
|
if depend.startswith("!"):
|
||||||
continue
|
continue
|
||||||
# Check if binary package is missing
|
# Check if binary package is missing
|
||||||
if not pmb.parse.apkindex.package(args, depend, arch, False):
|
if not pmb.parse.apkindex.package(depend, arch, False):
|
||||||
raise RuntimeError("Missing binary package for dependency '" +
|
raise RuntimeError("Missing binary package for dependency '" +
|
||||||
depend + "' of '" + pkgname + "', but"
|
depend + "' of '" + pkgname + "', but"
|
||||||
" pmbootstrap won't build any depends since"
|
" pmbootstrap won't build any depends since"
|
||||||
" it was started with --no-depends.")
|
" it was started with --no-depends.")
|
||||||
# Check if binary package is outdated
|
# Check if binary package is outdated
|
||||||
apkbuild_dep = get_apkbuild(args, depend, arch)
|
apkbuild_dep = get_apkbuild(depend, arch)
|
||||||
if apkbuild_dep and \
|
if apkbuild_dep and \
|
||||||
pmb.build.is_necessary(args, arch, apkbuild_dep):
|
pmb.build.is_necessary(arch, apkbuild_dep):
|
||||||
raise RuntimeError(f"Binary package for dependency '{depend}'"
|
raise RuntimeError(f"Binary package for dependency '{depend}'"
|
||||||
f" of '{pkgname}' is outdated, but"
|
f" of '{pkgname}' is outdated, but"
|
||||||
f" pmbootstrap won't build any depends"
|
f" pmbootstrap won't build any depends"
|
||||||
|
@ -168,7 +170,7 @@ def build_depends(args: PmbArgs, apkbuild, arch, strict):
|
||||||
for depend in depends:
|
for depend in depends:
|
||||||
if depend.startswith("!"):
|
if depend.startswith("!"):
|
||||||
continue
|
continue
|
||||||
if package(args, depend, arch, strict=strict):
|
if package(context, depend, arch, strict=strict):
|
||||||
depends_built += [depend]
|
depends_built += [depend]
|
||||||
logging.verbose(pkgname + ": build dependencies: done, built: " +
|
logging.verbose(pkgname + ": build dependencies: done, built: " +
|
||||||
", ".join(depends_built))
|
", ".join(depends_built))
|
||||||
|
@ -176,7 +178,7 @@ def build_depends(args: PmbArgs, apkbuild, arch, strict):
|
||||||
return (depends, depends_built)
|
return (depends, depends_built)
|
||||||
|
|
||||||
|
|
||||||
def is_necessary_warn_depends(args: PmbArgs, apkbuild, arch, force, depends_built):
|
def is_necessary_warn_depends(apkbuild, arch, force, depends_built):
|
||||||
"""Check if a build is necessary, and warn if it is not, but there were dependencies built.
|
"""Check if a build is necessary, and warn if it is not, but there were dependencies built.
|
||||||
|
|
||||||
:returns: True or False
|
:returns: True or False
|
||||||
|
@ -185,7 +187,7 @@ def is_necessary_warn_depends(args: PmbArgs, apkbuild, arch, force, depends_buil
|
||||||
|
|
||||||
# Check if necessary (this warns about binary version > aport version, so
|
# Check if necessary (this warns about binary version > aport version, so
|
||||||
# call it even in force mode)
|
# call it even in force mode)
|
||||||
ret = pmb.build.is_necessary(args, arch, apkbuild)
|
ret = pmb.build.is_necessary(arch, apkbuild)
|
||||||
if force:
|
if force:
|
||||||
ret = True
|
ret = True
|
||||||
|
|
||||||
|
@ -197,7 +199,7 @@ def is_necessary_warn_depends(args: PmbArgs, apkbuild, arch, force, depends_buil
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def init_buildenv(args: PmbArgs, apkbuild, arch, strict=False, force=False, cross=None,
|
def init_buildenv(context: Context, apkbuild, arch, strict=False, force=False, cross=None,
|
||||||
chroot: Chroot = Chroot.native(), skip_init_buildenv=False, src=None):
|
chroot: Chroot = Chroot.native(), skip_init_buildenv=False, src=None):
|
||||||
"""Build all dependencies.
|
"""Build all dependencies.
|
||||||
|
|
||||||
|
@ -219,30 +221,30 @@ def init_buildenv(args: PmbArgs, apkbuild, arch, strict=False, force=False, cros
|
||||||
depends_arch = pmb.config.arch_native
|
depends_arch = pmb.config.arch_native
|
||||||
|
|
||||||
# Build dependencies
|
# Build dependencies
|
||||||
depends, built = build_depends(args, apkbuild, depends_arch, strict)
|
depends, built = build_depends(context, apkbuild, depends_arch, strict)
|
||||||
|
|
||||||
# Check if build is necessary
|
# Check if build is necessary
|
||||||
if not is_necessary_warn_depends(args, apkbuild, arch, force, built):
|
if not is_necessary_warn_depends(apkbuild, arch, force, built):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Install and configure abuild, ccache, gcc, dependencies
|
# Install and configure abuild, ccache, gcc, dependencies
|
||||||
if not skip_init_buildenv:
|
if not skip_init_buildenv:
|
||||||
pmb.build.init(args, chroot)
|
pmb.build.init(chroot)
|
||||||
pmb.build.other.configure_abuild(args, chroot)
|
pmb.build.other.configure_abuild(chroot)
|
||||||
if args.ccache:
|
if context.ccache:
|
||||||
pmb.build.other.configure_ccache(args, chroot)
|
pmb.build.other.configure_ccache(chroot)
|
||||||
if "rust" in depends or "cargo" in depends:
|
if "rust" in depends or "cargo" in depends:
|
||||||
pmb.chroot.apk.install(args, ["sccache"], chroot)
|
pmb.chroot.apk.install(["sccache"], chroot)
|
||||||
if not strict and "pmb:strict" not in apkbuild["options"] and len(depends):
|
if not strict and "pmb:strict" not in apkbuild["options"] and len(depends):
|
||||||
pmb.chroot.apk.install(args, depends, chroot)
|
pmb.chroot.apk.install(depends, chroot)
|
||||||
if src:
|
if src:
|
||||||
pmb.chroot.apk.install(args, ["rsync"], chroot)
|
pmb.chroot.apk.install(["rsync"], chroot)
|
||||||
|
|
||||||
# Cross-compiler init
|
# Cross-compiler init
|
||||||
if cross:
|
if cross:
|
||||||
pmb.build.init_compiler(args, depends, cross, arch)
|
pmb.build.init_compiler(context, depends, cross, arch)
|
||||||
if cross == "crossdirect":
|
if cross == "crossdirect":
|
||||||
pmb.chroot.mount_native_into_foreign(args, chroot)
|
pmb.chroot.mount_native_into_foreign(chroot)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -270,7 +272,7 @@ def get_pkgver(original_pkgver, original_source=False, now=None):
|
||||||
return no_suffix + new_suffix
|
return no_suffix + new_suffix
|
||||||
|
|
||||||
|
|
||||||
def override_source(args: PmbArgs, apkbuild, pkgver, src, chroot: Chroot=Chroot.native()):
|
def override_source(apkbuild, pkgver, src, chroot: Chroot=Chroot.native()):
|
||||||
"""Mount local source inside chroot and append new functions (prepare() etc.)
|
"""Mount local source inside chroot and append new functions (prepare() etc.)
|
||||||
to the APKBUILD to make it use the local source.
|
to the APKBUILD to make it use the local source.
|
||||||
"""
|
"""
|
||||||
|
@ -286,7 +288,7 @@ def override_source(args: PmbArgs, apkbuild, pkgver, src, chroot: Chroot=Chroot.
|
||||||
append_path = "/tmp/APKBUILD.append"
|
append_path = "/tmp/APKBUILD.append"
|
||||||
append_path_outside = chroot / append_path
|
append_path_outside = chroot / append_path
|
||||||
if append_path_outside.exists():
|
if append_path_outside.exists():
|
||||||
pmb.chroot.root(args, ["rm", append_path], chroot)
|
pmb.chroot.root(["rm", append_path], chroot)
|
||||||
|
|
||||||
# Add src path to pkgdesc, cut it off after max length
|
# Add src path to pkgdesc, cut it off after max length
|
||||||
pkgdesc = ("[" + src + "] " + apkbuild["pkgdesc"])[:127]
|
pkgdesc = ("[" + src + "] " + apkbuild["pkgdesc"])[:127]
|
||||||
|
@ -327,14 +329,14 @@ def override_source(args: PmbArgs, apkbuild, pkgver, src, chroot: Chroot=Chroot.
|
||||||
with open(append_path_outside, "w", encoding="utf-8") as handle:
|
with open(append_path_outside, "w", encoding="utf-8") as handle:
|
||||||
for line in append.split("\n"):
|
for line in append.split("\n"):
|
||||||
handle.write(line[13:].replace(" " * 4, "\t") + "\n")
|
handle.write(line[13:].replace(" " * 4, "\t") + "\n")
|
||||||
pmb.chroot.user(args, ["cat", append_path], chroot)
|
pmb.chroot.user(["cat", append_path], chroot)
|
||||||
|
|
||||||
# Append it to the APKBUILD
|
# Append it to the APKBUILD
|
||||||
apkbuild_path = "/home/pmos/build/APKBUILD"
|
apkbuild_path = "/home/pmos/build/APKBUILD"
|
||||||
shell_cmd = ("cat " + apkbuild_path + " " + append_path + " > " +
|
shell_cmd = ("cat " + apkbuild_path + " " + append_path + " > " +
|
||||||
append_path + "_")
|
append_path + "_")
|
||||||
pmb.chroot.user(args, ["sh", "-c", shell_cmd], chroot)
|
pmb.chroot.user(["sh", "-c", shell_cmd], chroot)
|
||||||
pmb.chroot.user(args, ["mv", append_path + "_", apkbuild_path], chroot)
|
pmb.chroot.user(["mv", append_path + "_", apkbuild_path], chroot)
|
||||||
|
|
||||||
|
|
||||||
def mount_pmaports(destination, chroot: Chroot=Chroot.native()):
|
def mount_pmaports(destination, chroot: Chroot=Chroot.native()):
|
||||||
|
@ -344,10 +346,10 @@ def mount_pmaports(destination, chroot: Chroot=Chroot.native()):
|
||||||
:param destination: mount point inside the chroot
|
:param destination: mount point inside the chroot
|
||||||
"""
|
"""
|
||||||
outside_destination = chroot / destination
|
outside_destination = chroot / destination
|
||||||
pmb.helpers.mount.bind(args.aports, outside_destination, umount=True)
|
pmb.helpers.mount.bind(get_context().config.aports, outside_destination, umount=True)
|
||||||
|
|
||||||
|
|
||||||
def link_to_git_dir(args: PmbArgs, suffix):
|
def link_to_git_dir(suffix):
|
||||||
""" Make ``/home/pmos/build/.git`` point to the .git dir from pmaports.git, with a
|
""" Make ``/home/pmos/build/.git`` point to the .git dir from pmaports.git, with a
|
||||||
symlink so abuild does not fail (#1841).
|
symlink so abuild does not fail (#1841).
|
||||||
|
|
||||||
|
@ -367,15 +369,15 @@ def link_to_git_dir(args: PmbArgs, suffix):
|
||||||
# at that point. Use umount=True, so we don't have an old path mounted
|
# at that point. Use umount=True, so we don't have an old path mounted
|
||||||
# (some tests change the pmaports dir).
|
# (some tests change the pmaports dir).
|
||||||
destination = "/mnt/pmaports"
|
destination = "/mnt/pmaports"
|
||||||
mount_pmaports(args, destination, suffix)
|
mount_pmaports(destination, suffix)
|
||||||
|
|
||||||
# Create .git symlink
|
# Create .git symlink
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/build"], suffix)
|
pmb.chroot.user(["mkdir", "-p", "/home/pmos/build"], suffix)
|
||||||
pmb.chroot.user(args, ["ln", "-sf", destination + "/.git",
|
pmb.chroot.user(["ln", "-sf", destination + "/.git",
|
||||||
"/home/pmos/build/.git"], suffix)
|
"/home/pmos/build/.git"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def run_abuild(args: PmbArgs, apkbuild, arch, strict=False, force=False, cross=None,
|
def run_abuild(context: Context, apkbuild, arch, strict=False, force=False, cross=None,
|
||||||
suffix: Chroot=Chroot.native(), src=None, bootstrap_stage=BootstrapStage.NONE):
|
suffix: Chroot=Chroot.native(), src=None, bootstrap_stage=BootstrapStage.NONE):
|
||||||
"""
|
"""
|
||||||
Set up all environment variables and construct the abuild command (all
|
Set up all environment variables and construct the abuild command (all
|
||||||
|
@ -415,11 +417,11 @@ def run_abuild(args: PmbArgs, apkbuild, arch, strict=False, force=False, cross=N
|
||||||
if cross == "crossdirect":
|
if cross == "crossdirect":
|
||||||
env["PATH"] = ":".join(["/native/usr/lib/crossdirect/" + arch,
|
env["PATH"] = ":".join(["/native/usr/lib/crossdirect/" + arch,
|
||||||
pmb.config.chroot_path])
|
pmb.config.chroot_path])
|
||||||
if not args.ccache:
|
if not context.ccache:
|
||||||
env["CCACHE_DISABLE"] = "1"
|
env["CCACHE_DISABLE"] = "1"
|
||||||
|
|
||||||
# Use sccache without crossdirect (crossdirect uses it via rustc.sh)
|
# Use sccache without crossdirect (crossdirect uses it via rustc.sh)
|
||||||
if args.ccache and cross != "crossdirect":
|
if context.ccache and cross != "crossdirect":
|
||||||
env["RUSTC_WRAPPER"] = "/usr/bin/sccache"
|
env["RUSTC_WRAPPER"] = "/usr/bin/sccache"
|
||||||
|
|
||||||
# Cache binary objects from go in this path (like ccache)
|
# Cache binary objects from go in this path (like ccache)
|
||||||
|
@ -431,7 +433,7 @@ def run_abuild(args: PmbArgs, apkbuild, arch, strict=False, force=False, cross=N
|
||||||
# e.g. when using --src they are not bundled, in that case it makes sense
|
# e.g. when using --src they are not bundled, in that case it makes sense
|
||||||
# to point GOMODCACHE at pmbootstrap's work dir so the modules are only
|
# to point GOMODCACHE at pmbootstrap's work dir so the modules are only
|
||||||
# downloaded once.
|
# downloaded once.
|
||||||
if args.go_mod_cache:
|
if context.go_mod_cache:
|
||||||
env["GOMODCACHE"] = "/home/pmos/go/pkg/mod"
|
env["GOMODCACHE"] = "/home/pmos/go/pkg/mod"
|
||||||
|
|
||||||
if bootstrap_stage:
|
if bootstrap_stage:
|
||||||
|
@ -450,18 +452,18 @@ def run_abuild(args: PmbArgs, apkbuild, arch, strict=False, force=False, cross=N
|
||||||
cmd += ["-f"]
|
cmd += ["-f"]
|
||||||
|
|
||||||
# Copy the aport to the chroot and build it
|
# Copy the aport to the chroot and build it
|
||||||
pmb.build.copy_to_buildpath(args, apkbuild["pkgname"], suffix)
|
pmb.build.copy_to_buildpath(apkbuild["pkgname"], suffix)
|
||||||
override_source(args, apkbuild, pkgver, src, suffix)
|
override_source(apkbuild, pkgver, src, suffix)
|
||||||
link_to_git_dir(args, suffix)
|
link_to_git_dir(suffix)
|
||||||
pmb.chroot.user(args, cmd, suffix, Path("/home/pmos/build"), env=env)
|
pmb.chroot.user(cmd, suffix, Path("/home/pmos/build"), env=env)
|
||||||
return (output, cmd, env)
|
return (output, cmd, env)
|
||||||
|
|
||||||
|
|
||||||
def finish(args: PmbArgs, apkbuild, arch, output: str, chroot: Chroot, strict=False):
|
def finish(apkbuild, arch, output: str, chroot: Chroot, strict=False):
|
||||||
"""Various finishing tasks that need to be done after a build."""
|
"""Various finishing tasks that need to be done after a build."""
|
||||||
# Verify output file
|
# Verify output file
|
||||||
channel: str = pmb.config.pmaports.read_config(args)["channel"]
|
channel: str = pmb.config.pmaports.read_config()["channel"]
|
||||||
out_dir = (pmb.config.work / "packages" / channel)
|
out_dir = (get_context().config.work / "packages" / channel)
|
||||||
if not (out_dir / output).exists():
|
if not (out_dir / output).exists():
|
||||||
raise RuntimeError(f"Package not found after build: {(out_dir / output)}")
|
raise RuntimeError(f"Package not found after build: {(out_dir / output)}")
|
||||||
|
|
||||||
|
@ -473,14 +475,14 @@ def finish(args: PmbArgs, apkbuild, arch, output: str, chroot: Chroot, strict=Fa
|
||||||
# Uninstall build dependencies (strict mode)
|
# Uninstall build dependencies (strict mode)
|
||||||
if strict or "pmb:strict" in apkbuild["options"]:
|
if strict or "pmb:strict" in apkbuild["options"]:
|
||||||
logging.info(f"({chroot}) uninstall build dependencies")
|
logging.info(f"({chroot}) uninstall build dependencies")
|
||||||
pmb.chroot.user(args, ["abuild", "undeps"], chroot, Path("/home/pmos/build"),
|
pmb.chroot.user(["abuild", "undeps"], chroot, Path("/home/pmos/build"),
|
||||||
env={"SUDO_APK": "abuild-apk --no-progress"})
|
env={"SUDO_APK": "abuild-apk --no-progress"})
|
||||||
# If the build depends contain postmarketos-keys or postmarketos-base,
|
# If the build depends contain postmarketos-keys or postmarketos-base,
|
||||||
# abuild will have removed the postmarketOS repository key (pma#1230)
|
# abuild will have removed the postmarketOS repository key (pma#1230)
|
||||||
pmb.chroot.init_keys(args)
|
pmb.chroot.init_keys()
|
||||||
|
|
||||||
|
|
||||||
def package(args: PmbArgs, pkgname, arch=None, force=False, strict=False,
|
def package(context: Context, pkgname, arch=None, force=False, strict=False,
|
||||||
skip_init_buildenv=False, src=None,
|
skip_init_buildenv=False, src=None,
|
||||||
bootstrap_stage=BootstrapStage.NONE):
|
bootstrap_stage=BootstrapStage.NONE):
|
||||||
"""
|
"""
|
||||||
|
@ -515,24 +517,24 @@ def package(args: PmbArgs, pkgname, arch=None, force=False, strict=False,
|
||||||
return
|
return
|
||||||
|
|
||||||
# Only build when APKBUILD exists
|
# Only build when APKBUILD exists
|
||||||
apkbuild = get_apkbuild(args, pkgname, arch)
|
apkbuild = get_apkbuild(pkgname, arch)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Detect the build environment (skip unnecessary builds)
|
# Detect the build environment (skip unnecessary builds)
|
||||||
if not check_build_for_arch(args, pkgname, arch):
|
if not check_build_for_arch(pkgname, arch):
|
||||||
return
|
return
|
||||||
chroot = pmb.build.autodetect.chroot(apkbuild, arch)
|
chroot = pmb.build.autodetect.chroot(apkbuild, arch)
|
||||||
cross = pmb.build.autodetect.crosscompile(args, apkbuild, arch, chroot)
|
cross = pmb.build.autodetect.crosscompile(apkbuild, arch, chroot)
|
||||||
if not init_buildenv(args, apkbuild, arch, strict, force, cross, chroot,
|
if not init_buildenv(context, apkbuild, arch, strict, force, cross, chroot,
|
||||||
skip_init_buildenv, src):
|
skip_init_buildenv, src):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Build and finish up
|
# Build and finish up
|
||||||
try:
|
try:
|
||||||
(output, cmd, env) = run_abuild(args, apkbuild, arch, strict, force, cross,
|
(output, cmd, env) = run_abuild(context, apkbuild, arch, strict, force, cross,
|
||||||
chroot, src, bootstrap_stage)
|
chroot, src, bootstrap_stage)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
raise BuildFailedError(f"Build for {arch}/{pkgname} failed!")
|
raise BuildFailedError(f"Build for {arch}/{pkgname} failed!")
|
||||||
finish(args, apkbuild, arch, output, chroot, strict)
|
finish(apkbuild, arch, output, chroot, strict)
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -6,10 +6,10 @@ from typing import Dict, Optional
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType, get_context
|
||||||
|
|
||||||
|
|
||||||
# FIXME (#2324): type hint Arch
|
# FIXME (#2324): type hint Arch
|
||||||
|
@ -31,7 +31,7 @@ def arch_from_deviceinfo(args: PmbArgs, pkgname, aport: Path) -> Optional[str]:
|
||||||
|
|
||||||
# Return its arch
|
# Return its arch
|
||||||
device = pkgname.split("-", 1)[1]
|
device = pkgname.split("-", 1)[1]
|
||||||
arch = pmb.parse.deviceinfo(args, device)["arch"]
|
arch = pmb.parse.deviceinfo(device)["arch"]
|
||||||
logging.verbose(pkgname + ": arch from deviceinfo: " + arch)
|
logging.verbose(pkgname + ": arch from deviceinfo: " + arch)
|
||||||
return arch
|
return arch
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ def arch(args: PmbArgs, pkgname: str):
|
||||||
* device arch (this will be preferred instead if build_default_device_arch is true)
|
* device arch (this will be preferred instead if build_default_device_arch is true)
|
||||||
* first arch in the APKBUILD
|
* first arch in the APKBUILD
|
||||||
"""
|
"""
|
||||||
aport = pmb.helpers.pmaports.find(args, pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
if not aport:
|
if not aport:
|
||||||
raise FileNotFoundError(f"APKBUILD not found for {pkgname}")
|
raise FileNotFoundError(f"APKBUILD not found for {pkgname}")
|
||||||
ret = arch_from_deviceinfo(args, pkgname, aport)
|
ret = arch_from_deviceinfo(args, pkgname, aport)
|
||||||
|
@ -57,7 +57,7 @@ def arch(args: PmbArgs, pkgname: str):
|
||||||
apkbuild = pmb.parse.apkbuild(aport)
|
apkbuild = pmb.parse.apkbuild(aport)
|
||||||
arches = apkbuild["arch"]
|
arches = apkbuild["arch"]
|
||||||
|
|
||||||
if args.build_default_device_arch:
|
if get_context().config.build_default_device_arch:
|
||||||
preferred_arch = args.deviceinfo["arch"]
|
preferred_arch = args.deviceinfo["arch"]
|
||||||
preferred_arch_2nd = pmb.config.arch_native
|
preferred_arch_2nd = pmb.config.arch_native
|
||||||
else:
|
else:
|
||||||
|
@ -86,11 +86,11 @@ def chroot(apkbuild: Dict[str, str], arch: str) -> Chroot:
|
||||||
return Chroot.buildroot(arch)
|
return Chroot.buildroot(arch)
|
||||||
|
|
||||||
|
|
||||||
def crosscompile(args: PmbArgs, apkbuild, arch, suffix: Chroot):
|
def crosscompile(apkbuild, arch, suffix: Chroot):
|
||||||
"""
|
"""
|
||||||
:returns: None, "native", "crossdirect"
|
:returns: None, "native", "crossdirect"
|
||||||
"""
|
"""
|
||||||
if not args.cross:
|
if not get_context().cross:
|
||||||
return None
|
return None
|
||||||
if not pmb.parse.arch.cpu_emulation_required(arch):
|
if not pmb.parse.arch.cpu_emulation_required(arch):
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -6,7 +6,7 @@ from pathlib import Path
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.build
|
import pmb.build
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
@ -14,25 +14,25 @@ from pmb.core import Chroot
|
||||||
|
|
||||||
def update(args: PmbArgs, pkgname):
|
def update(args: PmbArgs, pkgname):
|
||||||
"""Fetch all sources and update the checksums in the APKBUILD."""
|
"""Fetch all sources and update the checksums in the APKBUILD."""
|
||||||
pmb.build.init_abuild_minimal(args)
|
pmb.build.init_abuild_minimal()
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
pmb.build.copy_to_buildpath(args, pkgname)
|
||||||
logging.info("(native) generate checksums for " + pkgname)
|
logging.info("(native) generate checksums for " + pkgname)
|
||||||
pmb.chroot.user(args, ["abuild", "checksum"],
|
pmb.chroot.user(["abuild", "checksum"],
|
||||||
working_dir=Path("/home/pmos/build"))
|
working_dir=Path("/home/pmos/build"))
|
||||||
|
|
||||||
# Copy modified APKBUILD back
|
# Copy modified APKBUILD back
|
||||||
source = Chroot.native() / "home/pmos/build/APKBUILD"
|
source = Chroot.native() / "home/pmos/build/APKBUILD"
|
||||||
target = f"{os.fspath(pmb.helpers.pmaports.find(args, pkgname))}/"
|
target = f"{os.fspath(pmb.helpers.pmaports.find(pkgname))}/"
|
||||||
pmb.helpers.run.user(["cp", source, target])
|
pmb.helpers.run.user(["cp", source, target])
|
||||||
|
|
||||||
|
|
||||||
def verify(args: PmbArgs, pkgname):
|
def verify(args: PmbArgs, pkgname):
|
||||||
"""Fetch all sources and verify their checksums."""
|
"""Fetch all sources and verify their checksums."""
|
||||||
pmb.build.init_abuild_minimal(args)
|
pmb.build.init_abuild_minimal()
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
pmb.build.copy_to_buildpath(args, pkgname)
|
||||||
logging.info("(native) verify checksums for " + pkgname)
|
logging.info("(native) verify checksums for " + pkgname)
|
||||||
|
|
||||||
# Fetch and verify sources, "fetch" alone does not verify them:
|
# Fetch and verify sources, "fetch" alone does not verify them:
|
||||||
# https://github.com/alpinelinux/abuild/pull/86
|
# https://github.com/alpinelinux/abuild/pull/86
|
||||||
pmb.chroot.user(args, ["abuild", "fetch", "verify"],
|
pmb.chroot.user(["abuild", "fetch", "verify"],
|
||||||
working_dir=Path("/home/pmos/build"))
|
working_dir=Path("/home/pmos/build"))
|
||||||
|
|
|
@ -7,15 +7,16 @@ from pathlib import Path
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import pmb.aportgen
|
import pmb.aportgen
|
||||||
|
import pmb.aportgen.core
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.build.autodetect
|
import pmb.build.autodetect
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers
|
import pmb.helpers
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def match_kbuild_out(word):
|
def match_kbuild_out(word):
|
||||||
|
@ -90,16 +91,17 @@ def find_kbuild_output_dir(function_body):
|
||||||
"can't resolve it, please open an issue.")
|
"can't resolve it, please open an issue.")
|
||||||
|
|
||||||
|
|
||||||
def modify_apkbuild(args: PmbArgs, pkgname: str, aport: Path):
|
def modify_apkbuild(pkgname: str, aport: Path):
|
||||||
"""Modify kernel APKBUILD to package build output from envkernel.sh."""
|
"""Modify kernel APKBUILD to package build output from envkernel.sh."""
|
||||||
apkbuild_path = aport + "/APKBUILD"
|
work = get_context().config.work
|
||||||
|
apkbuild_path = aport / "APKBUILD"
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
||||||
if os.path.exists(pmb.config.work / "aportgen"):
|
if os.path.exists(work / "aportgen"):
|
||||||
pmb.helpers.run.user(["rm", "-r", pmb.config.work / "aportgen"])
|
pmb.helpers.run.user(["rm", "-r", work / "aportgen"])
|
||||||
|
|
||||||
pmb.helpers.run.user(["mkdir", pmb.config.work / "aportgen"])
|
pmb.helpers.run.user(["mkdir", work / "aportgen"])
|
||||||
pmb.helpers.run.user(["cp", "-r", apkbuild_path,
|
pmb.helpers.run.user(["cp", "-r", apkbuild_path,
|
||||||
pmb.config.work / "aportgen"])
|
work / "aportgen"])
|
||||||
|
|
||||||
pkgver = pmb.build._package.get_pkgver(apkbuild["pkgver"],
|
pkgver = pmb.build._package.get_pkgver(apkbuild["pkgver"],
|
||||||
original_source=False)
|
original_source=False)
|
||||||
|
@ -108,7 +110,7 @@ def modify_apkbuild(args: PmbArgs, pkgname: str, aport: Path):
|
||||||
"subpackages": "",
|
"subpackages": "",
|
||||||
"builddir": "/home/pmos/build/src"}
|
"builddir": "/home/pmos/build/src"}
|
||||||
|
|
||||||
pmb.aportgen.core.rewrite(args, pkgname, apkbuild_path, fields=fields)
|
pmb.aportgen.core.rewrite(pkgname, apkbuild_path, fields=fields)
|
||||||
|
|
||||||
|
|
||||||
def run_abuild(args: PmbArgs, pkgname: str, arch: str, apkbuild_path: Path, kbuild_out):
|
def run_abuild(args: PmbArgs, pkgname: str, arch: str, apkbuild_path: Path, kbuild_out):
|
||||||
|
@ -140,16 +142,16 @@ def run_abuild(args: PmbArgs, pkgname: str, arch: str, apkbuild_path: Path, kbui
|
||||||
"as an argument to make.")
|
"as an argument to make.")
|
||||||
|
|
||||||
# Create working directory for abuild
|
# Create working directory for abuild
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
pmb.build.copy_to_buildpath(pkgname)
|
||||||
|
|
||||||
# Create symlink from abuild working directory to envkernel build directory
|
# Create symlink from abuild working directory to envkernel build directory
|
||||||
if kbuild_out != "":
|
if kbuild_out != "":
|
||||||
if os.path.islink(chroot / "mnt/linux" / kbuild_out) and \
|
if os.path.islink(chroot / "mnt/linux" / kbuild_out) and \
|
||||||
os.path.lexists(chroot / "mnt/linux" / kbuild_out):
|
os.path.lexists(chroot / "mnt/linux" / kbuild_out):
|
||||||
pmb.chroot.root(args, ["rm", "/mnt/linux" / kbuild_out])
|
pmb.chroot.root(["rm", "/mnt/linux" / kbuild_out])
|
||||||
pmb.chroot.root(args, ["ln", "-s", "/mnt/linux",
|
pmb.chroot.root(["ln", "-s", "/mnt/linux",
|
||||||
build_path / "src"])
|
build_path / "src"])
|
||||||
pmb.chroot.root(args, ["ln", "-s", kbuild_out_source,
|
pmb.chroot.root(["ln", "-s", kbuild_out_source,
|
||||||
build_path / "src" / kbuild_out])
|
build_path / "src" / kbuild_out])
|
||||||
|
|
||||||
cmd: List[PathString] = ["cp", apkbuild_path, chroot / build_path / "APKBUILD"]
|
cmd: List[PathString] = ["cp", apkbuild_path, chroot / build_path / "APKBUILD"]
|
||||||
|
@ -161,7 +163,7 @@ def run_abuild(args: PmbArgs, pkgname: str, arch: str, apkbuild_path: Path, kbui
|
||||||
"CBUILD": pmb.config.arch_native,
|
"CBUILD": pmb.config.arch_native,
|
||||||
"SUDO_APK": "abuild-apk --no-progress"}
|
"SUDO_APK": "abuild-apk --no-progress"}
|
||||||
cmd = ["abuild", "rootpkg"]
|
cmd = ["abuild", "rootpkg"]
|
||||||
pmb.chroot.user(args, cmd, working_dir=build_path, env=env)
|
pmb.chroot.user(cmd, working_dir=build_path, env=env)
|
||||||
|
|
||||||
# Clean up bindmount
|
# Clean up bindmount
|
||||||
pmb.helpers.mount.umount_all(chroot / "mnt/linux")
|
pmb.helpers.mount.umount_all(chroot / "mnt/linux")
|
||||||
|
@ -170,8 +172,8 @@ def run_abuild(args: PmbArgs, pkgname: str, arch: str, apkbuild_path: Path, kbui
|
||||||
if kbuild_out != "":
|
if kbuild_out != "":
|
||||||
if os.path.islink(chroot / "mnt/linux" / kbuild_out) and \
|
if os.path.islink(chroot / "mnt/linux" / kbuild_out) and \
|
||||||
os.path.lexists(chroot / "mnt/linux" / kbuild_out):
|
os.path.lexists(chroot / "mnt/linux" / kbuild_out):
|
||||||
pmb.chroot.root(args, ["rm", "/mnt/linux" / kbuild_out])
|
pmb.chroot.root(["rm", "/mnt/linux" / kbuild_out])
|
||||||
pmb.chroot.root(args, ["rm", build_path / "src"])
|
pmb.chroot.root(["rm", build_path / "src"])
|
||||||
|
|
||||||
|
|
||||||
def package_kernel(args: PmbArgs):
|
def package_kernel(args: PmbArgs):
|
||||||
|
@ -181,10 +183,10 @@ def package_kernel(args: PmbArgs):
|
||||||
raise RuntimeError("--envkernel needs exactly one linux-* package as "
|
raise RuntimeError("--envkernel needs exactly one linux-* package as "
|
||||||
"argument.")
|
"argument.")
|
||||||
|
|
||||||
aport = pmb.helpers.pmaports.find(args, pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
|
|
||||||
modify_apkbuild(args, pkgname, aport)
|
modify_apkbuild(pkgname, aport)
|
||||||
apkbuild_path = pmb.config.work / "aportgen/APKBUILD"
|
apkbuild_path = get_context().config.work / "aportgen/APKBUILD"
|
||||||
|
|
||||||
arch = args.deviceinfo["arch"]
|
arch = args.deviceinfo["arch"]
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path, check_pkgname=False)
|
||||||
|
@ -201,7 +203,7 @@ def package_kernel(args: PmbArgs):
|
||||||
pmb.build.init(args, chroot)
|
pmb.build.init(args, chroot)
|
||||||
if pmb.parse.arch.cpu_emulation_required(arch):
|
if pmb.parse.arch.cpu_emulation_required(arch):
|
||||||
depends.append("binutils-" + arch)
|
depends.append("binutils-" + arch)
|
||||||
pmb.chroot.apk.install(args, depends, chroot)
|
pmb.chroot.apk.install(depends, chroot)
|
||||||
|
|
||||||
output = (arch + "/" + apkbuild["pkgname"] + "-" + apkbuild["pkgver"] +
|
output = (arch + "/" + apkbuild["pkgname"] + "-" + apkbuild["pkgver"] +
|
||||||
"-r" + apkbuild["pkgrel"] + ".apk")
|
"-r" + apkbuild["pkgrel"] + ".apk")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core.context import Context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
@ -8,13 +9,13 @@ import pmb.build
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def init_abuild_minimal(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def init_abuild_minimal(chroot: Chroot=Chroot.native()):
|
||||||
"""Initialize a minimal chroot with abuild where one can do 'abuild checksum'."""
|
"""Initialize a minimal chroot with abuild where one can do 'abuild checksum'."""
|
||||||
marker = chroot / "tmp/pmb_chroot_abuild_init_done"
|
marker = chroot / "tmp/pmb_chroot_abuild_init_done"
|
||||||
if os.path.exists(marker):
|
if os.path.exists(marker):
|
||||||
|
@ -22,45 +23,45 @@ def init_abuild_minimal(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
|
|
||||||
# pigz is multithreaded and makes compression must faster, we install it in the native
|
# pigz is multithreaded and makes compression must faster, we install it in the native
|
||||||
# chroot and then symlink it into the buildroot so we aren't running it through QEMU.
|
# chroot and then symlink it into the buildroot so we aren't running it through QEMU.
|
||||||
pmb.chroot.apk.install(args, ["pigz"], Chroot.native(), build=False)
|
pmb.chroot.apk.install(["pigz"], Chroot.native(), build=False)
|
||||||
pmb.chroot.apk.install(args, ["abuild"], chroot, build=False)
|
pmb.chroot.apk.install(["abuild"], chroot, build=False)
|
||||||
|
|
||||||
# Fix permissions
|
# Fix permissions
|
||||||
pmb.chroot.root(args, ["chown", "root:abuild",
|
pmb.chroot.root(["chown", "root:abuild",
|
||||||
"/var/cache/distfiles"], chroot)
|
"/var/cache/distfiles"], chroot)
|
||||||
pmb.chroot.root(args, ["chmod", "g+w",
|
pmb.chroot.root(["chmod", "g+w",
|
||||||
"/var/cache/distfiles"], chroot)
|
"/var/cache/distfiles"], chroot)
|
||||||
|
|
||||||
# Add user to group abuild
|
# Add user to group abuild
|
||||||
pmb.chroot.root(args, ["adduser", "pmos", "abuild"], chroot)
|
pmb.chroot.root(["adduser", "pmos", "abuild"], chroot)
|
||||||
|
|
||||||
pathlib.Path(marker).touch()
|
pathlib.Path(marker).touch()
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def init(chroot: Chroot=Chroot.native()):
|
||||||
"""Initialize a chroot for building packages with abuild."""
|
"""Initialize a chroot for building packages with abuild."""
|
||||||
marker = chroot / "tmp/pmb_chroot_build_init_done"
|
marker = chroot / "tmp/pmb_chroot_build_init_done"
|
||||||
if marker.exists():
|
if marker.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
# Initialize chroot, install packages
|
# Initialize chroot, install packages
|
||||||
pmb.chroot.init(args, Chroot.native())
|
pmb.chroot.init(Chroot.native())
|
||||||
pmb.chroot.init(args, chroot)
|
pmb.chroot.init(chroot)
|
||||||
init_abuild_minimal(args, chroot)
|
init_abuild_minimal(chroot)
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, pmb.config.build_packages, chroot,
|
pmb.chroot.apk.install(pmb.config.build_packages, chroot,
|
||||||
build=False)
|
build=False)
|
||||||
|
|
||||||
# Generate package signing keys
|
# Generate package signing keys
|
||||||
if not os.path.exists(pmb.config.work / "config_abuild/abuild.conf"):
|
if not os.path.exists(get_context().config.work / "config_abuild/abuild.conf"):
|
||||||
logging.info(f"({chroot}) generate abuild keys")
|
logging.info(f"({chroot}) generate abuild keys")
|
||||||
pmb.chroot.user(args, ["abuild-keygen", "-n", "-q", "-a"],
|
pmb.chroot.user(["abuild-keygen", "-n", "-q", "-a"],
|
||||||
chroot, env={"PACKAGER": "pmos <pmos@local>"})
|
chroot, env={"PACKAGER": "pmos <pmos@local>"})
|
||||||
|
|
||||||
# Copy package signing key to /etc/apk/keys
|
# Copy package signing key to /etc/apk/keys
|
||||||
for key in (chroot / "mnt/pmbootstrap/abuild-config").glob("*.pub"):
|
for key in (chroot / "mnt/pmbootstrap/abuild-config").glob("*.pub"):
|
||||||
key = key.relative_to(chroot.path)
|
key = key.relative_to(chroot.path)
|
||||||
pmb.chroot.root(args, ["cp", key, "/etc/apk/keys/"], chroot)
|
pmb.chroot.root(["cp", key, "/etc/apk/keys/"], chroot)
|
||||||
|
|
||||||
apk_arch = chroot.arch
|
apk_arch = chroot.arch
|
||||||
|
|
||||||
|
@ -93,25 +94,25 @@ def init(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
for i in range(len(lines)):
|
for i in range(len(lines)):
|
||||||
lines[i] = lines[i][16:]
|
lines[i] = lines[i][16:]
|
||||||
handle.write("\n".join(lines))
|
handle.write("\n".join(lines))
|
||||||
pmb.chroot.root(args, ["cp", "/tmp/apk_wrapper.sh",
|
pmb.chroot.root(["cp", "/tmp/apk_wrapper.sh",
|
||||||
"/usr/local/bin/abuild-apk"], chroot)
|
"/usr/local/bin/abuild-apk"], chroot)
|
||||||
pmb.chroot.root(args, ["chmod", "+x", "/usr/local/bin/abuild-apk"], chroot)
|
pmb.chroot.root(["chmod", "+x", "/usr/local/bin/abuild-apk"], chroot)
|
||||||
|
|
||||||
# abuild.conf: Don't clean the build folder after building, so we can
|
# abuild.conf: Don't clean the build folder after building, so we can
|
||||||
# inspect it afterwards for debugging
|
# inspect it afterwards for debugging
|
||||||
pmb.chroot.root(args, ["sed", "-i", "-e", "s/^CLEANUP=.*/CLEANUP=''/",
|
pmb.chroot.root(["sed", "-i", "-e", "s/^CLEANUP=.*/CLEANUP=''/",
|
||||||
"/etc/abuild.conf"], chroot)
|
"/etc/abuild.conf"], chroot)
|
||||||
|
|
||||||
# abuild.conf: Don't clean up installed packages in strict mode, so
|
# abuild.conf: Don't clean up installed packages in strict mode, so
|
||||||
# abuild exits directly when pressing ^C in pmbootstrap.
|
# abuild exits directly when pressing ^C in pmbootstrap.
|
||||||
pmb.chroot.root(args, ["sed", "-i", "-e",
|
pmb.chroot.root(["sed", "-i", "-e",
|
||||||
"s/^ERROR_CLEANUP=.*/ERROR_CLEANUP=''/",
|
"s/^ERROR_CLEANUP=.*/ERROR_CLEANUP=''/",
|
||||||
"/etc/abuild.conf"], chroot)
|
"/etc/abuild.conf"], chroot)
|
||||||
|
|
||||||
pathlib.Path(marker).touch()
|
pathlib.Path(marker).touch()
|
||||||
|
|
||||||
|
|
||||||
def init_compiler(args: PmbArgs, depends, cross, arch):
|
def init_compiler(context: Context, depends, cross, arch):
|
||||||
cross_pkgs = ["ccache-cross-symlinks", "abuild"]
|
cross_pkgs = ["ccache-cross-symlinks", "abuild"]
|
||||||
if "gcc4" in depends:
|
if "gcc4" in depends:
|
||||||
cross_pkgs += ["gcc4-" + arch]
|
cross_pkgs += ["gcc4-" + arch]
|
||||||
|
@ -124,11 +125,11 @@ def init_compiler(args: PmbArgs, depends, cross, arch):
|
||||||
if cross == "crossdirect":
|
if cross == "crossdirect":
|
||||||
cross_pkgs += ["crossdirect"]
|
cross_pkgs += ["crossdirect"]
|
||||||
if "rust" in depends or "cargo" in depends:
|
if "rust" in depends or "cargo" in depends:
|
||||||
if args.ccache:
|
if context.ccache:
|
||||||
cross_pkgs += ["sccache"]
|
cross_pkgs += ["sccache"]
|
||||||
# crossdirect for rust installs all build dependencies in the
|
# crossdirect for rust installs all build dependencies in the
|
||||||
# native chroot too, as some of them can be required for building
|
# native chroot too, as some of them can be required for building
|
||||||
# native macros / build scripts
|
# native macros / build scripts
|
||||||
cross_pkgs += depends
|
cross_pkgs += depends
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, cross_pkgs, Chroot.native())
|
pmb.chroot.apk.install(cross_pkgs, Chroot.native())
|
||||||
|
|
|
@ -11,7 +11,7 @@ import pmb.build.checksum
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
@ -65,7 +65,7 @@ def get_outputdir(args: PmbArgs, pkgname: str, apkbuild: Dict[str, Any]) -> Path
|
||||||
|
|
||||||
# New style ($builddir)
|
# New style ($builddir)
|
||||||
cmd = "srcdir=/home/pmos/build/src source APKBUILD; echo $builddir"
|
cmd = "srcdir=/home/pmos/build/src source APKBUILD; echo $builddir"
|
||||||
ret = Path(pmb.chroot.user(args, ["sh", "-c", cmd],
|
ret = Path(pmb.chroot.user(["sh", "-c", cmd],
|
||||||
chroot, Path("/home/pmos/build"),
|
chroot, Path("/home/pmos/build"),
|
||||||
output_return=True).rstrip())
|
output_return=True).rstrip())
|
||||||
if (chroot / ret / ".config").exists():
|
if (chroot / ret / ".config").exists():
|
||||||
|
@ -87,9 +87,9 @@ def get_outputdir(args: PmbArgs, pkgname: str, apkbuild: Dict[str, Any]) -> Path
|
||||||
def extract_and_patch_sources(args: PmbArgs, pkgname: str, arch):
|
def extract_and_patch_sources(args: PmbArgs, pkgname: str, arch):
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
pmb.build.copy_to_buildpath(args, pkgname)
|
||||||
logging.info("(native) extract kernel source")
|
logging.info("(native) extract kernel source")
|
||||||
pmb.chroot.user(args, ["abuild", "unpack"], working_dir=Path("/home/pmos/build"))
|
pmb.chroot.user(["abuild", "unpack"], working_dir=Path("/home/pmos/build"))
|
||||||
logging.info("(native) apply patches")
|
logging.info("(native) apply patches")
|
||||||
pmb.chroot.user(args, ["abuild", "prepare"], working_dir=Path("/home/pmos/build"),
|
pmb.chroot.user(["abuild", "prepare"], working_dir=Path("/home/pmos/build"),
|
||||||
output="interactive", env={"CARCH": arch})
|
output="interactive", env={"CARCH": arch})
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig):
|
||||||
pkgname = "linux-" + pkgname
|
pkgname = "linux-" + pkgname
|
||||||
|
|
||||||
# Read apkbuild
|
# Read apkbuild
|
||||||
aport = pmb.helpers.pmaports.find(args, pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
apkbuild = pmb.parse.apkbuild(aport / "APKBUILD")
|
apkbuild = pmb.parse.apkbuild(aport / "APKBUILD")
|
||||||
arch = args.arch or get_arch(apkbuild)
|
arch = args.arch or get_arch(apkbuild)
|
||||||
suffix = pmb.build.autodetect.chroot(apkbuild, arch)
|
suffix = pmb.build.autodetect.chroot(apkbuild, arch)
|
||||||
|
@ -128,7 +128,7 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig):
|
||||||
else:
|
else:
|
||||||
depends += ["ncurses-dev"]
|
depends += ["ncurses-dev"]
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, depends)
|
pmb.chroot.apk.install(depends)
|
||||||
|
|
||||||
# Copy host's .xauthority into native
|
# Copy host's .xauthority into native
|
||||||
if copy_xauth:
|
if copy_xauth:
|
||||||
|
@ -150,7 +150,7 @@ def menuconfig(args: PmbArgs, pkgname: str, use_oldconfig):
|
||||||
env["CC"] = f"{hostspec}-gcc"
|
env["CC"] = f"{hostspec}-gcc"
|
||||||
if color:
|
if color:
|
||||||
env["MENUCONFIG_COLOR"] = color
|
env["MENUCONFIG_COLOR"] = color
|
||||||
pmb.chroot.user(args, ["make", kopt], Chroot.native(),
|
pmb.chroot.user(["make", kopt], Chroot.native(),
|
||||||
outputdir, output="tui", env=env)
|
outputdir, output="tui", env=env)
|
||||||
|
|
||||||
# Find the updated config
|
# Find the updated config
|
||||||
|
|
|
@ -4,12 +4,12 @@ import os
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.chroot.run
|
import pmb.chroot.run
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
import pmb.build
|
import pmb.build
|
||||||
|
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def newapkbuild(args: PmbArgs, folder, args_passed, force=False):
|
def newapkbuild(args: PmbArgs, folder, args_passed, force=False):
|
||||||
|
@ -18,11 +18,11 @@ def newapkbuild(args: PmbArgs, folder, args_passed, force=False):
|
||||||
build = Path("/home/pmos/build")
|
build = Path("/home/pmos/build")
|
||||||
build_outside = Chroot.native() / build
|
build_outside = Chroot.native() / build
|
||||||
if build_outside.exists():
|
if build_outside.exists():
|
||||||
pmb.chroot.root(args, ["rm", "-r", build])
|
pmb.chroot.root(["rm", "-r", build])
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", build])
|
pmb.chroot.user(["mkdir", "-p", build])
|
||||||
|
|
||||||
# Run newapkbuild
|
# Run newapkbuild
|
||||||
pmb.chroot.user(args, ["newapkbuild"] + args_passed, working_dir=build)
|
pmb.chroot.user(["newapkbuild"] + args_passed, working_dir=build)
|
||||||
glob_result = list(build_outside.glob("/*/APKBUILD"))
|
glob_result = list(build_outside.glob("/*/APKBUILD"))
|
||||||
if not len(glob_result):
|
if not len(glob_result):
|
||||||
return
|
return
|
||||||
|
@ -30,13 +30,13 @@ def newapkbuild(args: PmbArgs, folder, args_passed, force=False):
|
||||||
# Paths for copying
|
# Paths for copying
|
||||||
source_apkbuild = glob_result[0]
|
source_apkbuild = glob_result[0]
|
||||||
pkgname = pmb.parse.apkbuild(source_apkbuild, False)["pkgname"]
|
pkgname = pmb.parse.apkbuild(source_apkbuild, False)["pkgname"]
|
||||||
target = args.aports / folder / pkgname
|
target = get_context().config.aports / folder / pkgname
|
||||||
|
|
||||||
# Move /home/pmos/build/$pkgname/* to /home/pmos/build/*
|
# Move /home/pmos/build/$pkgname/* to /home/pmos/build/*
|
||||||
for path in build_outside.glob("/*/*"):
|
for path in build_outside.glob("/*/*"):
|
||||||
path_inside = build / pkgname / os.path.basename(path)
|
path_inside = build / pkgname / os.path.basename(path)
|
||||||
pmb.chroot.user(args, ["mv", path_inside, build])
|
pmb.chroot.user(["mv", path_inside, build])
|
||||||
pmb.chroot.user(args, ["rmdir", build / pkgname])
|
pmb.chroot.user(["rmdir", build / pkgname])
|
||||||
|
|
||||||
# Overwrite confirmation
|
# Overwrite confirmation
|
||||||
if os.path.exists(target):
|
if os.path.exists(target):
|
||||||
|
|
|
@ -8,7 +8,7 @@ import datetime
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
@ -16,12 +16,12 @@ import pmb.helpers.run
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def copy_to_buildpath(args: PmbArgs, package, chroot: Chroot=Chroot.native()):
|
def copy_to_buildpath(package, chroot: Chroot=Chroot.native()):
|
||||||
# Sanity check
|
# Sanity check
|
||||||
aport = pmb.helpers.pmaports.find(args, package)
|
aport = pmb.helpers.pmaports.find(package)
|
||||||
if not os.path.exists(aport / "APKBUILD"):
|
if not os.path.exists(aport / "APKBUILD"):
|
||||||
raise ValueError(f"Path does not contain an APKBUILD file: {aport}")
|
raise ValueError(f"Path does not contain an APKBUILD file: {aport}")
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ def copy_to_buildpath(args: PmbArgs, package, chroot: Chroot=Chroot.native()):
|
||||||
continue
|
continue
|
||||||
pmb.helpers.run.root(["cp", "-rL", aport / file, build / file])
|
pmb.helpers.run.root(["cp", "-rL", aport / file, build / file])
|
||||||
|
|
||||||
pmb.chroot.root(args, ["chown", "-R", "pmos:pmos",
|
pmb.chroot.root(["chown", "-R", "pmos:pmos",
|
||||||
"/home/pmos/build"], chroot)
|
"/home/pmos/build"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def is_necessary(args: PmbArgs, arch, apkbuild, indexes=None):
|
def is_necessary(arch, apkbuild, indexes=None):
|
||||||
"""Check if the package has already been built.
|
"""Check if the package has already been built.
|
||||||
|
|
||||||
Compared to abuild's check, this check also works for different architectures.
|
Compared to abuild's check, this check also works for different architectures.
|
||||||
|
@ -61,7 +61,7 @@ def is_necessary(args: PmbArgs, arch, apkbuild, indexes=None):
|
||||||
msg = "Build is necessary for package '" + package + "': "
|
msg = "Build is necessary for package '" + package + "': "
|
||||||
|
|
||||||
# Get version from APKINDEX
|
# Get version from APKINDEX
|
||||||
index_data = pmb.parse.apkindex.package(args, package, arch, False,
|
index_data = pmb.parse.apkindex.package(package, arch, False,
|
||||||
indexes)
|
indexes)
|
||||||
if not index_data:
|
if not index_data:
|
||||||
logging.debug(msg + "No binary package available")
|
logging.debug(msg + "No binary package available")
|
||||||
|
@ -101,8 +101,8 @@ def index_repo(args: PmbArgs, arch=None):
|
||||||
"""
|
"""
|
||||||
pmb.build.init(args)
|
pmb.build.init(args)
|
||||||
|
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
pkgdir = (pmb.config.work / "packages" / channel)
|
pkgdir = (get_context().config.work / "packages" / channel)
|
||||||
paths: List[Path] = []
|
paths: List[Path] = []
|
||||||
if arch:
|
if arch:
|
||||||
paths = [pkgdir / arch]
|
paths = [pkgdir / arch]
|
||||||
|
@ -124,55 +124,57 @@ def index_repo(args: PmbArgs, arch=None):
|
||||||
["mv", "APKINDEX.tar.gz_", "APKINDEX.tar.gz"]
|
["mv", "APKINDEX.tar.gz_", "APKINDEX.tar.gz"]
|
||||||
]
|
]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.user(args, command, working_dir=path_repo_chroot)
|
pmb.chroot.user(command, working_dir=path_repo_chroot)
|
||||||
else:
|
else:
|
||||||
logging.debug(f"NOTE: Can't build index for: {path}")
|
logging.debug(f"NOTE: Can't build index for: {path}")
|
||||||
pmb.parse.apkindex.clear_cache(path / "APKINDEX.tar.gz")
|
pmb.parse.apkindex.clear_cache(path / "APKINDEX.tar.gz")
|
||||||
|
|
||||||
|
|
||||||
def configure_abuild(args: PmbArgs, chroot: Chroot, verify=False):
|
def configure_abuild(chroot: Chroot, verify=False):
|
||||||
"""Set the correct JOBS count in ``abuild.conf``.
|
"""Set the correct JOBS count in ``abuild.conf``.
|
||||||
|
|
||||||
:param verify: internally used to test if changing the config has worked.
|
:param verify: internally used to test if changing the config has worked.
|
||||||
"""
|
"""
|
||||||
|
jobs = get_context().config.jobs
|
||||||
path = chroot / "etc/abuild.conf"
|
path = chroot / "etc/abuild.conf"
|
||||||
prefix = "export JOBS="
|
prefix = "export JOBS="
|
||||||
with path.open(encoding="utf-8") as handle:
|
with path.open(encoding="utf-8") as handle:
|
||||||
for line in handle:
|
for line in handle:
|
||||||
if not line.startswith(prefix):
|
if not line.startswith(prefix):
|
||||||
continue
|
continue
|
||||||
if line != (prefix + args.jobs + "\n"):
|
if line != (prefix + jobs + "\n"):
|
||||||
if verify:
|
if verify:
|
||||||
raise RuntimeError(f"Failed to configure abuild: {path}"
|
raise RuntimeError(f"Failed to configure abuild: {path}"
|
||||||
"\nTry to delete the file"
|
"\nTry to delete the file"
|
||||||
"(or zap the chroot).")
|
"(or zap the chroot).")
|
||||||
pmb.chroot.root(args, ["sed", "-i", "-e",
|
pmb.chroot.root(["sed", "-i", "-e",
|
||||||
f"s/^{prefix}.*/{prefix}{args.jobs}/",
|
f"s/^{prefix}.*/{prefix}{jobs}/",
|
||||||
"/etc/abuild.conf"],
|
"/etc/abuild.conf"],
|
||||||
chroot)
|
chroot)
|
||||||
configure_abuild(args, chroot, True)
|
configure_abuild(chroot, True)
|
||||||
return
|
return
|
||||||
pmb.chroot.root(args, ["sed", "-i", f"$ a\\{prefix}{args.jobs}", "/etc/abuild.conf"], chroot)
|
pmb.chroot.root(["sed", "-i", f"$ a\\{prefix}{jobs}", "/etc/abuild.conf"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def configure_ccache(args: PmbArgs, chroot: Chroot=Chroot.native(), verify=False):
|
def configure_ccache(chroot: Chroot=Chroot.native(), verify=False):
|
||||||
"""Set the maximum ccache size.
|
"""Set the maximum ccache size.
|
||||||
|
|
||||||
:param verify: internally used to test if changing the config has worked.
|
:param verify: internally used to test if changing the config has worked.
|
||||||
"""
|
"""
|
||||||
# Check if the settings have been set already
|
# Check if the settings have been set already
|
||||||
arch = chroot.arch
|
arch = chroot.arch
|
||||||
path = pmb.config.work / f"cache_ccache_{arch}" / "ccache.conf"
|
config = get_context().config
|
||||||
|
path = config.work / f"cache_ccache_{arch}" / "ccache.conf"
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
with open(path, encoding="utf-8") as handle:
|
with open(path, encoding="utf-8") as handle:
|
||||||
for line in handle:
|
for line in handle:
|
||||||
if line == ("max_size = " + args.ccache_size + "\n"):
|
if line == ("max_size = " + config.ccache_size + "\n"):
|
||||||
return
|
return
|
||||||
if verify:
|
if verify:
|
||||||
raise RuntimeError(f"Failed to configure ccache: {path}\nTry to"
|
raise RuntimeError(f"Failed to configure ccache: {path}\nTry to"
|
||||||
" delete the file (or zap the chroot).")
|
" delete the file (or zap the chroot).")
|
||||||
|
|
||||||
# Set the size and verify
|
# Set the size and verify
|
||||||
pmb.chroot.user(args, ["ccache", "--max-size", args.ccache_size],
|
pmb.chroot.user(["ccache", "--max-size", config.ccache_size],
|
||||||
chroot)
|
chroot)
|
||||||
configure_ccache(args, chroot, True)
|
configure_ccache(chroot, True)
|
||||||
|
|
|
@ -8,9 +8,10 @@ from pmb.helpers import logging
|
||||||
import shlex
|
import shlex
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
import pmb.build
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.apk
|
import pmb.helpers.apk
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
@ -23,7 +24,7 @@ import pmb.parse.version
|
||||||
from pmb.core import Chroot, get_context
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def update_repository_list(args: PmbArgs, suffix: Chroot, postmarketos_mirror=True,
|
def update_repository_list(suffix: Chroot, postmarketos_mirror=True,
|
||||||
check=False):
|
check=False):
|
||||||
"""
|
"""
|
||||||
Update /etc/apk/repositories, if it is outdated (when the user changed the
|
Update /etc/apk/repositories, if it is outdated (when the user changed the
|
||||||
|
@ -52,7 +53,7 @@ def update_repository_list(args: PmbArgs, suffix: Chroot, postmarketos_mirror=Tr
|
||||||
pmb.helpers.run.root(["mkdir", "-p", path.parent])
|
pmb.helpers.run.root(["mkdir", "-p", path.parent])
|
||||||
|
|
||||||
# Up to date: Save cache, return
|
# Up to date: Save cache, return
|
||||||
lines_new = pmb.helpers.repo.urls(args, postmarketos_mirror=postmarketos_mirror)
|
lines_new = pmb.helpers.repo.urls(postmarketos_mirror=postmarketos_mirror)
|
||||||
if lines_old == lines_new:
|
if lines_old == lines_new:
|
||||||
pmb.helpers.other.cache["apk_repository_list_updated"].append(suffix)
|
pmb.helpers.other.cache["apk_repository_list_updated"].append(suffix)
|
||||||
return
|
return
|
||||||
|
@ -68,10 +69,10 @@ def update_repository_list(args: PmbArgs, suffix: Chroot, postmarketos_mirror=Tr
|
||||||
for line in lines_new:
|
for line in lines_new:
|
||||||
pmb.helpers.run.root(["sh", "-c", "echo "
|
pmb.helpers.run.root(["sh", "-c", "echo "
|
||||||
f"{shlex.quote(line)} >> {path}"])
|
f"{shlex.quote(line)} >> {path}"])
|
||||||
update_repository_list(args, suffix, postmarketos_mirror, True)
|
update_repository_list(suffix, postmarketos_mirror, True)
|
||||||
|
|
||||||
|
|
||||||
def check_min_version(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def check_min_version(chroot: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
Check the minimum apk version, before running it the first time in the
|
Check the minimum apk version, before running it the first time in the
|
||||||
current session (lifetime of one pmbootstrap call).
|
current session (lifetime of one pmbootstrap call).
|
||||||
|
@ -90,7 +91,7 @@ def check_min_version(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
# Compare
|
# Compare
|
||||||
version_installed = installed(chroot)["apk-tools"]["version"]
|
version_installed = installed(chroot)["apk-tools"]["version"]
|
||||||
pmb.helpers.apk.check_outdated(
|
pmb.helpers.apk.check_outdated(
|
||||||
args, version_installed,
|
version_installed,
|
||||||
"Delete your http cache and zap all chroots, then try again:"
|
"Delete your http cache and zap all chroots, then try again:"
|
||||||
" 'pmbootstrap zap -hc'")
|
" 'pmbootstrap zap -hc'")
|
||||||
|
|
||||||
|
@ -98,32 +99,6 @@ def check_min_version(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
pmb.helpers.other.cache["apk_min_version_checked"].append(chroot.path)
|
pmb.helpers.other.cache["apk_min_version_checked"].append(chroot.path)
|
||||||
|
|
||||||
|
|
||||||
def install_build(args: PmbArgs, package, arch):
|
|
||||||
"""
|
|
||||||
Build an outdated package unless pmbootstrap was invoked with
|
|
||||||
"pmbootstrap install" and the option to build packages during pmb install
|
|
||||||
is disabled.
|
|
||||||
|
|
||||||
:param package: name of the package to build
|
|
||||||
:param arch: architecture of the package to build
|
|
||||||
"""
|
|
||||||
# User may have disabled building packages during "pmbootstrap install"
|
|
||||||
if args.action == "install" and not args.build_pkgs_on_install:
|
|
||||||
if not pmb.parse.apkindex.package(args, package, arch, False):
|
|
||||||
raise RuntimeError(f"{package}: no binary package found for"
|
|
||||||
f" {arch}, and compiling packages during"
|
|
||||||
" 'pmbootstrap install' has been disabled."
|
|
||||||
" Consider changing this option in"
|
|
||||||
" 'pmbootstrap init'.")
|
|
||||||
# Use the existing binary package
|
|
||||||
return
|
|
||||||
|
|
||||||
# Build the package if it's in pmaports and there is no binary package
|
|
||||||
# with the same pkgver and pkgrel. This check is done in
|
|
||||||
# pmb.build.is_necessary, which gets called in pmb.build.package.
|
|
||||||
return pmb.build.package(args, package, arch)
|
|
||||||
|
|
||||||
|
|
||||||
def packages_split_to_add_del(packages):
|
def packages_split_to_add_del(packages):
|
||||||
"""
|
"""
|
||||||
Sort packages into "to_add" and "to_del" lists depending on their pkgname
|
Sort packages into "to_add" and "to_del" lists depending on their pkgname
|
||||||
|
@ -145,7 +120,7 @@ def packages_split_to_add_del(packages):
|
||||||
return (to_add, to_del)
|
return (to_add, to_del)
|
||||||
|
|
||||||
|
|
||||||
def packages_get_locally_built_apks(args: PmbArgs, packages, arch: str) -> List[Path]:
|
def packages_get_locally_built_apks(packages, arch: str) -> List[Path]:
|
||||||
"""
|
"""
|
||||||
Iterate over packages and if existing, get paths to locally built packages.
|
Iterate over packages and if existing, get paths to locally built packages.
|
||||||
This is used to force apk to upgrade packages to newer local versions, even
|
This is used to force apk to upgrade packages to newer local versions, even
|
||||||
|
@ -156,16 +131,16 @@ def packages_get_locally_built_apks(args: PmbArgs, packages, arch: str) -> List[
|
||||||
:returns: list of apk file paths that are valid inside the chroots, e.g.
|
:returns: list of apk file paths that are valid inside the chroots, e.g.
|
||||||
["/mnt/pmbootstrap/packages/x86_64/hello-world-1-r6.apk", ...]
|
["/mnt/pmbootstrap/packages/x86_64/hello-world-1-r6.apk", ...]
|
||||||
"""
|
"""
|
||||||
channel: str = pmb.config.pmaports.read_config(args)["channel"]
|
channel: str = pmb.config.pmaports.read_config()["channel"]
|
||||||
ret: List[Path] = []
|
ret: List[Path] = []
|
||||||
|
|
||||||
for package in packages:
|
for package in packages:
|
||||||
data_repo = pmb.parse.apkindex.package(args, package, arch, False)
|
data_repo = pmb.parse.apkindex.package(package, arch, False)
|
||||||
if not data_repo:
|
if not data_repo:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
apk_file = f"{package}-{data_repo['version']}.apk"
|
apk_file = f"{package}-{data_repo['version']}.apk"
|
||||||
apk_path = pmb.config.work / "packages" / channel / arch / apk_file
|
apk_path = get_context().config.work / "packages" / channel / arch / apk_file
|
||||||
if not apk_path.exists():
|
if not apk_path.exists():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -210,7 +185,7 @@ def install_run_apk(to_add, to_add_local, to_del, chroot: Chroot):
|
||||||
# it from there.
|
# it from there.
|
||||||
apk_static = Chroot.native() / "sbin/apk.static"
|
apk_static = Chroot.native() / "sbin/apk.static"
|
||||||
arch = chroot.arch
|
arch = chroot.arch
|
||||||
apk_cache = pmb.config.work / f"cache_apk_{arch}"
|
apk_cache = get_context().config.work / f"cache_apk_{arch}"
|
||||||
|
|
||||||
for (i, command) in enumerate(commands):
|
for (i, command) in enumerate(commands):
|
||||||
# --no-interactive is a parameter to `add`, so it must be appended or apk
|
# --no-interactive is a parameter to `add`, so it must be appended or apk
|
||||||
|
@ -233,7 +208,7 @@ def install_run_apk(to_add, to_add_local, to_del, chroot: Chroot):
|
||||||
pmb.helpers.run.root([apk_static, "--no-progress"] + command)
|
pmb.helpers.run.root([apk_static, "--no-progress"] + command)
|
||||||
|
|
||||||
|
|
||||||
def install(args: PmbArgs, packages, chroot: Chroot, build=True):
|
def install(packages, chroot: Chroot, build=True):
|
||||||
"""
|
"""
|
||||||
Install packages from pmbootstrap's local package index or the pmOS/Alpine
|
Install packages from pmbootstrap's local package index or the pmOS/Alpine
|
||||||
binary package mirrors. Iterate over all dependencies recursively, and
|
binary package mirrors. Iterate over all dependencies recursively, and
|
||||||
|
@ -247,6 +222,7 @@ def install(args: PmbArgs, packages, chroot: Chroot, build=True):
|
||||||
repositories, set this to False for performance optimization.
|
repositories, set this to False for performance optimization.
|
||||||
"""
|
"""
|
||||||
arch = chroot.arch
|
arch = chroot.arch
|
||||||
|
context = get_context()
|
||||||
|
|
||||||
if not packages:
|
if not packages:
|
||||||
logging.verbose("pmb.chroot.apk.install called with empty packages list,"
|
logging.verbose("pmb.chroot.apk.install called with empty packages list,"
|
||||||
|
@ -254,21 +230,21 @@ def install(args: PmbArgs, packages, chroot: Chroot, build=True):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Initialize chroot
|
# Initialize chroot
|
||||||
check_min_version(args, chroot)
|
check_min_version(chroot)
|
||||||
|
|
||||||
installed_pkgs = pmb.chroot.user(["apk", "info", "-e"] + packages, chroot, output_return=True, check=False)
|
installed_pkgs = pmb.chroot.user(["apk", "info", "-e"] + packages, chroot, output_return=True, check=False)
|
||||||
if installed_pkgs is not None and installed_pkgs.strip().split("\n") == packages:
|
if installed_pkgs is not None and installed_pkgs.strip().split("\n") == packages:
|
||||||
logging.debug(f"({chroot}) all packages already installed")
|
logging.debug(f"({chroot}) all packages already installed")
|
||||||
return
|
return
|
||||||
|
|
||||||
packages_with_depends = pmb.parse.depends.recurse(args, packages, chroot)
|
packages_with_depends = pmb.parse.depends.recurse(packages, chroot)
|
||||||
to_add, to_del = packages_split_to_add_del(packages_with_depends)
|
to_add, to_del = packages_split_to_add_del(packages_with_depends)
|
||||||
|
|
||||||
if build:
|
if build and context.config.build_pkgs_on_install:
|
||||||
for package in to_add:
|
for package in to_add:
|
||||||
install_build(args, package, arch)
|
pmb.build.package(context, package, arch)
|
||||||
|
|
||||||
to_add_local = packages_get_locally_built_apks(args, to_add, arch)
|
to_add_local = packages_get_locally_built_apks(to_add, arch)
|
||||||
to_add_no_deps, _ = packages_split_to_add_del(packages)
|
to_add_no_deps, _ = packages_split_to_add_del(packages)
|
||||||
|
|
||||||
logging.info(f"({chroot}) install {' '.join(to_add_no_deps)}")
|
logging.info(f"({chroot}) install {' '.join(to_add_no_deps)}")
|
||||||
|
|
|
@ -7,7 +7,7 @@ import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import stat
|
import stat
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.apk
|
import pmb.helpers.apk
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
@ -15,6 +15,7 @@ import pmb.config.load
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.helpers.http
|
import pmb.helpers.http
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
def read_signature_info(tar):
|
def read_signature_info(tar):
|
||||||
|
@ -77,7 +78,7 @@ def extract_temp(tar, sigfilename):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def verify_signature(args: PmbArgs, files, sigkey_path):
|
def verify_signature(files, sigkey_path):
|
||||||
"""
|
"""
|
||||||
Verify the signature with openssl.
|
Verify the signature with openssl.
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ def verify_signature(args: PmbArgs, files, sigkey_path):
|
||||||
" delete the download and try again.")
|
" delete the download and try again.")
|
||||||
|
|
||||||
|
|
||||||
def extract(args: PmbArgs, version, apk_path):
|
def extract(version, apk_path):
|
||||||
"""
|
"""
|
||||||
Extract everything to temporary locations, verify signatures and reported
|
Extract everything to temporary locations, verify signatures and reported
|
||||||
versions. When everything is right, move the extracted apk.static to the
|
versions. When everything is right, move the extracted apk.static to the
|
||||||
|
@ -111,7 +112,7 @@ def extract(args: PmbArgs, version, apk_path):
|
||||||
files = extract_temp(tar, sigfilename)
|
files = extract_temp(tar, sigfilename)
|
||||||
|
|
||||||
# Verify signature
|
# Verify signature
|
||||||
verify_signature(args, files, sigkey_path)
|
verify_signature(files, sigkey_path)
|
||||||
os.unlink(files["sig"]["temp_path"])
|
os.unlink(files["sig"]["temp_path"])
|
||||||
temp_path = files["apk"]["temp_path"]
|
temp_path = files["apk"]["temp_path"]
|
||||||
|
|
||||||
|
@ -131,45 +132,45 @@ def extract(args: PmbArgs, version, apk_path):
|
||||||
" and try again.")
|
" and try again.")
|
||||||
|
|
||||||
# Move it to the right path
|
# Move it to the right path
|
||||||
target_path = pmb.config.work / "apk.static"
|
target_path = get_context().config.work / "apk.static"
|
||||||
shutil.move(temp_path, target_path)
|
shutil.move(temp_path, target_path)
|
||||||
|
|
||||||
|
|
||||||
def download(args: PmbArgs, file):
|
def download(file):
|
||||||
"""
|
"""
|
||||||
Download a single file from an Alpine mirror.
|
Download a single file from an Alpine mirror.
|
||||||
"""
|
"""
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir = channel_cfg["mirrordir_alpine"]
|
mirrordir = channel_cfg["mirrordir_alpine"]
|
||||||
base_url = f"{args.mirror_alpine}{mirrordir}/main/{pmb.config.arch_native}"
|
base_url = f"{get_context().config.mirror_alpine}{mirrordir}/main/{pmb.config.arch_native}"
|
||||||
return pmb.helpers.http.download(args, f"{base_url}/{file}", file)
|
return pmb.helpers.http.download(f"{base_url}/{file}", file)
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs):
|
def init():
|
||||||
"""
|
"""
|
||||||
Download, verify, extract $WORK/apk.static.
|
Download, verify, extract $WORK/apk.static.
|
||||||
"""
|
"""
|
||||||
# Get and parse the APKINDEX
|
# Get and parse the APKINDEX
|
||||||
apkindex = pmb.helpers.repo.alpine_apkindex_path(args, "main")
|
apkindex = pmb.helpers.repo.alpine_apkindex_path("main")
|
||||||
index_data = pmb.parse.apkindex.package(args, "apk-tools-static",
|
index_data = pmb.parse.apkindex.package("apk-tools-static",
|
||||||
indexes=[apkindex])
|
indexes=[apkindex])
|
||||||
version = index_data["version"]
|
version = index_data["version"]
|
||||||
|
|
||||||
# Verify the apk-tools-static version
|
# Verify the apk-tools-static version
|
||||||
pmb.helpers.apk.check_outdated(
|
pmb.helpers.apk.check_outdated(
|
||||||
args, version, "Run 'pmbootstrap update', then try again.")
|
version, "Run 'pmbootstrap update', then try again.")
|
||||||
|
|
||||||
# Download, extract, verify apk-tools-static
|
# Download, extract, verify apk-tools-static
|
||||||
apk_name = f"apk-tools-static-{version}.apk"
|
apk_name = f"apk-tools-static-{version}.apk"
|
||||||
apk_static = download(args, apk_name)
|
apk_static = download(apk_name)
|
||||||
extract(args, version, apk_static)
|
extract(version, apk_static)
|
||||||
|
|
||||||
|
|
||||||
def run(args: PmbArgs, parameters):
|
def run(parameters):
|
||||||
# --no-interactive is a parameter to `add`, so it must be appended or apk
|
# --no-interactive is a parameter to `add`, so it must be appended or apk
|
||||||
# gets confused
|
# gets confused
|
||||||
parameters += ["--no-interactive"]
|
parameters += ["--no-interactive"]
|
||||||
|
|
||||||
if args.offline:
|
if get_context().offline:
|
||||||
parameters = ["--no-network"] + parameters
|
parameters = ["--no-network"] + parameters
|
||||||
pmb.helpers.apk.apk_with_progress([pmb.config.work / "apk.static"] + parameters)
|
pmb.helpers.apk.apk_with_progress([get_context().config.work / "apk.static"] + parameters)
|
||||||
|
|
|
@ -4,31 +4,33 @@ import os
|
||||||
from pmb.core.chroot import Chroot
|
from pmb.core.chroot import Chroot
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
|
import pmb.chroot.apk
|
||||||
|
|
||||||
|
|
||||||
def is_registered(arch_qemu):
|
def is_registered(arch_qemu):
|
||||||
return os.path.exists("/proc/sys/fs/binfmt_misc/qemu-" + arch_qemu)
|
return os.path.exists("/proc/sys/fs/binfmt_misc/qemu-" + arch_qemu)
|
||||||
|
|
||||||
|
|
||||||
def register(args: PmbArgs, arch):
|
def register(arch):
|
||||||
"""
|
"""
|
||||||
Get arch, magic, mask.
|
Get arch, magic, mask.
|
||||||
"""
|
"""
|
||||||
arch_qemu = pmb.parse.arch.alpine_to_qemu(arch)
|
arch_qemu = pmb.parse.arch.alpine_to_qemu(arch)
|
||||||
|
chroot = Chroot.native()
|
||||||
|
|
||||||
# always make sure the qemu-<arch> binary is installed, since registering
|
# always make sure the qemu-<arch> binary is installed, since registering
|
||||||
# may happen outside of this method (e.g. by OS)
|
# may happen outside of this method (e.g. by OS)
|
||||||
if f"qemu-{arch_qemu}" not in pmb.chroot.apk.installed(args):
|
if f"qemu-{arch_qemu}" not in pmb.chroot.apk.installed(chroot):
|
||||||
pmb.chroot.apk.install(args, ["qemu-" + arch_qemu], Chroot.native())
|
pmb.chroot.apk.install(["qemu-" + arch_qemu], chroot)
|
||||||
|
|
||||||
if is_registered(arch_qemu):
|
if is_registered(arch_qemu):
|
||||||
return
|
return
|
||||||
pmb.helpers.other.check_binfmt_misc(args)
|
pmb.helpers.other.check_binfmt_misc()
|
||||||
|
|
||||||
# Don't continue if the actions from check_binfmt_misc caused the OS to
|
# Don't continue if the actions from check_binfmt_misc caused the OS to
|
||||||
# automatically register the target arch
|
# automatically register the target arch
|
||||||
|
|
|
@ -7,15 +7,15 @@ from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
|
import pmb.chroot.binfmt
|
||||||
import pmb.chroot.apk_static
|
import pmb.chroot.apk_static
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.workdir
|
import pmb.config.workdir
|
||||||
from pmb.core.types import PmbArgs
|
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType, get_context
|
||||||
|
|
||||||
cache_chroot_is_outdated: List[str] = []
|
cache_chroot_is_outdated: List[str] = []
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class UsrMerge(enum.Enum):
|
||||||
OFF = 2
|
OFF = 2
|
||||||
|
|
||||||
|
|
||||||
def copy_resolv_conf(args: PmbArgs, chroot: Chroot):
|
def copy_resolv_conf(chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
Use pythons super fast file compare function (due to caching)
|
Use pythons super fast file compare function (due to caching)
|
||||||
and copy the /etc/resolv.conf to the chroot, in case it is
|
and copy the /etc/resolv.conf to the chroot, in case it is
|
||||||
|
@ -45,7 +45,7 @@ def copy_resolv_conf(args: PmbArgs, chroot: Chroot):
|
||||||
pmb.helpers.run.root(["touch", resolv_path])
|
pmb.helpers.run.root(["touch", resolv_path])
|
||||||
|
|
||||||
|
|
||||||
def mark_in_chroot(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def mark_in_chroot(chroot: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
Touch a flag so we can know when we're running in chroot (and
|
Touch a flag so we can know when we're running in chroot (and
|
||||||
don't accidentally flash partitions on our host). This marker
|
don't accidentally flash partitions on our host). This marker
|
||||||
|
@ -56,7 +56,7 @@ def mark_in_chroot(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
pmb.helpers.run.root(["touch", in_chroot_file])
|
pmb.helpers.run.root(["touch", in_chroot_file])
|
||||||
|
|
||||||
|
|
||||||
def setup_qemu_emulation(args: PmbArgs, chroot: Chroot):
|
def setup_qemu_emulation(chroot: Chroot):
|
||||||
arch = chroot.arch
|
arch = chroot.arch
|
||||||
if not pmb.parse.arch.cpu_emulation_required(arch):
|
if not pmb.parse.arch.cpu_emulation_required(arch):
|
||||||
return
|
return
|
||||||
|
@ -64,13 +64,13 @@ def setup_qemu_emulation(args: PmbArgs, chroot: Chroot):
|
||||||
arch_qemu = pmb.parse.arch.alpine_to_qemu(arch)
|
arch_qemu = pmb.parse.arch.alpine_to_qemu(arch)
|
||||||
|
|
||||||
# mount --bind the qemu-user binary
|
# mount --bind the qemu-user binary
|
||||||
pmb.chroot.binfmt.register(args, arch)
|
pmb.chroot.binfmt.register(arch)
|
||||||
pmb.helpers.mount.bind_file(Chroot.native() / f"/usr/bin/qemu-{arch_qemu}",
|
pmb.helpers.mount.bind_file(Chroot.native() / f"/usr/bin/qemu-{arch_qemu}",
|
||||||
chroot / f"usr/bin/qemu-{arch_qemu}-static",
|
chroot / f"usr/bin/qemu-{arch_qemu}-static",
|
||||||
create_folders=True)
|
create_folders=True)
|
||||||
|
|
||||||
|
|
||||||
def init_keys(args: PmbArgs):
|
def init_keys():
|
||||||
"""
|
"""
|
||||||
All Alpine and postmarketOS repository keys are shipped with pmbootstrap.
|
All Alpine and postmarketOS repository keys are shipped with pmbootstrap.
|
||||||
Copy them into $WORK/config_apk_keys, which gets mounted inside the various
|
Copy them into $WORK/config_apk_keys, which gets mounted inside the various
|
||||||
|
@ -81,27 +81,27 @@ def init_keys(args: PmbArgs):
|
||||||
not installed yet.
|
not installed yet.
|
||||||
"""
|
"""
|
||||||
for key in pmb.config.apk_keys_path.glob("*.pub"):
|
for key in pmb.config.apk_keys_path.glob("*.pub"):
|
||||||
target = pmb.config.work / "config_apk_keys" / key.name
|
target = get_context().config.work / "config_apk_keys" / key.name
|
||||||
if not target.exists():
|
if not target.exists():
|
||||||
# Copy as root, so the resulting files in chroots are owned by root
|
# Copy as root, so the resulting files in chroots are owned by root
|
||||||
pmb.helpers.run.root(["cp", key, target])
|
pmb.helpers.run.root(["cp", key, target])
|
||||||
|
|
||||||
|
|
||||||
def init_usr_merge(args: PmbArgs, chroot: Chroot):
|
def init_usr_merge(chroot: Chroot):
|
||||||
logging.info(f"({chroot}) merge /usr")
|
logging.info(f"({chroot}) merge /usr")
|
||||||
script = f"{pmb.config.pmb_src}/pmb/data/merge-usr.sh"
|
script = f"{pmb.config.pmb_src}/pmb/data/merge-usr.sh"
|
||||||
pmb.helpers.run.root(["sh", "-e", script, "CALLED_FROM_PMB",
|
pmb.helpers.run.root(["sh", "-e", script, "CALLED_FROM_PMB",
|
||||||
chroot.path])
|
chroot.path])
|
||||||
|
|
||||||
|
|
||||||
def warn_if_chroot_is_outdated(args: PmbArgs, chroot: Chroot):
|
def warn_if_chroot_is_outdated(chroot: Chroot):
|
||||||
global cache_chroot_is_outdated
|
global cache_chroot_is_outdated
|
||||||
|
|
||||||
# Only check / display the warning once per session
|
# Only check / display the warning once per session
|
||||||
if str(chroot) in cache_chroot_is_outdated:
|
if str(chroot) in cache_chroot_is_outdated:
|
||||||
return
|
return
|
||||||
|
|
||||||
if pmb.config.workdir.chroots_outdated(args, chroot):
|
if pmb.config.workdir.chroots_outdated(chroot):
|
||||||
days_warn = int(pmb.config.chroot_outdated / 3600 / 24)
|
days_warn = int(pmb.config.chroot_outdated / 3600 / 24)
|
||||||
logging.warning(f"WARNING: Your {chroot} chroot is older than"
|
logging.warning(f"WARNING: Your {chroot} chroot is older than"
|
||||||
f" {days_warn} days. Consider running"
|
f" {days_warn} days. Consider running"
|
||||||
|
@ -110,7 +110,7 @@ def warn_if_chroot_is_outdated(args: PmbArgs, chroot: Chroot):
|
||||||
cache_chroot_is_outdated += [str(chroot)]
|
cache_chroot_is_outdated += [str(chroot)]
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs, chroot: Chroot=Chroot.native(), usr_merge=UsrMerge.AUTO,
|
def init(chroot: Chroot=Chroot.native(), usr_merge=UsrMerge.AUTO,
|
||||||
postmarketos_mirror=True):
|
postmarketos_mirror=True):
|
||||||
"""
|
"""
|
||||||
Initialize a chroot by copying the resolv.conf and updating
|
Initialize a chroot by copying the resolv.conf and updating
|
||||||
|
@ -125,61 +125,62 @@ def init(args: PmbArgs, chroot: Chroot=Chroot.native(), usr_merge=UsrMerge.AUTO,
|
||||||
# When already initialized: just prepare the chroot
|
# When already initialized: just prepare the chroot
|
||||||
arch = chroot.arch
|
arch = chroot.arch
|
||||||
|
|
||||||
|
config = get_context().config
|
||||||
already_setup = str(chroot) in pmb.helpers.other.cache["pmb.chroot.init"]
|
already_setup = str(chroot) in pmb.helpers.other.cache["pmb.chroot.init"]
|
||||||
if already_setup:
|
if already_setup:
|
||||||
logging.warning(f"({chroot}) FIXME! init() called multiple times!")
|
logging.warning(f"({chroot}) FIXME! init() called multiple times!")
|
||||||
return
|
return
|
||||||
|
|
||||||
pmb.chroot.mount(args, chroot)
|
pmb.chroot.mount(chroot)
|
||||||
setup_qemu_emulation(args, chroot)
|
setup_qemu_emulation(chroot)
|
||||||
mark_in_chroot(args, chroot)
|
mark_in_chroot(chroot)
|
||||||
if (chroot / "bin/sh").is_symlink():
|
if (chroot / "bin/sh").is_symlink():
|
||||||
pmb.config.workdir.chroot_check_channel(args, chroot)
|
pmb.config.workdir.chroot_check_channel(chroot)
|
||||||
copy_resolv_conf(args, chroot)
|
copy_resolv_conf(chroot)
|
||||||
pmb.chroot.apk.update_repository_list(args, chroot, postmarketos_mirror)
|
pmb.chroot.apk.update_repository_list(chroot, postmarketos_mirror)
|
||||||
warn_if_chroot_is_outdated(args, chroot)
|
warn_if_chroot_is_outdated(chroot)
|
||||||
pmb.helpers.other.cache["pmb.chroot.init"][str(chroot)] = True
|
pmb.helpers.other.cache["pmb.chroot.init"][str(chroot)] = True
|
||||||
return
|
return
|
||||||
|
|
||||||
# Require apk-tools-static
|
# Require apk-tools-static
|
||||||
pmb.chroot.apk_static.init(args)
|
pmb.chroot.apk_static.init()
|
||||||
|
|
||||||
logging.info(f"({chroot}) install alpine-base")
|
logging.info(f"({chroot}) install alpine-base")
|
||||||
|
|
||||||
# Initialize cache
|
# Initialize cache
|
||||||
apk_cache = pmb.config.work / f"cache_apk_{arch}"
|
apk_cache = config.work / f"cache_apk_{arch}"
|
||||||
pmb.helpers.run.root(["ln", "-s", "-f", "/var/cache/apk",
|
pmb.helpers.run.root(["ln", "-s", "-f", "/var/cache/apk",
|
||||||
chroot / "etc/apk/cache"])
|
chroot / "etc/apk/cache"])
|
||||||
|
|
||||||
# Initialize /etc/apk/keys/, resolv.conf, repositories
|
# Initialize /etc/apk/keys/, resolv.conf, repositories
|
||||||
init_keys(args)
|
init_keys()
|
||||||
copy_resolv_conf(args, chroot)
|
copy_resolv_conf(chroot)
|
||||||
pmb.chroot.apk.update_repository_list(args, chroot, postmarketos_mirror)
|
pmb.chroot.apk.update_repository_list(chroot, postmarketos_mirror)
|
||||||
|
|
||||||
pmb.config.workdir.chroot_save_init(args, chroot)
|
pmb.config.workdir.chroot_save_init(chroot)
|
||||||
|
|
||||||
# Install alpine-base
|
# Install alpine-base
|
||||||
pmb.helpers.repo.update(args, arch)
|
pmb.helpers.repo.update(arch)
|
||||||
pkgs = ["alpine-base"]
|
pkgs = ["alpine-base"]
|
||||||
# install apk static in the native chroot so we can run it
|
# install apk static in the native chroot so we can run it
|
||||||
# we have a forked apk for systemd and this is the easiest
|
# we have a forked apk for systemd and this is the easiest
|
||||||
# way to install/run it.
|
# way to install/run it.
|
||||||
if chroot.type == ChrootType.NATIVE:
|
if chroot.type == ChrootType.NATIVE:
|
||||||
pkgs += ["apk-tools-static"]
|
pkgs += ["apk-tools-static"]
|
||||||
pmb.chroot.apk_static.run(args, ["--root", chroot.path,
|
pmb.chroot.apk_static.run(["--root", chroot.path,
|
||||||
"--cache-dir", apk_cache,
|
"--cache-dir", apk_cache,
|
||||||
"--initdb", "--arch", arch,
|
"--initdb", "--arch", arch,
|
||||||
"add"] + pkgs)
|
"add"] + pkgs)
|
||||||
|
|
||||||
# Merge /usr
|
# Merge /usr
|
||||||
if usr_merge is UsrMerge.AUTO and pmb.config.is_systemd_selected(args):
|
if usr_merge is UsrMerge.AUTO and pmb.config.is_systemd_selected(config):
|
||||||
usr_merge = UsrMerge.ON
|
usr_merge = UsrMerge.ON
|
||||||
if usr_merge is UsrMerge.ON:
|
if usr_merge is UsrMerge.ON:
|
||||||
init_usr_merge(args, chroot)
|
init_usr_merge(chroot)
|
||||||
|
|
||||||
# Building chroots: create "pmos" user, add symlinks to /home/pmos
|
# Building chroots: create "pmos" user, add symlinks to /home/pmos
|
||||||
if not chroot.type == ChrootType.ROOTFS:
|
if not chroot.type == ChrootType.ROOTFS:
|
||||||
pmb.chroot.root(args, ["adduser", "-D", "pmos", "-u",
|
pmb.chroot.root(["adduser", "-D", "pmos", "-u",
|
||||||
pmb.config.chroot_uid_user],
|
pmb.config.chroot_uid_user],
|
||||||
chroot)
|
chroot)
|
||||||
|
|
||||||
|
@ -187,11 +188,11 @@ def init(args: PmbArgs, chroot: Chroot=Chroot.native(), usr_merge=UsrMerge.AUTO,
|
||||||
for target, link_name in pmb.config.chroot_home_symlinks.items():
|
for target, link_name in pmb.config.chroot_home_symlinks.items():
|
||||||
link_dir = os.path.dirname(link_name)
|
link_dir = os.path.dirname(link_name)
|
||||||
if not os.path.exists(chroot / link_dir):
|
if not os.path.exists(chroot / link_dir):
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", link_dir], chroot)
|
pmb.chroot.user(["mkdir", "-p", link_dir], chroot)
|
||||||
if not os.path.exists(chroot / target):
|
if not os.path.exists(chroot / target):
|
||||||
pmb.chroot.root(args, ["mkdir", "-p", target], chroot)
|
pmb.chroot.root(["mkdir", "-p", target], chroot)
|
||||||
pmb.chroot.user(args, ["ln", "-s", target, link_name], chroot)
|
pmb.chroot.user(["ln", "-s", target, link_name], chroot)
|
||||||
pmb.chroot.root(args, ["chown", "pmos:pmos", target], chroot)
|
pmb.chroot.root(["chown", "pmos:pmos", target], chroot)
|
||||||
|
|
||||||
# Upgrade packages in the chroot, in case alpine-base, apk, etc. have been
|
# Upgrade packages in the chroot, in case alpine-base, apk, etc. have been
|
||||||
# built from source with pmbootstrap
|
# built from source with pmbootstrap
|
||||||
|
@ -201,6 +202,6 @@ def init(args: PmbArgs, chroot: Chroot=Chroot.native(), usr_merge=UsrMerge.AUTO,
|
||||||
if os.getenv("PMB_APK_FORCE_MISSING_REPOSITORIES") == "1":
|
if os.getenv("PMB_APK_FORCE_MISSING_REPOSITORIES") == "1":
|
||||||
command = ["--force-missing-repositories"] + command
|
command = ["--force-missing-repositories"] + command
|
||||||
|
|
||||||
pmb.chroot.root(args, ["apk"] + command, chroot)
|
pmb.chroot.root(["apk"] + command, chroot)
|
||||||
|
|
||||||
pmb.helpers.other.cache["pmb.chroot.init"][str(chroot)]
|
pmb.helpers.other.cache["pmb.chroot.init"][str(chroot)] = True
|
||||||
|
|
|
@ -6,26 +6,26 @@ import pmb.chroot.initfs_hooks
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
|
||||||
def build(args: PmbArgs, flavor, chroot: Chroot):
|
def build(args: PmbArgs, flavor, chroot: Chroot):
|
||||||
# Update mkinitfs and hooks
|
# Update mkinitfs and hooks
|
||||||
pmb.chroot.apk.install(args, ["postmarketos-mkinitfs"], chroot)
|
pmb.chroot.apk.install(["postmarketos-mkinitfs"], chroot)
|
||||||
pmb.chroot.initfs_hooks.update(args, chroot)
|
pmb.chroot.initfs_hooks.update(args, chroot)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
|
||||||
# Call mkinitfs
|
# Call mkinitfs
|
||||||
logging.info(f"({chroot}) mkinitfs {flavor}")
|
logging.info(f"({chroot}) mkinitfs {flavor}")
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
pmb.chroot.root(args, ["mkinitfs"], chroot)
|
pmb.chroot.root(["mkinitfs"], chroot)
|
||||||
else:
|
else:
|
||||||
release_file = (chroot / "usr/share/kernel" / flavor / "kernel.release")
|
release_file = (chroot / "usr/share/kernel" / flavor / "kernel.release")
|
||||||
with release_file.open() as handle:
|
with release_file.open() as handle:
|
||||||
release = handle.read().rstrip()
|
release = handle.read().rstrip()
|
||||||
pmb.chroot.root(args, ["mkinitfs", "-o",
|
pmb.chroot.root(["mkinitfs", "-o",
|
||||||
f"/boot/initramfs-{flavor}", release],
|
f"/boot/initramfs-{flavor}", release],
|
||||||
chroot)
|
chroot)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def extract(args: PmbArgs, flavor, chroot: Chroot, extra=False):
|
||||||
# Extraction folder
|
# Extraction folder
|
||||||
inside = "/tmp/initfs-extracted"
|
inside = "/tmp/initfs-extracted"
|
||||||
|
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
initfs_file = "/boot/initramfs"
|
initfs_file = "/boot/initramfs"
|
||||||
else:
|
else:
|
||||||
|
@ -53,7 +53,7 @@ def extract(args: PmbArgs, flavor, chroot: Chroot, extra=False):
|
||||||
" already exists."
|
" already exists."
|
||||||
" Do you want to overwrite it?"):
|
" Do you want to overwrite it?"):
|
||||||
raise RuntimeError("Aborted!")
|
raise RuntimeError("Aborted!")
|
||||||
pmb.chroot.root(args, ["rm", "-r", inside], chroot)
|
pmb.chroot.root(["rm", "-r", inside], chroot)
|
||||||
|
|
||||||
# Extraction script (because passing a file to stdin is not allowed
|
# Extraction script (because passing a file to stdin is not allowed
|
||||||
# in pmbootstrap's chroot/shell functions for security reasons)
|
# in pmbootstrap's chroot/shell functions for security reasons)
|
||||||
|
@ -71,7 +71,7 @@ def extract(args: PmbArgs, flavor, chroot: Chroot, extra=False):
|
||||||
["rm", "/tmp/_extract.sh", f"{inside}/_initfs"]
|
["rm", "/tmp/_extract.sh", f"{inside}/_initfs"]
|
||||||
]
|
]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, command, chroot)
|
pmb.chroot.root(command, chroot)
|
||||||
|
|
||||||
# Return outside path for logging
|
# Return outside path for logging
|
||||||
return outside
|
return outside
|
||||||
|
@ -82,8 +82,8 @@ def ls(args: PmbArgs, flavor, suffix, extra=False):
|
||||||
if extra:
|
if extra:
|
||||||
tmp = "/tmp/initfs-extra-extracted"
|
tmp = "/tmp/initfs-extra-extracted"
|
||||||
extract(args, flavor, suffix, extra)
|
extract(args, flavor, suffix, extra)
|
||||||
pmb.chroot.root(args, ["ls", "-lahR", "."], suffix, Path(tmp), "stdout")
|
pmb.chroot.root(["ls", "-lahR", "."], suffix, Path(tmp), "stdout")
|
||||||
pmb.chroot.root(args, ["rm", "-r", tmp], suffix)
|
pmb.chroot.root(["rm", "-r", tmp], suffix)
|
||||||
|
|
||||||
|
|
||||||
def frontend(args: PmbArgs):
|
def frontend(args: PmbArgs):
|
||||||
|
@ -108,12 +108,12 @@ def frontend(args: PmbArgs):
|
||||||
|
|
||||||
# Handle hook actions
|
# Handle hook actions
|
||||||
elif action == "hook_ls":
|
elif action == "hook_ls":
|
||||||
pmb.chroot.initfs_hooks.ls(args, chroot)
|
pmb.chroot.initfs_hooks.ls(chroot)
|
||||||
else:
|
else:
|
||||||
if action == "hook_add":
|
if action == "hook_add":
|
||||||
pmb.chroot.initfs_hooks.add(args, args.hook, chroot)
|
pmb.chroot.initfs_hooks.add(args.hook, chroot)
|
||||||
elif action == "hook_del":
|
elif action == "hook_del":
|
||||||
pmb.chroot.initfs_hooks.delete(args, args.hook, chroot)
|
pmb.chroot.initfs_hooks.delete(args.hook, chroot)
|
||||||
|
|
||||||
# Rebuild the initfs after adding/removing a hook
|
# Rebuild the initfs after adding/removing a hook
|
||||||
build(args, flavor, chroot)
|
build(args, flavor, chroot)
|
||||||
|
|
|
@ -6,11 +6,11 @@ from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def list_chroot(args: PmbArgs, suffix: Chroot, remove_prefix=True):
|
def list_chroot(suffix: Chroot, remove_prefix=True):
|
||||||
ret = []
|
ret = []
|
||||||
prefix = pmb.config.initfs_hook_prefix
|
prefix = pmb.config.initfs_hook_prefix
|
||||||
for pkgname in pmb.chroot.apk.installed(suffix).keys():
|
for pkgname in pmb.chroot.apk.installed(suffix).keys():
|
||||||
|
@ -22,41 +22,41 @@ def list_chroot(args: PmbArgs, suffix: Chroot, remove_prefix=True):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def list_aports(args: PmbArgs):
|
def list_aports():
|
||||||
ret = []
|
ret = []
|
||||||
prefix = pmb.config.initfs_hook_prefix
|
prefix = pmb.config.initfs_hook_prefix
|
||||||
for path in glob.glob(f"{args.aports}/*/{prefix}*"):
|
for path in glob.glob(f"{get_context().config.aports}/*/{prefix}*"):
|
||||||
ret.append(os.path.basename(path)[len(prefix):])
|
ret.append(os.path.basename(path)[len(prefix):])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def ls(args: PmbArgs, suffix: Chroot):
|
def ls(suffix: Chroot):
|
||||||
hooks_chroot = list_chroot(args, suffix)
|
hooks_chroot = list_chroot(suffix)
|
||||||
hooks_aports = list_aports(args)
|
hooks_aports = list_aports()
|
||||||
|
|
||||||
for hook in hooks_aports:
|
for hook in hooks_aports:
|
||||||
line = f"* {hook} ({'' if hook in hooks_chroot else 'not '}installed)"
|
line = f"* {hook} ({'' if hook in hooks_chroot else 'not '}installed)"
|
||||||
logging.info(line)
|
logging.info(line)
|
||||||
|
|
||||||
|
|
||||||
def add(args: PmbArgs, hook, suffix: Chroot):
|
def add(hook, suffix: Chroot):
|
||||||
if hook not in list_aports(args):
|
if hook not in list_aports():
|
||||||
raise RuntimeError("Invalid hook name!"
|
raise RuntimeError("Invalid hook name!"
|
||||||
" Run 'pmbootstrap initfs hook_ls'"
|
" Run 'pmbootstrap initfs hook_ls'"
|
||||||
" to get a list of all hooks.")
|
" to get a list of all hooks.")
|
||||||
prefix = pmb.config.initfs_hook_prefix
|
prefix = pmb.config.initfs_hook_prefix
|
||||||
pmb.chroot.apk.install(args, [f"{prefix}{hook}"], suffix)
|
pmb.chroot.apk.install([f"{prefix}{hook}"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def delete(args: PmbArgs, hook, suffix: Chroot):
|
def delete(hook, suffix: Chroot):
|
||||||
if hook not in list_chroot(args, suffix):
|
if hook not in list_chroot(suffix):
|
||||||
raise RuntimeError("There is no such hook installed!")
|
raise RuntimeError("There is no such hook installed!")
|
||||||
prefix = pmb.config.initfs_hook_prefix
|
prefix = pmb.config.initfs_hook_prefix
|
||||||
pmb.chroot.root(args, ["apk", "del", f"{prefix}{hook}"], suffix)
|
pmb.chroot.root(["apk", "del", f"{prefix}{hook}"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def update(args: PmbArgs, suffix: Chroot):
|
def update(args: PmbArgs, suffix: Chroot):
|
||||||
"""
|
"""
|
||||||
Rebuild and update all hooks that are out of date
|
Rebuild and update all hooks that are out of date
|
||||||
"""
|
"""
|
||||||
pmb.chroot.apk.install(args, list_chroot(args, suffix, False), suffix)
|
pmb.chroot.apk.install(list_chroot(suffix, False), suffix)
|
||||||
|
|
|
@ -5,13 +5,14 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
import pmb.helpers.run
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def create_device_nodes(args: PmbArgs, chroot: Chroot):
|
def create_device_nodes(chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
Create device nodes for null, zero, full, random, urandom in the chroot.
|
Create device nodes for null, zero, full, random, urandom in the chroot.
|
||||||
"""
|
"""
|
||||||
|
@ -48,7 +49,7 @@ def create_device_nodes(args: PmbArgs, chroot: Chroot):
|
||||||
raise RuntimeError(f"Failed to create device nodes in the '{chroot}' chroot.")
|
raise RuntimeError(f"Failed to create device nodes in the '{chroot}' chroot.")
|
||||||
|
|
||||||
|
|
||||||
def mount_dev_tmpfs(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def mount_dev_tmpfs(chroot: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
Mount tmpfs inside the chroot's dev folder to make sure we can create
|
Mount tmpfs inside the chroot's dev folder to make sure we can create
|
||||||
device nodes, even if the filesystem of the work folder does not support
|
device nodes, even if the filesystem of the work folder does not support
|
||||||
|
@ -70,22 +71,22 @@ def mount_dev_tmpfs(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
||||||
pmb.helpers.run.root(["mount", "-t", "tmpfs",
|
pmb.helpers.run.root(["mount", "-t", "tmpfs",
|
||||||
"-o", "nodev,nosuid,noexec",
|
"-o", "nodev,nosuid,noexec",
|
||||||
"tmpfs", dev / "shm"])
|
"tmpfs", dev / "shm"])
|
||||||
create_device_nodes(args, chroot)
|
create_device_nodes(chroot)
|
||||||
|
|
||||||
# Setup /dev/fd as a symlink
|
# Setup /dev/fd as a symlink
|
||||||
pmb.helpers.run.root(["ln", "-sf", "/proc/self/fd", f"{dev}/"])
|
pmb.helpers.run.root(["ln", "-sf", "/proc/self/fd", f"{dev}/"])
|
||||||
|
|
||||||
|
|
||||||
def mount(args: PmbArgs, chroot: Chroot=Chroot.native()):
|
def mount(chroot: Chroot):
|
||||||
# Mount tmpfs as the chroot's /dev
|
# Mount tmpfs as the chroot's /dev
|
||||||
mount_dev_tmpfs(args, chroot)
|
mount_dev_tmpfs(chroot)
|
||||||
|
|
||||||
# Get all mountpoints
|
# Get all mountpoints
|
||||||
arch = pmb.parse.arch.from_chroot_suffix(args, chroot)
|
arch = chroot.arch
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
mountpoints: Dict[Path, Path] = {}
|
mountpoints: Dict[Path, Path] = {}
|
||||||
for src_template, target_template in pmb.config.chroot_mount_bind.items():
|
for src_template, target_template in pmb.config.chroot_mount_bind.items():
|
||||||
src_template = src_template.replace("$WORK", os.fspath(pmb.config.work))
|
src_template = src_template.replace("$WORK", os.fspath(get_context().config.work))
|
||||||
src_template = src_template.replace("$ARCH", arch)
|
src_template = src_template.replace("$ARCH", arch)
|
||||||
src_template = src_template.replace("$CHANNEL", channel)
|
src_template = src_template.replace("$CHANNEL", channel)
|
||||||
mountpoints[Path(src_template)] = Path(target_template)
|
mountpoints[Path(src_template)] = Path(target_template)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import os
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.install
|
import pmb.install
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ def kernel_flavor_installed(args: PmbArgs, chroot: Chroot, autoinstall=True):
|
||||||
if autoinstall:
|
if autoinstall:
|
||||||
packages = ([f"device-{args.device}"] +
|
packages = ([f"device-{args.device}"] +
|
||||||
pmb.install.get_kernel_package(args, args.device))
|
pmb.install.get_kernel_package(args, args.device))
|
||||||
pmb.chroot.apk.install(args, packages, chroot)
|
pmb.chroot.apk.install(packages, chroot)
|
||||||
|
|
||||||
glob_result = list((chroot / "usr/share/kernel").glob("*"))
|
glob_result = list((chroot / "usr/share/kernel").glob("*"))
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ def tempfolder(args: PmbArgs, path: Path, chroot: Chroot=Chroot.native()):
|
||||||
:returns: the path
|
:returns: the path
|
||||||
"""
|
"""
|
||||||
if chroot / path:
|
if chroot / path:
|
||||||
pmb.chroot.root(args, ["rm", "-r", path])
|
pmb.chroot.root(["rm", "-r", path])
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", path])
|
pmb.chroot.user(["mkdir", "-p", path])
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,4 +73,4 @@ def copy_xauthority(args: PmbArgs):
|
||||||
if os.path.exists(copy):
|
if os.path.exists(copy):
|
||||||
pmb.helpers.run.root(["rm", copy])
|
pmb.helpers.run.root(["rm", copy])
|
||||||
pmb.helpers.run.root(["cp", original, copy])
|
pmb.helpers.run.root(["cp", original, copy])
|
||||||
pmb.chroot.root(args, ["chown", "pmos:pmos", "/home/pmos/.Xauthority"])
|
pmb.chroot.root(["chown", "pmos:pmos", "/home/pmos/.Xauthority"])
|
||||||
|
|
|
@ -11,7 +11,7 @@ import pmb.chroot.binfmt
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.run_core
|
import pmb.helpers.run_core
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
from pmb.core.types import Env, PathString, PmbArgs
|
from pmb.types import Env, PathString, PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def executables_absolute_path():
|
def executables_absolute_path():
|
||||||
|
@ -29,7 +29,7 @@ def executables_absolute_path():
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def root(args: PmbArgs, cmd: Sequence[PathString], chroot: Chroot=Chroot.native(), working_dir: PurePath=PurePath("/"), output="log",
|
def root(cmd: Sequence[PathString], chroot: Chroot=Chroot.native(), working_dir: PurePath=PurePath("/"), output="log",
|
||||||
output_return=False, check=None, env={},
|
output_return=False, check=None, env={},
|
||||||
disable_timeout=False, add_proxy_env_vars=True):
|
disable_timeout=False, add_proxy_env_vars=True):
|
||||||
"""
|
"""
|
||||||
|
@ -88,7 +88,7 @@ def root(args: PmbArgs, cmd: Sequence[PathString], chroot: Chroot=Chroot.native(
|
||||||
disable_timeout)
|
disable_timeout)
|
||||||
|
|
||||||
|
|
||||||
def user(args: PmbArgs, cmd, chroot: Chroot=Chroot.native(), working_dir: Path = Path("/"), output="log",
|
def user(cmd, chroot: Chroot=Chroot.native(), working_dir: Path = Path("/"), output="log",
|
||||||
output_return=False, check=None, env={}):
|
output_return=False, check=None, env={}):
|
||||||
"""
|
"""
|
||||||
Run a command inside a chroot as "user". We always use the BusyBox
|
Run a command inside a chroot as "user". We always use the BusyBox
|
||||||
|
@ -109,19 +109,19 @@ def user(args: PmbArgs, cmd, chroot: Chroot=Chroot.native(), working_dir: Path =
|
||||||
|
|
||||||
flat_cmd = pmb.helpers.run_core.flat_cmd(cmd, env=env)
|
flat_cmd = pmb.helpers.run_core.flat_cmd(cmd, env=env)
|
||||||
cmd = ["busybox", "su", "pmos", "-c", flat_cmd]
|
cmd = ["busybox", "su", "pmos", "-c", flat_cmd]
|
||||||
return pmb.chroot.root(args, cmd, chroot, working_dir, output,
|
return pmb.chroot.root(cmd, chroot, working_dir, output,
|
||||||
output_return, check, {},
|
output_return, check, {},
|
||||||
add_proxy_env_vars=False)
|
add_proxy_env_vars=False)
|
||||||
|
|
||||||
|
|
||||||
def exists(args: PmbArgs, username, chroot: Chroot=Chroot.native()):
|
def exists(username, chroot: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
Checks if username exists in the system
|
Checks if username exists in the system
|
||||||
|
|
||||||
:param username: User name
|
:param username: User name
|
||||||
:returns: bool
|
:returns: bool
|
||||||
"""
|
"""
|
||||||
output = pmb.chroot.root(args, ["getent", "passwd", username],
|
output = pmb.chroot.root(["getent", "passwd", username],
|
||||||
chroot, output_return=True, check=False)
|
chroot, output_return=True, check=False)
|
||||||
return len(output) > 0
|
return len(output) > 0
|
||||||
|
|
||||||
|
|
|
@ -5,24 +5,24 @@ import socket
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
import pmb.install.losetup
|
import pmb.install.losetup
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType, get_context
|
||||||
|
|
||||||
|
|
||||||
def kill_adb(args: PmbArgs):
|
def kill_adb():
|
||||||
"""
|
"""
|
||||||
Kill adb daemon if it's running.
|
Kill adb daemon if it's running.
|
||||||
"""
|
"""
|
||||||
port = 5038
|
port = 5038
|
||||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
||||||
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
||||||
pmb.chroot.root(args, ["adb", "-P", str(port), "kill-server"])
|
pmb.chroot.root(["adb", "-P", str(port), "kill-server"])
|
||||||
|
|
||||||
|
|
||||||
def kill_sccache(args: PmbArgs):
|
def kill_sccache():
|
||||||
"""
|
"""
|
||||||
Kill sccache daemon if it's running. Unlike ccache it automatically spawns
|
Kill sccache daemon if it's running. Unlike ccache it automatically spawns
|
||||||
a daemon when you call it and exits after some time of inactivity.
|
a daemon when you call it and exits after some time of inactivity.
|
||||||
|
@ -30,17 +30,17 @@ def kill_sccache(args: PmbArgs):
|
||||||
port = 4226
|
port = 4226
|
||||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
||||||
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
||||||
pmb.chroot.root(args, ["sccache", "--stop-server"])
|
pmb.chroot.root(["sccache", "--stop-server"])
|
||||||
|
|
||||||
|
|
||||||
def shutdown_cryptsetup_device(args: PmbArgs, name: str):
|
def shutdown_cryptsetup_device(name: str):
|
||||||
"""
|
"""
|
||||||
:param name: cryptsetup device name, usually "pm_crypt" in pmbootstrap
|
:param name: cryptsetup device name, usually "pm_crypt" in pmbootstrap
|
||||||
"""
|
"""
|
||||||
if not (Chroot.native() / "dev/mapper" / name).exists():
|
if not (Chroot.native() / "dev/mapper" / name).exists():
|
||||||
return
|
return
|
||||||
pmb.chroot.apk.install(args, ["cryptsetup"])
|
pmb.chroot.apk.install(["cryptsetup"], Chroot.native())
|
||||||
status = pmb.chroot.root(args, ["cryptsetup", "status", name],
|
status = pmb.chroot.root(["cryptsetup", "status", name],
|
||||||
output_return=True, check=False)
|
output_return=True, check=False)
|
||||||
if not status:
|
if not status:
|
||||||
logging.warning("WARNING: Failed to run cryptsetup to get the status"
|
logging.warning("WARNING: Failed to run cryptsetup to get the status"
|
||||||
|
@ -49,31 +49,31 @@ def shutdown_cryptsetup_device(args: PmbArgs, name: str):
|
||||||
return
|
return
|
||||||
|
|
||||||
if status.startswith("/dev/mapper/" + name + " is active."):
|
if status.startswith("/dev/mapper/" + name + " is active."):
|
||||||
pmb.chroot.root(args, ["cryptsetup", "luksClose", name])
|
pmb.chroot.root(["cryptsetup", "luksClose", name])
|
||||||
elif status.startswith("/dev/mapper/" + name + " is inactive."):
|
elif status.startswith("/dev/mapper/" + name + " is inactive."):
|
||||||
# When "cryptsetup status" fails, the device is not mounted and we
|
# When "cryptsetup status" fails, the device is not mounted and we
|
||||||
# have a left over file (#83)
|
# have a left over file (#83)
|
||||||
pmb.chroot.root(args, ["rm", "/dev/mapper/" + name])
|
pmb.chroot.root(["rm", "/dev/mapper/" + name])
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Failed to parse 'cryptsetup status' output!")
|
raise RuntimeError("Failed to parse 'cryptsetup status' output!")
|
||||||
|
|
||||||
|
|
||||||
def shutdown(args: PmbArgs, only_install_related=False):
|
def shutdown(args: PmbArgs, only_install_related=False):
|
||||||
# Stop daemons
|
# Stop daemons
|
||||||
kill_adb(args)
|
kill_adb()
|
||||||
kill_sccache(args)
|
kill_sccache()
|
||||||
|
|
||||||
chroot = Chroot.native()
|
chroot = Chroot.native()
|
||||||
|
|
||||||
# Umount installation-related paths (order is important!)
|
# Umount installation-related paths (order is important!)
|
||||||
pmb.helpers.mount.umount_all(chroot / "mnt/install")
|
pmb.helpers.mount.umount_all(chroot / "mnt/install")
|
||||||
shutdown_cryptsetup_device(args, "pm_crypt")
|
shutdown_cryptsetup_device("pm_crypt")
|
||||||
|
|
||||||
# Umount all losetup mounted images
|
# Umount all losetup mounted images
|
||||||
if pmb.helpers.mount.ismount(chroot / "dev/loop-control"):
|
if pmb.helpers.mount.ismount(chroot / "dev/loop-control"):
|
||||||
for path_outside in (chroot / "/home/pmos/rootfs").glob("*.img"):
|
for path_outside in (chroot / "/home/pmos/rootfs").glob("*.img"):
|
||||||
path = path_outside.relative_to(chroot.path)
|
path = path_outside.relative_to(chroot.path)
|
||||||
pmb.install.losetup.umount(args, path)
|
pmb.install.losetup.umount(path)
|
||||||
|
|
||||||
# Umount device rootfs and installer chroots
|
# Umount device rootfs and installer chroots
|
||||||
for chroot_type in [ChrootType.ROOTFS, ChrootType.INSTALLER]:
|
for chroot_type in [ChrootType.ROOTFS, ChrootType.INSTALLER]:
|
||||||
|
@ -86,14 +86,14 @@ def shutdown(args: PmbArgs, only_install_related=False):
|
||||||
# the chroots, but we want it gone afterwards (e.g. when the chroot
|
# the chroots, but we want it gone afterwards (e.g. when the chroot
|
||||||
# contents get copied to a rootfs / installer image, or if creating an
|
# contents get copied to a rootfs / installer image, or if creating an
|
||||||
# android recovery zip from its contents).
|
# android recovery zip from its contents).
|
||||||
for marker in pmb.config.work.glob("chroot_*/in-pmbootstrap"):
|
for marker in get_context().config.work.glob("chroot_*/in-pmbootstrap"):
|
||||||
pmb.helpers.run.root(["rm", marker])
|
pmb.helpers.run.root(["rm", marker])
|
||||||
|
|
||||||
if not only_install_related:
|
if not only_install_related:
|
||||||
# Umount all folders inside work dir
|
# Umount all folders inside work dir
|
||||||
# The folders are explicitly iterated over, so folders symlinked inside
|
# The folders are explicitly iterated over, so folders symlinked inside
|
||||||
# work dir get umounted as well (used in test_pkgrel_bump.py, #1595)
|
# work dir get umounted as well (used in test_pkgrel_bump.py, #1595)
|
||||||
for path in pmb.config.work.glob("*"):
|
for path in get_context().config.work.glob("*"):
|
||||||
pmb.helpers.mount.umount_all(path)
|
pmb.helpers.mount.umount_all(path)
|
||||||
|
|
||||||
# Clean up the rest
|
# Clean up the rest
|
||||||
|
|
|
@ -7,11 +7,11 @@ import os
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
import pmb.config.workdir
|
import pmb.config.workdir
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
|
@ -32,7 +32,7 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
:param rust: Remove rust related caches
|
:param rust: Remove rust related caches
|
||||||
:param netboot: Remove images for netboot
|
:param netboot: Remove images for netboot
|
||||||
|
|
||||||
NOTE: This function gets called in pmb/config/init.py, with only pmb.config.work
|
NOTE: This function gets called in pmb/config/init.py, with only get_context().config.work
|
||||||
and args.device set!
|
and args.device set!
|
||||||
"""
|
"""
|
||||||
# Get current work folder size
|
# Get current work folder size
|
||||||
|
@ -50,7 +50,7 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
|
|
||||||
pmb.chroot.shutdown(args)
|
pmb.chroot.shutdown(args)
|
||||||
|
|
||||||
# Deletion patterns for folders inside pmb.config.work
|
# Deletion patterns for folders inside get_context().config.work
|
||||||
patterns = list(Chroot.iter_patterns())
|
patterns = list(Chroot.iter_patterns())
|
||||||
if pkgs_local:
|
if pkgs_local:
|
||||||
patterns += ["packages"]
|
patterns += ["packages"]
|
||||||
|
@ -66,7 +66,7 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
# Delete everything matching the patterns
|
# Delete everything matching the patterns
|
||||||
for pattern in patterns:
|
for pattern in patterns:
|
||||||
logging.debug(f"Deleting {pattern}")
|
logging.debug(f"Deleting {pattern}")
|
||||||
pattern = os.path.realpath(f"{pmb.config.work}/{pattern}")
|
pattern = os.path.realpath(f"{get_context().config.work}/{pattern}")
|
||||||
matches = glob.glob(pattern)
|
matches = glob.glob(pattern)
|
||||||
for match in matches:
|
for match in matches:
|
||||||
if (not confirm or
|
if (not confirm or
|
||||||
|
@ -87,8 +87,8 @@ def zap(args: PmbArgs, confirm=True, dry=False, pkgs_local=False, http=False,
|
||||||
|
|
||||||
|
|
||||||
def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
if not os.path.exists(f"{pmb.config.work}/packages/{channel}"):
|
if not os.path.exists(f"{get_context().config.work}/packages/{channel}"):
|
||||||
return
|
return
|
||||||
|
|
||||||
question = "Remove binary packages that are newer than the corresponding" \
|
question = "Remove binary packages that are newer than the corresponding" \
|
||||||
|
@ -97,7 +97,7 @@ def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
return
|
return
|
||||||
|
|
||||||
reindex = False
|
reindex = False
|
||||||
for apkindex_path in (pmb.config.work / "packages" / channel).glob("*/APKINDEX.tar.gz"):
|
for apkindex_path in (get_context().config.work / "packages" / channel).glob("*/APKINDEX.tar.gz"):
|
||||||
# Delete packages without same version in aports
|
# Delete packages without same version in aports
|
||||||
blocks = pmb.parse.apkindex.parse_blocks(apkindex_path)
|
blocks = pmb.parse.apkindex.parse_blocks(apkindex_path)
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
|
@ -108,7 +108,7 @@ def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
|
|
||||||
# Apk path
|
# Apk path
|
||||||
apk_path_short = f"{arch}/{pkgname}-{version}.apk"
|
apk_path_short = f"{arch}/{pkgname}-{version}.apk"
|
||||||
apk_path = f"{pmb.config.work}/packages/{channel}/{apk_path_short}"
|
apk_path = f"{get_context().config.work}/packages/{channel}/{apk_path_short}"
|
||||||
if not os.path.exists(apk_path):
|
if not os.path.exists(apk_path):
|
||||||
logging.info("WARNING: Package mentioned in index not"
|
logging.info("WARNING: Package mentioned in index not"
|
||||||
f" found: {apk_path_short}")
|
f" found: {apk_path_short}")
|
||||||
|
@ -140,7 +140,7 @@ def zap_pkgs_local_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
|
|
||||||
def zap_pkgs_online_mismatch(args: PmbArgs, confirm=True, dry=False):
|
def zap_pkgs_online_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
# Check whether we need to do anything
|
# Check whether we need to do anything
|
||||||
paths = glob.glob(f"{pmb.config.work}/cache_apk_*")
|
paths = glob.glob(f"{get_context().config.work}/cache_apk_*")
|
||||||
if not len(paths):
|
if not len(paths):
|
||||||
return
|
return
|
||||||
if (confirm and not pmb.helpers.cli.confirm(args,
|
if (confirm and not pmb.helpers.cli.confirm(args,
|
||||||
|
@ -162,4 +162,4 @@ def zap_pkgs_online_mismatch(args: PmbArgs, confirm=True, dry=False):
|
||||||
# Clean the cache with apk
|
# Clean the cache with apk
|
||||||
logging.info(f"({suffix}) apk -v cache clean")
|
logging.info(f"({suffix}) apk -v cache clean")
|
||||||
if not dry:
|
if not dry:
|
||||||
pmb.chroot.root(args, ["apk", "-v", "cache", "clean"], suffix)
|
pmb.chroot.root(["apk", "-v", "cache", "clean"], suffix)
|
||||||
|
|
|
@ -6,7 +6,7 @@ from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
@ -135,9 +135,9 @@ def copy_git_repo_to_chroot(args: PmbArgs, topdir):
|
||||||
f"{tarball_path}.files"], topdir)
|
f"{tarball_path}.files"], topdir)
|
||||||
|
|
||||||
ci_dir = Path("/home/pmos/ci")
|
ci_dir = Path("/home/pmos/ci")
|
||||||
pmb.chroot.user(args, ["rm", "-rf", ci_dir])
|
pmb.chroot.user(["rm", "-rf", ci_dir])
|
||||||
pmb.chroot.user(args, ["mkdir", ci_dir])
|
pmb.chroot.user(["mkdir", ci_dir])
|
||||||
pmb.chroot.user(args, ["tar", "-xf", "/tmp/git.tar.gz"],
|
pmb.chroot.user(["tar", "-xf", "/tmp/git.tar.gz"],
|
||||||
working_dir=ci_dir)
|
working_dir=ci_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ def run_scripts(args: PmbArgs, topdir, scripts):
|
||||||
repo_copied = True
|
repo_copied = True
|
||||||
|
|
||||||
env = {"TESTUSER": "pmos"}
|
env = {"TESTUSER": "pmos"}
|
||||||
rc = pmb.chroot.root(args, [script_path], check=False, env=env,
|
rc = pmb.chroot.root([script_path], check=False, env=env,
|
||||||
working_dir=Path("/home/pmos/ci"),
|
working_dir=Path("/home/pmos/ci"),
|
||||||
output="tui")
|
output="tui")
|
||||||
if rc:
|
if rc:
|
||||||
|
|
|
@ -6,7 +6,7 @@ import enum
|
||||||
from typing import Generator, Optional
|
from typing import Generator, Optional
|
||||||
from pathlib import Path, PosixPath, PurePosixPath
|
from pathlib import Path, PosixPath, PurePosixPath
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
from pmb.helpers import frontend
|
from pmb.helpers import frontend
|
||||||
|
|
||||||
from .base import Command
|
from .base import Command
|
||||||
|
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
||||||
from typing import Generator, List, Optional
|
from typing import Generator, List, Optional
|
||||||
from pathlib import Path, PosixPath, PurePosixPath
|
from pathlib import Path, PosixPath, PurePosixPath
|
||||||
from pmb import commands
|
from pmb import commands
|
||||||
from pmb.core.types import PathString
|
from pmb.types import PathString
|
||||||
from pmb.helpers import run
|
from pmb.helpers import run
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb import config
|
from pmb import config
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pmb.core.types import AportGenEntry, PathString
|
from pmb.types import AportGenEntry, PathString
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
import sys
|
import sys
|
||||||
from typing import Dict, List, Sequence, TypedDict
|
from typing import Dict, List, Sequence, TypedDict
|
||||||
|
@ -14,7 +14,6 @@ from typing import Dict, List, Sequence, TypedDict
|
||||||
# FIXME (#2324): this sucks, we should re-organise this and not rely on "lifting"
|
# FIXME (#2324): this sucks, we should re-organise this and not rely on "lifting"
|
||||||
# this functions this way
|
# this functions this way
|
||||||
from pmb.config.load import load, sanity_checks, save
|
from pmb.config.load import load, sanity_checks, save
|
||||||
from pmb.config.merge_with_args import merge_with_args
|
|
||||||
from pmb.config.sudo import which_sudo
|
from pmb.config.sudo import which_sudo
|
||||||
from pmb.config.other import is_systemd_selected
|
from pmb.config.other import is_systemd_selected
|
||||||
|
|
||||||
|
@ -25,7 +24,6 @@ from pmb.config.other import is_systemd_selected
|
||||||
pmb_src: Path = Path(Path(__file__) / "../../..").resolve()
|
pmb_src: Path = Path(Path(__file__) / "../../..").resolve()
|
||||||
apk_keys_path: Path = (pmb_src / "pmb/data/keys")
|
apk_keys_path: Path = (pmb_src / "pmb/data/keys")
|
||||||
arch_native = pmb.parse.arch.alpine_native()
|
arch_native = pmb.parse.arch.alpine_native()
|
||||||
work: Path
|
|
||||||
|
|
||||||
# apk-tools minimum version
|
# apk-tools minimum version
|
||||||
# https://pkgs.alpinelinux.org/packages?name=apk-tools&branch=edge
|
# https://pkgs.alpinelinux.org/packages?name=apk-tools&branch=edge
|
||||||
|
@ -77,15 +75,6 @@ def sudo(cmd: Sequence[PathString]) -> Sequence[PathString]:
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
def work_dir(_work: Path) -> None:
|
|
||||||
"""Set the work directory. This is used in the main program to set the
|
|
||||||
work directory before any other code is run. It is not meant to be used
|
|
||||||
anywhere else."""
|
|
||||||
global work
|
|
||||||
if "work" in globals():
|
|
||||||
raise RuntimeError("work_dir() called multiple times!")
|
|
||||||
work = _work
|
|
||||||
|
|
||||||
# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
|
# Keys saved in the config file (mostly what we ask in 'pmbootstrap init')
|
||||||
config_keys = [
|
config_keys = [
|
||||||
"aports",
|
"aports",
|
||||||
|
@ -116,42 +105,7 @@ config_keys = [
|
||||||
"work",
|
"work",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Config file/commandline default values
|
|
||||||
# $WORK gets replaced with the actual value for pmb.config.work (which may be
|
|
||||||
# overridden on the commandline)
|
|
||||||
defaults = {
|
defaults = {
|
||||||
# This first chunk matches config_keys
|
|
||||||
"aports": "$WORK/cache_git/pmaports",
|
|
||||||
"boot_size": "256",
|
|
||||||
"build_default_device_arch": False,
|
|
||||||
"build_pkgs_on_install": True,
|
|
||||||
"ccache_size": "5G",
|
|
||||||
"device": "qemu-amd64",
|
|
||||||
"extra_packages": "none",
|
|
||||||
"extra_space": "0",
|
|
||||||
"hostname": "",
|
|
||||||
"is_default_channel": True,
|
|
||||||
"jobs": str(multiprocessing.cpu_count() + 1),
|
|
||||||
"kernel": "stable",
|
|
||||||
"keymap": "",
|
|
||||||
"locale": "en_US.UTF-8",
|
|
||||||
# NOTE: mirrors use http by default to leverage caching
|
|
||||||
"mirror_alpine": "http://dl-cdn.alpinelinux.org/alpine/",
|
|
||||||
# NOTE: mirrors_postmarketos variable type is supposed to be
|
|
||||||
# comma-separated string, not a python list or any other type!
|
|
||||||
"mirrors_postmarketos": "http://mirror.postmarketos.org/postmarketos/",
|
|
||||||
"qemu_redir_stdio": False,
|
|
||||||
"ssh_key_glob": "~/.ssh/id_*.pub",
|
|
||||||
"ssh_keys": False,
|
|
||||||
"sudo_timer": False,
|
|
||||||
"systemd": "default",
|
|
||||||
"timezone": "GMT",
|
|
||||||
"ui": "console",
|
|
||||||
"ui_extras": False,
|
|
||||||
"user": "user",
|
|
||||||
"work": os.path.expanduser("~") + "/.local/var/pmbootstrap",
|
|
||||||
|
|
||||||
# These values are not part of config_keys
|
|
||||||
"cipher": "aes-xts-plain64",
|
"cipher": "aes-xts-plain64",
|
||||||
"config": (os.environ.get('XDG_CONFIG_HOME') or
|
"config": (os.environ.get('XDG_CONFIG_HOME') or
|
||||||
os.path.expanduser("~/.config")) + "/pmbootstrap.cfg",
|
os.path.expanduser("~/.config")) + "/pmbootstrap.cfg",
|
||||||
|
@ -223,7 +177,7 @@ chroot_path = ":".join([
|
||||||
chroot_host_path = os.environ["PATH"] + ":/usr/sbin/"
|
chroot_host_path = os.environ["PATH"] + ":/usr/sbin/"
|
||||||
|
|
||||||
# Folders that get mounted inside the chroot
|
# Folders that get mounted inside the chroot
|
||||||
# $WORK gets replaced with pmb.config.work
|
# $WORK gets replaced with get_context().config.work
|
||||||
# $ARCH gets replaced with the chroot architecture (eg. x86_64, armhf)
|
# $ARCH gets replaced with the chroot architecture (eg. x86_64, armhf)
|
||||||
# $CHANNEL gets replaced with the release channel (e.g. edge, v21.03)
|
# $CHANNEL gets replaced with the release channel (e.g. edge, v21.03)
|
||||||
# Use no more than one dir after /mnt/pmbootstrap, see remove_mnt_pmbootstrap.
|
# Use no more than one dir after /mnt/pmbootstrap, see remove_mnt_pmbootstrap.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.core.chroot import Chroot
|
from pmb.core.chroot import Chroot
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import glob
|
import glob
|
||||||
|
@ -11,7 +12,7 @@ from typing import Any, List
|
||||||
import pmb.aportgen
|
import pmb.aportgen
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
|
@ -67,7 +68,7 @@ def ask_for_work_path(args: PmbArgs):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
work = os.path.expanduser(pmb.helpers.cli.ask(
|
work = os.path.expanduser(pmb.helpers.cli.ask(
|
||||||
"Work path", None, pmb.config.work, False))
|
"Work path", None, get_context().config.work, False))
|
||||||
work = os.path.realpath(work)
|
work = os.path.realpath(work)
|
||||||
exists = os.path.exists(work)
|
exists = os.path.exists(work)
|
||||||
|
|
||||||
|
@ -107,7 +108,7 @@ def ask_for_channel(args: PmbArgs):
|
||||||
|
|
||||||
:returns: channel name (e.g. "edge", "v21.03")
|
:returns: channel name (e.g. "edge", "v21.03")
|
||||||
"""
|
"""
|
||||||
channels_cfg = pmb.helpers.git.parse_channels_cfg(args)
|
channels_cfg = pmb.helpers.git.parse_channels_cfg(get_context().config.aports)
|
||||||
count = len(channels_cfg["channels"])
|
count = len(channels_cfg["channels"])
|
||||||
|
|
||||||
# List channels
|
# List channels
|
||||||
|
@ -123,7 +124,7 @@ def ask_for_channel(args: PmbArgs):
|
||||||
# Otherwise, if valid: channel from pmaports.cfg of current branch
|
# Otherwise, if valid: channel from pmaports.cfg of current branch
|
||||||
# The actual channel name is not saved in pmbootstrap.cfg, because then we
|
# The actual channel name is not saved in pmbootstrap.cfg, because then we
|
||||||
# would need to sync it with what is checked out in pmaports.git.
|
# would need to sync it with what is checked out in pmaports.git.
|
||||||
default = pmb.config.pmaports.read_config(args)["channel"]
|
default = pmb.config.pmaports.read_config()["channel"]
|
||||||
choices = channels_cfg["channels"].keys()
|
choices = channels_cfg["channels"].keys()
|
||||||
if args.is_default_channel or default not in choices:
|
if args.is_default_channel or default not in choices:
|
||||||
default = channels_cfg["meta"]["recommended"]
|
default = channels_cfg["meta"]["recommended"]
|
||||||
|
@ -145,7 +146,7 @@ def ask_for_ui(args: PmbArgs, info):
|
||||||
if not device_is_accelerated:
|
if not device_is_accelerated:
|
||||||
for i in reversed(range(len(ui_list))):
|
for i in reversed(range(len(ui_list))):
|
||||||
pkgname = f"postmarketos-ui-{ui_list[i][0]}"
|
pkgname = f"postmarketos-ui-{ui_list[i][0]}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, pkgname,
|
apkbuild = pmb.helpers.pmaports.get(pkgname,
|
||||||
subpackages=False,
|
subpackages=False,
|
||||||
must_exist=False)
|
must_exist=False)
|
||||||
if apkbuild and "pmb:gpu-accel" in apkbuild["options"]:
|
if apkbuild and "pmb:gpu-accel" in apkbuild["options"]:
|
||||||
|
@ -176,7 +177,7 @@ def ask_for_ui(args: PmbArgs, info):
|
||||||
|
|
||||||
|
|
||||||
def ask_for_ui_extras(args: PmbArgs, ui):
|
def ask_for_ui_extras(args: PmbArgs, ui):
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, f"postmarketos-ui-{ui}",
|
apkbuild = pmb.helpers.pmaports.get(f"postmarketos-ui-{ui}",
|
||||||
subpackages=False, must_exist=False)
|
subpackages=False, must_exist=False)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
return False
|
return False
|
||||||
|
@ -193,15 +194,15 @@ def ask_for_ui_extras(args: PmbArgs, ui):
|
||||||
|
|
||||||
|
|
||||||
def ask_for_systemd(args: PmbArgs, ui):
|
def ask_for_systemd(args: PmbArgs, ui):
|
||||||
if "systemd" not in pmb.config.pmaports.read_config_repos(args):
|
if "systemd" not in pmb.config.pmaports.read_config_repos():
|
||||||
return args.systemd
|
return args.systemd
|
||||||
|
|
||||||
if pmb.helpers.ui.check_option(args, ui, "pmb:systemd-never"):
|
if pmb.helpers.ui.check_option(ui, "pmb:systemd-never"):
|
||||||
logging.info("Based on your UI selection, OpenRC will be used as init"
|
logging.info("Based on your UI selection, OpenRC will be used as init"
|
||||||
" system. This UI does not support systemd.")
|
" system. This UI does not support systemd.")
|
||||||
return args.systemd
|
return args.systemd
|
||||||
|
|
||||||
default_is_systemd = pmb.helpers.ui.check_option(args, ui, "pmb:systemd")
|
default_is_systemd = pmb.helpers.ui.check_option(ui, "pmb:systemd")
|
||||||
not_str = " " if default_is_systemd else " not "
|
not_str = " " if default_is_systemd else " not "
|
||||||
logging.info("Based on your UI selection, 'default' will result"
|
logging.info("Based on your UI selection, 'default' will result"
|
||||||
f" in{not_str}installing systemd.")
|
f" in{not_str}installing systemd.")
|
||||||
|
@ -267,7 +268,7 @@ def ask_for_provider_select(args: PmbArgs, apkbuild, providers_cfg):
|
||||||
providers. Updated with new providers after selection
|
providers. Updated with new providers after selection
|
||||||
"""
|
"""
|
||||||
for select in apkbuild["_pmb_select"]:
|
for select in apkbuild["_pmb_select"]:
|
||||||
providers = pmb.helpers.pmaports.find_providers(args, select)
|
providers = pmb.helpers.pmaports.find_providers(select)
|
||||||
logging.info(f"Available providers for {select} ({len(providers)}):")
|
logging.info(f"Available providers for {select} ({len(providers)}):")
|
||||||
|
|
||||||
has_default = False
|
has_default = False
|
||||||
|
@ -322,7 +323,7 @@ def ask_for_provider_select_pkg(args: PmbArgs, pkgname, providers_cfg):
|
||||||
:param providers_cfg: the configuration section with previously selected
|
:param providers_cfg: the configuration section with previously selected
|
||||||
providers. Updated with new providers after selection
|
providers. Updated with new providers after selection
|
||||||
"""
|
"""
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, pkgname,
|
apkbuild = pmb.helpers.pmaports.get(pkgname,
|
||||||
subpackages=False, must_exist=False)
|
subpackages=False, must_exist=False)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
return
|
return
|
||||||
|
@ -330,7 +331,7 @@ def ask_for_provider_select_pkg(args: PmbArgs, pkgname, providers_cfg):
|
||||||
ask_for_provider_select(args, apkbuild, providers_cfg)
|
ask_for_provider_select(args, apkbuild, providers_cfg)
|
||||||
|
|
||||||
|
|
||||||
def ask_for_device_kernel(args: PmbArgs, device):
|
def ask_for_device_kernel(args: PmbArgs, device: str):
|
||||||
"""Ask for the kernel that should be used with the device.
|
"""Ask for the kernel that should be used with the device.
|
||||||
|
|
||||||
:param device: code name, e.g. "lg-mako"
|
:param device: code name, e.g. "lg-mako"
|
||||||
|
@ -341,7 +342,7 @@ def ask_for_device_kernel(args: PmbArgs, device):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Get kernels
|
# Get kernels
|
||||||
kernels = pmb.parse._apkbuild.kernels(args, device)
|
kernels = pmb.parse._apkbuild.kernels(device)
|
||||||
if not kernels:
|
if not kernels:
|
||||||
return args.kernel
|
return args.kernel
|
||||||
|
|
||||||
|
@ -383,7 +384,7 @@ def ask_for_device(args: PmbArgs):
|
||||||
* device_exists: bool indicating if device port exists in repo
|
* device_exists: bool indicating if device port exists in repo
|
||||||
* kernel: type of kernel (downstream, etc)
|
* kernel: type of kernel (downstream, etc)
|
||||||
"""
|
"""
|
||||||
vendors = sorted(pmb.helpers.devices.list_vendors(args))
|
vendors = sorted(pmb.helpers.devices.list_vendors(get_context().config.aports))
|
||||||
logging.info("Choose your target device vendor (either an "
|
logging.info("Choose your target device vendor (either an "
|
||||||
"existing one, or a new one for porting).")
|
"existing one, or a new one for porting).")
|
||||||
logging.info(f"Available vendors ({len(vendors)}): {', '.join(vendors)}")
|
logging.info(f"Available vendors ({len(vendors)}): {', '.join(vendors)}")
|
||||||
|
@ -409,7 +410,7 @@ def ask_for_device(args: PmbArgs):
|
||||||
else:
|
else:
|
||||||
# Archived devices can be selected, but are not displayed
|
# Archived devices can be selected, but are not displayed
|
||||||
devices = sorted(pmb.helpers.devices.list_codenames(
|
devices = sorted(pmb.helpers.devices.list_codenames(
|
||||||
args, vendor, archived=False))
|
get_context().config.aports, vendor, archived=False))
|
||||||
# Remove "vendor-" prefixes from device list
|
# Remove "vendor-" prefixes from device list
|
||||||
codenames = [x.split('-', 1)[1] for x in devices]
|
codenames = [x.split('-', 1)[1] for x in devices]
|
||||||
logging.info(f"Available codenames ({len(codenames)}): " +
|
logging.info(f"Available codenames ({len(codenames)}): " +
|
||||||
|
@ -422,7 +423,7 @@ def ask_for_device(args: PmbArgs):
|
||||||
codenames)
|
codenames)
|
||||||
|
|
||||||
device = f"{vendor}-{codename}"
|
device = f"{vendor}-{codename}"
|
||||||
device_path = pmb.helpers.devices.find_path(args, device, 'deviceinfo')
|
device_path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
||||||
if device_path is None:
|
if device_path is None:
|
||||||
if device == args.device:
|
if device == args.device:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
|
@ -460,7 +461,7 @@ def ask_for_additional_options(args: PmbArgs, cfg):
|
||||||
f" parallel jobs: {args.jobs},"
|
f" parallel jobs: {args.jobs},"
|
||||||
f" ccache per arch: {args.ccache_size},"
|
f" ccache per arch: {args.ccache_size},"
|
||||||
f" sudo timer: {context.sudo_timer},"
|
f" sudo timer: {context.sudo_timer},"
|
||||||
f" mirror: {','.join(args.mirrors_postmarketos)}")
|
f" mirror: {','.join(context.config.mirrors_postmarketos)}")
|
||||||
|
|
||||||
if not pmb.helpers.cli.confirm(args, "Change them?",
|
if not pmb.helpers.cli.confirm(args, "Change them?",
|
||||||
default=False):
|
default=False):
|
||||||
|
@ -517,7 +518,7 @@ def ask_for_additional_options(args: PmbArgs, cfg):
|
||||||
# Mirrors
|
# Mirrors
|
||||||
# prompt for mirror change
|
# prompt for mirror change
|
||||||
logging.info("Selected mirror:"
|
logging.info("Selected mirror:"
|
||||||
f" {','.join(args.mirrors_postmarketos)}")
|
f" {','.join(context.config.mirrors_postmarketos)}")
|
||||||
if pmb.helpers.cli.confirm(args, "Change mirror?", default=False):
|
if pmb.helpers.cli.confirm(args, "Change mirror?", default=False):
|
||||||
mirrors = ask_for_mirror(args)
|
mirrors = ask_for_mirror(args)
|
||||||
cfg["pmbootstrap"]["mirrors_postmarketos"] = ",".join(mirrors)
|
cfg["pmbootstrap"]["mirrors_postmarketos"] = ",".join(mirrors)
|
||||||
|
@ -527,7 +528,7 @@ def ask_for_mirror(args: PmbArgs):
|
||||||
regex = "^[1-9][0-9]*$" # single non-zero number only
|
regex = "^[1-9][0-9]*$" # single non-zero number only
|
||||||
|
|
||||||
json_path = pmb.helpers.http.download(
|
json_path = pmb.helpers.http.download(
|
||||||
args, "https://postmarketos.org/mirrors.json", "pmos_mirrors",
|
"https://postmarketos.org/mirrors.json", "pmos_mirrors",
|
||||||
cache=False)
|
cache=False)
|
||||||
with open(json_path, "rt") as handle:
|
with open(json_path, "rt") as handle:
|
||||||
s = handle.read()
|
s = handle.read()
|
||||||
|
@ -558,7 +559,7 @@ def ask_for_mirror(args: PmbArgs):
|
||||||
urls.append(link_list[0])
|
urls.append(link_list[0])
|
||||||
|
|
||||||
mirror_indexes = []
|
mirror_indexes = []
|
||||||
for mirror in args.mirrors_postmarketos:
|
for mirror in get_context().config.mirrors_postmarketos:
|
||||||
for i in range(len(urls)):
|
for i in range(len(urls)):
|
||||||
if urls[i] == mirror:
|
if urls[i] == mirror:
|
||||||
mirror_indexes.append(str(i + 1))
|
mirror_indexes.append(str(i + 1))
|
||||||
|
@ -647,64 +648,64 @@ def frontend(args: PmbArgs):
|
||||||
require_programs()
|
require_programs()
|
||||||
|
|
||||||
# Work folder (needs to be first, so we can create chroots early)
|
# Work folder (needs to be first, so we can create chroots early)
|
||||||
cfg = pmb.config.load(args)
|
config = pmb.config.load(args)
|
||||||
work, work_exists = ask_for_work_path(args)
|
config.work, work_exists = ask_for_work_path(args)
|
||||||
cfg["pmbootstrap"]["work"] = work
|
|
||||||
|
|
||||||
# Update args and save config (so chroots and 'pmbootstrap log' work)
|
# Update args and save config (so chroots and 'pmbootstrap log' work)
|
||||||
pmb.helpers.args.update_work(args, work)
|
pmb.helpers.args.update_work(args, config.work)
|
||||||
pmb.config.save(args, cfg)
|
pmb.config.save(args.config, config)
|
||||||
|
|
||||||
# Migrate work dir if necessary
|
# Migrate work dir if necessary
|
||||||
pmb.helpers.other.migrate_work_folder(args)
|
pmb.helpers.other.migrate_work_folder(args)
|
||||||
|
|
||||||
# Clone pmaports
|
# Clone pmaports
|
||||||
pmb.config.pmaports.init(args)
|
pmb.config.pmaports.init()
|
||||||
|
|
||||||
# Choose release channel, possibly switch pmaports branch
|
# Choose release channel, possibly switch pmaports branch
|
||||||
channel = ask_for_channel(args)
|
channel = ask_for_channel(args)
|
||||||
pmb.config.pmaports.switch_to_channel_branch(args, channel)
|
pmb.config.pmaports.switch_to_channel_branch(args, channel)
|
||||||
cfg["pmbootstrap"]["is_default_channel"] = "False"
|
# FIXME: ???
|
||||||
|
config.is_default_channel = False
|
||||||
|
|
||||||
# Copy the git hooks if master was checked out. (Don't symlink them and
|
# Copy the git hooks if master was checked out. (Don't symlink them and
|
||||||
# only do it on master, so the git hooks don't change unexpectedly when
|
# only do it on master, so the git hooks don't change unexpectedly when
|
||||||
# having a random branch checked out.)
|
# having a random branch checked out.)
|
||||||
branch_current = pmb.helpers.git.rev_parse(args.aports,
|
branch_current = pmb.helpers.git.rev_parse(get_context().config.aports,
|
||||||
extra_args=["--abbrev-ref"])
|
extra_args=["--abbrev-ref"])
|
||||||
if branch_current == "master":
|
if branch_current == "master":
|
||||||
logging.info("NOTE: pmaports is on master branch, copying git hooks.")
|
logging.info("NOTE: pmaports is on master branch, copying git hooks.")
|
||||||
pmb.config.pmaports.install_githooks(args)
|
pmb.config.pmaports.install_githooks()
|
||||||
|
|
||||||
# Device
|
# Device
|
||||||
device, device_exists, kernel = ask_for_device(args)
|
device, device_exists, kernel = ask_for_device(args)
|
||||||
cfg["pmbootstrap"]["device"] = device
|
config.device = device
|
||||||
cfg["pmbootstrap"]["kernel"] = kernel
|
config.kernel = kernel
|
||||||
|
|
||||||
info = pmb.parse.deviceinfo(args, device)
|
info = pmb.parse.deviceinfo(args, device)
|
||||||
apkbuild_path = pmb.helpers.devices.find_path(args, device, 'APKBUILD')
|
apkbuild_path = pmb.helpers.devices.find_path(device, 'APKBUILD')
|
||||||
if apkbuild_path:
|
if apkbuild_path:
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
||||||
ask_for_provider_select(args, apkbuild, cfg["providers"])
|
ask_for_provider_select(args, apkbuild, config.providers)
|
||||||
|
|
||||||
# Device keymap
|
# Device keymap
|
||||||
if device_exists:
|
if device_exists:
|
||||||
cfg["pmbootstrap"]["keymap"] = ask_for_keymaps(args, info)
|
config.keymap = ask_for_keymaps(args, info)
|
||||||
|
|
||||||
cfg["pmbootstrap"]["user"] = ask_for_username(args)
|
config.user = ask_for_username(args)
|
||||||
ask_for_provider_select_pkg(args, "postmarketos-base", cfg["providers"])
|
ask_for_provider_select_pkg(args, "postmarketos-base", config.providers)
|
||||||
ask_for_provider_select_pkg(args, "postmarketos-base-ui", cfg["providers"])
|
ask_for_provider_select_pkg(args, "postmarketos-base-ui", config.providers)
|
||||||
|
|
||||||
# UI and various build options
|
# UI and various build options
|
||||||
ui = ask_for_ui(args, info)
|
ui = ask_for_ui(args, info)
|
||||||
cfg["pmbootstrap"]["ui"] = ui
|
config.ui = ui
|
||||||
cfg["pmbootstrap"]["ui_extras"] = str(ask_for_ui_extras(args, ui))
|
config.ui_extras = ask_for_ui_extras(args, ui)
|
||||||
|
|
||||||
# systemd
|
# systemd
|
||||||
cfg["pmbootstrap"]["systemd"] = ask_for_systemd(args, ui)
|
config.systemd = ask_for_systemd(args, ui)
|
||||||
|
|
||||||
ask_for_provider_select_pkg(args, f"postmarketos-ui-{ui}",
|
ask_for_provider_select_pkg(args, f"postmarketos-ui-{ui}",
|
||||||
cfg["providers"])
|
config.providers)
|
||||||
ask_for_additional_options(args, cfg)
|
ask_for_additional_options(args, config)
|
||||||
|
|
||||||
# Extra packages to be installed to rootfs
|
# Extra packages to be installed to rootfs
|
||||||
logging.info("Additional packages that will be installed to rootfs."
|
logging.info("Additional packages that will be installed to rootfs."
|
||||||
|
@ -713,29 +714,28 @@ def frontend(args: PmbArgs):
|
||||||
extra = pmb.helpers.cli.ask("Extra packages", None,
|
extra = pmb.helpers.cli.ask("Extra packages", None,
|
||||||
args.extra_packages,
|
args.extra_packages,
|
||||||
validation_regex=r"^([-.+\w]+)(,[-.+\w]+)*$")
|
validation_regex=r"^([-.+\w]+)(,[-.+\w]+)*$")
|
||||||
cfg["pmbootstrap"]["extra_packages"] = extra
|
config.extra_packages = extra
|
||||||
|
|
||||||
# Configure timezone info
|
# Configure timezone info
|
||||||
cfg["pmbootstrap"]["timezone"] = ask_for_timezone(args)
|
config.timezone = ask_for_timezone(args)
|
||||||
|
|
||||||
# Locale
|
# Locale
|
||||||
cfg["pmbootstrap"]["locale"] = ask_for_locale(args)
|
config.locale = ask_for_locale(args)
|
||||||
|
|
||||||
# Hostname
|
# Hostname
|
||||||
cfg["pmbootstrap"]["hostname"] = ask_for_hostname(args, device)
|
config.hostname = ask_for_hostname(args, device)
|
||||||
|
|
||||||
# SSH keys
|
# SSH keys
|
||||||
cfg["pmbootstrap"]["ssh_keys"] = str(ask_for_ssh_keys(args))
|
config.ssh_keys = ask_for_ssh_keys(args)
|
||||||
|
|
||||||
# pmaports path (if users change it with: 'pmbootstrap --aports=... init')
|
# pmaports path (if users change it with: 'pmbootstrap --aports=... init')
|
||||||
cfg["pmbootstrap"]["aports"] = args.aports
|
config.aports = get_context().config.aports
|
||||||
|
|
||||||
# Build outdated packages in pmbootstrap install
|
# Build outdated packages in pmbootstrap install
|
||||||
cfg["pmbootstrap"]["build_pkgs_on_install"] = str(
|
config.build_pkgs_on_install = ask_build_pkgs_on_install(args)
|
||||||
ask_build_pkgs_on_install(args))
|
|
||||||
|
|
||||||
# Save config
|
# Save config
|
||||||
pmb.config.save(args, cfg)
|
pmb.config.save(args.config, config)
|
||||||
|
|
||||||
# Zap existing chroots
|
# Zap existing chroots
|
||||||
if (work_exists and device_exists and
|
if (work_exists and device_exists and
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pathlib import Path, PosixPath
|
||||||
|
from typing import Any, Dict
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import Config
|
||||||
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def sanity_check(args: PmbArgs, cfg, key, allowed, print_path):
|
def sanity_check(args: PmbArgs, cfg: Config, key, allowed, print_path):
|
||||||
value = cfg["pmbootstrap"][key]
|
value = getattr(cfg, key)
|
||||||
|
|
||||||
if value in allowed:
|
if value in allowed:
|
||||||
return
|
return
|
||||||
|
@ -23,12 +26,14 @@ def sanity_check(args: PmbArgs, cfg, key, allowed, print_path):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def sanity_checks(args: PmbArgs, cfg, print_path=True):
|
def sanity_checks(args: PmbArgs, cfg: Config, print_path=True):
|
||||||
for key, allowed in pmb.config.allowed_values.items():
|
for key, allowed in pmb.config.allowed_values.items():
|
||||||
sanity_check(args, cfg, key, allowed, print_path)
|
sanity_check(args, cfg, key, allowed, print_path)
|
||||||
|
|
||||||
|
|
||||||
def load(args: PmbArgs):
|
def load(args: PmbArgs) -> Config:
|
||||||
|
config = Config()
|
||||||
|
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
if os.path.isfile(args.config):
|
if os.path.isfile(args.config):
|
||||||
cfg.read(args.config)
|
cfg.read(args.config)
|
||||||
|
@ -38,27 +43,47 @@ def load(args: PmbArgs):
|
||||||
if "providers" not in cfg:
|
if "providers" not in cfg:
|
||||||
cfg["providers"] = {}
|
cfg["providers"] = {}
|
||||||
|
|
||||||
for key in pmb.config.defaults:
|
for key in Config.__dict__.keys():
|
||||||
if key in pmb.config.config_keys and key not in cfg["pmbootstrap"]:
|
if key == "providers":
|
||||||
cfg["pmbootstrap"][key] = str(pmb.config.defaults[key])
|
setattr(config, key, cfg["providers"])
|
||||||
|
# Handle whacky type conversions
|
||||||
|
elif key == "mirrors_postmarketos":
|
||||||
|
config.mirrors_postmarketos = cfg["pmbootstrap"]["mirrors_postmarketos"].split(",")
|
||||||
|
# Convert strings to paths
|
||||||
|
elif type(getattr(Config, key)) == PosixPath:
|
||||||
|
setattr(config, key, Path(cfg["pmbootstrap"][key]))
|
||||||
|
elif isinstance(getattr(Config, key), bool):
|
||||||
|
setattr(config, key, cfg["pmbootstrap"][key].lower() == "true")
|
||||||
|
elif key in cfg["pmbootstrap"]:
|
||||||
|
setattr(config, key, cfg["pmbootstrap"][key])
|
||||||
|
|
||||||
# We used to save default values in the config, which can *not* be
|
sanity_checks(args, config)
|
||||||
# configured in "pmbootstrap init". That doesn't make sense, we always
|
|
||||||
# want to use the defaults from pmb/config/__init__.py in that case,
|
|
||||||
# not some outdated version we saved some time back (eg. aports folder,
|
|
||||||
# postmarketOS binary packages mirror).
|
|
||||||
if key not in pmb.config.config_keys and key in cfg["pmbootstrap"]:
|
|
||||||
logging.debug("Ignored unconfigurable and possibly outdated"
|
|
||||||
" default value from config:"
|
|
||||||
f" {cfg['pmbootstrap'][key]}")
|
|
||||||
del cfg["pmbootstrap"][key]
|
|
||||||
|
|
||||||
sanity_checks(args, cfg)
|
return config
|
||||||
|
|
||||||
return cfg
|
def save(output: Path, config: Config):
|
||||||
|
logging.debug(f"Save config: {output}")
|
||||||
|
output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
output.touch(0o700, exist_ok=True)
|
||||||
|
|
||||||
def save(args: PmbArgs, cfg):
|
cfg = configparser.ConfigParser()
|
||||||
logging.debug(f"Save config: {args.config}")
|
cfg["pmbootstrap"] = {}
|
||||||
os.makedirs(os.path.dirname(args.config), 0o700, True)
|
cfg["providers"] = {}
|
||||||
with open(args.config, "w") as handle:
|
|
||||||
|
for key in Config.__dict__.keys():
|
||||||
|
print(key)
|
||||||
|
if key == "providers":
|
||||||
|
cfg["providers"] = config.providers
|
||||||
|
# Handle whacky type conversions
|
||||||
|
elif key == "mirrors_postmarketos":
|
||||||
|
cfg["pmbootstrap"]["mirrors_postmarketos"] = ",".join(config.mirrors_postmarketos)
|
||||||
|
# Convert strings to paths
|
||||||
|
elif type(getattr(Config, key)) == Path:
|
||||||
|
cfg["pmbootstrap"][key] = str(getattr(config, key))
|
||||||
|
elif isinstance(getattr(Config, key), bool):
|
||||||
|
cfg["pmbootstrap"][key] = str(getattr(config, key))
|
||||||
|
else:
|
||||||
|
cfg["pmbootstrap"] = getattr(config, key)
|
||||||
|
|
||||||
|
with output.open("w") as handle:
|
||||||
cfg.write(handle)
|
cfg.write(handle)
|
||||||
|
|
|
@ -2,45 +2,42 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def merge_with_args(args: PmbArgs):
|
# def merge_with_args(args: PmbArgs):
|
||||||
"""We have the internal config (pmb/config/__init__.py) and the user config
|
# """We have the internal config (pmb/config/__init__.py) and the user config
|
||||||
(usually ~/.config/pmbootstrap.cfg, can be changed with the '-c'
|
# (usually ~/.config/pmbootstrap.cfg, can be changed with the '-c'
|
||||||
parameter).
|
# parameter).
|
||||||
|
|
||||||
Args holds the variables parsed from the commandline (e.g. -j fills out
|
# Args holds the variables parsed from the commandline (e.g. -j fills out
|
||||||
args.jobs), and values specified on the commandline count the most.
|
# args.jobs), and values specified on the commandline count the most.
|
||||||
|
|
||||||
In case it is not specified on the commandline, for the keys in
|
# In case it is not specified on the commandline, for the keys in
|
||||||
pmb.config.config_keys, we look into the value set in the the user config.
|
# pmb.config.config_keys, we look into the value set in the the user config.
|
||||||
|
|
||||||
When that is empty as well (e.g. just before pmbootstrap init), or the key
|
# When that is empty as well (e.g. just before pmbootstrap init), or the key
|
||||||
is not in pmb.config_keys, we use the default value from the internal
|
# is not in pmb.config_keys, we use the default value from the internal
|
||||||
config.
|
# config.
|
||||||
"""
|
# """
|
||||||
# Use defaults from the user's config file
|
# # Use defaults from the user's config file
|
||||||
cfg = pmb.config.load(args)
|
# cfg = pmb.config.load(args)
|
||||||
for key in cfg["pmbootstrap"]:
|
# for key in cfg["pmbootstrap"]:
|
||||||
if key not in args or getattr(args, key) is None:
|
# if key not in args or getattr(args, key) is None:
|
||||||
value = cfg["pmbootstrap"][key]
|
# value = cfg["pmbootstrap"][key]
|
||||||
if key in pmb.config.defaults:
|
# if key in pmb.config.defaults:
|
||||||
default = pmb.config.defaults[key]
|
# default = pmb.config.defaults[key]
|
||||||
if isinstance(default, bool):
|
# if isinstance(default, bool):
|
||||||
value = (value.lower() == "true")
|
# value = (value.lower() == "true")
|
||||||
setattr(args, key, value)
|
# setattr(args, key, value)
|
||||||
setattr(args, 'selected_providers', cfg['providers'])
|
# setattr(args, 'selected_providers', cfg['providers'])
|
||||||
|
|
||||||
# Use defaults from pmb.config.defaults
|
# # Use defaults from pmb.config.defaults
|
||||||
for key, value in pmb.config.defaults.items():
|
# for key, value in pmb.config.defaults.items():
|
||||||
if key not in args or getattr(args, key) is None:
|
# if key not in args or getattr(args, key) is None:
|
||||||
setattr(args, key, value)
|
# setattr(args, key, value)
|
||||||
|
|
||||||
pmb.config.work_dir(Path(cfg["pmbootstrap"]["work"]))
|
# pmb.config.work_dir(Path(cfg["pmbootstrap"]["work"]))
|
||||||
|
|
||||||
# Make sure args.aports is a Path object
|
# # Make sure args.aports is a Path object
|
||||||
setattr(args, "aports", Path(args.aports))
|
# setattr(args, "aports", Path(args.aports))
|
||||||
|
|
||||||
# args.work is deprecated!
|
|
||||||
delattr(args, "work")
|
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
# Copyright 2024 Oliver Smith
|
# Copyright 2024 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import Config
|
||||||
import pmb.helpers.ui
|
import pmb.helpers.ui
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
|
|
||||||
|
|
||||||
def is_systemd_selected(args: PmbArgs):
|
def is_systemd_selected(config: Config):
|
||||||
if "systemd" not in pmb.config.pmaports.read_config_repos(args):
|
if "systemd" not in pmb.config.pmaports.read_config_repos():
|
||||||
return False
|
return False
|
||||||
if pmb.helpers.ui.check_option(args, args.ui, "pmb:systemd-never"):
|
if pmb.helpers.ui.check_option(config.ui, "pmb:systemd-never"):
|
||||||
return False
|
return False
|
||||||
if args.systemd == "always":
|
if config.systemd == "always":
|
||||||
return True
|
return True
|
||||||
if args.systemd == "never":
|
if config.systemd == "never":
|
||||||
return False
|
return False
|
||||||
return pmb.helpers.ui.check_option(args, args.ui, "pmb:systemd")
|
return pmb.helpers.ui.check_option(config.ui, "pmb:systemd")
|
||||||
|
|
||||||
|
|
||||||
def systemd_selected_str(args):
|
def systemd_selected_str(config: Config):
|
||||||
if "systemd" not in pmb.config.pmaports.read_config_repos(args):
|
if "systemd" not in pmb.config.pmaports.read_config_repos():
|
||||||
return "no", "not supported by pmaports branch"
|
return "no", "not supported by pmaports branch"
|
||||||
if pmb.helpers.ui.check_option(args, args.ui, "pmb:systemd-never"):
|
if pmb.helpers.ui.check_option(config.ui, "pmb:systemd-never"):
|
||||||
return "no", "not supported by selected UI"
|
return "no", "not supported by selected UI"
|
||||||
if args.systemd == "always":
|
if config.systemd == "always":
|
||||||
return "yes", "'always' selected in 'pmbootstrap init'"
|
return "yes", "'always' selected in 'pmbootstrap init'"
|
||||||
if args.systemd == "never":
|
if config.systemd == "never":
|
||||||
return "no", "'never' selected in 'pmbootstrap init'"
|
return "no", "'never' selected in 'pmbootstrap init'"
|
||||||
if pmb.helpers.ui.check_option(args, args.ui, "pmb:systemd"):
|
if pmb.helpers.ui.check_option(config.ui, "pmb:systemd"):
|
||||||
return "yes", "default for selected UI"
|
return "yes", "default for selected UI"
|
||||||
return "no", "default for selected UI"
|
return "no", "default for selected UI"
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import configparser
|
import configparser
|
||||||
|
from pathlib import Path
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
@ -56,7 +58,7 @@ def check_version_pmbootstrap(min_ver):
|
||||||
" of pmbootstrap from git.")
|
" of pmbootstrap from git.")
|
||||||
|
|
||||||
|
|
||||||
def read_config_repos(args: PmbArgs):
|
def read_config_repos():
|
||||||
""" Read the sections starting with "repo:" from pmaports.cfg. """
|
""" Read the sections starting with "repo:" from pmaports.cfg. """
|
||||||
# Try cache first
|
# Try cache first
|
||||||
cache_key = "pmb.config.pmaports.read_config_repos"
|
cache_key = "pmb.config.pmaports.read_config_repos"
|
||||||
|
@ -64,7 +66,7 @@ def read_config_repos(args: PmbArgs):
|
||||||
return pmb.helpers.other.cache[cache_key]
|
return pmb.helpers.other.cache[cache_key]
|
||||||
|
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
cfg.read(f"{args.aports}/pmaports.cfg")
|
cfg.read(f"{get_context().config.aports}/pmaports.cfg")
|
||||||
|
|
||||||
ret = {}
|
ret = {}
|
||||||
for section in cfg.keys():
|
for section in cfg.keys():
|
||||||
|
@ -78,21 +80,22 @@ def read_config_repos(args: PmbArgs):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def read_config(args: PmbArgs):
|
def read_config():
|
||||||
"""Read and verify pmaports.cfg."""
|
"""Read and verify pmaports.cfg."""
|
||||||
# Try cache first
|
# Try cache first
|
||||||
cache_key = "pmb.config.pmaports.read_config"
|
cache_key = "pmb.config.pmaports.read_config"
|
||||||
if pmb.helpers.other.cache[cache_key]:
|
if pmb.helpers.other.cache[cache_key]:
|
||||||
return pmb.helpers.other.cache[cache_key]
|
return pmb.helpers.other.cache[cache_key]
|
||||||
|
|
||||||
|
aports = get_context().config.aports
|
||||||
# Migration message
|
# Migration message
|
||||||
if not os.path.exists(args.aports):
|
if not os.path.exists(aports):
|
||||||
logging.error(f"ERROR: pmaports dir not found: {args.aports}")
|
logging.error(f"ERROR: pmaports dir not found: {aports}")
|
||||||
logging.error("Did you run 'pmbootstrap init'?")
|
logging.error("Did you run 'pmbootstrap init'?")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Require the config
|
# Require the config
|
||||||
path_cfg = args.aports / "pmaports.cfg"
|
path_cfg = aports / "pmaports.cfg"
|
||||||
if not os.path.exists(path_cfg):
|
if not os.path.exists(path_cfg):
|
||||||
raise RuntimeError("Invalid pmaports repository, could not find the"
|
raise RuntimeError("Invalid pmaports repository, could not find the"
|
||||||
f" config: {path_cfg}")
|
f" config: {path_cfg}")
|
||||||
|
@ -114,7 +117,7 @@ def read_config(args: PmbArgs):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def read_config_channel(args: PmbArgs):
|
def read_config_channel():
|
||||||
"""Get the properties of the currently active channel in pmaports.git.
|
"""Get the properties of the currently active channel in pmaports.git.
|
||||||
|
|
||||||
As specified in channels.cfg (https://postmarketos.org/channels.cfg).
|
As specified in channels.cfg (https://postmarketos.org/channels.cfg).
|
||||||
|
@ -125,18 +128,19 @@ def read_config_channel(args: PmbArgs):
|
||||||
"mirrordir_alpine": ...}
|
"mirrordir_alpine": ...}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
channel = read_config(args)["channel"]
|
aports = get_context().config.aports
|
||||||
channels_cfg = pmb.helpers.git.parse_channels_cfg(args)
|
channel = read_config()["channel"]
|
||||||
|
channels_cfg = pmb.helpers.git.parse_channels_cfg(aports)
|
||||||
|
|
||||||
if channel in channels_cfg["channels"]:
|
if channel in channels_cfg["channels"]:
|
||||||
return channels_cfg["channels"][channel]
|
return channels_cfg["channels"][channel]
|
||||||
|
|
||||||
# Channel not in channels.cfg, try to be helpful
|
# Channel not in channels.cfg, try to be helpful
|
||||||
branch = pmb.helpers.git.rev_parse(args.aports,
|
branch = pmb.helpers.git.rev_parse(aports,
|
||||||
extra_args=["--abbrev-ref"])
|
extra_args=["--abbrev-ref"])
|
||||||
branches_official = pmb.helpers.git.get_branches_official("pmaports")
|
branches_official = pmb.helpers.git.get_branches_official(aports)
|
||||||
branches_official = ", ".join(branches_official)
|
branches_official = ", ".join(branches_official)
|
||||||
remote = pmb.helpers.git.get_upstream_remote("pmaports")
|
remote = pmb.helpers.git.get_upstream_remote(aports)
|
||||||
logging.info("NOTE: fix the error by rebasing or cherry picking relevant"
|
logging.info("NOTE: fix the error by rebasing or cherry picking relevant"
|
||||||
" commits from this branch onto a branch that is on a"
|
" commits from this branch onto a branch that is on a"
|
||||||
f" supported channel: {branches_official}")
|
f" supported channel: {branches_official}")
|
||||||
|
@ -150,7 +154,7 @@ def read_config_channel(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
if not os.path.exists(get_context().aports):
|
if not os.path.exists(get_context().config.aports):
|
||||||
clone()
|
clone()
|
||||||
read_config()
|
read_config()
|
||||||
|
|
||||||
|
@ -163,14 +167,15 @@ def switch_to_channel_branch(args: PmbArgs, channel_new):
|
||||||
:returns: True if another branch was checked out, False otherwise
|
:returns: True if another branch was checked out, False otherwise
|
||||||
"""
|
"""
|
||||||
# Check current pmaports branch channel
|
# Check current pmaports branch channel
|
||||||
channel_current = read_config(args)["channel"]
|
channel_current = read_config()["channel"]
|
||||||
if channel_current == channel_new:
|
if channel_current == channel_new:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
aports = get_context().config.aports
|
||||||
# List current and new branches/channels
|
# List current and new branches/channels
|
||||||
channels_cfg = pmb.helpers.git.parse_channels_cfg(args)
|
channels_cfg = pmb.helpers.git.parse_channels_cfg(aports)
|
||||||
branch_new = channels_cfg["channels"][channel_new]["branch_pmaports"]
|
branch_new = channels_cfg["channels"][channel_new]["branch_pmaports"]
|
||||||
branch_current = pmb.helpers.git.rev_parse(args.aports,
|
branch_current = pmb.helpers.git.rev_parse(aports,
|
||||||
extra_args=["--abbrev-ref"])
|
extra_args=["--abbrev-ref"])
|
||||||
logging.info(f"Currently checked out branch '{branch_current}' of"
|
logging.info(f"Currently checked out branch '{branch_current}' of"
|
||||||
f" pmaports.git is on channel '{channel_current}'.")
|
f" pmaports.git is on channel '{channel_current}'.")
|
||||||
|
@ -183,25 +188,26 @@ def switch_to_channel_branch(args: PmbArgs, channel_new):
|
||||||
# Attempt to switch branch (git gives a nice error message, mentioning
|
# Attempt to switch branch (git gives a nice error message, mentioning
|
||||||
# which files need to be committed/stashed, so just pass it through)
|
# which files need to be committed/stashed, so just pass it through)
|
||||||
if pmb.helpers.run.user(["git", "checkout", branch_new],
|
if pmb.helpers.run.user(["git", "checkout", branch_new],
|
||||||
args.aports, "interactive", check=False):
|
aports, "interactive", check=False):
|
||||||
raise RuntimeError("Failed to switch branch. Go to your pmaports and"
|
raise RuntimeError("Failed to switch branch. Go to your pmaports and"
|
||||||
" fix what git complained about, then try again: "
|
" fix what git complained about, then try again: "
|
||||||
f"{args.aports}")
|
f"{aports}")
|
||||||
|
|
||||||
# Verify pmaports.cfg on new branch
|
# Verify pmaports.cfg on new branch
|
||||||
read_config(args)
|
read_config()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def install_githooks(args: PmbArgs):
|
def install_githooks():
|
||||||
hooks_dir = os.path.join(args.aports, ".githooks")
|
aports = get_context().config.aports
|
||||||
if not os.path.exists(hooks_dir):
|
hooks_dir = aports / ".githooks"
|
||||||
|
if not hooks_dir.exists():
|
||||||
logging.info("No .githooks dir found")
|
logging.info("No .githooks dir found")
|
||||||
return
|
return
|
||||||
for h in os.listdir(hooks_dir):
|
for h in os.listdir(hooks_dir):
|
||||||
src = os.path.join(hooks_dir, h)
|
src = os.path.join(hooks_dir, h)
|
||||||
# Use git default hooks dir so users can ignore our hooks
|
# Use git default hooks dir so users can ignore our hooks
|
||||||
# if they dislike them by setting "core.hooksPath" git config
|
# if they dislike them by setting "core.hooksPath" git config
|
||||||
dst = os.path.join(args.aports, ".git", "hooks", h)
|
dst = aports / ".git/hooks" / h
|
||||||
if pmb.helpers.run.user(["cp", src, dst], check=False):
|
if pmb.helpers.run.user(["cp", src, dst], check=False):
|
||||||
logging.warning(f"WARNING: Copying git hook failed: {dst}")
|
logging.warning(f"WARNING: Copying git hook failed: {dst}")
|
||||||
|
|
|
@ -11,15 +11,15 @@ from typing import Optional
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def chroot_save_init(args: PmbArgs, suffix: Chroot):
|
def chroot_save_init(suffix: Chroot):
|
||||||
"""Save the chroot initialization data in $WORK/workdir.cfg."""
|
"""Save the chroot initialization data in $WORK/workdir.cfg."""
|
||||||
# Read existing cfg
|
# Read existing cfg
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
path = pmb.config.work / "workdir.cfg"
|
path = get_context().config.work / "workdir.cfg"
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
cfg.read(path)
|
cfg.read(path)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ def chroot_save_init(args: PmbArgs, suffix: Chroot):
|
||||||
cfg[key] = {}
|
cfg[key] = {}
|
||||||
|
|
||||||
# Update sections
|
# Update sections
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
cfg["chroot-channels"][str(suffix)] = channel
|
cfg["chroot-channels"][str(suffix)] = channel
|
||||||
cfg["chroot-init-dates"][str(suffix)] = str(int(time.time()))
|
cfg["chroot-init-dates"][str(suffix)] = str(int(time.time()))
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def chroot_save_init(args: PmbArgs, suffix: Chroot):
|
||||||
cfg.write(handle)
|
cfg.write(handle)
|
||||||
|
|
||||||
|
|
||||||
def chroots_outdated(args: PmbArgs, chroot: Optional[Chroot]=None):
|
def chroots_outdated(chroot: Optional[Chroot]=None):
|
||||||
"""Check if init dates from workdir.cfg indicate that any chroot is
|
"""Check if init dates from workdir.cfg indicate that any chroot is
|
||||||
outdated.
|
outdated.
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ def chroots_outdated(args: PmbArgs, chroot: Optional[Chroot]=None):
|
||||||
False otherwise
|
False otherwise
|
||||||
"""
|
"""
|
||||||
# Skip if workdir.cfg doesn't exist
|
# Skip if workdir.cfg doesn't exist
|
||||||
path = pmb.config.work / "workdir.cfg"
|
path = get_context().config.work / "workdir.cfg"
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ def chroots_outdated(args: PmbArgs, chroot: Optional[Chroot]=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def chroot_check_channel(args: PmbArgs, chroot: Chroot):
|
def chroot_check_channel(chroot: Chroot):
|
||||||
path = pmb.config.work / "workdir.cfg"
|
path = get_context().config.work / "workdir.cfg"
|
||||||
msg_again = "Run 'pmbootstrap zap' to delete your chroots and try again."
|
msg_again = "Run 'pmbootstrap zap' to delete your chroots and try again."
|
||||||
msg_unknown = ("Could not figure out on which release channel the"
|
msg_unknown = ("Could not figure out on which release channel the"
|
||||||
f" '{chroot}' chroot is.")
|
f" '{chroot}' chroot is.")
|
||||||
|
@ -82,7 +82,7 @@ def chroot_check_channel(args: PmbArgs, chroot: Chroot):
|
||||||
if key not in cfg or str(chroot) not in cfg[key]:
|
if key not in cfg or str(chroot) not in cfg[key]:
|
||||||
raise RuntimeError(f"{msg_unknown} {msg_again}")
|
raise RuntimeError(f"{msg_unknown} {msg_again}")
|
||||||
|
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
channel_cfg = cfg[key][str(chroot)]
|
channel_cfg = cfg[key][str(chroot)]
|
||||||
if channel != channel_cfg:
|
if channel != channel_cfg:
|
||||||
raise RuntimeError(f"Chroot '{chroot}' was created for the"
|
raise RuntimeError(f"Chroot '{chroot}' was created for the"
|
||||||
|
@ -98,7 +98,7 @@ def clean(args: PmbArgs):
|
||||||
False if config did not change
|
False if config did not change
|
||||||
"""
|
"""
|
||||||
# Skip if workdir.cfg doesn't exist
|
# Skip if workdir.cfg doesn't exist
|
||||||
path = pmb.config.work / "workdir.cfg"
|
path = get_context().config.work / "workdir.cfg"
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,6 @@
|
||||||
# Copyright 2024 Caleb Connolly
|
# Copyright 2024 Caleb Connolly
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from pmb.core.chroot import Chroot, ChrootType
|
from .chroot import Chroot, ChrootType
|
||||||
from pmb.core.context import Context
|
from .context import Context, get_context, set_context
|
||||||
|
from .config import Config
|
||||||
__context: Context
|
|
||||||
|
|
||||||
def get_context() -> Context:
|
|
||||||
"""Get immutable global runtime context."""
|
|
||||||
global __context
|
|
||||||
|
|
||||||
# We must defer this to first call to avoid
|
|
||||||
# circular imports.
|
|
||||||
if "__context" not in globals():
|
|
||||||
__context = Context()
|
|
||||||
return __context
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import enum
|
||||||
from typing import Generator, Optional
|
from typing import Generator, Optional
|
||||||
from pathlib import Path, PosixPath, PurePosixPath
|
from pathlib import Path, PosixPath, PurePosixPath
|
||||||
import pmb.config
|
import pmb.config
|
||||||
|
from .context import get_context
|
||||||
|
|
||||||
class ChrootType(enum.Enum):
|
class ChrootType(enum.Enum):
|
||||||
ROOTFS = "rootfs"
|
ROOTFS = "rootfs"
|
||||||
|
@ -69,7 +70,7 @@ class Chroot:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> Path:
|
def path(self) -> Path:
|
||||||
return Path(pmb.config.work, self.dirname)
|
return Path(get_context().config.work, self.dirname)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -182,4 +183,4 @@ class Chroot:
|
||||||
Glob all initialized chroot directories
|
Glob all initialized chroot directories
|
||||||
"""
|
"""
|
||||||
for pattern in Chroot.iter_patterns():
|
for pattern in Chroot.iter_patterns():
|
||||||
yield from Path(pmb.config.work).glob(pattern)
|
yield from Path(get_context().config.work).glob(pattern)
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
"""Global runtime context"""
|
"""Global runtime context"""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import List, Optional
|
||||||
import pmb.config
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from pmb.types import Config
|
||||||
|
|
||||||
|
|
||||||
class Context():
|
class Context():
|
||||||
|
@ -17,14 +17,62 @@ class Context():
|
||||||
# The architecture of the selected device
|
# The architecture of the selected device
|
||||||
device_arch: Optional[str]
|
device_arch: Optional[str]
|
||||||
offline: bool
|
offline: bool
|
||||||
aports: Path
|
|
||||||
|
|
||||||
def __init__(self):
|
# Never build packages
|
||||||
|
sdnfivnsifdvsbdf: bool
|
||||||
|
|
||||||
|
# The pmbootstrap subcommand
|
||||||
|
command: str
|
||||||
|
|
||||||
|
## FIXME: build options, should not be here ##
|
||||||
|
# disable cross compilation and use QEMU
|
||||||
|
cross: bool
|
||||||
|
no_depends: bool
|
||||||
|
ignore_depends: bool
|
||||||
|
ccache: bool
|
||||||
|
go_mod_cache: bool
|
||||||
|
|
||||||
|
config: Config
|
||||||
|
|
||||||
|
def __init__(self, config: Config):
|
||||||
self.details_to_stdout = False
|
self.details_to_stdout = False
|
||||||
self.command_timeout = 0
|
self.command_timeout = 0
|
||||||
self.sudo_timer = False
|
self.sudo_timer = False
|
||||||
self.log = pmb.config.work / "log.txt"
|
self.log = config.work / "log.txt"
|
||||||
self.quiet = False
|
self.quiet = False
|
||||||
self.device_arch = None
|
self.device_arch = None
|
||||||
self.offline = False
|
self.offline = False
|
||||||
self.aports = pmb.config.work / "cache_git" / "pmaports"
|
self.config = config
|
||||||
|
self.sdnfivnsifdvsbdf = False
|
||||||
|
self.command = ""
|
||||||
|
self.cross = False
|
||||||
|
self.no_depends = False
|
||||||
|
self.ignore_depends = False
|
||||||
|
self.ccache = False
|
||||||
|
self.go_mod_cache = False
|
||||||
|
|
||||||
|
|
||||||
|
__context: Context
|
||||||
|
|
||||||
|
def get_context(allow_failure: bool=False) -> Context:
|
||||||
|
"""Get immutable global runtime context."""
|
||||||
|
global __context
|
||||||
|
|
||||||
|
# We must defer this to first call to avoid
|
||||||
|
# circular imports.
|
||||||
|
if "__context" not in globals():
|
||||||
|
if allow_failure:
|
||||||
|
return None
|
||||||
|
raise RuntimeError("Context not loaded yet")
|
||||||
|
return __context
|
||||||
|
|
||||||
|
def set_context(context: Context):
|
||||||
|
"""Set global runtime context."""
|
||||||
|
global __context
|
||||||
|
|
||||||
|
if "__context" in globals():
|
||||||
|
raise RuntimeError("Context already loaded")
|
||||||
|
|
||||||
|
__context = context
|
||||||
|
|
||||||
|
|
||||||
|
|
43
pmb/core/crosstool.py
Normal file
43
pmb/core/crosstool.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# Copyright 2024 Caleb Connolly
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
import enum
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Optional, Tuple, TypedDict, Union
|
||||||
|
|
||||||
|
from pmb.core.chroot import ChrootType
|
||||||
|
from pmb.types import PathString
|
||||||
|
|
||||||
|
class CrossToolTarget(enum.Enum):
|
||||||
|
BUILDROOT = 0
|
||||||
|
ROOTFS = 1
|
||||||
|
|
||||||
|
class CrossTool():
|
||||||
|
__target: CrossToolTarget
|
||||||
|
__package: str
|
||||||
|
__paths: List[Path]
|
||||||
|
|
||||||
|
def __init__(self, target: CrossToolTarget, package: str, paths: List[PathString]):
|
||||||
|
self.__target = target
|
||||||
|
self.__package = package
|
||||||
|
self.__paths = list(map(lambda p: Path(p) if isinstance(p, str) else p, paths))
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"CrossTool({self.__target}, {self.__package}, {self.__paths})"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def package(self) -> str:
|
||||||
|
return self.__package
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paths(self) -> List[Path]:
|
||||||
|
return self.__paths
|
||||||
|
|
||||||
|
def should_install(self, target: ChrootType) -> bool:
|
||||||
|
if target == ChrootType.BUILDROOT and self.__target == CrossToolTarget.BUILDROOT:
|
||||||
|
return True
|
||||||
|
if target == ChrootType.ROOTFS or target == ChrootType.INSTALLER and self.__target == CrossToolTarget.ROOTFS:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
|
@ -1,7 +1,7 @@
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.frontend
|
import pmb.helpers.frontend
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
|
|
|
@ -6,7 +6,7 @@ from pathlib import Path
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
@ -23,7 +23,7 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
suffix_flavor = f"-{flavor}"
|
suffix_flavor = f"-{flavor}"
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
suffix_flavor = ""
|
suffix_flavor = ""
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
# Temporary folder
|
# Temporary folder
|
||||||
temp_folder = "/tmp/odin-flashable-tar"
|
temp_folder = "/tmp/odin-flashable-tar"
|
||||||
if (Chroot.native() / temp_folder).exists():
|
if (Chroot.native() / temp_folder).exists():
|
||||||
pmb.chroot.root(args, ["rm", "-rf", temp_folder])
|
pmb.chroot.root(["rm", "-rf", temp_folder])
|
||||||
|
|
||||||
# Odin flashable tar generation script
|
# Odin flashable tar generation script
|
||||||
# (because redirecting stdin/stdout is not allowed
|
# (because redirecting stdin/stdout is not allowed
|
||||||
|
@ -86,15 +86,15 @@ def odin(args: PmbArgs, flavor, folder: Path):
|
||||||
["rm", "/tmp/_odin.sh"]
|
["rm", "/tmp/_odin.sh"]
|
||||||
]
|
]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, command, suffix)
|
pmb.chroot.root(command, suffix)
|
||||||
|
|
||||||
# Move Odin flashable tar to native chroot and cleanup temp folder
|
# Move Odin flashable tar to native chroot and cleanup temp folder
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/rootfs"])
|
pmb.chroot.user(["mkdir", "-p", "/home/pmos/rootfs"])
|
||||||
pmb.chroot.root(args, ["mv", f"/mnt/rootfs_{args.device}{temp_folder}"
|
pmb.chroot.root(["mv", f"/mnt/rootfs_{args.device}{temp_folder}"
|
||||||
f"/{odin_device_tar_md5}", "/home/pmos/rootfs/"]),
|
f"/{odin_device_tar_md5}", "/home/pmos/rootfs/"]),
|
||||||
pmb.chroot.root(args, ["chown", "pmos:pmos",
|
pmb.chroot.root(["chown", "pmos:pmos",
|
||||||
f"/home/pmos/rootfs/{odin_device_tar_md5}"])
|
f"/home/pmos/rootfs/{odin_device_tar_md5}"])
|
||||||
pmb.chroot.root(args, ["rmdir", temp_folder], suffix)
|
pmb.chroot.root(["rmdir", temp_folder], suffix)
|
||||||
|
|
||||||
# Create the symlink
|
# Create the symlink
|
||||||
file = Chroot.native() / "home/pmos/rootfs" / odin_device_tar_md5
|
file = Chroot.native() / "home/pmos/rootfs" / odin_device_tar_md5
|
||||||
|
|
|
@ -8,7 +8,7 @@ import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
@ -21,7 +21,7 @@ def symlinks(args: PmbArgs, flavor, folder: Path):
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
suffix = f"-{flavor}"
|
suffix = f"-{flavor}"
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
suffix = ""
|
suffix = ""
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.install
|
import pmb.install
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
|
@ -116,7 +116,7 @@ def flash_lk2nd(args: PmbArgs):
|
||||||
# manually since supporting the codepath with heimdall requires more effort.
|
# manually since supporting the codepath with heimdall requires more effort.
|
||||||
pmb.flasher.init(args)
|
pmb.flasher.init(args)
|
||||||
logging.info("(native) checking current fastboot product")
|
logging.info("(native) checking current fastboot product")
|
||||||
output = pmb.chroot.root(args, ["fastboot", "getvar", "product"],
|
output = pmb.chroot.root(["fastboot", "getvar", "product"],
|
||||||
output="interactive", output_return=True)
|
output="interactive", output_return=True)
|
||||||
# Variable "product" is e.g. "LK2ND_MSM8974" or "lk2nd-msm8226" depending
|
# Variable "product" is e.g. "LK2ND_MSM8974" or "lk2nd-msm8226" depending
|
||||||
# on the lk2nd version.
|
# on the lk2nd version.
|
||||||
|
@ -126,7 +126,7 @@ def flash_lk2nd(args: PmbArgs):
|
||||||
|
|
||||||
# Get the lk2nd package (which is a dependency of the device package)
|
# Get the lk2nd package (which is a dependency of the device package)
|
||||||
device_pkg = f"device-{args.device}"
|
device_pkg = f"device-{args.device}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, device_pkg)
|
apkbuild = pmb.helpers.pmaports.get(device_pkg)
|
||||||
lk2nd_pkg = None
|
lk2nd_pkg = None
|
||||||
for dep in apkbuild["depends"]:
|
for dep in apkbuild["depends"]:
|
||||||
if dep.startswith("lk2nd"):
|
if dep.startswith("lk2nd"):
|
||||||
|
@ -137,7 +137,7 @@ def flash_lk2nd(args: PmbArgs):
|
||||||
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
raise RuntimeError(f"{device_pkg} does not depend on any lk2nd package")
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
||||||
pmb.chroot.apk.install(args, [lk2nd_pkg], suffix)
|
pmb.chroot.apk.install([lk2nd_pkg], suffix)
|
||||||
|
|
||||||
logging.info("(native) flash lk2nd image")
|
logging.info("(native) flash lk2nd image")
|
||||||
pmb.flasher.run(args, "flash_lk2nd")
|
pmb.flasher.run(args, "flash_lk2nd")
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
from pmb.helpers.mount import mount_device_rootfs
|
from pmb.helpers.mount import mount_device_rootfs
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType
|
||||||
|
@ -28,19 +28,19 @@ def install_depends(args: PmbArgs):
|
||||||
# Depends for some flash methods may be different for various pmaports
|
# Depends for some flash methods may be different for various pmaports
|
||||||
# branches, so read them from pmaports.cfg.
|
# branches, so read them from pmaports.cfg.
|
||||||
if method == "fastboot":
|
if method == "fastboot":
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
depends = pmaports_cfg.get("supported_fastboot_depends",
|
depends = pmaports_cfg.get("supported_fastboot_depends",
|
||||||
"android-tools,avbtool").split(",")
|
"android-tools,avbtool").split(",")
|
||||||
elif method == "heimdall-bootimg":
|
elif method == "heimdall-bootimg":
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
depends = pmaports_cfg.get("supported_heimdall_depends",
|
depends = pmaports_cfg.get("supported_heimdall_depends",
|
||||||
"heimdall,avbtool").split(",")
|
"heimdall,avbtool").split(",")
|
||||||
elif method == "mtkclient":
|
elif method == "mtkclient":
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
depends = pmaports_cfg.get("supported_mtkclient_depends",
|
depends = pmaports_cfg.get("supported_mtkclient_depends",
|
||||||
"mtkclient,android-tools").split(",")
|
"mtkclient,android-tools").split(",")
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, depends, Chroot.native())
|
pmb.chroot.apk.install(depends, Chroot.native())
|
||||||
|
|
||||||
|
|
||||||
def init(args: PmbArgs):
|
def init(args: PmbArgs):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
|
|
||||||
|
@ -80,4 +80,4 @@ def run(args: PmbArgs, action, flavor=None):
|
||||||
# Remove empty strings
|
# Remove empty strings
|
||||||
command = [x for x in command if x != '']
|
command = [x for x in command if x != '']
|
||||||
# Run the action
|
# Run the action
|
||||||
pmb.chroot.root(args, command, output="interactive")
|
pmb.chroot.root(command, output="interactive")
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def variables(args: PmbArgs, flavor, method):
|
def variables(args: PmbArgs, flavor, method):
|
||||||
|
@ -99,7 +99,7 @@ def variables(args: PmbArgs, flavor, method):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
vars["$FLAVOR"] = ""
|
vars["$FLAVOR"] = ""
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -6,12 +6,12 @@ from typing import List, Sequence
|
||||||
|
|
||||||
import pmb.chroot.run
|
import pmb.chroot.run
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.run_core
|
import pmb.helpers.run_core
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
def _prepare_fifo():
|
def _prepare_fifo():
|
||||||
"""Prepare the progress fifo for reading / writing.
|
"""Prepare the progress fifo for reading / writing.
|
||||||
|
@ -24,8 +24,8 @@ def _prepare_fifo():
|
||||||
path of the fifo as needed by cat to read from it (always
|
path of the fifo as needed by cat to read from it (always
|
||||||
relative to the host)
|
relative to the host)
|
||||||
"""
|
"""
|
||||||
pmb.helpers.run.root(["mkdir", "-p", pmb.config.work / "tmp"])
|
pmb.helpers.run.root(["mkdir", "-p", get_context().config.work / "tmp"])
|
||||||
fifo = fifo_outside = pmb.config.work / "tmp/apk_progress_fifo"
|
fifo = fifo_outside = get_context().config.work / "tmp/apk_progress_fifo"
|
||||||
if os.path.exists(fifo_outside):
|
if os.path.exists(fifo_outside):
|
||||||
pmb.helpers.run.root(["rm", "-f", fifo_outside])
|
pmb.helpers.run.root(["rm", "-f", fifo_outside])
|
||||||
pmb.helpers.run.root(["mkfifo", fifo_outside])
|
pmb.helpers.run.root(["mkfifo", fifo_outside])
|
||||||
|
@ -88,7 +88,7 @@ def apk_with_progress(command: Sequence[PathString]):
|
||||||
log_msg)
|
log_msg)
|
||||||
|
|
||||||
|
|
||||||
def check_outdated(args: PmbArgs, version_installed, action_msg):
|
def check_outdated(version_installed, action_msg):
|
||||||
"""Check if the provided alpine version is outdated.
|
"""Check if the provided alpine version is outdated.
|
||||||
|
|
||||||
This depends on the alpine mirrordir (edge, v3.12, ...) related to currently checked out
|
This depends on the alpine mirrordir (edge, v3.12, ...) related to currently checked out
|
||||||
|
@ -99,7 +99,7 @@ def check_outdated(args: PmbArgs, version_installed, action_msg):
|
||||||
this
|
this
|
||||||
:raises: RuntimeError if the version is outdated
|
:raises: RuntimeError if the version is outdated
|
||||||
"""
|
"""
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir_alpine = channel_cfg["mirrordir_alpine"]
|
mirrordir_alpine = channel_cfg["mirrordir_alpine"]
|
||||||
version_min = pmb.config.apk_tools_min_version[mirrordir_alpine]
|
version_min = pmb.config.apk_tools_min_version[mirrordir_alpine]
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import re
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
import pmb.helpers.http
|
import pmb.helpers.http
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
@ -263,7 +263,7 @@ def upgrade(args: PmbArgs, pkgname, git=True, stable=True) -> None:
|
||||||
# Initialize request headers
|
# Initialize request headers
|
||||||
init_req_headers()
|
init_req_headers()
|
||||||
|
|
||||||
package = pmb.helpers.pmaports.get(args, pkgname)
|
package = pmb.helpers.pmaports.get(pkgname)
|
||||||
# Run the correct function
|
# Run the correct function
|
||||||
if "_git" in package["pkgver"]:
|
if "_git" in package["pkgver"]:
|
||||||
if git:
|
if git:
|
||||||
|
|
|
@ -4,7 +4,8 @@ import copy
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.core.context import Context
|
||||||
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.args
|
import pmb.helpers.args
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ import pmb.helpers.args
|
||||||
Examples:
|
Examples:
|
||||||
args.aports ("$WORK/cache_git/pmaports", override with --aports)
|
args.aports ("$WORK/cache_git/pmaports", override with --aports)
|
||||||
args.device ("samsung-i9100", "qemu-amd64" etc.)
|
args.device ("samsung-i9100", "qemu-amd64" etc.)
|
||||||
pmb.config.work ("/home/user/.local/var/pmbootstrap", override with --work)
|
get_context().config.work ("/home/user/.local/var/pmbootstrap", override with --work)
|
||||||
|
|
||||||
3. Parsed configs
|
3. Parsed configs
|
||||||
Similar to the cache above, specific config files get parsed and added
|
Similar to the cache above, specific config files get parsed and added
|
||||||
|
@ -46,28 +47,6 @@ import pmb.helpers.args
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def fix_mirrors_postmarketos(args: PmbArgs):
|
|
||||||
"""Fix args.mirrors_postmarketos when it is supposed to be empty or the default value.
|
|
||||||
|
|
||||||
In pmb/parse/arguments.py, we set the -mp/--mirror-pmOS argument to
|
|
||||||
action="append" and start off with an empty list. That way, users can
|
|
||||||
specify multiple custom mirrors by specifying -mp multiple times on the
|
|
||||||
command line. Here we fix the default and no mirrors case.
|
|
||||||
|
|
||||||
NOTE: we don't use nargs="+", because it does not play nicely with
|
|
||||||
subparsers: <https://bugs.python.org/issue9338>
|
|
||||||
"""
|
|
||||||
# -mp not specified: use default mirrors
|
|
||||||
if not args.mirrors_postmarketos:
|
|
||||||
cfg = pmb.config.load(args)
|
|
||||||
args.mirrors_postmarketos = \
|
|
||||||
cfg["pmbootstrap"]["mirrors_postmarketos"].split(",")
|
|
||||||
|
|
||||||
# -mp="": use no postmarketOS mirrors (build everything locally)
|
|
||||||
if args.mirrors_postmarketos == [""]:
|
|
||||||
args.mirrors_postmarketos = []
|
|
||||||
|
|
||||||
|
|
||||||
def check_pmaports_path(args: PmbArgs):
|
def check_pmaports_path(args: PmbArgs):
|
||||||
"""Make sure that args.aports exists when it was overridden by --aports.
|
"""Make sure that args.aports exists when it was overridden by --aports.
|
||||||
|
|
||||||
|
@ -79,28 +58,28 @@ def check_pmaports_path(args: PmbArgs):
|
||||||
f" not exist: {args.aports}")
|
f" not exist: {args.aports}")
|
||||||
|
|
||||||
|
|
||||||
def replace_placeholders(args: PmbArgs):
|
# def replace_placeholders(args: PmbArgs):
|
||||||
"""Replace $WORK and ~ (for path variables) in variables from any config.
|
# """Replace $WORK and ~ (for path variables) in variables from any config.
|
||||||
|
|
||||||
(user's config file, default config settings or config parameters specified on commandline)
|
# (user's config file, default config settings or config parameters specified on commandline)
|
||||||
"""
|
# """
|
||||||
# Replace $WORK
|
# # Replace $WORK
|
||||||
for key, value in pmb.config.defaults.items():
|
# for key, value in pmb.config.defaults.items():
|
||||||
if key not in args:
|
# if key not in args:
|
||||||
continue
|
# continue
|
||||||
old = getattr(args, key)
|
# old = getattr(args, key)
|
||||||
if isinstance(old, str):
|
# if isinstance(old, str):
|
||||||
setattr(args, key, old.replace("$WORK", str(pmb.config.work)))
|
# setattr(args, key, old.replace("$WORK", str(get_context().config.work)))
|
||||||
|
|
||||||
# Replace ~ (path variables only)
|
# # Replace ~ (path variables only)
|
||||||
for key in ["aports", "config", "work"]:
|
# for key in ["aports", "config", "work"]:
|
||||||
if key in args:
|
# if key in args:
|
||||||
setattr(args, key, Path(getattr(args, key)).expanduser())
|
# setattr(args, key, Path(getattr(args, key)).expanduser())
|
||||||
|
|
||||||
|
|
||||||
def add_deviceinfo(args: PmbArgs):
|
def add_deviceinfo(args: PmbArgs):
|
||||||
"""Add and verify the deviceinfo (only after initialization)"""
|
"""Add and verify the deviceinfo (only after initialization)"""
|
||||||
setattr(args, "deviceinfo", pmb.parse.deviceinfo(args))
|
setattr(args, "deviceinfo", pmb.parse.deviceinfo())
|
||||||
arch = args.deviceinfo["arch"]
|
arch = args.deviceinfo["arch"]
|
||||||
if (arch != pmb.config.arch_native and
|
if (arch != pmb.config.arch_native and
|
||||||
arch not in pmb.config.build_device_architectures):
|
arch not in pmb.config.build_device_architectures):
|
||||||
|
@ -111,20 +90,28 @@ def add_deviceinfo(args: PmbArgs):
|
||||||
|
|
||||||
def init(args: PmbArgs) -> PmbArgs:
|
def init(args: PmbArgs) -> PmbArgs:
|
||||||
# Basic initialization
|
# Basic initialization
|
||||||
fix_mirrors_postmarketos(args)
|
config = pmb.config.load(args)
|
||||||
pmb.config.merge_with_args(args)
|
# pmb.config.merge_with_args(args)
|
||||||
replace_placeholders(args)
|
# replace_placeholders(args)
|
||||||
|
|
||||||
# Configure runtime context
|
# Configure runtime context
|
||||||
context = pmb.core.get_context()
|
context = Context(config)
|
||||||
context.command_timeout = args.timeout
|
context.command_timeout = args.timeout
|
||||||
context.details_to_stdout = args.details_to_stdout
|
context.details_to_stdout = args.details_to_stdout
|
||||||
context.sudo_timer = args.sudo_timer
|
|
||||||
context.quiet = args.quiet
|
context.quiet = args.quiet
|
||||||
context.offline = args.offline
|
context.offline = args.offline
|
||||||
|
context.command = args.action
|
||||||
|
context.cross = args.cross
|
||||||
|
if args.mirrors_postmarketos:
|
||||||
|
context.config.mirrors_postmarketos = args.mirrors_postmarketos
|
||||||
|
if args.mirror_alpine:
|
||||||
|
context.config.mirror_alpine = args.mirror_alpine
|
||||||
if args.aports:
|
if args.aports:
|
||||||
print(f"Using pmaports from: {args.aports}")
|
print(f"Using pmaports from: {args.aports}")
|
||||||
context.aports = args.aports
|
context.config.aports = args.aports
|
||||||
|
|
||||||
|
# Initialize context
|
||||||
|
pmb.core.set_context(context)
|
||||||
|
|
||||||
# Initialize logs (we could raise errors below)
|
# Initialize logs (we could raise errors below)
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
|
@ -133,19 +120,22 @@ def init(args: PmbArgs) -> PmbArgs:
|
||||||
check_pmaports_path(args)
|
check_pmaports_path(args)
|
||||||
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
if args.action not in ["init", "checksum", "config", "bootimg_analyze", "log",
|
||||||
"pull", "shutdown", "zap"]:
|
"pull", "shutdown", "zap"]:
|
||||||
pmb.config.pmaports.read_config(args)
|
pmb.config.pmaports.read_config()
|
||||||
add_deviceinfo(args)
|
add_deviceinfo(args)
|
||||||
pmb.helpers.git.parse_channels_cfg()
|
pmb.helpers.git.parse_channels_cfg(config.aports)
|
||||||
context.device_arch = args.deviceinfo["arch"]
|
context.device_arch = args.deviceinfo["arch"]
|
||||||
|
|
||||||
# Remove attributes from args so they don't get used by mistake
|
# Remove attributes from args so they don't get used by mistake
|
||||||
delattr(args, "timeout")
|
delattr(args, "timeout")
|
||||||
delattr(args, "details_to_stdout")
|
delattr(args, "details_to_stdout")
|
||||||
delattr(args, "sudo_timer")
|
|
||||||
delattr(args, "log")
|
delattr(args, "log")
|
||||||
delattr(args, "quiet")
|
delattr(args, "quiet")
|
||||||
delattr(args, "offline")
|
delattr(args, "offline")
|
||||||
delattr(args, "aports")
|
delattr(args, "aports")
|
||||||
|
delattr(args, "mirrors_postmarketos")
|
||||||
|
delattr(args, "mirror_alpine")
|
||||||
|
# args.work is deprecated!
|
||||||
|
delattr(args, "work")
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import readline
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,17 @@
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.core import get_context
|
||||||
import pmb.parse
|
|
||||||
|
|
||||||
|
|
||||||
def find_path(args: PmbArgs, codename: str, file='') -> Optional[Path]:
|
def find_path(codename: str, file='') -> Optional[Path]:
|
||||||
"""Find path to device APKBUILD under `device/*/device-`.
|
"""Find path to device APKBUILD under `device/*/device-`.
|
||||||
|
|
||||||
:param codename: device codename
|
:param codename: device codename
|
||||||
:param file: file to look for (e.g. APKBUILD or deviceinfo), may be empty
|
:param file: file to look for (e.g. APKBUILD or deviceinfo), may be empty
|
||||||
:returns: path to APKBUILD
|
:returns: path to APKBUILD
|
||||||
"""
|
"""
|
||||||
g = list((args.aports / "device").glob(f"*/device-{codename}/{file}"))
|
g = list((get_context().config.aports / "device").glob(f"*/device-{codename}/{file}"))
|
||||||
if not g:
|
if not g:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -25,7 +24,7 @@ def find_path(args: PmbArgs, codename: str, file='') -> Optional[Path]:
|
||||||
return g[0]
|
return g[0]
|
||||||
|
|
||||||
|
|
||||||
def list_codenames(args: PmbArgs, vendor=None, archived=True):
|
def list_codenames(aports: Path, vendor=None, archived=True):
|
||||||
"""Get all devices, for which aports are available.
|
"""Get all devices, for which aports are available.
|
||||||
|
|
||||||
:param vendor: vendor name to choose devices from, or None for all vendors
|
:param vendor: vendor name to choose devices from, or None for all vendors
|
||||||
|
@ -33,7 +32,7 @@ def list_codenames(args: PmbArgs, vendor=None, archived=True):
|
||||||
:returns: ["first-device", "second-device", ...]
|
:returns: ["first-device", "second-device", ...]
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for path in args.aports.glob("device/*/device-*"):
|
for path in aports.glob("device/*/device-*"):
|
||||||
if not archived and 'archived' in path.parts:
|
if not archived and 'archived' in path.parts:
|
||||||
continue
|
continue
|
||||||
device = os.path.basename(path).split("-", 1)[1]
|
device = os.path.basename(path).split("-", 1)[1]
|
||||||
|
@ -42,30 +41,13 @@ def list_codenames(args: PmbArgs, vendor=None, archived=True):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def list_vendors(args: PmbArgs):
|
def list_vendors(aports: Path):
|
||||||
"""Get all device vendors, for which aports are available.
|
"""Get all device vendors, for which aports are available.
|
||||||
|
|
||||||
:returns: {"vendor1", "vendor2", ...}
|
:returns: {"vendor1", "vendor2", ...}
|
||||||
"""
|
"""
|
||||||
ret = set()
|
ret = set()
|
||||||
for path in (args.aports / "device").glob("*/device-*"):
|
for path in (aports / "device").glob("*/device-*"):
|
||||||
vendor = path.name.split("-", 2)[1]
|
vendor = path.name.split("-", 2)[1]
|
||||||
ret.add(vendor)
|
ret.add(vendor)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def list_apkbuilds(args: PmbArgs):
|
|
||||||
""":returns: { "first-device": {"pkgname": ..., "pkgver": ...}, ... }"""
|
|
||||||
ret = {}
|
|
||||||
for device in list_codenames(args):
|
|
||||||
apkbuild_path = next(args.aports.glob(f"device/*/device-{device}/APKBUILD"))
|
|
||||||
ret[device] = pmb.parse.apkbuild(apkbuild_path)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def list_deviceinfos(args: PmbArgs):
|
|
||||||
""":returns: { "first-device": {"name": ..., "screen_width": ...}, ... }"""
|
|
||||||
ret = {}
|
|
||||||
for device in list_codenames(args):
|
|
||||||
ret[device] = pmb.parse.deviceinfo(args, device)
|
|
||||||
return ret
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ def replace_apkbuild(args: PmbArgs, pkgname, key, new, in_quotes=False):
|
||||||
:param in_quotes: expect the value to be in quotation marks ("")
|
:param in_quotes: expect the value to be in quotation marks ("")
|
||||||
"""
|
"""
|
||||||
# Read old value
|
# Read old value
|
||||||
path = pmb.helpers.pmaports.find(args, pkgname) / "APKBUILD"
|
path = pmb.helpers.pmaports.find(pkgname) / "APKBUILD"
|
||||||
apkbuild = pmb.parse.apkbuild(path)
|
apkbuild = pmb.parse.apkbuild(path)
|
||||||
old = apkbuild[key]
|
old = apkbuild[key]
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import pmb.chroot.initfs
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
import pmb.ci
|
import pmb.ci
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import Config, PathString, PmbArgs
|
||||||
import pmb.export
|
import pmb.export
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.aportupgrade
|
import pmb.helpers.aportupgrade
|
||||||
|
@ -37,7 +37,7 @@ import pmb.netboot
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
import pmb.qemu
|
import pmb.qemu
|
||||||
import pmb.sideload
|
import pmb.sideload
|
||||||
from pmb.core import ChrootType, Chroot
|
from pmb.core import ChrootType, Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def _parse_flavor(args: PmbArgs, autoinstall=True):
|
def _parse_flavor(args: PmbArgs, autoinstall=True):
|
||||||
|
@ -62,7 +62,7 @@ def _parse_flavor(args: PmbArgs, autoinstall=True):
|
||||||
|
|
||||||
def _parse_suffix(args: PmbArgs) -> Chroot:
|
def _parse_suffix(args: PmbArgs) -> Chroot:
|
||||||
if "rootfs" in args and args.rootfs:
|
if "rootfs" in args and args.rootfs:
|
||||||
return Chroot(ChrootType.ROOTFS, args.device)
|
return Chroot(ChrootType.ROOTFS, get_context().config.device)
|
||||||
elif args.buildroot:
|
elif args.buildroot:
|
||||||
if args.buildroot == "device":
|
if args.buildroot == "device":
|
||||||
return Chroot.buildroot(args.deviceinfo["arch"])
|
return Chroot.buildroot(args.deviceinfo["arch"])
|
||||||
|
@ -122,10 +122,11 @@ def build(args: PmbArgs):
|
||||||
pmb.helpers.repo_bootstrap.require_bootstrap(args, arch_package,
|
pmb.helpers.repo_bootstrap.require_bootstrap(args, arch_package,
|
||||||
f"build {package} for {arch_package}")
|
f"build {package} for {arch_package}")
|
||||||
|
|
||||||
|
context = get_context()
|
||||||
# Build all packages
|
# Build all packages
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
arch_package = args.arch or pmb.build.autodetect.arch(args, package)
|
||||||
if not pmb.build.package(args, package, arch_package, force,
|
if not pmb.build.package(context, package, arch_package, force,
|
||||||
args.strict, src=src):
|
args.strict, src=src):
|
||||||
logging.info("NOTE: Package '" + package + "' is up to date. Use"
|
logging.info("NOTE: Package '" + package + "' is up to date. Use"
|
||||||
" 'pmbootstrap build " + package + " --force'"
|
" 'pmbootstrap build " + package + " --force'"
|
||||||
|
@ -169,11 +170,11 @@ def chroot(args: PmbArgs):
|
||||||
raise RuntimeError("--xauth is only supported for native chroot.")
|
raise RuntimeError("--xauth is only supported for native chroot.")
|
||||||
|
|
||||||
# apk: check minimum version, install packages
|
# apk: check minimum version, install packages
|
||||||
pmb.chroot.apk.check_min_version(args, suffix)
|
pmb.chroot.apk.check_min_version(suffix)
|
||||||
if args.add:
|
if args.add:
|
||||||
pmb.chroot.apk.install(args, args.add.split(","), suffix)
|
pmb.chroot.apk.install(args.add.split(","), suffix)
|
||||||
|
|
||||||
pmb.chroot.init(args, suffix)
|
pmb.chroot.init(suffix)
|
||||||
|
|
||||||
# Xauthority
|
# Xauthority
|
||||||
env = {}
|
env = {}
|
||||||
|
@ -198,11 +199,11 @@ def chroot(args: PmbArgs):
|
||||||
if args.user:
|
if args.user:
|
||||||
logging.info(f"({suffix}) % su pmos -c '" +
|
logging.info(f"({suffix}) % su pmos -c '" +
|
||||||
" ".join(args.command) + "'")
|
" ".join(args.command) + "'")
|
||||||
pmb.chroot.user(args, args.command, suffix, output=args.output,
|
pmb.chroot.user(args.command, suffix, output=args.output,
|
||||||
env=env)
|
env=env)
|
||||||
else:
|
else:
|
||||||
logging.info(f"({suffix}) % " + " ".join(args.command))
|
logging.info(f"({suffix}) % " + " ".join(args.command))
|
||||||
pmb.chroot.root(args, args.command, suffix, output=args.output,
|
pmb.chroot.root(args.command, suffix, output=args.output,
|
||||||
env=env)
|
env=env)
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,24 +213,27 @@ def config(args: PmbArgs):
|
||||||
logging.info("NOTE: Valid config keys: " + ", ".join(keys))
|
logging.info("NOTE: Valid config keys: " + ", ".join(keys))
|
||||||
raise RuntimeError("Invalid config key: " + args.name)
|
raise RuntimeError("Invalid config key: " + args.name)
|
||||||
|
|
||||||
cfg = pmb.config.load(args)
|
config = pmb.config.load(args)
|
||||||
if args.reset:
|
if args.reset:
|
||||||
if args.name is None:
|
if args.name is None:
|
||||||
raise RuntimeError("config --reset requires a name to be given.")
|
raise RuntimeError("config --reset requires a name to be given.")
|
||||||
value = pmb.config.defaults[args.name]
|
def_value = getattr(Config(), args.name)
|
||||||
cfg["pmbootstrap"][args.name] = value
|
setattr(config, args.name, def_value)
|
||||||
logging.info(f"Config changed to default: {args.name}='{value}'")
|
logging.info(f"Config changed to default: {args.name}='{value}'")
|
||||||
pmb.config.save(args, cfg)
|
pmb.config.save(args.config, config)
|
||||||
elif args.value is not None:
|
elif args.value is not None:
|
||||||
cfg["pmbootstrap"][args.name] = args.value
|
setattr(config, args.name, args.value)
|
||||||
pmb.config.sanity_checks(args, cfg, False)
|
pmb.config.sanity_checks(args, config, False)
|
||||||
logging.info("Config changed: " + args.name + "='" + args.value + "'")
|
logging.info("Config changed: " + args.name + "='" + args.value + "'")
|
||||||
pmb.config.save(args, cfg)
|
pmb.config.save(args.config, config)
|
||||||
elif args.name:
|
elif args.name:
|
||||||
value = cfg["pmbootstrap"].get(args.name, "")
|
if hasattr(config, args.name):
|
||||||
|
value = getattr(config, args.name)
|
||||||
|
else:
|
||||||
|
value = ""
|
||||||
print(value)
|
print(value)
|
||||||
else:
|
else:
|
||||||
cfg.write(sys.stdout)
|
print(open(args.config).read())
|
||||||
|
|
||||||
# Don't write the "Done" message
|
# Don't write the "Done" message
|
||||||
pmb.helpers.logging.disable()
|
pmb.helpers.logging.disable()
|
||||||
|
@ -240,7 +244,7 @@ def repo_bootstrap(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def repo_missing(args: PmbArgs):
|
def repo_missing(args: PmbArgs):
|
||||||
missing = pmb.helpers.repo_missing.generate(args, args.arch, args.overview,
|
missing = pmb.helpers.repo_missing.generate(args.arch, args.overview,
|
||||||
args.package, args.built)
|
args.package, args.built)
|
||||||
print(json.dumps(missing, indent=4))
|
print(json.dumps(missing, indent=4))
|
||||||
|
|
||||||
|
@ -344,7 +348,7 @@ def install(args: PmbArgs):
|
||||||
args.build_pkgs_on_install = False
|
args.build_pkgs_on_install = False
|
||||||
|
|
||||||
# Safest way to avoid installing local packages is having none
|
# Safest way to avoid installing local packages is having none
|
||||||
if (pmb.config.work / "packages").glob("*"):
|
if (get_context().config.work / "packages").glob("*"):
|
||||||
raise ValueError("--no-local-pkgs specified, but locally built"
|
raise ValueError("--no-local-pkgs specified, but locally built"
|
||||||
" packages found. Consider 'pmbootstrap zap -p'"
|
" packages found. Consider 'pmbootstrap zap -p'"
|
||||||
" to delete them.")
|
" to delete them.")
|
||||||
|
@ -365,7 +369,7 @@ def export(args: PmbArgs):
|
||||||
|
|
||||||
def update(args: PmbArgs):
|
def update(args: PmbArgs):
|
||||||
existing_only = not args.non_existing
|
existing_only = not args.non_existing
|
||||||
if not pmb.helpers.repo.update(args, args.arch, True, existing_only):
|
if not pmb.helpers.repo.update(args.arch, True, existing_only):
|
||||||
logging.info("No APKINDEX files exist, so none have been updated."
|
logging.info("No APKINDEX files exist, so none have been updated."
|
||||||
" The pmbootstrap command downloads the APKINDEX files on"
|
" The pmbootstrap command downloads the APKINDEX files on"
|
||||||
" demand.")
|
" demand.")
|
||||||
|
@ -430,7 +434,7 @@ def kconfig(args: PmbArgs):
|
||||||
else:
|
else:
|
||||||
packages = [args.package]
|
packages = [args.package]
|
||||||
if not args.package:
|
if not args.package:
|
||||||
for pkg in pmb.helpers.pmaports.get_list(args):
|
for pkg in pmb.helpers.pmaports.get_list():
|
||||||
if pkg.startswith("linux-"):
|
if pkg.startswith("linux-"):
|
||||||
packages.append(pkg.split("linux-")[1])
|
packages.append(pkg.split("linux-")[1])
|
||||||
|
|
||||||
|
@ -442,7 +446,7 @@ def kconfig(args: PmbArgs):
|
||||||
if not args.force:
|
if not args.force:
|
||||||
pkgname = package if package.startswith("linux-") \
|
pkgname = package if package.startswith("linux-") \
|
||||||
else "linux-" + package
|
else "linux-" + package
|
||||||
aport = pmb.helpers.pmaports.find(args, pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
apkbuild = pmb.parse.apkbuild(aport)
|
apkbuild = pmb.parse.apkbuild(aport)
|
||||||
if "!pmb:kconfigcheck" in apkbuild["options"]:
|
if "!pmb:kconfigcheck" in apkbuild["options"]:
|
||||||
skipped += 1
|
skipped += 1
|
||||||
|
@ -472,13 +476,13 @@ def deviceinfo_parse(args: PmbArgs):
|
||||||
# Default to all devices
|
# Default to all devices
|
||||||
devices = args.devices
|
devices = args.devices
|
||||||
if not devices:
|
if not devices:
|
||||||
devices = pmb.helpers.devices.list_codenames(args)
|
devices = pmb.helpers.devices.list_codenames(get_context().config.aports)
|
||||||
|
|
||||||
# Iterate over all devices
|
# Iterate over all devices
|
||||||
kernel = args.deviceinfo_parse_kernel
|
kernel = args.deviceinfo_parse_kernel
|
||||||
for device in devices:
|
for device in devices:
|
||||||
print(f"{device}, with kernel={kernel}:")
|
print(f"{device}, with kernel={kernel}:")
|
||||||
print(json.dumps(pmb.parse.deviceinfo(args, device, kernel), indent=4,
|
print(json.dumps(pmb.parse.deviceinfo(device, kernel), indent=4,
|
||||||
sort_keys=True))
|
sort_keys=True))
|
||||||
|
|
||||||
|
|
||||||
|
@ -486,12 +490,12 @@ def apkbuild_parse(args: PmbArgs):
|
||||||
# Default to all packages
|
# Default to all packages
|
||||||
packages: Sequence[str] = args.packages
|
packages: Sequence[str] = args.packages
|
||||||
if not packages:
|
if not packages:
|
||||||
packages = pmb.helpers.pmaports.get_list(args)
|
packages = pmb.helpers.pmaports.get_list()
|
||||||
|
|
||||||
# Iterate over all packages
|
# Iterate over all packages
|
||||||
for package in packages:
|
for package in packages:
|
||||||
print(package + ":")
|
print(package + ":")
|
||||||
aport = pmb.helpers.pmaports.find(args, package)
|
aport = pmb.helpers.pmaports.find(package)
|
||||||
print(json.dumps(pmb.parse.apkbuild(aport), indent=4,
|
print(json.dumps(pmb.parse.apkbuild(aport), indent=4,
|
||||||
sort_keys=True))
|
sort_keys=True))
|
||||||
|
|
||||||
|
@ -512,7 +516,7 @@ def pkgrel_bump(args: PmbArgs):
|
||||||
else:
|
else:
|
||||||
# Each package must exist
|
# Each package must exist
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
pmb.helpers.pmaports.find(args, package)
|
pmb.helpers.pmaports.find(package)
|
||||||
|
|
||||||
# Increase pkgrel
|
# Increase pkgrel
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
|
@ -529,7 +533,7 @@ def aportupgrade(args: PmbArgs):
|
||||||
else:
|
else:
|
||||||
# Each package must exist
|
# Each package must exist
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
pmb.helpers.pmaports.find(args, package)
|
pmb.helpers.pmaports.find(package)
|
||||||
|
|
||||||
# Check each package for a new version
|
# Check each package for a new version
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
|
@ -551,9 +555,9 @@ def stats(args: PmbArgs):
|
||||||
chroot = Chroot.buildroot(args.arch)
|
chroot = Chroot.buildroot(args.arch)
|
||||||
|
|
||||||
# Install ccache and display stats
|
# Install ccache and display stats
|
||||||
pmb.chroot.apk.install(args, ["ccache"], chroot)
|
pmb.chroot.apk.install(["ccache"], chroot)
|
||||||
logging.info(f"({chroot}) % ccache -s")
|
logging.info(f"({chroot}) % ccache -s")
|
||||||
pmb.chroot.user(args, ["ccache", "-s"], chroot, output="stdout")
|
pmb.chroot.user(["ccache", "-s"], chroot, output="stdout")
|
||||||
|
|
||||||
|
|
||||||
def work_migrate(args: PmbArgs):
|
def work_migrate(args: PmbArgs):
|
||||||
|
@ -581,7 +585,7 @@ def bootimg_analyze(args: PmbArgs):
|
||||||
logging.info(tmp_output)
|
logging.info(tmp_output)
|
||||||
|
|
||||||
|
|
||||||
def pull(args: PmbArgs):
|
def pull():
|
||||||
failed = []
|
failed = []
|
||||||
for repo in pmb.config.git_repos.keys():
|
for repo in pmb.config.git_repos.keys():
|
||||||
if pmb.helpers.git.pull(repo) < 0:
|
if pmb.helpers.git.pull(repo) < 0:
|
||||||
|
@ -610,7 +614,7 @@ def pull(args: PmbArgs):
|
||||||
def lint(args: PmbArgs):
|
def lint(args: PmbArgs):
|
||||||
packages: Sequence[str] = args.packages
|
packages: Sequence[str] = args.packages
|
||||||
if not packages:
|
if not packages:
|
||||||
packages = pmb.helpers.pmaports.get_list(args)
|
packages = pmb.helpers.pmaports.get_list()
|
||||||
|
|
||||||
pmb.helpers.lint.check(args, packages)
|
pmb.helpers.lint.check(args, packages)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import pmb.helpers.pmaports
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
|
||||||
|
|
||||||
def get_path(context: Context, name_repo):
|
def get_path(name_repo: str):
|
||||||
"""Get the path to the repository.
|
"""Get the path to the repository.
|
||||||
|
|
||||||
The path is either the default one in the work dir, or a user-specified one in args.
|
The path is either the default one in the work dir, or a user-specified one in args.
|
||||||
|
@ -24,8 +24,8 @@ def get_path(context: Context, name_repo):
|
||||||
:returns: full path to repository
|
:returns: full path to repository
|
||||||
"""
|
"""
|
||||||
if name_repo == "pmaports":
|
if name_repo == "pmaports":
|
||||||
return context.aports
|
return get_context().config.aports
|
||||||
return pmb.config.work / "cache_git" / name_repo
|
return get_context().config.work / "cache_git" / name_repo
|
||||||
|
|
||||||
|
|
||||||
def clone(name_repo):
|
def clone(name_repo):
|
||||||
|
@ -40,7 +40,7 @@ def clone(name_repo):
|
||||||
if name_repo not in pmb.config.git_repos:
|
if name_repo not in pmb.config.git_repos:
|
||||||
raise ValueError("No git repository configured for " + name_repo)
|
raise ValueError("No git repository configured for " + name_repo)
|
||||||
|
|
||||||
path = get_path(get_context(), name_repo)
|
path = get_path(name_repo)
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
# Build git command
|
# Build git command
|
||||||
url = pmb.config.git_repos[name_repo][0]
|
url = pmb.config.git_repos[name_repo][0]
|
||||||
|
@ -49,7 +49,7 @@ def clone(name_repo):
|
||||||
|
|
||||||
# Create parent dir and clone
|
# Create parent dir and clone
|
||||||
logging.info("Clone git repository: " + url)
|
logging.info("Clone git repository: " + url)
|
||||||
os.makedirs(pmb.config.work / "cache_git", exist_ok=True)
|
os.makedirs(get_context().config.work / "cache_git", exist_ok=True)
|
||||||
pmb.helpers.run.user(command, output="stdout")
|
pmb.helpers.run.user(command, output="stdout")
|
||||||
|
|
||||||
# FETCH_HEAD does not exist after initial clone. Create it, so
|
# FETCH_HEAD does not exist after initial clone. Create it, so
|
||||||
|
@ -59,7 +59,7 @@ def clone(name_repo):
|
||||||
open(fetch_head, "w").close()
|
open(fetch_head, "w").close()
|
||||||
|
|
||||||
|
|
||||||
def rev_parse(path, revision="HEAD", extra_args: list = []):
|
def rev_parse(path: Path, revision="HEAD", extra_args: list = []):
|
||||||
"""Run "git rev-parse" in a specific repository dir.
|
"""Run "git rev-parse" in a specific repository dir.
|
||||||
|
|
||||||
:param path: to the git repository
|
:param path: to the git repository
|
||||||
|
@ -84,29 +84,29 @@ def can_fast_forward(path, branch_upstream, branch="HEAD"):
|
||||||
raise RuntimeError("Unexpected exit code from git: " + str(ret))
|
raise RuntimeError("Unexpected exit code from git: " + str(ret))
|
||||||
|
|
||||||
|
|
||||||
def clean_worktree(path):
|
def clean_worktree(path: Path):
|
||||||
"""Check if there are not any modified files in the git dir."""
|
"""Check if there are not any modified files in the git dir."""
|
||||||
command = ["git", "status", "--porcelain"]
|
command = ["git", "status", "--porcelain"]
|
||||||
return pmb.helpers.run.user_output(command, path) == ""
|
return pmb.helpers.run.user_output(command, path) == ""
|
||||||
|
|
||||||
|
|
||||||
def get_upstream_remote(context: Context, name_repo):
|
def get_upstream_remote(aports: Path):
|
||||||
"""Find the remote, which matches the git URL from the config.
|
"""Find the remote, which matches the git URL from the config.
|
||||||
|
|
||||||
Usually "origin", but the user may have set up their git repository differently.
|
Usually "origin", but the user may have set up their git repository differently.
|
||||||
"""
|
"""
|
||||||
|
name_repo = aports.parts[-1]
|
||||||
urls = pmb.config.git_repos[name_repo]
|
urls = pmb.config.git_repos[name_repo]
|
||||||
path = get_path(context, name_repo)
|
|
||||||
command = ["git", "remote", "-v"]
|
command = ["git", "remote", "-v"]
|
||||||
output = pmb.helpers.run.user_output(command, path)
|
output = pmb.helpers.run.user_output(command, aports)
|
||||||
for line in output.split("\n"):
|
for line in output.split("\n"):
|
||||||
if any(u in line for u in urls):
|
if any(u in line for u in urls):
|
||||||
return line.split("\t", 1)[0]
|
return line.split("\t", 1)[0]
|
||||||
raise RuntimeError("{}: could not find remote name for any URL '{}' in git"
|
raise RuntimeError("{}: could not find remote name for any URL '{}' in git"
|
||||||
" repository: {}".format(name_repo, urls, path))
|
" repository: {}".format(name_repo, urls, aports))
|
||||||
|
|
||||||
|
|
||||||
def parse_channels_cfg():
|
def parse_channels_cfg(aports: Path):
|
||||||
"""Parse channels.cfg from pmaports.git, origin/master branch.
|
"""Parse channels.cfg from pmaports.git, origin/master branch.
|
||||||
|
|
||||||
Reference: https://postmarketos.org/channels.cfg
|
Reference: https://postmarketos.org/channels.cfg
|
||||||
|
@ -123,13 +123,11 @@ def parse_channels_cfg():
|
||||||
if pmb.helpers.other.cache[cache_key]:
|
if pmb.helpers.other.cache[cache_key]:
|
||||||
return pmb.helpers.other.cache[cache_key]
|
return pmb.helpers.other.cache[cache_key]
|
||||||
|
|
||||||
context = get_context()
|
|
||||||
|
|
||||||
# Read with configparser
|
# Read with configparser
|
||||||
cfg = configparser.ConfigParser()
|
cfg = configparser.ConfigParser()
|
||||||
remote = get_upstream_remote(context, "pmaports")
|
remote = get_upstream_remote(aports)
|
||||||
command = ["git", "show", f"{remote}/master:channels.cfg"]
|
command = ["git", "show", f"{remote}/master:channels.cfg"]
|
||||||
stdout = pmb.helpers.run.user_output(command, context.aports,
|
stdout = pmb.helpers.run.user_output(command, aports,
|
||||||
check=False)
|
check=False)
|
||||||
try:
|
try:
|
||||||
cfg.read_string(stdout)
|
cfg.read_string(stdout)
|
||||||
|
@ -162,7 +160,7 @@ def parse_channels_cfg():
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_branches_official(name_repo):
|
def get_branches_official(repo: Path):
|
||||||
"""Get all branches that point to official release channels.
|
"""Get all branches that point to official release channels.
|
||||||
|
|
||||||
:returns: list of supported branches, e.g. ["master", "3.11"]
|
:returns: list of supported branches, e.g. ["master", "3.11"]
|
||||||
|
@ -170,17 +168,17 @@ def get_branches_official(name_repo):
|
||||||
# This functions gets called with pmaports and aports_upstream, because
|
# This functions gets called with pmaports and aports_upstream, because
|
||||||
# both are displayed in "pmbootstrap status". But it only makes sense
|
# both are displayed in "pmbootstrap status". But it only makes sense
|
||||||
# to display pmaports there, related code will be refactored soon (#1903).
|
# to display pmaports there, related code will be refactored soon (#1903).
|
||||||
if name_repo != "pmaports":
|
if repo.parts[-1] != "pmaports":
|
||||||
return ["master"]
|
return ["master"]
|
||||||
|
|
||||||
channels_cfg = parse_channels_cfg()
|
channels_cfg = parse_channels_cfg(repo)
|
||||||
ret = []
|
ret = []
|
||||||
for channel, channel_data in channels_cfg["channels"].items():
|
for channel, channel_data in channels_cfg["channels"].items():
|
||||||
ret.append(channel_data["branch_pmaports"])
|
ret.append(channel_data["branch_pmaports"])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def pull(name_repo):
|
def pull(repo_name: str):
|
||||||
"""Check if on official branch and essentially try ``git pull --ff-only``.
|
"""Check if on official branch and essentially try ``git pull --ff-only``.
|
||||||
|
|
||||||
Instead of really doing ``git pull --ff-only``, do it in multiple steps
|
Instead of really doing ``git pull --ff-only``, do it in multiple steps
|
||||||
|
@ -189,18 +187,17 @@ def pull(name_repo):
|
||||||
|
|
||||||
:returns: integer, >= 0 on success, < 0 on error
|
:returns: integer, >= 0 on success, < 0 on error
|
||||||
"""
|
"""
|
||||||
branches_official = get_branches_official(name_repo)
|
repo = get_path(repo_name)
|
||||||
context = get_context()
|
branches_official = get_branches_official(repo)
|
||||||
|
|
||||||
# Skip if repo wasn't cloned
|
# Skip if repo wasn't cloned
|
||||||
path = get_path(context, name_repo)
|
if not os.path.exists(repo):
|
||||||
if not os.path.exists(path):
|
logging.debug(repo_name + ": repo was not cloned, skipping pull!")
|
||||||
logging.debug(name_repo + ": repo was not cloned, skipping pull!")
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Skip if not on official branch
|
# Skip if not on official branch
|
||||||
branch = rev_parse(path, extra_args=["--abbrev-ref"])
|
branch = rev_parse(repo, extra_args=["--abbrev-ref"])
|
||||||
msg_start = "{} (branch: {}):".format(name_repo, branch)
|
msg_start = "{} (branch: {}):".format(repo_name, branch)
|
||||||
if branch not in branches_official:
|
if branch not in branches_official:
|
||||||
logging.warning("{} not on one of the official branches ({}), skipping"
|
logging.warning("{} not on one of the official branches ({}), skipping"
|
||||||
" pull!"
|
" pull!"
|
||||||
|
@ -208,13 +205,13 @@ def pull(name_repo):
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
# Skip if workdir is not clean
|
# Skip if workdir is not clean
|
||||||
if not clean_worktree(path):
|
if not clean_worktree(repo):
|
||||||
logging.warning(msg_start + " workdir is not clean, skipping pull!")
|
logging.warning(msg_start + " workdir is not clean, skipping pull!")
|
||||||
return -2
|
return -2
|
||||||
|
|
||||||
# Skip if branch is tracking different remote
|
# Skip if branch is tracking different remote
|
||||||
branch_upstream = get_upstream_remote(context, name_repo) + "/" + branch
|
branch_upstream = get_upstream_remote(repo) + "/" + branch
|
||||||
remote_ref = rev_parse(path, branch + "@{u}", ["--abbrev-ref"])
|
remote_ref = rev_parse(repo, branch + "@{u}", ["--abbrev-ref"])
|
||||||
if remote_ref != branch_upstream:
|
if remote_ref != branch_upstream:
|
||||||
logging.warning("{} is tracking unexpected remote branch '{}' instead"
|
logging.warning("{} is tracking unexpected remote branch '{}' instead"
|
||||||
" of '{}'".format(msg_start, remote_ref,
|
" of '{}'".format(msg_start, remote_ref,
|
||||||
|
@ -223,16 +220,16 @@ def pull(name_repo):
|
||||||
|
|
||||||
# Fetch (exception on failure, meaning connection to server broke)
|
# Fetch (exception on failure, meaning connection to server broke)
|
||||||
logging.info(msg_start + " git pull --ff-only")
|
logging.info(msg_start + " git pull --ff-only")
|
||||||
if not context.offline:
|
if not get_context().offline:
|
||||||
pmb.helpers.run.user(["git", "fetch"], path)
|
pmb.helpers.run.user(["git", "fetch"], repo)
|
||||||
|
|
||||||
# Skip if already up to date
|
# Skip if already up to date
|
||||||
if rev_parse(path, branch) == rev_parse(path, branch_upstream):
|
if rev_parse(repo, branch) == rev_parse(repo, branch_upstream):
|
||||||
logging.info(msg_start + " already up to date")
|
logging.info(msg_start + " already up to date")
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
# Skip if we can't fast-forward
|
# Skip if we can't fast-forward
|
||||||
if not can_fast_forward(path, branch_upstream):
|
if not can_fast_forward(repo, branch_upstream):
|
||||||
logging.warning("{} can't fast-forward to {}, looks like you changed"
|
logging.warning("{} can't fast-forward to {}, looks like you changed"
|
||||||
" the git history of your local branch. Skipping pull!"
|
" the git history of your local branch. Skipping pull!"
|
||||||
"".format(msg_start, branch_upstream))
|
"".format(msg_start, branch_upstream))
|
||||||
|
@ -241,21 +238,21 @@ def pull(name_repo):
|
||||||
# Fast-forward now (should not fail due to checks above, so it's fine to
|
# Fast-forward now (should not fail due to checks above, so it's fine to
|
||||||
# throw an exception on error)
|
# throw an exception on error)
|
||||||
command = ["git", "merge", "--ff-only", branch_upstream]
|
command = ["git", "merge", "--ff-only", branch_upstream]
|
||||||
pmb.helpers.run.user(command, path, "stdout")
|
pmb.helpers.run.user(command, repo, "stdout")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def get_topdir(path: Path):
|
def get_topdir(repo: Path):
|
||||||
"""Get top-dir of git repo.
|
"""Get top-dir of git repo.
|
||||||
|
|
||||||
:returns: a string with the top dir of the git repository,
|
:returns: a string with the top dir of the git repository,
|
||||||
or an empty string if it's not a git repository.
|
or an empty string if it's not a git repository.
|
||||||
"""
|
"""
|
||||||
return pmb.helpers.run.user(["git", "rev-parse", "--show-toplevel"],
|
return pmb.helpers.run.user(["git", "rev-parse", "--show-toplevel"],
|
||||||
path, output_return=True, check=False).rstrip()
|
repo, output_return=True, check=False).rstrip()
|
||||||
|
|
||||||
|
|
||||||
def get_files(path):
|
def get_files(repo: Path):
|
||||||
"""Get all files inside a git repository, that are either already in the git tree or are not in gitignore.
|
"""Get all files inside a git repository, that are either already in the git tree or are not in gitignore.
|
||||||
|
|
||||||
Do not list deleted files. To be used for creating a tarball of the git repository.
|
Do not list deleted files. To be used for creating a tarball of the git repository.
|
||||||
|
@ -265,12 +262,12 @@ def get_files(path):
|
||||||
:returns: all files in a git repository as list, relative to path
|
:returns: all files in a git repository as list, relative to path
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
files = pmb.helpers.run.user_output(["git", "ls-files"], path).split("\n")
|
files = pmb.helpers.run.user_output(["git", "ls-files"], repo).split("\n")
|
||||||
files += pmb.helpers.run.user_output(["git", "ls-files",
|
files += pmb.helpers.run.user_output(["git", "ls-files",
|
||||||
"--exclude-standard", "--other"],
|
"--exclude-standard", "--other"],
|
||||||
path).split("\n")
|
repo).split("\n")
|
||||||
for file in files:
|
for file in files:
|
||||||
if os.path.exists(f"{path}/{file}"):
|
if os.path.exists(f"{repo}/{file}"):
|
||||||
ret += [file]
|
ret += [file]
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -8,7 +8,8 @@ from pathlib import Path
|
||||||
import shutil
|
import shutil
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.core import get_context
|
||||||
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
|
||||||
def cache_file(prefix: str, url: str) -> Path:
|
def cache_file(prefix: str, url: str) -> Path:
|
||||||
|
@ -16,7 +17,7 @@ def cache_file(prefix: str, url: str) -> Path:
|
||||||
return Path(f"{prefix}_{hashlib.sha256(url.encode('utf-8')).hexdigest()}")
|
return Path(f"{prefix}_{hashlib.sha256(url.encode('utf-8')).hexdigest()}")
|
||||||
|
|
||||||
|
|
||||||
def download(args: PmbArgs, url, prefix, cache=True, loglevel=logging.INFO,
|
def download(url, prefix, cache=True, loglevel=logging.INFO,
|
||||||
allow_404=False):
|
allow_404=False):
|
||||||
"""Download a file to disk.
|
"""Download a file to disk.
|
||||||
|
|
||||||
|
@ -34,18 +35,19 @@ def download(args: PmbArgs, url, prefix, cache=True, loglevel=logging.INFO,
|
||||||
:returns: path to the downloaded file in the cache or None on 404
|
:returns: path to the downloaded file in the cache or None on 404
|
||||||
"""
|
"""
|
||||||
# Create cache folder
|
# Create cache folder
|
||||||
if not os.path.exists(pmb.config.work / "cache_http"):
|
context = get_context()
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "cache_http"])
|
if not os.path.exists(context.config.work / "cache_http"):
|
||||||
|
pmb.helpers.run.user(["mkdir", "-p", context.config.work / "cache_http"])
|
||||||
|
|
||||||
# Check if file exists in cache
|
# Check if file exists in cache
|
||||||
path = pmb.config.work / "cache_http" / cache_file(prefix, url)
|
path = context.config.work / "cache_http" / cache_file(prefix, url)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
if cache:
|
if cache:
|
||||||
return path
|
return path
|
||||||
pmb.helpers.run.user(["rm", path])
|
pmb.helpers.run.user(["rm", path])
|
||||||
|
|
||||||
# Offline and not cached
|
# Offline and not cached
|
||||||
if args.offline:
|
if context.offline:
|
||||||
raise RuntimeError("File not found in cache and offline flag is"
|
raise RuntimeError("File not found in cache and offline flag is"
|
||||||
f" enabled: {url}")
|
f" enabled: {url}")
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import os
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.build
|
import pmb.build
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ def check(args: PmbArgs, pkgnames):
|
||||||
|
|
||||||
:param pkgnames: Names of the packages to lint
|
:param pkgnames: Names of the packages to lint
|
||||||
"""
|
"""
|
||||||
pmb.chroot.apk.install(args, ["atools"])
|
pmb.chroot.apk.install(["atools"])
|
||||||
|
|
||||||
# Mount pmaports.git inside the chroot so that we don't have to copy the
|
# Mount pmaports.git inside the chroot so that we don't have to copy the
|
||||||
# package folders
|
# package folders
|
||||||
|
@ -28,7 +28,7 @@ def check(args: PmbArgs, pkgnames):
|
||||||
# root
|
# root
|
||||||
apkbuilds = []
|
apkbuilds = []
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
aport = pmb.helpers.pmaports.find(args, pkgname)
|
aport = pmb.helpers.pmaports.find(pkgname)
|
||||||
if not (aport / "APKBUILD").exists():
|
if not (aport / "APKBUILD").exists():
|
||||||
raise ValueError(f"Path does not contain an APKBUILD file: {aport}")
|
raise ValueError(f"Path does not contain an APKBUILD file: {aport}")
|
||||||
relpath = os.path.relpath(aport, args.aports)
|
relpath = os.path.relpath(aport, args.aports)
|
||||||
|
@ -40,7 +40,7 @@ def check(args: PmbArgs, pkgnames):
|
||||||
pkgstr = ", ".join(pkgnames)
|
pkgstr = ", ".join(pkgnames)
|
||||||
logging.info(f"(native) linting {pkgstr} with apkbuild-lint")
|
logging.info(f"(native) linting {pkgstr} with apkbuild-lint")
|
||||||
options = pmb.config.apkbuild_custom_valid_options
|
options = pmb.config.apkbuild_custom_valid_options
|
||||||
return pmb.chroot.root(args, ["apkbuild-lint"] + apkbuilds,
|
return pmb.chroot.root(["apkbuild-lint"] + apkbuilds,
|
||||||
check=False, output="stdout",
|
check=False, output="stdout",
|
||||||
output_return=True,
|
output_return=True,
|
||||||
working_dir=pmaports,
|
working_dir=pmaports,
|
||||||
|
|
|
@ -7,7 +7,7 @@ from typing import TextIO
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.core.context import Context
|
from pmb.core.context import Context
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
logfd: TextIO
|
logfd: TextIO
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ def add_verbose_log_level():
|
||||||
def init(args: PmbArgs):
|
def init(args: PmbArgs):
|
||||||
"""Set log format and add the log file descriptor to logfd, add the verbose log level."""
|
"""Set log format and add the log file descriptor to logfd, add the verbose log level."""
|
||||||
global logfd
|
global logfd
|
||||||
context = pmb.core.get_context()
|
context = get_context()
|
||||||
# Set log file descriptor (logfd)
|
# Set log file descriptor (logfd)
|
||||||
if context.details_to_stdout:
|
if context.details_to_stdout:
|
||||||
logfd = sys.stdout
|
logfd = sys.stdout
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import os
|
import os
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
from typing import List
|
from typing import List
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers
|
import pmb.helpers
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -7,7 +8,7 @@ import re
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.init
|
import pmb.config.init
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
|
@ -15,7 +16,7 @@ from typing import Dict, Any
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
|
||||||
def folder_size(args: PmbArgs, path: Path):
|
def folder_size(path: Path):
|
||||||
"""Run `du` to calculate the size of a folder.
|
"""Run `du` to calculate the size of a folder.
|
||||||
|
|
||||||
(this is less code and faster than doing the same task in pure Python)
|
(this is less code and faster than doing the same task in pure Python)
|
||||||
|
@ -47,7 +48,7 @@ def check_grsec():
|
||||||
" patchset. This is not supported.")
|
" patchset. This is not supported.")
|
||||||
|
|
||||||
|
|
||||||
def check_binfmt_misc(args):
|
def check_binfmt_misc():
|
||||||
"""Check if the 'binfmt_misc' module is loaded.
|
"""Check if the 'binfmt_misc' module is loaded.
|
||||||
|
|
||||||
This is done by checking, if /proc/sys/fs/binfmt_misc/ exists.
|
This is done by checking, if /proc/sys/fs/binfmt_misc/ exists.
|
||||||
|
@ -71,16 +72,17 @@ def check_binfmt_misc(args):
|
||||||
raise RuntimeError(f"Failed to set up binfmt_misc, see: {link}")
|
raise RuntimeError(f"Failed to set up binfmt_misc, see: {link}")
|
||||||
|
|
||||||
|
|
||||||
def migrate_success(args: PmbArgs, version):
|
def migrate_success(work: Path, version):
|
||||||
logging.info("Migration to version " + str(version) + " done")
|
logging.info("Migration to version " + str(version) + " done")
|
||||||
with open(pmb.config.work / "version", "w") as handle:
|
with open(work / "version", "w") as handle:
|
||||||
handle.write(str(version) + "\n")
|
handle.write(str(version) + "\n")
|
||||||
|
|
||||||
|
|
||||||
def migrate_work_folder(args: PmbArgs):
|
def migrate_work_folder(args: PmbArgs):
|
||||||
# Read current version
|
# Read current version
|
||||||
|
context = get_context()
|
||||||
current = 0
|
current = 0
|
||||||
path = pmb.config.work / "version"
|
path = context.config.work / "version"
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
with open(path, "r") as f:
|
with open(path, "r") as f:
|
||||||
current = int(f.read().rstrip())
|
current = int(f.read().rstrip())
|
||||||
|
@ -100,18 +102,18 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
logging.info("* Building chroots have a different username (#709)")
|
logging.info("* Building chroots have a different username (#709)")
|
||||||
logging.info("Migration will do the following:")
|
logging.info("Migration will do the following:")
|
||||||
logging.info("* Zap your chroots")
|
logging.info("* Zap your chroots")
|
||||||
logging.info(f"* Adjust '{pmb.config.work / 'config_abuild/abuild.conf'}'")
|
logging.info(f"* Adjust '{context.config.work / 'config_abuild/abuild.conf'}'")
|
||||||
if not pmb.helpers.cli.confirm(args):
|
if not pmb.helpers.cli.confirm(args):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
# Zap and update abuild.conf
|
# Zap and update abuild.conf
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(args, False)
|
||||||
conf = pmb.config.work / "config_abuild/abuild.conf"
|
conf = context.config.work / "config_abuild/abuild.conf"
|
||||||
if os.path.exists(conf):
|
if os.path.exists(conf):
|
||||||
pmb.helpers.run.root(["sed", "-i",
|
pmb.helpers.run.root(["sed", "-i",
|
||||||
"s./home/user/./home/pmos/.g", conf])
|
"s./home/user/./home/pmos/.g", conf])
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(args, 1)
|
migrate_success(context.config.work, 1)
|
||||||
current = 1
|
current = 1
|
||||||
|
|
||||||
# 1 => 2
|
# 1 => 2
|
||||||
|
@ -120,7 +122,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
logging.info("Changelog:")
|
logging.info("Changelog:")
|
||||||
logging.info("* Fix: cache_distfiles was writable for everyone")
|
logging.info("* Fix: cache_distfiles was writable for everyone")
|
||||||
logging.info("Migration will do the following:")
|
logging.info("Migration will do the following:")
|
||||||
logging.info(f"* Fix permissions of '{pmb.config.work / 'cache_distfiles'}'")
|
logging.info(f"* Fix permissions of '{context.config.work / 'cache_distfiles'}'")
|
||||||
if not pmb.helpers.cli.confirm(args):
|
if not pmb.helpers.cli.confirm(args):
|
||||||
raise RuntimeError("Aborted.")
|
raise RuntimeError("Aborted.")
|
||||||
|
|
||||||
|
@ -129,8 +131,8 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
for cmd in [["chown", "-R", "root:abuild", dir],
|
for cmd in [["chown", "-R", "root:abuild", dir],
|
||||||
["chmod", "-R", "664", dir],
|
["chmod", "-R", "664", dir],
|
||||||
["chmod", "a+X", dir]]:
|
["chmod", "a+X", dir]]:
|
||||||
pmb.chroot.root(args, cmd)
|
pmb.chroot.root(cmd)
|
||||||
migrate_success(args, 2)
|
migrate_success(context.config.work, 2)
|
||||||
current = 2
|
current = 2
|
||||||
|
|
||||||
if current == 2:
|
if current == 2:
|
||||||
|
@ -146,12 +148,12 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(args, False)
|
||||||
|
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(args, 3)
|
migrate_success(context.config.work, 3)
|
||||||
current = 3
|
current = 3
|
||||||
|
|
||||||
if current == 3:
|
if current == 3:
|
||||||
# Ask for confirmation
|
# Ask for confirmation
|
||||||
path = pmb.config.work / "cache_git"
|
path = context.config.work / "cache_git"
|
||||||
logging.info("Changelog:")
|
logging.info("Changelog:")
|
||||||
logging.info("* pmbootstrap clones repositories with host system's")
|
logging.info("* pmbootstrap clones repositories with host system's")
|
||||||
logging.info(" 'git' instead of using it from an Alpine chroot")
|
logging.info(" 'git' instead of using it from an Alpine chroot")
|
||||||
|
@ -170,7 +172,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
os.makedirs(path, 0o700, True)
|
os.makedirs(path, 0o700, True)
|
||||||
|
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(args, 4)
|
migrate_success(context.config.work, 4)
|
||||||
current = 4
|
current = 4
|
||||||
|
|
||||||
if current == 4:
|
if current == 4:
|
||||||
|
@ -187,23 +189,23 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(args, False)
|
||||||
|
|
||||||
# Move packages to edge subdir
|
# Move packages to edge subdir
|
||||||
edge_path = pmb.config.work / "packages/edge"
|
edge_path = context.config.work / "packages/edge"
|
||||||
pmb.helpers.run.root(["mkdir", "-p", edge_path])
|
pmb.helpers.run.root(["mkdir", "-p", edge_path])
|
||||||
for arch in pmb.config.build_device_architectures:
|
for arch in pmb.config.build_device_architectures:
|
||||||
old_path = pmb.config.work / "packages" / arch
|
old_path = context.config.work / "packages" / arch
|
||||||
new_path = edge_path / arch
|
new_path = edge_path / arch
|
||||||
if old_path.exists():
|
if old_path.exists():
|
||||||
if new_path.exists():
|
if new_path.exists():
|
||||||
raise RuntimeError(f"Won't move '{old_path}' to"
|
raise RuntimeError(f"Won't move '{old_path}' to"
|
||||||
f" '{new_path}', destination already"
|
f" '{new_path}', destination already"
|
||||||
" exists! Consider 'pmbootstrap zap -p'"
|
" exists! Consider 'pmbootstrap zap -p'"
|
||||||
f" to delete '{pmb.config.work}/packages'.")
|
f" to delete '{context.config.work}/packages'.")
|
||||||
pmb.helpers.run.root(["mv", old_path, new_path])
|
pmb.helpers.run.root(["mv", old_path, new_path])
|
||||||
pmb.helpers.run.root(["chown", pmb.config.chroot_uid_user,
|
pmb.helpers.run.root(["chown", pmb.config.chroot_uid_user,
|
||||||
edge_path])
|
edge_path])
|
||||||
|
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(args, 5)
|
migrate_success(context.config.work, 5)
|
||||||
current = 5
|
current = 5
|
||||||
|
|
||||||
if current == 5:
|
if current == 5:
|
||||||
|
@ -214,7 +216,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
logging.info("Migration will do the following:")
|
logging.info("Migration will do the following:")
|
||||||
logging.info("* Zap your chroots")
|
logging.info("* Zap your chroots")
|
||||||
logging.info("* Adjust subdirs of your locally built packages dir:")
|
logging.info("* Adjust subdirs of your locally built packages dir:")
|
||||||
logging.info(f" {pmb.config.work}/packages")
|
logging.info(f" {context.config.work}/packages")
|
||||||
logging.info(" stable => v20.05")
|
logging.info(" stable => v20.05")
|
||||||
logging.info(" stable-next => v21.03")
|
logging.info(" stable-next => v21.03")
|
||||||
if not pmb.helpers.cli.confirm(args):
|
if not pmb.helpers.cli.confirm(args):
|
||||||
|
@ -225,13 +227,13 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
pmb.chroot.zap(args, False)
|
pmb.chroot.zap(args, False)
|
||||||
|
|
||||||
# Migrate
|
# Migrate
|
||||||
packages_dir = f"{pmb.config.work}/packages"
|
packages_dir = f"{context.config.work}/packages"
|
||||||
for old, new in pmb.config.pmaports_channels_legacy.items():
|
for old, new in pmb.config.pmaports_channels_legacy.items():
|
||||||
if os.path.exists(f"{packages_dir}/{old}"):
|
if os.path.exists(f"{packages_dir}/{old}"):
|
||||||
pmb.helpers.run.root(["mv", old, new], packages_dir)
|
pmb.helpers.run.root(["mv", old, new], packages_dir)
|
||||||
|
|
||||||
# Update version file
|
# Update version file
|
||||||
migrate_success(args, 6)
|
migrate_success(context.config.work, 6)
|
||||||
current = 6
|
current = 6
|
||||||
|
|
||||||
# Can't migrate, user must delete it
|
# Can't migrate, user must delete it
|
||||||
|
@ -239,7 +241,7 @@ def migrate_work_folder(args: PmbArgs):
|
||||||
raise RuntimeError("Sorry, we can't migrate that automatically. Please"
|
raise RuntimeError("Sorry, we can't migrate that automatically. Please"
|
||||||
" run 'pmbootstrap shutdown', then delete your"
|
" run 'pmbootstrap shutdown', then delete your"
|
||||||
" current work folder manually ('sudo rm -rf "
|
" current work folder manually ('sudo rm -rf "
|
||||||
f"{pmb.config.work}') and start over with 'pmbootstrap"
|
f"{context.config.work}') and start over with 'pmbootstrap"
|
||||||
" init'. All your binary packages and caches will"
|
" init'. All your binary packages and caches will"
|
||||||
" be lost.")
|
" be lost.")
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import copy
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ def remove_operators(package):
|
||||||
return package
|
return package
|
||||||
|
|
||||||
|
|
||||||
def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True):
|
def get(pkgname, arch, replace_subpkgnames=False, must_exist=True):
|
||||||
"""Find a package in pmaports, and as fallback in the APKINDEXes of the binary packages.
|
"""Find a package in pmaports, and as fallback in the APKINDEXes of the binary packages.
|
||||||
|
|
||||||
:param pkgname: package name (e.g. "hello-world")
|
:param pkgname: package name (e.g. "hello-world")
|
||||||
|
@ -59,7 +59,7 @@ def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True
|
||||||
|
|
||||||
# Find in pmaports
|
# Find in pmaports
|
||||||
ret: Dict[str, Any] = {}
|
ret: Dict[str, Any] = {}
|
||||||
pmaport = pmb.helpers.pmaports.get(args, pkgname, False)
|
pmaport = pmb.helpers.pmaports.get(pkgname, False)
|
||||||
if pmaport:
|
if pmaport:
|
||||||
ret = {"arch": pmaport["arch"],
|
ret = {"arch": pmaport["arch"],
|
||||||
"depends": pmb.build._package.get_depends(args, pmaport),
|
"depends": pmb.build._package.get_depends(args, pmaport),
|
||||||
|
@ -69,8 +69,8 @@ def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True
|
||||||
|
|
||||||
# Find in APKINDEX (given arch)
|
# Find in APKINDEX (given arch)
|
||||||
if not ret or not pmb.helpers.pmaports.check_arches(ret["arch"], arch):
|
if not ret or not pmb.helpers.pmaports.check_arches(ret["arch"], arch):
|
||||||
pmb.helpers.repo.update(args, arch)
|
pmb.helpers.repo.update(arch)
|
||||||
ret_repo = pmb.parse.apkindex.package(args, pkgname, arch, False)
|
ret_repo = pmb.parse.apkindex.package(pkgname, arch, False)
|
||||||
|
|
||||||
# Save as result if there was no pmaport, or if the pmaport can not be
|
# Save as result if there was no pmaport, or if the pmaport can not be
|
||||||
# built for the given arch, but there is a binary package for that arch
|
# built for the given arch, but there is a binary package for that arch
|
||||||
|
@ -80,10 +80,10 @@ def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True
|
||||||
|
|
||||||
# Find in APKINDEX (other arches)
|
# Find in APKINDEX (other arches)
|
||||||
if not ret:
|
if not ret:
|
||||||
pmb.helpers.repo.update(args)
|
pmb.helpers.repo.update()
|
||||||
for arch_i in pmb.config.build_device_architectures:
|
for arch_i in pmb.config.build_device_architectures:
|
||||||
if arch_i != arch:
|
if arch_i != arch:
|
||||||
ret = pmb.parse.apkindex.package(args, pkgname, arch_i, False)
|
ret = pmb.parse.apkindex.package(pkgname, arch_i, False)
|
||||||
if ret:
|
if ret:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True
|
||||||
if replace_subpkgnames:
|
if replace_subpkgnames:
|
||||||
depends_new = []
|
depends_new = []
|
||||||
for depend in ret["depends"]:
|
for depend in ret["depends"]:
|
||||||
depend_data = get(args, depend, arch, must_exist=False)
|
depend_data = get(depend, arch, must_exist=False)
|
||||||
if not depend_data:
|
if not depend_data:
|
||||||
logging.warning(f"WARNING: {pkgname}: failed to resolve"
|
logging.warning(f"WARNING: {pkgname}: failed to resolve"
|
||||||
f" dependency '{depend}'")
|
f" dependency '{depend}'")
|
||||||
|
@ -131,7 +131,7 @@ def get(args: PmbArgs, pkgname, arch, replace_subpkgnames=False, must_exist=True
|
||||||
" could not find this package in any APKINDEX!")
|
" could not find this package in any APKINDEX!")
|
||||||
|
|
||||||
|
|
||||||
def depends_recurse(args: PmbArgs, pkgname, arch):
|
def depends_recurse(pkgname, arch):
|
||||||
"""Recursively resolve all of the package's dependencies.
|
"""Recursively resolve all of the package's dependencies.
|
||||||
|
|
||||||
:param pkgname: name of the package (e.g. "device-samsung-i9100")
|
:param pkgname: name of the package (e.g. "device-samsung-i9100")
|
||||||
|
@ -151,7 +151,7 @@ def depends_recurse(args: PmbArgs, pkgname, arch):
|
||||||
ret = []
|
ret = []
|
||||||
while len(queue):
|
while len(queue):
|
||||||
pkgname_queue = queue.pop()
|
pkgname_queue = queue.pop()
|
||||||
package = get(args, pkgname_queue, arch)
|
package = get(pkgname_queue, arch)
|
||||||
|
|
||||||
# Add its depends to the queue
|
# Add its depends to the queue
|
||||||
for depend in package["depends"]:
|
for depend in package["depends"]:
|
||||||
|
@ -170,7 +170,7 @@ def depends_recurse(args: PmbArgs, pkgname, arch):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def check_arch(args: PmbArgs, pkgname, arch, binary=True):
|
def check_arch(pkgname, arch, binary=True):
|
||||||
"""Check if a package be built for a certain architecture, or is there a binary package for it.
|
"""Check if a package be built for a certain architecture, or is there a binary package for it.
|
||||||
|
|
||||||
:param pkgname: name of the package
|
:param pkgname: name of the package
|
||||||
|
@ -181,7 +181,7 @@ def check_arch(args: PmbArgs, pkgname, arch, binary=True):
|
||||||
:returns: True when the package can be built, or there is a binary package, False otherwise
|
:returns: True when the package can be built, or there is a binary package, False otherwise
|
||||||
"""
|
"""
|
||||||
if binary:
|
if binary:
|
||||||
arches = get(args, pkgname, arch)["arch"]
|
arches = get(pkgname, arch)["arch"]
|
||||||
else:
|
else:
|
||||||
arches = pmb.helpers.pmaports.get(args, pkgname)["arch"]
|
arches = pmb.helpers.pmaports.get(pkgname)["arch"]
|
||||||
return pmb.helpers.pmaports.check_arches(arches, arch)
|
return pmb.helpers.pmaports.check_arches(arches, arch)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.file
|
import pmb.helpers.file
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
|
@ -18,7 +18,7 @@ def package(args: PmbArgs, pkgname, reason="", dry=False):
|
||||||
:param dry: don't modify the APKBUILD, just print the message
|
:param dry: don't modify the APKBUILD, just print the message
|
||||||
"""
|
"""
|
||||||
# Current and new pkgrel
|
# Current and new pkgrel
|
||||||
path = pmb.helpers.pmaports.find(args, pkgname) / "APKBUILD"
|
path = pmb.helpers.pmaports.find(pkgname) / "APKBUILD"
|
||||||
apkbuild = pmb.parse.apkbuild(path)
|
apkbuild = pmb.parse.apkbuild(path)
|
||||||
pkgrel = int(apkbuild["pkgrel"])
|
pkgrel = int(apkbuild["pkgrel"])
|
||||||
pkgrel_new = pkgrel + 1
|
pkgrel_new = pkgrel + 1
|
||||||
|
@ -84,7 +84,7 @@ def auto_apkindex_package(args: PmbArgs, arch, aport, apk, dry=False):
|
||||||
# Ignore conflict-dependencies
|
# Ignore conflict-dependencies
|
||||||
continue
|
continue
|
||||||
|
|
||||||
providers = pmb.parse.apkindex.providers(args, depend, arch,
|
providers = pmb.parse.apkindex.providers(depend, arch,
|
||||||
must_exist=False)
|
must_exist=False)
|
||||||
if providers == {}:
|
if providers == {}:
|
||||||
# We're only interested in missing depends starting with "so:"
|
# We're only interested in missing depends starting with "so:"
|
||||||
|
|
|
@ -12,7 +12,7 @@ from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Sequence, Dict
|
from typing import Optional, Sequence, Dict
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
|
||||||
def _find_apkbuilds() -> Dict[str, Path]:
|
def _find_apkbuilds() -> Dict[str, Path]:
|
||||||
|
@ -23,7 +23,7 @@ def _find_apkbuilds() -> Dict[str, Path]:
|
||||||
return apkbuilds
|
return apkbuilds
|
||||||
|
|
||||||
apkbuilds = {}
|
apkbuilds = {}
|
||||||
for apkbuild in glob.iglob(f"{get_context().aports}/**/*/APKBUILD", recursive=True):
|
for apkbuild in glob.iglob(f"{get_context().config.aports}/**/*/APKBUILD", recursive=True):
|
||||||
package = Path(apkbuild).parent.name
|
package = Path(apkbuild).parent.name
|
||||||
if package in apkbuilds:
|
if package in apkbuilds:
|
||||||
raise RuntimeError(f"Package {package} found in multiple aports "
|
raise RuntimeError(f"Package {package} found in multiple aports "
|
||||||
|
@ -199,7 +199,7 @@ def find_optional(package: str) -> Optional[Path]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get(args: PmbArgs, pkgname, must_exist=True, subpackages=True):
|
def get(pkgname, must_exist=True, subpackages=True):
|
||||||
"""Find and parse an APKBUILD file.
|
"""Find and parse an APKBUILD file.
|
||||||
|
|
||||||
Run 'pmbootstrap apkbuild_parse hello-world' for a full output example.
|
Run 'pmbootstrap apkbuild_parse hello-world' for a full output example.
|
||||||
|
|
|
@ -9,12 +9,13 @@ See also:
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.http
|
import pmb.helpers.http
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.other
|
import pmb.helpers.other
|
||||||
|
@ -47,7 +48,7 @@ def apkindex_hash(url: str, length: int=8) -> Path:
|
||||||
return Path(f"APKINDEX.{ret}.tar.gz")
|
return Path(f"APKINDEX.{ret}.tar.gz")
|
||||||
|
|
||||||
|
|
||||||
def urls(args: PmbArgs, user_repository=True, postmarketos_mirror=True, alpine=True):
|
def urls(user_repository=True, postmarketos_mirror=True, alpine=True):
|
||||||
"""Get a list of repository URLs, as they are in /etc/apk/repositories.
|
"""Get a list of repository URLs, as they are in /etc/apk/repositories.
|
||||||
|
|
||||||
:param user_repository: add /mnt/pmbootstrap/packages
|
:param user_repository: add /mnt/pmbootstrap/packages
|
||||||
|
@ -60,18 +61,19 @@ def urls(args: PmbArgs, user_repository=True, postmarketos_mirror=True, alpine=T
|
||||||
|
|
||||||
# Get mirrordirs from channels.cfg (postmarketOS mirrordir is the same as
|
# Get mirrordirs from channels.cfg (postmarketOS mirrordir is the same as
|
||||||
# the pmaports branch of the channel, no need to make it more complicated)
|
# the pmaports branch of the channel, no need to make it more complicated)
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
mirrordir_pmos = channel_cfg["branch_pmaports"]
|
mirrordir_pmos = channel_cfg["branch_pmaports"]
|
||||||
mirrordir_alpine = channel_cfg["mirrordir_alpine"]
|
mirrordir_alpine = channel_cfg["mirrordir_alpine"]
|
||||||
|
|
||||||
# Local user repository (for packages compiled with pmbootstrap)
|
# Local user repository (for packages compiled with pmbootstrap)
|
||||||
if user_repository:
|
if user_repository:
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
ret.append(str(pmb.config.work / "packages" / channel))
|
ret.append(str(get_context().config.work / "packages" / channel))
|
||||||
|
|
||||||
|
context = get_context()
|
||||||
# Upstream postmarketOS binary repository
|
# Upstream postmarketOS binary repository
|
||||||
if postmarketos_mirror:
|
if postmarketos_mirror:
|
||||||
for mirror in args.mirrors_postmarketos:
|
for mirror in context.config.mirrors_postmarketos:
|
||||||
# Remove "master" mirrordir to avoid breakage until bpo is adjusted
|
# Remove "master" mirrordir to avoid breakage until bpo is adjusted
|
||||||
# (build.postmarketos.org#63) and to give potential other users of
|
# (build.postmarketos.org#63) and to give potential other users of
|
||||||
# this flag a heads up.
|
# this flag a heads up.
|
||||||
|
@ -88,12 +90,12 @@ def urls(args: PmbArgs, user_repository=True, postmarketos_mirror=True, alpine=T
|
||||||
if mirrordir_alpine == "edge":
|
if mirrordir_alpine == "edge":
|
||||||
directories.append("testing")
|
directories.append("testing")
|
||||||
for dir in directories:
|
for dir in directories:
|
||||||
ret.append(f"{args.mirror_alpine}{mirrordir_alpine}/{dir}")
|
ret.append(f"{context.config.mirror_alpine}{mirrordir_alpine}/{dir}")
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def apkindex_files(args: PmbArgs, arch=None, user_repository=True, pmos=True,
|
def apkindex_files(arch=None, user_repository=True, pmos=True,
|
||||||
alpine=True) -> List[Path]:
|
alpine=True) -> List[Path]:
|
||||||
"""Get a list of outside paths to all resolved APKINDEX.tar.gz files for a specific arch.
|
"""Get a list of outside paths to all resolved APKINDEX.tar.gz files for a specific arch.
|
||||||
|
|
||||||
|
@ -109,17 +111,17 @@ def apkindex_files(args: PmbArgs, arch=None, user_repository=True, pmos=True,
|
||||||
ret = []
|
ret = []
|
||||||
# Local user repository (for packages compiled with pmbootstrap)
|
# Local user repository (for packages compiled with pmbootstrap)
|
||||||
if user_repository:
|
if user_repository:
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
ret = [pmb.config.work / "packages" / channel / arch / "APKINDEX.tar.gz"]
|
ret = [get_context().config.work / "packages" / channel / arch / "APKINDEX.tar.gz"]
|
||||||
|
|
||||||
# Resolve the APKINDEX.$HASH.tar.gz files
|
# Resolve the APKINDEX.$HASH.tar.gz files
|
||||||
for url in urls(args, False, pmos, alpine):
|
for url in urls(False, pmos, alpine):
|
||||||
ret.append(pmb.config.work / f"cache_apk_{arch}" / apkindex_hash(url))
|
ret.append(get_context().config.work / f"cache_apk_{arch}" / apkindex_hash(url))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def update(args: PmbArgs, arch=None, force=False, existing_only=False):
|
def update(arch=None, force=False, existing_only=False):
|
||||||
"""Download the APKINDEX files for all URLs depending on the architectures.
|
"""Download the APKINDEX files for all URLs depending on the architectures.
|
||||||
|
|
||||||
:param arch: * one Alpine architecture name ("x86_64", "armhf", ...)
|
:param arch: * one Alpine architecture name ("x86_64", "armhf", ...)
|
||||||
|
@ -132,7 +134,7 @@ def update(args: PmbArgs, arch=None, force=False, existing_only=False):
|
||||||
"""
|
"""
|
||||||
# Skip in offline mode, only show once
|
# Skip in offline mode, only show once
|
||||||
cache_key = "pmb.helpers.repo.update"
|
cache_key = "pmb.helpers.repo.update"
|
||||||
if args.offline:
|
if get_context().offline:
|
||||||
if not pmb.helpers.other.cache[cache_key]["offline_msg_shown"]:
|
if not pmb.helpers.other.cache[cache_key]["offline_msg_shown"]:
|
||||||
logging.info("NOTE: skipping package index update (offline mode)")
|
logging.info("NOTE: skipping package index update (offline mode)")
|
||||||
pmb.helpers.other.cache[cache_key]["offline_msg_shown"] = True
|
pmb.helpers.other.cache[cache_key]["offline_msg_shown"] = True
|
||||||
|
@ -148,11 +150,11 @@ def update(args: PmbArgs, arch=None, force=False, existing_only=False):
|
||||||
# outdated_arches: ["armhf", "x86_64", ... ]
|
# outdated_arches: ["armhf", "x86_64", ... ]
|
||||||
outdated = {}
|
outdated = {}
|
||||||
outdated_arches = []
|
outdated_arches = []
|
||||||
for url in urls(args, False):
|
for url in urls(False):
|
||||||
for arch in architectures:
|
for arch in architectures:
|
||||||
# APKINDEX file name from the URL
|
# APKINDEX file name from the URL
|
||||||
url_full = url + "/" + arch + "/APKINDEX.tar.gz"
|
url_full = url + "/" + arch + "/APKINDEX.tar.gz"
|
||||||
cache_apk_outside = pmb.config.work / f"cache_apk_{arch}"
|
cache_apk_outside = get_context().config.work / f"cache_apk_{arch}"
|
||||||
apkindex = cache_apk_outside / f"APKINDEX.{apkindex_hash(url)}.tar.gz"
|
apkindex = cache_apk_outside / f"APKINDEX.{apkindex_hash(url)}.tar.gz"
|
||||||
|
|
||||||
# Find update reason, possibly skip non-existing or known 404 files
|
# Find update reason, possibly skip non-existing or known 404 files
|
||||||
|
@ -186,8 +188,8 @@ def update(args: PmbArgs, arch=None, force=False, existing_only=False):
|
||||||
|
|
||||||
# Download and move to right location
|
# Download and move to right location
|
||||||
for (i, (url, target)) in enumerate(outdated.items()):
|
for (i, (url, target)) in enumerate(outdated.items()):
|
||||||
pmb.helpers.cli.progress_print(args, i / len(outdated))
|
pmb.helpers.cli.progress_print(i / len(outdated))
|
||||||
temp = pmb.helpers.http.download(args, url, "APKINDEX", False,
|
temp = pmb.helpers.http.download(url, "APKINDEX", False,
|
||||||
logging.DEBUG, True)
|
logging.DEBUG, True)
|
||||||
if not temp:
|
if not temp:
|
||||||
pmb.helpers.other.cache[cache_key]["404"].append(url)
|
pmb.helpers.other.cache[cache_key]["404"].append(url)
|
||||||
|
@ -196,12 +198,12 @@ def update(args: PmbArgs, arch=None, force=False, existing_only=False):
|
||||||
if not os.path.exists(target_folder):
|
if not os.path.exists(target_folder):
|
||||||
pmb.helpers.run.root(["mkdir", "-p", target_folder])
|
pmb.helpers.run.root(["mkdir", "-p", target_folder])
|
||||||
pmb.helpers.run.root(["cp", temp, target])
|
pmb.helpers.run.root(["cp", temp, target])
|
||||||
pmb.helpers.cli.progress_flush(args)
|
pmb.helpers.cli.progress_flush()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def alpine_apkindex_path(args: PmbArgs, repo="main", arch=None):
|
def alpine_apkindex_path(repo="main", arch=None):
|
||||||
"""Get the path to a specific Alpine APKINDEX file on disk and download it if necessary.
|
"""Get the path to a specific Alpine APKINDEX file on disk and download it if necessary.
|
||||||
|
|
||||||
:param repo: Alpine repository name (e.g. "main")
|
:param repo: Alpine repository name (e.g. "main")
|
||||||
|
@ -214,10 +216,10 @@ def alpine_apkindex_path(args: PmbArgs, repo="main", arch=None):
|
||||||
|
|
||||||
# Download the file
|
# Download the file
|
||||||
arch = arch or pmb.config.arch_native
|
arch = arch or pmb.config.arch_native
|
||||||
update(args, arch)
|
update(arch)
|
||||||
|
|
||||||
# Find it on disk
|
# Find it on disk
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel()
|
||||||
repo_link = f"{args.mirror_alpine}{channel_cfg['mirrordir_alpine']}/{repo}"
|
repo_link = f"{get_context().config.mirror_alpine}{channel_cfg['mirrordir_alpine']}/{repo}"
|
||||||
cache_folder = pmb.config.work / (f"cache_apk_{arch}")
|
cache_folder = get_context().config.work / (f"cache_apk_{arch}")
|
||||||
return cache_folder / apkindex_hash(repo_link)
|
return cache_folder / apkindex_hash(repo_link)
|
||||||
|
|
|
@ -6,7 +6,8 @@ import glob
|
||||||
|
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
progress_done = 0
|
progress_done = 0
|
||||||
|
@ -25,7 +26,7 @@ def get_arch(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def check_repo_arg(args: PmbArgs):
|
def check_repo_arg(args: PmbArgs):
|
||||||
cfg = pmb.config.pmaports.read_config_repos(args)
|
cfg = pmb.config.pmaports.read_config_repos()
|
||||||
repo = args.repository
|
repo = args.repository
|
||||||
|
|
||||||
if repo in cfg:
|
if repo in cfg:
|
||||||
|
@ -41,8 +42,8 @@ def check_repo_arg(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def check_existing_pkgs(args: PmbArgs, arch):
|
def check_existing_pkgs(args: PmbArgs, arch):
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
path = pmb.config.work / "packages" / channel / arch
|
path = get_context().config.work / "packages" / channel / arch
|
||||||
|
|
||||||
if glob.glob(f"{path}/*"):
|
if glob.glob(f"{path}/*"):
|
||||||
logging.info(f"Packages path: {path}")
|
logging.info(f"Packages path: {path}")
|
||||||
|
@ -57,7 +58,7 @@ def check_existing_pkgs(args: PmbArgs, arch):
|
||||||
|
|
||||||
|
|
||||||
def get_steps(args: PmbArgs):
|
def get_steps(args: PmbArgs):
|
||||||
cfg = pmb.config.pmaports.read_config_repos(args)
|
cfg = pmb.config.pmaports.read_config_repos()
|
||||||
prev_step = 0
|
prev_step = 0
|
||||||
ret = {}
|
ret = {}
|
||||||
|
|
||||||
|
@ -132,11 +133,11 @@ def run_steps(args: PmbArgs, steps, arch, chroot: Chroot):
|
||||||
if chroot != Chroot.native():
|
if chroot != Chroot.native():
|
||||||
log_progress(f"initializing native chroot (merge /usr: {usr_merge.name})")
|
log_progress(f"initializing native chroot (merge /usr: {usr_merge.name})")
|
||||||
# Native chroot needs pmOS binary package repo for cross compilers
|
# Native chroot needs pmOS binary package repo for cross compilers
|
||||||
pmb.chroot.init(args, Chroot.native(), usr_merge)
|
pmb.chroot.init(Chroot.native(), usr_merge)
|
||||||
|
|
||||||
log_progress(f"initializing {chroot} chroot (merge /usr: {usr_merge.name})")
|
log_progress(f"initializing {chroot} chroot (merge /usr: {usr_merge.name})")
|
||||||
# Initialize without pmOS binary package repo
|
# Initialize without pmOS binary package repo
|
||||||
pmb.chroot.init(args, chroot, usr_merge, postmarketos_mirror=False)
|
pmb.chroot.init(chroot, usr_merge, postmarketos_mirror=False)
|
||||||
|
|
||||||
for package in get_packages(bootstrap_line):
|
for package in get_packages(bootstrap_line):
|
||||||
log_progress(f"building {package}")
|
log_progress(f"building {package}")
|
||||||
|
@ -181,9 +182,9 @@ def require_bootstrap(args: PmbArgs, arch, trigger_str):
|
||||||
:param arch: for which architecture
|
:param arch: for which architecture
|
||||||
:param trigger_str: message for the user to understand what caused this
|
:param trigger_str: message for the user to understand what caused this
|
||||||
"""
|
"""
|
||||||
if pmb.config.other.is_systemd_selected(args):
|
if pmb.config.other.is_systemd_selected(get_context().config):
|
||||||
pmb.helpers.repo.update(args, arch)
|
pmb.helpers.repo.update(arch)
|
||||||
pkg = pmb.parse.apkindex.package(args, "postmarketos-base-systemd",
|
pkg = pmb.parse.apkindex.package("postmarketos-base-systemd",
|
||||||
arch, False)
|
arch, False)
|
||||||
if not pkg:
|
if not pkg:
|
||||||
require_bootstrap_error("systemd", arch, trigger_str)
|
require_bootstrap_error("systemd", arch, trigger_str)
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.package
|
import pmb.helpers.package
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
|
||||||
def filter_missing_packages(args: PmbArgs, arch, pkgnames):
|
def filter_missing_packages(arch, pkgnames):
|
||||||
"""Create a subset of pkgnames with missing or outdated binary packages.
|
"""Create a subset of pkgnames with missing or outdated binary packages.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
@ -17,15 +17,15 @@ def filter_missing_packages(args: PmbArgs, arch, pkgnames):
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
binary = pmb.parse.apkindex.package(args, pkgname, arch, False)
|
binary = pmb.parse.apkindex.package(pkgname, arch, False)
|
||||||
must_exist = False if binary else True
|
must_exist = False if binary else True
|
||||||
pmaport = pmb.helpers.pmaports.get(args, pkgname, must_exist)
|
pmaport = pmb.helpers.pmaports.get(pkgname, must_exist)
|
||||||
if pmaport and pmb.build.is_necessary(args, arch, pmaport):
|
if pmaport and pmb.build.is_necessary(arch, pmaport):
|
||||||
ret.append(pkgname)
|
ret.append(pkgname)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def filter_aport_packages(args: PmbArgs, arch, pkgnames):
|
def filter_aport_packages(pkgnames):
|
||||||
"""Create a subset of pkgnames where each one has an aport.
|
"""Create a subset of pkgnames where each one has an aport.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
@ -34,12 +34,12 @@ def filter_aport_packages(args: PmbArgs, arch, pkgnames):
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
if pmb.helpers.pmaports.find_optional(args, pkgname):
|
if pmb.helpers.pmaports.find_optional(pkgname):
|
||||||
ret += [pkgname]
|
ret += [pkgname]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def filter_arch_packages(args: PmbArgs, arch, pkgnames):
|
def filter_arch_packages(arch, pkgnames):
|
||||||
"""Create a subset of pkgnames with packages removed that can not be built for a certain arch.
|
"""Create a subset of pkgnames with packages removed that can not be built for a certain arch.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
@ -48,12 +48,12 @@ def filter_arch_packages(args: PmbArgs, arch, pkgnames):
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
if pmb.helpers.package.check_arch(args, pkgname, arch, False):
|
if pmb.helpers.package.check_arch(pkgname, arch, False):
|
||||||
ret += [pkgname]
|
ret += [pkgname]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_relevant_packages(args: PmbArgs, arch, pkgname=None, built=False):
|
def get_relevant_packages(arch, pkgname=None, built=False):
|
||||||
"""Get all packages that can be built for the architecture in question.
|
"""Get all packages that can be built for the architecture in question.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
@ -63,20 +63,20 @@ def get_relevant_packages(args: PmbArgs, arch, pkgname=None, built=False):
|
||||||
["devicepkg-dev", "hello-world", "osk-sdl"]
|
["devicepkg-dev", "hello-world", "osk-sdl"]
|
||||||
"""
|
"""
|
||||||
if pkgname:
|
if pkgname:
|
||||||
if not pmb.helpers.package.check_arch(args, pkgname, arch, False):
|
if not pmb.helpers.package.check_arch(pkgname, arch, False):
|
||||||
raise RuntimeError(pkgname + " can't be built for " + arch + ".")
|
raise RuntimeError(pkgname + " can't be built for " + arch + ".")
|
||||||
ret = pmb.helpers.package.depends_recurse(args, pkgname, arch)
|
ret = pmb.helpers.package.depends_recurse(pkgname, arch)
|
||||||
else:
|
else:
|
||||||
ret = pmb.helpers.pmaports.get_list(args)
|
ret = pmb.helpers.pmaports.get_list()
|
||||||
ret = filter_arch_packages(args, arch, ret)
|
ret = filter_arch_packages(arch, ret)
|
||||||
if built:
|
if built:
|
||||||
ret = filter_aport_packages(args, arch, ret)
|
ret = filter_aport_packages(ret)
|
||||||
if not len(ret):
|
if not len(ret):
|
||||||
logging.info("NOTE: no aport found for any package in the"
|
logging.info("NOTE: no aport found for any package in the"
|
||||||
" dependency tree, it seems they are all provided by"
|
" dependency tree, it seems they are all provided by"
|
||||||
" upstream (Alpine).")
|
" upstream (Alpine).")
|
||||||
else:
|
else:
|
||||||
ret = filter_missing_packages(args, arch, ret)
|
ret = filter_missing_packages(arch, ret)
|
||||||
if not len(ret):
|
if not len(ret):
|
||||||
logging.info("NOTE: all relevant packages are up to date, use"
|
logging.info("NOTE: all relevant packages are up to date, use"
|
||||||
" --built to include the ones that have already been"
|
" --built to include the ones that have already been"
|
||||||
|
@ -87,7 +87,7 @@ def get_relevant_packages(args: PmbArgs, arch, pkgname=None, built=False):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def generate_output_format(args: PmbArgs, arch, pkgnames):
|
def generate_output_format(arch, pkgnames):
|
||||||
"""Generate the detailed output format.
|
"""Generate the detailed output format.
|
||||||
|
|
||||||
:param arch: architecture
|
:param arch: architecture
|
||||||
|
@ -105,15 +105,15 @@ def generate_output_format(args: PmbArgs, arch, pkgnames):
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
entry = pmb.helpers.package.get(args, pkgname, arch, True)
|
entry = pmb.helpers.package.get(pkgname, arch, True)
|
||||||
ret += [{"pkgname": entry["pkgname"],
|
ret += [{"pkgname": entry["pkgname"],
|
||||||
"repo": pmb.helpers.pmaports.get_repo(args, pkgname),
|
"repo": pmb.helpers.pmaports.get_repo(pkgname),
|
||||||
"version": entry["version"],
|
"version": entry["version"],
|
||||||
"depends": entry["depends"]}]
|
"depends": entry["depends"]}]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def generate(args: PmbArgs, arch, overview, pkgname=None, built=False):
|
def generate(arch, overview, pkgname=None, built=False):
|
||||||
"""Get packages that need to be built, with all their dependencies.
|
"""Get packages that need to be built, with all their dependencies.
|
||||||
|
|
||||||
:param arch: architecture (e.g. "armhf")
|
:param arch: architecture (e.g. "armhf")
|
||||||
|
@ -129,9 +129,9 @@ def generate(args: PmbArgs, arch, overview, pkgname=None, built=False):
|
||||||
"".format(packages_str, arch))
|
"".format(packages_str, arch))
|
||||||
|
|
||||||
# Order relevant packages
|
# Order relevant packages
|
||||||
ret = get_relevant_packages(args, arch, pkgname, built)
|
ret = get_relevant_packages(arch, pkgname, built)
|
||||||
|
|
||||||
# Output format
|
# Output format
|
||||||
if overview:
|
if overview:
|
||||||
return ret
|
return ret
|
||||||
return generate_output_format(args, arch, ret)
|
return generate_output_format(arch, ret)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||||
import subprocess
|
import subprocess
|
||||||
import pmb.helpers.run_core
|
import pmb.helpers.run_core
|
||||||
from typing import Any, Dict, List, Optional, Sequence
|
from typing import Any, Dict, List, Optional, Sequence
|
||||||
from pmb.core.types import Env, PathString, PmbArgs
|
from pmb.types import Env, PathString, PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def user(cmd: Sequence[PathString], working_dir: Optional[Path] = None, output: str = "log", output_return: bool = False,
|
def user(cmd: Sequence[PathString], working_dir: Optional[Path] = None, output: str = "log", output_return: bool = False,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import fcntl
|
import fcntl
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.core.types import PathString, Env
|
from pmb.types import PathString, Env
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.workdir
|
import pmb.config.workdir
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import Config, PmbArgs
|
||||||
|
from pmb.core import get_context
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,8 +16,8 @@ def print_status_line(key: str, value: str):
|
||||||
print(f"{key.ljust(padding)} {value}")
|
print(f"{key.ljust(padding)} {value}")
|
||||||
|
|
||||||
|
|
||||||
def print_channel(args: PmbArgs) -> None:
|
def print_channel(config: Config) -> None:
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
channel = pmaports_cfg["channel"]
|
channel = pmaports_cfg["channel"]
|
||||||
|
|
||||||
# Get branch name (if on branch) or current commit
|
# Get branch name (if on branch) or current commit
|
||||||
|
@ -32,28 +33,29 @@ def print_channel(args: PmbArgs) -> None:
|
||||||
print_status_line("Channel", value)
|
print_status_line("Channel", value)
|
||||||
|
|
||||||
|
|
||||||
def print_device(args: PmbArgs) -> None:
|
def print_device(args: PmbArgs, config: Config) -> None:
|
||||||
kernel = ""
|
kernel = ""
|
||||||
if pmb.parse._apkbuild.kernels(args, args.device):
|
if pmb.parse._apkbuild.kernels(config.device):
|
||||||
kernel = f", kernel: {args.kernel}"
|
kernel = f", kernel: {config.kernel}"
|
||||||
|
|
||||||
value = f"{args.device} ({args.deviceinfo['arch']}{kernel})"
|
value = f"{config.device} ({args.deviceinfo['arch']}{kernel})"
|
||||||
print_status_line("Device", value)
|
print_status_line("Device", value)
|
||||||
|
|
||||||
|
|
||||||
def print_ui(args: PmbArgs) -> None:
|
def print_ui(config: Config) -> None:
|
||||||
print_status_line("UI", args.ui)
|
print_status_line("UI", config.ui)
|
||||||
|
|
||||||
|
|
||||||
def print_systemd(args: PmbArgs) -> None:
|
def print_systemd(config: Config) -> None:
|
||||||
yesno, reason = pmb.config.other.systemd_selected_str(args)
|
yesno, reason = pmb.config.other.systemd_selected_str(config)
|
||||||
print_status_line("systemd", f"{yesno} ({reason})")
|
print_status_line("systemd", f"{yesno} ({reason})")
|
||||||
|
|
||||||
|
|
||||||
def print_status(args: PmbArgs) -> None:
|
def print_status(args: PmbArgs) -> None:
|
||||||
""" :param details: if True, print each passing check instead of a summary
|
""" :param details: if True, print each passing check instead of a summary
|
||||||
:returns: True if all checks passed, False otherwise """
|
:returns: True if all checks passed, False otherwise """
|
||||||
print_channel(args)
|
config = get_context().config
|
||||||
print_device(args)
|
print_channel(config)
|
||||||
print_ui(args)
|
print_device(args, config)
|
||||||
print_systemd(args)
|
print_ui(config)
|
||||||
|
print_systemd(config)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from pmb.core import get_context
|
from pmb.core import get_context
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.helpers.package
|
import pmb.helpers.package
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
|
@ -19,7 +19,7 @@ def list_ui(args: PmbArgs, arch):
|
||||||
" customization. The \"console\" UI should be selected if"
|
" customization. The \"console\" UI should be selected if"
|
||||||
" a graphical UI is not desired.")]
|
" a graphical UI is not desired.")]
|
||||||
context = get_context() # noqa: F821
|
context = get_context() # noqa: F821
|
||||||
for path in sorted(context.aports.glob("main/postmarketos-ui-*")):
|
for path in sorted(context.config.aports.glob("main/postmarketos-ui-*")):
|
||||||
apkbuild = pmb.parse.apkbuild(path)
|
apkbuild = pmb.parse.apkbuild(path)
|
||||||
ui = os.path.basename(path).split("-", 2)[2]
|
ui = os.path.basename(path).split("-", 2)[2]
|
||||||
if pmb.helpers.package.check_arch(args, apkbuild["pkgname"], arch):
|
if pmb.helpers.package.check_arch(args, apkbuild["pkgname"], arch):
|
||||||
|
@ -27,10 +27,10 @@ def list_ui(args: PmbArgs, arch):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def check_option(args: PmbArgs, ui, option):
|
def check_option(ui, option):
|
||||||
"""
|
"""
|
||||||
Check if an option, such as pmb:systemd, is inside an UI's APKBUILD.
|
Check if an option, such as pmb:systemd, is inside an UI's APKBUILD.
|
||||||
"""
|
"""
|
||||||
pkgname = f"postmarketos-ui-{ui}"
|
pkgname = f"postmarketos-ui-{ui}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, pkgname, subpackages=False)
|
apkbuild = pmb.helpers.pmaports.get(pkgname, subpackages=False)
|
||||||
return option in apkbuild["options"]
|
return option in apkbuild["options"]
|
||||||
|
|
|
@ -9,13 +9,14 @@ import sys
|
||||||
from typing import Dict, List, Optional, Sequence, TypedDict
|
from typing import Dict, List, Optional, Sequence, TypedDict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pmb.build
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PartitionLayout, PmbArgs
|
from pmb.types import Config, PartitionLayout, PmbArgs
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
from pmb.helpers.mount import mount_device_rootfs
|
from pmb.helpers.mount import mount_device_rootfs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
|
@ -24,7 +25,7 @@ import pmb.install.blockdevice
|
||||||
import pmb.install.recovery
|
import pmb.install.recovery
|
||||||
import pmb.install.ui
|
import pmb.install.ui
|
||||||
import pmb.install
|
import pmb.install
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot, ChrootType, get_context
|
||||||
|
|
||||||
# Keep track of the packages we already visited in get_recommends() to avoid
|
# Keep track of the packages we already visited in get_recommends() to avoid
|
||||||
# infinite recursion
|
# infinite recursion
|
||||||
|
@ -32,7 +33,7 @@ get_recommends_visited: List[str] = []
|
||||||
get_selected_providers_visited: List[str] = []
|
get_selected_providers_visited: List[str] = []
|
||||||
|
|
||||||
|
|
||||||
def get_subpartitions_size(args: PmbArgs, chroot: Chroot):
|
def get_subpartitions_size(chroot: Chroot):
|
||||||
"""
|
"""
|
||||||
Calculate the size of the boot and root subpartition.
|
Calculate the size of the boot and root subpartition.
|
||||||
|
|
||||||
|
@ -40,18 +41,19 @@ def get_subpartitions_size(args: PmbArgs, chroot: Chroot):
|
||||||
:returns: (boot, root) the size of the boot and root
|
:returns: (boot, root) the size of the boot and root
|
||||||
partition as integer in MiB
|
partition as integer in MiB
|
||||||
"""
|
"""
|
||||||
boot = int(args.boot_size)
|
config = get_context().config
|
||||||
|
boot = int(config.boot_size)
|
||||||
|
|
||||||
# Estimate root partition size, then add some free space. The size
|
# Estimate root partition size, then add some free space. The size
|
||||||
# calculation is not as trivial as one may think, and depending on the
|
# calculation is not as trivial as one may think, and depending on the
|
||||||
# file system etc it seems to be just impossible to get it right.
|
# file system etc it seems to be just impossible to get it right.
|
||||||
root = pmb.helpers.other.folder_size(args, chroot.path) / 1024
|
root = pmb.helpers.other.folder_size(chroot.path) / 1024
|
||||||
root *= 1.20
|
root *= 1.20
|
||||||
root += 50 + int(args.extra_space)
|
root += 50 + int(config.extra_space)
|
||||||
return (boot, root)
|
return (boot, root)
|
||||||
|
|
||||||
|
|
||||||
def get_nonfree_packages(args: PmbArgs, device):
|
def get_nonfree_packages(device):
|
||||||
"""
|
"""
|
||||||
Get any legacy non-free subpackages in the APKBUILD.
|
Get any legacy non-free subpackages in the APKBUILD.
|
||||||
Also see: https://postmarketos.org/edge/2024/02/15/default-nonfree-fw/
|
Also see: https://postmarketos.org/edge/2024/02/15/default-nonfree-fw/
|
||||||
|
@ -60,7 +62,7 @@ def get_nonfree_packages(args: PmbArgs, device):
|
||||||
["device-nokia-n900-nonfree-firmware"]
|
["device-nokia-n900-nonfree-firmware"]
|
||||||
"""
|
"""
|
||||||
# Read subpackages
|
# Read subpackages
|
||||||
device_path = pmb.helpers.devices.find_path(args, device, 'APKBUILD')
|
device_path = pmb.helpers.devices.find_path(device, 'APKBUILD')
|
||||||
if not device_path:
|
if not device_path:
|
||||||
raise RuntimeError(f"Device package not found for {device}")
|
raise RuntimeError(f"Device package not found for {device}")
|
||||||
|
|
||||||
|
@ -134,15 +136,15 @@ def copy_files_from_chroot(args: PmbArgs, chroot: Chroot):
|
||||||
|
|
||||||
# Update or copy all files
|
# Update or copy all files
|
||||||
if args.rsync:
|
if args.rsync:
|
||||||
pmb.chroot.apk.install(args, ["rsync"], Chroot.native())
|
pmb.chroot.apk.install(["rsync"], Chroot.native())
|
||||||
rsync_flags = "-a"
|
rsync_flags = "-a"
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
rsync_flags += "vP"
|
rsync_flags += "vP"
|
||||||
pmb.chroot.root(args, ["rsync", rsync_flags, "--delete"] + folders +
|
pmb.chroot.root(["rsync", rsync_flags, "--delete"] + folders +
|
||||||
["/mnt/install/"], working_dir=mountpoint)
|
["/mnt/install/"], working_dir=mountpoint)
|
||||||
pmb.chroot.root(args, ["rm", "-rf", "/mnt/install/home"])
|
pmb.chroot.root(["rm", "-rf", "/mnt/install/home"])
|
||||||
else:
|
else:
|
||||||
pmb.chroot.root(args, ["cp", "-a"] + folders + ["/mnt/install/"],
|
pmb.chroot.root(["cp", "-a"] + folders + ["/mnt/install/"],
|
||||||
working_dir=mountpoint)
|
working_dir=mountpoint)
|
||||||
|
|
||||||
|
|
||||||
|
@ -174,7 +176,7 @@ def configure_apk(args: PmbArgs):
|
||||||
|
|
||||||
# Official keys + local keys
|
# Official keys + local keys
|
||||||
if args.install_local_pkgs:
|
if args.install_local_pkgs:
|
||||||
keys_dir = pmb.config.work / "config_apk_keys"
|
keys_dir = get_context().config.work / "config_apk_keys"
|
||||||
|
|
||||||
# Copy over keys
|
# Copy over keys
|
||||||
rootfs = (Chroot.native() / "mnt/install")
|
rootfs = (Chroot.native() / "mnt/install")
|
||||||
|
@ -194,7 +196,7 @@ def configure_apk(args: PmbArgs):
|
||||||
pmb.helpers.run.user(["cat", rootfs / "etc/apk/repositories"])
|
pmb.helpers.run.user(["cat", rootfs / "etc/apk/repositories"])
|
||||||
|
|
||||||
|
|
||||||
def set_user(args: PmbArgs):
|
def set_user(config: Config):
|
||||||
"""
|
"""
|
||||||
Create user with UID 10000 if it doesn't exist.
|
Create user with UID 10000 if it doesn't exist.
|
||||||
Usually the ID for the first user created is 1000, but higher ID is
|
Usually the ID for the first user created is 1000, but higher ID is
|
||||||
|
@ -202,21 +204,21 @@ def set_user(args: PmbArgs):
|
||||||
this was done to avoid conflict with Android UIDs/GIDs, but pmOS has since
|
this was done to avoid conflict with Android UIDs/GIDs, but pmOS has since
|
||||||
dropped support for hybris/Halium.
|
dropped support for hybris/Halium.
|
||||||
"""
|
"""
|
||||||
chroot = Chroot.rootfs(args.device)
|
chroot = Chroot.rootfs(config.device)
|
||||||
if not pmb.chroot.user_exists(args, args.user, chroot):
|
if not pmb.chroot.user_exists(config.user, chroot):
|
||||||
pmb.chroot.root(args, ["adduser", "-D", "-u", "10000", args.user],
|
pmb.chroot.root(["adduser", "-D", "-u", "10000", config.user],
|
||||||
chroot)
|
chroot)
|
||||||
|
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
groups = []
|
groups = []
|
||||||
groups += pmaports_cfg.get("install_user_groups",
|
groups += pmaports_cfg.get("install_user_groups",
|
||||||
"audio,input,netdev,plugdev,video,wheel").split(",")
|
"audio,input,netdev,plugdev,video,wheel").split(",")
|
||||||
groups += pmb.install.ui.get_groups(args)
|
groups += pmb.install.ui.get_groups(config)
|
||||||
|
|
||||||
for group in groups:
|
for group in groups:
|
||||||
pmb.chroot.root(args, ["addgroup", "-S", group], chroot,
|
pmb.chroot.root(["addgroup", "-S", group], chroot,
|
||||||
check=False)
|
check=False)
|
||||||
pmb.chroot.root(args, ["addgroup", args.user, group], chroot)
|
pmb.chroot.root(["addgroup", config.user, group], chroot)
|
||||||
|
|
||||||
|
|
||||||
def setup_login_chpasswd_user_from_arg(args: PmbArgs, chroot: Chroot):
|
def setup_login_chpasswd_user_from_arg(args: PmbArgs, chroot: Chroot):
|
||||||
|
@ -237,7 +239,7 @@ def setup_login_chpasswd_user_from_arg(args: PmbArgs, chroot: Chroot):
|
||||||
with open(path_outside, "w", encoding="utf-8") as handle:
|
with open(path_outside, "w", encoding="utf-8") as handle:
|
||||||
handle.write(f"{args.user}:{args.password}")
|
handle.write(f"{args.user}:{args.password}")
|
||||||
|
|
||||||
pmb.chroot.root(args, ["sh", "-c", f"cat {shlex.quote(path)} | chpasswd"],
|
pmb.chroot.root(["sh", "-c", f"cat {shlex.quote(path)} | chpasswd"],
|
||||||
chroot)
|
chroot)
|
||||||
|
|
||||||
os.unlink(path_outside)
|
os.unlink(path_outside)
|
||||||
|
@ -251,7 +253,7 @@ def is_root_locked(args: PmbArgs, chroot: Chroot):
|
||||||
|
|
||||||
:param suffix: either rootfs_{args.device} or installer_{args.device}
|
:param suffix: either rootfs_{args.device} or installer_{args.device}
|
||||||
"""
|
"""
|
||||||
shadow_root = pmb.chroot.root(args, ["grep", "^root:!:", "/etc/shadow"],
|
shadow_root = pmb.chroot.root(["grep", "^root:!:", "/etc/shadow"],
|
||||||
chroot, output_return=True, check=False)
|
chroot, output_return=True, check=False)
|
||||||
return shadow_root.startswith("root:!:")
|
return shadow_root.startswith("root:!:")
|
||||||
|
|
||||||
|
@ -272,7 +274,7 @@ def setup_login(args: PmbArgs, chroot: Chroot):
|
||||||
else:
|
else:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
pmb.chroot.root(args, ["passwd", args.user], chroot,
|
pmb.chroot.root(["passwd", args.user], chroot,
|
||||||
output="interactive")
|
output="interactive")
|
||||||
break
|
break
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
@ -284,17 +286,17 @@ def setup_login(args: PmbArgs, chroot: Chroot):
|
||||||
logging.debug(f"({chroot}) root is already locked")
|
logging.debug(f"({chroot}) root is already locked")
|
||||||
else:
|
else:
|
||||||
logging.debug(f"({chroot}) locking root")
|
logging.debug(f"({chroot}) locking root")
|
||||||
pmb.chroot.root(args, ["passwd", "-l", "root"], chroot)
|
pmb.chroot.root(["passwd", "-l", "root"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def copy_ssh_keys(args: PmbArgs):
|
def copy_ssh_keys(config: Config):
|
||||||
"""
|
"""
|
||||||
If requested, copy user's SSH public keys to the device if they exist
|
If requested, copy user's SSH public keys to the device if they exist
|
||||||
"""
|
"""
|
||||||
if not args.ssh_keys:
|
if not config.ssh_keys:
|
||||||
return
|
return
|
||||||
keys = []
|
keys = []
|
||||||
for key in glob.glob(os.path.expanduser(args.ssh_key_glob)):
|
for key in glob.glob(os.path.expanduser(config.ssh_key_glob)):
|
||||||
with open(key, "r") as infile:
|
with open(key, "r") as infile:
|
||||||
keys += infile.readlines()
|
keys += infile.readlines()
|
||||||
|
|
||||||
|
@ -310,7 +312,7 @@ def copy_ssh_keys(args: PmbArgs):
|
||||||
outfile.write("%s" % key)
|
outfile.write("%s" % key)
|
||||||
outfile.close()
|
outfile.close()
|
||||||
|
|
||||||
target = Chroot.native() / "mnt/install/home/" / args.user / ".ssh"
|
target = Chroot.native() / "mnt/install/home/" / config.user / ".ssh"
|
||||||
pmb.helpers.run.root(["mkdir", target])
|
pmb.helpers.run.root(["mkdir", target])
|
||||||
pmb.helpers.run.root(["chmod", "700", target])
|
pmb.helpers.run.root(["chmod", "700", target])
|
||||||
pmb.helpers.run.root(["cp", authorized_keys, target / "authorized_keys"])
|
pmb.helpers.run.root(["cp", authorized_keys, target / "authorized_keys"])
|
||||||
|
@ -318,30 +320,30 @@ def copy_ssh_keys(args: PmbArgs):
|
||||||
pmb.helpers.run.root(["chown", "-R", "10000:10000", target])
|
pmb.helpers.run.root(["chown", "-R", "10000:10000", target])
|
||||||
|
|
||||||
|
|
||||||
def setup_keymap(args: PmbArgs):
|
def setup_keymap(config: Config):
|
||||||
"""
|
"""
|
||||||
Set the keymap with the setup-keymap utility if the device requires it
|
Set the keymap with the setup-keymap utility if the device requires it
|
||||||
"""
|
"""
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.device)
|
chroot = Chroot(ChrootType.ROOTFS, config.device)
|
||||||
info = pmb.parse.deviceinfo(args, device=args.device)
|
info = pmb.parse.deviceinfo(device=config.device)
|
||||||
if "keymaps" not in info or info["keymaps"].strip() == "":
|
if "keymaps" not in info or info["keymaps"].strip() == "":
|
||||||
logging.info("NOTE: No valid keymap specified for device")
|
logging.info("NOTE: No valid keymap specified for device")
|
||||||
return
|
return
|
||||||
options = info["keymaps"].split(' ')
|
options = info["keymaps"].split(' ')
|
||||||
if (args.keymap != "" and
|
if (config.keymap != "" and
|
||||||
args.keymap is not None and
|
config.keymap is not None and
|
||||||
args.keymap in options):
|
config.keymap in options):
|
||||||
layout, variant = args.keymap.split("/")
|
layout, variant = config.keymap.split("/")
|
||||||
pmb.chroot.root(args, ["setup-keymap", layout, variant], chroot,
|
pmb.chroot.root(["setup-keymap", layout, variant], chroot,
|
||||||
output="interactive")
|
output="interactive")
|
||||||
|
|
||||||
# Check xorg config
|
# Check xorg config
|
||||||
config = None
|
xconfig = None
|
||||||
if (chroot / "etc/X11/xorg.conf.d").exists():
|
if (chroot / "etc/X11/xorg.conf.d").exists():
|
||||||
config = pmb.chroot.root(args, ["grep", "-rl", "XkbLayout",
|
xconfig = pmb.chroot.root(["grep", "-rl", "XkbLayout",
|
||||||
"/etc/X11/xorg.conf.d/"],
|
"/etc/X11/xorg.conf.d/"],
|
||||||
chroot, check=False, output_return=True)
|
chroot, check=False, output_return=True)
|
||||||
if config:
|
if xconfig:
|
||||||
# Nokia n900 (RX-51) randomly merges some keymaps so we
|
# Nokia n900 (RX-51) randomly merges some keymaps so we
|
||||||
# have to specify a composite keymap for a few countries. See:
|
# have to specify a composite keymap for a few countries. See:
|
||||||
# https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/symbols/nokia_vndr/rx-51
|
# https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/symbols/nokia_vndr/rx-51
|
||||||
|
@ -352,17 +354,17 @@ def setup_keymap(args: PmbArgs):
|
||||||
if variant == "rx51_pt" or variant == "rx51_es":
|
if variant == "rx51_pt" or variant == "rx51_es":
|
||||||
layout = "ptes"
|
layout = "ptes"
|
||||||
# Multiple files can contain the keyboard layout, take last
|
# Multiple files can contain the keyboard layout, take last
|
||||||
config = config.splitlines()[-1]
|
xconfig = xconfig.splitlines()[-1]
|
||||||
old_text = "Option *\\\"XkbLayout\\\" *\\\".*\\\""
|
old_text = "Option *\\\"XkbLayout\\\" *\\\".*\\\""
|
||||||
new_text = "Option \\\"XkbLayout\\\" \\\"" + layout + "\\\""
|
new_text = "Option \\\"XkbLayout\\\" \\\"" + layout + "\\\""
|
||||||
pmb.chroot.root(args, ["sed", "-i", "s/" + old_text + "/" +
|
pmb.chroot.root(["sed", "-i", "s/" + old_text + "/" +
|
||||||
new_text + "/", config], chroot)
|
new_text + "/", xconfig], chroot)
|
||||||
else:
|
else:
|
||||||
logging.info("NOTE: No valid keymap specified for device")
|
logging.info("NOTE: No valid keymap specified for device")
|
||||||
|
|
||||||
|
|
||||||
def setup_timezone(args: PmbArgs):
|
def setup_timezone(config: Config):
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
suffix = Chroot(ChrootType.ROOTFS, config.device)
|
||||||
|
|
||||||
arch = args.deviceinfo["arch"]
|
arch = args.deviceinfo["arch"]
|
||||||
alpine_conf = pmb.helpers.package.get(args, "alpine-conf", arch)
|
alpine_conf = pmb.helpers.package.get(args, "alpine-conf", arch)
|
||||||
|
@ -378,7 +380,7 @@ def setup_timezone(args: PmbArgs):
|
||||||
if not pmb.parse.version.check_string(version, ">=3.14.0"):
|
if not pmb.parse.version.check_string(version, ">=3.14.0"):
|
||||||
setup_tz_cmd += ["-z"]
|
setup_tz_cmd += ["-z"]
|
||||||
setup_tz_cmd += [args.timezone]
|
setup_tz_cmd += [args.timezone]
|
||||||
pmb.chroot.root(args, setup_tz_cmd, suffix)
|
pmb.chroot.root(setup_tz_cmd, suffix)
|
||||||
|
|
||||||
|
|
||||||
def setup_hostname(args: PmbArgs):
|
def setup_hostname(args: PmbArgs):
|
||||||
|
@ -402,12 +404,12 @@ def setup_hostname(args: PmbArgs):
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
||||||
# Generate /etc/hostname
|
# Generate /etc/hostname
|
||||||
pmb.chroot.root(args, ["sh", "-c", "echo " + shlex.quote(hostname) +
|
pmb.chroot.root(["sh", "-c", "echo " + shlex.quote(hostname) +
|
||||||
" > /etc/hostname"], suffix)
|
" > /etc/hostname"], suffix)
|
||||||
# Update /etc/hosts
|
# Update /etc/hosts
|
||||||
regex = (r"s/^127\.0\.0\.1.*/127.0.0.1\t" + re.escape(hostname) +
|
regex = (r"s/^127\.0\.0\.1.*/127.0.0.1\t" + re.escape(hostname) +
|
||||||
" localhost.localdomain localhost/")
|
" localhost.localdomain localhost/")
|
||||||
pmb.chroot.root(args, ["sed", "-i", "-e", regex, "/etc/hosts"], suffix)
|
pmb.chroot.root(["sed", "-i", "-e", regex, "/etc/hosts"], suffix)
|
||||||
|
|
||||||
|
|
||||||
def setup_appstream(args: PmbArgs):
|
def setup_appstream(args: PmbArgs):
|
||||||
|
@ -421,10 +423,10 @@ def setup_appstream(args: PmbArgs):
|
||||||
if "alpine-appstream-downloader" not in installed_pkgs or args.offline:
|
if "alpine-appstream-downloader" not in installed_pkgs or args.offline:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not pmb.chroot.root(args, ["alpine-appstream-downloader",
|
if not pmb.chroot.root(["alpine-appstream-downloader",
|
||||||
"/mnt/appstream-data"], suffix, check=False):
|
"/mnt/appstream-data"], suffix, check=False):
|
||||||
pmb.chroot.root(args, ["mkdir", "-p", "/var/lib/swcatalog"], suffix)
|
pmb.chroot.root(["mkdir", "-p", "/var/lib/swcatalog"], suffix)
|
||||||
pmb.chroot.root(args, ["cp", "-r", "/mnt/appstream-data/icons",
|
pmb.chroot.root(["cp", "-r", "/mnt/appstream-data/icons",
|
||||||
"/mnt/appstream-data/xml",
|
"/mnt/appstream-data/xml",
|
||||||
"-t", "/var/lib/swcatalog"], suffix)
|
"-t", "/var/lib/swcatalog"], suffix)
|
||||||
|
|
||||||
|
@ -435,7 +437,7 @@ def disable_sshd(args: PmbArgs):
|
||||||
|
|
||||||
# check=False: rc-update doesn't exit with 0 if already disabled
|
# check=False: rc-update doesn't exit with 0 if already disabled
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.device)
|
chroot = Chroot(ChrootType.ROOTFS, args.device)
|
||||||
pmb.chroot.root(args, ["rc-update", "del", "sshd", "default"], chroot,
|
pmb.chroot.root(["rc-update", "del", "sshd", "default"], chroot,
|
||||||
check=False)
|
check=False)
|
||||||
|
|
||||||
# Verify that it's gone
|
# Verify that it's gone
|
||||||
|
@ -473,7 +475,7 @@ def disable_firewall(args: PmbArgs):
|
||||||
|
|
||||||
# check=False: rc-update doesn't exit with 0 if already disabled
|
# check=False: rc-update doesn't exit with 0 if already disabled
|
||||||
chroot = Chroot(ChrootType.ROOTFS, args.device)
|
chroot = Chroot(ChrootType.ROOTFS, args.device)
|
||||||
pmb.chroot.root(args, ["rc-update", "del", "nftables", "default"], chroot,
|
pmb.chroot.root(["rc-update", "del", "nftables", "default"], chroot,
|
||||||
check=False)
|
check=False)
|
||||||
|
|
||||||
# Verify that it's gone
|
# Verify that it's gone
|
||||||
|
@ -485,7 +487,7 @@ def disable_firewall(args: PmbArgs):
|
||||||
|
|
||||||
|
|
||||||
def print_firewall_info(args: PmbArgs):
|
def print_firewall_info(args: PmbArgs):
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
pmaports_ok = pmaports_cfg.get("supported_firewall", None) == "nftables"
|
pmaports_ok = pmaports_cfg.get("supported_firewall", None) == "nftables"
|
||||||
|
|
||||||
# Find kernel pmaport (will not be found if Alpine kernel is used)
|
# Find kernel pmaport (will not be found if Alpine kernel is used)
|
||||||
|
@ -495,8 +497,7 @@ def print_firewall_info(args: PmbArgs):
|
||||||
arch = args.deviceinfo["arch"]
|
arch = args.deviceinfo["arch"]
|
||||||
kernel = get_kernel_package(args, args.device)
|
kernel = get_kernel_package(args, args.device)
|
||||||
if kernel:
|
if kernel:
|
||||||
kernel_apkbuild = pmb.build._package.get_apkbuild(args, kernel[0],
|
kernel_apkbuild = pmb.build._package.get_apkbuild(kernel[0], arch)
|
||||||
arch)
|
|
||||||
if kernel_apkbuild:
|
if kernel_apkbuild:
|
||||||
opts = kernel_apkbuild["options"]
|
opts = kernel_apkbuild["options"]
|
||||||
apkbuild_has_opt = "pmb:kconfigcheck-nftables" in opts
|
apkbuild_has_opt = "pmb:kconfigcheck-nftables" in opts
|
||||||
|
@ -607,7 +608,7 @@ def embed_firmware(args: PmbArgs, suffix: Chroot):
|
||||||
logging.info("Embed firmware {} in the SD card image at offset {} with"
|
logging.info("Embed firmware {} in the SD card image at offset {} with"
|
||||||
" step size {}".format(binary, offset, step))
|
" step size {}".format(binary, offset, step))
|
||||||
filename = os.path.join(device_rootfs, binary_file.lstrip("/"))
|
filename = os.path.join(device_rootfs, binary_file.lstrip("/"))
|
||||||
pmb.chroot.root(args, ["dd", "if=" + filename, "of=/dev/install",
|
pmb.chroot.root(["dd", "if=" + filename, "of=/dev/install",
|
||||||
"bs=" + str(step), "seek=" + str(offset)])
|
"bs=" + str(step), "seek=" + str(offset)])
|
||||||
|
|
||||||
|
|
||||||
|
@ -627,12 +628,13 @@ def write_cgpt_kpart(args: PmbArgs, layout, suffix: Chroot):
|
||||||
args, ["dd", f"if={filename}", f"of=/dev/installp{layout['kernel']}"])
|
args, ["dd", f"if={filename}", f"of=/dev/installp{layout['kernel']}"])
|
||||||
|
|
||||||
|
|
||||||
def sanity_check_boot_size(args: PmbArgs):
|
def sanity_check_boot_size():
|
||||||
default = pmb.config.defaults["boot_size"]
|
default = Config().boot_size
|
||||||
if isinstance(default, str) and int(args.boot_size) >= int(default):
|
config = get_context().config
|
||||||
|
if int(config.boot_size) >= int(default):
|
||||||
return
|
return
|
||||||
logging.error("ERROR: your pmbootstrap has a small/invalid boot_size of"
|
logging.error("ERROR: your pmbootstrap has a small/invalid boot_size of"
|
||||||
f" {args.boot_size} configured, probably because the config"
|
f" {config.boot_size} configured, probably because the config"
|
||||||
" has been created with an old version.")
|
" has been created with an old version.")
|
||||||
logging.error("This can lead to problems later on, we recommend setting it"
|
logging.error("This can lead to problems later on, we recommend setting it"
|
||||||
f" to {default} MiB.")
|
f" to {default} MiB.")
|
||||||
|
@ -727,7 +729,6 @@ def get_uuid(args: PmbArgs, partition: Path):
|
||||||
:param partition: block device for getting UUID from
|
:param partition: block device for getting UUID from
|
||||||
"""
|
"""
|
||||||
return pmb.chroot.root(
|
return pmb.chroot.root(
|
||||||
args,
|
|
||||||
[
|
[
|
||||||
"blkid",
|
"blkid",
|
||||||
"-s", "UUID",
|
"-s", "UUID",
|
||||||
|
@ -751,7 +752,7 @@ def create_crypttab(args: PmbArgs, layout, chroot: Chroot):
|
||||||
crypttab = f"root UUID={luks_uuid} none luks\n"
|
crypttab = f"root UUID={luks_uuid} none luks\n"
|
||||||
|
|
||||||
(chroot / "tmp/crypttab").open("w").write(crypttab)
|
(chroot / "tmp/crypttab").open("w").write(crypttab)
|
||||||
pmb.chroot.root(args, ["mv", "/tmp/crypttab", "/etc/crypttab"], chroot)
|
pmb.chroot.root(["mv", "/tmp/crypttab", "/etc/crypttab"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def create_fstab(args: PmbArgs, layout, chroot: Chroot):
|
def create_fstab(args: PmbArgs, layout, chroot: Chroot):
|
||||||
|
@ -804,7 +805,7 @@ def create_fstab(args: PmbArgs, layout, chroot: Chroot):
|
||||||
|
|
||||||
with (chroot / "tmp/fstab").open("w") as f:
|
with (chroot / "tmp/fstab").open("w") as f:
|
||||||
f.write(fstab)
|
f.write(fstab)
|
||||||
pmb.chroot.root(args, ["mv", "/tmp/fstab", "/etc/fstab"], chroot)
|
pmb.chroot.root(["mv", "/tmp/fstab", "/etc/fstab"], chroot)
|
||||||
|
|
||||||
|
|
||||||
def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, steps,
|
def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, steps,
|
||||||
|
@ -824,7 +825,7 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
# Partition and fill image file/disk block device
|
# Partition and fill image file/disk block device
|
||||||
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(args, True)
|
||||||
(size_boot, size_root) = get_subpartitions_size(args, chroot)
|
(size_boot, size_root) = get_subpartitions_size(chroot)
|
||||||
layout = get_partition_layout(size_reserve, args.deviceinfo["cgpt_kpart"] \
|
layout = get_partition_layout(size_reserve, args.deviceinfo["cgpt_kpart"] \
|
||||||
and args.install_cgpt)
|
and args.install_cgpt)
|
||||||
if not args.rsync:
|
if not args.rsync:
|
||||||
|
@ -850,7 +851,7 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
|
|
||||||
# Run mkinitfs to pass UUIDs to cmdline
|
# Run mkinitfs to pass UUIDs to cmdline
|
||||||
logging.info(f"({chroot}) mkinitfs")
|
logging.info(f"({chroot}) mkinitfs")
|
||||||
pmb.chroot.root(args, ["mkinitfs"], chroot)
|
pmb.chroot.root(["mkinitfs"], chroot)
|
||||||
|
|
||||||
# Clean up after running mkinitfs in chroot
|
# Clean up after running mkinitfs in chroot
|
||||||
pmb.helpers.mount.umount_all(chroot.path)
|
pmb.helpers.mount.umount_all(chroot.path)
|
||||||
|
@ -883,25 +884,25 @@ def install_system_image(args: PmbArgs, size_reserve, chroot: Chroot, step, step
|
||||||
if sparse and not split and not disk:
|
if sparse and not split and not disk:
|
||||||
workdir = Path("/home/pmos/rootfs")
|
workdir = Path("/home/pmos/rootfs")
|
||||||
logging.info("(native) make sparse rootfs")
|
logging.info("(native) make sparse rootfs")
|
||||||
pmb.chroot.apk.install(args, ["android-tools"], Chroot.native())
|
pmb.chroot.apk.install(["android-tools"], Chroot.native())
|
||||||
sys_image = args.device + ".img"
|
sys_image = args.device + ".img"
|
||||||
sys_image_sparse = args.device + "-sparse.img"
|
sys_image_sparse = args.device + "-sparse.img"
|
||||||
pmb.chroot.user(args, ["img2simg", sys_image, sys_image_sparse],
|
pmb.chroot.user(["img2simg", sys_image, sys_image_sparse],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
pmb.chroot.user(args, ["mv", "-f", sys_image_sparse, sys_image],
|
pmb.chroot.user(["mv", "-f", sys_image_sparse, sys_image],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
# patch sparse image for Samsung devices if specified
|
# patch sparse image for Samsung devices if specified
|
||||||
samsungify_strategy = args.deviceinfo["flash_sparse_samsung_format"]
|
samsungify_strategy = args.deviceinfo["flash_sparse_samsung_format"]
|
||||||
if samsungify_strategy:
|
if samsungify_strategy:
|
||||||
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
logging.info("(native) convert sparse image into Samsung's sparse image format")
|
||||||
pmb.chroot.apk.install(args, ["sm-sparse-image-tool"], Chroot.native())
|
pmb.chroot.apk.install(["sm-sparse-image-tool"], Chroot.native())
|
||||||
sys_image = f"{args.device}.img"
|
sys_image = f"{args.device}.img"
|
||||||
sys_image_patched = f"{args.device}-patched.img"
|
sys_image_patched = f"{args.device}-patched.img"
|
||||||
pmb.chroot.user(args, ["sm_sparse_image_tool", "samsungify", "--strategy",
|
pmb.chroot.user(["sm_sparse_image_tool", "samsungify", "--strategy",
|
||||||
samsungify_strategy, sys_image, sys_image_patched],
|
samsungify_strategy, sys_image, sys_image_patched],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
pmb.chroot.user(args, ["mv", "-f", sys_image_patched, sys_image],
|
pmb.chroot.user(["mv", "-f", sys_image_patched, sys_image],
|
||||||
working_dir=workdir)
|
working_dir=workdir)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1016,10 +1017,10 @@ def install_on_device_installer(args: PmbArgs, step, steps):
|
||||||
packages = ([f"device-{args.device}",
|
packages = ([f"device-{args.device}",
|
||||||
"postmarketos-ondev"] +
|
"postmarketos-ondev"] +
|
||||||
get_kernel_package(args, args.device) +
|
get_kernel_package(args, args.device) +
|
||||||
get_nonfree_packages(args, args.device))
|
get_nonfree_packages(args.device))
|
||||||
|
|
||||||
chroot_installer = Chroot(ChrootType.INSTALLER, args.device)
|
chroot_installer = Chroot(ChrootType.INSTALLER, args.device)
|
||||||
pmb.chroot.apk.install(args, packages, chroot_installer)
|
pmb.chroot.apk.install(packages, chroot_installer)
|
||||||
|
|
||||||
# Move rootfs image into installer chroot
|
# Move rootfs image into installer chroot
|
||||||
img_path_dest = chroot_installer / "var/lib/rootfs.img"
|
img_path_dest = chroot_installer / "var/lib/rootfs.img"
|
||||||
|
@ -1035,7 +1036,7 @@ def install_on_device_installer(args: PmbArgs, step, steps):
|
||||||
# file into another format. This can all be done without pmbootstrap
|
# file into another format. This can all be done without pmbootstrap
|
||||||
# changes in the postmarketos-ondev package.
|
# changes in the postmarketos-ondev package.
|
||||||
logging.info(f"({chroot_installer}) ondev-prepare")
|
logging.info(f"({chroot_installer}) ondev-prepare")
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
channel_cfg = pmb.config.pmaports.read_config_channel(args)
|
||||||
env = {"ONDEV_CHANNEL": channel,
|
env = {"ONDEV_CHANNEL": channel,
|
||||||
"ONDEV_CHANNEL_BRANCH_APORTS": channel_cfg["branch_aports"],
|
"ONDEV_CHANNEL_BRANCH_APORTS": channel_cfg["branch_aports"],
|
||||||
|
@ -1045,7 +1046,7 @@ def install_on_device_installer(args: PmbArgs, step, steps):
|
||||||
"ONDEV_CIPHER": args.cipher,
|
"ONDEV_CIPHER": args.cipher,
|
||||||
"ONDEV_PMBOOTSTRAP_VERSION": pmb.__version__,
|
"ONDEV_PMBOOTSTRAP_VERSION": pmb.__version__,
|
||||||
"ONDEV_UI": args.ui}
|
"ONDEV_UI": args.ui}
|
||||||
pmb.chroot.root(args, ["ondev-prepare"], chroot_installer, env=env)
|
pmb.chroot.root(["ondev-prepare"], chroot_installer, env=env)
|
||||||
|
|
||||||
# Copy files specified with 'pmbootstrap install --ondev --cp'
|
# Copy files specified with 'pmbootstrap install --ondev --cp'
|
||||||
if args.ondev_cp:
|
if args.ondev_cp:
|
||||||
|
@ -1061,14 +1062,14 @@ def install_on_device_installer(args: PmbArgs, step, steps):
|
||||||
if not args.ondev_no_rootfs:
|
if not args.ondev_no_rootfs:
|
||||||
img_boot = f"{args.device}-boot.img"
|
img_boot = f"{args.device}-boot.img"
|
||||||
logging.info(f"(native) rm {img_boot}")
|
logging.info(f"(native) rm {img_boot}")
|
||||||
pmb.chroot.root(args, ["rm", f"/home/pmos/rootfs/{img_boot}"])
|
pmb.chroot.root(["rm", f"/home/pmos/rootfs/{img_boot}"])
|
||||||
|
|
||||||
# Disable root login
|
# Disable root login
|
||||||
setup_login(args, chroot_installer)
|
setup_login(args, chroot_installer)
|
||||||
|
|
||||||
# Generate installer image
|
# Generate installer image
|
||||||
size_reserve = round(os.path.getsize(img_path_dest) / 1024 / 1024) + 200
|
size_reserve = round(os.path.getsize(img_path_dest) / 1024 / 1024) + 200
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
boot_label = pmaports_cfg.get("supported_install_boot_label",
|
boot_label = pmaports_cfg.get("supported_install_boot_label",
|
||||||
"pmOS_inst_boot")
|
"pmOS_inst_boot")
|
||||||
install_system_image(args, size_reserve, chroot_installer, step, steps,
|
install_system_image(args, size_reserve, chroot_installer, step, steps,
|
||||||
|
@ -1100,12 +1101,12 @@ def get_selected_providers(args: PmbArgs, packages):
|
||||||
# aren't in pmaports. This is fine, with the assumption that
|
# aren't in pmaports. This is fine, with the assumption that
|
||||||
# installation will fail later in some other method if they truly don't
|
# installation will fail later in some other method if they truly don't
|
||||||
# exist in any repo.
|
# exist in any repo.
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, package, subpackages=False, must_exist=False)
|
apkbuild = pmb.helpers.pmaports.get(package, subpackages=False, must_exist=False)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
continue
|
continue
|
||||||
for select in apkbuild['_pmb_select']:
|
for select in apkbuild['_pmb_select']:
|
||||||
if select in args.selected_providers:
|
if select in get_context().config.providers:
|
||||||
ret += [args.selected_providers[select]]
|
ret += [get_context().config.providers[select]]
|
||||||
logging.debug(f"{package}: install selected_providers:"
|
logging.debug(f"{package}: install selected_providers:"
|
||||||
f" {', '.join(ret)}")
|
f" {', '.join(ret)}")
|
||||||
# Also iterate through dependencies to collect any providers they have
|
# Also iterate through dependencies to collect any providers they have
|
||||||
|
@ -1148,7 +1149,7 @@ def get_recommends(args: PmbArgs, packages) -> Sequence[str]:
|
||||||
# aren't in pmaports. This is fine, with the assumption that
|
# aren't in pmaports. This is fine, with the assumption that
|
||||||
# installation will fail later in some other method if they truly don't
|
# installation will fail later in some other method if they truly don't
|
||||||
# exist in any repo.
|
# exist in any repo.
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, package, must_exist=False)
|
apkbuild = pmb.helpers.pmaports.get(package, must_exist=False)
|
||||||
if not apkbuild:
|
if not apkbuild:
|
||||||
continue
|
continue
|
||||||
if package in apkbuild["subpackages"]:
|
if package in apkbuild["subpackages"]:
|
||||||
|
@ -1178,44 +1179,47 @@ def get_recommends(args: PmbArgs, packages) -> Sequence[str]:
|
||||||
def create_device_rootfs(args: PmbArgs, step, steps):
|
def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
# List all packages to be installed (including the ones specified by --add)
|
# List all packages to be installed (including the ones specified by --add)
|
||||||
# and upgrade the installed packages/apkindexes
|
# and upgrade the installed packages/apkindexes
|
||||||
logging.info(f'*** ({step}/{steps}) CREATE DEVICE ROOTFS ("{args.device}")'
|
context = get_context()
|
||||||
|
config = context.config
|
||||||
|
device = context.config.device
|
||||||
|
logging.info(f'*** ({step}/{steps}) CREATE DEVICE ROOTFS ("{device}")'
|
||||||
' ***')
|
' ***')
|
||||||
|
|
||||||
suffix = Chroot(ChrootType.ROOTFS, args.device)
|
suffix = Chroot(ChrootType.ROOTFS, device)
|
||||||
pmb.chroot.init(args, suffix)
|
pmb.chroot.init(suffix)
|
||||||
# Create user before installing packages, so post-install scripts of
|
# Create user before installing packages, so post-install scripts of
|
||||||
# pmaports can figure out the username (legacy reasons: pmaports#820)
|
# pmaports can figure out the username (legacy reasons: pmaports#820)
|
||||||
set_user(args)
|
set_user(context.config)
|
||||||
|
|
||||||
# Fill install_packages
|
# Fill install_packages
|
||||||
install_packages = (pmb.config.install_device_packages +
|
install_packages = (pmb.config.install_device_packages +
|
||||||
["device-" + args.device])
|
["device-" + device])
|
||||||
if not args.install_base:
|
if not args.install_base:
|
||||||
install_packages = [p for p in install_packages
|
install_packages = [p for p in install_packages
|
||||||
if p != "postmarketos-base"]
|
if p != "postmarketos-base"]
|
||||||
if args.ui.lower() != "none":
|
if config.ui.lower() != "none":
|
||||||
install_packages += ["postmarketos-ui-" + args.ui]
|
install_packages += ["postmarketos-ui-" + config.ui]
|
||||||
|
|
||||||
if pmb.config.other.is_systemd_selected(args):
|
if pmb.config.other.is_systemd_selected(context.config):
|
||||||
install_packages += ["postmarketos-base-systemd"]
|
install_packages += ["postmarketos-base-systemd"]
|
||||||
|
|
||||||
# Add additional providers of base/device/UI package
|
# Add additional providers of base/device/UI package
|
||||||
install_packages += get_selected_providers(args, install_packages)
|
install_packages += get_selected_providers(args, install_packages)
|
||||||
|
|
||||||
install_packages += get_kernel_package(args, args.device)
|
install_packages += get_kernel_package(args, device)
|
||||||
install_packages += get_nonfree_packages(args, args.device)
|
install_packages += get_nonfree_packages(device)
|
||||||
if args.ui.lower() != "none":
|
if context.config.ui.lower() != "none":
|
||||||
if args.ui_extras:
|
if context.config.ui_extras:
|
||||||
install_packages += ["postmarketos-ui-" + args.ui + "-extras"]
|
install_packages += ["postmarketos-ui-" + config.ui + "-extras"]
|
||||||
if args.extra_packages.lower() != "none":
|
if context.config.extra_packages.lower() != "none":
|
||||||
install_packages += args.extra_packages.split(",")
|
install_packages += context.config.extra_packages.split(",")
|
||||||
if args.add:
|
if args.add:
|
||||||
install_packages += args.add.split(",")
|
install_packages += args.add.split(",")
|
||||||
locale_is_set = (args.locale != pmb.config.defaults["locale"])
|
locale_is_set = (config.locale != pmb.config.defaults["locale"])
|
||||||
if locale_is_set:
|
if locale_is_set:
|
||||||
install_packages += ["lang", "musl-locales"]
|
install_packages += ["lang", "musl-locales"]
|
||||||
|
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
# postmarketos-base supports a dummy package for blocking unl0kr install
|
# postmarketos-base supports a dummy package for blocking unl0kr install
|
||||||
# when not required
|
# when not required
|
||||||
if pmaports_cfg.get("supported_base_nofde", None):
|
if pmaports_cfg.get("supported_base_nofde", None):
|
||||||
|
@ -1233,7 +1237,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
else:
|
else:
|
||||||
install_packages += ["postmarketos-base-nofde"]
|
install_packages += ["postmarketos-base-nofde"]
|
||||||
|
|
||||||
pmb.helpers.repo.update(args, args.deviceinfo["arch"])
|
pmb.helpers.repo.update(args.deviceinfo["arch"])
|
||||||
|
|
||||||
# Install uninstallable "dependencies" by default
|
# Install uninstallable "dependencies" by default
|
||||||
install_packages += get_recommends(args, install_packages)
|
install_packages += get_recommends(args, install_packages)
|
||||||
|
@ -1242,12 +1246,12 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
# dependency, in case the version increased
|
# dependency, in case the version increased
|
||||||
if args.build_pkgs_on_install:
|
if args.build_pkgs_on_install:
|
||||||
for pkgname in install_packages:
|
for pkgname in install_packages:
|
||||||
pmb.build.package(args, pkgname, args.deviceinfo["arch"])
|
pmb.build.package(pkgname, args.deviceinfo["arch"])
|
||||||
|
|
||||||
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
# Install all packages to device rootfs chroot (and rebuild the initramfs,
|
||||||
# because that doesn't always happen automatically yet, e.g. when the user
|
# because that doesn't always happen automatically yet, e.g. when the user
|
||||||
# installed a hook without pmbootstrap - see #69 for more info)
|
# installed a hook without pmbootstrap - see #69 for more info)
|
||||||
pmb.chroot.apk.install(args, install_packages, suffix)
|
pmb.chroot.apk.install(install_packages, suffix)
|
||||||
flavor = pmb.chroot.other.kernel_flavor_installed(args, suffix)
|
flavor = pmb.chroot.other.kernel_flavor_installed(args, suffix)
|
||||||
pmb.chroot.initfs.build(args, flavor, suffix)
|
pmb.chroot.initfs.build(args, flavor, suffix)
|
||||||
|
|
||||||
|
@ -1266,7 +1270,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
# alpine-baselayout by /etc/profile. Since they don't override the
|
# alpine-baselayout by /etc/profile. Since they don't override the
|
||||||
# locale if it exists, it warranties we have preference
|
# locale if it exists, it warranties we have preference
|
||||||
line = f"export LANG=${{LANG:-{shlex.quote(args.locale)}}}"
|
line = f"export LANG=${{LANG:-{shlex.quote(args.locale)}}}"
|
||||||
pmb.chroot.root(args, ["sh", "-c", f"echo {shlex.quote(line)}"
|
pmb.chroot.root(["sh", "-c", f"echo {shlex.quote(line)}"
|
||||||
" > /etc/profile.d/10locale-pmos.sh"], suffix)
|
" > /etc/profile.d/10locale-pmos.sh"], suffix)
|
||||||
|
|
||||||
# Set the hostname as the device name
|
# Set the hostname as the device name
|
||||||
|
@ -1280,7 +1284,7 @@ def create_device_rootfs(args: PmbArgs, step, steps):
|
||||||
|
|
||||||
def install(args: PmbArgs):
|
def install(args: PmbArgs):
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
sanity_check_boot_size(args)
|
sanity_check_boot_size()
|
||||||
if not args.android_recovery_zip and args.disk:
|
if not args.android_recovery_zip and args.disk:
|
||||||
sanity_check_disk(args)
|
sanity_check_disk(args)
|
||||||
sanity_check_disk_size(args)
|
sanity_check_disk_size(args)
|
||||||
|
@ -1303,8 +1307,8 @@ def install(args: PmbArgs):
|
||||||
# Install required programs in native chroot
|
# Install required programs in native chroot
|
||||||
step = 1
|
step = 1
|
||||||
logging.info(f"*** ({step}/{steps}) PREPARE NATIVE CHROOT ***")
|
logging.info(f"*** ({step}/{steps}) PREPARE NATIVE CHROOT ***")
|
||||||
pmb.chroot.init(args, Chroot.native())
|
pmb.chroot.init(Chroot.native())
|
||||||
pmb.chroot.apk.install(args, pmb.config.install_native_packages, Chroot.native(),
|
pmb.chroot.apk.install(pmb.config.install_native_packages, Chroot.native(),
|
||||||
build=False)
|
build=False)
|
||||||
step += 1
|
step += 1
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@ from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
import pmb.install.losetup
|
import pmb.install.losetup
|
||||||
import pmb.helpers.cli
|
import pmb.helpers.cli
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def previous_install(args: PmbArgs, path: Path):
|
def previous_install(args: PmbArgs, path: Path):
|
||||||
|
@ -28,7 +28,7 @@ def previous_install(args: PmbArgs, path: Path):
|
||||||
pmb.helpers.mount.bind_file(blockdevice_outside,
|
pmb.helpers.mount.bind_file(blockdevice_outside,
|
||||||
Chroot.native() / blockdevice_inside)
|
Chroot.native() / blockdevice_inside)
|
||||||
try:
|
try:
|
||||||
label = pmb.chroot.root(args, ["blkid", "-s", "LABEL",
|
label = pmb.chroot.root(["blkid", "-s", "LABEL",
|
||||||
"-o", "value",
|
"-o", "value",
|
||||||
blockdevice_inside],
|
blockdevice_inside],
|
||||||
output_return=True)
|
output_return=True)
|
||||||
|
@ -87,19 +87,19 @@ def create_and_mount_image(args: PmbArgs, size_boot, size_root, size_reserve,
|
||||||
outside = chroot / img_path
|
outside = chroot / img_path
|
||||||
if os.path.exists(outside):
|
if os.path.exists(outside):
|
||||||
pmb.helpers.mount.umount_all(chroot / "mnt")
|
pmb.helpers.mount.umount_all(chroot / "mnt")
|
||||||
pmb.install.losetup.umount(args, img_path)
|
pmb.install.losetup.umount(img_path)
|
||||||
pmb.chroot.root(args, ["rm", img_path])
|
pmb.chroot.root(["rm", img_path])
|
||||||
|
|
||||||
# Make sure there is enough free space
|
# Make sure there is enough free space
|
||||||
size_mb = round(size_boot + size_reserve + size_root)
|
size_mb = round(size_boot + size_reserve + size_root)
|
||||||
disk_data = os.statvfs(pmb.config.work)
|
disk_data = os.statvfs(get_context().config.work)
|
||||||
free = round((disk_data.f_bsize * disk_data.f_bavail) / (1024**2))
|
free = round((disk_data.f_bsize * disk_data.f_bavail) / (1024**2))
|
||||||
if size_mb > free:
|
if size_mb > free:
|
||||||
raise RuntimeError("Not enough free space to create rootfs image! "
|
raise RuntimeError("Not enough free space to create rootfs image! "
|
||||||
f"(free: {free}M, required: {size_mb}M)")
|
f"(free: {free}M, required: {size_mb}M)")
|
||||||
|
|
||||||
# Create empty image files
|
# Create empty image files
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/rootfs"])
|
pmb.chroot.user(["mkdir", "-p", "/home/pmos/rootfs"])
|
||||||
size_mb_full = str(size_mb) + "M"
|
size_mb_full = str(size_mb) + "M"
|
||||||
size_mb_boot = str(round(size_boot)) + "M"
|
size_mb_boot = str(round(size_boot)) + "M"
|
||||||
size_mb_root = str(round(size_root)) + "M"
|
size_mb_root = str(round(size_root)) + "M"
|
||||||
|
@ -110,7 +110,7 @@ def create_and_mount_image(args: PmbArgs, size_boot, size_root, size_reserve,
|
||||||
for img_path, size_mb in images.items():
|
for img_path, size_mb in images.items():
|
||||||
logging.info(f"(native) create {img_path.name} "
|
logging.info(f"(native) create {img_path.name} "
|
||||||
f"({size_mb})")
|
f"({size_mb})")
|
||||||
pmb.chroot.root(args, ["truncate", "-s", size_mb, img_path])
|
pmb.chroot.root(["truncate", "-s", size_mb, img_path])
|
||||||
|
|
||||||
# Mount to /dev/install
|
# Mount to /dev/install
|
||||||
mount_image_paths = {img_path_full: "/dev/install"}
|
mount_image_paths = {img_path_full: "/dev/install"}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def install_fsprogs(args: PmbArgs, filesystem):
|
def install_fsprogs(args: PmbArgs, filesystem):
|
||||||
|
@ -11,7 +11,7 @@ def install_fsprogs(args: PmbArgs, filesystem):
|
||||||
fsprogs = pmb.config.filesystems.get(filesystem)
|
fsprogs = pmb.config.filesystems.get(filesystem)
|
||||||
if not fsprogs:
|
if not fsprogs:
|
||||||
raise RuntimeError(f"Unsupported filesystem: {filesystem}")
|
raise RuntimeError(f"Unsupported filesystem: {filesystem}")
|
||||||
pmb.chroot.apk.install(args, [fsprogs])
|
pmb.chroot.apk.install([fsprogs])
|
||||||
|
|
||||||
|
|
||||||
def format_and_mount_boot(args: PmbArgs, device, boot_label):
|
def format_and_mount_boot(args: PmbArgs, device, boot_label):
|
||||||
|
@ -28,21 +28,21 @@ def format_and_mount_boot(args: PmbArgs, device, boot_label):
|
||||||
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
||||||
f" {mountpoint}")
|
f" {mountpoint}")
|
||||||
if filesystem == "fat16":
|
if filesystem == "fat16":
|
||||||
pmb.chroot.root(args, ["mkfs.fat", "-F", "16", "-n", boot_label,
|
pmb.chroot.root(["mkfs.fat", "-F", "16", "-n", boot_label,
|
||||||
device])
|
device])
|
||||||
elif filesystem == "fat32":
|
elif filesystem == "fat32":
|
||||||
pmb.chroot.root(args, ["mkfs.fat", "-F", "32", "-n", boot_label,
|
pmb.chroot.root(["mkfs.fat", "-F", "32", "-n", boot_label,
|
||||||
device])
|
device])
|
||||||
elif filesystem == "ext2":
|
elif filesystem == "ext2":
|
||||||
pmb.chroot.root(args, ["mkfs.ext2", "-F", "-q", "-L", boot_label,
|
pmb.chroot.root(["mkfs.ext2", "-F", "-q", "-L", boot_label,
|
||||||
device])
|
device])
|
||||||
elif filesystem == "btrfs":
|
elif filesystem == "btrfs":
|
||||||
pmb.chroot.root(args, ["mkfs.btrfs", "-f", "-q", "-L", boot_label,
|
pmb.chroot.root(["mkfs.btrfs", "-f", "-q", "-L", boot_label,
|
||||||
device])
|
device])
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Filesystem " + filesystem + " is not supported!")
|
raise RuntimeError("Filesystem " + filesystem + " is not supported!")
|
||||||
pmb.chroot.root(args, ["mkdir", "-p", mountpoint])
|
pmb.chroot.root(["mkdir", "-p", mountpoint])
|
||||||
pmb.chroot.root(args, ["mount", device, mountpoint])
|
pmb.chroot.root(["mount", device, mountpoint])
|
||||||
|
|
||||||
|
|
||||||
def format_luks_root(args: PmbArgs, device):
|
def format_luks_root(args: PmbArgs, device):
|
||||||
|
@ -56,15 +56,15 @@ def format_luks_root(args: PmbArgs, device):
|
||||||
logging.info(" *** TYPE IN THE FULL DISK ENCRYPTION PASSWORD (TWICE!) ***")
|
logging.info(" *** TYPE IN THE FULL DISK ENCRYPTION PASSWORD (TWICE!) ***")
|
||||||
|
|
||||||
# Avoid cryptsetup warning about missing locking directory
|
# Avoid cryptsetup warning about missing locking directory
|
||||||
pmb.chroot.root(args, ["mkdir", "-p", "/run/cryptsetup"])
|
pmb.chroot.root(["mkdir", "-p", "/run/cryptsetup"])
|
||||||
|
|
||||||
pmb.chroot.root(args, ["cryptsetup", "luksFormat",
|
pmb.chroot.root(["cryptsetup", "luksFormat",
|
||||||
"-q",
|
"-q",
|
||||||
"--cipher", args.cipher,
|
"--cipher", args.cipher,
|
||||||
"--iter-time", args.iter_time,
|
"--iter-time", args.iter_time,
|
||||||
"--use-random",
|
"--use-random",
|
||||||
device], output="interactive")
|
device], output="interactive")
|
||||||
pmb.chroot.root(args, ["cryptsetup", "luksOpen", device, "pm_crypt"],
|
pmb.chroot.root(["cryptsetup", "luksOpen", device, "pm_crypt"],
|
||||||
output="interactive")
|
output="interactive")
|
||||||
|
|
||||||
if not (Chroot.native() / mountpoint).exists():
|
if not (Chroot.native() / mountpoint).exists():
|
||||||
|
@ -73,7 +73,7 @@ def format_luks_root(args: PmbArgs, device):
|
||||||
|
|
||||||
def get_root_filesystem(args: PmbArgs):
|
def get_root_filesystem(args: PmbArgs):
|
||||||
ret = args.filesystem or args.deviceinfo["root_filesystem"] or "ext4"
|
ret = args.filesystem or args.deviceinfo["root_filesystem"] or "ext4"
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
|
|
||||||
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
supported = pmaports_cfg.get("supported_root_filesystems", "ext4")
|
||||||
supported_list = supported.split(",")
|
supported_list = supported.split(",")
|
||||||
|
@ -116,9 +116,9 @@ def prepare_btrfs_subvolumes(args: PmbArgs, device, mountpoint):
|
||||||
["btrfs", "subvol", "set-default", f"{mountpoint}/@"])
|
["btrfs", "subvol", "set-default", f"{mountpoint}/@"])
|
||||||
|
|
||||||
# Make directories to mount subvols onto
|
# Make directories to mount subvols onto
|
||||||
pmb.chroot.root(args, ["umount", mountpoint])
|
pmb.chroot.root(["umount", mountpoint])
|
||||||
pmb.chroot.root(args, ["mount", device, mountpoint])
|
pmb.chroot.root(["mount", device, mountpoint])
|
||||||
pmb.chroot.root(args, ["mkdir",
|
pmb.chroot.root(["mkdir",
|
||||||
f"{mountpoint}/home",
|
f"{mountpoint}/home",
|
||||||
f"{mountpoint}/root",
|
f"{mountpoint}/root",
|
||||||
f"{mountpoint}/.snapshots",
|
f"{mountpoint}/.snapshots",
|
||||||
|
@ -127,8 +127,8 @@ def prepare_btrfs_subvolumes(args: PmbArgs, device, mountpoint):
|
||||||
|
|
||||||
# snapshots contain sensitive information,
|
# snapshots contain sensitive information,
|
||||||
# and should only be readable by root.
|
# and should only be readable by root.
|
||||||
pmb.chroot.root(args, ["chmod", "700", f"{mountpoint}/root"])
|
pmb.chroot.root(["chmod", "700", f"{mountpoint}/root"])
|
||||||
pmb.chroot.root(args, ["chmod", "700", f"{mountpoint}/.snapshots"])
|
pmb.chroot.root(["chmod", "700", f"{mountpoint}/.snapshots"])
|
||||||
|
|
||||||
# Mount subvols
|
# Mount subvols
|
||||||
pmb.chroot.root(args,
|
pmb.chroot.root(args,
|
||||||
|
@ -149,7 +149,7 @@ def prepare_btrfs_subvolumes(args: PmbArgs, device, mountpoint):
|
||||||
|
|
||||||
# Disable CoW for /var, to avoid write multiplication
|
# Disable CoW for /var, to avoid write multiplication
|
||||||
# and slowdown on databases, containers and VM images.
|
# and slowdown on databases, containers and VM images.
|
||||||
pmb.chroot.root(args, ["chattr", "+C", f"{mountpoint}/var"])
|
pmb.chroot.root(["chattr", "+C", f"{mountpoint}/var"])
|
||||||
|
|
||||||
|
|
||||||
def format_and_mount_root(args: PmbArgs, device, root_label, disk):
|
def format_and_mount_root(args: PmbArgs, device, root_label, disk):
|
||||||
|
@ -182,13 +182,13 @@ def format_and_mount_root(args: PmbArgs, device, root_label, disk):
|
||||||
|
|
||||||
install_fsprogs(args, filesystem)
|
install_fsprogs(args, filesystem)
|
||||||
logging.info(f"(native) format {device} (root, {filesystem})")
|
logging.info(f"(native) format {device} (root, {filesystem})")
|
||||||
pmb.chroot.root(args, mkfs_root_args + [device])
|
pmb.chroot.root(mkfs_root_args + [device])
|
||||||
|
|
||||||
# Mount
|
# Mount
|
||||||
mountpoint = "/mnt/install"
|
mountpoint = "/mnt/install"
|
||||||
logging.info("(native) mount " + device + " to " + mountpoint)
|
logging.info("(native) mount " + device + " to " + mountpoint)
|
||||||
pmb.chroot.root(args, ["mkdir", "-p", mountpoint])
|
pmb.chroot.root(["mkdir", "-p", mountpoint])
|
||||||
pmb.chroot.root(args, ["mount", device, mountpoint])
|
pmb.chroot.root(["mount", device, mountpoint])
|
||||||
|
|
||||||
if not args.rsync and filesystem == "btrfs":
|
if not args.rsync and filesystem == "btrfs":
|
||||||
# Make flat btrfs subvolume layout
|
# Make flat btrfs subvolume layout
|
||||||
|
|
|
@ -8,7 +8,7 @@ from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
|
@ -46,7 +46,7 @@ def mount(args: PmbArgs, img_path: Path):
|
||||||
if sector_size:
|
if sector_size:
|
||||||
losetup_cmd += ["-b", str(int(sector_size))]
|
losetup_cmd += ["-b", str(int(sector_size))]
|
||||||
|
|
||||||
pmb.chroot.root(args, losetup_cmd, check=False)
|
pmb.chroot.root(losetup_cmd, check=False)
|
||||||
try:
|
try:
|
||||||
device_by_back_file(args, img_path)
|
device_by_back_file(args, img_path)
|
||||||
return
|
return
|
||||||
|
@ -57,13 +57,13 @@ def mount(args: PmbArgs, img_path: Path):
|
||||||
raise RuntimeError(f"Failed to mount loop device: {img_path}")
|
raise RuntimeError(f"Failed to mount loop device: {img_path}")
|
||||||
|
|
||||||
|
|
||||||
def device_by_back_file(args: PmbArgs, back_file: Path) -> Path:
|
def device_by_back_file(back_file: Path) -> Path:
|
||||||
"""
|
"""
|
||||||
Get the /dev/loopX device that points to a specific image file.
|
Get the /dev/loopX device that points to a specific image file.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Get list from losetup
|
# Get list from losetup
|
||||||
losetup_output = pmb.chroot.root(args, ["losetup", "--json", "--list"],
|
losetup_output = pmb.chroot.root(["losetup", "--json", "--list"],
|
||||||
output_return=True)
|
output_return=True)
|
||||||
if not losetup_output:
|
if not losetup_output:
|
||||||
raise RuntimeError("losetup failed")
|
raise RuntimeError("losetup failed")
|
||||||
|
@ -76,14 +76,14 @@ def device_by_back_file(args: PmbArgs, back_file: Path) -> Path:
|
||||||
raise RuntimeError(f"Failed to find loop device for {back_file}")
|
raise RuntimeError(f"Failed to find loop device for {back_file}")
|
||||||
|
|
||||||
|
|
||||||
def umount(args: PmbArgs, img_path: Path):
|
def umount(img_path: Path):
|
||||||
"""
|
"""
|
||||||
:param img_path: Path to the img file inside native chroot.
|
:param img_path: Path to the img file inside native chroot.
|
||||||
"""
|
"""
|
||||||
device: Path
|
device: Path
|
||||||
try:
|
try:
|
||||||
device = device_by_back_file(args, img_path)
|
device = device_by_back_file(img_path)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
return
|
return
|
||||||
logging.debug(f"(native) umount {device}")
|
logging.debug(f"(native) umount {device}")
|
||||||
pmb.chroot.root(args, ["losetup", "-d", device])
|
pmb.chroot.root(["losetup", "-d", device])
|
||||||
|
|
|
@ -7,7 +7,7 @@ import os
|
||||||
import time
|
import time
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.install.losetup
|
import pmb.install.losetup
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ def partition(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
commands += [["set", str(layout["boot"]), "esp", "on"]]
|
commands += [["set", str(layout["boot"]), "esp", "on"]]
|
||||||
|
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, ["parted", "-s", "/dev/install"] +
|
pmb.chroot.root(["parted", "-s", "/dev/install"] +
|
||||||
command, check=False)
|
command, check=False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ def partition_cgpt(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
:param size_reserve: empty partition between root and boot in MiB (pma#463)
|
:param size_reserve: empty partition between root and boot in MiB (pma#463)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, ["cgpt"], build=False)
|
pmb.chroot.apk.install(["cgpt"], build=False)
|
||||||
|
|
||||||
cgpt = {
|
cgpt = {
|
||||||
'kpart_start': args.deviceinfo["cgpt_kpart_start"],
|
'kpart_start': args.deviceinfo["cgpt_kpart_start"],
|
||||||
|
@ -196,4 +196,4 @@ def partition_cgpt(args: PmbArgs, layout, size_boot, size_reserve):
|
||||||
]
|
]
|
||||||
|
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, command, check=False)
|
pmb.chroot.root(command, check=False)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from pmb.helpers import logging
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.flasher
|
import pmb.flasher
|
||||||
import pmb.helpers.frontend
|
import pmb.helpers.frontend
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ def create_zip(args: PmbArgs, suffix):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
options["FLAVOR"] = ""
|
options["FLAVOR"] = ""
|
||||||
else:
|
else:
|
||||||
|
@ -71,4 +71,4 @@ def create_zip(args: PmbArgs, suffix):
|
||||||
["gzip", "-f1", "rootfs.tar"],
|
["gzip", "-f1", "rootfs.tar"],
|
||||||
["build-recovery-zip", args.device]]
|
["build-recovery-zip", args.device]]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, command, suffix, working_dir=zip_root)
|
pmb.chroot.root(command, suffix, working_dir=zip_root)
|
||||||
|
|
|
@ -3,23 +3,23 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import Config
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
|
||||||
def get_groups(args: PmbArgs) -> List[str]:
|
def get_groups(config: Config) -> List[str]:
|
||||||
""" Get all groups to which the user additionally must be added.
|
""" Get all groups to which the user additionally must be added.
|
||||||
The list of groups are listed in _pmb_groups of the UI and
|
The list of groups are listed in _pmb_groups of the UI and
|
||||||
UI-extras package.
|
UI-extras package.
|
||||||
|
|
||||||
:returns: list of groups, e.g. ["feedbackd", "udev"] """
|
:returns: list of groups, e.g. ["feedbackd", "udev"] """
|
||||||
ret: List[str] = []
|
ret: List[str] = []
|
||||||
if args.ui == "none":
|
if config.ui == "none":
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
# UI package
|
# UI package
|
||||||
meta = f"postmarketos-ui-{args.ui}"
|
meta = f"postmarketos-ui-{config.ui}"
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, meta)
|
apkbuild = pmb.helpers.pmaports.get(meta)
|
||||||
groups = apkbuild["_pmb_groups"]
|
groups = apkbuild["_pmb_groups"]
|
||||||
if groups:
|
if groups:
|
||||||
logging.debug(f"{meta}: install _pmb_groups:"
|
logging.debug(f"{meta}: install _pmb_groups:"
|
||||||
|
@ -28,7 +28,7 @@ def get_groups(args: PmbArgs) -> List[str]:
|
||||||
|
|
||||||
# UI-extras subpackage
|
# UI-extras subpackage
|
||||||
meta_extras = f"{meta}-extras"
|
meta_extras = f"{meta}-extras"
|
||||||
if args.ui_extras and meta_extras in apkbuild["subpackages"]:
|
if config.ui_extras and meta_extras in apkbuild["subpackages"]:
|
||||||
groups = apkbuild["subpackages"][meta_extras]["_pmb_groups"]
|
groups = apkbuild["subpackages"][meta_extras]["_pmb_groups"]
|
||||||
if groups:
|
if groups:
|
||||||
logging.debug(f"{meta_extras}: install _pmb_groups:"
|
logging.debug(f"{meta_extras}: install _pmb_groups:"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pmb.chroot.run
|
import pmb.chroot.run
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def start_nbd_server(args: PmbArgs, ip="172.16.42.2", port=9999):
|
||||||
:param port: port of nbd server
|
:param port: port of nbd server
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, ['nbd'])
|
pmb.chroot.apk.install(['nbd'])
|
||||||
|
|
||||||
chroot = Chroot.native()
|
chroot = Chroot.native()
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ def start_nbd_server(args: PmbArgs, ip="172.16.42.2", port=9999):
|
||||||
f"{args.device}?"):
|
f"{args.device}?"):
|
||||||
return
|
return
|
||||||
pmb.chroot.run(args, ["cp", rootfs_path2, rootfs_path])
|
pmb.chroot.run(args, ["cp", rootfs_path2, rootfs_path])
|
||||||
logging.info(f"NOTE: Copied device image to {pmb.config.work}"
|
logging.info(f"NOTE: Copied device image to {get_context().config.work}"
|
||||||
f"/images_netboot/. The image will persist \"pmbootstrap "
|
f"/images_netboot/. The image will persist \"pmbootstrap "
|
||||||
f"zap\" for your convenience. Use \"pmbootstrap netboot "
|
f"zap\" for your convenience. Use \"pmbootstrap netboot "
|
||||||
f"serve --help\" for more options.")
|
f"serve --help\" for more options.")
|
||||||
|
|
|
@ -8,7 +8,7 @@ import re
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ def apkbuild(path: Path, check_pkgver=True, check_pkgname=True):
|
||||||
path = path / "APKBUILD"
|
path = path / "APKBUILD"
|
||||||
|
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise FileNotFoundError(f"{path.relative_to(pmb.config.work)} not found!")
|
raise FileNotFoundError(f"{path.relative_to(get_context().config.work)} not found!")
|
||||||
|
|
||||||
# Try to get a cached result first (we assume that the aports don't change
|
# Try to get a cached result first (we assume that the aports don't change
|
||||||
# in one pmbootstrap call)
|
# in one pmbootstrap call)
|
||||||
|
@ -367,7 +367,7 @@ def apkbuild(path: Path, check_pkgver=True, check_pkgname=True):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def kernels(args: PmbArgs, device):
|
def kernels(device: str):
|
||||||
"""
|
"""
|
||||||
Get the possible kernels from a device-* APKBUILD.
|
Get the possible kernels from a device-* APKBUILD.
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ def kernels(args: PmbArgs, device):
|
||||||
"downstream": "Downstream description"}
|
"downstream": "Downstream description"}
|
||||||
"""
|
"""
|
||||||
# Read the APKBUILD
|
# Read the APKBUILD
|
||||||
apkbuild_path = pmb.helpers.devices.find_path(args, device, 'APKBUILD')
|
apkbuild_path = pmb.helpers.devices.find_path(device, 'APKBUILD')
|
||||||
if apkbuild_path is None:
|
if apkbuild_path is None:
|
||||||
return None
|
return None
|
||||||
subpackages = apkbuild(apkbuild_path)["subpackages"]
|
subpackages = apkbuild(apkbuild_path)["subpackages"]
|
||||||
|
|
|
@ -6,7 +6,6 @@ from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tarfile
|
import tarfile
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
|
||||||
import pmb.helpers.package
|
import pmb.helpers.package
|
||||||
import pmb.helpers.repo
|
import pmb.helpers.repo
|
||||||
import pmb.parse.version
|
import pmb.parse.version
|
||||||
|
@ -261,7 +260,7 @@ def clear_cache(path: Path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def providers(args: PmbArgs, package, arch=None, must_exist=True, indexes=None):
|
def providers(package, arch=None, must_exist=True, indexes=None):
|
||||||
"""
|
"""
|
||||||
Get all packages, which provide one package.
|
Get all packages, which provide one package.
|
||||||
|
|
||||||
|
@ -277,7 +276,7 @@ def providers(args: PmbArgs, package, arch=None, must_exist=True, indexes=None):
|
||||||
"""
|
"""
|
||||||
if not indexes:
|
if not indexes:
|
||||||
arch = arch or pmb.config.arch_native
|
arch = arch or pmb.config.arch_native
|
||||||
indexes = pmb.helpers.repo.apkindex_files(args, arch)
|
indexes = pmb.helpers.repo.apkindex_files(arch)
|
||||||
|
|
||||||
package = pmb.helpers.package.remove_operators(package)
|
package = pmb.helpers.package.remove_operators(package)
|
||||||
|
|
||||||
|
@ -353,7 +352,7 @@ def provider_shortest(providers, pkgname):
|
||||||
return providers[ret]
|
return providers[ret]
|
||||||
|
|
||||||
|
|
||||||
def package(args: PmbArgs, package, arch=None, must_exist=True, indexes=None):
|
def package(package, arch=None, must_exist=True, indexes=None):
|
||||||
"""
|
"""
|
||||||
Get a specific package's data from an apkindex.
|
Get a specific package's data from an apkindex.
|
||||||
|
|
||||||
|
@ -372,7 +371,7 @@ def package(args: PmbArgs, package, arch=None, must_exist=True, indexes=None):
|
||||||
or None when the package was not found.
|
or None when the package was not found.
|
||||||
"""
|
"""
|
||||||
# Provider with the same package
|
# Provider with the same package
|
||||||
package_providers = providers(args, package, arch, must_exist, indexes)
|
package_providers = providers(package, arch, must_exist, indexes)
|
||||||
if package in package_providers:
|
if package in package_providers:
|
||||||
return package_providers[package]
|
return package_providers[package]
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,6 @@ import platform
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
|
||||||
from pmb.core import Chroot, ChrootType
|
|
||||||
|
|
||||||
def alpine_native():
|
def alpine_native():
|
||||||
machine = platform.machine()
|
machine = platform.machine()
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import Config, PmbArgs
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import argcomplete # type:ignore[import-untyped]
|
import argcomplete # type:ignore[import-untyped]
|
||||||
|
@ -637,7 +637,8 @@ def get_parser():
|
||||||
parser = argparse.ArgumentParser(prog="pmbootstrap")
|
parser = argparse.ArgumentParser(prog="pmbootstrap")
|
||||||
arch_native = pmb.config.arch_native
|
arch_native = pmb.config.arch_native
|
||||||
arch_choices = set(pmb.config.build_device_architectures + [arch_native])
|
arch_choices = set(pmb.config.build_device_architectures + [arch_native])
|
||||||
mirrors_pmos_default = pmb.config.defaults["mirrors_postmarketos"]
|
default_config = Config()
|
||||||
|
mirrors_pmos_default = ",".join(default_config.mirrors_postmarketos)
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
parser.add_argument("-V", "--version", action="version",
|
parser.add_argument("-V", "--version", action="version",
|
||||||
|
@ -653,7 +654,7 @@ def get_parser():
|
||||||
metavar="URL", action="append", default=[])
|
metavar="URL", action="append", default=[])
|
||||||
parser.add_argument("-m", "--mirror-alpine", dest="mirror_alpine",
|
parser.add_argument("-m", "--mirror-alpine", dest="mirror_alpine",
|
||||||
help="Alpine Linux mirror, default: "
|
help="Alpine Linux mirror, default: "
|
||||||
f"{pmb.config.defaults['mirror_alpine']}",
|
f"{default_config.mirror_alpine}",
|
||||||
metavar="URL")
|
metavar="URL")
|
||||||
parser.add_argument("-j", "--jobs", help="parallel jobs when compiling")
|
parser.add_argument("-j", "--jobs", help="parallel jobs when compiling")
|
||||||
parser.add_argument("-E", "--extra-space",
|
parser.add_argument("-E", "--extra-space",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import os
|
import os
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.chroot.run
|
import pmb.chroot.run
|
||||||
import pmb.chroot.other
|
import pmb.chroot.other
|
||||||
|
@ -79,7 +79,7 @@ def bootimg(args: PmbArgs, path: Path):
|
||||||
logging.info("NOTE: You will be prompted for your sudo/doas password, so"
|
logging.info("NOTE: You will be prompted for your sudo/doas password, so"
|
||||||
" we can set up a chroot to extract and analyze your"
|
" we can set up a chroot to extract and analyze your"
|
||||||
" boot.img file")
|
" boot.img file")
|
||||||
pmb.chroot.apk.install(args, ["file", "unpackbootimg"], Chroot.native())
|
pmb.chroot.apk.install(["file", "unpackbootimg"], Chroot.native())
|
||||||
|
|
||||||
temp_path = pmb.chroot.other.tempfolder(args, Path("/tmp/bootimg_parser"))
|
temp_path = pmb.chroot.other.tempfolder(args, Path("/tmp/bootimg_parser"))
|
||||||
bootimg_path = Chroot.native() / temp_path / "boot.img"
|
bootimg_path = Chroot.native() / temp_path / "boot.img"
|
||||||
|
@ -89,7 +89,7 @@ def bootimg(args: PmbArgs, path: Path):
|
||||||
pmb.helpers.run.root(["cp", path, bootimg_path])
|
pmb.helpers.run.root(["cp", path, bootimg_path])
|
||||||
pmb.helpers.run.root(["chmod", "a+r", bootimg_path])
|
pmb.helpers.run.root(["chmod", "a+r", bootimg_path])
|
||||||
|
|
||||||
file_output = pmb.chroot.user(args, ["file", "-b", "boot.img"],
|
file_output = pmb.chroot.user(["file", "-b", "boot.img"],
|
||||||
working_dir=temp_path,
|
working_dir=temp_path,
|
||||||
output_return=True).rstrip()
|
output_return=True).rstrip()
|
||||||
if "android bootimg" not in file_output.lower():
|
if "android bootimg" not in file_output.lower():
|
||||||
|
@ -111,7 +111,7 @@ def bootimg(args: PmbArgs, path: Path):
|
||||||
file_output + ")")
|
file_output + ")")
|
||||||
|
|
||||||
# Extract all the files
|
# Extract all the files
|
||||||
pmb.chroot.user(args, ["unpackbootimg", "-i", "boot.img"],
|
pmb.chroot.user(["unpackbootimg", "-i", "boot.img"],
|
||||||
working_dir=temp_path)
|
working_dir=temp_path)
|
||||||
|
|
||||||
output = {}
|
output = {}
|
||||||
|
|
|
@ -4,20 +4,20 @@ from typing import Dict, List, Sequence, Set
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
from pmb.core import Chroot
|
from pmb.core import Chroot, get_context
|
||||||
|
|
||||||
|
|
||||||
def package_from_aports(args: PmbArgs, pkgname_depend):
|
def package_from_aports(pkgname_depend):
|
||||||
"""
|
"""
|
||||||
:returns: None when there is no aport, or a dict with the keys pkgname,
|
:returns: None when there is no aport, or a dict with the keys pkgname,
|
||||||
depends, version. The version is the combined pkgver and pkgrel.
|
depends, version. The version is the combined pkgver and pkgrel.
|
||||||
"""
|
"""
|
||||||
# Get the aport
|
# Get the aport
|
||||||
aport = pmb.helpers.pmaports.find_optional(args, pkgname_depend)
|
aport = pmb.helpers.pmaports.find_optional(pkgname_depend)
|
||||||
if not aport:
|
if not aport:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ def package_from_aports(args: PmbArgs, pkgname_depend):
|
||||||
"version": version}
|
"version": version}
|
||||||
|
|
||||||
|
|
||||||
def package_provider(args: PmbArgs, pkgname, pkgnames_install, suffix: Chroot=Chroot.native()):
|
def package_provider(pkgname, pkgnames_install, suffix: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
:param pkgnames_install: packages to be installed
|
:param pkgnames_install: packages to be installed
|
||||||
:returns: a block from the apkindex: {"pkgname": "...", ...}
|
:returns: a block from the apkindex: {"pkgname": "...", ...}
|
||||||
|
@ -42,7 +42,7 @@ def package_provider(args: PmbArgs, pkgname, pkgnames_install, suffix: Chroot=Ch
|
||||||
"""
|
"""
|
||||||
# Get all providers
|
# Get all providers
|
||||||
arch = suffix.arch
|
arch = suffix.arch
|
||||||
providers = pmb.parse.apkindex.providers(args, pkgname, arch, False)
|
providers = pmb.parse.apkindex.providers(pkgname, arch, False)
|
||||||
|
|
||||||
# 0. No provider
|
# 0. No provider
|
||||||
if len(providers) == 0:
|
if len(providers) == 0:
|
||||||
|
@ -67,7 +67,7 @@ def package_provider(args: PmbArgs, pkgname, pkgnames_install, suffix: Chroot=Ch
|
||||||
return provider
|
return provider
|
||||||
|
|
||||||
# 4. Pick a package that is already installed
|
# 4. Pick a package that is already installed
|
||||||
installed = pmb.chroot.apk.installed(args, suffix)
|
installed = pmb.chroot.apk.installed(suffix)
|
||||||
for provider_pkgname, provider in providers.items():
|
for provider_pkgname, provider in providers.items():
|
||||||
if provider_pkgname in installed:
|
if provider_pkgname in installed:
|
||||||
logging.verbose(f"{pkgname}: choosing provider '{provider_pkgname}"
|
logging.verbose(f"{pkgname}: choosing provider '{provider_pkgname}"
|
||||||
|
@ -76,7 +76,7 @@ def package_provider(args: PmbArgs, pkgname, pkgnames_install, suffix: Chroot=Ch
|
||||||
return provider
|
return provider
|
||||||
|
|
||||||
# 5. Pick an explicitly selected provider
|
# 5. Pick an explicitly selected provider
|
||||||
provider_pkgname = args.selected_providers.get(pkgname, "")
|
provider_pkgname = get_context().config.providers.get(pkgname, "")
|
||||||
if provider_pkgname in providers:
|
if provider_pkgname in providers:
|
||||||
logging.verbose(f"{pkgname}: choosing provider '{provider_pkgname}', "
|
logging.verbose(f"{pkgname}: choosing provider '{provider_pkgname}', "
|
||||||
"because it was explicitly selected.")
|
"because it was explicitly selected.")
|
||||||
|
@ -92,7 +92,7 @@ def package_provider(args: PmbArgs, pkgname, pkgnames_install, suffix: Chroot=Ch
|
||||||
return pmb.parse.apkindex.provider_shortest(providers, pkgname)
|
return pmb.parse.apkindex.provider_shortest(providers, pkgname)
|
||||||
|
|
||||||
|
|
||||||
def package_from_index(args: PmbArgs, pkgname_depend, pkgnames_install, package_aport,
|
def package_from_index(pkgname_depend, pkgnames_install, package_aport,
|
||||||
suffix: Chroot=Chroot.native()):
|
suffix: Chroot=Chroot.native()):
|
||||||
"""
|
"""
|
||||||
:returns: None when there is no aport and no binary package, or a dict with
|
:returns: None when there is no aport and no binary package, or a dict with
|
||||||
|
@ -100,7 +100,7 @@ def package_from_index(args: PmbArgs, pkgname_depend, pkgnames_install, package_
|
||||||
binary package provider.
|
binary package provider.
|
||||||
"""
|
"""
|
||||||
# No binary package
|
# No binary package
|
||||||
provider = package_provider(args, pkgname_depend, pkgnames_install, suffix)
|
provider = package_provider(pkgname_depend, pkgnames_install, suffix)
|
||||||
if not provider:
|
if not provider:
|
||||||
return package_aport
|
return package_aport
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ def package_from_index(args: PmbArgs, pkgname_depend, pkgnames_install, package_
|
||||||
return provider
|
return provider
|
||||||
|
|
||||||
|
|
||||||
def recurse(args: PmbArgs, pkgnames, suffix: Chroot=Chroot.native()) -> Sequence[str]:
|
def recurse(pkgnames, suffix: Chroot=Chroot.native()) -> Sequence[str]:
|
||||||
"""
|
"""
|
||||||
Find all dependencies of the given pkgnames.
|
Find all dependencies of the given pkgnames.
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ def recurse(args: PmbArgs, pkgnames, suffix: Chroot=Chroot.native()) -> Sequence
|
||||||
|
|
||||||
# Get depends and pkgname from aports
|
# Get depends and pkgname from aports
|
||||||
pkgnames_install = list(ret) + todo
|
pkgnames_install = list(ret) + todo
|
||||||
package = package_from_aports(args, pkgname_depend)
|
package = package_from_aports(pkgname_depend)
|
||||||
package = package_from_index(args, pkgname_depend, pkgnames_install,
|
package = package_from_index(pkgname_depend, pkgnames_install,
|
||||||
package, suffix)
|
package, suffix)
|
||||||
|
|
||||||
# Nothing found
|
# Nothing found
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import copy
|
import copy
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import os
|
import os
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.devices
|
import pmb.helpers.devices
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ def sanity_check(info, path):
|
||||||
f" and try again: {path}")
|
f" and try again: {path}")
|
||||||
|
|
||||||
|
|
||||||
def _parse_kernel_suffix(args: PmbArgs, info, device, kernel):
|
def _parse_kernel_suffix(info, device, kernel):
|
||||||
"""
|
"""
|
||||||
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
Remove the kernel suffix (as selected in 'pmbootstrap init') from
|
||||||
deviceinfo variables. Related:
|
deviceinfo variables. Related:
|
||||||
|
@ -92,7 +93,7 @@ def _parse_kernel_suffix(args: PmbArgs, info, device, kernel):
|
||||||
# Do nothing if the configured kernel isn't available in the kernel (e.g.
|
# Do nothing if the configured kernel isn't available in the kernel (e.g.
|
||||||
# after switching from device with multiple kernels to device with only one
|
# after switching from device with multiple kernels to device with only one
|
||||||
# kernel)
|
# kernel)
|
||||||
kernels = pmb.parse._apkbuild.kernels(args, device)
|
kernels = pmb.parse._apkbuild.kernels(device)
|
||||||
if not kernels or kernel not in kernels:
|
if not kernels or kernel not in kernels:
|
||||||
logging.verbose(f"parse_kernel_suffix: {kernel} not in {kernels}")
|
logging.verbose(f"parse_kernel_suffix: {kernel} not in {kernels}")
|
||||||
return info
|
return info
|
||||||
|
@ -114,23 +115,25 @@ def _parse_kernel_suffix(args: PmbArgs, info, device, kernel):
|
||||||
|
|
||||||
|
|
||||||
# FIXME (#2324): Make deviceinfo a type! (class!!!)
|
# FIXME (#2324): Make deviceinfo a type! (class!!!)
|
||||||
def deviceinfo(args: PmbArgs, device=None, kernel=None) -> Dict[str, str]:
|
def deviceinfo(device=None, kernel=None) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
:param device: defaults to args.device
|
:param device: defaults to args.device
|
||||||
:param kernel: defaults to args.kernel
|
:param kernel: defaults to args.kernel
|
||||||
"""
|
"""
|
||||||
|
context = get_context()
|
||||||
if not device:
|
if not device:
|
||||||
device = args.device
|
device = context.config.device
|
||||||
if not kernel:
|
if not kernel:
|
||||||
kernel = args.kernel
|
kernel = context.config.kernel
|
||||||
|
|
||||||
if not os.path.exists(args.aports):
|
aports = context.config.aports
|
||||||
logging.fatal(f"Aports directory is missing, expected: {args.aports}")
|
if not aports.exists():
|
||||||
|
logging.fatal(f"Aports directory is missing, expected: {aports}")
|
||||||
logging.fatal("Please provide a path to the aports directory using the"
|
logging.fatal("Please provide a path to the aports directory using the"
|
||||||
" -p flag")
|
" -p flag")
|
||||||
raise RuntimeError("Aports directory missing")
|
raise RuntimeError("Aports directory missing")
|
||||||
|
|
||||||
path = pmb.helpers.devices.find_path(args, device, 'deviceinfo')
|
path = pmb.helpers.devices.find_path(device, 'deviceinfo')
|
||||||
if not path:
|
if not path:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Device '" + device + "' not found. Run 'pmbootstrap init' to"
|
"Device '" + device + "' not found. Run 'pmbootstrap init' to"
|
||||||
|
@ -154,6 +157,6 @@ def deviceinfo(args: PmbArgs, device=None, kernel=None) -> Dict[str, str]:
|
||||||
if key not in ret:
|
if key not in ret:
|
||||||
ret[key] = ""
|
ret[key] = ""
|
||||||
|
|
||||||
ret = _parse_kernel_suffix(args, ret, device, kernel)
|
ret = _parse_kernel_suffix(ret, device, kernel)
|
||||||
sanity_check(ret, path)
|
sanity_check(ret, path)
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -7,7 +7,7 @@ import os
|
||||||
|
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.config
|
import pmb.config
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
from pmb.helpers.exceptions import NonBugError
|
from pmb.helpers.exceptions import NonBugError
|
||||||
|
@ -255,7 +255,7 @@ def check(args: PmbArgs, pkgname, components_list=[], details=False, must_exist=
|
||||||
ret = True
|
ret = True
|
||||||
aport: Path
|
aport: Path
|
||||||
try:
|
try:
|
||||||
aport = pmb.helpers.pmaports.find(args, "linux-" + flavor)
|
aport = pmb.helpers.pmaports.find("linux-" + flavor)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
if must_exist:
|
if must_exist:
|
||||||
raise e
|
raise e
|
||||||
|
|
|
@ -17,7 +17,7 @@ import pmb.chroot.other
|
||||||
import pmb.chroot.initfs
|
import pmb.chroot.initfs
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
import pmb.parse.cpuinfo
|
import pmb.parse.cpuinfo
|
||||||
|
@ -79,11 +79,11 @@ def create_gdk_loader_cache(args: PmbArgs) -> Path:
|
||||||
if not (chroot_native / cache_path).is_file():
|
if not (chroot_native / cache_path).is_file():
|
||||||
raise RuntimeError(f"gdk pixbuf cache file not found: {cache_path}")
|
raise RuntimeError(f"gdk pixbuf cache file not found: {cache_path}")
|
||||||
|
|
||||||
pmb.chroot.root(args, ["cp", cache_path, custom_cache_path])
|
pmb.chroot.root(["cp", cache_path, custom_cache_path])
|
||||||
cmd: Sequence[PathString] = ["sed", "-i", "-e",
|
cmd: Sequence[PathString] = ["sed", "-i", "-e",
|
||||||
f"s@\"{gdk_cache_dir}@\"{chroot_native / gdk_cache_dir}@",
|
f"s@\"{gdk_cache_dir}@\"{chroot_native / gdk_cache_dir}@",
|
||||||
custom_cache_path]
|
custom_cache_path]
|
||||||
pmb.chroot.root(args, cmd)
|
pmb.chroot.root(cmd)
|
||||||
return chroot_native / custom_cache_path
|
return chroot_native / custom_cache_path
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ def command_qemu(args: PmbArgs, arch, img_path, img_path_2nd=None):
|
||||||
flavor = pmb.chroot.other.kernel_flavor_installed(args, chroot)
|
flavor = pmb.chroot.other.kernel_flavor_installed(args, chroot)
|
||||||
flavor_suffix = f"-{flavor}"
|
flavor_suffix = f"-{flavor}"
|
||||||
# Backwards compatibility with old mkinitfs (pma#660)
|
# Backwards compatibility with old mkinitfs (pma#660)
|
||||||
pmaports_cfg = pmb.config.pmaports.read_config(args)
|
pmaports_cfg = pmb.config.pmaports.read_config()
|
||||||
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
if pmaports_cfg.get("supported_mkinitfs_without_flavors", False):
|
||||||
flavor_suffix = ""
|
flavor_suffix = ""
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ def install_depends(args: PmbArgs, arch):
|
||||||
if args.efi:
|
if args.efi:
|
||||||
depends.append("ovmf")
|
depends.append("ovmf")
|
||||||
|
|
||||||
pmb.chroot.apk.install(args, depends, Chroot.native())
|
pmb.chroot.apk.install(depends, Chroot.native())
|
||||||
|
|
||||||
|
|
||||||
def run(args: PmbArgs):
|
def run(args: PmbArgs):
|
||||||
|
|
|
@ -5,13 +5,14 @@ from typing import List
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
from pmb.core.types import PathString, PmbArgs
|
from pmb.types import PathString, PmbArgs
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import pmb.helpers.run_core
|
import pmb.helpers.run_core
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.parse.arch
|
import pmb.parse.arch
|
||||||
import pmb.config.pmaports
|
import pmb.config.pmaports
|
||||||
import pmb.build
|
import pmb.build
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
def scp_abuild_key(args: PmbArgs, user: str, host: str, port: str):
|
def scp_abuild_key(args: PmbArgs, user: str, host: str, port: str):
|
||||||
|
@ -21,7 +22,7 @@ def scp_abuild_key(args: PmbArgs, user: str, host: str, port: str):
|
||||||
:param host: target device ssh hostname
|
:param host: target device ssh hostname
|
||||||
:param port: target device ssh port """
|
:param port: target device ssh port """
|
||||||
|
|
||||||
keys = list((pmb.config.work / "config_abuild").glob("*.pub"))
|
keys = list((get_context().config.work / "config_abuild").glob("*.pub"))
|
||||||
key = keys[0]
|
key = keys[0]
|
||||||
key_name = os.path.basename(key)
|
key_name = os.path.basename(key)
|
||||||
|
|
||||||
|
@ -91,17 +92,18 @@ def sideload(args: PmbArgs, user: str, host: str, port: str, arch: str, copy_key
|
||||||
:param pkgnames: list of pkgnames to be built """
|
:param pkgnames: list of pkgnames to be built """
|
||||||
|
|
||||||
paths = []
|
paths = []
|
||||||
channel: str = pmb.config.pmaports.read_config(args)["channel"]
|
channel: str = pmb.config.pmaports.read_config()["channel"]
|
||||||
|
|
||||||
if arch is None:
|
if arch is None:
|
||||||
arch = ssh_find_arch(args, user, host, port)
|
arch = ssh_find_arch(args, user, host, port)
|
||||||
|
|
||||||
|
context = get_context()
|
||||||
for pkgname in pkgnames:
|
for pkgname in pkgnames:
|
||||||
data_repo = pmb.parse.apkindex.package(args, pkgname, arch, True)
|
data_repo = pmb.parse.apkindex.package(pkgname, arch, True)
|
||||||
apk_file = f"{pkgname}-{data_repo['version']}.apk"
|
apk_file = f"{pkgname}-{data_repo['version']}.apk"
|
||||||
host_path = pmb.config.work / "packages" / channel / arch / apk_file
|
host_path = context.config.work / "packages" / channel / arch / apk_file
|
||||||
if not host_path.is_file():
|
if not host_path.is_file():
|
||||||
pmb.build.package(args, pkgname, arch, force=True)
|
pmb.build.package(context, pkgname, arch, force=True)
|
||||||
|
|
||||||
if not host_path.is_file():
|
if not host_path.is_file():
|
||||||
raise RuntimeError(f"The package '{pkgname}' could not be built")
|
raise RuntimeError(f"The package '{pkgname}' could not be built")
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
import multiprocessing
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Optional, Tuple, TypedDict, Union
|
from typing import Dict, List, Optional, Tuple, TypedDict, Union
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ class AportGenEntry(TypedDict):
|
||||||
|
|
||||||
# Property list generated with:
|
# Property list generated with:
|
||||||
# $ rg --vimgrep "((^|\s)args\.\w+)" --only-matching | cut -d"." -f3 | sort | uniq
|
# $ rg --vimgrep "((^|\s)args\.\w+)" --only-matching | cut -d"." -f3 | sort | uniq
|
||||||
class PmbArgs(Namespace):
|
class PmbArgs():
|
||||||
action_flasher: str
|
action_flasher: str
|
||||||
action_initfs: str
|
action_initfs: str
|
||||||
action_kconfig: str
|
action_kconfig: str
|
||||||
|
@ -52,9 +54,9 @@ class PmbArgs(Namespace):
|
||||||
cmdline: str
|
cmdline: str
|
||||||
command: str
|
command: str
|
||||||
config: Path
|
config: Path
|
||||||
|
cross: bool
|
||||||
details: bool
|
details: bool
|
||||||
details_to_stdout: bool
|
details_to_stdout: bool
|
||||||
device: str
|
|
||||||
deviceinfo: Dict[str, str]
|
deviceinfo: Dict[str, str]
|
||||||
deviceinfo_parse_kernel: str
|
deviceinfo_parse_kernel: str
|
||||||
devices: str
|
devices: str
|
||||||
|
@ -63,7 +65,6 @@ class PmbArgs(Namespace):
|
||||||
efi: str
|
efi: str
|
||||||
envkernel: str
|
envkernel: str
|
||||||
export_folder: Path
|
export_folder: Path
|
||||||
extra_packages: str
|
|
||||||
extra_space: str
|
extra_space: str
|
||||||
fast: str
|
fast: str
|
||||||
file: str
|
file: str
|
||||||
|
@ -148,8 +149,6 @@ class PmbArgs(Namespace):
|
||||||
suffix: str
|
suffix: str
|
||||||
systemd: str
|
systemd: str
|
||||||
timeout: float
|
timeout: float
|
||||||
ui: str
|
|
||||||
ui_extras: str
|
|
||||||
user: str
|
user: str
|
||||||
value: str
|
value: str
|
||||||
verbose: str
|
verbose: str
|
||||||
|
@ -157,3 +156,39 @@ class PmbArgs(Namespace):
|
||||||
work: Path
|
work: Path
|
||||||
xauth: str
|
xauth: str
|
||||||
zap: str
|
zap: str
|
||||||
|
|
||||||
|
|
||||||
|
class Config():
|
||||||
|
aports: Path = Path(os.path.expanduser("~") +
|
||||||
|
"/.local/var/pmbootstrap/cache_git/pmaports")
|
||||||
|
boot_size: int = 256
|
||||||
|
build_default_device_arch: bool = False
|
||||||
|
build_pkgs_on_install: bool = True
|
||||||
|
ccache_size: str = "5G" # yeahhhh this one has a suffix
|
||||||
|
device: str = "qemu-amd64"
|
||||||
|
extra_packages: str = "none"
|
||||||
|
extra_space: int = 0
|
||||||
|
hostname: str = ""
|
||||||
|
is_default_channel: bool = True
|
||||||
|
jobs: str = str(multiprocessing.cpu_count() + 1)
|
||||||
|
kernel: str = "stable"
|
||||||
|
keymap: str = ""
|
||||||
|
locale: str = "en_US.UTF-8"
|
||||||
|
# NOTE: mirrors use http by default to leverage caching
|
||||||
|
mirror_alpine: str = "http://dl-cdn.alpinelinux.org/alpine/"
|
||||||
|
# NOTE: mirrors_postmarketos variable type is supposed to be
|
||||||
|
# comma-separated string, not a python list or any other type!
|
||||||
|
mirrors_postmarketos: List[str] = ["http://mirror.postmarketos.org/postmarketos/"]
|
||||||
|
qemu_redir_stdio: bool = False
|
||||||
|
ssh_key_glob: str = "~/.ssh/id_*.pub"
|
||||||
|
ssh_keys: bool = False
|
||||||
|
sudo_timer: bool = False
|
||||||
|
systemd: str = "default"
|
||||||
|
timezone: str = "GMT"
|
||||||
|
ui: str = "console"
|
||||||
|
ui_extras: bool = False
|
||||||
|
user: str = "user"
|
||||||
|
work: Path = Path(os.path.expanduser("~") + "/.local/var/pmbootstrap")
|
||||||
|
|
||||||
|
providers: Dict[str, str] = { }
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
""" Common code for git tests """
|
""" Common code for git tests """
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pmb.helpers.git
|
import pmb.helpers.git
|
||||||
import pmb.helpers.run
|
import pmb.helpers.run
|
||||||
import shutil
|
import shutil
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
def prepare_tmpdir(args: PmbArgs, monkeypatch, tmpdir):
|
def prepare_tmpdir(args: PmbArgs, monkeypatch, tmpdir):
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import List
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pmb.core.types import PathString
|
from pmb.types import PathString
|
||||||
import pmb_test # noqa
|
import pmb_test # noqa
|
||||||
import pmb.build
|
import pmb.build
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
|
@ -19,7 +19,7 @@ def args(tmpdir, request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap.py", "init"]
|
sys.argv = ["pmbootstrap.py", "init"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
return args
|
return args
|
||||||
|
|
|
@ -13,7 +13,7 @@ import pmb.chroot.apk_static
|
||||||
import pmb.config
|
import pmb.config
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.helpers.logging
|
import pmb.helpers.logging
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -21,7 +21,7 @@ def args(request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap.py", "chroot"]
|
sys.argv = ["pmbootstrap.py", "chroot"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
return args
|
return args
|
||||||
|
@ -30,13 +30,13 @@ def args(request):
|
||||||
def test_read_signature_info(args: PmbArgs):
|
def test_read_signature_info(args: PmbArgs):
|
||||||
# Tempfolder inside chroot for fake apk files
|
# Tempfolder inside chroot for fake apk files
|
||||||
tmp_path = Path("/tmp/test_read_signature_info")
|
tmp_path = Path("/tmp/test_read_signature_info")
|
||||||
tmp_path_outside = pmb.config.work / "chroot_native" / tmp_path
|
tmp_path_outside = get_context().config.work / "chroot_native" / tmp_path
|
||||||
if os.path.exists(tmp_path_outside):
|
if os.path.exists(tmp_path_outside):
|
||||||
pmb.chroot.root(args, ["rm", "-r", tmp_path])
|
pmb.chroot.root(["rm", "-r", tmp_path])
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", tmp_path])
|
pmb.chroot.user(["mkdir", "-p", tmp_path])
|
||||||
|
|
||||||
# No signature found
|
# No signature found
|
||||||
pmb.chroot.user(args, ["tar", "-czf", tmp_path / "no_sig.apk",
|
pmb.chroot.user(["tar", "-czf", tmp_path / "no_sig.apk",
|
||||||
"/etc/issue"])
|
"/etc/issue"])
|
||||||
with tarfile.open(tmp_path_outside / "no_sig.apk", "r:gz") as tar:
|
with tarfile.open(tmp_path_outside / "no_sig.apk", "r:gz") as tar:
|
||||||
with pytest.raises(RuntimeError) as e:
|
with pytest.raises(RuntimeError) as e:
|
||||||
|
@ -44,10 +44,10 @@ def test_read_signature_info(args: PmbArgs):
|
||||||
assert "Could not find signature" in str(e.value)
|
assert "Could not find signature" in str(e.value)
|
||||||
|
|
||||||
# Signature file with invalid name
|
# Signature file with invalid name
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", tmp_path / "sbin"])
|
pmb.chroot.user(["mkdir", "-p", tmp_path / "sbin"])
|
||||||
pmb.chroot.user(args, ["cp", "/etc/issue", tmp_path /
|
pmb.chroot.user(["cp", "/etc/issue", tmp_path /
|
||||||
"sbin/apk.static.SIGN.RSA.invalid.pub"])
|
"sbin/apk.static.SIGN.RSA.invalid.pub"])
|
||||||
pmb.chroot.user(args, ["tar", "-czf", tmp_path / "invalid_sig.apk",
|
pmb.chroot.user(["tar", "-czf", tmp_path / "invalid_sig.apk",
|
||||||
"sbin/apk.static.SIGN.RSA.invalid.pub"],
|
"sbin/apk.static.SIGN.RSA.invalid.pub"],
|
||||||
working_dir=tmp_path)
|
working_dir=tmp_path)
|
||||||
with tarfile.open(tmp_path_outside / "invalid_sig.apk", "r:gz") as tar:
|
with tarfile.open(tmp_path_outside / "invalid_sig.apk", "r:gz") as tar:
|
||||||
|
@ -59,10 +59,10 @@ def test_read_signature_info(args: PmbArgs):
|
||||||
path = list(pmb.config.apk_keys_path.glob("/*.pub"))[0]
|
path = list(pmb.config.apk_keys_path.glob("/*.pub"))[0]
|
||||||
name = os.path.basename(path)
|
name = os.path.basename(path)
|
||||||
path_archive = "sbin/apk.static.SIGN.RSA." + name
|
path_archive = "sbin/apk.static.SIGN.RSA." + name
|
||||||
pmb.chroot.user(args, ["mv",
|
pmb.chroot.user(["mv",
|
||||||
tmp_path / "sbin/apk.static.SIGN.RSA.invalid.pub",
|
tmp_path / "sbin/apk.static.SIGN.RSA.invalid.pub",
|
||||||
tmp_path / path_archive])
|
tmp_path / path_archive])
|
||||||
pmb.chroot.user(args, ["tar", "-czf", tmp_path / "realistic_name_sig.apk",
|
pmb.chroot.user(["tar", "-czf", tmp_path / "realistic_name_sig.apk",
|
||||||
path_archive], working_dir=tmp_path)
|
path_archive], working_dir=tmp_path)
|
||||||
with tarfile.open(tmp_path_outside / "realistic_name_sig.apk", "r:gz")\
|
with tarfile.open(tmp_path_outside / "realistic_name_sig.apk", "r:gz")\
|
||||||
as tar:
|
as tar:
|
||||||
|
@ -72,23 +72,23 @@ def test_read_signature_info(args: PmbArgs):
|
||||||
assert sigkey_path == path
|
assert sigkey_path == path
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
pmb.chroot.user(args, ["rm", "-r", tmp_path])
|
pmb.chroot.user(["rm", "-r", tmp_path])
|
||||||
|
|
||||||
|
|
||||||
def test_successful_extraction(args: PmbArgs, tmpdir):
|
def test_successful_extraction(args: PmbArgs, tmpdir):
|
||||||
if os.path.exists(pmb.config.work / "apk.static"):
|
if os.path.exists(get_context().config.work / "apk.static"):
|
||||||
os.remove(pmb.config.work / "apk.static")
|
os.remove(get_context().config.work / "apk.static")
|
||||||
|
|
||||||
pmb.chroot.apk_static.init(args)
|
pmb.chroot.apk_static.init(args)
|
||||||
assert os.path.exists(pmb.config.work / "apk.static")
|
assert os.path.exists(get_context().config.work / "apk.static")
|
||||||
os.remove(pmb.config.work / "apk.static")
|
os.remove(get_context().config.work / "apk.static")
|
||||||
|
|
||||||
|
|
||||||
def test_signature_verification(args: PmbArgs, tmpdir):
|
def test_signature_verification(args: PmbArgs, tmpdir):
|
||||||
if os.path.exists(pmb.config.work / "apk.static"):
|
if os.path.exists(get_context().config.work / "apk.static"):
|
||||||
os.remove(pmb.config.work / "apk.static")
|
os.remove(get_context().config.work / "apk.static")
|
||||||
|
|
||||||
version = pmb.parse.apkindex.package(args, "apk-tools-static")["version"]
|
version = pmb.parse.apkindex.package("apk-tools-static")["version"]
|
||||||
apk_path = pmb.chroot.apk_static.download(
|
apk_path = pmb.chroot.apk_static.download(
|
||||||
args, f"apk-tools-static-{version}.apk")
|
args, f"apk-tools-static-{version}.apk")
|
||||||
|
|
||||||
|
@ -119,8 +119,8 @@ def test_signature_verification(args: PmbArgs, tmpdir):
|
||||||
|
|
||||||
|
|
||||||
def test_outdated_version(args: PmbArgs, monkeypatch):
|
def test_outdated_version(args: PmbArgs, monkeypatch):
|
||||||
if os.path.exists(pmb.config.work / "apk.static"):
|
if os.path.exists(get_context().config.work / "apk.static"):
|
||||||
os.remove(pmb.config.work / "apk.static")
|
os.remove(get_context().config.work / "apk.static")
|
||||||
|
|
||||||
# Change min version for all branches
|
# Change min version for all branches
|
||||||
min_copy = copy.copy(pmb.config.apk_tools_min_version)
|
min_copy = copy.copy(pmb.config.apk_tools_min_version)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pytest
|
import pytest
|
||||||
import shutil
|
import shutil
|
||||||
import filecmp
|
import filecmp
|
||||||
|
@ -22,7 +22,7 @@ def args(tmpdir, request):
|
||||||
cfg = f"{pmb_test.const.testdata}/channels.cfg"
|
cfg = f"{pmb_test.const.testdata}/channels.cfg"
|
||||||
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "chroot"]
|
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "chroot"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
args.fork_alpine = False
|
args.fork_alpine = False
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
|
@ -85,7 +85,7 @@ def test_aportgen(args: PmbArgs, tmpdir):
|
||||||
os.mkdir(tmpdir + "/cross")
|
os.mkdir(tmpdir + "/cross")
|
||||||
|
|
||||||
# Create aportgen folder -> code path where it still exists
|
# Create aportgen folder -> code path where it still exists
|
||||||
pmb.helpers.run.user(["mkdir", "-p", pmb.config.work / "aportgen"])
|
pmb.helpers.run.user(["mkdir", "-p", get_context().config.work / "aportgen"])
|
||||||
|
|
||||||
# Generate all valid packages (gcc twice -> different code path)
|
# Generate all valid packages (gcc twice -> different code path)
|
||||||
pkgnames = ["musl-armv7",
|
pkgnames = ["musl-armv7",
|
||||||
|
@ -116,7 +116,7 @@ def test_aportgen_get_upstream_aport(args: PmbArgs, monkeypatch):
|
||||||
# Equal version
|
# Equal version
|
||||||
func = pmb.aportgen.core.get_upstream_aport
|
func = pmb.aportgen.core.get_upstream_aport
|
||||||
upstream = "gcc"
|
upstream = "gcc"
|
||||||
upstream_full = pmb.config.work / "cache_git/aports_upstream/main/" + upstream
|
upstream_full = get_context().config.work / "cache_git/aports_upstream/main/" + upstream
|
||||||
apkbuild = {"pkgver": "2.0", "pkgrel": "0"}
|
apkbuild = {"pkgver": "2.0", "pkgrel": "0"}
|
||||||
package = {"version": "2.0-r0"}
|
package = {"version": "2.0-r0"}
|
||||||
assert func(args, upstream) == upstream_full
|
assert func(args, upstream) == upstream_full
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
from pmb.core import get_context
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -21,7 +22,7 @@ def args(tmpdir, request):
|
||||||
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "build", "-i",
|
sys.argv = ["pmbootstrap.py", "--config-channels", cfg, "build", "-i",
|
||||||
"device-testsuite-testdevice"]
|
"device-testsuite-testdevice"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
|
|
||||||
|
@ -73,9 +74,10 @@ def generate(args: PmbArgs, monkeypatch, answers):
|
||||||
pmb.aportgen.generate(args, "linux-testsuite-testdevice")
|
pmb.aportgen.generate(args, "linux-testsuite-testdevice")
|
||||||
monkeypatch.undo()
|
monkeypatch.undo()
|
||||||
|
|
||||||
apkbuild_path = (f"{args.aports}/device/testing/"
|
aports = get_context().config.aports
|
||||||
|
apkbuild_path = (aports / "device/testing/"
|
||||||
"device-testsuite-testdevice/APKBUILD")
|
"device-testsuite-testdevice/APKBUILD")
|
||||||
apkbuild_path_linux = (args.aports + "/device/testing/"
|
apkbuild_path_linux = (aports / "device/testing/"
|
||||||
"linux-testsuite-testdevice/APKBUILD")
|
"linux-testsuite-testdevice/APKBUILD")
|
||||||
|
|
||||||
# The build fails if the email is not a valid email, so remove them just
|
# The build fails if the email is not a valid email, so remove them just
|
||||||
|
@ -88,11 +90,11 @@ def generate(args: PmbArgs, monkeypatch, answers):
|
||||||
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
apkbuild = pmb.parse.apkbuild(apkbuild_path)
|
||||||
apkbuild_linux = pmb.parse.apkbuild(apkbuild_path_linux,
|
apkbuild_linux = pmb.parse.apkbuild(apkbuild_path_linux,
|
||||||
check_pkgver=False)
|
check_pkgver=False)
|
||||||
deviceinfo = pmb.parse.deviceinfo(args, "testsuite-testdevice")
|
deviceinfo = pmb.parse.deviceinfo("testsuite-testdevice")
|
||||||
return (deviceinfo, apkbuild, apkbuild_linux)
|
return (deviceinfo, apkbuild, apkbuild_linux)
|
||||||
|
|
||||||
|
|
||||||
def remove_contributor_maintainer_lines(args: PmbArgs, path):
|
def remove_contributor_maintainer_lines(path):
|
||||||
with open(path, "r+", encoding="utf-8") as handle:
|
with open(path, "r+", encoding="utf-8") as handle:
|
||||||
lines_new = []
|
lines_new = []
|
||||||
for line in handle.readlines():
|
for line in handle.readlines():
|
||||||
|
|
|
@ -9,6 +9,7 @@ import pmb.chroot.apk_static
|
||||||
import pmb.parse.apkindex
|
import pmb.parse.apkindex
|
||||||
import pmb.helpers.logging
|
import pmb.helpers.logging
|
||||||
import pmb.parse.bootimg
|
import pmb.parse.bootimg
|
||||||
|
from pmb.core import get_context
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -16,7 +17,7 @@ def args(request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap.py", "chroot"]
|
sys.argv = ["pmbootstrap.py", "chroot"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
return args
|
return args
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import pmb_test # noqa
|
import pmb_test # noqa
|
||||||
|
@ -15,7 +15,7 @@ def args(request, tmpdir):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap.py", "chroot"]
|
sys.argv = ["pmbootstrap.py", "chroot"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ def cache_apkindex(version):
|
||||||
|
|
||||||
def test_build_is_necessary(args: PmbArgs):
|
def test_build_is_necessary(args: PmbArgs):
|
||||||
# Prepare APKBUILD and APKINDEX data
|
# Prepare APKBUILD and APKINDEX data
|
||||||
aport = pmb.helpers.pmaports.find(args, "hello-world")
|
aport = pmb.helpers.pmaports.find("hello-world")
|
||||||
apkbuild = pmb.parse.apkbuild(f"{aport}/APKBUILD")
|
apkbuild = pmb.parse.apkbuild(f"{aport}/APKBUILD")
|
||||||
apkbuild["pkgver"] = "1"
|
apkbuild["pkgver"] = "1"
|
||||||
apkbuild["pkgrel"] = "2"
|
apkbuild["pkgrel"] = "2"
|
||||||
|
@ -73,7 +73,7 @@ def test_build_is_necessary_no_binary_available(args: PmbArgs):
|
||||||
hello-world package has not been built yet.
|
hello-world package has not been built yet.
|
||||||
"""
|
"""
|
||||||
indexes = list(pmb.helpers.other.cache["apkindex"].keys())
|
indexes = list(pmb.helpers.other.cache["apkindex"].keys())
|
||||||
aport = pmb.helpers.pmaports.find(args, "hello-world")
|
aport = pmb.helpers.pmaports.find("hello-world")
|
||||||
apkbuild = pmb.parse.apkbuild(f"{aport}/APKBUILD")
|
apkbuild = pmb.parse.apkbuild(f"{aport}/APKBUILD")
|
||||||
assert pmb.build.is_necessary(args, None, apkbuild, indexes) is True
|
assert pmb.build.is_necessary(args, None, apkbuild, indexes) is True
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
from pmb.core.types import PmbArgs
|
from pmb.types import PmbArgs
|
||||||
import pytest
|
import pytest
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
@ -23,7 +23,7 @@ def args(tmpdir, request):
|
||||||
import pmb.parse
|
import pmb.parse
|
||||||
sys.argv = ["pmbootstrap", "init"]
|
sys.argv = ["pmbootstrap", "init"]
|
||||||
args = pmb.parse.arguments()
|
args = pmb.parse.arguments()
|
||||||
args.log = pmb.config.work / "log_testsuite.txt"
|
args.log = get_context().config.work / "log_testsuite.txt"
|
||||||
pmb.helpers.logging.init(args)
|
pmb.helpers.logging.init(args)
|
||||||
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
request.addfinalizer(pmb.helpers.logging.logfd.close)
|
||||||
return args
|
return args
|
||||||
|
@ -351,9 +351,9 @@ def test_build_depends_high_level(args: PmbArgs, monkeypatch):
|
||||||
fake_build_is_necessary)
|
fake_build_is_necessary)
|
||||||
|
|
||||||
# Build hello-world to get its full output path
|
# Build hello-world to get its full output path
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
output_hello = pmb.build.package(args, "hello-world")
|
output_hello = pmb.build.package(args, "hello-world")
|
||||||
output_hello_outside = pmb.config.work / "packages" / channel / output_hello
|
output_hello_outside = get_context().config.work / "packages" / channel / output_hello
|
||||||
assert output_hello_outside.exists()
|
assert output_hello_outside.exists()
|
||||||
|
|
||||||
# Make sure the wrapper exists
|
# Make sure the wrapper exists
|
||||||
|
@ -386,7 +386,7 @@ def test_build_local_source_high_level(args: PmbArgs, tmpdir):
|
||||||
aports = tmpdir + "/aports"
|
aports = tmpdir + "/aports"
|
||||||
aport = aports + "/device/testing/device-" + args.device
|
aport = aports + "/device/testing/device-" + args.device
|
||||||
os.makedirs(aport)
|
os.makedirs(aport)
|
||||||
path_original = pmb.helpers.pmaports.find(args, f"device-{args.device}")
|
path_original = pmb.helpers.pmaports.find(f"device-{args.device}")
|
||||||
shutil.copy(f"{path_original}/deviceinfo", aport)
|
shutil.copy(f"{path_original}/deviceinfo", aport)
|
||||||
|
|
||||||
# aports: Add modified hello-world aport (source="", uses $builddir)
|
# aports: Add modified hello-world aport (source="", uses $builddir)
|
||||||
|
@ -412,7 +412,7 @@ def test_build_local_source_high_level(args: PmbArgs, tmpdir):
|
||||||
pmb.helpers.run.root(["chmod", "500", unreadable])
|
pmb.helpers.run.root(["chmod", "500", unreadable])
|
||||||
|
|
||||||
# Test native arch and foreign arch chroot
|
# Test native arch and foreign arch chroot
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
# TODO: test disabled, seems to *only* fail on gitlab runners and nowhere else.
|
# TODO: test disabled, seems to *only* fail on gitlab runners and nowhere else.
|
||||||
# See: https://gitlab.com/postmarketOS/pmbootstrap/-/issues/2346
|
# See: https://gitlab.com/postmarketOS/pmbootstrap/-/issues/2346
|
||||||
# for arch in [pmb.config.arch_native, "armhf"]:
|
# for arch in [pmb.config.arch_native, "armhf"]:
|
||||||
|
@ -449,7 +449,7 @@ def test_build_abuild_leftovers(args: PmbArgs, tmpdir):
|
||||||
aports = f"{tmpdir}/aports"
|
aports = f"{tmpdir}/aports"
|
||||||
aport = f"{aports}/device/testing/device-{args.device}"
|
aport = f"{aports}/device/testing/device-{args.device}"
|
||||||
os.makedirs(aport)
|
os.makedirs(aport)
|
||||||
path_original = pmb.helpers.pmaports.find(args, f"device-{args.device}")
|
path_original = pmb.helpers.pmaports.find(f"device-{args.device}")
|
||||||
shutil.copy(f"{path_original}/deviceinfo", aport)
|
shutil.copy(f"{path_original}/deviceinfo", aport)
|
||||||
|
|
||||||
# aports: Add modified hello-world aport (source="", uses $builddir)
|
# aports: Add modified hello-world aport (source="", uses $builddir)
|
||||||
|
@ -468,7 +468,7 @@ def test_build_abuild_leftovers(args: PmbArgs, tmpdir):
|
||||||
f"{src}/broken-tarball-symlink.tar.gz")
|
f"{src}/broken-tarball-symlink.tar.gz")
|
||||||
|
|
||||||
# Delete all hello-world packages
|
# Delete all hello-world packages
|
||||||
channel = pmb.config.pmaports.read_config(args)["channel"]
|
channel = pmb.config.pmaports.read_config()["channel"]
|
||||||
pattern = f"{args.work}/packages/{channel}/*/hello-world-*_p*.apk"
|
pattern = f"{args.work}/packages/{channel}/*/hello-world-*_p*.apk"
|
||||||
for path in glob.glob(pattern):
|
for path in glob.glob(pattern):
|
||||||
pmb.helpers.run.root(["rm", path])
|
pmb.helpers.run.root(["rm", path])
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue