Project

General

Profile

« Previous | Next » 

Revision 866922f8

Added by koszko over 1 year ago

properly handle percent-encoded characters in .deb file names

View differences:

src/hydrilla/builder/local_apt.py
35 35
from pathlib import Path, PurePosixPath
36 36
from tempfile import TemporaryDirectory, NamedTemporaryFile
37 37
from hashlib import sha256
38
from urllib.parse import unquote
38 39
from contextlib import contextmanager
39 40
from typing import Optional, Iterable
40 41

  
......
296 297

  
297 298
    Return value is a list of names of all downloaded files.
298 299
    """
300
    install_line_regex = re.compile(r'^Inst (?P<name>\S+) \((?P<version>\S+) ')
301

  
299 302
    with local_apt(list, keys) as apt:
300 303
        if with_deps:
301 304
            cp = apt.get('install', '--yes', '--just-print', *packages)
302 305

  
303
            deps_listing = re.match(
304
                r'''
305
                .*
306
                The\sfollowing\sNEW\spackages\swill\sbe\sinstalled:
307
                (.*)
308
                0\supgraded,
309
                ''',
310
                cp.stdout,
311
                re.MULTILINE | re.DOTALL | re.VERBOSE)
306
            lines = cp.stdout.split('\n')
307
            matches = [install_line_regex.match(l) for l in lines]
308
            packages = [f'{m.group("name")}={m.group("version")}'
309
                        for m in matches if m]
312 310

  
313
            if deps_listing is None:
311
            if not packages:
314 312
                raise AptError(_('apt_install_output_not_understood'), cp)
315 313

  
316
            packages = deps_listing.group(1).split()
317

  
318 314
        # Download .debs to indirectly to destination_dir by first placing them
319 315
        # in a temporary subdirectory.
320 316
        with TemporaryDirectory(dir=destination_dir) as td:
......
343 339
                        .format(deb_file.name)
344 340
                    raise AptError(msg, cp)
345 341

  
346
                names_vers.append((match.group('name'), match.group('ver')))
342
                names_vers.append((
343
                    unquote(match.group('name')),
344
                    unquote(match.group('ver'))
345
                ))
347 346
                downloaded.append(deb_file.name)
348 347

  
349 348
            apt.get('source', '--download-only',
tests/test_local_apt.py
128 128
The following NEW packages will be installed:
129 129
  fonts-mathjax libjs-mathjax
130 130
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
131
Inst fonts-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
132
Inst libjs-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
133
Conf fonts-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
134
Conf libjs-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
131
Inst fonts-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
132
Inst libjs-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
133
Conf fonts-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
134
Conf libjs-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
135 135
'''
136 136

  
137 137
def run_apt_get_install(command, returncode=0, **kwargs):
......
153 153
    Instead of running an 'apt-get download' command just write some dummy
154 154
    .deb to the appropriate directory.
155 155
    """
156
    expected = ['apt-get', '-c', '<conf_path>', 'download', 'libjs-mathjax']
157
    if 'fonts-mathjax' in command:
158
        expected.insert(-1, 'fonts-mathjax')
156
    expected = ['apt-get', '-c', '<conf_path>', 'download']
157
    if 'libjs-mathjax' in command:
158
        expected.append('libjs-mathjax')
159
    else:
160
        expected.append('fonts-mathjax=0:2.7.9+dfsg-1')
161
        expected.append('libjs-mathjax=0:2.7.9+dfsg-1')
159 162

  
160 163
    conf_path = Path(process_run_args(command, kwargs, expected)['conf_path'])
161 164

  
162 165
    destination = Path(kwargs.get('cwd') or Path.cwd())
163 166

  
167
    package_name_regex = re.compile(r'^[^=]+-mathjax')
168

  
164 169
    for word in expected:
165
        if word.endswith('-mathjax'):
166
            deb_path = destination / f'{word}_2.7.9+dfsg-1_all.deb'
170
        match = package_name_regex.match(word)
171
        if match:
172
            filename = f'{match.group(0)}_0%3a2.7.9+dfsg-1_all.deb'
173
            deb_path = destination / filename
167 174
            deb_path.write_text(f'dummy {deb_path.name}')
168 175

  
169 176
    return MockedCompletedProcess(command, returncode,
......
175 182
    "tarballs" to the appropriate directory.
176 183
    """
177 184
    expected = ['apt-get', '-c', '<conf_path>', 'source',
178
                '--download-only', 'libjs-mathjax=2.7.9+dfsg-1']
179
    if 'fonts-mathjax=2.7.9+dfsg-1' in command:
180
        if command[-1] == 'fonts-mathjax=2.7.9+dfsg-1':
181
            expected.append('fonts-mathjax=2.7.9+dfsg-1')
185
                '--download-only', 'libjs-mathjax=0:2.7.9+dfsg-1']
186
    if 'fonts-mathjax=0:2.7.9+dfsg-1' in command:
187
        if command[-1] == 'fonts-mathjax=0:2.7.9+dfsg-1':
188
            expected.append('fonts-mathjax=0:2.7.9+dfsg-1')
182 189
        else:
183
            expected.insert(-1, 'fonts-mathjax=2.7.9+dfsg-1')
190
            expected.insert(-1, 'fonts-mathjax=0:2.7.9+dfsg-1')
184 191

  
185 192
    destination = Path(kwargs.get('cwd') or Path.cwd())
186 193
    for filename in [
......
335 342
    local_apt.download_apt_packages(sources_list, local_apt.default_keys,
336 343
                                    ['libjs-mathjax'], destination)
337 344

  
338
    libjs_mathjax_path = destination / 'libjs-mathjax_2.7.9+dfsg-1_all.deb'
339
    fonts_mathjax_path = destination / 'fonts-mathjax_2.7.9+dfsg-1_all.deb'
345
    libjs_mathjax_path = destination / 'libjs-mathjax_0%3a2.7.9+dfsg-1_all.deb'
346
    fonts_mathjax_path = destination / 'fonts-mathjax_0%3a2.7.9+dfsg-1_all.deb'
340 347

  
341 348
    source_paths = [
342 349
        destination / 'mathjax_2.7.9+dfsg-1.debian.tar.xz',

Also available in: Unified diff