mirror of
https://github.com/BigfootACA/arch-image-builder.git
synced 2024-09-21 14:00:55 +08:00
Compare commits
21 Commits
8baedd5358
...
37aed6dfee
Author | SHA1 | Date | |
---|---|---|---|
37aed6dfee | |||
37c8f1ff21 | |||
d44bc72beb | |||
c81a64fb06 | |||
f8fbcbf24c | |||
b58cfb153d | |||
623fc7e793 | |||
496221588f | |||
cd9a2a504f | |||
4bae93f7d8 | |||
94e33d2565 | |||
bb0508cede | |||
0fa8d98e58 | |||
97bcdf7379 | |||
b5f69b7b08 | |||
205079fd83 | |||
e54f17a02f | |||
11ee7f3517 | |||
e49f667db9 | |||
7ad662ab28 | |||
84d8a0c247 |
21
README.md
21
README.md
@ -23,20 +23,21 @@ pacman -S qemu-user-static-binfmt
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```commandline
|
```commandline
|
||||||
python build.py -c target/ayn-odin2-sdcard,locale/zh-cn,desktop/gnome
|
python build.py -c target/ayn-odin2-sdcard,locale/zh-cn,desktop/gnome -m bfsu,tuna
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
|-------------------------------------|----------------------------------|
|
|-------------------------------------|------------------------------------|
|
||||||
| -C, --clean | Clean workspace before build |
|
| -C, --clean | Clean workspace before build |
|
||||||
| -p PRESET, --preset PRESET | Select preset to create package |
|
| -m MIRROR, --mirror MIRROR | Select mirror to download package |
|
||||||
| -c CONFIG, --config CONFIG | Select configs to build |
|
| -p PRESET, --preset PRESET | Select preset to create package |
|
||||||
| -o WORKSPACE, --workspace WORKSPACE | Set workspace for builder |
|
| -c CONFIG, --config CONFIG | Select configs to build |
|
||||||
| -d, --debug | Enable debug logging |
|
| -o WORKSPACE, --workspace WORKSPACE | Set workspace for builder |
|
||||||
| -G, --no-gpgcheck | Disable GPG check |
|
| -d, --debug | Enable debug logging |
|
||||||
| -r, --repack | Repack rootfs only |
|
| -G, --no-gpgcheck | Disable GPG check |
|
||||||
|
| -r, --repack | Repack rootfs only |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -4,8 +4,10 @@ import logging
|
|||||||
import shutil
|
import shutil
|
||||||
import libarchive
|
import libarchive
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
from builder.lib.serializable import SerializableDict
|
||||||
from builder.lib.context import ArchBuilderContext
|
from builder.lib.context import ArchBuilderContext
|
||||||
from builder.lib.config import ArchBuilderConfigError
|
from builder.lib.config import ArchBuilderConfigError
|
||||||
|
from builder.lib.subscript import resolve_simple_values
|
||||||
log = getLogger(__name__)
|
log = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -30,6 +32,51 @@ def progress_cb(target, percent, n, i):
|
|||||||
log.info(f"processing {target} ({i}/{n})")
|
log.info(f"processing {target} ({i}/{n})")
|
||||||
|
|
||||||
|
|
||||||
|
class PacmanRepoServer(SerializableDict):
|
||||||
|
url: str = None
|
||||||
|
name: str = None
|
||||||
|
mirror: bool = False
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str = None,
|
||||||
|
url: str = None,
|
||||||
|
mirror: bool = None
|
||||||
|
):
|
||||||
|
if url is not None: self.url = url
|
||||||
|
if name is not None: self.name = name
|
||||||
|
if mirror is not None: self.mirror = mirror
|
||||||
|
|
||||||
|
|
||||||
|
class PacmanRepo(SerializableDict):
|
||||||
|
name: str = None
|
||||||
|
priority: int = 10000
|
||||||
|
servers: list[PacmanRepoServer] = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str = None,
|
||||||
|
priority: int = None,
|
||||||
|
servers: list[PacmanRepoServer] = None
|
||||||
|
):
|
||||||
|
if name is not None: self.name = name
|
||||||
|
if priority is not None: self.priority = priority
|
||||||
|
if servers is not None: self.servers = servers
|
||||||
|
else: self.servers = []
|
||||||
|
|
||||||
|
def add_server(
|
||||||
|
self,
|
||||||
|
name: str = None,
|
||||||
|
url: str = None,
|
||||||
|
mirror: bool = None
|
||||||
|
):
|
||||||
|
self.servers.append(PacmanRepoServer(
|
||||||
|
name=name,
|
||||||
|
url=url,
|
||||||
|
mirror=mirror,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
class Pacman:
|
class Pacman:
|
||||||
handle: pyalpm.Handle
|
handle: pyalpm.Handle
|
||||||
ctx: ArchBuilderContext
|
ctx: ArchBuilderContext
|
||||||
@ -37,17 +84,22 @@ class Pacman:
|
|||||||
databases: dict[str: pyalpm.DB]
|
databases: dict[str: pyalpm.DB]
|
||||||
config: dict
|
config: dict
|
||||||
caches: list[str]
|
caches: list[str]
|
||||||
|
repos: list[PacmanRepo]
|
||||||
|
|
||||||
def append_repos(self, lines: list[str]):
|
def append_repos(self, lines: list[str]):
|
||||||
"""
|
"""
|
||||||
Add all databases into config
|
Add all databases into config
|
||||||
"""
|
"""
|
||||||
for repo in self.databases:
|
for repo in self.repos:
|
||||||
db = self.databases[repo]
|
lines.append(f"[{repo.name}]\n")
|
||||||
lines.append(f"[{repo}]\n")
|
for server in repo.servers:
|
||||||
for server in db.servers:
|
if server.mirror:
|
||||||
log.debug(f"server {server}")
|
lines.append(f"# Mirror {server.name}\n")
|
||||||
lines.append(f"Server = {server}\n")
|
log.debug(f"use mirror {server.name} url {server.url}")
|
||||||
|
else:
|
||||||
|
lines.append("# Original Repo\n")
|
||||||
|
log.debug(f"use original repo url {server.url}")
|
||||||
|
lines.append(f"Server = {server.url}\n")
|
||||||
|
|
||||||
def append_config(self, lines: list[str]):
|
def append_config(self, lines: list[str]):
|
||||||
"""
|
"""
|
||||||
@ -127,54 +179,27 @@ class Pacman:
|
|||||||
ret = self.ctx.run_external(cmds)
|
ret = self.ctx.run_external(cmds)
|
||||||
if ret != 0: raise OSError(f"pacman failed with {ret}")
|
if ret != 0: raise OSError(f"pacman failed with {ret}")
|
||||||
|
|
||||||
def add_database(self, repo: dict):
|
|
||||||
"""
|
|
||||||
Add a database and update it
|
|
||||||
"""
|
|
||||||
def resolve(url: str) -> str:
|
|
||||||
"""
|
|
||||||
Replace pacman.conf variables
|
|
||||||
"""
|
|
||||||
return (url
|
|
||||||
.replace("$arch", self.ctx.tgt_arch)
|
|
||||||
.replace("$repo", name))
|
|
||||||
if "name" not in repo:
|
|
||||||
raise ArchBuilderConfigError("repo name not set")
|
|
||||||
name = repo["name"]
|
|
||||||
|
|
||||||
# never add local into database
|
|
||||||
if name == "local" or "/" in name:
|
|
||||||
raise ArchBuilderConfigError("bad repo name")
|
|
||||||
|
|
||||||
# register database
|
|
||||||
if name not in self.databases:
|
|
||||||
self.databases[name] = self.handle.register_syncdb(
|
|
||||||
name, pyalpm.SIG_DATABASE_MARGINAL_OK
|
|
||||||
)
|
|
||||||
db = self.databases[name]
|
|
||||||
|
|
||||||
# add databases servers
|
|
||||||
servers: list[str] = []
|
|
||||||
if "server" in repo:
|
|
||||||
servers.append(resolve(repo["server"]))
|
|
||||||
if "servers" in repo:
|
|
||||||
for server in repo["servers"]:
|
|
||||||
servers.append(resolve(server))
|
|
||||||
db.servers = servers
|
|
||||||
|
|
||||||
# update database now via pyalpm
|
|
||||||
log.info(f"updating database {name}")
|
|
||||||
db.update(False)
|
|
||||||
|
|
||||||
def load_databases(self):
|
def load_databases(self):
|
||||||
"""
|
"""
|
||||||
Add all databases and load them
|
Add all databases and load them
|
||||||
"""
|
"""
|
||||||
cfg = self.config
|
for mirror in self.repos:
|
||||||
if "repo" not in cfg:
|
# register database
|
||||||
raise ArchBuilderConfigError("no repos found in config")
|
if mirror.name not in self.databases:
|
||||||
for repo in cfg["repo"]:
|
self.databases[mirror.name] = self.handle.register_syncdb(
|
||||||
self.add_database(repo)
|
mirror.name, pyalpm.SIG_DATABASE_MARGINAL_OK
|
||||||
|
)
|
||||||
|
db = self.databases[mirror.name]
|
||||||
|
|
||||||
|
# add databases servers
|
||||||
|
servers: list[str] = []
|
||||||
|
for server in mirror.servers:
|
||||||
|
servers.append(server.url)
|
||||||
|
db.servers = servers
|
||||||
|
|
||||||
|
# update database now via pyalpm
|
||||||
|
log.info(f"updating database {mirror.name}")
|
||||||
|
db.update(False)
|
||||||
self.init_config()
|
self.init_config()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
@ -231,6 +256,78 @@ class Pacman:
|
|||||||
os.makedirs(work_cache, mode=0o0755, exist_ok=True)
|
os.makedirs(work_cache, mode=0o0755, exist_ok=True)
|
||||||
os.makedirs(root_cache, mode=0o0755, exist_ok=True)
|
os.makedirs(root_cache, mode=0o0755, exist_ok=True)
|
||||||
|
|
||||||
|
def add_repo(self, repo: PacmanRepo):
|
||||||
|
if not repo or not repo.name or len(repo.servers) <= 0:
|
||||||
|
raise ArchBuilderConfigError("bad repo")
|
||||||
|
self.repos.append(repo)
|
||||||
|
self.repos.sort(key=lambda r: r.priority)
|
||||||
|
|
||||||
|
def init_repos(self):
|
||||||
|
"""
|
||||||
|
Initialize mirrors
|
||||||
|
"""
|
||||||
|
if "repo" not in self.config:
|
||||||
|
raise ArchBuilderConfigError("no repos found in config")
|
||||||
|
mirrors = self.ctx.get("mirrors", [])
|
||||||
|
for repo in self.config["repo"]:
|
||||||
|
if "name" not in repo:
|
||||||
|
raise ArchBuilderConfigError("repo name not set")
|
||||||
|
|
||||||
|
# never add local into database
|
||||||
|
if repo["name"] == "local" or "/" in repo["name"]:
|
||||||
|
raise ArchBuilderConfigError("bad repo name")
|
||||||
|
|
||||||
|
# create pacman repo instance
|
||||||
|
pacman_repo = PacmanRepo(name=repo["name"])
|
||||||
|
if "priority" in repo:
|
||||||
|
pacman_repo.priority = repo["priority"]
|
||||||
|
|
||||||
|
originals: list[str] = []
|
||||||
|
servers: list[str] = []
|
||||||
|
|
||||||
|
# add all original repo url
|
||||||
|
if "server" in repo: servers.append(repo["server"])
|
||||||
|
if "servers" in repo: servers.extend(repo["server"])
|
||||||
|
if len(servers) <= 0:
|
||||||
|
raise ArchBuilderConfigError("no any original repo url found")
|
||||||
|
|
||||||
|
# resolve original repo url
|
||||||
|
for server in servers:
|
||||||
|
originals.append(resolve_simple_values(server, {
|
||||||
|
"arch": self.ctx.tgt_arch,
|
||||||
|
"repo": repo["name"],
|
||||||
|
}))
|
||||||
|
|
||||||
|
# add repo mirror url
|
||||||
|
for mirror in mirrors:
|
||||||
|
if "name" not in mirror:
|
||||||
|
raise ArchBuilderConfigError("mirror name not set")
|
||||||
|
if "repos" not in mirror:
|
||||||
|
raise ArchBuilderConfigError("repos list not set")
|
||||||
|
for repo in mirror["repos"]:
|
||||||
|
if "original" not in repo:
|
||||||
|
raise ArchBuilderConfigError("original url not set")
|
||||||
|
if "mirror" not in repo:
|
||||||
|
raise ArchBuilderConfigError("mirror url not set")
|
||||||
|
for original in originals:
|
||||||
|
if original.startswith(repo["original"]):
|
||||||
|
path = original[len(repo["original"]):]
|
||||||
|
real_url = repo["mirror"] + path
|
||||||
|
pacman_repo.add_server(
|
||||||
|
name=mirror["name"],
|
||||||
|
url=real_url,
|
||||||
|
mirror=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# add original url
|
||||||
|
for original in originals:
|
||||||
|
pacman_repo.add_server(
|
||||||
|
url=original,
|
||||||
|
mirror=False
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add_repo(pacman_repo)
|
||||||
|
|
||||||
def __init__(self, ctx: ArchBuilderContext):
|
def __init__(self, ctx: ArchBuilderContext):
|
||||||
"""
|
"""
|
||||||
Initialize pacman context
|
Initialize pacman context
|
||||||
@ -250,7 +347,9 @@ class Pacman:
|
|||||||
self.handle.progresscb = progress_cb
|
self.handle.progresscb = progress_cb
|
||||||
self.databases = {}
|
self.databases = {}
|
||||||
self.caches = []
|
self.caches = []
|
||||||
|
self.repos = []
|
||||||
self.init_cache()
|
self.init_cache()
|
||||||
|
self.init_repos()
|
||||||
for cache in self.caches:
|
for cache in self.caches:
|
||||||
self.handle.add_cachedir(cache)
|
self.handle.add_cachedir(cache)
|
||||||
self.init_config()
|
self.init_config()
|
||||||
|
27
builder/disk/file.py
Normal file
27
builder/disk/file.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import os
|
||||||
|
from logging import getLogger
|
||||||
|
from builder.disk.content import ImageContentBuilder
|
||||||
|
from builder.lib.config import ArchBuilderConfigError
|
||||||
|
log = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ImageFileBuilder(ImageContentBuilder):
|
||||||
|
def build(self):
|
||||||
|
cmds = ["dd"]
|
||||||
|
ctx = self.builder.ctx
|
||||||
|
cfg = self.builder.config
|
||||||
|
if "file" not in cfg:
|
||||||
|
raise ArchBuilderConfigError("file not set")
|
||||||
|
file: str = cfg["file"]
|
||||||
|
if file.startswith("/"): file = file[1:]
|
||||||
|
path = os.path.join(ctx.get_rootfs(), file)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise FileNotFoundError(f"image file {path} not found")
|
||||||
|
cmds.append("status=progress")
|
||||||
|
cmds.append(f"if={path}")
|
||||||
|
cmds.append(f"of={self.builder.device}")
|
||||||
|
cmds.append(f"bs={self.builder.sector}")
|
||||||
|
log.info(f"start writing image file {path}")
|
||||||
|
ret = ctx.run_external(cmds)
|
||||||
|
if ret != 0: raise OSError("dd failed")
|
||||||
|
log.info(f"write image file {path} done")
|
@ -19,6 +19,11 @@ class FileSystemBuilder(ImageContentBuilder):
|
|||||||
|
|
||||||
def proc_cmdline_root(self, cfg: dict, mnt: MountPoint):
|
def proc_cmdline_root(self, cfg: dict, mnt: MountPoint):
|
||||||
ccfg = self.builder.ctx.config_orig
|
ccfg = self.builder.ctx.config_orig
|
||||||
|
mnt.remove_option("ro")
|
||||||
|
mnt.remove_option("rw")
|
||||||
|
for opt in mnt.option:
|
||||||
|
if opt.startswith("x-"):
|
||||||
|
mnt.option.remove(opt)
|
||||||
if "kernel" not in ccfg: ccfg["kernel"] = {}
|
if "kernel" not in ccfg: ccfg["kernel"] = {}
|
||||||
kern = ccfg["kernel"]
|
kern = ccfg["kernel"]
|
||||||
if "cmdline" not in kern: kern["cmdline"] = []
|
if "cmdline" not in kern: kern["cmdline"] = []
|
||||||
@ -27,12 +32,16 @@ class FileSystemBuilder(ImageContentBuilder):
|
|||||||
raise ArchBuilderConfigError("root already set in cmdline")
|
raise ArchBuilderConfigError("root already set in cmdline")
|
||||||
if mnt.target != "/":
|
if mnt.target != "/":
|
||||||
log.warning(f"root target is not / ({mnt.target})")
|
log.warning(f"root target is not / ({mnt.target})")
|
||||||
|
if not mnt.source.startswith("/") and "=" not in mnt.source:
|
||||||
|
log.warning(f"bad root source ({mnt.source})")
|
||||||
ecmds = [
|
ecmds = [
|
||||||
"ro", "rootwait",
|
"ro", "rootwait",
|
||||||
f"root={mnt.source}",
|
f"root={mnt.source}",
|
||||||
f"rootfstype={mnt.fstype}",
|
|
||||||
f"rootflags={mnt.options}",
|
|
||||||
]
|
]
|
||||||
|
if mnt.fstype != "none":
|
||||||
|
ecmds.append(f"rootfstype={mnt.fstype}")
|
||||||
|
if len(mnt.option) > 0:
|
||||||
|
ecmds.append(f"rootflags={mnt.options}")
|
||||||
scmds = " ".join(ecmds)
|
scmds = " ".join(ecmds)
|
||||||
log.debug(f"add root cmdline {scmds}")
|
log.debug(f"add root cmdline {scmds}")
|
||||||
cmds.extend(ecmds)
|
cmds.extend(ecmds)
|
||||||
@ -53,7 +62,10 @@ class FileSystemBuilder(ImageContentBuilder):
|
|||||||
|
|
||||||
def proc_grow(self, cfg: dict, mnt: MountPoint):
|
def proc_grow(self, cfg: dict, mnt: MountPoint):
|
||||||
root = self.builder.ctx.get_rootfs()
|
root = self.builder.ctx.get_rootfs()
|
||||||
if "ptype" not in cfg: raise ArchBuilderConfigError("no ptype set for grow")
|
if "ptype" not in cfg:
|
||||||
|
log.warning("no partition type set, grow filesystem only")
|
||||||
|
mnt.option.append("x-systemd.growfs")
|
||||||
|
return
|
||||||
ptype = DiskTypesGPT.lookup_one_uuid(cfg["ptype"])
|
ptype = DiskTypesGPT.lookup_one_uuid(cfg["ptype"])
|
||||||
if ptype is None: raise ArchBuilderConfigError(f"unknown type {cfg['ptype']}")
|
if ptype is None: raise ArchBuilderConfigError(f"unknown type {cfg['ptype']}")
|
||||||
mnt.option.append("x-systemd.growfs")
|
mnt.option.append("x-systemd.growfs")
|
||||||
@ -110,7 +122,7 @@ class FileSystemBuilder(ImageContentBuilder):
|
|||||||
self.builder.ctx.fstab.append(mnt)
|
self.builder.ctx.fstab.append(mnt)
|
||||||
self.builder.ctx.fsmap[mnt.source] = self.builder.device
|
self.builder.ctx.fsmap[mnt.source] = self.builder.device
|
||||||
if "boot" in fstab and fstab["boot"]:
|
if "boot" in fstab and fstab["boot"]:
|
||||||
self.proc_cmdline_root(cfg, mnt)
|
self.proc_cmdline_root(cfg, mnt.clone())
|
||||||
|
|
||||||
def format(self, fstype: str):
|
def format(self, fstype: str):
|
||||||
from builder.disk.filesystem.creator import FileSystemCreators
|
from builder.disk.filesystem.creator import FileSystemCreators
|
||||||
|
@ -2,6 +2,7 @@ from builder.disk.content import ImageContentBuilder
|
|||||||
from builder.disk.layout.build import DiskLayoutBuilder
|
from builder.disk.layout.build import DiskLayoutBuilder
|
||||||
from builder.disk.filesystem.build import FileSystemBuilder
|
from builder.disk.filesystem.build import FileSystemBuilder
|
||||||
from builder.disk.abootimg import AndroidBootBuilder
|
from builder.disk.abootimg import AndroidBootBuilder
|
||||||
|
from builder.disk.file import ImageFileBuilder
|
||||||
|
|
||||||
|
|
||||||
types: list[tuple[str, type[ImageContentBuilder]]] = [
|
types: list[tuple[str, type[ImageContentBuilder]]] = [
|
||||||
@ -9,4 +10,5 @@ types: list[tuple[str, type[ImageContentBuilder]]] = [
|
|||||||
("filesystem", FileSystemBuilder),
|
("filesystem", FileSystemBuilder),
|
||||||
("aboot", AndroidBootBuilder),
|
("aboot", AndroidBootBuilder),
|
||||||
("avndboot", AndroidBootBuilder),
|
("avndboot", AndroidBootBuilder),
|
||||||
|
("image", ImageFileBuilder),
|
||||||
]
|
]
|
||||||
|
@ -262,7 +262,7 @@ class MountPoint(SerializableDict):
|
|||||||
mnt.source = self.source
|
mnt.source = self.source
|
||||||
mnt.target = self.target
|
mnt.target = self.target
|
||||||
mnt.fstype = self.fstype
|
mnt.fstype = self.fstype
|
||||||
mnt.option = self.option
|
mnt.options = self.options
|
||||||
mnt.fs_freq = self.fs_freq
|
mnt.fs_freq = self.fs_freq
|
||||||
mnt.fs_passno = self.fs_passno
|
mnt.fs_passno = self.fs_passno
|
||||||
return mnt
|
return mnt
|
||||||
|
@ -39,6 +39,13 @@ def dict_get(key: str, root: dict):
|
|||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_simple_values(original: str, values: dict) -> str:
|
||||||
|
value = str(original)
|
||||||
|
for key in values:
|
||||||
|
value = value.replace(f"${key}", values[key])
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class SubScript:
|
class SubScript:
|
||||||
root: dict
|
root: dict
|
||||||
resolved: list[str]
|
resolved: list[str]
|
||||||
@ -74,8 +81,9 @@ class SubScript:
|
|||||||
while last < len(content):
|
while last < len(content):
|
||||||
last = content.find("$", last)
|
last = content.find("$", last)
|
||||||
if last < 0: break
|
if last < 0: break
|
||||||
if content[last:last+2] == "$$":
|
if content[last:last + 2] == "$$":
|
||||||
last += 2
|
content = content[:last] + content[last + 1:]
|
||||||
|
last += 1
|
||||||
continue
|
continue
|
||||||
if len(content) <= last + 2 or content[last + 1] != "{":
|
if len(content) <= last + 2 or content[last + 1] != "{":
|
||||||
raise ValueError(f"unexpected token in subscript at {lvl}")
|
raise ValueError(f"unexpected token in subscript at {lvl}")
|
||||||
|
@ -18,6 +18,7 @@ def parse_arguments(ctx: ArchBuilderContext):
|
|||||||
parser.add_argument("-C", "--clean", help="Clean workspace before build", default=False, action='store_true')
|
parser.add_argument("-C", "--clean", help="Clean workspace before build", default=False, action='store_true')
|
||||||
parser.add_argument("-p", "--preset", help="Select preset to create package")
|
parser.add_argument("-p", "--preset", help="Select preset to create package")
|
||||||
parser.add_argument("-c", "--config", help="Select config to build", action='append')
|
parser.add_argument("-c", "--config", help="Select config to build", action='append')
|
||||||
|
parser.add_argument("-m", "--mirror", help="Select mirror to download package", action='append')
|
||||||
parser.add_argument("-o", "--workspace", help="Set workspace for builder", default=ctx.work)
|
parser.add_argument("-o", "--workspace", help="Set workspace for builder", default=ctx.work)
|
||||||
parser.add_argument("-d", "--debug", help="Enable debug logging", default=False, action='store_true')
|
parser.add_argument("-d", "--debug", help="Enable debug logging", default=False, action='store_true')
|
||||||
parser.add_argument("-G", "--no-gpgcheck", help="Disable GPG check", default=False, action='store_true')
|
parser.add_argument("-G", "--no-gpgcheck", help="Disable GPG check", default=False, action='store_true')
|
||||||
@ -45,6 +46,10 @@ def parse_arguments(ctx: ArchBuilderContext):
|
|||||||
pcfgs = ctx.get("package.configs", [])
|
pcfgs = ctx.get("package.configs", [])
|
||||||
configs.extend(pcfgs)
|
configs.extend(pcfgs)
|
||||||
|
|
||||||
|
if args.mirror:
|
||||||
|
for mirror in args.mirror:
|
||||||
|
configs.extend([f"mirrors/{name}" for name in mirror.split(",")])
|
||||||
|
|
||||||
# load and populate configs
|
# load and populate configs
|
||||||
config.load_configs(ctx, configs)
|
config.load_configs(ctx, configs)
|
||||||
config.populate_config(ctx)
|
config.populate_config(ctx)
|
||||||
|
52
configs/common/persistent-mac.yaml
Normal file
52
configs/common/persistent-mac.yaml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
filesystem:
|
||||||
|
files:
|
||||||
|
- path: /etc/systemd/scripts/generate-mac.sh
|
||||||
|
content: |
|
||||||
|
#!/bin/bash
|
||||||
|
mac="$$((cat /etc/machine-id; echo "$$@"; ) | sha256sum -)"
|
||||||
|
echo "42:$${mac:0:2}:$${mac:4:2}:$${mac:8:2}:$${mac:12:2}:$${mac:16:2}"
|
||||||
|
- path: /etc/systemd/scripts/net-update-mac.sh
|
||||||
|
content: |
|
||||||
|
#!/bin/bash
|
||||||
|
MAC="$$(bash /etc/systemd/scripts/generate-mac.sh "$$@")"
|
||||||
|
ip link set dev "$$@" down &> /dev/null || true
|
||||||
|
ip link set dev "$$@" address "$$MAC"
|
||||||
|
- path: /etc/systemd/scripts/bt-update-mac.sh
|
||||||
|
content: |
|
||||||
|
#!/bin/bash
|
||||||
|
MAC="$$(bash /etc/systemd/scripts/generate-mac.sh bluetooth)"
|
||||||
|
for i in {0..5}; do
|
||||||
|
sleep "$$i"
|
||||||
|
if bluetoothctl mgmt.public-addr "$$MAC"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit "$$?"
|
||||||
|
- path: /etc/systemd/system/bt-update-mac.service
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Update Bluetooth Persistent MAC Address
|
||||||
|
After=bluetooth.service systemd-machine-id-commit.service
|
||||||
|
Wants=bluetooth.service
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=bash /etc/systemd/scripts/bt-update-mac.sh
|
||||||
|
SyslogIdentifier=bt-update-mac
|
||||||
|
[Install]
|
||||||
|
WantedBy=bluetooth.target
|
||||||
|
- path: /etc/systemd/system/net-update-mac@.service
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Update Persistent MAC Address for %i
|
||||||
|
Before=network.target
|
||||||
|
After=wait-interface@%i.service systemd-machine-id-commit.service
|
||||||
|
Wants=wait-interface@%i.service
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=bash /etc/systemd/scripts/net-update-mac.sh %i
|
||||||
|
SyslogIdentifier=wlan-update-mac
|
||||||
|
[Install]
|
||||||
|
WantedBy=sysinit.target
|
||||||
|
+also:
|
||||||
|
- packages/bluez
|
||||||
|
- common/systemd-wait-for
|
80
configs/common/systemd-wait-for.yaml
Normal file
80
configs/common/systemd-wait-for.yaml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
filesystem:
|
||||||
|
files:
|
||||||
|
- path: /etc/systemd/system/wait-addresses@.service
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Wait for addresses %i
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=bash /etc/systemd/scripts/wait-addresses.sh %i 60
|
||||||
|
SyslogIdentifier=wait-addresses
|
||||||
|
[Install]
|
||||||
|
WantedBy=network-online.target
|
||||||
|
- path: /etc/systemd/system/wait-interface@.service
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Wait for interface %i
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=bash /etc/systemd/scripts/wait-interface.sh %i 60
|
||||||
|
SyslogIdentifier=wait-interface
|
||||||
|
[Install]
|
||||||
|
WantedBy=network-online.target
|
||||||
|
- path: /etc/systemd/system/wait-reached@.service
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Wait for reached %i
|
||||||
|
After=network-online.target
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=bash /etc/systemd/scripts/wait-reached.sh %i 60
|
||||||
|
SyslogIdentifier=wait-reached
|
||||||
|
[Install]
|
||||||
|
WantedBy=network-online.target
|
||||||
|
- path: /etc/systemd/scripts/wait-addresses.sh
|
||||||
|
content: |
|
||||||
|
#!/usr/bin/bash
|
||||||
|
address="$${1}"
|
||||||
|
timeout="$${2}"
|
||||||
|
[ -z "$${address}" ]&&exit 2
|
||||||
|
[ -z "$${timeout}" ]&&timeout=10
|
||||||
|
[[ "$${timeout}" -lt 0 ]]&&exit 2
|
||||||
|
int=0
|
||||||
|
timeout=$$((timeout*5))
|
||||||
|
while ! ip address show | grep -w "$${address}" &>/dev/null; do
|
||||||
|
int=$$((int+1))
|
||||||
|
[[ "$${int}" -gt "$${timeout}" ]]&&exit 1
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
true
|
||||||
|
- path: /etc/systemd/scripts/wait-interface.sh
|
||||||
|
content: |
|
||||||
|
#!/usr/bin/bash
|
||||||
|
interface="$${1}"
|
||||||
|
timeout="$${2}"
|
||||||
|
[ -z "$${interface}" ]&&exit 2
|
||||||
|
[ -z "$${timeout}" ]&&timeout=10
|
||||||
|
[[ "$${timeout}" -lt 0 ]]&&exit 2
|
||||||
|
int=0
|
||||||
|
timeout=$$((timeout*5))
|
||||||
|
while ! [ -h "/sys/class/net/$${interface}" ]; do
|
||||||
|
int=$$((int+1))
|
||||||
|
[[ "$${int}" -gt "$${timeout}" ]]&&exit 1
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
true
|
||||||
|
- path: /etc/systemd/scripts/wait-reached.sh
|
||||||
|
content: |
|
||||||
|
#!/usr/bin/bash
|
||||||
|
address="$${1}"
|
||||||
|
stimeout="$${2}"
|
||||||
|
[ -z "$${address}" ]&&exit 2
|
||||||
|
[ -z "$${stimeout}" ]&&stimeout=10
|
||||||
|
[[ "$${stimeout}" -lt 0 ]]&&exit 2
|
||||||
|
int=0
|
||||||
|
while ! timeout 1s ping -c 1 -W 1 "$${address}" &>/dev/null; do
|
||||||
|
int=$$((int+1))
|
||||||
|
[[ "$${int}" -gt "$${stimeout}" ]]&&exit 1
|
||||||
|
sleep 0.5
|
||||||
|
done
|
||||||
|
true
|
@ -2,6 +2,7 @@
|
|||||||
pacman:
|
pacman:
|
||||||
install:
|
install:
|
||||||
- gnome
|
- gnome
|
||||||
|
- gnome-packagekit
|
||||||
systemd:
|
systemd:
|
||||||
default: graphical.target
|
default: graphical.target
|
||||||
enable:
|
enable:
|
||||||
|
@ -25,10 +25,16 @@ pacman:
|
|||||||
|
|
||||||
# Vulkan dependency
|
# Vulkan dependency
|
||||||
- xcb-util-keysyms
|
- xcb-util-keysyms
|
||||||
|
|
||||||
|
# AYN Odin2 RGB LED Tuner
|
||||||
|
- rgb-led
|
||||||
systemd:
|
systemd:
|
||||||
disable:
|
disable:
|
||||||
# No modem in this device
|
# No modem in this device
|
||||||
- rmtfs.service
|
- rmtfs.service
|
||||||
|
enable:
|
||||||
|
- bt-update-mac.service
|
||||||
|
- net-update-mac@wlp1s0.service
|
||||||
filesystem:
|
filesystem:
|
||||||
files:
|
files:
|
||||||
# GamePAD workaround
|
# GamePAD workaround
|
||||||
@ -54,6 +60,10 @@ filesystem:
|
|||||||
[Resolve]
|
[Resolve]
|
||||||
MulticastDNS=no
|
MulticastDNS=no
|
||||||
LLMNR=no
|
LLMNR=no
|
||||||
|
- path: /etc/NetworkManager/conf.d/80-no-wifi-powersave.conf
|
||||||
|
content: |
|
||||||
|
[connection]
|
||||||
|
wifi.powersave = 2
|
||||||
sysconf:
|
sysconf:
|
||||||
chassis: handset
|
chassis: handset
|
||||||
environments:
|
environments:
|
||||||
@ -102,6 +112,9 @@ mkinitcpio:
|
|||||||
# USB Gadget tools
|
# USB Gadget tools
|
||||||
- packages/systemd-gadget
|
- packages/systemd-gadget
|
||||||
|
|
||||||
|
# Android Debug Bridge Daemon via USB Gadget
|
||||||
|
- packages/adbd
|
||||||
|
|
||||||
# OpenSSH Server
|
# OpenSSH Server
|
||||||
- packages/openssh
|
- packages/openssh
|
||||||
|
|
||||||
@ -110,3 +123,9 @@ mkinitcpio:
|
|||||||
|
|
||||||
# Bluetooth related services
|
# Bluetooth related services
|
||||||
- packages/bluez
|
- packages/bluez
|
||||||
|
|
||||||
|
# Persistent MAC Address
|
||||||
|
- common/persistent-mac
|
||||||
|
|
||||||
|
# Root without password
|
||||||
|
- common/wheel-nopasswd
|
||||||
|
26
configs/mirrors/bfsu.yaml
Normal file
26
configs/mirrors/bfsu.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
mirrors:
|
||||||
|
- name: bfsu
|
||||||
|
repos:
|
||||||
|
# ArchLinux
|
||||||
|
- original: https://geo.mirror.pkgbuild.com/
|
||||||
|
mirror: https://mirrors.bfsu.edu.cn/archlinux/
|
||||||
|
|
||||||
|
# ArchLinux ARM
|
||||||
|
- name: archlinuxarm
|
||||||
|
original: http://mirror.archlinuxarm.org/
|
||||||
|
mirror: https://mirrors.bfsu.edu.cn/archlinuxarm/
|
||||||
|
|
||||||
|
# Arch4Edu
|
||||||
|
- name: arch4edu
|
||||||
|
original: https://repository.arch4edu.org/
|
||||||
|
mirror: https://mirrors.bfsu.edu.cn/arch4edu/
|
||||||
|
|
||||||
|
# ArchLinux CN
|
||||||
|
- name: archlinuxcn
|
||||||
|
original: https://repo.archlinuxcn.org/
|
||||||
|
mirror: https://mirrors.bfsu.edu.cn/archlinuxcn/
|
||||||
|
|
||||||
|
# BlackArch
|
||||||
|
- name: blackarch
|
||||||
|
original: https://www.blackarch.org/blackarch/
|
||||||
|
mirror: https://mirrors.bfsu.edu.cn/blackarch/
|
26
configs/mirrors/tuna.yaml
Normal file
26
configs/mirrors/tuna.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
mirrors:
|
||||||
|
- name: tuna
|
||||||
|
repos:
|
||||||
|
# ArchLinux
|
||||||
|
- original: https://geo.mirror.pkgbuild.com/
|
||||||
|
mirror: https://mirrors.tuna.tsinghua.edu.cn/archlinux/
|
||||||
|
|
||||||
|
# ArchLinux ARM
|
||||||
|
- name: archlinuxarm
|
||||||
|
original: http://mirror.archlinuxarm.org/
|
||||||
|
mirror: https://mirrors.tuna.tsinghua.edu.cn/archlinuxarm/
|
||||||
|
|
||||||
|
# Arch4Edu
|
||||||
|
- name: arch4edu
|
||||||
|
original: https://repository.arch4edu.org/
|
||||||
|
mirror: https://mirrors.tuna.tsinghua.edu.cn/arch4edu/
|
||||||
|
|
||||||
|
# ArchLinux CN
|
||||||
|
- name: archlinuxcn
|
||||||
|
original: https://repo.archlinuxcn.org/
|
||||||
|
mirror: https://mirrors.tuna.tsinghua.edu.cn/archlinuxcn/
|
||||||
|
|
||||||
|
# BlackArch
|
||||||
|
- name: blackarch
|
||||||
|
original: https://www.blackarch.org/blackarch/
|
||||||
|
mirror: https://mirrors.tuna.tsinghua.edu.cn/blackarch/
|
21
configs/mirrors/ustc.yaml
Normal file
21
configs/mirrors/ustc.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
mirrors:
|
||||||
|
- name: ustc
|
||||||
|
repos:
|
||||||
|
# ArchLinux
|
||||||
|
- original: https://geo.mirror.pkgbuild.com/
|
||||||
|
mirror: https://mirrors.ustc.edu.cn/archlinux/
|
||||||
|
|
||||||
|
# ArchLinux ARM
|
||||||
|
- name: archlinuxarm
|
||||||
|
original: http://mirror.archlinuxarm.org/
|
||||||
|
mirror: https://mirrors.ustc.edu.cn/archlinuxarm/
|
||||||
|
|
||||||
|
# ArchLinux CN
|
||||||
|
- name: archlinuxcn
|
||||||
|
original: https://repo.archlinuxcn.org/
|
||||||
|
mirror: https://mirrors.ustc.edu.cn/archlinuxcn/
|
||||||
|
|
||||||
|
# BlackArch
|
||||||
|
- name: blackarch
|
||||||
|
original: https://www.blackarch.org/blackarch/
|
||||||
|
mirror: https://mirrors.ustc.edu.cn/blackarch/
|
9
configs/packages/adbd.yaml
Normal file
9
configs/packages/adbd.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Android Debug Bridge Daemon via USB Gadget
|
||||||
|
pacman:
|
||||||
|
install:
|
||||||
|
- adbd
|
||||||
|
systemd:
|
||||||
|
enable:
|
||||||
|
- adbd-usb.service
|
||||||
|
+also:
|
||||||
|
- packages/systemd-gadget
|
@ -2,6 +2,8 @@
|
|||||||
pacman:
|
pacman:
|
||||||
install:
|
install:
|
||||||
- bluez
|
- bluez
|
||||||
|
- bluez-tools
|
||||||
|
- bluez-utils
|
||||||
systemd:
|
systemd:
|
||||||
enable:
|
enable:
|
||||||
- bluetooth.service
|
- bluetooth.service
|
||||||
|
@ -9,5 +9,15 @@ systemd:
|
|||||||
- getty@ttyGS0.service
|
- getty@ttyGS0.service
|
||||||
- usbgadget-func-acm.service
|
- usbgadget-func-acm.service
|
||||||
enable:
|
enable:
|
||||||
|
- gadget-init.service
|
||||||
|
- gadget-start.service
|
||||||
|
- usbgadget-func-rndis.service
|
||||||
# Enable systemd-networkd for RNDIS
|
# Enable systemd-networkd for RNDIS
|
||||||
- systemd-networkd.service
|
- systemd-networkd.service
|
||||||
|
filesystem:
|
||||||
|
files:
|
||||||
|
- path: /etc/systemd/network/sharenet.network.d/override.conf
|
||||||
|
content: |
|
||||||
|
[DHCPServer]
|
||||||
|
EmitRouter=no
|
||||||
|
EmitDNS=no
|
||||||
|
@ -2,6 +2,6 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: arch4edu
|
- name: arch4edu
|
||||||
priority: 800
|
priority: 800
|
||||||
server: https://mirrors.bfsu.edu.cn/arch4edu/${arch}
|
server: https://repository.arch4edu.org/$$arch
|
||||||
install:
|
install:
|
||||||
- arch4edu/arch4edu-keyring
|
- arch4edu/arch4edu-keyring
|
||||||
|
@ -2,13 +2,13 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: core
|
- name: core
|
||||||
priority: 100
|
priority: 100
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinux/core/os/${arch}
|
server: https://geo.mirror.pkgbuild.com/$$repo/os/$$arch
|
||||||
- name: extra
|
- name: extra
|
||||||
priority: 110
|
priority: 110
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinux/extra/os/${arch}
|
server: https://geo.mirror.pkgbuild.com/$$repo/os/$$arch
|
||||||
- name: multilib
|
- name: multilib
|
||||||
priority: 120
|
priority: 120
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinux/multilib/os/${arch}
|
server: https://geo.mirror.pkgbuild.com/$$repo/os/$$arch
|
||||||
trust:
|
trust:
|
||||||
- eworm@archlinux.org
|
- eworm@archlinux.org
|
||||||
- dvzrv@archlinux.org
|
- dvzrv@archlinux.org
|
||||||
|
@ -2,16 +2,16 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: core
|
- name: core
|
||||||
priority: 100
|
priority: 100
|
||||||
server: http://mirrors.bfsu.edu.cn/archlinuxarm/${arch}/core
|
server: http://mirror.archlinuxarm.org/$$arch/$$repo
|
||||||
- name: extra
|
- name: extra
|
||||||
priority: 110
|
priority: 110
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinuxarm/${arch}/extra
|
server: http://mirror.archlinuxarm.org/$$arch/$$repo
|
||||||
- name: alarm
|
- name: alarm
|
||||||
priority: 120
|
priority: 120
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinuxarm/${arch}/alarm
|
server: http://mirror.archlinuxarm.org/$$arch/$$repo
|
||||||
- name: aur
|
- name: aur
|
||||||
priority: 130
|
priority: 130
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinuxarm/${arch}/aur
|
server: http://mirror.archlinuxarm.org/$$arch/$$repo
|
||||||
trust:
|
trust:
|
||||||
- builder@archlinuxarm.org
|
- builder@archlinuxarm.org
|
||||||
install:
|
install:
|
||||||
|
@ -2,7 +2,7 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: archlinuxcn
|
- name: archlinuxcn
|
||||||
priority: 500
|
priority: 500
|
||||||
server: https://mirrors.bfsu.edu.cn/archlinuxcn/${arch}
|
server: https://repo.archlinuxcn.org/$$arch
|
||||||
trust:
|
trust:
|
||||||
- farseerfc@archlinux.org
|
- farseerfc@archlinux.org
|
||||||
install:
|
install:
|
||||||
|
@ -2,7 +2,7 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: blackarch
|
- name: blackarch
|
||||||
priority: 1000
|
priority: 1000
|
||||||
server: https://mirrors.bfsu.edu.cn/blackarch/blackarch/os/${arch}
|
server: https://www.blackarch.org/$$repo/os/$$arch
|
||||||
trust:
|
trust:
|
||||||
- noptrix@nullsecurity.net
|
- noptrix@nullsecurity.net
|
||||||
install:
|
install:
|
||||||
|
@ -2,7 +2,7 @@ pacman:
|
|||||||
repo:
|
repo:
|
||||||
- name: renegade-project
|
- name: renegade-project
|
||||||
priority: 200
|
priority: 200
|
||||||
server: https://mirror.renegade-project.tech/arch/${arch}
|
server: https://mirror.renegade-project.tech/arch/$$arch
|
||||||
trust:
|
trust:
|
||||||
- renegade-project@classfun.cn
|
- renegade-project@classfun.cn
|
||||||
install:
|
install:
|
||||||
|
@ -9,6 +9,7 @@ image:
|
|||||||
size: 8GiB
|
size: 8GiB
|
||||||
sector: 4096
|
sector: 4096
|
||||||
mount: /
|
mount: /
|
||||||
|
grow: yes
|
||||||
fstab:
|
fstab:
|
||||||
boot: yes
|
boot: yes
|
||||||
flags: rw,noatime,discard
|
flags: rw,noatime,discard
|
||||||
|
Loading…
Reference in New Issue
Block a user