From 505da062b88b729a90d4bcf31c4075bd0afd3251 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 6 Nov 2012 10:26:06 -0800 Subject: [PATCH 1/6] Implement local transport's fetch --- src/transports/local.c | 145 +++++++++++++++++++++++++++++++++-- tests-clar/clone/nonetwork.c | 7 -- 2 files changed, 138 insertions(+), 14 deletions(-) diff --git a/src/transports/local.c b/src/transports/local.c index 0a63a12ea..8b3a2d481 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -10,11 +10,19 @@ #include "git2/repository.h" #include "git2/object.h" #include "git2/tag.h" -#include "refs.h" #include "git2/transport.h" +#include "git2/revwalk.h" +#include "git2/odb_backend.h" +#include "git2/pack.h" +#include "git2/commit.h" +#include "git2/revparse.h" +#include "pack-objects.h" +#include "refs.h" #include "posix.h" #include "path.h" #include "buffer.h" +#include "repository.h" +#include "odb.h" typedef struct { git_transport parent; @@ -34,7 +42,7 @@ static int add_ref(transport_local *t, const char *name) git_object *obj = NULL, *target = NULL; git_buf buf = GIT_BUF_INIT; - head = (git_remote_head *)git__malloc(sizeof(git_remote_head)); + head = (git_remote_head *)git__calloc(1, sizeof(git_remote_head)); GITERR_CHECK_ALLOC(head); head->name = git__strdup(name); @@ -200,15 +208,137 @@ static int local_ls(git_transport *transport, git_headlist_cb list_cb, void *pay static int local_negotiate_fetch( git_transport *transport, git_repository *repo, - const git_remote_head * const *refs, size_t count) + const git_remote_head * const *refs, + size_t count) { - GIT_UNUSED(transport); - GIT_UNUSED(repo); + transport_local *t = (transport_local*)transport; + git_remote_head *rhead; + unsigned int i; + GIT_UNUSED(refs); GIT_UNUSED(count); - giterr_set(GITERR_NET, "Fetch via local transport isn't implemented. Sorry"); - return -1; + /* Fill in the loids */ + git_vector_foreach(&t->refs, i, rhead) { + git_object *obj; + + int error = git_revparse_single(&obj, repo, rhead->name); + if (!error) + git_oid_cpy(&rhead->loid, git_object_id(obj)); + else if (error != GIT_ENOTFOUND) + return error; + giterr_clear(); + } + + return 0; +} + +typedef struct foreach_data { + git_transfer_progress *stats; + git_transfer_progress_callback progress_cb; + void *progress_payload; + git_odb_writepack *writepack; +} foreach_data; + +static int foreach_cb(void *buf, size_t len, void *payload) +{ + foreach_data *data = (foreach_data*)payload; + + data->stats->received_bytes += len; + return data->writepack->add(data->writepack, buf, len, data->stats); +} + +static int local_download_pack( + git_transport *transport, + git_repository *repo, + git_transfer_progress *stats, + git_transfer_progress_callback progress_cb, + void *progress_payload) +{ + transport_local *t = (transport_local*)transport; + git_revwalk *walk = NULL; + git_remote_head *rhead; + unsigned int i; + int error = -1; + git_oid oid; + git_packbuilder *pack = NULL; + git_odb_writepack *writepack = NULL; + + if ((error = git_revwalk_new(&walk, t->repo)) < 0) + goto cleanup; + git_revwalk_sorting(walk, GIT_SORT_TIME); + + if ((error = git_packbuilder_new(&pack, t->repo)) < 0) + goto cleanup; + + stats->total_objects = 0; + stats->indexed_objects = 0; + stats->received_objects = 0; + stats->received_bytes = 0; + + git_vector_foreach(&t->refs, i, rhead) { + git_object *obj; + if ((error = git_object_lookup(&obj, t->repo, &rhead->oid, GIT_OBJ_ANY)) < 0) + goto cleanup; + + 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)) + error = git_revwalk_hide(walk, &rhead->loid); + } else { + /* Tag or some other wanted object. Add it on its own */ + stats->total_objects++; + error = git_packbuilder_insert(pack, &rhead->oid, rhead->name); + } + git_object_free(obj); + } + + /* Walk the objects, building a packfile */ + + while ((error = git_revwalk_next(&oid, walk)) == 0) { + git_commit *commit; + + stats->total_objects++; + + if (!git_object_lookup((git_object**)&commit, t->repo, &oid, GIT_OBJ_COMMIT)) { + const git_oid *tree_oid = git_commit_tree_oid(commit); + git_commit_free(commit); + + /* Add the commit and its tree */ + if ((error = git_packbuilder_insert(pack, &oid, NULL)) < 0 || + (error = git_packbuilder_insert_tree(pack, tree_oid))) + goto cleanup; + } + } + + if (progress_cb) progress_cb(stats, progress_payload); + + { + git_odb *odb; + if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || + (error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0) + goto cleanup; + } + + /* Write the data to the ODB */ + { + foreach_data data = {0}; + data.stats = stats; + data.progress_cb = progress_cb; + data.progress_payload = progress_payload; + data.writepack = writepack; + + if ((error = git_packbuilder_foreach(pack, foreach_cb, &data)) < 0) + goto cleanup; + } + error = writepack->commit(writepack, stats); + +cleanup: + if (writepack) writepack->free(writepack); + git_packbuilder_free(pack); + git_revwalk_free(walk); + return error; } static int local_is_connected(git_transport *transport, int *connected) @@ -283,6 +413,7 @@ int git_transport_local(git_transport **out, void *param) t->parent.connect = local_connect; t->parent.negotiate_fetch = local_negotiate_fetch; + t->parent.download_pack = local_download_pack; t->parent.close = local_close; t->parent.free = local_free; t->parent.ls = local_ls; diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 3984f3fe7..36bf63670 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -3,7 +3,6 @@ #include "git2/clone.h" #include "repository.h" -#define DO_LOCAL_TEST 0 #define LIVE_REPO_URL "git://github.com/libgit2/TestGitRepository" static git_repository *g_repo; @@ -73,12 +72,9 @@ void test_clone_nonetwork__local(void) { git_buf src = GIT_BUF_INIT; build_local_file_url(&src, cl_fixture("testrepo.git")); - -#if DO_LOCAL_TEST cl_set_cleanup(&cleanup_repository, "./local"); cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL, NULL, NULL)); -#endif git_buf_free(&src); } @@ -87,12 +83,9 @@ void test_clone_nonetwork__local_bare(void) { git_buf src = GIT_BUF_INIT; build_local_file_url(&src, cl_fixture("testrepo.git")); - -#if DO_LOCAL_TEST cl_set_cleanup(&cleanup_repository, "./local.git"); cl_git_pass(git_clone_bare(&g_repo, git_buf_cstr(&src), "./local.git", NULL, NULL)); -#endif git_buf_free(&src); } From 11fabe73a07ba7c5ef4a713d71b3643c9b0970db Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 8 Nov 2012 20:18:19 -0800 Subject: [PATCH 2/6] Local fetch: add tests --- tests-clar/network/fetchlocal.c | 103 ++++++++++++++++++ .../resources/partial-testrepo/.gitted/HEAD | 1 + .../resources/partial-testrepo/.gitted/config | 7 ++ .../resources/partial-testrepo/.gitted/index | Bin 0 -> 328 bytes .../13/85f264afb75a56a5bec74243be9b367ba4ca08 | Bin 0 -> 19 bytes .../14/4344043ba4d4a405da03de3844aa829ae8be0e | Bin 0 -> 163 bytes .../16/8e4ebd1c667499548ae12403b19b22a5c5e925 | Bin 0 -> 147 bytes .../18/1037049a54a1eb5fab404658a3a250b44335d7 | Bin 0 -> 51 bytes .../18/10dff58d8a660512d4832e740f692884338ccd | Bin 0 -> 119 bytes .../45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 | Bin 0 -> 18 bytes .../4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 | 2 + .../4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 | Bin 0 -> 50 bytes .../5b/5b025afb0b4c913b4c338a42934a3863bf3644 | 2 + .../62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc | Bin 0 -> 50 bytes .../66/3adb09143767984f7be83a91effa47e128c735 | Bin 0 -> 19 bytes .../75/057dd4114e74cca1d750d0aee1647c903cb60a | Bin 0 -> 119 bytes .../81/4889a078c031f61ed08ab5fa863aea9314344d | Bin 0 -> 82 bytes .../84/96071c1b46c854b31185ea97743be6a8774479 | Bin 0 -> 126 bytes .../9f/d738e8f7967c078dceed8190330fc8648ee56a | 3 + .../a4/a7dce85cf63874e984719f4fdd239f5145052f | 2 + .../a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd | Bin 0 -> 28 bytes .../a8/233120f6ad708f843d861ce2b7228ec4e3dec6 | Bin 0 -> 26 bytes .../c4/7800c7266a2be04c571c04d5a6614691ea99bd | 3 + .../cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 | Bin 0 -> 162 bytes .../d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 | Bin 0 -> 147 bytes .../f6/0079018b664e4e79329a7ef9559c8d9e0378d1 | Bin 0 -> 82 bytes .../fa/49b077972391ad58037050f2a75f74e3671e92 | Bin 0 -> 24 bytes .../fd/093bff70906175335656e6ce6ae05783708765 | Bin 0 -> 82 bytes .../.gitted/objects/pack/.gitkeep | 0 .../partial-testrepo/.gitted/refs/heads/dir | 1 + 30 files changed, 124 insertions(+) create mode 100644 tests-clar/network/fetchlocal.c create mode 100644 tests-clar/resources/partial-testrepo/.gitted/HEAD create mode 100644 tests-clar/resources/partial-testrepo/.gitted/config create mode 100644 tests-clar/resources/partial-testrepo/.gitted/index create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/16/8e4ebd1c667499548ae12403b19b22a5c5e925 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/18/10dff58d8a660512d4832e740f692884338ccd create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/cf/80f8de9f1185bf3a05f993f6121880dd0cfbc9 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/fd/093bff70906175335656e6ce6ae05783708765 create mode 100644 tests-clar/resources/partial-testrepo/.gitted/objects/pack/.gitkeep create mode 100644 tests-clar/resources/partial-testrepo/.gitted/refs/heads/dir diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c new file mode 100644 index 000000000..85c2575bf --- /dev/null +++ b/tests-clar/network/fetchlocal.c @@ -0,0 +1,103 @@ +#include "clar_libgit2.h" + +#include "buffer.h" +#include "path.h" +#include "remote.h" + +static void build_local_file_url(git_buf *out, const char *fixture) +{ + const char *in_buf; + + git_buf path_buf = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify_dir(&path_buf, fixture, NULL)); + cl_git_pass(git_buf_puts(out, "file://")); + +#ifdef _MSC_VER + /* + * A FILE uri matches the following format: file://[host]/path + * where "host" can be empty and "path" is an absolute path to the resource. + * + * In this test, no hostname is used, but we have to ensure the leading triple slashes: + * + * *nix: file:///usr/home/... + * Windows: file:///C:/Users/... + */ + cl_git_pass(git_buf_putc(out, '/')); +#endif + + in_buf = git_buf_cstr(&path_buf); + + /* + * A very hacky Url encoding that only takes care of escaping the spaces + */ + while (*in_buf) { + if (*in_buf == ' ') + cl_git_pass(git_buf_puts(out, "%20")); + else + cl_git_pass(git_buf_putc(out, *in_buf)); + + in_buf++; + } + + git_buf_free(&path_buf); +} + +static void transfer_cb(const git_transfer_progress *stats, void *payload) +{ + int *callcount = (int*)payload; + GIT_UNUSED(stats); + (*callcount)++; +} + +void test_network_fetchlocal__complete(void) +{ + git_buf url = GIT_BUF_INIT; + git_repository *repo; + git_remote *origin; + int callcount = 0; + git_strarray refnames = {0}; + + build_local_file_url(&url, cl_fixture("testrepo.git")); + cl_git_pass(git_repository_init(&repo, "foo", true)); + + cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, git_buf_cstr(&url))); + cl_git_pass(git_remote_connect(origin, GIT_DIR_FETCH)); + cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_update_tips(origin)); + + cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL)); + cl_assert_equal_i(18, refnames.count); + cl_assert(callcount > 0); + + git_strarray_free(&refnames); + git_remote_free(origin); + git_repository_free(repo); +} + +void test_network_fetchlocal__partial(void) +{ + git_repository *repo = cl_git_sandbox_init("partial-testrepo"); + git_buf url = GIT_BUF_INIT; + git_remote *origin; + int callcount = 0; + git_strarray refnames = {0}; + + cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL)); + cl_assert_equal_i(1, refnames.count); + + build_local_file_url(&url, cl_fixture("testrepo.git")); + cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, git_buf_cstr(&url))); + cl_git_pass(git_remote_connect(origin, GIT_DIR_FETCH)); + cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); + cl_git_pass(git_remote_update_tips(origin)); + + cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL)); + cl_assert_equal_i(19, refnames.count); /* 18 remote + 1 local */ + cl_assert(callcount > 0); + + git_strarray_free(&refnames); + git_remote_free(origin); + + cl_git_sandbox_cleanup(); +} diff --git a/tests-clar/resources/partial-testrepo/.gitted/HEAD b/tests-clar/resources/partial-testrepo/.gitted/HEAD new file mode 100644 index 000000000..4bfb9c93f --- /dev/null +++ b/tests-clar/resources/partial-testrepo/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/dir diff --git a/tests-clar/resources/partial-testrepo/.gitted/config b/tests-clar/resources/partial-testrepo/.gitted/config new file mode 100644 index 000000000..99abaab97 --- /dev/null +++ b/tests-clar/resources/partial-testrepo/.gitted/config @@ -0,0 +1,7 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true +[branch "dir"] diff --git a/tests-clar/resources/partial-testrepo/.gitted/index b/tests-clar/resources/partial-testrepo/.gitted/index new file mode 100644 index 0000000000000000000000000000000000000000..4f241f9142f629a2cccb3f7527906a67ab23478e GIT binary patch literal 328 zcmZ?q402{*U|<4bmVjAz*nu--7WB8+ zw#hu&uGDwr@x5aVY(cJ$F21hF`q9j30-Ey{$sCq6tJ|C+=IJy1t6x}6eE-Y+p~i7j z2KGe#B)yV~5+rw^nbVBs9%k2_&HK!@+pu@snX_km&hCak)f>VY_>+nf^O7^-(=u~X z@tfCzW**OS(YAy4Uo4l&*`Fgc-@zx$>A&G#2KKzva;Q0{LLMu1v`F9O=3sDJ5MF0n I)f+e+0InHZ3;+NC literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 b/tests-clar/resources/partial-testrepo/.gitted/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 new file mode 100644 index 0000000000000000000000000000000000000000..cedb2a22e6914c3bbbed90bbedf8fd2095bf5a7d GIT binary patch literal 19 acmb-^#H0=gNM4#XbHp#9nm{w}~e~VA>HVh0*UTU2h zI2R9X6@d~QlL~cNq^RqWRXRmSLrR(%JGOQZ^5)H}%nh;F=&ild+RI_ zmV#MRj)u23E-Tz*hDTd@OK?t~A6%bP8@F`IOTB>gogYF7*uxPAM6=s{u*n~(xsN7F<>w>FfcPQQ3!H%bn$g%SfOmF@NI2De~WFK%%kl}eMcVO zJ7!`41PX}^Nw33h?e?CjxkvQwq~t@#jW^oro`LF4DoV^t&WKOT%t_TNsVHG^-Pyd) zY`YD6$DKKQw&(0__*17G-5C`FfcPQQ3!H%bn$g%SfOmF@NI2De~WFK%%kl}eMcVO zI|fyeRFs&PoDrXvnUktlQc=R-y0dwo*>)TDjyrSqY|q)<@TYo1I8Fm*0&IVk`D literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 b/tests-clar/resources/partial-testrepo/.gitted/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 new file mode 100644 index 0000000000000000000000000000000000000000..7ca4ceed50400af7e36b25ff200a7be95f0bc61f GIT binary patch literal 18 acmb9W-v4`FgG<-NYX2*C}Bvmy3HwKo<76B`i0fR_rKg9Y8*EO I00q(x`N*;qRsaA1 literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 b/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 new file mode 100644 index 000000000..c1f22c54f --- /dev/null +++ b/tests-clar/resources/partial-testrepo/.gitted/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 @@ -0,0 +1,2 @@ +x 1ENi@k2 "X$YW0YcÅszMD08!s Xgd::@X0Pw"F/RUzmZZV}|/o5I!1z:vUim}/> +F- \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc b/tests-clar/resources/partial-testrepo/.gitted/objects/62/eb56dabb4b9929bc15dd9263c2c733b13d2dcc new file mode 100644 index 0000000000000000000000000000000000000000..b669961d8f9fe449aa715bcc4574e838309f83f1 GIT binary patch literal 50 zcmV-20L}k+0V^p=O;s>9W-v4`Ff%bxNYX2*C}Bvmy3HwKo<76B`i0fR_rKg9Y8*EO I00nyv_QnPi@Bjb+ literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 b/tests-clar/resources/partial-testrepo/.gitted/objects/66/3adb09143767984f7be83a91effa47e128c735 new file mode 100644 index 0000000000000000000000000000000000000000..9ff5eb2b5dde9d39204782babe64bb240aced32f GIT binary patch literal 19 acmb7G-5C`FfcPQQ3!H%bn$g%5N`dHvVMD1*wTH+ot*d0HmhE8 ziUX=5sVFfoIU_zTGbdHAq@skub!YQFv+XwQ9e3vJ*`Bkz;ZOC3aH!I})N-(rU!EJv Zrz=lf8^K%<@M(E`$>VgnNdSzWFYprfIFkSX literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d b/tests-clar/resources/partial-testrepo/.gitted/objects/81/4889a078c031f61ed08ab5fa863aea9314344d new file mode 100644 index 0000000000000000000000000000000000000000..2f9b6b6e3d9250ba09360734aa47973a993b59d1 GIT binary patch literal 82 zcmV-Y0ImOc0V^p=O;s?nWH2-^Ff%bx2y%6F@pWZbp=_w|ZEZn+i*1|CqwPw4M;_lh o233)lTCP`8QNplXwC&*i7t3XG_U8!Ackl^w`fs=w02$OB|A$m1)Bpeg literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 b/tests-clar/resources/partial-testrepo/.gitted/objects/84/96071c1b46c854b31185ea97743be6a8774479 new file mode 100644 index 0000000000000000000000000000000000000000..5df58dda56789631c78aeed62708e1b694440195 GIT binary patch literal 126 zcmV-^0D=E_0iBK82?8+?0R2uC+kmpkZXSY&U

RiSaIAE^xQ@?_ml44FkiJ(R)*{ z(H(TH6>PFd5&0~h#n$X!k{LPpBqYvbW+w8_Xyl{wSm9BID%@u&V}Z+7esG(*wD+lu geg*3yQ9w!oju;WmZug_se_Eq;)3!|J3!n-%%(!(uEdT%j literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a b/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a new file mode 100644 index 000000000..a79612435 --- /dev/null +++ b/tests-clar/resources/partial-testrepo/.gitted/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a @@ -0,0 +1,3 @@ +x[ +0E*fդ "W0-Ft݁pS[Yx^ +Db CLhut}8X*4ZsYUA X3RM) s6輢Mរ&Jm;}<\@ޏpĀv?jۺL?H \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f b/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f new file mode 100644 index 000000000..f8588696b --- /dev/null +++ b/tests-clar/resources/partial-testrepo/.gitted/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f @@ -0,0 +1,2 @@ +x;j1Dmdǎ|M3`V{ >QvL0I?!4Z=!צ8F!rsQy9]$D&l6A>jFWҵ IKNiZ%S + U~̽>' w [ DGڡQ-M>dO}\8g_ШoYr \ No newline at end of file diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd b/tests-clar/resources/partial-testrepo/.gitted/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd new file mode 100644 index 0000000000000000000000000000000000000000..d0d7e736e536a41bcb885005f8bf258c61cad682 GIT binary patch literal 28 kcmbBQQQ6W+Sv9;eTEK4oHX{LN+y0Ic;3tpET3 literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 b/tests-clar/resources/partial-testrepo/.gitted/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 new file mode 100644 index 0000000000000000000000000000000000000000..18a7f61c29ea8c5c9a48e3b30bead7f058d06293 GIT binary patch literal 26 icmb7F<>w>FfcPQQ3!H%bn$g%SfOmF@NI2De~WFK%%kl}eMcVO zJ7!`41PX}^ejLs3-n~BfTijGk=2g@8)A6h8lA*ejiW2jZGvd=Sb5iw6DoPk!cQ)@c z+it_&ac9n+?K!&}{#0)WhbqlWEe9)EF4}hR{)^=@Is0>j<~#U=IsG@>3joZzJl^$Q BMxFow literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 b/tests-clar/resources/partial-testrepo/.gitted/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 new file mode 100644 index 0000000000000000000000000000000000000000..03770969aa16f40d4192c733408f152fc17b1f19 GIT binary patch literal 82 zcmV-Y0ImOc0V^p=O;s?nWH2-^Ff%bx2y%6F@pWYoZvB+9etT5d(tXFBocGN(t6p-7 o1F9k~wOp^HqJ-g>=Z5m>$`jW{Fc$=TS{`5WI9+ZM01*fsda7_Ea{vGU literal 0 HcmV?d00001 diff --git a/tests-clar/resources/partial-testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 b/tests-clar/resources/partial-testrepo/.gitted/objects/fa/49b077972391ad58037050f2a75f74e3671e92 new file mode 100644 index 0000000000000000000000000000000000000000..112998d425717bb922ce74e8f6f0f831d8dc4510 GIT binary patch literal 24 gcmb Date: Thu, 8 Nov 2012 21:29:17 -0800 Subject: [PATCH 3/6] Avoid copying duplicate commits --- src/transports/local.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/transports/local.c b/src/transports/local.c index 8b3a2d481..436ac435a 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -263,6 +263,7 @@ static int local_download_pack( git_oid oid; git_packbuilder *pack = NULL; git_odb_writepack *writepack = NULL; + git_odb *odb = NULL; if ((error = git_revwalk_new(&walk, t->repo)) < 0) goto cleanup; @@ -295,10 +296,15 @@ static int local_download_pack( } /* Walk the objects, building a packfile */ + 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; + stats->total_objects++; if (!git_object_lookup((git_object**)&commit, t->repo, &oid, GIT_OBJ_COMMIT)) { @@ -313,13 +319,8 @@ static int local_download_pack( } if (progress_cb) progress_cb(stats, progress_payload); - - { - git_odb *odb; - if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || - (error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0) - goto cleanup; - } + if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0) + goto cleanup; /* Write the data to the ODB */ { From 2ff1a0d0f0eb7a214253fea3769c3fe64142446c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 9 Nov 2012 16:59:46 -0800 Subject: [PATCH 4/6] Helpers for local-filesystem remote URLs --- tests-clar/clar_helpers.c | 49 +++++++++++++++++++++++++++++ tests-clar/clar_libgit2.h | 4 +++ tests-clar/clone/nonetwork.c | 54 +++----------------------------- tests-clar/network/fetchlocal.c | 50 +++-------------------------- tests-clar/network/remotelocal.c | 41 +----------------------- 5 files changed, 63 insertions(+), 135 deletions(-) diff --git a/tests-clar/clar_helpers.c b/tests-clar/clar_helpers.c index 250c9223b..178ae68b1 100644 --- a/tests-clar/clar_helpers.c +++ b/tests-clar/clar_helpers.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "posix.h" +#include "path.h" void clar_on_init(void) { @@ -222,3 +223,51 @@ bool cl_is_chmod_supported(void) return _is_supported; } +const char* cl_git_fixture_url(const char *fixturename) +{ + return cl_git_path_url(cl_fixture(fixturename)); +} + +const char* cl_git_path_url(const char *path) +{ + static char url[4096]; + + const char *in_buf; + git_buf path_buf = GIT_BUF_INIT; + git_buf url_buf = GIT_BUF_INIT; + + cl_git_pass(git_path_prettify_dir(&path_buf, path, NULL)); + cl_git_pass(git_buf_puts(&url_buf, "file://")); + +#ifdef _MSC_VER + /* + * A FILE uri matches the following format: file://[host]/path + * where "host" can be empty and "path" is an absolute path to the resource. + * + * In this test, no hostname is used, but we have to ensure the leading triple slashes: + * + * *nix: file:///usr/home/... + * Windows: file:///C:/Users/... + */ + cl_git_pass(git_buf_putc(url_buf, '/')); +#endif + + in_buf = git_buf_cstr(&path_buf); + + /* + * A very hacky Url encoding that only takes care of escaping the spaces + */ + while (*in_buf) { + if (*in_buf == ' ') + cl_git_pass(git_buf_puts(&url_buf, "%20")); + else + cl_git_pass(git_buf_putc(&url_buf, *in_buf)); + + in_buf++; + } + + strncpy(url, git_buf_cstr(&url_buf), 4096); + git_buf_free(&url_buf); + git_buf_free(&path_buf); + return url; +} diff --git a/tests-clar/clar_libgit2.h b/tests-clar/clar_libgit2.h index ce3688ec4..fd20c1259 100644 --- a/tests-clar/clar_libgit2.h +++ b/tests-clar/clar_libgit2.h @@ -57,4 +57,8 @@ int cl_rename(const char *source, const char *dest); git_repository *cl_git_sandbox_init(const char *sandbox); void cl_git_sandbox_cleanup(void); +/* Local-repo url helpers */ +const char* cl_git_fixture_url(const char *fixturename); +const char* cl_git_path_url(const char *path); + #endif diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 36bf63670..59f43362f 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -19,46 +19,6 @@ static void cleanup_repository(void *path) cl_fixture_cleanup((const char *)path); } -// TODO: This is copy/pasted from network/remotelocal.c. -static void build_local_file_url(git_buf *out, const char *fixture) -{ - const char *in_buf; - - git_buf path_buf = GIT_BUF_INIT; - - cl_git_pass(git_path_prettify_dir(&path_buf, fixture, NULL)); - cl_git_pass(git_buf_puts(out, "file://")); - -#ifdef GIT_WIN32 - /* - * A FILE uri matches the following format: file://[host]/path - * where "host" can be empty and "path" is an absolute path to the resource. - * - * In this test, no hostname is used, but we have to ensure the leading triple slashes: - * - * *nix: file:///usr/home/... - * Windows: file:///C:/Users/... - */ - cl_git_pass(git_buf_putc(out, '/')); -#endif - - in_buf = git_buf_cstr(&path_buf); - - /* - * A very hacky Url encoding that only takes care of escaping the spaces - */ - while (*in_buf) { - if (*in_buf == ' ') - cl_git_pass(git_buf_puts(out, "%20")); - else - cl_git_pass(git_buf_putc(out, *in_buf)); - - in_buf++; - } - - git_buf_free(&path_buf); -} - void test_clone_nonetwork__bad_url(void) { /* Clone should clean up the mess if the URL isn't a git repository */ @@ -70,24 +30,18 @@ void test_clone_nonetwork__bad_url(void) void test_clone_nonetwork__local(void) { - git_buf src = GIT_BUF_INIT; - build_local_file_url(&src, cl_fixture("testrepo.git")); + const char *src = cl_git_fixture_url("testrepo.git"); cl_set_cleanup(&cleanup_repository, "./local"); - cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL, NULL, NULL)); - - git_buf_free(&src); + cl_git_pass(git_clone(&g_repo, src, "./local", NULL, NULL, NULL)); } void test_clone_nonetwork__local_bare(void) { - git_buf src = GIT_BUF_INIT; - build_local_file_url(&src, cl_fixture("testrepo.git")); + const char *src = cl_git_fixture_url("testrepo.git"); cl_set_cleanup(&cleanup_repository, "./local.git"); - cl_git_pass(git_clone_bare(&g_repo, git_buf_cstr(&src), "./local.git", NULL, NULL)); - - git_buf_free(&src); + cl_git_pass(git_clone_bare(&g_repo, src, "./local.git", NULL, NULL)); } void test_clone_nonetwork__fail_when_the_target_is_a_file(void) diff --git a/tests-clar/network/fetchlocal.c b/tests-clar/network/fetchlocal.c index 85c2575bf..b5bb1761c 100644 --- a/tests-clar/network/fetchlocal.c +++ b/tests-clar/network/fetchlocal.c @@ -4,45 +4,6 @@ #include "path.h" #include "remote.h" -static void build_local_file_url(git_buf *out, const char *fixture) -{ - const char *in_buf; - - git_buf path_buf = GIT_BUF_INIT; - - cl_git_pass(git_path_prettify_dir(&path_buf, fixture, NULL)); - cl_git_pass(git_buf_puts(out, "file://")); - -#ifdef _MSC_VER - /* - * A FILE uri matches the following format: file://[host]/path - * where "host" can be empty and "path" is an absolute path to the resource. - * - * In this test, no hostname is used, but we have to ensure the leading triple slashes: - * - * *nix: file:///usr/home/... - * Windows: file:///C:/Users/... - */ - cl_git_pass(git_buf_putc(out, '/')); -#endif - - in_buf = git_buf_cstr(&path_buf); - - /* - * A very hacky Url encoding that only takes care of escaping the spaces - */ - while (*in_buf) { - if (*in_buf == ' ') - cl_git_pass(git_buf_puts(out, "%20")); - else - cl_git_pass(git_buf_putc(out, *in_buf)); - - in_buf++; - } - - git_buf_free(&path_buf); -} - static void transfer_cb(const git_transfer_progress *stats, void *payload) { int *callcount = (int*)payload; @@ -52,16 +13,15 @@ static void transfer_cb(const git_transfer_progress *stats, void *payload) void test_network_fetchlocal__complete(void) { - git_buf url = GIT_BUF_INIT; git_repository *repo; git_remote *origin; int callcount = 0; git_strarray refnames = {0}; - build_local_file_url(&url, cl_fixture("testrepo.git")); + const char *url = cl_git_fixture_url("testrepo.git"); cl_git_pass(git_repository_init(&repo, "foo", true)); - cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, git_buf_cstr(&url))); + cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_connect(origin, GIT_DIR_FETCH)); cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); cl_git_pass(git_remote_update_tips(origin)); @@ -78,16 +38,16 @@ void test_network_fetchlocal__complete(void) void test_network_fetchlocal__partial(void) { git_repository *repo = cl_git_sandbox_init("partial-testrepo"); - git_buf url = GIT_BUF_INIT; git_remote *origin; int callcount = 0; git_strarray refnames = {0}; + const char *url; cl_git_pass(git_reference_list(&refnames, repo, GIT_REF_LISTALL)); cl_assert_equal_i(1, refnames.count); - build_local_file_url(&url, cl_fixture("testrepo.git")); - cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, git_buf_cstr(&url))); + url = cl_git_fixture_url("testrepo.git"); + cl_git_pass(git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, url)); cl_git_pass(git_remote_connect(origin, GIT_DIR_FETCH)); cl_git_pass(git_remote_download(origin, transfer_cb, &callcount)); cl_git_pass(git_remote_update_tips(origin)); diff --git a/tests-clar/network/remotelocal.c b/tests-clar/network/remotelocal.c index d4bb1dfef..f7ae83423 100644 --- a/tests-clar/network/remotelocal.c +++ b/tests-clar/network/remotelocal.c @@ -7,45 +7,6 @@ static git_repository *repo; static git_buf file_path_buf = GIT_BUF_INIT; static git_remote *remote; -static void build_local_file_url(git_buf *out, const char *fixture) -{ - const char *in_buf; - - git_buf path_buf = GIT_BUF_INIT; - - cl_git_pass(git_path_prettify_dir(&path_buf, fixture, NULL)); - cl_git_pass(git_buf_puts(out, "file://")); - -#ifdef _MSC_VER - /* - * A FILE uri matches the following format: file://[host]/path - * where "host" can be empty and "path" is an absolute path to the resource. - * - * In this test, no hostname is used, but we have to ensure the leading triple slashes: - * - * *nix: file:///usr/home/... - * Windows: file:///C:/Users/... - */ - cl_git_pass(git_buf_putc(out, '/')); -#endif - - in_buf = git_buf_cstr(&path_buf); - - /* - * A very hacky Url encoding that only takes care of escaping the spaces - */ - while (*in_buf) { - if (*in_buf == ' ') - cl_git_pass(git_buf_puts(out, "%20")); - else - cl_git_pass(git_buf_putc(out, *in_buf)); - - in_buf++; - } - - git_buf_free(&path_buf); -} - void test_network_remotelocal__initialize(void) { cl_git_pass(git_repository_init(&repo, "remotelocal/", 0)); @@ -82,7 +43,7 @@ static int ensure_peeled__cb(git_remote_head *head, void *payload) static void connect_to_local_repository(const char *local_repository) { - build_local_file_url(&file_path_buf, local_repository); + git_buf_sets(&file_path_buf, cl_git_path_url(local_repository)); cl_git_pass(git_remote_new(&remote, repo, NULL, git_buf_cstr(&file_path_buf), NULL)); cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH)); From 0f5520f73aeda936f67024411b9c1b34bb09d6ac Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 12 Nov 2012 07:55:09 -0800 Subject: [PATCH 5/6] Fix error check --- src/transports/local.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/local.c b/src/transports/local.c index 436ac435a..2e02bd970 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -313,7 +313,7 @@ static int local_download_pack( /* Add the commit and its tree */ if ((error = git_packbuilder_insert(pack, &oid, NULL)) < 0 || - (error = git_packbuilder_insert_tree(pack, tree_oid))) + (error = git_packbuilder_insert_tree(pack, tree_oid)) < 0) goto cleanup; } } From 14157652ee83ef67b9376fe5f1c6ff00c539100a Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Mon, 12 Nov 2012 07:57:03 -0800 Subject: [PATCH 6/6] Remove unnecessary progress logic The indexer handles this better than the fetch logic does. --- src/transports/local.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/transports/local.c b/src/transports/local.c index 2e02bd970..cbf6a4ea3 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -289,7 +289,6 @@ static int local_download_pack( error = git_revwalk_hide(walk, &rhead->loid); } else { /* Tag or some other wanted object. Add it on its own */ - stats->total_objects++; error = git_packbuilder_insert(pack, &rhead->oid, rhead->name); } git_object_free(obj); @@ -305,8 +304,6 @@ static int local_download_pack( /* Skip commits we already have */ if (git_odb_exists(odb, &oid)) continue; - stats->total_objects++; - if (!git_object_lookup((git_object**)&commit, t->repo, &oid, GIT_OBJ_COMMIT)) { const git_oid *tree_oid = git_commit_tree_oid(commit); git_commit_free(commit); @@ -318,7 +315,6 @@ static int local_download_pack( } } - if (progress_cb) progress_cb(stats, progress_payload); if ((error = git_odb_write_pack(&writepack, odb, progress_cb, progress_payload)) < 0) goto cleanup;