Commit 45b60d7b8db79da18cecfd667dc7051f31dc8fe6

Ben Straub 2012-10-18T15:17:12

Correct progress reporting from checkout

diff --git a/examples/network/clone.c b/examples/network/clone.c
index 39b3241..fd30bca 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 d9b3246..a20a6f9 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;