diff --git a/swh/loader/cvs/loader.py b/swh/loader/cvs/loader.py --- a/swh/loader/cvs/loader.py +++ b/swh/loader/cvs/loader.py @@ -31,7 +31,7 @@ RcsKeywords, file_path, ) -from swh.loader.cvs.cvsclient import CVSClient, decode_path +from swh.loader.cvs.cvsclient import CVSClient, CVSProtocolError, decode_path import swh.loader.cvs.rcsparse as rcsparse from swh.loader.cvs.rlog import RlogConv from swh.loader.exception import NotFound @@ -497,8 +497,16 @@ cvsroot_path, self.cvs_module_name, ) + try: + main_rlog_file = self.cvsclient.fetch_rlog() + except CVSProtocolError as cvs_err: + if "cannot find module" in str(cvs_err): + raise NotFound( + f"CVS module named {self.cvs_module_name} cannot be found" + ) + else: + raise self.rlog = RlogConv(cvsroot_path, CHANGESET_FUZZ_SEC) - main_rlog_file = self.cvsclient.fetch_rlog() self.rlog.parse_rlog(main_rlog_file) # Find file deletion events only visible in Attic directories. main_changesets = self.rlog.changesets diff --git a/swh/loader/cvs/tests/test_loader.py b/swh/loader/cvs/tests/test_loader.py --- a/swh/loader/cvs/tests/test_loader.py +++ b/swh/loader/cvs/tests/test_loader.py @@ -48,6 +48,34 @@ ) +def test_loader_cvs_ssh_module_not_found(swh_storage, tmp_path, mocker): + url = "ssh://anoncvs@anoncvs.example.org/cvsroot/foo" + + mocker.patch("swh.loader.cvs.cvsclient.socket") + mocker.patch("swh.loader.cvs.cvsclient.subprocess") + from swh.loader.cvs.loader import CVSClient as Client + + conn_read_line = mocker.patch.object(Client, "conn_read_line") + conn_read_line.side_effect = [ + # server response lines when client is initialized + b"Valid-requests ", + b"ok\n", + # server response line when CVS module is missing + "E cvs rlog: cannot find module `foo' - ignored\n".encode(), + ] + + loader = CvsLoader(swh_storage, url, cvsroot_path=tmp_path) + + assert loader.load() == {"status": "uneventful"} + + assert_last_visit_matches( + swh_storage, + url, + status="not_found", + type="cvs", + ) + + def test_loader_cvs_visit(swh_storage, datadir, tmp_path): """Eventful visit should yield 1 snapshot""" archive_name = "runbaby"