Gentoo Archives: gentoo-commits

From: "Michał Górny" <mgorny@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/, bin/, /
Date: Fri, 09 Sep 2022 10:16:39
Message-Id: 1662718558.020feffb39cd6c4c68a4a81be6ccd2426b062e8d.mgorny@gentoo
1 commit: 020feffb39cd6c4c68a4a81be6ccd2426b062e8d
2 Author: Sheng Yu <syu.os <AT> protonmail <DOT> com>
3 AuthorDate: Fri Aug 19 20:40:59 2022 +0000
4 Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
5 CommitDate: Fri Sep 9 10:15:58 2022 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=020feffb
7
8 Add gpkg-sign tool to sign exist GPKG files.
9
10 Signed-off-by: Sheng Yu <syu.os <AT> protonmail.com>
11 Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
12
13 bin/gpkg-sign | 68 +++++++++++++++++++++++++++++++++++++++++++++++++
14 lib/portage/gpkg.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
15 setup.py | 1 +
16 3 files changed, 142 insertions(+)
17
18 diff --git a/bin/gpkg-sign b/bin/gpkg-sign
19 new file mode 100755
20 index 000000000..57fc6ce98
21 --- /dev/null
22 +++ b/bin/gpkg-sign
23 @@ -0,0 +1,68 @@
24 +#!/usr/bin/env python
25 +# Copyright 1999-2022 Gentoo Authors
26 +# Distributed under the terms of the GNU General Public License v2
27 +
28 +import argparse
29 +import sys
30 +
31 +import portage
32 +import portage.exception
33 +
34 +portage._internal_caller = True
35 +from portage import gpkg
36 +
37 +
38 +def main(
39 + gpkg_file, keep_current_signature=False, allow_unsigned=False, skip_signed=False
40 +):
41 + eout = portage.output.EOutput()
42 + try:
43 + package = gpkg.gpkg(settings=portage.settings, gpkg_file=gpkg_file)
44 + if allow_unsigned:
45 + package.request_signature = False
46 + package._verify_binpkg()
47 + if skip_signed and package.signature_exist:
48 + eout.einfo(f"{gpkg_file} already signed, skipping.")
49 + return
50 + package.update_signature(keep_current_signature=keep_current_signature)
51 + eout.einfo(f"{gpkg_file} signed.")
52 + except portage.exception.FileNotFound:
53 + eout.eerror(f"File not found: {gpkg_file}")
54 + exit(1)
55 + except portage.exception.InvalidBinaryPackageFormat:
56 + eout.eerror(f"Invalid binary package format: {gpkg_file}")
57 + exit(1)
58 + except portage.exception.SignatureException:
59 + eout.eerror(f"Signature exception: {gpkg_file}")
60 + exit(1)
61 +
62 +
63 +if __name__ == "__main__":
64 + usage = "gpkg-sign [options] <gpkg package file>"
65 + parser = argparse.ArgumentParser(usage=usage)
66 + parser.add_argument(
67 + "--keep-current-signature",
68 + action="store_true",
69 + help="Keep existing signature when updating signature (default: false)",
70 + )
71 + parser.add_argument(
72 + "--allow-unsigned",
73 + action="store_true",
74 + help="Allow signing from unsigned packages when binpkg-request-signature is enabled (default: false)",
75 + )
76 + parser.add_argument(
77 + "--skip-signed",
78 + action="store_true",
79 + help="Skip signing if a package is already signed (default: false)",
80 + )
81 + options, args = parser.parse_known_args(sys.argv[1:])
82 +
83 + if not args:
84 + parser.error("no GPKG oackage file specified")
85 +
86 + main(
87 + args[0],
88 + keep_current_signature=options.keep_current_signature,
89 + allow_unsigned=options.allow_unsigned,
90 + skip_signed=options.skip_signed,
91 + )
92
93 diff --git a/lib/portage/gpkg.py b/lib/portage/gpkg.py
94 index 303773616..644ff412b 100644
95 --- a/lib/portage/gpkg.py
96 +++ b/lib/portage/gpkg.py
97 @@ -781,6 +781,7 @@ class gpkg:
98 self.base_name = base_name
99 self.checksums = []
100 self.manifest_old = []
101 + signature_exist = None
102
103 # Compression is the compression algorithm, if set to None will
104 # not use compression.
105 @@ -1118,6 +1119,77 @@ class gpkg:
106
107 shutil.move(tmp_gpkg_file_name, self.gpkg_file)
108
109 + def update_signature(self, keep_current_signature=False):
110 + """
111 + Add / update signature in the gpkg file.
112 + if keep_current_signature is True, keep the current signature, otherwise, re-signing it.
113 + """
114 + self.create_signature = True
115 + self._verify_binpkg()
116 + self.checksums = []
117 +
118 + with open(self.gpkg_file, "rb") as container:
119 + container_tar_format = self._get_tar_format(container)
120 + if container_tar_format is None:
121 + raise InvalidBinaryPackageFormat("Cannot identify tar format")
122 +
123 + # container
124 + tmp_gpkg_file_name = f"{self.gpkg_file}.{os.getpid()}"
125 + with tarfile.TarFile(
126 + name=tmp_gpkg_file_name, mode="w", format=container_tar_format
127 + ) as container:
128 + # gpkg version
129 + gpkg_version_file = tarfile.TarInfo(self.gpkg_version)
130 + gpkg_version_file.mtime = datetime.utcnow().timestamp()
131 + container.addfile(gpkg_version_file)
132 +
133 + # reuse other stuffs
134 + with tarfile.open(self.gpkg_file, "r") as container_old:
135 + manifest_old = self.manifest_old.copy()
136 + file_list_old = [f[1] for f in manifest_old]
137 +
138 + for m in manifest_old:
139 + file_name_old = m[1]
140 + if os.path.basename(file_name_old).endswith(".sig"):
141 + continue
142 + old_data_tarinfo = container_old.getmember(file_name_old)
143 + new_data_tarinfo = copy(old_data_tarinfo)
144 +
145 + container.addfile(
146 + new_data_tarinfo, container_old.extractfile(old_data_tarinfo)
147 + )
148 + self.checksums.append(m)
149 +
150 + # Check if signature file exists and reuse or create new one.
151 + if keep_current_signature and (
152 + file_name_old + ".sig" in file_list_old
153 + ):
154 + old_data_sign_tarinfo = container_old.getmember(
155 + file_name_old + ".sig"
156 + )
157 + new_data_sign_tarinfo = copy(old_data_sign_tarinfo)
158 + container.addfile(
159 + new_data_sign_tarinfo,
160 + container_old.extractfile(old_data_sign_tarinfo),
161 + )
162 + for manifest_sign in manifest_old:
163 + if manifest_sign[1] == file_name_old + ".sig":
164 + self.checksums.append(manifest_sign)
165 + break
166 + else:
167 + checksum_info = checksum_helper(
168 + self.settings, gpg_operation=checksum_helper.SIGNING
169 + )
170 + checksum_info.update(
171 + container_old.extractfile(old_data_tarinfo).read()
172 + )
173 + checksum_info.finish()
174 + self._add_signature(checksum_info, new_data_tarinfo, container)
175 +
176 + self._add_manifest(container)
177 +
178 + shutil.move(tmp_gpkg_file_name, self.gpkg_file)
179 +
180 def _add_metadata(self, container, metadata, compression_cmd):
181 """
182 add metadata to container
183 @@ -1611,6 +1683,7 @@ class gpkg:
184
185 # Save current Manifest for other operations.
186 self.manifest_old = manifest.copy()
187 + self.signature_exist = signature_exist
188
189 def _generate_metadata_from_dir(self, metadata_dir):
190 """
191
192 diff --git a/setup.py b/setup.py
193 index 8ed507d16..e65963e49 100755
194 --- a/setup.py
195 +++ b/setup.py
196 @@ -66,6 +66,7 @@ x_scripts = {
197 "bin/glsa-check",
198 "bin/portageq",
199 "bin/quickpkg",
200 + "bin/gpkg-sign",
201 ],
202 "sbin": [
203 "bin/archive-conf",