mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-23 21:38:19 +00:00
Merge pull request #1214 from schu/push-handle-tags
push: properly handle tags
This commit is contained in:
commit
252b24049c
@ -44,7 +44,7 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo,
|
|||||||
* allocate or free any `git_reference` objects for simple situations.
|
* allocate or free any `git_reference` objects for simple situations.
|
||||||
*
|
*
|
||||||
* The name will be checked for validity.
|
* The name will be checked for validity.
|
||||||
* See `git_reference_create_symbolic()` for rules about valid names.
|
* See `git_reference_symbolic_create()` for rules about valid names.
|
||||||
*
|
*
|
||||||
* @param out Pointer to oid to be filled in
|
* @param out Pointer to oid to be filled in
|
||||||
* @param repo The repository in which to look up the reference
|
* @param repo The repository in which to look up the reference
|
||||||
@ -124,7 +124,7 @@ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo,
|
|||||||
* not a symbolic one).
|
* not a symbolic one).
|
||||||
*
|
*
|
||||||
* To find the OID of a symbolic ref, call `git_reference_resolve()` and
|
* To find the OID of a symbolic ref, call `git_reference_resolve()` and
|
||||||
* then this function (or maybe use `git_reference_name_to_oid()` to
|
* then this function (or maybe use `git_reference_name_to_id()` to
|
||||||
* directly resolve a reference name all the way through to an OID).
|
* directly resolve a reference name all the way through to an OID).
|
||||||
*
|
*
|
||||||
* @param ref The reference
|
* @param ref The reference
|
||||||
|
87
src/push.c
87
src/push.c
@ -68,18 +68,37 @@ static void free_status(push_status *status)
|
|||||||
git__free(status);
|
git__free(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_ref(char *ref)
|
static int check_rref(char *ref)
|
||||||
{
|
{
|
||||||
if (strcmp(ref, "HEAD") &&
|
if (git__prefixcmp(ref, "refs/")) {
|
||||||
git__prefixcmp(ref, "refs/heads/") &&
|
giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
|
||||||
git__prefixcmp(ref, "refs/tags/")) {
|
|
||||||
giterr_set(GITERR_INVALID, "No valid reference '%s'", ref);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_refspec(push_spec **spec, const char *str)
|
static int check_lref(git_push *push, char *ref)
|
||||||
|
{
|
||||||
|
/* lref must be resolvable to an existing object */
|
||||||
|
git_object *obj;
|
||||||
|
int error = git_revparse_single(&obj, push->repo, ref);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error == GIT_ENOTFOUND)
|
||||||
|
giterr_set(GITERR_REFERENCE,
|
||||||
|
"src refspec '%s' does not match any existing object", ref);
|
||||||
|
else
|
||||||
|
giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
git_object_free(obj);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_refspec(git_push *push, push_spec **spec, const char *str)
|
||||||
{
|
{
|
||||||
push_spec *s;
|
push_spec *s;
|
||||||
char *delim;
|
char *delim;
|
||||||
@ -94,22 +113,22 @@ static int parse_refspec(push_spec **spec, const char *str)
|
|||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define check(ref) \
|
|
||||||
if (!ref || check_ref(ref) < 0) goto on_error
|
|
||||||
|
|
||||||
delim = strchr(str, ':');
|
delim = strchr(str, ':');
|
||||||
if (delim == NULL) {
|
if (delim == NULL) {
|
||||||
s->lref = git__strdup(str);
|
s->lref = git__strdup(str);
|
||||||
check(s->lref);
|
if (!s->lref || check_lref(push, s->lref) < 0)
|
||||||
|
goto on_error;
|
||||||
} else {
|
} else {
|
||||||
if (delim - str) {
|
if (delim - str) {
|
||||||
s->lref = git__strndup(str, delim - str);
|
s->lref = git__strndup(str, delim - str);
|
||||||
check(s->lref);
|
if (!s->lref || check_lref(push, s->lref) < 0)
|
||||||
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(delim + 1)) {
|
if (strlen(delim + 1)) {
|
||||||
s->rref = git__strdup(delim + 1);
|
s->rref = git__strdup(delim + 1);
|
||||||
check(s->rref);
|
if (!s->rref || check_rref(s->rref) < 0)
|
||||||
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,11 +138,10 @@ static int parse_refspec(push_spec **spec, const char *str)
|
|||||||
/* If rref is ommitted, use the same ref name as lref */
|
/* If rref is ommitted, use the same ref name as lref */
|
||||||
if (!s->rref) {
|
if (!s->rref) {
|
||||||
s->rref = git__strdup(s->lref);
|
s->rref = git__strdup(s->lref);
|
||||||
check(s->rref);
|
if (!s->rref || check_rref(s->rref) < 0)
|
||||||
|
goto on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef check
|
|
||||||
|
|
||||||
*spec = s;
|
*spec = s;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -136,7 +154,7 @@ int git_push_add_refspec(git_push *push, const char *refspec)
|
|||||||
{
|
{
|
||||||
push_spec *spec;
|
push_spec *spec;
|
||||||
|
|
||||||
if (parse_refspec(&spec, refspec) < 0 ||
|
if (parse_refspec(push, &spec, refspec) < 0 ||
|
||||||
git_vector_insert(&push->specs, spec) < 0)
|
git_vector_insert(&push->specs, spec) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -158,6 +176,9 @@ static int revwalk(git_vector *commits, git_push *push)
|
|||||||
git_revwalk_sorting(rw, GIT_SORT_TIME);
|
git_revwalk_sorting(rw, GIT_SORT_TIME);
|
||||||
|
|
||||||
git_vector_foreach(&push->specs, i, spec) {
|
git_vector_foreach(&push->specs, i, spec) {
|
||||||
|
git_otype type;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
if (git_oid_iszero(&spec->loid))
|
if (git_oid_iszero(&spec->loid))
|
||||||
/*
|
/*
|
||||||
* Delete reference on remote side;
|
* Delete reference on remote side;
|
||||||
@ -168,7 +189,39 @@ static int revwalk(git_vector *commits, git_push *push)
|
|||||||
if (git_oid_equal(&spec->loid, &spec->roid))
|
if (git_oid_equal(&spec->loid, &spec->roid))
|
||||||
continue; /* up-to-date */
|
continue; /* up-to-date */
|
||||||
|
|
||||||
if (git_revwalk_push(rw, &spec->loid) < 0)
|
if (git_odb_read_header(&size, &type, push->repo->_odb, &spec->loid) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if (type == GIT_OBJ_TAG) {
|
||||||
|
git_tag *tag;
|
||||||
|
git_object *target;
|
||||||
|
|
||||||
|
if (git_packbuilder_insert(push->pb, &spec->loid, NULL) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if (git_tag_lookup(&tag, push->repo, &spec->loid) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
|
if (git_tag_peel(&target, tag) < 0) {
|
||||||
|
git_tag_free(tag);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
git_tag_free(tag);
|
||||||
|
|
||||||
|
if (git_object_type(target) == GIT_OBJ_COMMIT) {
|
||||||
|
if (git_revwalk_push(rw, git_object_id(target)) < 0) {
|
||||||
|
git_object_free(target);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (git_packbuilder_insert(
|
||||||
|
push->pb, git_object_id(target), NULL) < 0) {
|
||||||
|
git_object_free(target);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
git_object_free(target);
|
||||||
|
} else if (git_revwalk_push(rw, &spec->loid) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (!spec->force) {
|
if (!spec->force) {
|
||||||
|
@ -22,8 +22,10 @@ static git_oid _oid_b3;
|
|||||||
static git_oid _oid_b2;
|
static git_oid _oid_b2;
|
||||||
static git_oid _oid_b1;
|
static git_oid _oid_b1;
|
||||||
|
|
||||||
/* git_oid *oid, git_repository *repo, (string literal) blob */
|
static git_oid _tag_commit;
|
||||||
#define CREATE_BLOB(oid, repo, blob) git_blob_create_frombuffer(oid, repo, blob, sizeof(blob) - 1)
|
static git_oid _tag_tree;
|
||||||
|
static git_oid _tag_blob;
|
||||||
|
static git_oid _tag_lightweight;
|
||||||
|
|
||||||
static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload)
|
static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload)
|
||||||
{
|
{
|
||||||
@ -157,6 +159,11 @@ void test_online_push__initialize(void)
|
|||||||
git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247");
|
git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247");
|
||||||
git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247");
|
git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247");
|
||||||
|
|
||||||
|
git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac");
|
||||||
|
git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e");
|
||||||
|
git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498");
|
||||||
|
git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce");
|
||||||
|
|
||||||
/* Remote URL environment variable must be set. User and password are optional. */
|
/* Remote URL environment variable must be set. User and password are optional. */
|
||||||
_remote_url = cl_getenv("GITTEST_REMOTE_URL");
|
_remote_url = cl_getenv("GITTEST_REMOTE_URL");
|
||||||
_remote_user = cl_getenv("GITTEST_REMOTE_USER");
|
_remote_user = cl_getenv("GITTEST_REMOTE_USER");
|
||||||
@ -407,6 +414,46 @@ void test_online_push__fast_fwd(void)
|
|||||||
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
|
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_online_push__tag_commit(void)
|
||||||
|
{
|
||||||
|
const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" };
|
||||||
|
push_status exp_stats[] = { { "refs/tags/tag-commit", NULL } };
|
||||||
|
expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } };
|
||||||
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
|
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_online_push__tag_tree(void)
|
||||||
|
{
|
||||||
|
const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" };
|
||||||
|
push_status exp_stats[] = { { "refs/tags/tag-tree", NULL } };
|
||||||
|
expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } };
|
||||||
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
|
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_online_push__tag_blob(void)
|
||||||
|
{
|
||||||
|
const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" };
|
||||||
|
push_status exp_stats[] = { { "refs/tags/tag-blob", NULL } };
|
||||||
|
expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } };
|
||||||
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
|
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_online_push__tag_lightweight(void)
|
||||||
|
{
|
||||||
|
const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" };
|
||||||
|
push_status exp_stats[] = { { "refs/tags/tag-lightweight", NULL } };
|
||||||
|
expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } };
|
||||||
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
|
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
||||||
|
}
|
||||||
|
|
||||||
void test_online_push__force(void)
|
void test_online_push__force(void)
|
||||||
{
|
{
|
||||||
const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"};
|
const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"};
|
||||||
@ -525,3 +572,25 @@ void test_online_push__expressions(void)
|
|||||||
exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr),
|
exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr),
|
||||||
NULL, 0, 0);
|
NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_online_push__notes(void)
|
||||||
|
{
|
||||||
|
git_oid note_oid, *target_oid, expected_oid;
|
||||||
|
git_signature *signature;
|
||||||
|
const char *specs[] = { "refs/notes/commits:refs/notes/commits" };
|
||||||
|
push_status exp_stats[] = { { "refs/notes/commits", NULL } };
|
||||||
|
expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } };
|
||||||
|
git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb");
|
||||||
|
|
||||||
|
target_oid = &_oid_b6;
|
||||||
|
|
||||||
|
/* Create note to push */
|
||||||
|
cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */
|
||||||
|
cl_git_pass(git_note_create(¬e_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0));
|
||||||
|
|
||||||
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
|
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
||||||
|
|
||||||
|
git_signature_free(signature);
|
||||||
|
}
|
||||||
|
Binary file not shown.
@ -0,0 +1,3 @@
|
|||||||
|
x5ŤK
|
||||||
|
1D]罥;1i"^Ŕ•'čÎô|d`dŚooqQE˝Í«*Pŕݢ+
|
||||||
|
á 3…$,
}ě%˘Rßw¬É+sç9»úy輨«ÍĐrřĂ`+ܦ2ŠÍp/ă[mp~µuÝę8-—öS<>™r„=˘Ű,?ĂZ+g
|
@ -0,0 +1,4 @@
|
|||||||
|
x5ÍM
|
||||||
|
1`×=Eö˘4ÓNAĸňýÉüČŔHŤooq‘Ç{›/G@ň»5=$+”SOÝ)nĄxâ≻Ř[Ć@4úy
|
||||||
|
h1Ú„v‡˙ĄÂmÎS”îyz'©
|
||||||
|
çWk×-ŽóziŮQc<ĂޢµfS~Âpv+…
|
1
tests-clar/resources/push_src/.gitted/refs/tags/tag-blob
Normal file
1
tests-clar/resources/push_src/.gitted/refs/tags/tag-blob
Normal file
@ -0,0 +1 @@
|
|||||||
|
b483ae7ba66decee9aee971f501221dea84b1498
|
@ -0,0 +1 @@
|
|||||||
|
805c54522e614f29f70d2413a0470247d8b424ac
|
@ -0,0 +1 @@
|
|||||||
|
951bbbb90e2259a4c8950db78946784fb53fcbce
|
1
tests-clar/resources/push_src/.gitted/refs/tags/tag-tree
Normal file
1
tests-clar/resources/push_src/.gitted/refs/tags/tag-tree
Normal file
@ -0,0 +1 @@
|
|||||||
|
ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e
|
Loading…
Reference in New Issue
Block a user