1 |
This patch allows to set the compressor for binary packages via a |
2 |
BINPKG_COMPRESSION variable. BINPKG_COMPRESSION_ARGS allows to specify |
3 |
command-line arguments for the chosen compressor. |
4 |
--- |
5 |
bin/misc-functions.sh | 6 ++- |
6 |
bin/quickpkg | 62 ++++++++++++++++------ |
7 |
man/make.conf.5 | 25 +++++++++ |
8 |
pym/_emerge/BinpkgExtractorAsync.py | 43 +++++++++++++-- |
9 |
pym/portage/dbapi/bintree.py | 8 +-- |
10 |
.../package/ebuild/_config/special_env_vars.py | 2 +- |
11 |
pym/portage/package/ebuild/doebuild.py | 34 ++++++++++-- |
12 |
pym/portage/util/compression_probe.py | 45 +++++++++++++--- |
13 |
8 files changed, 186 insertions(+), 39 deletions(-) |
14 |
|
15 |
diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh |
16 |
index 58755a1e1..079369313 100755 |
17 |
--- a/bin/misc-functions.sh |
18 |
+++ b/bin/misc-functions.sh |
19 |
@@ -453,7 +453,7 @@ __dyn_package() { |
20 |
# Make sure $PWD is not ${D} so that we don't leave gmon.out files |
21 |
# in there in case any tools were built with -pg in CFLAGS. |
22 |
|
23 |
- cd "${T}" |
24 |
+ cd "${T}" || die |
25 |
|
26 |
if [[ -n ${PKG_INSTALL_MASK} ]] ; then |
27 |
PROOT=${T}/packaging/ |
28 |
@@ -478,8 +478,10 @@ __dyn_package() { |
29 |
[ -z "${PORTAGE_BINPKG_TMPFILE}" ] && \ |
30 |
die "PORTAGE_BINPKG_TMPFILE is unset" |
31 |
mkdir -p "${PORTAGE_BINPKG_TMPFILE%/*}" || die "mkdir failed" |
32 |
+ [ -z "${PORTAGE_COMPRESSION_COMMAND}" ] && \ |
33 |
+ die "PORTAGE_COMPRESSION_COMMAND is unset" |
34 |
tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS -C "${PROOT}" . | \ |
35 |
- $PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_BINPKG_TMPFILE" |
36 |
+ $PORTAGE_COMPRESSION_COMMAND -c > "$PORTAGE_BINPKG_TMPFILE" |
37 |
assert "failed to pack binary package: '$PORTAGE_BINPKG_TMPFILE'" |
38 |
PYTHONPATH=${PORTAGE_PYTHONPATH:-${PORTAGE_PYM_PATH}} \ |
39 |
"${PORTAGE_PYTHON:-/usr/bin/python}" "$PORTAGE_BIN_PATH"/xpak-helper.py recompose \ |
40 |
diff --git a/bin/quickpkg b/bin/quickpkg |
41 |
index 4f26ee912..750400592 100755 |
42 |
--- a/bin/quickpkg |
43 |
+++ b/bin/quickpkg |
44 |
@@ -8,6 +8,7 @@ import argparse |
45 |
import errno |
46 |
import math |
47 |
import signal |
48 |
+import subprocess |
49 |
import sys |
50 |
import tarfile |
51 |
|
52 |
@@ -22,11 +23,13 @@ from portage.dbapi.dep_expand import dep_expand |
53 |
from portage.dep import Atom, use_reduce |
54 |
from portage.exception import (AmbiguousPackageName, InvalidAtom, InvalidData, |
55 |
InvalidDependString, PackageSetNotFound, PermissionDenied) |
56 |
-from portage.util import ConfigProtect, ensure_dirs, shlex_split, _xattr |
57 |
+from portage.util import ConfigProtect, ensure_dirs, shlex_split, varexpand, _xattr |
58 |
xattr = _xattr.xattr |
59 |
from portage.dbapi.vartree import dblink, tar_contents |
60 |
from portage.checksum import perform_md5 |
61 |
from portage._sets import load_default_config, SETPREFIX |
62 |
+from portage.process import find_binary |
63 |
+from portage.util.compression_probe import _compressors |
64 |
|
65 |
def quickpkg_atom(options, infos, arg, eout): |
66 |
settings = portage.settings |
67 |
@@ -50,16 +53,16 @@ def quickpkg_atom(options, infos, arg, eout): |
68 |
" ".join(e.args[0])) |
69 |
del e |
70 |
infos["missing"].append(arg) |
71 |
- return |
72 |
+ return 1 |
73 |
except (InvalidAtom, InvalidData): |
74 |
eout.eerror("Invalid atom: %s" % (arg,)) |
75 |
infos["missing"].append(arg) |
76 |
- return |
77 |
+ return 1 |
78 |
if atom[:1] == '=' and arg[:1] != '=': |
79 |
# dep_expand() allows missing '=' but it's really invalid |
80 |
eout.eerror("Invalid atom: %s" % (arg,)) |
81 |
infos["missing"].append(arg) |
82 |
- return |
83 |
+ return 1 |
84 |
|
85 |
matches = vardb.match(atom) |
86 |
pkgs_for_arg = 0 |
87 |
@@ -108,16 +111,16 @@ def quickpkg_atom(options, infos, arg, eout): |
88 |
in settings.features)) |
89 |
def protect(filename): |
90 |
if not confprot.isprotected(filename): |
91 |
- return False |
92 |
+ return 1 |
93 |
if include_unmodified_config: |
94 |
file_data = contents[filename] |
95 |
if file_data[0] == "obj": |
96 |
orig_md5 = file_data[2].lower() |
97 |
cur_md5 = perform_md5(filename, calc_prelink=1) |
98 |
if orig_md5 == cur_md5: |
99 |
- return False |
100 |
+ return 1 |
101 |
excluded_config_files.append(filename) |
102 |
- return True |
103 |
+ return os.EX_OK |
104 |
existing_metadata = dict(zip(fix_metadata_keys, |
105 |
vardb.aux_get(cpv, fix_metadata_keys))) |
106 |
category, pf = portage.catsplit(cpv) |
107 |
@@ -134,12 +137,32 @@ def quickpkg_atom(options, infos, arg, eout): |
108 |
binpkg_tmpfile = os.path.join(bintree.pkgdir, |
109 |
cpv + ".tbz2." + str(os.getpid())) |
110 |
ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
111 |
- # The tarfile module will write pax headers holding the |
112 |
- # xattrs only if PAX_FORMAT is specified here. |
113 |
- tar = tarfile.open(binpkg_tmpfile, "w:bz2", |
114 |
- format=tarfile.PAX_FORMAT if xattrs else tarfile.DEFAULT_FORMAT) |
115 |
- tar_contents(contents, root, tar, protect=protect, xattrs=xattrs) |
116 |
- tar.close() |
117 |
+ binpkg_compression = settings.get("BINPKG_COMPRESSION", "bzip2") |
118 |
+ try: |
119 |
+ compression = _compressors[binpkg_compression] |
120 |
+ except KeyError as e: |
121 |
+ eout.eerror("Invalid or unsupported compression method: %s" % e.args[0]) |
122 |
+ return 1 |
123 |
+ try: |
124 |
+ compression_binary = shlex_split(varexpand(compression["compress"], mydict=settings))[0] |
125 |
+ except IndexError as e: |
126 |
+ eout.eerror("Invalid or unsupported compression method: %s" % e.args[0]) |
127 |
+ return 1 |
128 |
+ if find_binary(compression_binary) is None: |
129 |
+ missing_package = compression["package"] |
130 |
+ eout.eerror("File compression unsupported %s. Missing package: %s" % (binpkg_compression, missing_package)) |
131 |
+ return 1 |
132 |
+ cmd = [varexpand(x, mydict=settings) for x in shlex_split(compression["compress"])] |
133 |
+ # Filter empty elements that make Popen fail |
134 |
+ cmd = [x for x in cmd if x != ""] |
135 |
+ with open(binpkg_tmpfile, "wb") as fobj: |
136 |
+ proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=fobj) |
137 |
+ # The tarfile module will write pax headers holding the |
138 |
+ # xattrs only if PAX_FORMAT is specified here. |
139 |
+ with tarfile.open(mode="w|",format=tarfile.PAX_FORMAT if xattrs else tarfile.DEFAULT_FORMAT, fileobj=proc.stdin) as tar: |
140 |
+ tar_contents(contents, root, tar, protect=protect, xattrs=xattrs) |
141 |
+ proc.stdin.close() |
142 |
+ proc.wait() |
143 |
xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata) |
144 |
finally: |
145 |
if have_lock: |
146 |
@@ -154,16 +177,20 @@ def quickpkg_atom(options, infos, arg, eout): |
147 |
eout.eerror(str(e)) |
148 |
del e |
149 |
eout.eerror("Failed to create package: '%s'" % binpkg_path) |
150 |
+ return 1 |
151 |
else: |
152 |
eout.eend(0) |
153 |
infos["successes"].append((cpv, s.st_size)) |
154 |
infos["config_files_excluded"] += len(excluded_config_files) |
155 |
for filename in excluded_config_files: |
156 |
eout.ewarn("Excluded config: '%s'" % filename) |
157 |
+ return os.EX_OK |
158 |
if not pkgs_for_arg: |
159 |
eout.eerror("Could not find anything " + \ |
160 |
"to match '%s'; skipping" % arg) |
161 |
infos["missing"].append(arg) |
162 |
+ return 1 |
163 |
+ return os.EX_OK |
164 |
|
165 |
def quickpkg_set(options, infos, arg, eout): |
166 |
eroot = portage.settings['EROOT'] |
167 |
@@ -179,7 +206,7 @@ def quickpkg_set(options, infos, arg, eout): |
168 |
if not set in sets: |
169 |
eout.eerror("Package set not found: '%s'; skipping" % (arg,)) |
170 |
infos["missing"].append(arg) |
171 |
- return |
172 |
+ return 1 |
173 |
|
174 |
try: |
175 |
atoms = setconfig.getSetAtoms(set) |
176 |
@@ -187,10 +214,11 @@ def quickpkg_set(options, infos, arg, eout): |
177 |
eout.eerror("Failed to process package set '%s' because " % set + |
178 |
"it contains the non-existent package set '%s'; skipping" % e) |
179 |
infos["missing"].append(arg) |
180 |
- return |
181 |
- |
182 |
+ return 1 |
183 |
+ retval = os.EX_OK |
184 |
for atom in atoms: |
185 |
- quickpkg_atom(options, infos, atom, eout) |
186 |
+ retval |= quickpkg_atom(options, infos, atom, eout) |
187 |
+ return retval |
188 |
|
189 |
|
190 |
def quickpkg_extended_atom(options, infos, atom, eout): |
191 |
diff --git a/man/make.conf.5 b/man/make.conf.5 |
192 |
index aea189e4a..8e0d04967 100644 |
193 |
--- a/man/make.conf.5 |
194 |
+++ b/man/make.conf.5 |
195 |
@@ -110,6 +110,31 @@ ACCEPT_RESTRICT="*" |
196 |
ACCEPT_RESTRICT="* -bindist" |
197 |
.fi |
198 |
.TP |
199 |
+\fBBINPKG_COMPRESSION\fR = \fI"compression"\fR |
200 |
+This variable is used to determine the compression used for \fIbinary |
201 |
+packages\fR. Supported settings and compression algorithms are: bzip2, gzip, |
202 |
+lz4, lzip, lzop, xz, zstd. |
203 |
+.br |
204 |
+Defaults to "bzip2". |
205 |
+.br |
206 |
+.I Example: |
207 |
+.nf |
208 |
+# Set it to use lz4: |
209 |
+BINPKG_COMPRESSION="lz4" |
210 |
+.fi |
211 |
+.TP |
212 |
+\fBBINPKG_COMPRESSION_ARGS\fR = \fI"arguments for compression command"\fR |
213 |
+This variable is used to add additional arguments to the compression command |
214 |
+selected by \fBBINPKG_COMPRESSION\fR. |
215 |
+.br |
216 |
+Defaults to "". |
217 |
+.br |
218 |
+.I Example: |
219 |
+.nf |
220 |
+# Set it to use compression level 9: |
221 |
+BINPKG_COMPRESSION_ARGS="-9" |
222 |
+.fi |
223 |
+.TP |
224 |
.B CBUILD |
225 |
This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR |
226 |
as \fI\-\-build=${CBUILD}\fR only if it is defined. Do not set this yourself |
227 |
diff --git a/pym/_emerge/BinpkgExtractorAsync.py b/pym/_emerge/BinpkgExtractorAsync.py |
228 |
index 0bf3c74c9..e85f4ecac 100644 |
229 |
--- a/pym/_emerge/BinpkgExtractorAsync.py |
230 |
+++ b/pym/_emerge/BinpkgExtractorAsync.py |
231 |
@@ -6,8 +6,15 @@ import logging |
232 |
from _emerge.SpawnProcess import SpawnProcess |
233 |
import portage |
234 |
from portage.localization import _ |
235 |
-from portage.util.compression_probe import (compression_probe, |
236 |
- _decompressors) |
237 |
+from portage.util.compression_probe import ( |
238 |
+ compression_probe, |
239 |
+ _compressors, |
240 |
+) |
241 |
+from portage.process import find_binary |
242 |
+from portage.util import ( |
243 |
+ shlex_split, |
244 |
+ varexpand, |
245 |
+) |
246 |
import signal |
247 |
import subprocess |
248 |
|
249 |
@@ -28,8 +35,11 @@ class BinpkgExtractorAsync(SpawnProcess): |
250 |
tar_options.append(portage._shell_quote("--xattrs-exclude=%s" % x)) |
251 |
tar_options = " ".join(tar_options) |
252 |
|
253 |
- decomp_cmd = _decompressors.get( |
254 |
- compression_probe(self.pkg_path)) |
255 |
+ decomp = _compressors.get(compression_probe(self.pkg_path)) |
256 |
+ if decomp is not None: |
257 |
+ decomp_cmd = decomp.get("decompress") |
258 |
+ else: |
259 |
+ decomp_cmd = None |
260 |
if decomp_cmd is None: |
261 |
self.scheduler.output("!!! %s\n" % |
262 |
_("File compression header unrecognized: %s") % |
263 |
@@ -39,6 +49,31 @@ class BinpkgExtractorAsync(SpawnProcess): |
264 |
self._async_wait() |
265 |
return |
266 |
|
267 |
+ try: |
268 |
+ decompression_binary = shlex_split(varexpand(decomp_cmd, mydict=self.env))[0] |
269 |
+ except IndexError: |
270 |
+ decompression_binary = "" |
271 |
+ |
272 |
+ if find_binary(decompression_binary) is None: |
273 |
+ # Try alternative command if it exists |
274 |
+ if _compressors.get(compression_probe(self.pkg_path)).get("decompress_alt"): |
275 |
+ decomp_cmd = _compressors.get( |
276 |
+ compression_probe(self.pkg_path)).get("decompress_alt") |
277 |
+ try: |
278 |
+ decompression_binary = shlex_split(varexpand(decomp_cmd, mydict=self.env))[0] |
279 |
+ except IndexError: |
280 |
+ decompression_binary = "" |
281 |
+ |
282 |
+ if find_binary(decompression_binary) is None: |
283 |
+ missing_package = _compressors.get(compression_probe(self.pkg_path)).get("package") |
284 |
+ self.scheduler.output("!!! %s\n" % |
285 |
+ _("File compression unsupported %s.\n Command was: %s.\n Maybe missing package: %s") % |
286 |
+ (self.pkg_path, varexpand(decomp_cmd, mydict=self.env), missing_package), log_path=self.logfile, |
287 |
+ background=self.background, level=logging.ERROR) |
288 |
+ self.returncode = 1 |
289 |
+ self._async_wait() |
290 |
+ return |
291 |
+ |
292 |
# Add -q to decomp_cmd opts, in order to avoid "trailing garbage |
293 |
# after EOF ignored" warning messages due to xpak trailer. |
294 |
# SIGPIPE handling (128 + SIGPIPE) should be compatible with |
295 |
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py |
296 |
index ca90ba8f9..c833968c2 100644 |
297 |
--- a/pym/portage/dbapi/bintree.py |
298 |
+++ b/pym/portage/dbapi/bintree.py |
299 |
@@ -141,7 +141,6 @@ class bindbapi(fakedbapi): |
300 |
return [aux_cache.get(x, "") for x in wants] |
301 |
mysplit = mycpv.split("/") |
302 |
mylist = [] |
303 |
- tbz2name = mysplit[1]+".tbz2" |
304 |
if not self.bintree._remotepkgs or \ |
305 |
not self.bintree.isremote(mycpv): |
306 |
try: |
307 |
@@ -1448,9 +1447,10 @@ class binarytree(object): |
308 |
@staticmethod |
309 |
def _parse_build_id(filename): |
310 |
build_id = -1 |
311 |
- hyphen = filename.rfind("-", 0, -6) |
312 |
+ suffixlen = len(".xpak") |
313 |
+ hyphen = filename.rfind("-", 0, -(suffixlen + 1)) |
314 |
if hyphen != -1: |
315 |
- build_id = filename[hyphen+1:-5] |
316 |
+ build_id = filename[hyphen+1:-suffixlen] |
317 |
try: |
318 |
build_id = long(build_id) |
319 |
except ValueError: |
320 |
@@ -1497,7 +1497,7 @@ class binarytree(object): |
321 |
if self._remote_has_index: |
322 |
rel_url = self._remotepkgs[instance_key].get("PATH") |
323 |
if not rel_url: |
324 |
- rel_url = pkgname+".tbz2" |
325 |
+ rel_url = pkgname + ".tbz2" |
326 |
remote_base_uri = self._remotepkgs[instance_key]["BASE_URI"] |
327 |
url = remote_base_uri.rstrip("/") + "/" + rel_url.lstrip("/") |
328 |
else: |
329 |
diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py |
330 |
index f7810e007..f9b29af93 100644 |
331 |
--- a/pym/portage/package/ebuild/_config/special_env_vars.py |
332 |
+++ b/pym/portage/package/ebuild/_config/special_env_vars.py |
333 |
@@ -56,7 +56,7 @@ environ_whitelist += [ |
334 |
"PORTAGE_BIN_PATH", |
335 |
"PORTAGE_BUILDDIR", "PORTAGE_BUILD_GROUP", "PORTAGE_BUILD_USER", |
336 |
"PORTAGE_BUNZIP2_COMMAND", "PORTAGE_BZIP2_COMMAND", |
337 |
- "PORTAGE_COLORMAP", "PORTAGE_COMPRESS", |
338 |
+ "PORTAGE_COLORMAP", "PORTAGE_COMPRESS", "PORTAGE_COMPRESSION_COMMAND", |
339 |
"PORTAGE_COMPRESS_EXCLUDE_SUFFIXES", |
340 |
"PORTAGE_CONFIGROOT", "PORTAGE_DEBUG", "PORTAGE_DEPCACHEDIR", |
341 |
"PORTAGE_DOHTML_UNWARNED_SKIPPED_EXTENSIONS", |
342 |
diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py |
343 |
index e7db54bcf..3e75d1a51 100644 |
344 |
--- a/pym/portage/package/ebuild/doebuild.py |
345 |
+++ b/pym/portage/package/ebuild/doebuild.py |
346 |
@@ -68,11 +68,19 @@ from portage.exception import (DigestException, FileNotFound, |
347 |
from portage.localization import _ |
348 |
from portage.output import colormap |
349 |
from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs |
350 |
-from portage.util import apply_recursive_permissions, \ |
351 |
- apply_secpass_permissions, noiselimit, \ |
352 |
- writemsg, writemsg_stdout, write_atomic |
353 |
+from portage.process import find_binary |
354 |
+from portage.util import ( apply_recursive_permissions, |
355 |
+ apply_secpass_permissions, |
356 |
+ noiselimit, |
357 |
+ shlex_split, |
358 |
+ varexpand, |
359 |
+ writemsg, |
360 |
+ writemsg_stdout, |
361 |
+ write_atomic |
362 |
+ ) |
363 |
from portage.util.cpuinfo import get_cpu_count |
364 |
from portage.util.lafilefixer import rewrite_lafile |
365 |
+from portage.util.compression_probe import _compressors |
366 |
from portage.util.socks5 import get_socks5_proxy |
367 |
from portage.versions import _pkgsplit |
368 |
from _emerge.BinpkgEnvExtractor import BinpkgEnvExtractor |
369 |
@@ -518,6 +526,26 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, |
370 |
mysettings["KV"] = "" |
371 |
mysettings.backup_changes("KV") |
372 |
|
373 |
+ binpkg_compression = mysettings.get("BINPKG_COMPRESSION", "bzip2") |
374 |
+ try: |
375 |
+ compression = _compressors[binpkg_compression] |
376 |
+ except KeyError as e: |
377 |
+ writemsg("Warning: Invalid or unsupported compression method: %s" % e.args[0]) |
378 |
+ else: |
379 |
+ try: |
380 |
+ compression_binary = shlex_split(varexpand(compression["compress"], mydict=settings))[0] |
381 |
+ except IndexError as e: |
382 |
+ writemsg("Warning: Invalid or unsupported compression method: %s" % e.args[0]) |
383 |
+ else: |
384 |
+ if find_binary(compression_binary) is None: |
385 |
+ missing_package = compression["package"] |
386 |
+ writemsg("Warning: File compression unsupported %s. Missing package: %s" % (binpkg_compression, missing_package)) |
387 |
+ else: |
388 |
+ cmd = [varexpand(x, mydict=settings) for x in shlex_split(compression["compress"])] |
389 |
+ # Filter empty elements |
390 |
+ cmd = [x for x in cmd if x != ""] |
391 |
+ mysettings['PORTAGE_COMPRESSION_COMMAND'] = ' '.join(cmd) |
392 |
+ |
393 |
_doebuild_manifest_cache = None |
394 |
_doebuild_broken_ebuilds = set() |
395 |
_doebuild_broken_manifests = set() |
396 |
diff --git a/pym/portage/util/compression_probe.py b/pym/portage/util/compression_probe.py |
397 |
index 754621016..b15200044 100644 |
398 |
--- a/pym/portage/util/compression_probe.py |
399 |
+++ b/pym/portage/util/compression_probe.py |
400 |
@@ -11,14 +11,43 @@ if sys.hexversion >= 0x3000000: |
401 |
from portage import _encodings, _unicode_encode |
402 |
from portage.exception import FileNotFound, PermissionDenied |
403 |
|
404 |
-_decompressors = { |
405 |
- "bzip2": "${PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d}", |
406 |
- "gzip": "gzip -d", |
407 |
- "lz4": "lz4 -d", |
408 |
- "lzip": "lzip -d", |
409 |
- "lzop": "lzop -d", |
410 |
- "xz": "xz -d", |
411 |
- "zstd": "zstd -d", |
412 |
+_compressors = { |
413 |
+ "bzip2": { |
414 |
+ "compress": "${PORTAGE_BZIP2_COMMAND} ${BINPKG_COMPRESSION_ARGS}", |
415 |
+ "decompress": "${PORTAGE_BUNZIP2_COMMAND}", |
416 |
+ "decompress_alt": "${PORTAGE_BZIP2_COMMAND} -d", |
417 |
+ "package": "app-arch/bzip2", |
418 |
+ }, |
419 |
+ "gzip": { |
420 |
+ "compress": "gzip ${BINPKG_COMPRESSION_ARGS}", |
421 |
+ "decompress": "gzip -d", |
422 |
+ "package": "app-arch/gzip", |
423 |
+ }, |
424 |
+ "lz4": { |
425 |
+ "compress": "lz4 ${BINPKG_COMPRESSION_ARGS}", |
426 |
+ "decompress": "lz4 -d", |
427 |
+ "package": "app-arch/lz4", |
428 |
+ }, |
429 |
+ "lzip": { |
430 |
+ "compress": "lzip ${BINPKG_COMPRESSION_ARGS}", |
431 |
+ "decompress": "lzip -d", |
432 |
+ "package": "app-arch/lzip", |
433 |
+ }, |
434 |
+ "lzop": { |
435 |
+ "compress": "lzop ${BINPKG_COMPRESSION_ARGS}", |
436 |
+ "decompress": "lzop -d", |
437 |
+ "package": "app-arch/lzop", |
438 |
+ }, |
439 |
+ "xz": { |
440 |
+ "compress": "xz ${BINPKG_COMPRESSION_ARGS}", |
441 |
+ "decompress": "xz -d", |
442 |
+ "package": "app-arch/xz-utils", |
443 |
+ }, |
444 |
+ "zstd": { |
445 |
+ "compress": "zstd ${BINPKG_COMPRESSION_ARGS}", |
446 |
+ "decompress": "zstd -d", |
447 |
+ "package": "app-arch/zstd", |
448 |
+ }, |
449 |
} |
450 |
|
451 |
_compression_re = re.compile(b'^(' + |
452 |
-- |
453 |
2.13.3 |