summaryrefslogtreecommitdiff
path: root/attr.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2011-07-06 15:38:18 -0700
committerJunio C Hamano <gitster@pobox.com>2011-07-06 15:38:18 -0700
commit71ee7fd15457a0252c089420b5b66de266dcbd2f (patch)
tree98d4d7d1f72c30fd7695f011be78d3e45158c41a /attr.c
parent4d9e42f8f11c57b32b976a943c8ddaf6214e64b8 (diff)
parente923eaeb901ff056421b9007adcbbce271caa7b6 (diff)
downloadgit-71ee7fd15457a0252c089420b5b66de266dcbd2f.tar.gz
Merge commit 'v1.7.0' into jc/checkout-reflog-fix
* commit 'v1.7.0': (4188 commits) Git 1.7.0 Fix typo in 1.6.6.2 release notes Re-fix check-ref-format documentation mark-up archive documentation: attributes are taken from the tree by default Documentation: minor fixes to RelNotes-1.7.0 bash: support 'git am's new '--continue' option filter-branch: Fix error message for --prune-empty --commit-filter am: switch --resolved to --continue Update draft release notes to 1.7.0 one more time Git 1.6.6.2 t8003: check exit code of command and error message separately check-ref-format documentation: fix enumeration mark-up Documentation: quote braces in {upstream} notation t3902: Protect against OS X normalization blame: prevent a segv when -L given start > EOF git-push: document all the status flags used in the output Fix parsing of imap.preformattedHTML and imap.sslverify git-add documentation: Fix shell quoting example Revert "pack-objects: fix pack generation when using pack_size_limit" archive: simplify archive format guessing ...
Diffstat (limited to 'attr.c')
-rw-r--r--attr.c103
1 files changed, 76 insertions, 27 deletions
diff --git a/attr.c b/attr.c
index 17f6a4dca5..f5346ed32a 100644
--- a/attr.c
+++ b/attr.c
@@ -1,3 +1,4 @@
+#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
#include "attr.h"
@@ -34,8 +35,7 @@ static struct git_attr *(git_attr_hash[HASHSIZE]);
static unsigned hash_name(const char *name, int namelen)
{
- unsigned val = 0;
- unsigned char c;
+ unsigned val = 0, c;
while (namelen--) {
c = *name++;
@@ -65,7 +65,7 @@ static int invalid_attr_name(const char *name, int namelen)
return 0;
}
-struct git_attr *git_attr(const char *name, int len)
+static struct git_attr *git_attr_internal(const char *name, int len)
{
unsigned hval = hash_name(name, len);
unsigned pos = hval % HASHSIZE;
@@ -95,6 +95,11 @@ struct git_attr *git_attr(const char *name, int len)
return a;
}
+struct git_attr *git_attr(const char *name)
+{
+ return git_attr_internal(name, strlen(name));
+}
+
/*
* .gitattributes file is one line per record, each of which is
*
@@ -162,7 +167,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
else {
e->setto = xmemdupz(equals + 1, ep - equals - 1);
}
- e->attr = git_attr(cp, len);
+ e->attr = git_attr_internal(cp, len);
}
(*num_attr)++;
return ep + strspn(ep, blank);
@@ -221,9 +226,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
sizeof(struct attr_state) * num_attr +
(is_macro ? 0 : namelen + 1));
if (is_macro)
- res->u.attr = git_attr(name, namelen);
+ res->u.attr = git_attr_internal(name, namelen);
else {
- res->u.pattern = (char*)&(res->state[num_attr]);
+ res->u.pattern = (char *)&(res->state[num_attr]);
memcpy(res->u.pattern, name, namelen);
res->u.pattern[namelen] = 0;
}
@@ -274,7 +279,7 @@ static void free_attr_elem(struct attr_stack *e)
setto == ATTR__UNKNOWN)
;
else
- free((char*) setto);
+ free((char *) setto);
}
free(a);
}
@@ -318,6 +323,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 +348,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 +359,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 +375,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 +400,32 @@ 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 if (direction == GIT_ATTR_CHECKIN) {
+ 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);
+ }
+ else
+ 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 +453,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) {
@@ -438,7 +472,7 @@ static void bootstrap_attr_stack(void)
elem->prev = attr_stack;
attr_stack = elem;
- if (!is_bare_repository()) {
+ if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
elem = read_attr(GITATTRIBUTES_FILE, 1);
elem->origin = strdup("");
elem->prev = attr_stack;
@@ -505,7 +539,7 @@ static void prepare_attr_stack(const char *path, int dirlen)
/*
* Read from parent directories and push them down
*/
- if (!is_bare_repository()) {
+ if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
while (1) {
char *cp;
@@ -526,6 +560,8 @@ static void prepare_attr_stack(const char *path, int dirlen)
}
}
+ strbuf_release(&pathbuf);
+
/*
* Finally push the "info" one at the top of the stack.
*/
@@ -642,3 +678,16 @@ 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;
+
+ if (is_bare_repository() && new != GIT_ATTR_INDEX)
+ die("BUG: non-INDEX attr direction in a bare repo");
+
+ direction = new;
+ if (new != old)
+ drop_attr_stack();
+ use_index = istate;
+}