summaryrefslogtreecommitdiff
path: root/git
diff options
context:
space:
mode:
authorYobmod <yobmod@gmail.com>2021-07-08 23:12:42 +0100
committerYobmod <yobmod@gmail.com>2021-07-08 23:12:42 +0100
commitd344abf5594bebe0147feaba7e87c0079d28374f (patch)
tree6f67e6c07607df2f32dff835263f4301799b4707 /git
parentfe5fef9ebd63ff79e57035cacbe647d096f110bc (diff)
downloadgitpython-d344abf5594bebe0147feaba7e87c0079d28374f.tar.gz
Fix traverse_trees_recursive()
Diffstat (limited to 'git')
-rw-r--r--git/index/fun.py148
-rw-r--r--git/objects/fun.py8
2 files changed, 73 insertions, 83 deletions
diff --git a/git/index/fun.py b/git/index/fun.py
index dbe25276..cd71237d 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -13,7 +13,6 @@ from stat import (
S_IFREG,
S_IXUSR,
)
-
import subprocess
from git.cmd import PROC_CREATIONFLAGS, handle_process_output
@@ -58,11 +57,7 @@ from git.types import PathLike, TypeGuard
if TYPE_CHECKING:
from .base import IndexFile
- from git.objects.fun import EntryTupOrNone
-
-
-def is_three_entry_list(inp) -> TypeGuard[List['EntryTupOrNone']]:
- return isinstance(inp, (tuple, list)) and len(inp) == 3
+ # from git.objects.fun import EntryTupOrNone
# ------------------------------------------------------------------------------------
@@ -192,8 +187,8 @@ def entry_key(*entry: Union[BaseIndexEntry, PathLike, int]) -> Tuple[PathLike, i
""":return: Key suitable to be used for the index.entries dictionary
:param entry: One instance of type BaseIndexEntry or the path and the stage"""
- def is_entry_tuple(entry: Tuple) -> TypeGuard[Tuple[PathLike, int]]:
- return isinstance(entry, tuple) and len(entry) == 2
+ def is_entry_key_tup(entry_key: Tuple) -> TypeGuard[Tuple[PathLike, int]]:
+ return isinstance(entry_key, tuple) and len(entry_key) == 2
if len(entry) == 1:
entry_first = entry[0]
@@ -201,7 +196,7 @@ def entry_key(*entry: Union[BaseIndexEntry, PathLike, int]) -> Tuple[PathLike, i
return (entry_first.path, entry_first.stage)
else:
# entry = tuple(entry)
- assert is_entry_tuple(entry)
+ assert is_entry_key_tup(entry)
return entry
# END handle entry
@@ -340,79 +335,74 @@ def aggressive_tree_merge(odb, tree_shas: Sequence[bytes]) -> List[BaseIndexEntr
raise ValueError("Cannot handle %i trees at once" % len(tree_shas))
# three trees
- entries = traverse_trees_recursive(odb, tree_shas, '')
- base = entries[0]
- ours = entries[1]
- theirs = entries[2]
- assert is_three_entry_list(entries), f"{type(entries)=} and {len(entries)=}" # type:ignore
-
- if base is not None:
- # base version exists
- if ours is not None:
- # ours exists
- if theirs is not None:
- # it exists in all branches, if it was changed in both
- # its a conflict, otherwise we take the changed version
- # This should be the most common branch, so it comes first
- if(base[0] != ours[0] and base[0] != theirs[0] and ours[0] != theirs[0]) or \
- (base[1] != ours[1] and base[1] != theirs[1] and ours[1] != theirs[1]):
- # changed by both
- out.append(_tree_entry_to_baseindexentry(base, 1))
- out.append(_tree_entry_to_baseindexentry(ours, 2))
- out.append(_tree_entry_to_baseindexentry(theirs, 3))
- elif base[0] != ours[0] or base[1] != ours[1]:
- # only we changed it
- out.append(_tree_entry_to_baseindexentry(ours, 0))
+ for base, ours, theirs in traverse_trees_recursive(odb, tree_shas, ''):
+ if base is not None:
+ # base version exists
+ if ours is not None:
+ # ours exists
+ if theirs is not None:
+ # it exists in all branches, if it was changed in both
+ # its a conflict, otherwise we take the changed version
+ # This should be the most common branch, so it comes first
+ if(base[0] != ours[0] and base[0] != theirs[0] and ours[0] != theirs[0]) or \
+ (base[1] != ours[1] and base[1] != theirs[1] and ours[1] != theirs[1]):
+ # changed by both
+ out.append(_tree_entry_to_baseindexentry(base, 1))
+ out.append(_tree_entry_to_baseindexentry(ours, 2))
+ out.append(_tree_entry_to_baseindexentry(theirs, 3))
+ elif base[0] != ours[0] or base[1] != ours[1]:
+ # only we changed it
+ out.append(_tree_entry_to_baseindexentry(ours, 0))
+ else:
+ # either nobody changed it, or they did. In either
+ # case, use theirs
+ out.append(_tree_entry_to_baseindexentry(theirs, 0))
+ # END handle modification
else:
- # either nobody changed it, or they did. In either
- # case, use theirs
- out.append(_tree_entry_to_baseindexentry(theirs, 0))
- # END handle modification
- else:
- if ours[0] != base[0] or ours[1] != base[1]:
- # they deleted it, we changed it, conflict
- out.append(_tree_entry_to_baseindexentry(base, 1))
- out.append(_tree_entry_to_baseindexentry(ours, 2))
- # else:
- # we didn't change it, ignore
- # pass
- # END handle our change
- # END handle theirs
- else:
- if theirs is None:
- # deleted in both, its fine - its out
- pass
+ if ours[0] != base[0] or ours[1] != base[1]:
+ # they deleted it, we changed it, conflict
+ out.append(_tree_entry_to_baseindexentry(base, 1))
+ out.append(_tree_entry_to_baseindexentry(ours, 2))
+ # else:
+ # we didn't change it, ignore
+ # pass
+ # END handle our change
+ # END handle theirs
else:
- if theirs[0] != base[0] or theirs[1] != base[1]:
- # deleted in ours, changed theirs, conflict
- out.append(_tree_entry_to_baseindexentry(base, 1))
- out.append(_tree_entry_to_baseindexentry(theirs, 3))
- # END theirs changed
- # else:
- # theirs didn't change
- # pass
- # END handle theirs
- # END handle ours
- else:
- # all three can't be None
- if ours is None and theirs is not None:
- # added in their branch
- out.append(_tree_entry_to_baseindexentry(theirs, 0))
- elif theirs is None and ours is not None:
- # added in our branch
- out.append(_tree_entry_to_baseindexentry(ours, 0))
- elif ours is not None and theirs is not None:
- # both have it, except for the base, see whether it changed
- if ours[0] != theirs[0] or ours[1] != theirs[1]:
- out.append(_tree_entry_to_baseindexentry(ours, 2))
- out.append(_tree_entry_to_baseindexentry(theirs, 3))
- else:
- # it was added the same in both
+ if theirs is None:
+ # deleted in both, its fine - its out
+ pass
+ else:
+ if theirs[0] != base[0] or theirs[1] != base[1]:
+ # deleted in ours, changed theirs, conflict
+ out.append(_tree_entry_to_baseindexentry(base, 1))
+ out.append(_tree_entry_to_baseindexentry(theirs, 3))
+ # END theirs changed
+ # else:
+ # theirs didn't change
+ # pass
+ # END handle theirs
+ # END handle ours
+ else:
+ # all three can't be None
+ if ours is None and theirs is not None:
+ # added in their branch
+ out.append(_tree_entry_to_baseindexentry(theirs, 0))
+ elif theirs is None and ours is not None:
+ # added in our branch
out.append(_tree_entry_to_baseindexentry(ours, 0))
- # END handle two items
- # END handle heads
- # END handle base exists
-# END for each entries tuple
+ elif ours is not None and theirs is not None:
+ # both have it, except for the base, see whether it changed
+ if ours[0] != theirs[0] or ours[1] != theirs[1]:
+ out.append(_tree_entry_to_baseindexentry(ours, 2))
+ out.append(_tree_entry_to_baseindexentry(theirs, 3))
+ else:
+ # it was added the same in both
+ out.append(_tree_entry_to_baseindexentry(ours, 0))
+ # END handle two items
+ # END handle heads
+ # END handle base exists
+ # END for each entries tuple
return out
diff --git a/git/objects/fun.py b/git/objects/fun.py
index e6ad7892..2abd7b09 100644
--- a/git/objects/fun.py
+++ b/git/objects/fun.py
@@ -144,9 +144,9 @@ def _to_full_path(item: EntryTupOrNone, path_prefix: str) -> EntryTupOrNone:
def traverse_trees_recursive(odb: 'GitCmdObjectDB', tree_shas: Sequence[Union[bytes, None]],
- path_prefix: str) -> List[EntryTupOrNone]:
+ path_prefix: str) -> List[List[EntryTupOrNone]]:
"""
- :return: list with entries according to the given binary tree-shas.
+ :return: list of list with entries according to the given binary tree-shas.
The result is encoded in a list
of n tuple|None per blob/commit, (n == len(tree_shas)), where
* [0] == 20 byte sha
@@ -170,7 +170,7 @@ def traverse_trees_recursive(odb: 'GitCmdObjectDB', tree_shas: Sequence[Union[by
trees_data.append(data)
# END for each sha to get data for
- out = []
+ out: List[List[EntryTupOrNone]] = []
# find all matching entries and recursively process them together if the match
# is a tree. If the match is a non-tree item, put it into the result.
@@ -201,7 +201,7 @@ def traverse_trees_recursive(odb: 'GitCmdObjectDB', tree_shas: Sequence[Union[by
out.extend(traverse_trees_recursive(
odb, [((ei and ei[0]) or None) for ei in entries], path_prefix + name + '/'))
else:
- out.extend([_to_full_path(e, path_prefix) for e in entries])
+ out.append([_to_full_path(e, path_prefix) for e in entries])
# END handle recursion
# finally mark it done