diff --git a/swh/loader/svn/loader.py b/swh/loader/svn/loader.py --- a/swh/loader/svn/loader.py +++ b/swh/loader/svn/loader.py @@ -381,6 +381,7 @@ error_msgs = [ "Unable to connect to a repository at URL", "Unknown URL type", + "is not a working copy", ] for msg in error_msgs: if msg in e.args[0]: @@ -771,7 +772,15 @@ def prepare(self): # First, check if previous revisions have been loaded for the # subversion origin and get the number of the last one - last_loaded_svn_rev = self.get_last_loaded_svn_rev(self.svn_url) + last_loaded_svn_rev = self.get_last_loaded_svn_rev(self.origin.url) + + self.svnrepo = self.svn_repo( + self.origin.url, self.origin.url, self.temp_dir, self.max_content_size + ) + + # Ensure to use remote URL retrieved by SvnRepo as origin URL might redirect + # and svnrdump does not handle URL redirection + self.svn_url = self.svnrepo.remote_url # Then for stale repository, check if the last loaded revision in the archive # is different from the last revision on the remote subversion server. @@ -780,9 +789,6 @@ last_loaded_snp_and_rev = self._latest_snapshot_revision(self.origin.url) if last_loaded_snp_and_rev is not None: last_loaded_snp, last_loaded_rev = last_loaded_snp_and_rev - self.svnrepo = self.svn_repo( - self.origin.url, self.origin.url, self.temp_dir, self.max_content_size - ) stale_repository = self.svnrepo.head_revision() == last_loaded_svn_rev if stale_repository and self.check_history_not_altered( last_loaded_svn_rev, last_loaded_rev 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 @@ -59,12 +59,17 @@ self.from_dump = from_dump auth = Auth([get_username_provider()]) + # one client for update operation + self.client = client.Client(auth=auth) + + if not self.remote_url.startswith("file://"): + # use redirection URL if any for remote operations + self.remote_url = self.info(self.remote_url).url + # one connection for log iteration self.conn_log = self.remote_access(auth) # another for replay self.conn = self.remote_access(auth) - # one client for update operation - self.client = client.Client(auth=auth) self.local_dirname = local_dirname local_name = os.path.basename(self.remote_url) 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 @@ -2065,3 +2065,36 @@ type="svn", snapshot=None, ) + + +def test_loader_svn_from_remote_dump_url_redirect(swh_storage, tmp_path, mocker): + repo_url = "http://svn.example.org/repo" + repo_redirect_url = "https://svn.example.org/repo" + + # mock remote subversion operations + from swh.loader.svn.svn import client + + mocker.patch("swh.loader.svn.svn.RemoteAccess") + init_svn_repo_from_dump = mocker.patch( + "swh.loader.svn.loader.init_svn_repo_from_dump" + ) + init_svn_repo_from_dump.return_value = ("", "") + mock_client = mocker.MagicMock() + mocker.patch.object(client, "Client", mock_client) + + class Info: + repos_root_url = repo_redirect_url + url = repo_redirect_url + + mock_client().info.return_value = {"repo": Info()} + + # init remote dump loader and mock some methods + loader = SvnLoaderFromRemoteDump(swh_storage, repo_url, temp_directory=tmp_path) + loader.dump_svn_revisions = mocker.MagicMock() + loader.start_from = mocker.MagicMock(return_value=(0, 0)) + + # prepare loading + loader.prepare() + + # check redirection URL has been used to dump repository + assert loader.dump_svn_revisions.call_args_list[0][0][0] == repo_redirect_url