local: let the packbuilder perform smarter object insertion

Currently we use the most naïve and inefficient method for figuring out
which objects to send to the remote whereby we end up trying to insert
subdirs which have not changed multiple times.

Instead, make use of the packbuilder's built-in more efficient method
which uses the walk to feed the object list and avoids inserting an
object and its descendants.
This commit is contained in:
Carlos Martín Nieto 2015-03-04 20:57:52 +01:00
parent 04a36feff1
commit e68b31a1a9

View File

@ -513,7 +513,6 @@ static int local_download_pack(
git_remote_head *rhead; git_remote_head *rhead;
unsigned int i; unsigned int i;
int error = -1; int error = -1;
git_oid oid;
git_packbuilder *pack = NULL; git_packbuilder *pack = NULL;
git_odb_writepack *writepack = NULL; git_odb_writepack *writepack = NULL;
git_odb *odb = NULL; git_odb *odb = NULL;
@ -539,15 +538,22 @@ static int local_download_pack(
if (git_object_type(obj) == GIT_OBJ_COMMIT) { if (git_object_type(obj) == GIT_OBJ_COMMIT) {
/* Revwalker includes only wanted commits */ /* Revwalker includes only wanted commits */
error = git_revwalk_push(walk, &rhead->oid); error = git_revwalk_push(walk, &rhead->oid);
if (!git_oid_iszero(&rhead->loid)) if (!error && !git_oid_iszero(&rhead->loid)) {
error = git_revwalk_hide(walk, &rhead->loid); error = git_revwalk_hide(walk, &rhead->loid);
if (error == GIT_ENOTFOUND)
error = 0;
}
} else { } else {
/* Tag or some other wanted object. Add it on its own */
error = git_packbuilder_insert(pack, &rhead->oid, rhead->name); error = git_packbuilder_insert(pack, &rhead->oid, rhead->name);
} }
git_object_free(obj); git_object_free(obj);
if (error < 0)
goto cleanup;
} }
if ((error = git_packbuilder_insert_walk(pack, walk)))
goto cleanup;
if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0) if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
goto cleanup; goto cleanup;
@ -559,35 +565,6 @@ static int local_download_pack(
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
goto cleanup; goto cleanup;
while ((error = git_revwalk_next(&oid, walk)) == 0) {
git_commit *commit;
/* Skip commits we already have */
if (git_odb_exists(odb, &oid)) continue;
if (!git_object_lookup((git_object**)&commit, t->repo, &oid, GIT_OBJ_COMMIT)) {
const git_oid *tree_oid = git_commit_tree_id(commit);
/* Add the commit and its tree */
if ((error = git_packbuilder_insert(pack, &oid, NULL)) < 0 ||
(error = git_packbuilder_insert_tree(pack, tree_oid)) < 0) {
git_commit_free(commit);
goto cleanup;
}
git_commit_free(commit);
git_buf_clear(&progress_info);
if ((error = git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack))) < 0)
goto cleanup;
if (t->progress_cb &&
(error = t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload)) < 0)
goto cleanup;
}
}
/* One last one with the newline */ /* One last one with the newline */
git_buf_clear(&progress_info); git_buf_clear(&progress_info);
git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack)); git_buf_printf(&progress_info, counting_objects_fmt, git_packbuilder_object_count(pack));
@ -612,6 +589,7 @@ static int local_download_pack(
if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0) if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) != 0)
goto cleanup; goto cleanup;
} }
error = writepack->commit(writepack, stats); error = writepack->commit(writepack, stats);
cleanup: cleanup: