]>
git.proxmox.com Git - libgit2.git/blob - src/push.c
2 * Copyright (C) 2009-2012 the libgit2 contributors
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.
12 #include "pack-objects.h"
17 int git_push_new(git_push
**out
, git_remote
*remote
)
23 p
= git__calloc(1, sizeof(*p
));
24 GITERR_CHECK_ALLOC(p
);
26 p
->repo
= remote
->repo
;
30 if (git_vector_init(&p
->specs
, 0, NULL
) < 0) {
35 if (git_vector_init(&p
->status
, 0, NULL
) < 0) {
36 git_vector_free(&p
->specs
);
45 static void free_refspec(push_spec
*spec
)
51 git__free(spec
->lref
);
54 git__free(spec
->rref
);
59 static void free_status(push_status
*status
)
65 git__free(status
->msg
);
67 git__free(status
->ref
);
71 static int check_ref(char *ref
)
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
);
82 static int parse_refspec(push_spec
**spec
, const char *str
)
89 s
= git__calloc(1, sizeof(*s
));
90 GITERR_CHECK_ALLOC(s
);
98 if (!ref || check_ref(ref) < 0) goto on_error
100 delim
= strchr(str
, ':');
102 s
->lref
= git__strdup(str
);
106 s
->lref
= git__strndup(str
, delim
- str
);
110 if (strlen(delim
+ 1)) {
111 s
->rref
= git__strdup(delim
+ 1);
116 if (!s
->lref
&& !s
->rref
)
119 /* If rref is ommitted, use the same ref name as lref */
121 s
->rref
= git__strdup(s
->lref
);
135 int git_push_add_refspec(git_push
*push
, const char *refspec
)
139 if (parse_refspec(&spec
, refspec
) < 0 ||
140 git_vector_insert(&push
->specs
, spec
) < 0)
146 static int revwalk(git_vector
*commits
, git_push
*push
)
148 git_remote_head
*head
;
155 if (git_revwalk_new(&rw
, push
->repo
) < 0)
158 git_revwalk_sorting(rw
, GIT_SORT_TIME
);
160 git_vector_foreach(&push
->specs
, i
, spec
) {
161 if (git_oid_iszero(&spec
->loid
))
163 * Delete reference on remote side;
164 * nothing to do here.
168 if (git_oid_equal(&spec
->loid
, &spec
->roid
))
169 continue; /* up-to-date */
171 if (git_revwalk_push(rw
, &spec
->loid
) < 0)
177 if (git_oid_iszero(&spec
->roid
))
180 if (!git_odb_exists(push
->repo
->_odb
, &spec
->roid
)) {
182 error
= GIT_ENONFASTFORWARD
;
186 error
= git_merge_base(&base
, push
->repo
,
187 &spec
->loid
, &spec
->roid
);
189 if (error
== GIT_ENOTFOUND
||
190 (!error
&& !git_oid_equal(&base
, &spec
->roid
))) {
192 error
= GIT_ENONFASTFORWARD
;
201 git_vector_foreach(&push
->remote
->refs
, i
, head
) {
202 if (git_oid_iszero(&head
->oid
))
206 git_revwalk_hide(rw
, &head
->oid
);
209 while ((error
= git_revwalk_next(&oid
, rw
)) == 0) {
210 git_oid
*o
= git__malloc(GIT_OID_RAWSZ
);
211 GITERR_CHECK_ALLOC(o
);
212 git_oid_cpy(o
, &oid
);
213 if (git_vector_insert(commits
, o
) < 0) {
220 git_revwalk_free(rw
);
221 return error
== GIT_ITEROVER
? 0 : error
;
224 static int queue_objects(git_push
*push
)
231 if (git_vector_init(&commits
, 0, NULL
) < 0)
234 if ((error
= revwalk(&commits
, push
)) < 0)
237 if (!commits
.length
) {
238 git_vector_free(&commits
);
239 return 0; /* nothing to do */
242 git_vector_foreach(&commits
, i
, o
) {
243 if ((error
= git_packbuilder_insert(push
->pb
, o
, NULL
)) < 0)
247 git_vector_foreach(&commits
, i
, o
) {
250 if ((error
= git_object_lookup(&obj
, push
->repo
, o
, GIT_OBJ_ANY
)) < 0)
253 switch (git_object_type(obj
)) {
254 case GIT_OBJ_TAG
: /* TODO: expect tags */
256 if ((error
= git_packbuilder_insert_tree(push
->pb
,
257 git_commit_tree_id((git_commit
*)obj
))) < 0) {
258 git_object_free(obj
);
265 git_object_free(obj
);
266 giterr_set(GITERR_INVALID
, "Given object type invalid");
270 git_object_free(obj
);
275 git_vector_foreach(&commits
, i
, o
) {
278 git_vector_free(&commits
);
282 static int calculate_work(git_push
*push
)
284 git_remote_head
*head
;
288 /* Update local and remote oids*/
290 git_vector_foreach(&push
->specs
, i
, spec
) {
292 /* This is a create or update. Local ref must exist. */
293 if (git_reference_name_to_id(
294 &spec
->loid
, push
->repo
, spec
->lref
) < 0) {
295 giterr_set(GIT_ENOTFOUND
, "No such reference '%s'", spec
->lref
);
301 /* Remote ref may or may not (e.g. during create) already exist. */
302 git_vector_foreach(&push
->remote
->refs
, j
, head
) {
303 if (!strcmp(spec
->rref
, head
->name
)) {
304 git_oid_cpy(&spec
->roid
, &head
->oid
);
314 static int do_push(git_push
*push
)
317 git_transport
*transport
= push
->remote
->transport
;
320 * A pack-file MUST be sent if either create or update command
321 * is used, even if the server already has all the necessary
322 * objects. In this case the client MUST send an empty pack-file.
325 if ((error
= git_packbuilder_new(&push
->pb
, push
->repo
)) < 0 ||
326 (error
= calculate_work(push
)) < 0 ||
327 (error
= queue_objects(push
)) < 0 ||
328 (error
= transport
->push(transport
, push
)) < 0)
334 git_packbuilder_free(push
->pb
);
338 static int cb_filter_refs(git_remote_head
*ref
, void *data
)
340 git_remote
*remote
= (git_remote
*) data
;
341 return git_vector_insert(&remote
->refs
, ref
);
344 static int filter_refs(git_remote
*remote
)
346 git_vector_clear(&remote
->refs
);
347 return git_remote_ls(remote
, cb_filter_refs
, remote
);
350 int git_push_finish(git_push
*push
)
354 if (!git_remote_connected(push
->remote
) &&
355 (error
= git_remote_connect(push
->remote
, GIT_DIRECTION_PUSH
)) < 0)
358 if ((error
= filter_refs(push
->remote
)) < 0 ||
359 (error
= do_push(push
)) < 0)
365 int git_push_unpack_ok(git_push
*push
)
367 return push
->unpack_ok
;
370 int git_push_status_foreach(git_push
*push
,
371 int (*cb
)(const char *ref
, const char *msg
, void *data
),
377 git_vector_foreach(&push
->status
, i
, status
) {
378 if (cb(status
->ref
, status
->msg
, data
) < 0)
385 void git_push_free(git_push
*push
)
394 git_vector_foreach(&push
->specs
, i
, spec
) {
397 git_vector_free(&push
->specs
);
399 git_vector_foreach(&push
->status
, i
, status
) {
402 git_vector_free(&push
->status
);