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 @@ -393,14 +393,29 @@ peg_rev: Optional[int], rev: Optional[int] = None, recurse: bool = False, - ): + ) -> Dict[str, bytes]: """Simple wrapper around subvertpy.client.Client.propget enabling to retry the command if a network error occurs. See documentation of svn_client_propget5 function from subversion C API to get details about parameters. """ - return self.client.propget(name, target, peg_rev, rev, recurse) + target_is_url = urlparse(target).scheme != "" + if target_is_url: + # subvertpy 0.11 has a buggy implementation of propget bindings when + # target is an URL (https://github.com/jelmer/subvertpy/issues/35) + # as a workaround we implement propget for URL using non buggy proplist bindings + svn_depth_infinity = 3 + svn_depth_empty = 0 + proplist = self.client.proplist( + quote_svn_url(target), + peg_revision=peg_rev, + revision=rev, + depth=svn_depth_infinity if recurse else svn_depth_empty, + ) + return {path: props[name] for path, props in proplist if name in props} + else: + return self.client.propget(name, target, peg_rev, rev, recurse) def export_temporary(self, revision: int) -> Tuple[str, bytes]: """Export the repository to a given revision in a temporary location. This is up 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 @@ -2432,3 +2432,56 @@ "+baz", ): assert debug_log in caplog.text + + +def test_loader_svnrepo_propget_on_url(swh_storage, repo_url, tmp_path): + # create sample repository + add_commit( + repo_url, + "Create files with some having svn:eol-style property set", + [ + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="trunk/data/foo", + data=b"foo\n", + properties={"svn:eol-style": "native"}, + ), + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="trunk/data/bar", + data=b"bar\n", + properties={"svn:eol-style": "native"}, + ), + CommitChange( + change_type=CommitChangeType.AddOrUpdate, + path="trunk/data/baz", + data=b"baz\n", + ), + ], + ) + + # load it + loader = SvnLoader( + swh_storage, + repo_url, + temp_directory=tmp_path, + debug=True, + check_revision=1, + ) + assert loader.load() == {"status": "eventful"} + + foo_file_url = f"{repo_url}/trunk/data/foo" + bar_file_url = f"{repo_url}/trunk/data/bar" + baz_file_url = f"{repo_url}/trunk/data/baz" + assert loader.svnrepo.propget("svn:eol-style", foo_file_url, peg_rev=1, rev=1) == { + foo_file_url: b"native" + } + + assert loader.svnrepo.propget( + "svn:eol-style", repo_url, peg_rev=1, rev=1, recurse=True + ) == { + foo_file_url: b"native", + bar_file_url: b"native", + } + + assert loader.svnrepo.propget("svn:eol-style", baz_file_url, peg_rev=1, rev=1) == {}