Skip to content

Commit e65167d

Browse files
committed
built-in add -i: allow filtering the modified files list
In `update` command of `git add -i`, we are primarily interested in the list of modified files that have worktree (i.e. unstaged) changes. The Perl script version of `git add -i` has a parameter of the `list_modified()` function for that matter. In C, we can be a lot more precise, using an `enum`. The C implementation of the filter also has an easier time to avoid unnecessary work, simply by using an adaptive order of the `diff-index` and `diff-files` calls, and then not adding unnecessary entries in the first place. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent ddb913e commit e65167d

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

add-interactive.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ struct collection_status {
262262

263263
const char *reference;
264264

265+
unsigned skip_unseen:1;
265266
struct file_list *list;
266267
struct hashmap file_map;
267268
};
@@ -290,6 +291,8 @@ static void collect_changes_cb(struct diff_queue_struct *q,
290291
entry = hashmap_get_from_hash(&s->file_map, hash, name);
291292
if (entry)
292293
file_index = entry->index;
294+
else if (s->skip_unseen)
295+
continue;
293296
else {
294297
FLEX_ALLOC_STR(entry, pathname, name);
295298
hashmap_entry_init(entry, hash);
@@ -309,24 +312,39 @@ static void collect_changes_cb(struct diff_queue_struct *q,
309312
}
310313
}
311314

312-
static int get_modified_files(struct repository *r, struct file_list *list,
315+
enum modified_files_filter {
316+
NO_FILTER = 0,
317+
WORKTREE_ONLY = 1,
318+
INDEX_ONLY = 2,
319+
};
320+
321+
static int get_modified_files(struct repository *r,
322+
enum modified_files_filter filter,
323+
struct file_list *list,
313324
const struct pathspec *ps)
314325
{
315326
struct object_id head_oid;
316327
int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
317328
&head_oid, NULL);
318329
struct collection_status s = { FROM_WORKTREE };
330+
int i;
319331

320332
if (repo_read_index_preload(r, ps, 0) < 0)
321333
return error(_("could not read index"));
322334

323335
s.list = list;
324336
hashmap_init(&s.file_map, pathname_entry_cmp, NULL, 0);
325337

326-
for (s.phase = FROM_WORKTREE; s.phase <= FROM_INDEX; s.phase++) {
338+
for (i = 0; i < 2; i++) {
327339
struct rev_info rev;
328340
struct setup_revision_opt opt = { 0 };
329341

342+
if (filter == INDEX_ONLY)
343+
s.phase = i ? FROM_WORKTREE : FROM_INDEX;
344+
else
345+
s.phase = i ? FROM_INDEX : FROM_WORKTREE;
346+
s.skip_unseen = filter && i;
347+
330348
opt.def = is_initial ?
331349
empty_tree_oid_hex() : oid_to_hex(&head_oid);
332350

@@ -412,7 +430,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
412430
{
413431
reset_file_list(files);
414432

415-
if (get_modified_files(s->r, files, ps) < 0)
433+
if (get_modified_files(s->r, 0, files, ps) < 0)
416434
return -1;
417435

418436
if (files->nr)

0 commit comments

Comments
 (0)