зеркало из https://github.com/microsoft/git.git
Read attributes from the index that is being checked out
Traditionally we used .gitattributes file from the work tree if exists, and otherwise read from the index as a fallback. When switching to a branch that has an updated .gitattributes file, and entries in it give different attributes to other paths being checked out, we should instead read from the .gitattributes in the index. This breaks a use case of fixing incorrect entries in the .gitattributes in the work tree (without adding it to the index) and checking other paths out, though. $ edit .gitattributes ;# mark foo.dat as binary $ rm foo.dat $ git checkout foo.dat Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
924189d6a2
Коммит
06f33c1735
73
attr.c
73
attr.c
|
@ -1,3 +1,4 @@
|
|||
#define NO_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "cache.h"
|
||||
#include "attr.h"
|
||||
|
||||
|
@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
|
|||
return res;
|
||||
}
|
||||
|
||||
static enum git_attr_direction direction;
|
||||
static struct index_state *use_index;
|
||||
|
||||
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
|
||||
{
|
||||
FILE *fp = fopen(path, "r");
|
||||
|
@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
|
|||
unsigned long sz;
|
||||
enum object_type type;
|
||||
void *data;
|
||||
struct index_state *istate = use_index ? use_index : &the_index;
|
||||
|
||||
len = strlen(path);
|
||||
pos = cache_name_pos(path, len);
|
||||
pos = index_name_pos(istate, path, len);
|
||||
if (pos < 0) {
|
||||
/*
|
||||
* We might be in the middle of a merge, in which
|
||||
|
@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
|
|||
*/
|
||||
int i;
|
||||
for (i = -pos - 1;
|
||||
(pos < 0 && i < active_nr &&
|
||||
!strcmp(active_cache[i]->name, path));
|
||||
(pos < 0 && i < istate->cache_nr &&
|
||||
!strcmp(istate->cache[i]->name, path));
|
||||
i++)
|
||||
if (ce_stage(active_cache[i]) == 2)
|
||||
if (ce_stage(istate->cache[i]) == 2)
|
||||
pos = i;
|
||||
}
|
||||
if (pos < 0)
|
||||
return NULL;
|
||||
data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
|
||||
data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
|
||||
if (!data || type != OBJ_BLOB) {
|
||||
free(data);
|
||||
return NULL;
|
||||
|
@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
|
|||
return data;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
char *buf, *sp;
|
||||
int lineno = 0;
|
||||
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
buf = read_index_data(path);
|
||||
if (!buf)
|
||||
return res;
|
||||
return NULL;
|
||||
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
for (sp = buf; *sp; ) {
|
||||
char *ep;
|
||||
int more;
|
||||
|
@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const char *path, int macro_ok)
|
||||
{
|
||||
struct attr_stack *res;
|
||||
|
||||
if (direction == GIT_ATTR_CHECKOUT) {
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
if (!res)
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
}
|
||||
else {
|
||||
res = read_attr_from_file(path, macro_ok);
|
||||
if (!res)
|
||||
/*
|
||||
* There is no checked out .gitattributes file there, but
|
||||
* we might have it in the index. We allow operation in a
|
||||
* sparsely checked out work tree, so read from it.
|
||||
*/
|
||||
res = read_attr_from_index(path, macro_ok);
|
||||
}
|
||||
if (!res)
|
||||
res = xcalloc(1, sizeof(*res));
|
||||
return res;
|
||||
}
|
||||
|
||||
#if DEBUG_ATTR
|
||||
static void debug_info(const char *what, struct attr_stack *elem)
|
||||
{
|
||||
|
@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
|
|||
#define debug_set(a,b,c,d) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
static void drop_attr_stack(void)
|
||||
{
|
||||
while (attr_stack) {
|
||||
struct attr_stack *elem = attr_stack;
|
||||
attr_stack = elem->prev;
|
||||
free_attr_elem(elem);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootstrap_attr_stack(void)
|
||||
{
|
||||
if (!attr_stack) {
|
||||
|
@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
|
||||
{
|
||||
enum git_attr_direction old = direction;
|
||||
direction = new;
|
||||
if (new != old)
|
||||
drop_attr_stack();
|
||||
use_index = istate;
|
||||
}
|
||||
|
|
6
attr.h
6
attr.h
|
@ -31,4 +31,10 @@ struct git_attr_check {
|
|||
|
||||
int git_checkattr(const char *path, int, struct git_attr_check *);
|
||||
|
||||
enum git_attr_direction {
|
||||
GIT_ATTR_CHECKIN,
|
||||
GIT_ATTR_CHECKOUT
|
||||
};
|
||||
void git_attr_set_direction(enum git_attr_direction, struct index_state *);
|
||||
|
||||
#endif /* ATTR_H */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "unpack-trees.h"
|
||||
#include "progress.h"
|
||||
#include "refs.h"
|
||||
#include "attr.h"
|
||||
|
||||
/*
|
||||
* Error messages expected by scripts out of plumbing commands such as
|
||||
|
@ -105,6 +106,7 @@ static int check_updates(struct unpack_trees_options *o)
|
|||
cnt = 0;
|
||||
}
|
||||
|
||||
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
|
||||
for (i = 0; i < index->cache_nr; i++) {
|
||||
struct cache_entry *ce = index->cache[i];
|
||||
|
||||
|
@ -130,6 +132,7 @@ static int check_updates(struct unpack_trees_options *o)
|
|||
}
|
||||
}
|
||||
stop_progress(&progress);
|
||||
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
|
||||
return errs != 0;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче