diff --git a/attr.c b/attr.c index 8d778f1d26..129399310a 100644 --- a/attr.c +++ b/attr.c @@ -336,13 +336,70 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) return res; } +static void *read_index_data(const char *path) +{ + int pos, len; + unsigned long sz; + enum object_type type; + void *data; + + len = strlen(path); + pos = cache_name_pos(path, len); + if (pos < 0) { + /* + * We might be in the middle of a merge, in which + * case we would read stage #2 (ours). + */ + int i; + for (i = -pos - 1; + (pos < 0 && i < active_nr && + !strcmp(active_cache[i]->name, path)); + i++) + if (ce_stage(active_cache[i]) == 2) + pos = i; + } + if (pos < 0) + return NULL; + data = read_sha1_file(active_cache[pos]->sha1, &type, &sz); + if (!data || type != OBJ_BLOB) { + free(data); + return NULL; + } + return data; +} + static struct attr_stack *read_attr(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) - res = xcalloc(1, sizeof(*res)); + 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; + + for (sp = buf; *sp; ) { + char *ep; + int more; + for (ep = sp; *ep && *ep != '\n'; ep++) + ; + more = (*ep == '\n'); + *ep = '\0'; + handle_attr_line(res, sp, path, ++lineno, macro_ok); + sp = ep + more; + } + free(buf); return res; } diff --git a/entry.c b/entry.c index 0625112339..fc3a506ece 100644 --- a/entry.c +++ b/entry.c @@ -112,6 +112,16 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout if (!new) return error("git-checkout-index: unable to read sha1 file of %s (%s)", path, sha1_to_hex(ce->sha1)); + + /* + * Convert from git internal format to working tree format + */ + buf = convert_to_working_tree(ce->name, new, &size); + if (buf) { + free(new); + new = buf; + } + if (to_tempfile) { strcpy(path, ".merge_file_XXXXXX"); fd = mkstemp(path); @@ -123,15 +133,6 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout path, strerror(errno)); } - /* - * Convert from git internal format to working tree format - */ - buf = convert_to_working_tree(ce->name, new, &size); - if (buf) { - free(new); - new = buf; - } - wrote = write_in_full(fd, new, size); close(fd); free(new); diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index fe1dfd08a0..0807d9f01a 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -290,4 +290,85 @@ test_expect_success '.gitattributes says two and three are text' ' fi ' +test_expect_success 'in-tree .gitattributes (1)' ' + + echo "one -crlf" >>.gitattributes && + git add .gitattributes && + git commit -m "Add .gitattributes" && + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset -u HEAD && + + if remove_cr one >/dev/null + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + remove_cr three >/dev/null || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (2)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -f -q -u -a && + + if remove_cr one >/dev/null + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + remove_cr three >/dev/null || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (3)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -u .gitattributes && + git checkout-index -u one dir/two three && + + if remove_cr one >/dev/null + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + remove_cr three >/dev/null || { + echo "Eh? three should still have CRLF" + false + } +' + +test_expect_success 'in-tree .gitattributes (4)' ' + + rm -rf tmp one dir .gitattributes patch.file three && + git read-tree --reset HEAD && + git checkout-index -u one dir/two three && + git checkout-index -u .gitattributes && + + if remove_cr one >/dev/null + then + echo "Eh? one should not have CRLF" + false + else + : happy + fi && + remove_cr three >/dev/null || { + echo "Eh? three should still have CRLF" + false + } +' + test_done