From: "Shawn O. Pearce" <spearce@spearce•org>
To: Junio C Hamano <junkio@cox•net>
Cc: git@vger•kernel.org
Subject: [PATCH 4/4] Display a progress meter during merge-recursive.
Date: Sun, 14 Jan 2007 00:28:58 -0500 [thread overview]
Message-ID: <20070114052858.GD19113@spearce.org> (raw)
In-Reply-To: <d352c8adb1ec1c4e74b33d51d397d5756b82ceac.1168752482.git.spearce@spearce.org>
Because large merges on slow systems can take up to a minute to
execute we should try to keep the user entertained with a progress
meter to let them know how far we have progressed through the
current merge.
The progress meter considers each entry in the in-memory index to
be a unit, which means a single recursive merge will double the
number of units in the progress meter. Files which are unmerged
after the 3-way tree merge are also considered a unit within the
progress meter.
Signed-off-by: Shawn O. Pearce <spearce@spearce•org>
---
merge-recursive.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index c16062b..c4e21bc 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -79,6 +79,11 @@ static struct path_list current_directory_set = {NULL, 0, 0, 1};
static int call_depth = 0;
static int verbosity = 2;
static int buffer_output = 1;
+static int do_progress = 1;
+static unsigned last_percent;
+static unsigned merged_cnt;
+static unsigned total_cnt;
+static volatile sig_atomic_t progress_update;
static struct output_buffer *output_list, *output_end;
static int show (int v)
@@ -153,6 +158,39 @@ static void output_commit_title(struct commit *commit)
}
}
+static void progress_interval(int signum)
+{
+ progress_update = 1;
+}
+
+static void setup_progress_signal(void)
+{
+ struct sigaction sa;
+ struct itimerval v;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = progress_interval;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sigaction(SIGALRM, &sa, NULL);
+
+ v.it_interval.tv_sec = 1;
+ v.it_interval.tv_usec = 0;
+ v.it_value = v.it_interval;
+ setitimer(ITIMER_REAL, &v, NULL);
+}
+
+static void display_progress()
+{
+ unsigned percent = merged_cnt * 100 / total_cnt;
+ if (progress_update || percent != last_percent) {
+ fprintf(stderr, "%4u%% (%u/%u) done\r",
+ percent, merged_cnt, total_cnt);
+ progress_update = 0;
+ last_percent = percent;
+ }
+}
+
static struct cache_entry *make_cache_entry(unsigned int mode,
const unsigned char *sha1, const char *path, int stage, int refresh)
{
@@ -315,11 +353,14 @@ static struct path_list *get_unmerged(void)
int i;
unmerged->strdup_paths = 1;
+ total_cnt += active_nr;
- for (i = 0; i < active_nr; i++) {
+ for (i = 0; i < active_nr; i++, merged_cnt++) {
struct path_list_item *item;
struct stage_data *e;
struct cache_entry *ce = active_cache[i];
+ if (do_progress)
+ display_progress();
if (!ce_stage(ce))
continue;
@@ -1096,13 +1137,15 @@ static int merge_trees(struct tree *head,
re_merge = get_renames(merge, common, head, merge, entries);
clean = process_renames(re_head, re_merge,
branch1, branch2);
- for (i = 0; i < entries->nr; i++) {
+ total_cnt += entries->nr;
+ for (i = 0; i < entries->nr; i++, merged_cnt++) {
const char *path = entries->items[i].path;
struct stage_data *e = entries->items[i].util;
- if (e->processed)
- continue;
- if (!process_entry(path, e, branch1, branch2))
+ if (!e->processed
+ && !process_entry(path, e, branch1, branch2))
clean = 0;
+ if (do_progress)
+ display_progress();
}
path_list_clear(re_merge, 0);
@@ -1210,6 +1253,12 @@ static int merge(struct commit *h1,
commit_list_insert(h1, &(*result)->parents);
commit_list_insert(h2, &(*result)->parents->next);
}
+ if (!call_depth && do_progress) {
+ merged_cnt = total_cnt;
+ progress_update = 1;
+ display_progress();
+ fputc('\n', stderr);
+ }
flush_output();
return clean;
}
@@ -1279,6 +1328,10 @@ int main(int argc, char *argv[])
}
if (argc - i != 3) /* "--" "<head>" "<remote>" */
die("Not handling anything other than two heads merge.");
+ if (verbosity >= 5) {
+ buffer_output = 0;
+ do_progress = 0;
+ }
branch1 = argv[++i];
branch2 = argv[++i];
@@ -1288,8 +1341,12 @@ int main(int argc, char *argv[])
branch1 = better_branch_name(branch1);
branch2 = better_branch_name(branch2);
- if (verbosity >= 5)
+ if (verbosity >= 5) {
buffer_output = 0;
+ do_progress = 0;
+ }
+ if (do_progress)
+ setup_progress_signal();
if (show(3))
printf("Merging %s with %s\n", branch1, branch2);
--
1.5.0.rc1.g4494
next prev parent reply other threads:[~2007-01-14 5:29 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <d352c8adb1ec1c4e74b33d51d397d5756b82ceac.1168752482.git.spearce@spearce.org>
2007-01-14 5:28 ` [PATCH 2/4] Allow the user to control the verbosity of merge-recursive Shawn O. Pearce
2007-01-14 5:28 ` [PATCH 3/4] Enable output buffering in merge-recursive Shawn O. Pearce
2007-01-14 5:28 ` Shawn O. Pearce [this message]
2007-01-14 13:04 ` [PATCH 4/4] Display a progress meter during merge-recursive Johannes Schindelin
2007-01-14 19:11 ` Junio C Hamano
2007-01-14 22:50 ` Shawn O. Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070114052858.GD19113@spearce.org \
--to=spearce@spearce$(echo .)org \
--cc=git@vger$(echo .)kernel.org \
--cc=junkio@cox$(echo .)net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox