2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
13 #include "pack-objects.h"
18 static int push_spec_rref_cmp(const void *a
, const void *b
)
20 const push_spec
*push_spec_a
= a
, *push_spec_b
= b
;
22 return strcmp(push_spec_a
->refspec
.dst
, push_spec_b
->refspec
.dst
);
25 static int push_status_ref_cmp(const void *a
, const void *b
)
27 const push_status
*push_status_a
= a
, *push_status_b
= b
;
29 return strcmp(push_status_a
->ref
, push_status_b
->ref
);
32 int git_push_new(git_push
**out
, git_remote
*remote
, const git_push_options
*opts
)
38 GIT_ERROR_CHECK_VERSION(opts
, GIT_PUSH_OPTIONS_VERSION
, "git_push_options");
40 p
= git__calloc(1, sizeof(*p
));
41 GIT_ERROR_CHECK_ALLOC(p
);
43 p
->repo
= remote
->repo
;
46 p
->pb_parallelism
= opts
? opts
->pb_parallelism
: 1;
49 GIT_ERROR_CHECK_VERSION(&opts
->callbacks
, GIT_REMOTE_CALLBACKS_VERSION
, "git_remote_callbacks");
50 memcpy(&p
->callbacks
, &opts
->callbacks
, sizeof(git_remote_callbacks
));
53 if (git_vector_init(&p
->specs
, 0, push_spec_rref_cmp
) < 0) {
58 if (git_vector_init(&p
->status
, 0, push_status_ref_cmp
) < 0) {
59 git_vector_free(&p
->specs
);
64 if (git_vector_init(&p
->updates
, 0, NULL
) < 0) {
65 git_vector_free(&p
->status
);
66 git_vector_free(&p
->specs
);
75 static void free_refspec(push_spec
*spec
)
80 git_refspec__dispose(&spec
->refspec
);
84 static int check_rref(char *ref
)
86 if (git__prefixcmp(ref
, "refs/")) {
87 git_error_set(GIT_ERROR_INVALID
, "not a valid reference '%s'", ref
);
94 static int check_lref(git_push
*push
, char *ref
)
96 /* lref must be resolvable to an existing object */
98 int error
= git_revparse_single(&obj
, push
->repo
, ref
);
104 if (error
== GIT_ENOTFOUND
)
105 git_error_set(GIT_ERROR_REFERENCE
,
106 "src refspec '%s' does not match any existing object", ref
);
108 git_error_set(GIT_ERROR_INVALID
, "not a valid reference '%s'", ref
);
112 static int parse_refspec(git_push
*push
, push_spec
**spec
, const char *str
)
118 s
= git__calloc(1, sizeof(*s
));
119 GIT_ERROR_CHECK_ALLOC(s
);
121 if (git_refspec__parse(&s
->refspec
, str
, false) < 0) {
122 git_error_set(GIT_ERROR_INVALID
, "invalid refspec %s", str
);
126 if (s
->refspec
.src
&& s
->refspec
.src
[0] != '\0' &&
127 check_lref(push
, s
->refspec
.src
) < 0) {
131 if (check_rref(s
->refspec
.dst
) < 0)
142 int git_push_add_refspec(git_push
*push
, const char *refspec
)
146 if (parse_refspec(push
, &spec
, refspec
) < 0 ||
147 git_vector_insert(&push
->specs
, spec
) < 0)
153 int git_push_update_tips(git_push
*push
, const git_remote_callbacks
*callbacks
)
155 git_str remote_ref_name
= GIT_STR_INIT
;
157 git_refspec
*fetch_spec
;
158 push_spec
*push_spec
= NULL
;
159 git_reference
*remote_ref
;
163 git_vector_foreach(&push
->status
, i
, status
) {
164 int fire_callback
= 1;
166 /* Skip unsuccessful updates which have non-empty messages */
170 /* Find the corresponding remote ref */
171 fetch_spec
= git_remote__matching_refspec(push
->remote
, status
->ref
);
175 /* Clear the buffer which can be dirty from previous iteration */
176 git_str_clear(&remote_ref_name
);
178 if ((error
= git_refspec__transform(&remote_ref_name
, fetch_spec
, status
->ref
)) < 0)
181 /* Find matching push ref spec */
182 git_vector_foreach(&push
->specs
, j
, push_spec
) {
183 if (!strcmp(push_spec
->refspec
.dst
, status
->ref
))
187 /* Could not find the corresponding push ref spec for this push update */
188 if (j
== push
->specs
.length
)
191 /* Update the remote ref */
192 if (git_oid_is_zero(&push_spec
->loid
)) {
193 error
= git_reference_lookup(&remote_ref
, push
->remote
->repo
, git_str_cstr(&remote_ref_name
));
196 error
= git_reference_delete(remote_ref
);
197 git_reference_free(remote_ref
);
200 error
= git_reference_create(NULL
, push
->remote
->repo
,
201 git_str_cstr(&remote_ref_name
), &push_spec
->loid
, 1,
206 if (error
!= GIT_ENOTFOUND
)
213 if (fire_callback
&& callbacks
&& callbacks
->update_tips
) {
214 error
= callbacks
->update_tips(git_str_cstr(&remote_ref_name
),
215 &push_spec
->roid
, &push_spec
->loid
, callbacks
->payload
);
225 git_str_dispose(&remote_ref_name
);
230 * Insert all tags until we find a non-tag object, which is returned
233 static int enqueue_tag(git_object
**out
, git_push
*push
, git_oid
*id
)
235 git_object
*obj
= NULL
, *target
= NULL
;
238 if ((error
= git_object_lookup(&obj
, push
->repo
, id
, GIT_OBJECT_TAG
)) < 0)
241 while (git_object_type(obj
) == GIT_OBJECT_TAG
) {
242 if ((error
= git_packbuilder_insert(push
->pb
, git_object_id(obj
), NULL
)) < 0)
245 if ((error
= git_tag_target(&target
, (git_tag
*) obj
)) < 0)
248 git_object_free(obj
);
253 git_object_free(obj
);
260 static int queue_objects(git_push
*push
)
262 git_remote_head
*head
;
268 if (git_revwalk_new(&rw
, push
->repo
) < 0)
271 git_revwalk_sorting(rw
, GIT_SORT_TIME
);
273 git_vector_foreach(&push
->specs
, i
, spec
) {
277 if (git_oid_is_zero(&spec
->loid
))
279 * Delete reference on remote side;
280 * nothing to do here.
284 if (git_oid_equal(&spec
->loid
, &spec
->roid
))
285 continue; /* up-to-date */
287 if ((error
= git_odb_read_header(&size
, &type
, push
->repo
->_odb
, &spec
->loid
)) < 0)
290 if (type
== GIT_OBJECT_TAG
) {
293 if ((error
= enqueue_tag(&target
, push
, &spec
->loid
)) < 0)
296 if (git_object_type(target
) == GIT_OBJECT_COMMIT
) {
297 if ((error
= git_revwalk_push(rw
, git_object_id(target
))) < 0) {
298 git_object_free(target
);
302 if ((error
= git_packbuilder_insert(
303 push
->pb
, git_object_id(target
), NULL
)) < 0) {
304 git_object_free(target
);
308 git_object_free(target
);
309 } else if ((error
= git_revwalk_push(rw
, &spec
->loid
)) < 0)
312 if (!spec
->refspec
.force
) {
315 if (git_oid_is_zero(&spec
->roid
))
318 if (!git_odb_exists(push
->repo
->_odb
, &spec
->roid
)) {
319 git_error_set(GIT_ERROR_REFERENCE
,
320 "cannot push because a reference that you are trying to update on the remote contains commits that are not present locally.");
321 error
= GIT_ENONFASTFORWARD
;
325 error
= git_merge_base(&base
, push
->repo
,
326 &spec
->loid
, &spec
->roid
);
328 if (error
== GIT_ENOTFOUND
||
329 (!error
&& !git_oid_equal(&base
, &spec
->roid
))) {
330 git_error_set(GIT_ERROR_REFERENCE
,
331 "cannot push non-fastforwardable reference");
332 error
= GIT_ENONFASTFORWARD
;
341 git_vector_foreach(&push
->remote
->refs
, i
, head
) {
342 if (git_oid_is_zero(&head
->oid
))
345 if ((error
= git_revwalk_hide(rw
, &head
->oid
)) < 0 &&
346 error
!= GIT_ENOTFOUND
&& error
!= GIT_EINVALIDSPEC
&& error
!= GIT_EPEEL
)
350 error
= git_packbuilder_insert_walk(push
->pb
, rw
);
353 git_revwalk_free(rw
);
357 static int add_update(git_push
*push
, push_spec
*spec
)
359 git_push_update
*u
= git__calloc(1, sizeof(git_push_update
));
360 GIT_ERROR_CHECK_ALLOC(u
);
362 u
->src_refname
= git__strdup(spec
->refspec
.src
);
363 GIT_ERROR_CHECK_ALLOC(u
->src_refname
);
365 u
->dst_refname
= git__strdup(spec
->refspec
.dst
);
366 GIT_ERROR_CHECK_ALLOC(u
->dst_refname
);
368 git_oid_cpy(&u
->src
, &spec
->roid
);
369 git_oid_cpy(&u
->dst
, &spec
->loid
);
371 return git_vector_insert(&push
->updates
, u
);
374 static int calculate_work(git_push
*push
)
376 git_remote_head
*head
;
380 /* Update local and remote oids*/
382 git_vector_foreach(&push
->specs
, i
, spec
) {
383 if (spec
->refspec
.src
&& spec
->refspec
.src
[0]!= '\0') {
384 /* This is a create or update. Local ref must exist. */
385 if (git_reference_name_to_id(
386 &spec
->loid
, push
->repo
, spec
->refspec
.src
) < 0) {
387 git_error_set(GIT_ERROR_REFERENCE
, "no such reference '%s'", spec
->refspec
.src
);
392 /* Remote ref may or may not (e.g. during create) already exist. */
393 git_vector_foreach(&push
->remote
->refs
, j
, head
) {
394 if (!strcmp(spec
->refspec
.dst
, head
->name
)) {
395 git_oid_cpy(&spec
->roid
, &head
->oid
);
400 if (add_update(push
, spec
) < 0)
407 static int do_push(git_push
*push
)
410 git_transport
*transport
= push
->remote
->transport
;
411 git_remote_callbacks
*callbacks
= &push
->callbacks
;
413 if (!transport
->push
) {
414 git_error_set(GIT_ERROR_NET
, "remote transport doesn't support push");
420 * A pack-file MUST be sent if either create or update command
421 * is used, even if the server already has all the necessary
422 * objects. In this case the client MUST send an empty pack-file.
425 if ((error
= git_packbuilder_new(&push
->pb
, push
->repo
)) < 0)
428 git_packbuilder_set_threads(push
->pb
, push
->pb_parallelism
);
430 if (callbacks
&& callbacks
->pack_progress
)
431 if ((error
= git_packbuilder_set_callbacks(push
->pb
, callbacks
->pack_progress
, callbacks
->payload
)) < 0)
434 if ((error
= calculate_work(push
)) < 0)
437 if (callbacks
&& callbacks
->push_negotiation
&&
438 (error
= callbacks
->push_negotiation((const git_push_update
**) push
->updates
.contents
,
439 push
->updates
.length
, callbacks
->payload
)) < 0)
442 if ((error
= queue_objects(push
)) < 0 ||
443 (error
= transport
->push(transport
, push
)) < 0)
447 git_packbuilder_free(push
->pb
);
451 static int filter_refs(git_remote
*remote
)
453 const git_remote_head
**heads
;
456 git_vector_clear(&remote
->refs
);
458 if (git_remote_ls(&heads
, &heads_len
, remote
) < 0)
461 for (i
= 0; i
< heads_len
; i
++) {
462 if (git_vector_insert(&remote
->refs
, (void *)heads
[i
]) < 0)
469 int git_push_finish(git_push
*push
)
473 if (!git_remote_connected(push
->remote
)) {
474 git_error_set(GIT_ERROR_NET
, "remote is disconnected");
478 if ((error
= filter_refs(push
->remote
)) < 0 ||
479 (error
= do_push(push
)) < 0)
482 if (!push
->unpack_ok
) {
484 git_error_set(GIT_ERROR_NET
, "unpacking the sent packfile failed on the remote");
490 int git_push_status_foreach(git_push
*push
,
491 int (*cb
)(const char *ref
, const char *msg
, void *data
),
497 git_vector_foreach(&push
->status
, i
, status
) {
498 int error
= cb(status
->ref
, status
->msg
, data
);
500 return git_error_set_after_callback(error
);
506 void git_push_status_free(push_status
*status
)
511 git__free(status
->msg
);
512 git__free(status
->ref
);
516 void git_push_free(git_push
*push
)
520 git_push_update
*update
;
526 git_vector_foreach(&push
->specs
, i
, spec
) {
529 git_vector_free(&push
->specs
);
531 git_vector_foreach(&push
->status
, i
, status
) {
532 git_push_status_free(status
);
534 git_vector_free(&push
->status
);
536 git_vector_foreach(&push
->updates
, i
, update
) {
537 git__free(update
->src_refname
);
538 git__free(update
->dst_refname
);
541 git_vector_free(&push
->updates
);
546 int git_push_options_init(git_push_options
*opts
, unsigned int version
)
548 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
549 opts
, version
, git_push_options
, GIT_PUSH_OPTIONS_INIT
);
553 #ifndef GIT_DEPRECATE_HARD
554 int git_push_init_options(git_push_options
*opts
, unsigned int version
)
556 return git_push_options_init(opts
, version
);