summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-03-04 20:57:52 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2015-03-11 02:37:25 +0100
commite68b31a1a9f338908a4c72d48734b30c303f0901 (patch)
treec63f8a044c87ffe625d59ea05a3e59bcb42c168e
parent04a36feff152fef2fd5f45c46b5cf25e84c7099f (diff)
downloadlibgit2-cmn/pack-objects-walk.tar.gz
local: let the packbuilder perform smarter object insertioncmn/pack-objects-walk
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.
-rw-r--r--src/transports/local.c42
1 files changed, 10 insertions, 32 deletions
diff --git a/src/transports/local.c b/src/transports/local.c
index bedd2390b..620d63ab4 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -513,7 +513,6 @@ static int local_download_pack(
git_remote_head *rhead;
unsigned int i;
int error = -1;
- git_oid oid;
git_packbuilder *pack = NULL;
git_odb_writepack *writepack = NULL;
git_odb *odb = NULL;
@@ -539,15 +538,22 @@ 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 (!git_oid_iszero(&rhead->loid))
+ 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(pack, &rhead->oid, rhead->name);
}
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)
goto cleanup;
@@ -559,35 +565,6 @@ static int local_download_pack(
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
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 */
git_buf_clear(&progress_info);
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)
goto cleanup;
}
+
error = writepack->commit(writepack, stats);
cleanup: