qOn Tue, Mar 26, 2013 at 11:39:27AM -0700, Junio C Hamano wrote:
> So here is an attempt to fix the unintended regression, on top of
> 9db9eecfe5c2 (attr: avoid calling find_basename() twice per path,
> 2013-01-16). It consists of four patches.
Not that I disagree with this. Just wanted to see how far the "dtype"
idea went. How about this? git_check_attr() now takes dtype as an
argument and the caller must not add the trailing slash. This could be
split into two patches, one for git_check_attr prototype change, and
the other the real meat.
-- 8< --
diff --git a/archive.c b/archive.c
index 93e00bb..ab811b3 100644
--- a/archive.c
+++ b/archive.c
@@ -112,7 +112,7 @@ static int write_archive_entry(const unsigned char *sha1,
const char *base,
write_archive_entry_fn_t write_entry = c->write_entry;
struct git_attr_check check[2];
const char *path_without_prefix;
- int err;
+ int err, dtype;
args->convert = 0;
strbuf_reset(&path);
@@ -120,18 +120,18 @@ static int write_archive_entry(const unsigned char *sha1,
const char *base,
strbuf_add(&path, args->base, args->baselen);
strbuf_add(&path, base, baselen);
strbuf_addstr(&path, filename);
- if (S_ISDIR(mode) || S_ISGITLINK(mode))
- strbuf_addch(&path, '/');
+ dtype = S_ISDIR(mode) || S_ISGITLINK(mode) ? DT_DIR : DT_REG;
path_without_prefix = path.buf + args->baselen;
setup_archive_check(check);
- if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
+ if (!git_check_attr(path_without_prefix, dtype, ARRAY_SIZE(check),
check)) {
if (ATTR_TRUE(check[0].value))
return 0;
args->convert = ATTR_TRUE(check[1].value);
}
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
+ strbuf_addch(&path, '/');
if (args->verbose)
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
err = write_entry(args, sha1, path.buf, path.len, mode);
diff --git a/attr.c b/attr.c
index e2f9377..ab6422c 100644
--- a/attr.c
+++ b/attr.c
@@ -255,6 +255,8 @@ static struct match_attr *parse_attr_line(const char *line,
const char *src,
&res->u.pat.patternlen,
&res->u.pat.flags,
&res->u.pat.nowildcardlen);
+ if (res->u.pat.flags & EXC_FLAG_MUSTBEDIR)
+ p[res->u.pat.patternlen] = '\0';
if (res->u.pat.flags & EXC_FLAG_NEGATIVE) {
warning(_("Negative patterns are ignored in git
attributes\n"
"Use '\\!' for literal leading
exclamation."));
@@ -657,15 +659,14 @@ static void prepare_attr_stack(const char *path, int
dirlen)
}
static int path_matches(const char *pathname, int pathlen,
- const char *basename,
+ const char *basename, int dtype,
const struct pattern *pat,
const char *base, int baselen)
{
const char *pattern = pat->pattern;
int prefix = pat->nowildcardlen;
- if ((pat->flags & EXC_FLAG_MUSTBEDIR) &&
- ((!pathlen) || (pathname[pathlen-1] != '/')))
+ if ((pat->flags & EXC_FLAG_MUSTBEDIR) && dtype != DT_DIR)
return 0;
if (pat->flags & EXC_FLAG_NODIR) {
@@ -704,7 +705,7 @@ static int fill_one(const char *what, struct match_attr *a,
int rem)
}
static int fill(const char *path, int pathlen, const char *basename,
- struct attr_stack *stk, int rem)
+ int dtype, struct attr_stack *stk, int rem)
{
int i;
const char *base = stk->origin ? stk->origin : "";
@@ -713,7 +714,7 @@ static int fill(const char *path, int pathlen, const char
*basename,
struct match_attr *a = stk->attrs[i];
if (a->is_macro)
continue;
- if (path_matches(path, pathlen, basename,
+ if (path_matches(path, pathlen, basename, dtype,
&a->u.pat, base, stk->originlen))
rem = fill_one("fill", a, rem);
}
@@ -748,20 +749,17 @@ static int macroexpand_one(int attr_nr, int rem)
* Collect all attributes for path into the array pointed to by
* check_all_attr.
*/
-static void collect_all_attrs(const char *path)
+static void collect_all_attrs(const char *path, int dtype)
{
struct attr_stack *stk;
int i, pathlen, rem, dirlen;
- const char *basename, *cp, *last_slash = NULL;
+ const char *basename, *cp;
- for (cp = path; *cp; cp++) {
- if (*cp == '/' && cp[1])
- last_slash = cp;
- }
- pathlen = cp - path;
- if (last_slash) {
- basename = last_slash + 1;
- dirlen = last_slash - path;
+ cp = strrchr(path, '/');
+ pathlen = strlen(path);
+ if (cp) {
+ basename = cp + 1;
+ dirlen = cp - path;
} else {
basename = path;
dirlen = 0;
@@ -773,14 +771,14 @@ static void collect_all_attrs(const char *path)
rem = attr_nr;
for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
- rem = fill(path, pathlen, basename, stk, rem);
+ rem = fill(path, pathlen, basename, dtype, stk, rem);
}
-int git_check_attr(const char *path, int num, struct git_attr_check *check)
+int git_check_attr(const char *path, int dtype, int num, struct git_attr_check
*check)
{
int i;
- collect_all_attrs(path);
+ collect_all_attrs(path, dtype);
for (i = 0; i < num; i++) {
const char *value =
check_all_attr[check[i].attr->attr_nr].value;
@@ -796,7 +794,7 @@ int git_all_attrs(const char *path, int *num, struct
git_attr_check **check)
{
int i, count, j;
- collect_all_attrs(path);
+ collect_all_attrs(path, DT_REG);
/* Count the number of attributes that are set. */
count = 0;
diff --git a/attr.h b/attr.h
index 8b08d33..ce39c9c 100644
--- a/attr.h
+++ b/attr.h
@@ -36,7 +36,7 @@ struct git_attr_check {
*/
char *git_attr_name(struct git_attr *);
-int git_check_attr(const char *path, int, struct git_attr_check *);
+int git_check_attr(const char *path, int, int, struct git_attr_check *);
/*
* Retrieve all attributes that apply to the specified path. *num
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..261e57d 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -49,7 +49,7 @@ static void check_attr(const char *prefix, int cnt,
char *full_path =
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
if (check != NULL) {
- if (git_check_attr(full_path, cnt, check))
+ if (git_check_attr(full_path, DT_REG, cnt, check))
die("git_check_attr died");
output_attr(cnt, check, file);
} else {
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f069462..7a77288 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -894,7 +894,7 @@ static int no_try_delta(const char *path)
struct git_attr_check check[1];
setup_delta_attr_check(check);
- if (git_check_attr(path, ARRAY_SIZE(check), check))
+ if (git_check_attr(path, DT_REG, ARRAY_SIZE(check), check))
return 0;
if (ATTR_FALSE(check->value))
return 1;
diff --git a/convert.c b/convert.c
index 3520252..3f09cbb 100644
--- a/convert.c
+++ b/convert.c
@@ -755,7 +755,7 @@ static void convert_attrs(struct conv_attrs *ca, const char
*path)
git_config(read_convert_config, NULL);
}
- if (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) {
+ if (!git_check_attr(path, DT_REG, NUM_CONV_ATTRS, ccheck)) {
ca->crlf_action = git_path_check_crlf(path, ccheck + 4);
if (ca->crlf_action == CRLF_GUESS)
ca->crlf_action = git_path_check_crlf(path, ccheck + 0);
diff --git a/ll-merge.c b/ll-merge.c
index fb61ea6..1944392 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -342,7 +342,7 @@ static int git_path_check_merge(const char *path, struct
git_attr_check check[2]
check[0].attr = git_attr("merge");
check[1].attr = git_attr("conflict-marker-size");
}
- return git_check_attr(path, 2, check);
+ return git_check_attr(path, DT_REG, 2, check);
}
static void normalize_file(mmfile_t *mm, const char *path)
@@ -399,7 +399,7 @@ int ll_merge_marker_size(const char *path)
if (!check.attr)
check.attr = git_attr("conflict-marker-size");
- if (!git_check_attr(path, 1, &check) && check.value) {
+ if (!git_check_attr(path, DT_REG, 1, &check) && check.value) {
marker_size = atoi(check.value);
if (marker_size <= 0)
marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh
index 0c847fb..98ccc3c 100755
--- a/t/t5002-archive-attr-pattern.sh
+++ b/t/t5002-archive-attr-pattern.sh
@@ -27,6 +27,10 @@ test_expect_success 'setup' '
echo ignored-only-if-dir/ export-ignore >>.git/info/attributes &&
git add ignored-only-if-dir &&
+ mkdir -p ignored-without-slash &&
+ echo ignored without slash >ignored-without-slash/foo &&
+ git add ignored-without-slash/foo &&
+ echo ignored-without-slash export-ignore >>.git/info/attributes &&
mkdir -p one-level-lower/two-levels-lower/ignored-only-if-dir &&
echo ignored by ignored dir
>one-level-lower/two-levels-lower/ignored-only-if-dir/ignored-by-ignored-dir &&
@@ -49,6 +53,8 @@ test_expect_exists
archive/not-ignored-dir/ignored-only-if-dir
test_expect_exists archive/not-ignored-dir/
test_expect_missing archive/ignored-only-if-dir/
test_expect_missing archive/ignored-ony-if-dir/ignored-by-ignored-dir
+test_expect_missing archive/ignored-without-slash/ &&
+test_expect_missing archive/ignored-without-slash/foo &&
test_expect_exists archive/one-level-lower/
test_expect_missing
archive/one-level-lower/two-levels-lower/ignored-only-if-dir/
test_expect_missing
archive/one-level-lower/two-levels-lower/ignored-ony-if-dir/ignored-by-ignored-dir
diff --git a/userdiff.c b/userdiff.c
index ea43a03..fd4f576 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -260,7 +260,7 @@ struct userdiff_driver *userdiff_find_by_path(const char
*path)
if (!path)
return NULL;
- if (git_check_attr(path, 1, &check))
+ if (git_check_attr(path, DT_REG, 1, &check))
return NULL;
if (ATTR_TRUE(check.value))
diff --git a/ws.c b/ws.c
index b498d75..34c2145 100644
--- a/ws.c
+++ b/ws.c
@@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname)
struct git_attr_check attr_whitespace_rule;
setup_whitespace_attr_check(&attr_whitespace_rule);
- if (!git_check_attr(pathname, 1, &attr_whitespace_rule)) {
+ if (!git_check_attr(pathname, DT_REG, 1, &attr_whitespace_rule)) {
const char *value;
value = attr_whitespace_rule.value;
-- 8< --
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html