Merge branch 'jc/attributes-checkout'

* jc/attributes-checkout:
  Add a test for checking whether gitattributes is honored by checkout.
  Read attributes from the index that is being checked out
This commit is contained in:
Junio C Hamano 2009-03-26 00:27:33 -07:00
commit 6ba8b079cb
4 changed files with 95 additions and 18 deletions

73
attr.c
View file

@ -1,3 +1,4 @@
#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h" #include "cache.h"
#include "attr.h" #include "attr.h"
@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
return res; 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) static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
{ {
FILE *fp = fopen(path, "r"); FILE *fp = fopen(path, "r");
@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
unsigned long sz; unsigned long sz;
enum object_type type; enum object_type type;
void *data; void *data;
struct index_state *istate = use_index ? use_index : &the_index;
len = strlen(path); len = strlen(path);
pos = cache_name_pos(path, len); pos = index_name_pos(istate, path, len);
if (pos < 0) { if (pos < 0) {
/* /*
* We might be in the middle of a merge, in which * 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; int i;
for (i = -pos - 1; for (i = -pos - 1;
(pos < 0 && i < active_nr && (pos < 0 && i < istate->cache_nr &&
!strcmp(active_cache[i]->name, path)); !strcmp(istate->cache[i]->name, path));
i++) i++)
if (ce_stage(active_cache[i]) == 2) if (ce_stage(istate->cache[i]) == 2)
pos = i; pos = i;
} }
if (pos < 0) if (pos < 0)
return NULL; 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) { if (!data || type != OBJ_BLOB) {
free(data); free(data);
return NULL; return NULL;
@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
return data; 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; struct attr_stack *res;
char *buf, *sp; char *buf, *sp;
int lineno = 0; 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); buf = read_index_data(path);
if (!buf) if (!buf)
return res; return NULL;
res = xcalloc(1, sizeof(*res));
for (sp = buf; *sp; ) { for (sp = buf; *sp; ) {
char *ep; char *ep;
int more; int more;
@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
return res; 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 #if DEBUG_ATTR
static void debug_info(const char *what, struct attr_stack *elem) 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) #define debug_set(a,b,c,d) do { ; } while (0)
#endif #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) static void bootstrap_attr_stack(void)
{ {
if (!attr_stack) { if (!attr_stack) {
@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
return 0; 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
View file

@ -31,4 +31,10 @@ struct git_attr_check {
int git_checkattr(const char *path, int, 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 */ #endif /* ATTR_H */

View file

@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' '
} }
' '
test_expect_success 'checkout with existing .gitattributes' '
git config core.autocrlf true &&
git config --unset core.safecrlf &&
echo ".file2 -crlfQ" | q_to_cr >> .gitattributes &&
git add .gitattributes &&
git commit -m initial &&
echo ".file -crlfQ" | q_to_cr >> .gitattributes &&
echo "contents" > .file &&
git add .gitattributes .file &&
git commit -m second &&
git checkout master~1 &&
git checkout master &&
test "$(git diff-files --raw)" = ""
'
test_expect_success 'checkout when deleting .gitattributes' '
git rm .gitattributes &&
echo "contentsQ" | q_to_cr > .file2 &&
git add .file2 &&
git commit -m third
git checkout master~1 &&
git checkout master &&
remove_cr .file2 >/dev/null
'
test_expect_success 'invalid .gitattributes (must not crash)' ' test_expect_success 'invalid .gitattributes (must not crash)' '
echo "three +crlf" >>.gitattributes && echo "three +crlf" >>.gitattributes &&

View file

@ -7,6 +7,7 @@
#include "unpack-trees.h" #include "unpack-trees.h"
#include "progress.h" #include "progress.h"
#include "refs.h" #include "refs.h"
#include "attr.h"
/* /*
* Error messages expected by scripts out of plumbing commands such as * Error messages expected by scripts out of plumbing commands such as
@ -86,6 +87,7 @@ static int check_updates(struct unpack_trees_options *o)
cnt = 0; cnt = 0;
} }
git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
for (i = 0; i < index->cache_nr; i++) { for (i = 0; i < index->cache_nr; i++) {
struct cache_entry *ce = index->cache[i]; struct cache_entry *ce = index->cache[i];
@ -110,6 +112,7 @@ static int check_updates(struct unpack_trees_options *o)
} }
} }
stop_progress(&progress); stop_progress(&progress);
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
return errs != 0; return errs != 0;
} }