Skip to content

Commit 4d8a4e6

Browse files
committed
built-in add -i: re-implement add-untracked in C
This is yet another command, ported to C. It builds nicely on the support functions introduced for other commands, with the notable difference that only names are displayed for untracked files, no file type or diff summary. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent b1c0a31 commit 4d8a4e6

File tree

1 file changed

+97
-1
lines changed

1 file changed

+97
-1
lines changed

add-interactive.c

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "refs.h"
88
#include "prefix-map.h"
99
#include "lockfile.h"
10+
#include "pathspec.h"
11+
#include "dir.h"
1012

1113
struct add_i_state {
1214
struct repository *r;
@@ -462,6 +464,7 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
462464
struct print_file_item_data {
463465
const char *modified_fmt, *color, *reset;
464466
struct strbuf buf, name, index, worktree;
467+
unsigned only_names:1;
465468
};
466469

467470
static void print_file_item(int i, int selected, struct prefix_item *item,
@@ -485,6 +488,12 @@ static void print_file_item(int i, int selected, struct prefix_item *item,
485488
highlighted = d->name.buf;
486489
}
487490

491+
if (d->only_names) {
492+
printf("%c%2d: %s", selected ? '*' : ' ', i + 1,
493+
highlighted ? highlighted : item->name);
494+
return;
495+
}
496+
488497
populate_wi_changes(&d->worktree, &c->worktree, _("nothing"));
489498
populate_wi_changes(&d->index, &c->index, _("unchanged"));
490499
strbuf_addf(&d->buf, d->modified_fmt,
@@ -679,6 +688,92 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
679688
return res;
680689
}
681690

691+
static int get_untracked_files(struct repository *r, struct file_list *list,
692+
const struct pathspec *ps)
693+
{
694+
struct dir_struct dir = { 0 };
695+
size_t i;
696+
697+
if (repo_read_index(r) < 0)
698+
return error(_("could not read index"));
699+
700+
setup_standard_excludes(&dir);
701+
add_exclude_list(&dir, EXC_CMDL, "--exclude option");
702+
fill_directory(&dir, r->index, ps);
703+
704+
for (i = 0; i < dir.nr; i++) {
705+
struct dir_entry *ent = dir.entries[i];
706+
707+
if (index_name_is_other(r->index, ent->name, ent->len)) {
708+
struct file_item *item;
709+
710+
FLEXPTR_ALLOC_MEM(item, item.name, ent->name, ent->len);
711+
712+
ALLOC_GROW(list->file, list->nr + 1, list->alloc);
713+
list->file[list->nr++] = item;
714+
}
715+
}
716+
717+
return 0;
718+
}
719+
720+
static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
721+
struct file_list *files,
722+
struct list_and_choose_options *opts)
723+
{
724+
struct print_file_item_data *d = opts->list_opts.print_item_data;
725+
int res = 0, fd, *selected = NULL;
726+
size_t count, i;
727+
728+
struct lock_file index_lock;
729+
730+
reset_file_list(files);
731+
if (get_untracked_files(s->r, files, ps) < 0)
732+
return -1;
733+
734+
if (!files->nr) {
735+
printf(_("No untracked files.\n"));
736+
goto finish_add_untracked;
737+
}
738+
739+
opts->prompt = N_("Add untracked");
740+
CALLOC_ARRAY(selected, files->nr);
741+
742+
d->only_names = 1;
743+
count = list_and_choose((struct prefix_item **)files->file,
744+
selected, files->nr, s, opts);
745+
d->only_names = 0;
746+
if (count <= 0)
747+
goto finish_add_untracked;
748+
749+
fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
750+
if (fd < 0) {
751+
res = -1;
752+
goto finish_add_untracked;
753+
}
754+
755+
for (i = 0; i < files->nr; i++) {
756+
const char *name = files->file[i]->item.name;
757+
if (selected[i] &&
758+
add_file_to_index(s->r->index, name, 0) < 0) {
759+
res = error(_("could not stage '%s'"), name);
760+
break;
761+
}
762+
}
763+
764+
if (!res && write_locked_index(s->r->index, &index_lock, COMMIT_LOCK) < 0)
765+
res = error(_("could not write index"));
766+
767+
if (!res)
768+
printf(Q_("added %d path\n",
769+
"added %d paths\n", count), (int)count);
770+
771+
finish_add_untracked:
772+
putchar('\n');
773+
free(selected);
774+
return res;
775+
}
776+
682777
static int run_help(struct add_i_state *s, const struct pathspec *ps,
683778
struct file_list *files,
684779
struct list_and_choose_options *opts)
@@ -771,9 +866,10 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
771866
status = { { "status" }, run_status },
772867
update = { { "update" }, run_update },
773868
revert = { { "revert" }, run_revert },
869+
add_untracked = { { "add untracked" }, run_add_untracked },
774870
help = { { "help" }, run_help };
775871
struct command_item *commands[] = {
776-
&status, &update, &revert,
872+
&status, &update, &revert, &add_untracked,
777873
&help
778874
};
779875

0 commit comments

Comments
 (0)