Commit 13f7ecd7 by Russell Belfer

Add git_object_short_id API to get short id string

This finds a short id string that will unambiguously select the
given object, starting with the core.abbrev length (usually 7)
and growing until it is no longer ambiguous.
parent f5753999
......@@ -10,6 +10,7 @@
#include "common.h"
#include "types.h"
#include "oid.h"
#include "buffer.h"
/**
* @file git2/object.h
......@@ -104,6 +105,15 @@ GIT_EXTERN(int) git_object_lookup_bypath(
GIT_EXTERN(const git_oid *) git_object_id(const git_object *obj);
/**
* Get a short abbreviated OID string for the object
*
* @param out Buffer to write string into
* @param obj The object to get an ID for
* @return 0 on success, <0 for error
*/
GIT_EXTERN(int) git_object_short_id(git_buf *out, const git_object *obj);
/**
* Get the object type of an object
*
* @param obj the repository object
......
......@@ -397,3 +397,46 @@ cleanup:
git_tree_free(tree);
return error;
}
int git_object_short_id(git_buf *out, const git_object *obj)
{
git_repository *repo;
int len = GIT_ABBREV_DEFAULT, error;
git_oid id = {{0}};
git_odb *odb;
assert(out && obj);
git_buf_sanitize(out);
repo = git_object_owner(obj);
if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0)
return error;
if ((error = git_repository_odb(&odb, repo)) < 0)
return error;
while (len < GIT_OID_HEXSZ) {
/* set up short oid */
memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
if (len & 1)
id.id[len / 2] &= 0xf0;
error = git_odb_exists_prefix(NULL, odb, &id, len);
if (error != GIT_EAMBIGUOUS)
break;
giterr_clear();
len++;
}
if (!error && !(error = git_buf_grow(out, len + 1))) {
git_oid_tostr(out->ptr, len + 1, &id);
out->size = len;
}
git_odb_free(odb);
return error;
}
#include "clar_libgit2.h"
git_repository *_repo;
void test_object_shortid__initialize(void)
{
cl_git_pass(git_repository_open(&_repo, cl_fixture("duplicate.git")));
}
void test_object_shortid__cleanup(void)
{
git_repository_free(_repo);
_repo = NULL;
}
void test_object_shortid__select(void)
{
git_oid full;
git_object *obj;
git_buf shorty = {0};
git_oid_fromstr(&full, "ce013625030ba8dba906f756967f9e9ca394464a");
cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
cl_git_pass(git_object_short_id(&shorty, obj));
cl_assert_equal_i(7, shorty.size);
cl_assert_equal_s("ce01362", shorty.ptr);
git_object_free(obj);
git_oid_fromstr(&full, "dea509d097ce692e167dfc6a48a7a280cc5e877e");
cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
cl_git_pass(git_object_short_id(&shorty, obj));
cl_assert_equal_i(9, shorty.size);
cl_assert_equal_s("dea509d09", shorty.ptr);
git_object_free(obj);
git_oid_fromstr(&full, "dea509d0b3cb8ee0650f6ca210bc83f4678851ba");
cl_git_pass(git_object_lookup(&obj, _repo, &full, GIT_OBJ_ANY));
cl_git_pass(git_object_short_id(&shorty, obj));
cl_assert_equal_i(9, shorty.size);
cl_assert_equal_s("dea509d0b", shorty.ptr);
git_object_free(obj);
git_buf_free(&shorty);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment