i = 0;
while (PyDict_Next(entries, &pos, &key, &value)) {
PyObject *py_mode, *py_int_mode, *py_sha;
-
+
+ if (!PyString_Check(key)) {
+ PyErr_SetString(PyExc_TypeError, "Name is not a string");
+ free(qsort_entries);
+ return NULL;
+ }
+
if (PyTuple_Size(value) != 2) {
PyErr_SetString(PyExc_ValueError, "Tuple has invalid size");
free(qsort_entries);
}
py_sha = PyTuple_GET_ITEM(value, 1);
- if (!PyString_CheckExact(key)) {
- PyErr_SetString(PyExc_TypeError, "Name is not a string");
+ if (!PyString_Check(py_sha)) {
+ PyErr_SetString(PyExc_TypeError, "SHA is not a string");
free(qsort_entries);
return NULL;
}
the items would be serialized.
:param entries: Dictionary mapping names to (mode, sha) tuples
- :return: Iterator over (name, mode, sha)
+ :return: Iterator over (name, mode, hexsha)
"""
for name, entry in sorted(entries.iteritems(), cmp=cmp_entry):
- yield name, entry[0], entry[1]
+ mode, hexsha = entry
+ # Stricter type checks than normal to mirror checks in the C version.
+ mode = int(mode)
+ if not isinstance(hexsha, str):
+ raise TypeError('Expected a string for SHA, got %r' % hexsha)
+ yield name, mode, hexsha
def cmp_entry((name1, value1), (name2, value2)):
parse_timezone,
parse_tree,
_parse_tree_py,
+ sorted_tree_items,
+ _sorted_tree_items_py,
)
from dulwich.tests import (
TestSkipped,
self.assertCheckFails(Commit, text)
+_TREE_ITEMS = {
+ 'a.c': (0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ 'a': (stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ 'a/c': (stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ }
+
+_SORTED_TREE_ITEMS = [
+ ('a.c', 0100755, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ ('a', stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ ('a/c', stat.S_IFDIR, 'd80c186a03f423a81b39df39dc87fd269736ca86'),
+ ]
+
+
class TreeTests(ShaFileCheckTests):
def test_simple(self):
def test_tree_dir_sort(self):
x = Tree()
- x["a.c"] = (0100755, "d80c186a03f423a81b39df39dc87fd269736ca86")
- x["a"] = (stat.S_IFDIR, "d80c186a03f423a81b39df39dc87fd269736ca86")
- x["a/c"] = (stat.S_IFDIR, "d80c186a03f423a81b39df39dc87fd269736ca86")
- self.assertEquals(["a.c", "a", "a/c"], [p[0] for p in x.iteritems()])
+ for name, item in _TREE_ITEMS.iteritems():
+ x[name] = item
+ self.assertEquals(_SORTED_TREE_ITEMS, list(x.iteritems()))
def _do_test_parse_tree(self, parse_tree):
dir = os.path.join(os.path.dirname(__file__), 'data', 'trees')
raise TestSkipped('parse_tree extension not found')
self._do_test_parse_tree(parse_tree)
+ def _do_test_sorted_tree_items(self, sorted_tree_items):
+ def do_sort(entries):
+ return list(sorted_tree_items(entries))
+
+ self.assertEqual(_SORTED_TREE_ITEMS, do_sort(_TREE_ITEMS))
+
+ # C/Python implementations may differ in specific error types, but
+ # should all error on invalid inputs.
+ # For example, the C implementation has stricter type checks, so may
+ # raise TypeError where the Python implementation raises AttributeError.
+ errors = (TypeError, ValueError, AttributeError)
+ self.assertRaises(errors, do_sort, 'foo')
+ self.assertRaises(errors, do_sort, {'foo': (1, 2, 3)})
+
+ myhexsha = 'd80c186a03f423a81b39df39dc87fd269736ca86'
+ self.assertRaises(errors, do_sort, {'foo': ('xxx', myhexsha)})
+ self.assertRaises(errors, do_sort, {'foo': (0100755, 12345)})
+
+ def test_sorted_tree_items(self):
+ self._do_test_sorted_tree_items(_sorted_tree_items_py)
+
+ def test_sorted_tree_items_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(sorted_tree_items)
+
def test_check(self):
t = Tree
sha = hex_to_sha(a_sha)