1 |
On Fri, 16 Jan 2015 00:30:31 -0800 |
2 |
Zac Medico <zmedico@g.o> wrote: |
3 |
|
4 |
> This adds support for using a binary package's compression header to |
5 |
> determine the compression type, providing forward-compatibility for |
6 |
> xz and gzip decompression. The file name extension is disregared, so |
7 |
> that it will be possible to use a compression-independent file naming |
8 |
> scheme in the future (see bug #150031 for discussion about proposed |
9 |
> file naming schemes). |
10 |
> |
11 |
> Currently, only decompression is supported. It's useful to provide |
12 |
> forward-compatibility now, so that binhost clients will be prepared |
13 |
> to handle future binhost servers that use xz or gzip compression. |
14 |
> |
15 |
> X-Gentoo-Bug: 142579 |
16 |
> X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=142579 |
17 |
> --- |
18 |
|
19 |
|
20 |
oooh, now that is sooooooo much better :D |
21 |
|
22 |
Merge approved! |
23 |
|
24 |
|
25 |
(P.S. too pretty to erase the code below ;) |
26 |
|
27 |
|
28 |
|
29 |
> pym/_emerge/BinpkgExtractorAsync.py | 25 ++++++++++--- |
30 |
> pym/portage/util/compression_probe.py | 68 |
31 |
> +++++++++++++++++++++++++++++++++++ 2 files changed, 89 |
32 |
> insertions(+), 4 deletions(-) create mode 100644 |
33 |
> pym/portage/util/compression_probe.py |
34 |
> |
35 |
> diff --git a/pym/_emerge/BinpkgExtractorAsync.py |
36 |
> b/pym/_emerge/BinpkgExtractorAsync.py index be74c2f..6aaa448 100644 |
37 |
> --- a/pym/_emerge/BinpkgExtractorAsync.py |
38 |
> +++ b/pym/_emerge/BinpkgExtractorAsync.py |
39 |
> @@ -1,8 +1,13 @@ |
40 |
> # Copyright 1999-2013 Gentoo Foundation |
41 |
> # Distributed under the terms of the GNU General Public License v2 |
42 |
> |
43 |
> +import logging |
44 |
> + |
45 |
> from _emerge.SpawnProcess import SpawnProcess |
46 |
> import portage |
47 |
> +from portage.localization import _ |
48 |
> +from portage.util.compression_probe import (compression_probe, |
49 |
> + _decompressors) |
50 |
> import signal |
51 |
> import subprocess |
52 |
> |
53 |
> @@ -20,19 +25,31 @@ class BinpkgExtractorAsync(SpawnProcess): |
54 |
> if b"--xattrs" in output: |
55 |
> tar_options = "--xattrs" |
56 |
> |
57 |
> - # Add -q to bzip2 opts, in order to avoid "trailing |
58 |
> garbage after |
59 |
> - # EOF ignored" warning messages due to xpak trailer. |
60 |
> + decomp_cmd = _decompressors.get( |
61 |
> + compression_probe(self.pkg_path)) |
62 |
> + if decomp_cmd is None: |
63 |
> + self.scheduler.output("!!! %s\n" % |
64 |
> + _("File compression header |
65 |
> unrecognized: %s") % |
66 |
> + self.pkg_path, log_path=self.logfile, |
67 |
> + background=self.background, |
68 |
> level=logging.ERROR) |
69 |
> + self.returncode = 1 |
70 |
> + self._async_wait() |
71 |
> + return |
72 |
> + |
73 |
> + # Add -q to decomp_cmd opts, in order to avoid |
74 |
> "trailing garbage |
75 |
> + # after EOF ignored" warning messages due to xpak |
76 |
> trailer. # SIGPIPE handling (128 + SIGPIPE) should be compatible with |
77 |
> # assert_sigpipe_ok() that's used by the ebuild |
78 |
> unpack() helper. self.args = [self._shell_binary, "-c", |
79 |
> - |
80 |
> ("${PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d} -cq -- %s | |
81 |
> tar -xp %s -C %s -f - ; " + \ |
82 |
> + ("%s -cq -- %s | tar -xp %s -C %s -f - ; " + |
83 |
> \ "p=(${PIPESTATUS[@]}) ; " + \ |
84 |
> "if [[ ${p[0]} != 0 && ${p[0]} != %d ]] ; |
85 |
> then " % (128 + signal.SIGPIPE) + \ "echo bzip2 failed with status |
86 |
> ${p[0]} ; exit ${p[0]} ; fi ; " + \ "if [ ${p[1]} != 0 ] ; then " + \ |
87 |
> "echo tar failed with status ${p[1]} ; exit |
88 |
> ${p[1]} ; fi ; " + \ "exit 0 ;") % \ |
89 |
> - (portage._shell_quote(self.pkg_path), |
90 |
> + (decomp_cmd, |
91 |
> + portage._shell_quote(self.pkg_path), |
92 |
> tar_options, |
93 |
> portage._shell_quote(self.image_dir))] |
94 |
> |
95 |
> diff --git a/pym/portage/util/compression_probe.py |
96 |
> b/pym/portage/util/compression_probe.py new file mode 100644 |
97 |
> index 0000000..1dc3547 |
98 |
> --- /dev/null |
99 |
> +++ b/pym/portage/util/compression_probe.py |
100 |
> @@ -0,0 +1,68 @@ |
101 |
> +# Copyright 2015 Gentoo Foundation |
102 |
> +# Distributed under the terms of the GNU General Public License v2 |
103 |
> + |
104 |
> +import errno |
105 |
> +import re |
106 |
> +import sys |
107 |
> + |
108 |
> +if sys.hexversion >= 0x3000000: |
109 |
> + basestring = str |
110 |
> + |
111 |
> +from portage import _encodings, _unicode_encode |
112 |
> +from portage.exception import FileNotFound, PermissionDenied |
113 |
> + |
114 |
> +_decompressors = { |
115 |
> + "bzip2": |
116 |
> "${PORTAGE_BUNZIP2_COMMAND:-${PORTAGE_BZIP2_COMMAND} -d}", |
117 |
> + "gzip": "gzip -d", |
118 |
> + "xz": "xz -d", |
119 |
> +} |
120 |
> + |
121 |
> +_compression_re = re.compile(b'^(' + |
122 |
> + b'(?P<bzip2>\x42\x5a\x68\x39)|' + |
123 |
> + b'(?P<gzip>\x1f\x8b)|' + |
124 |
> + b'(?P<xz>\xfd\x37\x7a\x58\x5a\x00))') |
125 |
> + |
126 |
> +def compression_probe(f): |
127 |
> + """ |
128 |
> + Identify the compression type of a file. Returns one of the |
129 |
> + following identifier strings: |
130 |
> + |
131 |
> + bzip2 |
132 |
> + gzip |
133 |
> + xz |
134 |
> + |
135 |
> + @param f: a file path, or file-like object |
136 |
> + @type f: str or file |
137 |
> + @return: a string identifying the compression type, or None |
138 |
> if the |
139 |
> + compression type is unrecognized |
140 |
> + @rtype str or None |
141 |
> + """ |
142 |
> + |
143 |
> + open_file = isinstance(f, basestring) |
144 |
> + if open_file: |
145 |
> + try: |
146 |
> + f = open(_unicode_encode(f, |
147 |
> + encoding=_encodings['fs'], |
148 |
> errors='strict'), mode='rb') |
149 |
> + except IOError as e: |
150 |
> + if e.errno == PermissionDenied.errno: |
151 |
> + raise PermissionDenied(f) |
152 |
> + elif e.errno in (errno.ENOENT, errno.ESTALE): |
153 |
> + raise FileNotFound(f) |
154 |
> + else: |
155 |
> + raise |
156 |
> + |
157 |
> + try: |
158 |
> + return _compression_probe_file(f) |
159 |
> + finally: |
160 |
> + if open_file: |
161 |
> + f.close() |
162 |
> + |
163 |
> +def _compression_probe_file(f): |
164 |
> + |
165 |
> + m = _compression_re.match(f.read(6)) |
166 |
> + if m is not None: |
167 |
> + for k, v in m.groupdict().items(): |
168 |
> + if v is not None: |
169 |
> + return k |
170 |
> + |
171 |
> + return None |
172 |
|
173 |
|
174 |
|
175 |
-- |
176 |
Brian Dolbec <dolsen> |