mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-04 13:05:35 +00:00
Merge pull request #1568 from nulltoken/topic/revparse_ext
Introduce git_revparse_ext()
This commit is contained in:
commit
5b3d52ce37
@ -32,6 +32,28 @@ GIT_BEGIN_DECL
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec);
|
GIT_EXTERN(int) git_revparse_single(git_object **out, git_repository *repo, const char *spec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a single object, as specified by a revision string.
|
||||||
|
* See `man gitrevisions`,
|
||||||
|
* or http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for
|
||||||
|
* information on the syntax accepted.
|
||||||
|
*
|
||||||
|
* In some cases (`@{<-n>}` or `<branchname>@{upstream}`), the expression may
|
||||||
|
* point to an intermediate reference. When such expressions are being passed
|
||||||
|
* in, `reference_out` will be valued as well.
|
||||||
|
*
|
||||||
|
* @param object_out pointer to output object
|
||||||
|
* @param reference_out pointer to output reference or NULL
|
||||||
|
* @param repo the repository to search in
|
||||||
|
* @param spec the textual specification for an object
|
||||||
|
* @return 0 on success, GIT_ENOTFOUND, GIT_EAMBIGUOUS, GIT_EINVALIDSPEC
|
||||||
|
* or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_revparse_ext(
|
||||||
|
git_object **object_out,
|
||||||
|
git_reference **reference_out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *spec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revparse flags. These indicate the intended behavior of the spec passed to
|
* Revparse flags. These indicate the intended behavior of the spec passed to
|
||||||
|
@ -84,12 +84,16 @@ static int maybe_describe(git_object**out, git_repository *repo, const char *spe
|
|||||||
return maybe_abbrev(out, repo, substr+2);
|
return maybe_abbrev(out, repo, substr+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int revparse_lookup_object(git_object **out, git_repository *repo, const char *spec)
|
static int revparse_lookup_object(
|
||||||
|
git_object **object_out,
|
||||||
|
git_reference **reference_out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *spec)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
git_reference *ref;
|
git_reference *ref;
|
||||||
|
|
||||||
error = maybe_sha(out, repo, spec);
|
error = maybe_sha(object_out, repo, spec);
|
||||||
if (!error)
|
if (!error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -98,22 +102,27 @@ static int revparse_lookup_object(git_object **out, git_repository *repo, const
|
|||||||
|
|
||||||
error = git_reference_dwim(&ref, repo, spec);
|
error = git_reference_dwim(&ref, repo, spec);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = git_object_lookup(out, repo, git_reference_target(ref), GIT_OBJ_ANY);
|
|
||||||
git_reference_free(ref);
|
error = git_object_lookup(
|
||||||
|
object_out, repo, git_reference_target(ref), GIT_OBJ_ANY);
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
*reference_out = ref;
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error < 0 && error != GIT_ENOTFOUND)
|
if (error < 0 && error != GIT_ENOTFOUND)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = maybe_abbrev(out, repo, spec);
|
error = maybe_abbrev(object_out, repo, spec);
|
||||||
if (!error)
|
if (!error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (error < 0 && error != GIT_ENOTFOUND)
|
if (error < 0 && error != GIT_ENOTFOUND)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = maybe_describe(out, repo, spec);
|
error = maybe_describe(object_out, repo, spec);
|
||||||
if (!error)
|
if (!error)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -617,14 +626,8 @@ static int ensure_base_rev_loaded(git_object **object, git_reference **reference
|
|||||||
if (*object != NULL)
|
if (*object != NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (*reference != NULL) {
|
if (*reference != NULL)
|
||||||
if ((error = object_from_reference(object, *reference)) < 0)
|
return object_from_reference(object, *reference);
|
||||||
return error;
|
|
||||||
|
|
||||||
git_reference_free(*reference);
|
|
||||||
*reference = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!allow_empty_identifier && identifier_len == 0)
|
if (!allow_empty_identifier && identifier_len == 0)
|
||||||
return GIT_EINVALIDSPEC;
|
return GIT_EINVALIDSPEC;
|
||||||
@ -632,7 +635,7 @@ static int ensure_base_rev_loaded(git_object **object, git_reference **reference
|
|||||||
if (git_buf_put(&identifier, spec, identifier_len) < 0)
|
if (git_buf_put(&identifier, spec, identifier_len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
error = revparse_lookup_object(object, repo, git_buf_cstr(&identifier));
|
error = revparse_lookup_object(object, reference, repo, git_buf_cstr(&identifier));
|
||||||
git_buf_free(&identifier);
|
git_buf_free(&identifier);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -668,7 +671,12 @@ static int ensure_left_hand_identifier_is_not_known_yet(git_object *object, git_
|
|||||||
return GIT_EINVALIDSPEC;
|
return GIT_EINVALIDSPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_revparse_single(git_object **out, git_repository *repo, const char *spec)
|
int revparse__ext(
|
||||||
|
git_object **object_out,
|
||||||
|
git_reference **reference_out,
|
||||||
|
int *identifier_len_out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *spec)
|
||||||
{
|
{
|
||||||
size_t pos = 0, identifier_len = 0;
|
size_t pos = 0, identifier_len = 0;
|
||||||
int error = -1, n;
|
int error = -1, n;
|
||||||
@ -677,9 +685,10 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
git_reference *reference = NULL;
|
git_reference *reference = NULL;
|
||||||
git_object *base_rev = NULL;
|
git_object *base_rev = NULL;
|
||||||
|
|
||||||
assert(out && repo && spec);
|
assert(object_out && reference_out && repo && spec);
|
||||||
|
|
||||||
*out = NULL;
|
*object_out = NULL;
|
||||||
|
*reference_out = NULL;
|
||||||
|
|
||||||
while (spec[pos]) {
|
while (spec[pos]) {
|
||||||
switch (spec[pos]) {
|
switch (spec[pos]) {
|
||||||
@ -798,7 +807,9 @@ int git_revparse_single(git_object **out, git_repository *repo, const char *spec
|
|||||||
if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0)
|
if ((error = ensure_base_rev_loaded(&base_rev, &reference, spec, identifier_len, repo, false)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
*out = base_rev;
|
*object_out = base_rev;
|
||||||
|
*reference_out = reference;
|
||||||
|
*identifier_len_out = identifier_len;
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -808,12 +819,59 @@ cleanup:
|
|||||||
"Failed to parse revision specifier - Invalid pattern '%s'", spec);
|
"Failed to parse revision specifier - Invalid pattern '%s'", spec);
|
||||||
|
|
||||||
git_object_free(base_rev);
|
git_object_free(base_rev);
|
||||||
}
|
|
||||||
git_reference_free(reference);
|
git_reference_free(reference);
|
||||||
|
}
|
||||||
|
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_revparse_ext(
|
||||||
|
git_object **object_out,
|
||||||
|
git_reference **reference_out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *spec)
|
||||||
|
{
|
||||||
|
int error, identifier_len;
|
||||||
|
git_object *obj = NULL;
|
||||||
|
git_reference *ref = NULL;
|
||||||
|
|
||||||
|
if ((error = revparse__ext(&obj, &ref, &identifier_len, repo, spec)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
*object_out = obj;
|
||||||
|
*reference_out = ref;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
git_object_free(obj);
|
||||||
|
git_reference_free(ref);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_revparse_single(git_object **out, git_repository *repo, const char *spec)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
git_object *obj = NULL;
|
||||||
|
git_reference *ref = NULL;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
if ((error = git_revparse_ext(&obj, &ref, repo, spec)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
git_reference_free(ref);
|
||||||
|
|
||||||
|
*out = obj;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
git_object_free(obj);
|
||||||
|
git_reference_free(ref);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int git_revparse(
|
int git_revparse(
|
||||||
git_revspec *revspec,
|
git_revspec *revspec,
|
||||||
|
@ -9,13 +9,19 @@ static git_repository *g_repo;
|
|||||||
static git_object *g_obj;
|
static git_object *g_obj;
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo)
|
static void test_object_and_ref_inrepo(
|
||||||
|
const char *spec,
|
||||||
|
const char *expected_oid,
|
||||||
|
const char *expected_refname,
|
||||||
|
git_repository *repo,
|
||||||
|
bool assert_reference_retrieval)
|
||||||
{
|
{
|
||||||
char objstr[64] = {0};
|
char objstr[64] = {0};
|
||||||
git_object *obj = NULL;
|
git_object *obj = NULL;
|
||||||
|
git_reference *ref = NULL;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = git_revparse_single(&obj, repo, spec);
|
error = git_revparse_ext(&obj, &ref, repo, spec);
|
||||||
|
|
||||||
if (expected_oid != NULL) {
|
if (expected_oid != NULL) {
|
||||||
cl_assert_equal_i(0, error);
|
cl_assert_equal_i(0, error);
|
||||||
@ -24,7 +30,20 @@ static void test_object_inrepo(const char *spec, const char *expected_oid, git_r
|
|||||||
} else
|
} else
|
||||||
cl_assert_equal_i(GIT_ENOTFOUND, error);
|
cl_assert_equal_i(GIT_ENOTFOUND, error);
|
||||||
|
|
||||||
|
if (assert_reference_retrieval) {
|
||||||
|
if (expected_refname == NULL)
|
||||||
|
cl_assert(NULL == ref);
|
||||||
|
else
|
||||||
|
cl_assert_equal_s(expected_refname, git_reference_name(ref));
|
||||||
|
}
|
||||||
|
|
||||||
git_object_free(obj);
|
git_object_free(obj);
|
||||||
|
git_reference_free(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_object_inrepo(const char *spec, const char *expected_oid, git_repository *repo)
|
||||||
|
{
|
||||||
|
test_object_and_ref_inrepo(spec, expected_oid, NULL, repo, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_id_inrepo(
|
static void test_id_inrepo(
|
||||||
@ -63,6 +82,11 @@ static void test_object(const char *spec, const char *expected_oid)
|
|||||||
test_object_inrepo(spec, expected_oid, g_repo);
|
test_object_inrepo(spec, expected_oid, g_repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_object_and_ref(const char *spec, const char *expected_oid, const char *expected_refname)
|
||||||
|
{
|
||||||
|
test_object_and_ref_inrepo(spec, expected_oid, expected_refname, g_repo, true);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_rangelike(const char *rangelike,
|
static void test_rangelike(const char *rangelike,
|
||||||
const char *expected_left,
|
const char *expected_left,
|
||||||
const char *expected_right,
|
const char *expected_right,
|
||||||
@ -694,3 +718,24 @@ void test_refs_revparse__parses_range_operator(void)
|
|||||||
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
|
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
|
||||||
GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
|
GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_refs_revparse__ext_retrieves_both_the_reference_and_its_target(void)
|
||||||
|
{
|
||||||
|
test_object_and_ref(
|
||||||
|
"master@{upstream}",
|
||||||
|
"be3563ae3f795b2b4353bcce3a527ad0a4f7f644",
|
||||||
|
"refs/remotes/test/master");
|
||||||
|
|
||||||
|
test_object_and_ref(
|
||||||
|
"@{-1}",
|
||||||
|
"a4a7dce85cf63874e984719f4fdd239f5145052f",
|
||||||
|
"refs/heads/br2");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_refs_revparse__ext_can_expand_short_reference_names(void)
|
||||||
|
{
|
||||||
|
test_object_and_ref(
|
||||||
|
"master",
|
||||||
|
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
|
||||||
|
"refs/heads/master");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user