Relax refspecs accepted by push
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
diff --git a/include/git2/refs.h b/include/git2/refs.h
index a0abbc3..09cf613 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 634634d..6e856bd 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 9d949b7..0fc5779 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);
+}