Skip to content

Commit 930c8c8

Browse files
committed
built-in add -i: implement the update command
After `status` and `help`, it is now turn to port the `update` command to C, the second command that is shown in the main loop menu of `git add -i`. This `git add -i` command is the first one which lets the user choose a subset of a list of files, and as such, this patch lays the groundwork for the other commands of that category: - It teaches the `print_file_item()` function to show a unique prefix if we found any (the code to find it had been added already in the previous patch where we colored the unique prefixes of the main loop commands, but that patch uses the `print_command_item()` function to display the menu items). - This patch also adds the help text that is shown when the user input to select items from the shown list could not be parsed. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent fb05850 commit 930c8c8

File tree

1 file changed

+112
-12
lines changed

1 file changed

+112
-12
lines changed

add-interactive.c

Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "revision.h"
77
#include "refs.h"
88
#include "prefix-map.h"
9+
#include "lockfile.h"
910

1011
struct add_i_state {
1112
struct repository *r;
@@ -459,30 +460,43 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
459460
}
460461

461462
struct print_file_item_data {
462-
const char *modified_fmt;
463-
struct strbuf buf, index, worktree;
463+
const char *modified_fmt, *color, *reset;
464+
struct strbuf buf, name, index, worktree;
464465
};
465466

466467
static void print_file_item(int i, int selected, struct prefix_item *item,
467468
void *print_file_item_data)
468469
{
469470
struct file_item *c = (struct file_item *)item;
470471
struct print_file_item_data *d = print_file_item_data;
472+
const char *highlighted = NULL;
471473

472474
strbuf_reset(&d->index);
473475
strbuf_reset(&d->worktree);
474476
strbuf_reset(&d->buf);
475477

478+
/* Format the item with the prefix highlighted. */
479+
if (item->prefix_length > 0 &&
480+
is_valid_prefix(item->name, item->prefix_length)) {
481+
strbuf_reset(&d->name);
482+
strbuf_addf(&d->name, "%s%.*s%s%s", d->color,
483+
(int)item->prefix_length, item->name, d->reset,
484+
item->name + item->prefix_length);
485+
highlighted = d->name.buf;
486+
}
487+
476488
populate_wi_changes(&d->worktree, &c->worktree, _("nothing"));
477489
populate_wi_changes(&d->index, &c->index, _("unchanged"));
478490
strbuf_addf(&d->buf, d->modified_fmt,
479-
d->index.buf, d->worktree.buf, item->name);
491+
d->index.buf, d->worktree.buf,
492+
highlighted ? highlighted : item->name);
480493

481494
printf("%c%2d: %s", selected ? '*' : ' ', i + 1, d->buf.buf);
482495
}
483496

484497
static int run_status(struct add_i_state *s, const struct pathspec *ps,
485-
struct file_list *files, struct list_options *opts)
498+
struct file_list *files,
499+
struct list_and_choose_options *opts)
486500
{
487501
reset_file_list(files);
488502

@@ -491,14 +505,72 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
491505

492506
if (files->nr)
493507
list((struct prefix_item **)files->file, NULL, files->nr,
494-
s, opts);
508+
s, &opts->list_opts);
495509
putchar('\n');
496510

497511
return 0;
498512
}
499513

514+
static int run_update(struct add_i_state *s, const struct pathspec *ps,
515+
struct file_list *files,
516+
struct list_and_choose_options *opts)
517+
{
518+
int res = 0, fd, *selected = NULL;
519+
size_t count, i;
520+
struct lock_file index_lock;
521+
522+
reset_file_list(files);
523+
524+
if (get_modified_files(s->r, WORKTREE_ONLY, files, ps) < 0)
525+
return -1;
526+
527+
if (!files->nr) {
528+
putchar('\n');
529+
return 0;
530+
}
531+
532+
opts->prompt = N_("Update");
533+
CALLOC_ARRAY(selected, files->nr);
534+
535+
count = list_and_choose((struct prefix_item **)files->file,
536+
selected, files->nr, s, opts);
537+
if (count <= 0) {
538+
putchar('\n');
539+
free(selected);
540+
return 0;
541+
}
542+
543+
fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
544+
if (fd < 0) {
545+
putchar('\n');
546+
free(selected);
547+
return -1;
548+
}
549+
550+
for (i = 0; i < files->nr; i++) {
551+
const char *name = files->file[i]->item.name;
552+
if (selected[i] &&
553+
add_file_to_index(s->r->index, name, 0) < 0) {
554+
res = error(_("could not stage '%s'"), name);
555+
break;
556+
}
557+
}
558+
559+
if (!res && write_locked_index(s->r->index, &index_lock, COMMIT_LOCK) < 0)
560+
res = error(_("could not write index"));
561+
562+
if (!res)
563+
printf(Q_("updated %d path\n",
564+
"updated %d paths\n", count), (int)count);
565+
566+
putchar('\n');
567+
free(selected);
568+
return res;
569+
}
570+
500571
static int run_help(struct add_i_state *s, const struct pathspec *ps,
501-
struct file_list *files, struct list_options *opts)
572+
struct file_list *files,
573+
struct list_and_choose_options *opts)
502574
{
503575
const char *help_color = s->help_color;
504576

@@ -518,6 +590,27 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps,
518590
return 0;
519591
}
520592

593+
static void choose_prompt_help(struct add_i_state *s)
594+
{
595+
const char *help_color = s->help_color;
596+
color_fprintf_ln(stdout, help_color, "%s",
597+
_("Prompt help:"));
598+
color_fprintf_ln(stdout, help_color, "1 - %s",
599+
_("select a single item"));
600+
color_fprintf_ln(stdout, help_color, "3-5 - %s",
601+
_("select a range of items"));
602+
color_fprintf_ln(stdout, help_color, "2-3,6-9 - %s",
603+
_("select multiple ranges"));
604+
color_fprintf_ln(stdout, help_color, "foo - %s",
605+
_("select item based on unique prefix"));
606+
color_fprintf_ln(stdout, help_color, "-... - %s",
607+
_("unselect specified items"));
608+
color_fprintf_ln(stdout, help_color, "* - %s",
609+
_("choose all items"));
610+
color_fprintf_ln(stdout, help_color, " - %s",
611+
_("(empty) finish selecting"));
612+
}
613+
521614
struct print_command_item_data {
522615
const char *color, *reset;
523616
};
@@ -539,7 +632,8 @@ static void print_command_item(int i, int selected, struct prefix_item *item,
539632
struct command_item {
540633
struct prefix_item item;
541634
int (*command)(struct add_i_state *s, const struct pathspec *ps,
542-
struct file_list *files, struct list_options *opts);
635+
struct file_list *files,
636+
struct list_and_choose_options *opts);
543637
};
544638

545639
static void command_prompt_help(struct add_i_state *s)
@@ -564,17 +658,20 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
564658
};
565659
struct command_item
566660
status = { { "status" }, run_status },
661+
update = { { "update" }, run_update },
567662
help = { { "help" }, run_help };
568663
struct command_item *commands[] = {
569-
&status,
664+
&status, &update,
570665
&help
571666
};
572667

573668
struct print_file_item_data print_file_item_data = {
574-
"%12s %12s %s", STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
669+
"%12s %12s %s", NULL, NULL,
670+
STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
575671
};
576-
struct list_options opts = {
577-
0, NULL, print_file_item, &print_file_item_data
672+
struct list_and_choose_options opts = {
673+
{ 0, NULL, print_file_item, &print_file_item_data },
674+
NULL, 0, choose_prompt_help
578675
};
579676
struct strbuf header = STRBUF_INIT;
580677
struct file_list files = { NULL };
@@ -595,11 +692,13 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
595692
data.color = "[";
596693
data.reset = "]";
597694
}
695+
print_file_item_data.color = data.color;
696+
print_file_item_data.reset = data.reset;
598697

599698
strbuf_addstr(&header, " ");
600699
strbuf_addf(&header, print_file_item_data.modified_fmt,
601700
_("staged"), _("unstaged"), _("path"));
602-
opts.header = header.buf;
701+
opts.list_opts.header = header.buf;
603702

604703
repo_refresh_and_write_index(r, REFRESH_QUIET, 1);
605704
if (run_status(&s, ps, &files, &opts) < 0)
@@ -619,6 +718,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
619718

620719
release_file_list(&files);
621720
strbuf_release(&print_file_item_data.buf);
721+
strbuf_release(&print_file_item_data.name);
622722
strbuf_release(&print_file_item_data.index);
623723
strbuf_release(&print_file_item_data.worktree);
624724
strbuf_release(&header);

0 commit comments

Comments
 (0)