From 087f64d3e3ea224dadb9b4ae1130b9499f49cff9 Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Mon, 17 Dec 2012 18:48:26 -0500 Subject: [PATCH 1/3] Relax refspecs accepted by push --- include/git2/refs.h | 2 +- src/push.c | 47 +++++++++++++++++++++++++++------------- tests-clar/online/push.c | 22 +++++++++++++++++++ 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/include/git2/refs.h b/include/git2/refs.h index a0abbc339..09cf61341 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -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. * * 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 repo The repository in which to look up the reference diff --git a/src/push.c b/src/push.c index 634634d84..6e856bd32 100644 --- a/src/push.c +++ b/src/push.c @@ -68,18 +68,37 @@ static void free_status(push_status *status) git__free(status); } -static int check_ref(char *ref) +static int check_rref(char *ref) { - if (strcmp(ref, "HEAD") && - git__prefixcmp(ref, "refs/heads/") && - git__prefixcmp(ref, "refs/tags/")) { - giterr_set(GITERR_INVALID, "No valid reference '%s'", ref); + if (git__prefixcmp(ref, "refs/")) { + giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref); return -1; } + 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; char *delim; @@ -94,22 +113,22 @@ static int parse_refspec(push_spec **spec, const char *str) str++; } -#define check(ref) \ - if (!ref || check_ref(ref) < 0) goto on_error - delim = strchr(str, ':'); if (delim == NULL) { s->lref = git__strdup(str); - check(s->lref); + if (!s->lref || check_lref(push, s->lref) < 0) + goto on_error; } else { if (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)) { s->rref = git__strdup(delim + 1); - check(s->rref); + if (!s->rref || check_rref(s->rref) < 0) + goto on_error; } } @@ -122,8 +141,6 @@ static int parse_refspec(push_spec **spec, const char *str) check(s->rref); } -#undef check - *spec = s; return 0; @@ -136,7 +153,7 @@ int git_push_add_refspec(git_push *push, const char *refspec) { push_spec *spec; - if (parse_refspec(&spec, refspec) < 0 || + if (parse_refspec(push, &spec, refspec) < 0 || git_vector_insert(&push->specs, spec) < 0) return -1; diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 9d949b77b..0fc57799f 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -525,3 +525,25 @@ void test_online_push__expressions(void) exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr), NULL, 0, 0); } + +void test_network_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")); + + do_push(specs, ARRAY_SIZE(specs), + exp_stats, ARRAY_SIZE(exp_stats), + exp_refs, ARRAY_SIZE(exp_refs), 0); + + git_signature_free(signature); +} From f85b62840a079fb4bee1838da50421a178850bd3 Mon Sep 17 00:00:00 2001 From: Michael Schubert Date: Tue, 25 Dec 2012 14:50:29 +0100 Subject: [PATCH 2/3] tests-clar/network: remove unused CREATE_BLOB --- tests-clar/online/push.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index 0fc57799f..c06d94cb3 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -22,9 +22,6 @@ static git_oid _oid_b3; static git_oid _oid_b2; static git_oid _oid_b1; -/* git_oid *oid, git_repository *repo, (string literal) blob */ -#define CREATE_BLOB(oid, repo, blob) git_blob_create_frombuffer(oid, repo, blob, sizeof(blob) - 1) - static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload) { GIT_UNUSED(url); From abeefbbe18710f86077eb4c5b825255256b8b6bc Mon Sep 17 00:00:00 2001 From: Michael Schubert Date: Wed, 26 Dec 2012 19:16:23 +0100 Subject: [PATCH 3/3] push: properly handle tags Currently, push doesn't really handle tags when queueing objects. Fix it. --- include/git2/refs.h | 2 +- src/push.c | 48 ++++++++++++++-- tests-clar/online/push.c | 54 +++++++++++++++++- .../80/5c54522e614f29f70d2413a0470247d8b424ac | Bin 0 -> 131 bytes .../b4/83ae7ba66decee9aee971f501221dea84b1498 | 3 + .../ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e | 4 ++ .../push_src/.gitted/refs/tags/tag-blob | 1 + .../push_src/.gitted/refs/tags/tag-commit | 1 + .../.gitted/refs/tags/tag-lightweight | 1 + .../push_src/.gitted/refs/tags/tag-tree | 1 + 10 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac create mode 100644 tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 create mode 100644 tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-blob create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-commit create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight create mode 100644 tests-clar/resources/push_src/.gitted/refs/tags/tag-tree diff --git a/include/git2/refs.h b/include/git2/refs.h index 09cf61341..d586917c2 100644 --- a/include/git2/refs.h +++ b/include/git2/refs.h @@ -124,7 +124,7 @@ GIT_EXTERN(int) git_reference_create(git_reference **out, git_repository *repo, * not a symbolic one). * * 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). * * @param ref The reference diff --git a/src/push.c b/src/push.c index 6e856bd32..71223645a 100644 --- a/src/push.c +++ b/src/push.c @@ -85,15 +85,15 @@ static int check_lref(git_push *push, char *ref) 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); + 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 { + } else git_object_free(obj); - } return 0; } @@ -138,7 +138,8 @@ static int parse_refspec(git_push *push, push_spec **spec, const char *str) /* If rref is ommitted, use the same ref name as lref */ if (!s->rref) { s->rref = git__strdup(s->lref); - check(s->rref); + if (!s->rref || check_rref(s->rref) < 0) + goto on_error; } *spec = s; @@ -175,6 +176,9 @@ static int revwalk(git_vector *commits, git_push *push) git_revwalk_sorting(rw, GIT_SORT_TIME); git_vector_foreach(&push->specs, i, spec) { + git_otype type; + size_t size; + if (git_oid_iszero(&spec->loid)) /* * Delete reference on remote side; @@ -185,7 +189,39 @@ static int revwalk(git_vector *commits, git_push *push) if (git_oid_equal(&spec->loid, &spec->roid)) 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; if (!spec->force) { diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c index c06d94cb3..15351ae08 100644 --- a/tests-clar/online/push.c +++ b/tests-clar/online/push.c @@ -22,6 +22,11 @@ static git_oid _oid_b3; static git_oid _oid_b2; static git_oid _oid_b1; +static git_oid _tag_commit; +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) { GIT_UNUSED(url); @@ -154,6 +159,11 @@ void test_online_push__initialize(void) git_oid_fromstr(&_oid_b2, "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 = cl_getenv("GITTEST_REMOTE_URL"); _remote_user = cl_getenv("GITTEST_REMOTE_USER"); @@ -404,6 +414,46 @@ void test_online_push__fast_fwd(void) 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) { const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"}; @@ -523,7 +573,7 @@ void test_online_push__expressions(void) NULL, 0, 0); } -void test_network_push__notes(void) +void test_online_push__notes(void) { git_oid note_oid, *target_oid, expected_oid; git_signature *signature; @@ -536,7 +586,7 @@ void test_network_push__notes(void) /* 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")); + 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), diff --git a/tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac b/tests-clar/resources/push_src/.gitted/objects/80/5c54522e614f29f70d2413a0470247d8b424ac new file mode 100644 index 0000000000000000000000000000000000000000..552670c06f373fd308bc1bc9ee0813fd7235c457 GIT binary patch literal 131 zcmV-}0DS*=0Y%I^4#F@H1W;<9VtWMgX8nmJgt!0|C-65hA~Fg~!R>JhL@}e8=CPju z742HM=g5#;FyzN^7$}WotVUC`3<(LnE|!!Fwoq1rKhF%YElXv=-RL>|@03@#);Rn8 lfLom3A+HRlS6`Q{jI#mDw literal 0 HcmV?d00001 diff --git a/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 b/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 new file mode 100644 index 000000000..1e0bd3b05 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498 @@ -0,0 +1,3 @@ +x5K +1D];1i"^'|d`d ooqQEͫ*Pݢ+ + 3$, }%Rw+s9y輨r`+ܦ2p/[mp~u8-Sr=,?Z+g \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e b/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e new file mode 100644 index 000000000..10f25eb7c --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/objects/ff/83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e @@ -0,0 +1,4 @@ +x5M +1 `=E4NA H ooq{/G@5=$+SO) nx[@4y +h1ڄvmSyz' +Wk-ziQc<ޢfS~pv+ \ No newline at end of file diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob b/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob new file mode 100644 index 000000000..abfebf22e --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-blob @@ -0,0 +1 @@ +b483ae7ba66decee9aee971f501221dea84b1498 diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit new file mode 100644 index 000000000..c023b8452 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-commit @@ -0,0 +1 @@ +805c54522e614f29f70d2413a0470247d8b424ac diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight b/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight new file mode 100644 index 000000000..711e466ae --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-lightweight @@ -0,0 +1 @@ +951bbbb90e2259a4c8950db78946784fb53fcbce diff --git a/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree new file mode 100644 index 000000000..7a530d381 --- /dev/null +++ b/tests-clar/resources/push_src/.gitted/refs/tags/tag-tree @@ -0,0 +1 @@ +ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e