summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-05-11 10:23:59 +0200
committerWojtek Kosior <koszko@koszko.org>2022-05-11 10:23:59 +0200
commit866922f80326671815c9187eed0ba6c4127b8721 (patch)
tree3d1b15fc432c070ca322347cc2fe882d6fc1fe66
parentbd588eb9a4b2890da6f9db928f302e2e98a7b9ce (diff)
downloadhydrilla-builder-866922f80326671815c9187eed0ba6c4127b8721.tar.gz
hydrilla-builder-866922f80326671815c9187eed0ba6c4127b8721.zip
properly handle percent-encoded characters in .deb file names
-rw-r--r--src/hydrilla/builder/local_apt.py25
-rw-r--r--tests/test_local_apt.py39
2 files changed, 35 insertions, 29 deletions
diff --git a/src/hydrilla/builder/local_apt.py b/src/hydrilla/builder/local_apt.py
index 4c93a4d..eee028d 100644
--- a/src/hydrilla/builder/local_apt.py
+++ b/src/hydrilla/builder/local_apt.py
@@ -35,6 +35,7 @@ CP = subprocess.CompletedProcess
from pathlib import Path, PurePosixPath
from tempfile import TemporaryDirectory, NamedTemporaryFile
from hashlib import sha256
+from urllib.parse import unquote
from contextlib import contextmanager
from typing import Optional, Iterable
@@ -296,25 +297,20 @@ def download_apt_packages(list: SourcesList, keys: [str], packages: [str],
Return value is a list of names of all downloaded files.
"""
+ install_line_regex = re.compile(r'^Inst (?P<name>\S+) \((?P<version>\S+) ')
+
with local_apt(list, keys) as apt:
if with_deps:
cp = apt.get('install', '--yes', '--just-print', *packages)
- deps_listing = re.match(
- r'''
- .*
- The\sfollowing\sNEW\spackages\swill\sbe\sinstalled:
- (.*)
- 0\supgraded,
- ''',
- cp.stdout,
- re.MULTILINE | re.DOTALL | re.VERBOSE)
+ lines = cp.stdout.split('\n')
+ matches = [install_line_regex.match(l) for l in lines]
+ packages = [f'{m.group("name")}={m.group("version")}'
+ for m in matches if m]
- if deps_listing is None:
+ if not packages:
raise AptError(_('apt_install_output_not_understood'), cp)
- packages = deps_listing.group(1).split()
-
# Download .debs to indirectly to destination_dir by first placing them
# in a temporary subdirectory.
with TemporaryDirectory(dir=destination_dir) as td:
@@ -343,7 +339,10 @@ def download_apt_packages(list: SourcesList, keys: [str], packages: [str],
.format(deb_file.name)
raise AptError(msg, cp)
- names_vers.append((match.group('name'), match.group('ver')))
+ names_vers.append((
+ unquote(match.group('name')),
+ unquote(match.group('ver'))
+ ))
downloaded.append(deb_file.name)
apt.get('source', '--download-only',
diff --git a/tests/test_local_apt.py b/tests/test_local_apt.py
index 1ff52cc..6ba2a06 100644
--- a/tests/test_local_apt.py
+++ b/tests/test_local_apt.py
@@ -128,10 +128,10 @@ Suggested packages:
The following NEW packages will be installed:
fonts-mathjax libjs-mathjax
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
-Inst fonts-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
-Inst libjs-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
-Conf fonts-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
-Conf libjs-mathjax (2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
+Inst fonts-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
+Inst libjs-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
+Conf fonts-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
+Conf libjs-mathjax (0:2.7.9+dfsg-1 Devuan:4.0/stable, Devuan:1.0.0/unstable [all])
'''
def run_apt_get_install(command, returncode=0, **kwargs):
@@ -153,17 +153,24 @@ def run_apt_get_download(command, returncode=0, **kwargs):
Instead of running an 'apt-get download' command just write some dummy
.deb to the appropriate directory.
"""
- expected = ['apt-get', '-c', '<conf_path>', 'download', 'libjs-mathjax']
- if 'fonts-mathjax' in command:
- expected.insert(-1, 'fonts-mathjax')
+ expected = ['apt-get', '-c', '<conf_path>', 'download']
+ if 'libjs-mathjax' in command:
+ expected.append('libjs-mathjax')
+ else:
+ expected.append('fonts-mathjax=0:2.7.9+dfsg-1')
+ expected.append('libjs-mathjax=0:2.7.9+dfsg-1')
conf_path = Path(process_run_args(command, kwargs, expected)['conf_path'])
destination = Path(kwargs.get('cwd') or Path.cwd())
+ package_name_regex = re.compile(r'^[^=]+-mathjax')
+
for word in expected:
- if word.endswith('-mathjax'):
- deb_path = destination / f'{word}_2.7.9+dfsg-1_all.deb'
+ match = package_name_regex.match(word)
+ if match:
+ filename = f'{match.group(0)}_0%3a2.7.9+dfsg-1_all.deb'
+ deb_path = destination / filename
deb_path.write_text(f'dummy {deb_path.name}')
return MockedCompletedProcess(command, returncode,
@@ -175,12 +182,12 @@ def run_apt_get_source(command, returncode=0, **kwargs):
"tarballs" to the appropriate directory.
"""
expected = ['apt-get', '-c', '<conf_path>', 'source',
- '--download-only', 'libjs-mathjax=2.7.9+dfsg-1']
- if 'fonts-mathjax=2.7.9+dfsg-1' in command:
- if command[-1] == 'fonts-mathjax=2.7.9+dfsg-1':
- expected.append('fonts-mathjax=2.7.9+dfsg-1')
+ '--download-only', 'libjs-mathjax=0:2.7.9+dfsg-1']
+ if 'fonts-mathjax=0:2.7.9+dfsg-1' in command:
+ if command[-1] == 'fonts-mathjax=0:2.7.9+dfsg-1':
+ expected.append('fonts-mathjax=0:2.7.9+dfsg-1')
else:
- expected.insert(-1, 'fonts-mathjax=2.7.9+dfsg-1')
+ expected.insert(-1, 'fonts-mathjax=0:2.7.9+dfsg-1')
destination = Path(kwargs.get('cwd') or Path.cwd())
for filename in [
@@ -335,8 +342,8 @@ def test_local_apt_download(mock_cache_dir):
local_apt.download_apt_packages(sources_list, local_apt.default_keys,
['libjs-mathjax'], destination)
- libjs_mathjax_path = destination / 'libjs-mathjax_2.7.9+dfsg-1_all.deb'
- fonts_mathjax_path = destination / 'fonts-mathjax_2.7.9+dfsg-1_all.deb'
+ libjs_mathjax_path = destination / 'libjs-mathjax_0%3a2.7.9+dfsg-1_all.deb'
+ fonts_mathjax_path = destination / 'fonts-mathjax_0%3a2.7.9+dfsg-1_all.deb'
source_paths = [
destination / 'mathjax_2.7.9+dfsg-1.debian.tar.xz',