diff --git a/builder/build/filesystem.py b/builder/build/filesystem.py index a0145ba..535755b 100644 --- a/builder/build/filesystem.py +++ b/builder/build/filesystem.py @@ -96,8 +96,8 @@ def add_file(ctx: ArchBuilderContext, file: dict): # at least path content if "path" not in file: raise ArchBuilderConfigError("no path set in file") - if "content" not in file and "source" not in file: - raise ArchBuilderConfigError("no content or source set in file") + if "content" not in file and "source" not in file and "url" not in file: + raise ArchBuilderConfigError(f"no content, source or url set in file") root = ctx.get_rootfs() path: str = file["path"] if path.startswith("/"): path = path[1:] @@ -109,7 +109,7 @@ def add_file(ctx: ArchBuilderContext, file: dict): # follow symbolic links follow = file["follow"] if "follow" in file else True - # source is a folder + # source is a folder folder = file["folder"] if "folder" in file else False # files mode @@ -139,9 +139,13 @@ def add_file(ctx: ArchBuilderContext, file: dict): src = os.path.join(ctx.dir, src) log.debug(f"copy {src} to {real}") if folder: - shutil.copytree(src, real, symlinks=follow) + shutil.copytree(src, real, symlinks=follow, dirs_exist_ok=True) else: shutil.copyfile(src, real, follow_symlinks=follow) + elif "url" in file: + cmds = ["wget", file["url"], "-O", real] + ret = ctx.run_external(cmds) + if ret != 0: raise OSError(f"wget failed with {ret}") else: assert False log.debug(f"chmod file {real} to {mode:04o}") diff --git a/builder/build/pacman.py b/builder/build/pacman.py index dbe56d8..464f0f4 100644 --- a/builder/build/pacman.py +++ b/builder/build/pacman.py @@ -64,7 +64,7 @@ def gen_config(ctx: ArchBuilderContext, pacman: Pacman): conf = os.path.join(ctx.get_rootfs(), "etc/pacman.conf") lines: list[str] = [] append_config(ctx, lines) - pacman.append_repos(lines) + pacman.append_repos(lines, True) with open_config(conf) as f: f.writelines(lines) log.info(f"generated pacman config {conf}") diff --git a/builder/component/pacman.py b/builder/component/pacman.py index 5108277..f75c487 100644 --- a/builder/component/pacman.py +++ b/builder/component/pacman.py @@ -52,17 +52,26 @@ class PacmanRepo(SerializableDict): name: str = None priority: int = 10000 servers: list[PacmanRepoServer] = None + mirrorlist: str = None + publickey: str = None + keyid: str = None def __init__( self, name: str = None, priority: int = None, - servers: list[PacmanRepoServer] = None + servers: list[PacmanRepoServer] = None, + mirrorlist: str = None, + publickey: str = None, + keyid: str = 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 = [] + if mirrorlist is not None: self.mirrorlist = mirrorlist + if publickey is not None: self.publickey = publickey + if keyid is not None: self.keyid = keyid def add_server( self, @@ -86,20 +95,23 @@ class Pacman: caches: list[str] repos: list[PacmanRepo] - def append_repos(self, lines: list[str]): + def append_repos(self, lines: list[str], rootfs: bool = False): """ Add all databases into config """ for repo in self.repos: lines.append(f"[{repo.name}]\n") - for server in repo.servers: - if server.mirror: - lines.append(f"# Mirror {server.name}\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") + if rootfs and repo.mirrorlist is not None: + lines.append(f"Include = /etc/pacman.d/{repo.name}-mirrorlist\n") + else: + for server in repo.servers: + if server.mirror: + lines.append(f"# Mirror {server.name}\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]): """ @@ -136,6 +148,24 @@ class Pacman: log.info("initializing pacman keyring") self.pacman_key(["--init"]) + # Download and add public keys and mirrorlist + for repo in self.repos: + if repo.mirrorlist is not None: + mirrorlist = os.path.join(self.ctx.work, f"etc/pacman.d/{repo.name}-mirrorlist") + cmds = ["wget", repo.mirrorlist, "-O", keypath] + ret = self.ctx.run_external(cmds) + if ret != 0: raise OSError(f"wget failed with {ret}") + if repo.publickey is not None: + keypath = os.path.join(self.ctx.work, f"{repo.name}.pub") + cmds = ["wget", repo.publickey, "-O", keypath] + ret = self.ctx.run_external(cmds) + if ret != 0: raise OSError(f"wget failed with {ret}") + self.pacman_key(["--add", keypath]) + self.lsign_key(repo.keyid) + elif repo.keyid is not None: + self.recv_keys(repo.keyid) + self.lsign_key(repo.keyid) + def init_config(self): """ Create host pacman.conf @@ -282,6 +312,19 @@ class Pacman: if "priority" in repo: pacman_repo.priority = repo["priority"] + if "mirrorlist" in repo: + pacman_repo.mirrorlist = repo["mirrorlist"] + + # add public key url and id + if "publickey" in repo and "keyid" not in repo: + raise ArchBuilderConfigError("publickey is provided without keyid") + + if "publickey" in repo: + pacman_repo.publickey = repo["publickey"] + + if "keyid" in repo: + pacman_repo.keyid = repo["keyid"] + originals: list[str] = [] servers: list[str] = [] diff --git a/configs/common/pacman-init.yaml b/configs/common/pacman-init.yaml new file mode 100644 index 0000000..d889090 --- /dev/null +++ b/configs/common/pacman-init.yaml @@ -0,0 +1,17 @@ +filesystem: + files: + - path: /etc/systemd/system/pacman-init.service + content: | + [Unit] + Description=Initializes Pacman keyring + Requires=etc-pacman.d-gnupg.mount + After=etc-pacman.d-gnupg.mount time-sync.target + BindsTo=etc-pacman.d-gnupg.mount + Before=archlinux-keyring-wkd-sync.service + [Service] + Type=oneshot + RemainAfterExit=yes + ExecStart=/usr/bin/pacman-key --init + ExecStart=/usr/bin/pacman-key --populate + [Install] + WantedBy=multi-user.target diff --git a/configs/desktop/plasma.yaml b/configs/desktop/plasma.yaml index c5a518d..c08286e 100644 --- a/configs/desktop/plasma.yaml +++ b/configs/desktop/plasma.yaml @@ -2,6 +2,9 @@ pacman: install: - plasma + - konsole + - kate + - dolphin - sddm - packagekit-qt6 systemd: @@ -17,3 +20,4 @@ filesystem: +also: # Ensure NetworkManager is enabled - packages/network-manager +- packages/firefox diff --git a/configs/locale/en-US.yaml b/configs/locale/en-US.yaml new file mode 100644 index 0000000..507947a --- /dev/null +++ b/configs/locale/en-US.yaml @@ -0,0 +1,33 @@ +# I18N for English (US) +locale: + enable: + - "en_US.UTF-8 UTF-8" + default: en_US.UTF-8 + +systemd: + enable: + - systemd-timesyncd + +filesystem: + files: + # Wireless regulatory + - path: /etc/conf.d/wireless-regdom + content: | + WIRELESS_REGDOM="US" + # Windows NTP Server + - path: /etc/systemd/timesyncd.conf.d/windows-ntp.conf + content: | + [Time] + NTP=time.windows.com + +sysconf: + environments: + GTK_IM_MODULE: ibus + QT_IM_MODULE: ibus + XMODIFIERS: '@im=ibus' + COUNTRY: US + LANG: en_US.UTF-8 + LANGUAGE: en_US.UTF-8 + LC_ALL: en_US.UTF-8 + TZ: US/Eastern +timezone: US/Eastern diff --git a/configs/locale/ru-RU.yaml b/configs/locale/ru-RU.yaml new file mode 100644 index 0000000..55148b7 --- /dev/null +++ b/configs/locale/ru-RU.yaml @@ -0,0 +1,33 @@ +# I18N for Russian +locale: + enable: + - "ru_RU.UTF-8 UTF-8" + - "en_US.UTF-8 UTF-8" + default: en_US.UTF-8 + +systemd: + enable: + - systemd-timesyncd + +filesystem: + files: + # Wireless regulatory + - path: /etc/conf.d/wireless-regdom + content: | + WIRELESS_REGDOM="RU" + - path: /etc/systemd/timesyncd.conf.d/ntp-pool-ntp.conf + content: | + [Time] + NTP=0.ru.pool.ntp.org + +sysconf: + environments: + GTK_IM_MODULE: ibus + QT_IM_MODULE: ibus + XMODIFIERS: '@im=ibus' + COUNTRY: RU + LANG: ru_RU.UTF-8 + LANGUAGE: ru_RU.UTF-8 + LC_ALL: ru_RU.UTF-8 + TZ: Europe/Moscow +timezone: Europe/Moscow diff --git a/configs/packages/firefox.yaml b/configs/packages/firefox.yaml new file mode 100644 index 0000000..570aa9b --- /dev/null +++ b/configs/packages/firefox.yaml @@ -0,0 +1,4 @@ +# Firefox +pacman: + install: + - firefox diff --git a/configs/packages/nvim.yaml b/configs/packages/nvim.yaml new file mode 100644 index 0000000..2e4798c --- /dev/null +++ b/configs/packages/nvim.yaml @@ -0,0 +1,10 @@ +pacman: + install: + - neovim + - neovide + - less +sysconf: + environments: + EDITOR: nvim + VISUAL: neovide + PAGER: less diff --git a/configs/repo/endeavouros.yaml b/configs/repo/endeavouros.yaml new file mode 100644 index 0000000..cc3ff17 --- /dev/null +++ b/configs/repo/endeavouros.yaml @@ -0,0 +1,12 @@ +pacman: + repo: + - name: endeavouros + priority: 200 + server: https://github.com/endeavouros-team/repo/raw/master/$$repo/$$arch/ + mirrorlist: https://raw.githubusercontent.com/endeavouros-team/PKGBUILDS/master/endeavouros-mirrorlist/endeavouros-mirrorlist + trust: + - info@endeavouros.com + - manuel@endeavouros.com + install: + - endeavouros/endeavouros-keyring + - endeavouros/endeavouros-mirrorlist diff --git a/configs/shell/bash.yaml b/configs/shell/bash.yaml new file mode 100644 index 0000000..87ec5b6 --- /dev/null +++ b/configs/shell/bash.yaml @@ -0,0 +1,3 @@ +pacman: + install: + - bash diff --git a/configs/shell/fish.yaml b/configs/shell/fish.yaml new file mode 100644 index 0000000..b1c1aa6 --- /dev/null +++ b/configs/shell/fish.yaml @@ -0,0 +1,4 @@ +pacman: + install: + - fish + - fisher