Skip to content

Commit d28c20b

Browse files
authored
Merge pull request #1799 from et-repositories/main
fix: treeNotSorted issue
2 parents 6978325 + bda5a17 commit d28c20b

File tree

3 files changed

+60
-49
lines changed

3 files changed

+60
-49
lines changed

Diff for: AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,6 @@ Contributors are:
5353
-Santos Gallegos <stsewd _at_ proton.me>
5454
-Wenhan Zhu <wzhu.cosmos _at_ gmail.com>
5555
-Eliah Kagan <eliah.kagan _at_ gmail.com>
56+
-Ethan Lin <et.repositories _at_ gmail.com>
5657

5758
Portions derived from other open source works and are clearly marked.

Diff for: git/objects/tree.py

+1-49
Original file line numberDiff line numberDiff line change
@@ -53,54 +53,6 @@
5353
__all__ = ("TreeModifier", "Tree")
5454

5555

56-
def git_cmp(t1: TreeCacheTup, t2: TreeCacheTup) -> int:
57-
a, b = t1[2], t2[2]
58-
# assert isinstance(a, str) and isinstance(b, str)
59-
len_a, len_b = len(a), len(b)
60-
min_len = min(len_a, len_b)
61-
min_cmp = cmp(a[:min_len], b[:min_len])
62-
63-
if min_cmp:
64-
return min_cmp
65-
66-
return len_a - len_b
67-
68-
69-
def merge_sort(a: List[TreeCacheTup], cmp: Callable[[TreeCacheTup, TreeCacheTup], int]) -> None:
70-
if len(a) < 2:
71-
return
72-
73-
mid = len(a) // 2
74-
lefthalf = a[:mid]
75-
righthalf = a[mid:]
76-
77-
merge_sort(lefthalf, cmp)
78-
merge_sort(righthalf, cmp)
79-
80-
i = 0
81-
j = 0
82-
k = 0
83-
84-
while i < len(lefthalf) and j < len(righthalf):
85-
if cmp(lefthalf[i], righthalf[j]) <= 0:
86-
a[k] = lefthalf[i]
87-
i = i + 1
88-
else:
89-
a[k] = righthalf[j]
90-
j = j + 1
91-
k = k + 1
92-
93-
while i < len(lefthalf):
94-
a[k] = lefthalf[i]
95-
i = i + 1
96-
k = k + 1
97-
98-
while j < len(righthalf):
99-
a[k] = righthalf[j]
100-
j = j + 1
101-
k = k + 1
102-
103-
10456
class TreeModifier:
10557
"""A utility class providing methods to alter the underlying cache in a list-like fashion.
10658
@@ -131,7 +83,7 @@ def set_done(self) -> "TreeModifier":
13183
13284
:return self:
13385
"""
134-
merge_sort(self._cache, git_cmp)
86+
self._cache.sort(key=lambda x: (x[2] + "/") if x[1] == Tree.tree_id << 12 else x[2])
13587
return self
13688

13789
# } END interface

Diff for: test/test_tree.py

+58
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
from git.objects import Tree, Blob
99
from test.lib import TestBase
1010

11+
import os
1112
import os.path as osp
13+
import subprocess
1214

1315

1416
class TestTree(TestBase):
@@ -40,6 +42,62 @@ def test_serializable(self):
4042
testtree._deserialize(stream)
4143
# END for each item in tree
4244

45+
def test_tree_modifier_ordering(self):
46+
def setup_git_repository_and_get_ordered_files():
47+
os.mkdir("tmp")
48+
os.chdir("tmp")
49+
subprocess.run(["git", "init", "-q"], check=True)
50+
os.mkdir("file")
51+
for filename in [
52+
"bin",
53+
"bin.d",
54+
"file.to",
55+
"file.toml",
56+
"file.toml.bin",
57+
"file0",
58+
"file/a",
59+
]:
60+
open(filename, "a").close()
61+
62+
subprocess.run(["git", "add", "."], check=True)
63+
subprocess.run(["git", "commit", "-m", "c1"], check=True)
64+
tree_hash = subprocess.check_output(["git", "rev-parse", "HEAD^{tree}"]).decode().strip()
65+
cat_file_output = subprocess.check_output(["git", "cat-file", "-p", tree_hash]).decode()
66+
return [line.split()[-1] for line in cat_file_output.split("\n") if line]
67+
68+
hexsha = "6c1faef799095f3990e9970bc2cb10aa0221cf9c"
69+
roottree = self.rorepo.tree(hexsha)
70+
blob_mode = Tree.blob_id << 12
71+
tree_mode = Tree.tree_id << 12
72+
73+
files_in_desired_order = [
74+
(blob_mode, "bin"),
75+
(blob_mode, "bin.d"),
76+
(blob_mode, "file.to"),
77+
(blob_mode, "file.toml"),
78+
(blob_mode, "file.toml.bin"),
79+
(blob_mode, "file0"),
80+
(tree_mode, "file"),
81+
]
82+
mod = roottree.cache
83+
for file_mode, file_name in files_in_desired_order:
84+
mod.add(hexsha, file_mode, file_name)
85+
# end for each file
86+
87+
def file_names_in_order():
88+
return [t[1] for t in files_in_desired_order]
89+
90+
def names_in_mod_cache():
91+
a = [t[2] for t in mod._cache]
92+
here = file_names_in_order()
93+
return [e for e in a if e in here]
94+
95+
git_file_names_in_order = setup_git_repository_and_get_ordered_files()
96+
os.chdir("..")
97+
98+
mod.set_done()
99+
assert names_in_mod_cache() == git_file_names_in_order, "set_done() performs git-sorting"
100+
43101
def test_traverse(self):
44102
root = self.rorepo.tree("0.1.6")
45103
num_recursive = 0

0 commit comments

Comments
 (0)