From 92f91b0e3bc3b7799b2b18ea07b167ad191a47a9 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 12:41:20 -0700 Subject: [PATCH 01/27] Clone: fix indentation --- include/git2/clone.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c4dfc652b..c34a9ae6a 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -36,12 +36,13 @@ GIT_BEGIN_DECL * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * about the error) */ -GIT_EXTERN(int) git_clone(git_repository **out, - const char *origin_url, - const char *workdir_path, - git_indexer_stats *fetch_stats, - git_indexer_stats *checkout_stats, - git_checkout_opts *checkout_opts); +GIT_EXTERN(int) git_clone( + git_repository **out, + const char *origin_url, + const char *workdir_path, + git_indexer_stats *fetch_stats, + git_indexer_stats *checkout_stats, + git_checkout_opts *checkout_opts); /** * Create a bare clone of a remote repository. @@ -52,10 +53,11 @@ GIT_EXTERN(int) git_clone(git_repository **out, * @param fetch_stats pointer to structure that receives fetch progress information (may be NULL) * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information about the error) */ -GIT_EXTERN(int) git_clone_bare(git_repository **out, - const char *origin_url, - const char *dest_path, - git_indexer_stats *fetch_stats); +GIT_EXTERN(int) git_clone_bare( + git_repository **out, + const char *origin_url, + const char *dest_path, + git_indexer_stats *fetch_stats); /** @} */ GIT_END_DECL From 3028be0723f42f31b1973da9f19f2b0468b11754 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 13:10:27 -0700 Subject: [PATCH 02/27] Add git_indexer_stats field to git_remote Also removing all the *stats parameters from external APIs that don't need them anymore. --- include/git2/remote.h | 2 +- src/clone.c | 2 +- src/fetch.c | 6 +++--- src/fetch.h | 2 +- src/remote.c | 6 +++--- src/remote.h | 1 + tests-clar/network/fetch.c | 3 +-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 6471acc6a..ecd597518 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -186,7 +186,7 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * @param filename where to store the temporary filename * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats); +GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes); /** * Check whether the remote is connected diff --git a/src/clone.c b/src/clone.c index 85e69ad97..215185610 100644 --- a/src/clone.c +++ b/src/clone.c @@ -263,7 +263,7 @@ static int setup_remotes_and_fetch(git_repository *repo, if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIR_FETCH)) { - if (!git_remote_download(origin, &bytes, fetch_stats)) { + if (!git_remote_download(origin, &bytes)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ diff --git a/src/fetch.c b/src/fetch.c index dc01f6791..242946356 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -302,7 +302,7 @@ on_error: return error; } -int git_fetch_download_pack(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats) +int git_fetch_download_pack(git_remote *remote, git_off_t *bytes) { git_transport *t = remote->transport; @@ -310,9 +310,9 @@ int git_fetch_download_pack(git_remote *remote, git_off_t *bytes, git_indexer_st return 0; if (t->own_logic) - return t->download_pack(t, remote->repo, bytes, stats); + return t->download_pack(t, remote->repo, bytes, &remote->stats); - return git_fetch__download_pack(t, remote->repo, bytes, stats); + return git_fetch__download_pack(t, remote->repo, bytes, &remote->stats); } diff --git a/src/fetch.h b/src/fetch.h index 87bb43b07..ae030c6eb 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -10,7 +10,7 @@ #include "netops.h" int git_fetch_negotiate(git_remote *remote); -int git_fetch_download_pack(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats); +int git_fetch_download_pack(git_remote *remote, git_off_t *bytes); int git_fetch__download_pack(git_transport *t, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats); int git_fetch_setup_walk(git_revwalk **out, git_repository *repo); diff --git a/src/remote.c b/src/remote.c index c47f2d1ec..82ab22f4a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -433,16 +433,16 @@ int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) return 0; } -int git_remote_download(git_remote *remote, git_off_t *bytes, git_indexer_stats *stats) +int git_remote_download(git_remote *remote, git_off_t *bytes) { int error; - assert(remote && bytes && stats); + assert(remote && bytes); if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote, bytes, stats); + return git_fetch_download_pack(remote, bytes); } int git_remote_update_tips(git_remote *remote) diff --git a/src/remote.h b/src/remote.h index 05073db8c..1ba82608b 100644 --- a/src/remote.h +++ b/src/remote.h @@ -25,6 +25,7 @@ struct git_remote { git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; + git_indexer_stats stats; unsigned int need_pack:1, download_tags:2, /* There are four possible values */ check_cert:1; diff --git a/tests-clar/network/fetch.c b/tests-clar/network/fetch.c index 5ff7b0af8..1e9a2323e 100644 --- a/tests-clar/network/fetch.c +++ b/tests-clar/network/fetch.c @@ -32,7 +32,6 @@ static void do_fetch(const char *url, int flag, int n) { git_remote *remote; git_off_t bytes; - git_indexer_stats stats; git_remote_callbacks callbacks; memset(&callbacks, 0, sizeof(git_remote_callbacks)); @@ -43,7 +42,7 @@ static void do_fetch(const char *url, int flag, int n) git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH)); - cl_git_pass(git_remote_download(remote, &bytes, &stats)); + cl_git_pass(git_remote_download(remote, &bytes)); git_remote_disconnect(remote); cl_git_pass(git_remote_update_tips(remote)); cl_assert_equal_i(counter, n); From d57c47dc07044b4fd3f5e9d57615329692823111 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 13:29:12 -0700 Subject: [PATCH 03/27] Add accessor for git_remote's stats field Also converted the network example to use it. --- examples/network/fetch.c | 17 ++++++++--------- include/git2/remote.h | 5 +++++ src/remote.c | 6 ++++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index fa941b97a..6c342be96 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -9,7 +9,6 @@ struct dl_data { git_remote *remote; git_off_t *bytes; - git_indexer_stats *stats; int ret; int finished; }; @@ -35,7 +34,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, data->bytes, data->stats) < 0) { + if (git_remote_download(data->remote, data->bytes) < 0) { data->ret = -1; goto exit; } @@ -70,14 +69,14 @@ int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; git_off_t bytes = 0; - git_indexer_stats stats; + const git_indexer_stats *stats; pthread_t worker; struct dl_data data; git_remote_callbacks callbacks; argc = argc; // Figure out whether it's a named remote or a URL - printf("Fetching %s\n", argv[1]); + printf("Fetching %s for repo %p\n", argv[1], repo); if (git_remote_load(&remote, repo, argv[1]) < 0) { if (git_remote_new(&remote, repo, NULL, argv[1], NULL) < 0) return -1; @@ -92,10 +91,10 @@ int fetch(git_repository *repo, int argc, char **argv) // Set up the information for the background worker thread data.remote = remote; data.bytes = &bytes; - data.stats = &stats; data.ret = 0; data.finished = 0; - memset(&stats, 0, sizeof(stats)); + + stats = git_remote_stats(remote); pthread_create(&worker, NULL, download, &data); @@ -106,16 +105,16 @@ int fetch(git_repository *repo, int argc, char **argv) do { usleep(10000); - if (stats.total > 0) + if (stats->total > 0) printf("Received %d/%d objects (%d) in %d bytes\r", - stats.received, stats.total, stats.processed, bytes); + stats->received, stats->total, stats->processed, bytes); } while (!data.finished); if (data.ret < 0) goto on_error; pthread_join(worker, NULL); - printf("\rReceived %d/%d objects in %zu bytes\n", stats.processed, stats.total, bytes); + printf("\rReceived %d/%d objects in %zu bytes\n", stats->processed, stats->total, bytes); // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); diff --git a/include/git2/remote.h b/include/git2/remote.h index ecd597518..9327320b4 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -313,6 +313,11 @@ struct git_remote_callbacks { */ GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callbacks); +/** + * Get the statistics structure that is filled in by the fetch operation. + */ +GIT_EXTERN(const git_indexer_stats *) git_remote_stats(git_remote *remote); + enum { GIT_REMOTE_DOWNLOAD_TAGS_UNSET, GIT_REMOTE_DOWNLOAD_TAGS_NONE, diff --git a/src/remote.c b/src/remote.c index 82ab22f4a..4b4044196 100644 --- a/src/remote.c +++ b/src/remote.c @@ -703,6 +703,12 @@ void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callback } } +inline const git_indexer_stats* git_remote_stats(git_remote *remote) +{ + assert(remote); + return &remote->stats; +} + int git_remote_autotag(git_remote *remote) { return remote->download_tags; From 2c8bbb27d91ec35162522079d632608fcaac2a57 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 20:16:21 -0700 Subject: [PATCH 04/27] Convert checkout_index to use progress callback --- include/git2/checkout.h | 11 +++++--- src/checkout.c | 24 +++++++---------- src/clone.c | 9 ++----- src/reset.c | 2 +- tests-clar/checkout/index.c | 51 ++++++++++++++++++++++++------------- 5 files changed, 54 insertions(+), 43 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index b4f9ad081..d0190c260 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -65,9 +65,15 @@ typedef struct git_checkout_opts { const git_oid *blob_oid, int file_mode, void *payload); - void *notify_payload; + /* Optional callback to notify the consumer of checkout progress. */ + void (* progress_cb)( + const char *path, + float progress, + void *payload); + void *progress_payload; + /** When not NULL, array of fnmatch patterns specifying * which paths should be taken into account */ @@ -101,8 +107,7 @@ GIT_EXTERN(int) git_checkout_head( */ GIT_EXTERN(int) git_checkout_index( git_repository *repo, - git_checkout_opts *opts, - git_indexer_stats *stats); + git_checkout_opts *opts); /** * Updates files in the index and working tree to match the content of the diff --git a/src/checkout.c b/src/checkout.c index b56b459d2..222eb26df 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -27,7 +27,7 @@ struct checkout_diff_data git_buf *path; size_t workdir_len; git_checkout_opts *checkout_opts; - git_indexer_stats *stats; + /*git_indexer_stats *stats;*/ git_repository *owner; bool can_symlink; bool found_submodules; @@ -204,6 +204,12 @@ static int checkout_remove_the_old( GIT_DIRREMOVAL_FILES_AND_DIRS); } + if (data->checkout_opts->progress_cb) + data->checkout_opts->progress_cb( + delta->new_file.path, + progress, + data->checkout_opts->progress_payload); + return data->error; } @@ -304,11 +310,9 @@ static void normalize_options(git_checkout_opts *normalized, git_checkout_opts * int git_checkout_index( git_repository *repo, - git_checkout_opts *opts, - git_indexer_stats *stats) + git_checkout_opts *opts) { git_diff_list *diff = NULL; - git_indexer_stats dummy_stats; git_diff_options diff_opts = {0}; git_checkout_opts checkout_opts; @@ -339,19 +343,11 @@ int git_checkout_index( normalize_options(&checkout_opts, opts); - if (!stats) - stats = &dummy_stats; - - stats->processed = 0; - /* total based on 3 passes, but it might be 2 if no submodules */ - stats->total = (unsigned int)git_diff_num_deltas(diff) * 3; - memset(&data, 0, sizeof(data)); data.path = &workdir; data.workdir_len = git_buf_len(&workdir); data.checkout_opts = &checkout_opts; - data.stats = stats; data.owner = repo; if ((error = retrieve_symlink_capabilities(repo, &data.can_symlink)) < 0) @@ -378,8 +374,6 @@ int git_checkout_index( diff, &data, checkout_create_the_new, NULL, NULL); } - stats->processed = stats->total; - cleanup: if (error == GIT_EUSER) error = (data.error != 0) ? data.error : -1; @@ -417,7 +411,7 @@ int git_checkout_tree( if ((error = git_index_write(index)) < 0) goto cleanup; - error = git_checkout_index(repo, opts, stats); + error = git_checkout_index(repo, opts); cleanup: git_index_free(index); diff --git a/src/clone.c b/src/clone.c index 215185610..0039b146d 100644 --- a/src/clone.c +++ b/src/clone.c @@ -248,16 +248,11 @@ cleanup: -static int setup_remotes_and_fetch(git_repository *repo, - const char *origin_url, - git_indexer_stats *fetch_stats) +static int setup_remotes_and_fetch(git_repository *repo, const char *origin_url) { int retcode = GIT_ERROR; git_remote *origin = NULL; git_off_t bytes = 0; - git_indexer_stats dummy_stats; - - if (!fetch_stats) fetch_stats = &dummy_stats; /* Create the "origin" remote */ if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { @@ -327,7 +322,7 @@ static int clone_internal( } if (!(retcode = git_repository_init(&repo, path, is_bare))) { - if ((retcode = setup_remotes_and_fetch(repo, origin_url, fetch_stats)) < 0) { + if ((retcode = setup_remotes_and_fetch(repo, origin_url)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); git_futils_rmdir_r(path, NULL, GIT_DIRREMOVAL_FILES_AND_DIRS); diff --git a/src/reset.c b/src/reset.c index dfa095be4..3fcad7f46 100644 --- a/src/reset.c +++ b/src/reset.c @@ -94,7 +94,7 @@ int git_reset( | GIT_CHECKOUT_OVERWRITE_MODIFIED | GIT_CHECKOUT_REMOVE_UNTRACKED; - if (git_checkout_index(repo, &opts, NULL) < 0) { + if (git_checkout_index(repo, &opts) < 0) { giterr_set(GITERR_INDEX, "%s - Failed to checkout the index.", ERROR_MSG); goto cleanup; } diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index f017a0fe2..944d679f8 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -69,7 +69,7 @@ void test_checkout_index__cannot_checkout_a_bare_repository(void) memset(&g_opts, 0, sizeof(g_opts)); g_repo = cl_git_sandbox_init("testrepo.git"); - cl_git_fail(git_checkout_index(g_repo, NULL, NULL)); + cl_git_fail(git_checkout_index(g_repo, NULL)); } void test_checkout_index__can_create_missing_files(void) @@ -79,7 +79,7 @@ void test_checkout_index__can_create_missing_files(void) cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); g_opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/README", "hey there\n"); test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); @@ -95,7 +95,7 @@ void test_checkout_index__can_remove_untracked_files(void) cl_assert_equal_i(true, git_path_isdir("./testrepo/dir/subdir/subsubdir")); g_opts.checkout_strategy = GIT_CHECKOUT_REMOVE_UNTRACKED; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); cl_assert_equal_i(false, git_path_isdir("./testrepo/dir")); } @@ -111,7 +111,7 @@ void test_checkout_index__honor_the_specified_pathspecs(void) cl_assert_equal_i(false, git_path_isfile("./testrepo/branch_file.txt")); cl_assert_equal_i(false, git_path_isfile("./testrepo/new.txt")); - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); cl_assert_equal_i(false, git_path_isfile("./testrepo/README")); test_file_contents("./testrepo/branch_file.txt", "hi\nbye!\n"); @@ -142,7 +142,7 @@ void test_checkout_index__honor_the_gitattributes_directives(void) cl_git_mkfile("./testrepo/.gitattributes", attributes); set_core_autocrlf_to(false); - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/README", "hey there\n"); test_file_contents("./testrepo/new.txt", "my new file\n"); @@ -157,7 +157,7 @@ void test_checkout_index__honor_coreautocrlf_setting_set_to_true(void) cl_git_pass(p_unlink("./testrepo/.gitattributes")); set_core_autocrlf_to(true); - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/README", expected_readme_text); #endif @@ -172,7 +172,7 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_true(void) { set_repo_symlink_handling_cap_to(true); - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); #ifdef GIT_WIN32 test_file_contents("./testrepo/link_to_new.txt", "new.txt"); @@ -194,7 +194,7 @@ void test_checkout_index__honor_coresymlinks_setting_set_to_false(void) { set_repo_symlink_handling_cap_to(false); - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/link_to_new.txt", "new.txt"); } @@ -204,7 +204,7 @@ void test_checkout_index__donot_overwrite_modified_file_by_default(void) cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); g_opts.checkout_strategy = 0; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/new.txt", "This isn't what's stored!"); } @@ -214,7 +214,7 @@ void test_checkout_index__can_overwrite_modified_file(void) cl_git_mkfile("./testrepo/new.txt", "This isn't what's stored!"); g_opts.checkout_strategy = GIT_CHECKOUT_OVERWRITE_MODIFIED; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/new.txt", "my new file\n"); } @@ -224,14 +224,14 @@ void test_checkout_index__options_disable_filters(void) cl_git_mkfile("./testrepo/.gitattributes", "*.txt text eol=crlf\n"); g_opts.disable_filters = false; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/new.txt", "my new file\r\n"); p_unlink("./testrepo/new.txt"); g_opts.disable_filters = true; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/new.txt", "my new file\n"); } @@ -249,7 +249,7 @@ void test_checkout_index__options_dir_modes(void) reset_index_to_treeish((git_object *)commit); g_opts.dir_mode = 0701; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); cl_git_pass(p_stat("./testrepo/a", &st)); cl_assert_equal_i(st.st_mode & 0777, 0701); @@ -269,7 +269,7 @@ void test_checkout_index__options_override_file_modes(void) g_opts.file_mode = 0700; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); cl_git_pass(p_stat("./testrepo/new.txt", &st)); cl_assert_equal_i(st.st_mode & 0777, 0700); @@ -283,7 +283,7 @@ void test_checkout_index__options_open_flags(void) g_opts.file_open_flags = O_CREAT | O_RDWR | O_APPEND; g_opts.checkout_strategy |= GIT_CHECKOUT_OVERWRITE_MODIFIED; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); test_file_contents("./testrepo/new.txt", "hi\nmy new file\n"); } @@ -328,7 +328,7 @@ void test_checkout_index__can_notify_of_skipped_files(void) g_opts.skipped_notify_cb = notify_cb; g_opts.notify_payload = &data; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); } static int dont_notify_cb( @@ -358,5 +358,22 @@ void test_checkout_index__wont_notify_of_expected_line_ending_changes(void) g_opts.skipped_notify_cb = dont_notify_cb; g_opts.notify_payload = NULL; - cl_git_pass(git_checkout_index(g_repo, &g_opts, NULL)); + cl_git_pass(git_checkout_index(g_repo, &g_opts)); +} + +static void progress(const char *path, float progress, void *payload) +{ + GIT_UNUSED(path); GIT_UNUSED(progress); + int *count = (int*)payload; + (*count)++; +} + +void test_checkout_index__calls_progress_callback(void) +{ + int count = 0; + g_opts.progress_cb = progress; + g_opts.progress_payload = &count; + + cl_git_pass(git_checkout_index(g_repo, &g_opts)); + cl_assert_equal_i(count, 5); } From 806426565f78ff0ee0ac12e125d59658e3ef34be Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 20:23:10 -0700 Subject: [PATCH 05/27] Convert checkout_* to use progress callback --- include/git2/checkout.h | 9 ++------- src/checkout.c | 8 +++----- src/clone.c | 2 +- tests-clar/checkout/tree.c | 24 +++++++++++++++++++++--- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/git2/checkout.h b/include/git2/checkout.h index d0190c260..9032c6b2c 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -86,22 +86,19 @@ typedef struct git_checkout_opts { * * @param repo repository to check out (must be non-bare) * @param opts specifies checkout options (may be NULL) - * @param stats structure through which progress information is reported * @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing * branch, GIT_ERROR otherwise (use giterr_last for information * about the error) */ GIT_EXTERN(int) git_checkout_head( git_repository *repo, - git_checkout_opts *opts, - git_indexer_stats *stats); + git_checkout_opts *opts); /** * Updates files in the working tree to match the content of the index. * * @param repo repository to check out (must be non-bare) * @param opts specifies checkout options (may be NULL) - * @param stats structure through which progress information is reported * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * about the error) */ @@ -117,15 +114,13 @@ GIT_EXTERN(int) git_checkout_index( * @param treeish a commit, tag or tree which content will be used to update * the working directory * @param opts specifies checkout options (may be NULL) - * @param stats structure through which progress information is reported * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information * about the error) */ GIT_EXTERN(int) git_checkout_tree( git_repository *repo, git_object *treeish, - git_checkout_opts *opts, - git_indexer_stats *stats); + git_checkout_opts *opts); /** @} */ GIT_END_DECL diff --git a/src/checkout.c b/src/checkout.c index 222eb26df..ef4ab8d11 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -387,8 +387,7 @@ cleanup: int git_checkout_tree( git_repository *repo, git_object *treeish, - git_checkout_opts *opts, - git_indexer_stats *stats) + git_checkout_opts *opts) { git_index *index = NULL; git_tree *tree = NULL; @@ -421,8 +420,7 @@ cleanup: int git_checkout_head( git_repository *repo, - git_checkout_opts *opts, - git_indexer_stats *stats) + git_checkout_opts *opts) { git_reference *head; int error; @@ -436,7 +434,7 @@ int git_checkout_head( if ((error = git_reference_peel(&tree, head, GIT_OBJ_TREE)) < 0) goto cleanup; - error = git_checkout_tree(repo, tree, opts, stats); + error = git_checkout_tree(repo, tree, opts); cleanup: git_reference_free(head); diff --git a/src/clone.c b/src/clone.c index 0039b146d..b84cd8dc9 100644 --- a/src/clone.c +++ b/src/clone.c @@ -333,7 +333,7 @@ static int clone_internal( } if (!retcode && should_checkout(repo, is_bare, checkout_opts)) - retcode = git_checkout_head(*out, checkout_opts, checkout_stats); + retcode = git_checkout_head(*out, checkout_opts); return retcode; } diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c index 6d573bfd7..c6989598d 100644 --- a/tests-clar/checkout/tree.c +++ b/tests-clar/checkout/tree.c @@ -27,7 +27,7 @@ void test_checkout_tree__cannot_checkout_a_non_treeish(void) /* blob */ cl_git_pass(git_revparse_single(&g_object, g_repo, "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd")); - cl_git_fail(git_checkout_tree(g_repo, g_object, NULL, NULL)); + cl_git_fail(git_checkout_tree(g_repo, g_object, NULL)); } void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void) @@ -41,7 +41,7 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_commit(void) cl_assert_equal_i(false, git_path_isdir("./testrepo/ab/")); - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts, NULL)); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/2.txt")); cl_assert_equal_i(true, git_path_isfile("./testrepo/ab/de/fgh/1.txt")); @@ -58,8 +58,26 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void) cl_assert_equal_i(false, git_path_isdir("./testrepo/de/")); - cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts, NULL)); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); cl_assert_equal_i(true, git_path_isfile("./testrepo/de/2.txt")); cl_assert_equal_i(true, git_path_isfile("./testrepo/de/fgh/1.txt")); } + +static void progress(const char *path, float progress, void *payload) +{ + GIT_UNUSED(path); GIT_UNUSED(progress); + int *count = (int*)payload; + (*count)++; +} + +void test_checkout_tree__calls_progress_callback(void) +{ + int count = 0; + g_opts.progress_cb = progress; + g_opts.progress_payload = &count; + + cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_assert_equal_i(count, 4); +} From 183d8bddeb859a27ee688dac53ea26ccc547d05c Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 16 Oct 2012 20:33:48 -0700 Subject: [PATCH 06/27] Remove checkout_stats from git_clone --- include/git2/clone.h | 1 - src/clone.c | 4 ---- tests-clar/clone/network.c | 25 ++++++++++++++++++------- tests-clar/clone/nonetwork.c | 8 ++++---- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index c34a9ae6a..72294c581 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -41,7 +41,6 @@ GIT_EXTERN(int) git_clone( const char *origin_url, const char *workdir_path, git_indexer_stats *fetch_stats, - git_indexer_stats *checkout_stats, git_checkout_opts *checkout_opts); /** diff --git a/src/clone.c b/src/clone.c index b84cd8dc9..2000de6f3 100644 --- a/src/clone.c +++ b/src/clone.c @@ -307,7 +307,6 @@ static int clone_internal( const char *origin_url, const char *path, git_indexer_stats *fetch_stats, - git_indexer_stats *checkout_stats, git_checkout_opts *checkout_opts, bool is_bare) { @@ -351,7 +350,6 @@ int git_clone_bare(git_repository **out, dest_path, fetch_stats, NULL, - NULL, 1); } @@ -360,7 +358,6 @@ int git_clone(git_repository **out, const char *origin_url, const char *workdir_path, git_indexer_stats *fetch_stats, - git_indexer_stats *checkout_stats, git_checkout_opts *checkout_opts) { assert(out && origin_url && workdir_path); @@ -370,7 +367,6 @@ int git_clone(git_repository **out, origin_url, workdir_path, fetch_stats, - checkout_stats, checkout_opts, 0); } diff --git a/tests-clar/clone/network.c b/tests-clar/clone/network.c index 1ebdfb5d1..72be0747c 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/clone/network.c @@ -29,7 +29,7 @@ void test_clone_network__network_full(void) cl_set_cleanup(&cleanup_repository, "./test2"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL)); cl_assert(!git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); @@ -55,7 +55,7 @@ void test_clone_network__cope_with_already_existing_directory(void) cl_set_cleanup(&cleanup_repository, "./foo"); p_mkdir("./foo", GIT_DIR_MODE); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); git_repository_free(g_repo); g_repo = NULL; } @@ -65,7 +65,7 @@ void test_clone_network__empty_repository(void) cl_set_cleanup(&cleanup_repository, "./empty"); - cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./empty", NULL, NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./empty", NULL, NULL)); cl_assert_equal_i(true, git_repository_is_empty(g_repo)); cl_assert_equal_i(true, git_repository_head_orphan(g_repo)); @@ -83,7 +83,7 @@ void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) cl_set_cleanup(&cleanup_repository, "./no-checkout"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL)); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); @@ -91,18 +91,27 @@ void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) git_buf_free(&path); } +static void progress(const char *path, float progress, void *payload) +{ + GIT_UNUSED(path); GIT_UNUSED(progress); + bool *was_called = (bool*)payload; + (*was_called) = true; +} + void test_clone_network__can_checkout_a_cloned_repo(void) { - git_checkout_opts opts; + git_checkout_opts opts = {0}; git_buf path = GIT_BUF_INIT; git_reference *head; + bool progress_cb_was_called = false; - memset(&opts, 0, sizeof(opts)); opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; + opts.progress_cb = &progress; + opts.progress_payload = &progress_cb_was_called; cl_set_cleanup(&cleanup_repository, "./default-checkout"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout", NULL, NULL, &opts)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout", NULL, &opts)); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); @@ -111,6 +120,8 @@ void test_clone_network__can_checkout_a_cloned_repo(void) cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_target(head)); + cl_assert_equal_i(true, progress_cb_was_called); + git_reference_free(head); git_buf_free(&path); } diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index 81f95b9b3..b8d0ac11a 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -63,7 +63,7 @@ static void build_local_file_url(git_buf *out, const char *fixture) void test_clone_nonetwork__bad_url(void) { /* Clone should clean up the mess if the URL isn't a git repository */ - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", NULL, NULL, NULL)); + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", NULL, NULL)); cl_assert(!git_path_exists("./foo")); cl_git_fail(git_clone_bare(&g_repo, "not_a_repo", "./foo.git", NULL)); cl_assert(!git_path_exists("./foo.git")); @@ -77,7 +77,7 @@ void test_clone_nonetwork__local(void) #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)); + cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL, NULL)); #endif git_buf_free(&src); @@ -102,7 +102,7 @@ void test_clone_nonetwork__fail_when_the_target_is_a_file(void) cl_set_cleanup(&cleanup_repository, "./foo"); cl_git_mkfile("./foo", "Bar!"); - cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); } void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) @@ -111,5 +111,5 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo p_mkdir("./foo", GIT_DIR_MODE); cl_git_mkfile("./foo/bar", "Baz!"); - cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); } From 1f7c74187328e6661fc3cab88b5d6fddf83bdf0d Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 17 Oct 2012 10:15:07 -0700 Subject: [PATCH 07/27] Remove dead code --- src/checkout.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/checkout.c b/src/checkout.c index ef4ab8d11..cbe13aa79 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -27,7 +27,6 @@ struct checkout_diff_data git_buf *path; size_t workdir_len; git_checkout_opts *checkout_opts; - /*git_indexer_stats *stats;*/ git_repository *owner; bool can_symlink; bool found_submodules; From 2b7efe03406411dd8fe25bcc15b0783313097692 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 17 Oct 2012 10:15:51 -0700 Subject: [PATCH 08/27] Example: compile fixes (not yet working) --- examples/network/clone.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index fb571bd3a..99e9ae9a2 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -24,8 +24,7 @@ static void *clone_thread(void *ptr) // Kick off the clone data->ret = git_clone(&repo, data->url, data->path, - &data->fetch_stats, &data->checkout_stats, - &data->opts); + &data->fetch_stats, &data->opts); if (repo) git_repository_free(repo); data->finished = 1; @@ -46,7 +45,7 @@ int do_clone(git_repository *repo, int argc, char **argv) // Data for background thread data.url = argv[1]; data.path = argv[2]; - data.opts.disable_filters = 1; + data.opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; printf("Cloning '%s' to '%s'\n", data.url, data.path); // Create the worker thread From 0ae81fc479bf3cf7ed31b3e3b070de7990102f1d Mon Sep 17 00:00:00 2001 From: nulltoken Date: Wed, 17 Oct 2012 15:30:22 +0200 Subject: [PATCH 09/27] index: remove read_tree() progress indicator git_index_read_tree() was exposing a parameter to provide the user with a progress indicator. Unfortunately, due to the recursive nature of the tree walk, the maximum number of items to process was unknown. Thus, the indicator was only counting processed entries, without providing any information how the number of remaining items. --- include/git2/index.h | 3 +-- src/checkout.c | 2 +- src/index.c | 17 ++++------------- src/reset.c | 2 +- tests-clar/checkout/index.c | 2 +- tests-clar/index/read_tree.c | 2 +- tests-clar/status/worktree.c | 2 +- 7 files changed, 10 insertions(+), 20 deletions(-) diff --git a/include/git2/index.h b/include/git2/index.h index 062932e1a..d8282e80f 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -343,10 +343,9 @@ GIT_EXTERN(int) git_index_entry_stage(const git_index_entry *entry); * * @param index an existing index object * @param tree tree to read - * @param stats structure that receives the total node count (may be NULL) * @return 0 or an error code */ -GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree, git_indexer_stats *stats); +GIT_EXTERN(int) git_index_read_tree(git_index *index, git_tree *tree); /** @} */ GIT_END_DECL diff --git a/src/checkout.c b/src/checkout.c index cbe13aa79..155ac5ac1 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -403,7 +403,7 @@ int git_checkout_tree( if ((error = git_repository_index(&index, repo)) < 0) goto cleanup; - if ((error = git_index_read_tree(index, tree, NULL)) < 0) + if ((error = git_index_read_tree(index, tree)) < 0) goto cleanup; if ((error = git_index_write(index)) < 0) diff --git a/src/index.c b/src/index.c index f9f3b14cc..362c2c690 100644 --- a/src/index.c +++ b/src/index.c @@ -1039,12 +1039,10 @@ typedef struct read_tree_data { static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *data) { - read_tree_data *rtd = data; + git_index *index = (git_index *)data; git_index_entry *entry = NULL; git_buf path = GIT_BUF_INIT; - rtd->stats->total++; - if (git_tree_entry__is_tree(tentry)) return 0; @@ -1059,7 +1057,7 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da entry->path = git_buf_detach(&path); git_buf_free(&path); - if (index_insert(rtd->index, entry, 0) < 0) { + if (index_insert(index, entry, 0) < 0) { index_entry_free(entry); return -1; } @@ -1067,16 +1065,9 @@ static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *da return 0; } -int git_index_read_tree(git_index *index, git_tree *tree, git_indexer_stats *stats) +int git_index_read_tree(git_index *index, git_tree *tree) { - git_indexer_stats dummy_stats; - read_tree_data rtd = {index, NULL}; - - if (!stats) stats = &dummy_stats; - stats->total = 0; - rtd.stats = stats; - git_index_clear(index); - return git_tree_walk(tree, read_tree_cb, GIT_TREEWALK_POST, &rtd); + return git_tree_walk(tree, read_tree_cb, GIT_TREEWALK_POST, index); } diff --git a/src/reset.c b/src/reset.c index 3fcad7f46..642318d90 100644 --- a/src/reset.c +++ b/src/reset.c @@ -73,7 +73,7 @@ int git_reset( goto cleanup; } - if (git_index_read_tree(index, tree, NULL) < 0) { + if (git_index_read_tree(index, tree) < 0) { giterr_set(GITERR_INDEX, "%s - Failed to update the index.", ERROR_MSG); goto cleanup; } diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index 944d679f8..a21af5f60 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -14,7 +14,7 @@ static void reset_index_to_treeish(git_object *treeish) cl_git_pass(git_object_peel(&tree, treeish, GIT_OBJ_TREE)); cl_git_pass(git_repository_index(&index, g_repo)); - cl_git_pass(git_index_read_tree(index, (git_tree *)tree, NULL)); + cl_git_pass(git_index_read_tree(index, (git_tree *)tree)); cl_git_pass(git_index_write(index)); git_object_free(tree); diff --git a/tests-clar/index/read_tree.c b/tests-clar/index/read_tree.c index 0479332dc..c657d4f71 100644 --- a/tests-clar/index/read_tree.c +++ b/tests-clar/index/read_tree.c @@ -33,7 +33,7 @@ void test_index_read_tree__read_write_involution(void) /* read-tree */ git_tree_lookup(&tree, repo, &expected); - cl_git_pass(git_index_read_tree(index, tree, NULL)); + cl_git_pass(git_index_read_tree(index, tree)); git_tree_free(tree); cl_git_pass(git_tree_create_fromindex(&tree_oid, index)); diff --git a/tests-clar/status/worktree.c b/tests-clar/status/worktree.c index 908d34510..4ff315f84 100644 --- a/tests-clar/status/worktree.c +++ b/tests-clar/status/worktree.c @@ -486,7 +486,7 @@ static void fill_index_wth_head_entries(git_repository *repo, git_index *index) cl_git_pass(git_commit_lookup(&commit, repo, &oid)); cl_git_pass(git_commit_tree(&tree, commit)); - cl_git_pass(git_index_read_tree(index, tree, NULL)); + cl_git_pass(git_index_read_tree(index, tree)); cl_git_pass(git_index_write(index)); git_tree_free(tree); From 216863c48fd05b08e9b0083d61dcb163a2add62a Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 17 Oct 2012 14:02:24 -0700 Subject: [PATCH 10/27] Fetch/indexer: progress callbacks --- include/git2/indexer.h | 13 ++++++++++++- include/git2/remote.h | 8 +++++++- src/clone.c | 2 +- src/fetch.c | 15 +++++++++++---- src/fetch.h | 16 ++++++++++++++-- src/indexer.c | 19 ++++++++++++++++++- src/remote.c | 8 ++++++-- tests-clar/network/fetch.c | 11 ++++++++++- 8 files changed, 79 insertions(+), 13 deletions(-) diff --git a/include/git2/indexer.h b/include/git2/indexer.h index 87f48fe27..0d3c9dd51 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -23,6 +23,11 @@ typedef struct git_indexer_stats { } git_indexer_stats; +/** + * Type for progress callbacks during indexing + */ +typedef void (*git_indexer_progress_callback)(const git_indexer_stats *stats, void *payload); + typedef struct git_indexer git_indexer; typedef struct git_indexer_stream git_indexer_stream; @@ -31,8 +36,14 @@ typedef struct git_indexer_stream git_indexer_stream; * * @param out where to store the indexer instance * @param path to the directory where the packfile should be stored + * @param progress_cb function to call with progress information + * @param progress_payload payload for the progress callback */ -GIT_EXTERN(int) git_indexer_stream_new(git_indexer_stream **out, const char *path); +GIT_EXTERN(int) git_indexer_stream_new( + git_indexer_stream **out, + const char *path, + git_indexer_progress_callback progress_cb, + void *progress_callback_payload); /** * Add data to the indexer diff --git a/include/git2/remote.h b/include/git2/remote.h index 9327320b4..ca75126f9 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -184,9 +184,15 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * * @param remote the remote to download from * @param filename where to store the temporary filename + * @param progress_cb function to call with progress information + * @param progress_payload payload for the progress callback * @return 0 or an error code */ -GIT_EXTERN(int) git_remote_download(git_remote *remote, git_off_t *bytes); +GIT_EXTERN(int) git_remote_download( + git_remote *remote, + git_off_t *bytes, + git_indexer_progress_callback progress_cb, + void *progress_payload); /** * Check whether the remote is connected diff --git a/src/clone.c b/src/clone.c index 2000de6f3..0acf588b4 100644 --- a/src/clone.c +++ b/src/clone.c @@ -258,7 +258,7 @@ static int setup_remotes_and_fetch(git_repository *repo, const char *origin_url) if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIR_FETCH)) { - if (!git_remote_download(origin, &bytes)) { + if (!git_remote_download(origin, &bytes, NULL, NULL)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ diff --git a/src/fetch.c b/src/fetch.c index 242946356..583c79a34 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -302,7 +302,11 @@ on_error: return error; } -int git_fetch_download_pack(git_remote *remote, git_off_t *bytes) +int git_fetch_download_pack( + git_remote *remote, + git_off_t *bytes, + git_indexer_progress_callback progress_cb, + void *progress_payload) { git_transport *t = remote->transport; @@ -312,7 +316,8 @@ int git_fetch_download_pack(git_remote *remote, git_off_t *bytes) if (t->own_logic) return t->download_pack(t, remote->repo, bytes, &remote->stats); - return git_fetch__download_pack(t, remote->repo, bytes, &remote->stats); + return git_fetch__download_pack(t, remote->repo, bytes, &remote->stats, + progress_cb, progress_payload); } @@ -348,7 +353,9 @@ int git_fetch__download_pack( git_transport *t, git_repository *repo, git_off_t *bytes, - git_indexer_stats *stats) + git_indexer_stats *stats, + git_indexer_progress_callback progress_cb, + void *progress_payload) { git_buf path = GIT_BUF_INIT; gitno_buffer *buf = &t->buffer; @@ -358,7 +365,7 @@ int git_fetch__download_pack( if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0) return -1; - if (git_indexer_stream_new(&idx, git_buf_cstr(&path)) < 0) + if (git_indexer_stream_new(&idx, git_buf_cstr(&path), progress_cb, progress_payload) < 0) goto on_error; git_buf_free(&path); diff --git a/src/fetch.h b/src/fetch.h index ae030c6eb..c10973422 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -10,9 +10,21 @@ #include "netops.h" int git_fetch_negotiate(git_remote *remote); -int git_fetch_download_pack(git_remote *remote, git_off_t *bytes); -int git_fetch__download_pack(git_transport *t, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats); +int git_fetch_download_pack( + git_remote *remote, + git_off_t *bytes, + git_indexer_progress_callback progress_cb, + void *progress_payload); + +int git_fetch__download_pack( + git_transport *t, + git_repository *repo, + git_off_t *bytes, + git_indexer_stats *stats, + git_indexer_progress_callback progress_cb, + void *progress_payload); + int git_fetch_setup_walk(git_revwalk **out, git_repository *repo); #endif diff --git a/src/indexer.c b/src/indexer.c index 7d4e18d7a..2d032fbd3 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -49,6 +49,8 @@ struct git_indexer_stream { git_vector deltas; unsigned int fanout[256]; git_oid hash; + git_indexer_progress_callback progress_cb; + void *progress_payload; }; struct delta_info { @@ -138,7 +140,11 @@ static int cache_cmp(const void *a, const void *b) return git_oid_cmp(&ea->sha1, &eb->sha1); } -int git_indexer_stream_new(git_indexer_stream **out, const char *prefix) +int git_indexer_stream_new( + git_indexer_stream **out, + const char *prefix, + git_indexer_progress_callback progress_cb, + void *progress_payload) { git_indexer_stream *idx; git_buf path = GIT_BUF_INIT; @@ -147,6 +153,8 @@ int git_indexer_stream_new(git_indexer_stream **out, const char *prefix) idx = git__calloc(1, sizeof(git_indexer_stream)); GITERR_CHECK_ALLOC(idx); + idx->progress_cb = progress_cb; + idx->progress_payload = progress_payload; error = git_buf_joinpath(&path, prefix, suff); if (error < 0) @@ -273,6 +281,12 @@ on_error: return -1; } +static void do_progress_callback(git_indexer_stream *idx, git_indexer_stats *stats) +{ + if (!idx->progress_cb) return; + idx->progress_cb(stats, idx->progress_payload); +} + int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_indexer_stats *stats) { int error; @@ -326,6 +340,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz memset(stats, 0, sizeof(git_indexer_stats)); stats->total = (unsigned int)idx->nr_objects; + do_progress_callback(idx, stats); } /* Now that we have data in the pack, let's try to parse it */ @@ -362,6 +377,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz return error; stats->received++; + do_progress_callback(idx, stats); continue; } @@ -381,6 +397,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz stats->processed = (unsigned int)++processed; stats->received++; + do_progress_callback(idx, stats); } return 0; diff --git a/src/remote.c b/src/remote.c index 4b4044196..662b8cc9b 100644 --- a/src/remote.c +++ b/src/remote.c @@ -433,7 +433,11 @@ int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) return 0; } -int git_remote_download(git_remote *remote, git_off_t *bytes) +int git_remote_download( + git_remote *remote, + git_off_t *bytes, + git_indexer_progress_callback progress_cb, + void *progress_payload) { int error; @@ -442,7 +446,7 @@ int git_remote_download(git_remote *remote, git_off_t *bytes) if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote, bytes); + return git_fetch_download_pack(remote, bytes, progress_cb, progress_payload); } int git_remote_update_tips(git_remote *remote) diff --git a/tests-clar/network/fetch.c b/tests-clar/network/fetch.c index 1e9a2323e..134e8fe2e 100644 --- a/tests-clar/network/fetch.c +++ b/tests-clar/network/fetch.c @@ -28,11 +28,19 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, return 0; } +static void progress(const git_indexer_stats *stats, void *payload) +{ + GIT_UNUSED(stats); + bool *was_called = (bool*)payload; + *was_called = true; +} + static void do_fetch(const char *url, int flag, int n) { git_remote *remote; git_off_t bytes; git_remote_callbacks callbacks; + bool progress_was_called = false; memset(&callbacks, 0, sizeof(git_remote_callbacks)); callbacks.update_tips = update_tips; @@ -42,10 +50,11 @@ static void do_fetch(const char *url, int flag, int n) git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH)); - cl_git_pass(git_remote_download(remote, &bytes)); + cl_git_pass(git_remote_download(remote, &bytes, progress, &progress_was_called)); git_remote_disconnect(remote); cl_git_pass(git_remote_update_tips(remote)); cl_assert_equal_i(counter, n); + cl_assert_equal_i(progress_was_called, true); git_remote_free(remote); } From 7635a1188a963f2fd7136a957ab9ab65baeff866 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 17 Oct 2012 14:06:32 -0700 Subject: [PATCH 11/27] Fix example compilation --- examples/network/fetch.c | 2 +- examples/network/index-pack.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 6c342be96..f7b2fd9de 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -34,7 +34,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, data->bytes) < 0) { + if (git_remote_download(data->remote, data->bytes, NULL, NULL) < 0) { data->ret = -1; goto exit; } diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c index 85aac4aff..69338b37f 100644 --- a/examples/network/index-pack.c +++ b/examples/network/index-pack.c @@ -33,7 +33,7 @@ int index_pack(git_repository *repo, int argc, char **argv) return EXIT_FAILURE; } - if (git_indexer_stream_new(&idx, ".") < 0) { + if (git_indexer_stream_new(&idx, ".", NULL, NULL) < 0) { puts("bad idx"); return -1; } From 9c3a98f1b0de30ff33969e2af5b90ed448c42389 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 09:57:19 -0700 Subject: [PATCH 12/27] Fix clone.c's indentation --- src/clone.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/clone.c b/src/clone.c index 0acf588b4..5f4858d84 100644 --- a/src/clone.c +++ b/src/clone.c @@ -337,10 +337,11 @@ static int clone_internal( return retcode; } -int git_clone_bare(git_repository **out, - const char *origin_url, - const char *dest_path, - git_indexer_stats *fetch_stats) +int git_clone_bare( + git_repository **out, + const char *origin_url, + const char *dest_path, + git_indexer_stats *fetch_stats) { assert(out && origin_url && dest_path); @@ -354,11 +355,12 @@ int git_clone_bare(git_repository **out, } -int git_clone(git_repository **out, - const char *origin_url, - const char *workdir_path, - git_indexer_stats *fetch_stats, - git_checkout_opts *checkout_opts) +int git_clone( + git_repository **out, + const char *origin_url, + const char *workdir_path, + git_indexer_stats *fetch_stats, + git_checkout_opts *checkout_opts) { assert(out && origin_url && workdir_path); From aa1e86741dcd314212f738b408e507de1771fedd Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 12:57:47 -0700 Subject: [PATCH 13/27] Clone: in-line callbacks for progress Also implemented in the git2 example. --- examples/network/clone.c | 92 ++++++++++++++++++++---------------- include/git2/clone.h | 6 ++- src/clone.c | 29 +++++++----- tests-clar/clone/network.c | 32 ++++++++----- tests-clar/clone/nonetwork.c | 12 ++--- 5 files changed, 99 insertions(+), 72 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 99e9ae9a2..39b3241d9 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -7,61 +7,69 @@ #include #include -struct dl_data { - git_indexer_stats fetch_stats; - git_indexer_stats checkout_stats; - git_checkout_opts opts; - int ret; - int finished; - const char *url; +typedef struct progress_data { + git_indexer_stats fetch_progress; + float checkout_progress; const char *path; -}; +} progress_data; -static void *clone_thread(void *ptr) +static void print_progress(const progress_data *pd) { - struct dl_data *data = (struct dl_data *)ptr; - git_repository *repo = NULL; + /* + int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; + int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; + int checkout_percent = (int)(100.f * pd->checkout_progress); + printf("net %3d%% / idx %3d%% / chk %3d%% %20s\r", + network_percent, index_percent, checkout_percent, pd->path); + */ + printf("net %5d /%5d – idx %5d /%5d – chk %.04f %20s\r", + pd->fetch_progress.received, pd->fetch_progress.total, + pd->fetch_progress.processed, pd->fetch_progress.total, + pd->checkout_progress, pd->path); +} - // Kick off the clone - data->ret = git_clone(&repo, data->url, data->path, - &data->fetch_stats, &data->opts); - if (repo) git_repository_free(repo); - data->finished = 1; - - pthread_exit(&data->ret); +static void fetch_progress(const git_indexer_stats *stats, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->fetch_progress = *stats; + print_progress(pd); +} +static void checkout_progress(const char *path, float progress, void *payload) +{ + progress_data *pd = (progress_data*)payload; + pd->checkout_progress = progress; + pd->path = path; + print_progress(pd); } int do_clone(git_repository *repo, int argc, char **argv) { - struct dl_data data = {0}; - pthread_t worker; + progress_data pd = {0}; + git_repository *cloned_repo = NULL; + git_checkout_opts checkout_opts = {0}; + const char *url = argv[1]; + const char *path = argv[2]; + int error; // Validate args if (argc < 3) { - printf("USAGE: %s \n", argv[0]); + printf ("USAGE: %s \n", argv[0]); return -1; } - // Data for background thread - data.url = argv[1]; - data.path = argv[2]; - data.opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; - printf("Cloning '%s' to '%s'\n", data.url, data.path); + // Set up options + checkout_opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; + checkout_opts.progress_cb = checkout_progress; + checkout_opts.progress_payload = &pd; - // Create the worker thread - pthread_create(&worker, NULL, clone_thread, &data); - - // Watch for progress information - do { - usleep(10000); - printf("Fetch %d/%d – Checkout %d/%d\n", - data.fetch_stats.processed, data.fetch_stats.total, - data.checkout_stats.processed, data.checkout_stats.total); - } while (!data.finished); - printf("Fetch %d/%d – Checkout %d/%d\n", - data.fetch_stats.processed, data.fetch_stats.total, - data.checkout_stats.processed, data.checkout_stats.total); - - return data.ret; + // Do the clone + error = git_clone(&cloned_repo, url, path, &fetch_progress, &pd, &checkout_opts); + printf("\n"); + if (error != 0) { + const git_error *err = giterr_last(); + if (err) printf("ERROR %d: %s\n", err->klass, err->message); + else printf("ERROR %d: no detailed info\n", error); + } + else if (cloned_repo) git_repository_free(cloned_repo); + return error; } - diff --git a/include/git2/clone.h b/include/git2/clone.h index 72294c581..dc49074dc 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -40,7 +40,8 @@ GIT_EXTERN(int) git_clone( git_repository **out, const char *origin_url, const char *workdir_path, - git_indexer_stats *fetch_stats, + git_indexer_progress_callback fetch_progress_cb, + void *fetch_progress_payload, git_checkout_opts *checkout_opts); /** @@ -56,7 +57,8 @@ GIT_EXTERN(int) git_clone_bare( git_repository **out, const char *origin_url, const char *dest_path, - git_indexer_stats *fetch_stats); + git_indexer_progress_callback fetch_progress_cb, + void *fetch_progress_payload); /** @} */ GIT_END_DECL diff --git a/src/clone.c b/src/clone.c index 5f4858d84..61e5e8567 100644 --- a/src/clone.c +++ b/src/clone.c @@ -248,7 +248,11 @@ cleanup: -static int setup_remotes_and_fetch(git_repository *repo, const char *origin_url) +static int setup_remotes_and_fetch( + git_repository *repo, + const char *origin_url, + git_indexer_progress_callback progress_cb, + void *progress_payload) { int retcode = GIT_ERROR; git_remote *origin = NULL; @@ -258,7 +262,7 @@ static int setup_remotes_and_fetch(git_repository *repo, const char *origin_url) if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIR_FETCH)) { - if (!git_remote_download(origin, &bytes, NULL, NULL)) { + if (!git_remote_download(origin, &bytes, progress_cb, progress_payload)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ @@ -306,22 +310,21 @@ static int clone_internal( git_repository **out, const char *origin_url, const char *path, - git_indexer_stats *fetch_stats, + git_indexer_progress_callback fetch_progress_cb, + void *fetch_progress_payload, git_checkout_opts *checkout_opts, bool is_bare) { int retcode = GIT_ERROR; git_repository *repo = NULL; - git_indexer_stats dummy_stats; - - if (!fetch_stats) fetch_stats = &dummy_stats; if (!path_is_okay(path)) { return GIT_ERROR; } if (!(retcode = git_repository_init(&repo, path, is_bare))) { - if ((retcode = setup_remotes_and_fetch(repo, origin_url)) < 0) { + if ((retcode = setup_remotes_and_fetch(repo, origin_url, + fetch_progress_cb, fetch_progress_payload)) < 0) { /* Failed to fetch; clean up */ git_repository_free(repo); git_futils_rmdir_r(path, NULL, GIT_DIRREMOVAL_FILES_AND_DIRS); @@ -341,7 +344,8 @@ int git_clone_bare( git_repository **out, const char *origin_url, const char *dest_path, - git_indexer_stats *fetch_stats) + git_indexer_progress_callback fetch_progress_cb, + void *fetch_progress_payload) { assert(out && origin_url && dest_path); @@ -349,7 +353,8 @@ int git_clone_bare( out, origin_url, dest_path, - fetch_stats, + fetch_progress_cb, + fetch_progress_payload, NULL, 1); } @@ -359,7 +364,8 @@ int git_clone( git_repository **out, const char *origin_url, const char *workdir_path, - git_indexer_stats *fetch_stats, + git_indexer_progress_callback fetch_progress_cb, + void *fetch_progress_payload, git_checkout_opts *checkout_opts) { assert(out && origin_url && workdir_path); @@ -368,7 +374,8 @@ int git_clone( out, origin_url, workdir_path, - fetch_stats, + fetch_progress_cb, + fetch_progress_payload, checkout_opts, 0); } diff --git a/tests-clar/clone/network.c b/tests-clar/clone/network.c index 72be0747c..62d4110c6 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/clone/network.c @@ -29,7 +29,7 @@ void test_clone_network__network_full(void) cl_set_cleanup(&cleanup_repository, "./test2"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./test2", NULL, NULL, NULL)); cl_assert(!git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); @@ -43,7 +43,7 @@ void test_clone_network__network_bare(void) cl_set_cleanup(&cleanup_repository, "./test"); - cl_git_pass(git_clone_bare(&g_repo, LIVE_REPO_URL, "./test", NULL)); + cl_git_pass(git_clone_bare(&g_repo, LIVE_REPO_URL, "./test", NULL, NULL)); cl_assert(git_repository_is_bare(g_repo)); cl_git_pass(git_remote_load(&origin, g_repo, "origin")); @@ -55,7 +55,7 @@ void test_clone_network__cope_with_already_existing_directory(void) cl_set_cleanup(&cleanup_repository, "./foo"); p_mkdir("./foo", GIT_DIR_MODE); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); git_repository_free(g_repo); g_repo = NULL; } @@ -65,7 +65,7 @@ void test_clone_network__empty_repository(void) cl_set_cleanup(&cleanup_repository, "./empty"); - cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./empty", NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_EMPTYREPO_URL, "./empty", NULL, NULL, NULL)); cl_assert_equal_i(true, git_repository_is_empty(g_repo)); cl_assert_equal_i(true, git_repository_head_orphan(g_repo)); @@ -83,7 +83,7 @@ void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) cl_set_cleanup(&cleanup_repository, "./no-checkout"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./no-checkout", NULL, NULL, NULL)); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); cl_assert_equal_i(false, git_path_isfile(git_buf_cstr(&path))); @@ -91,27 +91,36 @@ void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) git_buf_free(&path); } -static void progress(const char *path, float progress, void *payload) +static void checkout_progress(const char *path, float progress, void *payload) { GIT_UNUSED(path); GIT_UNUSED(progress); bool *was_called = (bool*)payload; (*was_called) = true; } +static void fetch_progress(const git_indexer_stats *stats, void *payload) +{ + GIT_UNUSED(stats); + bool *was_called = (bool*)payload; + (*was_called) = true; +} + void test_clone_network__can_checkout_a_cloned_repo(void) { git_checkout_opts opts = {0}; git_buf path = GIT_BUF_INIT; git_reference *head; - bool progress_cb_was_called = false; + bool checkout_progress_cb_was_called = false, + fetch_progress_cb_was_called = false; opts.checkout_strategy = GIT_CHECKOUT_CREATE_MISSING; - opts.progress_cb = &progress; - opts.progress_payload = &progress_cb_was_called; + opts.progress_cb = &checkout_progress; + opts.progress_payload = &checkout_progress_cb_was_called; cl_set_cleanup(&cleanup_repository, "./default-checkout"); - cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout", NULL, &opts)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./default-checkout", + &fetch_progress, &fetch_progress_cb_was_called, &opts)); cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); @@ -120,7 +129,8 @@ void test_clone_network__can_checkout_a_cloned_repo(void) cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_target(head)); - cl_assert_equal_i(true, progress_cb_was_called); + cl_assert_equal_i(true, checkout_progress_cb_was_called); + cl_assert_equal_i(true, fetch_progress_cb_was_called); git_reference_free(head); git_buf_free(&path); diff --git a/tests-clar/clone/nonetwork.c b/tests-clar/clone/nonetwork.c index b8d0ac11a..3984f3fe7 100644 --- a/tests-clar/clone/nonetwork.c +++ b/tests-clar/clone/nonetwork.c @@ -63,9 +63,9 @@ static void build_local_file_url(git_buf *out, const char *fixture) void test_clone_nonetwork__bad_url(void) { /* Clone should clean up the mess if the URL isn't a git repository */ - cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", NULL, NULL)); + cl_git_fail(git_clone(&g_repo, "not_a_repo", "./foo", NULL, NULL, NULL)); cl_assert(!git_path_exists("./foo")); - cl_git_fail(git_clone_bare(&g_repo, "not_a_repo", "./foo.git", NULL)); + cl_git_fail(git_clone_bare(&g_repo, "not_a_repo", "./foo.git", NULL, NULL)); cl_assert(!git_path_exists("./foo.git")); } @@ -77,7 +77,7 @@ void test_clone_nonetwork__local(void) #if DO_LOCAL_TEST cl_set_cleanup(&cleanup_repository, "./local"); - cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL, NULL)); + cl_git_pass(git_clone(&g_repo, git_buf_cstr(&src), "./local", NULL, NULL, NULL)); #endif git_buf_free(&src); @@ -91,7 +91,7 @@ void test_clone_nonetwork__local_bare(void) #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)); + cl_git_pass(git_clone_bare(&g_repo, git_buf_cstr(&src), "./local.git", NULL, NULL)); #endif git_buf_free(&src); @@ -102,7 +102,7 @@ void test_clone_nonetwork__fail_when_the_target_is_a_file(void) cl_set_cleanup(&cleanup_repository, "./foo"); cl_git_mkfile("./foo", "Bar!"); - cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); } void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(void) @@ -111,5 +111,5 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo p_mkdir("./foo", GIT_DIR_MODE); cl_git_mkfile("./foo/bar", "Baz!"); - cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL)); + cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", NULL, NULL, NULL)); } From 30a46ab1a9464fe92860b29306efb99e50c0d226 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 14:04:14 -0700 Subject: [PATCH 14/27] Adjust for rebase --- src/checkout.c | 2 -- tests-clar/checkout/typechange.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index 155ac5ac1..d9b3246b8 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -190,7 +190,6 @@ static int checkout_remove_the_old( git_checkout_opts *opts = data->checkout_opts; GIT_UNUSED(progress); - data->stats->processed++; if ((delta->status == GIT_DELTA_UNTRACKED && (opts->checkout_strategy & GIT_CHECKOUT_REMOVE_UNTRACKED) != 0) || @@ -221,7 +220,6 @@ static int checkout_create_the_new( bool do_checkout = false, do_notify = false; GIT_UNUSED(progress); - data->stats->processed++; if (delta->status == GIT_DELTA_MODIFIED || delta->status == GIT_DELTA_TYPECHANGE) diff --git a/tests-clar/checkout/typechange.c b/tests-clar/checkout/typechange.c index f013617d5..e86af52ee 100644 --- a/tests-clar/checkout/typechange.c +++ b/tests-clar/checkout/typechange.c @@ -49,7 +49,7 @@ void test_checkout_typechange__checkout_typechanges(void) cl_git_pass(git_revparse_single(&obj, g_repo, g_typechange_oids[i])); /* fprintf(stderr, "checking out '%s'\n", g_typechange_oids[i]); */ - cl_git_pass(git_checkout_tree(g_repo, obj, &opts, NULL)); + cl_git_pass(git_checkout_tree(g_repo, obj, &opts)); git_object_free(obj); From 45b60d7b8db79da18cecfd667dc7051f31dc8fe6 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 15:17:12 -0700 Subject: [PATCH 15/27] Correct progress reporting from checkout --- examples/network/clone.c | 6 +++--- src/checkout.c | 43 ++++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 39b3241d9..fd30bca5b 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -15,17 +15,17 @@ typedef struct progress_data { static void print_progress(const progress_data *pd) { - /* int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; int checkout_percent = (int)(100.f * pd->checkout_progress); - printf("net %3d%% / idx %3d%% / chk %3d%% %20s\r", + printf("net %3d%% / idx %3d%% / chk %3d%% %50s\r", network_percent, index_percent, checkout_percent, pd->path); - */ + /* printf("net %5d /%5d – idx %5d /%5d – chk %.04f %20s\r", pd->fetch_progress.received, pd->fetch_progress.total, pd->fetch_progress.processed, pd->fetch_progress.total, pd->checkout_progress, pd->path); + */ } static void fetch_progress(const git_indexer_stats *stats, void *payload) diff --git a/src/checkout.c b/src/checkout.c index d9b3246b8..a20a6f9d6 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -31,6 +31,7 @@ struct checkout_diff_data bool can_symlink; bool found_submodules; bool create_submodules; + int num_stages; int error; }; @@ -157,6 +158,23 @@ static int checkout_submodule( return 0; } +static void report_progress( + int stage, + float stage_progress, + struct checkout_diff_data *data, + const char *path) +{ + float per_stage_progress = 1.f/data->num_stages; + float overall_progress = (stage-1)*per_stage_progress + + stage_progress*per_stage_progress; + + if (data->checkout_opts->progress_cb) + data->checkout_opts->progress_cb( + path, + overall_progress, + data->checkout_opts->progress_payload); +} + static int checkout_blob( struct checkout_diff_data *data, const git_diff_file *file) @@ -202,11 +220,7 @@ static int checkout_remove_the_old( GIT_DIRREMOVAL_FILES_AND_DIRS); } - if (data->checkout_opts->progress_cb) - data->checkout_opts->progress_cb( - delta->new_file.path, - progress, - data->checkout_opts->progress_payload); + report_progress(1, progress, data, delta->new_file.path); return data->error; } @@ -246,14 +260,22 @@ static int checkout_create_the_new( if (do_checkout) { bool is_submodule = S_ISGITLINK(delta->old_file.mode); - if (is_submodule) + if (is_submodule) { data->found_submodules = true; + data->num_stages = 3; + } - if (!is_submodule && !data->create_submodules) + if (!is_submodule && !data->create_submodules) { error = checkout_blob(data, &delta->old_file); + report_progress(2, progress, data, delta->old_file.path); - else if (is_submodule && data->create_submodules) + } + + else if (is_submodule && data->create_submodules) { error = checkout_submodule(data, &delta->old_file); + report_progress(3, progress, data, delta->old_file.path); + } + } if (error) @@ -346,6 +368,7 @@ int git_checkout_index( data.workdir_len = git_buf_len(&workdir); data.checkout_opts = &checkout_opts; data.owner = repo; + data.num_stages = 2; if ((error = retrieve_symlink_capabilities(repo, &data.can_symlink)) < 0) goto cleanup; @@ -360,6 +383,8 @@ int git_checkout_index( * checked out during pass #2. */ + report_progress(1, 0.f, &data, NULL); + if (!(error = git_diff_foreach( diff, &data, checkout_remove_the_old, NULL, NULL)) && !(error = git_diff_foreach( @@ -371,6 +396,8 @@ int git_checkout_index( diff, &data, checkout_create_the_new, NULL, NULL); } + report_progress(data.num_stages, 1.f, &data, NULL); + cleanup: if (error == GIT_EUSER) error = (data.error != 0) ? data.error : -1; From 909f626541a78cad0366ba85c04f29522bb47da7 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 15:28:09 -0700 Subject: [PATCH 16/27] Indexing progress now goes to 100% --- src/indexer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/indexer.c b/src/indexer.c index 2d032fbd3..450d90ebe 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -446,6 +446,7 @@ static int resolve_deltas(git_indexer_stream *idx, git_indexer_stats *stats) git__free(obj.data); stats->processed++; + do_progress_callback(idx, stats); } return 0; From 25e8b20169a6f6919ad49cf32220975ab96b35c8 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Thu, 18 Oct 2012 15:35:03 -0700 Subject: [PATCH 17/27] Fix broken tests --- tests-clar/checkout/index.c | 10 +++++----- tests-clar/checkout/tree.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index a21af5f60..eac8515da 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -364,16 +364,16 @@ void test_checkout_index__wont_notify_of_expected_line_ending_changes(void) static void progress(const char *path, float progress, void *payload) { GIT_UNUSED(path); GIT_UNUSED(progress); - int *count = (int*)payload; - (*count)++; + bool *was_called = (bool*)payload; + *was_called = true; } void test_checkout_index__calls_progress_callback(void) { - int count = 0; + bool was_called = 0; g_opts.progress_cb = progress; - g_opts.progress_payload = &count; + g_opts.progress_payload = &was_called; cl_git_pass(git_checkout_index(g_repo, &g_opts)); - cl_assert_equal_i(count, 5); + cl_assert_equal_i(was_called, true); } diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c index c6989598d..88d3b3467 100644 --- a/tests-clar/checkout/tree.c +++ b/tests-clar/checkout/tree.c @@ -67,17 +67,17 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void) static void progress(const char *path, float progress, void *payload) { GIT_UNUSED(path); GIT_UNUSED(progress); - int *count = (int*)payload; - (*count)++; + bool *was_called = (bool*)payload; + *was_called = true; } void test_checkout_tree__calls_progress_callback(void) { - int count = 0; + bool was_called = 0; g_opts.progress_cb = progress; - g_opts.progress_payload = &count; + g_opts.progress_payload = &was_called; cl_git_pass(git_revparse_single(&g_object, g_repo, "master")); cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); - cl_assert_equal_i(count, 4); + cl_assert_equal_i(was_called, true); } From 7bcd9e23e8f64c8622e9213ee0fa3d75d058053b Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 19 Oct 2012 19:23:32 -0700 Subject: [PATCH 18/27] gitno_buffer: callback on each packet The fetch code takes advantage of this to implement a progress callback every 100kb of transfer. --- examples/network/clone.c | 7 ++++--- include/git2/indexer.h | 1 + src/fetch.c | 33 +++++++++++++++++++++++++++++++++ src/netops.c | 3 ++- src/netops.h | 2 ++ src/transports/http.c | 2 ++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index fd30bca5b..5ad9330b9 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -18,10 +18,11 @@ static void print_progress(const progress_data *pd) int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; int checkout_percent = (int)(100.f * pd->checkout_progress); - printf("net %3d%% / idx %3d%% / chk %3d%% %50s\r", - network_percent, index_percent, checkout_percent, pd->path); + int kbytes = pd->fetch_progress.bytes / 1024; + printf("net %3d%% (%6d kb) / idx %3d%% / chk %3d%% %50s\n", + network_percent, kbytes, index_percent, checkout_percent, pd->path); /* - printf("net %5d /%5d – idx %5d /%5d – chk %.04f %20s\r", + printf("net %5d /%5d – idx %5d /%5d – chk %.04f %20s\n", pd->fetch_progress.received, pd->fetch_progress.total, pd->fetch_progress.processed, pd->fetch_progress.total, pd->checkout_progress, pd->path); diff --git a/include/git2/indexer.h b/include/git2/indexer.h index 0d3c9dd51..ae01fd61d 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -20,6 +20,7 @@ typedef struct git_indexer_stats { unsigned int total; unsigned int processed; unsigned int received; + size_t bytes; } git_indexer_stats; diff --git a/src/fetch.c b/src/fetch.c index 583c79a34..3f69c2cbf 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -19,6 +19,8 @@ #include "netops.h" #include "pkt.h" +#define NETWORK_XFER_THRESHOLD (100*1024) + struct filter_payload { git_remote *remote; const git_refspec *spec, *tagspec; @@ -348,6 +350,28 @@ static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer * return 0; } +struct network_packetsize_payload +{ + git_indexer_progress_callback callback; + void *payload; + git_indexer_stats *stats; + git_off_t last_fired_bytes; +}; + +static void network_packetsize(int received, void *payload) +{ + struct network_packetsize_payload *npp = (struct network_packetsize_payload*)payload; + + /* Accumulate bytes */ + npp->stats->bytes += received; + + /* Fire notification if the threshold is reached */ + if ((npp->stats->bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) { + npp->last_fired_bytes = npp->stats->bytes; + npp->callback(npp->stats, npp->payload); + } +} + /* Receiving data from a socket and storing it is pretty much the same for git and HTTP */ int git_fetch__download_pack( git_transport *t, @@ -361,6 +385,15 @@ int git_fetch__download_pack( gitno_buffer *buf = &t->buffer; git_indexer_stream *idx = NULL; int error = -1; + struct network_packetsize_payload npp = {0}; + + if (progress_cb) { + npp.callback = progress_cb; + npp.payload = progress_payload; + npp.stats = stats; + buf->packetsize_cb = &network_packetsize; + buf->packetsize_payload = &npp; + } if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0) return -1; diff --git a/src/netops.c b/src/netops.c index df502e619..d9663e63c 100644 --- a/src/netops.c +++ b/src/netops.c @@ -117,6 +117,7 @@ static int gitno__recv_ssl(gitno_buffer *buf) } buf->offset += ret; + if (buf->packetsize_cb) buf->packetsize_cb(ret, buf->packetsize_payload); return ret; } #endif @@ -132,6 +133,7 @@ int gitno__recv(gitno_buffer *buf) } buf->offset += ret; + if (buf->packetsize_cb) buf->packetsize_cb(ret, buf->packetsize_payload); return ret; } @@ -142,7 +144,6 @@ void gitno_buffer_setup_callback( size_t len, int (*recv)(gitno_buffer *buf), void *cb_data) { - memset(buf, 0x0, sizeof(gitno_buffer)); memset(data, 0x0, len); buf->data = data; buf->len = len; diff --git a/src/netops.h b/src/netops.h index 7c53fd0dc..64da7fba9 100644 --- a/src/netops.h +++ b/src/netops.h @@ -20,6 +20,8 @@ struct gitno_buffer { #endif int (*recv)(gitno_buffer *buffer); void *cb_data; + void (*packetsize_cb)(int received, void *payload); + void *packetsize_payload; }; void gitno_buffer_setup(git_transport *t, gitno_buffer *buf, char *data, size_t len); diff --git a/src/transports/http.c b/src/transports/http.c index 93dd0c326..0efd220c3 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -379,6 +379,8 @@ static int http_recv_cb(gitno_buffer *buf) #ifndef GIT_WINHTTP gitno_buffer_setup(transport, &inner, buffer, sizeof(buffer)); + inner.packetsize_cb = buf->packetsize_cb; + inner.packetsize_payload = buf->packetsize_payload; if ((error = gitno_recv(&inner)) < 0) return -1; From 63afb005e86d49e0f84d135d3d8dddae085a003f Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 19 Oct 2012 19:33:23 -0700 Subject: [PATCH 19/27] Remove third stage from checkout progress reporting Also, now only reporting checkout progress for files that are actually being added or removed. --- src/checkout.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index a20a6f9d6..35e3d298a 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -31,7 +31,6 @@ struct checkout_diff_data bool can_symlink; bool found_submodules; bool create_submodules; - int num_stages; int error; }; @@ -164,7 +163,7 @@ static void report_progress( struct checkout_diff_data *data, const char *path) { - float per_stage_progress = 1.f/data->num_stages; + float per_stage_progress = 0.5; float overall_progress = (stage-1)*per_stage_progress + stage_progress*per_stage_progress; @@ -177,7 +176,8 @@ static void report_progress( static int checkout_blob( struct checkout_diff_data *data, - const git_diff_file *file) + const git_diff_file *file, + float progress) { git_blob *blob; int error; @@ -196,6 +196,7 @@ static int checkout_blob( error = blob_content_to_file( blob, git_buf_cstr(data->path), file->mode, data->checkout_opts); + report_progress(2, progress, data, file->path); git_blob_free(blob); return error; @@ -218,9 +219,9 @@ static int checkout_remove_the_old( delta->new_file.path, git_repository_workdir(data->owner), GIT_DIRREMOVAL_FILES_AND_DIRS); - } - report_progress(1, progress, data, delta->new_file.path); + report_progress(1, progress, data, delta->new_file.path); + } return data->error; } @@ -262,18 +263,14 @@ static int checkout_create_the_new( if (is_submodule) { data->found_submodules = true; - data->num_stages = 3; } if (!is_submodule && !data->create_submodules) { - error = checkout_blob(data, &delta->old_file); - report_progress(2, progress, data, delta->old_file.path); - + error = checkout_blob(data, &delta->old_file, progress); } else if (is_submodule && data->create_submodules) { error = checkout_submodule(data, &delta->old_file); - report_progress(3, progress, data, delta->old_file.path); } } @@ -368,7 +365,6 @@ int git_checkout_index( data.workdir_len = git_buf_len(&workdir); data.checkout_opts = &checkout_opts; data.owner = repo; - data.num_stages = 2; if ((error = retrieve_symlink_capabilities(repo, &data.can_symlink)) < 0) goto cleanup; @@ -396,7 +392,7 @@ int git_checkout_index( diff, &data, checkout_create_the_new, NULL, NULL); } - report_progress(data.num_stages, 1.f, &data, NULL); + report_progress(2, 1.f, &data, NULL); cleanup: if (error == GIT_EUSER) From cd001bbbfe75a366d9658849cf6c5931440c0c01 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 19 Oct 2012 19:37:47 -0700 Subject: [PATCH 20/27] Fix from rebase --- tests-clar/checkout/head.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-clar/checkout/head.c b/tests-clar/checkout/head.c index f2f81e5e2..129f24974 100644 --- a/tests-clar/checkout/head.c +++ b/tests-clar/checkout/head.c @@ -20,5 +20,5 @@ void test_checkout_head__checking_out_an_orphaned_head_returns_GIT_EORPHANEDHEAD cl_git_pass(git_reference_create_symbolic(&head, g_repo, GIT_HEAD_FILE, "refs/heads/hide/and/seek", 1)); git_reference_free(head); - cl_assert_equal_i(GIT_EORPHANEDHEAD, git_checkout_head(g_repo, NULL, NULL)); + cl_assert_equal_i(GIT_EORPHANEDHEAD, git_checkout_head(g_repo, NULL)); } From 9c05c17b7ac7caf7691a9056994bda735ea31c81 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 19 Oct 2012 20:05:18 -0700 Subject: [PATCH 21/27] Checkout progress now reports completed/total steps --- examples/network/clone.c | 12 ++++++++---- include/git2/checkout.h | 3 ++- src/checkout.c | 28 ++++++++++++++-------------- tests-clar/checkout/index.c | 4 ++-- tests-clar/checkout/tree.c | 4 ++-- tests-clar/clone/network.c | 4 ++-- 6 files changed, 30 insertions(+), 25 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 5ad9330b9..19bf0cca8 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -9,7 +9,8 @@ typedef struct progress_data { git_indexer_stats fetch_progress; - float checkout_progress; + size_t completed_steps; + size_t total_steps; const char *path; } progress_data; @@ -17,7 +18,9 @@ static void print_progress(const progress_data *pd) { int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; - int checkout_percent = (int)(100.f * pd->checkout_progress); + int checkout_percent = pd->total_steps > 0 + ? (100.f * pd->completed_steps) / pd->total_steps + : 0.f; int kbytes = pd->fetch_progress.bytes / 1024; printf("net %3d%% (%6d kb) / idx %3d%% / chk %3d%% %50s\n", network_percent, kbytes, index_percent, checkout_percent, pd->path); @@ -35,10 +38,11 @@ static void fetch_progress(const git_indexer_stats *stats, void *payload) pd->fetch_progress = *stats; print_progress(pd); } -static void checkout_progress(const char *path, float progress, void *payload) +static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) { progress_data *pd = (progress_data*)payload; - pd->checkout_progress = progress; + pd->completed_steps = cur; + pd->total_steps = tot; pd->path = path; print_progress(pd); } diff --git a/include/git2/checkout.h b/include/git2/checkout.h index 9032c6b2c..390d2f215 100644 --- a/include/git2/checkout.h +++ b/include/git2/checkout.h @@ -70,7 +70,8 @@ typedef struct git_checkout_opts { /* Optional callback to notify the consumer of checkout progress. */ void (* progress_cb)( const char *path, - float progress, + size_t completed_steps, + size_t total_steps, void *payload); void *progress_payload; diff --git a/src/checkout.c b/src/checkout.c index 35e3d298a..8ab3da8e2 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -32,6 +32,8 @@ struct checkout_diff_data bool found_submodules; bool create_submodules; int error; + size_t total_steps; + size_t completed_steps; }; static int buffer_to_file( @@ -158,26 +160,20 @@ static int checkout_submodule( } static void report_progress( - int stage, - float stage_progress, struct checkout_diff_data *data, const char *path) { - float per_stage_progress = 0.5; - float overall_progress = (stage-1)*per_stage_progress + - stage_progress*per_stage_progress; - if (data->checkout_opts->progress_cb) data->checkout_opts->progress_cb( path, - overall_progress, + data->completed_steps, + data->total_steps, data->checkout_opts->progress_payload); } static int checkout_blob( struct checkout_diff_data *data, - const git_diff_file *file, - float progress) + const git_diff_file *file) { git_blob *blob; int error; @@ -196,7 +192,7 @@ static int checkout_blob( error = blob_content_to_file( blob, git_buf_cstr(data->path), file->mode, data->checkout_opts); - report_progress(2, progress, data, file->path); + report_progress(data, file->path); git_blob_free(blob); return error; @@ -220,7 +216,8 @@ static int checkout_remove_the_old( git_repository_workdir(data->owner), GIT_DIRREMOVAL_FILES_AND_DIRS); - report_progress(1, progress, data, delta->new_file.path); + data->completed_steps++; + report_progress(data, delta->new_file.path); } return data->error; @@ -266,11 +263,13 @@ static int checkout_create_the_new( } if (!is_submodule && !data->create_submodules) { - error = checkout_blob(data, &delta->old_file, progress); + error = checkout_blob(data, &delta->old_file); + data->completed_steps++; } else if (is_submodule && data->create_submodules) { error = checkout_submodule(data, &delta->old_file); + data->completed_steps++; } } @@ -365,6 +364,7 @@ int git_checkout_index( data.workdir_len = git_buf_len(&workdir); data.checkout_opts = &checkout_opts; data.owner = repo; + data.total_steps = (size_t)git_diff_num_deltas(diff); if ((error = retrieve_symlink_capabilities(repo, &data.can_symlink)) < 0) goto cleanup; @@ -379,7 +379,7 @@ int git_checkout_index( * checked out during pass #2. */ - report_progress(1, 0.f, &data, NULL); + report_progress(&data, NULL); if (!(error = git_diff_foreach( diff, &data, checkout_remove_the_old, NULL, NULL)) && @@ -392,7 +392,7 @@ int git_checkout_index( diff, &data, checkout_create_the_new, NULL, NULL); } - report_progress(2, 1.f, &data, NULL); + report_progress(&data, NULL); cleanup: if (error == GIT_EUSER) diff --git a/tests-clar/checkout/index.c b/tests-clar/checkout/index.c index eac8515da..58b3c7e37 100644 --- a/tests-clar/checkout/index.c +++ b/tests-clar/checkout/index.c @@ -361,9 +361,9 @@ void test_checkout_index__wont_notify_of_expected_line_ending_changes(void) cl_git_pass(git_checkout_index(g_repo, &g_opts)); } -static void progress(const char *path, float progress, void *payload) +static void progress(const char *path, size_t cur, size_t tot, void *payload) { - GIT_UNUSED(path); GIT_UNUSED(progress); + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); bool *was_called = (bool*)payload; *was_called = true; } diff --git a/tests-clar/checkout/tree.c b/tests-clar/checkout/tree.c index 88d3b3467..598ea9fc7 100644 --- a/tests-clar/checkout/tree.c +++ b/tests-clar/checkout/tree.c @@ -64,9 +64,9 @@ void test_checkout_tree__can_checkout_a_subdirectory_from_a_subtree(void) cl_assert_equal_i(true, git_path_isfile("./testrepo/de/fgh/1.txt")); } -static void progress(const char *path, float progress, void *payload) +static void progress(const char *path, size_t cur, size_t tot, void *payload) { - GIT_UNUSED(path); GIT_UNUSED(progress); + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); bool *was_called = (bool*)payload; *was_called = true; } diff --git a/tests-clar/clone/network.c b/tests-clar/clone/network.c index 62d4110c6..3d78d43a3 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/clone/network.c @@ -91,9 +91,9 @@ void test_clone_network__can_prevent_the_checkout_of_a_standard_repo(void) git_buf_free(&path); } -static void checkout_progress(const char *path, float progress, void *payload) +static void checkout_progress(const char *path, size_t cur, size_t tot, void *payload) { - GIT_UNUSED(path); GIT_UNUSED(progress); + GIT_UNUSED(path); GIT_UNUSED(cur); GIT_UNUSED(tot); bool *was_called = (bool*)payload; (*was_called) = true; } From 2dae54a9419aaeb9d3d6a8eb6a28e13edb41bd58 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Fri, 19 Oct 2012 20:24:15 -0700 Subject: [PATCH 22/27] Improve clone sample's formatting --- examples/network/clone.c | 15 ++++++--------- src/checkout.c | 3 ++- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 19bf0cca8..6f98192cc 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -19,17 +19,14 @@ static void print_progress(const progress_data *pd) int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; int checkout_percent = pd->total_steps > 0 - ? (100.f * pd->completed_steps) / pd->total_steps + ? (100 * pd->completed_steps) / pd->total_steps : 0.f; int kbytes = pd->fetch_progress.bytes / 1024; - printf("net %3d%% (%6d kb) / idx %3d%% / chk %3d%% %50s\n", - network_percent, kbytes, index_percent, checkout_percent, pd->path); - /* - printf("net %5d /%5d – idx %5d /%5d – chk %.04f %20s\n", - pd->fetch_progress.received, pd->fetch_progress.total, - pd->fetch_progress.processed, pd->fetch_progress.total, - pd->checkout_progress, pd->path); - */ + printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4lu/%4lu) %s\n", + network_percent, kbytes, pd->fetch_progress.received, pd->fetch_progress.total, + index_percent, pd->fetch_progress.processed, pd->fetch_progress.total, + checkout_percent, pd->completed_steps, pd->total_steps, + pd->path); } static void fetch_progress(const git_indexer_stats *stats, void *payload) diff --git a/src/checkout.c b/src/checkout.c index 8ab3da8e2..b7bfa409a 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -192,7 +192,6 @@ static int checkout_blob( error = blob_content_to_file( blob, git_buf_cstr(data->path), file->mode, data->checkout_opts); - report_progress(data, file->path); git_blob_free(blob); return error; @@ -265,11 +264,13 @@ static int checkout_create_the_new( if (!is_submodule && !data->create_submodules) { error = checkout_blob(data, &delta->old_file); data->completed_steps++; + report_progress(data, delta->old_file.path); } else if (is_submodule && data->create_submodules) { error = checkout_submodule(data, &delta->old_file); data->completed_steps++; + report_progress(data, delta->old_file.path); } } From c70ad945cdf9b92e54e7e8a5769b1f35ea19ebbd Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Tue, 23 Oct 2012 09:21:32 -0700 Subject: [PATCH 23/27] Update doc strings, warn about callback perf --- include/git2/clone.h | 11 ++++++++--- include/git2/remote.h | 4 +++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/git2/clone.h b/include/git2/clone.h index dc49074dc..847295a21 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -29,8 +29,10 @@ GIT_BEGIN_DECL * @param out pointer that will receive the resulting repository object * @param origin_url repository to clone from * @param workdir_path local directory to clone to - * @param fetch_stats pointer to structure that receives fetch progress - * information (may be NULL) + * @param fetch_progress_cb optional callback for fetch progress. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. + * @param fetch_progress_payload payload for fetch_progress_cb * @param checkout_opts options for the checkout step. If NULL, no checkout * is performed * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information @@ -50,7 +52,10 @@ GIT_EXTERN(int) git_clone( * @param out pointer that will receive the resulting repository object * @param origin_url repository to clone from * @param dest_path local directory to clone to - * @param fetch_stats pointer to structure that receives fetch progress information (may be NULL) + * @param fetch_progress_cb optional callback for fetch progress. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. + * @param fetch_progress_payload payload for fetch_progress_cb * @return 0 on success, GIT_ERROR otherwise (use giterr_last for information about the error) */ GIT_EXTERN(int) git_clone_bare( diff --git a/include/git2/remote.h b/include/git2/remote.h index ca75126f9..35b1f2e5b 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -184,7 +184,9 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * * @param remote the remote to download from * @param filename where to store the temporary filename - * @param progress_cb function to call with progress information + * @param progress_cb function to call with progress information. Be aware that + * this is called inline with network and indexing operations, so performance + * may be affected. * @param progress_payload payload for the progress callback * @return 0 or an error code */ From c4958e6818399f401f03986db8772016a97377d7 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 24 Oct 2012 12:38:05 -0700 Subject: [PATCH 24/27] Fix documentation comment --- include/git2/remote.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/git2/remote.h b/include/git2/remote.h index 35b1f2e5b..e23997d9a 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -183,7 +183,8 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * filename will be NULL and the function will return success. * * @param remote the remote to download from - * @param filename where to store the temporary filename + * @param bytes buffer that receives the number of bytes transferred (updated + * while transfer is in progress) * @param progress_cb function to call with progress information. Be aware that * this is called inline with network and indexing operations, so performance * may be affected. From 7d222e13121aebc269b2923a66c7ba5b734e1a90 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 24 Oct 2012 13:29:14 -0700 Subject: [PATCH 25/27] Network progress: rename things git_indexer_stats and friends -> git_transfer_progress* Also made git_transfer_progress members more sanely named. --- examples/network/fetch.c | 2 +- include/git2/clone.h | 4 ++-- include/git2/indexer.h | 22 ++++++++++----------- include/git2/remote.h | 4 ++-- src/clone.c | 8 ++++---- src/fetch.c | 20 +++++++++---------- src/fetch.h | 6 +++--- src/index.c | 2 +- src/indexer.c | 36 +++++++++++++++++------------------ src/remote.c | 4 ++-- src/remote.h | 2 +- src/transport.h | 2 +- tests-clar/clone/network.c | 2 +- tests-clar/network/fetch.c | 2 +- tests-clar/pack/packbuilder.c | 2 +- 15 files changed, 59 insertions(+), 59 deletions(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index f7b2fd9de..39cb0deb8 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -69,7 +69,7 @@ int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; git_off_t bytes = 0; - const git_indexer_stats *stats; + const git_transfer_progress *stats; pthread_t worker; struct dl_data data; git_remote_callbacks callbacks; diff --git a/include/git2/clone.h b/include/git2/clone.h index 847295a21..7d8d32118 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -42,7 +42,7 @@ GIT_EXTERN(int) git_clone( git_repository **out, const char *origin_url, const char *workdir_path, - git_indexer_progress_callback fetch_progress_cb, + git_transfer_progress_callback fetch_progress_cb, void *fetch_progress_payload, git_checkout_opts *checkout_opts); @@ -62,7 +62,7 @@ GIT_EXTERN(int) git_clone_bare( git_repository **out, const char *origin_url, const char *dest_path, - git_indexer_progress_callback fetch_progress_cb, + git_transfer_progress_callback fetch_progress_cb, void *fetch_progress_payload); /** @} */ diff --git a/include/git2/indexer.h b/include/git2/indexer.h index ae01fd61d..a2a155473 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -16,18 +16,18 @@ GIT_BEGIN_DECL * This is passed as the first argument to the callback to allow the * user to see the progress. */ -typedef struct git_indexer_stats { - unsigned int total; - unsigned int processed; - unsigned int received; - size_t bytes; -} git_indexer_stats; +typedef struct git_transfer_progress { + unsigned int total_objects; + unsigned int indexed_objects; + unsigned int received_objects; + size_t received_bytes; +} git_transfer_progress; /** * Type for progress callbacks during indexing */ -typedef void (*git_indexer_progress_callback)(const git_indexer_stats *stats, void *payload); +typedef void (*git_transfer_progress_callback)(const git_transfer_progress *stats, void *payload); typedef struct git_indexer git_indexer; typedef struct git_indexer_stream git_indexer_stream; @@ -43,7 +43,7 @@ typedef struct git_indexer_stream git_indexer_stream; GIT_EXTERN(int) git_indexer_stream_new( git_indexer_stream **out, const char *path, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_callback_payload); /** @@ -54,7 +54,7 @@ GIT_EXTERN(int) git_indexer_stream_new( * @param size the size of the data * @param stats stat storage */ -GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats); /** * Finalize the pack and index @@ -63,7 +63,7 @@ GIT_EXTERN(int) git_indexer_stream_add(git_indexer_stream *idx, const void *data * * @param idx the indexer */ -GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats); /** * Get the packfile's hash @@ -100,7 +100,7 @@ GIT_EXTERN(int) git_indexer_new(git_indexer **out, const char *packname); * @param idx the indexer instance * @param stats storage for the running state */ -GIT_EXTERN(int) git_indexer_run(git_indexer *idx, git_indexer_stats *stats); +GIT_EXTERN(int) git_indexer_run(git_indexer *idx, git_transfer_progress *stats); /** * Write the index file to disk. diff --git a/include/git2/remote.h b/include/git2/remote.h index e23997d9a..897dfde8f 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -194,7 +194,7 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void GIT_EXTERN(int) git_remote_download( git_remote *remote, git_off_t *bytes, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload); /** @@ -325,7 +325,7 @@ GIT_EXTERN(void) git_remote_set_callbacks(git_remote *remote, git_remote_callbac /** * Get the statistics structure that is filled in by the fetch operation. */ -GIT_EXTERN(const git_indexer_stats *) git_remote_stats(git_remote *remote); +GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); enum { GIT_REMOTE_DOWNLOAD_TAGS_UNSET, diff --git a/src/clone.c b/src/clone.c index 61e5e8567..fc2bfa1fa 100644 --- a/src/clone.c +++ b/src/clone.c @@ -251,7 +251,7 @@ cleanup: static int setup_remotes_and_fetch( git_repository *repo, const char *origin_url, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload) { int retcode = GIT_ERROR; @@ -310,7 +310,7 @@ static int clone_internal( git_repository **out, const char *origin_url, const char *path, - git_indexer_progress_callback fetch_progress_cb, + git_transfer_progress_callback fetch_progress_cb, void *fetch_progress_payload, git_checkout_opts *checkout_opts, bool is_bare) @@ -344,7 +344,7 @@ int git_clone_bare( git_repository **out, const char *origin_url, const char *dest_path, - git_indexer_progress_callback fetch_progress_cb, + git_transfer_progress_callback fetch_progress_cb, void *fetch_progress_payload) { assert(out && origin_url && dest_path); @@ -364,7 +364,7 @@ int git_clone( git_repository **out, const char *origin_url, const char *workdir_path, - git_indexer_progress_callback fetch_progress_cb, + git_transfer_progress_callback fetch_progress_cb, void *fetch_progress_payload, git_checkout_opts *checkout_opts) { diff --git a/src/fetch.c b/src/fetch.c index 3f69c2cbf..ee85f083d 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -307,7 +307,7 @@ on_error: int git_fetch_download_pack( git_remote *remote, git_off_t *bytes, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload) { git_transport *t = remote->transport; @@ -323,7 +323,7 @@ int git_fetch_download_pack( } -static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer *buf, git_off_t *bytes, git_indexer_stats *stats) +static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer *buf, git_off_t *bytes, git_transfer_progress *stats) { int recvd; @@ -352,9 +352,9 @@ static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer * struct network_packetsize_payload { - git_indexer_progress_callback callback; + git_transfer_progress_callback callback; void *payload; - git_indexer_stats *stats; + git_transfer_progress *stats; git_off_t last_fired_bytes; }; @@ -363,11 +363,11 @@ static void network_packetsize(int received, void *payload) struct network_packetsize_payload *npp = (struct network_packetsize_payload*)payload; /* Accumulate bytes */ - npp->stats->bytes += received; + npp->stats->received_bytes += received; /* Fire notification if the threshold is reached */ - if ((npp->stats->bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) { - npp->last_fired_bytes = npp->stats->bytes; + if ((npp->stats->received_bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) { + npp->last_fired_bytes = npp->stats->received_bytes; npp->callback(npp->stats, npp->payload); } } @@ -377,8 +377,8 @@ int git_fetch__download_pack( git_transport *t, git_repository *repo, git_off_t *bytes, - git_indexer_stats *stats, - git_indexer_progress_callback progress_cb, + git_transfer_progress *stats, + git_transfer_progress_callback progress_cb, void *progress_payload) { git_buf path = GIT_BUF_INIT; @@ -402,7 +402,7 @@ int git_fetch__download_pack( goto on_error; git_buf_free(&path); - memset(stats, 0, sizeof(git_indexer_stats)); + memset(stats, 0, sizeof(git_transfer_progress)); *bytes = 0; /* diff --git a/src/fetch.h b/src/fetch.h index c10973422..23d0cf66f 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -14,15 +14,15 @@ int git_fetch_negotiate(git_remote *remote); int git_fetch_download_pack( git_remote *remote, git_off_t *bytes, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload); int git_fetch__download_pack( git_transport *t, git_repository *repo, git_off_t *bytes, - git_indexer_stats *stats, - git_indexer_progress_callback progress_cb, + git_transfer_progress *stats, + git_transfer_progress_callback progress_cb, void *progress_payload); int git_fetch_setup_walk(git_revwalk **out, git_repository *repo); diff --git a/src/index.c b/src/index.c index 362c2c690..f92c48df9 100644 --- a/src/index.c +++ b/src/index.c @@ -1034,7 +1034,7 @@ int git_index_entry_stage(const git_index_entry *entry) typedef struct read_tree_data { git_index *index; - git_indexer_stats *stats; + git_transfer_progress *stats; } read_tree_data; static int read_tree_cb(const char *root, const git_tree_entry *tentry, void *data) diff --git a/src/indexer.c b/src/indexer.c index 450d90ebe..4ebcdc6c2 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -49,7 +49,7 @@ struct git_indexer_stream { git_vector deltas; unsigned int fanout[256]; git_oid hash; - git_indexer_progress_callback progress_cb; + git_transfer_progress_callback progress_cb; void *progress_payload; }; @@ -143,7 +143,7 @@ static int cache_cmp(const void *a, const void *b) int git_indexer_stream_new( git_indexer_stream **out, const char *prefix, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload) { git_indexer_stream *idx; @@ -281,13 +281,13 @@ on_error: return -1; } -static void do_progress_callback(git_indexer_stream *idx, git_indexer_stats *stats) +static void do_progress_callback(git_indexer_stream *idx, git_transfer_progress *stats) { if (!idx->progress_cb) return; idx->progress_cb(stats, idx->progress_payload); } -int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_indexer_stats *stats) +int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t size, git_transfer_progress *stats) { int error; struct git_pack_header hdr; @@ -296,7 +296,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz assert(idx && data && stats); - processed = stats->processed; + processed = stats->indexed_objects; if (git_filebuf_write(&idx->pack_file, data, size) < 0) return -1; @@ -338,8 +338,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz if (git_vector_init(&idx->deltas, (unsigned int)(idx->nr_objects / 2), NULL) < 0) return -1; - memset(stats, 0, sizeof(git_indexer_stats)); - stats->total = (unsigned int)idx->nr_objects; + memset(stats, 0, sizeof(git_transfer_progress)); + stats->total_objects = (unsigned int)idx->nr_objects; do_progress_callback(idx, stats); } @@ -376,7 +376,7 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz if (error < 0) return error; - stats->received++; + stats->received_objects++; do_progress_callback(idx, stats); continue; } @@ -395,8 +395,8 @@ int git_indexer_stream_add(git_indexer_stream *idx, const void *data, size_t siz git__free(obj.data); - stats->processed = (unsigned int)++processed; - stats->received++; + stats->indexed_objects = (unsigned int)++processed; + stats->received_objects++; do_progress_callback(idx, stats); } @@ -429,7 +429,7 @@ static int index_path_stream(git_buf *path, git_indexer_stream *idx, const char return git_buf_oom(path) ? -1 : 0; } -static int resolve_deltas(git_indexer_stream *idx, git_indexer_stats *stats) +static int resolve_deltas(git_indexer_stream *idx, git_transfer_progress *stats) { unsigned int i; struct delta_info *delta; @@ -445,14 +445,14 @@ static int resolve_deltas(git_indexer_stream *idx, git_indexer_stats *stats) return -1; git__free(obj.data); - stats->processed++; + stats->indexed_objects++; do_progress_callback(idx, stats); } return 0; } -int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stats) +int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *stats) { git_mwindow *w = NULL; unsigned int i, long_offsets = 0, left; @@ -473,7 +473,7 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_indexer_stats *stat if (resolve_deltas(idx, stats) < 0) return -1; - if (stats->processed != stats->total) { + if (stats->indexed_objects != stats->total_objects) { giterr_set(GITERR_INDEXER, "Indexing error: early EOF"); return -1; } @@ -800,7 +800,7 @@ cleanup: return error; } -int git_indexer_run(git_indexer *idx, git_indexer_stats *stats) +int git_indexer_run(git_indexer *idx, git_transfer_progress *stats) { git_mwindow_file *mwf; git_off_t off = sizeof(struct git_pack_header); @@ -815,8 +815,8 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats) if (error < 0) return error; - stats->total = (unsigned int)idx->nr_objects; - stats->processed = processed = 0; + stats->total_objects = (unsigned int)idx->nr_objects; + stats->indexed_objects = processed = 0; while (processed < idx->nr_objects) { git_rawobj obj; @@ -886,7 +886,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats) git__free(obj.data); - stats->processed = ++processed; + stats->indexed_objects = ++processed; } cleanup: diff --git a/src/remote.c b/src/remote.c index 662b8cc9b..3e9a757a5 100644 --- a/src/remote.c +++ b/src/remote.c @@ -436,7 +436,7 @@ int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) int git_remote_download( git_remote *remote, git_off_t *bytes, - git_indexer_progress_callback progress_cb, + git_transfer_progress_callback progress_cb, void *progress_payload) { int error; @@ -707,7 +707,7 @@ void git_remote_set_callbacks(git_remote *remote, git_remote_callbacks *callback } } -inline const git_indexer_stats* git_remote_stats(git_remote *remote) +inline const git_transfer_progress* git_remote_stats(git_remote *remote) { assert(remote); return &remote->stats; diff --git a/src/remote.h b/src/remote.h index 1ba82608b..1b382e1bb 100644 --- a/src/remote.h +++ b/src/remote.h @@ -25,7 +25,7 @@ struct git_remote { git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; - git_indexer_stats stats; + git_transfer_progress stats; unsigned int need_pack:1, download_tags:2, /* There are four possible values */ check_cert:1; diff --git a/src/transport.h b/src/transport.h index 4c944b9e7..79afae000 100644 --- a/src/transport.h +++ b/src/transport.h @@ -113,7 +113,7 @@ struct git_transport { /** * Download the packfile */ - int (*download_pack)(struct git_transport *transport, git_repository *repo, git_off_t *bytes, git_indexer_stats *stats); + int (*download_pack)(struct git_transport *transport, git_repository *repo, git_off_t *bytes, git_transfer_progress *stats); /** * Close the connection */ diff --git a/tests-clar/clone/network.c b/tests-clar/clone/network.c index 3d78d43a3..0faaa5c81 100644 --- a/tests-clar/clone/network.c +++ b/tests-clar/clone/network.c @@ -98,7 +98,7 @@ static void checkout_progress(const char *path, size_t cur, size_t tot, void *pa (*was_called) = true; } -static void fetch_progress(const git_indexer_stats *stats, void *payload) +static void fetch_progress(const git_transfer_progress *stats, void *payload) { GIT_UNUSED(stats); bool *was_called = (bool*)payload; diff --git a/tests-clar/network/fetch.c b/tests-clar/network/fetch.c index 134e8fe2e..c3fb15eb9 100644 --- a/tests-clar/network/fetch.c +++ b/tests-clar/network/fetch.c @@ -28,7 +28,7 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, return 0; } -static void progress(const git_indexer_stats *stats, void *payload) +static void progress(const git_transfer_progress *stats, void *payload) { GIT_UNUSED(stats); bool *was_called = (bool*)payload; diff --git a/tests-clar/pack/packbuilder.c b/tests-clar/pack/packbuilder.c index fa7bec14e..6d17a709f 100644 --- a/tests-clar/pack/packbuilder.c +++ b/tests-clar/pack/packbuilder.c @@ -33,7 +33,7 @@ void test_pack_packbuilder__cleanup(void) void test_pack_packbuilder__create_pack(void) { - git_indexer_stats stats; + git_transfer_progress stats; git_oid oid, *o; unsigned int i; From 9762ad993dc1afff90a3d14751f1b1f666ad0c95 Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 24 Oct 2012 13:43:23 -0700 Subject: [PATCH 26/27] Renaming: fix example --- examples/network/clone.c | 15 ++++++++------- examples/network/fetch.c | 8 +++++--- examples/network/index-pack.c | 8 ++++---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index 6f98192cc..791600171 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -8,7 +8,7 @@ #include typedef struct progress_data { - git_indexer_stats fetch_progress; + git_transfer_progress fetch_progress; size_t completed_steps; size_t total_steps; const char *path; @@ -16,20 +16,21 @@ typedef struct progress_data { static void print_progress(const progress_data *pd) { - int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total; - int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total; + int network_percent = (100*pd->fetch_progress.received_objects) / pd->fetch_progress.total_objects; + int index_percent = (100*pd->fetch_progress.indexed_objects) / pd->fetch_progress.total_objects; int checkout_percent = pd->total_steps > 0 ? (100 * pd->completed_steps) / pd->total_steps : 0.f; - int kbytes = pd->fetch_progress.bytes / 1024; + int kbytes = pd->fetch_progress.received_bytes / 1024; printf("net %3d%% (%4d kb, %5d/%5d) / idx %3d%% (%5d/%5d) / chk %3d%% (%4lu/%4lu) %s\n", - network_percent, kbytes, pd->fetch_progress.received, pd->fetch_progress.total, - index_percent, pd->fetch_progress.processed, pd->fetch_progress.total, + network_percent, kbytes, + pd->fetch_progress.received_objects, pd->fetch_progress.total_objects, + index_percent, pd->fetch_progress.indexed_objects, pd->fetch_progress.total_objects, checkout_percent, pd->completed_steps, pd->total_steps, pd->path); } -static void fetch_progress(const git_indexer_stats *stats, void *payload) +static void fetch_progress(const git_transfer_progress *stats, void *payload) { progress_data *pd = (progress_data*)payload; pd->fetch_progress = *stats; diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 39cb0deb8..8bfe10c5c 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -105,16 +105,18 @@ int fetch(git_repository *repo, int argc, char **argv) do { usleep(10000); - if (stats->total > 0) + if (stats->total_objects > 0) printf("Received %d/%d objects (%d) in %d bytes\r", - stats->received, stats->total, stats->processed, bytes); + stats->received_objects, stats->total_objects, + stats->indexed_objects, bytes); } while (!data.finished); if (data.ret < 0) goto on_error; pthread_join(worker, NULL); - printf("\rReceived %d/%d objects in %zu bytes\n", stats->processed, stats->total, bytes); + printf("\rReceived %d/%d objects in %zu bytes\n", + stats->indexed_objects, stats->total_objects, bytes); // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); diff --git a/examples/network/index-pack.c b/examples/network/index-pack.c index 69338b37f..4d3dc84d6 100644 --- a/examples/network/index-pack.c +++ b/examples/network/index-pack.c @@ -10,10 +10,10 @@ // This could be run in the main loop whilst the application waits for // the indexing to finish in a worker thread -static int index_cb(const git_indexer_stats *stats, void *data) +static int index_cb(const git_transfer_progress *stats, void *data) { data = data; - printf("\rProcessing %d of %d", stats->processed, stats->total); + printf("\rProcessing %d of %d", stats->indexed_objects, stats->total_objects); return 0; } @@ -21,7 +21,7 @@ static int index_cb(const git_indexer_stats *stats, void *data) int index_pack(git_repository *repo, int argc, char **argv) { git_indexer_stream *idx; - git_indexer_stats stats = {0, 0}; + git_transfer_progress stats = {0, 0}; int error, fd; char hash[GIT_OID_HEXSZ + 1] = {0}; ssize_t read_bytes; @@ -63,7 +63,7 @@ int index_pack(git_repository *repo, int argc, char **argv) if ((error = git_indexer_stream_finalize(idx, &stats)) < 0) goto cleanup; - printf("\rIndexing %d of %d\n", stats.processed, stats.total); + printf("\rIndexing %d of %d\n", stats.indexed_objects, stats.total_objects); git_oid_fmt(hash, git_indexer_stream_hash(idx)); puts(hash); From 1e3b8ed5cfe784f73a123c33c90f573742d8839e Mon Sep 17 00:00:00 2001 From: Ben Straub Date: Wed, 24 Oct 2012 14:07:07 -0700 Subject: [PATCH 27/27] Remove 'bytes' param from git_remote_download --- examples/network/fetch.c | 9 +++------ include/git2/remote.h | 3 --- src/clone.c | 3 +-- src/fetch.c | 14 ++++---------- src/fetch.h | 2 -- src/remote.c | 5 ++--- src/transport.h | 2 +- tests-clar/network/fetch.c | 3 +-- 8 files changed, 12 insertions(+), 29 deletions(-) diff --git a/examples/network/fetch.c b/examples/network/fetch.c index 8bfe10c5c..496498e8c 100644 --- a/examples/network/fetch.c +++ b/examples/network/fetch.c @@ -8,7 +8,6 @@ struct dl_data { git_remote *remote; - git_off_t *bytes; int ret; int finished; }; @@ -34,7 +33,7 @@ static void *download(void *ptr) // Download the packfile and index it. This function updates the // amount of received data and the indexer stats which lets you // inform the user about progress. - if (git_remote_download(data->remote, data->bytes, NULL, NULL) < 0) { + if (git_remote_download(data->remote, NULL, NULL) < 0) { data->ret = -1; goto exit; } @@ -68,7 +67,6 @@ static int update_cb(const char *refname, const git_oid *a, const git_oid *b, vo int fetch(git_repository *repo, int argc, char **argv) { git_remote *remote = NULL; - git_off_t bytes = 0; const git_transfer_progress *stats; pthread_t worker; struct dl_data data; @@ -90,7 +88,6 @@ int fetch(git_repository *repo, int argc, char **argv) // Set up the information for the background worker thread data.remote = remote; - data.bytes = &bytes; data.ret = 0; data.finished = 0; @@ -108,7 +105,7 @@ int fetch(git_repository *repo, int argc, char **argv) if (stats->total_objects > 0) printf("Received %d/%d objects (%d) in %d bytes\r", stats->received_objects, stats->total_objects, - stats->indexed_objects, bytes); + stats->indexed_objects, stats->received_bytes); } while (!data.finished); if (data.ret < 0) @@ -116,7 +113,7 @@ int fetch(git_repository *repo, int argc, char **argv) pthread_join(worker, NULL); printf("\rReceived %d/%d objects in %zu bytes\n", - stats->indexed_objects, stats->total_objects, bytes); + stats->indexed_objects, stats->total_objects, stats->received_bytes); // Disconnect the underlying connection to prevent from idling. git_remote_disconnect(remote); diff --git a/include/git2/remote.h b/include/git2/remote.h index 897dfde8f..1ec1a0840 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -183,8 +183,6 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void * filename will be NULL and the function will return success. * * @param remote the remote to download from - * @param bytes buffer that receives the number of bytes transferred (updated - * while transfer is in progress) * @param progress_cb function to call with progress information. Be aware that * this is called inline with network and indexing operations, so performance * may be affected. @@ -193,7 +191,6 @@ GIT_EXTERN(int) git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void */ GIT_EXTERN(int) git_remote_download( git_remote *remote, - git_off_t *bytes, git_transfer_progress_callback progress_cb, void *progress_payload); diff --git a/src/clone.c b/src/clone.c index fc2bfa1fa..ab8b9bcbb 100644 --- a/src/clone.c +++ b/src/clone.c @@ -256,13 +256,12 @@ static int setup_remotes_and_fetch( { int retcode = GIT_ERROR; git_remote *origin = NULL; - git_off_t bytes = 0; /* Create the "origin" remote */ if (!git_remote_add(&origin, repo, GIT_REMOTE_ORIGIN, origin_url)) { /* Connect and download everything */ if (!git_remote_connect(origin, GIT_DIR_FETCH)) { - if (!git_remote_download(origin, &bytes, progress_cb, progress_payload)) { + if (!git_remote_download(origin, progress_cb, progress_payload)) { /* Create "origin/foo" branches for all remote branches */ if (!git_remote_update_tips(origin)) { /* Point HEAD to the same ref as the remote's head */ diff --git a/src/fetch.c b/src/fetch.c index ee85f083d..0aabe744f 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -306,7 +306,6 @@ on_error: int git_fetch_download_pack( git_remote *remote, - git_off_t *bytes, git_transfer_progress_callback progress_cb, void *progress_payload) { @@ -316,14 +315,14 @@ int git_fetch_download_pack( return 0; if (t->own_logic) - return t->download_pack(t, remote->repo, bytes, &remote->stats); + return t->download_pack(t, remote->repo, &remote->stats); - return git_fetch__download_pack(t, remote->repo, bytes, &remote->stats, + return git_fetch__download_pack(t, remote->repo, &remote->stats, progress_cb, progress_payload); } -static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer *buf, git_off_t *bytes, git_transfer_progress *stats) +static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer *buf, git_transfer_progress *stats) { int recvd; @@ -340,8 +339,6 @@ static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer * if ((recvd = gitno_recv(buf)) < 0) return -1; - - *bytes += recvd; } while(recvd > 0); if (git_indexer_stream_finalize(idx, stats)) @@ -376,7 +373,6 @@ static void network_packetsize(int received, void *payload) int git_fetch__download_pack( git_transport *t, git_repository *repo, - git_off_t *bytes, git_transfer_progress *stats, git_transfer_progress_callback progress_cb, void *progress_payload) @@ -403,7 +399,6 @@ int git_fetch__download_pack( git_buf_free(&path); memset(stats, 0, sizeof(git_transfer_progress)); - *bytes = 0; /* * If the remote doesn't support the side-band, we can feed @@ -411,7 +406,7 @@ int git_fetch__download_pack( * check which one belongs there. */ if (!t->caps.side_band && !t->caps.side_band_64k) { - if (no_sideband(t, idx, buf, bytes, stats) < 0) + if (no_sideband(t, idx, buf, stats) < 0) goto on_error; git_indexer_stream_free(idx); @@ -438,7 +433,6 @@ int git_fetch__download_pack( git__free(pkt); } else if (pkt->type == GIT_PKT_DATA) { git_pkt_data *p = (git_pkt_data *) pkt; - *bytes += p->len; if (git_indexer_stream_add(idx, p->data, p->len, stats) < 0) goto on_error; diff --git a/src/fetch.h b/src/fetch.h index 23d0cf66f..5b8c20665 100644 --- a/src/fetch.h +++ b/src/fetch.h @@ -13,14 +13,12 @@ int git_fetch_negotiate(git_remote *remote); int git_fetch_download_pack( git_remote *remote, - git_off_t *bytes, git_transfer_progress_callback progress_cb, void *progress_payload); int git_fetch__download_pack( git_transport *t, git_repository *repo, - git_off_t *bytes, git_transfer_progress *stats, git_transfer_progress_callback progress_cb, void *progress_payload); diff --git a/src/remote.c b/src/remote.c index 3e9a757a5..87c1ad8aa 100644 --- a/src/remote.c +++ b/src/remote.c @@ -435,18 +435,17 @@ int git_remote_ls(git_remote *remote, git_headlist_cb list_cb, void *payload) int git_remote_download( git_remote *remote, - git_off_t *bytes, git_transfer_progress_callback progress_cb, void *progress_payload) { int error; - assert(remote && bytes); + assert(remote); if ((error = git_fetch_negotiate(remote)) < 0) return error; - return git_fetch_download_pack(remote, bytes, progress_cb, progress_payload); + return git_fetch_download_pack(remote, progress_cb, progress_payload); } int git_remote_update_tips(git_remote *remote) diff --git a/src/transport.h b/src/transport.h index 79afae000..1a3eee57d 100644 --- a/src/transport.h +++ b/src/transport.h @@ -113,7 +113,7 @@ struct git_transport { /** * Download the packfile */ - int (*download_pack)(struct git_transport *transport, git_repository *repo, git_off_t *bytes, git_transfer_progress *stats); + int (*download_pack)(struct git_transport *transport, git_repository *repo, git_transfer_progress *stats); /** * Close the connection */ diff --git a/tests-clar/network/fetch.c b/tests-clar/network/fetch.c index c3fb15eb9..74e062884 100644 --- a/tests-clar/network/fetch.c +++ b/tests-clar/network/fetch.c @@ -38,7 +38,6 @@ static void progress(const git_transfer_progress *stats, void *payload) static void do_fetch(const char *url, int flag, int n) { git_remote *remote; - git_off_t bytes; git_remote_callbacks callbacks; bool progress_was_called = false; @@ -50,7 +49,7 @@ static void do_fetch(const char *url, int flag, int n) git_remote_set_callbacks(remote, &callbacks); git_remote_set_autotag(remote, flag); cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH)); - cl_git_pass(git_remote_download(remote, &bytes, progress, &progress_was_called)); + cl_git_pass(git_remote_download(remote, progress, &progress_was_called)); git_remote_disconnect(remote); cl_git_pass(git_remote_update_tips(remote)); cl_assert_equal_i(counter, n);