#include "cache.h"
#include "add-interactive.h"
#include "color.h"
#include "config.h"
#include "diffcore.h"
#include "revision.h"
#include "refs.h"
#include "string-list.h"
#include "lockfile.h"
#include "dir.h"
#include "run-command.h"
#include "prompt.h"
static void init_color(struct repository *r, struct add_i_state *s,
const char *slot_name, char *dst,
const char *default_color)
{
char *key = xstrfmt("color.interactive.%s", slot_name);
const char *value;
if (!s->use_color)
dst[0] = '\0';
else if (repo_config_get_value(r, key, &value) ||
color_parse(value, dst))
strlcpy(dst, default_color, COLOR_MAXLEN);
free(key);
}
void init_add_i_state(struct add_i_state *s, struct repository *r)
{
const char *value;
s->r = r;
if (repo_config_get_value(r, "color.interactive", &value))
s->use_color = -1;
else
s->use_color =
git_config_colorbool("color.interactive", value);
s->use_color = want_color(s->use_color);
init_color(r, s, "header", s->header_color, GIT_COLOR_BOLD);
init_color(r, s, "help", s->help_color, GIT_COLOR_BOLD_RED);
init_color(r, s, "prompt", s->prompt_color, GIT_COLOR_BOLD_BLUE);
init_color(r, s, "error", s->error_color, GIT_COLOR_BOLD_RED);
init_color(r, s, "reset", s->reset_color, GIT_COLOR_RESET);
init_color(r, s, "fraginfo", s->fraginfo_color,
diff_get_color(s->use_color, DIFF_FRAGINFO));
init_color(r, s, "context", s->context_color,
diff_get_color(s->use_color, DIFF_CONTEXT));
init_color(r, s, "old", s->file_old_color,
diff_get_color(s->use_color, DIFF_FILE_OLD));
init_color(r, s, "new", s->file_new_color,
diff_get_color(s->use_color, DIFF_FILE_NEW));
FREE_AND_NULL(s->interactive_diff_filter);
git_config_get_string("interactive.difffilter",
&s->interactive_diff_filter);
FREE_AND_NULL(s->interactive_diff_algorithm);
git_config_get_string("diff.algorithm",
&s->interactive_diff_algorithm);
git_config_get_bool("interactive.singlekey", &s->use_single_key);
}
void clear_add_i_state(struct add_i_state *s)
{
FREE_AND_NULL(s->interactive_diff_filter);
FREE_AND_NULL(s->interactive_diff_algorithm);
memset(s, 0, sizeof(*s));
s->use_color = -1;
}
/*
* A "prefix item list" is a list of items that are identified by a string, and
* a unique prefix (if any) is determined for each item.
*
* It is implemented in the form of a pair of `string_list`s, the first one
* duplicating the strings, with the `util` field pointing at a structure whose
* first field must be `size_t prefix_length`.
*
* That `prefix_length` field will be computed by `find_unique_prefixes()`; It
* will be set to zero if no valid, unique prefix could be found.
*
* The second `string_list` is called `sorted` and does _not_ duplicate the
* strings but simply reuses the first one's, with the `util` field pointing at
* the `string_item_list` of the first `string_list`. It will be populated and
* sorted by `find_unique_prefixes()`.
*/
struct prefix_item_list {
struct string_list items;
struct string_list sorted;
int *selected; /* for multi-selections */
size_t min_length, max_length;
};
#define PREFIX_ITEM_LIST_INIT \
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_NODUP, NULL, 1, 4 }
static void prefix_item_list_clear(struct prefix_item_list *list)
{
string_list_clear(&list->items, 1);
string_list_clear(&list->sorted, 0);
FREE_AND_NULL(list->selected);
}
static void extend_prefix_length(struct string_list_item *p,
const char *other_string, size_t max_length)
{
size_t *len = p->util;
if (!*len || memcmp(p->string, other_string, *len))
return;
for (;;) {
char c = p->string[*len];
/*
* Is `p` a strict prefix of `other`? Or have we exhausted the
* maximal length of the prefix? Or is the current character a
* multi-byte UTF-8 one? If so, there is no valid, unique
* prefix.
*/
if (!c || ++*len > max_length || !isascii(c)) {
*len = 0;
break;
}
if (c != other_string[*len - 1])
break;
}
}
static void find_unique_prefixes(struct prefix_item_list *list)
{
size_t i;
if (list->sorted.nr == list->items.nr)
return;
string_list_clear(&list->sorted, 0);
/* Avoid reallocating incrementally */
list->sorted.items = xmalloc(st_mult(sizeof(*list->sorted.items),
list->items.nr));
list->sorted.nr = list->sorted.alloc = list->items.nr;
for (i = 0; i < list->items.nr; i++) {
list->sorted.items[i].string = list->items.items[i].string;
list->sorted.items[i].util = list->items.items + i;
}
string_list_sort(&list->sorted);
for (i = 0; i < list->sorted.nr; i++) {
struct string_list_item *sorted_item = list->sorted.items + i;
struct string_list_item *item = sorted_item->util;
size_t *len = item->util;
*len = 0;
|