built-in add -p: handle diff.algorithm
[git] / add-interactive.c
1 #include "cache.h"
2 #include "add-interactive.h"
3 #include "color.h"
4 #include "config.h"
5 #include "diffcore.h"
6 #include "revision.h"
7 #include "refs.h"
8 #include "string-list.h"
9 #include "lockfile.h"
10 #include "dir.h"
11 #include "run-command.h"
12
13 static void init_color(struct repository *r, struct add_i_state *s,
14                        const char *slot_name, char *dst,
15                        const char *default_color)
16 {
17         char *key = xstrfmt("color.interactive.%s", slot_name);
18         const char *value;
19
20         if (!s->use_color)
21                 dst[0] = '\0';
22         else if (repo_config_get_value(r, key, &value) ||
23                  color_parse(value, dst))
24                 strlcpy(dst, default_color, COLOR_MAXLEN);
25
26         free(key);
27 }
28
29 void init_add_i_state(struct add_i_state *s, struct repository *r)
30 {
31         const char *value;
32
33         s->r = r;
34
35         if (repo_config_get_value(r, "color.interactive", &value))
36                 s->use_color = -1;
37         else
38                 s->use_color =
39                         git_config_colorbool("color.interactive", value);
40         s->use_color = want_color(s->use_color);
41
42         init_color(r, s, "header", s->header_color, GIT_COLOR_BOLD);
43         init_color(r, s, "help", s->help_color, GIT_COLOR_BOLD_RED);
44         init_color(r, s, "prompt", s->prompt_color, GIT_COLOR_BOLD_BLUE);
45         init_color(r, s, "error", s->error_color, GIT_COLOR_BOLD_RED);
46         init_color(r, s, "reset", s->reset_color, GIT_COLOR_RESET);
47         init_color(r, s, "fraginfo", s->fraginfo_color,
48                    diff_get_color(s->use_color, DIFF_FRAGINFO));
49         init_color(r, s, "context", s->context_color,
50                 diff_get_color(s->use_color, DIFF_CONTEXT));
51         init_color(r, s, "old", s->file_old_color,
52                 diff_get_color(s->use_color, DIFF_FILE_OLD));
53         init_color(r, s, "new", s->file_new_color,
54                 diff_get_color(s->use_color, DIFF_FILE_NEW));
55
56         FREE_AND_NULL(s->interactive_diff_filter);
57         git_config_get_string("interactive.difffilter",
58                               &s->interactive_diff_filter);
59
60         FREE_AND_NULL(s->interactive_diff_algorithm);
61         git_config_get_string("diff.algorithm",
62                               &s->interactive_diff_algorithm);
63 }
64
65 void clear_add_i_state(struct add_i_state *s)
66 {
67         FREE_AND_NULL(s->interactive_diff_filter);
68         FREE_AND_NULL(s->interactive_diff_algorithm);
69         memset(s, 0, sizeof(*s));
70         s->use_color = -1;
71 }
72
73 /*
74  * A "prefix item list" is a list of items that are identified by a string, and
75  * a unique prefix (if any) is determined for each item.
76  *
77  * It is implemented in the form of a pair of `string_list`s, the first one
78  * duplicating the strings, with the `util` field pointing at a structure whose
79  * first field must be `size_t prefix_length`.
80  *
81  * That `prefix_length` field will be computed by `find_unique_prefixes()`; It
82  * will be set to zero if no valid, unique prefix could be found.
83  *
84  * The second `string_list` is called `sorted` and does _not_ duplicate the
85  * strings but simply reuses the first one's, with the `util` field pointing at
86  * the `string_item_list` of the first `string_list`. It  will be populated and
87  * sorted by `find_unique_prefixes()`.
88  */
89 struct prefix_item_list {
90         struct string_list items;
91         struct string_list sorted;
92         int *selected; /* for multi-selections */
93         size_t min_length, max_length;
94 };
95 #define PREFIX_ITEM_LIST_INIT \
96         { STRING_LIST_INIT_DUP, STRING_LIST_INIT_NODUP, NULL, 1, 4 }
97
98 static void prefix_item_list_clear(struct prefix_item_list *list)
99 {
100         string_list_clear(&list->items, 1);
101         string_list_clear(&list->sorted, 0);
102         FREE_AND_NULL(list->selected);
103 }
104
105 static void extend_prefix_length(struct string_list_item *p,
106                                  const char *other_string, size_t max_length)
107 {
108         size_t *len = p->util;
109
110         if (!*len || memcmp(p->string, other_string, *len))
111                 return;
112
113         for (;;) {
114                 char c = p->string[*len];
115
116                 /*
117                  * Is `p` a strict prefix of `other`? Or have we exhausted the
118                  * maximal length of the prefix? Or is the current character a
119                  * multi-byte UTF-8 one? If so, there is no valid, unique
120                  * prefix.
121                  */
122                 if (!c || ++*len > max_length || !isascii(c)) {
123                         *len = 0;
124                         break;
125                 }
126
127                 if (c != other_string[*len - 1])
128                         break;
129         }
130 }
131
132 static void find_unique_prefixes(struct prefix_item_list *list)
133 {
134         size_t i;
135
136         if (list->sorted.nr == list->items.nr)
137                 return;
138
139         string_list_clear(&list->sorted, 0);
140         /* Avoid reallocating incrementally */
141         list->sorted.items = xmalloc(st_mult(sizeof(*list->sorted.items),
142                                              list->items.nr));
143         list->sorted.nr = list->sorted.alloc = list->items.nr;
144
145         for (i = 0; i < list->items.nr; i++) {
146                 list->sorted.items[i].string = list->items.items[i].string;
147                 list->sorted.items[i].util = list->items.items + i;
148         }
149
150         string_list_sort(&list->sorted);
151
152         for (i = 0; i < list->sorted.nr; i++) {
153                 struct string_list_item *sorted_item = list->sorted.items + i;
154                 struct string_list_item *item = sorted_item->util;
155                 size_t *len = item->util;
156
157                 *len = 0;
158                 while (*len < list->min_length) {
159                         char c = item->string[(*len)++];
160
161                         if (!c || !isascii(c)) {
162                                 *len = 0;
163                                 break;
164                         }
165                 }
166
167                 if (i > 0)
168                         extend_prefix_length(item, sorted_item[-1].string,
169                                              list->max_length);
170                 if (i + 1 < list->sorted.nr)
171                         extend_prefix_length(item, sorted_item[1].string,
172                                              list->max_length);
173         }
174 }
175
176 static ssize_t find_unique(const char *string, struct prefix_item_list *list)
177 {
178         int index = string_list_find_insert_index(&list->sorted, string, 1);
179         struct string_list_item *item;
180
181         if (list->items.nr != list->sorted.nr)
182                 BUG("prefix_item_list in inconsistent state (%"PRIuMAX
183                     " vs %"PRIuMAX")",
184                     (uintmax_t)list->items.nr, (uintmax_t)list->sorted.nr);
185
186         if (index < 0)
187                 item = list->sorted.items[-1 - index].util;
188         else if (index > 0 &&
189                  starts_with(list->sorted.items[index - 1].string, string))
190                 return -1;
191         else if (index + 1 < list->sorted.nr &&
192                  starts_with(list->sorted.items[index + 1].string, string))
193                 return -1;
194         else if (index < list->sorted.nr)
195                 item = list->sorted.items[index].util;
196         else
197                 return -1;
198         return item - list->items.items;
199 }
200
201 struct list_options {
202         int columns;
203         const char *header;
204         void (*print_item)(int i, int selected, struct string_list_item *item,
205                            void *print_item_data);
206         void *print_item_data;
207 };
208
209 static void list(struct add_i_state *s, struct string_list *list, int *selected,
210                  struct list_options *opts)
211 {
212         int i, last_lf = 0;
213
214         if (!list->nr)
215                 return;
216
217         if (opts->header)
218                 color_fprintf_ln(stdout, s->header_color,
219                                  "%s", opts->header);
220
221         for (i = 0; i < list->nr; i++) {
222                 opts->print_item(i, selected ? selected[i] : 0, list->items + i,
223                                  opts->print_item_data);
224
225                 if ((opts->columns) && ((i + 1) % (opts->columns))) {
226                         putchar('\t');
227                         last_lf = 0;
228                 }
229                 else {
230                         putchar('\n');
231                         last_lf = 1;
232                 }
233         }
234
235         if (!last_lf)
236                 putchar('\n');
237 }
238 struct list_and_choose_options {
239         struct list_options list_opts;
240
241         const char *prompt;
242         enum {
243                 SINGLETON = (1<<0),
244                 IMMEDIATE = (1<<1),
245         } flags;
246         void (*print_help)(struct add_i_state *s);
247 };
248
249 #define LIST_AND_CHOOSE_ERROR (-1)
250 #define LIST_AND_CHOOSE_QUIT  (-2)
251
252 /*
253  * Returns the selected index in singleton mode, the number of selected items
254  * otherwise.
255  *
256  * If an error occurred, returns `LIST_AND_CHOOSE_ERROR`. Upon EOF,
257  * `LIST_AND_CHOOSE_QUIT` is returned.
258  */
259 static ssize_t list_and_choose(struct add_i_state *s,
260                                struct prefix_item_list *items,
261                                struct list_and_choose_options *opts)
262 {
263         int singleton = opts->flags & SINGLETON;
264         int immediate = opts->flags & IMMEDIATE;
265
266         struct strbuf input = STRBUF_INIT;
267         ssize_t res = singleton ? LIST_AND_CHOOSE_ERROR : 0;
268
269         if (!singleton) {
270                 free(items->selected);
271                 CALLOC_ARRAY(items->selected, items->items.nr);
272         }
273
274         if (singleton && !immediate)
275                 BUG("singleton requires immediate");
276
277         find_unique_prefixes(items);
278
279         for (;;) {
280                 char *p;
281
282                 strbuf_reset(&input);
283
284                 list(s, &items->items, items->selected, &opts->list_opts);
285
286                 color_fprintf(stdout, s->prompt_color, "%s", opts->prompt);
287                 fputs(singleton ? "> " : ">> ", stdout);
288                 fflush(stdout);
289
290                 if (strbuf_getline(&input, stdin) == EOF) {
291                         putchar('\n');
292                         if (immediate)
293                                 res = LIST_AND_CHOOSE_QUIT;
294                         break;
295                 }
296                 strbuf_trim(&input);
297
298                 if (!input.len)
299                         break;
300
301                 if (!strcmp(input.buf, "?")) {
302                         opts->print_help(s);
303                         continue;
304                 }
305
306                 p = input.buf;
307                 for (;;) {
308                         size_t sep = strcspn(p, " \t\r\n,");
309                         int choose = 1;
310                         /* `from` is inclusive, `to` is exclusive */
311                         ssize_t from = -1, to = -1;
312
313                         if (!sep) {
314                                 if (!*p)
315                                         break;
316                                 p++;
317                                 continue;
318                         }
319
320                         /* Input that begins with '-'; de-select */
321                         if (*p == '-') {
322                                 choose = 0;
323                                 p++;
324                                 sep--;
325                         }
326
327                         if (sep == 1 && *p == '*') {
328                                 from = 0;
329                                 to = items->items.nr;
330                         } else if (isdigit(*p)) {
331                                 char *endp;
332                                 /*
333                                  * A range can be specified like 5-7 or 5-.
334                                  *
335                                  * Note: `from` is 0-based while the user input
336                                  * is 1-based, hence we have to decrement by
337                                  * one. We do not have to decrement `to` even
338                                  * if it is 0-based because it is an exclusive
339                                  * boundary.
340                                  */
341                                 from = strtoul(p, &endp, 10) - 1;
342                                 if (endp == p + sep)
343                                         to = from + 1;
344                                 else if (*endp == '-') {
345                                         to = strtoul(++endp, &endp, 10);
346                                         /* extra characters after the range? */
347                                         if (endp != p + sep)
348                                                 from = -1;
349                                 }
350                         }
351
352                         if (p[sep])
353                                 p[sep++] = '\0';
354                         if (from < 0) {
355                                 from = find_unique(p, items);
356                                 if (from >= 0)
357                                         to = from + 1;
358                         }
359
360                         if (from < 0 || from >= items->items.nr ||
361                             (singleton && from + 1 != to)) {
362                                 color_fprintf_ln(stdout, s->error_color,
363                                                  _("Huh (%s)?"), p);
364                                 break;
365                         } else if (singleton) {
366                                 res = from;
367                                 break;
368                         }
369
370                         if (to > items->items.nr)
371                                 to = items->items.nr;
372
373                         for (; from < to; from++)
374                                 if (items->selected[from] != choose) {
375                                         items->selected[from] = choose;
376                                         res += choose ? +1 : -1;
377                                 }
378
379                         p += sep;
380                 }
381
382                 if ((immediate && res != LIST_AND_CHOOSE_ERROR) ||
383                     !strcmp(input.buf, "*"))
384                         break;
385         }
386
387         strbuf_release(&input);
388         return res;
389 }
390
391 struct adddel {
392         uintmax_t add, del;
393         unsigned seen:1, unmerged:1, binary:1;
394 };
395
396 struct file_item {
397         size_t prefix_length;
398         struct adddel index, worktree;
399 };
400
401 static void add_file_item(struct string_list *files, const char *name)
402 {
403         struct file_item *item = xcalloc(sizeof(*item), 1);
404
405         string_list_append(files, name)->util = item;
406 }
407
408 struct pathname_entry {
409         struct hashmap_entry ent;
410         const char *name;
411         struct file_item *item;
412 };
413
414 static int pathname_entry_cmp(const void *unused_cmp_data,
415                               const struct hashmap_entry *he1,
416                               const struct hashmap_entry *he2,
417                               const void *name)
418 {
419         const struct pathname_entry *e1 =
420                 container_of(he1, const struct pathname_entry, ent);
421         const struct pathname_entry *e2 =
422                 container_of(he2, const struct pathname_entry, ent);
423
424         return strcmp(e1->name, name ? (const char *)name : e2->name);
425 }
426
427 struct collection_status {
428         enum { FROM_WORKTREE = 0, FROM_INDEX = 1 } mode;
429
430         const char *reference;
431
432         unsigned skip_unseen:1;
433         size_t unmerged_count, binary_count;
434         struct string_list *files;
435         struct hashmap file_map;
436 };
437
438 static void collect_changes_cb(struct diff_queue_struct *q,
439                                struct diff_options *options,
440                                void *data)
441 {
442         struct collection_status *s = data;
443         struct diffstat_t stat = { 0 };
444         int i;
445
446         if (!q->nr)
447                 return;
448
449         compute_diffstat(options, &stat, q);
450
451         for (i = 0; i < stat.nr; i++) {
452                 const char *name = stat.files[i]->name;
453                 int hash = strhash(name);
454                 struct pathname_entry *entry;
455                 struct file_item *file_item;
456                 struct adddel *adddel, *other_adddel;
457
458                 entry = hashmap_get_entry_from_hash(&s->file_map, hash, name,
459                                                     struct pathname_entry, ent);
460                 if (!entry) {
461                         if (s->skip_unseen)
462                                 continue;
463
464                         add_file_item(s->files, name);
465
466                         entry = xcalloc(sizeof(*entry), 1);
467                         hashmap_entry_init(&entry->ent, hash);
468                         entry->name = s->files->items[s->files->nr - 1].string;
469                         entry->item = s->files->items[s->files->nr - 1].util;
470                         hashmap_add(&s->file_map, &entry->ent);
471                 }
472
473                 file_item = entry->item;
474                 adddel = s->mode == FROM_INDEX ?
475                         &file_item->index : &file_item->worktree;
476                 other_adddel = s->mode == FROM_INDEX ?
477                         &file_item->worktree : &file_item->index;
478                 adddel->seen = 1;
479                 adddel->add = stat.files[i]->added;
480                 adddel->del = stat.files[i]->deleted;
481                 if (stat.files[i]->is_binary) {
482                         if (!other_adddel->binary)
483                                 s->binary_count++;
484                         adddel->binary = 1;
485                 }
486                 if (stat.files[i]->is_unmerged) {
487                         if (!other_adddel->unmerged)
488                                 s->unmerged_count++;
489                         adddel->unmerged = 1;
490                 }
491         }
492         free_diffstat_info(&stat);
493 }
494
495 enum modified_files_filter {
496         NO_FILTER = 0,
497         WORKTREE_ONLY = 1,
498         INDEX_ONLY = 2,
499 };
500
501 static int get_modified_files(struct repository *r,
502                               enum modified_files_filter filter,
503                               struct prefix_item_list *files,
504                               const struct pathspec *ps,
505                               size_t *unmerged_count,
506                               size_t *binary_count)
507 {
508         struct object_id head_oid;
509         int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
510                                              &head_oid, NULL);
511         struct collection_status s = { 0 };
512         int i;
513
514         if (discard_index(r->index) < 0 ||
515             repo_read_index_preload(r, ps, 0) < 0)
516                 return error(_("could not read index"));
517
518         prefix_item_list_clear(files);
519         s.files = &files->items;
520         hashmap_init(&s.file_map, pathname_entry_cmp, NULL, 0);
521
522         for (i = 0; i < 2; i++) {
523                 struct rev_info rev;
524                 struct setup_revision_opt opt = { 0 };
525
526                 if (filter == INDEX_ONLY)
527                         s.mode = (i == 0) ? FROM_INDEX : FROM_WORKTREE;
528                 else
529                         s.mode = (i == 0) ? FROM_WORKTREE : FROM_INDEX;
530                 s.skip_unseen = filter && i;
531
532                 opt.def = is_initial ?
533                         empty_tree_oid_hex() : oid_to_hex(&head_oid);
534
535                 init_revisions(&rev, NULL);
536                 setup_revisions(0, NULL, &rev, &opt);
537
538                 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
539                 rev.diffopt.format_callback = collect_changes_cb;
540                 rev.diffopt.format_callback_data = &s;
541
542                 if (ps)
543                         copy_pathspec(&rev.prune_data, ps);
544
545                 if (s.mode == FROM_INDEX)
546                         run_diff_index(&rev, 1);
547                 else {
548                         rev.diffopt.flags.ignore_dirty_submodules = 1;
549                         run_diff_files(&rev, 0);
550                 }
551
552                 if (ps)
553                         clear_pathspec(&rev.prune_data);
554         }
555         hashmap_free_entries(&s.file_map, struct pathname_entry, ent);
556         if (unmerged_count)
557                 *unmerged_count = s.unmerged_count;
558         if (binary_count)
559                 *binary_count = s.binary_count;
560
561         /* While the diffs are ordered already, we ran *two* diffs... */
562         string_list_sort(&files->items);
563
564         return 0;
565 }
566
567 static void render_adddel(struct strbuf *buf,
568                                 struct adddel *ad, const char *no_changes)
569 {
570         if (ad->binary)
571                 strbuf_addstr(buf, _("binary"));
572         else if (ad->seen)
573                 strbuf_addf(buf, "+%"PRIuMAX"/-%"PRIuMAX,
574                             (uintmax_t)ad->add, (uintmax_t)ad->del);
575         else
576                 strbuf_addstr(buf, no_changes);
577 }
578
579 /* filters out prefixes which have special meaning to list_and_choose() */
580 static int is_valid_prefix(const char *prefix, size_t prefix_len)
581 {
582         return prefix_len && prefix &&
583                 /*
584                  * We expect `prefix` to be NUL terminated, therefore this
585                  * `strcspn()` call is okay, even if it might do much more
586                  * work than strictly necessary.
587                  */
588                 strcspn(prefix, " \t\r\n,") >= prefix_len &&    /* separators */
589                 *prefix != '-' &&                               /* deselection */
590                 !isdigit(*prefix) &&                            /* selection */
591                 (prefix_len != 1 ||
592                  (*prefix != '*' &&                             /* "all" wildcard */
593                   *prefix != '?'));                             /* prompt help */
594 }
595
596 struct print_file_item_data {
597         const char *modified_fmt, *color, *reset;
598         struct strbuf buf, name, index, worktree;
599         unsigned only_names:1;
600 };
601
602 static void print_file_item(int i, int selected, struct string_list_item *item,
603                             void *print_file_item_data)
604 {
605         struct file_item *c = item->util;
606         struct print_file_item_data *d = print_file_item_data;
607         const char *highlighted = NULL;
608
609         strbuf_reset(&d->index);
610         strbuf_reset(&d->worktree);
611         strbuf_reset(&d->buf);
612
613         /* Format the item with the prefix highlighted. */
614         if (c->prefix_length > 0 &&
615             is_valid_prefix(item->string, c->prefix_length)) {
616                 strbuf_reset(&d->name);
617                 strbuf_addf(&d->name, "%s%.*s%s%s", d->color,
618                             (int)c->prefix_length, item->string, d->reset,
619                             item->string + c->prefix_length);
620                 highlighted = d->name.buf;
621         }
622
623         if (d->only_names) {
624                 printf("%c%2d: %s", selected ? '*' : ' ', i + 1,
625                        highlighted ? highlighted : item->string);
626                 return;
627         }
628
629         render_adddel(&d->worktree, &c->worktree, _("nothing"));
630         render_adddel(&d->index, &c->index, _("unchanged"));
631
632         strbuf_addf(&d->buf, d->modified_fmt, d->index.buf, d->worktree.buf,
633                     highlighted ? highlighted : item->string);
634
635         printf("%c%2d: %s", selected ? '*' : ' ', i + 1, d->buf.buf);
636 }
637
638 static int run_status(struct add_i_state *s, const struct pathspec *ps,
639                       struct prefix_item_list *files,
640                       struct list_and_choose_options *opts)
641 {
642         if (get_modified_files(s->r, NO_FILTER, files, ps, NULL, NULL) < 0)
643                 return -1;
644
645         list(s, &files->items, NULL, &opts->list_opts);
646         putchar('\n');
647
648         return 0;
649 }
650
651 static int run_update(struct add_i_state *s, const struct pathspec *ps,
652                       struct prefix_item_list *files,
653                       struct list_and_choose_options *opts)
654 {
655         int res = 0, fd;
656         size_t count, i;
657         struct lock_file index_lock;
658
659         if (get_modified_files(s->r, WORKTREE_ONLY, files, ps, NULL, NULL) < 0)
660                 return -1;
661
662         if (!files->items.nr) {
663                 putchar('\n');
664                 return 0;
665         }
666
667         opts->prompt = N_("Update");
668         count = list_and_choose(s, files, opts);
669         if (count <= 0) {
670                 putchar('\n');
671                 return 0;
672         }
673
674         fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
675         if (fd < 0) {
676                 putchar('\n');
677                 return -1;
678         }
679
680         for (i = 0; i < files->items.nr; i++) {
681                 const char *name = files->items.items[i].string;
682                 if (files->selected[i] &&
683                     add_file_to_index(s->r->index, name, 0) < 0) {
684                         res = error(_("could not stage '%s'"), name);
685                         break;
686                 }
687         }
688
689         if (!res && write_locked_index(s->r->index, &index_lock, COMMIT_LOCK) < 0)
690                 res = error(_("could not write index"));
691
692         if (!res)
693                 printf(Q_("updated %d path\n",
694                           "updated %d paths\n", count), (int)count);
695
696         putchar('\n');
697         return res;
698 }
699
700 static void revert_from_diff(struct diff_queue_struct *q,
701                              struct diff_options *opt, void *data)
702 {
703         int i, add_flags = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE;
704
705         for (i = 0; i < q->nr; i++) {
706                 struct diff_filespec *one = q->queue[i]->one;
707                 struct cache_entry *ce;
708
709                 if (!(one->mode && !is_null_oid(&one->oid))) {
710                         remove_file_from_index(opt->repo->index, one->path);
711                         printf(_("note: %s is untracked now.\n"), one->path);
712                 } else {
713                         ce = make_cache_entry(opt->repo->index, one->mode,
714                                               &one->oid, one->path, 0, 0);
715                         if (!ce)
716                                 die(_("make_cache_entry failed for path '%s'"),
717                                     one->path);
718                         add_index_entry(opt->repo->index, ce, add_flags);
719                 }
720         }
721 }
722
723 static int run_revert(struct add_i_state *s, const struct pathspec *ps,
724                       struct prefix_item_list *files,
725                       struct list_and_choose_options *opts)
726 {
727         int res = 0, fd;
728         size_t count, i, j;
729
730         struct object_id oid;
731         int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &oid,
732                                              NULL);
733         struct lock_file index_lock;
734         const char **paths;
735         struct tree *tree;
736         struct diff_options diffopt = { NULL };
737
738         if (get_modified_files(s->r, INDEX_ONLY, files, ps, NULL, NULL) < 0)
739                 return -1;
740
741         if (!files->items.nr) {
742                 putchar('\n');
743                 return 0;
744         }
745
746         opts->prompt = N_("Revert");
747         count = list_and_choose(s, files, opts);
748         if (count <= 0)
749                 goto finish_revert;
750
751         fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
752         if (fd < 0) {
753                 res = -1;
754                 goto finish_revert;
755         }
756
757         if (is_initial)
758                 oidcpy(&oid, s->r->hash_algo->empty_tree);
759         else {
760                 tree = parse_tree_indirect(&oid);
761                 if (!tree) {
762                         res = error(_("Could not parse HEAD^{tree}"));
763                         goto finish_revert;
764                 }
765                 oidcpy(&oid, &tree->object.oid);
766         }
767
768         ALLOC_ARRAY(paths, count + 1);
769         for (i = j = 0; i < files->items.nr; i++)
770                 if (files->selected[i])
771                         paths[j++] = files->items.items[i].string;
772         paths[j] = NULL;
773
774         parse_pathspec(&diffopt.pathspec, 0,
775                        PATHSPEC_PREFER_FULL | PATHSPEC_LITERAL_PATH,
776                        NULL, paths);
777
778         diffopt.output_format = DIFF_FORMAT_CALLBACK;
779         diffopt.format_callback = revert_from_diff;
780         diffopt.flags.override_submodule_config = 1;
781         diffopt.repo = s->r;
782
783         if (do_diff_cache(&oid, &diffopt))
784                 res = -1;
785         else {
786                 diffcore_std(&diffopt);
787                 diff_flush(&diffopt);
788         }
789         free(paths);
790         clear_pathspec(&diffopt.pathspec);
791
792         if (!res && write_locked_index(s->r->index, &index_lock,
793                                        COMMIT_LOCK) < 0)
794                 res = -1;
795         else
796                 res = repo_refresh_and_write_index(s->r, REFRESH_QUIET, 0, 1,
797                                                    NULL, NULL, NULL);
798
799         if (!res)
800                 printf(Q_("reverted %d path\n",
801                           "reverted %d paths\n", count), (int)count);
802
803 finish_revert:
804         putchar('\n');
805         return res;
806 }
807
808 static int get_untracked_files(struct repository *r,
809                                struct prefix_item_list *files,
810                                const struct pathspec *ps)
811 {
812         struct dir_struct dir = { 0 };
813         size_t i;
814         struct strbuf buf = STRBUF_INIT;
815
816         if (repo_read_index(r) < 0)
817                 return error(_("could not read index"));
818
819         prefix_item_list_clear(files);
820         setup_standard_excludes(&dir);
821         add_pattern_list(&dir, EXC_CMDL, "--exclude option");
822         fill_directory(&dir, r->index, ps);
823
824         for (i = 0; i < dir.nr; i++) {
825                 struct dir_entry *ent = dir.entries[i];
826
827                 if (index_name_is_other(r->index, ent->name, ent->len)) {
828                         strbuf_reset(&buf);
829                         strbuf_add(&buf, ent->name, ent->len);
830                         add_file_item(&files->items, buf.buf);
831                 }
832         }
833
834         strbuf_release(&buf);
835         return 0;
836 }
837
838 static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
839                       struct prefix_item_list *files,
840                       struct list_and_choose_options *opts)
841 {
842         struct print_file_item_data *d = opts->list_opts.print_item_data;
843         int res = 0, fd;
844         size_t count, i;
845         struct lock_file index_lock;
846
847         if (get_untracked_files(s->r, files, ps) < 0)
848                 return -1;
849
850         if (!files->items.nr) {
851                 printf(_("No untracked files.\n"));
852                 goto finish_add_untracked;
853         }
854
855         opts->prompt = N_("Add untracked");
856         d->only_names = 1;
857         count = list_and_choose(s, files, opts);
858         d->only_names = 0;
859         if (count <= 0)
860                 goto finish_add_untracked;
861
862         fd = repo_hold_locked_index(s->r, &index_lock, LOCK_REPORT_ON_ERROR);
863         if (fd < 0) {
864                 res = -1;
865                 goto finish_add_untracked;
866         }
867
868         for (i = 0; i < files->items.nr; i++) {
869                 const char *name = files->items.items[i].string;
870                 if (files->selected[i] &&
871                     add_file_to_index(s->r->index, name, 0) < 0) {
872                         res = error(_("could not stage '%s'"), name);
873                         break;
874                 }
875         }
876
877         if (!res &&
878             write_locked_index(s->r->index, &index_lock, COMMIT_LOCK) < 0)
879                 res = error(_("could not write index"));
880
881         if (!res)
882                 printf(Q_("added %d path\n",
883                           "added %d paths\n", count), (int)count);
884
885 finish_add_untracked:
886         putchar('\n');
887         return res;
888 }
889
890 static int run_patch(struct add_i_state *s, const struct pathspec *ps,
891                      struct prefix_item_list *files,
892                      struct list_and_choose_options *opts)
893 {
894         int res = 0;
895         ssize_t count, i, j;
896         size_t unmerged_count = 0, binary_count = 0;
897
898         if (get_modified_files(s->r, WORKTREE_ONLY, files, ps,
899                                &unmerged_count, &binary_count) < 0)
900                 return -1;
901
902         if (unmerged_count || binary_count) {
903                 for (i = j = 0; i < files->items.nr; i++) {
904                         struct file_item *item = files->items.items[i].util;
905
906                         if (item->index.binary || item->worktree.binary) {
907                                 free(item);
908                                 free(files->items.items[i].string);
909                         } else if (item->index.unmerged ||
910                                  item->worktree.unmerged) {
911                                 color_fprintf_ln(stderr, s->error_color,
912                                                  _("ignoring unmerged: %s"),
913                                                  files->items.items[i].string);
914                                 free(item);
915                                 free(files->items.items[i].string);
916                         } else
917                                 files->items.items[j++] = files->items.items[i];
918                 }
919                 files->items.nr = j;
920         }
921
922         if (!files->items.nr) {
923                 if (binary_count)
924                         fprintf(stderr, _("Only binary files changed.\n"));
925                 else
926                         fprintf(stderr, _("No changes.\n"));
927                 return 0;
928         }
929
930         opts->prompt = N_("Patch update");
931         count = list_and_choose(s, files, opts);
932         if (count >= 0) {
933                 struct argv_array args = ARGV_ARRAY_INIT;
934                 struct pathspec ps_selected = { 0 };
935
936                 for (i = 0; i < files->items.nr; i++)
937                         if (files->selected[i])
938                                 argv_array_push(&args,
939                                                 files->items.items[i].string);
940                 parse_pathspec(&ps_selected,
941                                PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
942                                PATHSPEC_LITERAL_PATH, "", args.argv);
943                 res = run_add_p(s->r, ADD_P_ADD, NULL, &ps_selected);
944                 argv_array_clear(&args);
945                 clear_pathspec(&ps_selected);
946         }
947
948         return res;
949 }
950
951 static int run_diff(struct add_i_state *s, const struct pathspec *ps,
952                     struct prefix_item_list *files,
953                     struct list_and_choose_options *opts)
954 {
955         int res = 0;
956         ssize_t count, i;
957
958         struct object_id oid;
959         int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &oid,
960                                              NULL);
961         if (get_modified_files(s->r, INDEX_ONLY, files, ps, NULL, NULL) < 0)
962                 return -1;
963
964         if (!files->items.nr) {
965                 putchar('\n');
966                 return 0;
967         }
968
969         opts->prompt = N_("Review diff");
970         opts->flags = IMMEDIATE;
971         count = list_and_choose(s, files, opts);
972         opts->flags = 0;
973         if (count >= 0) {
974                 struct argv_array args = ARGV_ARRAY_INIT;
975
976                 argv_array_pushl(&args, "git", "diff", "-p", "--cached",
977                                  oid_to_hex(!is_initial ? &oid :
978                                             s->r->hash_algo->empty_tree),
979                                  "--", NULL);
980                 for (i = 0; i < files->items.nr; i++)
981                         if (files->selected[i])
982                                 argv_array_push(&args,
983                                                 files->items.items[i].string);
984                 res = run_command_v_opt(args.argv, 0);
985                 argv_array_clear(&args);
986         }
987
988         putchar('\n');
989         return res;
990 }
991
992 static int run_help(struct add_i_state *s, const struct pathspec *unused_ps,
993                     struct prefix_item_list *unused_files,
994                     struct list_and_choose_options *unused_opts)
995 {
996         color_fprintf_ln(stdout, s->help_color, "status        - %s",
997                          _("show paths with changes"));
998         color_fprintf_ln(stdout, s->help_color, "update        - %s",
999                          _("add working tree state to the staged set of changes"));
1000         color_fprintf_ln(stdout, s->help_color, "revert        - %s",
1001                          _("revert staged set of changes back to the HEAD version"));
1002         color_fprintf_ln(stdout, s->help_color, "patch         - %s",
1003                          _("pick hunks and update selectively"));
1004         color_fprintf_ln(stdout, s->help_color, "diff          - %s",
1005                          _("view diff between HEAD and index"));
1006         color_fprintf_ln(stdout, s->help_color, "add untracked - %s",
1007                          _("add contents of untracked files to the staged set of changes"));
1008
1009         return 0;
1010 }
1011
1012 static void choose_prompt_help(struct add_i_state *s)
1013 {
1014         color_fprintf_ln(stdout, s->help_color, "%s",
1015                          _("Prompt help:"));
1016         color_fprintf_ln(stdout, s->help_color, "1          - %s",
1017                          _("select a single item"));
1018         color_fprintf_ln(stdout, s->help_color, "3-5        - %s",
1019                          _("select a range of items"));
1020         color_fprintf_ln(stdout, s->help_color, "2-3,6-9    - %s",
1021                          _("select multiple ranges"));
1022         color_fprintf_ln(stdout, s->help_color, "foo        - %s",
1023                          _("select item based on unique prefix"));
1024         color_fprintf_ln(stdout, s->help_color, "-...       - %s",
1025                          _("unselect specified items"));
1026         color_fprintf_ln(stdout, s->help_color, "*          - %s",
1027                          _("choose all items"));
1028         color_fprintf_ln(stdout, s->help_color, "           - %s",
1029                          _("(empty) finish selecting"));
1030 }
1031
1032 typedef int (*command_t)(struct add_i_state *s, const struct pathspec *ps,
1033                          struct prefix_item_list *files,
1034                          struct list_and_choose_options *opts);
1035
1036 struct command_item {
1037         size_t prefix_length;
1038         command_t command;
1039 };
1040
1041 struct print_command_item_data {
1042         const char *color, *reset;
1043 };
1044
1045 static void print_command_item(int i, int selected,
1046                                struct string_list_item *item,
1047                                void *print_command_item_data)
1048 {
1049         struct print_command_item_data *d = print_command_item_data;
1050         struct command_item *util = item->util;
1051
1052         if (!util->prefix_length ||
1053             !is_valid_prefix(item->string, util->prefix_length))
1054                 printf(" %2d: %s", i + 1, item->string);
1055         else
1056                 printf(" %2d: %s%.*s%s%s", i + 1,
1057                        d->color, (int)util->prefix_length, item->string,
1058                        d->reset, item->string + util->prefix_length);
1059 }
1060
1061 static void command_prompt_help(struct add_i_state *s)
1062 {
1063         const char *help_color = s->help_color;
1064         color_fprintf_ln(stdout, help_color, "%s", _("Prompt help:"));
1065         color_fprintf_ln(stdout, help_color, "1          - %s",
1066                          _("select a numbered item"));
1067         color_fprintf_ln(stdout, help_color, "foo        - %s",
1068                          _("select item based on unique prefix"));
1069         color_fprintf_ln(stdout, help_color, "           - %s",
1070                          _("(empty) select nothing"));
1071 }
1072
1073 int run_add_i(struct repository *r, const struct pathspec *ps)
1074 {
1075         struct add_i_state s = { NULL };
1076         struct print_command_item_data data = { "[", "]" };
1077         struct list_and_choose_options main_loop_opts = {
1078                 { 4, N_("*** Commands ***"), print_command_item, &data },
1079                 N_("What now"), SINGLETON | IMMEDIATE, command_prompt_help
1080         };
1081         struct {
1082                 const char *string;
1083                 command_t command;
1084         } command_list[] = {
1085                 { "status", run_status },
1086                 { "update", run_update },
1087                 { "revert", run_revert },
1088                 { "add untracked", run_add_untracked },
1089                 { "patch", run_patch },
1090                 { "diff", run_diff },
1091                 { "quit", NULL },
1092                 { "help", run_help },
1093         };
1094         struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT;
1095
1096         struct print_file_item_data print_file_item_data = {
1097                 "%12s %12s %s", NULL, NULL,
1098                 STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
1099         };
1100         struct list_and_choose_options opts = {
1101                 { 0, NULL, print_file_item, &print_file_item_data },
1102                 NULL, 0, choose_prompt_help
1103         };
1104         struct strbuf header = STRBUF_INIT;
1105         struct prefix_item_list files = PREFIX_ITEM_LIST_INIT;
1106         ssize_t i;
1107         int res = 0;
1108
1109         for (i = 0; i < ARRAY_SIZE(command_list); i++) {
1110                 struct command_item *util = xcalloc(sizeof(*util), 1);
1111                 util->command = command_list[i].command;
1112                 string_list_append(&commands.items, command_list[i].string)
1113                         ->util = util;
1114         }
1115
1116         init_add_i_state(&s, r);
1117
1118         /*
1119          * When color was asked for, use the prompt color for
1120          * highlighting, otherwise use square brackets.
1121          */
1122         if (s.use_color) {
1123                 data.color = s.prompt_color;
1124                 data.reset = s.reset_color;
1125         }
1126         print_file_item_data.color = data.color;
1127         print_file_item_data.reset = data.reset;
1128
1129         strbuf_addstr(&header, "      ");
1130         strbuf_addf(&header, print_file_item_data.modified_fmt,
1131                     _("staged"), _("unstaged"), _("path"));
1132         opts.list_opts.header = header.buf;
1133
1134         if (discard_index(r->index) < 0 ||
1135             repo_read_index(r) < 0 ||
1136             repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1,
1137                                          NULL, NULL, NULL) < 0)
1138                 warning(_("could not refresh index"));
1139
1140         res = run_status(&s, ps, &files, &opts);
1141
1142         for (;;) {
1143                 struct command_item *util;
1144
1145                 i = list_and_choose(&s, &commands, &main_loop_opts);
1146                 if (i < 0 || i >= commands.items.nr)
1147                         util = NULL;
1148                 else
1149                         util = commands.items.items[i].util;
1150
1151                 if (i == LIST_AND_CHOOSE_QUIT || (util && !util->command)) {
1152                         printf(_("Bye.\n"));
1153                         res = 0;
1154                         break;
1155                 }
1156
1157                 if (util)
1158                         res = util->command(&s, ps, &files, &opts);
1159         }
1160
1161         prefix_item_list_clear(&files);
1162         strbuf_release(&print_file_item_data.buf);
1163         strbuf_release(&print_file_item_data.name);
1164         strbuf_release(&print_file_item_data.index);
1165         strbuf_release(&print_file_item_data.worktree);
1166         strbuf_release(&header);
1167         prefix_item_list_clear(&commands);
1168         clear_add_i_state(&s);
1169
1170         return res;
1171 }