diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2013-08-12 16:15:36 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2013-08-16 01:32:29 +0200 |
commit | 5ce6c1e917a4282455fef6c7fd2236a7fb68653a (patch) | |
tree | d46873e7c6557268fb2a8428f7ddfb0838859d60 /src/push.c | |
parent | 1c13b0bfdcfb510863a6e5e3238f8a461551aa0f (diff) | |
download | libgit2-5ce6c1e917a4282455fef6c7fd2236a7fb68653a.tar.gz |
push: handle tag chains correctly
When dealing with a chain of tags, we need to enqueue each of them
individually, which means we can't use `git_tag_peel` as that jumps
over the intermediate tags.
Do the peeling manually so we can look at each object and take the
appropriate action.
Diffstat (limited to 'src/push.c')
-rw-r--r-- | src/push.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src/push.c b/src/push.c index 452d71789..eaaa46248 100644 --- a/src/push.c +++ b/src/push.c @@ -233,6 +233,37 @@ on_error: return error; } +/** + * Insert all tags until we find a non-tag object, which is returned + * in `out`. + */ +static int enqueue_tag(git_object **out, git_push *push, git_oid *id) +{ + git_object *obj = NULL, *target = NULL; + int error; + + if ((error = git_object_lookup(&obj, push->repo, id, GIT_OBJ_TAG)) < 0) + return error; + + while (git_object_type(obj) == GIT_OBJ_TAG) { + if ((error = git_packbuilder_insert(push->pb, git_object_id(obj), NULL)) < 0) + break; + + if ((error = git_tag_target(&target, (git_tag *) obj)) < 0) + break; + + git_object_free(obj); + obj = target; + } + + if (error < 0) + git_object_free(obj); + else + *out = obj; + + return error; +} + static int revwalk(git_vector *commits, git_push *push) { git_remote_head *head; @@ -265,21 +296,11 @@ static int revwalk(git_vector *commits, git_push *push) goto on_error; if (type == GIT_OBJ_TAG) { - git_tag *tag; git_object *target; - if (git_packbuilder_insert(push->pb, &spec->loid, NULL) < 0) + if ((error = enqueue_tag(&target, push, &spec->loid)) < 0) goto on_error; - if (git_tag_lookup(&tag, push->repo, &spec->loid) < 0) - goto on_error; - - if (git_tag_peel(&target, tag) < 0) { - git_tag_free(tag); - goto on_error; - } - git_tag_free(tag); - if (git_object_type(target) == GIT_OBJ_COMMIT) { if (git_revwalk_push(rw, git_object_id(target)) < 0) { git_object_free(target); |