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 @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2020 The Software Heritage developers +# Copyright (C) 2015-2021 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information @@ -16,9 +16,13 @@ import tempfile from typing import Any, Dict, Iterator, List, Optional, Tuple +from subvertpy import SubversionException + from swh.core.config import merge_configs from swh.loader.core.loader import BaseLoader from swh.loader.core.utils import clean_dangling_folders +from swh.loader.exception import NotFound +from swh.loader.svn.svn import SvnRepo from swh.model import from_disk, hashutil from swh.model.model import ( Content, @@ -32,7 +36,7 @@ ) from swh.storage.algos.snapshot import snapshot_get_latest -from . import converters, svn +from . import converters from .exception import SvnLoaderHistoryAltered, SvnLoaderUneventful from .utils import ( OutputStream, @@ -398,9 +402,20 @@ dir=self.temp_directory, ) - self.svnrepo = svn.SvnRepo( - self.svn_url, self.origin_url, local_dirname, self.max_content_length - ) + try: + self.svnrepo = SvnRepo( + self.svn_url, self.origin_url, local_dirname, self.max_content_length + ) + except SubversionException as e: + error_msgs = [ + "Unable to connect to a repository at URL", + "Unknown URL type", + ] + for msg in error_msgs: + if msg in e.args[0]: + self._load_status = "uneventful" + raise NotFound(e) + raise try: revision_start, revision_end, revision_parents = self.start_from( 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 @@ -5,6 +5,9 @@ import os +import pytest +from subvertpy import SubversionException + from swh.loader.svn.loader import SvnLoader, SvnLoaderFromRemoteDump from swh.loader.tests import ( assert_last_visit_matches, @@ -36,6 +39,59 @@ ) +def test_loader_svn_not_found_no_mock(swh_config, tmp_path): + """Given an unknown repository, the loader visit ends up in status not_found""" + unknown_repo_url = "unknown-repository" + loader = SvnLoader(unknown_repo_url, destination_path=tmp_path) + + assert loader.load() == {"status": "uneventful"} + + assert_last_visit_matches( + loader.storage, unknown_repo_url, status="not_found", type="svn", + ) + + +@pytest.mark.parametrize( + "exception_msg", ["Unable to connect to a repository at URL", "Unknown URL type",] +) +def test_loader_svn_not_found(swh_config, tmp_path, exception_msg, mocker): + """Given unknown repository issues, the loader visit ends up in status not_found""" + mock = mocker.patch("swh.loader.svn.loader.SvnRepo") + mock.side_effect = SubversionException(exception_msg, 0) + + unknown_repo_url = "unknown-repository" + loader = SvnLoader(unknown_repo_url, destination_path=tmp_path) + + assert loader.load() == {"status": "uneventful"} + + assert_last_visit_matches( + loader.storage, unknown_repo_url, status="not_found", type="svn", + ) + + +@pytest.mark.parametrize( + "exception", + [ + SubversionException("Irrelevant message, considered a failure", 10), + SubversionException("Present but fails to read, considered a failure", 20), + ValueError("considered a failure"), + ], +) +def test_loader_svn_failures(swh_config, tmp_path, exception, mocker): + """Given any errors raised, the loader visit ends up in status failed""" + mock = mocker.patch("swh.loader.svn.loader.SvnRepo") + mock.side_effect = exception + + existing_repo_url = "existing-repo-url" + loader = SvnLoader(existing_repo_url, destination_path=tmp_path) + + assert loader.load() == {"status": "failed"} + + assert_last_visit_matches( + loader.storage, existing_repo_url, status="failed", type="svn", + ) + + def test_loader_svn_new_visit(swh_config, datadir, tmp_path): """Eventful visit should yield 1 snapshot""" archive_name = "pkg-gourmet"