Commit 2c8bbb27d91ec35162522079d632608fcaac2a57

Ben Straub 2012-10-16T20:16:21

Convert checkout_index to use progress callback

diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index b4f9ad0..d0190c2 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 b56b459..222eb26 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 2151856..0039b14 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 dfa095b..3fcad7f 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 f017a0f..944d679 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);
 }