@matheusbsbs / matheus-bagliano / commits / 06f33c1735
Fork 0

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>

Junio C Hamano committed Mar 13, 2009 at 21:24 UTC 06f33c1735bf76e02f3e2601cde5161e969872a7
3 files changed +64 -18
attr.c
+55 -18
@@ -1,3 +1,4 @@
1 +#define NO_THE_INDEX_COMPATIBILITY_MACROS
2 #include "cache.h"
3 #include "attr.h"
4
@@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
319 return res;
320 }
321
322 +static enum git_attr_direction direction;
323 +static struct index_state *use_index;
324 +
325 static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
326 {
327 FILE *fp = fopen(path, "r");
@@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
344 unsigned long sz;
345 enum object_type type;
346 void *data;
347 + struct index_state *istate = use_index ? use_index : &the_index;
348
349 len = strlen(path);
345 - pos = cache_name_pos(path, len);
350 + pos = index_name_pos(istate, path, len);
351 if (pos < 0) {
352 /*
353 * We might be in the middle of a merge, in which
@@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
355 */
356 int i;
357 for (i = -pos - 1;
353 - (pos < 0 && i < active_nr &&
354 - !strcmp(active_cache[i]->name, path));
358 + (pos < 0 && i < istate->cache_nr &&
359 + !strcmp(istate->cache[i]->name, path));
360 i++)
356 - if (ce_stage(active_cache[i]) == 2)
361 + if (ce_stage(istate->cache[i]) == 2)
362 pos = i;
363 }
364 if (pos < 0)
365 return NULL;
361 - data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
366 + data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
367 if (!data || type != OBJ_BLOB) {
368 free(data);
369 return NULL;
@@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
371 return data;
372 }
373
369 -static struct attr_stack *read_attr(const char *path, int macro_ok)
374 +static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
375 {
376 struct attr_stack *res;
377 char *buf, *sp;
378 int lineno = 0;
379
375 - res = read_attr_from_file(path, macro_ok);
376 - if (res)
377 - return res;
378 -
379 - res = xcalloc(1, sizeof(*res));
380 -
381 - /*
382 - * There is no checked out .gitattributes file there, but
383 - * we might have it in the index. We allow operation in a
384 - * sparsely checked out work tree, so read from it.
385 - */
380 buf = read_index_data(path);
381 if (!buf)
388 - return res;
382 + return NULL;
383
384 + res = xcalloc(1, sizeof(*res));
385 for (sp = buf; *sp; ) {
386 char *ep;
387 int more;
@@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
396 return res;
397 }
398
399 +static struct attr_stack *read_attr(const char *path, int macro_ok)
400 +{
401 + struct attr_stack *res;
402 +
403 + if (direction == GIT_ATTR_CHECKOUT) {
404 + res = read_attr_from_index(path, macro_ok);
405 + if (!res)
406 + res = read_attr_from_file(path, macro_ok);
407 + }
408 + else {
409 + res = read_attr_from_file(path, macro_ok);
410 + if (!res)
411 + /*
412 + * There is no checked out .gitattributes file there, but
413 + * we might have it in the index. We allow operation in a
414 + * sparsely checked out work tree, so read from it.
415 + */
416 + res = read_attr_from_index(path, macro_ok);
417 + }
418 + if (!res)
419 + res = xcalloc(1, sizeof(*res));
420 + return res;
421 +}
422 +
423 #if DEBUG_ATTR
424 static void debug_info(const char *what, struct attr_stack *elem)
425 {
@@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
447 #define debug_set(a,b,c,d) do { ; } while (0)
448 #endif
449
450 +static void drop_attr_stack(void)
451 +{
452 + while (attr_stack) {
453 + struct attr_stack *elem = attr_stack;
454 + attr_stack = elem->prev;
455 + free_attr_elem(elem);
456 + }
457 +}
458 +
459 static void bootstrap_attr_stack(void)
460 {
461 if (!attr_stack) {
@@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
670
671 return 0;
672 }
673 +
674 +void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
675 +{
676 + enum git_attr_direction old = direction;
677 + direction = new;
678 + if (new != old)
679 + drop_attr_stack();
680 + use_index = istate;
681 +}
attr.h
+6
@@ -31,4 +31,10 @@ struct git_attr_check {
31
32 int git_checkattr(const char *path, int, struct git_attr_check *);
33
34 +enum git_attr_direction {
35 + GIT_ATTR_CHECKIN,
36 + GIT_ATTR_CHECKOUT
37 +};
38 +void git_attr_set_direction(enum git_attr_direction, struct index_state *);
39 +
40 #endif /* ATTR_H */
unpack-trees.c
+3
@@ -7,6 +7,7 @@
7 #include "unpack-trees.h"
8 #include "progress.h"
9 #include "refs.h"
10 +#include "attr.h"
11
12 /*
13 * Error messages expected by scripts out of plumbing commands such as
@@ -105,6 +106,7 @@ static int check_updates(struct unpack_trees_options *o)
106 cnt = 0;
107 }
108
109 + git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
110 for (i = 0; i < index->cache_nr; i++) {
111 struct cache_entry *ce = index->cache[i];
112
@@ -130,6 +132,7 @@ static int check_updates(struct unpack_trees_options *o)
132 }
133 }
134 stop_progress(&progress);
135 + git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
136 return errs != 0;
137 }
138