attr: remove an implicit dependency on the_index

Make the attr API take an index_state instead of assuming the_index in
attr code. All call sites are converted blindly to keep the patch
simple and retain current behavior. Individual call sites may receive
further updates to use the right index instead of the_index.

There is one ugly temporary workaround added in attr.c that needs some
more explanation.

Commit c24f3abace (apply: file commited with CRLF should roundtrip
diff and apply - 2017-08-19) forces one convert_to_git() call to NOT
read the index at all. But what do you know, we read it anyway by
falling back to the_index. When "istate" from convert_to_git is now
propagated down to read_attr_from_array() we will hit segfault
somewhere inside read_blob_data_from_index.

The right way of dealing with this is to kill "use_index" variable and
only follow "istate" but at this stage we are not ready for that:
while most git_attr_set_direction() calls just passes the_index to be
assigned to use_index, unpack-trees passes a different one which is
used by entry.c code, which has no way to know what index to use if we
delete use_index. So this has to be done later.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2018-08-13 18:14:20 +02:00 committed by Junio C Hamano
parent 07096c9696
commit 7a400a2c02
10 changed files with 55 additions and 32 deletions

View File

@ -109,7 +109,7 @@ static const struct attr_check *get_archive_attrs(const char *path)
static struct attr_check *check; static struct attr_check *check;
if (!check) if (!check)
check = attr_check_initl("export-ignore", "export-subst", NULL); check = attr_check_initl("export-ignore", "export-subst", NULL);
return git_check_attr(path, check) ? NULL : check; return git_check_attr(&the_index, path, check) ? NULL : check;
} }
static int check_attr_export_ignore(const struct attr_check *check) static int check_attr_export_ignore(const struct attr_check *check)

57
attr.c
View File

@ -708,10 +708,10 @@ static struct attr_stack *read_attr_from_array(const char **list)
* another thread could potentially be calling into the attribute system. * another thread could potentially be calling into the attribute system.
*/ */
static enum git_attr_direction direction; static enum git_attr_direction direction;
static struct index_state *use_index; static const struct index_state *use_index;
void git_attr_set_direction(enum git_attr_direction new_direction, void git_attr_set_direction(enum git_attr_direction new_direction,
struct index_state *istate) const struct index_state *istate)
{ {
if (is_bare_repository() && new_direction != GIT_ATTR_INDEX) if (is_bare_repository() && new_direction != GIT_ATTR_INDEX)
BUG("non-INDEX attr direction in a bare repo"); BUG("non-INDEX attr direction in a bare repo");
@ -743,13 +743,24 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
return res; return res;
} }
static struct attr_stack *read_attr_from_index(const char *path, int macro_ok) static struct attr_stack *read_attr_from_index(const struct index_state *istate,
const char *path,
int macro_ok)
{ {
struct attr_stack *res; struct attr_stack *res;
char *buf, *sp; char *buf, *sp;
int lineno = 0; int lineno = 0;
const struct index_state *to_read_from;
buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL); /*
* Temporary workaround for c24f3abace (apply: file commited
* with CRLF should roundtrip diff and apply - 2017-08-19)
*/
to_read_from = use_index ? use_index : istate;
if (!to_read_from)
return NULL;
buf = read_blob_data_from_index(to_read_from, path, NULL);
if (!buf) if (!buf)
return NULL; return NULL;
@ -768,15 +779,16 @@ static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
return res; return res;
} }
static struct attr_stack *read_attr(const char *path, int macro_ok) static struct attr_stack *read_attr(const struct index_state *istate,
const char *path, int macro_ok)
{ {
struct attr_stack *res = NULL; struct attr_stack *res = NULL;
if (direction == GIT_ATTR_INDEX) { if (direction == GIT_ATTR_INDEX) {
res = read_attr_from_index(path, macro_ok); res = read_attr_from_index(istate, path, macro_ok);
} else if (!is_bare_repository()) { } else if (!is_bare_repository()) {
if (direction == GIT_ATTR_CHECKOUT) { if (direction == GIT_ATTR_CHECKOUT) {
res = read_attr_from_index(path, macro_ok); res = read_attr_from_index(istate, path, macro_ok);
if (!res) if (!res)
res = read_attr_from_file(path, macro_ok); res = read_attr_from_file(path, macro_ok);
} else if (direction == GIT_ATTR_CHECKIN) { } else if (direction == GIT_ATTR_CHECKIN) {
@ -788,7 +800,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
* We allow operation in a sparsely checked out * We allow operation in a sparsely checked out
* work tree, so read from it. * work tree, so read from it.
*/ */
res = read_attr_from_index(path, macro_ok); res = read_attr_from_index(istate, path, macro_ok);
} }
} }
@ -859,7 +871,8 @@ static void push_stack(struct attr_stack **attr_stack_p,
} }
} }
static void bootstrap_attr_stack(struct attr_stack **stack) static void bootstrap_attr_stack(const struct index_state *istate,
struct attr_stack **stack)
{ {
struct attr_stack *e; struct attr_stack *e;
@ -883,7 +896,7 @@ static void bootstrap_attr_stack(struct attr_stack **stack)
} }
/* root directory */ /* root directory */
e = read_attr(GITATTRIBUTES_FILE, 1); e = read_attr(istate, GITATTRIBUTES_FILE, 1);
push_stack(stack, e, xstrdup(""), 0); push_stack(stack, e, xstrdup(""), 0);
/* info frame */ /* info frame */
@ -896,7 +909,8 @@ static void bootstrap_attr_stack(struct attr_stack **stack)
push_stack(stack, e, NULL, 0); push_stack(stack, e, NULL, 0);
} }
static void prepare_attr_stack(const char *path, int dirlen, static void prepare_attr_stack(const struct index_state *istate,
const char *path, int dirlen,
struct attr_stack **stack) struct attr_stack **stack)
{ {
struct attr_stack *info; struct attr_stack *info;
@ -917,7 +931,7 @@ static void prepare_attr_stack(const char *path, int dirlen,
* .gitattributes in deeper directories to shallower ones, * .gitattributes in deeper directories to shallower ones,
* and finally use the built-in set as the default. * and finally use the built-in set as the default.
*/ */
bootstrap_attr_stack(stack); bootstrap_attr_stack(istate, stack);
/* /*
* Pop the "info" one that is always at the top of the stack. * Pop the "info" one that is always at the top of the stack.
@ -973,7 +987,7 @@ static void prepare_attr_stack(const char *path, int dirlen,
strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len)); strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE); strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
next = read_attr(pathbuf.buf, 0); next = read_attr(istate, pathbuf.buf, 0);
/* reset the pathbuf to not include "/.gitattributes" */ /* reset the pathbuf to not include "/.gitattributes" */
strbuf_setlen(&pathbuf, len); strbuf_setlen(&pathbuf, len);
@ -1095,7 +1109,9 @@ static void determine_macros(struct all_attrs_item *all_attrs,
* If check->check_nr is non-zero, only attributes in check[] are collected. * If check->check_nr is non-zero, only attributes in check[] are collected.
* Otherwise all attributes are collected. * Otherwise all attributes are collected.
*/ */
static void collect_some_attrs(const char *path, struct attr_check *check) static void collect_some_attrs(const struct index_state *istate,
const char *path,
struct attr_check *check)
{ {
int i, pathlen, rem, dirlen; int i, pathlen, rem, dirlen;
const char *cp, *last_slash = NULL; const char *cp, *last_slash = NULL;
@ -1114,7 +1130,7 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
dirlen = 0; dirlen = 0;
} }
prepare_attr_stack(path, dirlen, &check->stack); prepare_attr_stack(istate, path, dirlen, &check->stack);
all_attrs_init(&g_attr_hashmap, check); all_attrs_init(&g_attr_hashmap, check);
determine_macros(check->all_attrs, check->stack); determine_macros(check->all_attrs, check->stack);
@ -1136,11 +1152,13 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem); fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
} }
int git_check_attr(const char *path, struct attr_check *check) int git_check_attr(const struct index_state *istate,
const char *path,
struct attr_check *check)
{ {
int i; int i;
collect_some_attrs(path, check); collect_some_attrs(istate, path, check);
for (i = 0; i < check->nr; i++) { for (i = 0; i < check->nr; i++) {
size_t n = check->items[i].attr->attr_nr; size_t n = check->items[i].attr->attr_nr;
@ -1153,12 +1171,13 @@ int git_check_attr(const char *path, struct attr_check *check)
return 0; return 0;
} }
void git_all_attrs(const char *path, struct attr_check *check) void git_all_attrs(const struct index_state *istate,
const char *path, struct attr_check *check)
{ {
int i; int i;
attr_check_reset(check); attr_check_reset(check);
collect_some_attrs(path, check); collect_some_attrs(istate, path, check);
for (i = 0; i < check->all_attrs_nr; i++) { for (i = 0; i < check->all_attrs_nr; i++) {
const char *name = check->all_attrs[i].attr->name; const char *name = check->all_attrs[i].attr->name;

10
attr.h
View File

@ -1,6 +1,8 @@
#ifndef ATTR_H #ifndef ATTR_H
#define ATTR_H #define ATTR_H
struct index_state;
/* An attribute is a pointer to this opaque structure */ /* An attribute is a pointer to this opaque structure */
struct git_attr; struct git_attr;
@ -60,13 +62,15 @@ void attr_check_free(struct attr_check *check);
*/ */
const char *git_attr_name(const struct git_attr *); const char *git_attr_name(const struct git_attr *);
int git_check_attr(const char *path, struct attr_check *check); int git_check_attr(const struct index_state *istate,
const char *path, struct attr_check *check);
/* /*
* Retrieve all attributes that apply to the specified path. * Retrieve all attributes that apply to the specified path.
* check holds the attributes and their values. * check holds the attributes and their values.
*/ */
void git_all_attrs(const char *path, struct attr_check *check); void git_all_attrs(const struct index_state *istate,
const char *path, struct attr_check *check);
enum git_attr_direction { enum git_attr_direction {
GIT_ATTR_CHECKIN, GIT_ATTR_CHECKIN,
@ -74,7 +78,7 @@ enum git_attr_direction {
GIT_ATTR_INDEX GIT_ATTR_INDEX
}; };
void git_attr_set_direction(enum git_attr_direction new_direction, void git_attr_set_direction(enum git_attr_direction new_direction,
struct index_state *istate); const struct index_state *istate);
void attr_start(void); void attr_start(void);

View File

@ -63,9 +63,9 @@ static void check_attr(const char *prefix,
prefix_path(prefix, prefix ? strlen(prefix) : 0, file); prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
if (collect_all) { if (collect_all) {
git_all_attrs(full_path, check); git_all_attrs(&the_index, full_path, check);
} else { } else {
if (git_check_attr(full_path, check)) if (git_check_attr(&the_index, full_path, check))
die("git_check_attr died"); die("git_check_attr died");
} }
output_attr(check, file); output_attr(check, file);

View File

@ -945,7 +945,7 @@ static int no_try_delta(const char *path)
if (!check) if (!check)
check = attr_check_initl("delta", NULL); check = attr_check_initl("delta", NULL);
if (git_check_attr(path, check)) if (git_check_attr(&the_index, path, check))
return 0; return 0;
if (ATTR_FALSE(check->items[0].value)) if (ATTR_FALSE(check->items[0].value))
return 1; return 1;

View File

@ -1303,7 +1303,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
git_config(read_convert_config, NULL); git_config(read_convert_config, NULL);
} }
if (!git_check_attr(path, check)) { if (!git_check_attr(&the_index, path, check)) {
struct attr_check_item *ccheck = check->items; struct attr_check_item *ccheck = check->items;
ca->crlf_action = git_path_check_crlf(ccheck + 4); ca->crlf_action = git_path_check_crlf(ccheck + 4);
if (ca->crlf_action == CRLF_UNDEFINED) if (ca->crlf_action == CRLF_UNDEFINED)

2
dir.c
View File

@ -281,7 +281,7 @@ static int match_attrs(const char *name, int namelen,
{ {
int i; int i;
git_check_attr(name, item->attr_check); git_check_attr(&the_index, name, item->attr_check);
for (i = 0; i < item->attr_match_nr; i++) { for (i = 0; i < item->attr_match_nr; i++) {
const char *value; const char *value;
int matched; int matched;

View File

@ -371,7 +371,7 @@ int ll_merge(mmbuffer_t *result_buf,
if (!check) if (!check)
check = attr_check_initl("merge", "conflict-marker-size", NULL); check = attr_check_initl("merge", "conflict-marker-size", NULL);
if (!git_check_attr(path, check)) { if (!git_check_attr(&the_index, path, check)) {
ll_driver_name = check->items[0].value; ll_driver_name = check->items[0].value;
if (check->items[1].value) { if (check->items[1].value) {
marker_size = atoi(check->items[1].value); marker_size = atoi(check->items[1].value);
@ -398,7 +398,7 @@ int ll_merge_marker_size(const char *path)
if (!check) if (!check)
check = attr_check_initl("conflict-marker-size", NULL); check = attr_check_initl("conflict-marker-size", NULL);
if (!git_check_attr(path, check) && check->items[0].value) { if (!git_check_attr(&the_index, path, check) && check->items[0].value) {
marker_size = atoi(check->items[0].value); marker_size = atoi(check->items[0].value);
if (marker_size <= 0) if (marker_size <= 0)
marker_size = DEFAULT_CONFLICT_MARKER_SIZE; marker_size = DEFAULT_CONFLICT_MARKER_SIZE;

View File

@ -278,7 +278,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)
check = attr_check_initl("diff", NULL); check = attr_check_initl("diff", NULL);
if (!path) if (!path)
return NULL; return NULL;
if (git_check_attr(path, check)) if (git_check_attr(&the_index, path, check))
return NULL; return NULL;
if (ATTR_TRUE(check->items[0].value)) if (ATTR_TRUE(check->items[0].value))

2
ws.c
View File

@ -78,7 +78,7 @@ unsigned whitespace_rule(const char *pathname)
if (!attr_whitespace_rule) if (!attr_whitespace_rule)
attr_whitespace_rule = attr_check_initl("whitespace", NULL); attr_whitespace_rule = attr_check_initl("whitespace", NULL);
if (!git_check_attr(pathname, attr_whitespace_rule)) { if (!git_check_attr(&the_index, pathname, attr_whitespace_rule)) {
const char *value; const char *value;
value = attr_whitespace_rule->items[0].value; value = attr_whitespace_rule->items[0].value;