summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git/objects/tree.py50
-rw-r--r--git/test/test_tree.py20
2 files changed, 69 insertions, 1 deletions
diff --git a/git/objects/tree.py b/git/objects/tree.py
index f9bee01e..24c88ee0 100644
--- a/git/objects/tree.py
+++ b/git/objects/tree.py
@@ -18,9 +18,53 @@ from .fun import (
tree_to_stream
)
+from gitdb.utils.compat import PY3
+
+if PY3:
+ cmp = lambda a, b: (a > b) - (a < b)
+
__all__ = ("TreeModifier", "Tree")
+def git_cmp(t1, t2):
+ a, b = t1[2], t2[2]
+ len_a, len_b = len(a), len(b)
+ min_len = min(len_a, len_b)
+ min_cmp = cmp(a[:min_len], b[:min_len])
+
+ if min_cmp:
+ return min_cmp
+
+ # return len_a - len_b
+ return len_b - len_a
+
+if PY3:
+ # taken from https://wiki.python.org/moin/HowTo/Sorting#The_Old_Way_Using_the_cmp_Parameter
+ class CmpToKey(object):
+ __slots__ = 'obj'
+
+ def __init__(self, obj, *args):
+ self.obj = obj
+
+ def __lt__(self, other):
+ return git_cmp(self.obj, other.obj) < 0
+
+ def __gt__(self, other):
+ return git_cmp(self.obj, other.obj) > 0
+
+ def __eq__(self, other):
+ return git_cmp(self.obj, other.obj) == 0
+
+ def __le__(self, other):
+ return git_cmp(self.obj, other.obj) <= 0
+
+ def __ge__(self, other):
+ return git_cmp(self.obj, other.obj) >= 0
+
+ def __ne__(self, other):
+ return git_cmp(self.obj, other.obj) != 0
+
+
class TreeModifier(object):
"""A utility class providing methods to alter the underlying cache in a list-like fashion.
@@ -47,7 +91,10 @@ class TreeModifier(object):
It may be called several times, but be aware that each call will cause
a sort operation
:return self:"""
- self._cache.sort(key=lambda t: t[2]) # sort by name
+ if PY3:
+ self._cache.sort(key=CmpToKey)
+ else:
+ self._cache.sort(cmp=git_cmp)
return self
#} END interface
@@ -286,3 +333,4 @@ class Tree(IndexObject, diff.Diffable, util.Traversable, util.Serializable):
# finalize map definition
Tree._map_id_to_type[Tree.tree_id] = Tree
+#
diff --git a/git/test/test_tree.py b/git/test/test_tree.py
index 7a16b777..5e94e70b 100644
--- a/git/test/test_tree.py
+++ b/git/test/test_tree.py
@@ -77,10 +77,30 @@ class TestTree(TestBase):
# del again, its fine
del(mod[invalid_name])
+ # SPECIAL ORDERING !
+ # Add items which should sort differently from standard alum sort order
+ mod.add(hexsha, Tree.blob_id << 12, 'fild')
+ mod.add(hexsha, Tree.blob_id << 12, 'file')
+ mod.add(hexsha, Tree.blob_id << 12, 'file.second')
+ mod.add(hexsha, Tree.blob_id << 12, 'filf')
+
+ def names_in_mod_cache():
+ return [t[2] for t in mod._cache]
+
+ def chunk_from(a, name, size):
+ index = a.index(name)
+ return a[index:index + size]
+
+ assert chunk_from(names_in_mod_cache(), 'fild', 4) == ['fild', 'file', 'file.second',
+ 'filf']
+
# have added one item, we are done
mod.set_done()
mod.set_done() # multiple times are okay
+ assert chunk_from(names_in_mod_cache(), 'fild', 4) == ['fild', 'file.second', 'file',
+ 'filf']
+
# serialize, its different now
stream = BytesIO()
testtree._serialize(stream)