Skip to content
Snippets Groups Projects
Commit 1a6013fb authored by Georges Racinet's avatar Georges Racinet
Browse files

RepositoryService: implement RemoveAll

Actually, this method is called by `gitaly-backup` as of Gitaly 15.10 only
(forwarded to the Rake task in upstream Git commit 4be1f22815bed, part of the
15.11 development cycle, not imported in Heptapod Rails repo yet).

Also, since for the time being an HGitaly storage always comes on top of
a regular Gitaly storage at the same path, we will actually want *not* to
call the HGitaly version for lots of time.
parent 9df798b0
No related branches found
No related tags found
2 merge requests!176Making Heptapod 0.38 the new stable,!170Changes for GitLab 15.9
Pipeline #69098 passed
......@@ -9,6 +9,7 @@
import itertools
import logging
import os
from pathlib import Path
import re
import shutil
import tempfile
......@@ -102,6 +103,8 @@
GetArchiveResponse,
HasLocalBranchesRequest,
HasLocalBranchesResponse,
RemoveAllRequest,
RemoveAllResponse,
RemoveRepositoryRequest,
RemoveRepositoryResponse,
RestoreCustomHooksRequest,
......@@ -625,6 +628,38 @@
gc.collect()
return CreateRepositoryFromBundleResponse()
def RemoveAll(self, request: RemoveAllRequest,
context) -> RemoveAllResponse:
"""Remove everything in the given storage.
This is exactly what Gitaly v15.9 does, hence including all temporary
files etc.
"""
storage = request.storage_name
root_dir = self.storages.get(storage)
if root_dir is None:
context.abort(
StatusCode.INVALID_ARGUMENT,
'remove all: GetStorageByName: '
'no such storage: "%s"' % storage
)
root_dir = Path(os.fsdecode(root_dir)).resolve()
# it would obviously be simpler to use shutil.rmtree() on root_dir
# and recreate the storage afterwards *but*
# - permission not guaranteed on the root dir
# - risky on error recovery
try:
for sub in root_dir.iterdir():
if sub.is_dir() and not sub.is_symlink():
shutil.rmtree(sub)
else:
# also works with broken symlinks (even loops)
sub.unlink()
except Exception as exc:
context.abort(StatusCode.INTERNAL, "remove all: %s" % exc)
return RemoveAllResponse()
def hg_init_repository(self, repository: Repository, context):
"""Initialize a mercurial repository from a request object.
......
......@@ -47,6 +47,7 @@
GetArchiveRequest,
GetCustomHooksRequest,
HasLocalBranchesRequest,
RemoveAllRequest,
RemoveRepositoryRequest,
RepositoryExistsRequest,
RestoreCustomHooksRequest,
......@@ -229,6 +230,9 @@
get_request_iter(ref_patterns)):
fobj.write(chunk.data)
def remove_all(self, storage_name):
return self.stub.RemoveAll(RemoveAllRequest(storage_name=storage_name))
def assert_compare_repos(self, target_repo_path):
"""Compare the fixture repo with another one.
"""
......@@ -1006,3 +1010,25 @@
# is not in the incremental bundle
# TODO do better and assert phases.public
assert unbundled_repo[sha1].phase() == phases.draft
def test_remove_all(fixture_with_repo):
fixture = fixture_with_repo
storage_path = fixture.storage_path('default')
(storage_path / 'foo').write_bytes(b'something')
(storage_path / 'bar').symlink_to('foo')
(storage_path / 'broken').symlink_to('missing')
fixture.remove_all(storage_name='default')
assert list(storage_path.iterdir()) == []
with pytest.raises(grpc.RpcError) as exc_info:
fixture.remove_all(storage_name='unknown')
assert exc_info.value.code() == grpc.StatusCode.INVALID_ARGUMENT
storage_path.rmdir() # create error condition by removing the root dir
with pytest.raises(grpc.RpcError) as exc_info:
fixture.remove_all(storage_name='default')
exc = exc_info.value
assert exc.code() == grpc.StatusCode.INTERNAL
assert "No such file or directory: '%s'" % storage_path in exc.details()
......@@ -21,6 +21,7 @@
CreateRepositoryFromBundleRequest,
FindMergeBaseRequest,
FullPathRequest,
RemoveAllRequest,
RemoveRepositoryRequest,
SearchFilesByNameRequest,
SetFullPathRequest,
......@@ -619,3 +620,17 @@
# unknown ref gives back an empty list of files, not an error
assert_compare(ref=b'unknown', query='.')
def test_remove_all(gitaly_comparison, server_repos_root):
fixture = gitaly_comparison
rpc_helper = fixture.rpc_helper(
stub_cls=RepositoryServiceStub,
method_name='RemoveAll',
request_cls=RemoveAllRequest,
repository_arg=False,
)
assert_compare_errors = rpc_helper.assert_compare_errors
# unknown storage
assert_compare_errors(storage_name='unknown')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment