mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 06:41:43 +00:00
fix case with package name which cannot be downloaded
(without special settings) The issue appears if file or its version contains one of special URI characters, e.g. +. Theu will be interpreted as query parameters by (some) servers (e.g. S3 works in this way). In this commit we rename archive to the one with safe name.
This commit is contained in:
@ -52,7 +52,7 @@ class Rebuild(Handler):
|
||||
if args.from_database:
|
||||
updates = Rebuild.extract_packages(application)
|
||||
else:
|
||||
updates = application.repository.packages_depends_on(depends_on)
|
||||
updates = application.repository.packages_depend_on(depends_on)
|
||||
|
||||
Rebuild.check_if_empty(args.exit_code, not updates)
|
||||
if args.dry_run:
|
||||
|
@ -24,8 +24,9 @@ from typing import Iterable, List, Optional, Set
|
||||
|
||||
from ahriman.core.build_tools.task import Task
|
||||
from ahriman.core.repository.cleaner import Cleaner
|
||||
from ahriman.core.util import tmpdir
|
||||
from ahriman.core.util import safe_filename, tmpdir
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.package_description import PackageDescription
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
@ -122,16 +123,16 @@ class Executor(Cleaner):
|
||||
for local in self.packages():
|
||||
if local.base in packages or all(package in requested for package in local.packages):
|
||||
to_remove = {
|
||||
package: Path(properties.filename)
|
||||
package: properties.filepath
|
||||
for package, properties in local.packages.items()
|
||||
if properties.filename is not None
|
||||
if properties.filepath is not None
|
||||
}
|
||||
remove_base(local.base)
|
||||
elif requested.intersection(local.packages.keys()):
|
||||
to_remove = {
|
||||
package: Path(properties.filename)
|
||||
package: properties.filepath
|
||||
for package, properties in local.packages.items()
|
||||
if package in requested and properties.filename is not None
|
||||
if package in requested and properties.filepath is not None
|
||||
}
|
||||
else:
|
||||
to_remove = {}
|
||||
@ -160,17 +161,25 @@ class Executor(Cleaner):
|
||||
Returns:
|
||||
Result: path to repository database
|
||||
"""
|
||||
def rename(archive: PackageDescription, base: str) -> None:
|
||||
if archive.filename is None:
|
||||
self.logger.warning("received empty package name for base %s", base)
|
||||
return # suppress type checking, it never can be none actually
|
||||
if (safe := safe_filename(archive.filename)) != archive.filename:
|
||||
shutil.move(self.paths.packages / archive.filename, self.paths.packages / safe)
|
||||
archive.filename = safe
|
||||
|
||||
def update_single(name: Optional[str], base: str) -> None:
|
||||
if name is None:
|
||||
self.logger.warning("received empty package name for base %s", base)
|
||||
return # suppress type checking, it never can be none actually
|
||||
# in theory it might be NOT packages directory, but we suppose it is
|
||||
# in theory, it might be NOT packages directory, but we suppose it is
|
||||
full_path = self.paths.packages / name
|
||||
files = self.sign.process_sign_package(full_path, base)
|
||||
for src in files:
|
||||
dst = self.paths.repository / src.name
|
||||
dst = self.paths.repository / safe_filename(src.name)
|
||||
shutil.move(src, dst)
|
||||
package_path = self.paths.repository / name
|
||||
package_path = self.paths.repository / safe_filename(name)
|
||||
self.repo.add(package_path)
|
||||
|
||||
current_packages = self.packages()
|
||||
@ -181,6 +190,7 @@ class Executor(Cleaner):
|
||||
for local in updates:
|
||||
try:
|
||||
for description in local.packages.values():
|
||||
rename(description, local.base)
|
||||
update_single(description.filename, local.base)
|
||||
self.reporter.set_success(local)
|
||||
result.add_success(local)
|
||||
|
@ -99,7 +99,7 @@ class Repository(Executor, UpdateHandler):
|
||||
"""
|
||||
return list(filter(package_like, self.paths.packages.iterdir()))
|
||||
|
||||
def packages_depends_on(self, depends_on: Optional[Iterable[str]]) -> List[Package]:
|
||||
def packages_depend_on(self, depends_on: Optional[Iterable[str]]) -> List[Package]:
|
||||
"""
|
||||
extract list of packages which depends on specified package
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
import datetime
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import shutil
|
||||
import subprocess
|
||||
@ -36,7 +37,7 @@ from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
__all__ = ["check_output", "check_user", "exception_response_text", "filter_json", "full_version", "enum_values",
|
||||
"package_like", "pretty_datetime", "pretty_size", "tmpdir", "walk"]
|
||||
"package_like", "pretty_datetime", "pretty_size", "safe_filename", "tmpdir", "walk"]
|
||||
|
||||
|
||||
def check_output(*args: str, exception: Optional[Exception], cwd: Optional[Path] = None,
|
||||
@ -272,6 +273,27 @@ def pretty_size(size: Optional[float], level: int = 0) -> str:
|
||||
return pretty_size(size / 1024, level + 1)
|
||||
|
||||
|
||||
def safe_filename(source: str) -> str:
|
||||
"""
|
||||
convert source string to its safe representation
|
||||
|
||||
Args:
|
||||
source(str): string to convert
|
||||
|
||||
Returns:
|
||||
str: result string in which all unsafe characters are replaced by dash
|
||||
"""
|
||||
# RFC-3986 https://datatracker.ietf.org/doc/html/rfc3986 states that unreserved characters are
|
||||
# https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
|
||||
# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
# however we would like to allow some gen-delims characters in filename, because those characters are used
|
||||
# as delimiter in other URI parts. The ones we allow are
|
||||
# ":" - used as separator in schema and userinfo
|
||||
# "[" and "]" - used for host part
|
||||
# "@" - used as separator between host and userinfo
|
||||
return re.sub(r"[^A-Za-z\d\-._~:\[\]@]", "-", source)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def tmpdir() -> Generator[Path, None, None]:
|
||||
"""
|
||||
|
Reference in New Issue
Block a user