Commit d05c10cb authored by Sushil Khanchi's avatar Sushil Khanchi 🐨
Browse files

DiffService: implement FindChangedPaths

parent 3ef9b3fcdc23
......@@ -10,6 +10,7 @@
import attr
from ..errors import (
not_found,
unknown_error,
unavailable_error,
)
......@@ -21,6 +22,7 @@
EMPTY_TREE_OID,
)
from mercurial import (
copies,
node,
patch as patchmod,
pycompat,
......@@ -29,6 +31,7 @@
scmutil,
)
from ..stub.diff_pb2 import (
ChangedPaths,
CommitDiffRequest,
CommitDiffResponse,
CommitDelta as MsgCommitDelta,
......@@ -55,6 +58,7 @@
split_batches,
WRITE_BUFFER_SIZE,
)
from ..util import chunked
logger = logging.getLogger(__name__)
......@@ -94,6 +98,15 @@
"""MAX_PATCH_BYTES_UPPERBOUND controls how much max_patch_bytes limit can reach
"""
Status_Type_Map = dict(
added=ChangedPaths.Status.ADDED,
modified=ChangedPaths.Status.MODIFIED,
removed=ChangedPaths.Status.DELETED,
copied=ChangedPaths.Status.COPIED,
# Note: Mercurial includes TYPE_CHANGE
# (symlink, regular file, submodule...etc) in MODIFIED status
)
@attr.s
class Limits:
......@@ -461,8 +474,42 @@
def FindChangedPaths(self, request: FindChangedPathsRequest,
context) -> FindChangedPathsResponse:
return not_implemented(context, FindChangedPathsResponse,
issue=54) # pragma no cover
repo = self.load_repo(request.repository, context)
csets = []
for cid in request.commits:
ctx = gitlab_revision_changeset(repo, parse_diff_request_cid(cid))
if ctx is None:
yield not_found(
context, FindChangedPathsResponse,
'FindChangedPaths: commit: %s can not be '
'found' % pycompat.sysstr(cid)
)
return
csets.append(ctx)
def in_changed_paths():
for ctx in csets:
p1 = ctx.p1()
status = p1.status(ctx)
for path in _status_paths(status, Status_Type_Map):
yield path
copy = copies.pathcopies(p1, ctx)
for path in copy:
yield ChangedPaths(
path=path,
status=Status_Type_Map['copied']
)
for paths in chunked(in_changed_paths()):
yield FindChangedPathsResponse(paths=paths)
def _status_paths(status, type_map):
for stype in ['added', 'modified', 'removed']:
for path in status.__getattribute__(stype):
yield ChangedPaths(
path=path,
status=type_map[stype]
)
def parse_diff_request_cid(cid):
......
......@@ -5,6 +5,7 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
import grpc
from mercurial.pycompat import sysstr
import pytest
from hgitaly.git import (
EMPTY_TREE_OID,
......@@ -15,6 +16,7 @@
from hgitaly.stub.diff_pb2 import (
CommitDeltaRequest,
CommitDiffRequest,
ChangedPaths,
DiffStatsRequest,
RawDiffRequest,
RawPatchRequest,
......@@ -18,6 +20,7 @@
DiffStatsRequest,
RawDiffRequest,
RawPatchRequest,
FindChangedPathsRequest,
)
from mercurial import (
node,
......@@ -474,3 +477,53 @@
with pytest.raises(grpc.RpcError) as exc_info:
do_rpc(sha_not_exists, ctx3.hex())
assert exc_info.value.code() == grpc.StatusCode.UNAVAILABLE
def test_find_changed_paths(grpc_channel, server_repos_root):
grpc_stub = DiffServiceStub(grpc_channel)
wrapper, grpc_repo = make_empty_repo(server_repos_root)
(wrapper.path / 'foo').write_text('foo content')
(wrapper.path / 'bar').write_text('bar content')
(wrapper.path / 'zoo').write_text('zoo content')
wrapper.commit(rel_paths=['foo', 'bar', 'zoo'],
add_remove=True)
(wrapper.path / 'too').write_text('too content')
(wrapper.path / 'foo').write_text('foo content modified')
(wrapper.path / 'bar').unlink()
wrapper.command(b'cp', wrapper.repo.root + b'/zoo',
wrapper.repo.root + b'/zaz')
ctx1 = wrapper.commit(rel_paths=['foo', 'bar', 'zaz', 'too'],
add_remove=True)
def do_rpc(commits):
request = FindChangedPathsRequest(
repository=grpc_repo,
commits=commits,
)
response = grpc_stub.FindChangedPaths(request)
resp_dict = dict()
for resp in response:
for changed_path in resp.paths:
resp_dict[changed_path.path] = changed_path.status
return resp_dict
# Actual test (for ctx1)
resp_dict = {
b'too': ChangedPaths.Status.ADDED,
b'foo': ChangedPaths.Status.MODIFIED,
b'bar': ChangedPaths.Status.DELETED,
b'zaz': ChangedPaths.Status.COPIED,
}
assert do_rpc([ctx1.hex()]) == resp_dict
# when commit_id does not correspond to a commit
wrong_cid = b'12face12' * 5
with pytest.raises(grpc.RpcError) as exc_info:
do_rpc([wrong_cid])
assert exc_info.value.code() == grpc.StatusCode.NOT_FOUND
assert (
'FindChangedPaths: commit: %s can not be found' % (sysstr(wrong_cid))
==
exc_info.value.details()
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment