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.org \
--cc=git@vger.kernel.org \
--cc=junkio@cox.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.