diff --git a/swh/loader/svn/replay.py b/swh/loader/svn/replay.py --- a/swh/loader/svn/replay.py +++ b/swh/loader/svn/replay.py @@ -304,7 +304,7 @@ with open(self.fullpath, "rb") as f: content = f.read() self.svnrepo.export( - os.path.join(self.svnrepo.remote_url.encode(), self.path), + os.path.join(self.svnrepo.remote_url, os.fsdecode(self.path)), to=self.fullpath, peg_rev=self.editor.revnum, ignore_keywords=True, diff --git a/swh/loader/svn/svn.py b/swh/loader/svn/svn.py --- a/swh/loader/svn/svn.py +++ b/swh/loader/svn/svn.py @@ -42,6 +42,10 @@ logger = logging.getLogger(__name__) +def quote_svn_url(url: str) -> str: + return url.replace(" ", "%20") + + class SvnRepo: """Svn repository representation. @@ -272,7 +276,7 @@ def info(self, origin_url: str): """Simple wrapper around subvertpy.client.Client.info enabling to retry the command if a network error occurs.""" - info = self.client.info(origin_url.rstrip("/")) + info = self.client.info(quote_svn_url(origin_url).rstrip("/")) return next(iter(info.values())) @svn_retry() @@ -312,12 +316,12 @@ logger.debug( "svn export %s %s%s %s", " ".join(options), - url, + quote_svn_url(url), f"@{peg_rev}" if peg_rev else "", to, ) return self.client.export( - url, + quote_svn_url(url), to=to, rev=rev, peg_rev=peg_rev, @@ -361,12 +365,12 @@ logger.debug( "svn checkout %s %s%s %s", " ".join(options), - self.remote_url, + quote_svn_url(url), f"@{peg_rev}" if peg_rev else "", path, ) return self.client.checkout( - url, + quote_svn_url(url), path=path, rev=rev, peg_rev=peg_rev, diff --git a/swh/loader/svn/tests/test_loader.py b/swh/loader/svn/tests/test_loader.py --- a/swh/loader/svn/tests/test_loader.py +++ b/swh/loader/svn/tests/test_loader.py @@ -2172,3 +2172,28 @@ ) check_snapshot(loader.snapshot, loader.storage) + + +def test_loader_with_spaces_in_svn_url(swh_storage, repo_url, tmp_path): + filename = "file with spaces.txt" + content = b"foo" + + add_commit( + repo_url, + "Add file with spaces in its name", + [ + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path=filename, + data=content, + ), + ], + ) + + svnrepo = SvnRepo(repo_url, repo_url, tmp_path, max_content_length=10000) + + dest_path = f"{tmp_path}/file" + svnrepo.export(f"{repo_url}/{filename}", to=dest_path) + + with open(dest_path, "rb") as f: + assert f.read() == content