Add support for using short hex string prefixes
Allows Repository_getitem, Repository_read(_raw), Repository_create_commit, Repository_create_tag and Object_read_raw to use short hex strings to lookup objects. Also test getting objects from Repository using prefixes, looking up commit trees and parents by hex prefix, and looking up tag targets by prefix. Also stop raising TypeError if passing a too-short hex prefix to the lookup functions, instead use ValueError.
This commit is contained in:
parent
73af642b8f
commit
160cf64abc
45
pygit2.c
45
pygit2.c
@ -190,9 +190,10 @@ Error_set_py_obj(int err, PyObject *py_obj)
|
||||
|
||||
assert(err < 0);
|
||||
|
||||
if (err == GIT_ENOTOID && !PyString_Check(py_obj)) {
|
||||
if (err == GIT_ENOTOID && !PyString_Check(py_obj)
|
||||
&& !PyUnicode_Check(py_obj)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Git object id must be byte string, not: %.200s",
|
||||
"Git object id must be byte or a text string, not: %.200s",
|
||||
Py_TYPE(py_obj)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
@ -209,17 +210,19 @@ Error_set_py_obj(int err, PyObject *py_obj)
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
lookup_object(Repository *repo, const git_oid *oid, git_otype type)
|
||||
lookup_object_prefix(Repository *repo, const git_oid *oid, size_t len,
|
||||
git_otype type)
|
||||
{
|
||||
int err;
|
||||
char hex[GIT_OID_HEXSZ + 1];
|
||||
git_object *obj;
|
||||
Object *py_obj = NULL;
|
||||
|
||||
err = git_object_lookup(&obj, repo->repo, oid, type);
|
||||
err = git_object_lookup_prefix(&obj, repo->repo, oid,
|
||||
(unsigned int)len, type);
|
||||
if (err < 0) {
|
||||
git_oid_fmt(hex, oid);
|
||||
hex[GIT_OID_HEXSZ] = '\0';
|
||||
hex[len] = '\0';
|
||||
return Error_set_str(err, hex);
|
||||
}
|
||||
|
||||
@ -248,6 +251,12 @@ lookup_object(Repository *repo, const git_oid *oid, git_otype type)
|
||||
return (PyObject*)py_obj;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
lookup_object(Repository *repo, const git_oid *oid, git_otype type)
|
||||
{
|
||||
return lookup_object_prefix(repo, oid, GIT_OID_HEXSZ, type);
|
||||
}
|
||||
|
||||
static git_otype
|
||||
int_to_loose_object_type(int type_id)
|
||||
{
|
||||
@ -415,18 +424,18 @@ Repository_getitem(Repository *self, PyObject *value)
|
||||
size_t len;
|
||||
|
||||
len = py_str_to_git_oid(value, &oid);
|
||||
TODO_SUPPORT_SHORT_HEXS(len)
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
return lookup_object(self, &oid, GIT_OBJ_ANY);
|
||||
return lookup_object_prefix(self, &oid, len, GIT_OBJ_ANY);
|
||||
}
|
||||
|
||||
static int
|
||||
Repository_read_raw(git_odb_object **obj, git_repository *repo,
|
||||
const git_oid *oid)
|
||||
const git_oid *oid, size_t len)
|
||||
{
|
||||
return git_odb_read(obj, git_repository_database(repo), oid);
|
||||
return git_odb_read_prefix(obj, git_repository_database(repo),
|
||||
oid, (unsigned int)len);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@ -438,11 +447,10 @@ Repository_read(Repository *self, PyObject *py_hex)
|
||||
size_t len;
|
||||
|
||||
len = py_str_to_git_oid(py_hex, &oid);
|
||||
TODO_SUPPORT_SHORT_HEXS(len)
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
err = Repository_read_raw(&obj, self->repo, &oid);
|
||||
err = Repository_read_raw(&obj, self->repo, &oid, len);
|
||||
if (err < 0)
|
||||
return Error_set_py_obj(err, py_hex);
|
||||
|
||||
@ -659,13 +667,12 @@ Repository_create_commit(Repository *self, PyObject *args)
|
||||
return NULL;
|
||||
|
||||
len = py_str_to_git_oid(py_oid, &oid);
|
||||
TODO_SUPPORT_SHORT_HEXS(len)
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
message = py_str_to_c_str(py_message);
|
||||
|
||||
err = git_tree_lookup(&tree, self->repo, &oid);
|
||||
err = git_tree_lookup_prefix(&tree, self->repo, &oid, (unsigned int)len);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
@ -679,12 +686,12 @@ Repository_create_commit(Repository *self, PyObject *args)
|
||||
for (i = 0; i < parent_count; i++) {
|
||||
py_parent = PyList_GET_ITEM(py_parents, i);
|
||||
len = py_str_to_git_oid(py_parent, &oid);
|
||||
TODO_SUPPORT_SHORT_HEXS(len)
|
||||
if (len == 0) {
|
||||
git_tree_close(tree);
|
||||
return free_parents(parents, i);
|
||||
}
|
||||
if (git_commit_lookup(&parents[i], self->repo, &oid)) {
|
||||
if (git_commit_lookup_prefix(&parents[i], self->repo, &oid,
|
||||
(unsigned int)len)) {
|
||||
git_tree_close(tree);
|
||||
return free_parents(parents, i);
|
||||
}
|
||||
@ -721,14 +728,14 @@ Repository_create_tag(Repository *self, PyObject *args)
|
||||
return NULL;
|
||||
|
||||
len = py_str_to_git_oid(py_oid, &oid);
|
||||
TODO_SUPPORT_SHORT_HEXS(len)
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
err = git_object_lookup(&target, self->repo, &oid, target_type);
|
||||
err = git_object_lookup_prefix(&target, self->repo, &oid,
|
||||
(unsigned int)len, target_type);
|
||||
if (err < 0) {
|
||||
git_oid_fmt(hex, &oid);
|
||||
hex[GIT_OID_HEXSZ] = '\0';
|
||||
hex[len] = '\0';
|
||||
return Error_set_str(err, hex);
|
||||
}
|
||||
|
||||
@ -1041,7 +1048,7 @@ Object_read_raw(Object *self)
|
||||
oid = git_object_id(self->obj);
|
||||
assert(oid);
|
||||
|
||||
err = Repository_read_raw(&obj, self->repo->repo, oid);
|
||||
err = Repository_read_raw(&obj, self->repo->repo, oid, GIT_OID_HEXSZ);
|
||||
if (err < 0) {
|
||||
aux = git_oid_to_py_str(oid);
|
||||
Error_set_py_obj(err, aux);
|
||||
|
@ -71,10 +71,15 @@ class CommitTest(utils.BareRepoTestCase):
|
||||
committer = ('John Doe', 'jdoe@example.com', 12346, 0)
|
||||
author = ('J. David Ibáñez', 'jdavid@example.com', 12345, 0)
|
||||
tree = '967fce8df97cc71722d3c2a5930ef3e6f1d27b12'
|
||||
tree_prefix = tree[:5]
|
||||
too_short_prefix = tree[:3]
|
||||
|
||||
parents = [COMMIT_SHA]
|
||||
sha = repo.create_commit(None, author, committer, message, tree,
|
||||
parents)
|
||||
parents = [COMMIT_SHA[:5]]
|
||||
self.assertRaises(ValueError, repo.create_commit, None, author,
|
||||
committer, message, too_short_prefix, parents)
|
||||
|
||||
sha = repo.create_commit(None, author, committer, message,
|
||||
tree_prefix, parents)
|
||||
commit = repo[sha]
|
||||
|
||||
self.assertEqual(GIT_OBJ_COMMIT, commit.type)
|
||||
|
@ -58,6 +58,10 @@ class RepositoryTest(utils.BareRepoTestCase):
|
||||
|
||||
a2 = self.repo.read('7f129fd57e31e935c6d60a0c794efe4e6927664b')
|
||||
self.assertEqual((GIT_OBJ_BLOB, 'a contents 2\n'), a2)
|
||||
|
||||
a_hex_prefix = A_HEX_SHA[:4]
|
||||
a3 = self.repo.read(a_hex_prefix)
|
||||
self.assertEqual((GIT_OBJ_BLOB, 'a contents\n'), a3)
|
||||
|
||||
def test_write(self):
|
||||
data = b"hello world"
|
||||
@ -82,6 +86,12 @@ class RepositoryTest(utils.BareRepoTestCase):
|
||||
self.assertEqual(A_HEX_SHA, a.hex)
|
||||
self.assertEqual(GIT_OBJ_BLOB, a.type)
|
||||
|
||||
def test_lookup_blob_prefix(self):
|
||||
a = self.repo[A_HEX_SHA[:5]]
|
||||
self.assertEqual(b'a contents\n', a.read_raw())
|
||||
self.assertEqual(A_HEX_SHA, a.hex)
|
||||
self.assertEqual(GIT_OBJ_BLOB, a.type)
|
||||
|
||||
def test_lookup_commit(self):
|
||||
commit_sha = '5fe808e8953c12735680c257f56600cb0de44b10'
|
||||
commit = self.repo[commit_sha]
|
||||
@ -91,6 +101,18 @@ class RepositoryTest(utils.BareRepoTestCase):
|
||||
'This commit has some additional text.\n'),
|
||||
commit.message)
|
||||
|
||||
def test_lookup_commit_prefix(self):
|
||||
commit_sha = '5fe808e8953c12735680c257f56600cb0de44b10'
|
||||
commit_sha_prefix = commit_sha[:7]
|
||||
too_short_prefix = commit_sha[:3]
|
||||
commit = self.repo[commit_sha_prefix]
|
||||
self.assertEqual(commit_sha, commit.hex)
|
||||
self.assertEqual(GIT_OBJ_COMMIT, commit.type)
|
||||
self.assertEqual(('Second test data commit.\n\n'
|
||||
'This commit has some additional text.\n'),
|
||||
commit.message)
|
||||
self.assertRaises(ValueError, self.repo.__getitem__, too_short_prefix)
|
||||
|
||||
def test_get_path(self):
|
||||
directory = realpath(self.repo.path)
|
||||
expected = realpath(join(self._temp_dir, 'testrepo.git'))
|
||||
|
@ -62,8 +62,13 @@ class TagTest(utils.BareRepoTestCase):
|
||||
message = 'Tag a blob.\n'
|
||||
tagger = ('John Doe', 'jdoe@example.com', 12347, 0)
|
||||
|
||||
sha = self.repo.create_tag(name, target, pygit2.GIT_OBJ_BLOB, tagger,
|
||||
message)
|
||||
target_prefix = target[:5]
|
||||
too_short_prefix = target[:3]
|
||||
self.assertRaises(ValueError, self.repo.create_tag, name,
|
||||
too_short_prefix, pygit2.GIT_OBJ_BLOB, tagger,
|
||||
message)
|
||||
sha = self.repo.create_tag(name, target_prefix, pygit2.GIT_OBJ_BLOB,
|
||||
tagger, message)
|
||||
tag = self.repo[sha]
|
||||
|
||||
self.assertEqual('3ee44658fd11660e828dfc96b9b5c5f38d5b49bb', tag.hex)
|
||||
|
Loading…
x
Reference in New Issue
Block a user