diff --git a/hydra/build.py b/hydra/build.py index 40ec5ff..5c98c58 100644 --- a/hydra/build.py +++ b/hydra/build.py @@ -237,8 +237,7 @@ if path.exists(): if step == 'fetch': inputs = json.loads((self.source_dir / 'image/sources.json').read_text()) try: - for name in ('stage3', 'portage'): - item = inputs[name] + for item in [inputs['stage3'], inputs['portage'], *inputs.get('local_packages', [])]: path = self.cache / item.get('filename', Path(urllib.parse.urlparse(item['url']).path).name) verify_hash(path, item['sha256']) except (OSError, BuildError): @@ -276,6 +275,8 @@ if path.exists(): verify_hash(archive, stage['sha256']) snapshot = self.download(inputs['portage']['url'], inputs['portage']['filename']) verify_hash(snapshot, inputs['portage']['sha256']) + for item in inputs.get('local_packages', []): + verify_hash(self.download(item['url'], item['filename']), item['sha256']) signature = self.download(stage['signature_url']) keyring = self.download(inputs['keyring_url']) verify_hash(keyring, inputs['keyring_sha256']) @@ -316,6 +317,9 @@ if [ ! -f /var/db/repos/gentoo/.hydra-snapshot ]; then printf '%s\\n' '{inputs['portage']['commit']}' > /var/db/repos/gentoo/.hydra-snapshot fi cp -a /hydra-source/image/portage/. /etc/portage/ +mkdir -p /var/db/repos/hydra /var/cache/distfiles +cp -a /hydra-source/image/overlay/. /var/db/repos/hydra/ +cp /hydra-cache/brightnessctl-0.5.1.tar.gz /var/cache/distfiles/brightnessctl-0.5.1.tar.gz mkdir -p /etc/portage/patches/app-emulation/qemu /etc/portage/patches/app-emulation/virt-viewer cp /hydra-source/patches/qemu-virtio-refresh-rate.patch /etc/portage/patches/app-emulation/qemu/10-hydra-refresh.patch cp /hydra-source/patches/virt-viewer-hydra-session.patch /etc/portage/patches/app-emulation/virt-viewer/10-hydra-session.patch diff --git a/image/overlay/metadata/layout.conf b/image/overlay/metadata/layout.conf new file mode 100644 index 0000000..20fcfea --- /dev/null +++ b/image/overlay/metadata/layout.conf @@ -0,0 +1,3 @@ +masters = gentoo +thin-manifests = true +sign-manifests = false diff --git a/image/overlay/profiles/repo_name b/image/overlay/profiles/repo_name new file mode 100644 index 0000000..83f0206 --- /dev/null +++ b/image/overlay/profiles/repo_name @@ -0,0 +1 @@ +hydra diff --git a/image/overlay/sys-apps/brightnessctl/Manifest b/image/overlay/sys-apps/brightnessctl/Manifest new file mode 100644 index 0000000..0b2b76e --- /dev/null +++ b/image/overlay/sys-apps/brightnessctl/Manifest @@ -0,0 +1 @@ +DIST brightnessctl-0.5.1.tar.gz 8284 BLAKE2B 7d2226aae10fddc606c5ce71ed4a04eda583acf245ea1532d8730c73dc02ea7aeed47a0e25ca7f9d40e7b0170bb08d87617e9f4aa082495e78894982870ca7cc SHA512 41ac86357b3b5a3d54a043140a6bdb1fb68d5080a16e86692059ad58f4b9134a8532432a3f664c70c665a4ad73ea8a94cc9b88fa84abc28f0356b8b397aaebc7 diff --git a/image/overlay/sys-apps/brightnessctl/brightnessctl-0.5.1.ebuild b/image/overlay/sys-apps/brightnessctl/brightnessctl-0.5.1.ebuild new file mode 100644 index 0000000..08fed88 --- /dev/null +++ b/image/overlay/sys-apps/brightnessctl/brightnessctl-0.5.1.ebuild @@ -0,0 +1,18 @@ +# HydraOS local package for the pinned Gentoo snapshot. +EAPI=8 +inherit toolchain-funcs udev +DESCRIPTION="Read and control backlight brightness without privileged launchers" +HOMEPAGE="https://github.com/Hummer12007/brightnessctl" +SRC_URI="https://github.com/Hummer12007/brightnessctl/archive/refs/tags/${PV}.tar.gz -> ${P}.tar.gz" +LICENSE="MIT" +SLOT="0" +KEYWORDS="amd64" +RDEPEND="virtual/udev" +src_compile() { + emake CC="$(tc-getCC)" VERSION="${PV}" +} +src_install() { + # Upstream's udev mode uses 0755, never its alternate setuid mode. + emake DESTDIR="${D}" PREFIX="${EPREFIX}/usr" UDEVDIR="${EPREFIX}$(get_udevdir)/rules.d" INSTALL_UDEV_RULES=1 install + dodoc README.md LICENSE +} diff --git a/image/portage/repos.conf/hydra.conf b/image/portage/repos.conf/hydra.conf new file mode 100644 index 0000000..67c900c --- /dev/null +++ b/image/portage/repos.conf/hydra.conf @@ -0,0 +1,4 @@ +[hydra] +location = /var/db/repos/hydra +masters = gentoo +auto-sync = no diff --git a/image/sources.json b/image/sources.json index 7cd21c3..4dce8c3 100644 --- a/image/sources.json +++ b/image/sources.json @@ -13,5 +13,15 @@ }, "keyring_url": "https://qa-reports.gentoo.org/output/service-keys.gpg", "keyring_sha256": "9fe40114c956c4c4d593f6e961ac9a994b0772863f4e685608fbdd8d77e39748", - "binhost": "https://distfiles.gentoo.org/releases/amd64/binpackages/23.0/x86-64/" + "binhost": "https://distfiles.gentoo.org/releases/amd64/binpackages/23.0/x86-64/", + "local_packages": [ + { + "atom": "sys-apps/brightnessctl", + "version": "0.5.1", + "url": "https://github.com/Hummer12007/brightnessctl/archive/refs/tags/0.5.1.tar.gz", + "filename": "brightnessctl-0.5.1.tar.gz", + "sha256": "a68869e23f56ac4f2e28f1783002810ddbf10f95e1af9b48b2912fb169f46994", + "license": "MIT" + } + ] } diff --git a/tests/test_image.py b/tests/test_image.py index b50e7df..e68507b 100644 --- a/tests/test_image.py +++ b/tests/test_image.py @@ -298,6 +298,25 @@ class ImageBuildTests(unittest.TestCase): self.builder.rootfs() self.assertFalse(self.builder.manifest()['rootfs']['complete']) + def test_corrupt_local_package_archive_invalidates_fetch_checkpoint(self): + import hashlib + source = self.project / 'image' + source.mkdir() + (source / 'sources.json').write_text(json.dumps({ + 'stage3': {'url': 'https://example.test/stage.tar', 'sha256': hashlib.sha256(b'stage').hexdigest()}, + 'portage': {'url': 'https://example.test/repo.tar', 'sha256': hashlib.sha256(b'repo').hexdigest()}, + 'local_packages': [{'url': 'https://example.test/brightnessctl.tar.gz', + 'filename': 'brightnessctl.tar.gz', 'sha256': hashlib.sha256(b'original-source').hexdigest()}]})) + with self.builder.locked(): + (self.builder.cache / 'stage.tar').write_bytes(b'stage') + (self.builder.cache / 'repo.tar').write_bytes(b'repo') + archive = self.builder.cache / 'brightnessctl.tar.gz' + archive.write_bytes(b'original-source') + self.builder.record('fetch') + self.assertTrue(self.builder.complete('fetch')) + archive.write_bytes(b'corrupted-source') + self.assertFalse(self.builder.complete('fetch')) + def test_changed_canonical_patch_invalidates_package_input_identity(self): patches = self.project / 'patches' patches.mkdir()