diff --git a/hgitaly/servicer.py b/hgitaly/servicer.py index dc2defecd55ca00735ea4a143f517f01e666a84e_aGdpdGFseS9zZXJ2aWNlci5weQ==..15c56172544ffbbafc4bb202096de0a890a07cea_aGdpdGFseS9zZXJ2aWNlci5weQ== 100644 --- a/hgitaly/servicer.py +++ b/hgitaly/servicer.py @@ -4,6 +4,7 @@ # GNU General Public License version 2 or any later version. # # SPDX-License-Identifier: GPL-2.0-or-later +from contextlib import contextmanager import gc import logging import os @@ -7,6 +8,7 @@ import gc import logging import os +from pathlib import Path import time import weakref @@ -17,6 +19,8 @@ ui as uimod, ) from mercurial.repoview import _filteredrepotypes + +from .workdir import working_directory from .stub.shared_pb2 import ( Repository, ) @@ -253,3 +257,19 @@ os.mkdir(to_create.pop(), mode=0o755) return temp_dir + + @contextmanager + def working_dir(self, gl_repo: Repository, repo, context, changeset=None): + """Provide a working directory updated to the given changeset. + + The working directory is part from the pool of reusable working + directories and created if needed. + """ + tmp = Path(os.fsdecode( + self.temp_dir(gl_repo.storage_name, context, ensure=True) + )) + rpath = normalize_rpath(gl_repo) + + with working_directory(tmp / 'workdirs' / rpath, repo, + changeset=changeset) as wd: + yield wd diff --git a/hgitaly/tests/test_servicer.py b/hgitaly/tests/test_servicer.py index dc2defecd55ca00735ea4a143f517f01e666a84e_aGdpdGFseS90ZXN0cy90ZXN0X3NlcnZpY2VyLnB5..15c56172544ffbbafc4bb202096de0a890a07cea_aGdpdGFseS90ZXN0cy90ZXN0X3NlcnZpY2VyLnB5 100644 --- a/hgitaly/tests/test_servicer.py +++ b/hgitaly/tests/test_servicer.py @@ -182,3 +182,37 @@ with pytest.raises(AbortContext): servicer.temp_dir('broken', context, ensure=True) assert context.code == grpc.StatusCode.INTERNAL + + +def test_working_dir(tmpdir): + context = FakeContext() + servicer = HGitalyServicer(dict(default=as_bytes(tmpdir))) + + storage_root = tmpdir.join('repos') + storage_root_bytes = pycompat.sysbytes(str(storage_root)) + servicer = HGitalyServicer(dict(storname=storage_root_bytes)) + # context is used for error raising only + context = FakeContext() + + wrapper = LocalRepoWrapper.init(storage_root.join('awesome-proj.hg')) + gl_repo = Repository(storage_name='storname', + relative_path='awesome-proj.hg') + repo = servicer.load_repo(gl_repo, context) + + with servicer.working_dir(gl_repo, repo, context) as wd: + wd_path = wd.path + wd_wrapper = LocalRepoWrapper.load(wd_path) + sha = wd_wrapper.commit_file('foo').hex() + + wrapper.reload() + ctx = wrapper.repo[sha] + assert ctx.hex() == sha + + with servicer.working_dir(gl_repo, repo, context, changeset=ctx) as wd: + assert wd.path == wd_path + wd_wrapper.reload() + sha2 = wd_wrapper.commit_file('nar').hex() + + wrapper.reload() + ctx2 = wrapper.repo[sha2] + assert ctx2.hex() == sha2