Skip to content

Commit 4d87b38

Browse files
committed
Merge branch 'nd/status-refresh-progress'
"git status" learns to show progress bar when refreshing the index takes a long time. * nd/status-refresh-progress: status: show progress bar if refreshing the index takes too long
2 parents e27bfaa + ae9af12 commit 4d87b38

File tree

6 files changed

+72
-11
lines changed

6 files changed

+72
-11
lines changed

builtin/am.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2328,7 +2328,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
23282328
/* Ensure a valid committer ident can be constructed */
23292329
git_committer_info(IDENT_STRICT);
23302330

2331-
if (read_index_preload(&the_index, NULL) < 0)
2331+
if (read_index_preload(&the_index, NULL, 0) < 0)
23322332
die(_("failed to read the index"));
23332333

23342334
if (in_progress) {

builtin/commit.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
12991299
static int no_renames = -1;
13001300
static const char *rename_score_arg = (const char *)-1;
13011301
static struct wt_status s;
1302+
unsigned int progress_flag = 0;
13021303
int fd;
13031304
struct object_id oid;
13041305
static struct option builtin_status_options[] = {
@@ -1359,8 +1360,13 @@ int cmd_status(int argc, const char **argv, const char *prefix)
13591360
PATHSPEC_PREFER_FULL,
13601361
prefix, argv);
13611362

1362-
read_cache_preload(&s.pathspec);
1363-
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &s.pathspec, NULL, NULL);
1363+
if (status_format != STATUS_FORMAT_PORCELAIN &&
1364+
status_format != STATUS_FORMAT_PORCELAIN_V2)
1365+
progress_flag = REFRESH_PROGRESS;
1366+
read_index_preload(&the_index, &s.pathspec, progress_flag);
1367+
refresh_index(&the_index,
1368+
REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
1369+
&s.pathspec, NULL, NULL);
13641370

13651371
if (use_optional_locks())
13661372
fd = hold_locked_index(&index_lock, 0);

cache.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ void validate_cache_entries(const struct index_state *istate);
410410

411411
#define read_cache() read_index(&the_index)
412412
#define read_cache_from(path) read_index_from(&the_index, (path), (get_git_dir()))
413-
#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec))
413+
#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec), 0)
414414
#define is_cache_unborn() is_index_unborn(&the_index)
415415
#define read_cache_unmerged() read_index_unmerged(&the_index)
416416
#define discard_cache() discard_index(&the_index)
@@ -659,7 +659,9 @@ extern int daemonize(void);
659659
/* Initialize and use the cache information */
660660
struct lock_file;
661661
extern int read_index(struct index_state *);
662-
extern int read_index_preload(struct index_state *, const struct pathspec *pathspec);
662+
extern int read_index_preload(struct index_state *,
663+
const struct pathspec *pathspec,
664+
unsigned int refresh_flags);
663665
extern int do_read_index(struct index_state *istate, const char *path,
664666
int must_exist); /* for testting only! */
665667
extern int read_index_from(struct index_state *, const char *path,
@@ -814,6 +816,7 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
814816
#define REFRESH_IGNORE_MISSING 0x0008 /* ignore non-existent */
815817
#define REFRESH_IGNORE_SUBMODULES 0x0010 /* ignore submodules */
816818
#define REFRESH_IN_PORCELAIN 0x0020 /* user friendly output, not "needs update" */
819+
#define REFRESH_PROGRESS 0x0040 /* show progress bar if stderr is tty */
817820
extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
818821
extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
819822

preload-index.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
#include "dir.h"
77
#include "fsmonitor.h"
88
#include "config.h"
9+
#include "progress.h"
910

1011
#ifdef NO_PTHREADS
1112
static void preload_index(struct index_state *index,
12-
const struct pathspec *pathspec)
13+
const struct pathspec *pathspec,
14+
unsigned int refresh_flags)
1315
{
1416
; /* nothing */
1517
}
@@ -26,16 +28,23 @@ static void preload_index(struct index_state *index,
2628
#define MAX_PARALLEL (20)
2729
#define THREAD_COST (500)
2830

31+
struct progress_data {
32+
unsigned long n;
33+
struct progress *progress;
34+
pthread_mutex_t mutex;
35+
};
36+
2937
struct thread_data {
3038
pthread_t pthread;
3139
struct index_state *index;
3240
struct pathspec pathspec;
41+
struct progress_data *progress;
3342
int offset, nr;
3443
};
3544

3645
static void *preload_thread(void *_data)
3746
{
38-
int nr;
47+
int nr, last_nr;
3948
struct thread_data *p = _data;
4049
struct index_state *index = p->index;
4150
struct cache_entry **cep = index->cache + p->offset;
@@ -44,6 +53,7 @@ static void *preload_thread(void *_data)
4453
nr = p->nr;
4554
if (nr + p->offset > index->cache_nr)
4655
nr = index->cache_nr - p->offset;
56+
last_nr = nr;
4757

4858
do {
4959
struct cache_entry *ce = *cep++;
@@ -59,6 +69,15 @@ static void *preload_thread(void *_data)
5969
continue;
6070
if (ce->ce_flags & CE_FSMONITOR_VALID)
6171
continue;
72+
if (p->progress && !(nr & 31)) {
73+
struct progress_data *pd = p->progress;
74+
75+
pthread_mutex_lock(&pd->mutex);
76+
pd->n += last_nr - nr;
77+
display_progress(pd->progress, pd->n);
78+
pthread_mutex_unlock(&pd->mutex);
79+
last_nr = nr;
80+
}
6281
if (!ce_path_match(index, ce, &p->pathspec, NULL))
6382
continue;
6483
if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
@@ -70,15 +89,24 @@ static void *preload_thread(void *_data)
7089
ce_mark_uptodate(ce);
7190
mark_fsmonitor_valid(ce);
7291
} while (--nr > 0);
92+
if (p->progress) {
93+
struct progress_data *pd = p->progress;
94+
95+
pthread_mutex_lock(&pd->mutex);
96+
display_progress(pd->progress, pd->n + last_nr);
97+
pthread_mutex_unlock(&pd->mutex);
98+
}
7399
cache_def_clear(&cache);
74100
return NULL;
75101
}
76102

77103
static void preload_index(struct index_state *index,
78-
const struct pathspec *pathspec)
104+
const struct pathspec *pathspec,
105+
unsigned int refresh_flags)
79106
{
80107
int threads, i, work, offset;
81108
struct thread_data data[MAX_PARALLEL];
109+
struct progress_data pd;
82110

83111
if (!core_preload_index)
84112
return;
@@ -94,13 +122,22 @@ static void preload_index(struct index_state *index,
94122
offset = 0;
95123
work = DIV_ROUND_UP(index->cache_nr, threads);
96124
memset(&data, 0, sizeof(data));
125+
126+
memset(&pd, 0, sizeof(pd));
127+
if (refresh_flags & REFRESH_PROGRESS && isatty(2)) {
128+
pd.progress = start_delayed_progress(_("Refreshing index"), index->cache_nr);
129+
pthread_mutex_init(&pd.mutex, NULL);
130+
}
131+
97132
for (i = 0; i < threads; i++) {
98133
struct thread_data *p = data+i;
99134
p->index = index;
100135
if (pathspec)
101136
copy_pathspec(&p->pathspec, pathspec);
102137
p->offset = offset;
103138
p->nr = work;
139+
if (pd.progress)
140+
p->progress = &pd;
104141
offset += work;
105142
if (pthread_create(&p->pthread, NULL, preload_thread, p))
106143
die("unable to create threaded lstat");
@@ -110,15 +147,18 @@ static void preload_index(struct index_state *index,
110147
if (pthread_join(p->pthread, NULL))
111148
die("unable to join threaded lstat");
112149
}
150+
stop_progress(&pd.progress);
151+
113152
trace_performance_leave("preload index");
114153
}
115154
#endif
116155

117156
int read_index_preload(struct index_state *index,
118-
const struct pathspec *pathspec)
157+
const struct pathspec *pathspec,
158+
unsigned int refresh_flags)
119159
{
120160
int retval = read_index(index);
121161

122-
preload_index(index, pathspec);
162+
preload_index(index, pathspec, refresh_flags);
123163
return retval;
124164
}

read-cache.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "utf8.h"
2525
#include "fsmonitor.h"
2626
#include "thread-utils.h"
27+
#include "progress.h"
2728

2829
/* Mask for the name length in ce_flags in the on-disk index */
2930

@@ -1483,6 +1484,11 @@ int refresh_index(struct index_state *istate, unsigned int flags,
14831484
const char *typechange_fmt;
14841485
const char *added_fmt;
14851486
const char *unmerged_fmt;
1487+
struct progress *progress = NULL;
1488+
1489+
if (flags & REFRESH_PROGRESS && isatty(2))
1490+
progress = start_delayed_progress(_("Refresh index"),
1491+
istate->cache_nr);
14861492

14871493
trace_performance_enter();
14881494
modified_fmt = (in_porcelain ? "M\t%s\n" : "%s: needs update\n");
@@ -1523,6 +1529,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
15231529
new_entry = refresh_cache_ent(istate, ce, options, &cache_errno, &changed);
15241530
if (new_entry == ce)
15251531
continue;
1532+
if (progress)
1533+
display_progress(progress, i);
15261534
if (!new_entry) {
15271535
const char *fmt;
15281536

@@ -1554,6 +1562,10 @@ int refresh_index(struct index_state *istate, unsigned int flags,
15541562

15551563
replace_index_entry(istate, i, new_entry);
15561564
}
1565+
if (progress) {
1566+
display_progress(progress, istate->cache_nr);
1567+
stop_progress(&progress);
1568+
}
15571569
trace_performance_leave("refresh index");
15581570
return has_errors;
15591571
}

sequencer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1913,7 +1913,7 @@ static int read_and_refresh_cache(struct replay_opts *opts)
19131913
{
19141914
struct lock_file index_lock = LOCK_INIT;
19151915
int index_fd = hold_locked_index(&index_lock, 0);
1916-
if (read_index_preload(&the_index, NULL) < 0) {
1916+
if (read_index_preload(&the_index, NULL, 0) < 0) {
19171917
rollback_lock_file(&index_lock);
19181918
return error(_("git %s: failed to read the index"),
19191919
_(action_name(opts)));

0 commit comments

Comments
 (0)