Skip to content

Commit

Permalink
reposync: Implement --safe-write-path option (RhBug:1898089)
Browse files Browse the repository at this point in the history
= changelog =
msg: With --safe-write-path option reposync can download repositories with relative package locations (like ../package-store/f/foo.rpm)
type: enhancement
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1898089
  • Loading branch information
m-blaha committed Oct 6, 2021
1 parent 9a00b1e commit fd44208
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
3 changes: 3 additions & 0 deletions doc/reposync.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ All general DNF options are accepted. Namely, the ``--repoid`` option can be use
``-p <download-path>, --download-path=<download-path>``
Root path under which the downloaded repositories are stored, relative to the current working directory. Defaults to the current working directory. Every downloaded repository has a subdirectory named after its ID under this path.

``--safe-write-path``
Root path that is considered safe for writing. If not specified it defaults to download path of the repository. Useful for repositories that use relative locations of packages out of repository directory (e.g. "../packages_store/foo.rpm"). Use with care, any file under the ``safe-write-path`` can be overwritten. Can be only used when syncing a single repository.

``--remote-time``
Try to set the timestamps of the downloaded files to those on the remote side.

Expand Down
27 changes: 20 additions & 7 deletions plugins/reposync.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def set_argparser(parser):
parser.add_argument('-u', '--urls', default=False, action='store_true',
help=_("Just list urls of what would be downloaded, "
"don't download"))
parser.add_argument('--safe-write-path', default=None,
help=_("Filesystem path that is considered safe for writing. Defaults to download path."))

def configure(self):
demands = self.cli.demands
Expand All @@ -108,9 +110,16 @@ def configure(self):
if self.opts.source:
repos.enable_source_repos()

if len(list(repos.iter_enabled())) > 1 and self.opts.norepopath:
raise dnf.cli.CliError(
_("Can't use --norepopath with multiple repositories"))
if self.opts.safe_write_path is not None:
self.opts.safe_write_path = os.path.realpath(self.opts.safe_write_path)

if len(list(repos.iter_enabled())) > 1:
if self.opts.norepopath:
raise dnf.cli.CliError(
_("Can't use --norepopath with multiple repositories"))
elif self.opts.safe_write_path is not None:
raise dnf.cli.CliError(
_("Can't use --safe-write-path with multiple repositories"))

for repo in repos.iter_enabled():
repo._repo.expire()
Expand Down Expand Up @@ -188,13 +197,17 @@ def pkg_download_path(self, pkg):
repo_target = self.repo_target(pkg.repo)
pkg_download_path = os.path.realpath(
os.path.join(repo_target, pkg.location))
# join() ensures repo_target ends with a path separator (otherwise the

# join() ensures safe_write_path ends with a path separator (otherwise the
# check would pass if pkg_download_path was a "sibling" path component
# of repo_target that has the same prefix).
if not pkg_download_path.startswith(os.path.join(repo_target, '')):
safe_write_path = os.path.join(self.opts.safe_write_path or repo_target, '')

if not pkg_download_path.startswith(safe_write_path):
raise dnf.exceptions.Error(
_("Download target '{}' is outside of download path '{}'.").format(
pkg_download_path, repo_target))
_("Download target '{0}' for location '{1}' of '{2}' package "
"is outside of safe write path '{3}'.").format(
pkg_download_path, pkg.location, pkg.name, safe_write_path))
return pkg_download_path

def delete_old_local_packages(self, repo, pkglist):
Expand Down

0 comments on commit fd44208

Please sign in to comment.