Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 252b240

Browse files
author
Vicent Martí
committed
Merge pull request #1214 from schu/push-handle-tags
push: properly handle tags
2 parents 11fccdd + abeefbb commit 252b240

File tree

10 files changed

+154
-21
lines changed

10 files changed

+154
-21
lines changed

include/git2/refs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ GIT_EXTERN(int) git_reference_lookup(git_reference **out, git_repository *repo,
4444
* allocate or free any `git_reference` objects for simple situations.
4545
*
4646
* The name will be checked for validity.
47-
* See `git_reference_create_symbolic()` for rules about valid names.
47+
* See `git_reference_symbolic_create()` for rules about valid names.
4848
*
4949
* @param out Pointer to oid to be filled in
5050
* @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,
124124
* not a symbolic one).
125125
*
126126
* To find the OID of a symbolic ref, call `git_reference_resolve()` and
127-
* then this function (or maybe use `git_reference_name_to_oid()` to
127+
* then this function (or maybe use `git_reference_name_to_id()` to
128128
* directly resolve a reference name all the way through to an OID).
129129
*
130130
* @param ref The reference

src/push.c

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,37 @@ static void free_status(push_status *status)
6868
git__free(status);
6969
}
7070

71-
static int check_ref(char *ref)
71+
static int check_rref(char *ref)
7272
{
73-
if (strcmp(ref, "HEAD") &&
74-
git__prefixcmp(ref, "refs/heads/") &&
75-
git__prefixcmp(ref, "refs/tags/")) {
76-
giterr_set(GITERR_INVALID, "No valid reference '%s'", ref);
73+
if (git__prefixcmp(ref, "refs/")) {
74+
giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
7775
return -1;
7876
}
77+
7978
return 0;
8079
}
8180

82-
static int parse_refspec(push_spec **spec, const char *str)
81+
static int check_lref(git_push *push, char *ref)
82+
{
83+
/* lref must be resolvable to an existing object */
84+
git_object *obj;
85+
int error = git_revparse_single(&obj, push->repo, ref);
86+
87+
if (error) {
88+
if (error == GIT_ENOTFOUND)
89+
giterr_set(GITERR_REFERENCE,
90+
"src refspec '%s' does not match any existing object", ref);
91+
else
92+
giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref);
93+
94+
return -1;
95+
} else
96+
git_object_free(obj);
97+
98+
return 0;
99+
}
100+
101+
static int parse_refspec(git_push *push, push_spec **spec, const char *str)
83102
{
84103
push_spec *s;
85104
char *delim;
@@ -94,22 +113,22 @@ static int parse_refspec(push_spec **spec, const char *str)
94113
str++;
95114
}
96115

97-
#define check(ref) \
98-
if (!ref || check_ref(ref) < 0) goto on_error
99-
100116
delim = strchr(str, ':');
101117
if (delim == NULL) {
102118
s->lref = git__strdup(str);
103-
check(s->lref);
119+
if (!s->lref || check_lref(push, s->lref) < 0)
120+
goto on_error;
104121
} else {
105122
if (delim - str) {
106123
s->lref = git__strndup(str, delim - str);
107-
check(s->lref);
124+
if (!s->lref || check_lref(push, s->lref) < 0)
125+
goto on_error;
108126
}
109127

110128
if (strlen(delim + 1)) {
111129
s->rref = git__strdup(delim + 1);
112-
check(s->rref);
130+
if (!s->rref || check_rref(s->rref) < 0)
131+
goto on_error;
113132
}
114133
}
115134

@@ -119,11 +138,10 @@ static int parse_refspec(push_spec **spec, const char *str)
119138
/* If rref is ommitted, use the same ref name as lref */
120139
if (!s->rref) {
121140
s->rref = git__strdup(s->lref);
122-
check(s->rref);
141+
if (!s->rref || check_rref(s->rref) < 0)
142+
goto on_error;
123143
}
124144

125-
#undef check
126-
127145
*spec = s;
128146
return 0;
129147

@@ -136,7 +154,7 @@ int git_push_add_refspec(git_push *push, const char *refspec)
136154
{
137155
push_spec *spec;
138156

139-
if (parse_refspec(&spec, refspec) < 0 ||
157+
if (parse_refspec(push, &spec, refspec) < 0 ||
140158
git_vector_insert(&push->specs, spec) < 0)
141159
return -1;
142160

@@ -158,6 +176,9 @@ static int revwalk(git_vector *commits, git_push *push)
158176
git_revwalk_sorting(rw, GIT_SORT_TIME);
159177

160178
git_vector_foreach(&push->specs, i, spec) {
179+
git_otype type;
180+
size_t size;
181+
161182
if (git_oid_iszero(&spec->loid))
162183
/*
163184
* Delete reference on remote side;
@@ -168,7 +189,39 @@ static int revwalk(git_vector *commits, git_push *push)
168189
if (git_oid_equal(&spec->loid, &spec->roid))
169190
continue; /* up-to-date */
170191

171-
if (git_revwalk_push(rw, &spec->loid) < 0)
192+
if (git_odb_read_header(&size, &type, push->repo->_odb, &spec->loid) < 0)
193+
goto on_error;
194+
195+
if (type == GIT_OBJ_TAG) {
196+
git_tag *tag;
197+
git_object *target;
198+
199+
if (git_packbuilder_insert(push->pb, &spec->loid, NULL) < 0)
200+
goto on_error;
201+
202+
if (git_tag_lookup(&tag, push->repo, &spec->loid) < 0)
203+
goto on_error;
204+
205+
if (git_tag_peel(&target, tag) < 0) {
206+
git_tag_free(tag);
207+
goto on_error;
208+
}
209+
git_tag_free(tag);
210+
211+
if (git_object_type(target) == GIT_OBJ_COMMIT) {
212+
if (git_revwalk_push(rw, git_object_id(target)) < 0) {
213+
git_object_free(target);
214+
goto on_error;
215+
}
216+
} else {
217+
if (git_packbuilder_insert(
218+
push->pb, git_object_id(target), NULL) < 0) {
219+
git_object_free(target);
220+
goto on_error;
221+
}
222+
}
223+
git_object_free(target);
224+
} else if (git_revwalk_push(rw, &spec->loid) < 0)
172225
goto on_error;
173226

174227
if (!spec->force) {

tests-clar/online/push.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ static git_oid _oid_b3;
2222
static git_oid _oid_b2;
2323
static git_oid _oid_b1;
2424

25-
/* git_oid *oid, git_repository *repo, (string literal) blob */
26-
#define CREATE_BLOB(oid, repo, blob) git_blob_create_frombuffer(oid, repo, blob, sizeof(blob) - 1)
25+
static git_oid _tag_commit;
26+
static git_oid _tag_tree;
27+
static git_oid _tag_blob;
28+
static git_oid _tag_lightweight;
2729

2830
static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload)
2931
{
@@ -157,6 +159,11 @@ void test_online_push__initialize(void)
157159
git_oid_fromstr(&_oid_b2, "a78705c3b2725f931d3ee05348d83cc26700f247");
158160
git_oid_fromstr(&_oid_b1, "a78705c3b2725f931d3ee05348d83cc26700f247");
159161

162+
git_oid_fromstr(&_tag_commit, "805c54522e614f29f70d2413a0470247d8b424ac");
163+
git_oid_fromstr(&_tag_tree, "ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e");
164+
git_oid_fromstr(&_tag_blob, "b483ae7ba66decee9aee971f501221dea84b1498");
165+
git_oid_fromstr(&_tag_lightweight, "951bbbb90e2259a4c8950db78946784fb53fcbce");
166+
160167
/* Remote URL environment variable must be set. User and password are optional. */
161168
_remote_url = cl_getenv("GITTEST_REMOTE_URL");
162169
_remote_user = cl_getenv("GITTEST_REMOTE_USER");
@@ -407,6 +414,46 @@ void test_online_push__fast_fwd(void)
407414
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
408415
}
409416

417+
void test_online_push__tag_commit(void)
418+
{
419+
const char *specs[] = { "refs/tags/tag-commit:refs/tags/tag-commit" };
420+
push_status exp_stats[] = { { "refs/tags/tag-commit", NULL } };
421+
expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } };
422+
do_push(specs, ARRAY_SIZE(specs),
423+
exp_stats, ARRAY_SIZE(exp_stats),
424+
exp_refs, ARRAY_SIZE(exp_refs), 0);
425+
}
426+
427+
void test_online_push__tag_tree(void)
428+
{
429+
const char *specs[] = { "refs/tags/tag-tree:refs/tags/tag-tree" };
430+
push_status exp_stats[] = { { "refs/tags/tag-tree", NULL } };
431+
expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } };
432+
do_push(specs, ARRAY_SIZE(specs),
433+
exp_stats, ARRAY_SIZE(exp_stats),
434+
exp_refs, ARRAY_SIZE(exp_refs), 0);
435+
}
436+
437+
void test_online_push__tag_blob(void)
438+
{
439+
const char *specs[] = { "refs/tags/tag-blob:refs/tags/tag-blob" };
440+
push_status exp_stats[] = { { "refs/tags/tag-blob", NULL } };
441+
expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } };
442+
do_push(specs, ARRAY_SIZE(specs),
443+
exp_stats, ARRAY_SIZE(exp_stats),
444+
exp_refs, ARRAY_SIZE(exp_refs), 0);
445+
}
446+
447+
void test_online_push__tag_lightweight(void)
448+
{
449+
const char *specs[] = { "refs/tags/tag-lightweight:refs/tags/tag-lightweight" };
450+
push_status exp_stats[] = { { "refs/tags/tag-lightweight", NULL } };
451+
expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } };
452+
do_push(specs, ARRAY_SIZE(specs),
453+
exp_stats, ARRAY_SIZE(exp_stats),
454+
exp_refs, ARRAY_SIZE(exp_refs), 0);
455+
}
456+
410457
void test_online_push__force(void)
411458
{
412459
const char *specs1[] = {"refs/heads/b3:refs/heads/tgt"};
@@ -525,3 +572,25 @@ void test_online_push__expressions(void)
525572
exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr),
526573
NULL, 0, 0);
527574
}
575+
576+
void test_online_push__notes(void)
577+
{
578+
git_oid note_oid, *target_oid, expected_oid;
579+
git_signature *signature;
580+
const char *specs[] = { "refs/notes/commits:refs/notes/commits" };
581+
push_status exp_stats[] = { { "refs/notes/commits", NULL } };
582+
expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } };
583+
git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb");
584+
585+
target_oid = &_oid_b6;
586+
587+
/* Create note to push */
588+
cl_git_pass(git_signature_new(&signature, "nulltoken", "[email protected]", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */
589+
cl_git_pass(git_note_create(&note_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0));
590+
591+
do_push(specs, ARRAY_SIZE(specs),
592+
exp_stats, ARRAY_SIZE(exp_stats),
593+
exp_refs, ARRAY_SIZE(exp_refs), 0);
594+
595+
git_signature_free(signature);
596+
}
131 Bytes
Binary file not shown.

tests-clar/resources/push_src/.gitted/objects/b4/83ae7ba66decee9aee971f501221dea84b1498

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
x5�K
2+
1D]���;1i"^��'���|d`d� ooqQE�ͫ*P�ݢ+
3+
� 3�$,}�%�R�w��+s�9��y輨���r��`+ܦ2��p/�[m�p~�u��8-��S��r�=��,?�Z+g
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
x5�M
2+
1 `�=E��4�NA� �������H� ooq��{�/G@�5=$+�SO�) n�x�����[�@4�y
3+
h1ڄv����m�S��yz'�
4+
�Wk�-��zi�Qc<�ޢ�fS~�pv+�
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
b483ae7ba66decee9aee971f501221dea84b1498
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
805c54522e614f29f70d2413a0470247d8b424ac
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
951bbbb90e2259a4c8950db78946784fb53fcbce
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ff83aa4c5e5d28e3bcba2f5c6e2adc61286a4e5e

0 commit comments

Comments
 (0)