From 96364599258e7e036298dd5737918bde346ec195 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 15 May 2021 22:53:20 +0100 Subject: Add initial types to IndexFile .init() to _to_relative_path() --- git/index/fun.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index e92e8e38..ea7a404b 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -1,6 +1,7 @@ # Contains standalone functions to accompany the index implementation and make it # more versatile # NOTE: Autodoc hates it if this is a docstring +from git.types import PathLike, TBD from io import BytesIO import os from stat import ( @@ -12,6 +13,7 @@ from stat import ( S_IFREG, ) import subprocess +from typing import List, Tuple, Union, cast from git.cmd import PROC_CREATIONFLAGS, handle_process_output from git.compat import ( @@ -166,11 +168,12 @@ def read_header(stream): return version, num_entries -def entry_key(*entry): +def entry_key(entry: Union[Tuple[BaseIndexEntry], Tuple[PathLike, TBD]]): """:return: Key suitable to be used for the index.entries dictionary :param entry: One instance of type BaseIndexEntry or the path and the stage""" if len(entry) == 1: - return (entry[0].path, entry[0].stage) + entry_first = cast(BaseIndexEntry, entry[0]) # type: BaseIndexEntry + return (entry_first.path, entry_first.stage) return tuple(entry) # END handle entry @@ -283,7 +286,7 @@ def _tree_entry_to_baseindexentry(tree_entry, stage): return BaseIndexEntry((tree_entry[1], tree_entry[0], stage << CE_STAGESHIFT, tree_entry[2])) -def aggressive_tree_merge(odb, tree_shas): +def aggressive_tree_merge(odb, tree_shas) -> List[BaseIndexEntry]: """ :return: list of BaseIndexEntries representing the aggressive merge of the given trees. All valid entries are on stage 0, whereas the conflicting ones are left @@ -292,7 +295,7 @@ def aggressive_tree_merge(odb, tree_shas): :param tree_shas: 1, 2 or 3 trees as identified by their binary 20 byte shas If 1 or two, the entries will effectively correspond to the last given tree If 3 are given, a 3 way merge is performed""" - out = [] + out = [] # type: List[BaseIndexEntry] out_append = out.append # one and two way is the same for us, as we don't have to handle an existing -- cgit v1.2.1 From 4dff2004308a7a1e5b9afc7a5b3b9cb515e12514 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 15 May 2021 22:58:47 +0100 Subject: Add initial types to IndexFile .init() to _to_relative_path() --- git/index/fun.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index ea7a404b..85b85ed5 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -1,7 +1,7 @@ # Contains standalone functions to accompany the index implementation and make it # more versatile # NOTE: Autodoc hates it if this is a docstring -from git.types import PathLike, TBD +from git.types import PathLike from io import BytesIO import os from stat import ( @@ -168,13 +168,13 @@ def read_header(stream): return version, num_entries -def entry_key(entry: Union[Tuple[BaseIndexEntry], Tuple[PathLike, TBD]]): +def entry_key(*entry: Union[Tuple[BaseIndexEntry], Tuple[PathLike, int]]): """:return: Key suitable to be used for the index.entries dictionary :param entry: One instance of type BaseIndexEntry or the path and the stage""" - if len(entry) == 1: + if len(*entry) == 1: entry_first = cast(BaseIndexEntry, entry[0]) # type: BaseIndexEntry return (entry_first.path, entry_first.stage) - return tuple(entry) + return tuple(*entry) # END handle entry -- cgit v1.2.1 From c3f91bd1c0e8aef1b416ae6b1f55e7bd93a4f281 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 15 May 2021 23:12:30 +0100 Subject: Add initial types to IndexFile .init() to _to_relative_path() --- git/index/fun.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index 85b85ed5..466d323c 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -13,7 +13,7 @@ from stat import ( S_IFREG, ) import subprocess -from typing import List, Tuple, Union, cast +from typing import List, Tuple, cast from git.cmd import PROC_CREATIONFLAGS, handle_process_output from git.compat import ( @@ -168,13 +168,15 @@ def read_header(stream): return version, num_entries -def entry_key(*entry: Union[Tuple[BaseIndexEntry], Tuple[PathLike, int]]): +def entry_key(*entry) -> Tuple[PathLike, int]: """:return: Key suitable to be used for the index.entries dictionary :param entry: One instance of type BaseIndexEntry or the path and the stage""" - if len(*entry) == 1: + if len(entry) == 1: entry_first = cast(BaseIndexEntry, entry[0]) # type: BaseIndexEntry return (entry_first.path, entry_first.stage) - return tuple(*entry) + else: + entry = cast(Tuple[PathLike, int], tuple(entry)) + return entry # END handle entry -- cgit v1.2.1 From 78d12aa7c922551dddd7168498e29eae32c9d109 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sun, 16 May 2021 18:04:30 +0100 Subject: Add remaining types to IndexFile ._preprocess_add_items() to .diff() --- git/index/fun.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index 466d323c..cc43f0a4 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -13,7 +13,7 @@ from stat import ( S_IFREG, ) import subprocess -from typing import List, Tuple, cast +from typing import List, Tuple, Union, cast from git.cmd import PROC_CREATIONFLAGS, handle_process_output from git.compat import ( @@ -168,7 +168,7 @@ def read_header(stream): return version, num_entries -def entry_key(*entry) -> Tuple[PathLike, int]: +def entry_key(*entry: Union[BaseIndexEntry, PathLike, int]) -> Tuple[PathLike, int]: """:return: Key suitable to be used for the index.entries dictionary :param entry: One instance of type BaseIndexEntry or the path and the stage""" if len(entry) == 1: -- cgit v1.2.1 From 025fe17da390c410e5bae4d6db0832afbfa26442 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Mon, 17 May 2021 13:11:57 +0100 Subject: add types to index.fun.py --- git/index/fun.py | 77 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 31 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index cc43f0a4..95dc3d56 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -1,7 +1,7 @@ # Contains standalone functions to accompany the index implementation and make it # more versatile # NOTE: Autodoc hates it if this is a docstring -from git.types import PathLike + from io import BytesIO import os from stat import ( @@ -13,7 +13,6 @@ from stat import ( S_IFREG, ) import subprocess -from typing import List, Tuple, Union, cast from git.cmd import PROC_CREATIONFLAGS, handle_process_output from git.compat import ( @@ -49,6 +48,17 @@ from .util import ( unpack ) +# typing ----------------------------------------------------------------------------- + +from typing import (Dict, IO, List, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast) + +from git.types import PathLike + +if TYPE_CHECKING: + from .base import IndexFile + +# ------------------------------------------------------------------------------------ + S_IFGITLINK = S_IFLNK | S_IFDIR # a submodule CE_NAMEMASK_INV = ~CE_NAMEMASK @@ -57,12 +67,12 @@ __all__ = ('write_cache', 'read_cache', 'write_tree_from_cache', 'entry_key', 'stat_mode_to_index_mode', 'S_IFGITLINK', 'run_commit_hook', 'hook_path') -def hook_path(name, git_dir): +def hook_path(name: str, git_dir: PathLike) -> str: """:return: path to the given named hook in the given git repository directory""" return osp.join(git_dir, 'hooks', name) -def run_commit_hook(name, index, *args): +def run_commit_hook(name: str, index: IndexFile, *args: str) -> None: """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance @@ -70,10 +80,10 @@ def run_commit_hook(name, index, *args): :raises HookExecutionError: """ hp = hook_path(name, index.repo.git_dir) if not os.access(hp, os.X_OK): - return + return None env = os.environ.copy() - env['GIT_INDEX_FILE'] = safe_decode(index.path) + env['GIT_INDEX_FILE'] = safe_decode(str(index.path)) env['GIT_EDITOR'] = ':' try: cmd = subprocess.Popen([hp] + list(args), @@ -86,14 +96,14 @@ def run_commit_hook(name, index, *args): except Exception as ex: raise HookExecutionError(hp, ex) from ex else: - stdout = [] - stderr = [] - handle_process_output(cmd, stdout.append, stderr.append, finalize_process) - stdout = ''.join(stdout) - stderr = ''.join(stderr) + stdout_list = [] # type: List[str] + stderr_list = [] # type: List[str] + handle_process_output(cmd, stdout_list.append, stderr_list.append, finalize_process) + stdout_str = ''.join(stderr_list) + stderr_str = ''.join(stderr_list) if cmd.returncode != 0: - stdout = force_text(stdout, defenc) - stderr = force_text(stderr, defenc) + stdout = force_text(stdout_str, defenc) + stderr = force_text(stderr_str, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout) # end handle return code @@ -108,7 +118,9 @@ def stat_mode_to_index_mode(mode): return S_IFREG | 0o644 | (mode & 0o111) # blobs with or without executable bit -def write_cache(entries, stream, extension_data=None, ShaStreamCls=IndexFileSHA1Writer): +def write_cache(entries: Sequence[Union[BaseIndexEntry, 'IndexEntry']], stream: IO[bytes], + extension_data: Union[None, bytes] = None, + ShaStreamCls: Type[IndexFileSHA1Writer] = IndexFileSHA1Writer) -> None: """Write the cache represented by entries to a stream :param entries: **sorted** list of entries @@ -121,10 +133,10 @@ def write_cache(entries, stream, extension_data=None, ShaStreamCls=IndexFileSHA1 :param extension_data: any kind of data to write as a trailer, it must begin a 4 byte identifier, followed by its size ( 4 bytes )""" # wrap the stream into a compatible writer - stream = ShaStreamCls(stream) + stream_sha = ShaStreamCls(stream) - tell = stream.tell - write = stream.write + tell = stream_sha.tell + write = stream_sha.write # header version = 2 @@ -136,8 +148,8 @@ def write_cache(entries, stream, extension_data=None, ShaStreamCls=IndexFileSHA1 beginoffset = tell() write(entry[4]) # ctime write(entry[5]) # mtime - path = entry[3] - path = force_bytes(path, encoding=defenc) + path_str = entry[3] # type: str + path = force_bytes(path_str, encoding=defenc) plen = len(path) & CE_NAMEMASK # path length assert plen == len(path), "Path %s too long to fit into index" % entry[3] flags = plen | (entry[2] & CE_NAMEMASK_INV) # clear possible previous values @@ -150,18 +162,19 @@ def write_cache(entries, stream, extension_data=None, ShaStreamCls=IndexFileSHA1 # write previously cached extensions data if extension_data is not None: - stream.write(extension_data) + stream_sha.write(extension_data) # write the sha over the content - stream.write_sha() + stream_sha.write_sha() -def read_header(stream): +def read_header(stream: IO[bytes]) -> Tuple[int, int]: """Return tuple(version_long, num_entries) from the given stream""" type_id = stream.read(4) if type_id != b"DIRC": raise AssertionError("Invalid index file header: %r" % type_id) - version, num_entries = unpack(">LL", stream.read(4 * 2)) + unpacked = cast(Tuple[int, int], unpack(">LL", stream.read(4 * 2))) + version, num_entries = unpacked # TODO: handle version 3: extended data, see read-cache.c assert version in (1, 2) @@ -180,7 +193,7 @@ def entry_key(*entry: Union[BaseIndexEntry, PathLike, int]) -> Tuple[PathLike, i # END handle entry -def read_cache(stream): +def read_cache(stream: IO[bytes]) -> Tuple[int, Dict[Tuple[PathLike, int], 'IndexEntry'], bytes, bytes]: """Read a cache file from the given stream :return: tuple(version, entries_dict, extension_data, content_sha) * version is the integer version number @@ -189,7 +202,7 @@ def read_cache(stream): * content_sha is a 20 byte sha on all cache file contents""" version, num_entries = read_header(stream) count = 0 - entries = {} + entries = {} # type: Dict[Tuple[PathLike, int], 'IndexEntry'] read = stream.read tell = stream.tell @@ -228,7 +241,8 @@ def read_cache(stream): return (version, entries, extension_data, content_sha) -def write_tree_from_cache(entries, odb, sl, si=0): +def write_tree_from_cache(entries: List[IndexEntry], odb, sl: slice, si: int = 0 + ) -> Tuple[bytes, List[Tuple[str, int, str]]]: """Create a tree from the given sorted list of entries and put the respective trees into the given object database @@ -238,7 +252,7 @@ def write_tree_from_cache(entries, odb, sl, si=0): :param sl: slice indicating the range we should process on the entries list :return: tuple(binsha, list(tree_entry, ...)) a tuple of a sha and a list of tree entries being a tuple of hexsha, mode, name""" - tree_items = [] + tree_items = [] # type: List[Tuple[Union[bytes, str], int, str]] tree_items_append = tree_items.append ci = sl.start end = sl.stop @@ -277,18 +291,19 @@ def write_tree_from_cache(entries, odb, sl, si=0): # finally create the tree sio = BytesIO() - tree_to_stream(tree_items, sio.write) + tree_to_stream(tree_items, sio.write) # converts bytes of each item[0] to str + tree_items_stringified = cast(List[Tuple[str, int, str]], tree_items) # type: List[Tuple[str, int, str]] sio.seek(0) istream = odb.store(IStream(str_tree_type, len(sio.getvalue()), sio)) - return (istream.binsha, tree_items) + return (istream.binsha, tree_items_stringified) -def _tree_entry_to_baseindexentry(tree_entry, stage): +def _tree_entry_to_baseindexentry(tree_entry: Tuple[str, int, str], stage: int) -> BaseIndexEntry: return BaseIndexEntry((tree_entry[1], tree_entry[0], stage << CE_STAGESHIFT, tree_entry[2])) -def aggressive_tree_merge(odb, tree_shas) -> List[BaseIndexEntry]: +def aggressive_tree_merge(odb, tree_shas: Sequence[bytes]) -> List[BaseIndexEntry]: """ :return: list of BaseIndexEntries representing the aggressive merge of the given trees. All valid entries are on stage 0, whereas the conflicting ones are left -- cgit v1.2.1 From 473fc3a348cd09b4ffca319daff32464d10d8ef9 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Mon, 17 May 2021 13:15:48 +0100 Subject: forward reference for IndexFile --- git/index/fun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index 95dc3d56..d9fe4108 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -72,7 +72,7 @@ def hook_path(name: str, git_dir: PathLike) -> str: return osp.join(git_dir, 'hooks', name) -def run_commit_hook(name: str, index: IndexFile, *args: str) -> None: +def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None: """Run the commit hook of the given name. Silently ignores hooks that do not exist. :param name: name of hook, like 'pre-commit' :param index: IndexFile instance -- cgit v1.2.1 From f08d3067310e0251e6d5a33dc5bc65f1b76a2d49 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Mon, 17 May 2021 18:06:13 +0100 Subject: forward reference for IndexFile --- git/index/fun.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index d9fe4108..c8a7617e 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -96,16 +96,17 @@ def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None: except Exception as ex: raise HookExecutionError(hp, ex) from ex else: - stdout_list = [] # type: List[str] - stderr_list = [] # type: List[str] + stdout_list = [] # type: List[str] + stderr_list = [] # type: List[str] handle_process_output(cmd, stdout_list.append, stderr_list.append, finalize_process) - stdout_str = ''.join(stderr_list) - stderr_str = ''.join(stderr_list) + stdout = ''.join(stdout_list) + stderr = ''.join(stderr_list) if cmd.returncode != 0: - stdout = force_text(stdout_str, defenc) - stderr = force_text(stderr_str, defenc) + stdout = force_text(stdout, defenc) + stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout) # end handle return code + # end handle return code def stat_mode_to_index_mode(mode): -- cgit v1.2.1 From c30bf3ba7548a0e996907b9a097ec322760eb43a Mon Sep 17 00:00:00 2001 From: Yobmod Date: Mon, 17 May 2021 18:13:20 +0100 Subject: Tidy up some comments --- git/index/fun.py | 1 - 1 file changed, 1 deletion(-) (limited to 'git/index/fun.py') diff --git a/git/index/fun.py b/git/index/fun.py index c8a7617e..f40928c3 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -106,7 +106,6 @@ def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None: stderr = force_text(stderr, defenc) raise HookExecutionError(hp, cmd.returncode, stderr, stdout) # end handle return code - # end handle return code def stat_mode_to_index_mode(mode): -- cgit v1.2.1