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 @@ -559,9 +559,15 @@ # revision, we need to determine if some were removed and delete the # associated paths externals = self.externals - old_externals = set(prev_externals) - set(self.externals) - for old_external in old_externals: - self.remove_external_path(os.fsencode(old_external)) + prev_externals_set = { + (path, url, rev) for path, (url, rev, _) in prev_externals.items() + } + externals_set = { + (path, url, rev) for path, (url, rev, _) in externals.items() + } + old_externals = prev_externals_set - externals_set + for path, _, _ in old_externals: + self.remove_external_path(os.fsencode(path)) else: # some external paths might have been removed in the current replayed # revision by a delete operation on an overlapping versioned path so we 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 @@ -2673,3 +2673,64 @@ loader.storage, repo_url, status="full", type="svn", ) check_snapshot(loader.snapshot, loader.storage) + + +def test_loader_modify_external_same_path( + swh_storage, repo_url, external_repo_url, tmp_path +): + # first commit on external + add_commit( + external_repo_url, + "Create a file in an external repository", + [ + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="code/foo.sh", + data=b"#!/bin/bash\necho foo", + ), + ], + ) + + # first commit + add_commit( + repo_url, + "Add trunk dir", + [CommitChange(change_type=CommitChangeType.AddOrUpdate, path="trunk/")], + ) + + # second commit + add_commit( + repo_url, + "Set external code on trunk dir", + [ + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="trunk/", + properties={ + "svn:externals": (f"{svn_urljoin(external_repo_url, 'code')} code") + }, + ), + ], + ) + + # third commit + add_commit( + repo_url, + "Change code external on trunk targeting an invalid URL", + [ + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="trunk/", + properties={"svn:externals": "file:///tmp/invalid/svn/repo/path code"}, + ), + ], + ) + + loader = SvnLoader( + swh_storage, repo_url, temp_directory=tmp_path, check_revision=1, + ) + assert loader.load() == {"status": "eventful"} + assert_last_visit_matches( + loader.storage, repo_url, status="full", type="svn", + ) + check_snapshot(loader.snapshot, loader.storage)