6
#include "revision.h"
7
#include "refs.h"
8
#include "string-list.h"
9
+#include "lockfile.h"
10
11
struct add_i_state {
12
struct repository *r;
378
};
379
380
struct file_item {
381
+ size_t prefix_length;
382
struct adddel index, worktree;
383
};
384
473
474
static int get_modified_files(struct repository *r,
475
enum modified_files_filter filter,
474
- struct string_list *files,
476
+ struct prefix_item_list *files,
477
const struct pathspec *ps)
478
{
479
struct object_id head_oid;
486
repo_read_index_preload(r, ps, 0) < 0)
487
return error(_("could not read index"));
488
487
- string_list_clear(files, 1);
488
- s.files = files;
489
+ prefix_item_list_clear(files);
490
+ s.files = &files->items;
491
hashmap_init(&s.file_map, pathname_entry_cmp, NULL, 0);
492
493
for (i = 0; i < 2; i++) {
526
hashmap_free_entries(&s.file_map, struct pathname_entry, ent);
527
528
/* While the diffs are ordered already, we ran *two* diffs... */
527
- string_list_sort(files);
529
+ string_list_sort(&files->items);
530
531
return 0;
532
}
561
}
562
563
struct print_file_item_data {
562
- const char *modified_fmt;
563
- struct strbuf buf, index, worktree;
564
+ const char *modified_fmt, *color, *reset;
565
+ struct strbuf buf, name, index, worktree;
566
};
567
568
static void print_file_item(int i, int selected, struct string_list_item *item,
570
{
571
struct file_item *c = item->util;
572
struct print_file_item_data *d = print_file_item_data;
573
+ const char *highlighted = NULL;
574
575
strbuf_reset(&d->index);
576
strbuf_reset(&d->worktree);
577
strbuf_reset(&d->buf);
578
579
+ /* Format the item with the prefix highlighted. */
580
+ if (c->prefix_length > 0 &&
581
+ is_valid_prefix(item->string, c->prefix_length)) {
582
+ strbuf_reset(&d->name);
583
+ strbuf_addf(&d->name, "%s%.*s%s%s", d->color,
584
+ (int)c->prefix_length, item->string, d->reset,
585
+ item->string + c->prefix_length);
586
+ highlighted = d->name.buf;
587
+ }
588
+
589
render_adddel(&d->worktree, &c->worktree, _("nothing"));
590
render_adddel(&d->index, &c->index, _("unchanged"));
578
- strbuf_addf(&d->buf, d->modified_fmt,
579
- d->index.buf, d->worktree.buf, item->string);
591
+
592
+ strbuf_addf(&d->buf, d->modified_fmt, d->index.buf, d->worktree.buf,
593
+ highlighted ? highlighted : item->string);
594
595
printf("%c%2d: %s", selected ? '*' : ' ', i + 1, d->buf.buf);
596
}
597
598
static int run_status(struct add_i_state *s, const struct pathspec *ps,
585
- struct string_list *files, struct list_options *opts)
599
+ struct prefix_item_list *files,
600
+ struct list_and_choose_options *opts)
601
{
602
if (get_modified_files(s->r, NO_FILTER, files, ps) < 0)
603
return -1;
604
590
- list(s, files, NULL, opts);
605
+ list(s, &files->items, NULL, &opts->list_opts);
606
putchar('\n');
607
608
return 0;
609
}
610
611
+static int run_update(struct add_i_state *s, const struct pathspec *ps,
612
+ struct prefix_item_list *files,
613
+ struct list_and_choose_options *opts)
614
+{
615
+ int res = 0, fd;
616
+ size_t count, i;
617
+ struct lock_file index_lock;
618
+
619
+ if (get_modified_files(s->r, WORKTREE_ONLY, files, ps) < 0)
620
+ return -1;
621
+
622
+ if (!files->items.nr) {
623
+ putchar('\n');
624
+ return 0;
625
+ }
626
+
627
+ opts->prompt = N_("Update");
628
+ count = list_and_choose(s, files, opts);
629
+ if (count <= 0) {
630
+ putchar('\n');
631
+ return 0;
632
+ }
633
+
634
+ fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
635
+ if (fd < 0) {
636
+ putchar('\n');
637
+ return -1;
638
+ }
639
+
640
+ for (i = 0; i < files->items.nr; i++) {
641
+ const char *name = files->items.items[i].string;
642
+ if (files->selected[i] &&
643
+ add_file_to_index(s->r->index, name, 0) < 0) {
644
+ res = error(_("could not stage '%s'"), name);
645
+ break;
646
+ }
647
+ }
648
+
649
+ if (!res && write_locked_index(s->r->index, &index_lock, COMMIT_LOCK) < 0)
650
+ res = error(_("could not write index"));
651
+
652
+ if (!res)
653
+ printf(Q_("updated %d path\n",
654
+ "updated %d paths\n", count), (int)count);
655
+
656
+ putchar('\n');
657
+ return res;
658
+}
659
+
660
static int run_help(struct add_i_state *s, const struct pathspec *unused_ps,
597
- struct string_list *unused_files,
598
- struct list_options *unused_opts)
661
+ struct prefix_item_list *unused_files,
662
+ struct list_and_choose_options *unused_opts)
663
{
664
color_fprintf_ln(stdout, s->help_color, "status - %s",
665
_("show paths with changes"));
677
return 0;
678
}
679
680
+static void choose_prompt_help(struct add_i_state *s)
681
+{
682
+ color_fprintf_ln(stdout, s->help_color, "%s",
683
+ _("Prompt help:"));
684
+ color_fprintf_ln(stdout, s->help_color, "1 - %s",
685
+ _("select a single item"));
686
+ color_fprintf_ln(stdout, s->help_color, "3-5 - %s",
687
+ _("select a range of items"));
688
+ color_fprintf_ln(stdout, s->help_color, "2-3,6-9 - %s",
689
+ _("select multiple ranges"));
690
+ color_fprintf_ln(stdout, s->help_color, "foo - %s",
691
+ _("select item based on unique prefix"));
692
+ color_fprintf_ln(stdout, s->help_color, "-... - %s",
693
+ _("unselect specified items"));
694
+ color_fprintf_ln(stdout, s->help_color, "* - %s",
695
+ _("choose all items"));
696
+ color_fprintf_ln(stdout, s->help_color, " - %s",
697
+ _("(empty) finish selecting"));
698
+}
699
+
700
typedef int (*command_t)(struct add_i_state *s, const struct pathspec *ps,
617
- struct string_list *files,
618
- struct list_options *opts);
701
+ struct prefix_item_list *files,
702
+ struct list_and_choose_options *opts);
703
704
struct command_item {
705
size_t prefix_length;
751
command_t command;
752
} command_list[] = {
753
{ "status", run_status },
754
+ { "update", run_update },
755
{ "help", run_help },
756
};
757
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT;
758
759
struct print_file_item_data print_file_item_data = {
675
- "%12s %12s %s", STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
760
+ "%12s %12s %s", NULL, NULL,
761
+ STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
762
};
677
- struct list_options opts = {
678
- 0, NULL, print_file_item, &print_file_item_data
763
+ struct list_and_choose_options opts = {
764
+ { 0, NULL, print_file_item, &print_file_item_data },
765
+ NULL, 0, choose_prompt_help
766
};
767
struct strbuf header = STRBUF_INIT;
681
- struct string_list files = STRING_LIST_INIT_DUP;
768
+ struct prefix_item_list files = PREFIX_ITEM_LIST_INIT;
769
ssize_t i;
770
int res = 0;
771
786
data.color = s.prompt_color;
787
data.reset = s.reset_color;
788
}
789
+ print_file_item_data.color = data.color;
790
+ print_file_item_data.reset = data.reset;
791
792
strbuf_addstr(&header, " ");
793
strbuf_addf(&header, print_file_item_data.modified_fmt,
794
_("staged"), _("unstaged"), _("path"));
706
- opts.header = header.buf;
795
+ opts.list_opts.header = header.buf;
796
797
if (discard_index(r->index) < 0 ||
798
repo_read_index(r) < 0 ||
816
}
817
}
818
730
- string_list_clear(&files, 1);
819
+ prefix_item_list_clear(&files);
820
strbuf_release(&print_file_item_data.buf);
821
+ strbuf_release(&print_file_item_data.name);
822
strbuf_release(&print_file_item_data.index);
823
strbuf_release(&print_file_item_data.worktree);
824
strbuf_release(&header);