This is a whether balloon patch (to check whether this balloons or not, uhm). Hit it hard, not me ;) It's part of the way to revive the old idea of making attributes depend on file type. I am not following the old path pattern is_symlink otherattr because that would mean something which looks like an attribute (is_symlink) but is not. Instead, symlink:pattern attrs is to specify attrs for pattern if it is a symlink. So, e.g., symlink:* diff=symlink together with a nice diff.symlink.textconv displays symlinks nicely. Most notable rough edges: - git_checkattr() gets a new mode parameter. I've stuck it in where I could, 0 anywhere else. This is appropriate in many places (where we know IS_REG a forteriori) but I'm not sure about all of them. - We/someone could teach git_checkattr other prefixes. - It is tested with one (1) symlink and works! - I would bundle it with Jeff's doc and test ;) - This is not a real commit message. Signed-off-by: Michael J Gruber <git@xxxxxxxxxxxxxxxxxxxx> --- archive.c | 2 +- attr.c | 5 ++++- attr.h | 2 +- builtin/check-attr.c | 7 ++++++- builtin/pack-objects.c | 2 +- convert.c | 4 ++-- diff.c | 5 ++--- grep.c | 2 +- ll-merge.c | 4 ++-- userdiff.c | 4 ++-- userdiff.h | 2 +- ws.c | 2 +- 12 files changed, 24 insertions(+), 17 deletions(-) diff --git a/archive.c b/archive.c index 1944ed4..2870f04 100644 --- a/archive.c +++ b/archive.c @@ -124,7 +124,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base, path_without_prefix = path.buf + args->baselen; setup_archive_check(check); - if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) { + if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check, mode)) { if (ATTR_TRUE(check[0].value)) return 0; convert = ATTR_TRUE(check[1].value); diff --git a/attr.c b/attr.c index 6aff695..c4481ac 100644 --- a/attr.c +++ b/attr.c @@ -708,7 +708,7 @@ static int macroexpand_one(int attr_nr, int rem) return rem; } -int git_checkattr(const char *path, int num, struct git_attr_check *check) +int git_checkattr(const char *path, int num, struct git_attr_check *check, unsigned short mode) { struct attr_stack *stk; const char *cp; @@ -718,6 +718,9 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) for (i = 0; i < attr_nr; i++) check_all_attr[i].value = ATTR__UNKNOWN; + if (S_ISLNK(mode)) + path = prefix_filename("symlink:", strlen("symlink:"), path); + /* else if (IS_WHATEVER(mode)) do_what_you_feel_like */ pathlen = strlen(path); cp = strrchr(path, '/'); if (!cp) diff --git a/attr.h b/attr.h index 8b3f19b..1af0bd4 100644 --- a/attr.h +++ b/attr.h @@ -29,7 +29,7 @@ struct git_attr_check { const char *value; }; -int git_checkattr(const char *path, int, struct git_attr_check *); +int git_checkattr(const char *path, int, struct git_attr_check *, unsigned short mode); enum git_attr_direction { GIT_ATTR_CHECKIN, diff --git a/builtin/check-attr.c b/builtin/check-attr.c index 3016d29..30be2c2 100644 --- a/builtin/check-attr.c +++ b/builtin/check-attr.c @@ -24,7 +24,12 @@ static void check_attr(int cnt, struct git_attr_check *check, const char** name, const char *file) { int j; - if (git_checkattr(file, cnt, check)) + unsigned int mode = 0; + struct stat st; + + if (!lstat(file, &st)) + mode = st.st_mode; + if (git_checkattr(file, cnt, check, mode)) die("git_checkattr died"); for (j = 0; j < cnt; j++) { const char *value = check[j].value; diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index b0503b2..4e9ff68 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -633,7 +633,7 @@ static int no_try_delta(const char *path) struct git_attr_check check[1]; setup_delta_attr_check(check); - if (git_checkattr(path, ARRAY_SIZE(check), check)) + if (git_checkattr(path, ARRAY_SIZE(check), check, 0)) return 0; if (ATTR_FALSE(check->value)) return 1; diff --git a/convert.c b/convert.c index d5aebed..d5c2b9c 100644 --- a/convert.c +++ b/convert.c @@ -736,7 +736,7 @@ int convert_to_git(const char *path, const char *src, size_t len, const char *filter = NULL; setup_convert_check(check); - if (!git_checkattr(path, ARRAY_SIZE(check), check)) { + if (!git_checkattr(path, ARRAY_SIZE(check), check, 0)) { struct convert_driver *drv; action = git_path_check_crlf(path, check + 4); if (action == CRLF_GUESS) @@ -773,7 +773,7 @@ static int convert_to_working_tree_internal(const char *path, const char *src, const char *filter = NULL; setup_convert_check(check); - if (!git_checkattr(path, ARRAY_SIZE(check), check)) { + if (!git_checkattr(path, ARRAY_SIZE(check), check, 0)) { struct convert_driver *drv; action = git_path_check_crlf(path, check + 4); if (action == CRLF_GUESS) diff --git a/diff.c b/diff.c index 6640857..22b5d94 100644 --- a/diff.c +++ b/diff.c @@ -1784,8 +1784,7 @@ static void diff_filespec_load_driver(struct diff_filespec *one) if (one->driver) return; - if (S_ISREG(one->mode)) - one->driver = userdiff_find_by_path(one->path); + one->driver = userdiff_find_by_path(one->path, one->mode); /* Fallback to default settings */ if (!one->driver) @@ -2683,7 +2682,7 @@ static void run_diff_cmd(const char *pgm, if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL)) pgm = NULL; else { - struct userdiff_driver *drv = userdiff_find_by_path(attr_path); + struct userdiff_driver *drv = userdiff_find_by_path(attr_path, two->mode); if (drv && drv->external) pgm = drv->external; } diff --git a/grep.c b/grep.c index 63c4280..05a77fc 100644 --- a/grep.c +++ b/grep.c @@ -877,7 +877,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name, memset(&xecfg, 0, sizeof(xecfg)); if (opt->funcname && !opt->unmatch_name_only && !opt->status_only && !opt->name_only && !binary_match_only && !collect_hits) { - struct userdiff_driver *drv = userdiff_find_by_path(name); + struct userdiff_driver *drv = userdiff_find_by_path(name, 0); if (drv && drv->funcname.pattern) { const struct userdiff_funcname *pe = &drv->funcname; xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); diff --git a/ll-merge.c b/ll-merge.c index 6ce512e..3f351e3 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -330,7 +330,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_checkattr(path, 2, check); + return git_checkattr(path, 2, check, 0); } static void normalize_file(mmfile_t *mm, const char *path) @@ -387,7 +387,7 @@ int ll_merge_marker_size(const char *path) if (!check.attr) check.attr = git_attr("conflict-marker-size"); - if (!git_checkattr(path, 1, &check) && check.value) { + if (!git_checkattr(path, 1, &check, 0) && check.value) { marker_size = atoi(check.value); if (marker_size <= 0) marker_size = DEFAULT_CONFLICT_MARKER_SIZE; diff --git a/userdiff.c b/userdiff.c index 1ff4797..e5d0adf 100644 --- a/userdiff.c +++ b/userdiff.c @@ -245,7 +245,7 @@ struct userdiff_driver *userdiff_find_by_name(const char *name) { return userdiff_find_by_namelen(name, len); } -struct userdiff_driver *userdiff_find_by_path(const char *path) +struct userdiff_driver *userdiff_find_by_path(const char *path, unsigned short mode) { static struct git_attr *attr; struct git_attr_check check; @@ -256,7 +256,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path) if (!path) return NULL; - if (git_checkattr(path, 1, &check)) + if (git_checkattr(path, 1, &check, mode)) return NULL; if (ATTR_TRUE(check.value)) diff --git a/userdiff.h b/userdiff.h index 942d594..e516f1d 100644 --- a/userdiff.h +++ b/userdiff.h @@ -21,6 +21,6 @@ struct userdiff_driver { int userdiff_config(const char *k, const char *v); struct userdiff_driver *userdiff_find_by_name(const char *name); -struct userdiff_driver *userdiff_find_by_path(const char *path); +struct userdiff_driver *userdiff_find_by_path(const char *path, unsigned short mode); #endif /* USERDIFF */ diff --git a/ws.c b/ws.c index 9fb9b14..51929d3 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_checkattr(pathname, 1, &attr_whitespace_rule)) { + if (!git_checkattr(pathname, 1, &attr_whitespace_rule, 0)) { const char *value; value = attr_whitespace_rule.value; -- 1.7.4.1.257.gb09fa -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html