Skip to content

Commit 3df0c46

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 c6ba59e commit 3df0c46

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;
@@ -455,6 +457,7 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
455457
struct print_file_item_data {
456458
const char *modified_fmt, *color, *reset;
457459
struct strbuf buf, name, index, worktree;
460+
unsigned only_names:1;
458461
};
459462

460463
static void print_file_item(int i, int selected, struct prefix_item *item,
@@ -478,6 +481,12 @@ static void print_file_item(int i, int selected, struct prefix_item *item,
478481
highlighted = d->name.buf;
479482
}
480483

484+
if (d->only_names) {
485+
printf("%c%2d: %s", selected ? '*' : ' ', i + 1,
486+
highlighted ? highlighted : item->name);
487+
return;
488+
}
489+
481490
populate_wi_changes(&d->worktree, &c->worktree, _("nothing"));
482491
populate_wi_changes(&d->index, &c->index, _("unchanged"));
483492
strbuf_addf(&d->buf, d->modified_fmt,
@@ -672,6 +681,92 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
672681
return res;
673682
}
674683

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

0 commit comments

Comments
 (0)