diff options
| -rw-r--r-- | src/pack-objects.c | 6 | ||||
| -rw-r--r-- | src/push.c | 171 | ||||
| -rw-r--r-- | src/transports/local.c | 23 |
3 files changed, 25 insertions, 175 deletions
diff --git a/src/pack-objects.c b/src/pack-objects.c index ef272e8f5..e9245143c 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1642,7 +1642,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree) if ((error = retrieve_object(&obj, pb, git_tree_id(tree))) < 0) return error; - if (obj->seen) + if (obj->seen || obj->uninteresting) return 0; obj->seen = 1; @@ -1666,6 +1666,10 @@ int insert_tree(git_packbuilder *pb, git_tree *tree) break; case GIT_OBJ_BLOB: + if ((error = retrieve_object(&obj, pb, git_tree_id(tree))) < 0) + return error; + if (obj->uninteresting) + continue; name = git_tree_entry_name(entry); if ((error = git_packbuilder_insert(pb, entry_id, name)) < 0) return error; diff --git a/src/push.c b/src/push.c index 41b66df06..85b683e62 100644 --- a/src/push.c +++ b/src/push.c @@ -263,12 +263,11 @@ static int enqueue_tag(git_object **out, git_push *push, git_oid *id) return error; } -static int revwalk(git_vector *commits, git_push *push) +static int queue_objects(git_push *push) { git_remote_head *head; push_spec *spec; git_revwalk *rw; - git_oid oid; unsigned int i; int error = -1; @@ -353,176 +352,10 @@ static int revwalk(git_vector *commits, git_push *push) git_revwalk_hide(rw, &head->oid); } - while ((error = git_revwalk_next(&oid, rw)) == 0) { - git_oid *o = git__malloc(GIT_OID_RAWSZ); - if (!o) { - error = -1; - goto on_error; - } - git_oid_cpy(o, &oid); - if ((error = git_vector_insert(commits, o)) < 0) - goto on_error; - } + error = git_packbuilder_insert_walk(push->pb, rw); on_error: git_revwalk_free(rw); - return error == GIT_ITEROVER ? 0 : error; -} - -static int enqueue_object( - const git_tree_entry *entry, - git_packbuilder *pb) -{ - switch (git_tree_entry_type(entry)) { - case GIT_OBJ_COMMIT: - return 0; - case GIT_OBJ_TREE: - return git_packbuilder_insert_tree(pb, entry->oid); - default: - return git_packbuilder_insert(pb, entry->oid, entry->filename); - } -} - -static int queue_differences( - git_tree *base, - git_tree *delta, - git_packbuilder *pb) -{ - git_tree *b_child = NULL, *d_child = NULL; - size_t b_length = git_tree_entrycount(base); - size_t d_length = git_tree_entrycount(delta); - size_t i = 0, j = 0; - int error; - - while (i < b_length && j < d_length) { - const git_tree_entry *b_entry = git_tree_entry_byindex(base, i); - const git_tree_entry *d_entry = git_tree_entry_byindex(delta, j); - int cmp = 0; - - if (!git_oid__cmp(b_entry->oid, d_entry->oid)) - goto loop; - - cmp = strcmp(b_entry->filename, d_entry->filename); - - /* If the entries are both trees and they have the same name but are - * different, then we'll recurse after adding the right-hand entry */ - if (!cmp && - git_tree_entry__is_tree(b_entry) && - git_tree_entry__is_tree(d_entry)) { - /* Add the right-hand entry */ - if ((error = git_packbuilder_insert(pb, d_entry->oid, - d_entry->filename)) < 0) - goto on_error; - - /* Acquire the subtrees and recurse */ - if ((error = git_tree_lookup(&b_child, - git_tree_owner(base), b_entry->oid)) < 0 || - (error = git_tree_lookup(&d_child, - git_tree_owner(delta), d_entry->oid)) < 0 || - (error = queue_differences(b_child, d_child, pb)) < 0) - goto on_error; - - git_tree_free(b_child); b_child = NULL; - git_tree_free(d_child); d_child = NULL; - } - /* If the object is new or different in the right-hand tree, - * then enumerate it */ - else if (cmp >= 0 && - (error = enqueue_object(d_entry, pb)) < 0) - goto on_error; - - loop: - if (cmp <= 0) i++; - if (cmp >= 0) j++; - } - - /* Drain the right-hand tree of entries */ - for (; j < d_length; j++) - if ((error = enqueue_object(git_tree_entry_byindex(delta, j), pb)) < 0) - goto on_error; - - error = 0; - -on_error: - if (b_child) - git_tree_free(b_child); - - if (d_child) - git_tree_free(d_child); - - return error; -} - -static int queue_objects(git_push *push) -{ - git_vector commits = GIT_VECTOR_INIT; - git_oid *oid; - size_t i; - unsigned j; - int error; - - if ((error = revwalk(&commits, push)) < 0) - goto on_error; - - git_vector_foreach(&commits, i, oid) { - git_commit *parent = NULL, *commit; - git_tree *tree = NULL, *ptree = NULL; - size_t parentcount; - - if ((error = git_commit_lookup(&commit, push->repo, oid)) < 0) - goto on_error; - - /* Insert the commit */ - if ((error = git_packbuilder_insert(push->pb, oid, NULL)) < 0) - goto loop_error; - - parentcount = git_commit_parentcount(commit); - - if (!parentcount) { - if ((error = git_packbuilder_insert_tree(push->pb, - git_commit_tree_id(commit))) < 0) - goto loop_error; - } else { - if ((error = git_tree_lookup(&tree, push->repo, - git_commit_tree_id(commit))) < 0 || - (error = git_packbuilder_insert(push->pb, - git_commit_tree_id(commit), NULL)) < 0) - goto loop_error; - - /* For each parent, add the items which are different */ - for (j = 0; j < parentcount; j++) { - if ((error = git_commit_parent(&parent, commit, j)) < 0 || - (error = git_commit_tree(&ptree, parent)) < 0 || - (error = queue_differences(ptree, tree, push->pb)) < 0) - goto loop_error; - - git_tree_free(ptree); ptree = NULL; - git_commit_free(parent); parent = NULL; - } - } - - error = 0; - - loop_error: - if (tree) - git_tree_free(tree); - - if (ptree) - git_tree_free(ptree); - - if (parent) - git_commit_free(parent); - - git_commit_free(commit); - - if (error < 0) - goto on_error; - } - - error = 0; - -on_error: - git_vector_free_deep(&commits); return error; } diff --git a/src/transports/local.c b/src/transports/local.c index 733ed2c20..ae117db29 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -507,6 +507,21 @@ static int local_counting(int stage, unsigned int current, unsigned int total, v return error; } +static int foreach_reference_cb(git_reference *reference, void *payload) +{ + git_revwalk *walk = (git_revwalk *)payload; + + int error = git_revwalk_hide(walk, git_reference_target(reference)); + /* The reference is in the local repository, so the target may not + * exist on the remote. It also may not be a commit. */ + if (error == GIT_ENOTFOUND || error == GITERR_INVALID) { + giterr_clear(); + error = 0; + } + + return error; +} + static int local_download_pack( git_transport *transport, git_repository *repo, @@ -546,11 +561,6 @@ static int local_download_pack( if (git_object_type(obj) == GIT_OBJ_COMMIT) { /* Revwalker includes only wanted commits */ error = git_revwalk_push(walk, &rhead->oid); - if (!error && !git_oid_iszero(&rhead->loid)) { - error = git_revwalk_hide(walk, &rhead->loid); - if (error == GIT_ENOTFOUND) - error = 0; - } } else { /* Tag or some other wanted object. Add it on its own */ error = git_packbuilder_insert_recur(pack, &rhead->oid, rhead->name); @@ -560,6 +570,9 @@ static int local_download_pack( goto cleanup; } + if ((error = git_reference_foreach(repo, foreach_reference_cb, walk))) + goto cleanup; + if ((error = git_packbuilder_insert_walk(pack, walk))) goto cleanup; |
