dulwich-users team mailing list archive
-
dulwich-users team
-
Mailing list archive
-
Message #00279
[PATCH 01/28] objects: Allow tree entries to be sorted by name.
From: Dave Borowitz <dborowitz@xxxxxxxxxx>
Change-Id: I31e00df32b2a331337b577a55311c5764c04c37c
---
dulwich/_objects.c | 24 +++++++++++++++++++-----
dulwich/objects.py | 25 +++++++++++++++++--------
dulwich/tests/test_objects.py | 19 ++++++++++++++++++-
3 files changed, 54 insertions(+), 14 deletions(-)
diff --git a/dulwich/_objects.c b/dulwich/_objects.c
index 0fe5c34..d100254 100644
--- a/dulwich/_objects.c
+++ b/dulwich/_objects.c
@@ -146,18 +146,32 @@ int cmp_tree_item(const void *_a, const void *_b)
return strcmp(remain_a, remain_b);
}
-static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
+int cmp_tree_item_name_order(const void *_a, const void *_b) {
+ const struct tree_item *a = _a, *b = _b;
+ return strcmp(a->name, b->name);
+}
+
+static PyObject *py_sorted_tree_items(PyObject *self, PyObject *args)
{
struct tree_item *qsort_entries = NULL;
- int num_entries, n = 0, i;
- PyObject *ret, *key, *value, *py_mode, *py_sha;
+ int name_order, num_entries, n = 0, i;
+ PyObject *entries, *py_name_order, *ret, *key, *value, *py_mode, *py_sha;
Py_ssize_t pos = 0;
+ int (*cmp)(const void *, const void *);
+
+ if (!PyArg_ParseTuple(args, "OO", &entries, &py_name_order))
+ goto error;
if (!PyDict_Check(entries)) {
PyErr_SetString(PyExc_TypeError, "Argument not a dictionary");
goto error;
}
+ name_order = PyObject_IsTrue(py_name_order);
+ if (name_order == -1)
+ goto error;
+ cmp = name_order ? cmp_tree_item_name_order : cmp_tree_item;
+
num_entries = PyDict_Size(entries);
if (PyErr_Occurred())
goto error;
@@ -199,7 +213,7 @@ static PyObject *py_sorted_tree_items(PyObject *self, PyObject *entries)
n++;
}
- qsort(qsort_entries, num_entries, sizeof(struct tree_item), cmp_tree_item);
+ qsort(qsort_entries, num_entries, sizeof(struct tree_item), cmp);
ret = PyList_New(num_entries);
if (ret == NULL) {
@@ -223,7 +237,7 @@ error:
static PyMethodDef py_objects_methods[] = {
{ "parse_tree", (PyCFunction)py_parse_tree, METH_VARARGS, NULL },
- { "sorted_tree_items", (PyCFunction)py_sorted_tree_items, METH_O, NULL },
+ { "sorted_tree_items", py_sorted_tree_items, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
diff --git a/dulwich/objects.py b/dulwich/objects.py
index 1878a1f..2d6416a 100644
--- a/dulwich/objects.py
+++ b/dulwich/objects.py
@@ -730,14 +730,17 @@ def serialize_tree(items):
yield "%04o %s\0%s" % (mode, name, hex_to_sha(hexsha))
-def sorted_tree_items(entries):
- """Iterate over a tree entries dictionary in the order in which
- the items would be serialized.
+def sorted_tree_items(entries, name_order):
+ """Iterate over a tree entries dictionary.
+ :param name_order: If True, iterate entries in order of their name. If
+ False, iterate entries in tree order, that is, treat subtree entries as
+ having '/' appended.
:param entries: Dictionary mapping names to (mode, sha) tuples
:return: Iterator over (name, mode, hexsha)
"""
- for name, entry in sorted(entries.iteritems(), cmp=cmp_entry):
+ cmp_func = name_order and cmp_entry_name_order or cmp_entry
+ for name, entry in sorted(entries.iteritems(), cmp=cmp_func):
mode, hexsha = entry
# Stricter type checks than normal to mirror checks in the C version.
mode = int(mode)
@@ -747,7 +750,7 @@ def sorted_tree_items(entries):
def cmp_entry((name1, value1), (name2, value2)):
- """Compare two tree entries."""
+ """Compare two tree entries in tree order."""
if stat.S_ISDIR(value1[0]):
name1 += "/"
if stat.S_ISDIR(value2[0]):
@@ -755,6 +758,11 @@ def cmp_entry((name1, value1), (name2, value2)):
return cmp(name1, name2)
+def cmp_entry_name_order(entry1, entry2):
+ """Compare two tree entries in name order."""
+ return cmp(entry1[0], entry2[0])
+
+
class Tree(ShaFile):
"""A Git tree object"""
@@ -833,13 +841,14 @@ class Tree(ShaFile):
return [
(mode, name, hexsha) for (name, mode, hexsha) in self.iteritems()]
- def iteritems(self):
- """Iterate over entries in the order in which they would be serialized.
+ def iteritems(self, name_order=False):
+ """Iterate over entries.
+ :param name_order: If True, iterate in name order instead of tree order.
:return: Iterator over (name, mode, sha) tuples
"""
self._ensure_parsed()
- return sorted_tree_items(self._entries)
+ return sorted_tree_items(self._entries, name_order)
def items(self):
"""Return the sorted entries in this tree.
diff --git a/dulwich/tests/test_objects.py b/dulwich/tests/test_objects.py
index 6ee6961..f86da62 100644
--- a/dulwich/tests/test_objects.py
+++ b/dulwich/tests/test_objects.py
@@ -476,7 +476,7 @@ class TreeTests(ShaFileCheckTests):
def _do_test_sorted_tree_items(self, sorted_tree_items):
def do_sort(entries):
- return list(sorted_tree_items(entries))
+ return list(sorted_tree_items(entries, False))
actual = do_sort(_TREE_ITEMS)
self.assertEqual(_SORTED_TREE_ITEMS, actual)
@@ -502,6 +502,23 @@ class TreeTests(ShaFileCheckTests):
raise TestSkipped('sorted_tree_items extension not found')
self._do_test_sorted_tree_items(sorted_tree_items)
+ def _do_test_sorted_tree_items_name_order(self, sorted_tree_items):
+ self.assertEqual([
+ TreeEntry('a', stat.S_IFDIR,
+ 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ TreeEntry('a.c', 0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ TreeEntry('a/c', stat.S_IFDIR,
+ 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ ], list(sorted_tree_items(_TREE_ITEMS, True)))
+
+ def test_sorted_tree_items_name_order(self):
+ self._do_test_sorted_tree_items_name_order(_sorted_tree_items_py)
+
+ def test_sorted_tree_items_name_order_extension(self):
+ if sorted_tree_items is _sorted_tree_items_py:
+ raise TestSkipped('sorted_tree_items extension not found')
+ self._do_test_sorted_tree_items_name_order(sorted_tree_items)
+
def test_check(self):
t = Tree
sha = hex_to_sha(a_sha)
--
1.7.3.2.168.gd6b63
References