# HG changeset patch # User RhodeCode Admin # Date 2023-06-06 08:55:47 # Node ID 7aab64a8b5fdb1ed629f2b37cdd34968d8db1d7d # Parent 62b12ad9ede4a0e0466a0336af3df0411685648d git: make use of pygit2 more - detect if is a good git repo - few fixes and cleanups for pygrack diff --git a/vcsserver/remote/git.py b/vcsserver/remote/git.py --- a/vcsserver/remote/git.py +++ b/vcsserver/remote/git.py @@ -186,19 +186,25 @@ class GitRemote(RemoteBase): region = self._region(wire) @region.conditional_cache_on_arguments(condition=cache_on) - def _assert_correct_path(_context_uid, _repo_id): - try: - repo_init = self._factory.repo_libgit2(wire) - with repo_init as repo: - pass - except pygit2.GitError: - path = wire.get('path') - tb = traceback.format_exc() - log.debug("Invalid Git path `%s`, tb: %s", path, tb) + def _assert_correct_path(_context_uid, _repo_id, fast_check): + if fast_check: + path = safe_str(wire['path']) + if pygit2.discover_repository(path): + return True return False + else: + try: + repo_init = self._factory.repo_libgit2(wire) + with repo_init: + pass + except pygit2.GitError: + path = wire.get('path') + tb = traceback.format_exc() + log.debug("Invalid Git path `%s`, tb: %s", path, tb) + return False + return True - return True - return _assert_correct_path(context_uid, repo_id) + return _assert_correct_path(context_uid, repo_id, True) @reraise_safe_exceptions def bare(self, wire): @@ -672,7 +678,7 @@ class GitRemote(RemoteBase): @reraise_safe_exceptions def sync_fetch(self, wire, url, refs=None, all_refs=False): - repo = self._factory.repo(wire) + self._factory.repo(wire) if refs and not isinstance(refs, (list, tuple)): refs = [refs] @@ -1266,7 +1272,7 @@ class GitRemote(RemoteBase): _copts = [] del opts['_bare'] else: - _copts = ['-c', 'core.quotepath=false', ] + _copts = ['-c', 'core.quotepath=false',] safe_call = False if '_safe' in opts: # no exc on failure @@ -1315,9 +1321,8 @@ class GitRemote(RemoteBase): bare = self.bare(wire) path = wire['path'] binary_dir = settings.BINARY_DIR - executable = None if binary_dir: - executable = os.path.join(binary_dir, 'python3') + os.path.join(binary_dir, 'python3') return install_git_hooks(path, bare, force_create=force) @reraise_safe_exceptions @@ -1334,9 +1339,11 @@ class GitRemote(RemoteBase): @reraise_safe_exceptions def set_head_ref(self, wire, head_name): log.debug('Setting refs/head to `%s`', head_name) - cmd = ['symbolic-ref', '"HEAD"', '"refs/heads/%s"' % head_name] - output, __ = self.run_git_command(wire, cmd) - return [head_name] + output.splitlines() + repo_init = self._factory.repo_libgit2(wire) + with repo_init as repo: + repo.set_head(f'refs/heads/{head_name}') + + return [head_name] + [f'set HEAD to refs/heads/{head_name}'] @reraise_safe_exceptions def archive_repo(self, wire, archive_dest_path, kind, mtime, archive_at_path, @@ -1362,14 +1369,14 @@ class GitRemote(RemoteBase): index.read_tree(tree) file_iter = index - for fn in file_iter: - file_path = fn.path - mode = fn.mode + for file_node in file_iter: + file_path = file_node.path + mode = file_node.mode is_link = stat.S_ISLNK(mode) if mode == pygit2.GIT_FILEMODE_COMMIT: log.debug('Skipping path %s as a commit node', file_path) continue - yield ArchiveNode(file_path, mode, is_link, repo[fn.hex].read_raw) + yield ArchiveNode(file_path, mode, is_link, repo[file_node.hex].read_raw) return archive_repo(file_walker, archive_dest_path, kind, mtime, archive_at_path, archive_dir_name, commit_id) diff --git a/vcsserver/tests/test_pygrack.py b/vcsserver/tests/test_pygrack.py --- a/vcsserver/tests/test_pygrack.py +++ b/vcsserver/tests/test_pygrack.py @@ -115,10 +115,14 @@ def test_pull_has_hook_messages(pygrack_ '0000', '0009done\n', ]) + + pre_pull = 'pre_pull_output' + post_pull = 'post_pull_output' + with mock.patch('vcsserver.hooks.git_pre_pull', - return_value=hooks.HookResponse(0, 'foo')): + return_value=hooks.HookResponse(0, pre_pull)): with mock.patch('vcsserver.hooks.git_post_pull', - return_value=hooks.HookResponse(1, 'bar')): + return_value=hooks.HookResponse(1, post_pull)): with mock.patch('vcsserver.subprocessio.SubprocessIOChunker', return_value=more_itertools.always_iterable([b'0008NAK\n0009subp\n0000'])): response = pygrack_app.post( @@ -129,7 +133,11 @@ def test_pull_has_hook_messages(pygrack_ proto = dulwich.protocol.Protocol(data.read, None) packets = list(proto.read_pkt_seq()) - assert packets == [b'NAK\n', b'\x02foo', b'subp\n', b'\x02bar'] + assert packets == [b'NAK\n', + # pre-pull only outputs if IT FAILS as in != 0 ret code + #b'\x02pre_pull_output', + b'subp\n', + b'\x02post_pull_output'] def test_get_want_capabilities(pygrack_instance):