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); +}