]>
git.proxmox.com Git - libgit2.git/blob - src/push.c
34867c2e432b4a420303de54cf3d88400f7acba1
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
)
38 p
= git__calloc(1, sizeof(*p
));
39 GIT_ERROR_CHECK_ALLOC(p
);
41 p
->repo
= remote
->repo
;
44 p
->pb_parallelism
= 1;
46 if (git_vector_init(&p
->specs
, 0, push_spec_rref_cmp
) < 0) {
51 if (git_vector_init(&p
->status
, 0, push_status_ref_cmp
) < 0) {
52 git_vector_free(&p
->specs
);
57 if (git_vector_init(&p
->updates
, 0, NULL
) < 0) {
58 git_vector_free(&p
->status
);
59 git_vector_free(&p
->specs
);
68 int git_push_set_options(git_push
*push
, const git_push_options
*opts
)
73 GIT_ERROR_CHECK_VERSION(opts
, GIT_PUSH_OPTIONS_VERSION
, "git_push_options");
75 push
->pb_parallelism
= opts
->pb_parallelism
;
76 push
->connection
.custom_headers
= &opts
->custom_headers
;
77 push
->connection
.proxy
= &opts
->proxy_opts
;
82 static void free_refspec(push_spec
*spec
)
87 git_refspec__dispose(&spec
->refspec
);
91 static int check_rref(char *ref
)
93 if (git__prefixcmp(ref
, "refs/")) {
94 git_error_set(GIT_ERROR_INVALID
, "not a valid reference '%s'", ref
);
101 static int check_lref(git_push
*push
, char *ref
)
103 /* lref must be resolvable to an existing object */
105 int error
= git_revparse_single(&obj
, push
->repo
, ref
);
106 git_object_free(obj
);
111 if (error
== GIT_ENOTFOUND
)
112 git_error_set(GIT_ERROR_REFERENCE
,
113 "src refspec '%s' does not match any existing object", ref
);
115 git_error_set(GIT_ERROR_INVALID
, "not a valid reference '%s'", ref
);
119 static int parse_refspec(git_push
*push
, push_spec
**spec
, const char *str
)
125 s
= git__calloc(1, sizeof(*s
));
126 GIT_ERROR_CHECK_ALLOC(s
);
128 if (git_refspec__parse(&s
->refspec
, str
, false) < 0) {
129 git_error_set(GIT_ERROR_INVALID
, "invalid refspec %s", str
);
133 if (s
->refspec
.src
&& s
->refspec
.src
[0] != '\0' &&
134 check_lref(push
, s
->refspec
.src
) < 0) {
138 if (check_rref(s
->refspec
.dst
) < 0)
149 int git_push_add_refspec(git_push
*push
, const char *refspec
)
153 if (parse_refspec(push
, &spec
, refspec
) < 0 ||
154 git_vector_insert(&push
->specs
, spec
) < 0)
160 int git_push_update_tips(git_push
*push
, const git_remote_callbacks
*callbacks
)
162 git_buf remote_ref_name
= GIT_BUF_INIT
;
164 git_refspec
*fetch_spec
;
165 push_spec
*push_spec
= NULL
;
166 git_reference
*remote_ref
;
170 git_vector_foreach(&push
->status
, i
, status
) {
171 int fire_callback
= 1;
173 /* Skip unsuccessful updates which have non-empty messages */
177 /* Find the corresponding remote ref */
178 fetch_spec
= git_remote__matching_refspec(push
->remote
, status
->ref
);
182 /* Clear the buffer which can be dirty from previous iteration */
183 git_buf_clear(&remote_ref_name
);
185 if ((error
= git_refspec_transform(&remote_ref_name
, fetch_spec
, status
->ref
)) < 0)
188 /* Find matching push ref spec */
189 git_vector_foreach(&push
->specs
, j
, push_spec
) {
190 if (!strcmp(push_spec
->refspec
.dst
, status
->ref
))
194 /* Could not find the corresponding push ref spec for this push update */
195 if (j
== push
->specs
.length
)
198 /* Update the remote ref */
199 if (git_oid_is_zero(&push_spec
->loid
)) {
200 error
= git_reference_lookup(&remote_ref
, push
->remote
->repo
, git_buf_cstr(&remote_ref_name
));
203 error
= git_reference_delete(remote_ref
);
204 git_reference_free(remote_ref
);
207 error
= git_reference_create(NULL
, push
->remote
->repo
,
208 git_buf_cstr(&remote_ref_name
), &push_spec
->loid
, 1,
213 if (error
!= GIT_ENOTFOUND
)
220 if (fire_callback
&& callbacks
&& callbacks
->update_tips
) {
221 error
= callbacks
->update_tips(git_buf_cstr(&remote_ref_name
),
222 &push_spec
->roid
, &push_spec
->loid
, callbacks
->payload
);
232 git_buf_dispose(&remote_ref_name
);
237 * Insert all tags until we find a non-tag object, which is returned
240 static int enqueue_tag(git_object
**out
, git_push
*push
, git_oid
*id
)
242 git_object
*obj
= NULL
, *target
= NULL
;
245 if ((error
= git_object_lookup(&obj
, push
->repo
, id
, GIT_OBJECT_TAG
)) < 0)
248 while (git_object_type(obj
) == GIT_OBJECT_TAG
) {
249 if ((error
= git_packbuilder_insert(push
->pb
, git_object_id(obj
), NULL
)) < 0)
252 if ((error
= git_tag_target(&target
, (git_tag
*) obj
)) < 0)
255 git_object_free(obj
);
260 git_object_free(obj
);
267 static int queue_objects(git_push
*push
)
269 git_remote_head
*head
;
275 if (git_revwalk_new(&rw
, push
->repo
) < 0)
278 git_revwalk_sorting(rw
, GIT_SORT_TIME
);
280 git_vector_foreach(&push
->specs
, i
, spec
) {
284 if (git_oid_is_zero(&spec
->loid
))
286 * Delete reference on remote side;
287 * nothing to do here.
291 if (git_oid_equal(&spec
->loid
, &spec
->roid
))
292 continue; /* up-to-date */
294 if (git_odb_read_header(&size
, &type
, push
->repo
->_odb
, &spec
->loid
) < 0)
297 if (type
== GIT_OBJECT_TAG
) {
300 if ((error
= enqueue_tag(&target
, push
, &spec
->loid
)) < 0)
303 if (git_object_type(target
) == GIT_OBJECT_COMMIT
) {
304 if (git_revwalk_push(rw
, git_object_id(target
)) < 0) {
305 git_object_free(target
);
309 if (git_packbuilder_insert(
310 push
->pb
, git_object_id(target
), NULL
) < 0) {
311 git_object_free(target
);
315 git_object_free(target
);
316 } else if (git_revwalk_push(rw
, &spec
->loid
) < 0)
319 if (!spec
->refspec
.force
) {
322 if (git_oid_is_zero(&spec
->roid
))
325 if (!git_odb_exists(push
->repo
->_odb
, &spec
->roid
)) {
326 git_error_set(GIT_ERROR_REFERENCE
,
327 "cannot push because a reference that you are trying to update on the remote contains commits that are not present locally.");
328 error
= GIT_ENONFASTFORWARD
;
332 error
= git_merge_base(&base
, push
->repo
,
333 &spec
->loid
, &spec
->roid
);
335 if (error
== GIT_ENOTFOUND
||
336 (!error
&& !git_oid_equal(&base
, &spec
->roid
))) {
337 git_error_set(GIT_ERROR_REFERENCE
,
338 "cannot push non-fastforwardable reference");
339 error
= GIT_ENONFASTFORWARD
;
348 git_vector_foreach(&push
->remote
->refs
, i
, head
) {
349 if (git_oid_is_zero(&head
->oid
))
352 if ((error
= git_revwalk_hide(rw
, &head
->oid
)) < 0 &&
353 error
!= GIT_ENOTFOUND
&& error
!= GIT_EINVALIDSPEC
&& error
!= GIT_EPEEL
)
357 error
= git_packbuilder_insert_walk(push
->pb
, rw
);
360 git_revwalk_free(rw
);
364 static int add_update(git_push
*push
, push_spec
*spec
)
366 git_push_update
*u
= git__calloc(1, sizeof(git_push_update
));
367 GIT_ERROR_CHECK_ALLOC(u
);
369 u
->src_refname
= git__strdup(spec
->refspec
.src
);
370 GIT_ERROR_CHECK_ALLOC(u
->src_refname
);
372 u
->dst_refname
= git__strdup(spec
->refspec
.dst
);
373 GIT_ERROR_CHECK_ALLOC(u
->dst_refname
);
375 git_oid_cpy(&u
->src
, &spec
->roid
);
376 git_oid_cpy(&u
->dst
, &spec
->loid
);
378 return git_vector_insert(&push
->updates
, u
);
381 static int calculate_work(git_push
*push
)
383 git_remote_head
*head
;
387 /* Update local and remote oids*/
389 git_vector_foreach(&push
->specs
, i
, spec
) {
390 if (spec
->refspec
.src
&& spec
->refspec
.src
[0]!= '\0') {
391 /* This is a create or update. Local ref must exist. */
392 if (git_reference_name_to_id(
393 &spec
->loid
, push
->repo
, spec
->refspec
.src
) < 0) {
394 git_error_set(GIT_ERROR_REFERENCE
, "no such reference '%s'", spec
->refspec
.src
);
399 /* Remote ref may or may not (e.g. during create) already exist. */
400 git_vector_foreach(&push
->remote
->refs
, j
, head
) {
401 if (!strcmp(spec
->refspec
.dst
, head
->name
)) {
402 git_oid_cpy(&spec
->roid
, &head
->oid
);
407 if (add_update(push
, spec
) < 0)
414 static int do_push(git_push
*push
, const git_remote_callbacks
*callbacks
)
417 git_transport
*transport
= push
->remote
->transport
;
419 if (!transport
->push
) {
420 git_error_set(GIT_ERROR_NET
, "remote transport doesn't support push");
426 * A pack-file MUST be sent if either create or update command
427 * is used, even if the server already has all the necessary
428 * objects. In this case the client MUST send an empty pack-file.
431 if ((error
= git_packbuilder_new(&push
->pb
, push
->repo
)) < 0)
434 git_packbuilder_set_threads(push
->pb
, push
->pb_parallelism
);
436 if (callbacks
&& callbacks
->pack_progress
)
437 if ((error
= git_packbuilder_set_callbacks(push
->pb
, callbacks
->pack_progress
, callbacks
->payload
)) < 0)
440 if ((error
= calculate_work(push
)) < 0)
443 if (callbacks
&& callbacks
->push_negotiation
&&
444 (error
= callbacks
->push_negotiation((const git_push_update
**) push
->updates
.contents
,
445 push
->updates
.length
, callbacks
->payload
)) < 0)
448 if ((error
= queue_objects(push
)) < 0 ||
449 (error
= transport
->push(transport
, push
, callbacks
)) < 0)
453 git_packbuilder_free(push
->pb
);
457 static int filter_refs(git_remote
*remote
)
459 const git_remote_head
**heads
;
462 git_vector_clear(&remote
->refs
);
464 if (git_remote_ls(&heads
, &heads_len
, remote
) < 0)
467 for (i
= 0; i
< heads_len
; i
++) {
468 if (git_vector_insert(&remote
->refs
, (void *)heads
[i
]) < 0)
475 int git_push_finish(git_push
*push
, const git_remote_callbacks
*callbacks
)
479 if (!git_remote_connected(push
->remote
) &&
480 (error
= git_remote__connect(push
->remote
, GIT_DIRECTION_PUSH
, callbacks
, &push
->connection
)) < 0)
483 if ((error
= filter_refs(push
->remote
)) < 0 ||
484 (error
= do_push(push
, callbacks
)) < 0)
487 if (!push
->unpack_ok
) {
489 git_error_set(GIT_ERROR_NET
, "unpacking the sent packfile failed on the remote");
495 int git_push_status_foreach(git_push
*push
,
496 int (*cb
)(const char *ref
, const char *msg
, void *data
),
502 git_vector_foreach(&push
->status
, i
, status
) {
503 int error
= cb(status
->ref
, status
->msg
, data
);
505 return git_error_set_after_callback(error
);
511 void git_push_status_free(push_status
*status
)
516 git__free(status
->msg
);
517 git__free(status
->ref
);
521 void git_push_free(git_push
*push
)
525 git_push_update
*update
;
531 git_vector_foreach(&push
->specs
, i
, spec
) {
534 git_vector_free(&push
->specs
);
536 git_vector_foreach(&push
->status
, i
, status
) {
537 git_push_status_free(status
);
539 git_vector_free(&push
->status
);
541 git_vector_foreach(&push
->updates
, i
, update
) {
542 git__free(update
->src_refname
);
543 git__free(update
->dst_refname
);
546 git_vector_free(&push
->updates
);
551 int git_push_options_init(git_push_options
*opts
, unsigned int version
)
553 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
554 opts
, version
, git_push_options
, GIT_PUSH_OPTIONS_INIT
);
558 int git_push_init_options(git_push_options
*opts
, unsigned int version
)
560 return git_push_options_init(opts
, version
);