diff --git a/heptapod/__init__.py b/heptapod/__init__.py index a262a8adc33aee851631cc24cdcb46ee138ebd55_aGVwdGFwb2QvX19pbml0X18ucHk=..a3d8f1eb9232660f7071b42dfc5b7b158ee437c9_aGVwdGFwb2QvX19pbml0X18ucHk= 100644 --- a/heptapod/__init__.py +++ b/heptapod/__init__.py @@ -1,1 +1,2 @@ # Python package +from . import patch # noqa: F401 diff --git a/heptapod/patch.py b/heptapod/patch.py new file mode 100644 index 0000000000000000000000000000000000000000..a3d8f1eb9232660f7071b42dfc5b7b158ee437c9_aGVwdGFwb2QvcGF0Y2gucHk= --- /dev/null +++ b/heptapod/patch.py @@ -0,0 +1,42 @@ +# Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. +# +# SPDX-License-Identifier: GPL-2.0-or-later +import os + +import dulwich +from dulwich.object_store import ( + DiskObjectStore, + INFODIR, + GitFile, +) + + +# backport from dulwich commits: +# 06b65c3c2aef57939143e33d404f9883ec286597 +# 544e90f8cbce1282ecb3d8ff73b5d7ecae905601 +# +# see also https://github.com/dulwich/dulwich/pull/815 and heptapod#370 +def _read_alternate_paths(self): + try: + f = GitFile(os.path.join(self.path, INFODIR, "alternates"), 'rb') + except FileNotFoundError: + return + with f: + for line in f.readlines(): + line = line.rstrip(b"\n") + if line.startswith(b"#"): + continue + if os.path.isabs(line): + yield os.fsdecode(line) + else: + yield os.fsdecode(os.path.join(os.fsencode(self.path), + line)) + + +if dulwich.__version__ < (0, 20, 14): + # our tests will run immediately on the dulwich with the fix, + # only coverage telling us it's time to remove the unneeded patch + DiskObjectStore._read_alternate_paths = _read_alternate_paths diff --git a/heptapod/tests/test_patch.py b/heptapod/tests/test_patch.py new file mode 100644 index 0000000000000000000000000000000000000000..a3d8f1eb9232660f7071b42dfc5b7b158ee437c9_aGVwdGFwb2QvdGVzdHMvdGVzdF9wYXRjaC5weQ== --- /dev/null +++ b/heptapod/tests/test_patch.py @@ -0,0 +1,32 @@ +# Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. +# +# SPDX-License-Identifier: GPL-2.0-or-later +import os +from dulwich.tests.test_object_store import ( + DiskObjectStore, + DiskObjectStoreTests, +) + + +class AlternatePathsTests(DiskObjectStoreTests): + + def test_read_alternate_paths(self): + store = DiskObjectStore(self.store_dir) + + abs_path = os.path.abspath(os.path.normpath('/abspath')) + # ensures in particular existence of the alternates file + store.add_alternate_path(abs_path) + self.assertEqual(set(store._read_alternate_paths()), {abs_path}) + + store.add_alternate_path("relative-path") + self.assertIn(os.path.join(store.path, "relative-path"), + set(store._read_alternate_paths())) + + # arguably, add_alternate_path() could strip comments. + # Meanwhile it's more convenient to use it than to import INFODIR + store.add_alternate_path("# comment") + for alt_path in store._read_alternate_paths(): + self.assertNotIn("#", alt_path)