From 8c701249d2257699c19822b528c101668abc55b9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 12 Apr 2007 23:05:29 -0700 Subject: Teach 'diff' about 'diff' attribute. This makes paths that explicitly unset 'diff' attribute not to produce "textual" diffs from 'git-diff' family. Signed-off-by: Junio C Hamano --- diff.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index fbb79d70a9..e4efb657e8 100644 --- a/diff.c +++ b/diff.c @@ -8,6 +8,7 @@ #include "delta.h" #include "xdiff-interface.h" #include "color.h" +#include "attr.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1051,13 +1052,34 @@ static void emit_binary_diff(mmfile_t *one, mmfile_t *two) emit_binary_diff_body(two, one); } +static void setup_diff_attr_check(struct git_attr_check *check) +{ + static struct git_attr *attr_diff; + + if (!attr_diff) + attr_diff = git_attr("diff", 4); + check->attr = attr_diff; +} + #define FIRST_FEW_BYTES 8000 -static int mmfile_is_binary(mmfile_t *mf) +static int file_is_binary(struct diff_filespec *one) { - long sz = mf->size; + unsigned long sz; + struct git_attr_check attr_diff_check; + + setup_diff_attr_check(&attr_diff_check); + if (!git_checkattr(one->path, 1, &attr_diff_check) && + (0 == attr_diff_check.isset)) + return 1; + if (!one->data) { + if (!DIFF_FILE_VALID(one)) + return 0; + diff_populate_filespec(one, 0); + } + sz = one->size; if (FIRST_FEW_BYTES < sz) sz = FIRST_FEW_BYTES; - return !!memchr(mf->ptr, 0, sz); + return !!memchr(one->data, 0, sz); } static void builtin_diff(const char *name_a, @@ -1114,7 +1136,7 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (!o->text && (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))) { + if (!o->text && (file_is_binary(one) || file_is_binary(two))) { /* Quite common confusing case */ if (mf1.size == mf2.size && !memcmp(mf1.ptr, mf2.ptr, mf1.size)) @@ -1190,7 +1212,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) { + if (file_is_binary(one) || file_is_binary(two)) { data->is_binary = 1; data->added = mf2.size; data->deleted = mf1.size; @@ -1228,7 +1250,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (mmfile_is_binary(&mf2)) + if (file_is_binary(two)) return; else { /* Crazy xdl interfaces.. */ @@ -1805,8 +1827,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) if (o->binary) { mmfile_t mf; - if ((!fill_mmfile(&mf, one) && mmfile_is_binary(&mf)) || - (!fill_mmfile(&mf, two) && mmfile_is_binary(&mf))) + if ((!fill_mmfile(&mf, one) && file_is_binary(one)) || + (!fill_mmfile(&mf, two) && file_is_binary(two))) abbrev = 40; } len += snprintf(msg + len, sizeof(msg) - len, @@ -2701,7 +2723,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) return error("unable to read files to diff"); /* Maybe hash p->two? into the patch id? */ - if (mmfile_is_binary(&mf2)) + if (file_is_binary(p->two)) continue; len1 = remove_space(p->one->path, strlen(p->one->path)); -- cgit v1.3 From 04786756f90a734445cc300a5acf9fcfc9fd4c04 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 15 Apr 2007 11:14:28 -0700 Subject: Expose subprojects as special files to "git diff" machinery The same way we generate diffs on symlinks as the the diff of text of the symlink, we can generate subproject diffs (when not recursing into them!) as the diff of the text that describes the subproject. Of course, since what descibes a subproject is just the SHA1, that's what we'll use. Add some pretty-printing to make it a bit more obvious what is going on, and we're done. So with this, we can get both raw diffs and "textual" diffs of subproject changes: - git diff --raw: :160000 160000 2de597b5ad348b7db04bd10cdd38cd81cbc93ab5 0000000... M sub-A - git diff: diff --git a/sub-A b/sub-A index 2de597b..e8f11a4 160000 --- a/sub-A +++ b/sub-A @@ -1 +1 @@ -Subproject commit 2de597b5ad348b7db04bd10cdd38cd81cbc93ab5 +Subproject commit e8f11a45c5c6b9e2fec6d136d3fb5aff75393d42 NOTE! We'll also want to have the ability to recurse into the subproject and actually diff it recursively, but that will involve a new command line option (I'd suggest "--subproject" and "-S", but the latter is in use by pickaxe), and some very different code. But regardless of ay future recursive behaviour, we need the non-recursive version too (and it should be the default, at least in the absense of config options, so that large superprojects don't default to something extremely expensive). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index fbb79d70a9..1e8e689be2 100644 --- a/diff.c +++ b/diff.c @@ -1397,6 +1397,22 @@ static int populate_from_stdin(struct diff_filespec *s) return 0; } +static int diff_populate_gitlink(struct diff_filespec *s, int size_only) +{ + int len; + char *data = xmalloc(100); + len = snprintf(data, 100, + "Subproject commit %s\n", sha1_to_hex(s->sha1)); + s->data = data; + s->size = len; + s->should_free = 1; + if (size_only) { + s->data = NULL; + free(data); + } + return 0; +} + /* * While doing rename detection and pickaxe operation, we may need to * grab the data for the blob (or file) for our own in-core comparison. @@ -1415,6 +1431,10 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (s->data) return err; + + if (S_ISDIRLNK(s->mode)) + return diff_populate_gitlink(s, size_only); + if (!s->sha1_valid || reuse_worktree_file(s->path, s->sha1, 0)) { struct stat st; -- cgit v1.3 From 40250af411f33afa0c39a5d461829b676453ce3b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 15 Apr 2007 14:35:11 -0700 Subject: Fix 'diff' attribute semantics. This is in the same spirit as the previous one. Earlier 'diff' meant 'do the built-in binary heuristics and disable patch text generation based on it' while '!diff' meant 'do not guess, do not generate patch text'. There was no way to say 'do generate patch text even when the heuristics says it has NUL in it'. Signed-off-by: Junio C Hamano --- diff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index e4efb657e8..dcea405ed3 100644 --- a/diff.c +++ b/diff.c @@ -1069,8 +1069,9 @@ static int file_is_binary(struct diff_filespec *one) setup_diff_attr_check(&attr_diff_check); if (!git_checkattr(one->path, 1, &attr_diff_check) && - (0 == attr_diff_check.isset)) - return 1; + (0 <= attr_diff_check.isset)) + return !attr_diff_check.isset; + if (!one->data) { if (!DIFF_FILE_VALID(one)) return 0; -- cgit v1.3 From 515106fa1335462393c08fa8712dddd767dc147a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 16 Apr 2007 21:33:31 -0700 Subject: Allow more than true/false to attributes. This allows you to define three values (and possibly more) to each attribute: true, false, and unset. Typically the handlers that notice and act on attribute values treat "unset" attribute to mean "do your default thing" (e.g. crlf that is unset would trigger "guess from contents"), so being able to override a setting to an unset state is actually useful. - If you want to set the attribute value to true, have an entry in .gitattributes file that mentions the attribute name; e.g. *.o binary - If you want to set the attribute value explicitly to false, use '-'; e.g. *.a -diff - If you want to make the attribute value _unset_, perhaps to override an earlier entry, use '!'; e.g. *.a -diff c.i.a !diff This also allows string values to attributes, with the natural syntax: attrname=attrvalue but you cannot use it, as nobody takes notice and acts on it yet. Signed-off-by: Junio C Hamano --- attr.c | 194 ++++++++++++++++++++++++++++++++------------------- attr.h | 12 +++- builtin-check-attr.c | 14 ++-- convert.c | 16 ++++- diff.c | 15 +++- 5 files changed, 169 insertions(+), 82 deletions(-) (limited to 'diff.c') diff --git a/attr.c b/attr.c index 60fe48f3b8..b3496a6eb5 100644 --- a/attr.c +++ b/attr.c @@ -1,6 +1,8 @@ #include "cache.h" #include "attr.h" +#define ATTR__UNKNOWN ((void *) -2) + /* * The basic design decision here is that we are not going to have * insanely large number of attributes. @@ -83,6 +85,7 @@ struct git_attr *git_attr(const char *name, int len) check_all_attr = xrealloc(check_all_attr, sizeof(*check_all_attr) * attr_nr); check_all_attr[a->attr_nr].attr = a; + check_all_attr[a->attr_nr].value = ATTR__UNKNOWN; return a; } @@ -92,12 +95,14 @@ struct git_attr *git_attr(const char *name, int len) * (1) glob pattern. * (2) whitespace * (3) whitespace separated list of attribute names, each of which - * could be prefixed with '-' to mean "not set". + * could be prefixed with '-' to mean "set to false", '!' to mean + * "unset". */ +/* What does a matched pattern decide? */ struct attr_state { - int unset; struct git_attr *attr; + void *setto; }; struct match_attr { @@ -112,13 +117,63 @@ struct match_attr { static const char blank[] = " \t\r\n"; +static const char *parse_attr(const char *src, int lineno, const char *cp, + int *num_attr, struct match_attr *res) +{ + const char *ep, *equals; + int len; + + ep = cp + strcspn(cp, blank); + equals = strchr(cp, '='); + if (equals && ep < equals) + equals = NULL; + if (equals) + len = equals - cp; + else + len = ep - cp; + if (!res) { + if (*cp == '-' || *cp == '!') { + cp++; + len--; + } + if (invalid_attr_name(cp, len)) { + fprintf(stderr, + "%.*s is not a valid attribute name: %s:%d\n", + len, cp, src, lineno); + return NULL; + } + } else { + struct attr_state *e; + + e = &(res->state[*num_attr]); + if (*cp == '-' || *cp == '!') { + e->setto = (*cp == '-') ? ATTR__FALSE : ATTR__UNSET; + cp++; + len--; + } + else if (!equals) + e->setto = ATTR__TRUE; + else { + char *value; + int vallen = ep - equals; + value = xmalloc(vallen); + memcpy(value, equals+1, vallen-1); + value[vallen-1] = 0; + e->setto = value; + } + e->attr = git_attr(cp, len); + } + (*num_attr)++; + return ep + strspn(ep, blank); +} + static struct match_attr *parse_attr_line(const char *line, const char *src, int lineno, int macro_ok) { int namelen; int num_attr; const char *cp, *name; - struct match_attr *res = res; + struct match_attr *res = NULL; int pass; int is_macro; @@ -153,42 +208,16 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, num_attr = 0; cp = name + namelen; cp = cp + strspn(cp, blank); - while (*cp) { - const char *ep; - ep = cp + strcspn(cp, blank); - if (!pass) { - if (*cp == '-') - cp++; - if (invalid_attr_name(cp, ep - cp)) { - fprintf(stderr, - "%.*s is not a valid attribute name: %s:%d\n", - (int)(ep - cp), cp, - src, lineno); - return NULL; - } - } else { - struct attr_state *e; - - e = &(res->state[num_attr]); - if (*cp == '-') { - e->unset = 1; - cp++; - } - e->attr = git_attr(cp, ep - cp); - } - num_attr++; - cp = ep + strspn(ep, blank); - } + while (*cp) + cp = parse_attr(src, lineno, cp, &num_attr, res); if (pass) break; - res = xcalloc(1, sizeof(*res) + sizeof(struct attr_state) * num_attr + (is_macro ? 0 : namelen + 1)); - if (is_macro) { + if (is_macro) res->u.attr = git_attr(name, namelen); - } else { res->u.pattern = (char*)&(res->state[num_attr]); memcpy(res->u.pattern, name, namelen); @@ -205,9 +234,9 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, * come from many places. * * (1) .gitattribute file of the same directory; - * (2) .gitattribute file of the parent directory if (1) does not have any match; - * this goes recursively upwards, just like .gitignore - * (3) perhaps $GIT_DIR/info/attributes, as the final fallback. + * (2) .gitattribute file of the parent directory if (1) does not have + * any match; this goes recursively upwards, just like .gitignore. + * (3) $GIT_DIR/info/attributes, which overrides both of the above. * * In the same file, later entries override the earlier match, so in the * global list, we would have entries from info/attributes the earliest @@ -229,8 +258,21 @@ static void free_attr_elem(struct attr_stack *e) { int i; free(e->origin); - for (i = 0; i < e->num_matches; i++) - free(e->attrs[i]); + for (i = 0; i < e->num_matches; i++) { + struct match_attr *a = e->attrs[i]; + int j; + for (j = 0; j < a->num_attr; j++) { + void *setto = a->state[j].setto; + if (setto == ATTR__TRUE || + setto == ATTR__FALSE || + setto == ATTR__UNSET || + setto == ATTR__UNKNOWN) + ; + else + free(setto); + } + free(a); + } free(e); } @@ -288,10 +330,19 @@ static void debug_info(const char *what, struct attr_stack *elem) { fprintf(stderr, "%s: %s\n", what, elem->origin ? elem->origin : "()"); } -static void debug_set(const char *what, const char *match, struct git_attr *attr, int set) +static void debug_set(const char *what, const char *match, struct git_attr *attr, void *v) { - fprintf(stderr, "%s: %s => %d (%s)\n", - what, attr->name, set, match); + const char *value = v; + + if (ATTR_TRUE(value)) + value = "set"; + else if (ATTR_FALSE(value)) + value = "unset"; + else if (ATTR_UNSET(value)) + value = "unspecified"; + + fprintf(stderr, "%s: %s => %s (%s)\n", + what, attr->name, (char *) value, match); } #define debug_push(a) debug_info("push", (a)) #define debug_pop(a) debug_info("pop", (a)) @@ -420,56 +471,53 @@ static int path_matches(const char *pathname, int pathlen, return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0; } +static int fill_one(const char *what, struct match_attr *a, int rem) +{ + struct git_attr_check *check = check_all_attr; + int i; + + for (i = 0; 0 < rem && i < a->num_attr; i++) { + struct git_attr *attr = a->state[i].attr; + void **n = &(check[attr->attr_nr].value); + void *v = a->state[i].setto; + + if (*n == ATTR__UNKNOWN) { + debug_set(what, a->u.pattern, attr, v); + *n = v; + rem--; + } + } + return rem; +} + static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem) { + int i; const char *base = stk->origin ? stk->origin : ""; - int i, j; - struct git_attr_check *check = check_all_attr; for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) { struct match_attr *a = stk->attrs[i]; if (a->is_macro) continue; if (path_matches(path, pathlen, - a->u.pattern, base, strlen(base))) { - for (j = 0; 0 < rem && j < a->num_attr; j++) { - struct git_attr *attr = a->state[j].attr; - int set = !a->state[j].unset; - int *n = &(check[attr->attr_nr].isset); - - if (*n < 0) { - debug_set("fill", a->u.pattern, attr, set); - *n = set; - rem--; - } - } - } + a->u.pattern, base, strlen(base))) + rem = fill_one("fill", a, rem); } return rem; } static int macroexpand(struct attr_stack *stk, int rem) { - int i, j; + int i; struct git_attr_check *check = check_all_attr; for (i = stk->num_matches - 1; 0 < rem && 0 <= i; i--) { struct match_attr *a = stk->attrs[i]; if (!a->is_macro) continue; - if (check[a->u.attr->attr_nr].isset < 0) + if (check[a->u.attr->attr_nr].value != ATTR__TRUE) continue; - for (j = 0; 0 < rem && j < a->num_attr; j++) { - struct git_attr *attr = a->state[j].attr; - int set = !a->state[j].unset; - int *n = &(check[attr->attr_nr].isset); - - if (*n < 0) { - debug_set("expand", a->u.attr->name, attr, set); - *n = set; - rem--; - } - } + rem = fill_one("expand", a, rem); } return rem; } @@ -482,7 +530,7 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) bootstrap_attr_stack(); for (i = 0; i < attr_nr; i++) - check_all_attr[i].isset = -1; + check_all_attr[i].value = ATTR__UNKNOWN; pathlen = strlen(path); cp = strrchr(path, '/'); @@ -498,8 +546,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) rem = macroexpand(stk, rem); - for (i = 0; i < num; i++) - check[i].isset = check_all_attr[check[i].attr->attr_nr].isset; + for (i = 0; i < num; i++) { + void *value = check_all_attr[check[i].attr->attr_nr].value; + if (value == ATTR__UNKNOWN) + value = ATTR__UNSET; + check[i].value = value; + } return 0; } diff --git a/attr.h b/attr.h index 1e5ab40694..8ec2d3d35c 100644 --- a/attr.h +++ b/attr.h @@ -6,9 +6,19 @@ struct git_attr; struct git_attr *git_attr(const char *, int); +/* Internal use */ +#define ATTR__TRUE ((void *) 1) +#define ATTR__FALSE ((void *) 0) +#define ATTR__UNSET ((void *) -1) + +/* For public to check git_attr_check results */ +#define ATTR_TRUE(v) ((v) == ATTR__TRUE) +#define ATTR_FALSE(v) ((v) == ATTR__FALSE) +#define ATTR_UNSET(v) ((v) == ATTR__UNSET) + struct git_attr_check { struct git_attr *attr; - int isset; + void *value; }; int git_checkattr(const char *path, int, struct git_attr_check *); diff --git a/builtin-check-attr.c b/builtin-check-attr.c index 634be9ed2e..6983a73c1b 100644 --- a/builtin-check-attr.c +++ b/builtin-check-attr.c @@ -42,11 +42,17 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) if (git_checkattr(argv[i], cnt, check)) die("git_checkattr died"); for (j = 0; j < cnt; j++) { + void *value = check[j].value; + + if (ATTR_TRUE(value)) + value = "set"; + else if (ATTR_FALSE(value)) + value = "unset"; + else if (ATTR_UNSET(value)) + value = "unspecified"; + write_name_quoted("", 0, argv[i], 1, stdout); - printf(": %s: %s\n", argv[j+1], - (check[j].isset < 0) ? "unspecified" : - (check[j].isset == 0) ? "unset" : - "set"); + printf(": %s: %s\n", argv[j+1], (char *) value); } } return 0; diff --git a/convert.c b/convert.c index d0d4b81871..68bb70f12f 100644 --- a/convert.c +++ b/convert.c @@ -225,9 +225,19 @@ static int git_path_check_crlf(const char *path) setup_crlf_check(&attr_crlf_check); - if (git_checkattr(path, 1, &attr_crlf_check)) - return -1; - return attr_crlf_check.isset; + if (!git_checkattr(path, 1, &attr_crlf_check)) { + void *value = attr_crlf_check.value; + if (ATTR_TRUE(value)) + return 1; + else if (ATTR_FALSE(value)) + return 0; + else if (ATTR_UNSET(value)) + ; + else + die("unknown value %s given to 'crlf' attribute", + (char *)value); + } + return -1; } int convert_to_git(const char *path, char **bufp, unsigned long *sizep) diff --git a/diff.c b/diff.c index dcea405ed3..a32078ea01 100644 --- a/diff.c +++ b/diff.c @@ -1068,9 +1068,18 @@ static int file_is_binary(struct diff_filespec *one) struct git_attr_check attr_diff_check; setup_diff_attr_check(&attr_diff_check); - if (!git_checkattr(one->path, 1, &attr_diff_check) && - (0 <= attr_diff_check.isset)) - return !attr_diff_check.isset; + if (!git_checkattr(one->path, 1, &attr_diff_check)) { + void *value = attr_diff_check.value; + if (ATTR_TRUE(value)) + return 0; + else if (ATTR_FALSE(value)) + return 1; + else if (ATTR_UNSET(value)) + ; + else + die("unknown value %s given to 'diff' attribute", + (char *)value); + } if (!one->data) { if (!DIFF_FILE_VALID(one)) -- cgit v1.3 From a5e92abde61d59a8612c5b87d0bae681e90f7fdb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 18 Apr 2007 16:16:37 -0700 Subject: Fix funny types used in attribute value representation It was bothering me a lot that I abused small integer values casted to (void *) to represent non string values in gitattributes. This corrects it by making the type of attribute values (const char *), and using the address of a few statically allocated character buffer to denote true/false. Unset attributes are represented as having NULLs as their values. Added in-header documentation to explain how git_checkattr() routine should be called. Signed-off-by: Junio C Hamano --- attr.c | 20 +++++++++++++------- attr.h | 22 +++++++++++++++------- builtin-check-attr.c | 4 ++-- convert.c | 2 +- diff.c | 4 ++-- merge-recursive.c | 17 ++++++++++------- 6 files changed, 43 insertions(+), 26 deletions(-) (limited to 'diff.c') diff --git a/attr.c b/attr.c index b3496a6eb5..285e689e5a 100644 --- a/attr.c +++ b/attr.c @@ -1,7 +1,13 @@ #include "cache.h" #include "attr.h" -#define ATTR__UNKNOWN ((void *) -2) +const char git_attr__true[] = "(builtin)true"; +const char git_attr__false[] = "\0(builtin)false"; +static const char git_attr__unknown[] = "(builtin)unknown"; +#define ATTR__TRUE git_attr__true +#define ATTR__FALSE git_attr__false +#define ATTR__UNSET NULL +#define ATTR__UNKNOWN git_attr__unknown /* * The basic design decision here is that we are not going to have @@ -102,7 +108,7 @@ struct git_attr *git_attr(const char *name, int len) /* What does a matched pattern decide? */ struct attr_state { struct git_attr *attr; - void *setto; + const char *setto; }; struct match_attr { @@ -262,14 +268,14 @@ static void free_attr_elem(struct attr_stack *e) struct match_attr *a = e->attrs[i]; int j; for (j = 0; j < a->num_attr; j++) { - void *setto = a->state[j].setto; + const char *setto = a->state[j].setto; if (setto == ATTR__TRUE || setto == ATTR__FALSE || setto == ATTR__UNSET || setto == ATTR__UNKNOWN) ; else - free(setto); + free((char*) setto); } free(a); } @@ -478,8 +484,8 @@ static int fill_one(const char *what, struct match_attr *a, int rem) for (i = 0; 0 < rem && i < a->num_attr; i++) { struct git_attr *attr = a->state[i].attr; - void **n = &(check[attr->attr_nr].value); - void *v = a->state[i].setto; + const char **n = &(check[attr->attr_nr].value); + const char *v = a->state[i].setto; if (*n == ATTR__UNKNOWN) { debug_set(what, a->u.pattern, attr, v); @@ -547,7 +553,7 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check) rem = macroexpand(stk, rem); for (i = 0; i < num; i++) { - void *value = check_all_attr[check[i].attr->attr_nr].value; + const char *value = check_all_attr[check[i].attr->attr_nr].value; if (value == ATTR__UNKNOWN) value = ATTR__UNSET; check[i].value = value; diff --git a/attr.h b/attr.h index 8ec2d3d35c..f1c2038b09 100644 --- a/attr.h +++ b/attr.h @@ -4,21 +4,29 @@ /* An attribute is a pointer to this opaque structure */ struct git_attr; +/* + * Given a string, return the gitattribute object that + * corresponds to it. + */ struct git_attr *git_attr(const char *, int); /* Internal use */ -#define ATTR__TRUE ((void *) 1) -#define ATTR__FALSE ((void *) 0) -#define ATTR__UNSET ((void *) -1) +extern const char git_attr__true[]; +extern const char git_attr__false[]; /* For public to check git_attr_check results */ -#define ATTR_TRUE(v) ((v) == ATTR__TRUE) -#define ATTR_FALSE(v) ((v) == ATTR__FALSE) -#define ATTR_UNSET(v) ((v) == ATTR__UNSET) +#define ATTR_TRUE(v) ((v) == git_attr__true) +#define ATTR_FALSE(v) ((v) == git_attr__false) +#define ATTR_UNSET(v) ((v) == NULL) +/* + * Send one or more git_attr_check to git_checkattr(), and + * each 'value' member tells what its value is. + * Unset one is returned as NULL. + */ struct git_attr_check { struct git_attr *attr; - void *value; + const char *value; }; int git_checkattr(const char *path, int, struct git_attr_check *); diff --git a/builtin-check-attr.c b/builtin-check-attr.c index 6983a73c1b..9d77f76ff1 100644 --- a/builtin-check-attr.c +++ b/builtin-check-attr.c @@ -42,7 +42,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) if (git_checkattr(argv[i], cnt, check)) die("git_checkattr died"); for (j = 0; j < cnt; j++) { - void *value = check[j].value; + const char *value = check[j].value; if (ATTR_TRUE(value)) value = "set"; @@ -52,7 +52,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) value = "unspecified"; write_name_quoted("", 0, argv[i], 1, stdout); - printf(": %s: %s\n", argv[j+1], (char *) value); + printf(": %s: %s\n", argv[j+1], value); } } return 0; diff --git a/convert.c b/convert.c index 68bb70f12f..a5f60c7c6b 100644 --- a/convert.c +++ b/convert.c @@ -226,7 +226,7 @@ static int git_path_check_crlf(const char *path) setup_crlf_check(&attr_crlf_check); if (!git_checkattr(path, 1, &attr_crlf_check)) { - void *value = attr_crlf_check.value; + const char *value = attr_crlf_check.value; if (ATTR_TRUE(value)) return 1; else if (ATTR_FALSE(value)) diff --git a/diff.c b/diff.c index a32078ea01..5f501864e6 100644 --- a/diff.c +++ b/diff.c @@ -1069,7 +1069,7 @@ static int file_is_binary(struct diff_filespec *one) setup_diff_attr_check(&attr_diff_check); if (!git_checkattr(one->path, 1, &attr_diff_check)) { - void *value = attr_diff_check.value; + const char *value = attr_diff_check.value; if (ATTR_TRUE(value)) return 0; else if (ATTR_FALSE(value)) @@ -1078,7 +1078,7 @@ static int file_is_binary(struct diff_filespec *one) ; else die("unknown value %s given to 'diff' attribute", - (char *)value); + value); } if (!one->data) { diff --git a/merge-recursive.c b/merge-recursive.c index 7b5ca8e717..ec8438b463 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -953,7 +953,7 @@ static void initialize_ll_merge(void) git_config(read_merge_config); } -static const struct ll_merge_driver *find_ll_merge_driver(void *merge_attr) +static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr) { struct ll_merge_driver *fn; const char *name; @@ -986,7 +986,7 @@ static const struct ll_merge_driver *find_ll_merge_driver(void *merge_attr) return &ll_merge_drv[LL_TEXT_MERGE]; } -static void *git_path_check_merge(const char *path) +static const char *git_path_check_merge(const char *path) { static struct git_attr_check attr_merge_check; @@ -994,7 +994,7 @@ static void *git_path_check_merge(const char *path) attr_merge_check.attr = git_attr("merge", 5); if (git_checkattr(path, 1, &attr_merge_check)) - return ATTR__UNSET; + return NULL; return attr_merge_check.value; } @@ -1008,7 +1008,7 @@ static int ll_merge(mmbuffer_t *result_buf, mmfile_t orig, src1, src2; char *name1, *name2; int merge_status; - void *merge_attr; + const char *ll_driver_name; const struct ll_merge_driver *driver; name1 = xstrdup(mkpath("%s:%s", branch1, a->path)); @@ -1018,11 +1018,14 @@ static int ll_merge(mmbuffer_t *result_buf, fill_mm(a->sha1, &src1); fill_mm(b->sha1, &src2); - merge_attr = git_path_check_merge(a->path); - driver = find_ll_merge_driver(merge_attr); + ll_driver_name = git_path_check_merge(a->path); + driver = find_ll_merge_driver(ll_driver_name); if (index_only && driver->recursive) { - merge_attr = git_attr(driver->recursive, strlen(driver->recursive)); + void *merge_attr; + + ll_driver_name = driver->recursive; + merge_attr = git_attr(ll_driver_name, strlen(ll_driver_name)); driver = find_ll_merge_driver(merge_attr); } merge_status = driver->fn(driver, a->path, -- cgit v1.3 From ac78e548049f4e86b38368d2c4b4dbb546c64ac6 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 19 Apr 2007 02:05:03 +0200 Subject: Simplify calling of CR/LF conversion routines Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- builtin-apply.c | 18 ++++++--------- cache.h | 4 ++-- convert.c | 71 ++++++++++++++++++++++++++++----------------------------- diff.c | 4 ++-- entry.c | 7 ++---- sha1_file.c | 7 +++--- 6 files changed, 51 insertions(+), 60 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index fd92ef7174..ccd342c1c4 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1475,8 +1475,8 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign } close(fd); nsize = got; - nbuf = buf; - if (convert_to_git(path, &nbuf, &nsize)) { + nbuf = convert_to_git(path, buf, &nsize); + if (nbuf) { free(buf); *buf_p = nbuf; *alloc_p = nsize; @@ -2355,9 +2355,8 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { - int fd, converted; + int fd; char *nbuf; - unsigned long nsize; if (has_symlinks && S_ISLNK(mode)) /* Although buf:size is counted string, it also is NUL @@ -2369,13 +2368,10 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, if (fd < 0) return -1; - nsize = size; - nbuf = (char *) buf; - converted = convert_to_working_tree(path, &nbuf, &nsize); - if (converted) { + nbuf = convert_to_working_tree(path, buf, &size); + if (nbuf) buf = nbuf; - size = nsize; - } + while (size) { int written = xwrite(fd, buf, size); if (written < 0) @@ -2387,7 +2383,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, } if (close(fd) < 0) die("closing file %s: %s", path, strerror(errno)); - if (converted) + if (nbuf) free(nbuf); return 0; } diff --git a/cache.h b/cache.h index 38ad00661d..8c804cb6ee 100644 --- a/cache.h +++ b/cache.h @@ -496,8 +496,8 @@ extern void trace_printf(const char *format, ...); extern void trace_argv_printf(const char **argv, int count, const char *format, ...); /* convert.c */ -extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep); -extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep); +extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep); +extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep); /* match-trees.c */ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); diff --git a/convert.c b/convert.c index da64253a16..742b895cfa 100644 --- a/convert.c +++ b/convert.c @@ -79,25 +79,24 @@ static int is_binary(unsigned long size, struct text_stat *stats) return 0; } -static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int action) +static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep, int action) { - char *buffer, *nbuf; + char *buffer, *dst; unsigned long size, nsize; struct text_stat stats; if ((action == CRLF_BINARY) || (action == CRLF_GUESS && !auto_crlf)) - return 0; + return NULL; size = *sizep; if (!size) - return 0; - buffer = *bufp; + return NULL; - gather_stats(buffer, size, &stats); + gather_stats(src, size, &stats); /* No CR? Nothing to convert, regardless. */ if (!stats.cr) - return 0; + return NULL; if (action == CRLF_GUESS) { /* @@ -106,13 +105,13 @@ static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int * stuff? */ if (stats.cr != stats.crlf) - return 0; + return NULL; /* * And add some heuristics for binary vs text, of course... */ if (is_binary(size, &stats)) - return 0; + return NULL; } /* @@ -120,10 +119,10 @@ static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int * to let the caller know that we switched buffers on it. */ nsize = size - stats.crlf; - nbuf = xmalloc(nsize); - *bufp = nbuf; + buffer = xmalloc(nsize); *sizep = nsize; + dst = buffer; if (action == CRLF_GUESS) { /* * If we guessed, we already know we rejected a file with @@ -131,54 +130,53 @@ static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int * follow it. */ do { - unsigned char c = *buffer++; + unsigned char c = *src++; if (c != '\r') - *nbuf++ = c; + *dst++ = c; } while (--size); } else { do { - unsigned char c = *buffer++; + unsigned char c = *src++; if (! (c == '\r' && (1 < size && *buffer == '\n'))) - *nbuf++ = c; + *dst++ = c; } while (--size); } - return 1; + return buffer; } -static int crlf_to_worktree(const char *path, char **bufp, unsigned long *sizep, int action) +static char *crlf_to_worktree(const char *path, const char *src, unsigned long *sizep, int action) { - char *buffer, *nbuf; + char *buffer, *dst; unsigned long size, nsize; struct text_stat stats; unsigned char last; if ((action == CRLF_BINARY) || (action == CRLF_INPUT) || (action == CRLF_GUESS && auto_crlf <= 0)) - return 0; + return NULL; size = *sizep; if (!size) - return 0; - buffer = *bufp; + return NULL; - gather_stats(buffer, size, &stats); + gather_stats(src, size, &stats); /* No LF? Nothing to convert, regardless. */ if (!stats.lf) - return 0; + return NULL; /* Was it already in CRLF format? */ if (stats.lf == stats.crlf) - return 0; + return NULL; if (action == CRLF_GUESS) { /* If we have any bare CR characters, we're not going to touch it */ if (stats.cr != stats.crlf) - return 0; + return NULL; if (is_binary(size, &stats)) - return 0; + return NULL; } /* @@ -186,19 +184,20 @@ static int crlf_to_worktree(const char *path, char **bufp, unsigned long *sizep, * to let the caller know that we switched buffers on it. */ nsize = size + stats.lf - stats.crlf; - nbuf = xmalloc(nsize); - *bufp = nbuf; + buffer = xmalloc(nsize); *sizep = nsize; last = 0; + + dst = buffer; do { - unsigned char c = *buffer++; + unsigned char c = *src++; if (c == '\n' && last != '\r') - *nbuf++ = '\r'; - *nbuf++ = c; + *dst++ = '\r'; + *dst++ = c; last = c; } while (--size); - return 1; + return buffer; } static void setup_crlf_check(struct git_attr_check *check) @@ -231,12 +230,12 @@ static int git_path_check_crlf(const char *path) return CRLF_GUESS; } -int convert_to_git(const char *path, char **bufp, unsigned long *sizep) +char *convert_to_git(const char *path, const char *src, unsigned long *sizep) { - return crlf_to_git(path, bufp, sizep, git_path_check_crlf(path)); + return crlf_to_git(path, src, sizep, git_path_check_crlf(path)); } -int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep) +char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep) { - return crlf_to_worktree(path, bufp, sizep, git_path_check_crlf(path)); + return crlf_to_worktree(path, src, sizep, git_path_check_crlf(path)); } diff --git a/diff.c b/diff.c index 5f501864e6..1cb1230a99 100644 --- a/diff.c +++ b/diff.c @@ -1493,9 +1493,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) /* * Convert from working tree format to canonical git format */ - buf = s->data; size = s->size; - if (convert_to_git(s->path, &buf, &size)) { + buf = convert_to_git(s->path, s->data, &size); + if (buf) { munmap(s->data, s->size); s->should_munmap = 0; s->data = buf; diff --git a/entry.c b/entry.c index d72f811580..3771209f19 100644 --- a/entry.c +++ b/entry.c @@ -79,7 +79,6 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat } switch (ntohl(ce->ce_mode) & S_IFMT) { char *buf; - unsigned long nsize; case S_IFREG: if (to_tempfile) { @@ -96,12 +95,10 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat /* * Convert from git internal format to working tree format */ - buf = new; - nsize = size; - if (convert_to_working_tree(ce->name, &buf, &nsize)) { + buf = convert_to_working_tree(ce->name, new, &size); + if (buf) { free(new); new = buf; - size = nsize; } wrote = write_in_full(fd, new, size); diff --git a/sha1_file.c b/sha1_file.c index 4304fe9bbc..1978d5f14e 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2277,10 +2277,9 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, */ if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) { unsigned long nsize = size; - char *nbuf = buf; - if (convert_to_git(path, &nbuf, &nsize)) { - if (size) - munmap(buf, size); + char *nbuf = convert_to_git(path, buf, &nsize); + if (nbuf) { + munmap(buf, size); size = nsize; buf = nbuf; re_allocated = 1; -- cgit v1.3 From f1af60bdba465779df92090ed370988f202ff043 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 22 Apr 2007 17:52:55 -0700 Subject: Support 'diff=pgm' attribute This enhances the attributes mechanism so that external programs meant for existing GIT_EXTERNAL_DIFF interface can be specifed per path. To configure such a custom diff driver, first define a custom diff driver in the configuration: [diff "my-c-diff"] command = <> Then mark the paths that you want to use this custom driver using the attribute mechanism. *.c diff=my-c-diff The intent of this separation is that the attribute mechanism is used for specifying the type of the contents, while the configuration mechanism is used to define what needs to be done to that type of the contents, which would be specific to both platform and personal taste. Signed-off-by: Junio C Hamano --- builtin-diff.c | 1 + combine-diff.c | 1 + diff.c | 87 ++++++++++++++++++++++++++++++++++++++++--- diff.h | 1 + t/t4020-diff-external.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 5 deletions(-) create mode 100755 t/t4020-diff-external.sh (limited to 'diff.c') diff --git a/builtin-diff.c b/builtin-diff.c index 21d13f0b30..2ae60097b8 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -225,6 +225,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) if (diff_setup_done(&rev.diffopt) < 0) die("diff_setup_done failed"); } + rev.diffopt.allow_external = 1; /* Do we have --cached and not have a pending object, then * default to HEAD by hand. Eek. diff --git a/combine-diff.c b/combine-diff.c index 3a9b32f6b8..cff9c5dc42 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -943,6 +943,7 @@ void diff_tree_combined(const unsigned char *sha1, diffopts = *opt; diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; diffopts.recursive = 1; + diffopts.allow_external = 0; show_log_first = !!rev->loginfo && !rev->no_commit_id; needsep = 0; diff --git a/diff.c b/diff.c index f516664968..9dfded7664 100644 --- a/diff.c +++ b/diff.c @@ -52,6 +52,49 @@ static int parse_diff_color_slot(const char *var, int ofs) die("bad config variable '%s'", var); } +static struct ll_diff_driver { + const char *name; + struct ll_diff_driver *next; + char *cmd; +} *user_diff, **user_diff_tail; + +/* + * Currently there is only "diff..command" variable; + * because there are "diff.color." variables, we are parsing + * this in a bit convoluted way to allow low level diff driver + * called "color". + */ +static int parse_lldiff_command(const char *var, const char *ep, const char *value) +{ + const char *name; + int namelen; + struct ll_diff_driver *drv; + + name = var + 5; + namelen = ep - name; + for (drv = user_diff; drv; drv = drv->next) + if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) + break; + if (!drv) { + char *namebuf; + drv = xcalloc(1, sizeof(struct ll_diff_driver)); + namebuf = xmalloc(namelen + 1); + memcpy(namebuf, name, namelen); + namebuf[namelen] = 0; + drv->name = namebuf; + drv->next = NULL; + if (!user_diff_tail) + user_diff_tail = &user_diff; + *user_diff_tail = drv; + user_diff_tail = &(drv->next); + } + + if (!value) + return error("%s: lacks value", var); + drv->cmd = strdup(value); + return 0; +} + /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should @@ -78,11 +121,18 @@ int git_diff_ui_config(const char *var, const char *value) diff_detect_rename_default = DIFF_DETECT_RENAME; return 0; } + if (!prefixcmp(var, "diff.")) { + const char *ep = strrchr(var, '.'); + + if (ep != var + 4 && !strcmp(ep, ".command")) + return parse_lldiff_command(var, ep, value); + } if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); color_parse(value, var, diff_colors[slot]); return 0; } + return git_default_config(var, value); } @@ -1074,11 +1124,6 @@ static int file_is_binary(struct diff_filespec *one) return 0; else if (ATTR_FALSE(value)) return 1; - else if (ATTR_UNSET(value)) - ; - else - die("unknown value %s given to 'diff' attribute", - value); } if (!one->data) { @@ -1752,6 +1797,30 @@ static void run_external_diff(const char *pgm, } } +static const char *external_diff_attr(const char *name) +{ + struct git_attr_check attr_diff_check; + + setup_diff_attr_check(&attr_diff_check); + if (!git_checkattr(name, 1, &attr_diff_check)) { + const char *value = attr_diff_check.value; + if (!ATTR_TRUE(value) && + !ATTR_FALSE(value) && + !ATTR_UNSET(value)) { + struct ll_diff_driver *drv; + + if (!user_diff_tail) { + user_diff_tail = &user_diff; + git_config(git_diff_ui_config); + } + for (drv = user_diff; drv; drv = drv->next) + if (!strcmp(drv->name, value)) + return drv->cmd; + } + } + return NULL; +} + static void run_diff_cmd(const char *pgm, const char *name, const char *other, @@ -1761,6 +1830,14 @@ static void run_diff_cmd(const char *pgm, struct diff_options *o, int complete_rewrite) { + if (!o->allow_external) + pgm = NULL; + else { + const char *cmd = external_diff_attr(name); + if (cmd) + pgm = cmd; + } + if (pgm) { run_external_diff(pgm, name, other, one, two, xfrm_msg, complete_rewrite); diff --git a/diff.h b/diff.h index a0d2ce1399..63738c1dd4 100644 --- a/diff.h +++ b/diff.h @@ -59,6 +59,7 @@ struct diff_options { color_diff_words:1, has_changes:1, quiet:1, + allow_external:1, exit_with_status:1; int context; int break_opt; diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh new file mode 100755 index 0000000000..f0045cd788 --- /dev/null +++ b/t/t4020-diff-external.sh @@ -0,0 +1,97 @@ +#!/bin/sh + +test_description='external diff interface test' + +. ./test-lib.sh + +_z40=0000000000000000000000000000000000000000 + +test_expect_success setup ' + + test_tick && + echo initial >file && + git add file && + git commit -m initial && + + test_tick && + echo second >file && + git add file && + git commit -m second && + + test_tick && + echo third >file +' + +test_expect_success 'GIT_EXTERNAL_DIFF environment' ' + + GIT_EXTERNAL_DIFF=echo git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' ' + + GIT_EXTERNAL_DIFF=echo git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute' ' + + git config diff.parrot.command echo && + + echo >.gitattributes "file diff=parrot" && + + git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'diff attribute should apply only to diff' ' + + git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_expect_success 'diff attribute' ' + + git config --unset diff.parrot.command && + git config diff.color.command echo && + + echo >.gitattributes "file diff=color" && + + git diff | { + read path oldfile oldhex oldmode newfile newhex newmode && + test "z$path" = zfile && + test "z$oldmode" = z100644 && + test "z$newhex" = "z$_z40" && + test "z$newmode" = z100644 && + oh=$(git rev-parse --verify HEAD:file) && + test "z$oh" = "z$oldhex" + } + +' + +test_expect_success 'diff attribute should apply only to diff' ' + + git log -p -1 HEAD | + grep "^diff --git a/file b/file" + +' + +test_done -- cgit v1.3 From cdda666201710dcf50d7ebee804aac65fdec32fd Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 3 May 2007 13:00:43 -0700 Subject: diff.c: fix "size cache" handling. We broke the size-cache handling when we changed the function signature of sha1_object_info() in 21666f1a. We obviously wanted to cache the size we obtained when sha1_object_info() succeeded, not when it failed. Signed-off-by: Junio C Hamano --- diff.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d8f9242ea8..b28933f870 100644 --- a/diff.c +++ b/diff.c @@ -1468,14 +1468,15 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) enum object_type type; struct sha1_size_cache *e; + if (size_only && use_size_cache && + (e = locate_size_cache(s->sha1, 1, 0)) != NULL) { + s->size = e->size; + return 0; + } + if (size_only) { - e = locate_size_cache(s->sha1, 1, 0); - if (e) { - s->size = e->size; - return 0; - } type = sha1_object_info(s->sha1, &s->size); - if (type < 0) + if (use_size_cache && 0 < type) locate_size_cache(s->sha1, 0, s->size); } else { -- cgit v1.3 From fc3abdf5cb16914fb22747d7c3fb44258712a36d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 3 May 2007 13:05:48 -0700 Subject: diff: release blobs after generating textual diff. This reduces the memory pressure when dealing with many paths. An unscientific test of running "diff-tree --stat --summary -M" between v2.6.19 and v2.6.20-rc1 in the linux kernel repository indicates that the number of minor faults are reduced by 2/3. Signed-off-by: Junio C Hamano --- diff.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 7bbe7590b2..2979bc57e4 100644 --- a/diff.c +++ b/diff.c @@ -1236,6 +1236,8 @@ static void builtin_diff(const char *name_a, } free_ab_and_return: + diff_free_filespec_data(one); + diff_free_filespec_data(two); free(a_one); free(b_two); return; @@ -1262,7 +1264,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, diff_populate_filespec(two, 0); data->deleted = count_lines(one->data, one->size); data->added = count_lines(two->data, two->size); - return; + goto free_and_return; } if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); @@ -1284,6 +1286,10 @@ static void builtin_diffstat(const char *name_a, const char *name_b, ecb.priv = diffstat; xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } + + free_and_return: + diff_free_filespec_data(one); + diff_free_filespec_data(two); } static void builtin_checkdiff(const char *name_a, const char *name_b, @@ -1306,7 +1312,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, die("unable to read files to diff"); if (file_is_binary(two)) - return; + goto free_and_return; else { /* Crazy xdl interfaces.. */ xpparam_t xpp; @@ -1320,6 +1326,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, ecb.priv = &data; xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } + free_and_return: + diff_free_filespec_data(one); + diff_free_filespec_data(two); } struct diff_filespec *alloc_filespec(const char *path) @@ -1507,7 +1516,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) size_only = 0; if (s->data) - return err; + return 0; if (S_ISDIRLNK(s->mode)) return diff_populate_gitlink(s, size_only); @@ -1597,8 +1606,11 @@ void diff_free_filespec_data(struct diff_filespec *s) free(s->data); else if (s->should_munmap) munmap(s->data, s->size); - s->should_free = s->should_munmap = 0; - s->data = NULL; + + if (s->should_free || s->should_munmap) { + s->should_free = s->should_munmap = 0; + s->data = NULL; + } free(s->cnt_data); s->cnt_data = NULL; } -- cgit v1.3 From 6e0b8ed6d35d0ed94b22652d6e8545b610cc43ab Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 7 May 2007 01:14:21 -0700 Subject: diff.c: do not use a separate "size cache". diff_filespec has a slot to record the size of the data already, so make use of it instead of a separate size cache. Signed-off-by: Junio C Hamano --- diff.c | 72 ++++-------------------------------------------------------------- 1 file changed, 4 insertions(+), 68 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 2979bc57e4..8354e71e07 100644 --- a/diff.c +++ b/diff.c @@ -16,8 +16,6 @@ #define FAST_WORKING_DIRECTORY 1 #endif -static int use_size_cache; - static int diff_detect_rename_default; static int diff_rename_limit_default = -1; static int diff_use_color_default; @@ -1408,55 +1406,6 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int return 1; } -static struct sha1_size_cache { - unsigned char sha1[20]; - unsigned long size; -} **sha1_size_cache; -static int sha1_size_cache_nr, sha1_size_cache_alloc; - -static struct sha1_size_cache *locate_size_cache(unsigned char *sha1, - int find_only, - unsigned long size) -{ - int first, last; - struct sha1_size_cache *e; - - first = 0; - last = sha1_size_cache_nr; - while (last > first) { - int cmp, next = (last + first) >> 1; - e = sha1_size_cache[next]; - cmp = hashcmp(e->sha1, sha1); - if (!cmp) - return e; - if (cmp < 0) { - last = next; - continue; - } - first = next+1; - } - /* not found */ - if (find_only) - return NULL; - /* insert to make it at "first" */ - if (sha1_size_cache_alloc <= sha1_size_cache_nr) { - sha1_size_cache_alloc = alloc_nr(sha1_size_cache_alloc); - sha1_size_cache = xrealloc(sha1_size_cache, - sha1_size_cache_alloc * - sizeof(*sha1_size_cache)); - } - sha1_size_cache_nr++; - if (first < sha1_size_cache_nr) - memmove(sha1_size_cache + first + 1, sha1_size_cache + first, - (sha1_size_cache_nr - first - 1) * - sizeof(*sha1_size_cache)); - e = xmalloc(sizeof(struct sha1_size_cache)); - sha1_size_cache[first] = e; - hashcpy(e->sha1, sha1); - e->size = size; - return e; -} - static int populate_from_stdin(struct diff_filespec *s) { #define INCREMENT 1024 @@ -1512,12 +1461,12 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (S_ISDIR(s->mode)) return -1; - if (!use_size_cache) - size_only = 0; - if (s->data) return 0; + if (size_only && 0 < s->size) + return 0; + if (S_ISDIRLNK(s->mode)) return diff_populate_gitlink(s, size_only); @@ -1579,19 +1528,8 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) } else { enum object_type type; - struct sha1_size_cache *e; - - if (size_only && use_size_cache && - (e = locate_size_cache(s->sha1, 1, 0)) != NULL) { - s->size = e->size; - return 0; - } - - if (size_only) { + if (size_only) type = sha1_object_info(s->sha1, &s->size); - if (use_size_cache && 0 < type) - locate_size_cache(s->sha1, 0, s->size); - } else { s->data = read_sha1_file(s->sha1, &type, &s->size); s->should_free = 1; @@ -2102,8 +2040,6 @@ int diff_setup_done(struct diff_options *options) */ read_cache(); } - if (options->setup & DIFF_SETUP_USE_SIZE_CACHE) - use_size_cache = 1; if (options->abbrev <= 0 || 40 < options->abbrev) options->abbrev = 40; /* full */ -- cgit v1.3 From 8a912bcb250d8bf57b225e1cf02c0d69d54c8920 Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Tue, 15 May 2007 14:49:22 +0200 Subject: Ensure return value from xread() is always stored into an ssize_t This patch fixes all calls to xread() where the return value is not stored into an ssize_t. The patch should not have any effect whatsoever, other than putting better/more appropriate type names on variables. Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- builtin-apply.c | 4 ++-- builtin-bundle.c | 2 +- builtin-fetch--tool.c | 4 ++-- builtin-unpack-objects.c | 2 +- combine-diff.c | 2 +- copy.c | 3 +-- diff.c | 2 +- imap-send.c | 2 +- index-pack.c | 2 +- pkt-line.c | 4 ++-- sha1_file.c | 2 +- ssh-upload.c | 2 +- 12 files changed, 15 insertions(+), 16 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 8b8705a6c0..0399743c4e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -185,7 +185,7 @@ static void *read_patch_file(int fd, unsigned long *sizep) void *buffer = xmalloc(alloc); for (;;) { - int nr = alloc - size; + ssize_t nr = alloc - size; if (nr < 1024) { alloc += CHUNKSIZE; buffer = xrealloc(buffer, alloc); @@ -1468,7 +1468,7 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign return error("unable to open %s", path); got = 0; for (;;) { - int ret = xread(fd, buf + got, size - got); + ssize_t ret = xread(fd, buf + got, size - got); if (ret <= 0) break; got += ret; diff --git a/builtin-bundle.c b/builtin-bundle.c index d1635a0a6b..306ad29597 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -48,7 +48,7 @@ static int read_string(int fd, char *buffer, int size) { int i; for (i = 0; i < size - 1; i++) { - int count = xread(fd, buffer + i, 1); + ssize_t count = xread(fd, buffer + i, 1); if (count < 0) return error("Read error: %s", strerror(errno)); if (count == 0) { diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 2065466f27..12adb3833c 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -6,11 +6,11 @@ static char *get_stdin(void) { - int offset = 0; + size_t offset = 0; char *data = xmalloc(CHUNK_SIZE); while (1) { - int cnt = xread(0, data + offset, CHUNK_SIZE); + ssize_t cnt = xread(0, data + offset, CHUNK_SIZE); if (cnt < 0) die("error reading standard input: %s", strerror(errno)); diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 2bbda67fab..a6ff62fd8c 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -34,7 +34,7 @@ static void *fill(int min) offset = 0; } do { - int ret = xread(0, buffer + len, sizeof(buffer) - len); + ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len); if (ret <= 0) { if (!ret) die("early EOF"); diff --git a/combine-diff.c b/combine-diff.c index cff9c5dc42..ea3ca5f950 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -714,7 +714,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, result_size = len; result = xmalloc(len + 1); while (sz < len) { - int done = xread(fd, result+sz, len-sz); + ssize_t done = xread(fd, result+sz, len-sz); if (done == 0) break; if (done < 0) diff --git a/copy.c b/copy.c index 08a3d388a4..d340bb253e 100644 --- a/copy.c +++ b/copy.c @@ -3,10 +3,9 @@ int copy_fd(int ifd, int ofd) { while (1) { - int len; char buffer[8192]; char *buf = buffer; - len = xread(ifd, buffer, sizeof(buffer)); + ssize_t len = xread(ifd, buffer, sizeof(buffer)); if (!len) break; if (len < 0) { diff --git a/diff.c b/diff.c index 8354e71e07..33297aa8a7 100644 --- a/diff.c +++ b/diff.c @@ -1411,7 +1411,7 @@ static int populate_from_stdin(struct diff_filespec *s) #define INCREMENT 1024 char *buf; unsigned long size; - int got; + ssize_t got; size = 0; buf = NULL; diff --git a/imap-send.c b/imap-send.c index 84df2fabb7..4283a4acda 100644 --- a/imap-send.c +++ b/imap-send.c @@ -224,7 +224,7 @@ socket_perror( const char *func, Socket_t *sock, int ret ) static int socket_read( Socket_t *sock, char *buf, int len ) { - int n = xread( sock->fd, buf, len ); + ssize_t n = xread( sock->fd, buf, len ); if (n <= 0) { socket_perror( "read", sock, n ); close( sock->fd ); diff --git a/index-pack.c b/index-pack.c index b9da19f55b..58c4a9c41d 100644 --- a/index-pack.c +++ b/index-pack.c @@ -82,7 +82,7 @@ static void *fill(int min) die("cannot fill %d bytes", min); flush(); do { - int ret = xread(input_fd, input_buffer + input_len, + ssize_t ret = xread(input_fd, input_buffer + input_len, sizeof(input_buffer) - input_len); if (ret <= 0) { if (!ret) diff --git a/pkt-line.c b/pkt-line.c index b4cb7e2756..b60526869a 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -65,10 +65,10 @@ void packet_write(int fd, const char *fmt, ...) static void safe_read(int fd, void *buffer, unsigned size) { - int n = 0; + size_t n = 0; while (n < size) { - int ret = xread(fd, (char *) buffer + n, size - n); + ssize_t ret = xread(fd, (char *) buffer + n, size - n); if (ret < 0) die("read error (%s)", strerror(errno)); if (!ret) diff --git a/sha1_file.c b/sha1_file.c index 32244d704e..be991ed22a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2276,7 +2276,7 @@ int read_pipe(int fd, char** return_buf, unsigned long* return_size) { char* buf = *return_buf; unsigned long size = *return_size; - int iret; + ssize_t iret; unsigned long off = 0; do { diff --git a/ssh-upload.c b/ssh-upload.c index 2f04572787..498d41e19b 100644 --- a/ssh-upload.c +++ b/ssh-upload.c @@ -86,7 +86,7 @@ static int serve_ref(int fd_in, int fd_out) static void service(int fd_in, int fd_out) { char type; - int retval; + ssize_t retval; do { retval = xread(fd_in, &type, 1); if (retval < 1) { -- cgit v1.3 From 1472966c04103874096fb786657459ea6628e451 Mon Sep 17 00:00:00 2001 From: "Fernando J. Pereda" Date: Sun, 20 May 2007 15:35:46 +0200 Subject: Use PATH_MAX instead of TEMPFILE_PATH_LEN Signed-off-by: Fernando J. Pereda Signed-off-by: Junio C Hamano --- diff.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index b28933f870..3c15553710 100644 --- a/diff.c +++ b/diff.c @@ -137,13 +137,11 @@ static const char *external_diff(void) return external_diff_cmd; } -#define TEMPFILE_PATH_LEN 50 - static struct diff_tempfile { const char *name; /* filename external diff should read from */ char hex[41]; char mode[10]; - char tmp_path[TEMPFILE_PATH_LEN]; + char tmp_path[PATH_MAX]; } diff_temp[2]; static int count_lines(const char *data, int size) @@ -1507,7 +1505,7 @@ static void prep_temp_blob(struct diff_tempfile *temp, { int fd; - fd = git_mkstemp(temp->tmp_path, TEMPFILE_PATH_LEN, ".diff_XXXXXX"); + fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX"); if (fd < 0) die("unable to create temp-file"); if (write_in_full(fd, blob, size) != size) -- cgit v1.3 From 302b9282c9ddfcc704ca759bdc98c1d5f75eba2f Mon Sep 17 00:00:00 2001 From: Martin Waitz Date: Mon, 21 May 2007 22:08:28 +0200 Subject: rename dirlink to gitlink. Unify naming of plumbing dirlink/gitlink concept: git ls-files -z '*.[ch]' | xargs -0 perl -pi -e 's/dirlink/gitlink/g;' -e 's/DIRLNK/GITLINK/g;' Signed-off-by: Junio C Hamano --- archive-tar.c | 4 ++-- archive-zip.c | 2 +- builtin-fsck.c | 4 ++-- builtin-ls-tree.c | 2 +- builtin-update-index.c | 4 ++-- cache-tree.c | 2 +- cache.h | 10 +++++----- diff.c | 2 +- dir.c | 6 +++--- dir.h | 2 +- entry.c | 4 ++-- list-objects.c | 2 +- read-cache.c | 6 +++--- tree.c | 4 ++-- 14 files changed, 27 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/archive-tar.c b/archive-tar.c index 33e76576f1..66fe3e375b 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -167,7 +167,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, } else { if (verbose) fprintf(stderr, "%.*s\n", path->len, path->buf); - if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { + if (S_ISDIR(mode) || S_ISGITLINK(mode)) { *header.typeflag = TYPEFLAG_DIR; mode = (mode | 0777) & ~tar_umask; } else if (S_ISLNK(mode)) { @@ -280,7 +280,7 @@ static int write_tar_entry(const unsigned char *sha1, memcpy(path.buf + baselen, filename, filenamelen); path.len = baselen + filenamelen; path.buf[path.len] = '\0'; - if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { + if (S_ISDIR(mode) || S_ISGITLINK(mode)) { strbuf_append_string(&path, "/"); buffer = NULL; size = 0; diff --git a/archive-zip.c b/archive-zip.c index 3cbf6bb8ac..444e1623db 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -182,7 +182,7 @@ static int write_zip_entry(const unsigned char *sha1, goto out; } - if (S_ISDIR(mode) || S_ISDIRLNK(mode)) { + if (S_ISDIR(mode) || S_ISGITLINK(mode)) { method = 0; attr2 = 16; result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0); diff --git a/builtin-fsck.c b/builtin-fsck.c index 44ce629a49..cbbcaf011a 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -256,7 +256,7 @@ static int fsck_tree(struct tree *item) case S_IFREG | 0644: case S_IFLNK: case S_IFDIR: - case S_IFDIRLNK: + case S_IFGITLINK: break; /* * This is nonstandard, but we had a few of these @@ -715,7 +715,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix) struct object *obj; mode = ntohl(active_cache[i]->ce_mode); - if (S_ISDIRLNK(mode)) + if (S_ISGITLINK(mode)) continue; blob = lookup_blob(active_cache[i]->sha1); if (!blob) diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c index 1cb4dca277..9a5977fb99 100644 --- a/builtin-ls-tree.c +++ b/builtin-ls-tree.c @@ -60,7 +60,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, int retval = 0; const char *type = blob_type; - if (S_ISDIRLNK(mode)) { + if (S_ISGITLINK(mode)) { /* * Maybe we want to have some recursive version here? * diff --git a/builtin-update-index.c b/builtin-update-index.c index 8f9899178b..509369e9e7 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -134,7 +134,7 @@ static int process_directory(const char *path, int len, struct stat *st) /* Exact match: file or existing gitlink */ if (pos >= 0) { struct cache_entry *ce = active_cache[pos]; - if (S_ISDIRLNK(ntohl(ce->ce_mode))) { + if (S_ISGITLINK(ntohl(ce->ce_mode))) { /* Do nothing to the index if there is no HEAD! */ if (resolve_gitlink_ref(path, "HEAD", sha1) < 0) @@ -178,7 +178,7 @@ static int process_file(const char *path, int len, struct stat *st) int pos = cache_name_pos(path, len); struct cache_entry *ce = pos < 0 ? NULL : active_cache[pos]; - if (ce && S_ISDIRLNK(ntohl(ce->ce_mode))) + if (ce && S_ISGITLINK(ntohl(ce->ce_mode))) return error("%s is already a gitlink, not replacing", path); return add_one_path(ce, path, len, st); diff --git a/cache-tree.c b/cache-tree.c index 6369cc7c53..350a79b768 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -326,7 +326,7 @@ static int update_one(struct cache_tree *it, mode = ntohl(ce->ce_mode); entlen = pathlen - baselen; } - if (mode != S_IFDIRLNK && !missing_ok && !has_sha1_file(sha1)) + if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) return error("invalid object %s", sha1_to_hex(sha1)); if (!ce->ce_mode) diff --git a/cache.h b/cache.h index 65b4685c1f..cd875bc2e9 100644 --- a/cache.h +++ b/cache.h @@ -40,8 +40,8 @@ * happens that everybody shares the same bit representation * in the UNIX world (and apparently wider too..) */ -#define S_IFDIRLNK 0160000 -#define S_ISDIRLNK(m) (((m) & S_IFMT) == S_IFDIRLNK) +#define S_IFGITLINK 0160000 +#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK) /* * Intensive research over the course of many years has shown that @@ -123,8 +123,8 @@ static inline unsigned int create_ce_mode(unsigned int mode) { if (S_ISLNK(mode)) return htonl(S_IFLNK); - if (S_ISDIR(mode) || S_ISDIRLNK(mode)) - return htonl(S_IFDIRLNK); + if (S_ISDIR(mode) || S_ISGITLINK(mode)) + return htonl(S_IFGITLINK); return htonl(S_IFREG | ce_permissions(mode)); } static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode) @@ -142,7 +142,7 @@ static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned in } #define canon_mode(mode) \ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ - S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFDIRLNK) + S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK) #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7) diff --git a/diff.c b/diff.c index b23e190678..0e260490d7 100644 --- a/diff.c +++ b/diff.c @@ -1465,7 +1465,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (size_only && 0 < s->size) return 0; - if (S_ISDIRLNK(s->mode)) + if (S_ISGITLINK(s->mode)) return diff_populate_gitlink(s, size_only); if (!s->sha1_valid || diff --git a/dir.c b/dir.c index 11fab7f4bf..f543f50f42 100644 --- a/dir.c +++ b/dir.c @@ -321,7 +321,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len) break; if (endchar == '/') return index_directory; - if (!endchar && S_ISDIRLNK(ntohl(ce->ce_mode))) + if (!endchar && S_ISGITLINK(ntohl(ce->ce_mode))) return index_gitdir; } return index_nonexistent; @@ -356,7 +356,7 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len) * also true and the directory is empty, in which case * we just ignore it entirely. * (b) if it looks like a git directory, and we don't have - * 'no_dirlinks' set we treat it as a gitlink, and show it + * 'no_gitlinks' set we treat it as a gitlink, and show it * as a directory. * (c) otherwise, we recurse into it. */ @@ -383,7 +383,7 @@ static enum directory_treatment treat_directory(struct dir_struct *dir, case index_nonexistent: if (dir->show_other_directories) break; - if (!dir->no_dirlinks) { + if (!dir->no_gitlinks) { unsigned char sha1[20]; if (resolve_gitlink_ref(dirname, "HEAD", sha1) == 0) return show_directory; diff --git a/dir.h b/dir.h index 817c674da1..172147fd3d 100644 --- a/dir.h +++ b/dir.h @@ -34,7 +34,7 @@ struct dir_struct { unsigned int show_ignored:1, show_other_directories:1, hide_empty_directories:1, - no_dirlinks:1; + no_gitlinks:1; struct dir_entry **entries; /* Exclude info */ diff --git a/entry.c b/entry.c index 82bf7259a7..ae6476496a 100644 --- a/entry.c +++ b/entry.c @@ -145,7 +145,7 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout "symlink %s (%s)", path, strerror(errno)); } break; - case S_IFDIRLNK: + case S_IFGITLINK: if (to_tempfile) return error("git-checkout-index: cannot create temporary subproject %s", path); if (mkdir(path, 0777) < 0) @@ -194,7 +194,7 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t unlink(path); if (S_ISDIR(st.st_mode)) { /* If it is a gitlink, leave it alone! */ - if (S_ISDIRLNK(ntohl(ce->ce_mode))) + if (S_ISGITLINK(ntohl(ce->ce_mode))) return 0; if (!state->force) return error("%s is a directory", path); diff --git a/list-objects.c b/list-objects.c index 310f8d3908..e5c88c278f 100644 --- a/list-objects.c +++ b/list-objects.c @@ -87,7 +87,7 @@ static void process_tree(struct rev_info *revs, process_tree(revs, lookup_tree(entry.sha1), p, &me, entry.path); - else if (S_ISDIRLNK(entry.mode)) + else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, p, &me, entry.path); else diff --git a/read-cache.c b/read-cache.c index d9f46da5cc..ad4e187537 100644 --- a/read-cache.c +++ b/read-cache.c @@ -92,7 +92,7 @@ static int ce_compare_gitlink(struct cache_entry *ce) /* * We don't actually require that the .git directory - * under DIRLNK directory be a valid git directory. It + * under GITLINK directory be a valid git directory. It * might even be missing (in case nobody populated that * sub-project). * @@ -115,7 +115,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st) return DATA_CHANGED; break; case S_IFDIR: - if (S_ISDIRLNK(ntohl(ce->ce_mode))) + if (S_ISGITLINK(ntohl(ce->ce_mode))) return 0; default: return TYPE_CHANGED; @@ -142,7 +142,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) (has_symlinks || !S_ISREG(st->st_mode))) changed |= TYPE_CHANGED; break; - case S_IFDIRLNK: + case S_IFGITLINK: if (!S_ISDIR(st->st_mode)) changed |= TYPE_CHANGED; else if (ce_compare_gitlink(ce)) diff --git a/tree.c b/tree.c index e4a39aa3c3..a3728270b4 100644 --- a/tree.c +++ b/tree.c @@ -157,7 +157,7 @@ static void track_tree_refs(struct tree *item) /* Count how many entries there are.. */ init_tree_desc(&desc, item->buffer, item->size); while (tree_entry(&desc, &entry)) { - if (S_ISDIRLNK(entry.mode)) + if (S_ISGITLINK(entry.mode)) continue; n_refs++; } @@ -169,7 +169,7 @@ static void track_tree_refs(struct tree *item) while (tree_entry(&desc, &entry)) { struct object *obj; - if (S_ISDIRLNK(entry.mode)) + if (S_ISGITLINK(entry.mode)) continue; if (S_ISDIR(entry.mode)) obj = &lookup_tree(entry.sha1)->object; -- cgit v1.3 From 5adf317b31729707fad4967c1aef6cdba43d0dd3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 26 May 2007 00:37:40 +0200 Subject: Replace the last 'dircache's by 'index' Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Documentation/git-ls-files.txt | 2 +- diff.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt index 79e0b7b71a..b7c8ab5f7a 100644 --- a/Documentation/git-ls-files.txt +++ b/Documentation/git-ls-files.txt @@ -124,7 +124,7 @@ which case it outputs: detailed information on unmerged paths. For an unmerged path, instead of recording a single mode/SHA1 pair, -the dircache records up to three such pairs; one from tree O in stage +the index records up to three such pairs; one from tree O in stage 1, A in stage 2, and B in stage 3. This information can be used by the user (or the porcelain) to see what should eventually be recorded at the path. (see git-read-tree for more information on state) diff --git a/diff.c b/diff.c index 3c15553710..487168be40 100644 --- a/diff.c +++ b/diff.c @@ -1258,7 +1258,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, } /* - * Given a name and sha1 pair, if the dircache tells us the file in + * Given a name and sha1 pair, if the index tells us the file in * the work tree has that object contents, return true, so that * prepare_temp_file() does not have to inflate and extract. */ -- cgit v1.3 From 6bfce93e04d13ecb42008a3cf214cc892f480f0c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 5 Jun 2007 03:36:11 +0100 Subject: Move buffer_is_binary() to xdiff-interface.h We already have two instances where we want to determine if a buffer contains binary data as opposed to text. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 7 +------ grep.c | 12 +----------- xdiff-interface.c | 8 ++++++++ xdiff-interface.h | 1 + 4 files changed, 11 insertions(+), 17 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 508bc51ed5..c57ac33414 100644 --- a/diff.c +++ b/diff.c @@ -1107,10 +1107,8 @@ static void setup_diff_attr_check(struct git_attr_check *check) check->attr = attr_diff; } -#define FIRST_FEW_BYTES 8000 static int file_is_binary(struct diff_filespec *one) { - unsigned long sz; struct git_attr_check attr_diff_check; setup_diff_attr_check(&attr_diff_check); @@ -1127,10 +1125,7 @@ static int file_is_binary(struct diff_filespec *one) return 0; diff_populate_filespec(one, 0); } - sz = one->size; - if (FIRST_FEW_BYTES < sz) - sz = FIRST_FEW_BYTES; - return !!memchr(one->data, 0, sz); + return buffer_is_binary(one->data, one->size); } static void builtin_diff(const char *name_a, diff --git a/grep.c b/grep.c index fcc6762302..f67d6716ea 100644 --- a/grep.c +++ b/grep.c @@ -1,5 +1,6 @@ #include "cache.h" #include "grep.h" +#include "xdiff-interface.h" void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t) @@ -232,17 +233,6 @@ static void show_line(struct grep_opt *opt, const char *bol, const char *eol, printf("%.*s\n", (int)(eol-bol), bol); } -/* - * NEEDSWORK: share code with diff.c - */ -#define FIRST_FEW_BYTES 8000 -static int buffer_is_binary(const char *ptr, unsigned long size) -{ - if (FIRST_FEW_BYTES < size) - size = FIRST_FEW_BYTES; - return !!memchr(ptr, 0, size); -} - static int fixmatch(const char *pattern, char *line, regmatch_t *match) { char *hit = strstr(line, pattern); diff --git a/xdiff-interface.c b/xdiff-interface.c index 10816e95a0..963bb89b08 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -122,4 +122,12 @@ int read_mmfile(mmfile_t *ptr, const char *filename) return 0; } +#define FIRST_FEW_BYTES 8000 +int buffer_is_binary(const char *ptr, unsigned long size) +{ + if (FIRST_FEW_BYTES < size) + size = FIRST_FEW_BYTES; + return !!memchr(ptr, 0, size); +} + diff --git a/xdiff-interface.h b/xdiff-interface.h index 1918808081..536f4e4d97 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -18,5 +18,6 @@ int parse_hunk_header(char *line, int len, int *ob, int *on, int *nb, int *nn); int read_mmfile(mmfile_t *ptr, const char *filename); +int buffer_is_binary(const char *ptr, unsigned long size); #endif -- cgit v1.3 From a6080a0a44d5ead84db3dabbbc80e82df838533d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 7 Jun 2007 00:04:01 -0700 Subject: War on whitespace This uses "git-apply --whitespace=strip" to fix whitespace errors that have crept in to our source files over time. There are a few files that need to have trailing whitespaces (most notably, test vectors). The results still passes the test, and build result in Documentation/ area is unchanged. Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.0.4.txt | 2 - Documentation/RelNotes-1.5.0.5.txt | 2 - Documentation/RelNotes-1.5.0.6.txt | 1 - Documentation/RelNotes-1.5.1.3.txt | 1 - Documentation/SubmittingPatches | 14 +- Documentation/asciidoc.conf | 2 - Documentation/config.txt | 2 - Documentation/core-tutorial.txt | 46 +- Documentation/diff-format.txt | 21 +- Documentation/diff-options.txt | 4 +- Documentation/diffcore.txt | 3 +- Documentation/docbook-xsl.css | 572 ++++++++++----------- Documentation/fetch-options.txt | 1 - Documentation/git-add.txt | 1 - Documentation/git-am.txt | 1 - Documentation/git-apply.txt | 1 - Documentation/git-archimport.txt | 45 +- Documentation/git-bisect.txt | 3 +- Documentation/git-branch.txt | 1 - Documentation/git-cat-file.txt | 1 - Documentation/git-check-attr.txt | 1 - Documentation/git-checkout-index.txt | 1 - Documentation/git-checkout.txt | 1 - Documentation/git-cherry-pick.txt | 1 - Documentation/git-cherry.txt | 1 - Documentation/git-clone.txt | 1 - Documentation/git-commit-tree.txt | 3 +- Documentation/git-config.txt | 1 - Documentation/git-convert-objects.txt | 1 - Documentation/git-count-objects.txt | 1 - Documentation/git-cvsexportcommit.txt | 15 +- Documentation/git-cvsimport.txt | 13 +- Documentation/git-daemon.txt | 1 - Documentation/git-describe.txt | 1 - Documentation/git-diff-files.txt | 3 +- Documentation/git-diff-index.txt | 3 +- Documentation/git-diff-tree.txt | 1 - Documentation/git-diff.txt | 1 - Documentation/git-fast-import.txt | 1 - Documentation/git-fmt-merge-msg.txt | 1 - Documentation/git-format-patch.txt | 1 - Documentation/git-fsck.txt | 1 - Documentation/git-get-tar-commit-id.txt | 1 - Documentation/git-grep.txt | 1 - Documentation/git-hash-object.txt | 3 +- Documentation/git-http-fetch.txt | 1 - Documentation/git-http-push.txt | 2 +- Documentation/git-index-pack.txt | 1 - Documentation/git-init-db.txt | 1 - Documentation/git-init.txt | 1 - Documentation/git-instaweb.txt | 1 - Documentation/git-local-fetch.txt | 1 - Documentation/git-log.txt | 1 - Documentation/git-ls-files.txt | 1 - Documentation/git-ls-remote.txt | 1 - Documentation/git-ls-tree.txt | 1 - Documentation/git-mailinfo.txt | 1 - Documentation/git-mailsplit.txt | 1 - Documentation/git-merge-base.txt | 1 - Documentation/git-merge-index.txt | 3 +- Documentation/git-merge-one-file.txt | 1 - Documentation/git-merge-tree.txt | 1 - Documentation/git-merge.txt | 2 +- Documentation/git-mergetool.txt | 1 - Documentation/git-mktag.txt | 1 - Documentation/git-mktree.txt | 1 - Documentation/git-mv.txt | 1 - Documentation/git-name-rev.txt | 1 - Documentation/git-p4import.txt | 1 - Documentation/git-pack-objects.txt | 1 - Documentation/git-pack-redundant.txt | 3 +- Documentation/git-patch-id.txt | 1 - Documentation/git-peek-remote.txt | 1 - Documentation/git-prune-packed.txt | 1 - Documentation/git-prune.txt | 1 - Documentation/git-pull.txt | 1 - Documentation/git-push.txt | 1 - Documentation/git-quiltimport.txt | 1 - Documentation/git-read-tree.txt | 1 - Documentation/git-rebase.txt | 1 - Documentation/git-reflog.txt | 1 - Documentation/git-relink.txt | 1 - Documentation/git-remote.txt | 1 - Documentation/git-repack.txt | 1 - Documentation/git-request-pull.txt | 1 - Documentation/git-rev-parse.txt | 1 - Documentation/git-revert.txt | 1 - Documentation/git-rm.txt | 1 - Documentation/git-runstatus.txt | 1 - Documentation/git-send-email.txt | 3 +- Documentation/git-sh-setup.txt | 1 - Documentation/git-shell.txt | 1 - Documentation/git-shortlog.txt | 1 - Documentation/git-show-index.txt | 1 - Documentation/git-show.txt | 1 - Documentation/git-ssh-fetch.txt | 1 - Documentation/git-ssh-upload.txt | 1 - Documentation/git-status.txt | 1 - Documentation/git-stripspace.txt | 1 - Documentation/git-svnimport.txt | 1 - Documentation/git-tar-tree.txt | 1 - Documentation/git-unpack-file.txt | 1 - Documentation/git-unpack-objects.txt | 1 - Documentation/git-update-index.txt | 9 +- Documentation/git-update-server-info.txt | 1 - Documentation/git-var.txt | 1 - Documentation/git-verify-pack.txt | 1 - Documentation/git-verify-tag.txt | 1 - Documentation/git-whatchanged.txt | 1 - Documentation/git-write-tree.txt | 1 - Documentation/git.txt | 1 - Documentation/gitk.txt | 1 - Documentation/howto/rebase-and-edit.txt | 20 +- .../howto/rebase-from-internal-branch.txt | 12 +- Documentation/howto/rebuild-from-update-hook.txt | 1 - Documentation/howto/revert-branch-rebase.txt | 2 +- Documentation/howto/separating-topic-branches.txt | 13 +- Documentation/howto/use-git-daemon.txt | 1 - Documentation/merge-options.txt | 1 - Documentation/pretty-formats.txt | 1 - Documentation/pretty-options.txt | 1 - Documentation/pull-fetch-param.txt | 2 +- Documentation/repository-layout.txt | 1 - Documentation/technical/pack-format.txt | 8 +- Documentation/user-manual.txt | 38 +- GIT-VERSION-GEN | 2 - INSTALL | 3 +- arm/sha1.c | 4 +- arm/sha1_arm.S | 1 - builtin-annotate.c | 1 - builtin-diff-index.c | 2 +- builtin-fmt-merge-msg.c | 1 - builtin-fsck.c | 4 +- builtin-ls-files.c | 2 +- builtin-name-rev.c | 1 - builtin-pack-objects.c | 2 +- builtin-rerere.c | 1 - builtin-shortlog.c | 1 - cache.h | 2 +- commit.c | 14 +- commit.h | 2 +- compat/mmap.c | 1 - config.c | 3 +- config.mak.in | 1 - connect.c | 2 +- contrib/README | 1 - contrib/blameview/README | 1 - contrib/gitview/gitview | 2 - contrib/hooks/post-receive-email | 2 +- contrib/remotes2config.sh | 2 - convert-objects.c | 2 +- copy.c | 1 - ctype.c | 1 - daemon.c | 4 +- date.c | 10 +- diff-lib.c | 2 +- diff.c | 4 +- diffcore-pickaxe.c | 2 +- entry.c | 2 +- environment.c | 2 - fetch-pack.c | 2 +- fetch.c | 4 +- git-archimport.perl | 175 ++++--- git-checkout.sh | 4 +- git-clone.sh | 5 +- git-commit.sh | 2 +- git-cvsexportcommit.perl | 2 +- git-cvsimport.perl | 12 +- git-gui/GIT-VERSION-GEN | 2 - git-gui/lib/class.tcl | 1 - git-merge-one-file.sh | 2 +- git-p4import.py | 1 - git-svnimport.perl | 4 +- git-tag.sh | 5 +- git-verify-tag.sh | 1 - git.spec.in | 2 +- gitk | 2 +- gitweb/README | 1 - help.c | 2 - http-fetch.c | 2 +- http-push.c | 2 +- http.c | 2 +- imap-send.c | 2 +- local-fetch.c | 8 +- lockfile.c | 1 - mailmap.c | 1 - match-trees.c | 1 - merge-index.c | 2 +- mktag.c | 2 +- mozilla-sha1/sha1.c | 19 +- mozilla-sha1/sha1.h | 18 +- object-refs.c | 2 - object.h | 2 +- pack-redundant.c | 4 +- patch-id.c | 2 +- path-list.c | 1 - perl/Makefile | 1 - pkt-line.c | 2 +- ppc/sha1.c | 2 +- read-cache.c | 10 +- rsh.h | 2 +- setup.c | 4 +- sha1_file.c | 8 +- shallow.c | 1 - ssh-upload.c | 10 +- strbuf.c | 1 - t/Makefile | 1 - t/lib-read-tree-m-3way.sh | 2 +- t/t0000-basic.sh | 2 +- t/t1200-tutorial.sh | 1 - t/t1300-repo-config.sh | 1 - t/t2000-checkout-cache-clash.sh | 2 - t/t2001-checkout-cache-clash.sh | 1 - t/t3030-merge-recursive.sh | 1 - t/t3403-rebase-skip.sh | 1 - t/t4006-diff-mode.sh | 1 - t/t4100-apply-stat.sh | 1 - t/t4110-apply-scan.sh | 1 - t/t4112-apply-renames.sh | 16 +- t/t4118-apply-empty-context.sh | 1 - t/t4119-apply-config.sh | 2 +- t/t4121-apply-diffs.sh | 1 - t/t4122-apply-symlink-inside.sh | 1 - t/t4200-rerere.sh | 2 - t/t5400-send-pack.sh | 2 +- t/t5520-pull.sh | 1 - t/t5710-info-alternate.sh | 1 - t/t6000lib.sh | 16 +- t/t6002-rev-list-bisect.sh | 8 +- t/t6021-merge-criss-cross.sh | 2 +- t/t6023-merge-file.sh | 1 - t/t6030-bisect-porcelain.sh | 1 - t/t6101-rev-parse-parents.sh | 1 - t/t9107-git-svn-migrate.sh | 1 - t/t9111/svnsync.dump | 2 - t/test-lib.sh | 2 +- templates/hooks--commit-msg | 1 - templates/hooks--post-receive | 1 - templates/hooks--pre-applypatch | 1 - templates/hooks--pre-commit | 1 - tree-walk.c | 1 - upload-pack.c | 2 +- var.c | 4 +- xdiff-interface.c | 2 - xdiff/xdiff.h | 1 - xdiff/xdiffi.c | 1 - xdiff/xdiffi.h | 1 - xdiff/xemit.c | 1 - xdiff/xemit.h | 1 - xdiff/xinclude.h | 1 - xdiff/xmacros.h | 1 - xdiff/xprepare.c | 1 - xdiff/xprepare.h | 1 - xdiff/xtypes.h | 1 - xdiff/xutils.c | 1 - xdiff/xutils.h | 1 - 256 files changed, 645 insertions(+), 852 deletions(-) (limited to 'diff.c') diff --git a/Documentation/RelNotes-1.5.0.4.txt b/Documentation/RelNotes-1.5.0.4.txt index b727a8d1e5..feefa5dfd4 100644 --- a/Documentation/RelNotes-1.5.0.4.txt +++ b/Documentation/RelNotes-1.5.0.4.txt @@ -20,5 +20,3 @@ Fixes since v1.5.0.3 * Documentation updates * User manual updates - - diff --git a/Documentation/RelNotes-1.5.0.5.txt b/Documentation/RelNotes-1.5.0.5.txt index aa86149d4f..eeec3d73d0 100644 --- a/Documentation/RelNotes-1.5.0.5.txt +++ b/Documentation/RelNotes-1.5.0.5.txt @@ -24,5 +24,3 @@ Fixes since v1.5.0.3 * Documentation updates * User manual updates - - diff --git a/Documentation/RelNotes-1.5.0.6.txt b/Documentation/RelNotes-1.5.0.6.txt index e15447ffdb..c02015ad5f 100644 --- a/Documentation/RelNotes-1.5.0.6.txt +++ b/Documentation/RelNotes-1.5.0.6.txt @@ -19,4 +19,3 @@ Fixes since v1.5.0.5 - user-manual has better cross references. - gitweb installation/deployment procedure is now documented. - diff --git a/Documentation/RelNotes-1.5.1.3.txt b/Documentation/RelNotes-1.5.1.3.txt index 2ddeabd029..876408b65a 100644 --- a/Documentation/RelNotes-1.5.1.3.txt +++ b/Documentation/RelNotes-1.5.1.3.txt @@ -43,4 +43,3 @@ Fixes since v1.5.1.2 description was given by the caller. Also contains various documentation updates. - diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index b9baa1d3b4..01354c2bb5 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -296,15 +296,15 @@ diff --git a/pico/pico.c b/pico/pico.c --- a/pico/pico.c +++ b/pico/pico.c @@ -219,7 +219,9 @@ PICO *pm; - switch(pico_all_done){ /* prepare for/handle final events */ - case COMP_EXIT : /* already confirmed */ - packheader(); + switch(pico_all_done){ /* prepare for/handle final events */ + case COMP_EXIT : /* already confirmed */ + packheader(); +#if 0 - stripwhitespace(); + stripwhitespace(); +#endif - c |= COMP_EXIT; - break; - + c |= COMP_EXIT; + break; + (Daniel Barkalow) diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 60e15ba349..99302c5beb 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -54,5 +54,3 @@ ifdef::backend-xhtml11[] [gitlink-inlinemacro] {target}{0?({0})} endif::backend-xhtml11[] - - diff --git a/Documentation/config.txt b/Documentation/config.txt index 5868d587a9..de408b6571 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -682,5 +682,3 @@ receive.denyNonFastForwards:: transfer.unpackLimit:: When `fetch.unpackLimit` or `receive.unpackLimit` are not set, the value of this variable is used instead. - - diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt index 6b9b9ad7d1..4fb6f4143c 100644 --- a/Documentation/core-tutorial.txt +++ b/Documentation/core-tutorial.txt @@ -9,11 +9,11 @@ repository, mainly because being hands-on and using explicit examples is often the best way of explaining what is going on. In normal life, most people wouldn't use the "core" git programs -directly, but rather script around them to make them more palatable. +directly, but rather script around them to make them more palatable. Understanding the core git stuff may help some people get those scripts done, though, and it may also be instructive in helping people understand what it is that the higher-level helper scripts are actually -doing. +doing. The core git is often called "plumbing", with the prettier user interfaces on top of it called "porcelain". You may not want to use the @@ -41,7 +41,7 @@ Creating a new git repository couldn't be easier: all git repositories start out empty, and the only thing you need to do is find yourself a subdirectory that you want to use as a working tree - either an empty one for a totally new project, or an existing working tree that you want -to import into git. +to import into git. For our first example, we're going to start a totally new repository from scratch, with no pre-existing files, and we'll call it `git-tutorial`. @@ -169,7 +169,7 @@ $ ls .git/objects/??/* and see two files: ---------------- -.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 +.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 .git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962 ---------------- @@ -220,7 +220,7 @@ you have not actually really "checked in" your files into git so far, you've only *told* git about them. However, since git knows about them, you can now start using some of the -most basic git commands to manipulate the files or look at their status. +most basic git commands to manipulate the files or look at their status. In particular, let's not even check in the two files into git yet, we'll start off by adding another line to `hello` first: @@ -350,7 +350,7 @@ Making a change Remember how we did the `git-update-index` on file `hello` and then we changed `hello` afterward, and could compare the new state of `hello` with the -state we saved in the index file? +state we saved in the index file? Further, remember how I said that `git-write-tree` writes the contents of the *index* file to the tree, and thus what we just committed was in @@ -370,7 +370,7 @@ file and the working tree, `git-diff-index` shows the differences between a committed *tree* and either the index file or the working tree. In other words, `git-diff-index` wants a tree to be diffed against, and before we did the commit, we couldn't do that, because we -didn't have anything to diff against. +didn't have anything to diff against. But now we can do @@ -379,7 +379,7 @@ $ git-diff-index -p HEAD ---------------- (where `-p` has the same meaning as it did in `git-diff-files`), and it -will show us the same difference, but for a totally different reason. +will show us the same difference, but for a totally different reason. Now we're comparing the working tree not against the index file, but against the tree we just wrote. It just so happens that those two are obviously the same, so we get the same result. @@ -398,7 +398,7 @@ working tree, but when given the `\--cached` flag, it is told to instead compare against just the index cache contents, and ignore the current working tree state entirely. Since we just wrote the index file to HEAD, doing `git-diff-index \--cached -p HEAD` should thus return -an empty set of differences, and that's exactly what it does. +an empty set of differences, and that's exactly what it does. [NOTE] ================ @@ -549,7 +549,7 @@ $ git-whatchanged -p --root ---------------- and you will see exactly what has changed in the repository over its -short history. +short history. [NOTE] The `\--root` flag is a flag to `git-diff-tree` to tell it to @@ -637,7 +637,7 @@ So the mental model of "the git information is always tied directly to the working tree that it describes" may not be technically 100% accurate, but it's a good model for all normal use. -This has two implications: +This has two implications: - if you grow bored with the tutorial repository you created (or you've made a mistake and want to start all over), you can just do simple @@ -705,7 +705,7 @@ Many (most?) public remote repositories will not contain any of the checked out files or even an index file, and will *only* contain the actual core git files. Such a repository usually doesn't even have the `.git` subdirectory, but has all the git files directly in the -repository. +repository. To create your own local live copy of such a "raw" git repository, you'd first create your own subdirectory for the project, and then copy the @@ -718,7 +718,7 @@ $ cd my-git $ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git ---------------- -followed by +followed by ---------------- $ git-read-tree HEAD @@ -738,7 +738,7 @@ up-to-date (so that you don't have to refresh it afterward), and the `-a` flag means "check out all files" (if you have a stale copy or an older version of a checked out tree you may also need to add the `-f` flag first, to tell git-checkout-index to *force* overwriting of any old -files). +files). Again, this can all be simplified with @@ -751,7 +751,7 @@ $ git checkout which will end up doing all of the above for you. You have now successfully copied somebody else's (mine) remote -repository, and checked it out. +repository, and checked it out. Creating a new branch @@ -760,14 +760,14 @@ Creating a new branch Branches in git are really nothing more than pointers into the git object database from within the `.git/refs/` subdirectory, and as we already discussed, the `HEAD` branch is nothing but a symlink to one of -these object pointers. +these object pointers. You can at any time create a new branch by just picking an arbitrary point in the project history, and just writing the SHA1 name of that object into a file under `.git/refs/heads/`. You can use any filename you want (and indeed, subdirectories), but the convention is that the "normal" branch is called `master`. That's just a convention, though, -and nothing enforces it. +and nothing enforces it. To show that as an example, let's go back to the git-tutorial repository we used earlier, and create a branch in it. You do that by simply just @@ -778,7 +778,7 @@ $ git checkout -b mybranch ------------ will create a new branch based at the current `HEAD` position, and switch -to it. +to it. [NOTE] ================================================ @@ -825,7 +825,7 @@ checking it out and switching to it. If so, just use the command $ git branch [startingpoint] ------------ -which will simply _create_ the branch, but will not do anything further. +which will simply _create_ the branch, but will not do anything further. You can then later -- once you decide that you want to actually develop on that branch -- switch to that branch with a regular `git checkout` with the branchname as the argument. @@ -884,7 +884,7 @@ $ gitk --all will show you graphically both of your branches (that's what the `\--all` means: normally it will just show you your current `HEAD`) and their histories. You can also see exactly how they came to be from a common -source. +source. Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want to merge the work we did on the `mybranch` branch into the `master` @@ -905,8 +905,8 @@ of it as it can automatically (which in this case is just merge the `example` file, which had no differences in the `mybranch` branch), and say: ---------------- - Auto-merging hello - CONFLICT (content): Merge conflict in hello + Auto-merging hello + CONFLICT (content): Merge conflict in hello Automatic merge failed; fix up by hand ---------------- @@ -1387,7 +1387,7 @@ repository. Kernel.org mirror network takes care of the propagation to other publicly visible machines: ------------ -$ git push master.kernel.org:/pub/scm/git/git.git/ +$ git push master.kernel.org:/pub/scm/git/git.git/ ------------ diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index e38a1f1405..18d49d2c3b 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -1,7 +1,7 @@ The output format from "git-diff-index", "git-diff-tree" and "git-diff-files" are very similar. -These commands all compare two sets of things; what is +These commands all compare two sets of things; what is compared differs: git-diff-index :: @@ -139,28 +139,28 @@ index fabadb8,cc95eb0..4866510 --- a/describe.c +++ b/describe.c @@@ -98,20 -98,12 +98,20 @@@ - return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; + return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; } - + - static void describe(char *arg) -static void describe(struct commit *cmit, int last_one) ++static void describe(char *arg, int last_one) { + unsigned char sha1[20]; + struct commit *cmit; - struct commit_list *list; - static int initialized = 0; - struct commit_name *n; - + struct commit_list *list; + static int initialized = 0; + struct commit_name *n; + + if (get_sha1(arg, sha1) < 0) + usage(describe_usage); + cmit = lookup_commit_reference(sha1); + if (!cmit) + usage(describe_usage); + - if (!initialized) { - initialized = 1; - for_each_ref(get_name); + if (!initialized) { + initialized = 1; + for_each_ref(get_name); ------------ 1. It is preceded with a "git diff" header, that looks like @@ -233,4 +233,3 @@ parents). When shown by `git diff-files -c`, it compares the two unresolved merge parents with the working tree file (i.e. file1 is stage 2 aka "our version", file2 is stage 3 aka "their version"). - diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 1689c74817..b2a05937f9 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -100,8 +100,8 @@ that matches other criteria, nothing is selected. --find-copies-harder:: - For performance reasons, by default, -C option finds copies only - if the original file of the copy was modified in the same + For performance reasons, by default, -C option finds copies only + if the original file of the copy was modified in the same changeset. This flag makes the command inspect unmodified files as candidates for the source of copy. This is a very expensive operation for large diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt index 34cd306bb1..c6a983a5d5 100644 --- a/Documentation/diffcore.txt +++ b/Documentation/diffcore.txt @@ -71,7 +71,7 @@ The first transformation in the chain is diffcore-pathspec, and is controlled by giving the pathname parameters to the git-diff-* commands on the command line. The pathspec is used to limit the world diff operates in. It removes the filepairs -outside the specified set of pathnames. E.g. If the input set +outside the specified set of pathnames. E.g. If the input set of filepairs included: ------------------------------------------------ @@ -269,4 +269,3 @@ Documentation *.c t ------------------------------------------------ - diff --git a/Documentation/docbook-xsl.css b/Documentation/docbook-xsl.css index 8821e305dd..b878b385c6 100644 --- a/Documentation/docbook-xsl.css +++ b/Documentation/docbook-xsl.css @@ -1,286 +1,286 @@ -/* - CSS stylesheet for XHTML produced by DocBook XSL stylesheets. - Tested with XSL stylesheets 1.61.2, 1.67.2 -*/ - -span.strong { - font-weight: bold; -} - -body blockquote { - margin-top: .75em; - line-height: 1.5; - margin-bottom: .75em; -} - -html body { - margin: 1em 5% 1em 5%; - line-height: 1.2; -} - -body div { - margin: 0; -} - -h1, h2, h3, h4, h5, h6, -div.toc p b, -div.list-of-figures p b, -div.list-of-tables p b, -div.abstract p.title -{ - color: #527bbd; - font-family: tahoma, verdana, sans-serif; -} - -div.toc p:first-child, -div.list-of-figures p:first-child, -div.list-of-tables p:first-child, -div.example p.title -{ - margin-bottom: 0.2em; -} - -body h1 { - margin: .0em 0 0 -4%; - line-height: 1.3; - border-bottom: 2px solid silver; -} - -body h2 { - margin: 0.5em 0 0 -4%; - line-height: 1.3; - border-bottom: 2px solid silver; -} - -body h3 { - margin: .8em 0 0 -3%; - line-height: 1.3; -} - -body h4 { - margin: .8em 0 0 -3%; - line-height: 1.3; -} - -body h5 { - margin: .8em 0 0 -2%; - line-height: 1.3; -} - -body h6 { - margin: .8em 0 0 -1%; - line-height: 1.3; -} - -body hr { - border: none; /* Broken on IE6 */ -} -div.footnotes hr { - border: 1px solid silver; -} - -div.navheader th, div.navheader td, div.navfooter td { - font-family: sans-serif; - font-size: 0.9em; - font-weight: bold; - color: #527bbd; -} -div.navheader img, div.navfooter img { - border-style: none; -} -div.navheader a, div.navfooter a { - font-weight: normal; -} -div.navfooter hr { - border: 1px solid silver; -} - -body td { - line-height: 1.2 -} - -body th { - line-height: 1.2; -} - -ol { - line-height: 1.2; -} - -ul, body dir, body menu { - line-height: 1.2; -} - -html { - margin: 0; - padding: 0; -} - -body h1, body h2, body h3, body h4, body h5, body h6 { - margin-left: 0 -} - -body pre { - margin: 0.5em 10% 0.5em 1em; - line-height: 1.0; - color: navy; -} - -tt.literal, code.literal { - color: navy; -} - -div.literallayout p { - padding: 0em; - margin: 0em; -} - -div.literallayout { - font-family: monospace; -# margin: 0.5em 10% 0.5em 1em; - margin: 0em; - color: navy; - border: 1px solid silver; - background: #f4f4f4; - padding: 0.5em; -} - -.programlisting, .screen { - border: 1px solid silver; - background: #f4f4f4; - margin: 0.5em 10% 0.5em 0; - padding: 0.5em 1em; -} - -div.sidebar { - background: #ffffee; - margin: 1.0em 10% 0.5em 0; - padding: 0.5em 1em; - border: 1px solid silver; -} -div.sidebar * { padding: 0; } -div.sidebar div { margin: 0; } -div.sidebar p.title { - font-family: sans-serif; - margin-top: 0.5em; - margin-bottom: 0.2em; -} - -div.bibliomixed { - margin: 0.5em 5% 0.5em 1em; -} - -div.glossary dt { - font-weight: bold; -} -div.glossary dd p { - margin-top: 0.2em; -} - -dl { - margin: .8em 0; - line-height: 1.2; -} - -dt { - margin-top: 0.5em; -} - -dt span.term { - font-style: italic; -} - -div.variablelist dd p { - margin-top: 0; -} - -div.itemizedlist li, div.orderedlist li { - margin-left: -0.8em; - margin-top: 0.5em; -} - -ul, ol { - list-style-position: outside; -} - -div.sidebar ul, div.sidebar ol { - margin-left: 2.8em; -} - -div.itemizedlist p.title, -div.orderedlist p.title, -div.variablelist p.title -{ - margin-bottom: -0.8em; -} - -div.revhistory table { - border-collapse: collapse; - border: none; -} -div.revhistory th { - border: none; - color: #527bbd; - font-family: tahoma, verdana, sans-serif; -} -div.revhistory td { - border: 1px solid silver; -} - -/* Keep TOC and index lines close together. */ -div.toc dl, div.toc dt, -div.list-of-figures dl, div.list-of-figures dt, -div.list-of-tables dl, div.list-of-tables dt, -div.indexdiv dl, div.indexdiv dt -{ - line-height: normal; - margin-top: 0; - margin-bottom: 0; -} - -/* - Table styling does not work because of overriding attributes in - generated HTML. -*/ -div.table table, -div.informaltable table -{ - margin-left: 0; - margin-right: 5%; - margin-bottom: 0.8em; -} -div.informaltable table -{ - margin-top: 0.4em -} -div.table thead, -div.table tfoot, -div.table tbody, -div.informaltable thead, -div.informaltable tfoot, -div.informaltable tbody -{ - /* No effect in IE6. */ - border-top: 2px solid #527bbd; - border-bottom: 2px solid #527bbd; -} -div.table thead, div.table tfoot, -div.informaltable thead, div.informaltable tfoot -{ - font-weight: bold; -} - -div.mediaobject img { - border: 1px solid silver; - margin-bottom: 0.8em; -} -div.figure p.title, -div.table p.title -{ - margin-top: 1em; - margin-bottom: 0.4em; -} - -@media print { - div.navheader, div.navfooter { display: none; } -} +/* + CSS stylesheet for XHTML produced by DocBook XSL stylesheets. + Tested with XSL stylesheets 1.61.2, 1.67.2 +*/ + +span.strong { + font-weight: bold; +} + +body blockquote { + margin-top: .75em; + line-height: 1.5; + margin-bottom: .75em; +} + +html body { + margin: 1em 5% 1em 5%; + line-height: 1.2; +} + +body div { + margin: 0; +} + +h1, h2, h3, h4, h5, h6, +div.toc p b, +div.list-of-figures p b, +div.list-of-tables p b, +div.abstract p.title +{ + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} + +div.toc p:first-child, +div.list-of-figures p:first-child, +div.list-of-tables p:first-child, +div.example p.title +{ + margin-bottom: 0.2em; +} + +body h1 { + margin: .0em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h2 { + margin: 0.5em 0 0 -4%; + line-height: 1.3; + border-bottom: 2px solid silver; +} + +body h3 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h4 { + margin: .8em 0 0 -3%; + line-height: 1.3; +} + +body h5 { + margin: .8em 0 0 -2%; + line-height: 1.3; +} + +body h6 { + margin: .8em 0 0 -1%; + line-height: 1.3; +} + +body hr { + border: none; /* Broken on IE6 */ +} +div.footnotes hr { + border: 1px solid silver; +} + +div.navheader th, div.navheader td, div.navfooter td { + font-family: sans-serif; + font-size: 0.9em; + font-weight: bold; + color: #527bbd; +} +div.navheader img, div.navfooter img { + border-style: none; +} +div.navheader a, div.navfooter a { + font-weight: normal; +} +div.navfooter hr { + border: 1px solid silver; +} + +body td { + line-height: 1.2 +} + +body th { + line-height: 1.2; +} + +ol { + line-height: 1.2; +} + +ul, body dir, body menu { + line-height: 1.2; +} + +html { + margin: 0; + padding: 0; +} + +body h1, body h2, body h3, body h4, body h5, body h6 { + margin-left: 0 +} + +body pre { + margin: 0.5em 10% 0.5em 1em; + line-height: 1.0; + color: navy; +} + +tt.literal, code.literal { + color: navy; +} + +div.literallayout p { + padding: 0em; + margin: 0em; +} + +div.literallayout { + font-family: monospace; +# margin: 0.5em 10% 0.5em 1em; + margin: 0em; + color: navy; + border: 1px solid silver; + background: #f4f4f4; + padding: 0.5em; +} + +.programlisting, .screen { + border: 1px solid silver; + background: #f4f4f4; + margin: 0.5em 10% 0.5em 0; + padding: 0.5em 1em; +} + +div.sidebar { + background: #ffffee; + margin: 1.0em 10% 0.5em 0; + padding: 0.5em 1em; + border: 1px solid silver; +} +div.sidebar * { padding: 0; } +div.sidebar div { margin: 0; } +div.sidebar p.title { + font-family: sans-serif; + margin-top: 0.5em; + margin-bottom: 0.2em; +} + +div.bibliomixed { + margin: 0.5em 5% 0.5em 1em; +} + +div.glossary dt { + font-weight: bold; +} +div.glossary dd p { + margin-top: 0.2em; +} + +dl { + margin: .8em 0; + line-height: 1.2; +} + +dt { + margin-top: 0.5em; +} + +dt span.term { + font-style: italic; +} + +div.variablelist dd p { + margin-top: 0; +} + +div.itemizedlist li, div.orderedlist li { + margin-left: -0.8em; + margin-top: 0.5em; +} + +ul, ol { + list-style-position: outside; +} + +div.sidebar ul, div.sidebar ol { + margin-left: 2.8em; +} + +div.itemizedlist p.title, +div.orderedlist p.title, +div.variablelist p.title +{ + margin-bottom: -0.8em; +} + +div.revhistory table { + border-collapse: collapse; + border: none; +} +div.revhistory th { + border: none; + color: #527bbd; + font-family: tahoma, verdana, sans-serif; +} +div.revhistory td { + border: 1px solid silver; +} + +/* Keep TOC and index lines close together. */ +div.toc dl, div.toc dt, +div.list-of-figures dl, div.list-of-figures dt, +div.list-of-tables dl, div.list-of-tables dt, +div.indexdiv dl, div.indexdiv dt +{ + line-height: normal; + margin-top: 0; + margin-bottom: 0; +} + +/* + Table styling does not work because of overriding attributes in + generated HTML. +*/ +div.table table, +div.informaltable table +{ + margin-left: 0; + margin-right: 5%; + margin-bottom: 0.8em; +} +div.informaltable table +{ + margin-top: 0.4em +} +div.table thead, +div.table tfoot, +div.table tbody, +div.informaltable thead, +div.informaltable tfoot, +div.informaltable tbody +{ + /* No effect in IE6. */ + border-top: 2px solid #527bbd; + border-bottom: 2px solid #527bbd; +} +div.table thead, div.table tfoot, +div.informaltable thead, div.informaltable tfoot +{ + font-weight: bold; +} + +div.mediaobject img { + border: 1px solid silver; + margin-bottom: 0.8em; +} +div.figure p.title, +div.table p.title +{ + margin-top: 1em; + margin-bottom: 0.4em; +} + +@media print { + div.navheader, div.navfooter { display: none; } +} diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt index bdc7332c7b..da034223f3 100644 --- a/Documentation/fetch-options.txt +++ b/Documentation/fetch-options.txt @@ -52,4 +52,3 @@ Deepen the history of a 'shallow' repository created by `git clone` with `--depth=` option (see gitlink:git-clone[1]) by the specified number of commits. - diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index a0c9f68580..76d2b05854 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -228,4 +228,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index f3387f5d09..e4a6b3a6f0 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -158,4 +158,3 @@ Documentation by Petr Baudis, Junio C Hamano and the git-list parameters supplied. If it cannot find the remote branch a merge comes from -it will just import it as a regular commit. If it can find it, it will mark it -as a merge whenever possible (see discussion below). +it will just import it as a regular commit. If it can find it, it will mark it +as a merge whenever possible (see discussion below). -The script expects you to provide the key roots where it can start the import -from an 'initial import' or 'tag' type of Arch commit. It will follow and -import new branches within the provided roots. +The script expects you to provide the key roots where it can start the import +from an 'initial import' or 'tag' type of Arch commit. It will follow and +import new branches within the provided roots. -It expects to be dealing with one project only. If it sees -branches that have different roots, it will refuse to run. In that case, -edit your parameters to define clearly the scope of the -import. +It expects to be dealing with one project only. If it sees +branches that have different roots, it will refuse to run. In that case, +edit your parameters to define clearly the scope of the +import. -`git-archimport` uses `tla` extensively in the background to access the +`git-archimport` uses `tla` extensively in the background to access the Arch repository. Make sure you have a recent version of `tla` available in the path. `tla` must -know about the repositories you pass to `git-archimport`. +know about the repositories you pass to `git-archimport`. -For the initial import `git-archimport` expects to find itself in an empty -directory. To follow the development of a project that uses Arch, rerun -`git-archimport` with the same parameters as the initial import to perform +For the initial import `git-archimport` expects to find itself in an empty +directory. To follow the development of a project that uses Arch, rerun +`git-archimport` with the same parameters as the initial import to perform incremental imports. While git-archimport will try to create sensible branch names for the @@ -54,15 +54,15 @@ convert Arch repositories that had been rotated periodically. MERGES ------ -Patch merge data from Arch is used to mark merges in git as well. git +Patch merge data from Arch is used to mark merges in git as well. git does not care much about tracking patches, and only considers a merge when a branch incorporates all the commits since the point they forked. The end result -is that git will have a good idea of how far branches have diverged. So the +is that git will have a good idea of how far branches have diverged. So the import process does lose some patch-trading metadata. -Fortunately, when you try and merge branches imported from Arch, -git will find a good merge base, and it has a good chance of identifying -patches that have been traded out-of-sequence between the branches. +Fortunately, when you try and merge branches imported from Arch, +git will find a good merge base, and it has a good chance of identifying +patches that have been traded out-of-sequence between the branches. OPTIONS ------- @@ -71,10 +71,10 @@ OPTIONS Display usage. -v:: - Verbose output. + Verbose output. -T:: - Many tags. Will create a tag for every commit, reflecting the commit + Many tags. Will create a tag for every commit, reflecting the commit name in the Arch repository. -f:: @@ -104,7 +104,7 @@ OPTIONS :: - Archive/branch identifier in a format that `tla log` understands. + Archive/branch identifier in a format that `tla log` understands. Author @@ -118,4 +118,3 @@ Documentation by Junio C Hamano, Martin Langhoff and the git-list +'git bisect' DESCRIPTION ----------- @@ -200,4 +200,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt index 8dc5171f5e..8d72bb9368 100644 --- a/Documentation/git-branch.txt +++ b/Documentation/git-branch.txt @@ -158,4 +158,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 075c0d05ef..afa095c795 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -71,4 +71,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index 918d8ee720..ea26da8e21 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -215,4 +215,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 68bba98260..47b1e8c2fc 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -68,4 +68,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt index 27b67b81a5..b62c97097f 100644 --- a/Documentation/git-cherry.txt +++ b/Documentation/git-cherry.txt @@ -64,4 +64,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 644bf126fb..2461c0ec2d 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -175,4 +175,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index 504a3aa1b4..9586b97291 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -40,7 +40,7 @@ OPTIONS -p :: Each '-p' indicates the id of a parent commit object. - + Commit Information ------------------ @@ -107,4 +107,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index da5c242241..827711c3c9 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -14,19 +14,19 @@ SYNOPSIS DESCRIPTION ----------- Exports a commit from GIT to a CVS checkout, making it easier -to merge patches from a git repository into a CVS repository. +to merge patches from a git repository into a CVS repository. -Execute it from the root of the CVS working copy. GIT_DIR must be defined. +Execute it from the root of the CVS working copy. GIT_DIR must be defined. See examples below. -It does its best to do the safe thing, it will check that the files are -unchanged and up to date in the CVS checkout, and it will not autocommit +It does its best to do the safe thing, it will check that the files are +unchanged and up to date in the CVS checkout, and it will not autocommit by default. Supports file additions, removals, and commits that affect binary files. If the commit is a merge commit, you must tell git-cvsexportcommit what parent -should the changeset be done against. +should the changeset be done against. OPTIONS ------- @@ -55,7 +55,7 @@ OPTIONS Force the parent commit, even if it is not a direct parent. -m:: - Prepend the commit message with the provided prefix. + Prepend the commit message with the provided prefix. Useful for patch series and the like. -u:: @@ -73,7 +73,7 @@ Merge one patch into CVS:: $ export GIT_DIR=~/project/.git $ cd ~/project_cvs_checkout $ git-cvsexportcommit -v -$ cvs commit -F .mgs +$ cvs commit -F .mgs ------------ Merge pending patches into CVS automatically -- only if you really know what you are doing :: @@ -95,4 +95,3 @@ Documentation by Martin Langhoff GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index e0be856546..3985e0164b 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -37,7 +37,7 @@ OPTIONS -d :: The root of the CVS archive. May be local (a simple path) or remote; - currently, only the :local:, :ext: and :pserver: access methods + currently, only the :local:, :ext: and :pserver: access methods are supported. If not given, git-cvsimport will try to read it from `CVS/Root`. If no such file exists, it checks for the `CVSROOT` environment variable. @@ -67,7 +67,7 @@ the old cvs2git tool. -k:: Kill keywords: will extract files with '-kk' from the CVS archive to avoid noisy changesets. Highly recommended, but off by default - to preserve compatibility with early imported trees. + to preserve compatibility with early imported trees. -u:: Convert underscores in tag and branch names to dots. @@ -89,15 +89,15 @@ If you need to pass multiple options, separate them with a comma. Instead of calling cvsps, read the provided cvsps output file. Useful for debugging or when cvsps is being handled outside cvsimport. --m:: +-m:: Attempt to detect merges based on the commit message. This option - will enable default regexes that try to capture the name source - branch name from the commit message. + will enable default regexes that try to capture the name source + branch name from the commit message. -M :: Attempt to detect merges based on the commit message with a custom regex. It can be used with '-m' to also see the default regexes. - You must escape forward slashes. + You must escape forward slashes. -S :: Skip paths matching the regex. @@ -156,4 +156,3 @@ Documentation by Matthias Urlichs . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 9ddab71203..4b30b18b42 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -235,4 +235,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt index dc47b65ced..ac23e28f27 100644 --- a/Documentation/git-describe.txt +++ b/Documentation/git-describe.txt @@ -124,4 +124,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 8d06775a6b..5eacab08dc 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -908,4 +908,3 @@ Documentation by Shawn O. Pearce . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt index 4913c2552f..6affc5bb4d 100644 --- a/Documentation/git-fmt-merge-msg.txt +++ b/Documentation/git-fmt-merge-msg.txt @@ -60,4 +60,3 @@ Documentation by Petr Baudis, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index ed6413a3c7..234c22f57f 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -145,4 +145,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index c5a5dad1ce..97faaa1d3a 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -144,4 +144,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index 5edc36f060..616f196d81 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -18,7 +18,7 @@ work tree), and optionally writes the resulting object into the object database. Reports its object ID to its standard output. This is used by "git-cvsimport" to update the index without modifying files in the work tree. When is not -specified, it defaults to "blob". +specified, it defaults to "blob". OPTIONS ------- @@ -43,4 +43,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list ' specification can be either a single pattern, or a pair of such patterns separated by a colon ":" (this means that a ref name -cannot have a colon in it). A single pattern '' is just a +cannot have a colon in it). A single pattern '' is just a shorthand for ':'. Each pattern pair consists of the source side (before the colon) diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt index 226926964e..a8a7f6f04b 100644 --- a/Documentation/git-index-pack.txt +++ b/Documentation/git-index-pack.txt @@ -98,4 +98,3 @@ Documentation by Sergey Vlasov GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt index 5412135d76..ab0201aec2 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.txt @@ -16,4 +16,3 @@ DESCRIPTION This is a synonym for gitlink:git-init[1]. Please refer to the documentation of that command. - diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt index 1b64d3ab03..413ed65143 100644 --- a/Documentation/git-init.txt +++ b/Documentation/git-init.txt @@ -108,4 +108,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index 51389ef37d..19b5f8895c 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -62,4 +62,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index ad7f1b9202..7b78599673 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -92,4 +92,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index 16956951dd..64aa6a1ea6 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -67,4 +67,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index abb0903696..c4f4cabbdc 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt index 3190aed108..6b71880ec4 100644 --- a/Documentation/git-merge-base.txt +++ b/Documentation/git-merge-base.txt @@ -40,4 +40,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list git-merge-index cat AA MM cat: : No such file or directory @@ -85,4 +85,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 912ef29efc..d285cba033 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -95,7 +95,7 @@ When things cleanly merge, these things happen: 1. the results are updated both in the index file and in your working tree, 2. index file is written out as a tree, -3. the tree gets committed, and +3. the tree gets committed, and 4. the `HEAD` pointer gets advanced. Because of 2., we require that the original state of the index diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index add01e855a..b89c51c65b 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -43,4 +43,3 @@ Documentation by Theodore Y Ts'o. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt index 2860a3d1ba..0ac3be10c7 100644 --- a/Documentation/git-mktag.txt +++ b/Documentation/git-mktag.txt @@ -44,4 +44,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index 6756b76bb1..2c9cf743c7 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -51,4 +51,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index cfe127ad9e..e3549b5044 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -185,4 +185,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt index 94bbea0db2..f2ceebac4b 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.txt @@ -17,7 +17,7 @@ are redundant. The output is suitable for piping to 'xargs rm' if you are in the root of the repository. git-pack-redundant accepts a list of objects on standard input. Any objects -given will be ignored when checking which packs are required. This makes the +given will be ignored when checking which packs are required. This makes the following command useful when wanting to remove packs which contain unreachable objects. @@ -55,4 +55,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt index a7e9fd021a..ad528a9224 100644 --- a/Documentation/git-patch-id.txt +++ b/Documentation/git-patch-id.txt @@ -40,4 +40,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index 74f37bd904..abc171266a 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -52,4 +52,3 @@ Documentation by Junio C Hamano. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt index 310033e460..3800edb7bb 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.txt @@ -50,4 +50,3 @@ gitlink:git-repack[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index 0b44f3015d..50ee5bddd0 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -58,4 +58,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index e9ad10672a..366c5dbdce 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -110,4 +110,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt index 296937a416..1c3ef4c593 100644 --- a/Documentation/git-quiltimport.txt +++ b/Documentation/git-quiltimport.txt @@ -58,4 +58,3 @@ Documentation by Eric Biederman GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index acb57447a8..84184d6294 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -356,4 +356,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt index 1e343bcdcd..f717e1e30c 100644 --- a/Documentation/git-reflog.txt +++ b/Documentation/git-reflog.txt @@ -65,4 +65,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-relink.txt b/Documentation/git-relink.txt index aca60120c8..fe631bb3dd 100644 --- a/Documentation/git-relink.txt +++ b/Documentation/git-relink.txt @@ -34,4 +34,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index 3dde7134a5..ab232c2f68 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -128,4 +128,3 @@ Documentation by J. Bruce Fields and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 2847c9b8d7..c33a512ffb 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -101,4 +101,3 @@ gitlink:git-prune-packed[1] GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt index 478a5fd6b7..087eeb7cc2 100644 --- a/Documentation/git-request-pull.txt +++ b/Documentation/git-request-pull.txt @@ -37,4 +37,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 7757abe621..e1cb4ef856 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -286,4 +286,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index 8081bbaffa..69db498447 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index a65f24a0f6..78f45dca2e 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -95,4 +95,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-runstatus.txt b/Documentation/git-runstatus.txt index 8bb52f4687..dee5d0da9d 100644 --- a/Documentation/git-runstatus.txt +++ b/Documentation/git-runstatus.txt @@ -66,4 +66,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 228b9f14f3..48f2d57b7b 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -32,4 +32,3 @@ Documentation by Petr Baudis and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index 15cc6f77c1..2220ef6ea8 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -56,4 +56,3 @@ Documentation by Junio C Hamano. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index be09b62beb..764d99356b 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -32,4 +32,3 @@ Documentation by Junio C Hamano GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt index 34c5caf2d0..a42e121150 100644 --- a/Documentation/git-show.txt +++ b/Documentation/git-show.txt @@ -84,4 +84,3 @@ This manual page is a stub. You can help the git documentation by expanding it. GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-ssh-fetch.txt b/Documentation/git-ssh-fetch.txt index 192b1f15a9..aaf3db06da 100644 --- a/Documentation/git-ssh-fetch.txt +++ b/Documentation/git-ssh-fetch.txt @@ -48,4 +48,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index bdae7d87dc..e97d15e8f2 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -174,4 +174,3 @@ Documentation by Matthias Urlichs . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 7bde73b1b8..2d01d9666f 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -90,4 +90,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list :: Directly insert the specified info into the index. - + --index-info:: Read index information from stdin. --chmod=(+|-)x:: - Set the execute permissions on the updated files. + Set the execute permissions on the updated files. --assume-unchanged, --no-assume-unchanged:: When these flags are specified, the object name recorded @@ -126,7 +126,7 @@ OPTIONS :: Files to act on. Note that files beginning with '.' are discarded. This includes - `./file` and `dir/./file`. If you don't want this, then use + `./file` and `dir/./file`. If you don't want this, then use cleaner names. The same applies to directories ending '/' and paths with '//' @@ -324,4 +324,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index 7a6132b016..f4c540f39b 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -51,4 +51,3 @@ Documentation by Junio C Hamano GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt index 0f9bdb58dc..48d17fd9c4 100644 --- a/Documentation/git-verify-tag.txt +++ b/Documentation/git-verify-tag.txt @@ -29,4 +29,3 @@ Documentation by Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt index 399bff3bbc..607df48f09 100644 --- a/Documentation/git-whatchanged.txt +++ b/Documentation/git-whatchanged.txt @@ -78,4 +78,3 @@ Documentation by David Greaves, Junio C Hamano and the git-list . GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt index 48c5894736..e9f82b97b9 100644 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@ -99,4 +99,3 @@ Documentation by Junio C Hamano, Jonas Fonseca, and the git-list GIT --- Part of the gitlink:git[7] suite - diff --git a/Documentation/howto/rebase-and-edit.txt b/Documentation/howto/rebase-and-edit.txt index 646c55cc69..554909fe08 100644 --- a/Documentation/howto/rebase-and-edit.txt +++ b/Documentation/howto/rebase-and-edit.txt @@ -9,16 +9,16 @@ Abstract: In this article, Linus demonstrates how a broken commit On Sat, 13 Aug 2005, Linus Torvalds wrote: -> That's correct. Same things apply: you can move a patch over, and create a -> new one with a modified comment, but basically the _old_ commit will be +> That's correct. Same things apply: you can move a patch over, and create a +> new one with a modified comment, but basically the _old_ commit will be > immutable. Let me clarify. You can entirely _drop_ old branches, so commits may be immutable, but -nothing forces you to keep them. Of course, when you drop a commit, you'll -always end up dropping all the commits that depended on it, and if you -actually got somebody else to pull that commit you can't drop it from +nothing forces you to keep them. Of course, when you drop a commit, you'll +always end up dropping all the commits that depended on it, and if you +actually got somebody else to pull that commit you can't drop it from _their_ repository, but undoing things is not impossible. For example, let's say that you've made a mess of things: you've committed @@ -29,7 +29,7 @@ want to save "b" and "c". What you can do is # for reference git branch broken - # Reset the main branch to three parents back: this + # Reset the main branch to three parents back: this # effectively undoes the three top commits git reset HEAD^^^ git checkout -f @@ -59,7 +59,7 @@ Finally, check out the end result again: to see that everything looks sensible. -And then, you can just remove the broken branch if you decide you really +And then, you can just remove the broken branch if you decide you really don't want it: # remove 'broken' branch @@ -68,8 +68,8 @@ don't want it: # Prune old objects if you're really really sure git prune -And yeah, I'm sure there are other ways of doing this. And as usual, the -above is totally untested, and I just wrote it down in this email, so if +And yeah, I'm sure there are other ways of doing this. And as usual, the +above is totally untested, and I just wrote it down in this email, so if I've done something wrong, you'll have to figure it out on your own ;) Linus @@ -77,5 +77,3 @@ I've done something wrong, you'll have to figure it out on your own ;) To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html - - diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.txt index 3b3a5c2e69..7a76045eb7 100644 --- a/Documentation/howto/rebase-from-internal-branch.txt +++ b/Documentation/howto/rebase-from-internal-branch.txt @@ -14,10 +14,10 @@ Petr Baudis writes: > Dear diary, on Sun, Aug 14, 2005 at 09:57:13AM CEST, I got a letter > where Junio C Hamano told me that... >> Linus Torvalds writes: ->> ->> > Junio, maybe you want to talk about how you move patches from your "pu" +>> +>> > Junio, maybe you want to talk about how you move patches from your "pu" >> > branch to the real branches. ->> +>> > Actually, wouldn't this be also precisely for what StGIT is intended to? Exactly my feeling. I was sort of waiting for Catalin to speak @@ -118,7 +118,7 @@ up your changes, along with other changes. where *your "master" head upstream --> #1 --> #2 --> #3 - used \ + used \ to be \--> #A --> #2' --> #3' --> #B --> #C *upstream head @@ -133,7 +133,7 @@ You fetch from upstream, but not merge. $ git fetch upstream This leaves the updated upstream head in .git/FETCH_HEAD but -does not touch your .git/HEAD nor .git/refs/heads/master. +does not touch your .git/HEAD nor .git/refs/heads/master. You run "git rebase" now. $ git rebase FETCH_HEAD master @@ -161,5 +161,3 @@ the #1' commit. To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html - - diff --git a/Documentation/howto/rebuild-from-update-hook.txt b/Documentation/howto/rebuild-from-update-hook.txt index 02621b54a0..8d55dfbfae 100644 --- a/Documentation/howto/rebuild-from-update-hook.txt +++ b/Documentation/howto/rebuild-from-update-hook.txt @@ -84,4 +84,3 @@ There are four things worth mentioning: - This is still crude and does not protect against simultaneous make invocations stomping on each other. I would need to add some locking mechanism for this. - diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.txt index d88ec23a97..865a666324 100644 --- a/Documentation/howto/revert-branch-rebase.txt +++ b/Documentation/howto/revert-branch-rebase.txt @@ -146,7 +146,7 @@ Everything is in the good order. I do not need the temporary branch nor tag anymore, so remove them: ------------------------------------------------ -$ rm -f .git/refs/tags/pu-anchor +$ rm -f .git/refs/tags/pu-anchor $ git branch -d revert-c99 ------------------------------------------------ diff --git a/Documentation/howto/separating-topic-branches.txt b/Documentation/howto/separating-topic-branches.txt index 090e2c9b01..0d73b31224 100644 --- a/Documentation/howto/separating-topic-branches.txt +++ b/Documentation/howto/separating-topic-branches.txt @@ -12,7 +12,7 @@ up with a history like this: "master" o---o - \ "topic" + \ "topic" o---o---o---o---o---o At this point, "topic" contains something I know I want, but it @@ -29,11 +29,11 @@ start building on top of "master": $ git checkout -b topicA master ... pick and apply pieces from P.diff to build ... commits on topicA branch. - + o---o---o / "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o Before doing each commit on "topicA" HEAD, I run "diff HEAD" @@ -59,7 +59,7 @@ other topic: /o---o---o |/ "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o After I am done, I'd try a pretend-merge between "topicA" and @@ -73,7 +73,7 @@ After I am done, I'd try a pretend-merge between "topicA" and /o---o---o----------' |/ "topicA" o---o"master" - \ "topic" + \ "topic" o---o---o---o---o---o The last diff better not to show anything other than cleanups @@ -84,8 +84,7 @@ for crufts. Then I can finally clean things up: "topicB" o---o---o---o---o - / + / /o---o---o |/ "topicA" o---o"master" - diff --git a/Documentation/howto/use-git-daemon.txt b/Documentation/howto/use-git-daemon.txt index 1a1eb246bf..4e2f75cb61 100644 --- a/Documentation/howto/use-git-daemon.txt +++ b/Documentation/howto/use-git-daemon.txt @@ -49,4 +49,3 @@ Now, test your daemon with $ git ls-remote git://127.0.0.1/rule-the-world.git If this does not work, find out why, and submit a patch to this document. - diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index 56f1d8d69d..d64c259bb3 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -25,4 +25,3 @@ If there is no `-s` option, a built-in list of strategies is used instead (`git-merge-recursive` when merging a single head, `git-merge-octopus` otherwise). - diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index d922e8e86c..c551ea61d2 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -121,4 +121,3 @@ The placeholders are: - '%Creset': reset color - '%m': left, right or boundary mark - '%n': newline - diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index 7d515be0fd..6338def5a7 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -11,4 +11,3 @@ command to re-code the commit log message in the encoding preferred by the user. For non plumbing commands this defaults to UTF-8. - diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index 8d4e950abc..b6eb7fc618 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -58,7 +58,7 @@ is often useful. + Some short-cut notations are also supported. + -* `tag ` means the same as `refs/tags/:refs/tags/`; +* `tag ` means the same as `refs/tags/:refs/tags/`; it requests fetching everything up to the given tag. * A parameter without a colon is equivalent to : when pulling/fetching, so it merges into the current diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt index 15221b5320..4c92e375fe 100644 --- a/Documentation/repository-layout.txt +++ b/Documentation/repository-layout.txt @@ -177,4 +177,3 @@ shallow:: This is similar to `info/grafts` but is internally used and maintained by shallow clone mechanism. See `--depth` option to gitlink:git-clone[1] and gitlink:git-fetch[1]. - diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index 9ce3c473ae..e5b31c81fa 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -80,7 +80,7 @@ Pack Idx file: +--------------------------------+ | main | offset | | index | object name 00XXXXXXXXXXXXXXXX | | -table +--------------------------------+ | +table +--------------------------------+ | | offset | | | object name 00XXXXXXXXXXXXXXXX | | +--------------------------------+ | @@ -97,14 +97,14 @@ trailer | | packfile checksum | | +--------------------------------+ | | idxfile checksum | | +--------------------------------+ - .-------. + .-------. | Pack file entry: <+ packed object header: 1-byte size extension bit (MSB) type (next 3 bit) - size0 (lower 4-bit) + size0 (lower 4-bit) n-byte sizeN (as long as MSB is set, each 7-bit) size0..sizeN form 4+7+7+..+7 bit integer, size0 is the least significant part, and sizeN is the @@ -114,5 +114,5 @@ Pack file entry: <+ is the size before compression). If it is DELTA, then 20-byte base object name SHA1 (the size above is the - size of the delta data that follows). + size of the delta data that follows). delta data, deflated. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 7eaafa80e9..957cd00761 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -154,11 +154,11 @@ Author: Jamal Hadi Salim Date: Sat Dec 2 22:22:25 2006 -0800 [XFRM]: Fix aevent structuring to be more complete. - + aevents can not uniquely identify an SA. We break the ABI with this patch, but consensus is that since it is not yet utilized by any (known) application then it is fine (better do it now than later). - + Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller @@ -167,7 +167,7 @@ index 8be626f..d7aac9d 100644 --- a/Documentation/networking/xfrm_sync.txt +++ b/Documentation/networking/xfrm_sync.txt @@ -47,10 +47,13 @@ aevent_id structure looks like: - + struct xfrm_aevent_id { struct xfrm_usersa_id sa_id; + xfrm_address_t saddr; @@ -1056,7 +1056,7 @@ $ git show ------------------------------------------------- As a special shortcut, - + ------------------------------------------------- $ git commit -a ------------------------------------------------- @@ -1554,7 +1554,7 @@ history. Fortunately, git also keeps a log, called a "reflog", of all the previous values of each branch. So in this case you can still find the -old history using, for example, +old history using, for example, ------------------------------------------------- $ git log master@{1} @@ -1630,7 +1630,7 @@ If you decide you want the history back, you can always create a new reference pointing to it, for example, a new branch: ------------------------------------------------ -$ git branch recovered-branch 7281251ddd +$ git branch recovered-branch 7281251ddd ------------------------------------------------ Other types of dangling objects (blobs and trees) are also possible, and @@ -1793,7 +1793,7 @@ like this: you push your personal repo ------------------> your public repo - ^ | + ^ | | | | you pull | they pull | | @@ -2359,7 +2359,7 @@ the result would create a new merge commit, like this: \ \ a--b--c--m <-- mywork ................................................ - + However, if you prefer to keep the history in mywork a simple series of commits without any merges, you may instead choose to use gitlink:git-rebase[1]: @@ -2735,7 +2735,7 @@ must have at least one root, and while you can tie several different root objects together into one project by creating a commit object which has two or more separate roots as its ultimate parents, that's probably just going to confuse people. So aim for the notion of "one root object -per project", even if git itself does not enforce that. +per project", even if git itself does not enforce that. A <> symbolically identifies and can be used to sign other objects. It contains the identifier and type of @@ -2757,7 +2757,7 @@ independently of the contents or the type of the object: all objects can be validated by verifying that (a) their hashes match the content of the file and (b) the object successfully inflates to a stream of bytes that forms a sequence of + + + + . +size> + + . The structured objects can further have their structure and connectivity to other objects verified. This is generally done with @@ -2954,7 +2954,7 @@ cache, and the normal operation is to re-generate it completely from a known tree object, or update/compare it with a live tree that is being developed. If you blow the directory cache away entirely, you generally haven't lost any information as long as you have the name of the tree -that it described. +that it described. At the same time, the index is at the same time also the staging area for creating new trees, and creating a new tree always @@ -2974,7 +2974,7 @@ Generally, all "git" operations work on the index file. Some operations work *purely* on the index file (showing the current state of the index), but most operations move data to and from the index file. Either from the database or from the working directory. Thus there are four -main combinations: +main combinations: [[working-directory-to-index]] working directory -> index @@ -3437,7 +3437,7 @@ because you interrupted a "git fetch" with ^C or something like that, leaving _some_ of the new objects in the object database, but just dangling and useless. -Anyway, once you are sure that you're not interested in any dangling +Anyway, once you are sure that you're not interested in any dangling state, you can just prune all unreachable objects: ------------------------------------------------ @@ -3448,12 +3448,12 @@ and they'll be gone. But you should only run "git prune" on a quiescent repository - it's kind of like doing a filesystem fsck recovery: you don't want to do that while the filesystem is mounted. -(The same is true of "git-fsck" itself, btw - but since -git-fsck never actually *changes* the repository, it just reports -on what it found, git-fsck itself is never "dangerous" to run. -Running it while somebody is actually changing the repository can cause -confusing and scary messages, but it won't actually do anything bad. In -contrast, running "git prune" while somebody is actively changing the +(The same is true of "git-fsck" itself, btw - but since +git-fsck never actually *changes* the repository, it just reports +on what it found, git-fsck itself is never "dangerous" to run. +Running it while somebody is actually changing the repository can cause +confusing and scary messages, but it won't actually do anything bad. In +contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). [[birdview-on-the-source-code]] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 06c360b267..289c8067b5 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -43,5 +43,3 @@ test "$VN" = "$VC" || { echo >&2 "GIT_VERSION = $VN" echo "GIT_VERSION = $VN" >$GVF } - - diff --git a/INSTALL b/INSTALL index 361c65bacc..95269cc513 100644 --- a/INSTALL +++ b/INSTALL @@ -31,7 +31,7 @@ Issues of note: interactive tools. None of the core git stuff needs the wrapper, it's just a convenient shorthand and while it is documented in some places, you can always replace "git commit" with "git-commit" - instead. + instead. But let's face it, most of us don't have GNU interactive tools, and even if we had it, we wouldn't know what it does. I don't think it @@ -111,4 +111,3 @@ Issues of note: would instead give you a copy of what you see at: http://www.kernel.org/pub/software/scm/git/docs/ - diff --git a/arm/sha1.c b/arm/sha1.c index 11b1a048b4..9e3ae038e8 100644 --- a/arm/sha1.c +++ b/arm/sha1.c @@ -49,7 +49,7 @@ void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n) void SHA1_Final(unsigned char *hash, SHA_CTX *c) { uint64_t bitlen; - uint32_t bitlen_hi, bitlen_lo; + uint32_t bitlen_hi, bitlen_lo; unsigned int i, offset, padlen; unsigned char bits[8]; static const unsigned char padding[64] = { 0x80, }; @@ -69,7 +69,7 @@ void SHA1_Final(unsigned char *hash, SHA_CTX *c) bits[5] = bitlen_lo >> 16; bits[6] = bitlen_lo >> 8; bits[7] = bitlen_lo; - SHA1_Update(c, bits, 8); + SHA1_Update(c, bits, 8); for (i = 0; i < 5; i++) { uint32_t v = c->hash[i]; diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S index a328b73375..8c1cb99fb4 100644 --- a/arm/sha1_arm.S +++ b/arm/sha1_arm.S @@ -181,4 +181,3 @@ sha_transform: .L_sha_K: .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 - diff --git a/builtin-annotate.c b/builtin-annotate.c index 9db7cfe74c..fc43eed36b 100644 --- a/builtin-annotate.c +++ b/builtin-annotate.c @@ -22,4 +22,3 @@ int cmd_annotate(int argc, const char **argv, const char *prefix) return cmd_blame(argc + 1, nargv, prefix); } - diff --git a/builtin-diff-index.c b/builtin-diff-index.c index d90eba95a6..81e7167438 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -23,7 +23,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) argc = setup_revisions(argc, argv, &rev, NULL); for (i = 1; i < argc; i++) { const char *arg = argv[i]; - + if (!strcmp(arg, "--cached")) cached = 1; else diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index 5c145d2165..ae60fccea7 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -357,4 +357,3 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/builtin-fsck.c b/builtin-fsck.c index bacae5dfa6..944a496650 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -351,7 +351,7 @@ static int fsck_commit(struct commit *commit) if (!commit->parents && show_root) printf("root %s\n", sha1_to_hex(commit->object.sha1)); if (!commit->date) - printf("bad commit date in %s\n", + printf("bad commit date in %s\n", sha1_to_hex(commit->object.sha1)); return 0; } @@ -719,7 +719,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix) heads = 0; for (i = 1; i < argc; i++) { - const char *arg = argv[i]; + const char *arg = argv[i]; if (*arg == '-') continue; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index f7c066b24b..5398a41415 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -117,7 +117,7 @@ static void show_other_files(struct dir_struct *dir) if (0 <= pos) continue; /* exact match */ pos = -pos - 1; - if (pos < active_nr) { + if (pos < active_nr) { ce = active_cache[pos]; if (ce_namelen(ce) == len && !memcmp(ce->name, ent->name, len)) diff --git a/builtin-name-rev.c b/builtin-name-rev.c index d3c42ed67e..61eba343ab 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -290,4 +290,3 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 8b9740c277..3d396ca37a 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -252,7 +252,7 @@ static void *delta_against(void *buf, unsigned long size, struct object_entry *e delta_buf = diff_delta(otherbuf, othersize, buf, size, &delta_size, 0); if (!delta_buf || delta_size != entry->delta_size) - die("delta size changed"); + die("delta size changed"); free(buf); free(otherbuf); return delta_buf; diff --git a/builtin-rerere.c b/builtin-rerere.c index 8c2c8bdc18..f6409b93c1 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -434,4 +434,3 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) path_list_clear(&merge_rr, 1); return 0; } - diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 8d3f742d43..16af6199ab 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -331,4 +331,3 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix) return 0; } - diff --git a/cache.h b/cache.h index 8a9d1f3883..5e7381eb1e 100644 --- a/cache.h +++ b/cache.h @@ -479,7 +479,7 @@ extern void prepare_packed_git(void); extern void reprepare_packed_git(void); extern void install_packed_git(struct packed_git *pack); -extern struct packed_git *find_sha1_pack(const unsigned char *sha1, +extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); extern void pack_report(void); diff --git a/commit.c b/commit.c index 5632e32685..57b69ca7fa 100644 --- a/commit.c +++ b/commit.c @@ -148,7 +148,7 @@ static int commit_graft_pos(const unsigned char *sha1) int register_commit_graft(struct commit_graft *graft, int ignore_dups) { int pos = commit_graft_pos(graft->sha1); - + if (0 <= pos) { if (ignore_dups) free(graft); @@ -406,7 +406,7 @@ struct commit_list * insert_by_date(struct commit *item, struct commit_list **li return commit_list_insert(item, pp); } - + void sort_by_date(struct commit_list **list) { struct commit_list *ret = NULL; @@ -1160,7 +1160,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, next = next->next; count++; } - + if (!count) return; /* allocate an array to help sort the list */ @@ -1188,11 +1188,11 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, } next=next->next; } - /* + /* * find the tips * - * tips are nodes not reachable from any other node in the list - * + * tips are nodes not reachable from any other node in the list + * * the tips serve as a starting set for the work queue. */ next=*list; @@ -1220,7 +1220,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, if (pn) { /* - * parents are only enqueued for emission + * parents are only enqueued for emission * when all their children have been emitted thereby * guaranteeing topological order. */ diff --git a/commit.h b/commit.h index 86e8dca0c9..75b43a53ed 100644 --- a/commit.h +++ b/commit.h @@ -66,7 +66,7 @@ extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit /** Removes the first commit from a list sorted by date, and adds all * of its parents. **/ -struct commit *pop_most_recent_commit(struct commit_list **list, +struct commit *pop_most_recent_commit(struct commit_list **list, unsigned int mark); struct commit *pop_commit(struct commit_list **stack); diff --git a/compat/mmap.c b/compat/mmap.c index 4cfaee3136..c9d46d1742 100644 --- a/compat/mmap.c +++ b/compat/mmap.c @@ -40,4 +40,3 @@ int git_munmap(void *start, size_t length) free(start); return 0; } - diff --git a/config.c b/config.c index 0614c2b29f..58d3ed5d37 100644 --- a/config.c +++ b/config.c @@ -621,7 +621,7 @@ static ssize_t find_beginning_of_line(const char* contents, size_t size, size_t equal_offset = size, bracket_offset = size; ssize_t offset; - for (offset = offset_-2; offset > 0 + for (offset = offset_-2; offset > 0 && contents[offset] != '\n'; offset--) switch (contents[offset]) { case '=': equal_offset = offset; break; @@ -989,4 +989,3 @@ int git_config_rename_section(const char *old_name, const char *new_name) free(config_filename); return ret; } - diff --git a/config.mak.in b/config.mak.in index eb9d7a5549..a3032e389f 100644 --- a/config.mak.in +++ b/config.mak.in @@ -38,4 +38,3 @@ NO_STRCASESTR=@NO_STRCASESTR@ NO_STRLCPY=@NO_STRLCPY@ NO_SETENV=@NO_SETENV@ NO_ICONV=@NO_ICONV@ - diff --git a/connect.c b/connect.c index 8cbda88dda..7fab9c0fd9 100644 --- a/connect.c +++ b/connect.c @@ -390,7 +390,7 @@ static int git_proxy_command_options(const char *var, const char *value) } if (0 <= matchlen) { /* core.gitproxy = none for kernel.org */ - if (matchlen == 4 && + if (matchlen == 4 && !memcmp(value, "none", 4)) matchlen = 0; git_proxy_command = xmalloc(matchlen + 1); diff --git a/contrib/README b/contrib/README index e1c0a01ff3..05f291c1f1 100644 --- a/contrib/README +++ b/contrib/README @@ -41,4 +41,3 @@ submit a patch to create a subdirectory of contrib/ and put your stuff there. -jc - diff --git a/contrib/blameview/README b/contrib/blameview/README index 50a6f67fd6..fada5ce909 100644 --- a/contrib/blameview/README +++ b/contrib/blameview/README @@ -7,4 +7,3 @@ To: Linus Torvalds Cc: git@vger.kernel.org Date: Sat, 27 Jan 2007 18:52:38 -0500 Message-ID: <20070127235238.GA28706@coredump.intra.peff.net> - diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview index 2d80e2bad2..3dc1ef50c7 100755 --- a/contrib/gitview/gitview +++ b/contrib/gitview/gitview @@ -1277,5 +1277,3 @@ if __name__ == "__main__": view = GitView( without_diff != 1) view.run(sys.argv[without_diff:]) - - diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email index d1bef9125b..c589a39a0c 100644 --- a/contrib/hooks/post-receive-email +++ b/contrib/hooks/post-receive-email @@ -199,7 +199,7 @@ generate_email_footer() hooks/post-receive - -- + -- $projectdesc EOF } diff --git a/contrib/remotes2config.sh b/contrib/remotes2config.sh index dc09eae972..0c8b954490 100644 --- a/contrib/remotes2config.sh +++ b/contrib/remotes2config.sh @@ -31,5 +31,3 @@ if [ -d "$GIT_DIR"/remotes ]; then esac done fi - - diff --git a/convert-objects.c b/convert-objects.c index cefbcebdca..90e7900e6d 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -194,7 +194,7 @@ static unsigned long parse_oldstyle_date(const char *buf) fmt++; } while (*buf && *fmt); printf("left: %s\n", buf); - return mktime(&tm); + return mktime(&tm); } static int convert_date_line(char *dst, void **buf, unsigned long *sp) diff --git a/copy.c b/copy.c index d340bb253e..c225d1b0ff 100644 --- a/copy.c +++ b/copy.c @@ -34,4 +34,3 @@ int copy_fd(int ifd, int ofd) close(ifd); return 0; } - diff --git a/ctype.c b/ctype.c index 56bdffa636..ee06eb7f48 100644 --- a/ctype.c +++ b/ctype.c @@ -20,4 +20,3 @@ unsigned char sane_ctype[256] = { AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 112-15 */ /* Nothing in the 128.. range */ }; - diff --git a/daemon.c b/daemon.c index 674e30dca3..77792509e3 100644 --- a/daemon.c +++ b/daemon.c @@ -133,7 +133,7 @@ static int avoid_alias(char *p) { int sl, ndot; - /* + /* * This resurrects the belts and suspenders paranoia check by HPA * done in <435560F7.4080006@zytor.com> thread, now enter_repo() * does not do getcwd() based path canonicalizations. @@ -247,7 +247,7 @@ static char *path_ok(struct interp *itable) int pathlen = strlen(path); /* The validation is done on the paths after enter_repo - * appends optional {.git,.git/.git} and friends, but + * appends optional {.git,.git/.git} and friends, but * it does not use getcwd(). So if your /pub is * a symlink to /mnt/pub, you can whitelist /pub and * do not have to say /mnt/pub. diff --git a/date.c b/date.c index 4690371e55..316841e8ad 100644 --- a/date.c +++ b/date.c @@ -403,7 +403,7 @@ static int match_multi_number(unsigned long num, char c, const char *date, char } /* - * We've seen a digit. Time? Year? Date? + * We've seen a digit. Time? Year? Date? */ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt) { @@ -495,7 +495,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt } else if (num > 0 && num < 13) { tm->tm_mon = num-1; } - + return n; } @@ -569,13 +569,13 @@ int parse_date(const char *date, char *result, int maxlen) if (!match) { /* BAD CRAP */ match = 1; - } + } date += match; } /* mktime uses local timezone */ - then = my_mktime(&tm); + then = my_mktime(&tm); if (offset == -1) offset = (then - mktime(&tm)) / 60; @@ -691,7 +691,7 @@ static const struct typelen { { "days", 24*60*60 }, { "weeks", 7*24*60*60 }, { NULL } -}; +}; static const char *approxidate_alpha(const char *date, struct tm *tm, int *num) { diff --git a/diff-lib.c b/diff-lib.c index 07f4e8106a..7fb19c7b87 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -664,7 +664,7 @@ int run_diff_index(struct rev_info *revs, int cached) const char *tree_name; int match_missing = 0; - /* + /* * Backward compatibility wart - "diff-index -m" does * not mean "do not ignore merges", but totally different. */ diff --git a/diff.c b/diff.c index c57ac33414..cafa7debeb 100644 --- a/diff.c +++ b/diff.c @@ -3031,7 +3031,7 @@ void diff_addremove(struct diff_options *options, * entries to the diff-core. They will be prefixed * with something like '=' or '*' (I haven't decided * which but should not make any difference). - * Feeding the same new and old to diff_change() + * Feeding the same new and old to diff_change() * also has the same effect. * Before the final output happens, they are pruned after * merged into rename/copy pairs as appropriate. @@ -3058,7 +3058,7 @@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *base, const char *path) { char concatpath[PATH_MAX]; struct diff_filespec *one, *two; diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index c4a77d71da..af9fffe6e8 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -102,7 +102,7 @@ void diffcore_pickaxe(const char *needle, int opts) for (i = 0; i < q->nr; i++) diff_free_filepair(q->queue[i]); } - else + else /* Showing only the filepairs that has the needle */ for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; diff --git a/entry.c b/entry.c index ae6476496a..c540ae13e8 100644 --- a/entry.c +++ b/entry.c @@ -31,7 +31,7 @@ static void remove_subtree(const char *path) struct dirent *de; char pathbuf[PATH_MAX]; char *name; - + if (!dir) die("cannot opendir %s (%s)", path, strerror(errno)); strcpy(pathbuf, path); diff --git a/environment.c b/environment.c index 9d3e5eb72f..8b9b89d0a0 100644 --- a/environment.c +++ b/environment.c @@ -105,5 +105,3 @@ char *get_graft_file(void) setup_git_env(); return git_graft_file; } - - diff --git a/fetch-pack.c b/fetch-pack.c index aa59043c03..9c81305be5 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -114,7 +114,7 @@ static const unsigned char* get_rev(void) commit->object.flags |= POPPED; if (!(commit->object.flags & COMMON)) non_common_revs--; - + parents = commit->parents; if (commit->object.flags & COMMON) { diff --git a/fetch.c b/fetch.c index 8e29d313f8..dda33e548b 100644 --- a/fetch.c +++ b/fetch.c @@ -15,7 +15,7 @@ int get_verbosely = 0; int get_recover = 0; static unsigned char current_commit_sha1[20]; -void pull_say(const char *fmt, const char *hex) +void pull_say(const char *fmt, const char *hex) { if (get_verbosely) fprintf(stderr, fmt, hex); @@ -153,7 +153,7 @@ static int process(struct object *obj) return 0; prefetch(obj->sha1); } - + object_list_insert(obj, process_queue_end); process_queue_end = &(*process_queue_end)->next; return 0; diff --git a/git-archimport.perl b/git-archimport.perl index c1e7c1ddcb..b21077206a 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -3,19 +3,19 @@ # This tool is copyright (c) 2005, Martin Langhoff. # It is released under the Gnu Public License, version 2. # -# The basic idea is to walk the output of tla abrowse, -# fetch the changesets and apply them. +# The basic idea is to walk the output of tla abrowse, +# fetch the changesets and apply them. # =head1 Invocation - git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] - [ -D depth] [ -t tempdir ] / [ / ] + git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] + [ -D depth] [ -t tempdir ] / [ / ] Imports a project from one or more Arch repositories. It will follow branches and repositories within the namespaces defined by the parameters supplied. If it cannot find the remote branch a merge comes from -it will just import it as a regular commit. If it can find it, it will mark it +it will just import it as a regular commit. If it can find it, it will mark it as a merge whenever possible. See man (1) git-archimport for more details. @@ -25,14 +25,14 @@ See man (1) git-archimport for more details. - create tag objects instead of ref tags - audit shell-escaping of filenames - hide our private tags somewhere smarter - - find a way to make "cat *patches | patch" safe even when patchfiles are missing newlines + - find a way to make "cat *patches | patch" safe even when patchfiles are missing newlines - sort and apply patches by graphing ancestry relations instead of just relying in dates supplied in the changeset itself. tla ancestry-graph -m could be helpful here... =head1 Devel tricks -Add print in front of the shell commands invoked via backticks. +Add print in front of the shell commands invoked via backticks. =head1 Devel Notes @@ -126,16 +126,16 @@ sub do_abrowse { my $stage = shift; while (my ($limit, $level) = each %arch_branches) { next unless $level == $stage; - - open ABROWSE, "$TLA abrowse -fkD --merges $limit |" + + open ABROWSE, "$TLA abrowse -fkD --merges $limit |" or die "Problems with tla abrowse: $!"; - + my %ps = (); # the current one my $lastseen = ''; - + while () { chomp; - + # first record padded w 8 spaces if (s/^\s{8}\b//) { my ($id, $type) = split(m/\s+/, $_, 2); @@ -147,13 +147,13 @@ sub do_abrowse { push (@psets, \%last_ps); $psets{ $last_ps{id} } = \%last_ps; } - + my $branch = extract_versionname($id); %ps = ( id => $id, branch => $branch ); if (%last_ps && ($last_ps{branch} eq $branch)) { $ps{parent_id} = $last_ps{id}; } - + $arch_branches{$branch} = 1; $lastseen = 'id'; @@ -166,16 +166,16 @@ sub do_abrowse { $ps{type} = 't'; # read which revision we've tagged when we parse the log $ps{tag} = $1; - } else { + } else { warn "Unknown type $type"; } $arch_branches{$branch} = 1; $lastseen = 'id'; - } elsif (s/^\s{10}//) { - # 10 leading spaces or more + } elsif (s/^\s{10}//) { + # 10 leading spaces or more # indicate commit metadata - + # date if ($lastseen eq 'id' && m/^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d)/){ $ps{date} = $1; @@ -186,12 +186,12 @@ sub do_abrowse { } elsif ($lastseen eq 'merges' && s/^\s{2}//) { my $id = $_; push (@{$ps{merges}}, $id); - + # aggressive branch finding: if ($opt_D) { my $branch = extract_versionname($id); my $repo = extract_reponame($branch); - + if (archive_reachable($repo) && !defined $arch_branches{$branch}) { $arch_branches{$branch} = $stage + 1; @@ -208,10 +208,10 @@ sub do_abrowse { if (@psets && $psets[$#psets]{branch} eq $ps{branch}) { $temp{parent_id} = $psets[$#psets]{id}; } - push (@psets, \%temp); + push (@psets, \%temp); $psets{ $temp{id} } = \%temp; - } - + } + close ABROWSE or die "$TLA abrowse failed on $limit\n"; } } # end foreach $root @@ -253,7 +253,7 @@ unless (-d $git_dir) { # initial import while (my $file = readdir(DIR)) { # skip non-interesting-files next unless -f "$ptag_dir/$file"; - + # convert first '--' to '/' from old git-archimport to use # as an archivename/c--b--v private tag if ($file !~ m!,!) { @@ -275,7 +275,7 @@ sub extract_reponame { my $fq_cvbr = shift; # archivename/[[[[category]branch]version]revision] return (split(/\//, $fq_cvbr))[0]; } - + sub extract_versionname { my $name = shift; $name =~ s/--(?:patch|version(?:fix)?|base)-\d+$//; @@ -283,7 +283,7 @@ sub extract_versionname { } # convert a fully-qualified revision or version to a unique dirname: -# normalperson@yhbt.net-05/mpd--uclinux--1--patch-2 +# normalperson@yhbt.net-05/mpd--uclinux--1--patch-2 # becomes: normalperson@yhbt.net-05,mpd--uclinux--1 # # the git notion of a branch is closer to @@ -339,7 +339,7 @@ sub git_branchname { sub process_patchset_accurate { my $ps = shift; - + # switch to that branch if we're not already in that branch: if (-e "$git_dir/refs/heads/$ps->{branch}") { system('git-checkout','-f',$ps->{branch}) == 0 or die "$! $?\n"; @@ -348,7 +348,7 @@ sub process_patchset_accurate { my $rm = safe_pipe_capture('git-ls-files','--others','-z'); rmtree(split(/\0/,$rm)) if $rm; } - + # Apply the import/changeset/merge into the working tree my $dir = sync_to_ps($ps); # read the new log entry: @@ -361,9 +361,9 @@ sub process_patchset_accurate { parselog($ps, \@commitlog); if ($ps->{id} =~ /--base-0$/ && $ps->{id} ne $psets[0]{id}) { - # this should work when importing continuations + # this should work when importing continuations if ($ps->{tag} && (my $branchpoint = eval { ptag($ps->{tag}) })) { - + # find where we are supposed to branch from if (! -e "$git_dir/refs/heads/$ps->{branch}") { system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; @@ -388,8 +388,8 @@ sub process_patchset_accurate { } # allow multiple bases/imports here since Arch supports cherry-picks # from unrelated trees - } - + } + # update the index with all the changes we got system('git-diff-files --name-only -z | '. 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n"; @@ -402,7 +402,7 @@ sub process_patchset_accurate { # does not handle permissions or any renames involving directories sub process_patchset_fast { my $ps = shift; - # + # # create the branch if needed # if ($ps->{type} eq 'i' && !$import) { @@ -417,9 +417,9 @@ sub process_patchset_fast { # new branch! we need to verify a few things die "Branch on a non-tag!" unless $ps->{type} eq 't'; my $branchpoint = ptag($ps->{tag}); - die "Tagging from unknown id unsupported: $ps->{tag}" + die "Tagging from unknown id unsupported: $ps->{tag}" unless $branchpoint; - + # find where we are supposed to branch from if (! -e "$git_dir/refs/heads/$ps->{branch}") { system('git-branch',$ps->{branch},$branchpoint) == 0 or die "$! $?\n"; @@ -435,13 +435,13 @@ sub process_patchset_fast { } system('git-checkout',$ps->{branch}) == 0 or die "$! $?\n"; return 0; - } + } die $! if $?; - } + } # # Apply the import/changeset/merge into the working tree - # + # if ($ps->{type} eq 'i' || $ps->{type} eq 't') { apply_import($ps) or die $!; $stats{import_or_tag}++; @@ -455,10 +455,10 @@ sub process_patchset_fast { # prepare update git's index, based on what arch knows # about the pset, resolve parents, etc # - - my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); + + my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); die "Error in cat-archive-log: $!" if $?; - + parselog($ps,\@commitlog); # imports don't give us good info @@ -485,10 +485,10 @@ sub process_patchset_fast { if (@$ren % 2) { die "Odd number of entries in rename!?"; } - + while (@$ren) { my $from = shift @$ren; - my $to = shift @$ren; + my $to = shift @$ren; unless (-d dirname($to)) { mkpath(dirname($to)); # will die on err @@ -529,20 +529,20 @@ if ($opt_f) { "Things may be a bit slow\n"; *process_patchset = *process_patchset_accurate; } - + foreach my $ps (@psets) { # process patchsets $ps->{branch} = git_branchname($ps->{id}); # - # ensure we have a clean state - # + # ensure we have a clean state + # if (my $dirty = `git-diff-files`) { die "Unclean tree when about to process $ps->{id} " . " - did we fail to commit cleanly before?\n$dirty"; } die $! if $?; - + # # skip commits already in repo # @@ -559,7 +559,7 @@ foreach my $ps (@psets) { my $tree = `git-write-tree`; die "cannot write tree $!" if $?; chomp $tree; - + # # Who's your daddy? # @@ -570,18 +570,18 @@ foreach my $ps (@psets) { close HEAD; chomp $p; push @par, '-p', $p; - } else { + } else { if ($ps->{type} eq 's') { warn "Could not find the right head for the branch $ps->{branch}"; } } } - + if ($ps->{merges}) { push @par, find_parents($ps); } - # + # # Commit, tag and clean state # $ENV{TZ} = 'GMT'; @@ -592,14 +592,14 @@ foreach my $ps (@psets) { $ENV{GIT_COMMITTER_EMAIL} = $ps->{email}; $ENV{GIT_COMMITTER_DATE} = $ps->{date}; - my $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) + my $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) or die $!; print WRITER $ps->{summary},"\n\n"; print WRITER $ps->{message},"\n"; - + # make it easy to backtrack and figure out which Arch revision this was: print WRITER 'git-archimport-id: ',$ps->{id},"\n"; - + close WRITER; my $commitid = ; # read chomp $commitid; @@ -611,7 +611,7 @@ foreach my $ps (@psets) { } # # Update the branch - # + # open HEAD, ">","$git_dir/refs/heads/$ps->{branch}"; print HEAD $commitid; close HEAD; @@ -640,7 +640,7 @@ exit 0; sub sync_to_ps { my $ps = shift; my $tree_dir = $tmp.'/'.tree_dirname($ps->{id}); - + $opt_v && print "sync_to_ps($ps->{id}) method: "; if (-d $tree_dir) { @@ -674,7 +674,7 @@ sub sync_to_ps { safe_pipe_capture($TLA,'get','--no-pristine',$ps->{id},$tree_dir); $stats{get_new}++; } - + # added -I flag to rsync since we're going to fast! AIEEEEE!!!! system('rsync','-aI','--delete','--exclude',$git_dir, # '--exclude','.arch-inventory', @@ -691,15 +691,15 @@ sub apply_import { mkpath($tmp); safe_pipe_capture($TLA,'get','-s','--no-pristine',$ps->{id},"$tmp/import"); - die "Cannot get import: $!" if $?; + die "Cannot get import: $!" if $?; system('rsync','-aI','--delete', '--exclude',$git_dir, '--exclude','.arch-ids','--exclude','{arch}', "$tmp/import/", './'); die "Cannot rsync import:$!" if $?; - + rmtree("$tmp/import"); die "Cannot remove tempdir: $!" if $?; - + return 1; } @@ -712,13 +712,13 @@ sub apply_cset { # get the changeset safe_pipe_capture($TLA,'get-changeset',$ps->{id},"$tmp/changeset"); die "Cannot get changeset: $!" if $?; - + # apply patches if (`find $tmp/changeset/patches -type f -name '*.patch'`) { # this can be sped up considerably by doing # (find | xargs cat) | patch # but that can get mucked up by patches - # with missing trailing newlines or the standard + # with missing trailing newlines or the standard # 'missing newline' flag in the patch - possibly # produced with an old/buggy diff. # slow and safe, we invoke patch once per patchfile @@ -741,7 +741,7 @@ sub apply_cset { # bring in new files system('rsync','-aI','--exclude',$git_dir, - '--exclude','.arch-ids', + '--exclude','.arch-ids', '--exclude', '{arch}', "$tmp/changeset/new-files-archive/",'./'); @@ -789,7 +789,7 @@ sub parselog { removed_files => 1, removed_directories => 1, ); - + chomp (@$log); while ($_ = shift @$log) { if (/^Continuation-of:\s*(.*)/) { @@ -828,7 +828,7 @@ sub parselog { } } } - + # drop leading empty lines from the log message while (@$log && $log->[0] eq '') { shift @$log; @@ -842,7 +842,7 @@ sub parselog { $ps->{summary} = $log->[0] . '...'; } $ps->{message} = join("\n",@$log); - + # skip Arch control files, unescape pika-escaped files foreach my $k (keys %want_headers) { next unless (defined $ps->{$k}); @@ -867,7 +867,7 @@ sub parselog { # write/read a tag sub tag { my ($tag, $commit) = @_; - + if ($opt_o) { $tag =~ s|/|--|g; } else { @@ -875,7 +875,7 @@ sub tag { $patchname =~ s/.*--//; $tag = git_branchname ($tag) . '--' . $patchname; } - + if ($commit) { open(C,">","$git_dir/refs/tags/$tag") or die "Cannot create tag $tag: $!\n"; @@ -902,8 +902,8 @@ sub ptag { my ($tag, $commit) = @_; # don't use subdirs for tags yet, it could screw up other porcelains - $tag =~ s|/|,|g; - + $tag =~ s|/|,|g; + my $tag_file = "$ptag_dir/$tag"; my $tag_branch_dir = dirname($tag_file); mkpath($tag_branch_dir) unless (-d $tag_branch_dir); @@ -915,7 +915,7 @@ sub ptag { or die "Cannot write tag $tag: $!\n"; close(C) or die "Cannot write tag $tag: $!\n"; - $rptags{$commit} = $tag + $rptags{$commit} = $tag unless $tag =~ m/--base-0$/; } else { # read # if the tag isn't there, return 0 @@ -941,7 +941,7 @@ sub find_parents { # Identify what branches are merging into me # and whether we are fully merged # git-merge-base should tell - # me what the base of the merge should be + # me what the base of the merge should be # my $ps = shift; @@ -963,14 +963,14 @@ sub find_parents { } # - # foreach branch find a merge base and walk it to the + # foreach branch find a merge base and walk it to the # head where we are, collecting the merged patchsets that # Arch has recorded. Keep that in @have # Compare that with the commits on the other branch # between merge-base and the tip of the branch (@need) # and see if we have a series of consecutive patches # starting from the merge base. The tip of the series - # of consecutive patches merged is our new parent for + # of consecutive patches merged is our new parent for # that branch. # foreach my $branch (keys %branches) { @@ -979,13 +979,13 @@ sub find_parents { next unless -e "$git_dir/refs/heads/$branch"; my $mergebase = `git-merge-base $branch $ps->{branch}`; - if ($?) { - # Don't die here, Arch supports one-way cherry-picking - # between branches with no common base (or any relationship - # at all beforehand) - warn "Cannot find merge base for $branch and $ps->{branch}"; - next; - } + if ($?) { + # Don't die here, Arch supports one-way cherry-picking + # between branches with no common base (or any relationship + # at all beforehand) + warn "Cannot find merge base for $branch and $ps->{branch}"; + next; + } chomp $mergebase; # now walk up to the mergepoint collecting what patches we have @@ -1010,7 +1010,7 @@ sub find_parents { # merge what we have with what ancestors have %have = (%have, %ancestorshave); - # see what the remote branch has - these are the merges we + # see what the remote branch has - these are the merges we # will want to have in a consecutive series from the mergebase my $otherbranchtip = git_rev_parse($branch); my @needraw = `git-rev-list --topo-order $otherbranchtip ^$mergebase`; @@ -1018,7 +1018,7 @@ sub find_parents { foreach my $needps (@needraw) { # get the psets $needps = commitid2pset($needps); # git-rev-list will also - # list commits merged in via earlier + # list commits merged in via earlier # merges. we are only interested in commits # from the branch we're looking at if ($branch eq $needps->{branch}) { @@ -1054,7 +1054,7 @@ sub find_parents { next unless ref $psets{$p}{merges}; my @merges = @{$psets{$p}{merges}}; foreach my $merge (@merges) { - if ($parents{$merge}) { + if ($parents{$merge}) { delete $parents{$merge}; } } @@ -1079,10 +1079,10 @@ sub git_rev_parse { sub commitid2pset { my $commitid = shift; chomp $commitid; - my $name = $rptags{$commitid} + my $name = $rptags{$commitid} || die "Cannot find reverse tag mapping for $commitid"; $name =~ s|,|/|; - my $ps = $psets{$name} + my $ps = $psets{$name} || (print Dumper(sort keys %psets)) && die "Cannot find patchset for $name"; return $ps; } @@ -1112,7 +1112,7 @@ sub archive_reachable { my $archive = shift; return 1 if $reachable{$archive}; return 0 if $unreachable{$archive}; - + if (system "$TLA whereis-archive $archive >/dev/null") { if ($opt_a && (system($TLA,'register-archive', "http://mirrors.sourcecontrol.net/$archive") == 0)) { @@ -1127,4 +1127,3 @@ sub archive_reachable { return 1; } } - diff --git a/git-checkout.sh b/git-checkout.sh index 6b6facfd5a..d561c88dcb 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -210,7 +210,7 @@ else esac # Match the index to the working tree, and do a three-way. - git diff-files --name-only | git update-index --remove --stdin && + git diff-files --name-only | git update-index --remove --stdin && work=`git write-tree` && git read-tree $v --reset -u $new || exit @@ -245,7 +245,7 @@ else (exit $saved_err) fi -# +# # Switch the HEAD pointer to the new branch if we # checked out a branch head, and remove any potential # old MERGE_HEAD's (subsequent commits will clearly not diff --git a/git-clone.sh b/git-clone.sh index fdd354f2da..5bfd8d1556 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -2,7 +2,7 @@ # # Copyright (c) 2005, Linus Torvalds # Copyright (c) 2005, Junio C Hamano -# +# # Clone a repository into a different directory that does not yet exist. # See git-sh-setup why. @@ -98,7 +98,7 @@ while *,--na|*,--nak|*,--nake|*,--naked|\ *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;; *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;; - *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) + *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) local_shared=yes; use_local=yes ;; 1,--template) usage ;; *,--template) @@ -410,4 +410,3 @@ fi rm -f "$GIT_DIR/CLONE_HEAD" "$GIT_DIR/REMOTE_HEAD" trap - 0 - diff --git a/git-commit.sh b/git-commit.sh index e8b60f7049..5547a02954 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -557,7 +557,7 @@ then } >>"$GIT_DIR"/COMMIT_EDITMSG else # we need to check if there is anything to commit - run_status >/dev/null + run_status >/dev/null fi if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" -a -z "$amend" ] then diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index 42060ef6e1..e9832d2bb9 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -197,7 +197,7 @@ if (@canstatusfiles) { # ... validate new files, foreach my $f (@afiles) { if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") { - $dirty = 1; + $dirty = 1; warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n"; warn "Status was: $cvsstat{$f}\n"; } diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 4e6c9c6cc7..3225a2a25d 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -145,7 +145,7 @@ my $cvs_tree; if ($#ARGV == 0) { $cvs_tree = $ARGV[0]; } elsif (-f 'CVS/Repository') { - open my $f, '<', 'CVS/Repository' or + open my $f, '<', 'CVS/Repository' or die 'Failed to open CVS/Repository'; $cvs_tree = <$f>; chomp $cvs_tree; @@ -434,7 +434,7 @@ sub file { my ($self,$fn,$rev) = @_; my $res; - my ($fh, $name) = tempfile('gitcvs.XXXXXX', + my ($fh, $name) = tempfile('gitcvs.XXXXXX', DIR => File::Spec->tmpdir(), UNLINK => 1); $self->_file($fn,$rev) and $res = $self->_line($fh); @@ -520,8 +520,8 @@ sub is_sha1 { sub get_headref ($$) { my $name = shift; - my $git_dir = shift; - + my $git_dir = shift; + my $f = "$git_dir/refs/heads/$name"; if (open(my $fh, $f)) { chomp(my $r = <$fh>); @@ -771,7 +771,7 @@ sub commit { $xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY ** $xtag =~ tr/_/\./ if ( $opt_u ); $xtag =~ s/[\/]/$opt_s/g; - + my $pid = open2($in, $out, 'git-mktag'); print $out "object $cid\n". "type commit\n". @@ -788,7 +788,7 @@ sub commit { $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { die "Cannot create tag object $xtag: $!\n"; } - + open(C,">$git_dir/refs/tags/$xtag") or die "Cannot create tag $xtag: $!\n"; diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN index 25647c8060..eee495a986 100755 --- a/git-gui/GIT-VERSION-GEN +++ b/git-gui/GIT-VERSION-GEN @@ -78,5 +78,3 @@ test "$VN" = "$VC" || { echo >&2 "GITGUI_VERSION = $VN" echo "GITGUI_VERSION = $VN" >$GVF } - - diff --git a/git-gui/lib/class.tcl b/git-gui/lib/class.tcl index 88b056522a..72494c1a1e 100644 --- a/git-gui/lib/class.tcl +++ b/git-gui/lib/class.tcl @@ -151,4 +151,3 @@ auto_mkindex_parser::command constructor {name args} { [format { [list source [file join $dir %s]]} \ [file split $scriptFile]] "\n" } - diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index 7d62d7902c..254d210bdc 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -88,7 +88,7 @@ case "${1:-.}${2:-.}${3:-.}" in # remove lines that are unique to ours. orig=`git-unpack-file $2` sz0=`wc -c <"$orig"` - diff -u -La/$orig -Lb/$orig $orig $src2 | git-apply --no-add + diff -u -La/$orig -Lb/$orig $orig $src2 | git-apply --no-add sz1=`wc -c <"$orig"` # If we do not have enough common material, it is not diff --git a/git-p4import.py b/git-p4import.py index 60a758bfe3..0f3d97b67e 100644 --- a/git-p4import.py +++ b/git-p4import.py @@ -358,4 +358,3 @@ for id in changes: if stitch == 1: git.clean_directories() stitch = 0 - diff --git a/git-svnimport.perl b/git-svnimport.perl index 3af8c7e110..f4597626b9 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -542,7 +542,7 @@ sub copy_path($$$$$$$$) { if ($node_kind eq $SVN::Node::dir) { $srcpath =~ s#/*$#/#; } - + my $pid = open my $f,'-|'; die $! unless defined $pid; if (!$pid) { @@ -560,7 +560,7 @@ sub copy_path($$$$$$$$) { } else { $p = $path; } - push(@$new,[$mode,$sha1,$p]); + push(@$new,[$mode,$sha1,$p]); } close($f) or print STDERR "$newrev:$newbranch: could not list files in $oldpath \@ $rev\n"; diff --git a/git-tag.sh b/git-tag.sh index 37cee978d2..c84043902f 100755 --- a/git-tag.sh +++ b/git-tag.sh @@ -64,7 +64,7 @@ do done ;; -m) - annotate=1 + annotate=1 shift message="$1" if test "$#" = "0"; then @@ -90,7 +90,7 @@ do username="$1" ;; -d) - shift + shift had_error=0 for tag do @@ -180,4 +180,3 @@ if [ "$annotate" ]; then fi git update-ref "refs/tags/$name" "$object" "$prev" - diff --git a/git-verify-tag.sh b/git-verify-tag.sh index 8db7dd0b7d..f2d5597dba 100755 --- a/git-verify-tag.sh +++ b/git-verify-tag.sh @@ -42,4 +42,3 @@ cat "$GIT_DIR/.tmp-vtag" | sed '/-----BEGIN PGP/Q' | gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1 rm -f "$GIT_DIR/.tmp-vtag" - diff --git a/git.spec.in b/git.spec.in index 3a45eb8761..b9dc1d59eb 100644 --- a/git.spec.in +++ b/git.spec.in @@ -63,7 +63,7 @@ Git tools for importing Perforce repositories. %package email Summary: Git tools for sending email Group: Development/Tools -Requires: git-core = %{version}-%{release} +Requires: git-core = %{version}-%{release} %description email Git tools for sending email. diff --git a/gitk b/gitk index a57e84cef7..87c3690ff3 100755 --- a/gitk +++ b/gitk @@ -337,7 +337,7 @@ proc readrefs {} { set tagids($name) $commit lappend idtags($commit) $name } - } + } catch { set tagcontents($name) [exec git cat-file tag $id] } diff --git a/gitweb/README b/gitweb/README index e02e90f042..7186cede2f 100644 --- a/gitweb/README +++ b/gitweb/README @@ -79,4 +79,3 @@ Originally written by: Any comment/question/concern to: Git mailing list - diff --git a/help.c b/help.c index 6a9af4d175..1cd33ece6b 100644 --- a/help.c +++ b/help.c @@ -219,5 +219,3 @@ int cmd_help(int argc, const char **argv, const char *prefix) return 0; } - - diff --git a/http-fetch.c b/http-fetch.c index 09baedc18a..202fae0ba8 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -828,7 +828,7 @@ static void abort_object_request(struct object_request *obj_req) } unlink(obj_req->tmpfile); if (obj_req->slot) { - release_active_slot(obj_req->slot); + release_active_slot(obj_req->slot); obj_req->slot = NULL; } release_object_request(obj_req); diff --git a/http-push.c b/http-push.c index 79d2c38608..7c3720f602 100644 --- a/http-push.c +++ b/http-push.c @@ -518,7 +518,7 @@ static void start_put(struct transfer_request *request) request->buffer.size = stream.total_out; request->buffer.posn = 0; - request->url = xmalloc(strlen(remote->url) + + request->url = xmalloc(strlen(remote->url) + strlen(request->lock->token) + 51); strcpy(request->url, remote->url); posn = request->url + strlen(remote->url); diff --git a/http.c b/http.c index ae27e0c940..c6fb8ace9f 100644 --- a/http.c +++ b/http.c @@ -137,7 +137,7 @@ static int http_options(const char *var, const char *value) return 0; } -#ifdef USE_CURL_MULTI +#ifdef USE_CURL_MULTI if (!strcmp("http.maxrequests", var)) { if (max_requests == -1) max_requests = git_config_int(var, value); diff --git a/imap-send.c b/imap-send.c index 4283a4acda..a5a0696084 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1239,7 +1239,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs ) msg->data[ msg->len ] = 0; *ofs += msg->len; - return 1; + return 1; } static imap_server_conf_t server = diff --git a/local-fetch.c b/local-fetch.c index 4b650efa8b..bf7ec6c2a3 100644 --- a/local-fetch.c +++ b/local-fetch.c @@ -114,7 +114,7 @@ static int fetch_pack(const unsigned char *sha1) return -1; target = find_sha1_pack(sha1, packs); if (!target) - return error("Couldn't find %s: not separate or in any pack", + return error("Couldn't find %s: not separate or in any pack", sha1_to_hex(sha1)); if (get_verbosely) { fprintf(stderr, "Getting pack %s\n", @@ -122,11 +122,11 @@ static int fetch_pack(const unsigned char *sha1) fprintf(stderr, " which contains %s\n", sha1_to_hex(sha1)); } - sprintf(filename, "%s/objects/pack/pack-%s.pack", + sprintf(filename, "%s/objects/pack/pack-%s.pack", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_name(target->sha1), sha1_to_hex(target->sha1), 1); - sprintf(filename, "%s/objects/pack/pack-%s.idx", + sprintf(filename, "%s/objects/pack/pack-%s.idx", path, sha1_to_hex(target->sha1)); copy_file(filename, sha1_pack_index_name(target->sha1), sha1_to_hex(target->sha1), 1); @@ -141,7 +141,7 @@ static int fetch_file(const unsigned char *sha1) char *hex = sha1_to_hex(sha1); char *dest_filename = sha1_file_name(sha1); - if (object_name_start < 0) { + if (object_name_start < 0) { strcpy(filename, path); /* e.g. git.git */ strcat(filename, "/objects/"); object_name_start = strlen(filename); diff --git a/lockfile.c b/lockfile.c index 23db35aff2..5ad2858b48 100644 --- a/lockfile.c +++ b/lockfile.c @@ -97,4 +97,3 @@ void rollback_lock_file(struct lock_file *lk) unlink(lk->filename); lk->filename[0] = 0; } - diff --git a/mailmap.c b/mailmap.c index cb567a2832..8714167059 100644 --- a/mailmap.c +++ b/mailmap.c @@ -89,4 +89,3 @@ int map_email(struct path_list *map, const char *email, char *name, int maxlen) } return 0; } - diff --git a/match-trees.c b/match-trees.c index 23cafe47b4..d7e29c4d1d 100644 --- a/match-trees.c +++ b/match-trees.c @@ -301,4 +301,3 @@ void shift_tree(const unsigned char *hash1, splice_tree(hash1, add_prefix, hash2, shifted); } - diff --git a/merge-index.c b/merge-index.c index 5599fd321b..fa719cb0b1 100644 --- a/merge-index.c +++ b/merge-index.c @@ -25,7 +25,7 @@ static void run_program(void) static int merge_entry(int pos, const char *path) { int found; - + if (pos >= active_nr) die("git-merge-index: %s not in the cache", path); arguments[0] = pgm; diff --git a/mktag.c b/mktag.c index 931011121e..070bc96c0d 100644 --- a/mktag.c +++ b/mktag.c @@ -11,7 +11,7 @@ * The first three lines are guaranteed to be at least 63 bytes: * "object \n" is 48 bytes, "type tag\n" at 9 bytes is the * shortest possible type-line, and "tag .\n" at 6 bytes is the - * shortest single-character-tag line. + * shortest single-character-tag line. * * We also artificially limit the size of the full object to 8kB. * Just because I'm a lazy bastard, and if you can't fit a signature diff --git a/mozilla-sha1/sha1.c b/mozilla-sha1/sha1.c index 847531d19f..3f06b83567 100644 --- a/mozilla-sha1/sha1.c +++ b/mozilla-sha1/sha1.c @@ -1,29 +1,29 @@ -/* +/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is SHA 180-1 Reference Implementation (Compact version) - * + * * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are + * Cryptography Research. Portions created by Paul Kocher are * Copyright (C) 1995-9 by Cryptography Research, Inc. All * Rights Reserved. - * + * * Contributor(s): * * Paul Kocher - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and @@ -149,4 +149,3 @@ static void shaHashBlock(SHA_CTX *ctx) { ctx->H[3] += D; ctx->H[4] += E; } - diff --git a/mozilla-sha1/sha1.h b/mozilla-sha1/sha1.h index 5d82afa3bd..16f2d3d43c 100644 --- a/mozilla-sha1/sha1.h +++ b/mozilla-sha1/sha1.h @@ -1,29 +1,29 @@ -/* +/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. - * + * * The Original Code is SHA 180-1 Header File - * + * * The Initial Developer of the Original Code is Paul Kocher of - * Cryptography Research. Portions created by Paul Kocher are + * Cryptography Research. Portions created by Paul Kocher are * Copyright (C) 1995-9 by Cryptography Research, Inc. All * Rights Reserved. - * + * * Contributor(s): * * Paul Kocher - * + * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and diff --git a/object-refs.c b/object-refs.c index 022e8d841c..5345671569 100644 --- a/object-refs.c +++ b/object-refs.c @@ -85,5 +85,3 @@ void mark_reachable(struct object *obj, unsigned int mask) mark_reachable(refs->ref[i], mask); } } - - diff --git a/object.h b/object.h index 94f19eed86..397bbfa090 100644 --- a/object.h +++ b/object.h @@ -66,7 +66,7 @@ void set_object_refs(struct object *obj, struct object_refs *refs); void mark_reachable(struct object *obj, unsigned int mask); -struct object_list *object_list_insert(struct object *item, +struct object_list *object_list_insert(struct object *item, struct object_list **list_p); void object_list_append(struct object *item, diff --git a/pack-redundant.c b/pack-redundant.c index 6bc3bdf3f4..f5cd0ac59e 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -81,7 +81,7 @@ static struct llist * llist_copy(struct llist *list) { struct llist *ret; struct llist_item *new, *old, *prev; - + llist_init(&ret); if ((ret->size = list->size) == 0) @@ -100,7 +100,7 @@ static struct llist * llist_copy(struct llist *list) } new->next = NULL; ret->back = new; - + return ret; } diff --git a/patch-id.c b/patch-id.c index 086d2d9c68..9349bc5580 100644 --- a/patch-id.c +++ b/patch-id.c @@ -81,4 +81,4 @@ int main(int argc, char **argv) generate_id_list(); return 0; -} +} diff --git a/path-list.c b/path-list.c index caaa5cc57b..dcb4b3ac13 100644 --- a/path-list.c +++ b/path-list.c @@ -100,4 +100,3 @@ void print_path_list(const char *text, const struct path_list *p) for (i = 0; i < p->nr; i++) printf("%s:%p\n", p->items[i].path, p->items[i].util); } - diff --git a/perl/Makefile b/perl/Makefile index 0d695fd2f3..5e079ad011 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -40,4 +40,3 @@ endif # (even though GIT-CFLAGS aren't used yet. If ever) ../GIT-CFLAGS: $(MAKE) -C .. GIT-CFLAGS - diff --git a/pkt-line.c b/pkt-line.c index b60526869a..355546a1ad 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -5,7 +5,7 @@ * Write a packetized stream, where each line is preceded by * its length (including the header) as a 4-byte hex number. * A length of 'zero' means end of stream (and a length of 1-3 - * would be an error). + * would be an error). * * This is all pretty stupid, but we use this packetized line * format to make a streaming format possible without ever diff --git a/ppc/sha1.c b/ppc/sha1.c index 0820398b00..738e36c1e8 100644 --- a/ppc/sha1.c +++ b/ppc/sha1.c @@ -50,7 +50,7 @@ int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) p += nb; } return 0; -} +} int SHA1_Final(unsigned char *hash, SHA_CTX *c) { diff --git a/read-cache.c b/read-cache.c index ad4e187537..4362b11f47 100644 --- a/read-cache.c +++ b/read-cache.c @@ -166,7 +166,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st) changed |= MTIME_CHANGED; if (ce->ce_ctime.nsec != htonl(st->st_ctim.tv_nsec)) changed |= CTIME_CHANGED; -#endif +#endif if (ce->ce_uid != htonl(st->st_uid) || ce->ce_gid != htonl(st->st_gid)) @@ -597,7 +597,7 @@ static int has_dir_name(struct index_state *istate, * is being added, or we already have path and path/file is being * added. Either one would result in a nonsense tree that has path * twice when git-write-tree tries to write it out. Prevent it. - * + * * If ok-to-replace is specified, we remove the conflicting entries * from the cache so the caller should recompute the insert position. * When this happens, we return non-zero. @@ -970,8 +970,8 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) write_buffer_len = buffered; len -= partial; data = (char *) data + partial; - } - return 0; + } + return 0; } static int write_index_ext_header(SHA_CTX *context, int fd, @@ -1037,7 +1037,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) * size to zero here, then the object name recorded * in index is the 6-byte file but the cached stat information * becomes zero --- which would then match what we would - * obtain from the filesystem next time we stat("frotz"). + * obtain from the filesystem next time we stat("frotz"). * * However, the second update-index, before calling * this function, notices that the cached size is 6 diff --git a/rsh.h b/rsh.h index 3b4194239d..ee2f499291 100644 --- a/rsh.h +++ b/rsh.h @@ -1,7 +1,7 @@ #ifndef RSH_H #define RSH_H -int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, +int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, char *url, int rmt_argc, char **rmt_argv); #endif diff --git a/setup.c b/setup.c index a45ea8309a..14f62c42e3 100644 --- a/setup.c +++ b/setup.c @@ -39,7 +39,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) if (len) { int speclen = strlen(path); char *n = xmalloc(speclen + len + 1); - + memcpy(n, prefix, len); memcpy(n + len, path, speclen+1); path = n; @@ -47,7 +47,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) return path; } -/* +/* * Unlike prefix_path, this should be used if the named file does * not have to interact with index entry; i.e. name of a random file * on the filesystem. diff --git a/sha1_file.c b/sha1_file.c index 30bcd46ceb..2b860868f5 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -193,7 +193,7 @@ char *sha1_pack_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -218,7 +218,7 @@ char *sha1_pack_index_name(const unsigned char *sha1) *buf++ = hex[val >> 4]; *buf++ = hex[val & 0xf]; } - + return base; } @@ -1139,7 +1139,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep) unsigned long size; /* - * The type can be at most ten bytes (including the + * The type can be at most ten bytes (including the * terminating '\0' that we add), and is followed by * a space. */ @@ -1738,7 +1738,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons return 0; } -struct packed_git *find_sha1_pack(const unsigned char *sha1, +struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs) { struct packed_git *p; diff --git a/shallow.c b/shallow.c index d17868929c..dbd9f5ad0a 100644 --- a/shallow.c +++ b/shallow.c @@ -101,4 +101,3 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth, return result; } - diff --git a/ssh-upload.c b/ssh-upload.c index 498d41e19b..20c35f03dd 100644 --- a/ssh-upload.c +++ b/ssh-upload.c @@ -29,24 +29,24 @@ static int serve_object(int fd_in, int fd_out) { } if (!size) return -1; - + if (verbose) fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); remote = 0; - + if (!has_sha1_file(sha1)) { fprintf(stderr, "git-ssh-upload: could not find %s\n", sha1_to_hex(sha1)); remote = -1; } - + if (write_in_full(fd_out, &remote, 1) != 1) return 0; - + if (remote < 0) return 0; - + return write_sha1_to_fd(fd_out, sha1); } diff --git a/strbuf.c b/strbuf.c index 7f14b0fb59..e33d06b87c 100644 --- a/strbuf.c +++ b/strbuf.c @@ -39,4 +39,3 @@ void read_line(struct strbuf *sb, FILE *fp, int term) { sb->eof = 1; strbuf_end(sb); } - diff --git a/t/Makefile b/t/Makefile index 19e38508a7..b25caca887 100644 --- a/t/Makefile +++ b/t/Makefile @@ -28,4 +28,3 @@ full-svn-test: .PHONY: $(T) clean .NOTPARALLEL: - diff --git a/t/lib-read-tree-m-3way.sh b/t/lib-read-tree-m-3way.sh index d195603dfa..586df2113f 100644 --- a/t/lib-read-tree-m-3way.sh +++ b/t/lib-read-tree-m-3way.sh @@ -87,7 +87,7 @@ test_expect_success \ test_expect_success \ 'recording branch A tree' \ 'tree_A=$(git-write-tree)' - + ################################################################ # Branch B # Start from O diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 186de70243..8bfe8320ea 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -37,7 +37,7 @@ fi find .git/objects -type f -print >should-be-empty test_expect_success \ '.git/objects should be empty after git-init in an empty repo.' \ - 'cmp -s /dev/null should-be-empty' + 'cmp -s /dev/null should-be-empty' # also it should have 2 subdirectories; no fan-out anymore, pack, and info. # 3 is counting "objects" itself diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh index ca2c30f7af..d3f8358485 100755 --- a/t/t1200-tutorial.sh +++ b/t/t1200-tutorial.sh @@ -159,4 +159,3 @@ test_expect_success 'git prune-packed' 'git prune-packed' test_expect_failure '-> only packed objects' 'find -type f .git/objects/[0-9a-f][0-9a-f]' test_done - diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 3f3fd2d7f7..7731fa72ce 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -514,4 +514,3 @@ git config --list > result test_expect_success 'value continued on next line' 'cmp result expect' test_done - diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh index 03ea4dece4..d556b41f13 100755 --- a/t/t2000-checkout-cache-clash.sh +++ b/t/t2000-checkout-cache-clash.sh @@ -49,5 +49,3 @@ test_expect_success \ 'test -f path0 && test -d path1 && test -f path1/file1' test_done - - diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh index 0dcab8f1de..b895a0fe36 100755 --- a/t/t2001-checkout-cache-clash.sh +++ b/t/t2001-checkout-cache-clash.sh @@ -84,4 +84,3 @@ test_expect_success \ test ! -h path1/file1 && test -f path1/file1' test_done - diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 86ee2b0bd3..607f57ff94 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -525,4 +525,3 @@ test_expect_success 'reset and bind merge' ' ' test_done - diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 977c498f00..9e11ed295d 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -54,4 +54,3 @@ test_expect_success 'merge and reference trees equal' \ test_debug 'gitk --all & sleep 1' test_done - diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh index e72c6fd1b4..b8acca1813 100755 --- a/t/t4006-diff-mode.sh +++ b/t/t4006-diff-mode.sh @@ -41,4 +41,3 @@ test_expect_success \ 'git diff expected check' test_done - diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh index 7b81c32e57..c23341feb5 100755 --- a/t/t4100-apply-stat.sh +++ b/t/t4100-apply-stat.sh @@ -44,4 +44,3 @@ test_expect_success \ git diff ../t4100/t-apply-7.expect current' test_done - diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh index 005f744816..9faef0d66e 100755 --- a/t/t4110-apply-scan.sh +++ b/t/t4110-apply-scan.sh @@ -98,4 +98,3 @@ test_expect_success "S = cmp" \ 'cmp apply.txt patch.txt' test_done - diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh index 69e9603c78..9baf810bee 100755 --- a/t/t4112-apply-renames.sh +++ b/t/t4112-apply-renames.sh @@ -49,10 +49,10 @@ copy to include/arch/cris/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/cris/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -74,9 +74,9 @@ copy to include/arch/cris/klibc/archsetjmp.h + unsigned long __sp; + unsigned long __srp; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/m32r/klibc/archsetjmp.h @@ -90,10 +90,10 @@ rename to include/arch/m32r/klibc/archsetjmp.h - * arch/x86_64/include/klibc/archsetjmp.h + * arch/m32r/include/klibc/archsetjmp.h */ - + #ifndef _KLIBC_ARCHSETJMP_H #define _KLIBC_ARCHSETJMP_H - + struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; @@ -108,9 +108,9 @@ rename to include/arch/m32r/klibc/archsetjmp.h unsigned long __r15; - unsigned long __rip; }; - + typedef struct __jmp_buf jmp_buf[1]; - + -#endif /* _SETJMP_H */ +#endif /* _KLIBC_ARCHSETJMP_H */ EOF diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 27cc6f2b88..dd88e81e04 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -53,4 +53,3 @@ test_expect_success 'apply --apply' ' ' test_done - diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index 620a9207bf..edae7056e4 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -24,7 +24,7 @@ cat >gpatch.file <<\EOF && +++ file1+ 2007-02-21 01:07:44.000000000 -0800 @@ -1 +1 @@ -A -+B ++B EOF sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file && diff --git a/t/t4121-apply-diffs.sh b/t/t4121-apply-diffs.sh index 2b2f1eda21..b95b89c341 100755 --- a/t/t4121-apply-diffs.sh +++ b/t/t4121-apply-diffs.sh @@ -30,4 +30,3 @@ test_expect_success \ '( git diff test~2 test~1; git diff test~1 test~0 )| git apply' test_done - diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 3ddfe64b02..841773f75f 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -53,4 +53,3 @@ test_expect_success 'check result' ' ' test_done - diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index c64ebbb2e9..a46d7f74be 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -148,5 +148,3 @@ test_expect_success 'old records rest in peace' \ "test ! -f $rr/preimage && test ! -f $rr2/preimage" test_done - - diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 477b267599..4eaea8f336 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -66,7 +66,7 @@ test_expect_success 'pack the destination repository' ' ' test_expect_success \ - 'pushing rewound head should not barf but require --force' ' + 'pushing rewound head should not barf but require --force' ' # should not fail but refuse to update. if git-send-pack ./victim/.git/ master then diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 243212d3da..93eaf2c154 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -54,4 +54,3 @@ test_expect_success 'the default remote . should not break explicit pull' ' ' test_done - diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh index 2f8e97cb7e..699df6ebd8 100755 --- a/t/t5710-info-alternate.sh +++ b/t/t5710-info-alternate.sh @@ -104,4 +104,3 @@ test_valid_repo' cd "$base_dir" test_done - diff --git a/t/t6000lib.sh b/t/t6000lib.sh index d40262159b..d548bf8026 100755 --- a/t/t6000lib.sh +++ b/t/t6000lib.sh @@ -17,17 +17,17 @@ unique_commit() _text=$1 _tree=$2 shift 2 - echo $_text | git-commit-tree $(tag $_tree) "$@" + echo $_text | git-commit-tree $(tag $_tree) "$@" } # Save the output of a command into the tag specified. Prepend # a substitution script for the tag onto the front of sed.script save_tag() { - _tag=$1 + _tag=$1 [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..." shift 1 - "$@" >.git/refs/tags/$_tag + "$@" >.git/refs/tags/$_tag echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp cat sed.script >> sed.script.tmp @@ -35,7 +35,7 @@ save_tag() mv sed.script.tmp sed.script } -# Replace unhelpful sha1 hashses with their symbolic equivalents +# Replace unhelpful sha1 hashses with their symbolic equivalents entag() { sed -f sed.script @@ -62,7 +62,7 @@ as_author() commit_date() { _commit=$1 - git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" + git-cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p" } on_committer_date() @@ -103,14 +103,14 @@ name_from_description() # Execute the test described by the first argument, by eval'ing # command line specified in the 2nd argument. Check the status code -# is zero and that the output matches the stream read from +# is zero and that the output matches the stream read from # stdin. test_output_expect_success() -{ +{ _description=$1 _test=$2 [ $# -eq 2 ] || error "usage: test_output_expect_success description test < $_name.expected - test_expect_success "$_description" "check_output $_name \"$_test\"" + test_expect_success "$_description" "check_output $_name \"$_test\"" } diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index fcb3302764..71cbb72e1b 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -26,7 +26,7 @@ test_bisection_diff() # Test if bisection size is close to half of list size within # tolerance. - # + # _bisect_err=`expr $_list_size - $_bisection_size \* 2` test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err` _bisect_err=`expr $_bisect_err / 2` ; # floor @@ -116,8 +116,8 @@ on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p test_sequence() { - _bisect_option=$1 - + _bisect_option=$1 + test_bisection_diff 0 $_bisect_option l0 ^root test_bisection_diff 0 $_bisect_option l1 ^root test_bisection_diff 0 $_bisect_option l2 ^root @@ -152,7 +152,7 @@ test_sequence() test_bisection_diff 0 $_bisect_option u3 ^U test_bisection_diff 0 $_bisect_option u4 ^U test_bisection_diff 0 $_bisect_option u5 ^U - + # # the following illustrates Linus' binary bug blatt idea. # diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh index 499cafb882..0ab14a6e81 100755 --- a/t/t6021-merge-criss-cross.sh +++ b/t/t6021-merge-criss-cross.sh @@ -20,7 +20,7 @@ test_expect_success 'prepare repository' \ 7 8 9" > file && -git add file && +git add file && git commit -m "Initial commit" file && git branch A && git branch B && diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index c76fccfb5a..43aa5d033d 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -135,4 +135,3 @@ EOF test_expect_success "expected conflict markers" "git diff expect out" test_done - diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 30f6ade13f..03cdba5808 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -102,4 +102,3 @@ test_expect_success \ # # test_done - diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index b0252b9413..dd6cc3a55c 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -40,4 +40,3 @@ test_expect_success 'short SHA-1 works' ' test $start = $abbrv' test_done - diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh index dc2afdaa45..d549665400 100755 --- a/t/t9107-git-svn-migrate.sh +++ b/t/t9107-git-svn-migrate.sh @@ -109,4 +109,3 @@ test_expect_success ".rev_db auto-converted to .rev_db.UUID" " " test_done - diff --git a/t/t9111/svnsync.dump b/t/t9111/svnsync.dump index a9a46eeb29..499fa9594f 100644 --- a/t/t9111/svnsync.dump +++ b/t/t9111/svnsync.dump @@ -558,5 +558,3 @@ Text-content-md5: 7abb78de7f2756ca8b511cbc879fd5e7 Content-length: 4 cba - - diff --git a/t/test-lib.sh b/t/test-lib.sh index dee3ad7621..8bf4cf49a2 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -232,7 +232,7 @@ test_create_repo () { mv .git/hooks .git/hooks-disabled cd "$owd" } - + test_done () { trap - exit case "$test_failure" in diff --git a/templates/hooks--commit-msg b/templates/hooks--commit-msg index 9b04f2d69c..c5cdb9d7ee 100644 --- a/templates/hooks--commit-msg +++ b/templates/hooks--commit-msg @@ -19,4 +19,3 @@ test "" = "$(grep '^Signed-off-by: ' "$1" | echo >&2 Duplicate Signed-off-by lines. exit 1 } - diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive index 190de2688c..b70c8fd364 100644 --- a/templates/hooks--post-receive +++ b/templates/hooks--post-receive @@ -14,4 +14,3 @@ #. /usr/share/doc/git-core/contrib/hooks/post-receive-email - diff --git a/templates/hooks--pre-applypatch b/templates/hooks--pre-applypatch index 5f56ce8053..eeccc934ca 100644 --- a/templates/hooks--pre-applypatch +++ b/templates/hooks--pre-applypatch @@ -12,4 +12,3 @@ test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} : - diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit index 723a9ef210..18b87309f6 100644 --- a/templates/hooks--pre-commit +++ b/templates/hooks--pre-commit @@ -68,4 +68,3 @@ perl -e ' } exit($found_bad); ' - diff --git a/tree-walk.c b/tree-walk.c index cbb24eb3f6..8d4b67317f 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -206,4 +206,3 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch free(tree); return retval; } - diff --git a/upload-pack.c b/upload-pack.c index d3a09e78d5..0e881c85b5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -678,7 +678,7 @@ int main(int argc, char **argv) break; } } - + if (i != argc-1) usage(upload_pack_usage); dir = argv[i]; diff --git a/var.c b/var.c index e585e59d31..4127031910 100644 --- a/var.c +++ b/var.c @@ -67,8 +67,8 @@ int main(int argc, char **argv) val = read_var(argv[1]); if (!val) usage(var_usage); - + printf("%s\n", val); - + return 0; } diff --git a/xdiff-interface.c b/xdiff-interface.c index 963bb89b08..e407cf11b1 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -129,5 +129,3 @@ int buffer_is_binary(const char *ptr, unsigned long size) size = FIRST_FEW_BYTES; return !!memchr(ptr, 0, size); } - - diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index e874a7c46a..9402bb0799 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -103,4 +103,3 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, #endif /* #ifdef __cplusplus */ #endif /* #if !defined(XDIFF_H) */ - diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c index 9aeebc473b..5cb7171a8f 100644 --- a/xdiff/xdiffi.c +++ b/xdiff/xdiffi.c @@ -565,4 +565,3 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, return 0; } - diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h index 472aeaecfa..3e099dc445 100644 --- a/xdiff/xdiffi.h +++ b/xdiff/xdiffi.h @@ -57,4 +57,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg); #endif /* #if !defined(XDIFFI_H) */ - diff --git a/xdiff/xemit.c b/xdiff/xemit.c index e291dc7608..78b1d4b8bb 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -194,4 +194,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, return 0; } - diff --git a/xdiff/xemit.h b/xdiff/xemit.h index e629417dd2..440a7390fa 100644 --- a/xdiff/xemit.h +++ b/xdiff/xemit.h @@ -31,4 +31,3 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, #endif /* #if !defined(XEMIT_H) */ - diff --git a/xdiff/xinclude.h b/xdiff/xinclude.h index 04a9da82c9..526ccb344d 100644 --- a/xdiff/xinclude.h +++ b/xdiff/xinclude.h @@ -40,4 +40,3 @@ #endif /* #if !defined(XINCLUDE_H) */ - diff --git a/xdiff/xmacros.h b/xdiff/xmacros.h index e2cd2023b3..8ef232cfad 100644 --- a/xdiff/xmacros.h +++ b/xdiff/xmacros.h @@ -51,4 +51,3 @@ do { \ #endif /* #if !defined(XMACROS_H) */ - diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c index 1be7b31950..e87ab57c65 100644 --- a/xdiff/xprepare.c +++ b/xdiff/xprepare.c @@ -466,4 +466,3 @@ static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2) { return 0; } - diff --git a/xdiff/xprepare.h b/xdiff/xprepare.h index 344c569e8b..8fb06a5374 100644 --- a/xdiff/xprepare.h +++ b/xdiff/xprepare.h @@ -32,4 +32,3 @@ void xdl_free_env(xdfenv_t *xe); #endif /* #if !defined(XPREPARE_H) */ - diff --git a/xdiff/xtypes.h b/xdiff/xtypes.h index 3593a664fc..2511aef8d8 100644 --- a/xdiff/xtypes.h +++ b/xdiff/xtypes.h @@ -65,4 +65,3 @@ typedef struct s_xdfenv { #endif /* #if !defined(XTYPES_H) */ - diff --git a/xdiff/xutils.c b/xdiff/xutils.c index bf91c0f73c..2ade97b257 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -380,4 +380,3 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, return 0; } - diff --git a/xdiff/xutils.h b/xdiff/xutils.h index 70d8b9838a..d5de8292e0 100644 --- a/xdiff/xutils.h +++ b/xdiff/xutils.h @@ -45,4 +45,3 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, #endif /* #if !defined(XUTILS_H) */ - -- cgit v1.3 From 16befb8b7fbfcc9b2d38931f4081669558300adf Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 8 Jun 2007 02:54:57 -0700 Subject: Even more missing static Signed-off-by: Junio C Hamano --- builtin-stripspace.c | 2 +- builtin.h | 1 - commit.c | 9 --------- commit.h | 2 -- diff.c | 4 +++- diff.h | 2 -- quote.c | 14 +------------- quote.h | 2 -- upload-pack.c | 2 +- 9 files changed, 6 insertions(+), 32 deletions(-) (limited to 'diff.c') diff --git a/builtin-stripspace.c b/builtin-stripspace.c index f0d4d9e2d1..62bd4b547b 100644 --- a/builtin-stripspace.c +++ b/builtin-stripspace.c @@ -26,7 +26,7 @@ static int cleanup(char *line) return 1; } -void stripspace(FILE *in, FILE *out) +static void stripspace(FILE *in, FILE *out) { int empties = -1; int incomplete = 0; diff --git a/builtin.h b/builtin.h index fe8ba9e65f..da4834c312 100644 --- a/builtin.h +++ b/builtin.h @@ -7,7 +7,6 @@ extern const char git_version_string[]; extern const char git_usage_string[]; extern void help_unknown_cmd(const char *cmd); -extern void stripspace(FILE *in, FILE *out); extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix); extern void prune_packed_objects(int); diff --git a/commit.c b/commit.c index 57b69ca7fa..4ca4d44ba0 100644 --- a/commit.c +++ b/commit.c @@ -1116,15 +1116,6 @@ struct commit *pop_commit(struct commit_list **stack) return item; } -int count_parents(struct commit * commit) -{ - int count; - struct commit_list * parents = commit->parents; - for (count = 0; parents; parents = parents->next,count++) - ; - return count; -} - void topo_sort_default_setter(struct commit *c, void *data) { c->util = data; diff --git a/commit.h b/commit.h index 75b43a53ed..a313b53c31 100644 --- a/commit.h +++ b/commit.h @@ -73,8 +73,6 @@ struct commit *pop_commit(struct commit_list **stack); void clear_commit_marks(struct commit *commit, unsigned int mark); -int count_parents(struct commit * commit); - /* * Performs an in-place topological sort of list supplied. * diff --git a/diff.c b/diff.c index cafa7debeb..1d234d361d 100644 --- a/diff.c +++ b/diff.c @@ -2103,6 +2103,8 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va return 1; } +static int diff_scoreopt_parse(const char *opt); + int diff_opt_parse(struct diff_options *options, const char **av, int ac) { const char *arg = av[0]; @@ -2274,7 +2276,7 @@ static int parse_num(const char **cp_p) return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale)); } -int diff_scoreopt_parse(const char *opt) +static int diff_scoreopt_parse(const char *opt) { int opt1, opt2, cmd; diff --git a/diff.h b/diff.h index 63738c1dd4..a7ee6d8c87 100644 --- a/diff.h +++ b/diff.h @@ -155,8 +155,6 @@ extern void diff_unmerge(struct diff_options *, unsigned mode, const unsigned char *sha1); -extern int diff_scoreopt_parse(const char *opt); - #define DIFF_SETUP_REVERSE 1 #define DIFF_SETUP_USE_CACHE 2 #define DIFF_SETUP_USE_SIZE_CACHE 4 diff --git a/quote.c b/quote.c index fb9e4ca253..aa440098e1 100644 --- a/quote.c +++ b/quote.c @@ -20,7 +20,7 @@ static inline int need_bs_quote(char c) return (c == '\'' || c == '!'); } -size_t sq_quote_buf(char *dst, size_t n, const char *src) +static size_t sq_quote_buf(char *dst, size_t n, const char *src) { char c; char *bp = dst; @@ -62,18 +62,6 @@ void sq_quote_print(FILE *stream, const char *src) fputc('\'', stream); } -char *sq_quote(const char *src) -{ - char *buf; - size_t cnt; - - cnt = sq_quote_buf(NULL, 0, src) + 1; - buf = xmalloc(cnt); - sq_quote_buf(buf, cnt, src); - - return buf; -} - char *sq_quote_argv(const char** argv, int count) { char *buf, *to; diff --git a/quote.h b/quote.h index bdc3610df5..8a59cc55d1 100644 --- a/quote.h +++ b/quote.h @@ -28,9 +28,7 @@ * excluding the final null regardless of the buffer size. */ -extern char *sq_quote(const char *src); extern void sq_quote_print(FILE *stream, const char *src); -extern size_t sq_quote_buf(char *dst, size_t n, const char *src); extern char *sq_quote_argv(const char** argv, int count); /* diff --git a/upload-pack.c b/upload-pack.c index 0e881c85b5..fe96ef15c4 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -62,7 +62,7 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz) return safe_write(fd, data, sz); } -FILE *pack_pipe = NULL; +static FILE *pack_pipe = NULL; static void show_commit(struct commit *commit) { if (commit->object.flags & BOUNDARY) -- cgit v1.3 From ca6c097089a38d447de0190ea61e9746a40a170c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 11 Jun 2007 21:12:19 +0100 Subject: Teach diff to imply --find-copies-harder upon -C -C Earlier, a second "-C" on the command line had no effect. But "--find-copies-harder" is so long to type, let's make doubled -C enable that option. It is in line with how "git blame" handles such doubled options to mean "work harder". Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 7 ++++--- diff.c | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index b2a05937f9..0f07c9c4a8 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -86,7 +86,7 @@ Detect renames. -C:: - Detect copies as well as renames. + Detect copies as well as renames. See also `--find-copies-harder`. --diff-filter=[ACDMRTUXB*]:: Select only files that are Added (`A`), Copied (`C`), @@ -100,12 +100,13 @@ that matches other criteria, nothing is selected. --find-copies-harder:: - For performance reasons, by default, -C option finds copies only + For performance reasons, by default, `-C` option finds copies only if the original file of the copy was modified in the same changeset. This flag makes the command inspect unmodified files as candidates for the source of copy. This is a very expensive operation for large - projects, so use it with caution. + projects, so use it with caution. Giving more than one + `-C` option has the same effect. -l:: -M and -C options require O(n^2) processing time where n diff --git a/diff.c b/diff.c index 1d234d361d..4aa9bbc011 100644 --- a/diff.c +++ b/diff.c @@ -2201,6 +2201,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->detect_rename = DIFF_DETECT_RENAME; } else if (!prefixcmp(arg, "-C")) { + if (options->detect_rename == DIFF_DETECT_COPY) + options->find_copies_harder = 1; if ((options->rename_score = diff_scoreopt_parse(arg)) == -1) return -1; -- cgit v1.3 From 634cd48a8afdd920fa26c8ec3ae43e96c82c81f2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 5 Jun 2007 03:36:11 +0100 Subject: Move buffer_is_binary() to xdiff-interface.h We already have two instances where we want to determine if a buffer contains binary data as opposed to text. [jc: cherry-picked 6bfce93e from 'master'] Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 7 +------ grep.c | 12 +----------- xdiff-interface.c | 8 ++++++++ xdiff-interface.h | 1 + 4 files changed, 11 insertions(+), 17 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index af282ddd88..dc6da5e253 100644 --- a/diff.c +++ b/diff.c @@ -1107,10 +1107,8 @@ static void setup_diff_attr_check(struct git_attr_check *check) check->attr = attr_diff; } -#define FIRST_FEW_BYTES 8000 static int file_is_binary(struct diff_filespec *one) { - unsigned long sz; struct git_attr_check attr_diff_check; setup_diff_attr_check(&attr_diff_check); @@ -1127,10 +1125,7 @@ static int file_is_binary(struct diff_filespec *one) return 0; diff_populate_filespec(one, 0); } - sz = one->size; - if (FIRST_FEW_BYTES < sz) - sz = FIRST_FEW_BYTES; - return !!memchr(one->data, 0, sz); + return buffer_is_binary(one->data, one->size); } static void builtin_diff(const char *name_a, diff --git a/grep.c b/grep.c index fcc6762302..f67d6716ea 100644 --- a/grep.c +++ b/grep.c @@ -1,5 +1,6 @@ #include "cache.h" #include "grep.h" +#include "xdiff-interface.h" void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t) @@ -232,17 +233,6 @@ static void show_line(struct grep_opt *opt, const char *bol, const char *eol, printf("%.*s\n", (int)(eol-bol), bol); } -/* - * NEEDSWORK: share code with diff.c - */ -#define FIRST_FEW_BYTES 8000 -static int buffer_is_binary(const char *ptr, unsigned long size) -{ - if (FIRST_FEW_BYTES < size) - size = FIRST_FEW_BYTES; - return !!memchr(ptr, 0, size); -} - static int fixmatch(const char *pattern, char *line, regmatch_t *match) { char *hit = strstr(line, pattern); diff --git a/xdiff-interface.c b/xdiff-interface.c index 10816e95a0..963bb89b08 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -122,4 +122,12 @@ int read_mmfile(mmfile_t *ptr, const char *filename) return 0; } +#define FIRST_FEW_BYTES 8000 +int buffer_is_binary(const char *ptr, unsigned long size) +{ + if (FIRST_FEW_BYTES < size) + size = FIRST_FEW_BYTES; + return !!memchr(ptr, 0, size); +} + diff --git a/xdiff-interface.h b/xdiff-interface.h index 1918808081..536f4e4d97 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -18,5 +18,6 @@ int parse_hunk_header(char *line, int len, int *ob, int *on, int *nb, int *nn); int read_mmfile(mmfile_t *ptr, const char *filename); +int buffer_is_binary(const char *ptr, unsigned long size); #endif -- cgit v1.3 From 750f7b668f33c9e8decbdd8141115328992d6fea Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 19 Jun 2007 14:22:46 -0700 Subject: Finally implement "git log --follow" Ok, I've really held off doing this too damn long, because I'm lazy, and I was always hoping that somebody else would do it. But no, people keep asking for it, but nobody actually did anything, so I decided I might as well bite the bullet, and instead of telling people they could add a "--follow" flag to "git log" to do what they want to do, I decided that it looks like I just have to do it for them.. The code wasn't actually that complicated, in that the diffstat for this patch literally says "70 insertions(+), 1 deletions(-)", but I will have to admit that in order to get to this fairly simple patch, you did have to know and understand the internal git diff generation machinery pretty well, and had to really be able to follow how commit generation interacts with generating patches and generating the log. So I suspect that while I was right that it wasn't that hard, I might have been expecting too much of random people - this patch does seem to be firmly in the core "Linus or Junio" territory. To make a long story short: I'm sorry for it taking so long until I just did it. I'm not going to guarantee that this works for everybody, but you really can just look at the patch, and after the appropriate appreciative noises ("Ooh, aah") over how clever I am, you can then just notice that the code itself isn't really that complicated. All the real new code is in the new "try_to_follow_renames()" function. It really isn't rocket science: we notice that the pathname we were looking at went away, so we start a full tree diff and try to see if we can instead make that pathname be a rename or a copy from some other previous pathname. And if we can, we just continue, except we show *that* particular diff, and ever after we use the _previous_ pathname. One thing to look out for: the "rename detection" is considered to be a singular event in the _linear_ "git log" output! That's what people want to do, but I just wanted to point out that this patch is *not* carrying around a "commit,pathname" kind of pair and it's *not* going to be able to notice the file coming from multiple *different* files in earlier history. IOW, if you use "git log --follow", then you get the stupid CVS/SVN kind of "files have single identities" kind of semantics, and git log will just pick the identity based on the normal move/copy heuristics _as_if_ the history could be linearized. Put another way: I think the model is broken, but given the broken model, I think this patch does just about as well as you can do. If you have merges with the same "file" having different filenames over the two branches, git will just end up picking _one_ of the pathnames at the point where the newer one goes away. It never looks at multiple pathnames in parallel. And if you understood all that, you probably didn't need it explained, and if you didn't understand the above blathering, it doesn't really mtter to you. What matters to you is that you can now do git log -p --follow builtin-rev-list.c and it will find the point where the old "rev-list.c" got renamed to "builtin-rev-list.c" and show it as such. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-log.c | 5 +++++ diff.c | 2 ++ diff.h | 1 + revision.c | 4 +++- tree-diff.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/builtin-log.c b/builtin-log.c index b9035ab799..073a2a16a3 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -58,6 +58,11 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; + if (rev->diffopt.follow_renames) { + rev->always_show_header = 0; + if (rev->diffopt.nr_paths != 1) + usage("git logs can only follow renames on one pathname at a time"); + } for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { diff --git a/diff.c b/diff.c index 4aa9bbc011..9938969fa5 100644 --- a/diff.c +++ b/diff.c @@ -2210,6 +2210,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) } else if (!strcmp(arg, "--find-copies-harder")) options->find_copies_harder = 1; + else if (!strcmp(arg, "--follow")) + options->follow_renames = 1; else if (!strcmp(arg, "--abbrev")) options->abbrev = DEFAULT_ABBREV; else if (!prefixcmp(arg, "--abbrev=")) { diff --git a/diff.h b/diff.h index a7ee6d8c87..9fd6d447d4 100644 --- a/diff.h +++ b/diff.h @@ -55,6 +55,7 @@ struct diff_options { full_index:1, silent_on_remove:1, find_copies_harder:1, + follow_renames:1, color_diff:1, color_diff_words:1, has_changes:1, diff --git a/revision.c b/revision.c index 1f4590b896..7834bb108e 100644 --- a/revision.c +++ b/revision.c @@ -1230,7 +1230,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (revs->prune_data) { diff_tree_setup_paths(revs->prune_data, &revs->pruning); - revs->prune_fn = try_to_simplify_commit; + /* Can't prune commits with rename following: the paths change.. */ + if (!revs->diffopt.follow_renames) + revs->prune_fn = try_to_simplify_commit; if (!revs->full_diff) diff_tree_setup_paths(revs->prune_data, &revs->diffopt); } diff --git a/tree-diff.c b/tree-diff.c index 852498eb49..42924e9b63 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -3,6 +3,7 @@ */ #include "cache.h" #include "diff.h" +#include "diffcore.h" #include "tree.h" static char *malloc_base(const char *base, int baselen, const char *path, int pathlen) @@ -290,6 +291,59 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru return 0; } +/* + * Does it look like the resulting diff might be due to a rename? + * - single entry + * - not a valid previous file + */ +static inline int diff_might_be_rename(void) +{ + return diff_queued_diff.nr == 1 && + !DIFF_FILE_VALID(diff_queued_diff.queue[0]->one); +} + +static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) +{ + struct diff_options diff_opts; + const char *paths[2]; + int i; + + diff_setup(&diff_opts); + diff_opts.recursive = 1; + diff_opts.detect_rename = DIFF_DETECT_RENAME; + diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; + diff_opts.single_follow = opt->paths[0]; + paths[0] = NULL; + diff_tree_setup_paths(paths, &diff_opts); + if (diff_setup_done(&diff_opts) < 0) + die("unable to set up diff options to follow renames"); + diff_tree(t1, t2, base, &diff_opts); + diffcore_std(&diff_opts); + + /* NOTE! Ignore the first diff! That was the old one! */ + for (i = 1; i < diff_queued_diff.nr; i++) { + struct diff_filepair *p = diff_queued_diff.queue[i]; + + /* + * Found a source? Not only do we use that for the new + * diff_queued_diff, we also use that as the path in + * the future! + */ + if ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, opt->paths[0])) { + diff_queued_diff.queue[0] = p; + opt->paths[0] = xstrdup(p->one->path); + diff_tree_setup_paths(opt->paths, opt); + break; + } + } + + /* + * Then, ignore any but the first entry! It might be the old one, + * or it might be the rename/copy we found + */ + diff_queued_diff.nr = 1; +} + int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt) { void *tree1, *tree2; @@ -306,6 +360,11 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha init_tree_desc(&t1, tree1, size1); init_tree_desc(&t2, tree2, size2); retval = diff_tree(&t1, &t2, base, opt); + if (opt->follow_renames && diff_might_be_rename()) { + init_tree_desc(&t1, tree1, size1); + init_tree_desc(&t2, tree2, size2); + try_to_follow_renames(&t1, &t2, base, opt); + } free(tree1); free(tree2); return retval; -- cgit v1.3 From 125b7630521918b75c136bd95309054d3f6d9da5 Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Mon, 25 Jun 2007 00:23:34 +0200 Subject: diff: round down similarity index Rounding down the printed (dis)similarity index allows us to use "100%" as a special value that indicates complete rewrites and fully equal file contents, respectively. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/diff-format.txt | 7 +++++++ diff.c | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 18d49d2c3b..001503205b 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -126,6 +126,13 @@ the file that rename/copy produces, respectively. If there is need for such substitution then the whole pathname is put in double quotes. +The similarity index is the percentage of unchanged lines, and +the dissimilarity index is the percentage of changed lines. It +is a rounded down integer, followed by a percent sign. The +similarity index value of 100% is thus reserved for two equal +files, while 100% dissimilarity means that no line from the old +file made it into the new one. + combined diff format -------------------- diff --git a/diff.c b/diff.c index 9938969fa5..e0edb98846 100644 --- a/diff.c +++ b/diff.c @@ -1813,6 +1813,11 @@ static void diff_fill_sha1_info(struct diff_filespec *one) hashclr(one->sha1); } +static int similarity_index(struct diff_filepair *p) +{ + return p->score * 100 / MAX_SCORE; +} + static void run_diff(struct diff_filepair *p, struct diff_options *o) { const char *pgm = external_diff(); @@ -1847,23 +1852,20 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) "similarity index %d%%\n" "copy from %s\n" "copy to %s\n", - (int)(0.5 + p->score * 100.0/MAX_SCORE), - name_munged, other_munged); + similarity_index(p), name_munged, other_munged); break; case DIFF_STATUS_RENAMED: len += snprintf(msg + len, sizeof(msg) - len, "similarity index %d%%\n" "rename from %s\n" "rename to %s\n", - (int)(0.5 + p->score * 100.0/MAX_SCORE), - name_munged, other_munged); + similarity_index(p), name_munged, other_munged); break; case DIFF_STATUS_MODIFIED: if (p->score) { len += snprintf(msg + len, sizeof(msg) - len, "dissimilarity index %d%%\n", - (int)(0.5 + p->score * - 100.0/MAX_SCORE)); + similarity_index(p)); complete_rewrite = 1; break; } @@ -2387,8 +2389,7 @@ static void diff_flush_raw(struct diff_filepair *p, } if (p->score) - sprintf(status, "%c%03d", p->status, - (int)(0.5 + p->score * 100.0/MAX_SCORE)); + sprintf(status, "%c%03d", p->status, similarity_index(p)); else { status[0] = p->status; status[1] = 0; @@ -2670,8 +2671,7 @@ static void show_rename_copy(const char *renamecopy, struct diff_filepair *p) { char *names = pprint_rename(p->one->path, p->two->path); - printf(" %s %s (%d%%)\n", renamecopy, names, - (int)(0.5 + p->score * 100.0/MAX_SCORE)); + printf(" %s %s (%d%%)\n", renamecopy, names, similarity_index(p)); free(names); show_mode_change(p, 0); } @@ -2695,7 +2695,7 @@ static void diff_summary(struct diff_filepair *p) if (p->score) { char *name = quote_one(p->two->path); printf(" rewrite %s (%d%%)\n", name, - (int)(0.5 + p->score * 100.0/MAX_SCORE)); + similarity_index(p)); free(name); show_mode_change(p, 0); } else show_mode_change(p, 1); -- cgit v1.3 From 706098af6b53403b5ea3db9216fb99afbe06f52d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 28 Jun 2007 22:56:07 -0700 Subject: diffcore_filespec: add is_binary diffcore-break and diffcore-rename would want to behave slightly differently depending on the binary-ness of the data, so add one bit to the filespec, as the structure is now passed down to diffcore_count_changes() function. Signed-off-by: Junio C Hamano --- diff.c | 16 ++++++++++++++++ diffcore.h | 1 + 2 files changed, 17 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 9938969fa5..74c1198e67 100644 --- a/diff.c +++ b/diff.c @@ -3005,6 +3005,22 @@ void diffcore_std(struct diff_options *options) { if (options->quiet) return; + + /* + * break/rename count similarity differently depending on + * the binary-ness. + */ + if ((options->break_opt != -1) || (options->detect_rename)) { + struct diff_queue_struct *q = &diff_queued_diff; + int i; + + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + p->one->is_binary = file_is_binary(p->one); + p->two->is_binary = file_is_binary(p->two); + } + } + if (options->break_opt != -1) diffcore_break(options->break_opt); if (options->detect_rename) diff --git a/diffcore.h b/diffcore.h index 990dec50f1..0c8abb5b94 100644 --- a/diffcore.h +++ b/diffcore.h @@ -37,6 +37,7 @@ struct diff_filespec { #define DIFF_FILE_VALID(spec) (((spec)->mode) != 0) unsigned should_free : 1; /* data should be free()'ed */ unsigned should_munmap : 1; /* data should be munmap()'ed */ + unsigned is_binary : 1; /* data should be considered "binary" */ }; extern struct diff_filespec *alloc_filespec(const char *); -- cgit v1.3 From 3cb567386d5d0349bfb5e3aaf85e973faf685dda Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 3 Jul 2007 16:01:06 +0100 Subject: diff --no-index: fix --name-status with added files Without this patch, an added file would be reported as /dev/null. Noticed by David Kastrup. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 3 ++- t/t4013-diff-various.sh | 2 ++ t/t4013/diff.diff_--name-status_dir2_dir | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 t/t4013/diff.diff_--name-status_dir2_dir (limited to 'diff.c') diff --git a/diff.c b/diff.c index dc6da5e253..da992dd485 100644 --- a/diff.c +++ b/diff.c @@ -2407,7 +2407,8 @@ static void diff_flush_raw(struct diff_filepair *p, printf("%s ", diff_unique_abbrev(p->two->sha1, abbrev)); } - printf("%s%c%s", status, inter_name_termination, path_one); + printf("%s%c%s", status, inter_name_termination, + two_paths || p->one->mode ? path_one : path_two); if (two_paths) printf("%c%s", inter_name_termination, path_two); putchar(line_termination); diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 8f4c29a6b5..4e7d68dda2 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -17,6 +17,7 @@ test_expect_success setup ' export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && mkdir dir && + mkdir dir2 && for i in 1 2 3; do echo $i; done >file0 && for i in A B; do echo $i; done >dir/sub && cat file0 >file2 && @@ -252,6 +253,7 @@ diff --patch-with-stat initial..side diff --patch-with-raw initial..side diff --patch-with-stat -r initial..side diff --patch-with-raw -r initial..side +diff --name-status dir2 dir EOF test_done diff --git a/t/t4013/diff.diff_--name-status_dir2_dir b/t/t4013/diff.diff_--name-status_dir2_dir new file mode 100644 index 0000000000..ef7fdb7335 --- /dev/null +++ b/t/t4013/diff.diff_--name-status_dir2_dir @@ -0,0 +1,3 @@ +$ git diff --name-status dir2 dir +A dir/sub +$ -- cgit v1.3 From 72909befaa043fcc975115bb56d25a6e7dc65fb6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 30 Jun 2007 18:47:07 +0100 Subject: Add diff-option --ext-diff To prevent funky games with external diff engines, git-log and friends prevent external diff engines from being called. That makes sense in the context of git-format-patch or git-rebase. However, for "git log -p" it is not so nice to get the message that binary files cannot be compared, while "git diff" has no problems with them, if you provided an external diff driver. With this patch, "git log --ext-diff -p" will do what you expect, and the option "--no-ext-diff" can be used to override that setting. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 8 ++++++++ diff.c | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 0f07c9c4a8..3d2b9d0a06 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -168,5 +168,13 @@ --quiet:: Disable all output of the program. Implies --exit-code. +--ext-diff:: + Allow an external diff helper to be executed. If you set an + external diff driver with gitlink:gitattributes(5), you need + to use this option with gitlink:git-log(1) and friends. + +--no-ext-diff:: + Disallow external diff drivers. + For more detailed explanation on these common options, see also link:diffcore.html[diffcore documentation]. diff --git a/diff.c b/diff.c index 93eca79c17..b6eb72be02 100644 --- a/diff.c +++ b/diff.c @@ -2241,6 +2241,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->exit_with_status = 1; else if (!strcmp(arg, "--quiet")) options->quiet = 1; + else if (!strcmp(arg, "--ext-diff")) + options->allow_external = 1; + else if (!strcmp(arg, "--no-ext-diff")) + options->allow_external = 0; else return 0; return 1; -- cgit v1.3 From 29a3eefde111f6a24292163c4308f00ab3572627 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 6 Jul 2007 00:18:54 -0700 Subject: Introduce diff_filespec_is_binary() This replaces an explicit initialization of filespec->is_binary field used for rename/break followed by direct access to that field with a wrapper function that lazily iniaitlizes and accesses the field. We would add more attribute accesses for the use of diff routines, and it would be better to make this abstraction earlier. Signed-off-by: Junio C Hamano --- diff.c | 71 ++++++++++++++++++++++++++++---------------------------- diffcore-delta.c | 2 +- diffcore.h | 2 ++ 3 files changed, 39 insertions(+), 36 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 19589707c4..16ea7100df 100644 --- a/diff.c +++ b/diff.c @@ -1102,30 +1102,45 @@ static void setup_diff_attr_check(struct git_attr_check *check) { static struct git_attr *attr_diff; - if (!attr_diff) + if (!attr_diff) { attr_diff = git_attr("diff", 4); - check->attr = attr_diff; + } + check[0].attr = attr_diff; } -static int file_is_binary(struct diff_filespec *one) +static void diff_filespec_check_attr(struct diff_filespec *one) { - struct git_attr_check attr_diff_check; + struct git_attr_check attr_diff_check[1]; - setup_diff_attr_check(&attr_diff_check); - if (!git_checkattr(one->path, 1, &attr_diff_check)) { - const char *value = attr_diff_check.value; + if (one->checked_attr) + return; + + setup_diff_attr_check(attr_diff_check); + one->is_binary = 0; + + if (!git_checkattr(one->path, ARRAY_SIZE(attr_diff_check), attr_diff_check)) { + const char *value; + + /* binaryness */ + value = attr_diff_check[0].value; if (ATTR_TRUE(value)) - return 0; + ; else if (ATTR_FALSE(value)) - return 1; + one->is_binary = 1; } - if (!one->data) { - if (!DIFF_FILE_VALID(one)) - return 0; + if (!one->data && DIFF_FILE_VALID(one)) diff_populate_filespec(one, 0); - } - return buffer_is_binary(one->data, one->size); + + if (one->data) + one->is_binary = buffer_is_binary(one->data, one->size); + +} + +int diff_filespec_is_binary(struct diff_filespec *one) +{ + diff_filespec_check_attr(one); + return one->is_binary; } static void builtin_diff(const char *name_a, @@ -1182,7 +1197,8 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (!o->text && (file_is_binary(one) || file_is_binary(two))) { + if (!o->text && + (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) { /* Quite common confusing case */ if (mf1.size == mf2.size && !memcmp(mf1.ptr, mf2.ptr, mf1.size)) @@ -1260,7 +1276,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (file_is_binary(one) || file_is_binary(two)) { + if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) { data->is_binary = 1; data->added = mf2.size; data->deleted = mf1.size; @@ -1302,7 +1318,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (file_is_binary(two)) + if (diff_filespec_is_binary(two)) goto free_and_return; else { /* Crazy xdl interfaces.. */ @@ -1880,8 +1896,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) if (o->binary) { mmfile_t mf; - if ((!fill_mmfile(&mf, one) && file_is_binary(one)) || - (!fill_mmfile(&mf, two) && file_is_binary(two))) + if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) || + (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) abbrev = 40; } len += snprintf(msg + len, sizeof(msg) - len, @@ -2783,7 +2799,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) return error("unable to read files to diff"); /* Maybe hash p->two? into the patch id? */ - if (file_is_binary(p->two)) + if (diff_filespec_is_binary(p->two)) continue; len1 = remove_space(p->one->path, strlen(p->one->path)); @@ -3011,21 +3027,6 @@ void diffcore_std(struct diff_options *options) if (options->quiet) return; - /* - * break/rename count similarity differently depending on - * the binary-ness. - */ - if ((options->break_opt != -1) || (options->detect_rename)) { - struct diff_queue_struct *q = &diff_queued_diff; - int i; - - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - p->one->is_binary = file_is_binary(p->one); - p->two->is_binary = file_is_binary(p->two); - } - } - if (options->break_opt != -1) diffcore_break(options->break_opt); if (options->detect_rename) diff --git a/diffcore-delta.c b/diffcore-delta.c index a038b166c5..d9729e5ec2 100644 --- a/diffcore-delta.c +++ b/diffcore-delta.c @@ -129,7 +129,7 @@ static struct spanhash_top *hash_chars(struct diff_filespec *one) struct spanhash_top *hash; unsigned char *buf = one->data; unsigned int sz = one->size; - int is_text = !one->is_binary; + int is_text = !diff_filespec_is_binary(one); i = INITIAL_HASH_SIZE; hash = xmalloc(sizeof(*hash) + sizeof(struct spanhash) * (1<mode) != 0) unsigned should_free : 1; /* data should be free()'ed */ unsigned should_munmap : 1; /* data should be munmap()'ed */ + unsigned checked_attr : 1; unsigned is_binary : 1; /* data should be considered "binary" */ }; @@ -46,6 +47,7 @@ extern void fill_filespec(struct diff_filespec *, const unsigned char *, extern int diff_populate_filespec(struct diff_filespec *, int); extern void diff_free_filespec_data(struct diff_filespec *); +extern int diff_filespec_is_binary(struct diff_filespec *); struct diff_filepair { struct diff_filespec *one; -- cgit v1.3 From 30b250104d9307e1225031c7fc39b66643265ed1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 4 Jul 2007 19:05:46 +0100 Subject: Future-proof source for changes in xdemitconf_t The instances of xdemitconf_t were initialized member by member. Instead, initialize them to all zero, so we do not have to update those places each time we introduce a new member. [jc: minimally fixed by getting rid of a new global] Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-blame.c | 2 +- builtin-rerere.c | 2 +- combine-diff.c | 3 +-- diff.c | 10 +++++----- merge-file.c | 1 + merge-tree.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index da23a6f9c9..0519339098 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -518,8 +518,8 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, xdemitcb_t ecb; xpp.flags = xdl_opts; + memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = context; - xecfg.flags = 0; ecb.outf = xdiff_outf; ecb.priv = &state; memset(&state, 0, sizeof(state)); diff --git a/builtin-rerere.c b/builtin-rerere.c index 29fb075d29..01f3848f14 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -282,8 +282,8 @@ static int diff_two(const char *file1, const char *label1, printf("--- a/%s\n+++ b/%s\n", label1, label2); fflush(stdout); xpp.flags = XDF_NEED_MINIMAL; + memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; - xecfg.flags = 0; ecb.outf = outf; xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb); diff --git a/combine-diff.c b/combine-diff.c index ea3ca5f950..ef622340a5 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -215,8 +215,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, parent_file.ptr = grab_blob(parent, &sz); parent_file.size = sz; xpp.flags = XDF_NEED_MINIMAL; - xecfg.ctxlen = 0; - xecfg.flags = 0; + memset(&xecfg, 0, sizeof(xecfg)); ecb.outf = xdiff_outf; ecb.priv = &state; memset(&state, 0, sizeof(state)); diff --git a/diff.c b/diff.c index 16ea7100df..d10e848c79 100644 --- a/diff.c +++ b/diff.c @@ -390,6 +390,7 @@ static void diff_words_show(struct diff_words_data *diff_words) mmfile_t minus, plus; int i; + memset(&xecfg, 0, sizeof(xecfg)); minus.size = diff_words->minus.text.size; minus.ptr = xmalloc(minus.size); memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size); @@ -408,7 +409,6 @@ static void diff_words_show(struct diff_words_data *diff_words) xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc; - xecfg.flags = 0; ecb.outf = xdiff_outf; ecb.priv = diff_words; diff_words->xm.consume = fn_out_diff_words_aux; @@ -1218,6 +1218,7 @@ static void builtin_diff(const char *name_a, xdemitcb_t ecb; struct emit_callback ecbdata; + memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; ecbdata.color_diff = o->color_diff; @@ -1286,9 +1287,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; - xecfg.ctxlen = 0; - xecfg.flags = 0; ecb.outf = xdiff_outf; ecb.priv = diffstat; xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); @@ -1326,9 +1326,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL; - xecfg.ctxlen = 0; - xecfg.flags = 0; ecb.outf = xdiff_outf; ecb.priv = &data; xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); @@ -2780,6 +2779,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) struct diff_filepair *p = q->queue[i]; int len1, len2; + memset(&xecfg, 0, sizeof(xecfg)); if (p->status == 0) return error("internal diff status error"); if (p->status == DIFF_STATUS_UNKNOWN) diff --git a/merge-file.c b/merge-file.c index 748d15c0e0..1e031eafe0 100644 --- a/merge-file.c +++ b/merge-file.c @@ -62,6 +62,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2) xdemitcb_t ecb; xpp.flags = XDF_NEED_MINIMAL; + memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; xecfg.flags = XDL_EMIT_COMMON; ecb.outf = common_outf; diff --git a/merge-tree.c b/merge-tree.c index 3b8d9e6887..7d4f628444 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -106,8 +106,8 @@ static void show_diff(struct merge_list *entry) xdemitcb_t ecb; xpp.flags = XDF_NEED_MINIMAL; + memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; - xecfg.flags = 0; ecb.outf = show_outf; ecb.priv = NULL; -- cgit v1.3 From f258475a6ede3617ae768b69e33f78cbab8312de Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 6 Jul 2007 00:45:10 -0700 Subject: Per-path attribute based hunk header selection. This makes"diff -p" hunk headers customizable via gitattributes mechanism. It is based on Johannes's earlier patch that allowed to define a single regexp to be used for everything. The mechanism to arrive at the regexp that is used to define hunk header is the same as other use of gitattributes. You assign an attribute, funcname (because "diff -p" typically uses the name of the function the patch is about as the hunk header), a simple string value. This can be one of the names of built-in pattern (currently, "java" is defined) or a custom pattern name, to be looked up from the configuration file. (in .gitattributes) *.java funcname=java *.perl funcname=perl (in .git/config) [funcname] java = ... # ugly and complicated regexp to override the built-in one. perl = ... # another ugly and complicated regexp to define a new one. Signed-off-by: Junio C Hamano --- diff.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++- diffcore.h | 1 + t/t4018-diff-funcname.sh | 60 ++++++++++++++++++++++++++++++ xdiff-interface.c | 71 +++++++++++++++++++++++++++++++++++ xdiff-interface.h | 2 + xdiff/xdiff.h | 4 ++ xdiff/xemit.c | 37 ++++++++++++------- 7 files changed, 256 insertions(+), 15 deletions(-) create mode 100644 t/t4018-diff-funcname.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index d10e848c79..04e7e91adf 100644 --- a/diff.c +++ b/diff.c @@ -1101,22 +1101,26 @@ static void emit_binary_diff(mmfile_t *one, mmfile_t *two) static void setup_diff_attr_check(struct git_attr_check *check) { static struct git_attr *attr_diff; + static struct git_attr *attr_diff_func_name; if (!attr_diff) { attr_diff = git_attr("diff", 4); + attr_diff_func_name = git_attr("funcname", 8); } check[0].attr = attr_diff; + check[1].attr = attr_diff_func_name; } static void diff_filespec_check_attr(struct diff_filespec *one) { - struct git_attr_check attr_diff_check[1]; + struct git_attr_check attr_diff_check[2]; if (one->checked_attr) return; setup_diff_attr_check(attr_diff_check); one->is_binary = 0; + one->hunk_header_ident = NULL; if (!git_checkattr(one->path, ARRAY_SIZE(attr_diff_check), attr_diff_check)) { const char *value; @@ -1127,6 +1131,13 @@ static void diff_filespec_check_attr(struct diff_filespec *one) ; else if (ATTR_FALSE(value)) one->is_binary = 1; + + /* hunk header ident */ + value = attr_diff_check[1].value; + if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value)) + ; + else + one->hunk_header_ident = value; } if (!one->data && DIFF_FILE_VALID(one)) @@ -1143,6 +1154,82 @@ int diff_filespec_is_binary(struct diff_filespec *one) return one->is_binary; } +static struct hunk_header_regexp { + char *name; + char *regexp; + struct hunk_header_regexp *next; +} *hunk_header_regexp_list, **hunk_header_regexp_tail; + +static int hunk_header_config(const char *var, const char *value) +{ + static const char funcname[] = "funcname."; + struct hunk_header_regexp *hh; + + if (prefixcmp(var, funcname)) + return 0; + var += strlen(funcname); + for (hh = hunk_header_regexp_list; hh; hh = hh->next) + if (!strcmp(var, hh->name)) { + free(hh->regexp); + hh->regexp = xstrdup(value); + return 0; + } + hh = xcalloc(1, sizeof(*hh)); + hh->name = xstrdup(var); + hh->regexp = xstrdup(value); + hh->next = NULL; + *hunk_header_regexp_tail = hh; + return 0; +} + +static const char *hunk_header_regexp(const char *ident) +{ + struct hunk_header_regexp *hh; + + if (!hunk_header_regexp_tail) { + hunk_header_regexp_tail = &hunk_header_regexp_list; + git_config(hunk_header_config); + } + for (hh = hunk_header_regexp_list; hh; hh = hh->next) + if (!strcmp(ident, hh->name)) + return hh->regexp; + return NULL; +} + +static const char *diff_hunk_header_regexp(struct diff_filespec *one) +{ + const char *ident, *regexp; + + diff_filespec_check_attr(one); + ident = one->hunk_header_ident; + + if (!ident) + /* + * If the config file has "funcname.default" defined, that + * regexp is used; otherwise NULL is returned and xemit uses + * the built-in default. + */ + return hunk_header_regexp("default"); + + /* Look up custom "funcname.$ident" regexp from config. */ + regexp = hunk_header_regexp(ident); + if (regexp) + return regexp; + + /* + * And define built-in fallback patterns here. Note that + * these can be overriden by the user's config settings. + */ + if (!strcmp(ident, "java")) + return "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" + "new\\|return\\|switch\\|throw\\|while\\)\n" + "^[ ]*\\(\\([ ]*" + "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" + "[ ]*([^;]*$\\)"; + + return NULL; +} + static void builtin_diff(const char *name_a, const char *name_b, struct diff_filespec *one, @@ -1217,6 +1304,11 @@ static void builtin_diff(const char *name_a, xdemitconf_t xecfg; xdemitcb_t ecb; struct emit_callback ecbdata; + const char *hunk_header_regexp; + + hunk_header_regexp = diff_hunk_header_regexp(one); + if (!hunk_header_regexp) + hunk_header_regexp = diff_hunk_header_regexp(two); memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); @@ -1226,6 +1318,8 @@ static void builtin_diff(const char *name_a, xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; + if (hunk_header_regexp) + xdiff_set_find_func(&xecfg, hunk_header_regexp); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) diff --git a/diffcore.h b/diffcore.h index dcab7e20bf..05985147ea 100644 --- a/diffcore.h +++ b/diffcore.h @@ -27,6 +27,7 @@ struct diff_filespec { char *path; void *data; void *cnt_data; + const void *hunk_header_ident; unsigned long size; int xfrm_flags; /* for use by the xfrm */ unsigned short mode; /* file mode */ diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh new file mode 100644 index 0000000000..dc7a47b3f1 --- /dev/null +++ b/t/t4018-diff-funcname.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# +# Copyright (c) 2007 Johannes E. Schindelin +# + +test_description='Test custom diff function name patterns' + +. ./test-lib.sh + +LF=' +' + +cat > Beer.java << EOF +public class Beer +{ + int special; + public static void main(String args[]) + { + String s=" "; + for(int x = 99; x > 0; x--) + { + System.out.print(x + " bottles of beer on the wall " + + x + " bottles of beer\n" + + "Take one down, pass it around, " + (x - 1) + + " bottles of beer on the wall.\n"); + } + System.out.print("Go to the store, buy some more,\n" + + "99 bottles of beer on the wall.\n"); + } +} +EOF + +sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java + +test_expect_success 'default behaviour' ' + git diff Beer.java Beer-correct.java | + grep "^@@.*@@ public class Beer" +' + +test_expect_success 'preset java pattern' ' + echo "*.java funcname=java" >.gitattributes && + git diff Beer.java Beer-correct.java | + grep "^@@.*@@ public static void main(" +' + +git config funcname.java '!static +!String +[^ ].*s.*' + +test_expect_success 'custom pattern' ' + git diff Beer.java Beer-correct.java | + grep "^@@.*@@ int special;$" +' + +test_expect_success 'last regexp must not be negated' ' + git config diff.functionnameregexp "!static" && + ! git diff Beer.java Beer-correct.java +' + +test_done diff --git a/xdiff-interface.c b/xdiff-interface.c index e407cf11b1..be866d12d3 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -129,3 +129,74 @@ int buffer_is_binary(const char *ptr, unsigned long size) size = FIRST_FEW_BYTES; return !!memchr(ptr, 0, size); } + +struct ff_regs { + int nr; + struct ff_reg { + regex_t re; + int negate; + } *array; +}; + +static long ff_regexp(const char *line, long len, + char *buffer, long buffer_size, void *priv) +{ + char *line_buffer = xstrndup(line, len); /* make NUL terminated */ + struct ff_regs *regs = priv; + regmatch_t pmatch[2]; + int result = 0, i; + + for (i = 0; i < regs->nr; i++) { + struct ff_reg *reg = regs->array + i; + if (reg->negate ^ !!regexec(®->re, + line_buffer, 2, pmatch, 0)) { + free(line_buffer); + return -1; + } + } + i = pmatch[1].rm_so >= 0 ? 1 : 0; + line += pmatch[i].rm_so; + result = pmatch[i].rm_eo - pmatch[i].rm_so; + if (result > buffer_size) + result = buffer_size; + else + while (result > 0 && (isspace(line[result - 1]) || + line[result - 1] == '\n')) + result--; + memcpy(buffer, line, result); + free(line_buffer); + return result; +} + +void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) +{ + int i; + struct ff_regs *regs; + + xecfg->find_func = ff_regexp; + regs = xecfg->find_func_priv = xmalloc(sizeof(struct ff_regs)); + for (i = 0, regs->nr = 1; value[i]; i++) + if (value[i] == '\n') + regs->nr++; + regs->array = xmalloc(regs->nr * sizeof(struct ff_reg)); + for (i = 0; i < regs->nr; i++) { + struct ff_reg *reg = regs->array + i; + const char *ep = strchr(value, '\n'), *expression; + char *buffer = NULL; + + reg->negate = (*value == '!'); + if (reg->negate && i == regs->nr - 1) + die("Last expression must not be negated: %s", value); + if (*value == '!') + value++; + if (ep) + expression = buffer = xstrndup(value, ep - value); + else + expression = value; + if (regcomp(®->re, expression, 0)) + die("Invalid regexp to look for hunk header: %s", expression); + if (buffer) + free(buffer); + value = ep + 1; + } +} diff --git a/xdiff-interface.h b/xdiff-interface.h index 536f4e4d97..fb742dbb6b 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -20,4 +20,6 @@ int parse_hunk_header(char *line, int len, int read_mmfile(mmfile_t *ptr, const char *filename); int buffer_is_binary(const char *ptr, unsigned long size); +extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line); + #endif diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index 9402bb0799..c00ddaa6e9 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -73,9 +73,13 @@ typedef struct s_xdemitcb { int (*outf)(void *, mmbuffer_t *, int); } xdemitcb_t; +typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv); + typedef struct s_xdemitconf { long ctxlen; unsigned long flags; + find_func_t find_func; + void *find_func_priv; } xdemitconf_t; typedef struct s_bdiffparam { diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 4b6e639112..d3d9c845c6 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -69,7 +69,24 @@ static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { } -static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { +static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) +{ + if (len > 0 && + (isalpha((unsigned char)*rec) || /* identifier? */ + *rec == '_' || /* also identifier? */ + *rec == '$')) { /* identifiers from VMS and other esoterico */ + if (len > sz) + len = sz; + while (0 < len && isspace((unsigned char)rec[len - 1])) + len--; + memcpy(buf, rec, len); + return len; + } + return -1; +} + +static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll, + find_func_t ff, void *ff_priv) { /* * Be quite stupid about this for now. Find a line in the old file @@ -80,22 +97,12 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) { const char *rec; long len; - *ll = 0; while (i-- > 0) { len = xdl_get_rec(xf, i, &rec); - if (len > 0 && - (isalpha((unsigned char)*rec) || /* identifier? */ - *rec == '_' || /* also identifier? */ - *rec == '$')) { /* mysterious GNU diff's invention */ - if (len > sz) - len = sz; - while (0 < len && isspace((unsigned char)rec[len - 1])) - len--; - memcpy(buf, rec, len); - *ll = len; + if ((*ll = ff(rec, len, buf, sz, ff_priv)) >= 0) return; - } } + *ll = 0; } @@ -120,6 +127,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdchange_t *xch, *xche; char funcbuf[80]; long funclen = 0; + find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff; if (xecfg->flags & XDL_EMIT_COMMON) return xdl_emit_common(xe, xscr, ecb, xecfg); @@ -143,7 +151,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, if (xecfg->flags & XDL_EMIT_FUNCNAMES) { xdl_find_func(&xe->xdf1, s1, funcbuf, - sizeof(funcbuf), &funclen); + sizeof(funcbuf), &funclen, + ff, xecfg->find_func_priv); } if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, funcbuf, funclen, ecb) < 0) -- cgit v1.3 From e0e324a4dc18a4341e1320a7cfac9733d81f8b0b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 7 Jul 2007 01:49:58 -0700 Subject: Fix configuration syntax to specify customized hunk header patterns. This updates the hunk header customization syntax. The special case 'funcname' attribute is gone. You assign the name of the type of contents to path's "diff" attribute as a string value in .gitattributes like this: *.java diff=java *.perl diff=perl *.doc diff=doc If you supply "diff..funcname" variable via the configuration mechanism (e.g. in $HOME/.gitconfig), the value is used as the regexp set to find the line to use for the hunk header (the variable is called "funcname" because such a line typically is the one that has the name of the function in programming language source text). If there is no such configuration, built-in default is used, if any. Currently there are two default patterns: default and java. Signed-off-by: Junio C Hamano --- diff.c | 147 ++++++++++++++++++++++++++--------------------- diffcore.h | 2 +- t/t4018-diff-funcname.sh | 6 +- 3 files changed, 84 insertions(+), 71 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 04e7e91adf..21e61af265 100644 --- a/diff.c +++ b/diff.c @@ -56,6 +56,14 @@ static struct ll_diff_driver { char *cmd; } *user_diff, **user_diff_tail; +static void read_config_if_needed(void) +{ + if (!user_diff_tail) { + user_diff_tail = &user_diff; + git_config(git_diff_ui_config); + } +} + /* * Currently there is only "diff..command" variable; * because there are "diff.color." variables, we are parsing @@ -93,6 +101,45 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val return 0; } +/* + * 'diff..funcname' attribute can be specified in the configuration + * to define a customized regexp to find the beginning of a function to + * be used for hunk header lines of "diff -p" style output. + */ +static struct funcname_pattern { + char *name; + char *pattern; + struct funcname_pattern *next; +} *funcname_pattern_list; + +static int parse_funcname_pattern(const char *var, const char *ep, const char *value) +{ + const char *name; + int namelen; + struct funcname_pattern *pp; + + name = var + 5; /* "diff." */ + namelen = ep - name; + + for (pp = funcname_pattern_list; pp; pp = pp->next) + if (!strncmp(pp->name, name, namelen) && !pp->name[namelen]) + break; + if (!pp) { + char *namebuf; + pp = xcalloc(1, sizeof(*pp)); + namebuf = xmalloc(namelen + 1); + memcpy(namebuf, name, namelen); + namebuf[namelen] = 0; + pp->name = namebuf; + pp->next = funcname_pattern_list; + funcname_pattern_list = pp; + } + if (pp->pattern) + free(pp->pattern); + pp->pattern = xstrdup(value); + return 0; +} + /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should @@ -122,8 +169,12 @@ int git_diff_ui_config(const char *var, const char *value) if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); - if (ep != var + 4 && !strcmp(ep, ".command")) - return parse_lldiff_command(var, ep, value); + if (ep != var + 4) { + if (!strcmp(ep, ".command")) + return parse_lldiff_command(var, ep, value); + if (!strcmp(ep, ".funcname")) + return parse_funcname_pattern(var, ep, value); + } } if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); @@ -1101,43 +1152,39 @@ static void emit_binary_diff(mmfile_t *one, mmfile_t *two) static void setup_diff_attr_check(struct git_attr_check *check) { static struct git_attr *attr_diff; - static struct git_attr *attr_diff_func_name; if (!attr_diff) { attr_diff = git_attr("diff", 4); - attr_diff_func_name = git_attr("funcname", 8); } check[0].attr = attr_diff; - check[1].attr = attr_diff_func_name; } static void diff_filespec_check_attr(struct diff_filespec *one) { - struct git_attr_check attr_diff_check[2]; + struct git_attr_check attr_diff_check; if (one->checked_attr) return; - setup_diff_attr_check(attr_diff_check); + setup_diff_attr_check(&attr_diff_check); one->is_binary = 0; - one->hunk_header_ident = NULL; + one->funcname_pattern_ident = NULL; - if (!git_checkattr(one->path, ARRAY_SIZE(attr_diff_check), attr_diff_check)) { + if (!git_checkattr(one->path, 1, &attr_diff_check)) { const char *value; /* binaryness */ - value = attr_diff_check[0].value; + value = attr_diff_check.value; if (ATTR_TRUE(value)) ; else if (ATTR_FALSE(value)) one->is_binary = 1; - /* hunk header ident */ - value = attr_diff_check[1].value; + /* funcname pattern ident */ if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value)) ; else - one->hunk_header_ident = value; + one->funcname_pattern_ident = value; } if (!one->data && DIFF_FILE_VALID(one)) @@ -1154,54 +1201,23 @@ int diff_filespec_is_binary(struct diff_filespec *one) return one->is_binary; } -static struct hunk_header_regexp { - char *name; - char *regexp; - struct hunk_header_regexp *next; -} *hunk_header_regexp_list, **hunk_header_regexp_tail; - -static int hunk_header_config(const char *var, const char *value) +static const char *funcname_pattern(const char *ident) { - static const char funcname[] = "funcname."; - struct hunk_header_regexp *hh; + struct funcname_pattern *pp; - if (prefixcmp(var, funcname)) - return 0; - var += strlen(funcname); - for (hh = hunk_header_regexp_list; hh; hh = hh->next) - if (!strcmp(var, hh->name)) { - free(hh->regexp); - hh->regexp = xstrdup(value); - return 0; - } - hh = xcalloc(1, sizeof(*hh)); - hh->name = xstrdup(var); - hh->regexp = xstrdup(value); - hh->next = NULL; - *hunk_header_regexp_tail = hh; - return 0; -} - -static const char *hunk_header_regexp(const char *ident) -{ - struct hunk_header_regexp *hh; - - if (!hunk_header_regexp_tail) { - hunk_header_regexp_tail = &hunk_header_regexp_list; - git_config(hunk_header_config); - } - for (hh = hunk_header_regexp_list; hh; hh = hh->next) - if (!strcmp(ident, hh->name)) - return hh->regexp; + read_config_if_needed(); + for (pp = funcname_pattern_list; pp; pp = pp->next) + if (!strcmp(ident, pp->name)) + return pp->pattern; return NULL; } -static const char *diff_hunk_header_regexp(struct diff_filespec *one) +static const char *diff_funcname_pattern(struct diff_filespec *one) { - const char *ident, *regexp; + const char *ident, *pattern; diff_filespec_check_attr(one); - ident = one->hunk_header_ident; + ident = one->funcname_pattern_ident; if (!ident) /* @@ -1209,12 +1225,12 @@ static const char *diff_hunk_header_regexp(struct diff_filespec *one) * regexp is used; otherwise NULL is returned and xemit uses * the built-in default. */ - return hunk_header_regexp("default"); + return funcname_pattern("default"); /* Look up custom "funcname.$ident" regexp from config. */ - regexp = hunk_header_regexp(ident); - if (regexp) - return regexp; + pattern = funcname_pattern(ident); + if (pattern) + return pattern; /* * And define built-in fallback patterns here. Note that @@ -1304,11 +1320,11 @@ static void builtin_diff(const char *name_a, xdemitconf_t xecfg; xdemitcb_t ecb; struct emit_callback ecbdata; - const char *hunk_header_regexp; + const char *funcname_pattern; - hunk_header_regexp = diff_hunk_header_regexp(one); - if (!hunk_header_regexp) - hunk_header_regexp = diff_hunk_header_regexp(two); + funcname_pattern = diff_funcname_pattern(one); + if (!funcname_pattern) + funcname_pattern = diff_funcname_pattern(two); memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); @@ -1318,8 +1334,8 @@ static void builtin_diff(const char *name_a, xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; - if (hunk_header_regexp) - xdiff_set_find_func(&xecfg, hunk_header_regexp); + if (funcname_pattern) + xdiff_set_find_func(&xecfg, funcname_pattern); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) @@ -1862,10 +1878,7 @@ static const char *external_diff_attr(const char *name) !ATTR_UNSET(value)) { struct ll_diff_driver *drv; - if (!user_diff_tail) { - user_diff_tail = &user_diff; - git_config(git_diff_ui_config); - } + read_config_if_needed(); for (drv = user_diff; drv; drv = drv->next) if (!strcmp(drv->name, value)) return drv->cmd; diff --git a/diffcore.h b/diffcore.h index 05985147ea..eef17c4ca2 100644 --- a/diffcore.h +++ b/diffcore.h @@ -27,7 +27,7 @@ struct diff_filespec { char *path; void *data; void *cnt_data; - const void *hunk_header_ident; + const char *funcname_pattern_ident; unsigned long size; int xfrm_flags; /* for use by the xfrm */ unsigned short mode; /* file mode */ diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index dc7a47b3f1..f9db81d3ab 100644 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -38,12 +38,12 @@ test_expect_success 'default behaviour' ' ' test_expect_success 'preset java pattern' ' - echo "*.java funcname=java" >.gitattributes && + echo "*.java diff=java" >.gitattributes && git diff Beer.java Beer-correct.java | grep "^@@.*@@ public static void main(" ' -git config funcname.java '!static +git config diff.java.funcname '!static !String [^ ].*s.*' @@ -53,7 +53,7 @@ test_expect_success 'custom pattern' ' ' test_expect_success 'last regexp must not be negated' ' - git config diff.functionnameregexp "!static" && + git config diff.java.funcname "!static" && ! git diff Beer.java Beer-correct.java ' -- cgit v1.3 From 2c3fa66f3577d1305fb0fac5a181261fb2597859 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 7 Jul 2007 12:25:11 -0700 Subject: diff: honor binariness specified in attributes The code shuffling mistakenly lost binariness specified with the attribute mecahnism and made it always guess from the data. Noticed by Johannes, with two test cases to t4020. Signed-off-by: Junio C Hamano --- diff.c | 14 +++++++++----- t/t4020-diff-external.sh | 12 ++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 21e61af265..b8473f58fb 100644 --- a/diff.c +++ b/diff.c @@ -1162,6 +1162,7 @@ static void setup_diff_attr_check(struct git_attr_check *check) static void diff_filespec_check_attr(struct diff_filespec *one) { struct git_attr_check attr_diff_check; + int check_from_data = 0; if (one->checked_attr) return; @@ -1179,6 +1180,8 @@ static void diff_filespec_check_attr(struct diff_filespec *one) ; else if (ATTR_FALSE(value)) one->is_binary = 1; + else + check_from_data = 1; /* funcname pattern ident */ if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value)) @@ -1187,12 +1190,13 @@ static void diff_filespec_check_attr(struct diff_filespec *one) one->funcname_pattern_ident = value; } - if (!one->data && DIFF_FILE_VALID(one)) - diff_populate_filespec(one, 0); - - if (one->data) - one->is_binary = buffer_is_binary(one->data, one->size); + if (check_from_data) { + if (!one->data && DIFF_FILE_VALID(one)) + diff_populate_filespec(one, 0); + if (one->data) + one->is_binary = buffer_is_binary(one->data, one->size); + } } int diff_filespec_is_binary(struct diff_filespec *one) diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index f0045cd788..ed3bd5b3fe 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -94,4 +94,16 @@ test_expect_success 'diff attribute should apply only to diff' ' ' +test_expect_success 'no diff with -diff' ' + echo >.gitattributes "file -diff" && + git diff | grep Binary +' + +echo NULZbetweenZwords | tr Z '\0' > file + +test_expect_success 'force diff with "diff"' ' + echo >.gitattributes "file diff" && + git diff | grep -a second +' + test_done -- cgit v1.3 From d3a93dc96786847f9d148da42ecadee5f027c9a7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 8 Jul 2007 00:25:59 -0700 Subject: diff.c: make built-in hunk header pattern a separate table This would hopefully make it easier to maintain. Initially we would have "java" and "tex" defined, as they are the only ones we already have. Signed-off-by: Junio C Hamano --- diff.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index b8473f58fb..cd6b0c4e0b 100644 --- a/diff.c +++ b/diff.c @@ -1216,9 +1216,22 @@ static const char *funcname_pattern(const char *ident) return NULL; } +static struct builtin_funcname_pattern { + const char *name; + const char *pattern; +} builtin_funcname_pattern[] = { + { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" + "new\\|return\\|switch\\|throw\\|while\\)\n" + "^[ ]*\\(\\([ ]*" + "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" + "[ ]*([^;]*$\\)" }, + { "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" }, +}; + static const char *diff_funcname_pattern(struct diff_filespec *one) { const char *ident, *pattern; + int i; diff_filespec_check_attr(one); ident = one->funcname_pattern_ident; @@ -1240,12 +1253,9 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) * And define built-in fallback patterns here. Note that * these can be overriden by the user's config settings. */ - if (!strcmp(ident, "java")) - return "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" - "new\\|return\\|switch\\|throw\\|while\\)\n" - "^[ ]*\\(\\([ ]*" - "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" - "[ ]*([^;]*$\\)"; + for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++) + if (!strcmp(ident, builtin_funcname_pattern[i].name)) + return builtin_funcname_pattern[i].pattern; return NULL; } -- cgit v1.3 From e7a7be8831b159b9a7331b34c3ec6915d4a72190 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 25 Jul 2007 21:34:53 -0700 Subject: git_mkstemp(): be careful not to overflow the path buffer. If user's TMPDIR is insanely long, return negative after setting errno to ENAMETOOLONG, pretending that the underlying mkstemp() choked on a temporary file path that is too long. Signed-off-by: Junio C Hamano --- diff.c | 2 +- path.c | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index cd6b0c4e0b..a5fc56bdad 100644 --- a/diff.c +++ b/diff.c @@ -1695,7 +1695,7 @@ static void prep_temp_blob(struct diff_tempfile *temp, fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX"); if (fd < 0) - die("unable to create temp-file"); + die("unable to create temp-file: %s", strerror(errno)); if (write_in_full(fd, blob, size) != size) die("unable to write temp-file"); close(fd); diff --git a/path.c b/path.c index c4ce96236a..dfff41f626 100644 --- a/path.c +++ b/path.c @@ -71,21 +71,17 @@ char *git_path(const char *fmt, ...) /* git_mkstemp() - create tmp file honoring TMPDIR variable */ int git_mkstemp(char *path, size_t len, const char *template) { - char *env, *pch = path; - - if ((env = getenv("TMPDIR")) == NULL) { - strcpy(pch, "/tmp/"); - len -= 5; - pch += 5; - } else { - size_t n = snprintf(pch, len, "%s/", env); - - len -= n; - pch += n; + const char *tmp; + size_t n; + + tmp = getenv("TMPDIR"); + if (!tmp) + tmp = "/tmp"; + n = snprintf(path, len, "%s/%s", tmp, template); + if (len <= n) { + errno = ENAMETOOLONG; + return -1; } - - strlcpy(pch, template, len); - return mkstemp(path); } -- cgit v1.3 From fb13227e089f22dc31a3b1624559153821056848 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 3 Aug 2007 13:33:31 -0700 Subject: git-diff: squelch "empty" diffs After starting to edit a working tree file but later when your edit ends up identical to the original (this can also happen when you ran a wholesale regexp replace with something like "perl -i" that does not actually modify many of the paths), "git diff" between the index and the working tree outputs many "empty" diffs that show "diff --git" headers and nothing else, because these paths are stat-dirty. While it was a way to warn the user that the earlier action of the user made the index ineffective as an optimization mechanism, it was felt too loud for the purpose of warning even to experienced users, and also resulted in confusing people new to git. This replaces the "empty" diffs with a single warning message at the end. Having many such paths hurts performance, and you can run "git-update-index --refresh" to update the lstat(2) information recorded in the index in such a case. "git-status" does so as a side effect, and that is more familiar to the end-user, so we recommend it to them. The change affects only "git diff" that outputs patch text, because that is where the annoyance of too many "empty" diff is most strongly felt, and because the warning message can be safely ignored by downstream tools without getting mistaken as part of the patch. For the low-level "git diff-files" and "git diff-index", the traditional behaviour is retained. Signed-off-by: Junio C Hamano --- builtin-diff.c | 8 ++++++++ diff.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ diff.h | 1 + 3 files changed, 61 insertions(+) (limited to 'diff.c') diff --git a/builtin-diff.c b/builtin-diff.c index 8dc17b0dd7..6ed7b6842e 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -222,6 +222,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) prefix = setup_git_directory_gently(&nongit); git_config(git_diff_ui_config); init_revisions(&rev, prefix); + rev.diffopt.skip_stat_unmatch = 1; if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix)) argc = 0; @@ -344,5 +345,12 @@ int cmd_diff(int argc, const char **argv, const char *prefix) ent, ents); if (rev.diffopt.exit_with_status) result = rev.diffopt.has_changes; + + if ((rev.diffopt.output_format & DIFF_FORMAT_PATCH) + && (1 < rev.diffopt.skip_stat_unmatch)) + printf("Warning: %d path%s touched but unmodified. " + "Consider running git-status.\n", + rev.diffopt.skip_stat_unmatch - 1, + rev.diffopt.skip_stat_unmatch == 2 ? "" : "s"); return result; } diff --git a/diff.c b/diff.c index a5fc56bdad..f884de77ac 100644 --- a/diff.c +++ b/diff.c @@ -3143,11 +3143,63 @@ static void diffcore_apply_filter(const char *filter) *q = outq; } +static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) +{ + int i; + struct diff_queue_struct *q = &diff_queued_diff; + struct diff_queue_struct outq; + outq.queue = NULL; + outq.nr = outq.alloc = 0; + + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + + /* + * 1. Entries that come from stat info dirtyness + * always have both sides (iow, not create/delete), + * one side of the object name is unknown, with + * the same mode and size. Keep the ones that + * do not match these criteria. They have real + * differences. + * + * 2. At this point, the file is known to be modified, + * with the same mode and size, and the object + * name of one side is unknown. Need to inspect + * the identical contents. + */ + if (!DIFF_FILE_VALID(p->one) || /* (1) */ + !DIFF_FILE_VALID(p->two) || + (p->one->sha1_valid && p->two->sha1_valid) || + (p->one->mode != p->two->mode) || + diff_populate_filespec(p->one, 1) || + diff_populate_filespec(p->two, 1) || + (p->one->size != p->two->size) || + + diff_populate_filespec(p->one, 0) || /* (2) */ + diff_populate_filespec(p->two, 0) || + memcmp(p->one->data, p->two->data, p->one->size)) + diff_q(&outq, p); + else { + /* + * The caller can subtract 1 from skip_stat_unmatch + * to determine how many paths were dirty only + * due to stat info mismatch. + */ + diffopt->skip_stat_unmatch++; + diff_free_filepair(p); + } + } + free(q->queue); + *q = outq; +} + void diffcore_std(struct diff_options *options) { if (options->quiet) return; + if (options->skip_stat_unmatch && !options->find_copies_harder) + diffcore_skip_stat_unmatch(options); if (options->break_opt != -1) diffcore_break(options->break_opt); if (options->detect_rename) diff --git a/diff.h b/diff.h index 9fd6d447d4..de21f8ecd0 100644 --- a/diff.h +++ b/diff.h @@ -65,6 +65,7 @@ struct diff_options { int context; int break_opt; int detect_rename; + int skip_stat_unmatch; int line_termination; int output_format; int pickaxe_opts; -- cgit v1.3 From 6d2d9e8666ef72c8878af4822e243ca33b6752a0 Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Wed, 15 Aug 2007 00:41:00 +0200 Subject: diff: squelch empty diffs even more When we compare two non-tracked files, or explicitly specify --no-index, the suggestion to run git-status is not helpful. The patch adds a new diff_options bitfield member, no_index, that is used instead of the special value of -2 of the rev_info field max_count to indicate that the index is not to be used. This makes it possible to pass that flag down to diffcore_skip_stat_unmatch(), which only has one diff_options parameter. This could even become a cleanup if we removed all assignments of max_count to a value of -2 (viz. replacement of a magic value with a self-documenting field name) but I didn't dare to do that so late in the rc game.. The no_index bit, if set, then tells diffcore_skip_stat_unmatch() to not account for any skipped stat-mismatches, which avoids the suggestion to run git-status. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- diff-lib.c | 8 ++++++-- diff.c | 3 ++- diff.h | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff-lib.c b/diff-lib.c index 92c0e39ad6..f5568c3b36 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -189,6 +189,7 @@ static int handle_diff_files_args(struct rev_info *revs, !strcmp(argv[1], "--no-index")) { revs->max_count = -2; revs->diffopt.exit_with_status = 1; + revs->diffopt.no_index = 1; } else if (!strcmp(argv[1], "-q")) *silent = 1; @@ -204,8 +205,10 @@ static int handle_diff_files_args(struct rev_info *revs, */ read_cache(); if (!is_in_index(revs->diffopt.paths[0]) || - !is_in_index(revs->diffopt.paths[1])) + !is_in_index(revs->diffopt.paths[1])) { revs->max_count = -2; + revs->diffopt.no_index = 1; + } } /* @@ -293,6 +296,7 @@ int setup_diff_no_index(struct rev_info *revs, else revs->diffopt.paths = argv + argc - 2; revs->diffopt.nr_paths = 2; + revs->diffopt.no_index = 1; revs->max_count = -2; return 0; } @@ -304,7 +308,7 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) if (handle_diff_files_args(revs, argc, argv, &silent_on_removed)) return -1; - if (revs->max_count == -2) { + if (revs->diffopt.no_index) { if (revs->diffopt.nr_paths != 2) return error("need two files/directories with --no-index"); if (queue_diff(&revs->diffopt, revs->diffopt.paths[0], diff --git a/diff.c b/diff.c index f884de77ac..97cc5bc085 100644 --- a/diff.c +++ b/diff.c @@ -3185,7 +3185,8 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) * to determine how many paths were dirty only * due to stat info mismatch. */ - diffopt->skip_stat_unmatch++; + if (!diffopt->no_index) + diffopt->skip_stat_unmatch++; diff_free_filepair(p); } } diff --git a/diff.h b/diff.h index de21f8ecd0..4546aad219 100644 --- a/diff.h +++ b/diff.h @@ -60,6 +60,7 @@ struct diff_options { color_diff_words:1, has_changes:1, quiet:1, + no_index:1, allow_external:1, exit_with_status:1; int context; -- cgit v1.3 From 2f82f760e1b2630073a05c44fe70bdce9706d9e5 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 18 Aug 2007 15:52:55 -0700 Subject: Take binary diffs into account for "git rebase" We used to not generate a patch ID for binary diffs, but that means that some commits may be skipped as being identical to already-applied diffs when doing a rebase. So just delete the code that skips the binary diff. At the very least, we'd want the filenames to be part of the patch ID, but we might also want to generate some hash for the binary diff itself too. This fixes an issue noticed by Torgil Svensson. Tested-by: Torgil Svensson Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 97cc5bc085..a7e76719d1 100644 --- a/diff.c +++ b/diff.c @@ -2919,10 +2919,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) fill_mmfile(&mf2, p->two) < 0) return error("unable to read files to diff"); - /* Maybe hash p->two? into the patch id? */ - if (diff_filespec_is_binary(p->two)) - continue; - len1 = remove_space(p->one->path, strlen(p->one->path)); len2 = remove_space(p->two->path, strlen(p->two->path)); if (p->one->mode == 0) -- cgit v1.3 From aecbf914c43ab76e055fa8a25b12456ae74d91bc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 31 Aug 2007 13:13:42 -0700 Subject: git-diff: resurrect the traditional empty "diff --git" behaviour The warning message to suggest "Consider running git-status" from "git-diff" that we experimented with during the 1.5.3 cycle turns out to be a bad idea. It robbed cache-dirty information from people who valued it, while still asking users to run "update-index --refresh". It was hoped that the new behaviour would at least have some educational value, but not showing the cache-dirty paths like before meant that the user would not even know easily which paths were cache-dirty, and it made the need to refresh the index look like even more unnecessary chore. This commit reinstates the traditional behaviour, but with a twist. By default, the empty "diff --git" output is totally squelched out from "git diff" output. At the end of the command, it automatically runs "update-index --refresh" as needed, without even bothering the user. In other words, people who do not care about the cache-dirtyness do not even have to see the warning. The traditional behaviour to see the stat-dirty output and to bypassing the overhead of content comparison can be specified by setting the configuration variable diff.autorefreshindex to false. Signed-off-by: Junio C Hamano --- Documentation/config.txt | 10 ++++++++++ builtin-diff.c | 34 +++++++++++++++++++++++++++------- cache.h | 3 +++ diff.c | 5 +++++ 4 files changed, 45 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 903610fecf..cf7617a5b1 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -396,6 +396,16 @@ color.status.:: commit.template:: Specify a file to use as the template for new commit messages. +diff.autorefreshindex:: + When using `git diff` to compare with work tree + files, do not consider stat-only change as changed. + Instead, silently run `git update-index --refresh` to + update the cached stat information for paths whose + contents in the work tree match the contents in the + index. This option defaults to true. Note that this + affects only `git diff` Porcelain, and not lower level + `diff` commands, such as `git diff-files`. + diff.renameLimit:: The number of files to consider when performing the copy/rename detection; equivalent to the git diff option '-l'. diff --git a/builtin-diff.c b/builtin-diff.c index 6ed7b6842e..f77352b40d 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -188,6 +188,30 @@ void add_head(struct rev_info *revs) add_pending_object(revs, obj, "HEAD"); } +static void refresh_index_quietly(void) +{ + struct lock_file *lock_file; + int fd; + + lock_file = xcalloc(1, sizeof(struct lock_file)); + fd = hold_locked_index(lock_file, 0); + if (fd < 0) + return; + discard_cache(); + read_cache(); + refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED); + if (active_cache_changed) { + if (write_cache(fd, active_cache, active_nr) || + close(fd) || + commit_locked_index(lock_file)) + ; /* + * silently ignore it -- we haven't mucked + * with the real index. + */ + } + rollback_lock_file(lock_file); +} + int cmd_diff(int argc, const char **argv, const char *prefix) { int i; @@ -222,7 +246,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) prefix = setup_git_directory_gently(&nongit); git_config(git_diff_ui_config); init_revisions(&rev, prefix); - rev.diffopt.skip_stat_unmatch = 1; + rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix)) argc = 0; @@ -346,11 +370,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) if (rev.diffopt.exit_with_status) result = rev.diffopt.has_changes; - if ((rev.diffopt.output_format & DIFF_FORMAT_PATCH) - && (1 < rev.diffopt.skip_stat_unmatch)) - printf("Warning: %d path%s touched but unmodified. " - "Consider running git-status.\n", - rev.diffopt.skip_stat_unmatch - 1, - rev.diffopt.skip_stat_unmatch == 2 ? "" : "s"); + if (1 < rev.diffopt.skip_stat_unmatch) + refresh_index_quietly(); return result; } diff --git a/cache.h b/cache.h index c7e00e7b05..70abbd59bf 100644 --- a/cache.h +++ b/cache.h @@ -594,6 +594,9 @@ extern char *convert_to_git(const char *path, const char *src, unsigned long *si extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep); extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size); +/* diff.c */ +extern int diff_auto_refresh_index; + /* match-trees.c */ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); diff --git a/diff.c b/diff.c index a7e76719d1..0d30d05263 100644 --- a/diff.c +++ b/diff.c @@ -19,6 +19,7 @@ static int diff_detect_rename_default; static int diff_rename_limit_default = -1; static int diff_use_color_default; +int diff_auto_refresh_index = 1; static char diff_colors[][COLOR_MAXLEN] = { "\033[m", /* reset */ @@ -166,6 +167,10 @@ int git_diff_ui_config(const char *var, const char *value) diff_detect_rename_default = DIFF_DETECT_RENAME; return 0; } + if (!strcmp(var, "diff.autorefreshindex")) { + diff_auto_refresh_index = git_config_bool(var, value); + return 0; + } if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); -- cgit v1.3 From af6eb82262e35687aa8f00d688e327cb845973fa Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 6 Sep 2007 13:20:09 +0200 Subject: Use strbuf API in apply, blame, commit-tree and diff Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-apply.c | 30 ++++++++------------------ builtin-blame.c | 35 +++++++++++------------------- builtin-commit-tree.c | 60 ++++++++++++--------------------------------------- diff.c | 27 ++++++++--------------- 4 files changed, 44 insertions(+), 108 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 976ec77041..90e328ef91 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -12,6 +12,7 @@ #include "blob.h" #include "delta.h" #include "builtin.h" +#include "strbuf.h" /* * --check turns on checking that the working tree matches the @@ -181,34 +182,21 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c static void *read_patch_file(int fd, unsigned long *sizep) { - unsigned long size = 0, alloc = CHUNKSIZE; - void *buffer = xmalloc(alloc); + struct strbuf buf; - for (;;) { - ssize_t nr = alloc - size; - if (nr < 1024) { - alloc += CHUNKSIZE; - buffer = xrealloc(buffer, alloc); - nr = alloc - size; - } - nr = xread(fd, (char *) buffer + size, nr); - if (!nr) - break; - if (nr < 0) - die("git-apply: read returned %s", strerror(errno)); - size += nr; - } - *sizep = size; + strbuf_init(&buf); + if (strbuf_read(&buf, fd) < 0) + die("git-apply: read returned %s", strerror(errno)); + *sizep = buf.len; /* * Make sure that we have some slop in the buffer * so that we can do speculative "memcmp" etc, and * see to it that it is NUL-filled. */ - if (alloc < size + SLOP) - buffer = xrealloc(buffer, size + SLOP); - memset((char *) buffer + size, 0, SLOP); - return buffer; + strbuf_grow(&buf, SLOP); + memset(buf.buf + buf.len, 0, SLOP); + return strbuf_detach(&buf); } static unsigned long linelen(const char *buffer, unsigned long size) diff --git a/builtin-blame.c b/builtin-blame.c index dc88a953a5..1b1e6da853 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -18,6 +18,7 @@ #include "cache-tree.h" #include "path-list.h" #include "mailmap.h" +#include "strbuf.h" static char blame_usage[] = "git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S ] [-M] [-C] [-C] [--contents ] [--incremental] [commit] [--] file\n" @@ -2001,11 +2002,10 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con struct commit *commit; struct origin *origin; unsigned char head_sha1[20]; - char *buf; + struct strbuf buf; const char *ident; int fd; time_t now; - unsigned long fin_size; int size, len; struct cache_entry *ce; unsigned mode; @@ -2023,9 +2023,11 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con origin = make_origin(commit, path); + strbuf_init(&buf); if (!contents_from || strcmp("-", contents_from)) { struct stat st; const char *read_from; + unsigned long fin_size; if (contents_from) { if (stat(contents_from, &st) < 0) @@ -2038,19 +2040,19 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con read_from = path; } fin_size = xsize_t(st.st_size); - buf = xmalloc(fin_size+1); mode = canon_mode(st.st_mode); switch (st.st_mode & S_IFMT) { case S_IFREG: fd = open(read_from, O_RDONLY); if (fd < 0) die("cannot open %s", read_from); - if (read_in_full(fd, buf, fin_size) != fin_size) + if (strbuf_read(&buf, fd) != xsize_t(st.st_size)) die("cannot read %s", read_from); break; case S_IFLNK: - if (readlink(read_from, buf, fin_size+1) != fin_size) + if (readlink(read_from, buf.buf, buf.alloc) != fin_size) die("cannot readlink %s", read_from); + buf.len = fin_size; break; default: die("unsupported file type %s", read_from); @@ -2059,26 +2061,13 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con else { /* Reading from stdin */ contents_from = "standard input"; - buf = NULL; - fin_size = 0; mode = 0; - while (1) { - ssize_t cnt = 8192; - buf = xrealloc(buf, fin_size + cnt); - cnt = xread(0, buf + fin_size, cnt); - if (cnt < 0) - die("read error %s from stdin", - strerror(errno)); - if (!cnt) - break; - fin_size += cnt; - } - buf = xrealloc(buf, fin_size + 1); + if (strbuf_read(&buf, 0) < 0) + die("read error %s from stdin", strerror(errno)); } - buf[fin_size] = 0; - origin->file.ptr = buf; - origin->file.size = fin_size; - pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1); + origin->file.ptr = buf.buf; + origin->file.size = buf.len; + pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1); commit->util = origin; /* diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index ccbcbe30da..bc9502c135 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -8,42 +8,13 @@ #include "tree.h" #include "builtin.h" #include "utf8.h" +#include "strbuf.h" #define BLOCKING (1ul << 14) /* * FIXME! Share the code with "write-tree.c" */ -static void init_buffer(char **bufp, unsigned int *sizep) -{ - *bufp = xmalloc(BLOCKING); - *sizep = 0; -} - -static void add_buffer(char **bufp, unsigned int *sizep, const char *fmt, ...) -{ - char one_line[2048]; - va_list args; - int len; - unsigned long alloc, size, newsize; - char *buf; - - va_start(args, fmt); - len = vsnprintf(one_line, sizeof(one_line), fmt, args); - va_end(args); - size = *sizep; - newsize = size + len + 1; - alloc = (size + 32767) & ~32767; - buf = *bufp; - if (newsize > alloc) { - alloc = (newsize + 32767) & ~32767; - buf = xrealloc(buf, alloc); - *bufp = buf; - } - *sizep = newsize - 1; - memcpy(buf + size, one_line, len); -} - static void check_valid(unsigned char *sha1, enum object_type expect) { enum object_type type = sha1_object_info(sha1, NULL); @@ -87,9 +58,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) int parents = 0; unsigned char tree_sha1[20]; unsigned char commit_sha1[20]; - char comment[1000]; - char *buffer; - unsigned int size; + struct strbuf buffer; int encoding_is_utf8; git_config(git_default_config); @@ -118,8 +87,9 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) /* Not having i18n.commitencoding is the same as having utf-8 */ encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); - init_buffer(&buffer, &size); - add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1)); + strbuf_init(&buffer); + strbuf_grow(&buffer, 8192); /* should avoid reallocs for the headers */ + strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree_sha1)); /* * NOTE! This ordering means that the same exact tree merged with a @@ -127,26 +97,24 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) * if everything else stays the same. */ for (i = 0; i < parents; i++) - add_buffer(&buffer, &size, "parent %s\n", sha1_to_hex(parent_sha1[i])); + strbuf_addf(&buffer, "parent %s\n", sha1_to_hex(parent_sha1[i])); /* Person/date information */ - add_buffer(&buffer, &size, "author %s\n", git_author_info(1)); - add_buffer(&buffer, &size, "committer %s\n", git_committer_info(1)); + strbuf_addf(&buffer, "author %s\n", git_author_info(1)); + strbuf_addf(&buffer, "committer %s\n", git_committer_info(1)); if (!encoding_is_utf8) - add_buffer(&buffer, &size, - "encoding %s\n", git_commit_encoding); - add_buffer(&buffer, &size, "\n"); + strbuf_addf(&buffer, "encoding %s\n", git_commit_encoding); + strbuf_addch(&buffer, '\n'); /* And add the comment */ - while (fgets(comment, sizeof(comment), stdin) != NULL) - add_buffer(&buffer, &size, "%s", comment); + if (strbuf_read(&buffer, 0) < 0) + die("git-commit-tree: read returned %s", strerror(errno)); /* And check the encoding */ - buffer[size] = '\0'; - if (encoding_is_utf8 && !is_utf8(buffer)) + if (encoding_is_utf8 && !is_utf8(buffer.buf)) fprintf(stderr, commit_utf8_warn); - if (!write_sha1_file(buffer, size, commit_type, commit_sha1)) { + if (!write_sha1_file(buffer.buf, buffer.len, commit_type, commit_sha1)) { printf("%s\n", sha1_to_hex(commit_sha1)); return 0; } diff --git a/diff.c b/diff.c index 0d30d05263..c054b234b8 100644 --- a/diff.c +++ b/diff.c @@ -9,6 +9,7 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" +#include "strbuf.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1545,26 +1546,16 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int static int populate_from_stdin(struct diff_filespec *s) { -#define INCREMENT 1024 - char *buf; - unsigned long size; - ssize_t got; - - size = 0; - buf = NULL; - while (1) { - buf = xrealloc(buf, size + INCREMENT); - got = xread(0, buf + size, INCREMENT); - if (!got) - break; /* EOF */ - if (got < 0) - return error("error while reading from stdin %s", + struct strbuf buf; + + strbuf_init(&buf); + if (strbuf_read(&buf, 0) < 0) + return error("error while reading from stdin %s", strerror(errno)); - size += got; - } + s->should_munmap = 0; - s->data = buf; - s->size = size; + s->size = buf.len; + s->data = strbuf_detach(&buf); s->should_free = 1; return 0; } -- cgit v1.3 From 5701115aa7cfe7edd57c2483085456a37e27a5ba Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Sat, 8 Sep 2007 12:30:22 +0200 Subject: git-diff: don't squelch the new SHA1 in submodule diffs The code to squelch empty diffs introduced by commit fb13227e089f22dc31a3b1624559153821056848 would inadvertently populate filespec "two" of a submodule change using the uninitialized (null) SHA1, thereby replacing the submodule SHA1 by 0{40} in the output. This change teaches diffcore_skip_stat_unmatch to handle submodule changes correctly. Signed-off-by: Sven Verdoolaege Signed-off-by: Junio C Hamano --- diff.c | 21 +++++++++++++++++---- t/t7400-submodule-basic.sh | 4 ++++ 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 0d30d05263..1aca5df522 100644 --- a/diff.c +++ b/diff.c @@ -3144,6 +3144,22 @@ static void diffcore_apply_filter(const char *filter) *q = outq; } +/* Check whether two filespecs with the same mode and size are identical */ +static int diff_filespec_is_identical(struct diff_filespec *one, + struct diff_filespec *two) +{ + if (S_ISGITLINK(one->mode)) { + diff_fill_sha1_info(one); + diff_fill_sha1_info(two); + return !hashcmp(one->sha1, two->sha1); + } + if (diff_populate_filespec(one, 0)) + return 0; + if (diff_populate_filespec(two, 0)) + return 0; + return !memcmp(one->data, two->data, one->size); +} + static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) { int i; @@ -3175,10 +3191,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) diff_populate_filespec(p->one, 1) || diff_populate_filespec(p->two, 1) || (p->one->size != p->two->size) || - - diff_populate_filespec(p->one, 0) || /* (2) */ - diff_populate_filespec(p->two, 0) || - memcmp(p->one->data, p->two->data, p->one->size)) + !diff_filespec_is_identical(p->one, p->two)) /* (2) */ diff_q(&outq, p); else { /* diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 9d142ed649..4fe3a41f07 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -152,6 +152,10 @@ test_expect_success 'the --cached sha1 should be rev1' ' git-submodule --cached status | grep "^+$rev1" ' +test_expect_success 'git diff should report the SHA1 of the new submodule commit' ' + git-diff | grep "^+Subproject commit $rev2" +' + test_expect_success 'update should checkout rev1' ' git-submodule update && head=$(cd lib && git rev-parse HEAD) && -- cgit v1.3 From f1696ee398e92bcea3cdc7b3da85d8e0f77f6c50 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 10 Sep 2007 12:35:04 +0200 Subject: Strbuf API extensions and fixes. * Add strbuf_rtrim to remove trailing spaces. * Add strbuf_insert to insert data at a given position. * Off-by one fix in strbuf_addf: strbuf_avail() does not counts the final \0 so the overflow test for snprintf is the strict comparison. This is not critical as the growth mechanism chosen will always allocate _more_ memory than asked, so the second test will not fail. It's some kind of miracle though. * Add size extension hints for strbuf_init and strbuf_read. If 0, default applies, else: + initial buffer has the given size for strbuf_init. + first growth checks it has at least this size rather than the default 8192. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- archive-tar.c | 4 ++-- builtin-apply.c | 4 ++-- builtin-blame.c | 6 +++--- builtin-checkout-index.c | 2 +- builtin-commit-tree.c | 5 ++--- builtin-rerere.c | 4 ++-- builtin-update-index.c | 4 ++-- cache-tree.c | 5 ++--- diff.c | 4 ++-- fast-import.c | 4 ++-- fetch.c | 2 +- mktree.c | 5 ++--- strbuf.c | 33 +++++++++++++++++++++++++++------ strbuf.h | 10 ++++++++-- 14 files changed, 58 insertions(+), 34 deletions(-) (limited to 'diff.c') diff --git a/archive-tar.c b/archive-tar.c index 0612bb6051..cc94cf3672 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -132,7 +132,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, struct strbuf ext_header; memset(&header, 0, sizeof(header)); - strbuf_init(&ext_header); + strbuf_init(&ext_header, 0); if (!sha1) { *header.typeflag = TYPEFLAG_GLOBAL_HEADER; @@ -214,7 +214,7 @@ static void write_global_extended_header(const unsigned char *sha1) { struct strbuf ext_header; - strbuf_init(&ext_header); + strbuf_init(&ext_header, 0); strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40); write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len); strbuf_release(&ext_header); diff --git a/builtin-apply.c b/builtin-apply.c index 90e328ef91..988e85f1e5 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -184,8 +184,8 @@ static void *read_patch_file(int fd, unsigned long *sizep) { struct strbuf buf; - strbuf_init(&buf); - if (strbuf_read(&buf, fd) < 0) + strbuf_init(&buf, 0); + if (strbuf_read(&buf, fd, 0) < 0) die("git-apply: read returned %s", strerror(errno)); *sizep = buf.len; diff --git a/builtin-blame.c b/builtin-blame.c index 1b1e6da853..b004f06cd8 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2023,7 +2023,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con origin = make_origin(commit, path); - strbuf_init(&buf); + strbuf_init(&buf, 0); if (!contents_from || strcmp("-", contents_from)) { struct stat st; const char *read_from; @@ -2046,7 +2046,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con fd = open(read_from, O_RDONLY); if (fd < 0) die("cannot open %s", read_from); - if (strbuf_read(&buf, fd) != xsize_t(st.st_size)) + if (strbuf_read(&buf, fd, 0) != xsize_t(st.st_size)) die("cannot read %s", read_from); break; case S_IFLNK: @@ -2062,7 +2062,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con /* Reading from stdin */ contents_from = "standard input"; mode = 0; - if (strbuf_read(&buf, 0) < 0) + if (strbuf_read(&buf, 0, 0) < 0) die("read error %s from stdin", strerror(errno)); } origin->file.ptr = buf.buf; diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 75377b9cab..153ba7dc12 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -274,7 +274,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) struct strbuf buf; if (all) die("git-checkout-index: don't mix '--all' and '--stdin'"); - strbuf_init(&buf); + strbuf_init(&buf, 0); while (1) { char *path_name; const char *p; diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index bc9502c135..325334fd65 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -87,8 +87,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) /* Not having i18n.commitencoding is the same as having utf-8 */ encoding_is_utf8 = is_encoding_utf8(git_commit_encoding); - strbuf_init(&buffer); - strbuf_grow(&buffer, 8192); /* should avoid reallocs for the headers */ + strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */ strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree_sha1)); /* @@ -107,7 +106,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) strbuf_addch(&buffer, '\n'); /* And add the comment */ - if (strbuf_read(&buffer, 0) < 0) + if (strbuf_read(&buffer, 0, 0) < 0) die("git-commit-tree: read returned %s", strerror(errno)); /* And check the encoding */ diff --git a/builtin-rerere.c b/builtin-rerere.c index 98d7702168..826d346fbc 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -78,8 +78,8 @@ static int handle_file(const char *path, FILE *f = fopen(path, "r"); FILE *out; - strbuf_init(&minus); - strbuf_init(&plus); + strbuf_init(&minus, 0); + strbuf_init(&plus, 0); if (!f) return error("Could not open %s", path); diff --git a/builtin-update-index.c b/builtin-update-index.c index a7a4574f2b..9240a288a7 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -303,7 +303,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length) static void read_index_info(int line_termination) { struct strbuf buf; - strbuf_init(&buf); + strbuf_init(&buf, 0); while (1) { char *ptr, *tab; char *path_name; @@ -716,7 +716,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) } if (read_from_stdin) { struct strbuf buf; - strbuf_init(&buf); + strbuf_init(&buf, 0); while (1) { char *path_name; const char *p; diff --git a/cache-tree.c b/cache-tree.c index 76af6f5d99..8f53c99f15 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -293,8 +293,7 @@ static int update_one(struct cache_tree *it, /* * Then write out the tree object for this level. */ - strbuf_init(&buffer); - strbuf_grow(&buffer, 8192); + strbuf_init(&buffer, 8192); for (i = 0; i < entries; i++) { struct cache_entry *ce = cache[i]; @@ -419,7 +418,7 @@ void *cache_tree_write(struct cache_tree *root, unsigned long *size_p) struct strbuf buffer; path[0] = 0; - strbuf_init(&buffer); + strbuf_init(&buffer, 0); write_one(root, path, 0, &buffer); *size_p = buffer.len; return strbuf_detach(&buffer); diff --git a/diff.c b/diff.c index 26d7bb96bc..7290309ea9 100644 --- a/diff.c +++ b/diff.c @@ -1548,8 +1548,8 @@ static int populate_from_stdin(struct diff_filespec *s) { struct strbuf buf; - strbuf_init(&buf); - if (strbuf_read(&buf, 0) < 0) + strbuf_init(&buf, 0); + if (strbuf_read(&buf, 0, 0) < 0) return error("error while reading from stdin %s", strerror(errno)); diff --git a/fast-import.c b/fast-import.c index 74ff0fdadd..2c0bfb9fab 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1640,7 +1640,7 @@ static void *cmd_data (size_t *size) { struct strbuf buffer; - strbuf_init(&buffer); + strbuf_init(&buffer, 0); if (prefixcmp(command_buf.buf, "data ")) die("Expected 'data n' command, found: %s", command_buf.buf); @@ -2318,7 +2318,7 @@ int main(int argc, const char **argv) git_config(git_default_config); alloc_objects(object_entry_alloc); - strbuf_init(&command_buf); + strbuf_init(&command_buf, 0); atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*)); branch_table = xcalloc(branch_table_sz, sizeof(struct branch*)); avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); diff --git a/fetch.c b/fetch.c index 811be87a3c..dd6ed9e41c 100644 --- a/fetch.c +++ b/fetch.c @@ -218,7 +218,7 @@ int pull_targets_stdin(char ***target, const char ***write_ref) int targets = 0, targets_alloc = 0; struct strbuf buf; *target = NULL; *write_ref = NULL; - strbuf_init(&buf); + strbuf_init(&buf, 0); while (1) { char *rf_one = NULL; char *tg_one; diff --git a/mktree.c b/mktree.c index 2e84889c02..3891cd9fb3 100644 --- a/mktree.c +++ b/mktree.c @@ -51,9 +51,8 @@ static void write_tree(unsigned char *sha1) qsort(entries, used, sizeof(*entries), ent_compare); for (size = i = 0; i < used; i++) size += 32 + entries[i]->len; - strbuf_init(&buf); - strbuf_grow(&buf, size); + strbuf_init(&buf, size); for (i = 0; i < used; i++) { struct treeent *ent = entries[i]; strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0'); @@ -83,7 +82,7 @@ int main(int ac, char **av) av++; } - strbuf_init(&sb); + strbuf_init(&sb, 0); while (1) { char *ptr, *ntr; unsigned mode; diff --git a/strbuf.c b/strbuf.c index 7136de14c6..d9190477e6 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,8 +1,10 @@ #include "cache.h" #include "strbuf.h" -void strbuf_init(struct strbuf *sb) { +void strbuf_init(struct strbuf *sb, size_t hint) { memset(sb, 0, sizeof(*sb)); + if (hint) + strbuf_grow(sb, hint); } void strbuf_release(struct strbuf *sb) { @@ -18,7 +20,7 @@ void strbuf_reset(struct strbuf *sb) { char *strbuf_detach(struct strbuf *sb) { char *res = sb->buf; - strbuf_init(sb); + strbuf_init(sb, 0); return res; } @@ -28,6 +30,24 @@ void strbuf_grow(struct strbuf *sb, size_t extra) { ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } +void strbuf_rtrim(struct strbuf *sb) +{ + while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1])) + sb->len--; + sb->buf[sb->len] = '\0'; +} + +void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len) { + strbuf_grow(sb, len); + if (pos >= sb->len) { + pos = sb->len; + } else { + memmove(sb->buf + pos + len, sb->buf + pos, sb->len - pos); + } + memcpy(sb->buf + pos, data, len); + strbuf_setlen(sb, sb->len + len); +} + void strbuf_add(struct strbuf *sb, const void *data, size_t len) { strbuf_grow(sb, len); memcpy(sb->buf + sb->len, data, len); @@ -44,12 +64,12 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) { if (len < 0) { len = 0; } - if (len >= strbuf_avail(sb)) { + if (len > strbuf_avail(sb)) { strbuf_grow(sb, len); va_start(ap, fmt); len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); va_end(ap); - if (len >= strbuf_avail(sb)) { + if (len > strbuf_avail(sb)) { die("this should not happen, your snprintf is broken"); } } @@ -67,14 +87,14 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) { return res; } -ssize_t strbuf_read(struct strbuf *sb, int fd) +ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) { size_t oldlen = sb->len; + strbuf_grow(sb, hint ? hint : 8192); for (;;) { ssize_t cnt; - strbuf_grow(sb, 8192); cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); if (cnt < 0) { strbuf_setlen(sb, oldlen); @@ -83,6 +103,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd) if (!cnt) break; sb->len += cnt; + strbuf_grow(sb, 8192); } sb->buf[sb->len] = '\0'; diff --git a/strbuf.h b/strbuf.h index b40dc99fd0..21fc111f9d 100644 --- a/strbuf.h +++ b/strbuf.h @@ -51,7 +51,7 @@ struct strbuf { #define STRBUF_INIT { 0, 0, 0, NULL } /*----- strbuf life cycle -----*/ -extern void strbuf_init(struct strbuf *); +extern void strbuf_init(struct strbuf *, size_t); extern void strbuf_release(struct strbuf *); extern void strbuf_reset(struct strbuf *); extern char *strbuf_detach(struct strbuf *); @@ -68,6 +68,9 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { extern void strbuf_grow(struct strbuf *, size_t); +/*----- content related -----*/ +extern void strbuf_rtrim(struct strbuf *); + /*----- add data in your buffer -----*/ static inline void strbuf_addch(struct strbuf *sb, int c) { strbuf_grow(sb, 1); @@ -75,6 +78,9 @@ static inline void strbuf_addch(struct strbuf *sb, int c) { sb->buf[sb->len] = '\0'; } +/* inserts after pos, or appends if pos >= sb->len */ +extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t); + extern void strbuf_add(struct strbuf *, const void *, size_t); static inline void strbuf_addstr(struct strbuf *sb, const char *s) { strbuf_add(sb, s, strlen(s)); @@ -88,7 +94,7 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); /* XXX: if read fails, any partial read is undone */ -extern ssize_t strbuf_read(struct strbuf *, int fd); +extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); extern void read_line(struct strbuf *, FILE *, int); -- cgit v1.3 From 0024a54923a12f8c05ce4290f5ebefab0cce4336 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 14 Sep 2007 10:39:48 -0700 Subject: Fix the rename detection limit checking This adds more proper rename detection limits. Instead of just checking the limit against the number of potential rename destinations, we verify that the rename matrix (which is what really matters) doesn't grow ridiculously large, and we also make sure that we don't overflow when doing the matrix size calculation. This also changes the default limits from unlimited, to a rename matrix that is limited to 100 entries on a side. You can raise it with the config entry, or by using the "-l" command line flag, but at least the default is now a sane number that avoids spending lots of time (and memory) in situations that likely don't merit it. The choice of default value is of course very debatable. Limiting the rename matrix to a 100x100 size will mean that even if you have just one obvious rename, but you also create (or delete) 10,000 files, the rename matrix will be so big that we disable the heuristics. Sounds reasonable to me, but let's see if people hit this (and, perhaps more importantly, actually *care*) in real life. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 2 +- diffcore-rename.c | 19 +++++++++++++++++-- wt-status.c | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 1aca5df522..0ee9ea1c1b 100644 --- a/diff.c +++ b/diff.c @@ -17,7 +17,7 @@ #endif static int diff_detect_rename_default; -static int diff_rename_limit_default = -1; +static int diff_rename_limit_default = 100; static int diff_use_color_default; int diff_auto_refresh_index = 1; diff --git a/diffcore-rename.c b/diffcore-rename.c index 6bde4396f2..41b35c3a9e 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -298,10 +298,25 @@ void diffcore_rename(struct diff_options *options) else if (detect_rename == DIFF_DETECT_COPY) register_rename_src(p->one, 1, p->score); } - if (rename_dst_nr == 0 || rename_src_nr == 0 || - (0 < rename_limit && rename_limit < rename_dst_nr)) + if (rename_dst_nr == 0 || rename_src_nr == 0) goto cleanup; /* nothing to do */ + /* + * This basically does a test for the rename matrix not + * growing larger than a "rename_limit" square matrix, ie: + * + * rename_dst_nr * rename_src_nr > rename_limit * rename_limit + * + * but handles the potential overflow case specially (and we + * assume at least 32-bit integers) + */ + if (rename_limit <= 0 || rename_limit > 32767) + rename_limit = 32767; + if (rename_dst_nr > rename_limit && rename_src_nr > rename_limit) + goto cleanup; + if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit) + goto cleanup; + /* We really want to cull the candidates list early * with cheap tests in order to avoid doing deltas. * The first round matches up the up-to-date entries, diff --git a/wt-status.c b/wt-status.c index 52054201c2..10ce6eedc7 100644 --- a/wt-status.c +++ b/wt-status.c @@ -227,6 +227,7 @@ static void wt_status_print_updated(struct wt_status *s) rev.diffopt.format_callback = wt_status_print_updated_cb; rev.diffopt.format_callback_data = s; rev.diffopt.detect_rename = 1; + rev.diffopt.rename_limit = 100; wt_read_cache(s); run_diff_index(&rev, 1); } -- cgit v1.3 From 5ecd293d1420bf641a927a015877950f4d79c067 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 16 Sep 2007 15:51:04 +0200 Subject: Rewrite convert_to_{git,working_tree} to use strbuf's. * Now, those functions take an "out" strbuf argument, where they store their result if any. In that case, it also returns 1, else it returns 0. * those functions support "in place" editing, in the sense that it's OK to call them this way: convert_to_git(path, sb->buf, sb->len, sb); When doable, conversions are done in place for real, else the strbuf content is just replaced with the new one, transparentely for the caller. If you want to create a new filter working this way, being the accumulation of filter1, filter2, ... filtern, then your meta_filter would be: int meta_filter(..., const char *src, size_t len, struct strbuf *sb) { int ret = 0; ret |= filter1(...., src, len, sb); if (ret) { src = sb->buf; len = sb->len; } ret |= filter2(...., src, len, sb); if (ret) { src = sb->buf; len = sb->len; } .... return ret | filtern(..., src, len, sb); } That's why subfilters the convert_to_* functions called were also rewritten to work this way. Signed-off-by: Pierre Habouzit Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-apply.c | 27 ++-- builtin-archive.c | 78 +++++----- cache.h | 6 +- convert.c | 414 ++++++++++++++++++++++-------------------------------- diff.c | 12 +- entry.c | 10 +- sha1_file.c | 10 +- 7 files changed, 240 insertions(+), 317 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 988e85f1e5..e5c29ebf35 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1446,8 +1446,7 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign { int fd; unsigned long got; - unsigned long nsize; - char *nbuf; + struct strbuf nbuf; unsigned long size = *size_p; char *buf = *buf_p; @@ -1466,13 +1465,12 @@ static int read_old_data(struct stat *st, const char *path, char **buf_p, unsign got += ret; } close(fd); - nsize = got; - nbuf = convert_to_git(path, buf, &nsize); - if (nbuf) { + strbuf_init(&nbuf, 0); + if (convert_to_git(path, buf, size, &nbuf)) { free(buf); - *buf_p = nbuf; - *alloc_p = nsize; - *size_p = nsize; + *buf_p = nbuf.buf; + *alloc_p = nbuf.alloc; + *size_p = nbuf.len; } return got != size; default: @@ -2439,7 +2437,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { int fd; - char *nbuf; + struct strbuf nbuf; if (S_ISGITLINK(mode)) { struct stat st; @@ -2458,9 +2456,11 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, if (fd < 0) return -1; - nbuf = convert_to_working_tree(path, buf, &size); - if (nbuf) - buf = nbuf; + strbuf_init(&nbuf, 0); + if (convert_to_working_tree(path, buf, size, &nbuf)) { + size = nbuf.len; + buf = nbuf.buf; + } while (size) { int written = xwrite(fd, buf, size); @@ -2473,8 +2473,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, } if (close(fd) < 0) die("closing file %s: %s", path, strerror(errno)); - if (nbuf) - free(nbuf); + strbuf_release(&nbuf); return 0; } diff --git a/builtin-archive.c b/builtin-archive.c index 6fa424d386..843a9e37bb 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -81,22 +81,21 @@ static int run_remote_archiver(const char *remote, int argc, return !!rv; } -static void *format_subst(const struct commit *commit, const char *format, - unsigned long *sizep) +static void format_subst(const struct commit *commit, + const char *src, size_t len, + struct strbuf *buf) { - unsigned long len = *sizep; - const char *a = format; - struct strbuf result; + char *to_free = NULL; struct strbuf fmt; - strbuf_init(&result, 0); + if (src == buf->buf) + to_free = strbuf_detach(buf); strbuf_init(&fmt, 0); - for (;;) { const char *b, *c; - b = memmem(a, len, "$Format:", 8); - if (!b || a + len < b + 9) + b = memmem(src, len, "$Format:", 8); + if (!b || src + len < b + 9) break; c = memchr(b + 8, '$', len - 8); if (!c) @@ -105,62 +104,57 @@ static void *format_subst(const struct commit *commit, const char *format, strbuf_reset(&fmt); strbuf_add(&fmt, b + 8, c - b - 8); - strbuf_add(&result, a, b - a); - format_commit_message(commit, fmt.buf, &result); - len -= c + 1 - a; - a = c + 1; + strbuf_add(buf, src, b - src); + format_commit_message(commit, fmt.buf, buf); + len -= c + 1 - src; + src = c + 1; } - - strbuf_add(&result, a, len); - - *sizep = result.len; - + strbuf_add(buf, src, len); strbuf_release(&fmt); - return strbuf_detach(&result); + free(to_free); } -static void *convert_to_archive(const char *path, - const void *src, unsigned long *sizep, - const struct commit *commit) +static int convert_to_archive(const char *path, + const void *src, size_t len, + struct strbuf *buf, + const struct commit *commit) { static struct git_attr *attr_export_subst; struct git_attr_check check[1]; if (!commit) - return NULL; + return 0; - if (!attr_export_subst) - attr_export_subst = git_attr("export-subst", 12); + if (!attr_export_subst) + attr_export_subst = git_attr("export-subst", 12); check[0].attr = attr_export_subst; if (git_checkattr(path, ARRAY_SIZE(check), check)) - return NULL; + return 0; if (!ATTR_TRUE(check[0].value)) - return NULL; + return 0; - return format_subst(commit, src, sizep); + format_subst(commit, src, len, buf); + return 1; } void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, - unsigned long *size, + unsigned long *sizep, const struct commit *commit) { - void *buffer, *converted; + void *buffer; - buffer = read_sha1_file(sha1, type, size); + buffer = read_sha1_file(sha1, type, sizep); if (buffer && S_ISREG(mode)) { - converted = convert_to_working_tree(path, buffer, size); - if (converted) { - free(buffer); - buffer = converted; - } - - converted = convert_to_archive(path, buffer, size, commit); - if (converted) { - free(buffer); - buffer = converted; - } + struct strbuf buf; + + strbuf_init(&buf, 0); + strbuf_attach(&buf, buffer, *sizep, *sizep + 1); + convert_to_working_tree(path, buf.buf, buf.len, &buf); + convert_to_archive(path, buf.buf, buf.len, &buf, commit); + *sizep = buf.len; + buffer = buf.buf; } return buffer; diff --git a/cache.h b/cache.h index 231f81d8e3..37eb57eaba 100644 --- a/cache.h +++ b/cache.h @@ -2,6 +2,7 @@ #define CACHE_H #include "git-compat-util.h" +#include "strbuf.h" #include SHA1_HEADER #include @@ -589,8 +590,9 @@ extern void trace_printf(const char *format, ...); extern void trace_argv_printf(const char **argv, int count, const char *format, ...); /* convert.c */ -extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep); -extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep); +/* returns 1 if *dst was used */ +extern int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst); +extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst); /* diff.c */ extern int diff_auto_refresh_index; diff --git a/convert.c b/convert.c index d77c8eb8b2..00a341c595 100644 --- a/convert.c +++ b/convert.c @@ -1,6 +1,7 @@ #include "cache.h" #include "attr.h" #include "run-command.h" +#include "strbuf.h" /* * convert.c - convert a file when checking it out and checking it in. @@ -80,24 +81,19 @@ static int is_binary(unsigned long size, struct text_stat *stats) return 0; } -static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep, int action) +static int crlf_to_git(const char *path, const char *src, size_t len, + struct strbuf *buf, int action) { - char *buffer, *dst; - unsigned long size, nsize; struct text_stat stats; + char *dst; - if ((action == CRLF_BINARY) || !auto_crlf) - return NULL; - - size = *sizep; - if (!size) - return NULL; - - gather_stats(src, size, &stats); + if ((action == CRLF_BINARY) || !auto_crlf || !len) + return 0; + gather_stats(src, len, &stats); /* No CR? Nothing to convert, regardless. */ if (!stats.cr) - return NULL; + return 0; if (action == CRLF_GUESS) { /* @@ -106,24 +102,17 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep * stuff? */ if (stats.cr != stats.crlf) - return NULL; + return 0; /* * And add some heuristics for binary vs text, of course... */ - if (is_binary(size, &stats)) - return NULL; + if (is_binary(len, &stats)) + return 0; } - /* - * Ok, allocate a new buffer, fill it in, and return it - * to let the caller know that we switched buffers. - */ - nsize = size - stats.crlf; - buffer = xmalloc(nsize); - *sizep = nsize; - - dst = buffer; + strbuf_grow(buf, len); + dst = buf->buf; if (action == CRLF_GUESS) { /* * If we guessed, we already know we rejected a file with @@ -134,71 +123,72 @@ static char *crlf_to_git(const char *path, const char *src, unsigned long *sizep unsigned char c = *src++; if (c != '\r') *dst++ = c; - } while (--size); + } while (--len); } else { do { unsigned char c = *src++; - if (! (c == '\r' && (1 < size && *src == '\n'))) + if (! (c == '\r' && (1 < len && *src == '\n'))) *dst++ = c; - } while (--size); + } while (--len); } - - return buffer; + strbuf_setlen(buf, dst - buf->buf); + return 1; } -static char *crlf_to_worktree(const char *path, const char *src, unsigned long *sizep, int action) +static int crlf_to_worktree(const char *path, const char *src, size_t len, + struct strbuf *buf, int action) { - char *buffer, *dst; - unsigned long size, nsize; + char *to_free = NULL; struct text_stat stats; - unsigned char last; if ((action == CRLF_BINARY) || (action == CRLF_INPUT) || auto_crlf <= 0) - return NULL; + return 0; - size = *sizep; - if (!size) - return NULL; + if (!len) + return 0; - gather_stats(src, size, &stats); + gather_stats(src, len, &stats); /* No LF? Nothing to convert, regardless. */ if (!stats.lf) - return NULL; + return 0; /* Was it already in CRLF format? */ if (stats.lf == stats.crlf) - return NULL; + return 0; if (action == CRLF_GUESS) { /* If we have any bare CR characters, we're not going to touch it */ if (stats.cr != stats.crlf) - return NULL; + return 0; - if (is_binary(size, &stats)) - return NULL; + if (is_binary(len, &stats)) + return 0; } - /* - * Ok, allocate a new buffer, fill it in, and return it - * to let the caller know that we switched buffers. - */ - nsize = size + stats.lf - stats.crlf; - buffer = xmalloc(nsize); - *sizep = nsize; - last = 0; - - dst = buffer; - do { - unsigned char c = *src++; - if (c == '\n' && last != '\r') - *dst++ = '\r'; - *dst++ = c; - last = c; - } while (--size); - - return buffer; + /* are we "faking" in place editing ? */ + if (src == buf->buf) + to_free = strbuf_detach(buf); + + strbuf_grow(buf, len + stats.lf - stats.crlf); + for (;;) { + const char *nl = memchr(src, '\n', len); + if (!nl) + break; + if (nl > src && nl[-1] == '\r') { + strbuf_add(buf, src, nl + 1 - src); + } else { + strbuf_add(buf, src, nl - src); + strbuf_addstr(buf, "\r\n"); + } + len -= nl + 1 - src; + src = nl + 1; + } + strbuf_add(buf, src, len); + + free(to_free); + return 1; } static int filter_buffer(const char *path, const char *src, @@ -246,8 +236,8 @@ static int filter_buffer(const char *path, const char *src, return (write_err || status); } -static char *apply_filter(const char *path, const char *src, - unsigned long *sizep, const char *cmd) +static int apply_filter(const char *path, const char *src, size_t len, + struct strbuf *dst, const char *cmd) { /* * Create a pipeline to have the command filter the buffer's @@ -255,21 +245,19 @@ static char *apply_filter(const char *path, const char *src, * * (child --> cmd) --> us */ - const int SLOP = 4096; int pipe_feed[2]; - int status; - char *dst; - unsigned long dstsize, dstalloc; + int status, ret = 1; struct child_process child_process; + struct strbuf nbuf; if (!cmd) - return NULL; + return 0; memset(&child_process, 0, sizeof(child_process)); if (pipe(pipe_feed) < 0) { error("cannot create pipe to run external filter %s", cmd); - return NULL; + return 0; } fflush(NULL); @@ -278,54 +266,37 @@ static char *apply_filter(const char *path, const char *src, error("cannot fork to run external filter %s", cmd); close(pipe_feed[0]); close(pipe_feed[1]); - return NULL; + return 0; } if (!child_process.pid) { dup2(pipe_feed[1], 1); close(pipe_feed[0]); close(pipe_feed[1]); - exit(filter_buffer(path, src, *sizep, cmd)); + exit(filter_buffer(path, src, len, cmd)); } close(pipe_feed[1]); - dstalloc = *sizep; - dst = xmalloc(dstalloc); - dstsize = 0; - - while (1) { - ssize_t numread = xread(pipe_feed[0], dst + dstsize, - dstalloc - dstsize); - - if (numread <= 0) { - if (!numread) - break; - error("read from external filter %s failed", cmd); - free(dst); - dst = NULL; - break; - } - dstsize += numread; - if (dstalloc <= dstsize + SLOP) { - dstalloc = dstsize + SLOP; - dst = xrealloc(dst, dstalloc); - } + strbuf_init(&nbuf, 0); + if (strbuf_read(&nbuf, pipe_feed[0], len) < 0) { + error("read from external filter %s failed", cmd); + ret = 0; } if (close(pipe_feed[0])) { - error("read from external filter %s failed", cmd); - free(dst); - dst = NULL; + ret = error("read from external filter %s failed", cmd); + ret = 0; } - status = finish_command(&child_process); if (status) { - error("external filter %s failed %d", cmd, -status); - free(dst); - dst = NULL; + ret = error("external filter %s failed %d", cmd, -status); + ret = 0; } - if (dst) - *sizep = dstsize; - return dst; + if (ret) { + *dst = nbuf; + } else { + strbuf_release(&nbuf); + } + return ret; } static struct convert_driver { @@ -449,137 +420,104 @@ static int count_ident(const char *cp, unsigned long size) return cnt; } -static char *ident_to_git(const char *path, const char *src, unsigned long *sizep, int ident) +static int ident_to_git(const char *path, const char *src, size_t len, + struct strbuf *buf, int ident) { - int cnt; - unsigned long size; - char *dst, *buf; + char *dst, *dollar; - if (!ident) - return NULL; - size = *sizep; - cnt = count_ident(src, size); - if (!cnt) - return NULL; - buf = xmalloc(size); - - for (dst = buf; size; size--) { - char ch = *src++; - *dst++ = ch; - if ((ch == '$') && (3 <= size) && - !memcmp("Id:", src, 3)) { - unsigned long rem = size - 3; - const char *cp = src + 3; - do { - ch = *cp++; - if (ch == '$') - break; - rem--; - } while (rem); - if (!rem) - continue; + if (!ident || !count_ident(src, len)) + return 0; + + strbuf_grow(buf, len); + dst = buf->buf; + for (;;) { + dollar = memchr(src, '$', len); + if (!dollar) + break; + memcpy(dst, src, dollar + 1 - src); + dst += dollar + 1 - src; + len -= dollar + 1 - src; + src = dollar + 1; + + if (len > 3 && !memcmp(src, "Id:", 3)) { + dollar = memchr(src + 3, '$', len - 3); + if (!dollar) + break; memcpy(dst, "Id$", 3); dst += 3; - size -= (cp - src); - src = cp; + len -= dollar + 1 - src; + src = dollar + 1; } } - - *sizep = dst - buf; - return buf; + memcpy(dst, src, len); + strbuf_setlen(buf, dst + len - buf->buf); + return 1; } -static char *ident_to_worktree(const char *path, const char *src, unsigned long *sizep, int ident) +static int ident_to_worktree(const char *path, const char *src, size_t len, + struct strbuf *buf, int ident) { - int cnt; - unsigned long size; - char *dst, *buf; unsigned char sha1[20]; + char *to_free = NULL, *dollar; + int cnt; if (!ident) - return NULL; + return 0; - size = *sizep; - cnt = count_ident(src, size); + cnt = count_ident(src, len); if (!cnt) - return NULL; + return 0; - hash_sha1_file(src, size, "blob", sha1); - buf = xmalloc(size + cnt * 43); - - for (dst = buf; size; size--) { - const char *cp; - /* Fetch next source character, move the pointer on */ - char ch = *src++; - /* Copy the current character to the destination */ - *dst++ = ch; - /* If the current character is "$" or there are less than three - * remaining bytes or the two bytes following this one are not - * "Id", then simply read the next character */ - if ((ch != '$') || (size < 3) || memcmp("Id", src, 2)) - continue; - /* - * Here when - * - There are more than 2 bytes remaining - * - The current three bytes are "$Id" - * with - * - ch == "$" - * - src[0] == "I" - */ + /* are we "faking" in place editing ? */ + if (src == buf->buf) + to_free = strbuf_detach(buf); + hash_sha1_file(src, len, "blob", sha1); - /* - * It's possible that an expanded Id has crept its way into the - * repository, we cope with that by stripping the expansion out - */ - if (src[2] == ':') { - /* Expanded keywords have "$Id:" at the front */ + strbuf_grow(buf, len + cnt * 43); + for (;;) { + /* step 1: run to the next '$' */ + dollar = memchr(src, '$', len); + if (!dollar) + break; + strbuf_add(buf, src, dollar + 1 - src); + len -= dollar + 1 - src; + src = dollar + 1; - /* discard up to but not including the closing $ */ - unsigned long rem = size - 3; - /* Point at first byte after the ":" */ - cp = src + 3; - /* - * Throw away characters until either - * - we reach a "$" - * - we run out of bytes (rem == 0) - */ - do { - ch = *cp; - if (ch == '$') - break; - cp++; - rem--; - } while (rem); - /* If the above finished because it ran out of characters, then - * this is an incomplete keyword, so don't run the expansion */ - if (!rem) - continue; - } else if (src[2] == '$') - cp = src + 2; - else - /* Anything other than "$Id:XXX$" or $Id$ and we skip the - * expansion */ + /* step 2: does it looks like a bit like Id:xxx$ or Id$ ? */ + if (len < 3 || memcmp("Id", src, 2)) continue; - /* cp is now pointing at the last $ of the keyword */ - - memcpy(dst, "Id: ", 4); - dst += 4; - memcpy(dst, sha1_to_hex(sha1), 40); - dst += 40; - *dst++ = ' '; + /* step 3: skip over Id$ or Id:xxxxx$ */ + if (src[2] == '$') { + src += 3; + len -= 3; + } else if (src[2] == ':') { + /* + * It's possible that an expanded Id has crept its way into the + * repository, we cope with that by stripping the expansion out + */ + dollar = memchr(src + 3, '$', len - 3); + if (!dollar) { + /* incomplete keyword, no more '$', so just quit the loop */ + break; + } - /* Adjust for the characters we've discarded */ - size -= (cp - src); - src = cp; + len -= dollar + 1 - src; + src = dollar + 1; + } else { + /* it wasn't a "Id$" or "Id:xxxx$" */ + continue; + } - /* Copy the final "$" */ - *dst++ = *src++; - size--; + /* step 4: substitute */ + strbuf_addstr(buf, "Id: "); + strbuf_add(buf, sha1_to_hex(sha1), 40); + strbuf_addstr(buf, " $"); } + strbuf_add(buf, src, len); - *sizep = dst - buf; - return buf; + free(to_free); + return 1; } static int git_path_check_crlf(const char *path, struct git_attr_check *check) @@ -618,13 +556,12 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check) return !!ATTR_TRUE(value); } -char *convert_to_git(const char *path, const char *src, unsigned long *sizep) +int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst) { struct git_attr_check check[3]; int crlf = CRLF_GUESS; - int ident = 0; + int ident = 0, ret = 0; char *filter = NULL; - char *buf, *buf2; setup_convert_check(check); if (!git_checkattr(path, ARRAY_SIZE(check), check)) { @@ -636,30 +573,25 @@ char *convert_to_git(const char *path, const char *src, unsigned long *sizep) filter = drv->clean; } - buf = apply_filter(path, src, sizep, filter); - - buf2 = crlf_to_git(path, buf ? buf : src, sizep, crlf); - if (buf2) { - free(buf); - buf = buf2; + ret |= apply_filter(path, src, len, dst, filter); + if (ret) { + src = dst->buf; + len = dst->len; } - - buf2 = ident_to_git(path, buf ? buf : src, sizep, ident); - if (buf2) { - free(buf); - buf = buf2; + ret |= crlf_to_git(path, src, len, dst, crlf); + if (ret) { + src = dst->buf; + len = dst->len; } - - return buf; + return ret | ident_to_git(path, src, len, dst, ident); } -char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep) +int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst) { struct git_attr_check check[3]; int crlf = CRLF_GUESS; - int ident = 0; + int ident = 0, ret = 0; char *filter = NULL; - char *buf, *buf2; setup_convert_check(check); if (!git_checkattr(path, ARRAY_SIZE(check), check)) { @@ -671,19 +603,15 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long * filter = drv->smudge; } - buf = ident_to_worktree(path, src, sizep, ident); - - buf2 = crlf_to_worktree(path, buf ? buf : src, sizep, crlf); - if (buf2) { - free(buf); - buf = buf2; + ret |= ident_to_worktree(path, src, len, dst, ident); + if (ret) { + src = dst->buf; + len = dst->len; } - - buf2 = apply_filter(path, buf ? buf : src, sizep, filter); - if (buf2) { - free(buf); - buf = buf2; + ret |= crlf_to_worktree(path, src, len, dst, crlf); + if (ret) { + src = dst->buf; + len = dst->len; } - - return buf; + return ret | apply_filter(path, src, len, dst, filter); } diff --git a/diff.c b/diff.c index 7290309ea9..f41bcd94ab 100644 --- a/diff.c +++ b/diff.c @@ -1600,10 +1600,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (!s->sha1_valid || reuse_worktree_file(s->path, s->sha1, 0)) { + struct strbuf buf; struct stat st; int fd; - char *buf; - unsigned long size; if (!strcmp(s->path, "-")) return populate_from_stdin(s); @@ -1644,13 +1643,12 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) /* * Convert from working tree format to canonical git format */ - size = s->size; - buf = convert_to_git(s->path, s->data, &size); - if (buf) { + strbuf_init(&buf, 0); + if (convert_to_git(s->path, s->data, s->size, &buf)) { munmap(s->data, s->size); s->should_munmap = 0; - s->data = buf; - s->size = size; + s->data = buf.buf; + s->size = buf.len; s->should_free = 1; } } diff --git a/entry.c b/entry.c index fc3a506ece..4a8c73bfae 100644 --- a/entry.c +++ b/entry.c @@ -104,7 +104,8 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout long wrote; switch (ntohl(ce->ce_mode) & S_IFMT) { - char *buf, *new; + char *new; + struct strbuf buf; unsigned long size; case S_IFREG: @@ -116,10 +117,11 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout /* * Convert from git internal format to working tree format */ - buf = convert_to_working_tree(ce->name, new, &size); - if (buf) { + strbuf_init(&buf, 0); + if (convert_to_working_tree(ce->name, new, size, &buf)) { free(new); - new = buf; + new = buf.buf; + size = buf.len; } if (to_tempfile) { diff --git a/sha1_file.c b/sha1_file.c index aea10961fd..64b5b46698 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2343,12 +2343,12 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, * Convert blobs to git internal format */ if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) { - unsigned long nsize = size; - char *nbuf = convert_to_git(path, buf, &nsize); - if (nbuf) { + struct strbuf nbuf; + strbuf_init(&nbuf, 0); + if (convert_to_git(path, buf, size, &nbuf)) { munmap(buf, size); - size = nsize; - buf = nbuf; + size = nbuf.len; + buf = nbuf.buf; re_allocated = 1; } } -- cgit v1.3 From ba3ed09728cb25e004d3b732de14fca8aeb602f6 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 15 Sep 2007 15:56:50 +0200 Subject: Now that cache.h needs strbuf.h, remove useless includes. Signed-off-by: Pierre Habouzit Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- archive-tar.c | 1 - builtin-apply.c | 1 - builtin-blame.c | 1 - builtin-checkout-index.c | 1 - builtin-commit-tree.c | 1 - builtin-fetch--tool.c | 1 - builtin-rerere.c | 1 - builtin-stripspace.c | 1 - builtin-tag.c | 1 - builtin-update-index.c | 1 - cache-tree.c | 1 - convert.c | 1 - diff.c | 1 - fast-import.c | 1 - fetch.c | 1 - imap-send.c | 1 - mktag.c | 1 - mktree.c | 1 - sha1_file.c | 1 - strbuf.c | 1 - 20 files changed, 20 deletions(-) (limited to 'diff.c') diff --git a/archive-tar.c b/archive-tar.c index cc94cf3672..a87bc4b83e 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -3,7 +3,6 @@ */ #include "cache.h" #include "commit.h" -#include "strbuf.h" #include "tar.h" #include "builtin.h" #include "archive.h" diff --git a/builtin-apply.c b/builtin-apply.c index e5c29ebf35..1256716aec 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -12,7 +12,6 @@ #include "blob.h" #include "delta.h" #include "builtin.h" -#include "strbuf.h" /* * --check turns on checking that the working tree matches the diff --git a/builtin-blame.c b/builtin-blame.c index b004f06cd8..e364b6c6c0 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -18,7 +18,6 @@ #include "cache-tree.h" #include "path-list.h" #include "mailmap.h" -#include "strbuf.h" static char blame_usage[] = "git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S ] [-M] [-C] [-C] [--contents ] [--incremental] [commit] [--] file\n" diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 153ba7dc12..85e8efe22f 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -38,7 +38,6 @@ */ #include "builtin.h" #include "cache.h" -#include "strbuf.h" #include "quote.h" #include "cache-tree.h" diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 325334fd65..88b0ab36eb 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -8,7 +8,6 @@ #include "tree.h" #include "builtin.h" #include "utf8.h" -#include "strbuf.h" #define BLOCKING (1ul << 14) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 90bdc32d13..514a3cc018 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -2,7 +2,6 @@ #include "cache.h" #include "refs.h" #include "commit.h" -#include "strbuf.h" static char *get_stdin(void) { diff --git a/builtin-rerere.c b/builtin-rerere.c index 826d346fbc..58288f61a3 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -1,7 +1,6 @@ #include "builtin.h" #include "cache.h" #include "path-list.h" -#include "strbuf.h" #include "xdiff/xdiff.h" #include "xdiff-interface.h" diff --git a/builtin-stripspace.c b/builtin-stripspace.c index c4cf2f05ca..1ce284710c 100644 --- a/builtin-stripspace.c +++ b/builtin-stripspace.c @@ -1,6 +1,5 @@ #include "builtin.h" #include "cache.h" -#include "strbuf.h" /* * Returns the length of a line, without trailing spaces. diff --git a/builtin-tag.c b/builtin-tag.c index 9f293421da..82ebda11b0 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -8,7 +8,6 @@ #include "cache.h" #include "builtin.h" -#include "strbuf.h" #include "refs.h" #include "tag.h" #include "run-command.h" diff --git a/builtin-update-index.c b/builtin-update-index.c index 9240a288a7..1091f1b26f 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -4,7 +4,6 @@ * Copyright (C) Linus Torvalds, 2005 */ #include "cache.h" -#include "strbuf.h" #include "quote.h" #include "cache-tree.h" #include "tree-walk.h" diff --git a/cache-tree.c b/cache-tree.c index 8f53c99f15..5471844af6 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -1,5 +1,4 @@ #include "cache.h" -#include "strbuf.h" #include "tree.h" #include "cache-tree.h" diff --git a/convert.c b/convert.c index 00a341c595..508d30b2f1 100644 --- a/convert.c +++ b/convert.c @@ -1,7 +1,6 @@ #include "cache.h" #include "attr.h" #include "run-command.h" -#include "strbuf.h" /* * convert.c - convert a file when checking it out and checking it in. diff --git a/diff.c b/diff.c index f41bcd94ab..56b672c4f0 100644 --- a/diff.c +++ b/diff.c @@ -9,7 +9,6 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" -#include "strbuf.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 diff --git a/fast-import.c b/fast-import.c index 2c0bfb9fab..1866d346bf 100644 --- a/fast-import.c +++ b/fast-import.c @@ -149,7 +149,6 @@ Format of STDIN stream: #include "pack.h" #include "refs.h" #include "csum-file.h" -#include "strbuf.h" #include "quote.h" #define PACK_ID_BITS 16 diff --git a/fetch.c b/fetch.c index dd6ed9e41c..c256e6f6b4 100644 --- a/fetch.c +++ b/fetch.c @@ -6,7 +6,6 @@ #include "tag.h" #include "blob.h" #include "refs.h" -#include "strbuf.h" int get_tree = 0; int get_history = 0; diff --git a/imap-send.c b/imap-send.c index ecd4216a56..86e4a0f6a0 100644 --- a/imap-send.c +++ b/imap-send.c @@ -23,7 +23,6 @@ */ #include "cache.h" -#include "strbuf.h" typedef struct store_conf { char *name; diff --git a/mktag.c b/mktag.c index 7567f9ec29..b05260c83f 100644 --- a/mktag.c +++ b/mktag.c @@ -1,5 +1,4 @@ #include "cache.h" -#include "strbuf.h" #include "tag.h" /* diff --git a/mktree.c b/mktree.c index 3891cd9fb3..5dab4bd367 100644 --- a/mktree.c +++ b/mktree.c @@ -4,7 +4,6 @@ * Copyright (c) Junio C Hamano, 2006 */ #include "cache.h" -#include "strbuf.h" #include "quote.h" #include "tree.h" diff --git a/sha1_file.c b/sha1_file.c index 64b5b46698..59325d46be 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -14,7 +14,6 @@ #include "tag.h" #include "tree.h" #include "refs.h" -#include "strbuf.h" #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) diff --git a/strbuf.c b/strbuf.c index ff551ac9ff..c5f9e2a28f 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,5 +1,4 @@ #include "cache.h" -#include "strbuf.h" void strbuf_init(struct strbuf *sb, size_t hint) { -- cgit v1.3 From 182af8343c307436bb5364309aa6d4d46fa5911d Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sun, 16 Sep 2007 00:32:36 +0200 Subject: Use xmemdupz() in many places. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- attr.c | 7 +------ builtin-add.c | 8 ++------ builtin-apply.c | 11 ++--------- builtin-fetch--tool.c | 6 +----- builtin-fmt-merge-msg.c | 17 ++++++----------- builtin-for-each-ref.c | 40 +++++++++------------------------------- builtin-log.c | 12 ++---------- builtin-ls-files.c | 9 +-------- builtin-mv.c | 5 +---- builtin-revert.c | 4 +--- builtin-shortlog.c | 11 ++--------- commit.c | 16 ++++++---------- connect.c | 4 +--- convert.c | 7 +------ diff.c | 13 ++----------- diffcore-order.c | 7 ++----- fast-import.c | 4 +--- http-push.c | 9 ++------- imap-send.c | 20 +++++--------------- merge-recursive.c | 19 ++++--------------- refs.c | 12 ++++-------- sha1_file.c | 12 +++--------- tag.c | 4 +--- 23 files changed, 60 insertions(+), 197 deletions(-) (limited to 'diff.c') diff --git a/attr.c b/attr.c index 129399310a..92704a3f61 100644 --- a/attr.c +++ b/attr.c @@ -160,12 +160,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, else if (!equals) e->setto = ATTR__TRUE; else { - char *value; - int vallen = ep - equals; - value = xmalloc(vallen); - memcpy(value, equals+1, vallen-1); - value[vallen-1] = 0; - e->setto = value; + e->setto = xmemdupz(equals + 1, ep - equals - 1); } e->attr = git_attr(cp, len); } diff --git a/builtin-add.c b/builtin-add.c index 0d7d0ce420..f9a65803d8 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -71,12 +71,8 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec, baselen = common_prefix(pathspec); path = "."; base = ""; - if (baselen) { - char *common = xmalloc(baselen + 1); - memcpy(common, *pathspec, baselen); - common[baselen] = 0; - path = base = common; - } + if (baselen) + path = base = xmemdupz(*pathspec, baselen); /* Read the directory and prune it */ read_directory(dir, path, base, baselen, pathspec); diff --git a/builtin-apply.c b/builtin-apply.c index f953c5b768..512c9b6142 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -293,11 +293,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate) return def; } - name = xmalloc(len + 1); - memcpy(name, start, len); - name[len] = 0; - free(def); - return name; + return xmemdupz(start, len); } static int count_slashes(const char *cp) @@ -687,10 +683,7 @@ static char *git_header_name(char *line, int llen) break; } if (second[len] == '\n' && !memcmp(name, second, len)) { - char *ret = xmalloc(len + 1); - memcpy(ret, name, len); - ret[len] = 0; - return ret; + return xmemdupz(name, len); } } } diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 514a3cc018..349b59c258 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -222,19 +222,15 @@ static char *find_local_name(const char *remote_name, const char *refs, } if (!strncmp(remote_name, ref, len) && ref[len] == ':') { const char *local_part = ref + len + 1; - char *ret; int retlen; if (!next) retlen = strlen(local_part); else retlen = next - local_part; - ret = xmalloc(retlen + 1); - memcpy(ret, local_part, retlen); - ret[retlen] = 0; *force_p = single_force; *not_for_merge_p = not_for_merge; - return ret; + return xmemdupz(local_part, retlen); } ref = next; } diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index ae60fccea7..8a3c962f89 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -140,12 +140,10 @@ static int handle_line(char *line) if (!strcmp(".", src) || !strcmp(src, origin)) { int len = strlen(origin); if (origin[0] == '\'' && origin[len - 1] == '\'') { - char *new_origin = xmalloc(len - 1); - memcpy(new_origin, origin + 1, len - 2); - new_origin[len - 2] = 0; - origin = new_origin; - } else + origin = xmemdupz(origin + 1, len - 2); + } else { origin = xstrdup(origin); + } } else { char *new_origin = xmalloc(strlen(origin) + strlen(src) + 5); sprintf(new_origin, "%s of %s", origin, src); @@ -211,14 +209,11 @@ static void shortlog(const char *name, unsigned char *sha1, bol += 2; eol = strchr(bol, '\n'); - if (eol) { - int len = eol - bol; - oneline = xmalloc(len + 1); - memcpy(oneline, bol, len); - oneline[len] = 0; - } else + oneline = xmemdupz(bol, eol - bol); + } else { oneline = xstrdup(bol); + } append_to_list(&subjects, oneline, NULL); } diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c index 0afa1c5c41..725c1df0fc 100644 --- a/builtin-for-each-ref.c +++ b/builtin-for-each-ref.c @@ -87,7 +87,6 @@ static int used_atom_cnt, sort_atom_limit, need_tagged; static int parse_atom(const char *atom, const char *ep) { const char *sp; - char *n; int i, at; sp = atom; @@ -120,10 +119,7 @@ static int parse_atom(const char *atom, const char *ep) (sizeof *used_atom) * used_atom_cnt); used_atom_type = xrealloc(used_atom_type, (sizeof(*used_atom_type) * used_atom_cnt)); - n = xmalloc(ep - atom + 1); - memcpy(n, atom, ep - atom); - n[ep-atom] = 0; - used_atom[at] = n; + used_atom[at] = xmemdupz(atom, ep - atom); used_atom_type[at] = valid_atom[i].cmp_type; return at; } @@ -305,46 +301,28 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un static const char *copy_line(const char *buf) { const char *eol = strchr(buf, '\n'); - char *line; - int len; if (!eol) return ""; - len = eol - buf; - line = xmalloc(len + 1); - memcpy(line, buf, len); - line[len] = 0; - return line; + return xmemdupz(buf, eol - buf); } static const char *copy_name(const char *buf) { - const char *eol = strchr(buf, '\n'); - const char *eoname = strstr(buf, " <"); - char *line; - int len; - if (!(eoname && eol && eoname < eol)) - return ""; - len = eoname - buf; - line = xmalloc(len + 1); - memcpy(line, buf, len); - line[len] = 0; - return line; + const char *cp; + for (cp = buf; *cp != '\n'; cp++) { + if (!strncmp(cp, " <", 2)) + return xmemdupz(buf, cp - buf); + } + return ""; } static const char *copy_email(const char *buf) { const char *email = strchr(buf, '<'); const char *eoemail = strchr(email, '>'); - char *line; - int len; if (!email || !eoemail) return ""; - eoemail++; - len = eoemail - email; - line = xmalloc(len + 1); - memcpy(line, email, len); - line[len] = 0; - return line; + return xmemdupz(email, eoemail + 1 - email); } static void grab_date(const char *buf, struct atom_value *v) diff --git a/builtin-log.c b/builtin-log.c index 60819d15c5..e8b982db7c 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -441,8 +441,6 @@ static const char *clean_message_id(const char *msg_id) { char ch; const char *a, *z, *m; - char *n; - size_t len; m = msg_id; while ((ch = *m) && (isspace(ch) || (ch == '<'))) @@ -458,11 +456,7 @@ static const char *clean_message_id(const char *msg_id) die("insane in-reply-to: %s", msg_id); if (++z == m) return a; - len = z - a; - n = xmalloc(len + 1); - memcpy(n, a, len); - n[len] = 0; - return n; + return xmemdupz(a, z - a); } int cmd_format_patch(int argc, const char **argv, const char *prefix) @@ -541,9 +535,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) endpos = strchr(committer, '>'); if (!endpos) die("bogos committer info %s\n", committer); - add_signoff = xmalloc(endpos - committer + 2); - memcpy(add_signoff, committer, endpos - committer + 1); - add_signoff[endpos - committer + 1] = 0; + add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { rev.mime_boundary = git_version_string; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index 6c1db86e80..48dd3f77a4 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -299,7 +299,6 @@ static void prune_cache(const char *prefix) static const char *verify_pathspec(const char *prefix) { const char **p, *n, *prev; - char *real_prefix; unsigned long max; prev = NULL; @@ -326,14 +325,8 @@ static const char *verify_pathspec(const char *prefix) if (prefix_offset > max || memcmp(prev, prefix, prefix_offset)) die("git-ls-files: cannot generate relative filenames containing '..'"); - real_prefix = NULL; prefix_len = max; - if (max) { - real_prefix = xmalloc(max + 1); - memcpy(real_prefix, prev, max); - real_prefix[max] = 0; - } - return real_prefix; + return max ? xmemdupz(prev, max) : NULL; } /* diff --git a/builtin-mv.c b/builtin-mv.c index b95b7d286a..b944651691 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -22,10 +22,7 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec, for (i = 0; i < count; i++) { int length = strlen(result[i]); if (length > 0 && result[i][length - 1] == '/') { - char *without_slash = xmalloc(length); - memcpy(without_slash, result[i], length - 1); - without_slash[length - 1] = '\0'; - result[i] = without_slash; + result[i] = xmemdupz(result[i], length - 1); } if (base_name) { const char *last_slash = strrchr(result[i], '/'); diff --git a/builtin-revert.c b/builtin-revert.c index 499bbe7343..a655c8ee2a 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -168,9 +168,7 @@ static void set_author_ident_env(const char *message) char *line, *pend, *email, *timestamp; p += 7; - line = xmalloc(eol + 1 - p); - memcpy(line, p, eol - p); - line[eol - p] = '\0'; + line = xmemdupz(p, eol - p); email = strchr(line, '<'); if (!email) die ("Could not extract author email from %s", diff --git a/builtin-shortlog.c b/builtin-shortlog.c index 16af6199ab..3fe754677d 100644 --- a/builtin-shortlog.c +++ b/builtin-shortlog.c @@ -39,10 +39,7 @@ static void insert_author_oneline(struct path_list *list, while (authorlen > 0 && isspace(author[authorlen - 1])) authorlen--; - buffer = xmalloc(authorlen + 1); - memcpy(buffer, author, authorlen); - buffer[authorlen] = '\0'; - + buffer = xmemdupz(author, authorlen); item = path_list_insert(buffer, list); if (item->util == NULL) item->util = xcalloc(1, sizeof(struct path_list)); @@ -66,13 +63,9 @@ static void insert_author_oneline(struct path_list *list, oneline++; onelinelen--; } - while (onelinelen > 0 && isspace(oneline[onelinelen - 1])) onelinelen--; - - buffer = xmalloc(onelinelen + 1); - memcpy(buffer, oneline, onelinelen); - buffer[onelinelen] = '\0'; + buffer = xmemdupz(oneline, onelinelen); if (dot3) { int dot3len = strlen(dot3); diff --git a/commit.c b/commit.c index 85889f9664..f86fa776c0 100644 --- a/commit.c +++ b/commit.c @@ -628,11 +628,7 @@ static char *get_header(const struct commit *commit, const char *key) if (eol - line > key_len && !strncmp(line, key, key_len) && line[key_len] == ' ') { - int len = eol - line - key_len; - char *ret = xmalloc(len); - memcpy(ret, line + key_len + 1, len - 1); - ret[len - 1] = '\0'; - return ret; + return xmemdupz(line + key_len + 1, eol - line - key_len - 1); } line = next; } @@ -709,7 +705,7 @@ static void fill_person(struct interp *table, const char *msg, int len) start = end + 1; while (end > 0 && isspace(msg[end - 1])) end--; - table[0].value = xstrndup(msg, end); + table[0].value = xmemdupz(msg, end); if (start >= len) return; @@ -721,7 +717,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (end >= len) return; - table[1].value = xstrndup(msg + start, end - start); + table[1].value = xmemdupz(msg + start, end - start); /* parse date */ for (start = end + 1; start < len && isspace(msg[start]); start++) @@ -732,7 +728,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (msg + start == ep) return; - table[5].value = xstrndup(msg + start, ep - (msg + start)); + table[5].value = xmemdupz(msg + start, ep - (msg + start)); /* parse tz */ for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) @@ -859,7 +855,7 @@ void format_commit_message(const struct commit *commit, ; /* do nothing */ if (state == SUBJECT) { - table[ISUBJECT].value = xstrndup(msg + i, eol - i); + table[ISUBJECT].value = xmemdupz(msg + i, eol - i); i = eol; } if (i == eol) { @@ -875,7 +871,7 @@ void format_commit_message(const struct commit *commit, msg + i + 10, eol - i - 10); else if (!prefixcmp(msg + i, "encoding ")) table[IENCODING].value = - xstrndup(msg + i + 9, eol - i - 9); + xmemdupz(msg + i + 9, eol - i - 9); i = eol; } if (msg[i]) diff --git a/connect.c b/connect.c index 8b1e9935a8..1653a0ef7f 100644 --- a/connect.c +++ b/connect.c @@ -393,9 +393,7 @@ static int git_proxy_command_options(const char *var, const char *value) if (matchlen == 4 && !memcmp(value, "none", 4)) matchlen = 0; - git_proxy_command = xmalloc(matchlen + 1); - memcpy(git_proxy_command, value, matchlen); - git_proxy_command[matchlen] = 0; + git_proxy_command = xmemdupz(value, matchlen); } return 0; } diff --git a/convert.c b/convert.c index 508d30b2f1..79c9df2e91 100644 --- a/convert.c +++ b/convert.c @@ -323,13 +323,8 @@ static int read_convert_config(const char *var, const char *value) if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) break; if (!drv) { - char *namebuf; drv = xcalloc(1, sizeof(struct convert_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - drv->name = namebuf; - drv->next = NULL; + drv->name = xmemdupz(name, namelen); *user_convert_tail = drv; user_convert_tail = &(drv->next); } diff --git a/diff.c b/diff.c index a5b69ed2d2..2216d756d1 100644 --- a/diff.c +++ b/diff.c @@ -83,13 +83,8 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) break; if (!drv) { - char *namebuf; drv = xcalloc(1, sizeof(struct ll_diff_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - drv->name = namebuf; - drv->next = NULL; + drv->name = xmemdupz(name, namelen); if (!user_diff_tail) user_diff_tail = &user_diff; *user_diff_tail = drv; @@ -126,12 +121,8 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v if (!strncmp(pp->name, name, namelen) && !pp->name[namelen]) break; if (!pp) { - char *namebuf; pp = xcalloc(1, sizeof(*pp)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - pp->name = namebuf; + pp->name = xmemdupz(name, namelen); pp->next = funcname_pattern_list; funcname_pattern_list = pp; } diff --git a/diffcore-order.c b/diffcore-order.c index 2a4bd8232e..23e93852d8 100644 --- a/diffcore-order.c +++ b/diffcore-order.c @@ -48,11 +48,8 @@ static void prepare_order(const char *orderfile) if (*ep == '\n') { *ep = 0; order[cnt] = cp; - } - else { - order[cnt] = xmalloc(ep-cp+1); - memcpy(order[cnt], cp, ep-cp); - order[cnt][ep-cp] = 0; + } else { + order[cnt] = xmemdupz(cp, ep - cp); } cnt++; } diff --git a/fast-import.c b/fast-import.c index e2a4834706..f9906586ee 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1864,9 +1864,7 @@ static void file_change_cr(struct branch *b, int rename) endp = strchr(s, ' '); if (!endp) die("Missing space after source: %s", command_buf.buf); - s_uq = xmalloc(endp - s + 1); - memcpy(s_uq, s, endp - s); - s_uq[endp - s] = 0; + s_uq = xmemdupz(s, endp - s); } s = s_uq; diff --git a/http-push.c b/http-push.c index 7c3720f602..276e1eb1d9 100644 --- a/http-push.c +++ b/http-push.c @@ -1271,10 +1271,7 @@ xml_cdata(void *userData, const XML_Char *s, int len) { struct xml_ctx *ctx = (struct xml_ctx *)userData; free(ctx->cdata); - ctx->cdata = xmalloc(len + 1); - /* NB: 's' is not null-terminated, can not use strlcpy here */ - memcpy(ctx->cdata, s, len); - ctx->cdata[len] = '\0'; + ctx->cdata = xmemdupz(s, len); } static struct remote_lock *lock_remote(const char *path, long timeout) @@ -2172,9 +2169,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) /* If it's a symref, set the refname; otherwise try for a sha1 */ if (!prefixcmp((char *)buffer.buffer, "ref: ")) { - *symref = xmalloc(buffer.posn - 5); - memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6); - (*symref)[buffer.posn - 6] = '\0'; + *symref = xmemdupz((char *)buffer.buffer + 5, buffer.posn - 6); } else { get_sha1_hex(buffer.buffer, sha1); } diff --git a/imap-send.c b/imap-send.c index 86e4a0f6a0..905d09746a 100644 --- a/imap-send.c +++ b/imap-send.c @@ -623,9 +623,7 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level ) goto bail; cur->len = s - p; s++; - cur->val = xmalloc( cur->len + 1 ); - memcpy( cur->val, p, cur->len ); - cur->val[cur->len] = 0; + cur->val = xmemdupz(p, cur->len); } else { /* atom */ p = s; @@ -633,12 +631,10 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level ) if (level && *s == ')') break; cur->len = s - p; - if (cur->len == 3 && !memcmp ("NIL", p, 3)) + if (cur->len == 3 && !memcmp ("NIL", p, 3)) { cur->val = NIL; - else { - cur->val = xmalloc( cur->len + 1 ); - memcpy( cur->val, p, cur->len ); - cur->val[cur->len] = 0; + } else { + cur->val = xmemdupz(p, cur->len); } } @@ -1221,13 +1217,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs ) if (p) msg->len = &p[1] - data; - msg->data = xmalloc( msg->len + 1 ); - if (!msg->data) - return 0; - - memcpy( msg->data, data, msg->len ); - msg->data[ msg->len ] = 0; - + msg->data = xmemdupz(data, msg->len); *ofs += msg->len; return 1; } diff --git a/merge-recursive.c b/merge-recursive.c index 19d5f3b287..14b56c2f20 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -432,19 +432,15 @@ static int update_stages(const char *path, struct diff_filespec *o, static int remove_path(const char *name) { - int ret, len; + int ret; char *slash, *dirs; ret = unlink(name); if (ret) return ret; - len = strlen(name); - dirs = xmalloc(len+1); - memcpy(dirs, name, len); - dirs[len] = '\0'; + dirs = xstrdup(name); while ((slash = strrchr(name, '/'))) { *slash = '\0'; - len = slash - name; if (rmdir(name) != 0) break; } @@ -578,9 +574,7 @@ static void update_file_flags(const unsigned char *sha, flush_buffer(fd, buf, size); close(fd); } else if (S_ISLNK(mode)) { - char *lnk = xmalloc(size + 1); - memcpy(lnk, buf, size); - lnk[size] = '\0'; + char *lnk = xmemdupz(buf, size); mkdir_p(path, 0777); unlink(path); symlink(lnk, path); @@ -872,14 +866,9 @@ static int read_merge_config(const char *var, const char *value) if (!strncmp(fn->name, name, namelen) && !fn->name[namelen]) break; if (!fn) { - char *namebuf; fn = xcalloc(1, sizeof(struct ll_merge_driver)); - namebuf = xmalloc(namelen + 1); - memcpy(namebuf, name, namelen); - namebuf[namelen] = 0; - fn->name = namebuf; + fn->name = xmemdupz(name, namelen); fn->fn = ll_ext_merge; - fn->next = NULL; *ll_user_merge_tail = fn; ll_user_merge_tail = &(fn->next); } diff --git a/refs.c b/refs.c index 7fb3350789..07e260c8a1 100644 --- a/refs.c +++ b/refs.c @@ -1246,15 +1246,11 @@ int create_symref(const char *ref_target, const char *refs_heads_master, static char *ref_msg(const char *line, const char *endp) { const char *ep; - char *msg; - line += 82; - for (ep = line; ep < endp && *ep != '\n'; ep++) - ; - msg = xmalloc(ep - line + 1); - memcpy(msg, line, ep - line); - msg[ep - line] = 0; - return msg; + ep = memchr(line, '\n', endp - line); + if (!ep) + ep = endp; + return xmemdupz(line, ep - line); } int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt) diff --git a/sha1_file.c b/sha1_file.c index 59325d46be..385c5d891a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1491,11 +1491,8 @@ found_cache_entry: ent->lru.next->prev = ent->lru.prev; ent->lru.prev->next = ent->lru.next; delta_base_cached -= ent->size; - } - else { - ret = xmalloc(ent->size + 1); - memcpy(ret, ent->data, ent->size); - ((char *)ret)[ent->size] = 0; + } else { + ret = xmemdupz(ent->data, ent->size); } *type = ent->type; *base_size = ent->size; @@ -1872,12 +1869,9 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type, co = find_cached_object(sha1); if (co) { - buf = xmalloc(co->size + 1); - memcpy(buf, co->buf, co->size); - ((char*)buf)[co->size] = 0; *type = co->type; *size = co->size; - return buf; + return xmemdupz(co->buf, co->size); } buf = read_packed_sha1(sha1, type, size); diff --git a/tag.c b/tag.c index bbacd59a23..f62bcdd994 100644 --- a/tag.c +++ b/tag.c @@ -68,9 +68,7 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size) memcpy(type, type_line + 5, typelen); type[typelen] = '\0'; taglen = sig_line - tag_line - strlen("tag \n"); - item->tag = xmalloc(taglen + 1); - memcpy(item->tag, tag_line + 4, taglen); - item->tag[taglen] = '\0'; + item->tag = xmemdupz(tag_line + 4, taglen); if (!strcmp(type, blob_type)) { item->tagged = &lookup_blob(sha1)->object; -- cgit v1.3 From 663af3422a648e87945e4d8c0cc3e13671f2bbde Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 20 Sep 2007 00:42:15 +0200 Subject: Full rework of quote_c_style and write_name_quoted. * quote_c_style works on a strbuf instead of a wild buffer. * quote_c_style is now clever enough to not add double quotes if not needed. * write_name_quoted inherits those advantages, but also take a different set of arguments. Now instead of asking for quotes or not, you pass a "terminator". If it's \0 then we assume you don't want to escape, else C escaping is performed. In any case, the terminator is also appended to the stream. It also no longer takes the prefix/prefix_len arguments, as it's seldomly used, and makes some optimizations harder. * write_name_quotedpfx is created to work like write_name_quoted and take the prefix/prefix_len arguments. Thanks to those API changes, diff.c has somehow lost weight, thanks to the removal of functions that were wrappers around the old write_name_quoted trying to give it a semantics like the new one, but performing a lot of allocations for this goal. Now we always write directly to the stream, no intermediate allocation is performed. As a side effect of the refactor in builtin-apply.c, the length of the bar graphs in diffstats are not affected anymore by the fact that the path was clipped. Signed-off-by: Pierre Habouzit --- builtin-apply.c | 77 +++++------- builtin-blame.c | 3 +- builtin-check-attr.c | 2 +- builtin-checkout-index.c | 4 +- builtin-ls-files.c | 13 +- builtin-ls-tree.c | 6 +- combine-diff.c | 16 +-- diff.c | 303 +++++++++++++++++------------------------------ quote.c | 209 ++++++++++++++++++-------------- quote.h | 8 +- 10 files changed, 273 insertions(+), 368 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 1cf68ede12..01c9d60642 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -163,15 +163,14 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c fputs(pre, output); if (patch->old_name && patch->new_name && strcmp(patch->old_name, patch->new_name)) { - write_name_quoted(NULL, 0, patch->old_name, 1, output); + quote_c_style(patch->old_name, NULL, output, 0); fputs(" => ", output); - write_name_quoted(NULL, 0, patch->new_name, 1, output); - } - else { + quote_c_style(patch->new_name, NULL, output, 0); + } else { const char *n = patch->new_name; if (!n) n = patch->old_name; - write_name_quoted(NULL, 0, n, 1, output); + quote_c_style(n, NULL, output, 0); } fputs(post, output); } @@ -1379,61 +1378,50 @@ static const char minuses[]= "-------------------------------------------------- static void show_stats(struct patch *patch) { - const char *prefix = ""; - char *name = patch->new_name; - char *qname = NULL; - int len, max, add, del, total; - - if (!name) - name = patch->old_name; + struct strbuf qname; + char *cp = patch->new_name ? patch->new_name : patch->old_name; + int max, add, del; - if (0 < (len = quote_c_style(name, NULL, NULL, 0))) { - qname = xmalloc(len + 1); - quote_c_style(name, qname, NULL, 0); - name = qname; - } + strbuf_init(&qname, 0); + quote_c_style(cp, &qname, NULL, 0); /* * "scale" the filename */ - len = strlen(name); max = max_len; if (max > 50) max = 50; - if (len > max) { - char *slash; - prefix = "..."; - max -= 3; - name += len - max; - slash = strchr(name, '/'); - if (slash) - name = slash; + + if (qname.len > max) { + cp = strchr(qname.buf + qname.len + 3 - max, '/'); + if (!cp) + cp = qname.buf + qname.len + 3 - max; + strbuf_splice(&qname, 0, cp - qname.buf, "...", 3); + } + + if (patch->is_binary) { + printf(" %-*s | Bin\n", max, qname.buf); + strbuf_release(&qname); + return; } - len = max; + + printf(" %-*s |", max, qname.buf); + strbuf_release(&qname); /* * scale the add/delete */ - max = max_change; - if (max + len > 70) - max = 70 - len; - + max = max + max_change > 70 ? 70 - max : max_change; add = patch->lines_added; del = patch->lines_deleted; - total = add + del; if (max_change > 0) { - total = (total * max + max_change / 2) / max_change; + int total = ((add + del) * max + max_change / 2) / max_change; add = (add * max + max_change / 2) / max_change; del = total - add; } - if (patch->is_binary) - printf(" %s%-*s | Bin\n", prefix, len, name); - else - printf(" %s%-*s |%5d %.*s%.*s\n", prefix, - len, name, patch->lines_added + patch->lines_deleted, - add, pluses, del, minuses); - free(qname); + printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted, + add, pluses, del, minuses); } static int read_old_data(struct stat *st, const char *path, struct strbuf *buf) @@ -2228,13 +2216,8 @@ static void numstat_patch_list(struct patch *patch) if (patch->is_binary) printf("-\t-\t"); else - printf("%d\t%d\t", - patch->lines_added, patch->lines_deleted); - if (line_termination && quote_c_style(name, NULL, NULL, 0)) - quote_c_style(name, NULL, stdout, 0); - else - fputs(name, stdout); - putchar(line_termination); + printf("%d\t%d\t", patch->lines_added, patch->lines_deleted); + write_name_quoted(name, stdout, line_termination); } } diff --git a/builtin-blame.c b/builtin-blame.c index e364b6c6c0..16c0ca8206 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -1430,8 +1430,7 @@ static void get_commit_info(struct commit *commit, static void write_filename_info(const char *path) { printf("filename "); - write_name_quoted(NULL, 0, path, 1, stdout); - putchar('\n'); + write_name_quoted(path, stdout, '\n'); } /* diff --git a/builtin-check-attr.c b/builtin-check-attr.c index d94973379c..6afdfa10a1 100644 --- a/builtin-check-attr.c +++ b/builtin-check-attr.c @@ -56,7 +56,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix) else if (ATTR_UNSET(value)) value = "unspecified"; - write_name_quoted("", 0, argv[i], 1, stdout); + quote_c_style(argv[i], NULL, stdout, 0); printf(": %s: %s\n", argv[j+1], value); } } diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index e6264c4bf0..70d619da8d 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -66,9 +66,7 @@ static void write_tempfile_record(const char *name, int prefix_length) fputs(topath[checkout_stage], stdout); putchar('\t'); - write_name_quoted("", 0, name + prefix_length, - line_termination, stdout); - putchar(line_termination); + write_name_quoted(name + prefix_length, stdout, line_termination); for (i = 0; i < 4; i++) { topath[i][0] = 0; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index 48dd3f77a4..2e6f43bb97 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -84,8 +84,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent) return; fputs(tag, stdout); - write_name_quoted("", 0, ent->name + offset, line_terminator, stdout); - putchar(line_terminator); + write_name_quoted(ent->name + offset, stdout, line_terminator); } static void show_other_files(struct dir_struct *dir) @@ -208,21 +207,15 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) if (!show_stage) { fputs(tag, stdout); - write_name_quoted("", 0, ce->name + offset, - line_terminator, stdout); - putchar(line_terminator); - } - else { + } else { printf("%s%06o %s %d\t", tag, ntohl(ce->ce_mode), abbrev ? find_unique_abbrev(ce->sha1,abbrev) : sha1_to_hex(ce->sha1), ce_stage(ce)); - write_name_quoted("", 0, ce->name + offset, - line_terminator, stdout); - putchar(line_terminator); } + write_name_quoted(ce->name + offset, stdout, line_terminator); } static void show_files(struct dir_struct *dir, const char *prefix) diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c index cb4be4fabb..7abe333ce9 100644 --- a/builtin-ls-tree.c +++ b/builtin-ls-tree.c @@ -112,10 +112,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, abbrev ? find_unique_abbrev(sha1, abbrev) : sha1_to_hex(sha1)); } - write_name_quoted(base + chomp_prefix, baselen - chomp_prefix, - pathname, - line_termination, stdout); - putchar(line_termination); + write_name_quotedpfx(base + chomp_prefix, baselen - chomp_prefix, + pathname, stdout, line_termination); return retval; } diff --git a/combine-diff.c b/combine-diff.c index ef622340a5..fe5a2a1953 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -650,10 +650,7 @@ static void dump_quoted_path(const char *prefix, const char *path, const char *c_meta, const char *c_reset) { printf("%s%s", c_meta, prefix); - if (quote_c_style(path, NULL, NULL, 0)) - quote_c_style(path, NULL, stdout, 0); - else - printf("%s", path); + quote_c_style(path, NULL, stdout, 0); printf("%s\n", c_reset); } @@ -900,16 +897,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re putchar(inter_name_termination); } - if (line_termination) { - if (quote_c_style(p->path, NULL, NULL, 0)) - quote_c_style(p->path, NULL, stdout, 0); - else - printf("%s", p->path); - putchar(line_termination); - } - else { - printf("%s%c", p->path, line_termination); - } + write_name_quoted(p->path, stdout, line_termination); } void show_combined_diff(struct combine_diff_path *p, diff --git a/diff.c b/diff.c index 2216d756d1..fb6d077f06 100644 --- a/diff.c +++ b/diff.c @@ -181,44 +181,23 @@ int git_diff_ui_config(const char *var, const char *value) return git_default_config(var, value); } -static char *quote_one(const char *str) -{ - int needlen; - char *xp; - - if (!str) - return NULL; - needlen = quote_c_style(str, NULL, NULL, 0); - if (!needlen) - return xstrdup(str); - xp = xmalloc(needlen + 1); - quote_c_style(str, xp, NULL, 0); - return xp; -} - static char *quote_two(const char *one, const char *two) { int need_one = quote_c_style(one, NULL, NULL, 1); int need_two = quote_c_style(two, NULL, NULL, 1); - char *xp; + struct strbuf res; + strbuf_init(&res, 0); if (need_one + need_two) { - if (!need_one) need_one = strlen(one); - if (!need_two) need_one = strlen(two); - - xp = xmalloc(need_one + need_two + 3); - xp[0] = '"'; - quote_c_style(one, xp + 1, NULL, 1); - quote_c_style(two, xp + need_one + 1, NULL, 1); - strcpy(xp + need_one + need_two + 1, "\""); - return xp; + strbuf_addch(&res, '"'); + quote_c_style(one, &res, NULL, 1); + quote_c_style(two, &res, NULL, 1); + strbuf_addch(&res, '"'); + } else { + strbuf_addstr(&res, one); + strbuf_addstr(&res, two); } - need_one = strlen(one); - need_two = strlen(two); - xp = xmalloc(need_one + need_two + 1); - strcpy(xp, one); - strcpy(xp + need_one, two); - return xp; + return res.buf; } static const char *external_diff(void) @@ -670,27 +649,20 @@ static char *pprint_rename(const char *a, const char *b) { const char *old = a; const char *new = b; - char *name = NULL; + struct strbuf name; int pfx_length, sfx_length; int len_a = strlen(a); int len_b = strlen(b); + int a_midlen, b_midlen; int qlen_a = quote_c_style(a, NULL, NULL, 0); int qlen_b = quote_c_style(b, NULL, NULL, 0); + strbuf_init(&name, 0); if (qlen_a || qlen_b) { - if (qlen_a) len_a = qlen_a; - if (qlen_b) len_b = qlen_b; - name = xmalloc( len_a + len_b + 5 ); - if (qlen_a) - quote_c_style(a, name, NULL, 0); - else - memcpy(name, a, len_a); - memcpy(name + len_a, " => ", 4); - if (qlen_b) - quote_c_style(b, name + len_a + 4, NULL, 0); - else - memcpy(name + len_a + 4, b, len_b + 1); - return name; + quote_c_style(a, &name, NULL, 0); + strbuf_addstr(&name, " => "); + quote_c_style(b, &name, NULL, 0); + return name.buf; } /* Find common prefix */ @@ -719,24 +691,26 @@ static char *pprint_rename(const char *a, const char *b) * pfx{sfx-a => sfx-b} * name-a => name-b */ + a_midlen = len_a - pfx_length - sfx_length; + b_midlen = len_b - pfx_length - sfx_length; + if (a_midlen < 0) + a_midlen = 0; + if (b_midlen < 0) + b_midlen = 0; + + strbuf_grow(&name, pfx_length + a_midlen + b_midlen + sfx_length + 7); if (pfx_length + sfx_length) { - int a_midlen = len_a - pfx_length - sfx_length; - int b_midlen = len_b - pfx_length - sfx_length; - if (a_midlen < 0) a_midlen = 0; - if (b_midlen < 0) b_midlen = 0; - - name = xmalloc(pfx_length + a_midlen + b_midlen + sfx_length + 7); - sprintf(name, "%.*s{%.*s => %.*s}%s", - pfx_length, a, - a_midlen, a + pfx_length, - b_midlen, b + pfx_length, - a + len_a - sfx_length); + strbuf_add(&name, a, pfx_length); + strbuf_addch(&name, '{'); } - else { - name = xmalloc(len_a + len_b + 5); - sprintf(name, "%s => %s", a, b); + strbuf_add(&name, a + pfx_length, a_midlen); + strbuf_addstr(&name, " => "); + strbuf_add(&name, b + pfx_length, b_midlen); + if (pfx_length + sfx_length) { + strbuf_addch(&name, '}'); + strbuf_add(&name, a + len_a - sfx_length, sfx_length); } - return name; + return name.buf; } struct diffstat_t { @@ -849,12 +823,13 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) int change = file->added + file->deleted; if (!file->is_renamed) { /* renames are already quoted by pprint_rename */ - len = quote_c_style(file->name, NULL, NULL, 0); - if (len) { - char *qname = xmalloc(len + 1); - quote_c_style(file->name, qname, NULL, 0); + struct strbuf buf; + strbuf_init(&buf, 0); + if (quote_c_style(file->name, &buf, NULL, 0)) { free(file->name); - file->name = qname; + file->name = buf.buf; + } else { + strbuf_release(&buf); } } @@ -992,12 +967,12 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) printf("-\t-\t"); else printf("%d\t%d\t", file->added, file->deleted); - if (options->line_termination && !file->is_renamed && - quote_c_style(file->name, NULL, NULL, 0)) - quote_c_style(file->name, NULL, stdout, 0); - else + if (!file->is_renamed) { + write_name_quoted(file->name, stdout, options->line_termination); + } else { fputs(file->name, stdout); - putchar(options->line_termination); + putchar(options->line_termination); + } } } @@ -1941,50 +1916,46 @@ static int similarity_index(struct diff_filepair *p) static void run_diff(struct diff_filepair *p, struct diff_options *o) { const char *pgm = external_diff(); - char msg[PATH_MAX*2+300], *xfrm_msg; - struct diff_filespec *one; - struct diff_filespec *two; + struct strbuf msg; + char *xfrm_msg; + struct diff_filespec *one = p->one; + struct diff_filespec *two = p->two; const char *name; const char *other; - char *name_munged, *other_munged; int complete_rewrite = 0; - int len; + if (DIFF_PAIR_UNMERGED(p)) { - /* unmerged */ run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0); return; } - name = p->one->path; + name = p->one->path; other = (strcmp(name, p->two->path) ? p->two->path : NULL); - name_munged = quote_one(name); - other_munged = quote_one(other); - one = p->one; two = p->two; - diff_fill_sha1_info(one); diff_fill_sha1_info(two); - len = 0; + strbuf_init(&msg, PATH_MAX * 2 + 300); switch (p->status) { case DIFF_STATUS_COPIED: - len += snprintf(msg + len, sizeof(msg) - len, - "similarity index %d%%\n" - "copy from %s\n" - "copy to %s\n", - similarity_index(p), name_munged, other_munged); + strbuf_addf(&msg, "similarity index %d%%", similarity_index(p)); + strbuf_addstr(&msg, "\ncopy from "); + quote_c_style(name, &msg, NULL, 0); + strbuf_addstr(&msg, "\ncopy to "); + quote_c_style(other, &msg, NULL, 0); + strbuf_addch(&msg, '\n'); break; case DIFF_STATUS_RENAMED: - len += snprintf(msg + len, sizeof(msg) - len, - "similarity index %d%%\n" - "rename from %s\n" - "rename to %s\n", - similarity_index(p), name_munged, other_munged); + strbuf_addf(&msg, "similarity index %d%%", similarity_index(p)); + strbuf_addstr(&msg, "\nrename from "); + quote_c_style(name, &msg, NULL, 0); + strbuf_addstr(&msg, "\nrename to "); + quote_c_style(other, &msg, NULL, 0); + strbuf_addch(&msg, '\n'); break; case DIFF_STATUS_MODIFIED: if (p->score) { - len += snprintf(msg + len, sizeof(msg) - len, - "dissimilarity index %d%%\n", + strbuf_addf(&msg, "dissimilarity index %d%%\n", similarity_index(p)); complete_rewrite = 1; break; @@ -2004,19 +1975,17 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) abbrev = 40; } - len += snprintf(msg + len, sizeof(msg) - len, - "index %.*s..%.*s", + strbuf_addf(&msg, "index %.*s..%.*s", abbrev, sha1_to_hex(one->sha1), abbrev, sha1_to_hex(two->sha1)); if (one->mode == two->mode) - len += snprintf(msg + len, sizeof(msg) - len, - " %06o", one->mode); - len += snprintf(msg + len, sizeof(msg) - len, "\n"); + strbuf_addf(&msg, " %06o", one->mode); + strbuf_addch(&msg, '\n'); } - if (len) - msg[--len] = 0; - xfrm_msg = len ? msg : NULL; + if (msg.len) + strbuf_setlen(&msg, msg.len - 1); + xfrm_msg = msg.len ? msg.buf : NULL; if (!pgm && DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) && @@ -2035,8 +2004,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o, complete_rewrite); - free(name_munged); - free(other_munged); + strbuf_release(&msg); } static void run_diffstat(struct diff_filepair *p, struct diff_options *o, @@ -2492,72 +2460,30 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len) return sha1_to_hex(sha1); } -static void diff_flush_raw(struct diff_filepair *p, - struct diff_options *options) +static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) { - int two_paths; - char status[10]; - int abbrev = options->abbrev; - const char *path_one, *path_two; - int inter_name_termination = '\t'; - int line_termination = options->line_termination; - - if (!line_termination) - inter_name_termination = 0; + int line_termination = opt->line_termination; + int inter_name_termination = line_termination ? '\t' : '\0'; - path_one = p->one->path; - path_two = p->two->path; - if (line_termination) { - path_one = quote_one(path_one); - path_two = quote_one(path_two); + if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) { + printf(":%06o %06o %s ", p->one->mode, p->two->mode, + diff_unique_abbrev(p->one->sha1, opt->abbrev)); + printf("%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev)); } - - if (p->score) - sprintf(status, "%c%03d", p->status, similarity_index(p)); - else { - status[0] = p->status; - status[1] = 0; - } - switch (p->status) { - case DIFF_STATUS_COPIED: - case DIFF_STATUS_RENAMED: - two_paths = 1; - break; - case DIFF_STATUS_ADDED: - case DIFF_STATUS_DELETED: - two_paths = 0; - break; - default: - two_paths = 0; - break; - } - if (!(options->output_format & DIFF_FORMAT_NAME_STATUS)) { - printf(":%06o %06o %s ", - p->one->mode, p->two->mode, - diff_unique_abbrev(p->one->sha1, abbrev)); - printf("%s ", - diff_unique_abbrev(p->two->sha1, abbrev)); + if (p->score) { + printf("%c%03d%c", p->status, similarity_index(p), + inter_name_termination); + } else { + printf("%c%c", p->status, inter_name_termination); } - printf("%s%c%s", status, inter_name_termination, - two_paths || p->one->mode ? path_one : path_two); - if (two_paths) - printf("%c%s", inter_name_termination, path_two); - putchar(line_termination); - if (path_one != p->one->path) - free((void*)path_one); - if (path_two != p->two->path) - free((void*)path_two); -} -static void diff_flush_name(struct diff_filepair *p, struct diff_options *opt) -{ - char *path = p->two->path; - - if (opt->line_termination) - path = quote_one(p->two->path); - printf("%s%c", path, opt->line_termination); - if (p->two->path != path) - free(path); + if (p->status == DIFF_STATUS_COPIED || p->status == DIFF_STATUS_RENAMED) { + write_name_quoted(p->one->path, stdout, inter_name_termination); + write_name_quoted(p->two->path, stdout, line_termination); + } else { + const char *path = p->one->mode ? p->one->path : p->two->path; + write_name_quoted(path, stdout, line_termination); + } } int diff_unmodified_pair(struct diff_filepair *p) @@ -2567,14 +2493,11 @@ int diff_unmodified_pair(struct diff_filepair *p) * let transformers to produce diff_filepairs any way they want, * and filter and clean them up here before producing the output. */ - struct diff_filespec *one, *two; + struct diff_filespec *one = p->one, *two = p->two; if (DIFF_PAIR_UNMERGED(p)) return 0; /* unmerged is interesting */ - one = p->one; - two = p->two; - /* deletion, addition, mode or type change * and rename are all interesting. */ @@ -2763,32 +2686,27 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt) else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS)) diff_flush_raw(p, opt); else if (fmt & DIFF_FORMAT_NAME) - diff_flush_name(p, opt); + write_name_quoted(p->two->path, stdout, opt->line_termination); } static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs) { - char *name = quote_one(fs->path); if (fs->mode) - printf(" %s mode %06o %s\n", newdelete, fs->mode, name); + printf(" %s mode %06o ", newdelete, fs->mode); else - printf(" %s %s\n", newdelete, name); - free(name); + printf(" %s ", newdelete); + write_name_quoted(fs->path, stdout, '\n'); } static void show_mode_change(struct diff_filepair *p, int show_name) { if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) { + printf(" mode change %06o => %06o%c", p->one->mode, p->two->mode, + show_name ? ' ' : '\n'); if (show_name) { - char *name = quote_one(p->two->path); - printf(" mode change %06o => %06o %s\n", - p->one->mode, p->two->mode, name); - free(name); + write_name_quoted(p->two->path, stdout, '\n'); } - else - printf(" mode change %06o => %06o\n", - p->one->mode, p->two->mode); } } @@ -2818,12 +2736,11 @@ static void diff_summary(struct diff_filepair *p) break; default: if (p->score) { - char *name = quote_one(p->two->path); - printf(" rewrite %s (%d%%)\n", name, - similarity_index(p)); - free(name); - show_mode_change(p, 0); - } else show_mode_change(p, 1); + puts(" rewrite "); + write_name_quoted(p->two->path, stdout, ' '); + printf("(%d%%)\n", similarity_index(p)); + } + show_mode_change(p, !p->score); break; } } @@ -2837,14 +2754,14 @@ struct patch_id_t { static int remove_space(char *line, int len) { int i; - char *dst = line; - unsigned char c; + char *dst = line; + unsigned char c; - for (i = 0; i < len; i++) - if (!isspace((c = line[i]))) - *dst++ = c; + for (i = 0; i < len; i++) + if (!isspace((c = line[i]))) + *dst++ = c; - return dst - line; + return dst - line; } static void patch_id_consume(void *priv, char *line, unsigned long len) diff --git a/quote.c b/quote.c index 7771c9c678..b1efe188d4 100644 --- a/quote.c +++ b/quote.c @@ -157,83 +157,143 @@ char *sq_dequote(char *arg) } } +/* 1 means: quote as octal + * 0 means: quote as octal if (quote_path_fully) + * -1 means: never quote + * c: quote as "\\c" + */ +#define X8(x) x, x, x, x, x, x, x, x +#define X16(x) X8(x), X8(x) +static signed char const sq_lookup[256] = { + /* 0 1 2 3 4 5 6 7 */ + /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a', + /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1, + /* 0x10 */ X16(1), + /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1, + /* 0x28 */ X16(-1), X16(-1), X16(-1), + /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1, + /* 0x60 */ X16(-1), X8(-1), + /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1, + /* 0x80 */ /* set to 0 */ +}; + +static inline int sq_must_quote(char c) { + return sq_lookup[(unsigned char)c] + quote_path_fully > 0; +} + +/* returns the longest prefix not needing a quote up to maxlen if positive. + This stops at the first \0 because it's marked as a character needing an + escape */ +static size_t next_quote_pos(const char *s, ssize_t maxlen) +{ + size_t len; + if (maxlen < 0) { + for (len = 0; !sq_must_quote(s[len]); len++); + } else { + for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++); + } + return len; +} + /* * C-style name quoting. * - * Does one of three things: - * - * (1) if outbuf and outfp are both NULL, inspect the input name and - * counts the number of bytes that are needed to hold c_style - * quoted version of name, counting the double quotes around - * it but not terminating NUL, and returns it. However, if name - * does not need c_style quoting, it returns 0. - * - * (2) if outbuf is not NULL, it must point at a buffer large enough - * to hold the c_style quoted version of name, enclosing double - * quotes, and terminating NUL. Fills outbuf with c_style quoted - * version of name enclosed in double-quote pair. Return value - * is undefined. + * (1) if sb and fp are both NULL, inspect the input name and counts the + * number of bytes that are needed to hold c_style quoted version of name, + * counting the double quotes around it but not terminating NUL, and + * returns it. + * However, if name does not need c_style quoting, it returns 0. * - * (3) if outfp is not NULL, outputs c_style quoted version of name, - * but not enclosed in double-quote pair. Return value is undefined. + * (2) if sb or fp are not NULL, it emits the c_style quoted version + * of name, enclosed with double quotes if asked and needed only. + * Return value is the same as in (1). */ - -static int quote_c_style_counted(const char *name, int namelen, - char *outbuf, FILE *outfp, int no_dq) +static size_t quote_c_style_counted(const char *name, ssize_t maxlen, + struct strbuf *sb, FILE *fp, int no_dq) { #undef EMIT -#define EMIT(c) \ - (outbuf ? (*outbuf++ = (c)) : outfp ? fputc(c, outfp) : (count++)) - -#define EMITQ() EMIT('\\') +#define EMIT(c) \ + do { \ + if (sb) strbuf_addch(sb, (c)); \ + if (fp) fputc((c), fp); \ + count++; \ + } while (0) +#define EMITBUF(s, l) \ + do { \ + if (sb) strbuf_add(sb, (s), (l)); \ + if (fp) fwrite((s), (l), 1, fp); \ + count += (l); \ + } while (0) + + size_t len, count = 0; + const char *p = name; - const char *sp; - unsigned char ch; - int count = 0, needquote = 0; + for (;;) { + int ch; - if (!no_dq) - EMIT('"'); - for (sp = name; sp < name + namelen; sp++) { - ch = *sp; - if (!ch) + len = next_quote_pos(p, maxlen); + if (len == maxlen || !p[len]) break; - if ((ch < ' ') || (ch == '"') || (ch == '\\') || - (quote_path_fully && (ch >= 0177))) { - needquote = 1; - switch (ch) { - case '\a': EMITQ(); ch = 'a'; break; - case '\b': EMITQ(); ch = 'b'; break; - case '\f': EMITQ(); ch = 'f'; break; - case '\n': EMITQ(); ch = 'n'; break; - case '\r': EMITQ(); ch = 'r'; break; - case '\t': EMITQ(); ch = 't'; break; - case '\v': EMITQ(); ch = 'v'; break; - - case '\\': /* fallthru */ - case '"': EMITQ(); break; - default: - /* octal */ - EMITQ(); - EMIT(((ch >> 6) & 03) + '0'); - EMIT(((ch >> 3) & 07) + '0'); - ch = (ch & 07) + '0'; - break; - } + + if (!no_dq && p == name) + EMIT('"'); + + EMITBUF(p, len); + EMIT('\\'); + p += len; + ch = (unsigned char)*p++; + if (sq_lookup[ch] >= ' ') { + EMIT(sq_lookup[ch]); + } else { + EMIT(((ch >> 6) & 03) + '0'); + EMIT(((ch >> 3) & 07) + '0'); + EMIT(((ch >> 0) & 07) + '0'); } - EMIT(ch); } + + EMITBUF(p, len); + if (p == name) /* no ending quote needed */ + return 0; + if (!no_dq) EMIT('"'); - if (outbuf) - *outbuf = 0; + return count; +} - return needquote ? count : 0; +size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) +{ + return quote_c_style_counted(name, -1, sb, fp, nodq); } -int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq) +void write_name_quoted(const char *name, FILE *fp, int terminator) { - int cnt = strlen(name); - return quote_c_style_counted(name, cnt, outbuf, outfp, no_dq); + if (terminator) { + quote_c_style(name, NULL, fp, 0); + } else { + fputs(name, fp); + } + fputc(terminator, fp); +} + +extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, + const char *name, FILE *fp, int terminator) +{ + int needquote = 0; + + if (terminator) { + needquote = next_quote_pos(pfx, pfxlen) < pfxlen + || name[next_quote_pos(name, -1)]; + } + if (needquote) { + fputc('"', fp); + quote_c_style_counted(pfx, pfxlen, NULL, fp, 1); + quote_c_style(name, NULL, fp, 1); + fputc('"', fp); + } else { + fwrite(pfx, pfxlen, 1, fp); + fputs(name, fp); + } + fputc(terminator, fp); } /* @@ -306,37 +366,6 @@ int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp) return -1; } -void write_name_quoted(const char *prefix, int prefix_len, - const char *name, int quote, FILE *out) -{ - int needquote; - - if (!quote) { - no_quote: - if (prefix_len) - fprintf(out, "%.*s", prefix_len, prefix); - fputs(name, out); - return; - } - - needquote = 0; - if (prefix_len) - needquote = quote_c_style_counted(prefix, prefix_len, - NULL, NULL, 0); - if (!needquote) - needquote = quote_c_style(name, NULL, NULL, 0); - if (needquote) { - fputc('"', out); - if (prefix_len) - quote_c_style_counted(prefix, prefix_len, - NULL, out, 1); - quote_c_style(name, NULL, out, 1); - fputc('"', out); - } - else - goto no_quote; -} - /* quoting as a string literal for other languages */ void perl_quote_print(FILE *stream, const char *src) diff --git a/quote.h b/quote.h index f48a3fc584..2769f71c93 100644 --- a/quote.h +++ b/quote.h @@ -44,11 +44,11 @@ extern int add_to_string(char **ptrp, int *sizep, const char *str, int quote); extern char *sq_dequote(char *); extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); -extern int quote_c_style(const char *name, char *outbuf, FILE *outfp, - int nodq); +extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq); -extern void write_name_quoted(const char *prefix, int prefix_len, - const char *name, int quote, FILE *out); +extern void write_name_quoted(const char *name, FILE *, int terminator); +extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, + const char *name, FILE *, int terminator); /* quoting as a string literal for other languages */ extern void perl_quote_print(FILE *stream, const char *src); -- cgit v1.3 From b315c5c08139c0d3c1e4867a305334e29da01d07 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Thu, 27 Sep 2007 12:58:23 +0200 Subject: strbuf change: be sure ->buf is never ever NULL. For that purpose, the ->buf is always initialized with a char * buf living in the strbuf module. It is made a char * so that we can sloppily accept things that perform: sb->buf[0] = '\0', and because you can't pass "" as an initializer for ->buf without making gcc unhappy for very good reasons. strbuf_init/_detach/_grow have been fixed to trust ->alloc and not ->buf anymore. as a consequence strbuf_detach is _mandatory_ to detach a buffer, copying ->buf isn't an option anymore, if ->buf is going to escape from the scope, and eventually be free'd. API changes: * strbuf_setlen now always works, so just make strbuf_reset a convenience macro. * strbuf_detatch takes a size_t* optional argument (meaning it can be NULL) to copy the buffer's len, as it was needed for this refactor to make the code more readable, and working like the callers. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-apply.c | 16 +++++++--------- builtin-archive.c | 5 ++--- builtin-fetch--tool.c | 2 +- commit.c | 2 +- convert.c | 4 ++-- diff.c | 14 ++++++-------- entry.c | 3 +-- fast-import.c | 2 +- imap-send.c | 2 +- quote.c | 2 +- sha1_file.c | 3 +-- strbuf.c | 30 +++++++++++++++++++----------- strbuf.h | 10 +++++----- 13 files changed, 48 insertions(+), 47 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 01c9d60642..740623e6c0 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -178,14 +178,13 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c #define CHUNKSIZE (8192) #define SLOP (16) -static void *read_patch_file(int fd, unsigned long *sizep) +static void *read_patch_file(int fd, size_t *sizep) { struct strbuf buf; strbuf_init(&buf, 0); if (strbuf_read(&buf, fd, 0) < 0) die("git-apply: read returned %s", strerror(errno)); - *sizep = buf.len; /* * Make sure that we have some slop in the buffer @@ -194,7 +193,7 @@ static void *read_patch_file(int fd, unsigned long *sizep) */ strbuf_grow(&buf, SLOP); memset(buf.buf + buf.len, 0, SLOP); - return strbuf_detach(&buf); + return strbuf_detach(&buf, sizep); } static unsigned long linelen(const char *buffer, unsigned long size) @@ -253,7 +252,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate) */ strbuf_remove(&name, 0, cp - name.buf); free(def); - return name.buf; + return strbuf_detach(&name, NULL); } } strbuf_release(&name); @@ -607,7 +606,7 @@ static char *git_header_name(char *line, int llen) if (strcmp(cp + 1, first.buf)) goto free_and_fail1; strbuf_release(&sp); - return first.buf; + return strbuf_detach(&first, NULL); } /* unquoted second */ @@ -618,7 +617,7 @@ static char *git_header_name(char *line, int llen) if (line + llen - cp != first.len + 1 || memcmp(first.buf, cp, first.len)) goto free_and_fail1; - return first.buf; + return strbuf_detach(&first, NULL); free_and_fail1: strbuf_release(&first); @@ -655,7 +654,7 @@ static char *git_header_name(char *line, int llen) isspace(name[len])) { /* Good */ strbuf_remove(&sp, 0, np - sp.buf); - return sp.buf; + return strbuf_detach(&sp, NULL); } free_and_fail2: @@ -1968,8 +1967,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * if (apply_fragments(&buf, patch) < 0) return -1; /* note with --reject this succeeds. */ - patch->result = buf.buf; - patch->resultsize = buf.len; + patch->result = strbuf_detach(&buf, &patch->resultsize); if (0 < patch->is_delete && patch->resultsize) return error("removal patch leaves file contents"); diff --git a/builtin-archive.c b/builtin-archive.c index 843a9e37bb..04385dea05 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -89,7 +89,7 @@ static void format_subst(const struct commit *commit, struct strbuf fmt; if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); strbuf_init(&fmt, 0); for (;;) { const char *b, *c; @@ -153,8 +153,7 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); convert_to_archive(path, buf.buf, buf.len, &buf, commit); - *sizep = buf.len; - buffer = buf.buf; + buffer = strbuf_detach(&buf, sizep); } return buffer; diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 349b59c258..1e43d79221 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -10,7 +10,7 @@ static char *get_stdin(void) if (strbuf_read(&buf, 0, 1024) < 0) { die("error reading standard input: %s", strerror(errno)); } - return strbuf_detach(&buf); + return strbuf_detach(&buf, NULL); } static void show_new(enum object_type type, unsigned char *sha1_new) diff --git a/commit.c b/commit.c index 55b08ec0b9..62cc74d7a9 100644 --- a/commit.c +++ b/commit.c @@ -663,7 +663,7 @@ static char *replace_encoding_header(char *buf, const char *encoding) len - strlen("encoding \n"), encoding, strlen(encoding)); } - return tmp.buf; + return strbuf_detach(&tmp, NULL); } static char *logmsg_reencode(const struct commit *commit, diff --git a/convert.c b/convert.c index 79c9df2e91..0d5e909c69 100644 --- a/convert.c +++ b/convert.c @@ -168,7 +168,7 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len, /* are we "faking" in place editing ? */ if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); strbuf_grow(buf, len + stats.lf - stats.crlf); for (;;) { @@ -464,7 +464,7 @@ static int ident_to_worktree(const char *path, const char *src, size_t len, /* are we "faking" in place editing ? */ if (src == buf->buf) - to_free = strbuf_detach(buf); + to_free = strbuf_detach(buf, NULL); hash_sha1_file(src, len, "blob", sha1); strbuf_grow(buf, len + cnt * 43); diff --git a/diff.c b/diff.c index fb6d077f06..ab575191d1 100644 --- a/diff.c +++ b/diff.c @@ -197,7 +197,7 @@ static char *quote_two(const char *one, const char *two) strbuf_addstr(&res, one); strbuf_addstr(&res, two); } - return res.buf; + return strbuf_detach(&res, NULL); } static const char *external_diff(void) @@ -662,7 +662,7 @@ static char *pprint_rename(const char *a, const char *b) quote_c_style(a, &name, NULL, 0); strbuf_addstr(&name, " => "); quote_c_style(b, &name, NULL, 0); - return name.buf; + return strbuf_detach(&name, NULL); } /* Find common prefix */ @@ -710,7 +710,7 @@ static char *pprint_rename(const char *a, const char *b) strbuf_addch(&name, '}'); strbuf_add(&name, a + len_a - sfx_length, sfx_length); } - return name.buf; + return strbuf_detach(&name, NULL); } struct diffstat_t { @@ -827,7 +827,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) strbuf_init(&buf, 0); if (quote_c_style(file->name, &buf, NULL, 0)) { free(file->name); - file->name = buf.buf; + file->name = strbuf_detach(&buf, NULL); } else { strbuf_release(&buf); } @@ -1519,8 +1519,7 @@ static int populate_from_stdin(struct diff_filespec *s) strerror(errno)); s->should_munmap = 0; - s->size = buf.len; - s->data = strbuf_detach(&buf); + s->data = strbuf_detach(&buf, &s->size); s->should_free = 1; return 0; } @@ -1612,8 +1611,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (convert_to_git(s->path, s->data, s->size, &buf)) { munmap(s->data, s->size); s->should_munmap = 0; - s->data = buf.buf; - s->size = buf.len; + s->data = strbuf_detach(&buf, &s->size); s->should_free = 1; } } diff --git a/entry.c b/entry.c index 4a8c73bfae..98f5f6d4ec 100644 --- a/entry.c +++ b/entry.c @@ -120,8 +120,7 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout strbuf_init(&buf, 0); if (convert_to_working_tree(ce->name, new, size, &buf)) { free(new); - new = buf.buf; - size = buf.len; + new = strbuf_detach(&buf, &size); } if (to_tempfile) { diff --git a/fast-import.c b/fast-import.c index a870a44e3d..e9c80be4cd 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1562,7 +1562,7 @@ static int read_next_command(void) } else { struct recent_command *rc; - strbuf_detach(&command_buf); + strbuf_detach(&command_buf, NULL); stdin_eof = strbuf_getline(&command_buf, stdin, '\n'); if (stdin_eof) return EOF; diff --git a/imap-send.c b/imap-send.c index e95cdde062..a429a76a63 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1180,7 +1180,7 @@ read_message( FILE *f, msg_data_t *msg ) } while (!feof(f)); msg->len = buf.len; - msg->data = strbuf_detach(&buf); + msg->data = strbuf_detach(&buf, NULL); return msg->len; } diff --git a/quote.c b/quote.c index 800fd88c9a..482be05b7a 100644 --- a/quote.c +++ b/quote.c @@ -22,7 +22,7 @@ void sq_quote_buf(struct strbuf *dst, const char *src) char *to_free = NULL; if (dst->buf == src) - to_free = strbuf_detach(dst); + to_free = strbuf_detach(dst, NULL); strbuf_addch(dst, '\''); while (*src) { diff --git a/sha1_file.c b/sha1_file.c index 385c5d891a..753742a47c 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2340,8 +2340,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, strbuf_init(&nbuf, 0); if (convert_to_git(path, buf, size, &nbuf)) { munmap(buf, size); - size = nbuf.len; - buf = nbuf.buf; + buf = strbuf_detach(&nbuf, &size); re_allocated = 1; } } diff --git a/strbuf.c b/strbuf.c index d1e338bfb6..0e431daa61 100644 --- a/strbuf.c +++ b/strbuf.c @@ -1,27 +1,33 @@ #include "cache.h" +/* + * Used as the default ->buf value, so that people can always assume + * buf is non NULL and ->buf is NUL terminated even for a freshly + * initialized strbuf. + */ +char strbuf_slopbuf[1]; + void strbuf_init(struct strbuf *sb, size_t hint) { - memset(sb, 0, sizeof(*sb)); + sb->alloc = sb->len = 0; + sb->buf = strbuf_slopbuf; if (hint) strbuf_grow(sb, hint); } void strbuf_release(struct strbuf *sb) { - free(sb->buf); - memset(sb, 0, sizeof(*sb)); -} - -void strbuf_reset(struct strbuf *sb) -{ - if (sb->len) - strbuf_setlen(sb, 0); + if (sb->alloc) { + free(sb->buf); + strbuf_init(sb, 0); + } } -char *strbuf_detach(struct strbuf *sb) +char *strbuf_detach(struct strbuf *sb, size_t *sz) { - char *res = sb->buf; + char *res = sb->alloc ? sb->buf : NULL; + if (sz) + *sz = sb->len; strbuf_init(sb, 0); return res; } @@ -40,6 +46,8 @@ void strbuf_grow(struct strbuf *sb, size_t extra) { if (sb->len + extra + 1 <= sb->len) die("you want to use way too much memory"); + if (!sb->alloc) + sb->buf = NULL; ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); } diff --git a/strbuf.h b/strbuf.h index 5657e3db14..6deec78479 100644 --- a/strbuf.h +++ b/strbuf.h @@ -10,8 +10,7 @@ * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to * build complex strings/buffers whose final size isn't easily known. * - * It is legal to copy the ->buf pointer away. Though if you want to reuse - * the strbuf after that, setting ->buf to NULL isn't legal. + * It is NOT legal to copy the ->buf pointer away. * `strbuf_detach' is the operation that detachs a buffer from its shell * while keeping the shell valid wrt its invariants. * @@ -41,19 +40,19 @@ #include +extern char strbuf_slopbuf[]; struct strbuf { size_t alloc; size_t len; char *buf; }; -#define STRBUF_INIT { 0, 0, NULL } +#define STRBUF_INIT { 0, 0, strbuf_slopbuf } /*----- strbuf life cycle -----*/ extern void strbuf_init(struct strbuf *, size_t); extern void strbuf_release(struct strbuf *); -extern void strbuf_reset(struct strbuf *); -extern char *strbuf_detach(struct strbuf *); +extern char *strbuf_detach(struct strbuf *, size_t *); extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) { struct strbuf tmp = *a; @@ -75,6 +74,7 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { sb->len = len; sb->buf[len] = '\0'; } +#define strbuf_reset(sb) strbuf_setlen(sb, 0) /*----- content related -----*/ extern void strbuf_rtrim(struct strbuf *); -- cgit v1.3 From eede7b7d110e2c354235d7a3f6c8f1644b5120e5 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 25 Sep 2007 15:29:42 -0400 Subject: diffcore-rename: cache file deltas We find rename candidates by computing a fingerprint hash of each file, and then comparing those fingerprints. There are inherently O(n^2) comparisons, so it pays in CPU time to hoist the (rather expensive) computation of the fingerprint out of that loop (or to cache it once we have computed it once). Previously, we didn't keep the filespec information around because then we had the potential to consume a great deal of memory. However, instead of keeping all of the filespec data, we can instead just keep the fingerprint. This patch implements and uses diff_free_filespec_data_large to accomplish that goal. We also have to change estimate_similarity not to needlessly repopulate the filespec data when we already have the hash. Practical tests showed 4.5x speedup for a 10% memory usage increase. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 7 ++++++- diffcore-rename.c | 7 ++++--- diffcore.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 0ee9ea1c1b..35e3c61986 100644 --- a/diff.c +++ b/diff.c @@ -1675,7 +1675,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) return 0; } -void diff_free_filespec_data(struct diff_filespec *s) +void diff_free_filespec_data_large(struct diff_filespec *s) { if (s->should_free) free(s->data); @@ -1686,6 +1686,11 @@ void diff_free_filespec_data(struct diff_filespec *s) s->should_free = s->should_munmap = 0; s->data = NULL; } +} + +void diff_free_filespec_data(struct diff_filespec *s) +{ + diff_free_filespec_data_large(s); free(s->cnt_data); s->cnt_data = NULL; } diff --git a/diffcore-rename.c b/diffcore-rename.c index 41b35c3a9e..4fc200064a 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -184,7 +184,8 @@ static int estimate_similarity(struct diff_filespec *src, if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE) return 0; - if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) + if ((!src->cnt_data && diff_populate_filespec(src, 0)) + || (!dst->cnt_data && diff_populate_filespec(dst, 0))) return 0; /* error but caught downstream */ @@ -377,10 +378,10 @@ void diffcore_rename(struct diff_options *options) m->score = estimate_similarity(one, two, minimum_score); m->name_score = basename_same(one, two); - diff_free_filespec_data(one); + diff_free_filespec_data_large(one); } /* We do not need the text anymore */ - diff_free_filespec_data(two); + diff_free_filespec_data_large(two); dst_cnt++; } /* cost matrix sorted by most to least similar pair */ diff --git a/diffcore.h b/diffcore.h index eef17c4ca2..4bf175bda9 100644 --- a/diffcore.h +++ b/diffcore.h @@ -48,6 +48,7 @@ extern void fill_filespec(struct diff_filespec *, const unsigned char *, extern int diff_populate_filespec(struct diff_filespec *, int); extern void diff_free_filespec_data(struct diff_filespec *); +extern void diff_free_filespec_data_large(struct diff_filespec *); extern int diff_filespec_is_binary(struct diff_filespec *); struct diff_filepair { -- cgit v1.3 From 8ae92e63895000ff9b12046325ae381f3c17d414 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 2 Oct 2007 21:01:03 -0700 Subject: rename diff_free_filespec_data_large() to diff_free_filespec_blob() Signed-off-by: Junio C Hamano --- diff.c | 4 ++-- diffcore-rename.c | 4 ++-- diffcore.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 35e3c61986..71b340c536 100644 --- a/diff.c +++ b/diff.c @@ -1675,7 +1675,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) return 0; } -void diff_free_filespec_data_large(struct diff_filespec *s) +void diff_free_filespec_blob(struct diff_filespec *s) { if (s->should_free) free(s->data); @@ -1690,7 +1690,7 @@ void diff_free_filespec_data_large(struct diff_filespec *s) void diff_free_filespec_data(struct diff_filespec *s) { - diff_free_filespec_data_large(s); + diff_free_filespec_blob(s); free(s->cnt_data); s->cnt_data = NULL; } diff --git a/diffcore-rename.c b/diffcore-rename.c index 4fc200064a..142e5376dd 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -378,10 +378,10 @@ void diffcore_rename(struct diff_options *options) m->score = estimate_similarity(one, two, minimum_score); m->name_score = basename_same(one, two); - diff_free_filespec_data_large(one); + diff_free_filespec_blob(one); } /* We do not need the text anymore */ - diff_free_filespec_data_large(two); + diff_free_filespec_blob(two); dst_cnt++; } /* cost matrix sorted by most to least similar pair */ diff --git a/diffcore.h b/diffcore.h index 4bf175bda9..eb618b1ec0 100644 --- a/diffcore.h +++ b/diffcore.h @@ -48,7 +48,7 @@ extern void fill_filespec(struct diff_filespec *, const unsigned char *, extern int diff_populate_filespec(struct diff_filespec *, int); extern void diff_free_filespec_data(struct diff_filespec *); -extern void diff_free_filespec_data_large(struct diff_filespec *); +extern void diff_free_filespec_blob(struct diff_filespec *); extern int diff_filespec_is_binary(struct diff_filespec *); struct diff_filepair { -- cgit v1.3 From d5535ec75ce1cdf57ef52b57c58c548121ce99ba Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 19 Oct 2007 21:47:56 +0200 Subject: Use run_command() to spawn external diff programs instead of fork/exec. Signed-off-by: Johannes Sixt Signed-off-by: Shawn O. Pearce --- diff.c | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 6648e01521..30b7544171 100644 --- a/diff.c +++ b/diff.c @@ -9,6 +9,7 @@ #include "xdiff-interface.h" #include "color.h" #include "attr.h" +#include "run-command.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -1748,40 +1749,6 @@ static void remove_tempfile_on_signal(int signo) raise(signo); } -static int spawn_prog(const char *pgm, const char **arg) -{ - pid_t pid; - int status; - - fflush(NULL); - pid = fork(); - if (pid < 0) - die("unable to fork"); - if (!pid) { - execvp(pgm, (char *const*) arg); - exit(255); - } - - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - return -1; - } - - /* Earlier we did not check the exit status because - * diff exits non-zero if files are different, and - * we are not interested in knowing that. It was a - * mistake which made it harder to quit a diff-* - * session that uses the git-apply-patch-script as - * the GIT_EXTERNAL_DIFF. A custom GIT_EXTERNAL_DIFF - * should also exit non-zero only when it wants to - * abort the entire diff-* session. - */ - if (WIFEXITED(status) && !WEXITSTATUS(status)) - return 0; - return -1; -} - /* An external diff command takes: * * diff-cmd name infile1 infile1-sha1 infile1-mode \ @@ -1834,7 +1801,8 @@ static void run_external_diff(const char *pgm, *arg++ = name; } *arg = NULL; - retval = spawn_prog(pgm, spawn_arg); + fflush(NULL); + retval = run_command_v_opt(spawn_arg, 0); remove_tempfile(); if (retval) { fprintf(stderr, "external diff died, stopping at %s.\n", name); -- cgit v1.3 From c32f749fec69f92ce3b076128e6322f8130bd881 Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Sun, 21 Oct 2007 11:23:49 +0200 Subject: Correct some sizeof(size_t) != sizeof(unsigned long) typing errors Fix size_t vs. unsigned long pointer mismatch warnings introduced with the addition of strbuf_detach(). Signed-off-by: Rene Scharfe Signed-off-by: Shawn O. Pearce --- builtin-apply.c | 2 +- builtin-archive.c | 4 +++- diff.c | 8 ++++++-- entry.c | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 05c6bc3592..8411b38c79 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -152,7 +152,7 @@ struct patch { unsigned int is_rename:1; struct fragment *fragments; char *result; - unsigned long resultsize; + size_t resultsize; char old_sha1_prefix[41]; char new_sha1_prefix[41]; struct patch *next; diff --git a/builtin-archive.c b/builtin-archive.c index 04385dea05..6f29c2f40a 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -148,12 +148,14 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1, buffer = read_sha1_file(sha1, type, sizep); if (buffer && S_ISREG(mode)) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); convert_to_archive(path, buf.buf, buf.len, &buf, commit); - buffer = strbuf_detach(&buf, sizep); + buffer = strbuf_detach(&buf, &size); + *sizep = size; } return buffer; diff --git a/diff.c b/diff.c index 6648e01521..dfb8595b70 100644 --- a/diff.c +++ b/diff.c @@ -1512,6 +1512,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int static int populate_from_stdin(struct diff_filespec *s) { struct strbuf buf; + size_t size = 0; strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 0) < 0) @@ -1519,7 +1520,8 @@ static int populate_from_stdin(struct diff_filespec *s) strerror(errno)); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; return 0; } @@ -1609,9 +1611,11 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) */ strbuf_init(&buf, 0); if (convert_to_git(s->path, s->data, s->size, &buf)) { + size_t size = 0; munmap(s->data, s->size); s->should_munmap = 0; - s->data = strbuf_detach(&buf, &s->size); + s->data = strbuf_detach(&buf, &size); + s->size = size; s->should_free = 1; } } diff --git a/entry.c b/entry.c index 98f5f6d4ec..cfadc6a292 100644 --- a/entry.c +++ b/entry.c @@ -119,8 +119,10 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout */ strbuf_init(&buf, 0); if (convert_to_working_tree(ce->name, new, size, &buf)) { + size_t newsize = 0; free(new); - new = strbuf_detach(&buf, &size); + new = strbuf_detach(&buf, &newsize); + size = newsize; } if (to_tempfile) { -- cgit v1.3 From 9fb88419ba85e641006c80db53620423f37f1c93 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:19:10 -0700 Subject: Ref-count the filespecs used by diffcore Rather than copy the filespecs when introducing new versions of them (for rename or copy detection), use a refcount and increment the count when reusing the diff_filespec. This avoids unnecessary allocations, but the real reason behind this is a future enhancement: we will want to track shared data across the copy/rename detection. In order to efficiently notice when a filespec is used by a rename, the rename machinery wants to keep track of a rename usage count which is shared across all different users of the filespec. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 15 +++++++++++---- diffcore-rename.c | 16 ++++++---------- diffcore.h | 2 ++ 3 files changed, 19 insertions(+), 14 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index dfb8595b70..0b320f6b96 100644 --- a/diff.c +++ b/diff.c @@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path) memset(spec, 0, sizeof(*spec)); spec->path = (char *)(spec + 1); memcpy(spec->path, path, namelen+1); + spec->count = 1; return spec; } +void free_filespec(struct diff_filespec *spec) +{ + if (!--spec->count) { + diff_free_filespec_data(spec); + free(spec); + } +} + void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1, unsigned short mode) { @@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue, void diff_free_filepair(struct diff_filepair *p) { - diff_free_filespec_data(p->one); - diff_free_filespec_data(p->two); - free(p->one); - free(p->two); + free_filespec(p->one); + free_filespec(p->two); free(p); } diff --git a/diffcore-rename.c b/diffcore-rename.c index 2077a9b981..3da06b702b 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -209,21 +209,19 @@ static int estimate_similarity(struct diff_filespec *src, static void record_rename_pair(int dst_index, int src_index, int score) { - struct diff_filespec *one, *two, *src, *dst; + struct diff_filespec *src, *dst; struct diff_filepair *dp; if (rename_dst[dst_index].pair) die("internal error: dst already matched."); src = rename_src[src_index].one; - one = alloc_filespec(src->path); - fill_filespec(one, src->sha1, src->mode); + src->count++; dst = rename_dst[dst_index].two; - two = alloc_filespec(dst->path); - fill_filespec(two, dst->sha1, dst->mode); + dst->count++; - dp = diff_queue(NULL, one, two); + dp = diff_queue(NULL, src, dst); dp->renamed_pair = 1; if (!strcmp(src->path, dst->path)) dp->score = rename_src[src_index].score; @@ -526,10 +524,8 @@ void diffcore_rename(struct diff_options *options) } } - for (i = 0; i < rename_dst_nr; i++) { - diff_free_filespec_data(rename_dst[i].two); - free(rename_dst[i].two); - } + for (i = 0; i < rename_dst_nr; i++) + free_filespec(rename_dst[i].two); free(rename_dst); rename_dst = NULL; diff --git a/diffcore.h b/diffcore.h index eb618b1ec0..30055ac5a9 100644 --- a/diffcore.h +++ b/diffcore.h @@ -29,6 +29,7 @@ struct diff_filespec { void *cnt_data; const char *funcname_pattern_ident; unsigned long size; + int count; /* Reference count */ int xfrm_flags; /* for use by the xfrm */ unsigned short mode; /* file mode */ unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; @@ -43,6 +44,7 @@ struct diff_filespec { }; extern struct diff_filespec *alloc_filespec(const char *); +extern void free_filespec(struct diff_filespec *); extern void fill_filespec(struct diff_filespec *, const unsigned char *, unsigned short); -- cgit v1.3 From 644797119d7a3b7a043a51a9cccd8758f8451f91 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 25 Oct 2007 11:20:56 -0700 Subject: copy vs rename detection: avoid unnecessary O(n*m) loops The core rename detection had some rather stupid code to check if a pathname was used by a later modification or rename, which basically walked the whole pathname space for all renames for each rename, in order to tell whether it was a pure rename (no remaining users) or should be considered a copy (other users of the source file remaining). That's really silly, since we can just keep a count of users around, and replace all those complex and expensive loops with just testing that simple counter (but this all depends on the previous commit that shared the diff_filespec data structure by using a separate reference count). Note that the reference count is not the same as the rename count: they behave otherwise rather similarly, but the reference count is tied to the allocation (and decremented at de-allocation, so that when it turns zero we can get rid of the memory), while the rename count is tied to the renames and is decremented when we find a rename (so that when it turns zero we know that it was a rename, not a copy). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 40 ++++++++++++++------------------ diffcore-rename.c | 68 ++++++++++++++----------------------------------------- diffcore.h | 2 +- 3 files changed, 35 insertions(+), 75 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 0b320f6b96..af85b94d1b 100644 --- a/diff.c +++ b/diff.c @@ -2597,9 +2597,9 @@ void diff_debug_filepair(const struct diff_filepair *p, int i) { diff_debug_filespec(p->one, i, "one"); diff_debug_filespec(p->two, i, "two"); - fprintf(stderr, "score %d, status %c stays %d broken %d\n", + fprintf(stderr, "score %d, status %c rename_used %d broken %d\n", p->score, p->status ? p->status : '?', - p->source_stays, p->broken_pair); + p->one->rename_used, p->broken_pair); } void diff_debug_queue(const char *msg, struct diff_queue_struct *q) @@ -2617,8 +2617,8 @@ void diff_debug_queue(const char *msg, struct diff_queue_struct *q) static void diff_resolve_rename_copy(void) { - int i, j; - struct diff_filepair *p, *pp; + int i; + struct diff_filepair *p; struct diff_queue_struct *q = &diff_queued_diff; diff_debug_queue("resolve-rename-copy", q); @@ -2640,27 +2640,21 @@ static void diff_resolve_rename_copy(void) * either in-place edit or rename/copy edit. */ else if (DIFF_PAIR_RENAME(p)) { - if (p->source_stays) { - p->status = DIFF_STATUS_COPIED; - continue; - } - /* See if there is some other filepair that - * copies from the same source as us. If so - * we are a copy. Otherwise we are either a - * copy if the path stays, or a rename if it - * does not, but we already handled "stays" case. + /* + * A rename might have re-connected a broken + * pair up, causing the pathnames to be the + * same again. If so, that's not a rename at + * all, just a modification.. + * + * Otherwise, see if this source was used for + * multiple renames, in which case we decrement + * the count, and call it a copy. */ - for (j = i + 1; j < q->nr; j++) { - pp = q->queue[j]; - if (strcmp(pp->one->path, p->one->path)) - continue; /* not us */ - if (!DIFF_PAIR_RENAME(pp)) - continue; /* not a rename/copy */ - /* pp is a rename/copy from the same source */ + if (!strcmp(p->one->path, p->two->path)) + p->status = DIFF_STATUS_MODIFIED; + else if (--p->one->rename_used > 0) p->status = DIFF_STATUS_COPIED; - break; - } - if (!p->status) + else p->status = DIFF_STATUS_RENAMED; } else if (hashcmp(p->one->sha1, p->two->sha1) || diff --git a/diffcore-rename.c b/diffcore-rename.c index 3da06b702b..edb2424d13 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -55,12 +55,10 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two, static struct diff_rename_src { struct diff_filespec *one; unsigned short score; /* to remember the break score */ - unsigned src_path_left : 1; } *rename_src; static int rename_src_nr, rename_src_alloc; static struct diff_rename_src *register_rename_src(struct diff_filespec *one, - int src_path_left, unsigned short score) { int first, last; @@ -92,7 +90,6 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one, (rename_src_nr - first - 1) * sizeof(*rename_src)); rename_src[first].one = one; rename_src[first].score = score; - rename_src[first].src_path_left = src_path_left; return &(rename_src[first]); } @@ -216,6 +213,7 @@ static void record_rename_pair(int dst_index, int src_index, int score) die("internal error: dst already matched."); src = rename_src[src_index].one; + src->rename_used++; src->count++; dst = rename_dst[dst_index].two; @@ -227,7 +225,6 @@ static void record_rename_pair(int dst_index, int src_index, int score) dp->score = rename_src[src_index].score; else dp->score = score; - dp->source_stays = rename_src[src_index].src_path_left; rename_dst[dst_index].pair = dp; } @@ -245,21 +242,6 @@ static int score_compare(const void *a_, const void *b_) return b->score - a->score; } -static int compute_stays(struct diff_queue_struct *q, - struct diff_filespec *one) -{ - int i; - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (strcmp(one->path, p->two->path)) - continue; - if (DIFF_PAIR_RENAME(p)) { - return 0; /* something else is renamed into this */ - } - } - return 1; -} - /* * Find exact renames first. * @@ -338,15 +320,25 @@ void diffcore_rename(struct diff_options *options) locate_rename_dst(p->two, 1); } else if (!DIFF_FILE_VALID(p->two)) { - /* If the source is a broken "delete", and + /* + * If the source is a broken "delete", and * they did not really want to get broken, * that means the source actually stays. + * So we increment the "rename_used" score + * by one, to indicate ourselves as a user + */ + if (p->broken_pair && !p->score) + p->one->rename_used++; + register_rename_src(p->one, p->score); + } + else if (detect_rename == DIFF_DETECT_COPY) { + /* + * Increment the "rename_used" score by + * one, to indicate ourselves as a user. */ - int stays = (p->broken_pair && !p->score); - register_rename_src(p->one, stays, p->score); + p->one->rename_used++; + register_rename_src(p->one, p->score); } - else if (detect_rename == DIFF_DETECT_COPY) - register_rename_src(p->one, 1, p->score); } if (rename_dst_nr == 0 || rename_src_nr == 0) goto cleanup; /* nothing to do */ @@ -472,16 +464,7 @@ void diffcore_rename(struct diff_options *options) pair_to_free = p; } else { - for (j = 0; j < rename_dst_nr; j++) { - if (!rename_dst[j].pair) - continue; - if (strcmp(rename_dst[j].pair-> - one->path, - p->one->path)) - continue; - break; - } - if (j < rename_dst_nr) + if (p->one->rename_used) /* this path remains */ pair_to_free = p; } @@ -507,23 +490,6 @@ void diffcore_rename(struct diff_options *options) *q = outq; diff_debug_queue("done collapsing", q); - /* We need to see which rename source really stays here; - * earlier we only checked if the path is left in the result, - * but even if a path remains in the result, if that is coming - * from copying something else on top of it, then the original - * source is lost and does not stay. - */ - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (DIFF_PAIR_RENAME(p) && p->source_stays) { - /* If one appears as the target of a rename-copy, - * then mark p->source_stays = 0; otherwise - * leave it as is. - */ - p->source_stays = compute_stays(q, p->one); - } - } - for (i = 0; i < rename_dst_nr; i++) free_filespec(rename_dst[i].two); diff --git a/diffcore.h b/diffcore.h index 30055ac5a9..cc96c20734 100644 --- a/diffcore.h +++ b/diffcore.h @@ -31,6 +31,7 @@ struct diff_filespec { unsigned long size; int count; /* Reference count */ int xfrm_flags; /* for use by the xfrm */ + int rename_used; /* Count of rename users */ unsigned short mode; /* file mode */ unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; * if false, use the name and read from @@ -58,7 +59,6 @@ struct diff_filepair { struct diff_filespec *two; unsigned short int score; char status; /* M C R N D U (see Documentation/diff-format.txt) */ - unsigned source_stays : 1; /* all of R/C are copies */ unsigned broken_pair : 1; unsigned renamed_pair : 1; unsigned is_unmerged : 1; -- cgit v1.3 From a9cc857ada7c57069ff00eed8d0addcf55849f39 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 2 Nov 2007 00:24:27 -0700 Subject: War on whitespace: first, a bit of retreat. This introduces core.whitespace configuration variable that lets you specify the definition of "whitespace error". Currently there are two kinds of whitespace errors defined: * trailing-space: trailing whitespaces at the end of the line. * space-before-tab: a SP appears immediately before HT in the indent part of the line. You can specify the desired types of errors to be detected by listing their names (unique abbreviations are accepted) separated by comma. By default, these two errors are always detected, as that is the traditional behaviour. You can disable detection of a particular type of error by prefixing a '-' in front of the name of the error, like this: [core] whitespace = -trailing-space This patch teaches the code to output colored diff with DIFF_WHITESPACE color to highlight the detected whitespace errors to honor the new configuration. Signed-off-by: Junio C Hamano --- cache.h | 9 +++++++++ config.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ diff.c | 13 ++++++++----- environment.c | 1 + 4 files changed, 70 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/cache.h b/cache.h index bfffa05dff..a6e5988f07 100644 --- a/cache.h +++ b/cache.h @@ -602,4 +602,13 @@ extern int diff_auto_refresh_index; /* match-trees.c */ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int); +/* + * whitespace rules. + * used by both diff and apply + */ +#define WS_TRAILING_SPACE 01 +#define WS_SPACE_BEFORE_TAB 02 +#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) +extern unsigned whitespace_rule; + #endif /* CACHE_H */ diff --git a/config.c b/config.c index dc3148d456..ffb418ccff 100644 --- a/config.c +++ b/config.c @@ -246,6 +246,53 @@ static unsigned long get_unit_factor(const char *end) die("unknown unit: '%s'", end); } +static struct whitespace_rule { + const char *rule_name; + unsigned rule_bits; +} whitespace_rule_names[] = { + { "trailing-space", WS_TRAILING_SPACE }, + { "space-before-tab", WS_SPACE_BEFORE_TAB }, +}; + +static unsigned parse_whitespace_rule(const char *string) +{ + unsigned rule = WS_DEFAULT_RULE; + + while (string) { + int i; + size_t len; + const char *ep; + int negated = 0; + + string = string + strspn(string, ", \t\n\r"); + ep = strchr(string, ','); + if (!ep) + len = strlen(string); + else + len = ep - string; + + if (*string == '-') { + negated = 1; + string++; + len--; + } + if (!len) + break; + for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) { + if (strncmp(whitespace_rule_names[i].rule_name, + string, len)) + continue; + if (negated) + rule &= ~whitespace_rule_names[i].rule_bits; + else + rule |= whitespace_rule_names[i].rule_bits; + break; + } + string = ep; + } + return rule; +} + int git_parse_long(const char *value, long *ret) { if (value && *value) { @@ -431,6 +478,11 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.whitespace")) { + whitespace_rule = parse_whitespace_rule(value); + return 0; + } + /* Add other config variables here and to Documentation/config.txt. */ return 0; } diff --git a/diff.c b/diff.c index a6aaaf7e5a..211235376d 100644 --- a/diff.c +++ b/diff.c @@ -508,7 +508,8 @@ static void emit_line_with_ws(int nparents, for (i = col0; i < len; i++) { if (line[i] == '\t') { last_tab_in_indent = i; - if (0 <= last_space_in_indent) + if ((whitespace_rule & WS_SPACE_BEFORE_TAB) && + 0 <= last_space_in_indent) need_highlight_leading_space = 1; } else if (line[i] == ' ') @@ -540,10 +541,12 @@ static void emit_line_with_ws(int nparents, tail = len - 1; if (line[tail] == '\n' && i < tail) tail--; - while (i < tail) { - if (!isspace(line[tail])) - break; - tail--; + if (whitespace_rule & WS_TRAILING_SPACE) { + while (i < tail) { + if (!isspace(line[tail])) + break; + tail--; + } } if ((i < tail && line[tail + 1] != '\n')) { /* This has whitespace between tail+1..len */ diff --git a/environment.c b/environment.c index b5a6c69f7c..624dd9677c 100644 --- a/environment.c +++ b/environment.c @@ -35,6 +35,7 @@ int pager_in_use; int pager_use_color = 1; char *editor_program; int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ +unsigned whitespace_rule = WS_DEFAULT_RULE; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; -- cgit v1.3 From 459fa6d0fe6a45b8b120463b56a68e943e3a8101 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 2 Oct 2007 18:00:27 -0700 Subject: git-diff: complain about >=8 consecutive spaces in initial indent This introduces a new whitespace error type, "indent-with-non-tab". The error is about starting a line with 8 or more SP, instead of indenting it with a HT. This is not enabled by default, as some projects employ an indenting policy to use only SPs and no HTs. The kernel folks and git contributors may want to enable this detection with: [core] whitespace = indent-with-non-tab Signed-off-by: Junio C Hamano --- cache.h | 1 + config.c | 1 + diff.c | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/cache.h b/cache.h index a6e5988f07..3f4282795e 100644 --- a/cache.h +++ b/cache.h @@ -608,6 +608,7 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i */ #define WS_TRAILING_SPACE 01 #define WS_SPACE_BEFORE_TAB 02 +#define WS_INDENT_WITH_NON_TAB 04 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) extern unsigned whitespace_rule; diff --git a/config.c b/config.c index ffb418ccff..d5b976696c 100644 --- a/config.c +++ b/config.c @@ -252,6 +252,7 @@ static struct whitespace_rule { } whitespace_rule_names[] = { { "trailing-space", WS_TRAILING_SPACE }, { "space-before-tab", WS_SPACE_BEFORE_TAB }, + { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB }, }; static unsigned parse_whitespace_rule(const char *string) diff --git a/diff.c b/diff.c index 211235376d..6bb902f4af 100644 --- a/diff.c +++ b/diff.c @@ -502,8 +502,11 @@ static void emit_line_with_ws(int nparents, int i; int tail = len; int need_highlight_leading_space = 0; - /* The line is a newly added line. Does it have funny leading - * whitespaces? In indent, SP should never precede a TAB. + /* + * The line is a newly added line. Does it have funny leading + * whitespaces? In indent, SP should never precede a TAB. In + * addition, under "indent with non tab" rule, there should not + * be more than 8 consecutive spaces. */ for (i = col0; i < len; i++) { if (line[i] == '\t') { @@ -517,6 +520,13 @@ static void emit_line_with_ws(int nparents, else break; } + if ((whitespace_rule & WS_INDENT_WITH_NON_TAB) && + 0 <= last_space_in_indent && + last_tab_in_indent < 0 && + 8 <= (i - col0)) { + last_tab_in_indent = i; + need_highlight_leading_space = 1; + } fputs(set, stdout); fwrite(line, col0, 1, stdout); fputs(reset, stdout); -- cgit v1.3 From 8f67f8aefb1b751073f8b36fae8be8f72eb93f4a Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Sat, 10 Nov 2007 20:05:14 +0100 Subject: Make the diff_options bitfields be an unsigned with explicit masks. reverse_diff was a bit-value in disguise, it's merged in the flags now. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- builtin-blame.c | 10 ++--- builtin-diff-files.c | 4 +- builtin-diff-index.c | 4 +- builtin-diff-tree.c | 7 +-- builtin-diff.c | 12 ++--- builtin-log.c | 24 +++++----- combine-diff.c | 10 ++--- diff-lib.c | 24 +++++----- diff.c | 123 +++++++++++++++++++++++++-------------------------- diff.h | 40 ++++++++++------- log-tree.c | 6 +-- merge-recursive.c | 2 +- patch-ids.c | 2 +- revision.c | 22 ++++----- tree-diff.c | 14 +++--- 15 files changed, 155 insertions(+), 149 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index ba80bf8942..c158d319dc 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -335,7 +335,7 @@ static struct origin *find_origin(struct scoreboard *sb, * same and diff-tree is fairly efficient about this. */ diff_setup(&diff_opts); - diff_opts.recursive = 1; + DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.detect_rename = 0; diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; paths[0] = origin->path; @@ -409,7 +409,7 @@ static struct origin *find_rename(struct scoreboard *sb, const char *paths[2]; diff_setup(&diff_opts); - diff_opts.recursive = 1; + DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.detect_rename = DIFF_DETECT_RENAME; diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_opts.single_follow = origin->path; @@ -1075,7 +1075,7 @@ static int find_copy_in_parent(struct scoreboard *sb, return 1; /* nothing remains for this target */ diff_setup(&diff_opts); - diff_opts.recursive = 1; + DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; paths[0] = NULL; @@ -1093,7 +1093,7 @@ static int find_copy_in_parent(struct scoreboard *sb, if ((opt & PICKAXE_BLAME_COPY_HARDEST) || ((opt & PICKAXE_BLAME_COPY_HARDER) && (!porigin || strcmp(target->path, porigin->path)))) - diff_opts.find_copies_harder = 1; + DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER); if (is_null_sha1(target->commit->object.sha1)) do_diff_cache(parent->tree->object.sha1, &diff_opts); @@ -1102,7 +1102,7 @@ static int find_copy_in_parent(struct scoreboard *sb, target->commit->tree->object.sha1, "", &diff_opts); - if (!diff_opts.find_copies_harder) + if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER)) diffcore_std(&diff_opts); retval = 0; diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 6cb30c8e12..046b7e34b5 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -31,5 +31,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_RAW; result = run_diff_files_cmd(&rev, argc, argv); - return rev.diffopt.exit_with_status ? rev.diffopt.has_changes: result; + if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) + return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; + return result; } diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 81e7167438..556c506bfa 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -44,5 +44,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) return -1; } result = run_diff_index(&rev, cached); - return rev.diffopt.exit_with_status ? rev.diffopt.has_changes: result; + if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) + return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; + return result; } diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 0b591c8716..2e13716eec 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -118,8 +118,8 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) } if (!read_stdin) - return opt->diffopt.exit_with_status ? - opt->diffopt.has_changes: 0; + return DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS) + && DIFF_OPT_TST(&opt->diffopt, HAS_CHANGES); if (opt->diffopt.detect_rename) opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | @@ -134,5 +134,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) else diff_tree_stdin(line); } - return opt->diffopt.exit_with_status ? opt->diffopt.has_changes: 0; + return DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS) + && DIFF_OPT_TST(&opt->diffopt, HAS_CHANGES); } diff --git a/builtin-diff.c b/builtin-diff.c index f557d21929..1b615991e1 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -35,7 +35,7 @@ static void stuff_change(struct diff_options *opt, !hashcmp(old_sha1, new_sha1) && (old_mode == new_mode)) return; - if (opt->reverse_diff) { + if (DIFF_OPT_TST(opt, REVERSE_DIFF)) { unsigned tmp; const unsigned char *tmp_u; const char *tmp_c; @@ -253,13 +253,13 @@ int cmd_diff(int argc, const char **argv, const char *prefix) if (diff_setup_done(&rev.diffopt) < 0) die("diff_setup_done failed"); } - rev.diffopt.allow_external = 1; - rev.diffopt.recursive = 1; + DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); + DIFF_OPT_SET(&rev.diffopt, RECURSIVE); /* If the user asked for our exit code then don't start a * pager or we would end up reporting its exit code instead. */ - if (!rev.diffopt.exit_with_status) + if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) setup_pager(); /* Do we have --cached and not have a pending object, then @@ -363,8 +363,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix) else result = builtin_diff_combined(&rev, argc, argv, ent, ents); - if (rev.diffopt.exit_with_status) - result = rev.diffopt.has_changes; + if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) + result = DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); diff --git a/builtin-log.c b/builtin-log.c index 8b2bf632c5..b69b0b42f1 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -55,13 +55,13 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; rev->verbose_header = 1; - rev->diffopt.recursive = 1; + DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; - if (rev->diffopt.follow_renames) { + if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) { rev->always_show_header = 0; if (rev->diffopt.nr_paths != 1) usage("git logs can only follow renames on one pathname at a time"); @@ -185,11 +185,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) struct tag *t = (struct tag *)o; printf("%stag %s%s\n\n", - diff_get_color(rev.diffopt.color_diff, - DIFF_COMMIT), + diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), t->tag, - diff_get_color(rev.diffopt.color_diff, - DIFF_RESET)); + diff_get_color_opt(&rev.diffopt, DIFF_RESET)); ret = show_object(o->sha1, 1); objects[i].item = (struct object *)t->tagged; i--; @@ -197,11 +195,9 @@ int cmd_show(int argc, const char **argv, const char *prefix) } case OBJ_TREE: printf("%stree %s%s\n\n", - diff_get_color(rev.diffopt.color_diff, - DIFF_COMMIT), + diff_get_color_opt(&rev.diffopt, DIFF_COMMIT), name, - diff_get_color(rev.diffopt.color_diff, - DIFF_RESET)); + diff_get_color_opt(&rev.diffopt, DIFF_RESET)); read_tree_recursive((struct tree *)o, "", 0, 0, NULL, show_tree_object); break; @@ -487,7 +483,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.combine_merges = 0; rev.ignore_merges = 1; rev.diffopt.msg_sep = ""; - rev.diffopt.recursive = 1; + DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; rev.extra_headers = extra_headers; @@ -590,8 +586,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH; - if (!rev.diffopt.text) - rev.diffopt.binary = 1; + if (!DIFF_OPT_TST(&rev.diffopt, TEXT)) + DIFF_OPT_SET(&rev.diffopt, BINARY); if (!output_directory && !use_stdout) output_directory = prefix; @@ -747,7 +743,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) revs.diff = 1; revs.combine_merges = 0; revs.ignore_merges = 1; - revs.diffopt.recursive = 1; + DIFF_OPT_SET(&revs.diffopt, RECURSIVE); if (add_pending_commit(head, &revs, 0)) die("Unknown commit %s", head); diff --git a/combine-diff.c b/combine-diff.c index fe5a2a1953..5a658dc0d5 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -664,7 +664,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int mode_differs = 0; int i, show_hunks; int working_tree_file = is_null_sha1(elem->sha1); - int abbrev = opt->full_index ? 40 : DEFAULT_ABBREV; + int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; mmfile_t result_file; context = opt->context; @@ -784,7 +784,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, if (show_hunks || mode_differs || working_tree_file) { const char *abb; - int use_color = opt->color_diff; + int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); const char *c_reset = diff_get_color(use_color, DIFF_RESET); int added = 0; @@ -836,7 +836,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, dump_quoted_path("+++ /dev/", "null", c_meta, c_reset); else dump_quoted_path("+++ b/", elem->path, c_meta, c_reset); - dump_sline(sline, cnt, num_parent, opt->color_diff); + dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF)); } free(result); @@ -929,8 +929,8 @@ void diff_tree_combined(const unsigned char *sha1, diffopts = *opt; diffopts.output_format = DIFF_FORMAT_NO_OUTPUT; - diffopts.recursive = 1; - diffopts.allow_external = 0; + DIFF_OPT_SET(&diffopts, RECURSIVE); + DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL); show_log_first = !!rev->loginfo && !rev->no_commit_id; needsep = 0; diff --git a/diff-lib.c b/diff-lib.c index da5571302d..290a170b05 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -121,7 +121,7 @@ static int queue_diff(struct diff_options *o, } else { struct diff_filespec *d1, *d2; - if (o->reverse_diff) { + if (DIFF_OPT_TST(o, REVERSE_DIFF)) { unsigned tmp; const char *tmp_c; tmp = mode1; mode1 = mode2; mode2 = tmp; @@ -188,8 +188,8 @@ static int handle_diff_files_args(struct rev_info *revs, else if (!strcmp(argv[1], "-n") || !strcmp(argv[1], "--no-index")) { revs->max_count = -2; - revs->diffopt.exit_with_status = 1; - revs->diffopt.no_index = 1; + DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS); + DIFF_OPT_SET(&revs->diffopt, NO_INDEX); } else if (!strcmp(argv[1], "-q")) *silent = 1; @@ -207,7 +207,7 @@ static int handle_diff_files_args(struct rev_info *revs, if (!is_in_index(revs->diffopt.paths[0]) || !is_in_index(revs->diffopt.paths[1])) { revs->max_count = -2; - revs->diffopt.no_index = 1; + DIFF_OPT_SET(&revs->diffopt, NO_INDEX); } } @@ -258,7 +258,7 @@ int setup_diff_no_index(struct rev_info *revs, break; } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) { i = argc - 3; - revs->diffopt.exit_with_status = 1; + DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS); break; } if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) && @@ -296,7 +296,7 @@ int setup_diff_no_index(struct rev_info *revs, else revs->diffopt.paths = argv + argc - 2; revs->diffopt.nr_paths = 2; - revs->diffopt.no_index = 1; + DIFF_OPT_SET(&revs->diffopt, NO_INDEX); revs->max_count = -2; if (diff_setup_done(&revs->diffopt) < 0) die("diff_setup_done failed"); @@ -310,7 +310,7 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) if (handle_diff_files_args(revs, argc, argv, &silent_on_removed)) return -1; - if (revs->diffopt.no_index) { + if (DIFF_OPT_TST(&revs->diffopt, NO_INDEX)) { if (revs->diffopt.nr_paths != 2) return error("need two files/directories with --no-index"); if (queue_diff(&revs->diffopt, revs->diffopt.paths[0], @@ -346,7 +346,8 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) struct cache_entry *ce = active_cache[i]; int changed; - if (revs->diffopt.quiet && revs->diffopt.has_changes) + if (DIFF_OPT_TST(&revs->diffopt, QUIET) && + DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES)) break; if (!ce_path_match(ce, revs->prune_data)) @@ -442,7 +443,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) continue; } changed = ce_match_stat(ce, &st, 0); - if (!changed && !revs->diffopt.find_copies_harder) + if (!changed && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) continue; oldmode = ntohl(ce->ce_mode); newmode = ntohl(ce_mode_from_stat(ce, st.st_mode)); @@ -561,7 +562,7 @@ static int show_modified(struct rev_info *revs, oldmode = old->ce_mode; if (mode == oldmode && !hashcmp(sha1, old->sha1) && - !revs->diffopt.find_copies_harder) + !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER)) return 0; mode = ntohl(mode); @@ -581,7 +582,8 @@ static int diff_cache(struct rev_info *revs, struct cache_entry *ce = *ac; int same = (entries > 1) && ce_same_name(ce, ac[1]); - if (revs->diffopt.quiet && revs->diffopt.has_changes) + if (DIFF_OPT_TST(&revs->diffopt, QUIET) && + DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES)) break; if (!ce_path_match(ce, pathspec)) diff --git a/diff.c b/diff.c index a6aaaf7e5a..67cce8b72e 100644 --- a/diff.c +++ b/diff.c @@ -814,10 +814,10 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) } /* Find the longest filename and max number of changes */ - reset = diff_get_color(options->color_diff, DIFF_RESET); - set = diff_get_color(options->color_diff, DIFF_PLAIN); - add_c = diff_get_color(options->color_diff, DIFF_FILE_NEW); - del_c = diff_get_color(options->color_diff, DIFF_FILE_OLD); + reset = diff_get_color_opt(options, DIFF_RESET); + set = diff_get_color_opt(options, DIFF_PLAIN); + add_c = diff_get_color_opt(options, DIFF_FILE_NEW); + del_c = diff_get_color_opt(options, DIFF_FILE_OLD); for (i = 0; i < data->nr; i++) { struct diffstat_file *file = data->files[i]; @@ -1243,8 +1243,8 @@ static void builtin_diff(const char *name_a, mmfile_t mf1, mf2; const char *lbl[2]; char *a_one, *b_two; - const char *set = diff_get_color(o->color_diff, DIFF_METAINFO); - const char *reset = diff_get_color(o->color_diff, DIFF_RESET); + const char *set = diff_get_color_opt(o, DIFF_METAINFO); + const char *reset = diff_get_color_opt(o, DIFF_RESET); a_one = quote_two("a/", name_a + (*name_a == '/')); b_two = quote_two("b/", name_b + (*name_b == '/')); @@ -1277,7 +1277,7 @@ static void builtin_diff(const char *name_a, goto free_ab_and_return; if (complete_rewrite) { emit_rewrite_diff(name_a, name_b, one, two, - o->color_diff); + DIFF_OPT_TST(o, COLOR_DIFF)); o->found_changes = 1; goto free_ab_and_return; } @@ -1286,13 +1286,13 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (!o->text && + if (!DIFF_OPT_TST(o, TEXT) && (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) { /* Quite common confusing case */ if (mf1.size == mf2.size && !memcmp(mf1.ptr, mf2.ptr, mf1.size)) goto free_ab_and_return; - if (o->binary) + if (DIFF_OPT_TST(o, BINARY)) emit_binary_diff(&mf1, &mf2); else printf("Binary files %s and %s differ\n", @@ -1315,7 +1315,7 @@ static void builtin_diff(const char *name_a, memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; - ecbdata.color_diff = o->color_diff; + ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); ecbdata.found_changesp = &o->found_changes; xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; @@ -1331,11 +1331,11 @@ static void builtin_diff(const char *name_a, ecb.outf = xdiff_outf; ecb.priv = &ecbdata; ecbdata.xm.consume = fn_out_consume; - if (o->color_diff_words) + if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); - if (o->color_diff_words) + if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); } @@ -1409,7 +1409,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, data.xm.consume = checkdiff_consume; data.filename = name_b ? name_b : name_a; data.lineno = 0; - data.color_diff = o->color_diff; + data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); @@ -1853,7 +1853,7 @@ static void run_diff_cmd(const char *pgm, struct diff_options *o, int complete_rewrite) { - if (!o->allow_external) + if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL)) pgm = NULL; else { const char *cmd = external_diff_attr(name); @@ -1951,9 +1951,9 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) } if (hashcmp(one->sha1, two->sha1)) { - int abbrev = o->full_index ? 40 : DEFAULT_ABBREV; + int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV; - if (o->binary) { + if (DIFF_OPT_TST(o, BINARY)) { mmfile_t mf; if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) || (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) @@ -2045,7 +2045,10 @@ void diff_setup(struct diff_options *options) options->change = diff_change; options->add_remove = diff_addremove; - options->color_diff = diff_use_color_default; + if (diff_use_color_default) + DIFF_OPT_SET(options, COLOR_DIFF); + else + DIFF_OPT_CLR(options, COLOR_DIFF); options->detect_rename = diff_detect_rename_default; } @@ -2064,7 +2067,7 @@ int diff_setup_done(struct diff_options *options) if (count > 1) die("--name-only, --name-status, --check and -s are mutually exclusive"); - if (options->find_copies_harder) + if (DIFF_OPT_TST(options, FIND_COPIES_HARDER)) options->detect_rename = DIFF_DETECT_COPY; if (options->output_format & (DIFF_FORMAT_NAME | @@ -2088,12 +2091,12 @@ int diff_setup_done(struct diff_options *options) DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_CHECKDIFF)) - options->recursive = 1; + DIFF_OPT_SET(options, RECURSIVE); /* * Also pickaxe would not work very well if you do not say recursive */ if (options->pickaxe) - options->recursive = 1; + DIFF_OPT_SET(options, RECURSIVE); if (options->detect_rename && options->rename_limit < 0) options->rename_limit = diff_rename_limit_default; @@ -2115,9 +2118,9 @@ int diff_setup_done(struct diff_options *options) * to have found. It does not make sense not to return with * exit code in such a case either. */ - if (options->quiet) { + if (DIFF_OPT_TST(options, QUIET)) { options->output_format = DIFF_FORMAT_NO_OUTPUT; - options->exit_with_status = 1; + DIFF_OPT_SET(options, EXIT_WITH_STATUS); } /* @@ -2125,7 +2128,7 @@ int diff_setup_done(struct diff_options *options) * upon the first hit. We need to run diff as usual. */ if (options->pickaxe || options->filter) - options->quiet = 0; + DIFF_OPT_CLR(options, QUIET); return 0; } @@ -2188,15 +2191,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_PATCH; else if (!strcmp(arg, "--raw")) options->output_format |= DIFF_FORMAT_RAW; - else if (!strcmp(arg, "--patch-with-raw")) { + else if (!strcmp(arg, "--patch-with-raw")) options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW; - } - else if (!strcmp(arg, "--numstat")) { + else if (!strcmp(arg, "--numstat")) options->output_format |= DIFF_FORMAT_NUMSTAT; - } - else if (!strcmp(arg, "--shortstat")) { + else if (!strcmp(arg, "--shortstat")) options->output_format |= DIFF_FORMAT_SHORTSTAT; - } else if (!prefixcmp(arg, "--stat")) { char *end; int width = options->stat_width; @@ -2228,33 +2228,30 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_CHECKDIFF; else if (!strcmp(arg, "--summary")) options->output_format |= DIFF_FORMAT_SUMMARY; - else if (!strcmp(arg, "--patch-with-stat")) { + else if (!strcmp(arg, "--patch-with-stat")) options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT; - } else if (!strcmp(arg, "-z")) options->line_termination = 0; else if (!prefixcmp(arg, "-l")) options->rename_limit = strtoul(arg+2, NULL, 10); else if (!strcmp(arg, "--full-index")) - options->full_index = 1; + DIFF_OPT_SET(options, FULL_INDEX); else if (!strcmp(arg, "--binary")) { options->output_format |= DIFF_FORMAT_PATCH; - options->binary = 1; - } - else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) { - options->text = 1; + DIFF_OPT_SET(options, BINARY); } + else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) + DIFF_OPT_SET(options, TEXT); else if (!strcmp(arg, "--name-only")) options->output_format |= DIFF_FORMAT_NAME; else if (!strcmp(arg, "--name-status")) options->output_format |= DIFF_FORMAT_NAME_STATUS; else if (!strcmp(arg, "-R")) - options->reverse_diff = 1; + DIFF_OPT_SET(options, REVERSE_DIFF); else if (!prefixcmp(arg, "-S")) options->pickaxe = arg + 2; - else if (!strcmp(arg, "-s")) { + else if (!strcmp(arg, "-s")) options->output_format |= DIFF_FORMAT_NO_OUTPUT; - } else if (!prefixcmp(arg, "-O")) options->orderfile = arg + 2; else if (!prefixcmp(arg, "--diff-filter=")) @@ -2264,28 +2261,25 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (!strcmp(arg, "--pickaxe-regex")) options->pickaxe_opts = DIFF_PICKAXE_REGEX; else if (!prefixcmp(arg, "-B")) { - if ((options->break_opt = - diff_scoreopt_parse(arg)) == -1) + if ((options->break_opt = diff_scoreopt_parse(arg)) == -1) return -1; } else if (!prefixcmp(arg, "-M")) { - if ((options->rename_score = - diff_scoreopt_parse(arg)) == -1) + if ((options->rename_score = diff_scoreopt_parse(arg)) == -1) return -1; options->detect_rename = DIFF_DETECT_RENAME; } else if (!prefixcmp(arg, "-C")) { if (options->detect_rename == DIFF_DETECT_COPY) - options->find_copies_harder = 1; - if ((options->rename_score = - diff_scoreopt_parse(arg)) == -1) + DIFF_OPT_SET(options, FIND_COPIES_HARDER); + if ((options->rename_score = diff_scoreopt_parse(arg)) == -1) return -1; options->detect_rename = DIFF_DETECT_COPY; } else if (!strcmp(arg, "--find-copies-harder")) - options->find_copies_harder = 1; + DIFF_OPT_SET(options, FIND_COPIES_HARDER); else if (!strcmp(arg, "--follow")) - options->follow_renames = 1; + DIFF_OPT_SET(options, FOLLOW_RENAMES); else if (!strcmp(arg, "--abbrev")) options->abbrev = DEFAULT_ABBREV; else if (!prefixcmp(arg, "--abbrev=")) { @@ -2296,9 +2290,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->abbrev = 40; } else if (!strcmp(arg, "--color")) - options->color_diff = 1; + DIFF_OPT_SET(options, COLOR_DIFF); else if (!strcmp(arg, "--no-color")) - options->color_diff = 0; + DIFF_OPT_CLR(options, COLOR_DIFF); else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) options->xdl_opts |= XDF_IGNORE_WHITESPACE; else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) @@ -2306,17 +2300,17 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (!strcmp(arg, "--ignore-space-at-eol")) options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL; else if (!strcmp(arg, "--color-words")) - options->color_diff = options->color_diff_words = 1; + options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; else if (!strcmp(arg, "--no-renames")) options->detect_rename = 0; else if (!strcmp(arg, "--exit-code")) - options->exit_with_status = 1; + DIFF_OPT_SET(options, EXIT_WITH_STATUS); else if (!strcmp(arg, "--quiet")) - options->quiet = 1; + DIFF_OPT_SET(options, QUIET); else if (!strcmp(arg, "--ext-diff")) - options->allow_external = 1; + DIFF_OPT_SET(options, ALLOW_EXTERNAL); else if (!strcmp(arg, "--no-ext-diff")) - options->allow_external = 0; + DIFF_OPT_CLR(options, ALLOW_EXTERNAL); else return 0; return 1; @@ -3071,7 +3065,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) * to determine how many paths were dirty only * due to stat info mismatch. */ - if (!diffopt->no_index) + if (!DIFF_OPT_TST(diffopt, NO_INDEX)) diffopt->skip_stat_unmatch++; diff_free_filepair(p); } @@ -3082,10 +3076,10 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) void diffcore_std(struct diff_options *options) { - if (options->quiet) + if (DIFF_OPT_TST(options, QUIET)) return; - if (options->skip_stat_unmatch && !options->find_copies_harder) + if (options->skip_stat_unmatch && !DIFF_OPT_TST(options, FIND_COPIES_HARDER)) diffcore_skip_stat_unmatch(options); if (options->break_opt != -1) diffcore_break(options->break_opt); @@ -3100,7 +3094,10 @@ void diffcore_std(struct diff_options *options) diff_resolve_rename_copy(); diffcore_apply_filter(options->filter); - options->has_changes = !!diff_queued_diff.nr; + if (diff_queued_diff.nr) + DIFF_OPT_SET(options, HAS_CHANGES); + else + DIFF_OPT_CLR(options, HAS_CHANGES); } @@ -3124,7 +3121,7 @@ void diff_addremove(struct diff_options *options, * Before the final output happens, they are pruned after * merged into rename/copy pairs as appropriate. */ - if (options->reverse_diff) + if (DIFF_OPT_TST(options, REVERSE_DIFF)) addremove = (addremove == '+' ? '-' : addremove == '-' ? '+' : addremove); @@ -3139,7 +3136,7 @@ void diff_addremove(struct diff_options *options, fill_filespec(two, sha1, mode); diff_queue(&diff_queued_diff, one, two); - options->has_changes = 1; + DIFF_OPT_SET(options, HAS_CHANGES); } void diff_change(struct diff_options *options, @@ -3151,7 +3148,7 @@ void diff_change(struct diff_options *options, char concatpath[PATH_MAX]; struct diff_filespec *one, *two; - if (options->reverse_diff) { + if (DIFF_OPT_TST(options, REVERSE_DIFF)) { unsigned tmp; const unsigned char *tmp_c; tmp = old_mode; old_mode = new_mode; new_mode = tmp; @@ -3165,7 +3162,7 @@ void diff_change(struct diff_options *options, fill_filespec(two, new_sha1, new_mode); diff_queue(&diff_queued_diff, one, two); - options->has_changes = 1; + DIFF_OPT_SET(options, HAS_CHANGES); } void diff_unmerge(struct diff_options *options, diff --git a/diff.h b/diff.h index 4546aad219..6ff2b0e318 100644 --- a/diff.h +++ b/diff.h @@ -43,26 +43,32 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_FORMAT_CALLBACK 0x1000 +#define DIFF_OPT_RECURSIVE (1 << 0) +#define DIFF_OPT_TREE_IN_RECURSIVE (1 << 1) +#define DIFF_OPT_BINARY (1 << 2) +#define DIFF_OPT_TEXT (1 << 3) +#define DIFF_OPT_FULL_INDEX (1 << 4) +#define DIFF_OPT_SILENT_ON_REMOVE (1 << 5) +#define DIFF_OPT_FIND_COPIES_HARDER (1 << 6) +#define DIFF_OPT_FOLLOW_RENAMES (1 << 7) +#define DIFF_OPT_COLOR_DIFF (1 << 8) +#define DIFF_OPT_COLOR_DIFF_WORDS (1 << 9) +#define DIFF_OPT_HAS_CHANGES (1 << 10) +#define DIFF_OPT_QUIET (1 << 11) +#define DIFF_OPT_NO_INDEX (1 << 12) +#define DIFF_OPT_ALLOW_EXTERNAL (1 << 13) +#define DIFF_OPT_EXIT_WITH_STATUS (1 << 14) +#define DIFF_OPT_REVERSE_DIFF (1 << 15) +#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) +#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) +#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) + struct diff_options { const char *filter; const char *orderfile; const char *pickaxe; const char *single_follow; - unsigned recursive:1, - tree_in_recursive:1, - binary:1, - text:1, - full_index:1, - silent_on_remove:1, - find_copies_harder:1, - follow_renames:1, - color_diff:1, - color_diff_words:1, - has_changes:1, - quiet:1, - no_index:1, - allow_external:1, - exit_with_status:1; + unsigned flags; int context; int break_opt; int detect_rename; @@ -71,7 +77,6 @@ struct diff_options { int output_format; int pickaxe_opts; int rename_score; - int reverse_diff; int rename_limit; int setup; int abbrev; @@ -105,6 +110,9 @@ enum color_diff { DIFF_WHITESPACE = 7, }; const char *diff_get_color(int diff_use_color, enum color_diff ix); +#define diff_get_color_opt(o, ix) \ + diff_get_color(DIFF_OPT_TST((o), COLOR_DIFF), ix) + extern const char mime_boundary_leader[]; diff --git a/log-tree.c b/log-tree.c index a34beb0b02..1f3fcf16ad 100644 --- a/log-tree.c +++ b/log-tree.c @@ -245,8 +245,7 @@ void show_log(struct rev_info *opt, const char *sep) opt->diffopt.stat_sep = buffer; } } else if (opt->commit_format != CMIT_FMT_USERFORMAT) { - fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT), - stdout); + fputs(diff_get_color_opt(&opt->diffopt, DIFF_COMMIT), stdout); if (opt->commit_format != CMIT_FMT_ONELINE) fputs("commit ", stdout); if (commit->object.flags & BOUNDARY) @@ -266,8 +265,7 @@ void show_log(struct rev_info *opt, const char *sep) diff_unique_abbrev(parent->object.sha1, abbrev_commit)); show_decorations(commit); - printf("%s", - diff_get_color(opt->diffopt.color_diff, DIFF_RESET)); + printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET)); putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n'); if (opt->reflog_info) { show_reflog_message(opt->reflog_info, diff --git a/merge-recursive.c b/merge-recursive.c index 6c6f595fbc..9a1e2f269d 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -366,7 +366,7 @@ static struct path_list *get_renames(struct tree *tree, renames = xcalloc(1, sizeof(struct path_list)); diff_setup(&opts); - opts.recursive = 1; + DIFF_OPT_SET(&opts, RECURSIVE); opts.detect_rename = DIFF_DETECT_RENAME; opts.rename_limit = rename_limit; opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff --git a/patch-ids.c b/patch-ids.c index a288fac992..3be5d3165e 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -121,7 +121,7 @@ int init_patch_ids(struct patch_ids *ids) { memset(ids, 0, sizeof(*ids)); diff_setup(&ids->diffopts); - ids->diffopts.recursive = 1; + DIFF_OPT_SET(&ids->diffopts, RECURSIVE); if (diff_setup_done(&ids->diffopts) < 0) return error("diff_setup_done failed"); return 0; diff --git a/revision.c b/revision.c index e76da0d448..f5b0e83ee3 100644 --- a/revision.c +++ b/revision.c @@ -250,7 +250,7 @@ static void file_add_remove(struct diff_options *options, } tree_difference = diff; if (tree_difference == REV_TREE_DIFFERENT) - options->has_changes = 1; + DIFF_OPT_SET(options, HAS_CHANGES); } static void file_change(struct diff_options *options, @@ -260,7 +260,7 @@ static void file_change(struct diff_options *options, const char *base, const char *path) { tree_difference = REV_TREE_DIFFERENT; - options->has_changes = 1; + DIFF_OPT_SET(options, HAS_CHANGES); } static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2) @@ -270,7 +270,7 @@ static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree if (!t2) return REV_TREE_DIFFERENT; tree_difference = REV_TREE_SAME; - revs->pruning.has_changes = 0; + DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES); if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &revs->pruning) < 0) return REV_TREE_DIFFERENT; @@ -294,7 +294,7 @@ static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1) init_tree_desc(&empty, "", 0); tree_difference = REV_TREE_SAME; - revs->pruning.has_changes = 0; + DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES); retval = diff_tree(&empty, &real, "", &revs->pruning); free(tree); @@ -662,8 +662,8 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->abbrev = DEFAULT_ABBREV; revs->ignore_merges = 1; revs->simplify_history = 1; - revs->pruning.recursive = 1; - revs->pruning.quiet = 1; + DIFF_OPT_SET(&revs->pruning, RECURSIVE); + DIFF_OPT_SET(&revs->pruning, QUIET); revs->pruning.add_remove = file_add_remove; revs->pruning.change = file_change; revs->lifo = 1; @@ -1054,13 +1054,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch } if (!strcmp(arg, "-r")) { revs->diff = 1; - revs->diffopt.recursive = 1; + DIFF_OPT_SET(&revs->diffopt, RECURSIVE); continue; } if (!strcmp(arg, "-t")) { revs->diff = 1; - revs->diffopt.recursive = 1; - revs->diffopt.tree_in_recursive = 1; + DIFF_OPT_SET(&revs->diffopt, RECURSIVE); + DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE); continue; } if (!strcmp(arg, "-m")) { @@ -1242,7 +1242,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->diff = 1; /* Pickaxe and rename following needs diffs */ - if (revs->diffopt.pickaxe || revs->diffopt.follow_renames) + if (revs->diffopt.pickaxe || DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES)) revs->diff = 1; if (revs->topo_order) @@ -1251,7 +1251,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (revs->prune_data) { diff_tree_setup_paths(revs->prune_data, &revs->pruning); /* Can't prune commits with rename following: the paths change.. */ - if (!revs->diffopt.follow_renames) + if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES)) revs->prune_fn = try_to_simplify_commit; if (!revs->full_diff) diff_tree_setup_paths(revs->prune_data, &revs->diffopt); diff --git a/tree-diff.c b/tree-diff.c index 7c261fd7c3..aa0a100295 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -39,7 +39,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const show_entry(opt, "+", t2, base, baselen); return 1; } - if (!opt->find_copies_harder && !hashcmp(sha1, sha2) && mode1 == mode2) + if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2) return 0; /* @@ -52,10 +52,10 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const return 0; } - if (opt->recursive && S_ISDIR(mode1)) { + if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { int retval; char *newbase = malloc_base(base, baselen, path1, pathlen1); - if (opt->tree_in_recursive) + if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) opt->change(opt, mode1, mode2, sha1, sha2, base, path1); retval = diff_tree_sha1(sha1, sha2, newbase, opt); @@ -206,7 +206,7 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); - if (opt->recursive && S_ISDIR(mode)) { + if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; int pathlen = tree_entry_len(path, sha1); char *newbase = malloc_base(base, baselen, path, pathlen); @@ -257,7 +257,7 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru int baselen = strlen(base); for (;;) { - if (opt->quiet && opt->has_changes) + if (DIFF_OPT_TST(opt, QUIET) && DIFF_OPT_TST(opt, HAS_CHANGES)) break; if (opt->nr_paths) { skip_uninteresting(t1, base, baselen, opt); @@ -315,7 +315,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co q->nr = 0; diff_setup(&diff_opts); - diff_opts.recursive = 1; + DIFF_OPT_SET(&diff_opts, RECURSIVE); diff_opts.detect_rename = DIFF_DETECT_RENAME; diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_opts.single_follow = opt->paths[0]; @@ -380,7 +380,7 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha init_tree_desc(&t1, tree1, size1); init_tree_desc(&t2, tree2, size2); retval = diff_tree(&t1, &t2, base, opt); - if (opt->follow_renames && diff_might_be_rename()) { + if (DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) { init_tree_desc(&t1, tree1, size1); init_tree_desc(&t2, tree2, size2); try_to_follow_renames(&t1, &t2, base, opt); -- cgit v1.3 From d054680c7d245b71ebba0dd030fd13dce213559a Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Wed, 7 Nov 2007 11:20:32 +0100 Subject: Reorder diff_opt_parse options more logically per topics. This is a line reordering patch _only_. Signed-off-by: Pierre Habouzit Signed-off-by: Junio C Hamano --- diff.c | 116 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 53 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 67cce8b72e..b08d28a578 100644 --- a/diff.c +++ b/diff.c @@ -2185,6 +2185,8 @@ static int diff_scoreopt_parse(const char *opt); int diff_opt_parse(struct diff_options *options, const char **av, int ac) { const char *arg = av[0]; + + /* Output format options */ if (!strcmp(arg, "-p") || !strcmp(arg, "-u")) options->output_format |= DIFF_FORMAT_PATCH; else if (opt_arg(arg, 'U', "unified", &options->context)) @@ -2197,6 +2199,18 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_NUMSTAT; else if (!strcmp(arg, "--shortstat")) options->output_format |= DIFF_FORMAT_SHORTSTAT; + else if (!strcmp(arg, "--check")) + options->output_format |= DIFF_FORMAT_CHECKDIFF; + else if (!strcmp(arg, "--summary")) + options->output_format |= DIFF_FORMAT_SUMMARY; + else if (!strcmp(arg, "--patch-with-stat")) + options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT; + else if (!strcmp(arg, "--name-only")) + options->output_format |= DIFF_FORMAT_NAME; + else if (!strcmp(arg, "--name-status")) + options->output_format |= DIFF_FORMAT_NAME_STATUS; + else if (!strcmp(arg, "-s")) + options->output_format |= DIFF_FORMAT_NO_OUTPUT; else if (!prefixcmp(arg, "--stat")) { char *end; int width = options->stat_width; @@ -2224,42 +2238,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->stat_name_width = name_width; options->stat_width = width; } - else if (!strcmp(arg, "--check")) - options->output_format |= DIFF_FORMAT_CHECKDIFF; - else if (!strcmp(arg, "--summary")) - options->output_format |= DIFF_FORMAT_SUMMARY; - else if (!strcmp(arg, "--patch-with-stat")) - options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT; - else if (!strcmp(arg, "-z")) - options->line_termination = 0; - else if (!prefixcmp(arg, "-l")) - options->rename_limit = strtoul(arg+2, NULL, 10); - else if (!strcmp(arg, "--full-index")) - DIFF_OPT_SET(options, FULL_INDEX); - else if (!strcmp(arg, "--binary")) { - options->output_format |= DIFF_FORMAT_PATCH; - DIFF_OPT_SET(options, BINARY); - } - else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) - DIFF_OPT_SET(options, TEXT); - else if (!strcmp(arg, "--name-only")) - options->output_format |= DIFF_FORMAT_NAME; - else if (!strcmp(arg, "--name-status")) - options->output_format |= DIFF_FORMAT_NAME_STATUS; - else if (!strcmp(arg, "-R")) - DIFF_OPT_SET(options, REVERSE_DIFF); - else if (!prefixcmp(arg, "-S")) - options->pickaxe = arg + 2; - else if (!strcmp(arg, "-s")) - options->output_format |= DIFF_FORMAT_NO_OUTPUT; - else if (!prefixcmp(arg, "-O")) - options->orderfile = arg + 2; - else if (!prefixcmp(arg, "--diff-filter=")) - options->filter = arg + 14; - else if (!strcmp(arg, "--pickaxe-all")) - options->pickaxe_opts = DIFF_PICKAXE_ALL; - else if (!strcmp(arg, "--pickaxe-regex")) - options->pickaxe_opts = DIFF_PICKAXE_REGEX; + + /* renames options */ else if (!prefixcmp(arg, "-B")) { if ((options->break_opt = diff_scoreopt_parse(arg)) == -1) return -1; @@ -2276,33 +2256,38 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) return -1; options->detect_rename = DIFF_DETECT_COPY; } + else if (!strcmp(arg, "--no-renames")) + options->detect_rename = 0; + + /* xdiff options */ + else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) + options->xdl_opts |= XDF_IGNORE_WHITESPACE; + else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) + options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; + else if (!strcmp(arg, "--ignore-space-at-eol")) + options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL; + + /* flags options */ + else if (!strcmp(arg, "--binary")) { + options->output_format |= DIFF_FORMAT_PATCH; + DIFF_OPT_SET(options, BINARY); + } + else if (!strcmp(arg, "--full-index")) + DIFF_OPT_SET(options, FULL_INDEX); + else if (!strcmp(arg, "-a") || !strcmp(arg, "--text")) + DIFF_OPT_SET(options, TEXT); + else if (!strcmp(arg, "-R")) + DIFF_OPT_SET(options, REVERSE_DIFF); else if (!strcmp(arg, "--find-copies-harder")) DIFF_OPT_SET(options, FIND_COPIES_HARDER); else if (!strcmp(arg, "--follow")) DIFF_OPT_SET(options, FOLLOW_RENAMES); - else if (!strcmp(arg, "--abbrev")) - options->abbrev = DEFAULT_ABBREV; - else if (!prefixcmp(arg, "--abbrev=")) { - options->abbrev = strtoul(arg + 9, NULL, 10); - if (options->abbrev < MINIMUM_ABBREV) - options->abbrev = MINIMUM_ABBREV; - else if (40 < options->abbrev) - options->abbrev = 40; - } else if (!strcmp(arg, "--color")) DIFF_OPT_SET(options, COLOR_DIFF); else if (!strcmp(arg, "--no-color")) DIFF_OPT_CLR(options, COLOR_DIFF); - else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE; - else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; - else if (!strcmp(arg, "--ignore-space-at-eol")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL; else if (!strcmp(arg, "--color-words")) options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; - else if (!strcmp(arg, "--no-renames")) - options->detect_rename = 0; else if (!strcmp(arg, "--exit-code")) DIFF_OPT_SET(options, EXIT_WITH_STATUS); else if (!strcmp(arg, "--quiet")) @@ -2311,6 +2296,31 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, ALLOW_EXTERNAL); else if (!strcmp(arg, "--no-ext-diff")) DIFF_OPT_CLR(options, ALLOW_EXTERNAL); + + /* misc options */ + else if (!strcmp(arg, "-z")) + options->line_termination = 0; + else if (!prefixcmp(arg, "-l")) + options->rename_limit = strtoul(arg+2, NULL, 10); + else if (!prefixcmp(arg, "-S")) + options->pickaxe = arg + 2; + else if (!strcmp(arg, "--pickaxe-all")) + options->pickaxe_opts = DIFF_PICKAXE_ALL; + else if (!strcmp(arg, "--pickaxe-regex")) + options->pickaxe_opts = DIFF_PICKAXE_REGEX; + else if (!prefixcmp(arg, "-O")) + options->orderfile = arg + 2; + else if (!prefixcmp(arg, "--diff-filter=")) + options->filter = arg + 14; + else if (!strcmp(arg, "--abbrev")) + options->abbrev = DEFAULT_ABBREV; + else if (!prefixcmp(arg, "--abbrev=")) { + options->abbrev = strtoul(arg + 9, NULL, 10); + if (options->abbrev < MINIMUM_ABBREV) + options->abbrev = MINIMUM_ABBREV; + else if (40 < options->abbrev) + options->abbrev = 40; + } else return 0; return 1; -- cgit v1.3 From f8b6809d52992ad14d035bcf7c8d8cfe00ef45a0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Nov 2007 23:06:44 -0800 Subject: Fix "quote" misconversion for rewrite diff output. 663af3422a648e87945e4d8c0cc3e13671f2bbde (Full rework of quote_c_style and write_name_quoted.) mistakenly used puts() when writing out a fixed string when it did not want to add a terminating LF. Signed-off-by: Junio C Hamano --- diff.c | 2 +- t/t4022-diff-rewrite.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100755 t/t4022-diff-rewrite.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index b08d28a578..6b54959610 100644 --- a/diff.c +++ b/diff.c @@ -2716,7 +2716,7 @@ static void diff_summary(struct diff_filepair *p) break; default: if (p->score) { - puts(" rewrite "); + fputs(" rewrite ", stdout); write_name_quoted(p->two->path, stdout, ' '); printf("(%d%%)\n", similarity_index(p)); } diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh new file mode 100755 index 0000000000..6de4acbd44 --- /dev/null +++ b/t/t4022-diff-rewrite.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='rewrite diff' + +. ./test-lib.sh + +test_expect_success setup ' + + cat ../../COPYING >test && + git add test && + tr 'a-zA-Z' 'n-za-mN-ZA-M' <../../COPYING >test + +' + +test_expect_success 'detect rewrite' ' + + actual=$(git diff-files -B --summary test) && + expr "$actual" : " rewrite test ([0-9]*%)$" || { + echo "Eh? <<$actual>>" + false + } + +' + +test_done + -- cgit v1.3 From 0f6f5a4022de5904926cd528c681468e3f635256 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 5 Dec 2007 17:26:11 -0800 Subject: git config --get-colorbool This adds an option to help scripts find out color settings from the configuration file. git config --get-colorbool color.diff inspects color.diff variable, and exits with status 0 (i.e. success) if color is to be used. It exits with status 1 otherwise. If a script wants "true"/"false" answer to the standard output of the command, it can pass an additional boolean parameter to its command line, telling if its standard output is a terminal, like this: git config --get-colorbool color.diff true When called like this, the command outputs "true" to its standard output if color is to be used (i.e. "color.diff" says "always", "auto", or "true"), and "false" otherwise. Signed-off-by: Junio C Hamano --- Documentation/git-config.txt | 10 ++++++++++ builtin-branch.c | 2 +- builtin-config.c | 41 ++++++++++++++++++++++++++++++++++++++++- color.c | 6 ++++-- color.h | 2 +- diff.c | 2 +- wt-status.c | 2 +- 7 files changed, 58 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 7640450787..98509b4f44 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -21,6 +21,7 @@ SYNOPSIS 'git-config' [] --remove-section name 'git-config' [] [-z|--null] -l | --list 'git-config' [] --get-color name [default] +'git-config' [] --get-colorbool name [stdout-is-tty] DESCRIPTION ----------- @@ -135,6 +136,15 @@ See also <>. output without getting confused e.g. by values that contain line breaks. +--get-colorbool name [stdout-is-tty]:: + + Find the color setting for `name` (e.g. `color.diff`) and output + "true" or "false". `stdout-is-tty` should be either "true" or + "false", and is taken into account when configuration says + "auto". If `stdout-is-tty` is missing, then checks the standard + output of the command itself, and exits with status 0 if color + is to be used, or exits with status 1 otherwise. + --get-color name default:: Find the color configured for `name` (e.g. `color.diff.new`) and diff --git a/builtin-branch.c b/builtin-branch.c index c64768beb2..089cae5929 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -65,7 +65,7 @@ static int parse_branch_color_slot(const char *var, int ofs) static int git_branch_config(const char *var, const char *value) { if (!strcmp(var, "color.branch")) { - branch_use_color = git_config_colorbool(var, value); + branch_use_color = git_config_colorbool(var, value, -1); return 0; } if (!prefixcmp(var, "color.branch.")) { diff --git a/builtin-config.c b/builtin-config.c index 6175dc3738..d10b03f50c 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -3,7 +3,7 @@ #include "color.h" static const char git_config_set_usage[] = -"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default]"; +"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]"; static char *key; static regex_t *key_regexp; @@ -208,6 +208,43 @@ static int get_color(int argc, const char **argv) return 0; } +static int stdout_is_tty; +static int get_colorbool_found; +static int git_get_colorbool_config(const char *var, const char *value) +{ + if (!strcmp(var, get_color_slot)) + get_colorbool_found = + git_config_colorbool(var, value, stdout_is_tty); + return 0; +} + +static int get_colorbool(int argc, const char **argv) +{ + /* + * git config --get-colorbool [] + * + * returns "true" or "false" depending on how + * is configured. + */ + + if (argc == 2) + stdout_is_tty = git_config_bool("command line", argv[1]); + else if (argc == 1) + stdout_is_tty = isatty(1); + else + usage(git_config_set_usage); + get_colorbool_found = 0; + get_color_slot = argv[0]; + git_config(git_get_colorbool_config); + + if (argc == 1) { + return get_colorbool_found ? 0 : 1; + } else { + printf("%s\n", get_colorbool_found ? "true" : "false"); + return 0; + } +} + int cmd_config(int argc, const char **argv, const char *prefix) { int nongit = 0; @@ -283,6 +320,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) return 0; } else if (!strcmp(argv[1], "--get-color")) { return get_color(argc-2, argv+2); + } else if (!strcmp(argv[1], "--get-colorbool")) { + return get_colorbool(argc-2, argv+2); } else break; argc--; diff --git a/color.c b/color.c index 97cfbda31a..7bd424a8f6 100644 --- a/color.c +++ b/color.c @@ -116,7 +116,7 @@ bad: die("bad config value '%s' for variable '%s'", value, var); } -int git_config_colorbool(const char *var, const char *value) +int git_config_colorbool(const char *var, const char *value, int stdout_is_tty) { if (value) { if (!strcasecmp(value, "never")) @@ -133,7 +133,9 @@ int git_config_colorbool(const char *var, const char *value) /* any normal truth value defaults to 'auto' */ auto_color: - if (isatty(1) || (pager_in_use && pager_use_color)) { + if (stdout_is_tty < 0) + stdout_is_tty = isatty(1); + if (stdout_is_tty || (pager_in_use && pager_use_color)) { char *term = getenv("TERM"); if (term && strcmp(term, "dumb")) return 1; diff --git a/color.h b/color.h index 68098006ed..ff63513d39 100644 --- a/color.h +++ b/color.h @@ -4,7 +4,7 @@ /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ #define COLOR_MAXLEN 24 -int git_config_colorbool(const char *var, const char *value); +int git_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *var, const char *value, char *dst); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); diff --git a/diff.c b/diff.c index 6b54959610..be6cf687a4 100644 --- a/diff.c +++ b/diff.c @@ -146,7 +146,7 @@ int git_diff_ui_config(const char *var, const char *value) return 0; } if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { - diff_use_color_default = git_config_colorbool(var, value); + diff_use_color_default = git_config_colorbool(var, value, -1); return 0; } if (!strcmp(var, "diff.renames")) { diff --git a/wt-status.c b/wt-status.c index d35386dae1..02dbb751db 100644 --- a/wt-status.c +++ b/wt-status.c @@ -391,7 +391,7 @@ void wt_status_print(struct wt_status *s) int git_status_config(const char *k, const char *v) { if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) { - wt_status_use_color = git_config_colorbool(k, v); + wt_status_use_color = git_config_colorbool(k, v, -1); return 0; } if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) { -- cgit v1.3 From cf1b7869f0c571bbd4f72a4355d9aca558baa0da Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Dec 2007 00:14:14 -0800 Subject: Use gitattributes to define per-path whitespace rule The `core.whitespace` configuration variable allows you to define what `diff` and `apply` should consider whitespace errors for all paths in the project (See gitlink:git-config[1]). This attribute gives you finer control per path. For example, if you have these in the .gitattributes: frotz whitespace nitfol -whitespace xyzzy whitespace=-trailing all types of whitespace problems known to git are noticed in path 'frotz' (i.e. diff shows them in diff.whitespace color, and apply warns about them), no whitespace problem is noticed in path 'nitfol', and the default types of whitespace problems except "trailing whitespace" are noticed for path 'xyzzy'. A project with mixed Python and C might want to have: *.c whitespace *.py whitespace=-indent-with-non-tab in its toplevel .gitattributes file. Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 31 +++++++++++++ Makefile | 2 +- builtin-apply.c | 36 ++++++++++------ cache.h | 4 +- config.c | 50 +-------------------- diff.c | 19 +++++--- environment.c | 2 +- t/t4019-diff-wserror.sh | 47 ++++++++++++++++++++ t/t4124-apply-ws-rule.sh | 20 ++++++++- ws.c | 96 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 233 insertions(+), 74 deletions(-) create mode 100644 ws.c (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 20cf8ff816..c4bcbb9358 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -360,6 +360,37 @@ When left unspecified, the driver itself is used for both internal merge and the final merge. +Checking whitespace errors +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`whitespace` +^^^^^^^^^^^^ + +The `core.whitespace` configuration variable allows you to define what +`diff` and `apply` should consider whitespace errors for all paths in +the project (See gitlink:git-config[1]). This attribute gives you finer +control per path. + +Set:: + + Notice all types of potential whitespace errors known to git. + +Unset:: + + Do not notice anything as error. + +Unspecified:: + + Use the value of `core.whitespace` configuration variable to + decide what to notice as error. + +String:: + + Specify a comma separate list of common whitespace problems to + notice in the same format as `core.whitespace` configuration + variable. + + EXAMPLE ------- diff --git a/Makefile b/Makefile index 042f79ef8f..ac6b079030 100644 --- a/Makefile +++ b/Makefile @@ -312,7 +312,7 @@ LIB_OBJS = \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o bundle.o walker.o parse-options.o + transport.o bundle.o walker.o parse-options.o ws.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/builtin-apply.c b/builtin-apply.c index 57efcd5aa7..ee3ef60268 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -144,6 +144,7 @@ struct patch { unsigned int old_mode, new_mode; int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */ int rejected; + unsigned ws_rule; unsigned long deflate_origlen; int lines_added, lines_deleted; int score; @@ -898,7 +899,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc return -1; } -static void check_whitespace(const char *line, int len) +static void check_whitespace(const char *line, int len, unsigned ws_rule) { const char *err = "Adds trailing whitespace"; int seen_space = 0; @@ -910,14 +911,14 @@ static void check_whitespace(const char *line, int len) * this function. That is, an addition of an empty line would * check the '+' here. Sneaky... */ - if ((whitespace_rule & WS_TRAILING_SPACE) && isspace(line[len-2])) + if ((ws_rule & WS_TRAILING_SPACE) && isspace(line[len-2])) goto error; /* * Make sure that there is no space followed by a tab in * indentation. */ - if (whitespace_rule & WS_SPACE_BEFORE_TAB) { + if (ws_rule & WS_SPACE_BEFORE_TAB) { err = "Space in indent is followed by a tab"; for (i = 1; i < len; i++) { if (line[i] == '\t') { @@ -935,7 +936,7 @@ static void check_whitespace(const char *line, int len) * Make sure that the indentation does not contain more than * 8 spaces. */ - if ((whitespace_rule & WS_INDENT_WITH_NON_TAB) && + if ((ws_rule & WS_INDENT_WITH_NON_TAB) && (8 < len) && !strncmp("+ ", line, 9)) { err = "Indent more than 8 places with spaces"; goto error; @@ -1001,7 +1002,7 @@ static int parse_fragment(char *line, unsigned long size, case '-': if (apply_in_reverse && ws_error_action != nowarn_ws_error) - check_whitespace(line, len); + check_whitespace(line, len, patch->ws_rule); deleted++; oldlines--; trailing = 0; @@ -1009,7 +1010,7 @@ static int parse_fragment(char *line, unsigned long size, case '+': if (!apply_in_reverse && ws_error_action != nowarn_ws_error) - check_whitespace(line, len); + check_whitespace(line, len, patch->ws_rule); added++; newlines--; trailing = 0; @@ -1318,6 +1319,10 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) if (offset < 0) return offset; + patch->ws_rule = whitespace_rule(patch->new_name + ? patch->new_name + : patch->old_name); + patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch); @@ -1568,7 +1573,8 @@ static void remove_last_line(const char **rbuf, int *rsize) *rsize = offset + 1; } -static int apply_line(char *output, const char *patch, int plen) +static int apply_line(char *output, const char *patch, int plen, + unsigned ws_rule) { /* * plen is number of bytes to be copied from patch, @@ -1593,7 +1599,7 @@ static int apply_line(char *output, const char *patch, int plen) /* * Strip trailing whitespace */ - if ((whitespace_rule & WS_TRAILING_SPACE) && + if ((ws_rule & WS_TRAILING_SPACE) && (1 < plen && isspace(patch[plen-1]))) { if (patch[plen] == '\n') add_nl_to_tail = 1; @@ -1610,12 +1616,12 @@ static int apply_line(char *output, const char *patch, int plen) char ch = patch[i]; if (ch == '\t') { last_tab_in_indent = i; - if ((whitespace_rule & WS_SPACE_BEFORE_TAB) && + if ((ws_rule & WS_SPACE_BEFORE_TAB) && 0 <= last_space_in_indent) need_fix_leading_space = 1; } else if (ch == ' ') { last_space_in_indent = i; - if ((whitespace_rule & WS_INDENT_WITH_NON_TAB) && + if ((ws_rule & WS_INDENT_WITH_NON_TAB) && last_tab_in_indent < 0 && 8 <= i) need_fix_leading_space = 1; @@ -1629,7 +1635,7 @@ static int apply_line(char *output, const char *patch, int plen) int consecutive_spaces = 0; int last = last_tab_in_indent + 1; - if (whitespace_rule & WS_INDENT_WITH_NON_TAB) { + if (ws_rule & WS_INDENT_WITH_NON_TAB) { /* have "last" point at one past the indent */ if (last_tab_in_indent < last_space_in_indent) last = last_space_in_indent + 1; @@ -1671,7 +1677,7 @@ static int apply_line(char *output, const char *patch, int plen) } static int apply_one_fragment(struct strbuf *buf, struct fragment *frag, - int inaccurate_eof) + int inaccurate_eof, unsigned ws_rule) { int match_beginning, match_end; const char *patch = frag->patch; @@ -1730,7 +1736,7 @@ static int apply_one_fragment(struct strbuf *buf, struct fragment *frag, case '+': if (first != '+' || !no_add) { int added = apply_line(new + newsize, patch, - plen); + plen, ws_rule); newsize += added; if (first == '+' && added == 1 && new[newsize-1] == '\n') @@ -1953,12 +1959,14 @@ static int apply_fragments(struct strbuf *buf, struct patch *patch) { struct fragment *frag = patch->fragments; const char *name = patch->old_name ? patch->old_name : patch->new_name; + unsigned ws_rule = patch->ws_rule; + unsigned inaccurate_eof = patch->inaccurate_eof; if (patch->is_binary) return apply_binary(buf, patch); while (frag) { - if (apply_one_fragment(buf, frag, patch->inaccurate_eof)) { + if (apply_one_fragment(buf, frag, inaccurate_eof, ws_rule)) { error("patch failed: %s:%ld", name, frag->oldpos); if (!apply_with_reject) return -1; diff --git a/cache.h b/cache.h index 3f4282795e..9cc6268d45 100644 --- a/cache.h +++ b/cache.h @@ -610,6 +610,8 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i #define WS_SPACE_BEFORE_TAB 02 #define WS_INDENT_WITH_NON_TAB 04 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) -extern unsigned whitespace_rule; +extern unsigned whitespace_rule_cfg; +extern unsigned whitespace_rule(const char *); +extern unsigned parse_whitespace_rule(const char *); #endif /* CACHE_H */ diff --git a/config.c b/config.c index d5b976696c..2500e0d59a 100644 --- a/config.c +++ b/config.c @@ -246,54 +246,6 @@ static unsigned long get_unit_factor(const char *end) die("unknown unit: '%s'", end); } -static struct whitespace_rule { - const char *rule_name; - unsigned rule_bits; -} whitespace_rule_names[] = { - { "trailing-space", WS_TRAILING_SPACE }, - { "space-before-tab", WS_SPACE_BEFORE_TAB }, - { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB }, -}; - -static unsigned parse_whitespace_rule(const char *string) -{ - unsigned rule = WS_DEFAULT_RULE; - - while (string) { - int i; - size_t len; - const char *ep; - int negated = 0; - - string = string + strspn(string, ", \t\n\r"); - ep = strchr(string, ','); - if (!ep) - len = strlen(string); - else - len = ep - string; - - if (*string == '-') { - negated = 1; - string++; - len--; - } - if (!len) - break; - for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) { - if (strncmp(whitespace_rule_names[i].rule_name, - string, len)) - continue; - if (negated) - rule &= ~whitespace_rule_names[i].rule_bits; - else - rule |= whitespace_rule_names[i].rule_bits; - break; - } - string = ep; - } - return rule; -} - int git_parse_long(const char *value, long *ret) { if (value && *value) { @@ -480,7 +432,7 @@ int git_default_config(const char *var, const char *value) } if (!strcmp(var, "core.whitespace")) { - whitespace_rule = parse_whitespace_rule(value); + whitespace_rule_cfg = parse_whitespace_rule(value); return 0; } diff --git a/diff.c b/diff.c index 6bb902f4af..c3a1942bbb 100644 --- a/diff.c +++ b/diff.c @@ -454,6 +454,7 @@ static void diff_words_show(struct diff_words_data *diff_words) struct emit_callback { struct xdiff_emit_state xm; int nparents, color_diff; + unsigned ws_rule; const char **label_path; struct diff_words_data *diff_words; int *found_changesp; @@ -493,8 +494,8 @@ static void emit_line(const char *set, const char *reset, const char *line, int } static void emit_line_with_ws(int nparents, - const char *set, const char *reset, const char *ws, - const char *line, int len) + const char *set, const char *reset, const char *ws, + const char *line, int len, unsigned ws_rule) { int col0 = nparents; int last_tab_in_indent = -1; @@ -511,7 +512,7 @@ static void emit_line_with_ws(int nparents, for (i = col0; i < len; i++) { if (line[i] == '\t') { last_tab_in_indent = i; - if ((whitespace_rule & WS_SPACE_BEFORE_TAB) && + if ((ws_rule & WS_SPACE_BEFORE_TAB) && 0 <= last_space_in_indent) need_highlight_leading_space = 1; } @@ -520,7 +521,7 @@ static void emit_line_with_ws(int nparents, else break; } - if ((whitespace_rule & WS_INDENT_WITH_NON_TAB) && + if ((ws_rule & WS_INDENT_WITH_NON_TAB) && 0 <= last_space_in_indent && last_tab_in_indent < 0 && 8 <= (i - col0)) { @@ -551,7 +552,7 @@ static void emit_line_with_ws(int nparents, tail = len - 1; if (line[tail] == '\n' && i < tail) tail--; - if (whitespace_rule & WS_TRAILING_SPACE) { + if (ws_rule & WS_TRAILING_SPACE) { while (i < tail) { if (!isspace(line[tail])) break; @@ -578,7 +579,7 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons emit_line(set, reset, line, len); else emit_line_with_ws(ecbdata->nparents, set, reset, ws, - line, len); + line, len, ecbdata->ws_rule); } static void fn_out_consume(void *priv, char *line, unsigned long len) @@ -994,6 +995,7 @@ struct checkdiff_t { struct xdiff_emit_state xm; const char *filename; int lineno, color_diff; + unsigned ws_rule; }; static void checkdiff_consume(void *priv, char *line, unsigned long len) @@ -1029,7 +1031,8 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (white_space_at_end) printf("white space at end"); printf(":%s ", reset); - emit_line_with_ws(1, set, reset, ws, line, len); + emit_line_with_ws(1, set, reset, ws, line, len, + data->ws_rule); } data->lineno++; @@ -1330,6 +1333,7 @@ static void builtin_diff(const char *name_a, ecbdata.label_path = lbl; ecbdata.color_diff = o->color_diff; ecbdata.found_changesp = &o->found_changes; + ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; @@ -1423,6 +1427,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, data.filename = name_b ? name_b : name_a; data.lineno = 0; data.color_diff = o->color_diff; + data.ws_rule = whitespace_rule(data.filename); if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); diff --git a/environment.c b/environment.c index 624dd9677c..2fbbc8e430 100644 --- a/environment.c +++ b/environment.c @@ -35,7 +35,7 @@ int pager_in_use; int pager_use_color = 1; char *editor_program; int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ -unsigned whitespace_rule = WS_DEFAULT_RULE; +unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh index dbc895b9b7..67e080bdbe 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -45,8 +45,24 @@ test_expect_success 'without -trail' ' ' +test_expect_success 'without -trail (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=-trail" >.gitattributes + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight normal >/dev/null && + grep HT error >/dev/null && + grep With normal >/dev/null && + grep No normal >/dev/null + +' + test_expect_success 'without -space' ' + rm -f .gitattributes git config core.whitespace -space git diff --color >output grep "$blue_grep" output >error @@ -59,8 +75,24 @@ test_expect_success 'without -space' ' ' +test_expect_success 'without -space (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=-space" >.gitattributes + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight normal >/dev/null && + grep HT normal >/dev/null && + grep With error >/dev/null && + grep No normal >/dev/null + +' + test_expect_success 'with indent-non-tab only' ' + rm -f .gitattributes git config core.whitespace indent,-trailing,-space git diff --color >output grep "$blue_grep" output >error @@ -73,4 +105,19 @@ test_expect_success 'with indent-non-tab only' ' ' +test_expect_success 'with indent-non-tab only (attribute)' ' + + git config --unset core.whitespace + echo "F whitespace=indent,-trailing,-space" >.gitattributes + git diff --color >output + grep "$blue_grep" output >error + grep -v "$blue_grep" output >normal + + grep Eight error >/dev/null && + grep HT normal >/dev/null && + grep With normal >/dev/null && + grep No normal >/dev/null + +' + test_done diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh index f53ac466d6..85f3da2b98 100755 --- a/t/t4124-apply-ws-rule.sh +++ b/t/t4124-apply-ws-rule.sh @@ -112,6 +112,15 @@ test_expect_success 'whitespace=error-all, no rule' ' ' +test_expect_success 'whitespace=error-all, no rule (attribute)' ' + + git config --unset core.whitespace && + echo "target -whitespace" >.gitattributes && + apply_patch --whitespace=error-all && + diff file target + +' + for t in - '' do case "$t" in '') tt='!' ;; *) tt= ;; esac @@ -121,11 +130,20 @@ do for i in - '' do case "$i" in '') ti='#' ;; *) ti= ;; esac - rule=${t}trailing,${s}space,${i}indent && + rule=${t}trailing,${s}space,${i}indent + + rm -f .gitattributes test_expect_success "rule=$rule" ' git config core.whitespace "$rule" && test_fix "$tt$ts$ti" ' + + test_expect_success "rule=$rule (attributes)" ' + git config --unset core.whitespace && + echo "target whitespace=$rule" >.gitattributes && + test_fix "$tt$ts$ti" + ' + done done done diff --git a/ws.c b/ws.c new file mode 100644 index 0000000000..52c10caf35 --- /dev/null +++ b/ws.c @@ -0,0 +1,96 @@ +/* + * Whitespace rules + * + * Copyright (c) 2007 Junio C Hamano + */ + +#include "cache.h" +#include "attr.h" + +static struct whitespace_rule { + const char *rule_name; + unsigned rule_bits; +} whitespace_rule_names[] = { + { "trailing-space", WS_TRAILING_SPACE }, + { "space-before-tab", WS_SPACE_BEFORE_TAB }, + { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB }, +}; + +unsigned parse_whitespace_rule(const char *string) +{ + unsigned rule = WS_DEFAULT_RULE; + + while (string) { + int i; + size_t len; + const char *ep; + int negated = 0; + + string = string + strspn(string, ", \t\n\r"); + ep = strchr(string, ','); + if (!ep) + len = strlen(string); + else + len = ep - string; + + if (*string == '-') { + negated = 1; + string++; + len--; + } + if (!len) + break; + for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) { + if (strncmp(whitespace_rule_names[i].rule_name, + string, len)) + continue; + if (negated) + rule &= ~whitespace_rule_names[i].rule_bits; + else + rule |= whitespace_rule_names[i].rule_bits; + break; + } + string = ep; + } + return rule; +} + +static void setup_whitespace_attr_check(struct git_attr_check *check) +{ + static struct git_attr *attr_whitespace; + + if (!attr_whitespace) + attr_whitespace = git_attr("whitespace", 10); + check[0].attr = attr_whitespace; +} + +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)) { + const char *value; + + value = attr_whitespace_rule.value; + if (ATTR_TRUE(value)) { + /* true (whitespace) */ + unsigned all_rule = 0; + int i; + for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) + all_rule |= whitespace_rule_names[i].rule_bits; + return all_rule; + } else if (ATTR_FALSE(value)) { + /* false (-whitespace) */ + return 0; + } else if (ATTR_UNSET(value)) { + /* reset to default (!whitespace) */ + return whitespace_rule_cfg; + } else { + /* string */ + return parse_whitespace_rule(value); + } + } else { + return whitespace_rule_cfg; + } +} -- cgit v1.3 From 0ac7903ee3c7c93d2426a4aa4f3732bee73e0365 Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Wed, 12 Dec 2007 09:12:01 +0100 Subject: Use "whitespace" consistently For consistency, change "white space" and "whitespaces" to "whitespace", fixing a couple of adjacent grammar problems in the docs. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 12 ++++++------ Documentation/glossary.txt | 3 +-- diff.c | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index d0154bbc0a..5d22b7b58c 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -175,19 +175,19 @@ endif::git-format-patch[] Shorthand for "--text". --ignore-space-at-eol:: - Ignore changes in white spaces at EOL. + Ignore changes in whitespace at EOL. --ignore-space-change:: - Ignore changes in amount of white space. This ignores white - space at line end, and consider all other sequences of one or - more white space characters to be equivalent. + Ignore changes in amount of whitespace. This ignores whitespace + at line end, and considers all other sequences of one or + more whitespace characters to be equivalent. -b:: Shorthand for "--ignore-space-change". --ignore-all-space:: - Ignore white space when comparing lines. This ignores - difference even if one line has white space where the other + Ignore whitespace when comparing lines. This ignores + differences even if one line has whitespace where the other line has none. -w:: diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index fc1874424e..65f55e4ced 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -244,8 +244,7 @@ This commit is referred to as a "merge commit", or sometimes just a The unique identifier of an <>. The <> of the object's contents using the Secure Hash Algorithm 1 and usually represented by the 40 character hexadecimal encoding of - the <> of the object (possibly followed by - a white space). + the <> of the object. [[def_object_type]]object type:: One of the identifiers diff --git a/diff.c b/diff.c index f780e3e8e6..e74a30399e 100644 --- a/diff.c +++ b/diff.c @@ -1015,7 +1015,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (line[i - 1] == '\t' && spaces) space_before_tab = 1; - /* check white space at line end */ + /* check whitespace at line end */ if (line[len - 1] == '\n') len--; if (isspace(line[len - 1])) @@ -1029,7 +1029,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) putchar(','); } if (white_space_at_end) - printf("white space at end"); + printf("whitespace at end"); printf(":%s ", reset); emit_line_with_ws(1, set, reset, ws, line, len, data->ws_rule); -- cgit v1.3 From f604652e05073aaef6d83e83b5d6499b55bb6dfd Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 11 Dec 2007 23:46:30 -0800 Subject: git-diff --numstat -z: make it machine readable The "-z" format is all about machine parsability, but showing renamed paths as "common/{a => b}/suffix" makes it impossible. The scripts would never have successfully parsed "--numstat -z -M" in the old format. This fixes the output format in a (hopefully minimally) backward incompatible way. * The output without -z is not changed. This has given a good way for humans to view added and deleted lines separately, and showing the path in combined, shorter way would preserve readability. * The output with -z is unchanged for paths that do not involve renames. Existing scripts that do not pass -M/-C are not affected at all. * The output with -z for a renamed path is shown in a format that can easily be distinguished from an unrenamed path. This is based on Jakub Narebski's patch. Bugs and documentation typos are mine. Signed-off-by: Junio C Hamano --- Documentation/diff-format.txt | 61 ++++++++++++++++++++++++++ diff.c | 100 ++++++++++++++++++++++++++++-------------- 2 files changed, 129 insertions(+), 32 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 2c3a4c433b..400cbb3b1c 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -84,3 +84,64 @@ all parents. include::diff-generate-patch.txt[] + + +other diff formats +------------------ + +The `--summary` option describes newly added, deleted, renamed and +copied files. The `--stat` option adds diffstat(1) graph to the +output. These options can be combined with other options, such as +`-p`, and are meant for human consumption. + +When showing a change that involves a rename or a copy, `--stat` output +formats the pathnames compactly by combining common prefix and suffix of +the pathnames. For example, a change that moves `arch/i386/Makefile` to +`arch/x86/Makefile` while modifying 4 lines will be shown like this: + +------------------------------------ +arch/{i386 => x86}/Makefile | 4 +-- +------------------------------------ + +The `--numstat` option gives the diffstat(1) information but is designed +for easier machine consumption. An entry in `--numstat` output looks +like this: + +---------------------------------------- +1 2 README +3 1 arch/{i386 => x86}/Makefile +---------------------------------------- + +That is, from left to right: + +. the number of added lines; +. a tab; +. the number of deleted lines; +. a tab; +. pathname (possibly with rename/copy information); +. a newline. + +When `-z` output option is in effect, the output is formatted this way: + +---------------------------------------- +1 2 README NUL +3 1 NUL arch/i386/Makefile NUL arch/x86/Makefile NUL +---------------------------------------- + +That is: + +. the number of added lines; +. a tab; +. the number of deleted lines; +. a tab; +. a NUL (only exists if renamed/copied); +. pathname in preimage; +. a NUL (only exists if renamed/copied); +. pathname in postimage (only exists if renamed/copied); +. a NUL. + +The extra `NUL` before the preimage path in renamed case is to allow +scripts that read the output to tell if the current record being read is +a single-path record or a rename/copy record without reading ahead. +After reading added and deleted lines, reading up to `NUL` would yield +the pathname, but if that is `NUL`, the record will show two paths. diff --git a/diff.c b/diff.c index e74a30399e..d97ebc501a 100644 --- a/diff.c +++ b/diff.c @@ -734,7 +734,9 @@ struct diffstat_t { int nr; int alloc; struct diffstat_file { + char *from_name; char *name; + char *print_name; unsigned is_unmerged:1; unsigned is_binary:1; unsigned is_renamed:1; @@ -755,11 +757,14 @@ static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat, } diffstat->files[diffstat->nr++] = x; if (name_b) { - x->name = pprint_rename(name_a, name_b); + x->from_name = xstrdup(name_a); + x->name = xstrdup(name_b); x->is_renamed = 1; } - else + else { + x->from_name = NULL; x->name = xstrdup(name_a); + } return x; } @@ -803,6 +808,28 @@ static void show_graph(char ch, int cnt, const char *set, const char *reset) printf("%s", reset); } +static void fill_print_name(struct diffstat_file *file) +{ + char *pname; + + if (file->print_name) + return; + + if (!file->is_renamed) { + struct strbuf buf; + strbuf_init(&buf, 0); + if (quote_c_style(file->name, &buf, NULL, 0)) { + pname = strbuf_detach(&buf, NULL); + } else { + pname = file->name; + strbuf_release(&buf); + } + } else { + pname = pprint_rename(file->from_name, file->name); + } + file->print_name = pname; +} + static void show_stats(struct diffstat_t* data, struct diff_options *options) { int i, len, add, del, total, adds = 0, dels = 0; @@ -836,19 +863,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) for (i = 0; i < data->nr; i++) { struct diffstat_file *file = data->files[i]; int change = file->added + file->deleted; - - if (!file->is_renamed) { /* renames are already quoted by pprint_rename */ - struct strbuf buf; - strbuf_init(&buf, 0); - if (quote_c_style(file->name, &buf, NULL, 0)) { - free(file->name); - file->name = strbuf_detach(&buf, NULL); - } else { - strbuf_release(&buf); - } - } - - len = strlen(file->name); + fill_print_name(file); + len = strlen(file->print_name); if (max_len < len) max_len = len; @@ -873,7 +889,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) for (i = 0; i < data->nr; i++) { const char *prefix = ""; - char *name = data->files[i]->name; + char *name = data->files[i]->print_name; int added = data->files[i]->added; int deleted = data->files[i]->deleted; int name_len; @@ -901,17 +917,17 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) printf("%s%d%s", add_c, added, reset); printf(" bytes"); printf("\n"); - goto free_diffstat_file; + continue; } else if (data->files[i]->is_unmerged) { show_name(prefix, name, len, reset, set); printf(" Unmerged\n"); - goto free_diffstat_file; + continue; } else if (!data->files[i]->is_renamed && (added + deleted == 0)) { total_files--; - goto free_diffstat_file; + continue; } /* @@ -933,11 +949,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) show_graph('+', add, add_c, reset); show_graph('-', del, del_c, reset); putchar('\n'); - free_diffstat_file: - free(data->files[i]->name); - free(data->files[i]); } - free(data->files); printf("%s %d files changed, %d insertions(+), %d deletions(-)%s\n", set, total_files, adds, dels, reset); } @@ -962,11 +974,7 @@ static void show_shortstats(struct diffstat_t* data) dels += deleted; } } - free(data->files[i]->name); - free(data->files[i]); } - free(data->files); - printf(" %d files changed, %d insertions(+), %d deletions(-)\n", total_files, adds, dels); } @@ -975,6 +983,9 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) { int i; + if (data->nr == 0) + return; + for (i = 0; i < data->nr; i++) { struct diffstat_file *file = data->files[i]; @@ -982,15 +993,39 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) printf("-\t-\t"); else printf("%d\t%d\t", file->added, file->deleted); - if (!file->is_renamed) { - write_name_quoted(file->name, stdout, options->line_termination); + if (options->line_termination) { + fill_print_name(file); + if (!file->is_renamed) + write_name_quoted(file->name, stdout, + options->line_termination); + else { + fputs(file->print_name, stdout); + putchar(options->line_termination); + } } else { - fputs(file->name, stdout); - putchar(options->line_termination); + if (file->is_renamed) { + putchar('\0'); + write_name_quoted(file->from_name, stdout, '\0'); + } + write_name_quoted(file->name, stdout, '\0'); } } } +static void free_diffstat_info(struct diffstat_t *diffstat) +{ + int i; + for (i = 0; i < diffstat->nr; i++) { + struct diffstat_file *f = diffstat->files[i]; + if (f->name != f->print_name) + free(f->print_name); + free(f->name); + free(f->from_name); + free(f); + } + free(diffstat->files); +} + struct checkdiff_t { struct xdiff_emit_state xm; const char *filename; @@ -2943,8 +2978,9 @@ void diff_flush(struct diff_options *options) show_numstat(&diffstat, options); if (output_format & DIFF_FORMAT_DIFFSTAT) show_stats(&diffstat, options); - else if (output_format & DIFF_FORMAT_SHORTSTAT) + if (output_format & DIFF_FORMAT_SHORTSTAT) show_shortstats(&diffstat); + free_diffstat_info(&diffstat); separator++; } -- cgit v1.3 From 86f8c2368523db5ee56c8856748b26c31ebeb0aa Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Wed, 12 Dec 2007 17:22:59 +0100 Subject: Fix "diff --check" whitespace detection "diff --check" would only detect spaces before tabs if a tab was the last character in the leading indent. Fix that and add a test case to make sure the bug doesn't regress in the future. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- diff.c | 13 ++++++++++--- t/t4015-diff-whitespace.sh | 9 +++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d97ebc501a..9c79ee2891 100644 --- a/diff.c +++ b/diff.c @@ -1044,11 +1044,18 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) int i, spaces = 0, space_before_tab = 0, white_space_at_end = 0; /* check space before tab */ - for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++) + for (i = 1; i < len; i++) { if (line[i] == ' ') spaces++; - if (line[i - 1] == '\t' && spaces) - space_before_tab = 1; + else if (line[i] == '\t') { + if (spaces) { + space_before_tab = 1; + break; + } + } + else + break; + } /* check whitespace at line end */ if (line[len - 1] == '\n') diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 79fdff3f3a..6adf9d11d0 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -117,4 +117,13 @@ EOF git diff -b > out test_expect_success 'another test, with -b' 'git diff expect out' + +test_expect_success 'check mixed spaces and tabs in indent' ' + + # This is indented with SP HT SP. + echo " foo();" > x && + git diff --check | grep "space before tab" + +' + test_done -- cgit v1.3 From c279d7e9869740a6d64b0d1d70f7968af68d2071 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 13 Dec 2007 13:25:07 -0800 Subject: xdl_diff: identify call sites. This inserts a new function xdi_diff() that currently does not do anything other than calling the underlying xdl_diff() to the callchain of current callers of xdl_diff() function. Signed-off-by: Junio C Hamano --- builtin-blame.c | 2 +- builtin-rerere.c | 2 +- combine-diff.c | 2 +- diff.c | 10 +++++----- merge-file.c | 2 +- merge-tree.c | 2 +- xdiff-interface.c | 5 +++++ xdiff-interface.h | 1 + 8 files changed, 16 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index 5466d01f9a..99ea0a02cb 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -542,7 +542,7 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, state.ret->chunks = NULL; state.ret->num = 0; - xdl_diff(file_p, file_o, &xpp, &xecfg, &ecb); + xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb); if (state.ret->num) { struct chunk *chunk; diff --git a/builtin-rerere.c b/builtin-rerere.c index 74493237c9..37e6248138 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -260,7 +260,7 @@ static int diff_two(const char *file1, const char *label1, memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; ecb.outf = outf; - xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb); + xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); diff --git a/combine-diff.c b/combine-diff.c index 5a658dc0d5..e22db89932 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -226,7 +226,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, state.num_parent = num_parent; state.n = n; - xdl_diff(&parent_file, result_file, &xpp, &xecfg, &ecb); + xdi_diff(&parent_file, result_file, &xpp, &xecfg, &ecb); free(parent_file.ptr); /* Assign line numbers for this parent. diff --git a/diff.c b/diff.c index 9c79ee2891..3dd2f35f73 100644 --- a/diff.c +++ b/diff.c @@ -439,7 +439,7 @@ static void diff_words_show(struct diff_words_data *diff_words) ecb.outf = xdiff_outf; ecb.priv = diff_words; diff_words->xm.consume = fn_out_diff_words_aux; - xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb); + xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); @@ -1393,7 +1393,7 @@ static void builtin_diff(const char *name_a, if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); - xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); } @@ -1446,7 +1446,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; ecb.outf = xdiff_outf; ecb.priv = diffstat; - xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } free_and_return: @@ -1486,7 +1486,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, xpp.flags = XDF_NEED_MINIMAL; ecb.outf = xdiff_outf; ecb.priv = &data; - xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } free_and_return: diff_free_filespec_data(one); @@ -2898,7 +2898,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) xecfg.flags = XDL_EMIT_FUNCNAMES; ecb.outf = xdiff_outf; ecb.priv = &data; - xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); } SHA1_Final(sha1, &ctx); diff --git a/merge-file.c b/merge-file.c index 1e031eafe0..2a939c9dd8 100644 --- a/merge-file.c +++ b/merge-file.c @@ -71,7 +71,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2) res->size = 0; ecb.priv = res; - return xdl_diff(f1, f2, &xpp, &xecfg, &ecb); + return xdi_diff(f1, f2, &xpp, &xecfg, &ecb); } void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsigned long *size) diff --git a/merge-tree.c b/merge-tree.c index 7d4f628444..e08324686c 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -119,7 +119,7 @@ static void show_diff(struct merge_list *entry) if (!dst.ptr) size = 0; dst.size = size; - xdl_diff(&src, &dst, &xpp, &xecfg, &ecb); + xdi_diff(&src, &dst, &xpp, &xecfg, &ecb); free(src.ptr); free(dst.ptr); } diff --git a/xdiff-interface.c b/xdiff-interface.c index be866d12d3..69a022c134 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -103,6 +103,11 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) return 0; } +int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb) +{ + return xdl_diff(mf1, mf2, xpp, xecfg, xecb); +} + int read_mmfile(mmfile_t *ptr, const char *filename) { struct stat st; diff --git a/xdiff-interface.h b/xdiff-interface.h index fb742dbb6b..f7f791d96b 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -13,6 +13,7 @@ struct xdiff_emit_state { unsigned long remainder_size; }; +int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf); int parse_hunk_header(char *line, int len, int *ob, int *on, -- cgit v1.3 From 62c64895cfcf3bbf34969a69fa96a631f7d5b14e Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Thu, 13 Dec 2007 21:24:52 +0100 Subject: "diff --check" should affect exit status "git diff" has a --check option that can be used to check for whitespace problems but it only reported by printing warnings to the console. Now when the --check option is used we give a non-zero exit status, making "git diff --check" nicer to use in scripts and hooks. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 4 +- builtin-diff-files.c | 2 + builtin-diff-index.c | 2 + builtin-diff-tree.c | 28 ++++----- builtin-diff.c | 6 +- diff.c | 9 +++ diff.h | 1 + t/t4015-diff-whitespace.sh | 137 ++++++++++++++++++++++++++++++++++++++++- 8 files changed, 171 insertions(+), 18 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 5d22b7b58c..9ecc1d7bc4 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -93,7 +93,9 @@ endif::git-format-patch[] --check:: Warn if changes introduce trailing whitespace - or an indent that uses a space before a tab. + or an indent that uses a space before a tab. Exits with + non-zero status if problems are found. Not compatible with + --exit-code. --full-index:: Instead of the first handful characters, show full diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 046b7e34b5..4afc8724e7 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -33,5 +33,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) result = run_diff_files_cmd(&rev, argc, argv); if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; + if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) + return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; return result; } diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 556c506bfa..532b284b10 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -46,5 +46,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) result = run_diff_index(&rev, cached); if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; + if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) + return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; return result; } diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 2e13716eec..9ab90cb4c5 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -117,23 +117,23 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) break; } - if (!read_stdin) - return DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS) - && DIFF_OPT_TST(&opt->diffopt, HAS_CHANGES); + if (read_stdin) { + if (opt->diffopt.detect_rename) + opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | + DIFF_SETUP_USE_CACHE); + while (fgets(line, sizeof(line), stdin)) { + unsigned char sha1[20]; - if (opt->diffopt.detect_rename) - opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | - DIFF_SETUP_USE_CACHE); - while (fgets(line, sizeof(line), stdin)) { - unsigned char sha1[20]; - - if (get_sha1_hex(line, sha1)) { - fputs(line, stdout); - fflush(stdout); + if (get_sha1_hex(line, sha1)) { + fputs(line, stdout); + fflush(stdout); + } + else + diff_tree_stdin(line); } - else - diff_tree_stdin(line); } + if (opt->diffopt.output_format & DIFF_FORMAT_CHECKDIFF) + return DIFF_OPT_TST(&opt->diffopt, CHECK_FAILED) != 0; return DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS) && DIFF_OPT_TST(&opt->diffopt, HAS_CHANGES); } diff --git a/builtin-diff.c b/builtin-diff.c index 55fb84c730..9d878f6a71 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -247,7 +247,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix) /* If the user asked for our exit code then don't start a * pager or we would end up reporting its exit code instead. */ - if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) + if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS) && + (!(rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF))) setup_pager(); /* Do we have --cached and not have a pending object, then @@ -353,7 +354,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix) ent, ents); if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) result = DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; - + if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) + return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); return result; diff --git a/diff.c b/diff.c index 3dd2f35f73..8237075484 100644 --- a/diff.c +++ b/diff.c @@ -1031,6 +1031,7 @@ struct checkdiff_t { const char *filename; int lineno, color_diff; unsigned ws_rule; + unsigned status; }; static void checkdiff_consume(void *priv, char *line, unsigned long len) @@ -1064,6 +1065,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) white_space_at_end = 1; if (space_before_tab || white_space_at_end) { + data->status = 1; printf("%s:%d: %s", data->filename, data->lineno, ws); if (space_before_tab) { printf("space before tab"); @@ -1491,6 +1493,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, free_and_return: diff_free_filespec_data(one); diff_free_filespec_data(two); + if (data.status) + DIFF_OPT_SET(o, CHECK_FAILED); } struct diff_filespec *alloc_filespec(const char *path) @@ -2121,7 +2125,12 @@ int diff_setup_done(struct diff_options *options) if (options->output_format & DIFF_FORMAT_NAME_STATUS) count++; if (options->output_format & DIFF_FORMAT_CHECKDIFF) + { count++; + if (DIFF_OPT_TST(options, QUIET) || + DIFF_OPT_TST(options, EXIT_WITH_STATUS)) + die("--check may not be used with --quiet or --exit-code"); + } if (options->output_format & DIFF_FORMAT_NO_OUTPUT) count++; if (count > 1) diff --git a/diff.h b/diff.h index a52496a108..5d50d93a52 100644 --- a/diff.h +++ b/diff.h @@ -59,6 +59,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_ALLOW_EXTERNAL (1 << 13) #define DIFF_OPT_EXIT_WITH_STATUS (1 << 14) #define DIFF_OPT_REVERSE_DIFF (1 << 15) +#define DIFF_OPT_CHECK_FAILED (1 << 16) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 6adf9d11d0..dc538b3e33 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -117,7 +117,6 @@ EOF git diff -b > out test_expect_success 'another test, with -b' 'git diff expect out' - test_expect_success 'check mixed spaces and tabs in indent' ' # This is indented with SP HT SP. @@ -126,4 +125,140 @@ test_expect_success 'check mixed spaces and tabs in indent' ' ' +test_expect_success 'check with no whitespace errors' ' + + git commit -m "snapshot" && + echo "foo();" > x && + git diff --check + +' + +test_expect_failure 'check with trailing whitespace' ' + + echo "foo(); " > x && + git diff --check + +' + +test_expect_failure 'check with space before tab in indent' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git diff --check + +' + +test_expect_failure '--check and --exit-code are exclusive' ' + + git checkout x && + git diff --check --exit-code + +' + +test_expect_failure '--check and --quiet are exclusive' ' + + git diff --check --quiet + +' + +test_expect_success 'check staged with no whitespace errors' ' + + echo "foo();" > x && + git add x && + git diff --cached --check + +' + +test_expect_failure 'check staged with trailing whitespace' ' + + echo "foo(); " > x && + git add x && + git diff --cached --check + +' + +test_expect_failure 'check staged with space before tab in indent' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + git diff --cached --check + +' + +test_expect_success 'check with no whitespace errors (diff-index)' ' + + echo "foo();" > x && + git add x && + git diff-index --check HEAD + +' + +test_expect_failure 'check with trailing whitespace (diff-index)' ' + + echo "foo(); " > x && + git add x && + git diff-index --check HEAD + +' + +test_expect_failure 'check with space before tab in indent (diff-index)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + git diff-index --check HEAD + +' + +test_expect_success 'check staged with no whitespace errors (diff-index)' ' + + echo "foo();" > x && + git add x && + git diff-index --cached --check HEAD + +' + +test_expect_failure 'check staged with trailing whitespace (diff-index)' ' + + echo "foo(); " > x && + git add x && + git diff-index --cached --check HEAD + +' + +test_expect_failure 'check staged with space before tab in indent (diff-index)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git add x && + git diff-index --cached --check HEAD + +' + +test_expect_success 'check with no whitespace errors (diff-tree)' ' + + echo "foo();" > x && + git commit -m "new commit" x && + git diff-tree --check HEAD^ HEAD + +' + +test_expect_failure 'check with trailing whitespace (diff-tree)' ' + + echo "foo(); " > x && + git commit -m "another commit" x && + git diff-tree --check HEAD^ HEAD + +' + +test_expect_failure 'check with space before tab in indent (diff-tree)' ' + + # indent has space followed by hard tab + echo " foo();" > x && + git commit -m "yet another" x && + git diff-tree --check HEAD^ HEAD + +' + test_done -- cgit v1.3 From da31b358fb39b32622c14343ffe157a765f3948b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 13 Dec 2007 23:40:27 -0800 Subject: diff --check: minor fixups There is no reason --exit-code and --check-diff must be mutually exclusive, so assign different bits to different results and allow them to be returned from the command. Introduce diff_result_code() to factor out the common code to decide final status code based on diffopt settings and use it everywhere. Update tests to match the above fix. Turning pager off when "diff --check" is used is a regression. Signed-off-by: Junio C Hamano --- builtin-diff-files.c | 6 +----- builtin-diff-index.c | 6 +----- builtin-diff-tree.c | 6 ++---- builtin-diff.c | 11 ++++------- diff.c | 19 ++++++++++++++----- diff.h | 2 ++ t/t4015-diff-whitespace.sh | 4 ++-- 7 files changed, 26 insertions(+), 28 deletions(-) (limited to 'diff.c') diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 4afc8724e7..9c04111656 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -31,9 +31,5 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_RAW; result = run_diff_files_cmd(&rev, argc, argv); - if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) - return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; - if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) - return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; - return result; + return diff_result_code(&rev.diffopt, result); } diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 532b284b10..0f2390a20a 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -44,9 +44,5 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) return -1; } result = run_diff_index(&rev, cached); - if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) - return DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; - if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) - return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; - return result; + return diff_result_code(&rev.diffopt, result); } diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 9ab90cb4c5..ebc50efbd2 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -132,8 +132,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) diff_tree_stdin(line); } } - if (opt->diffopt.output_format & DIFF_FORMAT_CHECKDIFF) - return DIFF_OPT_TST(&opt->diffopt, CHECK_FAILED) != 0; - return DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS) - && DIFF_OPT_TST(&opt->diffopt, HAS_CHANGES); + + return diff_result_code(&opt->diffopt, 0); } diff --git a/builtin-diff.c b/builtin-diff.c index 9d878f6a71..29365a0b17 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -244,11 +244,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix) DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); DIFF_OPT_SET(&rev.diffopt, RECURSIVE); - /* If the user asked for our exit code then don't start a + /* + * If the user asked for our exit code then don't start a * pager or we would end up reporting its exit code instead. */ - if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS) && - (!(rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF))) + if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) setup_pager(); /* Do we have --cached and not have a pending object, then @@ -352,10 +352,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) else result = builtin_diff_combined(&rev, argc, argv, ent, ents); - if (DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS)) - result = DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0; - if (rev.diffopt.output_format & DIFF_FORMAT_CHECKDIFF) - return DIFF_OPT_TST(&rev.diffopt, CHECK_FAILED) != 0; + result = diff_result_code(&rev.diffopt, result); if (1 < rev.diffopt.skip_stat_unmatch) refresh_index_quietly(); return result; diff --git a/diff.c b/diff.c index 8237075484..3e46ff8a75 100644 --- a/diff.c +++ b/diff.c @@ -2125,12 +2125,7 @@ int diff_setup_done(struct diff_options *options) if (options->output_format & DIFF_FORMAT_NAME_STATUS) count++; if (options->output_format & DIFF_FORMAT_CHECKDIFF) - { count++; - if (DIFF_OPT_TST(options, QUIET) || - DIFF_OPT_TST(options, EXIT_WITH_STATUS)) - die("--check may not be used with --quiet or --exit-code"); - } if (options->output_format & DIFF_FORMAT_NO_OUTPUT) count++; if (count > 1) @@ -3180,6 +3175,20 @@ void diffcore_std(struct diff_options *options) DIFF_OPT_CLR(options, HAS_CHANGES); } +int diff_result_code(struct diff_options *opt, int status) +{ + int result = 0; + if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) && + !(opt->output_format & DIFF_FORMAT_CHECKDIFF)) + return status; + if (DIFF_OPT_TST(opt, EXIT_WITH_STATUS) && + DIFF_OPT_TST(opt, HAS_CHANGES)) + result |= 01; + if ((opt->output_format & DIFF_FORMAT_CHECKDIFF) && + DIFF_OPT_TST(opt, CHECK_FAILED)) + result |= 02; + return result; +} void diff_addremove(struct diff_options *options, int addremove, unsigned mode, diff --git a/diff.h b/diff.h index 5d50d93a52..7e8000a5d7 100644 --- a/diff.h +++ b/diff.h @@ -247,4 +247,6 @@ extern int run_diff_index(struct rev_info *revs, int cached); extern int do_diff_cache(const unsigned char *, struct diff_options *); extern int diff_flush_patch_id(struct diff_options *, unsigned char *); +extern int diff_result_code(struct diff_options *, int); + #endif /* DIFF_H */ diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index dc538b3e33..757a27abdb 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -148,14 +148,14 @@ test_expect_failure 'check with space before tab in indent' ' ' -test_expect_failure '--check and --exit-code are exclusive' ' +test_expect_success '--check and --exit-code are not exclusive' ' git checkout x && git diff --check --exit-code ' -test_expect_failure '--check and --quiet are exclusive' ' +test_expect_success '--check and --quiet are not exclusive' ' git diff --check --quiet -- cgit v1.3 From c1795bb08aae9fb7e4dc1a01e292b85e59b1c640 Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Thu, 13 Dec 2007 14:32:29 +0100 Subject: Unify whitespace checking This commit unifies three separate places where whitespace checking was performed: - the whitespace checking previously done in builtin-apply.c is extracted into a function in ws.c - the equivalent logic in "git diff" is removed - the emit_line_with_ws() function is also removed because that also rechecks the whitespace, and its functionality is rolled into ws.c The new function is called check_and_emit_line() and it does two things: checks a line for whitespace errors and optionally emits it. The checking is based on lines of content rather than patch lines (in other words, the caller must strip the leading "+" or "-"); this was suggested by Junio on the mailing list to allow for a future extension to "git show" to display whitespace errors in blobs. At the same time we teach it to report all classes of whitespace errors found for a given line rather than reporting only the first found error. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- builtin-apply.c | 54 ++++-------------- cache.h | 4 ++ diff.c | 138 +++++++-------------------------------------- t/t4015-diff-whitespace.sh | 2 +- ws.c | 105 ++++++++++++++++++++++++++++++++++ 5 files changed, 139 insertions(+), 164 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index f2e9a332ca..ab393f32e9 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -900,56 +900,22 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc static void check_whitespace(const char *line, int len, unsigned ws_rule) { - const char *err = "Adds trailing whitespace"; - int seen_space = 0; - int i; - - /* - * We know len is at least two, since we have a '+' and we - * checked that the last character was a '\n' before calling - * this function. That is, an addition of an empty line would - * check the '+' here. Sneaky... - */ - if ((ws_rule & WS_TRAILING_SPACE) && isspace(line[len-2])) - goto error; - - /* - * Make sure that there is no space followed by a tab in - * indentation. - */ - if (ws_rule & WS_SPACE_BEFORE_TAB) { - err = "Space in indent is followed by a tab"; - for (i = 1; i < len; i++) { - if (line[i] == '\t') { - if (seen_space) - goto error; - } - else if (line[i] == ' ') - seen_space = 1; - else - break; - } - } - - /* - * Make sure that the indentation does not contain more than - * 8 spaces. - */ - if ((ws_rule & WS_INDENT_WITH_NON_TAB) && - (8 < len) && !strncmp("+ ", line, 9)) { - err = "Indent more than 8 places with spaces"; - goto error; - } - return; + char *err; + unsigned result = check_and_emit_line(line + 1, len - 1, ws_rule, + NULL, NULL, NULL, NULL); + if (!result) + return; - error: whitespace_error++; if (squelch_whitespace_errors && squelch_whitespace_errors < whitespace_error) ; - else + else { + err = whitespace_error_string(result); fprintf(stderr, "%s.\n%s:%d:%.*s\n", - err, patch_input_file, linenr, len-2, line+1); + err, patch_input_file, linenr, len - 2, line + 1); + free(err); + } } /* diff --git a/cache.h b/cache.h index 27d90fe543..39331c28be 100644 --- a/cache.h +++ b/cache.h @@ -655,6 +655,10 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i extern unsigned whitespace_rule_cfg; extern unsigned whitespace_rule(const char *); extern unsigned parse_whitespace_rule(const char *); +extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule, + FILE *stream, const char *set, + const char *reset, const char *ws); +extern char *whitespace_error_string(unsigned ws); /* ls-files */ int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen); diff --git a/diff.c b/diff.c index 3e46ff8a75..577c773c3e 100644 --- a/diff.c +++ b/diff.c @@ -486,88 +486,9 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) static void emit_line(const char *set, const char *reset, const char *line, int len) { - if (len > 0 && line[len-1] == '\n') - len--; fputs(set, stdout); fwrite(line, len, 1, stdout); - puts(reset); -} - -static void emit_line_with_ws(int nparents, - const char *set, const char *reset, const char *ws, - const char *line, int len, unsigned ws_rule) -{ - int col0 = nparents; - int last_tab_in_indent = -1; - int last_space_in_indent = -1; - int i; - int tail = len; - int need_highlight_leading_space = 0; - /* - * The line is a newly added line. Does it have funny leading - * whitespaces? In indent, SP should never precede a TAB. In - * addition, under "indent with non tab" rule, there should not - * be more than 8 consecutive spaces. - */ - for (i = col0; i < len; i++) { - if (line[i] == '\t') { - last_tab_in_indent = i; - if ((ws_rule & WS_SPACE_BEFORE_TAB) && - 0 <= last_space_in_indent) - need_highlight_leading_space = 1; - } - else if (line[i] == ' ') - last_space_in_indent = i; - else - break; - } - if ((ws_rule & WS_INDENT_WITH_NON_TAB) && - 0 <= last_space_in_indent && - last_tab_in_indent < 0 && - 8 <= (i - col0)) { - last_tab_in_indent = i; - need_highlight_leading_space = 1; - } - fputs(set, stdout); - fwrite(line, col0, 1, stdout); fputs(reset, stdout); - if (((i == len) || line[i] == '\n') && i != col0) { - /* The whole line was indent */ - emit_line(ws, reset, line + col0, len - col0); - return; - } - i = col0; - if (need_highlight_leading_space) { - while (i < last_tab_in_indent) { - if (line[i] == ' ') { - fputs(ws, stdout); - putchar(' '); - fputs(reset, stdout); - } - else - putchar(line[i]); - i++; - } - } - tail = len - 1; - if (line[tail] == '\n' && i < tail) - tail--; - if (ws_rule & WS_TRAILING_SPACE) { - while (i < tail) { - if (!isspace(line[tail])) - break; - tail--; - } - } - if ((i < tail && line[tail + 1] != '\n')) { - /* This has whitespace between tail+1..len */ - fputs(set, stdout); - fwrite(line + i, tail - i + 1, 1, stdout); - fputs(reset, stdout); - emit_line(ws, reset, line + tail + 1, len - tail - 1); - } - else - emit_line(set, reset, line + i, len - i); } static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) @@ -577,9 +498,13 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons if (!*ws) emit_line(set, reset, line, len); - else - emit_line_with_ws(ecbdata->nparents, set, reset, ws, - line, len, ecbdata->ws_rule); + else { + /* Emit just the prefix, then the rest. */ + emit_line(set, reset, line, ecbdata->nparents); + (void)check_and_emit_line(line + ecbdata->nparents, + len - ecbdata->nparents, ecbdata->ws_rule, + stdout, set, reset, ws); + } } static void fn_out_consume(void *priv, char *line, unsigned long len) @@ -1040,45 +965,20 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE); const char *reset = diff_get_color(data->color_diff, DIFF_RESET); const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW); + char *err; if (line[0] == '+') { - int i, spaces = 0, space_before_tab = 0, white_space_at_end = 0; - - /* check space before tab */ - for (i = 1; i < len; i++) { - if (line[i] == ' ') - spaces++; - else if (line[i] == '\t') { - if (spaces) { - space_before_tab = 1; - break; - } - } - else - break; - } - - /* check whitespace at line end */ - if (line[len - 1] == '\n') - len--; - if (isspace(line[len - 1])) - white_space_at_end = 1; - - if (space_before_tab || white_space_at_end) { - data->status = 1; - printf("%s:%d: %s", data->filename, data->lineno, ws); - if (space_before_tab) { - printf("space before tab"); - if (white_space_at_end) - putchar(','); - } - if (white_space_at_end) - printf("whitespace at end"); - printf(":%s ", reset); - emit_line_with_ws(1, set, reset, ws, line, len, - data->ws_rule); - } - + data->status = check_and_emit_line(line + 1, len - 1, + data->ws_rule, NULL, NULL, NULL, NULL); + if (!data->status) + return; + err = whitespace_error_string(data->status); + printf("%s:%d: %s%s:%s ", data->filename, data->lineno, + ws, err, reset); + free(err); + emit_line(set, reset, line, 1); + (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, + stdout, set, reset, ws); data->lineno++; } else if (line[0] == ' ') data->lineno++; diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 757a27abdb..595cd60623 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -121,7 +121,7 @@ test_expect_success 'check mixed spaces and tabs in indent' ' # This is indented with SP HT SP. echo " foo();" > x && - git diff --check | grep "space before tab" + git diff --check | grep "Space in indent is followed by a tab" ' diff --git a/ws.c b/ws.c index 52c10caf35..d7d1522f8a 100644 --- a/ws.c +++ b/ws.c @@ -94,3 +94,108 @@ unsigned whitespace_rule(const char *pathname) return whitespace_rule_cfg; } } + +/* The returned string should be freed by the caller. */ +char *whitespace_error_string(unsigned ws) +{ + struct strbuf err; + strbuf_init(&err, 0); + if (ws & WS_TRAILING_SPACE) + strbuf_addstr(&err, "Adds trailing whitespace"); + if (ws & WS_SPACE_BEFORE_TAB) { + if (err.len) + strbuf_addstr(&err, ", "); + strbuf_addstr(&err, "Space in indent is followed by a tab"); + } + if (ws & WS_INDENT_WITH_NON_TAB) { + if (err.len) + strbuf_addstr(&err, ", "); + strbuf_addstr(&err, "Indent more than 8 places with spaces"); + } + return strbuf_detach(&err, NULL); +} + +/* If stream is non-NULL, emits the line after checking. */ +unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule, + FILE *stream, const char *set, + const char *reset, const char *ws) +{ + unsigned result = 0; + int leading_space = -1; + int trailing_whitespace = -1; + int trailing_newline = 0; + int i; + + /* Logic is simpler if we temporarily ignore the trailing newline. */ + if (len > 0 && line[len - 1] == '\n') { + trailing_newline = 1; + len--; + } + + /* Check for trailing whitespace. */ + if (ws_rule & WS_TRAILING_SPACE) { + for (i = len - 1; i >= 0; i--) { + if (isspace(line[i])) { + trailing_whitespace = i; + result |= WS_TRAILING_SPACE; + } + else + break; + } + } + + /* Check for space before tab in initial indent. */ + for (i = 0; i < len; i++) { + if (line[i] == '\t') { + if ((ws_rule & WS_SPACE_BEFORE_TAB) && + (leading_space != -1)) + result |= WS_SPACE_BEFORE_TAB; + break; + } + else if (line[i] == ' ') + leading_space = i; + else + break; + } + + /* Check for indent using non-tab. */ + if ((ws_rule & WS_INDENT_WITH_NON_TAB) && leading_space >= 8) + result |= WS_INDENT_WITH_NON_TAB; + + if (stream) { + /* Highlight errors in leading whitespace. */ + if ((result & WS_SPACE_BEFORE_TAB) || + (result & WS_INDENT_WITH_NON_TAB)) { + fputs(ws, stream); + fwrite(line, leading_space + 1, 1, stream); + fputs(reset, stream); + leading_space++; + } + else + leading_space = 0; + + /* Now the rest of the line starts at leading_space. + * The non-highlighted part ends at trailing_whitespace. */ + if (trailing_whitespace == -1) + trailing_whitespace = len; + + /* Emit non-highlighted (middle) segment. */ + if (trailing_whitespace - leading_space > 0) { + fputs(set, stream); + fwrite(line + leading_space, + trailing_whitespace - leading_space, 1, stream); + fputs(reset, stream); + } + + /* Highlight errors in trailing whitespace. */ + if (trailing_whitespace != len) { + fputs(ws, stream); + fwrite(line + trailing_whitespace, + len - trailing_whitespace, 1, stream); + fputs(reset, stream); + } + if (trailing_newline) + fputc('\n', stream); + } + return result; +} -- cgit v1.3 From 45e2a4b2b0a07cda05dda08b47906100c4711e4e Mon Sep 17 00:00:00 2001 From: Wincent Colaiuta Date: Thu, 13 Dec 2007 14:32:30 +0100 Subject: Make "diff --check" output match "git apply" For consistency, make the two tools report whitespace errors in the same way (the output of "diff --check" has been tweaked to match that of "git apply"). Note that although the textual content is basically the same only "git diff --check" provides a colorized version of the problematic lines; making "git apply" do colorization will require more extensive changes (figuring out the diff colorization preferences of the user) and so that will be a subject for another commit. Signed-off-by: Wincent Colaiuta Signed-off-by: Junio C Hamano --- builtin-apply.c | 4 ++-- diff.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index ab393f32e9..2edd83bf40 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -912,8 +912,8 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule) ; else { err = whitespace_error_string(result); - fprintf(stderr, "%s.\n%s:%d:%.*s\n", - err, patch_input_file, linenr, len - 2, line + 1); + fprintf(stderr, "%s:%d: %s.\n%.*s\n", + patch_input_file, linenr, err, len - 2, line + 1); free(err); } } diff --git a/diff.c b/diff.c index 577c773c3e..08ec66c794 100644 --- a/diff.c +++ b/diff.c @@ -973,8 +973,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (!data->status) return; err = whitespace_error_string(data->status); - printf("%s:%d: %s%s:%s ", data->filename, data->lineno, - ws, err, reset); + printf("%s:%d: %s.\n", data->filename, data->lineno, err); free(err); emit_line(set, reset, line, 1); (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, -- cgit v1.3 From cbe021004fc8762076bf497cc0b259d110b3a753 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 17 Dec 2007 13:42:20 +0000 Subject: Support config variable diff.external We had the diff.external variable in the documentation of the config file since its conception, but failed to respect it. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 08ec66c794..e26584cdfc 100644 --- a/diff.c +++ b/diff.c @@ -20,6 +20,7 @@ static int diff_detect_rename_default; static int diff_rename_limit_default = 100; static int diff_use_color_default; +static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; static char diff_colors[][COLOR_MAXLEN] = { @@ -163,6 +164,10 @@ int git_diff_ui_config(const char *var, const char *value) diff_auto_refresh_index = git_config_bool(var, value); return 0; } + if (!strcmp(var, "diff.external")) { + external_diff_cmd_cfg = xstrdup(value); + return 0; + } if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); @@ -209,6 +214,8 @@ static const char *external_diff(void) if (done_preparing) return external_diff_cmd; external_diff_cmd = getenv("GIT_EXTERNAL_DIFF"); + if (!external_diff_cmd) + external_diff_cmd = external_diff_cmd_cfg; done_preparing = 1; return external_diff_cmd; } -- cgit v1.3 From eab9a40b6dd5c1c571b1deb264133db47bb4794d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 18 Dec 2007 19:32:14 +0000 Subject: Teach diff machinery to display other prefixes than "a/" and "b/" With the new options "--src-prefix=", "--dst-prefix=" and "--no-prefix", you can now control the path prefixes of the diff machinery. These used to by hardwired to "a/" for the source prefix and "b/" for the destination prefix. Initial patch by Pascal Obry. Sane option names suggested by Linus. Signed-off-by: Johannes Schindelin Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 9 +++++++++ diff.c | 25 +++++++++++++++++-------- diff.h | 1 + 3 files changed, 27 insertions(+), 8 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 9ecc1d7bc4..1a78635fba 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -211,5 +211,14 @@ endif::git-format-patch[] --no-ext-diff:: Disallow external diff drivers. +--src-prefix=:: + Show the given source prefix instead of "a/". + +--dst-prefix=:: + Show the given destination prefix instead of "b/". + +--no-prefix:: + Do not show any source or destination prefix. + For more detailed explanation on these common options, see also link:diffcore.html[diffcore documentation]. diff --git a/diff.c b/diff.c index e26584cdfc..61fd49236a 100644 --- a/diff.c +++ b/diff.c @@ -290,9 +290,10 @@ static void emit_rewrite_diff(const char *name_a, const char *name_b, struct diff_filespec *one, struct diff_filespec *two, - int color_diff) + struct diff_options *o) { int lc_a, lc_b; + int color_diff = DIFF_OPT_TST(o, COLOR_DIFF); const char *name_a_tab, *name_b_tab; const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO); const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO); @@ -309,9 +310,9 @@ static void emit_rewrite_diff(const char *name_a, diff_populate_filespec(two, 0); lc_a = count_lines(one->data, one->size); lc_b = count_lines(two->data, two->size); - printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -", - metainfo, name_a, name_a_tab, reset, - metainfo, name_b, name_b_tab, reset, fraginfo); + printf("%s--- %s%s%s%s\n%s+++ %s%s%s%s\n%s@@ -", + metainfo, o->a_prefix, name_a, name_a_tab, reset, + metainfo, o->b_prefix, name_b, name_b_tab, reset, fraginfo); print_line_count(lc_a); printf(" +"); print_line_count(lc_b); @@ -1212,8 +1213,8 @@ static void builtin_diff(const char *name_a, const char *set = diff_get_color_opt(o, DIFF_METAINFO); const char *reset = diff_get_color_opt(o, DIFF_RESET); - a_one = quote_two("a/", name_a + (*name_a == '/')); - b_two = quote_two("b/", name_b + (*name_b == '/')); + a_one = quote_two(o->a_prefix, name_a + (*name_a == '/')); + b_two = quote_two(o->b_prefix, name_b + (*name_b == '/')); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset); @@ -1242,8 +1243,7 @@ static void builtin_diff(const char *name_a, if ((one->mode ^ two->mode) & S_IFMT) goto free_ab_and_return; if (complete_rewrite) { - emit_rewrite_diff(name_a, name_b, one, two, - DIFF_OPT_TST(o, COLOR_DIFF)); + emit_rewrite_diff(name_a, name_b, one, two, o); o->found_changes = 1; goto free_ab_and_return; } @@ -2020,6 +2020,9 @@ void diff_setup(struct diff_options *options) else DIFF_OPT_CLR(options, COLOR_DIFF); options->detect_rename = diff_detect_rename_default; + + options->a_prefix = "a/"; + options->b_prefix = "b/"; } int diff_setup_done(struct diff_options *options) @@ -2291,6 +2294,12 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (40 < options->abbrev) options->abbrev = 40; } + else if (!prefixcmp(arg, "--src-prefix=")) + options->a_prefix = arg + 13; + else if (!prefixcmp(arg, "--dst-prefix=")) + options->b_prefix = arg + 13; + else if (!strcmp(arg, "--no-prefix")) + options->a_prefix = options->b_prefix = ""; else return 0; return 1; diff --git a/diff.h b/diff.h index 7e8000a5d7..beccf85962 100644 --- a/diff.h +++ b/diff.h @@ -69,6 +69,7 @@ struct diff_options { const char *orderfile; const char *pickaxe; const char *single_follow; + const char *a_prefix, *b_prefix; unsigned flags; int context; int break_opt; -- cgit v1.3 From d56250911f4ec074048f4edb34551eaf384172cc Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 26 Dec 2007 17:13:36 -0800 Subject: Fix rewrite_diff() name quoting. This moves the logic to quote two paths (prefix + path) in C-style introduced in the previous commit from the dump_quoted_path() in combine-diff.c to quote.c, and uses it to fix rewrite_diff() that never C-quoted the pathnames correctly. Signed-off-by: Junio C Hamano --- combine-diff.c | 11 +---------- diff.c | 12 +++++++++--- quote.c | 16 ++++++++++++++++ quote.h | 1 + 4 files changed, 27 insertions(+), 13 deletions(-) (limited to 'diff.c') diff --git a/combine-diff.c b/combine-diff.c index 7d710334ff..0e19cbaacc 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -656,16 +656,7 @@ static void dump_quoted_path(const char *head, strbuf_reset(&buf); strbuf_addstr(&buf, c_meta); strbuf_addstr(&buf, head); - if (quote_c_style(prefix, NULL, NULL, 0) || - quote_c_style(path, NULL, NULL, 0)) { - strbuf_addch(&buf, '"'); - quote_c_style(prefix, &buf, NULL, 1); - quote_c_style(path, &buf, NULL, 1); - strbuf_addch(&buf, '"'); - } else { - strbuf_addstr(&buf, prefix); - strbuf_addstr(&buf, path); - } + quote_two_c_style(&buf, prefix, path, 0); strbuf_addstr(&buf, c_reset); puts(buf.buf); } diff --git a/diff.c b/diff.c index 61fd49236a..5bdc111378 100644 --- a/diff.c +++ b/diff.c @@ -300,19 +300,25 @@ static void emit_rewrite_diff(const char *name_a, const char *old = diff_get_color(color_diff, DIFF_FILE_OLD); const char *new = diff_get_color(color_diff, DIFF_FILE_NEW); const char *reset = diff_get_color(color_diff, DIFF_RESET); + static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT; name_a += (*name_a == '/'); name_b += (*name_b == '/'); name_a_tab = strchr(name_a, ' ') ? "\t" : ""; name_b_tab = strchr(name_b, ' ') ? "\t" : ""; + strbuf_reset(&a_name); + strbuf_reset(&b_name); + quote_two_c_style(&a_name, o->a_prefix, name_a, 0); + quote_two_c_style(&b_name, o->b_prefix, name_b, 0); + diff_populate_filespec(one, 0); diff_populate_filespec(two, 0); lc_a = count_lines(one->data, one->size); lc_b = count_lines(two->data, two->size); - printf("%s--- %s%s%s%s\n%s+++ %s%s%s%s\n%s@@ -", - metainfo, o->a_prefix, name_a, name_a_tab, reset, - metainfo, o->b_prefix, name_b, name_b_tab, reset, fraginfo); + printf("%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -", + metainfo, a_name.buf, name_a_tab, reset, + metainfo, b_name.buf, name_b_tab, reset, fraginfo); print_line_count(lc_a); printf(" +"); print_line_count(lc_b); diff --git a/quote.c b/quote.c index 6986b4420f..d061626c34 100644 --- a/quote.c +++ b/quote.c @@ -213,6 +213,22 @@ size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq) return quote_c_style_counted(name, -1, sb, fp, nodq); } +void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq) +{ + if (quote_c_style(prefix, NULL, NULL, 0) || + quote_c_style(path, NULL, NULL, 0)) { + if (!nodq) + strbuf_addch(sb, '"'); + quote_c_style(prefix, sb, NULL, 1); + quote_c_style(path, sb, NULL, 1); + if (!nodq) + strbuf_addch(sb, '"'); + } else { + strbuf_addstr(sb, prefix); + strbuf_addstr(sb, path); + } +} + void write_name_quoted(const char *name, FILE *fp, int terminator) { if (terminator) { diff --git a/quote.h b/quote.h index ab7596f57b..4da110ec01 100644 --- a/quote.h +++ b/quote.h @@ -41,6 +41,7 @@ extern char *sq_dequote(char *); extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp); extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq); +extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); extern void write_name_quoted(const char *name, FILE *, int terminator); extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, -- cgit v1.3 From 9a1805a8726ee41f25be2e0f2d5f38f1150d38e4 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 4 Jan 2008 03:59:34 -0500 Subject: add a "basic" diff config callback The diff porcelain uses git_diff_ui_config to set porcelain-ish config options, like automatically turning on color. The plumbing specifically avoids calling this function, since it doesn't want things like automatic color or rename detection. However, some diff options should be set for both plumbing and porcelain. For example, one can still turn on color in git-diff-files using the --color command line option. This means we want the color config from color.diff.* (so that once color is on, we use the user's preferred scheme), but _not_ the color.diff variable. We split the diff config into "ui" and "basic", where "basic" is suitable for use by plumbing (so _most_ things affecting the output should still go into the "ui" part). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-diff-files.c | 2 +- builtin-diff-index.c | 2 +- builtin-diff-tree.c | 2 +- diff.c | 6 ++++++ diff.h | 1 + 5 files changed, 10 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/builtin-diff-files.c b/builtin-diff-files.c index 9c04111656..4abe3c28fb 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -21,7 +21,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) prefix = setup_git_directory_gently(&nongit); init_revisions(&rev, prefix); - git_config(git_default_config); /* no "diff" UI options */ + git_config(git_diff_basic_config); /* no "diff" UI options */ rev.abbrev = 0; if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix)) diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 0f2390a20a..2b955deb91 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -17,7 +17,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) int result; init_revisions(&rev, prefix); - git_config(git_default_config); /* no "diff" UI options */ + git_config(git_diff_basic_config); /* no "diff" UI options */ rev.abbrev = 0; argc = setup_revisions(argc, argv, &rev, NULL); diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index ebc50efbd2..832797ff3b 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -68,7 +68,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int read_stdin = 0; init_revisions(opt, prefix); - git_config(git_default_config); /* no "diff" UI options */ + git_config(git_diff_basic_config); /* no "diff" UI options */ nr_sha1 = 0; opt->abbrev = 0; opt->diff = 1; diff --git a/diff.c b/diff.c index 5bdc111378..44aa477c41 100644 --- a/diff.c +++ b/diff.c @@ -178,6 +178,12 @@ int git_diff_ui_config(const char *var, const char *value) return parse_funcname_pattern(var, ep, value); } } + + return git_diff_basic_config(var, value); +} + +int git_diff_basic_config(const char *var, const char *value) +{ if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); color_parse(value, var, diff_colors[slot]); diff --git a/diff.h b/diff.h index beccf85962..073d5cbf1b 100644 --- a/diff.h +++ b/diff.h @@ -172,6 +172,7 @@ extern void diff_unmerge(struct diff_options *, #define DIFF_SETUP_USE_CACHE 2 #define DIFF_SETUP_USE_SIZE_CACHE 4 +extern int git_diff_basic_config(const char *var, const char *value); extern int git_diff_ui_config(const char *var, const char *value); extern void diff_setup(struct diff_options *); extern int diff_opt_parse(struct diff_options *, const char **, int); -- cgit v1.3 From e467193ff3f57171c5c3232b4ba3595970efbfb5 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 4 Jan 2008 04:16:14 -0500 Subject: diff: load funcname patterns in "basic" config The funcname patterns influence the "comment" on @@ lines of the diff. They are safe to use with plumbing since they don't fundamentally change the meaning of the diff in any way. Since all diff users call either diff_ui_config or diff_basic_config, we can get rid of the lazy reading of the config. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 44aa477c41..4a908b28af 100644 --- a/diff.c +++ b/diff.c @@ -174,8 +174,6 @@ int git_diff_ui_config(const char *var, const char *value) if (ep != var + 4) { if (!strcmp(ep, ".command")) return parse_lldiff_command(var, ep, value); - if (!strcmp(ep, ".funcname")) - return parse_funcname_pattern(var, ep, value); } } @@ -190,6 +188,14 @@ int git_diff_basic_config(const char *var, const char *value) return 0; } + if (!prefixcmp(var, "diff.")) { + const char *ep = strrchr(var, '.'); + if (ep != var + 4) { + if (!strcmp(ep, ".funcname")) + return parse_funcname_pattern(var, ep, value); + } + } + return git_default_config(var, value); } @@ -1160,7 +1166,6 @@ static const char *funcname_pattern(const char *ident) { struct funcname_pattern *pp; - read_config_if_needed(); for (pp = funcname_pattern_list; pp; pp = pp->next) if (!strcmp(ident, pp->name)) return pp->pattern; -- cgit v1.3 From cae6c25a7fdd7a316318c2efdc48e63cce36a68c Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 4 Jan 2008 04:45:31 -0500 Subject: diff: remove lazy config loading There is no point to this. Either: 1. The program has already loaded git_diff_ui_config, in which case this is a noop. 2. The program didn't, which means it is plumbing that does not _want_ git_diff_ui_config to be loaded. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 4a908b28af..2c78d74a42 100644 --- a/diff.c +++ b/diff.c @@ -59,14 +59,6 @@ static struct ll_diff_driver { char *cmd; } *user_diff, **user_diff_tail; -static void read_config_if_needed(void) -{ - if (!user_diff_tail) { - user_diff_tail = &user_diff; - git_config(git_diff_ui_config); - } -} - /* * Currently there is only "diff..command" variable; * because there are "diff.color." variables, we are parsing @@ -1822,7 +1814,6 @@ static const char *external_diff_attr(const char *name) !ATTR_UNSET(value)) { struct ll_diff_driver *drv; - read_config_if_needed(); for (drv = user_diff; drv; drv = drv->next) if (!strcmp(drv->name, value)) return drv->cmd; -- cgit v1.3 From 23707811c56a7756cbd6188e510f0a486c35c929 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 2 Jan 2008 01:50:11 -0800 Subject: diff: do not chomp hunk-header in the middle of a character We truncate hunk-header line at 80 bytes, but that 80th byte could be in the middle of a character, which is bad. This uses pick_one_utf8_char() function to make sure we do not cut a character in the middle. This assumes that the internal representation of the text is UTF-8. This needs to be extended in the future but the optimal direction has not been decided yet. Signed-off-by: Junio C Hamano --- diff.c | 25 +++++++++++++++++++++++++ t/t4025-hunk-header.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100755 t/t4025-hunk-header.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index 2c78d74a42..b18c140e3d 100644 --- a/diff.c +++ b/diff.c @@ -10,6 +10,7 @@ #include "color.h" #include "attr.h" #include "run-command.h" +#include "utf8.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -469,10 +470,13 @@ static void diff_words_show(struct diff_words_data *diff_words) } } +typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len); + struct emit_callback { struct xdiff_emit_state xm; int nparents, color_diff; unsigned ws_rule; + sane_truncate_fn truncate; const char **label_path; struct diff_words_data *diff_words; int *found_changesp; @@ -525,6 +529,24 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons } } +static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len) +{ + const char *cp; + unsigned long allot; + size_t l = len; + + if (ecb->truncate) + return ecb->truncate(line, len); + cp = line; + allot = l; + while (0 < l) { + (void) utf8_width(&cp, &l); + if (!cp) + break; /* truncated in the middle? */ + } + return allot - l; +} + static void fn_out_consume(void *priv, char *line, unsigned long len) { int i; @@ -555,8 +577,11 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) ; if (2 <= i && i < len && line[i] == ' ') { ecbdata->nparents = i - 1; + len = sane_truncate_line(ecbdata, line, len); emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO), reset, line, len); + if (line[len-1] != '\n') + putchar('\n'); return; } diff --git a/t/t4025-hunk-header.sh b/t/t4025-hunk-header.sh new file mode 100755 index 0000000000..9ba06b74ce --- /dev/null +++ b/t/t4025-hunk-header.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description='diff hunk header truncation' + +. ./test-lib.sh + +N='日本語' +N1='日' +N2='日本' +NS="$N$N$N$N$N$N$N$N$N$N$N$N$N" + +test_expect_success setup ' + + ( + echo "A $NS" + for c in B C D E F G H I J K + do + echo " $c" + done + echo "L $NS" + for c in M N O P Q R S T U V + do + echo " $c" + done + ) >file && + git add file && + + sed -e "/^ [EP]/s/$/ modified/" file+ && + mv file+ file + +' + +test_expect_success 'hunk header truncation with an overly long line' ' + + git diff | sed -n -e "s/^.*@@//p" >actual && + ( + echo " A $N$N$N$N$N$N$N$N$N2" + echo " L $N$N$N$N$N$N$N$N$N1" + ) >expected && + diff -u actual expected + +' + +test_done -- cgit v1.3 From 9f6fe82233fff26abd1a5315ba7709ccee078ec1 Mon Sep 17 00:00:00 2001 From: Bill Lear Date: Wed, 16 Jan 2008 06:46:53 -0600 Subject: Correct spelling in diff.c comment Correct a spelling mistake in a comment. Signed-off-by: Bill Lear Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index b18c140e3d..9ee0c41ba9 100644 --- a/diff.c +++ b/diff.c @@ -1224,7 +1224,7 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) /* * And define built-in fallback patterns here. Note that - * these can be overriden by the user's config settings. + * these can be overridden by the user's config settings. */ for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++) if (!strcmp(ident, builtin_funcname_pattern[i].name)) -- cgit v1.3 From 472ca780773ac75fa6af881117ce5360957fae2d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 17 Jan 2008 10:03:06 -0500 Subject: color unchanged lines as "plain" in "diff --color-words" These were mistakenly being colored in "meta" color. Signed-off-by: Junio C Hamano --- diff.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 9ee0c41ba9..5b8afdcb05 100644 --- a/diff.c +++ b/diff.c @@ -552,7 +552,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) int i; int color; struct emit_callback *ecbdata = priv; - const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO); + const char *meta = diff_get_color(ecbdata->color_diff, DIFF_METAINFO); + const char *plain = diff_get_color(ecbdata->color_diff, DIFF_PLAIN); const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET); *(ecbdata->found_changesp) = 1; @@ -564,9 +565,9 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : ""; printf("%s--- %s%s%s\n", - set, ecbdata->label_path[0], reset, name_a_tab); + meta, ecbdata->label_path[0], reset, name_a_tab); printf("%s+++ %s%s%s\n", - set, ecbdata->label_path[1], reset, name_b_tab); + meta, ecbdata->label_path[1], reset, name_b_tab); ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; } @@ -586,7 +587,6 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) } if (len < ecbdata->nparents) { - set = reset; emit_line(reset, reset, line, len); return; } @@ -610,7 +610,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) diff_words_show(ecbdata->diff_words); line++; len--; - emit_line(set, reset, line, len); + emit_line(plain, reset, line, len); return; } for (i = 0; i < ecbdata->nparents && len; i++) { -- cgit v1.3 From eadb5831342bb2e756fa05c03642c4aa1929d4f5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 18 Jan 2008 23:45:24 -0800 Subject: Avoid running lstat(2) on the same cache entry. Aside from the lstat(2) done for work tree files, there are quite many lstat(2) calls in refname dwimming codepath. This patch is not about reducing them. * It adds a new ce_flag, CE_UPTODATE, that is meant to mark the cache entries that record a regular file blob that is up to date in the work tree. If somebody later walks the index and wants to see if the work tree has changes, they do not have to be checked with lstat(2) again. * fill_stat_cache_info() marks the cache entry it just added with CE_UPTODATE. This has the effect of marking the paths we write out of the index and lstat(2) immediately as "no need to lstat -- we know it is up-to-date", from quite a lot fo callers: - git-apply --index - git-update-index - git-checkout-index - git-add (uses add_file_to_index()) - git-commit (ditto) - git-mv (ditto) * refresh_cache_ent() also marks the cache entry that are clean with CE_UPTODATE. * write_index is changed not to write CE_UPTODATE out to the index file, because CE_UPTODATE is meant to be transient only in core. For the same reason, CE_UPDATE is not written to prevent an accident from happening. Signed-off-by: Junio C Hamano Signed-off-by: Linus Torvalds --- cache.h | 3 +++ diff.c | 23 ++++++++++++++--------- read-cache.c | 16 +++++++++++++++- 3 files changed, 32 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/cache.h b/cache.h index 9eaffdefd0..3a47cdc9d2 100644 --- a/cache.h +++ b/cache.h @@ -130,6 +130,7 @@ struct cache_entry { /* In-memory only */ #define CE_UPDATE (0x10000) #define CE_REMOVE (0x20000) +#define CE_UPTODATE (0x40000) static inline unsigned create_ce_flags(size_t len, unsigned stage) { @@ -149,6 +150,8 @@ static inline size_t ce_namelen(const struct cache_entry *ce) #define ce_size(ce) cache_entry_size(ce_namelen(ce)) #define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce)) #define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT) +#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE) +#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE) #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) static inline unsigned int create_ce_mode(unsigned int mode) diff --git a/diff.c b/diff.c index 5b8afdcb05..d464fe3b20 100644 --- a/diff.c +++ b/diff.c @@ -1510,17 +1510,22 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int if (pos < 0) return 0; ce = active_cache[pos]; - if ((lstat(name, &st) < 0) || - !S_ISREG(st.st_mode) || /* careful! */ - ce_match_stat(ce, &st, 0) || - hashcmp(sha1, ce->sha1)) + + /* + * This is not the sha1 we are looking for, or + * unreusable because it is not a regular file. + */ + if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode)) return 0; - /* we return 1 only when we can stat, it is a regular file, - * stat information matches, and sha1 recorded in the cache - * matches. I.e. we know the file in the work tree really is - * the same as the pair. + + /* + * If ce matches the file in the work tree, we can reuse it. */ - return 1; + if (ce_uptodate(ce) || + (!lstat(name, &st) && !ce_match_stat(ce, &st, 0))) + return 1; + + return 0; } static int populate_from_stdin(struct diff_filespec *s) diff --git a/read-cache.c b/read-cache.c index 528f697f59..8ba8f0f88f 100644 --- a/read-cache.c +++ b/read-cache.c @@ -40,6 +40,9 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st) if (assume_unchanged) ce->ce_flags |= CE_VALID; + + if (S_ISREG(st->st_mode)) + ce_mark_uptodate(ce); } static int ce_compare_data(struct cache_entry *ce, struct stat *st) @@ -412,6 +415,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int verbose) !ie_match_stat(istate, istate->cache[pos], &st, ce_option)) { /* Nothing changed, really */ free(ce); + ce_mark_uptodate(istate->cache[pos]); return 0; } @@ -779,6 +783,9 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, int changed, size; int ignore_valid = options & CE_MATCH_IGNORE_VALID; + if (ce_uptodate(ce)) + return ce; + if (lstat(ce->name, &st) < 0) { if (err) *err = errno; @@ -797,8 +804,15 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate, if (ignore_valid && assume_unchanged && !(ce->ce_flags & CE_VALID)) ; /* mark this one VALID again */ - else + else { + /* + * We do not mark the index itself "modified" + * because CE_UPTODATE flag is in-core only; + * we are not going to write this change out. + */ + ce_mark_uptodate(ce); return ce; + } } if (ie_modified(istate, ce, &st, options)) { -- cgit v1.3 From 21e5ad50fc5e7277c74cfbb3cf6502468e840f86 Mon Sep 17 00:00:00 2001 From: Steffen Prohaska Date: Wed, 6 Feb 2008 12:25:58 +0100 Subject: safecrlf: Add mechanism to warn about irreversible crlf conversions CRLF conversion bears a slight chance of corrupting data. autocrlf=true will convert CRLF to LF during commit and LF to CRLF during checkout. A file that contains a mixture of LF and CRLF before the commit cannot be recreated by git. For text files this is the right thing to do: it corrects line endings such that we have only LF line endings in the repository. But for binary files that are accidentally classified as text the conversion can corrupt data. If you recognize such corruption early you can easily fix it by setting the conversion type explicitly in .gitattributes. Right after committing you still have the original file in your work tree and this file is not yet corrupted. You can explicitly tell git that this file is binary and git will handle the file appropriately. Unfortunately, the desired effect of cleaning up text files with mixed line endings and the undesired effect of corrupting binary files cannot be distinguished. In both cases CRLFs are removed in an irreversible way. For text files this is the right thing to do because CRLFs are line endings, while for binary files converting CRLFs corrupts data. This patch adds a mechanism that can either warn the user about an irreversible conversion or can even refuse to convert. The mechanism is controlled by the variable core.safecrlf, with the following values: - false: disable safecrlf mechanism - warn: warn about irreversible conversions - true: refuse irreversible conversions The default is to warn. Users are only affected by this default if core.autocrlf is set. But the current default of git is to leave core.autocrlf unset, so users will not see warnings unless they deliberately chose to activate the autocrlf mechanism. The safecrlf mechanism's details depend on the git command. The general principles when safecrlf is active (not false) are: - we warn/error out if files in the work tree can modified in an irreversible way without giving the user a chance to backup the original file. - for read-only operations that do not modify files in the work tree we do not not print annoying warnings. There are exceptions. Even though... - "git add" itself does not touch the files in the work tree, the next checkout would, so the safety triggers; - "git apply" to update a text file with a patch does touch the files in the work tree, but the operation is about text files and CRLF conversion is about fixing the line ending inconsistencies, so the safety does not trigger; - "git diff" itself does not touch the files in the work tree, it is often run to inspect the changes you intend to next "git add". To catch potential problems early, safety triggers. The concept of a safety check was originally proposed in a similar way by Linus Torvalds. Thanks to Dimitry Potapov for insisting on getting the naked LF/autocrlf=true case right. Signed-off-by: Steffen Prohaska --- Documentation/config.txt | 45 ++++++++++++++++++++++++++++++++ Documentation/gitattributes.txt | 20 ++++++++++++++ builtin-apply.c | 2 +- builtin-blame.c | 2 +- cache.h | 11 +++++++- config.c | 9 +++++++ convert.c | 47 ++++++++++++++++++++++++++++----- diff.c | 2 +- environment.c | 1 + sha1_file.c | 3 ++- t/t0020-crlf.sh | 58 +++++++++++++++++++++++++++++++++++++++++ 11 files changed, 189 insertions(+), 11 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 4e222f15a5..7b8cae1541 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -139,6 +139,51 @@ core.autocrlf:: "text" (i.e. be subjected to the autocrlf mechanism) is decided purely based on the contents. +core.safecrlf:: + If true, makes git check if converting `CRLF` as controlled by + `core.autocrlf` is reversible. Git will verify if a command + modifies a file in the work tree either directly or indirectly. + For example, committing a file followed by checking out the + same file should yield the original file in the work tree. If + this is not the case for the current setting of + `core.autocrlf`, git will reject the file. The variable can + be set to "warn", in which case git will only warn about an + irreversible conversion but continue the operation. ++ +CRLF conversion bears a slight chance of corrupting data. +autocrlf=true will convert CRLF to LF during commit and LF to +CRLF during checkout. A file that contains a mixture of LF and +CRLF before the commit cannot be recreated by git. For text +files this is the right thing to do: it corrects line endings +such that we have only LF line endings in the repository. +But for binary files that are accidentally classified as text the +conversion can corrupt data. ++ +If you recognize such corruption early you can easily fix it by +setting the conversion type explicitly in .gitattributes. Right +after committing you still have the original file in your work +tree and this file is not yet corrupted. You can explicitly tell +git that this file is binary and git will handle the file +appropriately. ++ +Unfortunately, the desired effect of cleaning up text files with +mixed line endings and the undesired effect of corrupting binary +files cannot be distinguished. In both cases CRLFs are removed +in an irreversible way. For text files this is the right thing +to do because CRLFs are line endings, while for binary files +converting CRLFs corrupts data. ++ +Note, this safety check does not mean that a checkout will generate a +file identical to the original file for a different setting of +`core.autocrlf`, but only for the current one. For example, a text +file with `LF` would be accepted with `core.autocrlf=input` and could +later be checked out with `core.autocrlf=true`, in which case the +resulting file would contain `CRLF`, although the original file +contained `LF`. However, in both work trees the line endings would be +consistent, that is either all `LF` or all `CRLF`, but never mixed. A +file with mixed line endings would be reported by the `core.safecrlf` +mechanism. + core.symlinks:: If false, symbolic links are checked out as small plain files that contain the link text. linkgit:git-update-index[1] and diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 35a29fd60c..84ec9623a2 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -133,6 +133,26 @@ When `core.autocrlf` is set to "input", line endings are converted to LF upon checkin, but there is no conversion done upon checkout. +If `core.safecrlf` is set to "true" or "warn", git verifies if +the conversion is reversible for the current setting of +`core.autocrlf`. For "true", git rejects irreversible +conversions; for "warn", git only prints a warning but accepts +an irreversible conversion. The safety triggers to prevent such +a conversion done to the files in the work tree, but there are a +few exceptions. Even though... + +- "git add" itself does not touch the files in the work tree, the + next checkout would, so the safety triggers; + +- "git apply" to update a text file with a patch does touch the files + in the work tree, but the operation is about text files and CRLF + conversion is about fixing the line ending inconsistencies, so the + safety does not trigger; + +- "git diff" itself does not touch the files in the work tree, it is + often run to inspect the changes you intend to next "git add". To + catch potential problems early, safety triggers. + `ident` ^^^^^^^ diff --git a/builtin-apply.c b/builtin-apply.c index 15432b6782..3b5618d434 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1430,7 +1430,7 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf) case S_IFREG: if (strbuf_read_file(buf, path, st->st_size) != st->st_size) return error("unable to open or read %s", path); - convert_to_git(path, buf->buf, buf->len, buf); + convert_to_git(path, buf->buf, buf->len, buf, 0); return 0; default: return -1; diff --git a/builtin-blame.c b/builtin-blame.c index 9b4c02e87f..c361ee194e 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2073,7 +2073,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con if (strbuf_read(&buf, 0, 0) < 0) die("read error %s from stdin", strerror(errno)); } - convert_to_git(path, buf.buf, buf.len, &buf); + convert_to_git(path, buf.buf, buf.len, &buf, 0); origin->file.ptr = buf.buf; origin->file.size = buf.len; pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1); diff --git a/cache.h b/cache.h index 549f4bbac7..6003c83b2d 100644 --- a/cache.h +++ b/cache.h @@ -330,6 +330,14 @@ extern size_t packed_git_limit; extern size_t delta_base_cache_limit; extern int auto_crlf; +enum safe_crlf { + SAFE_CRLF_FALSE = 0, + SAFE_CRLF_FAIL = 1, + SAFE_CRLF_WARN = 2, +}; + +extern enum safe_crlf safe_crlf; + #define GIT_REPO_VERSION 0 extern int repository_format_version; extern int check_repository_format(void); @@ -633,7 +641,8 @@ extern void trace_argv_printf(const char **argv, const char *format, ...); /* convert.c */ /* returns 1 if *dst was used */ -extern int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst); +extern int convert_to_git(const char *path, const char *src, size_t len, + struct strbuf *dst, enum safe_crlf checksafe); extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst); /* add */ diff --git a/config.c b/config.c index 498259ebef..3256c99553 100644 --- a/config.c +++ b/config.c @@ -407,6 +407,15 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.safecrlf")) { + if (value && !strcasecmp(value, "warn")) { + safe_crlf = SAFE_CRLF_WARN; + return 0; + } + safe_crlf = git_config_bool(var, value); + return 0; + } + if (!strcmp(var, "user.name")) { strlcpy(git_default_name, value, sizeof(git_default_name)); return 0; diff --git a/convert.c b/convert.c index 80f114b2e2..3bbf0c51c2 100644 --- a/convert.c +++ b/convert.c @@ -85,8 +85,39 @@ static int is_binary(unsigned long size, struct text_stat *stats) return 0; } +static void check_safe_crlf(const char *path, int action, + struct text_stat *stats, enum safe_crlf checksafe) +{ + if (!checksafe) + return; + + if (action == CRLF_INPUT || auto_crlf <= 0) { + /* + * CRLFs would not be restored by checkout: + * check if we'd remove CRLFs + */ + if (stats->crlf) { + if (checksafe == SAFE_CRLF_WARN) + warning("CRLF will be replaced by LF in %s.", path); + else /* i.e. SAFE_CRLF_FAIL */ + die("CRLF would be replaced by LF in %s.", path); + } + } else if (auto_crlf > 0) { + /* + * CRLFs would be added by checkout: + * check if we have "naked" LFs + */ + if (stats->lf != stats->crlf) { + if (checksafe == SAFE_CRLF_WARN) + warning("LF will be replaced by CRLF in %s", path); + else /* i.e. SAFE_CRLF_FAIL */ + die("LF would be replaced by CRLF in %s", path); + } + } +} + static int crlf_to_git(const char *path, const char *src, size_t len, - struct strbuf *buf, int action) + struct strbuf *buf, int action, enum safe_crlf checksafe) { struct text_stat stats; char *dst; @@ -95,9 +126,6 @@ static int crlf_to_git(const char *path, const char *src, size_t len, return 0; gather_stats(src, len, &stats); - /* No CR? Nothing to convert, regardless. */ - if (!stats.cr) - return 0; if (action == CRLF_GUESS) { /* @@ -115,6 +143,12 @@ static int crlf_to_git(const char *path, const char *src, size_t len, return 0; } + check_safe_crlf(path, action, &stats, checksafe); + + /* Optimization: No CR? Nothing to convert, regardless. */ + if (!stats.cr) + return 0; + /* only grow if not in place */ if (strbuf_avail(buf) + buf->len < len) strbuf_grow(buf, len - buf->len); @@ -536,7 +570,8 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check) return !!ATTR_TRUE(value); } -int convert_to_git(const char *path, const char *src, size_t len, struct strbuf *dst) +int convert_to_git(const char *path, const char *src, size_t len, + struct strbuf *dst, enum safe_crlf checksafe) { struct git_attr_check check[3]; int crlf = CRLF_GUESS; @@ -558,7 +593,7 @@ int convert_to_git(const char *path, const char *src, size_t len, struct strbuf src = dst->buf; len = dst->len; } - ret |= crlf_to_git(path, src, len, dst, crlf); + ret |= crlf_to_git(path, src, len, dst, crlf, checksafe); if (ret) { src = dst->buf; len = dst->len; diff --git a/diff.c b/diff.c index 5b8afdcb05..562c20ed40 100644 --- a/diff.c +++ b/diff.c @@ -1624,7 +1624,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) * Convert from working tree format to canonical git format */ strbuf_init(&buf, 0); - if (convert_to_git(s->path, s->data, s->size, &buf)) { + if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) { size_t size = 0; munmap(s->data, s->size); s->should_munmap = 0; diff --git a/environment.c b/environment.c index 18a1c4eec4..e351e99ed7 100644 --- a/environment.c +++ b/environment.c @@ -35,6 +35,7 @@ int pager_use_color = 1; char *editor_program; char *excludes_file; int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */ +enum safe_crlf safe_crlf = SAFE_CRLF_WARN; unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; /* This is set by setup_git_dir_gently() and/or git_default_config() */ diff --git a/sha1_file.c b/sha1_file.c index 66a4e00fa8..41799492f9 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2358,7 +2358,8 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) { struct strbuf nbuf; strbuf_init(&nbuf, 0); - if (convert_to_git(path, buf, size, &nbuf)) { + if (convert_to_git(path, buf, size, &nbuf, + write_object ? safe_crlf : 0)) { munmap(buf, size); buf = strbuf_detach(&nbuf, &size); re_allocated = 1; diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 8b27aa892b..90ea081db6 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -8,6 +8,10 @@ q_to_nul () { tr Q '\000' } +q_to_cr () { + tr Q '\015' +} + append_cr () { sed -e 's/$/Q/' | tr Q '\015' } @@ -42,6 +46,60 @@ test_expect_success setup ' echo happy. ' +test_expect_success 'safecrlf: autocrlf=input, all CRLF' ' + + git config core.autocrlf input && + git config core.safecrlf true && + + for w in I am all CRLF; do echo $w; done | append_cr >allcrlf && + ! git add allcrlf +' + +test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' ' + + git config core.autocrlf input && + git config core.safecrlf true && + + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && + ! git add mixed +' + +test_expect_success 'safecrlf: autocrlf=true, all LF' ' + + git config core.autocrlf true && + git config core.safecrlf true && + + for w in I am all LF; do echo $w; done >alllf && + ! git add alllf +' + +test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' ' + + git config core.autocrlf true && + git config core.safecrlf true && + + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed && + ! git add mixed +' + +test_expect_success 'safecrlf: print warning only once' ' + + git config core.autocrlf input && + git config core.safecrlf warn && + + for w in I am all LF; do echo $w; done >doublewarn && + git add doublewarn && + git commit -m "nowarn" && + for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >doublewarn && + test $(git add doublewarn 2>&1 | grep "CRLF will be replaced by LF" | wc -l) = 1 +' + +test_expect_success 'switch off autocrlf, safecrlf, reset HEAD' ' + git config core.autocrlf false && + git config core.safecrlf false && + git reset --hard HEAD^ +' + test_expect_success 'update with autocrlf=input' ' rm -f tmp one dir/two three && -- cgit v1.3 From 64f30e948be5fb2cd2f65e91c0eab5ab4719c636 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Feb 2008 10:53:56 -0800 Subject: diff.c: guard config parser from value=NULL diff.external, diff.*.command, diff.color.*, color.diff.* and diff.*.funcname configuration variables expect a string value. Signed-off-by: Junio C Hamano --- diff.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 5b8afdcb05..4d2e23ae1b 100644 --- a/diff.c +++ b/diff.c @@ -158,6 +158,8 @@ int git_diff_ui_config(const char *var, const char *value) return 0; } if (!strcmp(var, "diff.external")) { + if (!value) + return config_error_nonbool(var); external_diff_cmd_cfg = xstrdup(value); return 0; } @@ -165,8 +167,11 @@ int git_diff_ui_config(const char *var, const char *value) const char *ep = strrchr(var, '.'); if (ep != var + 4) { - if (!strcmp(ep, ".command")) + if (!strcmp(ep, ".command")) { + if (!value) + return config_error_nonbool(var); return parse_lldiff_command(var, ep, value); + } } } @@ -177,6 +182,8 @@ int git_diff_basic_config(const char *var, const char *value) { if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); + if (!value) + return config_error_nonbool(var); color_parse(value, var, diff_colors[slot]); return 0; } @@ -184,8 +191,11 @@ int git_diff_basic_config(const char *var, const char *value) if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); if (ep != var + 4) { - if (!strcmp(ep, ".funcname")) + if (!strcmp(ep, ".funcname")) { + if (!value) + return config_error_nonbool(var); return parse_funcname_pattern(var, ep, value); + } } } -- cgit v1.3 From 7df7c019c2a46672c12a11a45600cdc698e03029 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 12 Feb 2008 13:26:31 -0800 Subject: Add "--dirstat" for some directory statistics This adds a new form of overview diffstat output, doing something that I have occasionally ended up doing manually (and badly, because it's actually pretty nasty to do), and that I think is very useful for an project like the kernel that has a fairly deep and well-separated directory structure with semantic meaning. What I mean by that is that it's often interesting to see exactly which sub-directories are impacted by a patch, and to what degree - even if you don't perhaps care so much about the individual files themselves. What makes the concept more interesting is that the "impact" is often hierarchical: in the kernel, for example, something could either have a very localized impact to "fs/ext3/" and then it's interesting to see that such a patch changes mostly that subdirectory, but you could have another patch that changes some generic VFS-layer issue which affects _many_ subdirectories that are all under "fs/", but none - or perhaps just a couple of them - of the individual filesystems are interesting in themselves. So what commonly happens is that you may have big changes in a specific sub-subdirectory, but still also significant separate changes to the subdirectory leading up to that - maybe you have significant VFS-level changes, but *also* changes under that VFS layer in the NFS-specific directories, for example. In that case, you do want the low-level parts that are significant to show up, but then the insignificant ones should show up as under the more generic top-level directory. This patch shows all of that with "--dirstat". The output can be either something simple like commit 81772fe... Author: Thomas Gleixner Date: Sun Feb 10 23:57:36 2008 +0100 x86: remove over noisy debug printk pageattr-test.c contains a noisy debug printk that people reported. The condition under which it prints (randomly tapping into a mem_map[] hole and not being able to c_p_a() there) is valid behavior and not interesting to report. Remove it. Signed-off-by: Thomas Gleixner Acked-by: Ingo Molnar Signed-off-by: Linus Torvalds 100.0% arch/x86/mm/ or something much more complex like commit e231c2e... Author: David Howells Date: Thu Feb 7 00:15:26 2008 -0800 Convert ERR_PTR(PTR_ERR(p)) instances to ERR_CAST(p) 20.5% crypto/ 7.6% fs/afs/ 7.6% fs/fuse/ 7.6% fs/gfs2/ 5.1% fs/jffs2/ 5.1% fs/nfs/ 5.1% fs/nfsd/ 7.6% fs/reiserfs/ 15.3% fs/ 7.6% net/rxrpc/ 10.2% security/keys/ where that latter example is an example of significant work in some individual fs/*/ subdirectories (like the patches to reiserfs accounting for 7.6% of the whole), but then discounting those individual filesystems, there's also 15.3% other "random" things that weren't worth reporting on their oen left over under fs/ in general (either in that directory itself, or in subdirectories of fs/ that didn't have enough changes to be reported individually). I'd like to stress that the "15.3% fs/" mentioned above is the stuff that is under fs/ but that was _not_ significant enough to report on its own. So the above does _not_ mean that 15.3% of the work was under fs/ per se, because that 15.3% does *not* include the already-reported 7.6% of afs, 7.6% of fuse etc. If you want to enable "cumulative" directory statistics, you can use the "--cumulative" flag, which adds up percentages recursively even when they have been already reported for a sub-directory. That cumulative output is disabled if *all* of the changes in one subdirectory come from a deeper subdirectory, to avoid repeating subdirectories all the way to the root. For an example of the cumulative reporting, the above commit becomes commit e231c2e... Author: David Howells Date: Thu Feb 7 00:15:26 2008 -0800 Convert ERR_PTR(PTR_ERR(p)) instances to ERR_CAST(p) 20.5% crypto/ 7.6% fs/afs/ 7.6% fs/fuse/ 7.6% fs/gfs2/ 5.1% fs/jffs2/ 5.1% fs/nfs/ 5.1% fs/nfsd/ 7.6% fs/reiserfs/ 61.5% fs/ 7.6% net/rxrpc/ 10.2% security/keys/ in which the commit percentages now obviously add up to much more than 100%: now the changes that were already reported for the sub-directories under fs/ are then cumulatively included in the whole percentage of fs/ (ie now shows 61.5% as opposed to the 15.3% without the cumulative reporting). The default reporting limit has been arbitrarily set at 3%, which seems to be a pretty good cut-off, but you can specify the cut-off manually by giving it as an option parameter (eg "--dirstat=5" makes the cut-off be at 5% instead) NOTE! The percentages are purely about the total lines added and removed, not anything smarter (or dumber) than that. Also note that you should not generally expect things to add up to 100%: not only does it round down, we don't report leftover scraps (they add up to the top-level change count, but we don't even bother reporting that, it only reports subdirectories). Quite frankly, as a top-level manager this is really convenient for me, but it's going to be very boring for git itself since there are few subdirectories. Also, don't expect things to make tons of sense if you combine this with "-M" and there are cross-directory renames etc. But even for git itself, you can get some fun statistics. Try out git log --dirstat and see the occasional mentions of things like Documentation/, git-gui/, gitweb/ and gitk-git/. Or try out something like git diff --dirstat v1.5.0..v1.5.4 which does kind of git an overview that shows *something*. But in general, the output is more exciting for big projects with deeper structure, and doing a git diff --dirstat v2.6.24..v2.6.25-rc1 on the kernel is what I actually wrote this for! Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- diff.h | 3 +++ 2 files changed, 92 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index cd8bc4dcc3..dd374d436f 100644 --- a/diff.c +++ b/diff.c @@ -990,6 +990,85 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) } } +struct diffstat_dir { + struct diffstat_file **files; + int nr, percent, cumulative; +}; + +static long gather_dirstat(struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen) +{ + unsigned long this_dir = 0; + unsigned int sources = 0; + + while (dir->nr) { + struct diffstat_file *f = *dir->files; + int namelen = strlen(f->name); + unsigned long this; + char *slash; + + if (namelen < baselen) + break; + if (memcmp(f->name, base, baselen)) + break; + slash = strchr(f->name + baselen, '/'); + if (slash) { + int newbaselen = slash + 1 - f->name; + this = gather_dirstat(dir, changed, f->name, newbaselen); + sources++; + } else { + this = f->added + f->deleted; + dir->files++; + dir->nr--; + sources += 2; + } + this_dir += this; + } + + /* + * We don't report dirstat's for + * - the top level + * - or cases where everything came from a single directory + * under this directory (sources == 1). + */ + if (baselen && sources != 1) { + int permille = this_dir * 1000 / changed; + if (permille) { + int percent = permille / 10; + if (percent >= dir->percent) { + printf("%4d.%01d%% %.*s\n", percent, permille % 10, baselen, base); + if (!dir->cumulative) + return 0; + } + } + } + return this_dir; +} + +static void show_dirstat(struct diffstat_t *data, struct diff_options *options) +{ + int i; + unsigned long changed; + struct diffstat_dir dir; + + /* Calculate total changes */ + changed = 0; + for (i = 0; i < data->nr; i++) { + changed += data->files[i]->added; + changed += data->files[i]->deleted; + } + + /* This can happen even with many files, if everything was renames */ + if (!changed) + return; + + /* Show all directories with more than x% of the changes */ + dir.files = data->files; + dir.nr = data->nr; + dir.percent = options->dirstat_percent; + dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE; + gather_dirstat(&dir, changed, "", 0); +} + static void free_diffstat_info(struct diffstat_t *diffstat) { int i; @@ -2058,6 +2137,7 @@ void diff_setup(struct diff_options *options) options->line_termination = '\n'; options->break_opt = -1; options->rename_limit = -1; + options->dirstat_percent = 3; options->context = 3; options->msg_sep = ""; @@ -2099,6 +2179,7 @@ int diff_setup_done(struct diff_options *options) DIFF_FORMAT_NUMSTAT | DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SHORTSTAT | + DIFF_FORMAT_DIRSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH); @@ -2110,6 +2191,7 @@ int diff_setup_done(struct diff_options *options) DIFF_FORMAT_NUMSTAT | DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SHORTSTAT | + DIFF_FORMAT_DIRSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_CHECKDIFF)) DIFF_OPT_SET(options, RECURSIVE); @@ -2220,6 +2302,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_NUMSTAT; else if (!strcmp(arg, "--shortstat")) options->output_format |= DIFF_FORMAT_SHORTSTAT; + else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent)) + options->output_format |= DIFF_FORMAT_DIRSTAT; + else if (!strcmp(arg, "--cumulative")) + options->output_format |= DIFF_FORMAT_CUMULATIVE; else if (!strcmp(arg, "--check")) options->output_format |= DIFF_FORMAT_CHECKDIFF; else if (!strcmp(arg, "--summary")) @@ -2938,7 +3024,7 @@ void diff_flush(struct diff_options *options) separator++; } - if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) { + if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIRSTAT)) { struct diffstat_t diffstat; memset(&diffstat, 0, sizeof(struct diffstat_t)); @@ -2948,6 +3034,8 @@ void diff_flush(struct diff_options *options) if (check_pair_status(p)) diff_flush_stat(p, options, &diffstat); } + if (output_format & DIFF_FORMAT_DIRSTAT) + show_dirstat(&diffstat, options); if (output_format & DIFF_FORMAT_NUMSTAT) show_numstat(&diffstat, options); if (output_format & DIFF_FORMAT_DIFFSTAT) diff --git a/diff.h b/diff.h index 073d5cbf1b..8c6bb54119 100644 --- a/diff.h +++ b/diff.h @@ -30,6 +30,8 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_FORMAT_SUMMARY 0x0008 #define DIFF_FORMAT_PATCH 0x0010 #define DIFF_FORMAT_SHORTSTAT 0x0020 +#define DIFF_FORMAT_DIRSTAT 0x0040 +#define DIFF_FORMAT_CUMULATIVE 0x0080 /* These override all above */ #define DIFF_FORMAT_NAME 0x0100 @@ -80,6 +82,7 @@ struct diff_options { int pickaxe_opts; int rename_score; int rename_limit; + int dirstat_percent; int setup; int abbrev; const char *msg_sep; -- cgit v1.3 From cd676a513672eeb9663c6d4de276a1c860a4b879 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 12 Feb 2008 14:26:02 -0800 Subject: diff --relative: output paths as relative to the current subdirectory This adds --relative option to the diff family. When you start from a subdirectory: $ git diff --relative shows only the diff that is inside your current subdirectory, and without $prefix part. People who usually live in subdirectories may like it. There are a few things I should also mention about the change: - This works not just with diff but also works with the log family of commands, but the history pruning is not affected. In other words, if you go to a subdirectory, you can say: $ git log --relative -p but it will show the log message even for commits that do not touch the current directory. You can limit it by giving pathspec yourself: $ git log --relative -p . This originally was not a conscious design choice, but we have a way to affect diff pathspec and pruning pathspec independently. IOW "git log --full-diff -p ." tells it to prune history to commits that affect the current subdirectory but show the changes with full context. I think it makes more sense to leave pruning independent from --relative than the obvious alternative of always pruning with the current subdirectory, which would break the symmetry. - Because this works also with the log family, you could format-patch a single change, limiting the effect to your subdirectory, like so: $ cd gitk-git $ git format-patch -1 --relative 911f1eb But because that is a special purpose usage, this option will never become the default, with or without repository or user preference configuration. The risk of producing a partial patch and sending it out by mistake is too great if we did so. - This is inherently incompatible with --no-index, which is a bolted-on hack that does not have much to do with git itself. I didn't bother checking and erroring out on the combined use of the options, but probably I should. Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 5 +++ builtin-diff.c | 11 ++++- diff.c | 100 ++++++++++++++++++++++++++++++++++------- diff.h | 3 ++ revision.c | 4 ++ 5 files changed, 105 insertions(+), 18 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 8d35cbd60d..286c30c01a 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -170,6 +170,11 @@ endif::git-format-patch[] Swap two inputs; that is, show differences from index or on-disk file to tree contents. +--relative:: + When run from a subdirectory of the project, it can be + told to exclude changes outside the directory and show + pathnames relative to it with this option. + --text:: Treat all files as text. diff --git a/builtin-diff.c b/builtin-diff.c index 8d7a5697f2..19fa668185 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -43,12 +43,17 @@ static void stuff_change(struct diff_options *opt, tmp_u = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_u; tmp_c = old_name; old_name = new_name; new_name = tmp_c; } + + if (opt->prefix && + (strncmp(old_name, opt->prefix, opt->prefix_length) || + strncmp(new_name, opt->prefix, opt->prefix_length))) + return; + one = alloc_filespec(old_name); two = alloc_filespec(new_name); fill_filespec(one, old_sha1, old_mode); fill_filespec(two, new_sha1, new_mode); - /* NEEDSWORK: shouldn't this part of diffopt??? */ diff_queue(&diff_queued_diff, one, two); } @@ -241,6 +246,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix) if (diff_setup_done(&rev.diffopt) < 0) die("diff_setup_done failed"); } + if (rev.diffopt.prefix && nongit) { + rev.diffopt.prefix = NULL; + rev.diffopt.prefix_length = 0; + } DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); DIFF_OPT_SET(&rev.diffopt, RECURSIVE); diff --git a/diff.c b/diff.c index 5b8afdcb05..db4bd557b7 100644 --- a/diff.c +++ b/diff.c @@ -1397,6 +1397,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, } static void builtin_checkdiff(const char *name_a, const char *name_b, + const char *attr_path, struct diff_filespec *one, struct diff_filespec *two, struct diff_options *o) { @@ -1411,7 +1412,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, data.filename = name_b ? name_b : name_a; data.lineno = 0; data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); - data.ws_rule = whitespace_rule(data.filename); + data.ws_rule = whitespace_rule(attr_path); if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); @@ -1831,6 +1832,9 @@ static const char *external_diff_attr(const char *name) { struct git_attr_check attr_diff_check; + if (!name) + return NULL; + setup_diff_attr_check(&attr_diff_check); if (!git_checkattr(name, 1, &attr_diff_check)) { const char *value = attr_diff_check.value; @@ -1850,6 +1854,7 @@ static const char *external_diff_attr(const char *name) static void run_diff_cmd(const char *pgm, const char *name, const char *other, + const char *attr_path, struct diff_filespec *one, struct diff_filespec *two, const char *xfrm_msg, @@ -1859,7 +1864,7 @@ static void run_diff_cmd(const char *pgm, if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL)) pgm = NULL; else { - const char *cmd = external_diff_attr(name); + const char *cmd = external_diff_attr(attr_path); if (cmd) pgm = cmd; } @@ -1900,6 +1905,15 @@ static int similarity_index(struct diff_filepair *p) return p->score * 100 / MAX_SCORE; } +static void strip_prefix(int prefix_length, const char **namep, const char **otherp) +{ + /* Strip the prefix but do not molest /dev/null and absolute paths */ + if (*namep && **namep != '/') + *namep += prefix_length; + if (*otherp && **otherp != '/') + *otherp += prefix_length; +} + static void run_diff(struct diff_filepair *p, struct diff_options *o) { const char *pgm = external_diff(); @@ -1909,16 +1923,21 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) struct diff_filespec *two = p->two; const char *name; const char *other; + const char *attr_path; int complete_rewrite = 0; + name = p->one->path; + other = (strcmp(name, p->two->path) ? p->two->path : NULL); + attr_path = name; + if (o->prefix_length) + strip_prefix(o->prefix_length, &name, &other); if (DIFF_PAIR_UNMERGED(p)) { - run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0); + run_diff_cmd(pgm, name, NULL, attr_path, + NULL, NULL, NULL, o, 0); return; } - name = p->one->path; - other = (strcmp(name, p->two->path) ? p->two->path : NULL); diff_fill_sha1_info(one); diff_fill_sha1_info(two); @@ -1981,15 +2000,17 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) * needs to be split into deletion and creation. */ struct diff_filespec *null = alloc_filespec(two->path); - run_diff_cmd(NULL, name, other, one, null, xfrm_msg, o, 0); + run_diff_cmd(NULL, name, other, attr_path, + one, null, xfrm_msg, o, 0); free(null); null = alloc_filespec(one->path); - run_diff_cmd(NULL, name, other, null, two, xfrm_msg, o, 0); + run_diff_cmd(NULL, name, other, attr_path, + null, two, xfrm_msg, o, 0); free(null); } else - run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o, - complete_rewrite); + run_diff_cmd(pgm, name, other, attr_path, + one, two, xfrm_msg, o, complete_rewrite); strbuf_release(&msg); } @@ -2010,6 +2031,9 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o, name = p->one->path; other = (strcmp(name, p->two->path) ? p->two->path : NULL); + if (o->prefix_length) + strip_prefix(o->prefix_length, &name, &other); + diff_fill_sha1_info(p->one); diff_fill_sha1_info(p->two); @@ -2022,6 +2046,7 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) { const char *name; const char *other; + const char *attr_path; if (DIFF_PAIR_UNMERGED(p)) { /* unmerged */ @@ -2030,11 +2055,15 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) name = p->one->path; other = (strcmp(name, p->two->path) ? p->two->path : NULL); + attr_path = other ? other : name; + + if (o->prefix_length) + strip_prefix(o->prefix_length, &name, &other); diff_fill_sha1_info(p->one); diff_fill_sha1_info(p->two); - builtin_checkdiff(name, other, p->one, p->two, o); + builtin_checkdiff(name, other, attr_path, p->one, p->two, o); } void diff_setup(struct diff_options *options) @@ -2076,6 +2105,13 @@ int diff_setup_done(struct diff_options *options) if (DIFF_OPT_TST(options, FIND_COPIES_HARDER)) options->detect_rename = DIFF_DETECT_COPY; + if (!DIFF_OPT_TST(options, RELATIVE_NAME)) + options->prefix = NULL; + if (options->prefix) + options->prefix_length = strlen(options->prefix); + else + options->prefix_length = 0; + if (options->output_format & (DIFF_FORMAT_NAME | DIFF_FORMAT_NAME_STATUS | DIFF_FORMAT_CHECKDIFF | @@ -2264,6 +2300,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) } else if (!strcmp(arg, "--no-renames")) options->detect_rename = 0; + else if (!strcmp(arg, "--relative")) + DIFF_OPT_SET(options, RELATIVE_NAME); /* xdiff options */ else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) @@ -2475,12 +2513,20 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) printf("%c%c", p->status, inter_name_termination); } - if (p->status == DIFF_STATUS_COPIED || p->status == DIFF_STATUS_RENAMED) { - write_name_quoted(p->one->path, stdout, inter_name_termination); - write_name_quoted(p->two->path, stdout, line_termination); + if (p->status == DIFF_STATUS_COPIED || + p->status == DIFF_STATUS_RENAMED) { + const char *name_a, *name_b; + name_a = p->one->path; + name_b = p->two->path; + strip_prefix(opt->prefix_length, &name_a, &name_b); + write_name_quoted(name_a, stdout, inter_name_termination); + write_name_quoted(name_b, stdout, line_termination); } else { - const char *path = p->one->mode ? p->one->path : p->two->path; - write_name_quoted(path, stdout, line_termination); + const char *name_a, *name_b; + name_a = p->one->mode ? p->one->path : p->two->path; + name_b = NULL; + strip_prefix(opt->prefix_length, &name_a, &name_b); + write_name_quoted(name_a, stdout, line_termination); } } @@ -2677,8 +2723,13 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt) diff_flush_checkdiff(p, opt); else if (fmt & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS)) diff_flush_raw(p, opt); - else if (fmt & DIFF_FORMAT_NAME) - write_name_quoted(p->two->path, stdout, opt->line_termination); + else if (fmt & DIFF_FORMAT_NAME) { + const char *name_a, *name_b; + name_a = p->two->path; + name_b = NULL; + strip_prefix(opt->prefix_length, &name_a, &name_b); + write_name_quoted(name_a, stdout, opt->line_termination); + } } static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs) @@ -3164,6 +3215,11 @@ void diff_addremove(struct diff_options *options, if (!path) path = ""; sprintf(concatpath, "%s%s", base, path); + + if (options->prefix && + strncmp(concatpath, options->prefix, options->prefix_length)) + return; + one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); @@ -3193,6 +3249,11 @@ void diff_change(struct diff_options *options, } if (!path) path = ""; sprintf(concatpath, "%s%s", base, path); + + if (options->prefix && + strncmp(concatpath, options->prefix, options->prefix_length)) + return; + one = alloc_filespec(concatpath); two = alloc_filespec(concatpath); fill_filespec(one, old_sha1, old_mode); @@ -3207,6 +3268,11 @@ void diff_unmerge(struct diff_options *options, unsigned mode, const unsigned char *sha1) { struct diff_filespec *one, *two; + + if (options->prefix && + strncmp(path, options->prefix, options->prefix_length)) + return; + one = alloc_filespec(path); two = alloc_filespec(path); fill_filespec(one, sha1, mode); diff --git a/diff.h b/diff.h index 073d5cbf1b..fcd9653822 100644 --- a/diff.h +++ b/diff.h @@ -60,6 +60,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_EXIT_WITH_STATUS (1 << 14) #define DIFF_OPT_REVERSE_DIFF (1 << 15) #define DIFF_OPT_CHECK_FAILED (1 << 16) +#define DIFF_OPT_RELATIVE_NAME (1 << 17) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) @@ -82,6 +83,8 @@ struct diff_options { int rename_limit; int setup; int abbrev; + const char *prefix; + int prefix_length; const char *msg_sep; const char *stat_sep; long xdl_opts; diff --git a/revision.c b/revision.c index 6e85aaa3fb..6d9188b6cb 100644 --- a/revision.c +++ b/revision.c @@ -720,6 +720,10 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->commit_format = CMIT_FMT_DEFAULT; diff_setup(&revs->diffopt); + if (prefix) { + revs->diffopt.prefix = prefix; + revs->diffopt.prefix_length = strlen(prefix); + } } static void add_pending_commit_list(struct rev_info *revs, -- cgit v1.3 From c0cb4a067972700f0682fbab13768bcc7dc7a3c3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 13 Feb 2008 00:34:39 -0800 Subject: diff --relative: help working in a bare repository This allows the --relative option to say which subdirectory to pretend to be in, so that in a bare repository, you can say: $ git log --relative=drivers/ v2.6.20..v2.6.22 -- drivers/scsi/ Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 7 +++++-- diff.c | 4 ++++ revision.c | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 286c30c01a..8dc5b001c4 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -170,10 +170,13 @@ endif::git-format-patch[] Swap two inputs; that is, show differences from index or on-disk file to tree contents. ---relative:: +--relative[=]:: When run from a subdirectory of the project, it can be told to exclude changes outside the directory and show - pathnames relative to it with this option. + pathnames relative to it with this option. When you are + not in a subdirectory (e.g. in a bare repository), you + can name which subdirectory to make the output relative + to by giving a as an argument. --text:: Treat all files as text. diff --git a/diff.c b/diff.c index db4bd557b7..2b89b16007 100644 --- a/diff.c +++ b/diff.c @@ -2302,6 +2302,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->detect_rename = 0; else if (!strcmp(arg, "--relative")) DIFF_OPT_SET(options, RELATIVE_NAME); + else if (!prefixcmp(arg, "--relative=")) { + DIFF_OPT_SET(options, RELATIVE_NAME); + options->prefix = arg + 11; + } /* xdiff options */ else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) diff --git a/revision.c b/revision.c index 6d9188b6cb..4d6f57b64e 100644 --- a/revision.c +++ b/revision.c @@ -720,7 +720,7 @@ void init_revisions(struct rev_info *revs, const char *prefix) revs->commit_format = CMIT_FMT_DEFAULT; diff_setup(&revs->diffopt); - if (prefix) { + if (prefix && !revs->diffopt.prefix) { revs->diffopt.prefix = prefix; revs->diffopt.prefix_length = strlen(prefix); } -- cgit v1.3 From 588071112c7ca14a04d674e4f019572f0bb77326 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 15 Feb 2008 09:37:54 -0800 Subject: diff.c: fixup garding of config parser from value=NULL Christian Couder noticed that there still were a handcrafted error() call that we should have converted to config_error_nonbool() where parse_lldiff_command() parses the configuration file. Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 4d2e23ae1b..2aaace890c 100644 --- a/diff.c +++ b/diff.c @@ -87,7 +87,7 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val } if (!value) - return error("%s: lacks value", var); + return config_error_nonbool(var); drv->cmd = strdup(value); return 0; } -- cgit v1.3 From 8ca496e97d100195c9015f4da8ddaad693e91961 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Thu, 14 Feb 2008 06:50:00 +0100 Subject: diff.c: replace a 'strdup' with 'xstrdup'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 2aaace890c..047310fc94 100644 --- a/diff.c +++ b/diff.c @@ -88,7 +88,7 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val if (!value) return config_error_nonbool(var); - drv->cmd = strdup(value); + drv->cmd = xstrdup(value); return 0; } -- cgit v1.3 From 2c778210f8877e8f5c88715c2d25d1a43d976566 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Feb 2008 05:59:53 +0100 Subject: diff.c: remove useless check for value != NULL It is not necessary to check if value != NULL before calling 'parse_lldiff_command' as there is already a check inside this function. By the way this patch also improves the existing check inside 'parse_lldiff_command' by using: return config_error_nonbool(var); instead of: return error("%s: lacks value", var); Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- diff.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 047310fc94..ed41ce418e 100644 --- a/diff.c +++ b/diff.c @@ -166,13 +166,8 @@ int git_diff_ui_config(const char *var, const char *value) if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); - if (ep != var + 4) { - if (!strcmp(ep, ".command")) { - if (!value) - return config_error_nonbool(var); - return parse_lldiff_command(var, ep, value); - } - } + if (ep != var + 4 && !strcmp(ep, ".command")) + return parse_lldiff_command(var, ep, value); } return git_diff_basic_config(var, value); -- cgit v1.3 From b20a60d0c0f23384cb4141d75d9a7c90e99c1432 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 16 Feb 2008 06:02:17 +0100 Subject: diff.c: add "const" qualifier to "char *cmd" member of "struct ll_diff_driver" Also use "git_config_string" to simplify code where "cmd" is set. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- diff.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index ed41ce418e..f082f55bc5 100644 --- a/diff.c +++ b/diff.c @@ -57,7 +57,7 @@ static int parse_diff_color_slot(const char *var, int ofs) static struct ll_diff_driver { const char *name; struct ll_diff_driver *next; - char *cmd; + const char *cmd; } *user_diff, **user_diff_tail; /* @@ -86,10 +86,7 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val user_diff_tail = &(drv->next); } - if (!value) - return config_error_nonbool(var); - drv->cmd = xstrdup(value); - return 0; + return git_config_string(&(drv->cmd), var, value); } /* -- cgit v1.3 From 0ef617f4b6ea78ad63dd11e90f8c854238176981 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 15 Feb 2008 20:30:05 -0800 Subject: diff: Fix miscounting of --check output c1795bb (Unify whitespace checking) incorrectly made the checking function return without incrementing the line numbers when there is no whitespace problem is found on a '+' line. This resurrects the earlier behaviour. Noticed and reported by Jay Soffian. The test script was stolen from Jay's independent fix. Signed-off-by: Junio C Hamano --- diff.c | 4 ++-- t/t4015-diff-whitespace.sh | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f082f55bc5..39f6e21aa3 100644 --- a/diff.c +++ b/diff.c @@ -1013,6 +1013,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) char *err; if (line[0] == '+') { + data->lineno++; data->status = check_and_emit_line(line + 1, len - 1, data->ws_rule, NULL, NULL, NULL, NULL); if (!data->status) @@ -1023,13 +1024,12 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) emit_line(set, reset, line, 1); (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, stdout, set, reset, ws); - data->lineno++; } else if (line[0] == ' ') data->lineno++; else if (line[0] == '@') { char *plus = strchr(line, '+'); if (plus) - data->lineno = strtol(plus, NULL, 10); + data->lineno = strtol(plus, NULL, 10) - 1; else die("invalid diff"); } diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index d30169fbdc..83c54b747f 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -326,4 +326,13 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: ! git diff --check ' + +test_expect_success 'line numbers in --check output are correct' ' + + echo "" > x && + echo "foo(); " >> x && + git diff --check | grep "x:2:" + +' + test_done -- cgit v1.3 From 6b2f2d9805dd22c6f74957e0d76a1d2921b40c16 Mon Sep 17 00:00:00 2001 From: Matthias Kestenholz Date: Mon, 18 Feb 2008 08:26:03 +0100 Subject: Add color.ui variable which globally enables colorization if set Signed-off-by: Matthias Kestenholz Signed-off-by: Junio C Hamano --- Documentation/config.txt | 7 +++++++ builtin-branch.c | 10 +++++++--- builtin-commit.c | 4 ++++ builtin-diff.c | 5 +++++ builtin-log.c | 17 +++++++++++++++++ color.c | 12 ++++++++++++ color.h | 11 +++++++++++ diff.c | 6 +++--- diff.h | 1 + wt-status.c | 6 +++--- 10 files changed, 70 insertions(+), 9 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index f2f6a774e0..7b676710ba 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -489,6 +489,13 @@ color.status.:: commit.template:: Specify a file to use as the template for new commit messages. +color.ui:: + When set to `always`, always use colors in all git commands which + are capable of colored output. When false (or `never`), never. When + set to `true` or `auto`, use colors only when the output is to the + terminal. When more specific variables of color.* are set, they always + take precedence over this setting. Defaults to false. + diff.autorefreshindex:: When using `git diff` to compare with work tree files, do not consider stat-only change as changed. diff --git a/builtin-branch.c b/builtin-branch.c index e414c88983..9edf2eb816 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -31,7 +31,7 @@ static unsigned char head_sha1[20]; static int branch_track = 1; -static int branch_use_color; +static int branch_use_color = -1; static char branch_colors[][COLOR_MAXLEN] = { "\033[m", /* reset */ "", /* PLAIN (normal) */ @@ -79,12 +79,12 @@ static int git_branch_config(const char *var, const char *value) branch_track = git_config_bool(var, value); return 0; } - return git_default_config(var, value); + return git_color_default_config(var, value); } static const char *branch_get_color(enum color_branch ix) { - if (branch_use_color) + if (branch_use_color > 0) return branch_colors[ix]; return ""; } @@ -588,6 +588,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix) }; git_config(git_branch_config); + + if (branch_use_color == -1) + branch_use_color = git_use_color_default; + track = branch_track; argc = parse_options(argc, argv, options, builtin_branch_usage, 0); if (!!delete + !!rename + !!force_create > 1) diff --git a/builtin-commit.c b/builtin-commit.c index 6612b4f405..065e1f7b7f 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -7,6 +7,7 @@ #include "cache.h" #include "cache-tree.h" +#include "color.h" #include "dir.h" #include "builtin.h" #include "diff.h" @@ -771,6 +772,9 @@ int cmd_status(int argc, const char **argv, const char *prefix) git_config(git_status_config); + if (wt_status_use_color == -1) + wt_status_use_color = git_use_color_default; + argc = parse_and_validate_options(argc, argv, builtin_status_usage); index_file = prepare_index(argc, argv, prefix); diff --git a/builtin-diff.c b/builtin-diff.c index 8d7a5697f2..8f53f52dcb 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -4,6 +4,7 @@ * Copyright (c) 2006 Junio C Hamano */ #include "cache.h" +#include "color.h" #include "commit.h" #include "blob.h" #include "tag.h" @@ -229,6 +230,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix) prefix = setup_git_directory_gently(&nongit); git_config(git_diff_ui_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index; diff --git a/builtin-log.c b/builtin-log.c index 99d69f0791..f2216d3187 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -5,6 +5,7 @@ * 2006 Junio Hamano */ #include "cache.h" +#include "color.h" #include "commit.h" #include "diff.h" #include "revision.h" @@ -235,6 +236,10 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.diff = 1; rev.simplify_history = 0; @@ -307,6 +312,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) int i, count, ret = 0; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.diff = 1; rev.combine_merges = 1; @@ -367,6 +376,10 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); init_reflog_walk(&rev.reflog_info); rev.abbrev_commit = 1; @@ -395,6 +408,10 @@ int cmd_log(int argc, const char **argv, const char *prefix) struct rev_info rev; git_config(git_log_config); + + if (diff_use_color_default == -1) + diff_use_color_default = git_use_color_default; + init_revisions(&rev, prefix); rev.always_show_header = 1; cmd_log_init(argc, argv, prefix, &rev); diff --git a/color.c b/color.c index cb70340420..12a6453f90 100644 --- a/color.c +++ b/color.c @@ -3,6 +3,8 @@ #define COLOR_RESET "\033[m" +int git_use_color_default = 0; + static int parse_color(const char *name, int len) { static const char * const color_names[] = { @@ -143,6 +145,16 @@ int git_config_colorbool(const char *var, const char *value, int stdout_is_tty) return 0; } +int git_color_default_config(const char *var, const char *value) +{ + if (!strcmp(var, "color.ui")) { + git_use_color_default = git_config_colorbool(var, value, -1); + return 0; + } + + return git_default_config(var, value); +} + static int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args, const char *trail) { diff --git a/color.h b/color.h index ff63513d39..ecda5569a2 100644 --- a/color.h +++ b/color.h @@ -4,6 +4,17 @@ /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ #define COLOR_MAXLEN 24 +/* + * This variable stores the value of color.ui + */ +extern int git_use_color_default; + + +/* + * Use this instead of git_default_config if you need the value of color.ui. + */ +int git_color_default_config(const char *var, const char *value); + int git_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *var, const char *value, char *dst); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); diff --git a/diff.c b/diff.c index 58fe7750f9..c30c252272 100644 --- a/diff.c +++ b/diff.c @@ -20,7 +20,7 @@ static int diff_detect_rename_default; static int diff_rename_limit_default = 100; -static int diff_use_color_default; +int diff_use_color_default = -1; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; @@ -191,7 +191,7 @@ int git_diff_basic_config(const char *var, const char *value) } } - return git_default_config(var, value); + return git_color_default_config(var, value); } static char *quote_two(const char *one, const char *two) @@ -2055,7 +2055,7 @@ void diff_setup(struct diff_options *options) options->change = diff_change; options->add_remove = diff_addremove; - if (diff_use_color_default) + if (diff_use_color_default > 0) DIFF_OPT_SET(options, COLOR_DIFF); else DIFF_OPT_CLR(options, COLOR_DIFF); diff --git a/diff.h b/diff.h index 073d5cbf1b..8e73f07d7e 100644 --- a/diff.h +++ b/diff.h @@ -174,6 +174,7 @@ extern void diff_unmerge(struct diff_options *, extern int git_diff_basic_config(const char *var, const char *value); extern int git_diff_ui_config(const char *var, const char *value); +extern int diff_use_color_default; extern void diff_setup(struct diff_options *); extern int diff_opt_parse(struct diff_options *, const char **, int); extern int diff_setup_done(struct diff_options *); diff --git a/wt-status.c b/wt-status.c index 0b060934e2..32d780af1e 100644 --- a/wt-status.c +++ b/wt-status.c @@ -9,7 +9,7 @@ #include "diffcore.h" int wt_status_relative_paths = 1; -int wt_status_use_color = 0; +int wt_status_use_color = -1; static char wt_status_colors[][COLOR_MAXLEN] = { "", /* WT_STATUS_HEADER: normal */ "\033[32m", /* WT_STATUS_UPDATED: green */ @@ -40,7 +40,7 @@ static int parse_status_slot(const char *var, int offset) static const char* color(int slot) { - return wt_status_use_color ? wt_status_colors[slot] : ""; + return wt_status_use_color > 0 ? wt_status_colors[slot] : ""; } void wt_status_prepare(struct wt_status *s) @@ -401,5 +401,5 @@ int git_status_config(const char *k, const char *v) wt_status_relative_paths = git_config_bool(k, v); return 0; } - return git_default_config(k, v); + return git_color_default_config(k, v); } -- cgit v1.3 From 14a5c7c19351a7db56803c9086b133fe131f55f6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 20 Feb 2008 19:01:16 -0500 Subject: diff: fix java funcname pattern for solaris The Solaris regex library doesn't like having the '$' anchor inside capture parentheses. It rejects the match, causing t4018 to fail. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index c30c252272..699b21f4e3 100644 --- a/diff.c +++ b/diff.c @@ -1199,7 +1199,7 @@ static struct builtin_funcname_pattern { "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" - "[ ]*([^;]*$\\)" }, + "[ ]*([^;]*\\)$" }, { "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" }, }; -- cgit v1.3 From 8e0f70033b2bd1679a6e5971978fdc3ee09bdb72 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 31 Jan 2008 18:26:32 +0100 Subject: Avoid unnecessary "if-before-free" tests. This change removes all obvious useless if-before-free tests. E.g., it replaces code like this: if (some_expression) free (some_expression); with the now-equivalent: free (some_expression); It is equivalent not just because POSIX has required free(NULL) to work for a long time, but simply because it has worked for so long that no reasonable porting target fails the test. Here's some evidence from nearly 1.5 years ago: http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html FYI, the change below was prepared by running the following: git ls-files -z | xargs -0 \ perl -0x3b -pi -e \ 's/\bif\s*\(\s*(\S+?)(?:\s*!=\s*NULL)?\s*\)\s+(free\s*\(\s*\1\s*\))/$2/s' Note however, that it doesn't handle brace-enclosed blocks like "if (x) { free (x); }". But that's ok, since there were none like that in git sources. Beware: if you do use the above snippet, note that it can produce syntactically invalid C code. That happens when the affected "if"-statement has a matching "else". E.g., it would transform this if (x) free (x); else foo (); into this: free (x); else foo (); There were none of those here, either. If you're interested in automating detection of the useless tests, you might like the useless-if-before-free script in gnulib: [it *does* detect brace-enclosed free statements, and has a --name=S option to make it detect free-like functions with different names] http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=build-aux/useless-if-before-free Addendum: Remove one more (in imap-send.c), spotted by Jean-Luc Herren . Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- builtin-blame.c | 3 +-- builtin-branch.c | 9 +++------ builtin-fast-export.c | 3 +-- builtin-http-fetch.c | 3 +-- builtin-pack-objects.c | 3 +-- builtin-revert.c | 3 +-- connect.c | 3 +-- diff.c | 9 +++------ dir.c | 3 +-- http-push.c | 18 ++++++------------ imap-send.c | 5 ++--- interpolate.c | 3 +-- pretty.c | 3 +-- remote.c | 3 +-- setup.c | 3 +-- sha1_name.c | 6 ++---- xdiff-interface.c | 3 +-- 17 files changed, 28 insertions(+), 55 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index 59d7237f21..bfd562d7d2 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -123,8 +123,7 @@ static inline struct origin *origin_incref(struct origin *o) static void origin_decref(struct origin *o) { if (o && --o->refcnt <= 0) { - if (o->file.ptr) - free(o->file.ptr); + free(o->file.ptr); free(o); } } diff --git a/builtin-branch.c b/builtin-branch.c index 9edf2eb816..79177007e6 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -126,8 +126,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) continue; } - if (name) - free(name); + free(name); name = xstrdup(mkpath(fmt, argv[i])); if (!resolve_ref(name, sha1, 1, NULL)) { @@ -172,8 +171,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds) } } - if (name) - free(name); + free(name); return(ret); } @@ -490,8 +488,7 @@ static void create_branch(const char *name, const char *start_name, if (write_ref_sha1(lock, sha1, msg) < 0) die("Failed to write ref: %s.", strerror(errno)); - if (real_ref) - free(real_ref); + free(real_ref); } static void rename_branch(const char *oldname, const char *newname, int force) diff --git a/builtin-fast-export.c b/builtin-fast-export.c index f741df5220..49b54de054 100755 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -196,8 +196,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) ? strlen(reencoded) : message ? strlen(message) : 0), reencoded ? reencoded : message ? message : ""); - if (reencoded) - free(reencoded); + free(reencoded); for (i = 0, p = commit->parents; p; p = p->next) { int mark = get_object_mark(&p->item->object); diff --git a/builtin-http-fetch.c b/builtin-http-fetch.c index 7f450c61d9..299093ff91 100644 --- a/builtin-http-fetch.c +++ b/builtin-http-fetch.c @@ -80,8 +80,7 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix) walker_free(walker); - if (rewritten_url) - free(rewritten_url); + free(rewritten_url); return rc; } diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index d2bb12e574..7dff6536de 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1428,8 +1428,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, * accounting lock. Compiler will optimize the strangeness * away when THREADED_DELTA_SEARCH is not defined. */ - if (trg_entry->delta_data) - free(trg_entry->delta_data); + free(trg_entry->delta_data); cache_lock(); if (trg_entry->delta_data) { delta_cache_size -= trg_entry->delta_size; diff --git a/builtin-revert.c b/builtin-revert.c index e219859f9b..b6dee6a56c 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -397,8 +397,7 @@ static int revert_or_cherry_pick(int argc, const char **argv) else return execl_git_cmd("commit", "-n", "-F", defmsg, NULL); } - if (reencoded_message) - free(reencoded_message); + free(reencoded_message); return 0; } diff --git a/connect.c b/connect.c index 5ac3572784..d12b105970 100644 --- a/connect.c +++ b/connect.c @@ -68,8 +68,7 @@ struct ref **get_remote_heads(int in, struct ref **list, name_len = strlen(name); if (len != name_len + 41) { - if (server_capabilities) - free(server_capabilities); + free(server_capabilities); server_capabilities = xstrdup(name + name_len + 1); } diff --git a/diff.c b/diff.c index 699b21f4e3..f08e663b86 100644 --- a/diff.c +++ b/diff.c @@ -118,8 +118,7 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v pp->next = funcname_pattern_list; funcname_pattern_list = pp; } - if (pp->pattern) - free(pp->pattern); + free(pp->pattern); pp->pattern = xstrdup(value); return 0; } @@ -492,10 +491,8 @@ static void free_diff_words_data(struct emit_callback *ecbdata) ecbdata->diff_words->plus.text.size) diff_words_show(ecbdata->diff_words); - if (ecbdata->diff_words->minus.text.ptr) - free (ecbdata->diff_words->minus.text.ptr); - if (ecbdata->diff_words->plus.text.ptr) - free (ecbdata->diff_words->plus.text.ptr); + free (ecbdata->diff_words->minus.text.ptr); + free (ecbdata->diff_words->plus.text.ptr); free(ecbdata->diff_words); ecbdata->diff_words = NULL; } diff --git a/dir.c b/dir.c index 1f507daff2..edc458e020 100644 --- a/dir.c +++ b/dir.c @@ -704,8 +704,7 @@ static struct path_simplify *create_simplify(const char **pathspec) static void free_simplify(struct path_simplify *simplify) { - if (simplify) - free(simplify); + free(simplify); } int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec) diff --git a/http-push.c b/http-push.c index 0beb7406c3..406270f6f4 100644 --- a/http-push.c +++ b/http-push.c @@ -664,8 +664,7 @@ static void release_request(struct transfer_request *request) close(request->local_fileno); if (request->local_stream) fclose(request->local_stream); - if (request->url != NULL) - free(request->url); + free(request->url); free(request); } @@ -1283,10 +1282,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout) strbuf_release(&in_buffer); if (lock->token == NULL || lock->timeout <= 0) { - if (lock->token != NULL) - free(lock->token); - if (lock->owner != NULL) - free(lock->owner); + free(lock->token); + free(lock->owner); free(url); free(lock); lock = NULL; @@ -1344,8 +1341,7 @@ static int unlock_remote(struct remote_lock *lock) prev->next = prev->next->next; } - if (lock->owner != NULL) - free(lock->owner); + free(lock->owner); free(lock->url); free(lock->token); free(lock); @@ -2035,8 +2031,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1) } free(url); - if (*symref != NULL) - free(*symref); + free(*symref); *symref = NULL; hashclr(sha1); @@ -2435,8 +2430,7 @@ int main(int argc, char **argv) } cleanup: - if (rewritten_url) - free(rewritten_url); + free(rewritten_url); if (info_ref_lock) unlock_remote(info_ref_lock); free(remote); diff --git a/imap-send.c b/imap-send.c index 9025d9aa3e..10cce15a42 100644 --- a/imap-send.c +++ b/imap-send.c @@ -472,7 +472,7 @@ v_issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb, if (socket_write( &imap->buf.sock, buf, bufl ) != bufl) { free( cmd->cmd ); free( cmd ); - if (cb && cb->data) + if (cb) free( cb->data ); return NULL; } @@ -858,8 +858,7 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd ) normal: if (cmdp->cb.done) cmdp->cb.done( ctx, cmdp, resp ); - if (cmdp->cb.data) - free( cmdp->cb.data ); + free( cmdp->cb.data ); free( cmdp->cmd ); free( cmdp ); if (!tcmd || tcmd == cmdp) diff --git a/interpolate.c b/interpolate.c index 6ef53f2465..7f03bd99c5 100644 --- a/interpolate.c +++ b/interpolate.c @@ -11,8 +11,7 @@ void interp_set_entry(struct interp *table, int slot, const char *value) char *oldval = table[slot].value; char *newval = NULL; - if (oldval) - free(oldval); + free(oldval); if (value) newval = xstrdup(value); diff --git a/pretty.c b/pretty.c index 997f5837d5..4bf3be2dd9 100644 --- a/pretty.c +++ b/pretty.c @@ -30,8 +30,7 @@ enum cmit_fmt get_commit_format(const char *arg) if (*arg == '=') arg++; if (!prefixcmp(arg, "format:")) { - if (user_format) - free(user_format); + free(user_format); user_format = xstrdup(arg + 7); return CMIT_FMT_USERFORMAT; } diff --git a/remote.c b/remote.c index 6b56473f5b..ae1ef5708c 100644 --- a/remote.c +++ b/remote.c @@ -506,8 +506,7 @@ void free_refs(struct ref *ref) struct ref *next; while (ref) { next = ref->next; - if (ref->peer_ref) - free(ref->peer_ref); + free(ref->peer_ref); free(ref); ref = next; } diff --git a/setup.c b/setup.c index dc247a84c4..89c81e54e6 100644 --- a/setup.c +++ b/setup.c @@ -448,8 +448,7 @@ int check_repository_format_version(const char *var, const char *value) } else if (strcmp(var, "core.worktree") == 0) { if (!value) return config_error_nonbool(var); - if (git_work_tree_cfg) - free(git_work_tree_cfg); + free(git_work_tree_cfg); git_work_tree_cfg = xstrdup(value); inside_work_tree = -1; } diff --git a/sha1_name.c b/sha1_name.c index c2805e736b..9d088cc2ca 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -625,8 +625,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1) commit = pop_most_recent_commit(&list, ONELINE_SEEN); if (!parse_object(commit->object.sha1)) continue; - if (temp_commit_buffer) - free(temp_commit_buffer); + free(temp_commit_buffer); if (commit->buffer) p = commit->buffer; else { @@ -643,8 +642,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1) break; } } - if (temp_commit_buffer) - free(temp_commit_buffer); + free(temp_commit_buffer); free_commit_list(list); for (l = backup; l; l = l->next) clear_commit_marks(l->item, ONELINE_SEEN); diff --git a/xdiff-interface.c b/xdiff-interface.c index 4b8e5cca80..bba236428a 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -233,8 +233,7 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) expression = value; if (regcomp(®->re, expression, 0)) die("Invalid regexp to look for hunk header: %s", expression); - if (buffer) - free(buffer); + free(buffer); value = ep + 1; } } -- cgit v1.3 From 2b0b551d7662a4246ed55b6a7029ba3caa65cf98 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 24 Feb 2008 17:37:15 -0800 Subject: diff --dirstat: saner handling of binary and unmerged files We do not account binary nor unmerged files when --shortstat is asked for (or the summary stat at the end of --stat). The new option --dirstat should work the same way as it is about summarizing the changes of multiple files by adding them up. Signed-off-by: Junio C Hamano --- diff.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index dd374d436f..bcc323f19f 100644 --- a/diff.c +++ b/diff.c @@ -1016,7 +1016,10 @@ static long gather_dirstat(struct diffstat_dir *dir, unsigned long changed, cons this = gather_dirstat(dir, changed, f->name, newbaselen); sources++; } else { - this = f->added + f->deleted; + if (f->is_unmerged || f->is_binary) + this = 0; + else + this = f->added + f->deleted; dir->files++; dir->nr--; sources += 2; @@ -1053,6 +1056,8 @@ static void show_dirstat(struct diffstat_t *data, struct diff_options *options) /* Calculate total changes */ changed = 0; for (i = 0; i < data->nr; i++) { + if (data->files[i]->is_binary || data->files[i]->is_unmerged) + continue; changed += data->files[i]->added; changed += data->files[i]->deleted; } -- cgit v1.3 From 1468bd47833c6ec3c85620d6af1d910e9378f714 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Mon, 25 Feb 2008 14:24:48 -0500 Subject: Use a single implementation and API for copy_file() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally by Kristian Hᅵgsberg; I fixed the conversion of rerere, which had a different API. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- builtin-init-db.c | 21 --------------------- builtin-rerere.c | 19 +------------------ cache.h | 1 + copy.c | 21 +++++++++++++++++++++ diff.c | 8 ++++---- 5 files changed, 27 insertions(+), 43 deletions(-) (limited to 'diff.c') diff --git a/builtin-init-db.c b/builtin-init-db.c index e1393b8d1e..ff6e87777a 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -29,27 +29,6 @@ static void safe_create_dir(const char *dir, int share) die("Could not make %s writable by group\n", dir); } -static int copy_file(const char *dst, const char *src, int mode) -{ - int fdi, fdo, status; - - mode = (mode & 0111) ? 0777 : 0666; - if ((fdi = open(src, O_RDONLY)) < 0) - return fdi; - if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { - close(fdi); - return fdo; - } - status = copy_fd(fdi, fdo); - if (close(fdo) != 0) - return error("%s: write error: %s", dst, strerror(errno)); - - if (!status && adjust_shared_perm(dst)) - return -1; - - return status; -} - static void copy_templates_1(char *path, int baselen, char *template, int template_baselen, DIR *dir) diff --git a/builtin-rerere.c b/builtin-rerere.c index a9e3ebc137..b2971f3445 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -267,23 +267,6 @@ static int diff_two(const char *file1, const char *label1, return 0; } -static int copy_file(const char *src, const char *dest) -{ - FILE *in, *out; - char buffer[32768]; - int count; - - if (!(in = fopen(src, "r"))) - return error("Could not open %s", src); - if (!(out = fopen(dest, "w"))) - return error("Could not open %s", dest); - while ((count = fread(buffer, 1, sizeof(buffer), in))) - fwrite(buffer, 1, count, out); - fclose(in); - fclose(out); - return 0; -} - static int do_plain_rerere(struct path_list *rr, int fd) { struct path_list conflict = { NULL, 0, 0, 1 }; @@ -343,7 +326,7 @@ static int do_plain_rerere(struct path_list *rr, int fd) continue; fprintf(stderr, "Recorded resolution for '%s'.\n", path); - copy_file(path, rr_path(name, "postimage")); + copy_file(rr_path(name, "postimage"), path, 0666); tail_optimization: if (i < rr->nr - 1) memmove(rr->items + i, diff --git a/cache.h b/cache.h index 43ba6a3ba5..98cfed63ee 100644 --- a/cache.h +++ b/cache.h @@ -602,6 +602,7 @@ extern const char *git_log_output_encoding; /* IO helper functions */ extern void maybe_flush_or_die(FILE *, const char *); extern int copy_fd(int ifd, int ofd); +extern int copy_file(const char *dst, const char *src, int mode); extern int read_in_full(int fd, void *buf, size_t count); extern int write_in_full(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count); diff --git a/copy.c b/copy.c index c225d1b0ff..afc4fbf414 100644 --- a/copy.c +++ b/copy.c @@ -34,3 +34,24 @@ int copy_fd(int ifd, int ofd) close(ifd); return 0; } + +int copy_file(const char *dst, const char *src, int mode) +{ + int fdi, fdo, status; + + mode = (mode & 0111) ? 0777 : 0666; + if ((fdi = open(src, O_RDONLY)) < 0) + return fdi; + if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { + close(fdi); + return fdo; + } + status = copy_fd(fdi, fdo); + if (close(fdo) != 0) + return error("%s: write error: %s", dst, strerror(errno)); + + if (!status && adjust_shared_perm(dst)) + return -1; + + return status; +} diff --git a/diff.c b/diff.c index 39f6e21aa3..76ba5f4afc 100644 --- a/diff.c +++ b/diff.c @@ -272,8 +272,8 @@ static void print_line_count(int count) } } -static void copy_file(int prefix, const char *data, int size, - const char *set, const char *reset) +static void copy_file_with_prefix(int prefix, const char *data, int size, + const char *set, const char *reset) { int ch, nl_just_seen = 1; while (0 < size--) { @@ -331,9 +331,9 @@ static void emit_rewrite_diff(const char *name_a, print_line_count(lc_b); printf(" @@%s\n", reset); if (lc_a) - copy_file('-', one->data, one->size, old, reset); + copy_file_with_prefix('-', one->data, one->size, old, reset); if (lc_b) - copy_file('+', two->data, two->size, new, reset); + copy_file_with_prefix('+', two->data, two->size, new, reset); } static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) -- cgit v1.3 From 2efb3b061709bd204f11d54c177dae89e4af0f67 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 1 Mar 2008 23:43:32 -0800 Subject: Clean up find_unique_abbrev() callers Now find_unique_abbrev() never returns NULL, there is no need for callers to prepare for seeing NULL and fall back to giving the full 40-hexdigits. While we are at it, drop "..." in the "git reset" output that reports the location of the new HEAD, between the abbreviated commit object name and the one line commit summary. Because we are always showing the HEAD (which cannot be missing!), we never had a case where we show the full 40 hexdigits that is not followed by three dots, and these three dots were stealing 3 columns from the precious horizontal screen real estate out of 80 that can better be used for the one line commit summary. Signed-off-by: Junio C Hamano --- builtin-reset.c | 8 ++------ builtin-send-pack.c | 4 +--- diff.c | 2 -- 3 files changed, 3 insertions(+), 11 deletions(-) (limited to 'diff.c') diff --git a/builtin-reset.c b/builtin-reset.c index af0037ec6e..bb3e19240a 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -63,14 +63,10 @@ static int reset_index_file(const unsigned char *sha1, int is_hard_reset) static void print_new_head_line(struct commit *commit) { - const char *hex, *dots = "...", *body; + const char *hex, *body; hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV); - if (!hex) { - hex = sha1_to_hex(commit->object.sha1); - dots = ""; - } - printf("HEAD is now at %s%s", hex, dots); + printf("HEAD is now at %s", hex); body = strstr(commit->buffer, "\n\n"); if (body) { const char *eol; diff --git a/builtin-send-pack.c b/builtin-send-pack.c index b0cfae83fc..930e0fb3fd 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -264,9 +264,7 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str static const char *status_abbrev(unsigned char sha1[20]) { - const char *abbrev; - abbrev = find_unique_abbrev(sha1, DEFAULT_ABBREV); - return abbrev ? abbrev : sha1_to_hex(sha1); + return find_unique_abbrev(sha1, DEFAULT_ABBREV); } static void print_ok_ref_status(struct ref *ref) diff --git a/diff.c b/diff.c index ad16164232..b80f656fb9 100644 --- a/diff.c +++ b/diff.c @@ -2581,8 +2581,6 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len) return sha1_to_hex(sha1); abbrev = find_unique_abbrev(sha1, len); - if (!abbrev) - return sha1_to_hex(sha1); abblen = strlen(abbrev); if (abblen < 37) { static char hex[41]; -- cgit v1.3 From 2b459b483cb264d3e9a39cd7857da2ccab08179f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 2 Mar 2008 00:07:59 -0800 Subject: diff: make sure work tree side is shown as 0{40} when different Ping Yin noticed that "git diff-index --raw" shows 0{40} when work tree has submodule difference, but "git diff --raw" didn't correctly do so. There was a mistake in the diffcore_skip_stat_unmatch() that was meant to clean up the stat-only difference for running diff between the index and work tree and diff between the tree and the work tree, to cause it re-read from the submodule repository HEAD. When ce_stat_match() says work tree is different, we should always say 0{40} on the work tree side. This patch fixes the issue, and adds tests. Signed-off-by: Junio C Hamano --- diff.c | 7 ++----- t/t4027-diff-submodule.sh | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100755 t/t4027-diff-submodule.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index b80f656fb9..00e1590c6e 100644 --- a/diff.c +++ b/diff.c @@ -3187,11 +3187,8 @@ static void diffcore_apply_filter(const char *filter) static int diff_filespec_is_identical(struct diff_filespec *one, struct diff_filespec *two) { - if (S_ISGITLINK(one->mode)) { - diff_fill_sha1_info(one); - diff_fill_sha1_info(two); - return !hashcmp(one->sha1, two->sha1); - } + if (S_ISGITLINK(one->mode)) + return 0; if (diff_populate_filespec(one, 0)) return 0; if (diff_populate_filespec(two, 0)) diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh new file mode 100755 index 0000000000..3d2d0816a3 --- /dev/null +++ b/t/t4027-diff-submodule.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description='difference in submodules' + +. ./test-lib.sh +. ../diff-lib.sh + +_z40=0000000000000000000000000000000000000000 +test_expect_success setup ' + test_tick && + test_create_repo sub && + ( + cd sub && + echo hello >world && + git add world && + git commit -m submodule + ) && + + test_tick && + echo frotz >nitfol && + git add nitfol sub && + git commit -m superproject && + + ( + cd sub && + echo goodbye >world && + git add world && + git commit -m "submodule #2" + ) && + + set x $( + cd sub && + git rev-list HEAD + ) && + echo ":160000 160000 $3 $_z40 M sub" >expect +' + +test_expect_success 'git diff --raw HEAD' ' + git diff --raw --abbrev=40 HEAD >actual && + diff -u expect actual +' + +test_expect_success 'git diff-index --raw HEAD' ' + git diff-index --raw HEAD >actual.index && + diff -u expect actual.index +' + +test_expect_success 'git diff-files --raw' ' + git diff-files --raw >actual.files && + diff -u expect actual.files +' + +test_done -- cgit v1.3 From c0c77734bf313455364b3be7d3537d40e1138bcc Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 9 Mar 2008 22:43:39 -0400 Subject: Write diff output to a file in struct diff_options Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- diff.c | 306 +++++++++++++++++++++++++++++++++++------------------------------ diff.h | 3 + 2 files changed, 169 insertions(+), 140 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 00e1590c6e..8022e678d1 100644 --- a/diff.c +++ b/diff.c @@ -256,40 +256,41 @@ static int count_lines(const char *data, int size) return count; } -static void print_line_count(int count) +static void print_line_count(FILE *file, int count) { switch (count) { case 0: - printf("0,0"); + fprintf(file, "0,0"); break; case 1: - printf("1"); + fprintf(file, "1"); break; default: - printf("1,%d", count); + fprintf(file, "1,%d", count); break; } } -static void copy_file_with_prefix(int prefix, const char *data, int size, +static void copy_file_with_prefix(FILE *file, + int prefix, const char *data, int size, const char *set, const char *reset) { int ch, nl_just_seen = 1; while (0 < size--) { ch = *data++; if (nl_just_seen) { - fputs(set, stdout); - putchar(prefix); + fputs(set, file); + putc(prefix, file); } if (ch == '\n') { nl_just_seen = 1; - fputs(reset, stdout); + fputs(reset, file); } else nl_just_seen = 0; - putchar(ch); + putc(ch, file); } if (!nl_just_seen) - printf("%s\n\\ No newline at end of file\n", reset); + fprintf(file, "%s\n\\ No newline at end of file\n", reset); } static void emit_rewrite_diff(const char *name_a, @@ -322,17 +323,18 @@ static void emit_rewrite_diff(const char *name_a, diff_populate_filespec(two, 0); lc_a = count_lines(one->data, one->size); lc_b = count_lines(two->data, two->size); - printf("%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -", - metainfo, a_name.buf, name_a_tab, reset, - metainfo, b_name.buf, name_b_tab, reset, fraginfo); - print_line_count(lc_a); - printf(" +"); - print_line_count(lc_b); - printf(" @@%s\n", reset); + fprintf(o->file, + "%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -", + metainfo, a_name.buf, name_a_tab, reset, + metainfo, b_name.buf, name_b_tab, reset, fraginfo); + print_line_count(o->file, lc_a); + fprintf(o->file, " +"); + print_line_count(o->file, lc_b); + fprintf(o->file, " @@%s\n", reset); if (lc_a) - copy_file_with_prefix('-', one->data, one->size, old, reset); + copy_file_with_prefix(o->file, '-', one->data, one->size, old, reset); if (lc_b) - copy_file_with_prefix('+', two->data, two->size, new, reset); + copy_file_with_prefix(o->file, '+', two->data, two->size, new, reset); } static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) @@ -372,9 +374,10 @@ static void diff_words_append(char *line, unsigned long len, struct diff_words_data { struct xdiff_emit_state xm; struct diff_words_buffer minus, plus; + FILE *file; }; -static void print_word(struct diff_words_buffer *buffer, int len, int color, +static void print_word(FILE *file, struct diff_words_buffer *buffer, int len, int color, int suppress_newline) { const char *ptr; @@ -391,15 +394,15 @@ static void print_word(struct diff_words_buffer *buffer, int len, int color, len--; } - fputs(diff_get_color(1, color), stdout); - fwrite(ptr, len, 1, stdout); - fputs(diff_get_color(1, DIFF_RESET), stdout); + fputs(diff_get_color(1, color), file); + fwrite(ptr, len, 1, file); + fputs(diff_get_color(1, DIFF_RESET), file); if (eol) { if (suppress_newline) buffer->suppressed_newline = 1; else - putchar('\n'); + putc('\n', file); } } @@ -409,20 +412,23 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) if (diff_words->minus.suppressed_newline) { if (line[0] != '+') - putchar('\n'); + putc('\n', diff_words->file); diff_words->minus.suppressed_newline = 0; } len--; switch (line[0]) { case '-': - print_word(&diff_words->minus, len, DIFF_FILE_OLD, 1); + print_word(diff_words->file, + &diff_words->minus, len, DIFF_FILE_OLD, 1); break; case '+': - print_word(&diff_words->plus, len, DIFF_FILE_NEW, 0); + print_word(diff_words->file, + &diff_words->plus, len, DIFF_FILE_NEW, 0); break; case ' ': - print_word(&diff_words->plus, len, DIFF_PLAIN, 0); + print_word(diff_words->file, + &diff_words->plus, len, DIFF_PLAIN, 0); diff_words->minus.current += len; break; } @@ -466,7 +472,7 @@ static void diff_words_show(struct diff_words_data *diff_words) diff_words->minus.text.size = diff_words->plus.text.size = 0; if (diff_words->minus.suppressed_newline) { - putchar('\n'); + putc('\n', diff_words->file); diff_words->minus.suppressed_newline = 0; } } @@ -481,6 +487,7 @@ struct emit_callback { const char **label_path; struct diff_words_data *diff_words; int *found_changesp; + FILE *file; }; static void free_diff_words_data(struct emit_callback *ecbdata) @@ -505,11 +512,11 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) return ""; } -static void emit_line(const char *set, const char *reset, const char *line, int len) +static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len) { - fputs(set, stdout); - fwrite(line, len, 1, stdout); - fputs(reset, stdout); + fputs(set, file); + fwrite(line, len, 1, file); + fputs(reset, file); } static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) @@ -518,13 +525,13 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW); if (!*ws) - emit_line(set, reset, line, len); + emit_line(ecbdata->file, set, reset, line, len); else { /* Emit just the prefix, then the rest. */ - emit_line(set, reset, line, ecbdata->nparents); + emit_line(ecbdata->file, set, reset, line, ecbdata->nparents); (void)check_and_emit_line(line + ecbdata->nparents, len - ecbdata->nparents, ecbdata->ws_rule, - stdout, set, reset, ws); + ecbdata->file, set, reset, ws); } } @@ -563,10 +570,10 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : ""; name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : ""; - printf("%s--- %s%s%s\n", - meta, ecbdata->label_path[0], reset, name_a_tab); - printf("%s+++ %s%s%s\n", - meta, ecbdata->label_path[1], reset, name_b_tab); + fprintf(ecbdata->file, "%s--- %s%s%s\n", + meta, ecbdata->label_path[0], reset, name_a_tab); + fprintf(ecbdata->file, "%s+++ %s%s%s\n", + meta, ecbdata->label_path[1], reset, name_b_tab); ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; } @@ -578,15 +585,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) if (2 <= i && i < len && line[i] == ' ') { ecbdata->nparents = i - 1; len = sane_truncate_line(ecbdata, line, len); - emit_line(diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO), + emit_line(ecbdata->file, + diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO), reset, line, len); if (line[len-1] != '\n') - putchar('\n'); + putc('\n', ecbdata->file); return; } if (len < ecbdata->nparents) { - emit_line(reset, reset, line, len); + emit_line(ecbdata->file, reset, reset, line, len); return; } @@ -609,7 +617,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) diff_words_show(ecbdata->diff_words); line++; len--; - emit_line(plain, reset, line, len); + emit_line(ecbdata->file, plain, reset, line, len); return; } for (i = 0; i < ecbdata->nparents && len; i++) { @@ -620,7 +628,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) } if (color != DIFF_FILE_NEW) { - emit_line(diff_get_color(ecbdata->color_diff, color), + emit_line(ecbdata->file, + diff_get_color(ecbdata->color_diff, color), reset, line, len); return; } @@ -759,20 +768,21 @@ static int scale_linear(int it, int width, int max_change) return ((it - 1) * (width - 1) + max_change - 1) / (max_change - 1); } -static void show_name(const char *prefix, const char *name, int len, +static void show_name(FILE *file, + const char *prefix, const char *name, int len, const char *reset, const char *set) { - printf(" %s%s%-*s%s |", set, prefix, len, name, reset); + fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset); } -static void show_graph(char ch, int cnt, const char *set, const char *reset) +static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset) { if (cnt <= 0) return; - printf("%s", set); + fprintf(file, "%s", set); while (cnt--) - putchar(ch); - printf("%s", reset); + putc(ch, file); + fprintf(file, "%s", reset); } static void fill_print_name(struct diffstat_file *file) @@ -877,18 +887,18 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) } if (data->files[i]->is_binary) { - show_name(prefix, name, len, reset, set); - printf(" Bin "); - printf("%s%d%s", del_c, deleted, reset); - printf(" -> "); - printf("%s%d%s", add_c, added, reset); - printf(" bytes"); - printf("\n"); + show_name(options->file, prefix, name, len, reset, set); + fprintf(options->file, " Bin "); + fprintf(options->file, "%s%d%s", del_c, deleted, reset); + fprintf(options->file, " -> "); + fprintf(options->file, "%s%d%s", add_c, added, reset); + fprintf(options->file, " bytes"); + fprintf(options->file, "\n"); continue; } else if (data->files[i]->is_unmerged) { - show_name(prefix, name, len, reset, set); - printf(" Unmerged\n"); + show_name(options->file, prefix, name, len, reset, set); + fprintf(options->file, " Unmerged\n"); continue; } else if (!data->files[i]->is_renamed && @@ -911,17 +921,18 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) del = scale_linear(del, width, max_change); total = add + del; } - show_name(prefix, name, len, reset, set); - printf("%5d ", added + deleted); - show_graph('+', add, add_c, reset); - show_graph('-', del, del_c, reset); - putchar('\n'); - } - printf("%s %d files changed, %d insertions(+), %d deletions(-)%s\n", + show_name(options->file, prefix, name, len, reset, set); + fprintf(options->file, "%5d ", added + deleted); + show_graph(options->file, '+', add, add_c, reset); + show_graph(options->file, '-', del, del_c, reset); + fprintf(options->file, "\n"); + } + fprintf(options->file, + "%s %d files changed, %d insertions(+), %d deletions(-)%s\n", set, total_files, adds, dels, reset); } -static void show_shortstats(struct diffstat_t* data) +static void show_shortstats(struct diffstat_t* data, struct diff_options *options) { int i, adds = 0, dels = 0, total_files = data->nr; @@ -942,7 +953,7 @@ static void show_shortstats(struct diffstat_t* data) } } } - printf(" %d files changed, %d insertions(+), %d deletions(-)\n", + fprintf(options->file, " %d files changed, %d insertions(+), %d deletions(-)\n", total_files, adds, dels); } @@ -957,24 +968,25 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) struct diffstat_file *file = data->files[i]; if (file->is_binary) - printf("-\t-\t"); + fprintf(options->file, "-\t-\t"); else - printf("%d\t%d\t", file->added, file->deleted); + fprintf(options->file, + "%d\t%d\t", file->added, file->deleted); if (options->line_termination) { fill_print_name(file); if (!file->is_renamed) - write_name_quoted(file->name, stdout, + write_name_quoted(file->name, options->file, options->line_termination); else { - fputs(file->print_name, stdout); - putchar(options->line_termination); + fputs(file->print_name, options->file); + putc(options->line_termination, options->file); } } else { if (file->is_renamed) { - putchar('\0'); - write_name_quoted(file->from_name, stdout, '\0'); + putc('\0', options->file); + write_name_quoted(file->from_name, options->file, '\0'); } - write_name_quoted(file->name, stdout, '\0'); + write_name_quoted(file->name, options->file, '\0'); } } } @@ -984,7 +996,7 @@ struct diffstat_dir { int nr, percent, cumulative; }; -static long gather_dirstat(struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen) +static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen) { unsigned long this_dir = 0; unsigned int sources = 0; @@ -1002,7 +1014,7 @@ static long gather_dirstat(struct diffstat_dir *dir, unsigned long changed, cons slash = strchr(f->name + baselen, '/'); if (slash) { int newbaselen = slash + 1 - f->name; - this = gather_dirstat(dir, changed, f->name, newbaselen); + this = gather_dirstat(file, dir, changed, f->name, newbaselen); sources++; } else { if (f->is_unmerged || f->is_binary) @@ -1027,7 +1039,7 @@ static long gather_dirstat(struct diffstat_dir *dir, unsigned long changed, cons if (permille) { int percent = permille / 10; if (percent >= dir->percent) { - printf("%4d.%01d%% %.*s\n", percent, permille % 10, baselen, base); + fprintf(file, "%4d.%01d%% %.*s\n", percent, permille % 10, baselen, base); if (!dir->cumulative) return 0; } @@ -1060,7 +1072,7 @@ static void show_dirstat(struct diffstat_t *data, struct diff_options *options) dir.nr = data->nr; dir.percent = options->dirstat_percent; dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE; - gather_dirstat(&dir, changed, "", 0); + gather_dirstat(options->file, &dir, changed, "", 0); } static void free_diffstat_info(struct diffstat_t *diffstat) @@ -1083,6 +1095,7 @@ struct checkdiff_t { int lineno, color_diff; unsigned ws_rule; unsigned status; + FILE *file; }; static void checkdiff_consume(void *priv, char *line, unsigned long len) @@ -1100,11 +1113,11 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (!data->status) return; err = whitespace_error_string(data->status); - printf("%s:%d: %s.\n", data->filename, data->lineno, err); + fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err); free(err); - emit_line(set, reset, line, 1); + emit_line(data->file, set, reset, line, 1); (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, - stdout, set, reset, ws); + data->file, set, reset, ws); } else if (line[0] == ' ') data->lineno++; else if (line[0] == '@') { @@ -1140,7 +1153,7 @@ static unsigned char *deflate_it(char *data, return deflated; } -static void emit_binary_diff_body(mmfile_t *one, mmfile_t *two) +static void emit_binary_diff_body(FILE *file, mmfile_t *one, mmfile_t *two) { void *cp; void *delta; @@ -1169,13 +1182,13 @@ static void emit_binary_diff_body(mmfile_t *one, mmfile_t *two) } if (delta && delta_size < deflate_size) { - printf("delta %lu\n", orig_size); + fprintf(file, "delta %lu\n", orig_size); free(deflated); data = delta; data_size = delta_size; } else { - printf("literal %lu\n", two->size); + fprintf(file, "literal %lu\n", two->size); free(delta); data = deflated; data_size = deflate_size; @@ -1193,17 +1206,18 @@ static void emit_binary_diff_body(mmfile_t *one, mmfile_t *two) line[0] = bytes - 26 + 'a' - 1; encode_85(line + 1, cp, bytes); cp = (char *) cp + bytes; - puts(line); + fputs(line, file); + fputc('\n', file); } - printf("\n"); + fprintf(file, "\n"); free(data); } -static void emit_binary_diff(mmfile_t *one, mmfile_t *two) +static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two) { - printf("GIT binary patch\n"); - emit_binary_diff_body(one, two); - emit_binary_diff_body(two, one); + fprintf(file, "GIT binary patch\n"); + emit_binary_diff_body(file, one, two); + emit_binary_diff_body(file, two, one); } static void setup_diff_attr_check(struct git_attr_check *check) @@ -1334,25 +1348,25 @@ static void builtin_diff(const char *name_a, b_two = quote_two(o->b_prefix, name_b + (*name_b == '/')); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; - printf("%sdiff --git %s %s%s\n", set, a_one, b_two, reset); + fprintf(o->file, "%sdiff --git %s %s%s\n", set, a_one, b_two, reset); if (lbl[0][0] == '/') { /* /dev/null */ - printf("%snew file mode %06o%s\n", set, two->mode, reset); + fprintf(o->file, "%snew file mode %06o%s\n", set, two->mode, reset); if (xfrm_msg && xfrm_msg[0]) - printf("%s%s%s\n", set, xfrm_msg, reset); + fprintf(o->file, "%s%s%s\n", set, xfrm_msg, reset); } else if (lbl[1][0] == '/') { - printf("%sdeleted file mode %06o%s\n", set, one->mode, reset); + fprintf(o->file, "%sdeleted file mode %06o%s\n", set, one->mode, reset); if (xfrm_msg && xfrm_msg[0]) - printf("%s%s%s\n", set, xfrm_msg, reset); + fprintf(o->file, "%s%s%s\n", set, xfrm_msg, reset); } else { if (one->mode != two->mode) { - printf("%sold mode %06o%s\n", set, one->mode, reset); - printf("%snew mode %06o%s\n", set, two->mode, reset); + fprintf(o->file, "%sold mode %06o%s\n", set, one->mode, reset); + fprintf(o->file, "%snew mode %06o%s\n", set, two->mode, reset); } if (xfrm_msg && xfrm_msg[0]) - printf("%s%s%s\n", set, xfrm_msg, reset); + fprintf(o->file, "%s%s%s\n", set, xfrm_msg, reset); /* * we do not run diff between different kind * of objects. @@ -1376,10 +1390,10 @@ static void builtin_diff(const char *name_a, !memcmp(mf1.ptr, mf2.ptr, mf1.size)) goto free_ab_and_return; if (DIFF_OPT_TST(o, BINARY)) - emit_binary_diff(&mf1, &mf2); + emit_binary_diff(o->file, &mf1, &mf2); else - printf("Binary files %s and %s differ\n", - lbl[0], lbl[1]); + fprintf(o->file, "Binary files %s and %s differ\n", + lbl[0], lbl[1]); o->found_changes = 1; } else { @@ -1401,6 +1415,7 @@ static void builtin_diff(const char *name_a, ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); ecbdata.found_changesp = &o->found_changes; ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a); + ecbdata.file = o->file; xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; @@ -1415,9 +1430,11 @@ static void builtin_diff(const char *name_a, ecb.outf = xdiff_outf; ecb.priv = &ecbdata; ecbdata.xm.consume = fn_out_consume; - if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) + if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) { ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); + ecbdata.diff_words->file = o->file; + } xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); @@ -1496,6 +1513,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, data.lineno = 0; data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); data.ws_rule = whitespace_rule(attr_path); + data.file = o->file; if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); @@ -1966,7 +1984,7 @@ static void run_diff_cmd(const char *pgm, builtin_diff(name, other ? other : name, one, two, xfrm_msg, o, complete_rewrite); else - printf("* Unmerged path %s\n", name); + fprintf(o->file, "* Unmerged path %s\n", name); } static void diff_fill_sha1_info(struct diff_filespec *one) @@ -2157,6 +2175,9 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) void diff_setup(struct diff_options *options) { memset(options, 0, sizeof(*options)); + + options->file = stdout; + options->line_termination = '\n'; options->break_opt = -1; options->rename_limit = -1; @@ -2470,7 +2491,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->b_prefix = arg + 13; else if (!strcmp(arg, "--no-prefix")) options->a_prefix = options->b_prefix = ""; - else + else if (!prefixcmp(arg, "--output=")) { + options->file = fopen(arg + strlen("--output="), "w"); + options->close_file = 1; + } else return 0; return 1; } @@ -2599,15 +2623,15 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) int inter_name_termination = line_termination ? '\t' : '\0'; if (!(opt->output_format & DIFF_FORMAT_NAME_STATUS)) { - printf(":%06o %06o %s ", p->one->mode, p->two->mode, - diff_unique_abbrev(p->one->sha1, opt->abbrev)); - printf("%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev)); + fprintf(opt->file, ":%06o %06o %s ", p->one->mode, p->two->mode, + diff_unique_abbrev(p->one->sha1, opt->abbrev)); + fprintf(opt->file, "%s ", diff_unique_abbrev(p->two->sha1, opt->abbrev)); } if (p->score) { - printf("%c%03d%c", p->status, similarity_index(p), - inter_name_termination); + fprintf(opt->file, "%c%03d%c", p->status, similarity_index(p), + inter_name_termination); } else { - printf("%c%c", p->status, inter_name_termination); + fprintf(opt->file, "%c%c", p->status, inter_name_termination); } if (p->status == DIFF_STATUS_COPIED || @@ -2616,14 +2640,14 @@ static void diff_flush_raw(struct diff_filepair *p, struct diff_options *opt) name_a = p->one->path; name_b = p->two->path; strip_prefix(opt->prefix_length, &name_a, &name_b); - write_name_quoted(name_a, stdout, inter_name_termination); - write_name_quoted(name_b, stdout, line_termination); + write_name_quoted(name_a, opt->file, inter_name_termination); + write_name_quoted(name_b, opt->file, line_termination); } else { const char *name_a, *name_b; name_a = p->one->mode ? p->one->path : p->two->path; name_b = NULL; strip_prefix(opt->prefix_length, &name_a, &name_b); - write_name_quoted(name_a, stdout, line_termination); + write_name_quoted(name_a, opt->file, line_termination); } } @@ -2825,62 +2849,62 @@ static void flush_one_pair(struct diff_filepair *p, struct diff_options *opt) name_a = p->two->path; name_b = NULL; strip_prefix(opt->prefix_length, &name_a, &name_b); - write_name_quoted(name_a, stdout, opt->line_termination); + write_name_quoted(name_a, opt->file, opt->line_termination); } } -static void show_file_mode_name(const char *newdelete, struct diff_filespec *fs) +static void show_file_mode_name(FILE *file, const char *newdelete, struct diff_filespec *fs) { if (fs->mode) - printf(" %s mode %06o ", newdelete, fs->mode); + fprintf(file, " %s mode %06o ", newdelete, fs->mode); else - printf(" %s ", newdelete); - write_name_quoted(fs->path, stdout, '\n'); + fprintf(file, " %s ", newdelete); + write_name_quoted(fs->path, file, '\n'); } -static void show_mode_change(struct diff_filepair *p, int show_name) +static void show_mode_change(FILE *file, struct diff_filepair *p, int show_name) { if (p->one->mode && p->two->mode && p->one->mode != p->two->mode) { - printf(" mode change %06o => %06o%c", p->one->mode, p->two->mode, + fprintf(file, " mode change %06o => %06o%c", p->one->mode, p->two->mode, show_name ? ' ' : '\n'); if (show_name) { - write_name_quoted(p->two->path, stdout, '\n'); + write_name_quoted(p->two->path, file, '\n'); } } } -static void show_rename_copy(const char *renamecopy, struct diff_filepair *p) +static void show_rename_copy(FILE *file, const char *renamecopy, struct diff_filepair *p) { char *names = pprint_rename(p->one->path, p->two->path); - printf(" %s %s (%d%%)\n", renamecopy, names, similarity_index(p)); + fprintf(file, " %s %s (%d%%)\n", renamecopy, names, similarity_index(p)); free(names); - show_mode_change(p, 0); + show_mode_change(file, p, 0); } -static void diff_summary(struct diff_filepair *p) +static void diff_summary(FILE *file, struct diff_filepair *p) { switch(p->status) { case DIFF_STATUS_DELETED: - show_file_mode_name("delete", p->one); + show_file_mode_name(file, "delete", p->one); break; case DIFF_STATUS_ADDED: - show_file_mode_name("create", p->two); + show_file_mode_name(file, "create", p->two); break; case DIFF_STATUS_COPIED: - show_rename_copy("copy", p); + show_rename_copy(file, "copy", p); break; case DIFF_STATUS_RENAMED: - show_rename_copy("rename", p); + show_rename_copy(file, "rename", p); break; default: if (p->score) { - fputs(" rewrite ", stdout); - write_name_quoted(p->two->path, stdout, ' '); - printf("(%d%%)\n", similarity_index(p)); + fputs(" rewrite ", file); + write_name_quoted(p->two->path, file, ' '); + fprintf(file, "(%d%%)\n", similarity_index(p)); } - show_mode_change(p, !p->score); + show_mode_change(file, p, !p->score); break; } } @@ -3088,14 +3112,14 @@ void diff_flush(struct diff_options *options) if (output_format & DIFF_FORMAT_DIFFSTAT) show_stats(&diffstat, options); if (output_format & DIFF_FORMAT_SHORTSTAT) - show_shortstats(&diffstat); + show_shortstats(&diffstat, options); free_diffstat_info(&diffstat); separator++; } if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) { for (i = 0; i < q->nr; i++) - diff_summary(q->queue[i]); + diff_summary(options->file, q->queue[i]); separator++; } @@ -3103,9 +3127,9 @@ void diff_flush(struct diff_options *options) if (separator) { if (options->stat_sep) { /* attach patch instead of inline */ - fputs(options->stat_sep, stdout); + fputs(options->stat_sep, options->file); } else { - putchar(options->line_termination); + putc(options->line_termination, options->file); } } @@ -3125,6 +3149,8 @@ free_queue: free(q->queue); q->queue = NULL; q->nr = q->alloc = 0; + if (options->close_file) + fclose(options->file); } static void diffcore_apply_filter(const char *filter) diff --git a/diff.h b/diff.h index 9a652e7f38..f2c77391a9 100644 --- a/diff.h +++ b/diff.h @@ -98,6 +98,9 @@ struct diff_options { /* this is set by diffcore for DIFF_FORMAT_PATCH */ int found_changes; + FILE *file; + int close_file; + int nr_paths; const char **paths; int *pathlens; -- cgit v1.3 From c04a7155a03e5ef089864912769baf9001f64aa9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 12 Feb 2008 17:06:58 -0800 Subject: diff: make --dirstat binary-file safe Instead of counting added and removed lines (and mixing the byte size reported for binary files in the result), summarize the extent of damage the same way as we count similarity for rename detection. Signed-off-by: Junio C Hamano --- diff.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 23 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 8022e678d1..3632b552b2 100644 --- a/diff.c +++ b/diff.c @@ -991,18 +991,23 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options) } } -struct diffstat_dir { - struct diffstat_file **files; - int nr, percent, cumulative; +struct dirstat_file { + const char *name; + unsigned long changed; }; -static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen) +struct dirstat_dir { + struct dirstat_file *files; + int alloc, nr, percent, cumulative; +}; + +static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long changed, const char *base, int baselen) { unsigned long this_dir = 0; unsigned int sources = 0; while (dir->nr) { - struct diffstat_file *f = *dir->files; + struct dirstat_file *f = dir->files; int namelen = strlen(f->name); unsigned long this; char *slash; @@ -1017,10 +1022,7 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c this = gather_dirstat(file, dir, changed, f->name, newbaselen); sources++; } else { - if (f->is_unmerged || f->is_binary) - this = 0; - else - this = f->added + f->deleted; + this = f->changed; dir->files++; dir->nr--; sources += 2; @@ -1048,19 +1050,58 @@ static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long c return this_dir; } -static void show_dirstat(struct diffstat_t *data, struct diff_options *options) +static void show_dirstat(struct diff_options *options) { int i; unsigned long changed; - struct diffstat_dir dir; + struct dirstat_dir dir; + struct diff_queue_struct *q = &diff_queued_diff; + + dir.files = NULL; + dir.alloc = 0; + dir.nr = 0; + dir.percent = options->dirstat_percent; + dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE; - /* Calculate total changes */ changed = 0; - for (i = 0; i < data->nr; i++) { - if (data->files[i]->is_binary || data->files[i]->is_unmerged) + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + const char *name; + unsigned long copied, added, damage; + + name = p->one->path ? p->one->path : p->two->path; + + if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) { + diff_populate_filespec(p->one, 0); + diff_populate_filespec(p->two, 0); + diffcore_count_changes(p->one, p->two, NULL, NULL, 0, + &copied, &added); + diff_free_filespec_data(p->one); + diff_free_filespec_data(p->two); + } else if (DIFF_FILE_VALID(p->one)) { + diff_populate_filespec(p->one, 1); + copied = added = 0; + diff_free_filespec_data(p->one); + } else if (DIFF_FILE_VALID(p->two)) { + diff_populate_filespec(p->two, 1); + copied = 0; + added = p->two->size; + diff_free_filespec_data(p->two); + } else continue; - changed += data->files[i]->added; - changed += data->files[i]->deleted; + + /* + * Original minus copied is the removed material, + * added is the new material. They are both damages + * made to the preimage. + */ + damage = (p->one->size - copied) + added; + + ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc); + dir.files[dir.nr].name = name; + dir.files[dir.nr].changed = damage; + changed += damage; + dir.nr++; } /* This can happen even with many files, if everything was renames */ @@ -1068,10 +1109,6 @@ static void show_dirstat(struct diffstat_t *data, struct diff_options *options) return; /* Show all directories with more than x% of the changes */ - dir.files = data->files; - dir.nr = data->nr; - dir.percent = options->dirstat_percent; - dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE; gather_dirstat(options->file, &dir, changed, "", 0); } @@ -3095,7 +3132,7 @@ void diff_flush(struct diff_options *options) separator++; } - if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIRSTAT)) { + if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) { struct diffstat_t diffstat; memset(&diffstat, 0, sizeof(struct diffstat_t)); @@ -3105,8 +3142,6 @@ void diff_flush(struct diff_options *options) if (check_pair_status(p)) diff_flush_stat(p, options, &diffstat); } - if (output_format & DIFF_FORMAT_DIRSTAT) - show_dirstat(&diffstat, options); if (output_format & DIFF_FORMAT_NUMSTAT) show_numstat(&diffstat, options); if (output_format & DIFF_FORMAT_DIFFSTAT) @@ -3116,6 +3151,8 @@ void diff_flush(struct diff_options *options) free_diffstat_info(&diffstat); separator++; } + if (output_format & DIFF_FORMAT_DIRSTAT) + show_dirstat(options); if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) { for (i = 0; i < q->nr; i++) -- cgit v1.3 From 028656552bc758b192027c25a1143f1c6ca66d64 Mon Sep 17 00:00:00 2001 From: Adam Simpkins Date: Tue, 29 Apr 2008 01:32:59 -0700 Subject: Remove dead code: show_log() sep argument and diff_options.msg_sep These variables were made unnecessary by commit 3969cf7db1a13a78f3b7a36d8c1084bbe0a53459. Signed-off-by: Adam Simpkins Signed-off-by: Junio C Hamano --- builtin-log.c | 1 - combine-diff.c | 6 +++--- diff.c | 1 - diff.h | 1 - log-tree.c | 27 +++++++++------------------ log-tree.h | 2 +- 6 files changed, 13 insertions(+), 25 deletions(-) (limited to 'diff.c') diff --git a/builtin-log.c b/builtin-log.c index 1670d0b334..256bbac93a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -770,7 +770,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diff = 1; rev.combine_merges = 0; rev.ignore_merges = 1; - rev.diffopt.msg_sep = ""; DIFF_OPT_SET(&rev.diffopt, RECURSIVE); rev.subject_prefix = fmt_patch_subject_prefix; diff --git a/combine-diff.c b/combine-diff.c index f1e7a4d5d9..41aaf83dd3 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -798,7 +798,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int deleted = 0; if (rev->loginfo && !rev->no_commit_id) - show_log(rev, opt->msg_sep); + show_log(rev); dump_quoted_path(dense ? "diff --cc " : "diff --combined ", "", elem->path, c_meta, c_reset); printf("%sindex ", c_meta); @@ -881,7 +881,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re inter_name_termination = 0; if (rev->loginfo && !rev->no_commit_id) - show_log(rev, opt->msg_sep); + show_log(rev); if (opt->output_format & DIFF_FORMAT_RAW) { offset = strlen(COLONS) - num_parent; @@ -962,7 +962,7 @@ void diff_tree_combined(const unsigned char *sha1, paths = intersect_paths(paths, i, num_parent); if (show_log_first && i == 0) { - show_log(rev, opt->msg_sep); + show_log(rev); if (rev->verbose_header && opt->output_format) putchar(opt->line_termination); } diff --git a/diff.c b/diff.c index 3632b552b2..e35384b444 100644 --- a/diff.c +++ b/diff.c @@ -2220,7 +2220,6 @@ void diff_setup(struct diff_options *options) options->rename_limit = -1; options->dirstat_percent = 3; options->context = 3; - options->msg_sep = ""; options->change = diff_change; options->add_remove = diff_addremove; diff --git a/diff.h b/diff.h index f2c77391a9..1bd94a4807 100644 --- a/diff.h +++ b/diff.h @@ -88,7 +88,6 @@ struct diff_options { int abbrev; const char *prefix; int prefix_length; - const char *msg_sep; const char *stat_sep; long xdl_opts; diff --git a/log-tree.c b/log-tree.c index 8f5436b747..4c7d7ef0c6 100644 --- a/log-tree.c +++ b/log-tree.c @@ -208,14 +208,13 @@ void log_write_email_headers(struct rev_info *opt, const char *name, *extra_headers_p = extra_headers; } -void show_log(struct rev_info *opt, const char *sep) +void show_log(struct rev_info *opt) { struct strbuf msgbuf; struct log_info *log = opt->loginfo; struct commit *commit = log->commit, *parent = log->parent; int abbrev = opt->diffopt.abbrev; int abbrev_commit = opt->abbrev_commit ? opt->abbrev : 40; - const char *extra; const char *subject = NULL, *extra_headers = opt->extra_headers; int need_8bit_cte = 0; @@ -240,17 +239,10 @@ void show_log(struct rev_info *opt, const char *sep) } /* - * The "oneline" format has several special cases: - * - The pretty-printed commit lacks a newline at the end - * of the buffer, but we do want to make sure that we - * have a newline there. If the separator isn't already - * a newline, add an extra one. - * - unlike other log messages, the one-line format does - * not have an empty line between entries. + * If use_terminator is set, add a newline at the end of the entry. + * Otherwise, add a diffopt.line_termination character before all + * entries but the first. (IOW, as a separator between entries) */ - extra = ""; - if (*sep != '\n' && opt->use_terminator) - extra = "\n"; if (opt->shown_one && !opt->use_terminator) putchar(opt->diffopt.line_termination); opt->shown_one = 1; @@ -292,10 +284,8 @@ void show_log(struct rev_info *opt, const char *sep) show_reflog_message(opt->reflog_info, opt->commit_format == CMIT_FMT_ONELINE, opt->date_mode); - if (opt->commit_format == CMIT_FMT_ONELINE) { - printf("%s", sep); + if (opt->commit_format == CMIT_FMT_ONELINE) return; - } } } @@ -319,7 +309,8 @@ void show_log(struct rev_info *opt, const char *sep) if (msgbuf.len) { fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); - printf("%s%s", extra, sep); + if (opt->use_terminator) + putchar('\n'); } strbuf_release(&msgbuf); } @@ -342,7 +333,7 @@ int log_tree_diff_flush(struct rev_info *opt) * an extra newline between the end of log and the * output for readability. */ - show_log(opt, opt->diffopt.msg_sep); + show_log(opt); if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) && opt->verbose_header && opt->commit_format != CMIT_FMT_ONELINE) { @@ -430,7 +421,7 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit) shown = log_tree_diff(opt, commit, &log); if (!shown && opt->loginfo && opt->always_show_header) { log.parent = NULL; - show_log(opt, ""); + show_log(opt); shown = 1; } opt->loginfo = NULL; diff --git a/log-tree.h b/log-tree.h index 8946ff377c..59ba4c48b7 100644 --- a/log-tree.h +++ b/log-tree.h @@ -11,7 +11,7 @@ void init_log_tree_opt(struct rev_info *); int log_tree_diff_flush(struct rev_info *); int log_tree_commit(struct rev_info *, struct commit *); int log_tree_opt_parse(struct rev_info *, const char **, int); -void show_log(struct rev_info *opt, const char *sep); +void show_log(struct rev_info *opt); void show_decorations(struct commit *commit); void log_write_email_headers(struct rev_info *opt, const char *name, const char **subject_p, -- cgit v1.3 From 50705915eae89eae490dff30fa370ed02e4d6e72 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 30 Apr 2008 13:24:43 -0400 Subject: bump rename limit defaults The current rename limit default of 100 was arbitrarily chosen. Testing[1] has shown that on modern hardware, a limit of 200 adds about a second of computation time, and a limit of 500 adds about 5 seconds of computation time. This patch bumps the default limit to 200 for viewing diffs, and to 500 for performing a merge. The limit for generating git-status templates is set independently; we bump it up to 200 here, as well, to match the diff limit. [1]: See <20080211113516.GB6344@coredump.intra.peff.net> Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-merge-recursive.c | 2 +- diff.c | 2 +- wt-status.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index 1293e3d342..3902e91069 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -364,7 +364,7 @@ static struct path_list *get_renames(struct tree *tree, opts.detect_rename = DIFF_DETECT_RENAME; opts.rename_limit = merge_rename_limit >= 0 ? merge_rename_limit : diff_rename_limit >= 0 ? diff_rename_limit : - 100; + 500; opts.output_format = DIFF_FORMAT_NO_OUTPUT; if (diff_setup_done(&opts) < 0) die("diff setup failed"); diff --git a/diff.c b/diff.c index 3632b552b2..f7355191dd 100644 --- a/diff.c +++ b/diff.c @@ -19,7 +19,7 @@ #endif static int diff_detect_rename_default; -static int diff_rename_limit_default = 100; +static int diff_rename_limit_default = 200; int diff_use_color_default = -1; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; diff --git a/wt-status.c b/wt-status.c index 532b4ea2c1..a44c543375 100644 --- a/wt-status.c +++ b/wt-status.c @@ -206,7 +206,7 @@ static void wt_status_print_updated(struct wt_status *s) rev.diffopt.format_callback = wt_status_print_updated_cb; rev.diffopt.format_callback_data = s; rev.diffopt.detect_rename = 1; - rev.diffopt.rename_limit = 100; + rev.diffopt.rename_limit = 200; rev.diffopt.break_opt = 0; run_diff_index(&rev, 1); } -- cgit v1.3 From ef90d6d4208a5130185b04f06e5f90a5f9959fe3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 14 May 2008 18:46:53 +0100 Subject: Provide git_config with a callback-data parameter git_config() only had a function parameter, but no callback data parameter. This assumes that all callback functions only modify global variables. With this patch, every callback gets a void * parameter, and it is hoped that this will help the libification effort. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- alias.c | 5 +++-- archive-tar.c | 6 +++--- builtin-add.c | 2 +- builtin-apply.c | 6 +++--- builtin-blame.c | 6 +++--- builtin-branch.c | 6 +++--- builtin-cat-file.c | 2 +- builtin-checkout-index.c | 2 +- builtin-checkout.c | 2 +- builtin-clean.c | 6 +++--- builtin-commit-tree.c | 2 +- builtin-commit.c | 8 ++++---- builtin-config.c | 26 ++++++++++++++------------ builtin-diff-files.c | 2 +- builtin-diff-index.c | 2 +- builtin-diff-tree.c | 2 +- builtin-diff.c | 2 +- builtin-fast-export.c | 2 +- builtin-fetch-pack.c | 6 +++--- builtin-fmt-merge-msg.c | 4 ++-- builtin-gc.c | 6 +++--- builtin-http-fetch.c | 2 +- builtin-init-db.c | 4 ++-- builtin-log.c | 18 +++++++++--------- builtin-ls-files.c | 2 +- builtin-ls-tree.c | 2 +- builtin-mailinfo.c | 2 +- builtin-merge-base.c | 2 +- builtin-merge-recursive.c | 6 +++--- builtin-mv.c | 2 +- builtin-name-rev.c | 2 +- builtin-pack-objects.c | 6 +++--- builtin-read-tree.c | 4 +--- builtin-reflog.c | 6 +++--- builtin-remote.c | 8 ++++---- builtin-rerere.c | 6 +++--- builtin-reset.c | 2 +- builtin-rev-list.c | 2 +- builtin-rev-parse.c | 2 +- builtin-revert.c | 2 +- builtin-rm.c | 2 +- builtin-show-branch.c | 6 +++--- builtin-symbolic-ref.c | 2 +- builtin-tag.c | 6 +++--- builtin-unpack-objects.c | 2 +- builtin-update-index.c | 2 +- builtin-update-ref.c | 2 +- builtin-verify-pack.c | 2 +- builtin-verify-tag.c | 2 +- builtin-write-tree.c | 2 +- cache.h | 10 +++++----- color.c | 4 ++-- color.h | 2 +- config.c | 27 ++++++++++++++------------- connect.c | 7 ++++--- convert.c | 4 ++-- daemon.c | 4 ++-- diff.c | 8 ++++---- diff.h | 4 ++-- fast-import.c | 6 +++--- hash-object.c | 2 +- help.c | 6 +++--- http.c | 6 +++--- imap-send.c | 4 ++-- index-pack.c | 6 +++--- ll-merge.c | 4 ++-- pager.c | 2 +- receive-pack.c | 6 +++--- remote.c | 4 ++-- setup.c | 4 ++-- unpack-file.c | 2 +- var.c | 8 ++++---- wt-status.c | 4 ++-- wt-status.h | 2 +- 74 files changed, 176 insertions(+), 173 deletions(-) (limited to 'diff.c') diff --git a/alias.c b/alias.c index 116cac87c3..995f3e6a0a 100644 --- a/alias.c +++ b/alias.c @@ -2,7 +2,8 @@ static const char *alias_key; static char *alias_val; -static int alias_lookup_cb(const char *k, const char *v) + +static int alias_lookup_cb(const char *k, const char *v, void *cb) { if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { if (!v) @@ -17,6 +18,6 @@ char *alias_lookup(const char *alias) { alias_key = alias; alias_val = NULL; - git_config(alias_lookup_cb); + git_config(alias_lookup_cb, NULL); return alias_val; } diff --git a/archive-tar.c b/archive-tar.c index 4add80284e..d7598f907d 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -220,7 +220,7 @@ static void write_global_extended_header(const unsigned char *sha1) strbuf_release(&ext_header); } -static int git_tar_config(const char *var, const char *value) +static int git_tar_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "tar.umask")) { if (value && !strcmp(value, "user")) { @@ -231,7 +231,7 @@ static int git_tar_config(const char *var, const char *value) } return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int write_tar_entry(const unsigned char *sha1, @@ -268,7 +268,7 @@ int write_tar_archive(struct archiver_args *args) { int plen = args->base ? strlen(args->base) : 0; - git_config(git_tar_config); + git_config(git_tar_config, NULL); archive_time = args->time; verbose = args->verbose; diff --git a/builtin-add.c b/builtin-add.c index 4a91e3eb11..15def7dada 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -203,7 +203,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) if (add_interactive) exit(interactive_add(argc, argv, prefix)); - git_config(git_default_config); + git_config(git_default_config, NULL); newfd = hold_locked_index(&lock_file, 1); diff --git a/builtin-apply.c b/builtin-apply.c index 1103625a4a..bbdf08a10a 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2979,11 +2979,11 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof) return 0; } -static int git_apply_config(const char *var, const char *value) +static int git_apply_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "apply.whitespace")) return git_config_string(&apply_default_whitespace, var, value); - return git_default_config(var, value); + return git_default_config(var, value, cb); } @@ -2999,7 +2999,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix) prefix = setup_git_directory_gently(&is_not_gitdir); prefix_length = prefix ? strlen(prefix) : 0; - git_config(git_apply_config); + git_config(git_apply_config, NULL); if (apply_default_whitespace) parse_whitespace_option(apply_default_whitespace); diff --git a/builtin-blame.c b/builtin-blame.c index bfd562d7d2..b451f6c64d 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -1993,7 +1993,7 @@ static void prepare_blame_range(struct scoreboard *sb, usage(blame_usage); } -static int git_blame_config(const char *var, const char *value) +static int git_blame_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "blame.showroot")) { show_root = git_config_bool(var, value); @@ -2003,7 +2003,7 @@ static int git_blame_config(const char *var, const char *value) blank_boundary = git_config_bool(var, value); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static struct commit *fake_working_tree_commit(const char *path, const char *contents_from) @@ -2141,7 +2141,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) cmd_is_annotate = !strcmp(argv[0], "annotate"); - git_config(git_blame_config); + git_config(git_blame_config, NULL); save_commit_buffer = 0; opt = 0; diff --git a/builtin-branch.c b/builtin-branch.c index 19c508a608..d279702ba9 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -63,7 +63,7 @@ static int parse_branch_color_slot(const char *var, int ofs) die("bad config variable '%s'", var); } -static int git_branch_config(const char *var, const char *value) +static int git_branch_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "color.branch")) { branch_use_color = git_config_colorbool(var, value, -1); @@ -76,7 +76,7 @@ static int git_branch_config(const char *var, const char *value) color_parse(value, var, branch_colors[slot]); return 0; } - return git_color_default_config(var, value); + return git_color_default_config(var, value, cb); } static const char *branch_get_color(enum color_branch ix) @@ -461,7 +461,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) OPT_END(), }; - git_config(git_branch_config); + git_config(git_branch_config, NULL); if (branch_use_color == -1) branch_use_color = git_use_color_default; diff --git a/builtin-cat-file.c b/builtin-cat-file.c index f132d583d3..b488fad431 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -85,7 +85,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix) int opt; const char *exp_type, *obj_name; - git_config(git_default_config); + git_config(git_default_config, NULL); if (argc != 3) usage("git-cat-file [-t|-s|-e|-p|] "); exp_type = argv[1]; diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 7e42024c67..eb1fc9aa6f 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -166,7 +166,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) int read_from_stdin = 0; int prefix_length; - git_config(git_default_config); + git_config(git_default_config, NULL); state.base_dir = ""; prefix_length = prefix ? strlen(prefix) : 0; diff --git a/builtin-checkout.c b/builtin-checkout.c index 10ec137cce..c077134e62 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -514,7 +514,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) memset(&opts, 0, sizeof(opts)); memset(&new, 0, sizeof(new)); - git_config(git_default_config); + git_config(git_default_config, NULL); opts.track = git_branch_track; diff --git a/builtin-clean.c b/builtin-clean.c index 6778a03ae4..80a7ff9ae4 100644 --- a/builtin-clean.c +++ b/builtin-clean.c @@ -19,11 +19,11 @@ static const char *const builtin_clean_usage[] = { NULL }; -static int git_clean_config(const char *var, const char *value) +static int git_clean_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "clean.requireforce")) force = !git_config_bool(var, value); - return git_default_config(var, value); + return git_default_config(var, value, cb); } int cmd_clean(int argc, const char **argv, const char *prefix) @@ -50,7 +50,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) OPT_END() }; - git_config(git_clean_config); + git_config(git_clean_config, NULL); if (force < 0) force = 0; else diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 6610d18358..e5e4bdbe86 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -60,7 +60,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) struct strbuf buffer; int encoding_is_utf8; - git_config(git_default_config); + git_config(git_default_config, NULL); if (argc < 2) usage(commit_tree_usage); diff --git a/builtin-commit.c b/builtin-commit.c index a65c2b8c37..9f0026ed00 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -773,7 +773,7 @@ int cmd_status(int argc, const char **argv, const char *prefix) const char *index_file; int commitable; - git_config(git_status_config); + git_config(git_status_config, NULL); if (wt_status_use_color == -1) wt_status_use_color = git_use_color_default; @@ -827,7 +827,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1) } } -int git_commit_config(const char *k, const char *v) +int git_commit_config(const char *k, const char *v, void *cb) { if (!strcmp(k, "commit.template")) { if (!v) @@ -836,7 +836,7 @@ int git_commit_config(const char *k, const char *v) return 0; } - return git_status_config(k, v); + return git_status_config(k, v, cb); } static const char commit_utf8_warn[] = @@ -864,7 +864,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) unsigned char commit_sha1[20]; struct ref_lock *ref_lock; - git_config(git_commit_config); + git_config(git_commit_config, NULL); argc = parse_and_validate_options(argc, argv, builtin_commit_usage); diff --git a/builtin-config.c b/builtin-config.c index 8ee01bdecd..3a441ef648 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -18,7 +18,7 @@ static char key_delim = ' '; static char term = '\n'; static enum { T_RAW, T_INT, T_BOOL, T_BOOL_OR_INT } type = T_RAW; -static int show_all_config(const char *key_, const char *value_) +static int show_all_config(const char *key_, const char *value_, void *cb) { if (value_) printf("%s%c%s%c", key_, delim, value_, term); @@ -27,7 +27,7 @@ static int show_all_config(const char *key_, const char *value_) return 0; } -static int show_config(const char* key_, const char* value_) +static int show_config(const char* key_, const char* value_, void *cb) { char value[256]; const char *vptr = value; @@ -121,14 +121,14 @@ static int get_value(const char* key_, const char* regex_) } if (do_all && system_wide) - git_config_from_file(show_config, system_wide); + git_config_from_file(show_config, system_wide, NULL); if (do_all && global) - git_config_from_file(show_config, global); - git_config_from_file(show_config, local); + git_config_from_file(show_config, global, NULL); + git_config_from_file(show_config, local, NULL); if (!do_all && !seen && global) - git_config_from_file(show_config, global); + git_config_from_file(show_config, global, NULL); if (!do_all && !seen && system_wide) - git_config_from_file(show_config, system_wide); + git_config_from_file(show_config, system_wide, NULL); free(key); if (regexp) { @@ -182,7 +182,7 @@ static int get_color_found; static const char *get_color_slot; static char parsed_color[COLOR_MAXLEN]; -static int git_get_color_config(const char *var, const char *value) +static int git_get_color_config(const char *var, const char *value, void *cb) { if (!strcmp(var, get_color_slot)) { if (!value) @@ -218,7 +218,7 @@ static int get_color(int argc, const char **argv) get_color_found = 0; parsed_color[0] = '\0'; - git_config(git_get_color_config); + git_config(git_get_color_config, NULL); if (!get_color_found && def_color) color_parse(def_color, "command line", parsed_color); @@ -230,7 +230,8 @@ static int get_color(int argc, const char **argv) static int stdout_is_tty; static int get_colorbool_found; static int get_diff_color_found; -static int git_get_colorbool_config(const char *var, const char *value) +static int git_get_colorbool_config(const char *var, const char *value, + void *cb) { if (!strcmp(var, get_color_slot)) { get_colorbool_found = @@ -265,7 +266,7 @@ static int get_colorbool(int argc, const char **argv) get_colorbool_found = -1; get_diff_color_found = -1; get_color_slot = argv[0]; - git_config(git_get_colorbool_config); + git_config(git_get_colorbool_config, NULL); if (get_colorbool_found < 0) { if (!strcmp(get_color_slot, "color.diff")) @@ -298,7 +299,8 @@ int cmd_config(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) { if (argc != 2) usage(git_config_set_usage); - if (git_config(show_all_config) < 0 && file && errno) + if (git_config(show_all_config, NULL) < 0 && + file && errno) die("unable to read config file %s: %s", file, strerror(errno)); return 0; diff --git a/builtin-diff-files.c b/builtin-diff-files.c index e2306c162a..907392a1f3 100644 --- a/builtin-diff-files.c +++ b/builtin-diff-files.c @@ -21,7 +21,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix) prefix = setup_git_directory_gently(&nongit); init_revisions(&rev, prefix); - git_config(git_diff_basic_config); /* no "diff" UI options */ + git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; if (!setup_diff_no_index(&rev, argc, argv, nongit, prefix)) diff --git a/builtin-diff-index.c b/builtin-diff-index.c index 2b955deb91..2f44ebfcdd 100644 --- a/builtin-diff-index.c +++ b/builtin-diff-index.c @@ -17,7 +17,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix) int result; init_revisions(&rev, prefix); - git_config(git_diff_basic_config); /* no "diff" UI options */ + git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ rev.abbrev = 0; argc = setup_revisions(argc, argv, &rev, NULL); diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 832797ff3b..9d2a48fd68 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -68,7 +68,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int read_stdin = 0; init_revisions(opt, prefix); - git_config(git_diff_basic_config); /* no "diff" UI options */ + git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ nr_sha1 = 0; opt->abbrev = 0; opt->diff = 1; diff --git a/builtin-diff.c b/builtin-diff.c index 7c2a8412fa..583291a9c0 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -234,7 +234,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) */ prefix = setup_git_directory_gently(&nongit); - git_config(git_diff_ui_config); + git_config(git_diff_ui_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; diff --git a/builtin-fast-export.c b/builtin-fast-export.c index e1c56303e5..ff759cc578 100755 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -372,7 +372,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) }; /* we handle encodings */ - git_config(git_default_config); + git_config(git_default_config, NULL); init_revisions(&revs, prefix); argc = setup_revisions(argc, argv, &revs, NULL); diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index c97a42739d..de1e8d1365 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -635,7 +635,7 @@ static int remove_duplicates(int nr_heads, char **heads) return dst; } -static int fetch_pack_config(const char *var, const char *value) +static int fetch_pack_config(const char *var, const char *value, void *cb) { if (strcmp(var, "fetch.unpacklimit") == 0) { fetch_unpack_limit = git_config_int(var, value); @@ -647,7 +647,7 @@ static int fetch_pack_config(const char *var, const char *value) return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static struct lock_file lock; @@ -657,7 +657,7 @@ static void fetch_pack_setup(void) static int did_setup; if (did_setup) return; - git_config(fetch_pack_config); + git_config(fetch_pack_config, NULL); if (0 <= transfer_unpack_limit) unpack_limit = transfer_unpack_limit; else if (0 <= fetch_unpack_limit) diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index b72cb59e6a..b892621ab5 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -10,7 +10,7 @@ static const char *fmt_merge_msg_usage = static int merge_summary; -static int fmt_merge_msg_config(const char *key, const char *value) +static int fmt_merge_msg_config(const char *key, const char *value, void *cb) { static int found_merge_log = 0; if (!strcmp("merge.log", key)) { @@ -260,7 +260,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) unsigned char head_sha1[20]; const char *current_branch; - git_config(fmt_merge_msg_config); + git_config(fmt_merge_msg_config, NULL); while (argc > 1) { if (!strcmp(argv[1], "--log") || !strcmp(argv[1], "--summary")) diff --git a/builtin-gc.c b/builtin-gc.c index f99ebc7926..e1a329917a 100644 --- a/builtin-gc.c +++ b/builtin-gc.c @@ -35,7 +35,7 @@ static const char *argv_repack[MAX_ADD] = {"repack", "-d", "-l", NULL}; static const char *argv_prune[] = {"prune", "--expire", NULL, NULL}; static const char *argv_rerere[] = {"rerere", "gc", NULL}; -static int gc_config(const char *var, const char *value) +static int gc_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "gc.packrefs")) { if (value && !strcmp(value, "notbare")) @@ -67,7 +67,7 @@ static int gc_config(const char *var, const char *value) prune_expire = xstrdup(value); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static void append_option(const char **cmd, const char *opt, int max_length) @@ -226,7 +226,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix) OPT_END() }; - git_config(gc_config); + git_config(gc_config, NULL); if (pack_refs < 0) pack_refs = !is_bare_repository(); diff --git a/builtin-http-fetch.c b/builtin-http-fetch.c index b1f33891c3..3a062487a7 100644 --- a/builtin-http-fetch.c +++ b/builtin-http-fetch.c @@ -18,7 +18,7 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix) int get_verbosely = 0; int get_recover = 0; - git_config(git_default_config); + git_config(git_default_config, NULL); while (arg < argc && argv[arg][0] == '-') { if (argv[arg][1] == 't') { diff --git a/builtin-init-db.c b/builtin-init-db.c index a76f5d3474..f6aa353529 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -142,7 +142,7 @@ static void copy_templates(const char *git_dir, int len, const char *template_di strcpy(template_path + template_len, "config"); repository_format_version = 0; git_config_from_file(check_repository_format_version, - template_path); + template_path, NULL); template_path[template_len] = 0; if (repository_format_version && @@ -197,7 +197,7 @@ static int create_default_files(const char *git_dir, const char *template_path) path[len] = 0; copy_templates(path, len, template_path); - git_config(git_default_config); + git_config(git_default_config, NULL); /* * We would have created the above under user's umask -- under diff --git a/builtin-log.c b/builtin-log.c index 80a01f8d44..addc7098cf 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -222,7 +222,7 @@ static int cmd_log_walk(struct rev_info *rev) return 0; } -static int git_log_config(const char *var, const char *value) +static int git_log_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.pretty")) return git_config_string(&fmt_pretty, var, value); @@ -236,14 +236,14 @@ static int git_log_config(const char *var, const char *value) default_show_root = git_config_bool(var, value); return 0; } - return git_diff_ui_config(var, value); + return git_diff_ui_config(var, value, cb); } int cmd_whatchanged(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -319,7 +319,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) struct object_array_entry *objects; int i, count, ret = 0; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -383,7 +383,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -416,7 +416,7 @@ int cmd_log(int argc, const char **argv, const char *prefix) { struct rev_info rev; - git_config(git_log_config); + git_config(git_log_config, NULL); if (diff_use_color_default == -1) diff_use_color_default = git_use_color_default; @@ -471,7 +471,7 @@ static void add_header(const char *value) extra_hdr[extra_hdr_nr++] = xstrndup(value, len); } -static int git_format_config(const char *var, const char *value) +static int git_format_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "format.headers")) { if (!value) @@ -497,7 +497,7 @@ static int git_format_config(const char *var, const char *value) return 0; } - return git_log_config(var, value); + return git_log_config(var, value, cb); } @@ -764,7 +764,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) char *add_signoff = NULL; struct strbuf buf; - git_config(git_format_config); + git_config(git_format_config, NULL); init_revisions(&rev, prefix); rev.commit_format = CMIT_FMT_EMAIL; rev.verbose_header = 1; diff --git a/builtin-ls-files.c b/builtin-ls-files.c index dc7eab89b3..75ba42246e 100644 --- a/builtin-ls-files.c +++ b/builtin-ls-files.c @@ -437,7 +437,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix) memset(&dir, 0, sizeof(dir)); if (prefix) prefix_offset = strlen(prefix); - git_config(git_default_config); + git_config(git_default_config, NULL); for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c index 7abe333ce9..f4a75ddbc3 100644 --- a/builtin-ls-tree.c +++ b/builtin-ls-tree.c @@ -122,7 +122,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) unsigned char sha1[20]; struct tree *tree; - git_config(git_default_config); + git_config(git_default_config, NULL); ls_tree_prefix = prefix; if (prefix && *prefix) chomp_prefix = strlen(prefix); diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index 11f154b31f..6e23ffd8af 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -962,7 +962,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix) /* NEEDSWORK: might want to do the optional .git/ directory * discovery */ - git_config(git_default_config); + git_config(git_default_config, NULL); def_charset = (git_commit_encoding ? git_commit_encoding : "utf-8"); metainfo_charset = def_charset; diff --git a/builtin-merge-base.c b/builtin-merge-base.c index 0108e22ade..bcf9395aaf 100644 --- a/builtin-merge-base.c +++ b/builtin-merge-base.c @@ -28,7 +28,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix) unsigned char rev1key[20], rev2key[20]; int show_all = 0; - git_config(git_default_config); + git_config(git_default_config, NULL); while (1 < argc && argv[1][0] == '-') { const char *arg = argv[1]; diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index 910c0d20e7..e16f5e2a4e 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -1336,7 +1336,7 @@ static struct commit *get_ref(const char *ref) return (struct commit *)object; } -static int merge_config(const char *var, const char *value) +static int merge_config(const char *var, const char *value, void *cb) { if (!strcasecmp(var, "merge.verbosity")) { verbosity = git_config_int(var, value); @@ -1346,7 +1346,7 @@ static int merge_config(const char *var, const char *value) rename_limit = git_config_int(var, value); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } int cmd_merge_recursive(int argc, const char **argv, const char *prefix) @@ -1367,7 +1367,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) subtree_merge = 1; } - git_config(merge_config); + git_config(merge_config, NULL); if (getenv("GIT_MERGE_VERBOSITY")) verbosity = strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10); diff --git a/builtin-mv.c b/builtin-mv.c index 94f6dd2aad..3edebef45f 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -81,7 +81,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) struct path_list deleted = {NULL, 0, 0, 0}; struct path_list changed = {NULL, 0, 0, 0}; - git_config(git_default_config); + git_config(git_default_config, NULL); newfd = hold_locked_index(&lock_file, 1); if (read_cache() < 0) diff --git a/builtin-name-rev.c b/builtin-name-rev.c index 384da4db13..cde5de56fa 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -195,7 +195,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) OPT_END(), }; - git_config(git_default_config); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, opts, name_rev_usage, 0); if (!!all + !!transform_stdin + !!argc > 1) { error("Specify either a list, or --all, not both!"); diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 777f272668..a8dc225a72 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1718,7 +1718,7 @@ static void prepare_pack(int window, int depth) free(delta_list); } -static int git_pack_config(const char *k, const char *v) +static int git_pack_config(const char *k, const char *v, void *cb) { if(!strcmp(k, "pack.window")) { window = git_config_int(k, v); @@ -1771,7 +1771,7 @@ static int git_pack_config(const char *k, const char *v) pack_size_limit_cfg = git_config_ulong(k, v); return 0; } - return git_default_config(k, v); + return git_default_config(k, v, cb); } static void read_object_list_from_stdin(void) @@ -1963,7 +1963,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) rp_av[1] = "--objects"; /* --thin will make it --objects-edge */ rp_ac = 2; - git_config(git_pack_config); + git_config(git_pack_config, NULL); if (!pack_compression_seen && core_compression_seen) pack_compression_level = core_compression_level; diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 7ac30883bc..5a09e17f1a 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -104,12 +104,10 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) opts.src_index = &the_index; opts.dst_index = &the_index; - git_config(git_default_config); + git_config(git_default_config, NULL); newfd = hold_locked_index(&lock_file, 1); - git_config(git_default_config); - for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/builtin-reflog.c b/builtin-reflog.c index 280e24e151..897d1dcac6 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -329,7 +329,7 @@ static int collect_reflog(const char *ref, const unsigned char *sha1, int unused return 0; } -static int reflog_expire_config(const char *var, const char *value) +static int reflog_expire_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "gc.reflogexpire")) { if (!value) @@ -343,7 +343,7 @@ static int reflog_expire_config(const char *var, const char *value) default_reflog_expire_unreachable = approxidate(value); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) @@ -352,7 +352,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix) unsigned long now = time(NULL); int i, status, do_all; - git_config(reflog_expire_config); + git_config(reflog_expire_config, NULL); save_commit_buffer = 0; do_all = status = 0; diff --git a/builtin-remote.c b/builtin-remote.c index 8b63619ef0..99a34dfe86 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -153,7 +153,7 @@ struct branch_info { static struct path_list branch_list; -static int config_read_branches(const char *key, const char *value) +static int config_read_branches(const char *key, const char *value, void *cb) { if (!prefixcmp(key, "branch.")) { char *name; @@ -200,7 +200,7 @@ static void read_branches(void) { if (branch_list.nr) return; - git_config(config_read_branches); + git_config(config_read_branches, NULL); sort_path_list(&branch_list); } @@ -514,7 +514,7 @@ struct remote_group { struct path_list *list; } remote_group; -static int get_remote_group(const char *key, const char *value) +static int get_remote_group(const char *key, const char *value, void *cb) { if (!prefixcmp(key, "remotes.") && !strcmp(key + 8, remote_group.name)) { @@ -546,7 +546,7 @@ static int update(int argc, const char **argv) remote_group.list = &list; for (i = 1; i < argc; i++) { remote_group.name = argv[i]; - result = git_config(get_remote_group); + result = git_config(get_remote_group, NULL); } if (!result && !list.nr && argc == 2 && !strcmp(argv[1], "default")) diff --git a/builtin-rerere.c b/builtin-rerere.c index c607aade63..5c811423cc 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -339,7 +339,7 @@ tail_optimization: return write_rr(rr, fd); } -static int git_rerere_config(const char *var, const char *value) +static int git_rerere_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "gc.rerereresolved")) cutoff_resolve = git_config_int(var, value); @@ -348,7 +348,7 @@ static int git_rerere_config(const char *var, const char *value) else if (!strcmp(var, "rerere.enabled")) rerere_enabled = git_config_bool(var, value); else - return git_default_config(var, value); + return git_default_config(var, value, cb); return 0; } @@ -376,7 +376,7 @@ static int setup_rerere(struct path_list *merge_rr) { int fd; - git_config(git_rerere_config); + git_config(git_rerere_config, NULL); if (!is_rerere_enabled()) return -1; diff --git a/builtin-reset.c b/builtin-reset.c index 79424bb26e..e32ddd90ac 100644 --- a/builtin-reset.c +++ b/builtin-reset.c @@ -186,7 +186,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix) OPT_END() }; - git_config(git_default_config); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, options, git_reset_usage, PARSE_OPT_KEEP_DASHDASH); diff --git a/builtin-rev-list.c b/builtin-rev-list.c index edc0bd35bb..274299044e 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -546,7 +546,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) int bisect_find_all = 0; int quiet = 0; - git_config(git_default_config); + git_config(git_default_config, NULL); init_revisions(&revs, prefix); revs.abbrev = 0; revs.commit_format = CMIT_FMT_UNSPECIFIED; diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index f8d8548e9c..1d019b3c16 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -381,7 +381,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) return cmd_parseopt(argc - 1, argv + 1, prefix); prefix = setup_git_directory(); - git_config(git_default_config); + git_config(git_default_config, NULL); for (i = 1; i < argc; i++) { const char *arg = argv[i]; diff --git a/builtin-revert.c b/builtin-revert.c index 2b57525d72..0270f9b85a 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -269,7 +269,7 @@ static int revert_or_cherry_pick(int argc, const char **argv) const char *message, *encoding; const char *defmsg = xstrdup(git_path("MERGE_MSG")); - git_config(git_default_config); + git_config(git_default_config, NULL); me = action == REVERT ? "revert" : "cherry-pick"; setenv(GIT_REFLOG_ACTION, me, 0); parse_args(argc, argv); diff --git a/builtin-rm.c b/builtin-rm.c index c0a8bb6cf5..22c9bd1c6c 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -144,7 +144,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix) const char **pathspec; char *seen; - git_config(git_default_config); + git_config(git_default_config, NULL); newfd = hold_locked_index(&lock_file, 1); diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 019abd3527..ee4269dd33 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -533,7 +533,7 @@ static void append_one_rev(const char *av) die("bad sha1 reference %s", av); } -static int git_show_branch_config(const char *var, const char *value) +static int git_show_branch_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "showbranch.default")) { if (!value) @@ -547,7 +547,7 @@ static int git_show_branch_config(const char *var, const char *value) return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int omit_in_dense(struct commit *commit, struct commit **rev, int n) @@ -611,7 +611,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix) int reflog = 0; const char *reflog_base = NULL; - git_config(git_show_branch_config); + git_config(git_show_branch_config, NULL); /* If nothing is specified, try the default first */ if (ac == 1 && default_num) { diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c index d33982b967..b49bdb6900 100644 --- a/builtin-symbolic-ref.c +++ b/builtin-symbolic-ref.c @@ -35,7 +35,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix) OPT_END(), }; - git_config(git_default_config); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0); if (msg &&!*msg) die("Refusing to perform update with empty message"); diff --git a/builtin-tag.c b/builtin-tag.c index 129ff57f11..e675206de3 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -256,7 +256,7 @@ static void set_signingkey(const char *value) die("signing key value too long (%.10s...)", value); } -static int git_tag_config(const char *var, const char *value) +static int git_tag_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "user.signingkey")) { if (!value) @@ -265,7 +265,7 @@ static int git_tag_config(const char *var, const char *value) return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static void write_tag_body(int fd, const unsigned char *sha1) @@ -408,7 +408,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) OPT_END() }; - git_config(git_tag_config); + git_config(git_tag_config, NULL); argc = parse_options(argc, argv, options, git_tag_usage, 0); diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index fecf0be779..85043d1fde 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -493,7 +493,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) int i; unsigned char sha1[20]; - git_config(git_default_config); + git_config(git_default_config, NULL); quiet = !isatty(2); diff --git a/builtin-update-index.c b/builtin-update-index.c index a8795d3d5f..e1ca8deac2 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -567,7 +567,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) int lock_error = 0; struct lock_file *lock_file; - git_config(git_default_config); + git_config(git_default_config, NULL); /* We can't free this memory, it becomes part of a linked list parsed atexit() */ lock_file = xcalloc(1, sizeof(struct lock_file)); diff --git a/builtin-update-ref.c b/builtin-update-ref.c index e90737c350..93c127196d 100644 --- a/builtin-update-ref.c +++ b/builtin-update-ref.c @@ -22,7 +22,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix) OPT_END(), }; - git_config(git_default_config); + git_config(git_default_config, NULL); argc = parse_options(argc, argv, options, git_update_ref_usage, 0); if (msg && !*msg) die("Refusing to perform update with empty message."); diff --git a/builtin-verify-pack.c b/builtin-verify-pack.c index 4958bbbf11..4c515a0570 100644 --- a/builtin-verify-pack.c +++ b/builtin-verify-pack.c @@ -55,7 +55,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix) int no_more_options = 0; int nothing_done = 1; - git_config(git_default_config); + git_config(git_default_config, NULL); while (1 < argc) { if (!no_more_options && argv[1][0] == '-') { if (!strcmp("-v", argv[1])) diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c index db81496b46..92eaa89a45 100644 --- a/builtin-verify-tag.c +++ b/builtin-verify-tag.c @@ -90,7 +90,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix) { int i = 1, verbose = 0, had_error = 0; - git_config(git_default_config); + git_config(git_default_config, NULL); if (argc == 1) usage(builtin_verify_tag_usage); diff --git a/builtin-write-tree.c b/builtin-write-tree.c index e838d01233..c218799744 100644 --- a/builtin-write-tree.c +++ b/builtin-write-tree.c @@ -18,7 +18,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix) unsigned char sha1[20]; const char *me = "git-write-tree"; - git_config(git_default_config); + git_config(git_default_config, NULL); while (1 < argc) { const char *arg = argv[1]; if (!strcmp(arg, "--missing-ok")) diff --git a/cache.h b/cache.h index 9cee9a5f3f..ebe4031b65 100644 --- a/cache.h +++ b/cache.h @@ -711,10 +711,10 @@ extern int matches_pack_name(struct packed_git *p, const char *name); /* Dumb servers support */ extern int update_server_info(int); -typedef int (*config_fn_t)(const char *, const char *); -extern int git_default_config(const char *, const char *); -extern int git_config_from_file(config_fn_t fn, const char *); -extern int git_config(config_fn_t fn); +typedef int (*config_fn_t)(const char *, const char *, void *); +extern int git_default_config(const char *, const char *, void *); +extern int git_config_from_file(config_fn_t fn, const char *, void *); +extern int git_config(config_fn_t fn, void *); extern int git_parse_long(const char *, long *); extern int git_parse_ulong(const char *, unsigned long *); extern int git_config_int(const char *, const char *); @@ -726,7 +726,7 @@ extern int git_config_set(const char *, const char *); extern int git_config_set_multivar(const char *, const char *, const char *, int); extern int git_config_rename_section(const char *, const char *); extern const char *git_etc_gitconfig(void); -extern int check_repository_format_version(const char *var, const char *value); +extern int check_repository_format_version(const char *var, const char *value, void *cb); extern int git_env_bool(const char *, int); extern int git_config_system(void); extern int git_config_global(void); diff --git a/color.c b/color.c index 12a6453f90..fc0b72ad59 100644 --- a/color.c +++ b/color.c @@ -145,14 +145,14 @@ int git_config_colorbool(const char *var, const char *value, int stdout_is_tty) return 0; } -int git_color_default_config(const char *var, const char *value) +int git_color_default_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "color.ui")) { git_use_color_default = git_config_colorbool(var, value, -1); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int color_vfprintf(FILE *fp, const char *color, const char *fmt, diff --git a/color.h b/color.h index ecda5569a2..6cf5c88aaf 100644 --- a/color.h +++ b/color.h @@ -13,7 +13,7 @@ extern int git_use_color_default; /* * Use this instead of git_default_config if you need the value of color.ui. */ -int git_color_default_config(const char *var, const char *value); +int git_color_default_config(const char *var, const char *value, void *cb); int git_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *var, const char *value, char *dst); diff --git a/config.c b/config.c index 0e22c7a642..5431e2dc01 100644 --- a/config.c +++ b/config.c @@ -111,7 +111,7 @@ static inline int iskeychar(int c) return isalnum(c) || c == '-'; } -static int get_value(config_fn_t fn, char *name, unsigned int len) +static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) { int c; char *value; @@ -139,7 +139,7 @@ static int get_value(config_fn_t fn, char *name, unsigned int len) if (!value) return -1; } - return fn(name, value); + return fn(name, value, data); } static int get_extended_base_var(char *name, int baselen, int c) @@ -197,7 +197,7 @@ static int get_base_var(char *name) } } -static int git_parse_file(config_fn_t fn) +static int git_parse_file(config_fn_t fn, void *data) { int comment = 0; int baselen = 0; @@ -228,7 +228,7 @@ static int git_parse_file(config_fn_t fn) if (!isalpha(c)) break; var[baselen] = tolower(c); - if (get_value(fn, var, baselen+1) < 0) + if (get_value(fn, data, var, baselen+1) < 0) break; } die("bad config file line %d in %s", config_linenr, config_file_name); @@ -332,7 +332,7 @@ int git_config_string(const char **dest, const char *var, const char *value) return 0; } -int git_default_config(const char *var, const char *value) +int git_default_config(const char *var, const char *value, void *dummy) { /* This needs a better name */ if (!strcmp(var, "core.filemode")) { @@ -512,7 +512,7 @@ int git_default_config(const char *var, const char *value) return 0; } -int git_config_from_file(config_fn_t fn, const char *filename) +int git_config_from_file(config_fn_t fn, const char *filename, void *data) { int ret; FILE *f = fopen(filename, "r"); @@ -523,7 +523,7 @@ int git_config_from_file(config_fn_t fn, const char *filename) config_file_name = filename; config_linenr = 1; config_file_eof = 0; - ret = git_parse_file(fn); + ret = git_parse_file(fn, data); fclose(f); config_file_name = NULL; } @@ -561,7 +561,7 @@ int git_config_global(void) return !git_env_bool("GIT_CONFIG_NOGLOBAL", 0); } -int git_config(config_fn_t fn) +int git_config(config_fn_t fn, void *data) { int ret = 0; char *repo_config = NULL; @@ -574,7 +574,8 @@ int git_config(config_fn_t fn) filename = getenv(CONFIG_ENVIRONMENT); if (!filename) { if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) - ret += git_config_from_file(fn, git_etc_gitconfig()); + ret += git_config_from_file(fn, git_etc_gitconfig(), + data); home = getenv("HOME"); filename = getenv(CONFIG_LOCAL_ENVIRONMENT); if (!filename) @@ -584,11 +585,11 @@ int git_config(config_fn_t fn) if (git_config_global() && home) { char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); if (!access(user_config, R_OK)) - ret = git_config_from_file(fn, user_config); + ret = git_config_from_file(fn, user_config, data); free(user_config); } - ret += git_config_from_file(fn, filename); + ret += git_config_from_file(fn, filename, data); free(repo_config); return ret; } @@ -618,7 +619,7 @@ static int matches(const char* key, const char* value) !regexec(store.value_regex, value, 0, NULL, 0))); } -static int store_aux(const char* key, const char* value) +static int store_aux(const char* key, const char* value, void *cb) { const char *ep; size_t section_len; @@ -947,7 +948,7 @@ int git_config_set_multivar(const char* key, const char* value, * As a side effect, we make sure to transform only a valid * existing config file. */ - if (git_config_from_file(store_aux, config_filename)) { + if (git_config_from_file(store_aux, config_filename, NULL)) { error("invalid config file %s", config_filename); free(store.key); if (store.value_regex != NULL) { diff --git a/connect.c b/connect.c index d12b105970..e92af29735 100644 --- a/connect.c +++ b/connect.c @@ -360,7 +360,8 @@ static char *git_proxy_command; static const char *rhost_name; static int rhost_len; -static int git_proxy_command_options(const char *var, const char *value) +static int git_proxy_command_options(const char *var, const char *value, + void *cb) { if (!strcmp(var, "core.gitproxy")) { const char *for_pos; @@ -404,7 +405,7 @@ static int git_proxy_command_options(const char *var, const char *value) return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int git_use_proxy(const char *host) @@ -412,7 +413,7 @@ static int git_use_proxy(const char *host) rhost_name = host; rhost_len = strlen(host); git_proxy_command = getenv("GIT_PROXY_COMMAND"); - git_config(git_proxy_command_options); + git_config(git_proxy_command_options, NULL); rhost_name = NULL; return (git_proxy_command && *git_proxy_command); } diff --git a/convert.c b/convert.c index d8c94cb3ed..1c66844783 100644 --- a/convert.c +++ b/convert.c @@ -323,7 +323,7 @@ static struct convert_driver { char *clean; } *user_convert, **user_convert_tail; -static int read_convert_config(const char *var, const char *value) +static int read_convert_config(const char *var, const char *value, void *cb) { const char *ep, *name; int namelen; @@ -385,7 +385,7 @@ static void setup_convert_check(struct git_attr_check *check) attr_ident = git_attr("ident", 5); attr_filter = git_attr("filter", 6); user_convert_tail = &user_convert; - git_config(read_convert_config); + git_config(read_convert_config, NULL); } check[0].attr = attr_crlf; check[1].attr = attr_ident; diff --git a/daemon.c b/daemon.c index 2b4a6f145c..63cd12cd9c 100644 --- a/daemon.c +++ b/daemon.c @@ -306,7 +306,7 @@ struct daemon_service { static struct daemon_service *service_looking_at; static int service_enabled; -static int git_daemon_config(const char *var, const char *value) +static int git_daemon_config(const char *var, const char *value, void *cb) { if (!prefixcmp(var, "daemon.") && !strcmp(var + 7, service_looking_at->config_name)) { @@ -356,7 +356,7 @@ static int run_service(struct interp *itable, struct daemon_service *service) if (service->overridable) { service_looking_at = service; service_enabled = -1; - git_config(git_daemon_config); + git_config(git_daemon_config, NULL); if (0 <= service_enabled) enabled = service_enabled; } diff --git a/diff.c b/diff.c index e35384b444..1f46ff0f08 100644 --- a/diff.c +++ b/diff.c @@ -129,7 +129,7 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v * never be affected by the setting of diff.renames * the user happens to have in the configuration file. */ -int git_diff_ui_config(const char *var, const char *value) +int git_diff_ui_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "diff.renamelimit")) { diff_rename_limit_default = git_config_int(var, value); @@ -166,10 +166,10 @@ int git_diff_ui_config(const char *var, const char *value) return parse_lldiff_command(var, ep, value); } - return git_diff_basic_config(var, value); + return git_diff_basic_config(var, value, cb); } -int git_diff_basic_config(const char *var, const char *value) +int git_diff_basic_config(const char *var, const char *value, void *cb) { if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); @@ -190,7 +190,7 @@ int git_diff_basic_config(const char *var, const char *value) } } - return git_color_default_config(var, value); + return git_color_default_config(var, value, cb); } static char *quote_two(const char *one, const char *two) diff --git a/diff.h b/diff.h index 1bd94a4807..1cf1eff485 100644 --- a/diff.h +++ b/diff.h @@ -180,8 +180,8 @@ extern void diff_unmerge(struct diff_options *, #define DIFF_SETUP_USE_CACHE 2 #define DIFF_SETUP_USE_SIZE_CACHE 4 -extern int git_diff_basic_config(const char *var, const char *value); -extern int git_diff_ui_config(const char *var, const char *value); +extern int git_diff_basic_config(const char *var, const char *value, void *cb); +extern int git_diff_ui_config(const char *var, const char *value, void *cb); extern int diff_use_color_default; extern void diff_setup(struct diff_options *); extern int diff_opt_parse(struct diff_options *, const char **, int); diff --git a/fast-import.c b/fast-import.c index 73e5439d97..36ec5b87f8 100644 --- a/fast-import.c +++ b/fast-import.c @@ -2352,7 +2352,7 @@ static void import_marks(const char *input_file) fclose(f); } -static int git_pack_config(const char *k, const char *v) +static int git_pack_config(const char *k, const char *v, void *cb) { if (!strcmp(k, "pack.depth")) { max_depth = git_config_int(k, v); @@ -2370,7 +2370,7 @@ static int git_pack_config(const char *k, const char *v) pack_compression_seen = 1; return 0; } - return git_default_config(k, v); + return git_default_config(k, v, cb); } static const char fast_import_usage[] = @@ -2381,7 +2381,7 @@ int main(int argc, const char **argv) unsigned int i, show_stats = 1; setup_git_directory(); - git_config(git_pack_config); + git_config(git_pack_config, NULL); if (!pack_compression_seen && core_compression_seen) pack_compression_level = core_compression_level; diff --git a/hash-object.c b/hash-object.c index 61e7160b36..3d773900ff 100644 --- a/hash-object.c +++ b/hash-object.c @@ -43,7 +43,7 @@ int main(int argc, char **argv) int no_more_flags = 0; int hashstdin = 0; - git_config(git_default_config); + git_config(git_default_config, NULL); for (i = 1 ; i < argc; i++) { if (!no_more_flags && argv[i][0] == '-') { diff --git a/help.c b/help.c index af80979fcb..d89d43796f 100644 --- a/help.c +++ b/help.c @@ -252,7 +252,7 @@ static int add_man_viewer_info(const char *var, const char *value) return 0; } -static int git_help_config(const char *var, const char *value) +static int git_help_config(const char *var, const char *value, void *cb) { if (!strcmp(var, "help.format")) { if (!value) @@ -269,7 +269,7 @@ static int git_help_config(const char *var, const char *value) if (!prefixcmp(var, "man.")) return add_man_viewer_info(var, value); - return git_default_config(var, value); + return git_default_config(var, value, cb); } /* most GUI terminals set COLUMNS (although some don't export it) */ @@ -641,7 +641,7 @@ int cmd_help(int argc, const char **argv, const char *prefix) const char *alias; setup_git_directory_gently(&nongit); - git_config(git_help_config); + git_config(git_help_config, NULL); argc = parse_options(argc, argv, builtin_help_options, builtin_help_usage, 0); diff --git a/http.c b/http.c index acf746a12d..2a21ccbb76 100644 --- a/http.c +++ b/http.c @@ -90,7 +90,7 @@ static void process_curl_messages(void) } #endif -static int http_options(const char *var, const char *value) +static int http_options(const char *var, const char *value, void *cb) { if (!strcmp("http.sslverify", var)) { if (curl_ssl_verify == -1) { @@ -169,7 +169,7 @@ static int http_options(const char *var, const char *value) } /* Fall back on the default ones */ - return git_default_config(var, value); + return git_default_config(var, value, cb); } static CURL* get_curl_handle(void) @@ -263,7 +263,7 @@ void http_init(struct remote *remote) if (low_speed_time != NULL) curl_low_speed_time = strtol(low_speed_time, NULL, 10); - git_config(http_options); + git_config(http_options, NULL); if (curl_ssl_verify == -1) curl_ssl_verify = 1; diff --git a/imap-send.c b/imap-send.c index db6559725e..1ec1310921 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1247,7 +1247,7 @@ static imap_server_conf_t server = static char *imap_folder; static int -git_imap_config(const char *key, const char *val) +git_imap_config(const char *key, const char *val, void *cb) { char imap_key[] = "imap."; @@ -1296,7 +1296,7 @@ main(int argc, char **argv) /* init the random number generator */ arc4_init(); - git_config( git_imap_config ); + git_config(git_imap_config, NULL); if (!imap_folder) { fprintf( stderr, "no imap store specified\n" ); diff --git a/index-pack.c b/index-pack.c index 9c0c27813f..aaba9443cc 100644 --- a/index-pack.c +++ b/index-pack.c @@ -765,7 +765,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, } } -static int git_index_pack_config(const char *k, const char *v) +static int git_index_pack_config(const char *k, const char *v, void *cb) { if (!strcmp(k, "pack.indexversion")) { pack_idx_default_version = git_config_int(k, v); @@ -773,7 +773,7 @@ static int git_index_pack_config(const char *k, const char *v) die("bad pack.indexversion=%d", pack_idx_default_version); return 0; } - return git_default_config(k, v); + return git_default_config(k, v, cb); } int main(int argc, char **argv) @@ -786,7 +786,7 @@ int main(int argc, char **argv) struct pack_idx_entry **idx_objects; unsigned char sha1[20]; - git_config(git_index_pack_config); + git_config(git_index_pack_config, NULL); for (i = 1; i < argc; i++) { char *arg = argv[i]; diff --git a/ll-merge.c b/ll-merge.c index 5ae74331bc..9837c842a3 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -225,7 +225,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn, static struct ll_merge_driver *ll_user_merge, **ll_user_merge_tail; static const char *default_ll_merge; -static int read_merge_config(const char *var, const char *value) +static int read_merge_config(const char *var, const char *value, void *cb) { struct ll_merge_driver *fn; const char *ep, *name; @@ -309,7 +309,7 @@ static void initialize_ll_merge(void) if (ll_user_merge_tail) return; ll_user_merge_tail = &ll_user_merge; - git_config(read_merge_config); + git_config(read_merge_config, NULL); } static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr) diff --git a/pager.c b/pager.c index ca002f9f79..dbd941421b 100644 --- a/pager.c +++ b/pager.c @@ -33,7 +33,7 @@ void setup_pager(void) return; if (!pager) { if (!pager_program) - git_config(git_default_config); + git_config(git_default_config, NULL); pager = pager_program; } if (!pager) diff --git a/receive-pack.c b/receive-pack.c index 828d49001d..b26f2e3a41 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -19,7 +19,7 @@ static int report_status; static char capabilities[] = " report-status delete-refs "; static int capabilities_sent; -static int receive_pack_config(const char *var, const char *value) +static int receive_pack_config(const char *var, const char *value, void *cb) { if (strcmp(var, "receive.denynonfastforwards") == 0) { deny_non_fast_forwards = git_config_bool(var, value); @@ -41,7 +41,7 @@ static int receive_pack_config(const char *var, const char *value) return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) @@ -489,7 +489,7 @@ int main(int argc, char **argv) if (is_repository_shallow()) die("attempt to push into a shallow repository"); - git_config(receive_pack_config); + git_config(receive_pack_config, NULL); if (0 <= transfer_unpack_limit) unpack_limit = transfer_unpack_limit; diff --git a/remote.c b/remote.c index 91cbb72dde..dff6c5f686 100644 --- a/remote.c +++ b/remote.c @@ -288,7 +288,7 @@ static void read_branches_file(struct remote *remote) remote->fetch_tags = 1; /* always auto-follow */ } -static int handle_config(const char *key, const char *value) +static int handle_config(const char *key, const char *value, void *cb) { const char *name; const char *subkey; @@ -410,7 +410,7 @@ static void read_config(void) current_branch = make_branch(head_ref + strlen("refs/heads/"), 0); } - git_config(handle_config); + git_config(handle_config, NULL); alias_all_urls(); } diff --git a/setup.c b/setup.c index b8fd476395..d630e374e7 100644 --- a/setup.c +++ b/setup.c @@ -300,7 +300,7 @@ void setup_work_tree(void) static int check_repository_format_gently(int *nongit_ok) { - git_config(check_repository_format_version); + git_config(check_repository_format_version, NULL); if (GIT_REPO_VERSION < repository_format_version) { if (!nongit_ok) die ("Expected git repo version <= %d, found %d", @@ -524,7 +524,7 @@ int git_config_perm(const char *var, const char *value) return i & 0666; } -int check_repository_format_version(const char *var, const char *value) +int check_repository_format_version(const char *var, const char *value, void *cb) { if (strcmp(var, "core.repositoryformatversion") == 0) repository_format_version = git_config_int(var, value); diff --git a/unpack-file.c b/unpack-file.c index 65c66eb0bf..bcdc8bbb3b 100644 --- a/unpack-file.c +++ b/unpack-file.c @@ -31,7 +31,7 @@ int main(int argc, char **argv) die("Not a valid object name %s", argv[1]); setup_git_directory(); - git_config(git_default_config); + git_config(git_default_config, NULL); puts(create_temp_file(sha1)); return 0; diff --git a/var.c b/var.c index c20ac919bd..724ba87a7c 100644 --- a/var.c +++ b/var.c @@ -39,13 +39,13 @@ static const char *read_var(const char *var) return val; } -static int show_config(const char *var, const char *value) +static int show_config(const char *var, const char *value, void *cb) { if (value) printf("%s=%s\n", var, value); else printf("%s\n", var); - return git_default_config(var, value); + return git_default_config(var, value, cb); } int main(int argc, char **argv) @@ -60,11 +60,11 @@ int main(int argc, char **argv) val = NULL; if (strcmp(argv[1], "-l") == 0) { - git_config(show_config); + git_config(show_config, NULL); list_vars(); return 0; } - git_config(git_default_config); + git_config(git_default_config, NULL); val = read_var(argv[1]); if (!val) usage(var_usage); diff --git a/wt-status.c b/wt-status.c index 532b4ea2c1..c932b39d20 100644 --- a/wt-status.c +++ b/wt-status.c @@ -362,7 +362,7 @@ void wt_status_print(struct wt_status *s) } } -int git_status_config(const char *k, const char *v) +int git_status_config(const char *k, const char *v, void *cb) { if (!strcmp(k, "status.submodulesummary")) { int is_bool; @@ -386,5 +386,5 @@ int git_status_config(const char *k, const char *v) wt_status_relative_paths = git_config_bool(k, v); return 0; } - return git_color_default_config(k, v); + return git_color_default_config(k, v, cb); } diff --git a/wt-status.h b/wt-status.h index 7d61410b17..f2c71302cb 100644 --- a/wt-status.h +++ b/wt-status.h @@ -27,7 +27,7 @@ struct wt_status { const char *prefix; }; -int git_status_config(const char *var, const char *value); +int git_status_config(const char *var, const char *value, void *cb); extern int wt_status_use_color; extern int wt_status_relative_paths; void wt_status_prepare(struct wt_status *s); -- cgit v1.3 From 50fd9bd8430a957ea6c6674ce6112f375985abbc Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 14 May 2008 18:03:31 +0100 Subject: diff options: Introduce --ignore-submodules The new option --ignore-submodules can now be used to ignore changes in submodules. Why? Sometimes it is not interesting when a submodule changed. For example, when reordering some commits in the superproject, a dirty submodule is usually totally uninteresting. So we will use this option in git-rebase to test for a dirty working tree. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 3 +++ diff.c | 9 +++++++++ diff.h | 1 + 3 files changed, 13 insertions(+) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 13234fa280..859d67990a 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -228,6 +228,9 @@ endif::git-format-patch[] --no-ext-diff:: Disallow external diff drivers. +--ignore-submodules:: + Ignore changes to submodules in the diff generation. + --src-prefix=:: Show the given source prefix instead of "a/". diff --git a/diff.c b/diff.c index 439d4746ca..d57bc299ee 100644 --- a/diff.c +++ b/diff.c @@ -2496,6 +2496,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, ALLOW_EXTERNAL); else if (!strcmp(arg, "--no-ext-diff")) DIFF_OPT_CLR(options, ALLOW_EXTERNAL); + else if (!strcmp(arg, "--ignore-submodules")) + DIFF_OPT_SET(options, IGNORE_SUBMODULES); /* misc options */ else if (!strcmp(arg, "-z")) @@ -3355,6 +3357,9 @@ void diff_addremove(struct diff_options *options, char concatpath[PATH_MAX]; struct diff_filespec *one, *two; + if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode)) + return; + /* This may look odd, but it is a preparation for * feeding "there are unchanged files which should * not produce diffs, but when you are doing copy @@ -3399,6 +3404,10 @@ void diff_change(struct diff_options *options, char concatpath[PATH_MAX]; struct diff_filespec *one, *two; + if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) + && S_ISGITLINK(new_mode)) + return; + if (DIFF_OPT_TST(options, REVERSE_DIFF)) { unsigned tmp; const unsigned char *tmp_c; diff --git a/diff.h b/diff.h index 3a02d38d12..1dfe1f98b1 100644 --- a/diff.h +++ b/diff.h @@ -63,6 +63,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_REVERSE_DIFF (1 << 15) #define DIFF_OPT_CHECK_FAILED (1 << 16) #define DIFF_OPT_RELATIVE_NAME (1 << 17) +#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) -- cgit v1.3 From 4d9b53591f64a11da0af4c2b8f11fd4730ce52dd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sat, 14 Jun 2008 03:27:45 -0400 Subject: avoid trailing whitespace in zero-change diffstat lines In some cases, we produce a diffstat line even though no lines have changed (e.g., because of an exact rename). In this case, there is no +/- "graph" after the number of changed lines. However, we output the space separator unconditionally, meaning that these lines contained a trailing space character. This isn't a huge problem, but in cleaning up the output we are able to eliminate some trailing whitespace from a test vector. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 3 ++- t/t4016-diff-quote.sh | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 62fdc5492b..f77f9e9447 100644 --- a/diff.c +++ b/diff.c @@ -922,7 +922,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) total = add + del; } show_name(options->file, prefix, name, len, reset, set); - fprintf(options->file, "%5d ", added + deleted); + fprintf(options->file, "%5d%s", added + deleted, + added + deleted ? " " : ""); show_graph(options->file, '+', add, add_c, reset); show_graph(options->file, '-', del, del_c, reset); fprintf(options->file, "\n"); diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index 0950250c9b..f07035ab7e 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -53,13 +53,13 @@ test_expect_success 'git diff --summary -M HEAD' ' ' cat >expect <<\EOF - pathname.1 => "Rpathname\twith HT.0" | 0 - pathname.3 => "Rpathname\nwith LF.0" | 0 - "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 - pathname.2 => Rpathname with SP.0 | 0 - "pathname\twith HT.2" => Rpathname with SP.1 | 0 - pathname.0 => Rpathname.0 | 0 - "pathname\twith HT.0" => Rpathname.1 | 0 + pathname.1 => "Rpathname\twith HT.0" | 0 + pathname.3 => "Rpathname\nwith LF.0" | 0 + "pathname\twith HT.3" => "Rpathname\nwith LF.1" | 0 + pathname.2 => Rpathname with SP.0 | 0 + "pathname\twith HT.2" => Rpathname with SP.1 | 0 + pathname.0 => Rpathname.0 | 0 + "pathname\twith HT.0" => Rpathname.1 | 0 7 files changed, 0 insertions(+), 0 deletions(-) EOF test_expect_success 'git diff --stat -M HEAD' ' -- cgit v1.3 From 06ff64ae3d8c1d446ff61cff78a8faa3a07bfe24 Mon Sep 17 00:00:00 2001 From: SZEDER Gábor Date: Tue, 17 Jun 2008 00:00:02 +0200 Subject: diff: reset color before printing newline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It worked that way since commit 50f575fc (Tweak diff colors, 2006-06-22), but commit c1795bb0 (Unify whitespace checking, 2007-12-13) changed it. This patch restores the old behaviour. Besides Linus' arguments in the log message of 50f575fc, resetting color before printing newline is also important to keep 'git add --patch' happy. If the last line(s) of a file are removed, then that hunk will end with a colored line. However, if the newline comes before the color reset, then the diff output will have an additional line at the end containing only the reset sequence. This causes trouble in git-add--interactive.perl's parse_diff function, because @colored will have one more element than @diff, and that last element will contain the color reset. The elements of these arrays will then be copied to @hunk, but only as many as the number of elements in @diff. As a result the last color reset is lost and all subsequent terminal output will be printed in color. Signed-off-by: SZEDER Gábor Signed-off-by: Junio C Hamano --- diff.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 8022e678d1..c0284775d3 100644 --- a/diff.c +++ b/diff.c @@ -514,9 +514,13 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len) { + if (len > 0 && line[len-1] == '\n') + len--; + fputs(set, file); fwrite(line, len, 1, file); fputs(reset, file); + fputc('\n', file); } static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) -- cgit v1.3 From 4afbcab9898ce63ad641dd0de6e9b69deda44330 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 16 Jun 2008 17:37:21 -0700 Subject: diff.c: fix emit_line() again not to add extra line Signed-off-by: Junio C Hamano --- diff.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index c0284775d3..20135cbe7c 100644 --- a/diff.c +++ b/diff.c @@ -514,13 +514,15 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len) { - if (len > 0 && line[len-1] == '\n') + int has_trailing_newline = (len > 0 && line[len-1] == '\n'); + if (has_trailing_newline) len--; fputs(set, file); fwrite(line, len, 1, file); fputs(reset, file); - fputc('\n', file); + if (has_trailing_newline) + fputc('\n', file); } static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len) -- cgit v1.3 From 18374e584ca7a820457c1d83ee99867c216e7b75 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 13:16:33 -0700 Subject: diff --check: do not discard error status upon seeing a good line "git diff --check" should return non-zero when there was any whitespace error but the code only paid attention to the error status of the last new line in the patch. Signed-off-by: Junio C Hamano --- diff.c | 8 +++++--- t/t4017-diff-retval.sh | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 5262490086..f281c5b82a 100644 --- a/diff.c +++ b/diff.c @@ -1150,12 +1150,14 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) char *err; if (line[0] == '+') { + unsigned bad; data->lineno++; - data->status = check_and_emit_line(line + 1, len - 1, + bad = check_and_emit_line(line + 1, len - 1, data->ws_rule, NULL, NULL, NULL, NULL); - if (!data->status) + if (!bad) return; - err = whitespace_error_string(data->status); + data->status |= bad; + err = whitespace_error_string(bad); fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err); free(err); emit_line(data->file, set, reset, line, 1); diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh index dc0b7126cc..0d0fb87f57 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -105,4 +105,12 @@ test_expect_success '--check with --no-pager returns 2 for dirty difference' ' ' + +test_expect_success 'check should test not just the last line' ' + echo "" >>a && + git --no-pager diff --check + test $? = 2 + +' + test_done -- cgit v1.3 From 5ff10dd602f5926f0f5a73ae7de5866713428aa7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 15:34:54 -0700 Subject: diff --check: explain why we do not care whether old side is binary All other codepaths refrain from running textual diff when either the old or the new side is binary, but this function only checks the new side. I was almost going to change it to check both, but that would be a bad change. Explain why to prevent future mistakes. Signed-off-by: Junio C Hamano --- diff.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 893942359b..c00d633c12 100644 --- a/diff.c +++ b/diff.c @@ -1544,8 +1544,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b, static void builtin_checkdiff(const char *name_a, const char *name_b, const char *attr_path, - struct diff_filespec *one, - struct diff_filespec *two, struct diff_options *o) + struct diff_filespec *one, + struct diff_filespec *two, + struct diff_options *o) { mmfile_t mf1, mf2; struct checkdiff_t data; @@ -1564,6 +1565,12 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); + /* + * All the other codepaths check both sides, but not checking + * the "old" side here is deliberate. We are checking the newly + * introduced changes, and as long as the "new" side is text, we + * can and should check what it introduces. + */ if (diff_filespec_is_binary(two)) goto free_and_return; else { -- cgit v1.3 From 8f8841e9c8e6a26153b0cf9417c7540cf65ef09f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 15:35:21 -0700 Subject: check_and_emit_line(): rename and refactor The function name was too bland and not explicit enough as to what it is checking. Split it into two, and call the one that checks if there is a whitespace breakage "ws_check()", and call the other one that checks and emits the line after color coding "ws_check_emit()". Signed-off-by: Junio C Hamano --- builtin-apply.c | 5 ++--- cache.h | 5 ++--- diff.c | 13 ++++++------- ws.c | 18 +++++++++++++++--- 4 files changed, 25 insertions(+), 16 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index c497889312..92f00471bb 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -979,8 +979,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc static void check_whitespace(const char *line, int len, unsigned ws_rule) { char *err; - unsigned result = check_and_emit_line(line + 1, len - 1, ws_rule, - NULL, NULL, NULL, NULL); + unsigned result = ws_check(line + 1, len - 1, ws_rule); if (!result) return; @@ -991,7 +990,7 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule) else { err = whitespace_error_string(result); fprintf(stderr, "%s:%d: %s.\n%.*s\n", - patch_input_file, linenr, err, len - 2, line + 1); + patch_input_file, linenr, err, len - 2, line + 1); free(err); } } diff --git a/cache.h b/cache.h index 64ef86e129..3dfa53c566 100644 --- a/cache.h +++ b/cache.h @@ -819,9 +819,8 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i extern unsigned whitespace_rule_cfg; extern unsigned whitespace_rule(const char *); extern unsigned parse_whitespace_rule(const char *); -extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule, - FILE *stream, const char *set, - const char *reset, const char *ws); +extern unsigned ws_check(const char *line, int len, unsigned ws_rule); +extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws); extern char *whitespace_error_string(unsigned ws); extern int ws_fix_copy(char *, const char *, int, unsigned, int *); diff --git a/diff.c b/diff.c index c00d633c12..52a34eec91 100644 --- a/diff.c +++ b/diff.c @@ -535,9 +535,9 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons else { /* Emit just the prefix, then the rest. */ emit_line(ecbdata->file, set, reset, line, ecbdata->nparents); - (void)check_and_emit_line(line + ecbdata->nparents, - len - ecbdata->nparents, ecbdata->ws_rule, - ecbdata->file, set, reset, ws); + ws_check_emit(line + ecbdata->nparents, + len - ecbdata->nparents, ecbdata->ws_rule, + ecbdata->file, set, reset, ws); } } @@ -1153,8 +1153,7 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (line[0] == '+') { unsigned bad; data->lineno++; - bad = check_and_emit_line(line + 1, len - 1, - data->ws_rule, NULL, NULL, NULL, NULL); + bad = ws_check(line + 1, len - 1, data->ws_rule); if (!bad) return; data->status |= bad; @@ -1162,8 +1161,8 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err); free(err); emit_line(data->file, set, reset, line, 1); - (void)check_and_emit_line(line + 1, len - 1, data->ws_rule, - data->file, set, reset, ws); + ws_check_emit(line + 1, len - 1, data->ws_rule, + data->file, set, reset, ws); } else if (line[0] == ' ') data->lineno++; else if (line[0] == '@') { diff --git a/ws.c b/ws.c index ba7e834ca8..24d3e3de07 100644 --- a/ws.c +++ b/ws.c @@ -117,9 +117,9 @@ char *whitespace_error_string(unsigned ws) } /* If stream is non-NULL, emits the line after checking. */ -unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule, - FILE *stream, const char *set, - const char *reset, const char *ws) +static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule, + FILE *stream, const char *set, + const char *reset, const char *ws) { unsigned result = 0; int written = 0; @@ -213,6 +213,18 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule, return result; } +void ws_check_emit(const char *line, int len, unsigned ws_rule, + FILE *stream, const char *set, + const char *reset, const char *ws) +{ + (void)ws_check_emit_1(line, len, ws_rule, stream, set, reset, ws); +} + +unsigned ws_check(const char *line, int len, unsigned ws_rule) +{ + return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL); +} + /* Copy the line to the buffer while fixing whitespaces */ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count) { -- cgit v1.3 From 1ba111d1d6bd90b2c120ceb05418e01ee304cc46 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 15:36:34 -0700 Subject: checkdiff: pass diff_options to the callback This way, we could later use more information from the diff_options. Signed-off-by: Junio C Hamano --- diff.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 52a34eec91..6bcbe20828 100644 --- a/diff.c +++ b/diff.c @@ -1136,18 +1136,19 @@ static void free_diffstat_info(struct diffstat_t *diffstat) struct checkdiff_t { struct xdiff_emit_state xm; const char *filename; - int lineno, color_diff; + int lineno; + struct diff_options *o; unsigned ws_rule; unsigned status; - FILE *file; }; static void checkdiff_consume(void *priv, char *line, unsigned long len) { struct checkdiff_t *data = priv; - const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE); - const char *reset = diff_get_color(data->color_diff, DIFF_RESET); - const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW); + int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF); + const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE); + const char *reset = diff_get_color(color_diff, DIFF_RESET); + const char *set = diff_get_color(color_diff, DIFF_FILE_NEW); char *err; if (line[0] == '+') { @@ -1158,11 +1159,12 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) return; data->status |= bad; err = whitespace_error_string(bad); - fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err); + fprintf(data->o->file, "%s:%d: %s.\n", + data->filename, data->lineno, err); free(err); - emit_line(data->file, set, reset, line, 1); + emit_line(data->o->file, set, reset, line, 1); ws_check_emit(line + 1, len - 1, data->ws_rule, - data->file, set, reset, ws); + data->o->file, set, reset, ws); } else if (line[0] == ' ') data->lineno++; else if (line[0] == '@') { @@ -1557,9 +1559,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, data.xm.consume = checkdiff_consume; data.filename = name_b ? name_b : name_a; data.lineno = 0; - data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF); + data.o = o; data.ws_rule = whitespace_rule(attr_path); - data.file = o->file; if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); -- cgit v1.3 From 877f23ccb88227203f2576abdfb5d1c15925fcb3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 15:36:59 -0700 Subject: Teach "diff --check" about new blank lines at end When a patch adds new blank lines at the end, "git apply --whitespace" warns. This teaches "diff --check" to do the same. Signed-off-by: Junio C Hamano --- cache.h | 1 + diff.c | 17 +++++++++++++++-- t/t4015-diff-whitespace.sh | 6 ++++++ ws.c | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/cache.h b/cache.h index 3dfa53c566..188428dd26 100644 --- a/cache.h +++ b/cache.h @@ -823,6 +823,7 @@ extern unsigned ws_check(const char *line, int len, unsigned ws_rule); extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws); extern char *whitespace_error_string(unsigned ws); extern int ws_fix_copy(char *, const char *, int, unsigned, int *); +extern int ws_blank_line(const char *line, int len, unsigned ws_rule); /* ls-files */ int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen); diff --git a/diff.c b/diff.c index 6bcbe20828..f31c721168 100644 --- a/diff.c +++ b/diff.c @@ -1140,6 +1140,7 @@ struct checkdiff_t { struct diff_options *o; unsigned ws_rule; unsigned status; + int trailing_blanks_start; }; static void checkdiff_consume(void *priv, char *line, unsigned long len) @@ -1154,6 +1155,10 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) if (line[0] == '+') { unsigned bad; data->lineno++; + if (!ws_blank_line(line + 1, len - 1, data->ws_rule)) + data->trailing_blanks_start = 0; + else if (!data->trailing_blanks_start) + data->trailing_blanks_start = data->lineno; bad = ws_check(line + 1, len - 1, data->ws_rule); if (!bad) return; @@ -1165,14 +1170,16 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) emit_line(data->o->file, set, reset, line, 1); ws_check_emit(line + 1, len - 1, data->ws_rule, data->o->file, set, reset, ws); - } else if (line[0] == ' ') + } else if (line[0] == ' ') { data->lineno++; - else if (line[0] == '@') { + data->trailing_blanks_start = 0; + } else if (line[0] == '@') { char *plus = strchr(line, '+'); if (plus) data->lineno = strtol(plus, NULL, 10) - 1; else die("invalid diff"); + data->trailing_blanks_start = 0; } } @@ -1584,6 +1591,12 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, ecb.outf = xdiff_outf; ecb.priv = &data; xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + + if (data.trailing_blanks_start) { + fprintf(o->file, "%s:%d: ends with blank lines.\n", + data.filename, data.trailing_blanks_start); + data.status = 1; /* report errors */ + } } free_and_return: diff_free_filespec_data(one); diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index b7cc6b28e6..0922c708f1 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -335,4 +335,10 @@ test_expect_success 'line numbers in --check output are correct' ' ' +test_expect_success 'checkdiff detects trailing blank lines' ' + echo "foo();" >x && + echo "" >>x && + git diff --check | grep "ends with blank" +' + test_done diff --git a/ws.c b/ws.c index 24d3e3de07..7a7ff130a3 100644 --- a/ws.c +++ b/ws.c @@ -225,6 +225,21 @@ unsigned ws_check(const char *line, int len, unsigned ws_rule) return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL); } +int ws_blank_line(const char *line, int len, unsigned ws_rule) +{ + /* + * We _might_ want to treat CR differently from other + * whitespace characters when ws_rule has WS_CR_AT_EOL, but + * for now we just use this stupid definition. + */ + while (len-- > 0) { + if (!isspace(*line)) + return 0; + line++; + } + return 1; +} + /* Copy the line to the buffer while fixing whitespaces */ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count) { -- cgit v1.3 From 049540435fa5f7f583b8f5af257322b17eac7375 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 26 Jun 2008 15:37:21 -0700 Subject: diff --check: detect leftover conflict markers This teaches "diff --check" to detect and complain if the change adds lines that look like leftover conflict markers. We should be able to remove the old Perl script used in the sample pre-commit hook and modernize the script with this facility. Signed-off-by: Junio C Hamano --- diff.c | 35 +++++++++++++++++++++++++++++++++++ t/t4017-diff-retval.sh | 14 ++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f31c721168..d515b06ea3 100644 --- a/diff.c +++ b/diff.c @@ -1143,6 +1143,35 @@ struct checkdiff_t { int trailing_blanks_start; }; +static int is_conflict_marker(const char *line, unsigned long len) +{ + char firstchar; + int cnt; + + if (len < 8) + return 0; + firstchar = line[0]; + switch (firstchar) { + case '=': case '>': case '<': + break; + default: + return 0; + } + for (cnt = 1; cnt < 7; cnt++) + if (line[cnt] != firstchar) + return 0; + /* line[0] thru line[6] are same as firstchar */ + if (firstchar == '=') { + /* divider between ours and theirs? */ + if (len != 8 || line[7] != '\n') + return 0; + } else if (len < 8 || !isspace(line[7])) { + /* not divider before ours nor after theirs */ + return 0; + } + return 1; +} + static void checkdiff_consume(void *priv, char *line, unsigned long len) { struct checkdiff_t *data = priv; @@ -1159,6 +1188,12 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len) data->trailing_blanks_start = 0; else if (!data->trailing_blanks_start) data->trailing_blanks_start = data->lineno; + if (is_conflict_marker(line + 1, len - 1)) { + data->status |= 1; + fprintf(data->o->file, + "%s:%d: leftover conflict marker\n", + data->filename, data->lineno); + } bad = ws_check(line + 1, len - 1, data->ws_rule); if (!bad) return; diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh index 0d0fb87f57..d748d45dae 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -113,4 +113,18 @@ test_expect_success 'check should test not just the last line' ' ' +test_expect_success 'check detects leftover conflict markers' ' + git reset --hard && + git checkout HEAD^ && + echo binary >>b && + git commit -m "side" b && + test_must_fail git merge master && + git add b && ( + git --no-pager diff --cached --check >test.out + test $? = 2 + ) && + test "$(grep "conflict marker" test.out | wc -l)" = 3 && + git reset --hard +' + test_done -- cgit v1.3 From 861d1af36ae168353fc352126c0bf2d189c2324a Mon Sep 17 00:00:00 2001 From: Olivier Marin Date: Fri, 27 Jun 2008 02:18:48 +0200 Subject: show_stats(): fix stats width calculation Before this patch, name_width becomes negative or null for width values less than 15 and name_width values greater than 25 (default: 50). This leads to output random data. This patch checks for minimal width and name_width values. Signed-off-by: Olivier Marin Signed-off-by: Junio C Hamano --- diff.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 893942359b..66851b5647 100644 --- a/diff.c +++ b/diff.c @@ -830,12 +830,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) /* Sanity: give at least 5 columns to the graph, * but leave at least 10 columns for the name. */ - if (width < name_width + 15) { - if (name_width <= 25) - width = name_width + 15; - else - name_width = width - 15; - } + if (width < 25) + width = 25; + if (name_width < 10) + name_width = 10; + else if (width < name_width + 15) + name_width = width - 15; /* Find the longest filename and max number of changes */ reset = diff_get_color_opt(options, DIFF_RESET); -- cgit v1.3 From daec808cc61af32de789a31dd5c96001915c3f2d Mon Sep 17 00:00:00 2001 From: Brian Hetro Date: Sat, 5 Jul 2008 01:24:43 -0400 Subject: diff.c: Use 'git_config_string' to get 'diff.external' Signed-off-by: Brian Hetro Signed-off-by: Junio C Hamano --- diff.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f281c5b82a..78c4d3a35a 100644 --- a/diff.c +++ b/diff.c @@ -153,12 +153,8 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) diff_auto_refresh_index = git_config_bool(var, value); return 0; } - if (!strcmp(var, "diff.external")) { - if (!value) - return config_error_nonbool(var); - external_diff_cmd_cfg = xstrdup(value); - return 0; - } + if (!strcmp(var, "diff.external")) + return git_config_string(&external_diff_cmd_cfg, var, value); if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); -- cgit v1.3 From fd55a19eb1d49ae54008d932a65f79cd6fda45c9 Mon Sep 17 00:00:00 2001 From: Dmitry Potapov Date: Wed, 16 Jul 2008 18:54:02 +0400 Subject: Fix buffer overflow in git diff If PATH_MAX on your system is smaller than a path stored, it may cause buffer overflow and stack corruption in diff_addremove() and diff_change() functions when running git-diff Signed-off-by: Dmitry Potapov Signed-off-by: Junio C Hamano --- diff-lib.c | 8 ++++---- diff.c | 11 ++--------- diff.h | 9 ++++----- revision.c | 4 ++-- tree-diff.c | 27 ++++++++++++++++++++++----- 5 files changed, 34 insertions(+), 25 deletions(-) (limited to 'diff.c') diff --git a/diff-lib.c b/diff-lib.c index b17722d66a..e7eaff9a68 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) if (silent_on_removed) continue; diff_addremove(&revs->diffopt, '-', ce->ce_mode, - ce->sha1, ce->name, NULL); + ce->sha1, ce->name); continue; } changed = ce_match_stat(ce, &st, ce_option); @@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) newmode = ce_mode_from_stat(ce, st.st_mode); diff_change(&revs->diffopt, oldmode, newmode, ce->sha1, (changed ? null_sha1 : ce->sha1), - ce->name, NULL); + ce->name); } diffcore_std(&revs->diffopt); @@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs, const unsigned char *sha1, unsigned int mode) { diff_addremove(&revs->diffopt, prefix[0], mode, - sha1, ce->name, NULL); + sha1, ce->name); } static int get_stat_data(struct cache_entry *ce, @@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata, return 0; diff_change(&revs->diffopt, oldmode, mode, - old->sha1, sha1, old->name, NULL); + old->sha1, sha1, old->name); return 0; } diff --git a/diff.c b/diff.c index 78c4d3a35a..386de826d3 100644 --- a/diff.c +++ b/diff.c @@ -3356,9 +3356,8 @@ int diff_result_code(struct diff_options *opt, int status) void diff_addremove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path) + const char *concatpath) { - char concatpath[PATH_MAX]; struct diff_filespec *one, *two; if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode)) @@ -3380,9 +3379,6 @@ void diff_addremove(struct diff_options *options, addremove = (addremove == '+' ? '-' : addremove == '-' ? '+' : addremove); - if (!path) path = ""; - sprintf(concatpath, "%s%s", base, path); - if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) return; @@ -3403,9 +3399,8 @@ void diff_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *concatpath) { - char concatpath[PATH_MAX]; struct diff_filespec *one, *two; if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) @@ -3418,8 +3413,6 @@ void diff_change(struct diff_options *options, tmp = old_mode; old_mode = new_mode; new_mode = tmp; tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; } - if (!path) path = ""; - sprintf(concatpath, "%s%s", base, path); if (options->prefix && strncmp(concatpath, options->prefix, options->prefix_length)) diff --git a/diff.h b/diff.h index 5dc0cb595b..50fb5ddb0b 100644 --- a/diff.h +++ b/diff.h @@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path); + const char *fullpath); typedef void (*add_remove_fn_t)(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path); + const char *fullpath); typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, struct diff_options *options, void *data); @@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, - const char *path); + const char *fullpath); extern void diff_change(struct diff_options *, unsigned mode1, unsigned mode2, const unsigned char *sha1, const unsigned char *sha2, - const char *base, const char *path); + const char *fullpath); extern void diff_unmerge(struct diff_options *, const char *path, diff --git a/revision.c b/revision.c index fc66755259..8dc3ca7bf6 100644 --- a/revision.c +++ b/revision.c @@ -259,7 +259,7 @@ static int tree_difference = REV_TREE_SAME; static void file_add_remove(struct diff_options *options, int addremove, unsigned mode, const unsigned char *sha1, - const char *base, const char *path) + const char *fullpath) { int diff = REV_TREE_DIFFERENT; @@ -285,7 +285,7 @@ static void file_change(struct diff_options *options, unsigned old_mode, unsigned new_mode, const unsigned char *old_sha1, const unsigned char *new_sha1, - const char *base, const char *path) + const char *fullpath) { tree_difference = REV_TREE_DIFFERENT; DIFF_OPT_SET(options, HAS_CHANGES); diff --git a/tree-diff.c b/tree-diff.c index e1e2e6c6ce..bbb126fc46 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa return newbase; } +static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen) +{ + char *fullname = xmalloc(baselen + pathlen + 1); + memcpy(fullname, base, baselen); + memcpy(fullname + baselen, path, pathlen); + fullname[baselen + pathlen] = 0; + return fullname; +} + static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen); @@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const const char *path1, *path2; const unsigned char *sha1, *sha2; int cmp, pathlen1, pathlen2; + char *fullname; sha1 = tree_entry_extract(t1, &path1, &mode1); sha2 = tree_entry_extract(t2, &path2, &mode2); @@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { int retval; char *newbase = malloc_base(base, baselen, path1, pathlen1); - if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) + if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { + newbase[baselen + pathlen1] = 0; opt->change(opt, mode1, mode2, - sha1, sha2, base, path1); + sha1, sha2, newbase); + newbase[baselen + pathlen1] = '/'; + } retval = diff_tree_sha1(sha1, sha2, newbase, opt); free(newbase); return retval; } - opt->change(opt, mode1, mode2, sha1, sha2, base, path1); + fullname = malloc_fullname(base, baselen, path1, pathlen1); + opt->change(opt, mode1, mode2, sha1, sha2, fullname); + free(fullname); return 0; } @@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree unsigned mode; const char *path; const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); + int pathlen = tree_entry_len(path, sha1); if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { enum object_type type; - int pathlen = tree_entry_len(path, sha1); char *newbase = malloc_base(base, baselen, path, pathlen); struct tree_desc inner; void *tree; @@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree free(tree); free(newbase); } else { - opt->add_remove(opt, prefix[0], mode, sha1, base, path); + char *fullname = malloc_fullname(base, baselen, path, pathlen); + opt->add_remove(opt, prefix[0], mode, sha1, fullname); + free(fullname); } } -- cgit v1.3 From 6b2fbaaffc5ec762eae5d23b58b1dc0a88e2275e Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Tue, 29 Jul 2008 22:49:33 -0700 Subject: format-patch: Produce better output with --inline or --attach This patch makes two small changes to improve the output of --inline and --attach. The first is to write a newline preceding the boundary. This is needed because MIME defines the encapsulation boundary as including the preceding CRLF (or in this case, just LF), so we should be writing one. Without this, the last newline in the pre-diff content is consumed instead. The second change is to always write the line termination character (default: newline) even when using --inline or --attach. This is simply to improve the aesthetics of the resulting message. When using --inline an email client should render the resulting message identically to the non-inline version. And when using --attach this adds a blank line preceding the attachment in the email, which is visually attractive. Signed-off-by: Kevin Ballard Signed-off-by: Junio C Hamano --- diff.c | 3 +-- log-tree.c | 2 +- t/t4013/diff.format-patch_--attach_--stdout_initial..master | 6 ++++++ t/t4013/diff.format-patch_--attach_--stdout_initial..master^ | 4 ++++ t/t4013/diff.format-patch_--attach_--stdout_initial..side | 2 ++ ...atch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master | 6 ++++++ t/t4013/diff.format-patch_--inline_--stdout_initial..master | 6 ++++++ t/t4013/diff.format-patch_--inline_--stdout_initial..master^ | 4 ++++ t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ | 2 ++ t/t4013/diff.format-patch_--inline_--stdout_initial..side | 2 ++ 10 files changed, 34 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index a07812c5c7..cbf25473c5 100644 --- a/diff.c +++ b/diff.c @@ -3223,11 +3223,10 @@ void diff_flush(struct diff_options *options) if (output_format & DIFF_FORMAT_PATCH) { if (separator) { + putc(options->line_termination, options->file); if (options->stat_sep) { /* attach patch instead of inline */ fputs(options->stat_sep, options->file); - } else { - putc(options->line_termination, options->file); } } diff --git a/log-tree.c b/log-tree.c index 5505606ed6..bd8b9e45ab 100644 --- a/log-tree.c +++ b/log-tree.c @@ -198,7 +198,7 @@ void log_write_email_headers(struct rev_info *opt, const char *name, extra_headers = subject_buffer; snprintf(buffer, sizeof(buffer) - 1, - "--%s%s\n" + "\n--%s%s\n" "Content-Type: text/x-patch;" " name=\"%s.diff\"\n" "Content-Transfer-Encoding: 8bit\n" diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master index cf6891f748..43346b9ba4 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit @@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" Content-Transfer-Encoding: 8bit @@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ index fe0258720c..d7490a9fd7 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit @@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side index 9ff828ee9d..38f790290a 100644 --- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side @@ -17,6 +17,8 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master index a8093be7ca..fca5cce373 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit @@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" Content-Transfer-Encoding: 8bit @@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master index aa110c0e7f..6d6fac3908 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit @@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" Content-Transfer-Encoding: 8bit @@ -122,6 +126,8 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ index 95e9ea4c59..18a1110def 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit @@ -75,6 +77,8 @@ Content-Transfer-Encoding: 8bit file1 | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 file1 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ index b8e81e1552..4f258b8858 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ @@ -19,6 +19,8 @@ This is the second commit. file2 | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) delete mode 100644 file2 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff" Content-Transfer-Encoding: 8bit diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side index 86ae923d71..e86dce69a3 100644 --- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side +++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side @@ -17,6 +17,8 @@ Content-Transfer-Encoding: 8bit file3 | 4 ++++ 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 file3 + + --------------g-i-t--v-e-r-s-i-o-n Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff" Content-Transfer-Encoding: 8bit -- cgit v1.3 From ad8c1d92600da963692d57c213979e638c357f1a Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 31 Jul 2008 09:21:48 +0200 Subject: diff: add ruby funcname pattern Provide a regexp that catches class, module and method definitions in Ruby scripts, since the built-in default only finds classes. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- diff.c | 1 + 1 file changed, 1 insertion(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index cbf25473c5..c253015c5d 100644 --- a/diff.c +++ b/diff.c @@ -1381,6 +1381,7 @@ static struct builtin_funcname_pattern { "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" "[ ]*([^;]*\\)$" }, { "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" }, + { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; static const char *diff_funcname_pattern(struct diff_filespec *one) -- cgit v1.3 From b50005b79f6c77f9846c3f34ba319675fe489b72 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Fri, 1 Aug 2008 17:00:15 -0400 Subject: Teach "git diff -p" Pascal/Delphi funcname pattern Finds classes, records, functions, procedures, and sections. Most lines need to start at the first column, or else there's no way to differentiate a procedure's definition from its declaration. Signed-off-by: Avery Pennarun Signed-off-by: Junio C Hamano --- diff.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index c253015c5d..75a8b16642 100644 --- a/diff.c +++ b/diff.c @@ -1380,6 +1380,12 @@ static struct builtin_funcname_pattern { "^[ ]*\\(\\([ ]*" "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" "[ ]*([^;]*\\)$" }, + { "pascal", "^\\(\\(procedure\\|function\\|constructor\\|" + "destructor\\|interface\\|implementation\\|" + "initialization\\|finalization\\)[ \t]*.*\\)$" + "\\|" + "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" + }, { "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -- cgit v1.3 From 807d86945336f676c9f650a6cbae9baa3191aaec Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sat, 2 Aug 2008 23:56:44 +0200 Subject: diff: chapter and part in funcname for tex This patch enhances the tex funcname by adding support for chapter and part sectioning commands. It also matches the starred version of the sectioning commands. Signed-off-by: Giuseppe Bilotta Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 75a8b16642..bd04fdfd28 100644 --- a/diff.c +++ b/diff.c @@ -1386,7 +1386,7 @@ static struct builtin_funcname_pattern { "\\|" "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" }, - { "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" }, + { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -- cgit v1.3 From 2b6ca6df2dbe9c23d0adfc1f59678a2d85c560b2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 5 Aug 2008 11:27:30 -0700 Subject: diff.renamelimit is a basic diff configuration The configuration was added as a core option in 3299c6f (diff: make default rename detection limit configurable., 2005-11-15), but 9ce392f (Move diff.renamelimit out of default configuration., 2005-11-21) separated diff-related stuff out of the core. Up to that point it was Ok. When we separated the Porcelain options out of the git_diff_config in 83ad63c (diff: do not use configuration magic at the core-level, 2006-07-08), we should have been more careful. This mistake made diff-tree plumbing and git-show Porcelain to notice different set of renames when the user explicitly asked for rename detection. Signed-off-by: Junio C Hamano --- diff.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 386de826d3..342733ba73 100644 --- a/diff.c +++ b/diff.c @@ -131,10 +131,6 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v */ int git_diff_ui_config(const char *var, const char *value, void *cb) { - if (!strcmp(var, "diff.renamelimit")) { - diff_rename_limit_default = git_config_int(var, value); - return 0; - } if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { diff_use_color_default = git_config_colorbool(var, value, -1); return 0; @@ -167,6 +163,11 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) int git_diff_basic_config(const char *var, const char *value, void *cb) { + if (!strcmp(var, "diff.renamelimit")) { + diff_rename_limit_default = git_config_int(var, value); + return 0; + } + if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); if (!value) -- cgit v1.3 From 04c6e9e9ca34226db095bbaa1218030f99f0b7c6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 11 Aug 2008 22:15:28 -0700 Subject: diff --check: do not unconditionally complain about trailing empty lines Recently "git diff --check" learned to detect new trailing blank lines just like "git apply --whitespace" does. However this check should not trigger unconditionally. This patch makes it honor the whitespace settings from core.whitespace and gitattributes. Signed-off-by: Junio C Hamano --- diff.c | 3 ++- t/t4019-diff-wserror.sh | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 8746c60b9c..6954f992c2 100644 --- a/diff.c +++ b/diff.c @@ -1631,7 +1631,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, ecb.priv = &data; xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); - if (data.trailing_blanks_start) { + if ((data.ws_rule & WS_TRAILING_SPACE) && + data.trailing_blanks_start) { fprintf(o->file, "%s:%d: ends with blank lines.\n", data.filename, data.trailing_blanks_start); data.status = 1; /* report errors */ diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh index 0d9cbb6261..7eae1f4500 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -13,7 +13,8 @@ test_expect_success setup ' echo " HT and SP indent" >>F && echo "With trailing SP " >>F && echo "Carriage ReturnQ" | tr Q "\015" >>F && - echo "No problem" >>F + echo "No problem" >>F && + echo >>F ' @@ -160,4 +161,21 @@ test_expect_success 'with cr-at-eol (attribute)' ' ' +test_expect_success 'trailing empty lines (1)' ' + + rm -f .gitattributes && + test_must_fail git diff --check >output && + grep "ends with blank lines." output && + grep "trailing whitespace" output + +' + +test_expect_success 'trailing empty lines (2)' ' + + echo "F -whitespace" >.gitattributes && + git diff --check >output && + ! test -s output + +' + test_done -- cgit v1.3 From 23b5beb28fdadbb1d80ebf686a35385609f7a180 Mon Sep 17 00:00:00 2001 From: Gustaf Hendeby Date: Tue, 12 Aug 2008 16:24:26 +0200 Subject: Teach git diff about BibTeX head hunk patterns All BibTeX entries starts with an @ followed by an entry type. Since there are many entry types and own can be defined, the pattern matches legal entry type names instead of just the default types (which would be a long list). The pattern also matches strings and comments since they will also be useful to position oneself in a bib-file. Signed-off-by: Gustaf Hendeby Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 2 ++ diff.c | 1 + 2 files changed, 3 insertions(+) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index c61a58d8f2..db16b0ca5b 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -310,6 +310,8 @@ configuration file (you still need to enable this with the attribute mechanism, via `.gitattributes`). The following built in patterns are available: +- `bibtex` suitable for files with BibTeX coded references. + - `java` suitable for source code in the Java lanugage. - `pascal` suitable for source code in the Pascal/Delphi language. diff --git a/diff.c b/diff.c index 6954f992c2..bf5d5f15a3 100644 --- a/diff.c +++ b/diff.c @@ -1387,6 +1387,7 @@ static struct builtin_funcname_pattern { "\\|" "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" }, + { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -- cgit v1.3 From c99db9d292c5f63c83ae2b441a67121d76553413 Mon Sep 17 00:00:00 2001 From: Brian Downing Date: Thu, 14 Aug 2008 00:36:50 -0500 Subject: Make xdi_diff_outf interface for running xdiff_outf diffs To prepare for the need to initialize and release resources for an xdi_diff with the xdiff_outf output function, make a new function to wrap this usage. Old: ecb.outf = xdiff_outf; ecb.priv = &state; ... xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb); New: xdi_diff_outf(file_p, file_o, &state.xm, &xpp, &xecfg, &ecb); Signed-off-by: Brian Downing Signed-off-by: Junio C Hamano --- builtin-blame.c | 4 +--- combine-diff.c | 5 ++--- diff.c | 20 +++++--------------- xdiff-interface.c | 13 ++++++++++++- xdiff-interface.h | 4 +++- 5 files changed, 23 insertions(+), 23 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index 4ea343189f..8cca3b16d2 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -528,15 +528,13 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, xpp.flags = xdl_opts; memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = context; - ecb.outf = xdiff_outf; - ecb.priv = &state; memset(&state, 0, sizeof(state)); state.xm.consume = process_u_diff; state.ret = xmalloc(sizeof(struct patch)); state.ret->chunks = NULL; state.ret->num = 0; - xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb); + xdi_diff_outf(file_p, file_o, &state.xm, &xpp, &xecfg, &ecb); if (state.ret->num) { struct chunk *chunk; diff --git a/combine-diff.c b/combine-diff.c index 9f80a1c5e3..72dd6d2234 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -217,8 +217,6 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, parent_file.size = sz; xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); - ecb.outf = xdiff_outf; - ecb.priv = &state; memset(&state, 0, sizeof(state)); state.xm.consume = consume_line; state.nmask = nmask; @@ -227,7 +225,8 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, state.num_parent = num_parent; state.n = n; - xdi_diff(&parent_file, result_file, &xpp, &xecfg, &ecb); + xdi_diff_outf(&parent_file, result_file, + &state.xm, &xpp, &xecfg, &ecb); free(parent_file.ptr); /* Assign line numbers for this parent. diff --git a/diff.c b/diff.c index bf5d5f15a3..913a92f3e9 100644 --- a/diff.c +++ b/diff.c @@ -459,10 +459,8 @@ static void diff_words_show(struct diff_words_data *diff_words) xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc; - ecb.outf = xdiff_outf; - ecb.priv = diff_words; diff_words->xm.consume = fn_out_diff_words_aux; - xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); + xdi_diff_outf(&minus, &plus, &diff_words->xm, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); @@ -1521,15 +1519,13 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); else if (!prefixcmp(diffopts, "-u")) xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); - ecb.outf = xdiff_outf; - ecb.priv = &ecbdata; ecbdata.xm.consume = fn_out_consume; if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) { ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); ecbdata.diff_words->file = o->file; } - xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, &ecbdata.xm, &xpp, &xecfg, &ecb); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); } @@ -1580,9 +1576,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; - ecb.outf = xdiff_outf; - ecb.priv = diffstat; - xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, &diffstat->xm, &xpp, &xecfg, &ecb); } free_and_return: @@ -1628,9 +1622,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL; - ecb.outf = xdiff_outf; - ecb.priv = &data; - xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, &data.xm, &xpp, &xecfg, &ecb); if ((data.ws_rule & WS_TRAILING_SPACE) && data.trailing_blanks_start) { @@ -3128,9 +3120,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = 3; xecfg.flags = XDL_EMIT_FUNCNAMES; - ecb.outf = xdiff_outf; - ecb.priv = &data; - xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, &data.xm, &xpp, &xecfg, &ecb); } SHA1_Final(sha1, &ctx); diff --git a/xdiff-interface.c b/xdiff-interface.c index 61dc5c5470..828b4966a9 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -61,7 +61,7 @@ static void consume_one(void *priv_, char *s, unsigned long size) } } -int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) +static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf) { struct xdiff_emit_state *priv = priv_; int i; @@ -141,6 +141,17 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co return xdl_diff(&a, &b, xpp, xecfg, xecb); } +int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2, + struct xdiff_emit_state *state, xpparam_t const *xpp, + xdemitconf_t const *xecfg, xdemitcb_t *xecb) +{ + int ret; + xecb->outf = xdiff_outf; + xecb->priv = state; + ret = xdi_diff(mf1, mf2, xpp, xecfg, xecb); + return ret; +} + int read_mmfile(mmfile_t *ptr, const char *filename) { struct stat st; diff --git a/xdiff-interface.h b/xdiff-interface.h index f7f791d96b..6f3b361a84 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -14,7 +14,9 @@ struct xdiff_emit_state { }; int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); -int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf); +int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2, + struct xdiff_emit_state *state, xpparam_t const *xpp, + xdemitconf_t const *xecfg, xdemitcb_t *xecb); int parse_hunk_header(char *line, int len, int *ob, int *on, int *nb, int *nn); -- cgit v1.3 From 8a3f524bf2ac534b313a7d8e70cc164cef744949 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 13 Aug 2008 23:18:22 -0700 Subject: xdiff-interface: hide the whole "xdiff_emit_state" business from the caller This further enhances xdi_diff_outf() interface so that it takes two common parameters: the callback function that processes one line at a time, and a pointer to its application specific callback data structure. xdi_diff_outf() creates its own "xdiff_emit_state" structure and stashes these two away inside it, which is used by the lowest level output function in the xdiff_outf() callchain, consume_one(), to call back to the application layer. With this restructuring, we lift the requirement that the caller supplied callback data structure embeds xdiff_emit_state structure as its first member. Signed-off-by: Junio C Hamano --- builtin-blame.c | 4 +--- combine-diff.c | 7 ++----- diff.c | 27 ++++++++++----------------- xdiff-interface.c | 23 ++++++++++++++++++----- xdiff-interface.h | 11 ++--------- 5 files changed, 33 insertions(+), 39 deletions(-) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index 8cca3b16d2..e4d12de8a9 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -465,7 +465,6 @@ struct patch { }; struct blame_diff_state { - struct xdiff_emit_state xm; struct patch *ret; unsigned hunk_post_context; unsigned hunk_in_pre_context : 1; @@ -529,12 +528,11 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = context; memset(&state, 0, sizeof(state)); - state.xm.consume = process_u_diff; state.ret = xmalloc(sizeof(struct patch)); state.ret->chunks = NULL; state.ret->num = 0; - xdi_diff_outf(file_p, file_o, &state.xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb); if (state.ret->num) { struct chunk *chunk; diff --git a/combine-diff.c b/combine-diff.c index 72dd6d2234..31ec0c5165 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -143,8 +143,6 @@ static void append_lost(struct sline *sline, int n, const char *line, int len) } struct combine_diff_state { - struct xdiff_emit_state xm; - unsigned int lno; int ob, on, nb, nn; unsigned long nmask; @@ -218,15 +216,14 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); memset(&state, 0, sizeof(state)); - state.xm.consume = consume_line; state.nmask = nmask; state.sline = sline; state.lno = 1; state.num_parent = num_parent; state.n = n; - xdi_diff_outf(&parent_file, result_file, - &state.xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(&parent_file, result_file, consume_line, &state, + &xpp, &xecfg, &ecb); free(parent_file.ptr); /* Assign line numbers for this parent. diff --git a/diff.c b/diff.c index 913a92f3e9..a6c143251c 100644 --- a/diff.c +++ b/diff.c @@ -369,7 +369,6 @@ static void diff_words_append(char *line, unsigned long len, } struct diff_words_data { - struct xdiff_emit_state xm; struct diff_words_buffer minus, plus; FILE *file; }; @@ -459,9 +458,8 @@ static void diff_words_show(struct diff_words_data *diff_words) xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc; - diff_words->xm.consume = fn_out_diff_words_aux; - xdi_diff_outf(&minus, &plus, &diff_words->xm, &xpp, &xecfg, &ecb); - + xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, + &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); diff_words->minus.text.size = diff_words->plus.text.size = 0; @@ -475,7 +473,6 @@ static void diff_words_show(struct diff_words_data *diff_words) typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len); struct emit_callback { - struct xdiff_emit_state xm; int nparents, color_diff; unsigned ws_rule; sane_truncate_fn truncate; @@ -706,8 +703,6 @@ static char *pprint_rename(const char *a, const char *b) } struct diffstat_t { - struct xdiff_emit_state xm; - int nr; int alloc; struct diffstat_file { @@ -1129,7 +1124,6 @@ static void free_diffstat_info(struct diffstat_t *diffstat) } struct checkdiff_t { - struct xdiff_emit_state xm; const char *filename; int lineno; struct diff_options *o; @@ -1519,13 +1513,13 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); else if (!prefixcmp(diffopts, "-u")) xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); - ecbdata.xm.consume = fn_out_consume; if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) { ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); ecbdata.diff_words->file = o->file; } - xdi_diff_outf(&mf1, &mf2, &ecbdata.xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, + &xpp, &xecfg, &ecb); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); } @@ -1576,7 +1570,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; - xdi_diff_outf(&mf1, &mf2, &diffstat->xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, + &xpp, &xecfg, &ecb); } free_and_return: @@ -1597,7 +1592,6 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, return; memset(&data, 0, sizeof(data)); - data.xm.consume = checkdiff_consume; data.filename = name_b ? name_b : name_a; data.lineno = 0; data.o = o; @@ -1622,7 +1616,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL; - xdi_diff_outf(&mf1, &mf2, &data.xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, + &xpp, &xecfg, &ecb); if ((data.ws_rule & WS_TRAILING_SPACE) && data.trailing_blanks_start) { @@ -3010,7 +3005,6 @@ static void diff_summary(FILE *file, struct diff_filepair *p) } struct patch_id_t { - struct xdiff_emit_state xm; SHA_CTX *ctx; int patchlen; }; @@ -3055,7 +3049,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) SHA1_Init(&ctx); memset(&data, 0, sizeof(struct patch_id_t)); data.ctx = &ctx; - data.xm.consume = patch_id_consume; for (i = 0; i < q->nr; i++) { xpparam_t xpp; @@ -3120,7 +3113,8 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = 3; xecfg.flags = XDL_EMIT_FUNCNAMES; - xdi_diff_outf(&mf1, &mf2, &data.xm, &xpp, &xecfg, &ecb); + xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, + &xpp, &xecfg, &ecb); } SHA1_Final(sha1, &ctx); @@ -3197,7 +3191,6 @@ void diff_flush(struct diff_options *options) struct diffstat_t diffstat; memset(&diffstat, 0, sizeof(struct diffstat_t)); - diffstat.xm.consume = diffstat_consume; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; if (check_pair_status(p)) diff --git a/xdiff-interface.c b/xdiff-interface.c index bf98866c4f..944ad9887f 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -1,5 +1,12 @@ #include "cache.h" #include "xdiff-interface.h" +#include "strbuf.h" + +struct xdiff_emit_state { + xdiff_emit_consume_fn consume; + void *consume_callback_data; + struct strbuf remainder; +}; static int parse_num(char **cp_p, int *num_p) { @@ -55,7 +62,7 @@ static void consume_one(void *priv_, char *s, unsigned long size) unsigned long this_size; ep = memchr(s, '\n', size); this_size = (ep == NULL) ? size : (ep - s + 1); - priv->consume(priv, s, this_size); + priv->consume(priv->consume_callback_data, s, this_size); size -= this_size; s += this_size; } @@ -128,15 +135,21 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co } int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2, - struct xdiff_emit_state *state, xpparam_t const *xpp, + xdiff_emit_consume_fn fn, void *consume_callback_data, + xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb) { int ret; + struct xdiff_emit_state state; + + memset(&state, 0, sizeof(state)); + state.consume = fn; + state.consume_callback_data = consume_callback_data; xecb->outf = xdiff_outf; - xecb->priv = state; - strbuf_init(&state->remainder, 0); + xecb->priv = &state; + strbuf_init(&state.remainder, 0); ret = xdi_diff(mf1, mf2, xpp, xecfg, xecb); - strbuf_release(&state->remainder); + strbuf_release(&state.remainder); return ret; } diff --git a/xdiff-interface.h b/xdiff-interface.h index f6a1ec2220..558492ba38 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -2,20 +2,13 @@ #define XDIFF_INTERFACE_H #include "xdiff/xdiff.h" -#include "strbuf.h" - -struct xdiff_emit_state; typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long); -struct xdiff_emit_state { - xdiff_emit_consume_fn consume; - struct strbuf remainder; -}; - int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2, - struct xdiff_emit_state *state, xpparam_t const *xpp, + xdiff_emit_consume_fn fn, void *consume_callback_data, + xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *xecb); int parse_hunk_header(char *line, int len, int *ob, int *on, -- cgit v1.3 From a624eaa7820f4f9814e41e911c665a0aba2fce34 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 15 Aug 2008 13:39:26 +0200 Subject: add boolean diff.suppress-blank-empty config option GNU diff's --suppress-blank-empty option makes it so that diff no longer outputs trailing white space unless the input data has it. With this option, empty context lines are now empty also in diff -u output. Before, they would have a single trailing space. * diff.c (diff_suppress_blank_empty): New global. (git_diff_basic_config): Set it. (fn_out_consume): Honor it. * t/t4029-diff-trailing-space.sh: New file. * Documentation/config.txt: Document it. Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- Documentation/config.txt | 4 ++++ diff.c | 13 +++++++++++++ t/t4029-diff-trailing-space.sh | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100755 t/t4029-diff-trailing-space.sh (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 676c39bb84..9020675866 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -567,6 +567,10 @@ diff.autorefreshindex:: affects only 'git-diff' Porcelain, and not lower level 'diff' commands, such as 'git-diff-files'. +diff.suppress-blank-empty:: + A boolean to inhibit the standard behavior of printing a space + before each empty output line. Defaults to false. + diff.external:: If this config variable is set, diff generation is not performed using the internal diff machinery, but using the diff --git a/diff.c b/diff.c index bf5d5f15a3..fe43407b78 100644 --- a/diff.c +++ b/diff.c @@ -20,6 +20,7 @@ static int diff_detect_rename_default; static int diff_rename_limit_default = 200; +static int diff_suppress_blank_empty; int diff_use_color_default = -1; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; @@ -176,6 +177,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } + /* like GNU diff's --suppress-blank-empty option */ + if (!strcmp(var, "diff.suppress-blank-empty")) { + diff_suppress_blank_empty = git_config_bool(var, value); + return 0; + } + if (!prefixcmp(var, "diff.")) { const char *ep = strrchr(var, '.'); if (ep != var + 4) { @@ -580,6 +587,12 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; } + if (diff_suppress_blank_empty + && len == 2 && line[0] == ' ' && line[1] == '\n') { + line[0] = '\n'; + len = 1; + } + /* This is not really necessary for now because * this codepath only deals with two-way diffs. */ diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh new file mode 100755 index 0000000000..4ca65e0332 --- /dev/null +++ b/t/t4029-diff-trailing-space.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Copyright (c) Jim Meyering +# +test_description='diff honors config option, diff.suppress-blank-empty' + +. ./test-lib.sh + +cat <<\EOF > exp || +diff --git a/f b/f +index 5f6a263..8cb8bae 100644 +--- a/f ++++ b/f +@@ -1,2 +1,2 @@ + +-x ++y +EOF +exit 1 + +test_expect_success \ + "$test_description" \ + 'printf "\nx\n" > f && + git add f && + git commit -q -m. f && + printf "\ny\n" > f && + git config --bool diff.suppress-blank-empty true && + git diff f > actual && + test_cmp exp actual && + perl -i.bak -p -e "s/^\$/ /" exp && + git config --bool diff.suppress-blank-empty false && + git diff f > actual && + test_cmp exp actual && + git config --bool --unset diff.suppress-blank-empty && + git diff f > actual && + test_cmp exp actual + ' + +test_done -- cgit v1.3 From c35539eb10b0ab2a180e523f03ff65dc061bd47e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 20 Aug 2008 11:47:55 -0700 Subject: diff --check: do not get confused by new blank lines in the middle The code remembered that the last diff output it saw was an empty line, and tried to reset that state whenever it sees a context line, a non-blank new line, or a new hunk. However, this codepath asks the underlying diff engine to feed diff without any context, and the "just saw an empty line" state was not reset if you added a new blank line in the last hunk of your patch, even if it is not the last line of the file. Signed-off-by: Junio C Hamano --- diff.c | 1 + t/t4015-diff-whitespace.sh | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index bf5d5f15a3..f70e6b4912 100644 --- a/diff.c +++ b/diff.c @@ -1627,6 +1627,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, xdemitcb_t ecb; memset(&xecfg, 0, sizeof(xecfg)); + xecfg.ctxlen = 1; /* at least one context line */ xpp.flags = XDF_NEED_MINIMAL; ecb.outf = xdiff_outf; ecb.priv = &data; diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index a27fccc8dc..ec98509fd2 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -341,4 +341,15 @@ test_expect_success 'checkdiff detects trailing blank lines' ' git diff --check | grep "ends with blank" ' +test_expect_success 'checkdiff allows new blank lines' ' + git checkout x && + mv x y && + ( + echo "/* This is new */" && + echo "" && + cat y + ) >x && + git diff --check +' + test_done -- cgit v1.3 From 7c17205b64a0e668d8a6e59109043bd4f2af3a0c Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Wed, 20 Aug 2008 19:57:07 +0400 Subject: Teach "git diff -p" Python funcname patterns Find classes, functions, and methods definitions. Signed-off-by: Kirill Smelkov Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 2 ++ diff.c | 1 + 2 files changed, 3 insertions(+) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index db16b0ca5b..9279df5349 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -316,6 +316,8 @@ patterns are available: - `pascal` suitable for source code in the Pascal/Delphi language. +- `python` suitable for source code in the Python language. + - `ruby` suitable for source code in the Ruby language. - `tex` suitable for source code for LaTeX documents. diff --git a/diff.c b/diff.c index 5923fe281b..2215416441 100644 --- a/diff.c +++ b/diff.c @@ -1394,6 +1394,7 @@ static struct builtin_funcname_pattern { }, { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, + { "python", "^\\s*\\(\\(class\\|def\\)\\s.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -- cgit v1.3 From 1a1fcf4abeb2ed4ef6075970788711cf62405158 Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Wed, 20 Aug 2008 19:49:15 +0200 Subject: Teach "git diff -p" HTML funcname patterns Find lines with

..

tags. [jc: while at it, reordered entries to sort alphabetically.] Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 2 ++ diff.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 9279df5349..5495d695c6 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -322,6 +322,8 @@ patterns are available: - `tex` suitable for source code for LaTeX documents. +- `html` suitable for HTML/XHTML documents. + Performing a three-way merge ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/diff.c b/diff.c index 2215416441..18fa7a712c 100644 --- a/diff.c +++ b/diff.c @@ -1381,6 +1381,8 @@ static struct builtin_funcname_pattern { const char *name; const char *pattern; } builtin_funcname_pattern[] = { + { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, + { "html", "^\\s*\\(<[Hh][1-6]\\s.*>.*\\)$" }, { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" @@ -1392,10 +1394,9 @@ static struct builtin_funcname_pattern { "\\|" "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" }, - { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, - { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, { "python", "^\\s*\\(\\(class\\|def\\)\\s.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, + { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, }; static const char *diff_funcname_pattern(struct diff_filespec *one) -- cgit v1.3 From 441bca0bbc6d80a78ce332ef4fa6225155dfbce6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 28 Aug 2008 16:19:08 -0700 Subject: Fix '--dirstat' with cross-directory renaming The dirstat code depends on the fact that we always generate diffs with the names sorted, since it then just does a single-pass walk-over of the sorted list of names and how many changes there were. The sorting means that all files are nicely grouped by directory. That all works fine. Except when we have rename detection, and suddenly the nicely sorted list of pathnames isn't all that sorted at all. And now the single-pass dirstat walk gets all confused, and you can get results like this: [torvalds@nehalem linux]$ git diff --dirstat=2 -M v2.6.27-rc4..v2.6.27-rc5 3.0% arch/powerpc/configs/ 6.8% arch/arm/configs/ 2.7% arch/powerpc/configs/ 4.2% arch/arm/configs/ 5.6% arch/powerpc/configs/ 8.4% arch/arm/configs/ 5.5% arch/powerpc/configs/ 23.3% arch/arm/configs/ 8.6% arch/powerpc/configs/ 4.0% arch/ 4.4% drivers/usb/musb/ 4.0% drivers/watchdog/ 7.6% drivers/ 3.5% fs/ The trivial fix is to add a sorting pass, fixing it to: [torvalds@nehalem linux]$ git diff --dirstat=2 -M v2.6.27-rc4..v2.6.27-rc5 43.0% arch/arm/configs/ 25.5% arch/powerpc/configs/ 5.3% arch/ 4.4% drivers/usb/musb/ 4.0% drivers/watchdog/ 7.6% drivers/ 3.5% fs/ Spot the difference. In case anybody wonders: it's because of a ton of renames from {include/asm-blackfin => arch/blackfin/include/asm} that just totally messed up the file ordering in between arch/arm and arch/powerpc. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f70e6b4912..7b4300a74a 100644 --- a/diff.c +++ b/diff.c @@ -1054,6 +1054,13 @@ static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long ch return this_dir; } +static int dirstat_compare(const void *_a, const void *_b) +{ + const struct dirstat_file *a = _a; + const struct dirstat_file *b = _b; + return strcmp(a->name, b->name); +} + static void show_dirstat(struct diff_options *options) { int i; @@ -1113,6 +1120,7 @@ static void show_dirstat(struct diff_options *options) return; /* Show all directories with more than x% of the changes */ + qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare); gather_dirstat(options->file, &dir, changed, "", 0); } -- cgit v1.3 From 392809702016cde59d50a7b07e8c27f6d0ec3c3f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 27 Aug 2008 19:48:01 -0700 Subject: diff: Help "less" hide ^M from the output When the tracked contents have CRLF line endings, colored diff output shows "^M" at the end of output lines, which is distracting, even though the pager we use by default ("less") knows to hide them. The problem is that "less" hides a carriage-return only at the end of the line, immediately before a line feed. The colored diff output does not take this into account, and emits four element sequence for each line: - force this color; - the line up to but not including the terminating line feed; - reset color - line feed. By including the carriage return at the end of the line in the second item, we are breaking the smart our pager has in order not to show "^M". This can be fixed by changing the sequence to: - force this color; - the line up to but not including the terminating end-of-line; - reset color - end-of-line. where end-of-line is either a single linefeed or a CRLF pair. When the output is not colored, "force this color" and "reset color" sequences are both empty, so we won't have this problem with or without this patch. Signed-off-by: Junio C Hamano --- combine-diff.c | 16 ++++++++++++++-- diff.c | 9 ++++++++- t/t4019-diff-wserror.sh | 12 ++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/combine-diff.c b/combine-diff.c index 4dfc330867..aa9d79ea0b 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -500,6 +500,18 @@ static int hunk_comment_line(const char *bol) return (isalpha(ch) || ch == '_' || ch == '$'); } +static void show_line_to_eol(const char *line, int len, const char *reset) +{ + int saw_cr_at_eol = 0; + if (len < 0) + len = strlen(line); + saw_cr_at_eol = (len && line[len-1] == '\r'); + + printf("%.*s%s%s\n", len - saw_cr_at_eol, line, + reset, + saw_cr_at_eol ? "\r" : ""); +} + static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, int use_color) { @@ -593,7 +605,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, else putchar(' '); } - printf("%s%s\n", ll->line, c_reset); + show_line_to_eol(ll->line, -1, c_reset); ll = ll->next; } if (cnt < lno) @@ -617,7 +629,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, putchar(' '); p_mask <<= 1; } - printf("%.*s%s\n", sl->len, sl->bol, c_reset); + show_line_to_eol(sl->bol, sl->len, c_reset); } } } diff --git a/diff.c b/diff.c index 7b4300a74a..6d56c69810 100644 --- a/diff.c +++ b/diff.c @@ -511,13 +511,20 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len) { - int has_trailing_newline = (len > 0 && line[len-1] == '\n'); + int has_trailing_newline, has_trailing_carriage_return; + + has_trailing_newline = (len > 0 && line[len-1] == '\n'); if (has_trailing_newline) len--; + has_trailing_carriage_return = (len > 0 && line[len-1] == '\r'); + if (has_trailing_carriage_return) + len--; fputs(set, file); fwrite(line, len, 1, file); fputs(reset, file); + if (has_trailing_carriage_return) + fputc('\r', file); if (has_trailing_newline) fputc('\n', file); } diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh index 7eae1f4500..84a1fe3115 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -178,4 +178,16 @@ test_expect_success 'trailing empty lines (2)' ' ' +test_expect_success 'do not color trailing cr in context' ' + git config --unset core.whitespace + rm -f .gitattributes && + echo AAAQ | tr Q "\015" >G && + git add G && + echo BBBQ | tr Q "\015" >>G + git diff --color G | tr "\015" Q >output && + grep "BBB.*${blue_grep}Q" output && + grep "AAA.*\[mQ" output + +' + test_done -- cgit v1.3 From a5a818ee4877e4458e8e6741a03ac3b19941d58a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 18 Aug 2008 20:08:09 -0700 Subject: diff: vary default prefix depending on what are compared With a new configuration "diff.mnemonicprefix", "git diff" shows the differences between various combinations of preimage and postimage trees with prefixes different from the standard "a/" and "b/". Hopefully this will make the distinction stand out for some people. "git diff" compares the (i)ndex and the (w)ork tree; "git diff HEAD" compares a (c)ommit and the (w)ork tree; "git diff --cached" compares a (c)ommit and the (i)ndex; "git-diff HEAD:file1 file2" compares an (o)bject and a (w)ork tree entity; "git diff --no-index a b" compares two non-git things (1) and (2). Because these mnemonics now have meanings, they are swapped when reverse diff is in effect and this feature is enabled. Signed-off-by: Junio C Hamano --- Documentation/config.txt | 16 ++++++++++++++++ builtin-diff.c | 2 ++ combine-diff.c | 8 ++++++-- diff-lib.c | 3 +++ diff-no-index.c | 1 + diff.c | 46 ++++++++++++++++++++++++++++++++++++++++------ diff.h | 2 ++ 7 files changed, 70 insertions(+), 8 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 81f981509a..74af36de5c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -581,6 +581,22 @@ diff.external:: you want to use an external diff program only on a subset of your files, you might want to use linkgit:gitattributes[5] instead. +diff.mnemonicprefix:: + If set, 'git-diff' uses a prefix pair that is different from the + standard "a/" and "b/" depending on what is being compared. When + this configuration is in effect, reverse diff output also swaps + the order of the prefixes: +'git-diff';; + compares the (i)ndex and the (w)ork tree; +'git-diff HEAD';; + compares a (c)ommit and the (w)ork tree; +'git diff --cached';; + compares a (c)ommit and the (i)ndex; +'git-diff HEAD:file1 file2';; + compares an (o)bject and a (w)ork tree entity; +'git diff --no-index a b';; + compares two non-git things (1) and (2). + diff.renameLimit:: The number of files to consider when performing the copy/rename detection; equivalent to the 'git-diff' option '-l'. diff --git a/builtin-diff.c b/builtin-diff.c index 7ffea97505..266337b832 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -74,6 +74,8 @@ static int builtin_diff_b_f(struct rev_info *revs, if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) die("'%s': not a regular file or symlink", path); + diff_set_mnemonic_prefix(&revs->diffopt, "o/", "w/"); + if (blob[0].mode == S_IFINVALID) blob[0].mode = canon_mode(st.st_mode); diff --git a/combine-diff.c b/combine-diff.c index 4dfc330867..19bd60e346 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -675,9 +675,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int i, show_hunks; int working_tree_file = is_null_sha1(elem->sha1); int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; + const char *a_prefix, *b_prefix; mmfile_t result_file; context = opt->context; + a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; + b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; + /* Read the result of merge first */ if (!working_tree_file) result = grab_blob(elem->sha1, &result_size); @@ -853,13 +857,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, dump_quoted_path("--- ", "", "/dev/null", c_meta, c_reset); else - dump_quoted_path("--- ", opt->a_prefix, elem->path, + dump_quoted_path("--- ", a_prefix, elem->path, c_meta, c_reset); if (deleted) dump_quoted_path("+++ ", "", "/dev/null", c_meta, c_reset); else - dump_quoted_path("+++ ", opt->b_prefix, elem->path, + dump_quoted_path("+++ ", b_prefix, elem->path, c_meta, c_reset); dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF)); diff --git a/diff-lib.c b/diff-lib.c index e7eaff9a68..ae96c64ca2 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -63,6 +63,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option) ? CE_MATCH_RACY_IS_DIRTY : 0); char symcache[PATH_MAX]; + diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/"); + if (diff_unmerged_stage < 0) diff_unmerged_stage = 2; entries = active_nr; @@ -469,6 +471,7 @@ int run_diff_index(struct rev_info *revs, int cached) if (unpack_trees(1, &t, &opts)) exit(128); + diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/"); diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); return 0; diff --git a/diff-no-index.c b/diff-no-index.c index 7d68b7f1be..b60d3455da 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -252,6 +252,7 @@ void diff_no_index(struct rev_info *revs, if (queue_diff(&revs->diffopt, revs->diffopt.paths[0], revs->diffopt.paths[1])) exit(1); + diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/"); diffcore_std(&revs->diffopt); diff_flush(&revs->diffopt); diff --git a/diff.c b/diff.c index 7b4300a74a..c1804efed9 100644 --- a/diff.c +++ b/diff.c @@ -23,6 +23,7 @@ static int diff_rename_limit_default = 200; int diff_use_color_default = -1; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; +static int diff_mnemonic_prefix; static char diff_colors[][COLOR_MAXLEN] = { "\033[m", /* reset */ @@ -149,6 +150,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) diff_auto_refresh_index = git_config_bool(var, value); return 0; } + if (!strcmp(var, "diff.mnemonicprefix")) { + diff_mnemonic_prefix = git_config_bool(var, value); + return 0; + } if (!strcmp(var, "diff.external")) return git_config_string(&external_diff_cmd_cfg, var, value); if (!prefixcmp(var, "diff.")) { @@ -305,6 +310,15 @@ static void emit_rewrite_diff(const char *name_a, const char *new = diff_get_color(color_diff, DIFF_FILE_NEW); const char *reset = diff_get_color(color_diff, DIFF_RESET); static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT; + const char *a_prefix, *b_prefix; + + if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) { + a_prefix = o->b_prefix; + b_prefix = o->a_prefix; + } else { + a_prefix = o->a_prefix; + b_prefix = o->b_prefix; + } name_a += (*name_a == '/'); name_b += (*name_b == '/'); @@ -313,8 +327,8 @@ static void emit_rewrite_diff(const char *name_a, strbuf_reset(&a_name); strbuf_reset(&b_name); - quote_two_c_style(&a_name, o->a_prefix, name_a, 0); - quote_two_c_style(&b_name, o->b_prefix, name_b, 0); + quote_two_c_style(&a_name, a_prefix, name_a, 0); + quote_two_c_style(&b_name, b_prefix, name_b, 0); diff_populate_filespec(one, 0); diff_populate_filespec(two, 0); @@ -1432,6 +1446,14 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) return NULL; } +void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b) +{ + if (!options->a_prefix) + options->a_prefix = a; + if (!options->b_prefix) + options->b_prefix = b; +} + static void builtin_diff(const char *name_a, const char *name_b, struct diff_filespec *one, @@ -1445,9 +1467,19 @@ static void builtin_diff(const char *name_a, char *a_one, *b_two; const char *set = diff_get_color_opt(o, DIFF_METAINFO); const char *reset = diff_get_color_opt(o, DIFF_RESET); + const char *a_prefix, *b_prefix; + + diff_set_mnemonic_prefix(o, "a/", "b/"); + if (DIFF_OPT_TST(o, REVERSE_DIFF)) { + a_prefix = o->b_prefix; + b_prefix = o->a_prefix; + } else { + a_prefix = o->a_prefix; + b_prefix = o->b_prefix; + } - a_one = quote_two(o->a_prefix, name_a + (*name_a == '/')); - b_two = quote_two(o->b_prefix, name_b + (*name_b == '/')); + a_one = quote_two(a_prefix, name_a + (*name_a == '/')); + b_two = quote_two(b_prefix, name_b + (*name_b == '/')); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; fprintf(o->file, "%sdiff --git %s %s%s\n", set, a_one, b_two, reset); @@ -2308,8 +2340,10 @@ void diff_setup(struct diff_options *options) DIFF_OPT_CLR(options, COLOR_DIFF); options->detect_rename = diff_detect_rename_default; - options->a_prefix = "a/"; - options->b_prefix = "b/"; + if (!diff_mnemonic_prefix) { + options->a_prefix = "a/"; + options->b_prefix = "b/"; + } } int diff_setup_done(struct diff_options *options) diff --git a/diff.h b/diff.h index 50fb5ddb0b..9a679f58f5 100644 --- a/diff.h +++ b/diff.h @@ -160,6 +160,8 @@ extern void diff_tree_combined(const unsigned char *sha1, const unsigned char pa extern void diff_tree_combined_merge(const unsigned char *sha1, int, struct rev_info *); +void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b); + extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, -- cgit v1.3 From f88d225feb117f0429540da90b2552e198fa2e82 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 2 Sep 2008 17:28:59 -0700 Subject: diff --cumulative is a sub-option of --dirstat The option used to be implemented as if it is a totally independent one, but "git diff --cumulative" would not mean anything without "--dirstat". This makes --cumulative imply --dirstat. Signed-off-by: Junio C Hamano --- diff.c | 9 ++++++--- diff.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 7b4300a74a..b3a7da70a5 100644 --- a/diff.c +++ b/diff.c @@ -1072,7 +1072,7 @@ static void show_dirstat(struct diff_options *options) dir.alloc = 0; dir.nr = 0; dir.percent = options->dirstat_percent; - dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE; + dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE); changed = 0; for (i = 0; i < q->nr; i++) { @@ -2298,6 +2298,7 @@ void diff_setup(struct diff_options *options) options->break_opt = -1; options->rename_limit = -1; options->dirstat_percent = 3; + DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE); options->context = 3; options->change = diff_change; @@ -2470,8 +2471,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->output_format |= DIFF_FORMAT_SHORTSTAT; else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent)) options->output_format |= DIFF_FORMAT_DIRSTAT; - else if (!strcmp(arg, "--cumulative")) - options->output_format |= DIFF_FORMAT_CUMULATIVE; + else if (!strcmp(arg, "--cumulative")) { + options->output_format |= DIFF_FORMAT_DIRSTAT; + DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE); + } else if (!strcmp(arg, "--check")) options->output_format |= DIFF_FORMAT_CHECKDIFF; else if (!strcmp(arg, "--summary")) diff --git a/diff.h b/diff.h index 50fb5ddb0b..7f53bebf33 100644 --- a/diff.h +++ b/diff.h @@ -31,7 +31,6 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_FORMAT_PATCH 0x0010 #define DIFF_FORMAT_SHORTSTAT 0x0020 #define DIFF_FORMAT_DIRSTAT 0x0040 -#define DIFF_FORMAT_CUMULATIVE 0x0080 /* These override all above */ #define DIFF_FORMAT_NAME 0x0100 @@ -64,6 +63,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_CHECK_FAILED (1 << 16) #define DIFF_OPT_RELATIVE_NAME (1 << 17) #define DIFF_OPT_IGNORE_SUBMODULES (1 << 18) +#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) -- cgit v1.3 From fd33777b7871eefa440f89ccf7c432895af09c74 Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Fri, 5 Sep 2008 22:27:35 +0300 Subject: diff --dirstat-by-file: count changed files, not lines This new option --dirstat-by-file is the same as --dirstat, but it counts "impacted files" instead of "impacted lines" (lines that are added or removed). Signed-off-by: Heikki Orsila Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 3 +++ diff.c | 10 +++++++++- diff.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 6e268326da..7788d4fa4a 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -65,6 +65,9 @@ endif::git-format-patch[] can be set with "--dirstat=limit". Changes in a child directory is not counted for the parent directory, unless "--cumulative" is used. +--dirstat-by-file[=limit]:: + Same as --dirstat, but counts changed files instead of lines. + --summary:: Output a condensed summary of extended header information such as creations, renames and mode changes. diff --git a/diff.c b/diff.c index cbd151bbc8..2de86eb760 100644 --- a/diff.c +++ b/diff.c @@ -1110,9 +1110,13 @@ static void show_dirstat(struct diff_options *options) /* * Original minus copied is the removed material, * added is the new material. They are both damages - * made to the preimage. + * made to the preimage. In --dirstat-by-file mode, count + * damaged files, not damaged lines. This is done by + * counting only a single damaged line per file. */ damage = (p->one->size - copied) + added; + if (DIFF_OPT_TST(options, DIRSTAT_BY_FILE) && damage > 0) + damage = 1; ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc); dir.files[dir.nr].name = name; @@ -2476,6 +2480,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) else if (!strcmp(arg, "--cumulative")) { options->output_format |= DIFF_FORMAT_DIRSTAT; DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE); + } else if (opt_arg(arg, 0, "dirstat-by-file", + &options->dirstat_percent)) { + options->output_format |= DIFF_FORMAT_DIRSTAT; + DIFF_OPT_SET(options, DIRSTAT_BY_FILE); } else if (!strcmp(arg, "--check")) options->output_format |= DIFF_FORMAT_CHECKDIFF; diff --git a/diff.h b/diff.h index 7f53bebf33..c34688881d 100644 --- a/diff.h +++ b/diff.h @@ -64,6 +64,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_RELATIVE_NAME (1 << 17) #define DIFF_OPT_IGNORE_SUBMODULES (1 << 18) #define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19) +#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) -- cgit v1.3 From 9d865356abc08b253bc15b5fb50471d80c828be1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 6 Sep 2008 19:09:16 -0700 Subject: diff Porcelain: do not disable auto index refreshing on -C -C When we enabled the automatic refreshing of the index to "diff" Porcelain, we disabled it when --find-copies-harder was asked, but there is no good reason to do so. In the following command sequence, the first "diff" shows an "empty" diff exposing stat dirtyness, while the second one does not. $ >foo $ git add foo $ touch foo $ git diff -C -C $ git diff -C This fixes the inconsistency. Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index b3a7da70a5..85d690183f 100644 --- a/diff.c +++ b/diff.c @@ -3394,7 +3394,7 @@ void diffcore_std(struct diff_options *options) if (DIFF_OPT_TST(options, QUIET)) return; - if (options->skip_stat_unmatch && !DIFF_OPT_TST(options, FIND_COPIES_HARDER)) + if (options->skip_stat_unmatch) diffcore_skip_stat_unmatch(options); if (options->break_opt != -1) diffcore_break(options->break_opt); -- cgit v1.3 From df58a8274d6865020682a6739bc59b87a9761991 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 1 Sep 2008 23:20:26 -0700 Subject: diff --quiet: make it synonym to --exit-code >/dev/null The point of --quiet was to return the status as early as possible without doing any extra processing. Well behaved scripts, when they expect to run many diff operations inside, are supposed to run "update-index --refresh" upfront; we do not want them to pay the price of iterating over the index and comparing the contents to fix the stat dirtiness, and we avoided most of the processing in diffcore_std() when --quiet is in effect. But scripts that adhere to the good practice won't have to pay any more price than the necessary lstat(2) that will report stat cleanliness, as long as only -q is given without any fancier diff options. More importantly, users who do ask for "--quiet -M --filter=D" (in order to notice only the deletion, not paths that disappeared only because they have been renamed away) deserve to get the result they asked for, even it means they have to pay the extra price; the alternative is to get a cheap early return that gives a result they did not ask for, which is much worse. Signed-off-by: Junio C Hamano --- diff.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 85d690183f..13be211568 100644 --- a/diff.c +++ b/diff.c @@ -2393,13 +2393,6 @@ int diff_setup_done(struct diff_options *options) DIFF_OPT_SET(options, EXIT_WITH_STATUS); } - /* - * If we postprocess in diffcore, we cannot simply return - * upon the first hit. We need to run diff as usual. - */ - if (options->pickaxe || options->filter) - DIFF_OPT_CLR(options, QUIET); - return 0; } @@ -3391,9 +3384,6 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) void diffcore_std(struct diff_options *options) { - if (DIFF_OPT_TST(options, QUIET)) - return; - if (options->skip_stat_unmatch) diffcore_skip_stat_unmatch(options); if (options->break_opt != -1) -- cgit v1.3 From af9ce1ffc6de9774e90a91f27fb1febd027f74f1 Mon Sep 17 00:00:00 2001 From: Andreas Ericsson Date: Sun, 7 Sep 2008 22:15:29 +0200 Subject: Teach "git diff -p" to locate PHP class methods Otherwise it will always print the class-name rather than the name of the function inside that class. While we're at it, reorder the gitattributes manpage to list the built-in funcname pattern names in alphabetical order. Signed-off-by: Andreas Ericsson Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 6 ++++-- diff.c | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 5fb5007413..75124d2612 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -311,18 +311,20 @@ patterns are available: - `bibtex` suitable for files with BibTeX coded references. +- `html` suitable for HTML/XHTML documents. + - `java` suitable for source code in the Java lanugage. - `pascal` suitable for source code in the Pascal/Delphi language. +- `php` suitable for source code in the PHP language. + - `python` suitable for source code in the Python language. - `ruby` suitable for source code in the Ruby language. - `tex` suitable for source code for LaTeX documents. -- `html` suitable for HTML/XHTML documents. - Performing a three-way merge ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/diff.c b/diff.c index cbd151bbc8..e7afbe28c1 100644 --- a/diff.c +++ b/diff.c @@ -1402,6 +1402,7 @@ static struct builtin_funcname_pattern { "\\|" "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" }, + { "php", "^[\t ]*\\(\\(function\\|class\\).*\\)" }, { "python", "^\\s*\\(\\(class\\|def\\)\\s.*\\)$" }, { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, -- cgit v1.3 From 45e7ca0f0e1042c26d56b578165365c3f70c0121 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:40:48 -0500 Subject: diff.c: return pattern entry pointer rather than just the hunk header pattern This is in preparation for associating a flag with each pattern which will control how the pattern is interpreted. For example, as a basic or extended regular expression. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- diff.c | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 5e01b2bb27..406a76a203 100644 --- a/diff.c +++ b/diff.c @@ -94,32 +94,35 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val * to define a customized regexp to find the beginning of a function to * be used for hunk header lines of "diff -p" style output. */ -static struct funcname_pattern { +struct funcname_pattern_entry { char *name; char *pattern; - struct funcname_pattern *next; +}; +static struct funcname_pattern_list { + struct funcname_pattern_list *next; + struct funcname_pattern_entry e; } *funcname_pattern_list; static int parse_funcname_pattern(const char *var, const char *ep, const char *value) { const char *name; int namelen; - struct funcname_pattern *pp; + struct funcname_pattern_list *pp; name = var + 5; /* "diff." */ namelen = ep - name; for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strncmp(pp->name, name, namelen) && !pp->name[namelen]) + if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen]) break; if (!pp) { pp = xcalloc(1, sizeof(*pp)); - pp->name = xmemdupz(name, namelen); + pp->e.name = xmemdupz(name, namelen); pp->next = funcname_pattern_list; funcname_pattern_list = pp; } - free(pp->pattern); - pp->pattern = xstrdup(value); + free(pp->e.pattern); + pp->e.pattern = xstrdup(value); return 0; } @@ -1377,20 +1380,17 @@ int diff_filespec_is_binary(struct diff_filespec *one) return one->is_binary; } -static const char *funcname_pattern(const char *ident) +static const struct funcname_pattern_entry *funcname_pattern(const char *ident) { - struct funcname_pattern *pp; + struct funcname_pattern_list *pp; for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strcmp(ident, pp->name)) - return pp->pattern; + if (!strcmp(ident, pp->e.name)) + return &pp->e; return NULL; } -static struct builtin_funcname_pattern { - const char *name; - const char *pattern; -} builtin_funcname_pattern[] = { +static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" @@ -1407,9 +1407,10 @@ static struct builtin_funcname_pattern { { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -static const char *diff_funcname_pattern(struct diff_filespec *one) +static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) { - const char *ident, *pattern; + const char *ident; + const struct funcname_pattern_entry *pe; int i; diff_filespec_check_attr(one); @@ -1424,9 +1425,9 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) return funcname_pattern("default"); /* Look up custom "funcname.$ident" regexp from config. */ - pattern = funcname_pattern(ident); - if (pattern) - return pattern; + pe = funcname_pattern(ident); + if (pe) + return pe; /* * And define built-in fallback patterns here. Note that @@ -1434,7 +1435,7 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) */ for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++) if (!strcmp(ident, builtin_funcname_pattern[i].name)) - return builtin_funcname_pattern[i].pattern; + return &builtin_funcname_pattern[i]; return NULL; } @@ -1512,11 +1513,11 @@ static void builtin_diff(const char *name_a, xdemitconf_t xecfg; xdemitcb_t ecb; struct emit_callback ecbdata; - const char *funcname_pattern; + const struct funcname_pattern_entry *pe; - funcname_pattern = diff_funcname_pattern(one); - if (!funcname_pattern) - funcname_pattern = diff_funcname_pattern(two); + pe = diff_funcname_pattern(one); + if (!pe) + pe = diff_funcname_pattern(two); memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); @@ -1528,8 +1529,8 @@ static void builtin_diff(const char *name_a, xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; - if (funcname_pattern) - xdiff_set_find_func(&xecfg, funcname_pattern); + if (pe) + xdiff_set_find_func(&xecfg, pe->pattern); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) -- cgit v1.3 From a013585b20ac757b0e75a72181ffa44674f35235 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:42:48 -0500 Subject: diff.c: associate a flag with each pattern and use it for compiling regex This is in preparation for allowing extended regular expression patterns. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- diff.c | 21 ++++++++++++--------- xdiff-interface.c | 4 ++-- xdiff-interface.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 406a76a203..6881cf4efa 100644 --- a/diff.c +++ b/diff.c @@ -97,13 +97,14 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val struct funcname_pattern_entry { char *name; char *pattern; + int cflags; }; static struct funcname_pattern_list { struct funcname_pattern_list *next; struct funcname_pattern_entry e; } *funcname_pattern_list; -static int parse_funcname_pattern(const char *var, const char *ep, const char *value) +static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags) { const char *name; int namelen; @@ -123,6 +124,7 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v } free(pp->e.pattern); pp->e.pattern = xstrdup(value); + pp->e.cflags = cflags; return 0; } @@ -185,7 +187,8 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) if (!strcmp(ep, ".funcname")) { if (!value) return config_error_nonbool(var); - return parse_funcname_pattern(var, ep, value); + return parse_funcname_pattern(var, ep, value, + 0); } } } @@ -1395,16 +1398,16 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" - "[ ]*([^;]*\\)$" }, + "[ ]*([^;]*\\)$", 0 }, { "pascal", "^\\(\\(procedure\\|function\\|constructor\\|" "destructor\\|interface\\|implementation\\|" "initialization\\|finalization\\)[ \t]*.*\\)$" "\\|" - "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" - }, - { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, - { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, - { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, + "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$", + 0 }, + { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$", 0 }, + { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$", 0 }, + { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$", 0 }, }; static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) @@ -1530,7 +1533,7 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; if (pe) - xdiff_set_find_func(&xecfg, pe->pattern); + xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) diff --git a/xdiff-interface.c b/xdiff-interface.c index 61dc5c5470..2c81f40cb6 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -206,7 +206,7 @@ static long ff_regexp(const char *line, long len, return result; } -void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) +void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags) { int i; struct ff_regs *regs; @@ -231,7 +231,7 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) expression = buffer = xstrndup(value, ep - value); else expression = value; - if (regcomp(®->re, expression, 0)) + if (regcomp(®->re, expression, cflags)) die("Invalid regexp to look for hunk header: %s", expression); free(buffer); value = ep + 1; diff --git a/xdiff-interface.h b/xdiff-interface.h index f7f791d96b..33cab9dd59 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -21,6 +21,6 @@ int parse_hunk_header(char *line, int len, int read_mmfile(mmfile_t *ptr, const char *filename); int buffer_is_binary(const char *ptr, unsigned long size); -extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line); +extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags); #endif -- cgit v1.3 From 45d9414fa5599b41578625961b53e18a9b9148c7 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:44:33 -0500 Subject: diff.*.xfuncname which uses "extended" regex's for hunk header selection Currently, the hunk headers produced by 'diff -p' are customizable by setting the diff.*.funcname option in the config file. The 'funcname' option takes a basic regular expression. This functionality was designed using the GNU regex library which, by default, allows using backslashed versions of some extended regular expression operators, even in Basic Regular Expression mode. For example, the following characters, when backslashed, are interpreted according to the extended regular expression rules: ?, +, and |. As such, the builtin funcname patterns were created using some extended regular expression operators. Other platforms which adhere more strictly to the POSIX spec do not interpret the backslashed extended RE operators in Basic Regular Expression mode. This causes the pattern matching for the builtin funcname patterns to fail on those platforms. Introduce a new option 'xfuncname' which uses extended regular expressions, and advertise it _instead_ of funcname. Since most users are on GNU platforms, the majority of funcname patterns are created and tested there. Advertising only xfuncname should help to avoid the creation of non-portable patterns which work with GNU regex but not elsewhere. Additionally, the extended regular expressions may be less ugly and complicated compared to the basic RE since many common special operators do not need to be backslashed. For example, the GNU Basic RE: ^[ ]*\\(\\(public\\|static\\).*\\)$ becomes the following Extended RE: ^[ ]*((public|static).*)$ Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 4 ++-- diff.c | 5 +++++ t/t4018-diff-funcname.sh | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 94e6752aa2..9259637609 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -288,13 +288,13 @@ for paths. *.tex diff=tex ------------------------ -Then, you would define "diff.tex.funcname" configuration to +Then, you would define "diff.tex.xfuncname" configuration to specify a regular expression that matches a line that you would want to appear as the hunk header, like this: ------------------------ [diff "tex"] - funcname = "^\\(\\\\\\(sub\\)*section{.*\\)$" + xfuncname = "^(\\\\(sub)*section\\{.*)$" ------------------------ Note. A single level of backslashes are eaten by the diff --git a/diff.c b/diff.c index 6881cf4efa..dabb4b4a02 100644 --- a/diff.c +++ b/diff.c @@ -189,6 +189,11 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return config_error_nonbool(var); return parse_funcname_pattern(var, ep, value, 0); + } else if (!strcmp(ep, ".xfuncname")) { + if (!value) + return config_error_nonbool(var); + return parse_funcname_pattern(var, ep, value, + REG_EXTENDED); } } } diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 18bcd9713d..602d68f092 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -58,7 +58,7 @@ test_expect_success 'last regexp must not be negated' ' ' test_expect_success 'alternation in pattern' ' - git config diff.java.funcname "^[ ]*\\(\\(public\\|static\\).*\\)$" + git config diff.java.xfuncname "^[ ]*((public|static).*)$" && git diff --no-index Beer.java Beer-correct.java | grep "^@@.*@@ public static void main(" ' -- cgit v1.3 From 6a6baf9b4e819a0bbfd70627f966cd7144dd8301 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 19 Sep 2008 23:45:04 -0700 Subject: diff: use extended regexp to find hunk headers Using ERE elements such as "|" (alternation) by backquoting in BRE is a GNU extension and should not be done in portable programs. Signed-off-by: Junio C Hamano --- diff.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index dabb4b4a02..175a044a34 100644 --- a/diff.c +++ b/diff.c @@ -1399,20 +1399,23 @@ static const struct funcname_pattern_entry *funcname_pattern(const char *ident) } static const struct funcname_pattern_entry builtin_funcname_pattern[] = { - { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" - "new\\|return\\|switch\\|throw\\|while\\)\n" - "^[ ]*\\(\\([ ]*" - "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" - "[ ]*([^;]*\\)$", 0 }, - { "pascal", "^\\(\\(procedure\\|function\\|constructor\\|" - "destructor\\|interface\\|implementation\\|" - "initialization\\|finalization\\)[ \t]*.*\\)$" - "\\|" - "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$", - 0 }, - { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$", 0 }, - { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$", 0 }, - { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$", 0 }, + { "java", + "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" + "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", + REG_EXTENDED }, + { "pascal", + "^((procedure|function|constructor|destructor|interface|" + "implementation|initialization|finalization)[ \t]*.*)$" + "|" + "^(.*=[ \t]*(class|record).*)$", + REG_EXTENDED }, + { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", + REG_EXTENDED }, + { "tex", + "^(\\\\((sub)*section|chapter|part)\\*{0,1}\{.*)$", + REG_EXTENDED }, + { "ruby", "^[ \t]*((class|module|def)[ \t].*)$", + REG_EXTENDED }, }; static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) -- cgit v1.3 From 1883a0d3b7ad7c9de1ac790bda6f1a6181237439 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 19 Sep 2008 23:52:49 -0700 Subject: diff: use extended regexp to find hunk headers Using ERE elements such as "|" (alternation) by backquoting in BRE is a GNU extension and should not be done in portable programs. Signed-off-by: Junio C Hamano --- diff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 5b9b074856..a733010170 100644 --- a/diff.c +++ b/diff.c @@ -1406,7 +1406,7 @@ static const struct funcname_pattern_entry *funcname_pattern(const char *ident) static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", REG_EXTENDED }, - { "html", "^\\s*\\(<[Hh][1-6]\\s.*>.*\\)$", 0 }, + { "html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", REG_EXTENDED }, { "java", "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", @@ -1417,8 +1417,8 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { "|" "^(.*=[ \t]*(class|record).*)$", REG_EXTENDED }, - { "php", "^[\t ]*\\(\\(function\\|class\\).*\\)", 0 }, - { "python", "^\\s*\\(\\(class\\|def\\)\\s.*\\)$", 0 }, + { "php", "^[\t ]*((function|class).*)", REG_EXTENDED }, + { "python", "^[ \t]*((class|def)[ \t].*)$", REG_EXTENDED }, { "ruby", "^[ \t]*((class|module|def)[ \t].*)$", REG_EXTENDED }, { "tex", -- cgit v1.3 From 3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 20 Sep 2008 00:52:11 -0700 Subject: diff: fix "multiple regexp" semantics to find hunk header comment When multiple regular expressions are concatenated with "\n", they were traditionally AND'ed together, and only a line that matches _all_ of them is taken as a match. This however is unwieldy when multiple regexp feature is used to specify alternatives. This fixes the semantics to take the first match. A nagative pattern, if matches, makes the line to fail as before. A match with a positive pattern will be the final match, and what it captures in $1 is used as the hunk header comment. We could write alternatives using "|" in ERE, but the machinery can only use captured $1 as the hunk header comment (or $0 if there is no match in $1), so you cannot write: "junk ( A | B ) | garbage ( C | D )" and expect both "junk" and "garbage" to get stripped with the existing code. With this fix, you can write it as: "junk ( A | B ) \n garbage ( C | D )" and the way capture works would match the user expectation more naturally. Signed-off-by: Junio C Hamano --- diff.c | 2 +- xdiff-interface.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index a733010170..1bcbbd5bb1 100644 --- a/diff.c +++ b/diff.c @@ -1414,7 +1414,7 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "pascal", "^((procedure|function|constructor|destructor|interface|" "implementation|initialization|finalization)[ \t]*.*)$" - "|" + "\n" "^(.*=[ \t]*(class|record).*)$", REG_EXTENDED }, { "php", "^[\t ]*((function|class).*)", REG_EXTENDED }, diff --git a/xdiff-interface.c b/xdiff-interface.c index 7f1a7d3ffc..6c6bb19973 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -194,26 +194,29 @@ static long ff_regexp(const char *line, long len, char *line_buffer = xstrndup(line, len); /* make NUL terminated */ struct ff_regs *regs = priv; regmatch_t pmatch[2]; - int result = 0, i; + int i; + int result = -1; for (i = 0; i < regs->nr; i++) { struct ff_reg *reg = regs->array + i; - if (reg->negate ^ !!regexec(®->re, - line_buffer, 2, pmatch, 0)) { - free(line_buffer); - return -1; + if (!regexec(®->re, line_buffer, 2, pmatch, 0)) { + if (reg->negate) + goto fail; + break; } } + if (regs->nr <= i) + goto fail; i = pmatch[1].rm_so >= 0 ? 1 : 0; line += pmatch[i].rm_so; result = pmatch[i].rm_eo - pmatch[i].rm_so; if (result > buffer_size) result = buffer_size; else - while (result > 0 && (isspace(line[result - 1]) || - line[result - 1] == '\n')) + while (result > 0 && (isspace(line[result - 1]))) result--; memcpy(buffer, line, result); + fail: free(line_buffer); return result; } -- cgit v1.3 From 96d1a8e9d44fd635fad8466dbe0aab6d73495c9f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 20 Sep 2008 15:30:12 -0700 Subject: diff hunk pattern: fix misconverted "\{" tex macro introducers Pointed out by Brandon Casey. Signed-off-by: Junio C Hamano --- diff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 175a044a34..a283738616 100644 --- a/diff.c +++ b/diff.c @@ -1409,10 +1409,10 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { "|" "^(.*=[ \t]*(class|record).*)$", REG_EXTENDED }, - { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", + { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", REG_EXTENDED }, { "tex", - "^(\\\\((sub)*section|chapter|part)\\*{0,1}\{.*)$", + "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", REG_EXTENDED }, { "ruby", "^[ \t]*((class|module|def)[ \t].*)$", REG_EXTENDED }, -- cgit v1.3 From fdac6692a0b0eda293f9f1bf4bc49b05b29f3c45 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 22 Sep 2008 18:26:20 -0500 Subject: t4018-diff-funcname: test syntax of builtin xfuncname patterns [jc: fixes bibtex pattern breakage exposed by this test] Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- diff.c | 2 +- t/t4018-diff-funcname.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 0f98bff46b..05dd8f0b56 100644 --- a/diff.c +++ b/diff.c @@ -1404,7 +1404,7 @@ static const struct funcname_pattern_entry *funcname_pattern(const char *ident) } static const struct funcname_pattern_entry builtin_funcname_pattern[] = { - { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", + { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", REG_EXTENDED }, { "html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", REG_EXTENDED }, { "java", diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 99fff973eb..520e095c59 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -32,7 +32,7 @@ EOF sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java -builtin_patterns="bibtex java pascal ruby tex" +builtin_patterns="bibtex html java pascal php python ruby tex" for p in $builtin_patterns do test_expect_success "builtin $p pattern compiles" ' -- cgit v1.3 From 416f80a60b209d2ca0326407b801e9fb6ed8fdd7 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 29 Sep 2008 16:52:01 -0500 Subject: diff.c: remove duplicate bibtex pattern introduced by merge 92bb9785 Signed-off-by: Brandon Casey Signed-off-by: Shawn O. Pearce --- diff.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index b001d7b507..7c982b4947 100644 --- a/diff.c +++ b/diff.c @@ -1439,8 +1439,6 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "python", "^[ \t]*((class|def)[ \t].*)$", REG_EXTENDED }, { "ruby", "^[ \t]*((class|module|def)[ \t].*)$", REG_EXTENDED }, - { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", - REG_EXTENDED }, { "tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", REG_EXTENDED }, -- cgit v1.3 From 9126f0091f271f090cc030a788219574ab0fea97 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 1 Oct 2008 14:05:20 -0400 Subject: fix openssl headers conflicting with custom SHA1 implementations On ARM I have the following compilation errors: CC fast-import.o In file included from cache.h:8, from builtin.h:6, from fast-import.c:142: arm/sha1.h:14: error: conflicting types for 'SHA_CTX' /usr/include/openssl/sha.h:105: error: previous declaration of 'SHA_CTX' was here arm/sha1.h:16: error: conflicting types for 'SHA1_Init' /usr/include/openssl/sha.h:115: error: previous declaration of 'SHA1_Init' was here arm/sha1.h:17: error: conflicting types for 'SHA1_Update' /usr/include/openssl/sha.h:116: error: previous declaration of 'SHA1_Update' was here arm/sha1.h:18: error: conflicting types for 'SHA1_Final' /usr/include/openssl/sha.h:117: error: previous declaration of 'SHA1_Final' was here make: *** [fast-import.o] Error 1 This is because openssl header files are always included in git-compat-util.h since commit 684ec6c63c whenever NO_OPENSSL is not set, which somehow brings in clashing with the custom ARM version. Compilation of git is probably broken on PPC too for the same reason. Turns out that the only file requiring openssl/ssl.h and openssl/err.h is imap-send.c. But only moving those problematic includes there doesn't solve the issue as it also includes cache.h which brings in the conflicting local SHA1 header file. As suggested by Jeff King, the best solution is to rename our references to SHA1 functions and structure to something git specific, and define those according to the implementation used. Signed-off-by: Nicolas Pitre Signed-off-by: Shawn O. Pearce --- arm/sha1.c | 16 ++++++++-------- arm/sha1.h | 15 ++++++++++----- arm/sha1_arm.S | 4 ++-- builtin-unpack-objects.c | 10 +++++----- cache.h | 8 +++++++- csum-file.c | 8 ++++---- csum-file.h | 2 +- diff.c | 12 ++++++------ fast-import.c | 18 +++++++++--------- http-push.c | 10 +++++----- http-walker.c | 10 +++++----- index-pack.c | 8 ++++---- mozilla-sha1/sha1.c | 18 +++++++++--------- mozilla-sha1/sha1.h | 13 +++++++++---- pack-check.c | 16 ++++++++-------- pack-write.c | 30 +++++++++++++++--------------- patch-id.c | 12 ++++++------ ppc/sha1.c | 18 +++++++++--------- ppc/sha1.h | 15 ++++++++++----- ppc/sha1ppc.S | 4 ++-- read-cache.c | 28 ++++++++++++++-------------- rerere.c | 10 +++++----- sha1_file.c | 10 +++++----- test-sha1.c | 8 ++++---- 24 files changed, 162 insertions(+), 141 deletions(-) (limited to 'diff.c') diff --git a/arm/sha1.c b/arm/sha1.c index 9e3ae038e8..c61ad4aff9 100644 --- a/arm/sha1.c +++ b/arm/sha1.c @@ -8,9 +8,9 @@ #include #include "sha1.h" -extern void sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W); +extern void arm_sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W); -void SHA1_Init(SHA_CTX *c) +void arm_SHA1_Init(arm_SHA_CTX *c) { c->len = 0; c->hash[0] = 0x67452301; @@ -20,7 +20,7 @@ void SHA1_Init(SHA_CTX *c) c->hash[4] = 0xc3d2e1f0; } -void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n) +void arm_SHA1_Update(arm_SHA_CTX *c, const void *p, unsigned long n) { uint32_t workspace[80]; unsigned int partial; @@ -32,12 +32,12 @@ void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n) if (partial) { done = 64 - partial; memcpy(c->buffer + partial, p, done); - sha_transform(c->hash, c->buffer, workspace); + arm_sha_transform(c->hash, c->buffer, workspace); partial = 0; } else done = 0; while (n >= done + 64) { - sha_transform(c->hash, p + done, workspace); + arm_sha_transform(c->hash, p + done, workspace); done += 64; } } else @@ -46,7 +46,7 @@ void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n) memcpy(c->buffer + partial, p + done, n - done); } -void SHA1_Final(unsigned char *hash, SHA_CTX *c) +void arm_SHA1_Final(unsigned char *hash, arm_SHA_CTX *c) { uint64_t bitlen; uint32_t bitlen_hi, bitlen_lo; @@ -57,7 +57,7 @@ void SHA1_Final(unsigned char *hash, SHA_CTX *c) bitlen = c->len << 3; offset = c->len & 0x3f; padlen = ((offset < 56) ? 56 : (64 + 56)) - offset; - SHA1_Update(c, padding, padlen); + arm_SHA1_Update(c, padding, padlen); bitlen_hi = bitlen >> 32; bitlen_lo = bitlen & 0xffffffff; @@ -69,7 +69,7 @@ void SHA1_Final(unsigned char *hash, SHA_CTX *c) bits[5] = bitlen_lo >> 16; bits[6] = bitlen_lo >> 8; bits[7] = bitlen_lo; - SHA1_Update(c, bits, 8); + arm_SHA1_Update(c, bits, 8); for (i = 0; i < 5; i++) { uint32_t v = c->hash[i]; diff --git a/arm/sha1.h b/arm/sha1.h index 3952646349..b61b618486 100644 --- a/arm/sha1.h +++ b/arm/sha1.h @@ -7,12 +7,17 @@ #include -typedef struct sha_context { +typedef struct { uint64_t len; uint32_t hash[5]; unsigned char buffer[64]; -} SHA_CTX; +} arm_SHA_CTX; -void SHA1_Init(SHA_CTX *c); -void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n); -void SHA1_Final(unsigned char *hash, SHA_CTX *c); +void arm_SHA1_Init(arm_SHA_CTX *c); +void arm_SHA1_Update(arm_SHA_CTX *c, const void *p, unsigned long n); +void arm_SHA1_Final(unsigned char *hash, arm_SHA_CTX *c); + +#define git_SHA_CTX arm_SHA_CTX +#define git_SHA1_Init arm_SHA1_Init +#define git_SHA1_Update arm_SHA1_Update +#define git_SHA1_Final arm_SHA1_Final diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S index 8c1cb99fb4..41e92636e0 100644 --- a/arm/sha1_arm.S +++ b/arm/sha1_arm.S @@ -10,7 +10,7 @@ */ .text - .globl sha_transform + .globl arm_sha_transform /* * void sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W); @@ -18,7 +18,7 @@ * note: the "data" pointer may be unaligned. */ -sha_transform: +arm_sha_transform: stmfd sp!, {r4 - r8, lr} diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 40b20f26e8..d2796b6309 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -19,7 +19,7 @@ static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] static unsigned char buffer[4096]; static unsigned int offset, len; static off_t consumed_bytes; -static SHA_CTX ctx; +static git_SHA_CTX ctx; /* * When running under --strict mode, objects whose reachability are @@ -59,7 +59,7 @@ static void *fill(int min) if (min > sizeof(buffer)) die("cannot fill %d bytes", min); if (offset) { - SHA1_Update(&ctx, buffer, offset); + git_SHA1_Update(&ctx, buffer, offset); memmove(buffer, buffer + offset, len); offset = 0; } @@ -539,10 +539,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) /* We don't take any non-flag arguments now.. Maybe some day */ usage(unpack_usage); } - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); unpack_all(); - SHA1_Update(&ctx, buffer, offset); - SHA1_Final(sha1, &ctx); + git_SHA1_Update(&ctx, buffer, offset); + git_SHA1_Final(sha1, &ctx); if (strict) write_rest(); if (hashcmp(fill(20), sha1)) diff --git a/cache.h b/cache.h index 7027c896bf..9f4e5c0d45 100644 --- a/cache.h +++ b/cache.h @@ -6,8 +6,14 @@ #include "hash.h" #include SHA1_HEADER -#include +#ifndef git_SHA_CTX +#define git_SHA_CTX SHA_CTX +#define git_SHA1_Init SHA1_Init +#define git_SHA1_Update SHA1_Update +#define git_SHA1_Final SHA1_Final +#endif +#include #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200 #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) #endif diff --git a/csum-file.c b/csum-file.c index bb70c75ee1..717d29fc03 100644 --- a/csum-file.c +++ b/csum-file.c @@ -36,11 +36,11 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags) unsigned offset = f->offset; if (offset) { - SHA1_Update(&f->ctx, f->buffer, offset); + git_SHA1_Update(&f->ctx, f->buffer, offset); sha1flush(f, f->buffer, offset); f->offset = 0; } - SHA1_Final(f->buffer, &f->ctx); + git_SHA1_Final(f->buffer, &f->ctx); if (result) hashcpy(result, f->buffer); if (flags & (CSUM_CLOSE | CSUM_FSYNC)) { @@ -82,7 +82,7 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count) buf = (char *) buf + nr; left -= nr; if (!left) { - SHA1_Update(&f->ctx, data, offset); + git_SHA1_Update(&f->ctx, data, offset); sha1flush(f, data, offset); offset = 0; } @@ -105,7 +105,7 @@ struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp f->tp = tp; f->name = name; f->do_crc = 0; - SHA1_Init(&f->ctx); + git_SHA1_Init(&f->ctx); return f; } diff --git a/csum-file.h b/csum-file.h index 72c9487f4f..9e13342eb3 100644 --- a/csum-file.h +++ b/csum-file.h @@ -7,7 +7,7 @@ struct progress; struct sha1file { int fd; unsigned int offset; - SHA_CTX ctx; + git_SHA_CTX ctx; off_t total; struct progress *tp; const char *name; diff --git a/diff.c b/diff.c index 7c982b4947..4e4e439e03 100644 --- a/diff.c +++ b/diff.c @@ -3087,7 +3087,7 @@ static void diff_summary(FILE *file, struct diff_filepair *p) } struct patch_id_t { - SHA_CTX *ctx; + git_SHA_CTX *ctx; int patchlen; }; @@ -3115,7 +3115,7 @@ static void patch_id_consume(void *priv, char *line, unsigned long len) new_len = remove_space(line, len); - SHA1_Update(data->ctx, line, new_len); + git_SHA1_Update(data->ctx, line, new_len); data->patchlen += new_len; } @@ -3124,11 +3124,11 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) { struct diff_queue_struct *q = &diff_queued_diff; int i; - SHA_CTX ctx; + git_SHA_CTX ctx; struct patch_id_t data; char buffer[PATH_MAX * 4 + 20]; - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); memset(&data, 0, sizeof(struct patch_id_t)); data.ctx = &ctx; @@ -3190,7 +3190,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) len2, p->two->path, len1, p->one->path, len2, p->two->path); - SHA1_Update(&ctx, buffer, len1); + git_SHA1_Update(&ctx, buffer, len1); xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = 3; @@ -3199,7 +3199,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) &xpp, &xecfg, &ecb); } - SHA1_Final(sha1, &ctx); + git_SHA1_Final(sha1, &ctx); return 0; } diff --git a/fast-import.c b/fast-import.c index ab6689a64d..3c035a5788 100644 --- a/fast-import.c +++ b/fast-import.c @@ -845,7 +845,7 @@ static int oecmp (const void *a_, const void *b_) static char *create_index(void) { static char tmpfile[PATH_MAX]; - SHA_CTX ctx; + git_SHA_CTX ctx; struct sha1file *f; struct object_entry **idx, **c, **last, *e; struct object_entry_pool *o; @@ -882,17 +882,17 @@ static char *create_index(void) idx_fd = xmkstemp(tmpfile); f = sha1fd(idx_fd, tmpfile); sha1write(f, array, 256 * sizeof(int)); - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); for (c = idx; c != last; c++) { uint32_t offset = htonl((*c)->offset); sha1write(f, &offset, 4); sha1write(f, (*c)->sha1, sizeof((*c)->sha1)); - SHA1_Update(&ctx, (*c)->sha1, 20); + git_SHA1_Update(&ctx, (*c)->sha1, 20); } sha1write(f, pack_data->sha1, sizeof(pack_data->sha1)); sha1close(f, NULL, CSUM_FSYNC); free(idx); - SHA1_Final(pack_data->sha1, &ctx); + git_SHA1_Final(pack_data->sha1, &ctx); return tmpfile; } @@ -1033,15 +1033,15 @@ static int store_object( unsigned char hdr[96]; unsigned char sha1[20]; unsigned long hdrlen, deltalen; - SHA_CTX c; + git_SHA_CTX c; z_stream s; hdrlen = sprintf((char*)hdr,"%s %lu", typename(type), (unsigned long)dat->len) + 1; - SHA1_Init(&c); - SHA1_Update(&c, hdr, hdrlen); - SHA1_Update(&c, dat->buf, dat->len); - SHA1_Final(sha1, &c); + git_SHA1_Init(&c); + git_SHA1_Update(&c, hdr, hdrlen); + git_SHA1_Update(&c, dat->buf, dat->len); + git_SHA1_Final(sha1, &c); if (sha1out) hashcpy(sha1out, sha1); diff --git a/http-push.c b/http-push.c index c9dd9a1f64..42f4d78e54 100644 --- a/http-push.c +++ b/http-push.c @@ -126,7 +126,7 @@ struct transfer_request char errorstr[CURL_ERROR_SIZE]; long http_code; unsigned char real_sha1[20]; - SHA_CTX c; + git_SHA_CTX c; z_stream stream; int zret; int rename; @@ -209,7 +209,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, request->stream.next_out = expn; request->stream.avail_out = sizeof(expn); request->zret = inflate(&request->stream, Z_SYNC_FLUSH); - SHA1_Update(&request->c, expn, + git_SHA1_Update(&request->c, expn, sizeof(expn) - request->stream.avail_out); } while (request->stream.avail_in && request->zret == Z_OK); data_received++; @@ -270,7 +270,7 @@ static void start_fetch_loose(struct transfer_request *request) inflateInit(&request->stream); - SHA1_Init(&request->c); + git_SHA1_Init(&request->c); url = xmalloc(strlen(remote->url) + 50); request->url = xmalloc(strlen(remote->url) + 50); @@ -310,7 +310,7 @@ static void start_fetch_loose(struct transfer_request *request) if (prev_read == -1) { memset(&request->stream, 0, sizeof(request->stream)); inflateInit(&request->stream); - SHA1_Init(&request->c); + git_SHA1_Init(&request->c); if (prev_posn>0) { prev_posn = 0; lseek(request->local_fileno, 0, SEEK_SET); @@ -742,7 +742,7 @@ static void finish_request(struct transfer_request *request) fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n"); inflateEnd(&request->stream); - SHA1_Final(request->real_sha1, &request->c); + git_SHA1_Final(request->real_sha1, &request->c); if (request->zret != Z_STREAM_END) { unlink(request->tmpfile); } else if (hashcmp(request->obj->sha1, request->real_sha1)) { diff --git a/http-walker.c b/http-walker.c index 9dc6b27b45..7271c7d19d 100644 --- a/http-walker.c +++ b/http-walker.c @@ -36,7 +36,7 @@ struct object_request char errorstr[CURL_ERROR_SIZE]; long http_code; unsigned char real_sha1[20]; - SHA_CTX c; + git_SHA_CTX c; z_stream stream; int zret; int rename; @@ -83,7 +83,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, obj_req->stream.next_out = expn; obj_req->stream.avail_out = sizeof(expn); obj_req->zret = inflate(&obj_req->stream, Z_SYNC_FLUSH); - SHA1_Update(&obj_req->c, expn, + git_SHA1_Update(&obj_req->c, expn, sizeof(expn) - obj_req->stream.avail_out); } while (obj_req->stream.avail_in && obj_req->zret == Z_OK); data_received++; @@ -144,7 +144,7 @@ static void start_object_request(struct walker *walker, inflateInit(&obj_req->stream); - SHA1_Init(&obj_req->c); + git_SHA1_Init(&obj_req->c); url = xmalloc(strlen(obj_req->repo->base) + 51); obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); @@ -184,7 +184,7 @@ static void start_object_request(struct walker *walker, if (prev_read == -1) { memset(&obj_req->stream, 0, sizeof(obj_req->stream)); inflateInit(&obj_req->stream); - SHA1_Init(&obj_req->c); + git_SHA1_Init(&obj_req->c); if (prev_posn>0) { prev_posn = 0; lseek(obj_req->local, 0, SEEK_SET); @@ -244,7 +244,7 @@ static void finish_object_request(struct object_request *obj_req) } inflateEnd(&obj_req->stream); - SHA1_Final(obj_req->real_sha1, &obj_req->c); + git_SHA1_Final(obj_req->real_sha1, &obj_req->c); if (obj_req->zret != Z_STREAM_END) { unlink(obj_req->tmpfile); return; diff --git a/index-pack.c b/index-pack.c index 530d820370..2e4c0885f2 100644 --- a/index-pack.c +++ b/index-pack.c @@ -67,7 +67,7 @@ static struct progress *progress; static unsigned char input_buffer[4096]; static unsigned int input_offset, input_len; static off_t consumed_bytes; -static SHA_CTX input_ctx; +static git_SHA_CTX input_ctx; static uint32_t input_crc32; static int input_fd, output_fd, pack_fd; @@ -119,7 +119,7 @@ static void flush(void) if (input_offset) { if (output_fd >= 0) write_or_die(output_fd, input_buffer, input_offset); - SHA1_Update(&input_ctx, input_buffer, input_offset); + git_SHA1_Update(&input_ctx, input_buffer, input_offset); memmove(input_buffer, input_buffer + input_offset, input_len); input_offset = 0; } @@ -188,7 +188,7 @@ static char *open_pack_file(char *pack_name) output_fd = -1; pack_fd = input_fd; } - SHA1_Init(&input_ctx); + git_SHA1_Init(&input_ctx); return pack_name; } @@ -588,7 +588,7 @@ static void parse_pack_objects(unsigned char *sha1) /* Check pack integrity */ flush(); - SHA1_Final(sha1, &input_ctx); + git_SHA1_Final(sha1, &input_ctx); if (hashcmp(fill(20), sha1)) die("pack is corrupted (SHA1 mismatch)"); use(20); diff --git a/mozilla-sha1/sha1.c b/mozilla-sha1/sha1.c index 3f06b83567..95a4ebf496 100644 --- a/mozilla-sha1/sha1.c +++ b/mozilla-sha1/sha1.c @@ -35,9 +35,9 @@ #include "sha1.h" -static void shaHashBlock(SHA_CTX *ctx); +static void shaHashBlock(moz_SHA_CTX *ctx); -void SHA1_Init(SHA_CTX *ctx) { +void moz_SHA1_Init(moz_SHA_CTX *ctx) { int i; ctx->lenW = 0; @@ -56,7 +56,7 @@ void SHA1_Init(SHA_CTX *ctx) { } -void SHA1_Update(SHA_CTX *ctx, const void *_dataIn, int len) { +void moz_SHA1_Update(moz_SHA_CTX *ctx, const void *_dataIn, int len) { const unsigned char *dataIn = _dataIn; int i; @@ -75,7 +75,7 @@ void SHA1_Update(SHA_CTX *ctx, const void *_dataIn, int len) { } -void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) { +void moz_SHA1_Final(unsigned char hashout[20], moz_SHA_CTX *ctx) { unsigned char pad0x80 = 0x80; unsigned char pad0x00 = 0x00; unsigned char padlen[8]; @@ -91,10 +91,10 @@ void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) { padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255); padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255); padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255); - SHA1_Update(ctx, &pad0x80, 1); + moz_SHA1_Update(ctx, &pad0x80, 1); while (ctx->lenW != 56) - SHA1_Update(ctx, &pad0x00, 1); - SHA1_Update(ctx, padlen, 8); + moz_SHA1_Update(ctx, &pad0x00, 1); + moz_SHA1_Update(ctx, padlen, 8); /* Output hash */ @@ -106,13 +106,13 @@ void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) { /* * Re-initialize the context (also zeroizes contents) */ - SHA1_Init(ctx); + moz_SHA1_Init(ctx); } #define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n)))) -static void shaHashBlock(SHA_CTX *ctx) { +static void shaHashBlock(moz_SHA_CTX *ctx) { int t; unsigned int A,B,C,D,E,TEMP; diff --git a/mozilla-sha1/sha1.h b/mozilla-sha1/sha1.h index 16f2d3d43c..aa48a46cf7 100644 --- a/mozilla-sha1/sha1.h +++ b/mozilla-sha1/sha1.h @@ -38,8 +38,13 @@ typedef struct { unsigned int W[80]; int lenW; unsigned int sizeHi,sizeLo; -} SHA_CTX; +} moz_SHA_CTX; -void SHA1_Init(SHA_CTX *ctx); -void SHA1_Update(SHA_CTX *ctx, const void *dataIn, int len); -void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx); +void moz_SHA1_Init(moz_SHA_CTX *ctx); +void moz_SHA1_Update(moz_SHA_CTX *ctx, const void *dataIn, int len); +void moz_SHA1_Final(unsigned char hashout[20], moz_SHA_CTX *ctx); + +#define git_SHA_CTX moz_SHA_CTX +#define git_SHA1_Init moz_SHA1_Init +#define git_SHA1_Update moz_SHA1_Update +#define git_SHA1_Final moz_SHA1_Final diff --git a/pack-check.c b/pack-check.c index f596bf2db5..90c33b1b84 100644 --- a/pack-check.c +++ b/pack-check.c @@ -47,7 +47,7 @@ static int verify_packfile(struct packed_git *p, { off_t index_size = p->index_size; const unsigned char *index_base = p->index_data; - SHA_CTX ctx; + git_SHA_CTX ctx; unsigned char sha1[20], *pack_sig; off_t offset = 0, pack_sig_ofs = p->pack_size - 20; uint32_t nr_objects, i; @@ -60,16 +60,16 @@ static int verify_packfile(struct packed_git *p, * immediately. */ - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); while (offset < pack_sig_ofs) { unsigned int remaining; unsigned char *in = use_pack(p, w_curs, offset, &remaining); offset += remaining; if (offset > pack_sig_ofs) remaining -= (unsigned int)(offset - pack_sig_ofs); - SHA1_Update(&ctx, in, remaining); + git_SHA1_Update(&ctx, in, remaining); } - SHA1_Final(sha1, &ctx); + git_SHA1_Final(sha1, &ctx); pack_sig = use_pack(p, w_curs, pack_sig_ofs, NULL); if (hashcmp(sha1, pack_sig)) err = error("%s SHA1 checksum mismatch", @@ -135,7 +135,7 @@ int verify_pack(struct packed_git *p) { off_t index_size; const unsigned char *index_base; - SHA_CTX ctx; + git_SHA_CTX ctx; unsigned char sha1[20]; int err = 0; struct pack_window *w_curs = NULL; @@ -146,9 +146,9 @@ int verify_pack(struct packed_git *p) index_base = p->index_data; /* Verify SHA1 sum of the index file */ - SHA1_Init(&ctx); - SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20)); - SHA1_Final(sha1, &ctx); + git_SHA1_Init(&ctx); + git_SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20)); + git_SHA1_Final(sha1, &ctx); if (hashcmp(sha1, index_base + index_size - 20)) err = error("Packfile index for %s SHA1 mismatch", p->pack_name); diff --git a/pack-write.c b/pack-write.c index 3621f1dd32..b426006c58 100644 --- a/pack-write.c +++ b/pack-write.c @@ -25,7 +25,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, off_t last_obj_offset = 0; uint32_t array[256]; int i, fd; - SHA_CTX ctx; + git_SHA_CTX ctx; uint32_t index_version; if (nr_objects) { @@ -86,7 +86,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, sha1write(f, array, 256 * 4); /* compute the SHA1 hash of sorted object names. */ - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); /* * Write the actual SHA1 entries.. @@ -99,7 +99,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, sha1write(f, &offset, 4); } sha1write(f, obj->sha1, 20); - SHA1_Update(&ctx, obj->sha1, 20); + git_SHA1_Update(&ctx, obj->sha1, 20); } if (index_version >= 2) { @@ -140,7 +140,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, sha1write(f, sha1, 20); sha1close(f, NULL, CSUM_FSYNC); - SHA1_Final(sha1, &ctx); + git_SHA1_Final(sha1, &ctx); return index_name; } @@ -168,12 +168,12 @@ void fixup_pack_header_footer(int pack_fd, off_t partial_pack_offset) { int aligned_sz, buf_sz = 8 * 1024; - SHA_CTX old_sha1_ctx, new_sha1_ctx; + git_SHA_CTX old_sha1_ctx, new_sha1_ctx; struct pack_header hdr; char *buf; - SHA1_Init(&old_sha1_ctx); - SHA1_Init(&new_sha1_ctx); + git_SHA1_Init(&old_sha1_ctx); + git_SHA1_Init(&new_sha1_ctx); if (lseek(pack_fd, 0, SEEK_SET) != 0) die("Failed seeking to start of %s: %s", pack_name, strerror(errno)); @@ -181,9 +181,9 @@ void fixup_pack_header_footer(int pack_fd, die("Unable to reread header of %s: %s", pack_name, strerror(errno)); if (lseek(pack_fd, 0, SEEK_SET) != 0) die("Failed seeking to start of %s: %s", pack_name, strerror(errno)); - SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr)); + git_SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr)); hdr.hdr_entries = htonl(object_count); - SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr)); + git_SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr)); write_or_die(pack_fd, &hdr, sizeof(hdr)); partial_pack_offset -= sizeof(hdr); @@ -198,7 +198,7 @@ void fixup_pack_header_footer(int pack_fd, break; if (n < 0) die("Failed to checksum %s: %s", pack_name, strerror(errno)); - SHA1_Update(&new_sha1_ctx, buf, n); + git_SHA1_Update(&new_sha1_ctx, buf, n); aligned_sz -= n; if (!aligned_sz) @@ -207,11 +207,11 @@ void fixup_pack_header_footer(int pack_fd, if (!partial_pack_sha1) continue; - SHA1_Update(&old_sha1_ctx, buf, n); + git_SHA1_Update(&old_sha1_ctx, buf, n); partial_pack_offset -= n; if (partial_pack_offset == 0) { unsigned char sha1[20]; - SHA1_Final(sha1, &old_sha1_ctx); + git_SHA1_Final(sha1, &old_sha1_ctx); if (hashcmp(sha1, partial_pack_sha1) != 0) die("Unexpected checksum for %s " "(disk corruption?)", pack_name); @@ -220,7 +220,7 @@ void fixup_pack_header_footer(int pack_fd, * pack, which also means making partial_pack_offset * big enough not to matter anymore. */ - SHA1_Init(&old_sha1_ctx); + git_SHA1_Init(&old_sha1_ctx); partial_pack_offset = ~partial_pack_offset; partial_pack_offset -= MSB(partial_pack_offset, 1); } @@ -228,8 +228,8 @@ void fixup_pack_header_footer(int pack_fd, free(buf); if (partial_pack_sha1) - SHA1_Final(partial_pack_sha1, &old_sha1_ctx); - SHA1_Final(new_pack_sha1, &new_sha1_ctx); + git_SHA1_Final(partial_pack_sha1, &old_sha1_ctx); + git_SHA1_Final(new_pack_sha1, &new_sha1_ctx); write_or_die(pack_fd, new_pack_sha1, 20); fsync_or_die(pack_fd, pack_name); } diff --git a/patch-id.c b/patch-id.c index 9349bc5580..871f1d20c0 100644 --- a/patch-id.c +++ b/patch-id.c @@ -1,6 +1,6 @@ #include "cache.h" -static void flush_current_id(int patchlen, unsigned char *id, SHA_CTX *c) +static void flush_current_id(int patchlen, unsigned char *id, git_SHA_CTX *c) { unsigned char result[20]; char name[50]; @@ -8,10 +8,10 @@ static void flush_current_id(int patchlen, unsigned char *id, SHA_CTX *c) if (!patchlen) return; - SHA1_Final(result, c); + git_SHA1_Final(result, c); memcpy(name, sha1_to_hex(id), 41); printf("%s %s\n", sha1_to_hex(result), name); - SHA1_Init(c); + git_SHA1_Init(c); } static int remove_space(char *line) @@ -31,10 +31,10 @@ static void generate_id_list(void) { static unsigned char sha1[20]; static char line[1000]; - SHA_CTX ctx; + git_SHA_CTX ctx; int patchlen = 0; - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); while (fgets(line, sizeof(line), stdin) != NULL) { unsigned char n[20]; char *p = line; @@ -67,7 +67,7 @@ static void generate_id_list(void) /* Compute the sha without whitespace */ len = remove_space(line); patchlen += len; - SHA1_Update(&ctx, line, len); + git_SHA1_Update(&ctx, line, len); } flush_current_id(patchlen, sha1, &ctx); } diff --git a/ppc/sha1.c b/ppc/sha1.c index 738e36c1e8..ec6a1926d4 100644 --- a/ppc/sha1.c +++ b/ppc/sha1.c @@ -10,10 +10,10 @@ #include #include "sha1.h" -extern void sha1_core(uint32_t *hash, const unsigned char *p, - unsigned int nblocks); +extern void ppc_sha1_core(uint32_t *hash, const unsigned char *p, + unsigned int nblocks); -int SHA1_Init(SHA_CTX *c) +int ppc_SHA1_Init(ppc_SHA_CTX *c) { c->hash[0] = 0x67452301; c->hash[1] = 0xEFCDAB89; @@ -25,7 +25,7 @@ int SHA1_Init(SHA_CTX *c) return 0; } -int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) +int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *ptr, unsigned long n) { unsigned long nb; const unsigned char *p = ptr; @@ -38,12 +38,12 @@ int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) nb = n; memcpy(&c->buf.b[c->cnt], p, nb); if ((c->cnt += nb) == 64) { - sha1_core(c->hash, c->buf.b, 1); + ppc_sha1_core(c->hash, c->buf.b, 1); c->cnt = 0; } } else { nb = n >> 6; - sha1_core(c->hash, p, nb); + ppc_sha1_core(c->hash, p, nb); nb <<= 6; } n -= nb; @@ -52,7 +52,7 @@ int SHA1_Update(SHA_CTX *c, const void *ptr, unsigned long n) return 0; } -int SHA1_Final(unsigned char *hash, SHA_CTX *c) +int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c) { unsigned int cnt = c->cnt; @@ -60,13 +60,13 @@ int SHA1_Final(unsigned char *hash, SHA_CTX *c) if (cnt > 56) { if (cnt < 64) memset(&c->buf.b[cnt], 0, 64 - cnt); - sha1_core(c->hash, c->buf.b, 1); + ppc_sha1_core(c->hash, c->buf.b, 1); cnt = 0; } if (cnt < 56) memset(&c->buf.b[cnt], 0, 56 - cnt); c->buf.l[7] = c->len; - sha1_core(c->hash, c->buf.b, 1); + ppc_sha1_core(c->hash, c->buf.b, 1); memcpy(hash, c->hash, 20); return 0; } diff --git a/ppc/sha1.h b/ppc/sha1.h index c3c51aa4d4..c405f734c2 100644 --- a/ppc/sha1.h +++ b/ppc/sha1.h @@ -5,7 +5,7 @@ */ #include -typedef struct sha_context { +typedef struct { uint32_t hash[5]; uint32_t cnt; uint64_t len; @@ -13,8 +13,13 @@ typedef struct sha_context { unsigned char b[64]; uint64_t l[8]; } buf; -} SHA_CTX; +} ppc_SHA_CTX; -int SHA1_Init(SHA_CTX *c); -int SHA1_Update(SHA_CTX *c, const void *p, unsigned long n); -int SHA1_Final(unsigned char *hash, SHA_CTX *c); +int ppc_SHA1_Init(ppc_SHA_CTX *c); +int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *p, unsigned long n); +int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c); + +#define git_SHA_CTX ppc_SHA_CTX +#define git_SHA1_Init ppc_SHA1_Init +#define git_SHA1_Update ppc_SHA1_Update +#define git_SHA1_Final ppc_SHA1_Final diff --git a/ppc/sha1ppc.S b/ppc/sha1ppc.S index f132696ee7..1711eef6e7 100644 --- a/ppc/sha1ppc.S +++ b/ppc/sha1ppc.S @@ -162,8 +162,8 @@ add RE(t),RE(t),%r0; rotlwi RB(t),RB(t),30 STEPUP4(fn, (t)+12, (s)+12,); \ STEPUP4(fn, (t)+16, (s)+16, loadk) - .globl sha1_core -sha1_core: + .globl ppc_sha1_core +ppc_sha1_core: stwu %r1,-80(%r1) stmw %r13,4(%r1) diff --git a/read-cache.c b/read-cache.c index 5b1b3ad03b..901064bf1a 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1072,16 +1072,16 @@ struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really) static int verify_hdr(struct cache_header *hdr, unsigned long size) { - SHA_CTX c; + git_SHA_CTX c; unsigned char sha1[20]; if (hdr->hdr_signature != htonl(CACHE_SIGNATURE)) return error("bad signature"); if (hdr->hdr_version != htonl(2)) return error("bad index version"); - SHA1_Init(&c); - SHA1_Update(&c, hdr, size - 20); - SHA1_Final(sha1, &c); + git_SHA1_Init(&c); + git_SHA1_Update(&c, hdr, size - 20); + git_SHA1_Final(sha1, &c); if (hashcmp(sha1, (unsigned char *)hdr + size - 20)) return error("bad index file sha1 signature"); return 0; @@ -1278,11 +1278,11 @@ int unmerged_index(const struct index_state *istate) static unsigned char write_buffer[WRITE_BUFFER_SIZE]; static unsigned long write_buffer_len; -static int ce_write_flush(SHA_CTX *context, int fd) +static int ce_write_flush(git_SHA_CTX *context, int fd) { unsigned int buffered = write_buffer_len; if (buffered) { - SHA1_Update(context, write_buffer, buffered); + git_SHA1_Update(context, write_buffer, buffered); if (write_in_full(fd, write_buffer, buffered) != buffered) return -1; write_buffer_len = 0; @@ -1290,7 +1290,7 @@ static int ce_write_flush(SHA_CTX *context, int fd) return 0; } -static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) +static int ce_write(git_SHA_CTX *context, int fd, void *data, unsigned int len) { while (len) { unsigned int buffered = write_buffer_len; @@ -1312,7 +1312,7 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len) return 0; } -static int write_index_ext_header(SHA_CTX *context, int fd, +static int write_index_ext_header(git_SHA_CTX *context, int fd, unsigned int ext, unsigned int sz) { ext = htonl(ext); @@ -1321,13 +1321,13 @@ static int write_index_ext_header(SHA_CTX *context, int fd, (ce_write(context, fd, &sz, 4) < 0)) ? -1 : 0; } -static int ce_flush(SHA_CTX *context, int fd) +static int ce_flush(git_SHA_CTX *context, int fd) { unsigned int left = write_buffer_len; if (left) { write_buffer_len = 0; - SHA1_Update(context, write_buffer, left); + git_SHA1_Update(context, write_buffer, left); } /* Flush first if not enough space for SHA1 signature */ @@ -1338,7 +1338,7 @@ static int ce_flush(SHA_CTX *context, int fd) } /* Append the SHA1 signature at the end */ - SHA1_Final(write_buffer + left, context); + git_SHA1_Final(write_buffer + left, context); left += 20; return (write_in_full(fd, write_buffer, left) != left) ? -1 : 0; } @@ -1392,7 +1392,7 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce) } } -static int ce_write_entry(SHA_CTX *c, int fd, struct cache_entry *ce) +static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce) { int size = ondisk_ce_size(ce); struct ondisk_cache_entry *ondisk = xcalloc(1, size); @@ -1416,7 +1416,7 @@ static int ce_write_entry(SHA_CTX *c, int fd, struct cache_entry *ce) int write_index(const struct index_state *istate, int newfd) { - SHA_CTX c; + git_SHA_CTX c; struct cache_header hdr; int i, err, removed; struct cache_entry **cache = istate->cache; @@ -1430,7 +1430,7 @@ int write_index(const struct index_state *istate, int newfd) hdr.hdr_version = htonl(2); hdr.hdr_entries = htonl(entries - removed); - SHA1_Init(&c); + git_SHA1_Init(&c); if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0) return -1; diff --git a/rerere.c b/rerere.c index 8447caeebc..121f911414 100644 --- a/rerere.c +++ b/rerere.c @@ -73,7 +73,7 @@ static int write_rr(struct string_list *rr, int out_fd) static int handle_file(const char *path, unsigned char *sha1, const char *output) { - SHA_CTX ctx; + git_SHA_CTX ctx; char buf[1024]; int hunk_no = 0; enum { @@ -95,7 +95,7 @@ static int handle_file(const char *path, } if (sha1) - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); strbuf_init(&one, 0); strbuf_init(&two, 0); @@ -127,9 +127,9 @@ static int handle_file(const char *path, fputs(">>>>>>>\n", out); } if (sha1) { - SHA1_Update(&ctx, one.buf ? one.buf : "", + git_SHA1_Update(&ctx, one.buf ? one.buf : "", one.len + 1); - SHA1_Update(&ctx, two.buf ? two.buf : "", + git_SHA1_Update(&ctx, two.buf ? two.buf : "", two.len + 1); } strbuf_reset(&one); @@ -154,7 +154,7 @@ static int handle_file(const char *path, if (out) fclose(out); if (sha1) - SHA1_Final(sha1, &ctx); + git_SHA1_Final(sha1, &ctx); if (hunk != RR_CONTEXT) { if (output) unlink(output); diff --git a/sha1_file.c b/sha1_file.c index 70ff904717..7515987868 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2132,16 +2132,16 @@ static void write_sha1_file_prepare(const void *buf, unsigned long len, const char *type, unsigned char *sha1, char *hdr, int *hdrlen) { - SHA_CTX c; + git_SHA_CTX c; /* Generate the header */ *hdrlen = sprintf(hdr, "%s %lu", type, len)+1; /* Sha1.. */ - SHA1_Init(&c); - SHA1_Update(&c, hdr, *hdrlen); - SHA1_Update(&c, buf, len); - SHA1_Final(sha1, &c); + git_SHA1_Init(&c); + git_SHA1_Update(&c, hdr, *hdrlen); + git_SHA1_Update(&c, buf, len); + git_SHA1_Final(sha1, &c); } /* diff --git a/test-sha1.c b/test-sha1.c index 78d7e983a7..9b98d07c78 100644 --- a/test-sha1.c +++ b/test-sha1.c @@ -2,7 +2,7 @@ int main(int ac, char **av) { - SHA_CTX ctx; + git_SHA_CTX ctx; unsigned char sha1[20]; unsigned bufsz = 8192; char *buffer; @@ -20,7 +20,7 @@ int main(int ac, char **av) die("OOPS"); } - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); while (1) { ssize_t sz, this_sz; @@ -39,9 +39,9 @@ int main(int ac, char **av) } if (this_sz == 0) break; - SHA1_Update(&ctx, buffer, this_sz); + git_SHA1_Update(&ctx, buffer, this_sz); } - SHA1_Final(sha1, &ctx); + git_SHA1_Final(sha1, &ctx); puts(sha1_to_hex(sha1)); exit(0); } -- cgit v1.3 From 71b989e7dd1dcf891369319cfeda0ed8b6a152e1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 5 Oct 2008 15:35:15 -0400 Subject: fix bogus "diff --git" header from "diff --no-index" When "git diff --no-index" is given an absolute pathname, it would generate a diff header with the absolute path prepended by the prefix, like: diff --git a/dev/null b/foo Not only is this nonsensical, and not only does it violate the description of diffs given in git-diff(1), but it would produce broken binary diffs. Unlike text diffs, the binary diffs don't contain the filenames anywhere else, and so "git apply" relies on this header to figure out the filename. This patch just refuses to use an invalid name for anything visible in the diff. Now, this fixes the "git diff --no-index --binary a /dev/null" kind of case (and we'll end up using "a" as the basename), but some other insane cases are impossible to handle. If you do git diff --no-index --binary a /bin/echo you'll still get a patch like diff --git a/a b/bin/echo old mode 100644 new mode 100755 index ... and "git apply" will refuse to apply it for a couple of reasons, and the diff is simply bogus. And that, btw, is no longer a bug, I think. It's impossible to know whethe the user meant for the patch to be a rename or not. And as such, refusing to apply it because you don't know what name you should use is probably _exactly_ the right thing to do! Original problem reported by Imre Deak. Test script and problem description by Jeff King. Signed-off-by: Jeff King Signed-off-by: Linus Torvalds Signed-off-by: Shawn O. Pearce --- diff.c | 4 ++++ t/t4012-diff-binary.sh | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 781fa15ac1..f91f256c56 100644 --- a/diff.c +++ b/diff.c @@ -1465,6 +1465,10 @@ static void builtin_diff(const char *name_a, const char *set = diff_get_color_opt(o, DIFF_METAINFO); const char *reset = diff_get_color_opt(o, DIFF_RESET); + /* Never use a non-valid filename anywhere if at all possible */ + name_a = DIFF_FILE_VALID(one) ? name_a : name_b; + name_b = DIFF_FILE_VALID(two) ? name_b : name_a; + a_one = quote_two(o->a_prefix, name_a + (*name_a == '/')); b_two = quote_two(o->b_prefix, name_b + (*name_b == '/')); lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 64c372a025..eac12712db 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -77,4 +77,25 @@ test_expect_success 'apply binary patch' \ tree1=`git write-tree` && test "$tree1" = "$tree0"' +q_to_nul() { + perl -pe 'y/Q/\000/' +} + +nul_to_q() { + perl -pe 'y/\000/Q/' +} + +test_expect_success 'diff --no-index with binary creation' ' + echo Q | q_to_nul >binary && + (:# hide error code from diff, which just indicates differences + git diff --binary --no-index /dev/null binary >current || + true + ) && + rm binary && + git apply --binary expected && + nul_to_q actual && + test_cmp expected actual +' + test_done -- cgit v1.3 From 5d1e958e2467ef295637844fd85be7a8ab187ef1 Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Wed, 1 Oct 2008 00:46:34 +0100 Subject: Teach git diff about Objective-C syntax Add support for recognition of Objective-C class & instance methods, C functions, and class implementation/interfaces. Signed-off-by: Jonathan del Strother Signed-off-by: Shawn O. Pearce --- Documentation/gitattributes.txt | 2 ++ diff.c | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'diff.c') diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 2ae771f2fb..26945593cb 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -315,6 +315,8 @@ patterns are available: - `java` suitable for source code in the Java language. +- `objc` suitable for source code in the Objective-C language. + - `pascal` suitable for source code in the Pascal/Delphi language. - `php` suitable for source code in the PHP language. diff --git a/diff.c b/diff.c index 02e948c9dd..2af3a97487 100644 --- a/diff.c +++ b/diff.c @@ -1429,6 +1429,16 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", REG_EXTENDED }, + { "objc", + /* Negate C statements that can look like functions */ + "!^[ \t]*(do|for|if|else|return|switch|while)\n" + /* Objective-C methods */ + "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n" + /* C functions */ + "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n" + /* Objective-C class/protocol definitions */ + "^(@(implementation|interface|protocol)[ \t].*)$", + REG_EXTENDED }, { "pascal", "^((procedure|function|constructor|destructor|interface|" "implementation|initialization|finalization)[ \t]*.*)$" -- cgit v1.3 From f285a2d7ed6548666989406de8f0e7233eb84368 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 9 Oct 2008 14:12:12 -0500 Subject: Replace calls to strbuf_init(&foo, 0) with STRBUF_INIT initializer Many call sites use strbuf_init(&foo, 0) to initialize local strbuf variable "foo" which has not been accessed since its declaration. These can be replaced with a static initialization using the STRBUF_INIT macro which is just as readable, saves a function call, and takes up fewer lines. Signed-off-by: Brandon Casey Signed-off-by: Shawn O. Pearce --- archive-tar.c | 6 ++---- archive.c | 6 ++---- builtin-apply.c | 26 ++++++++------------------ builtin-blame.c | 3 +-- builtin-branch.c | 3 +-- builtin-cat-file.c | 3 +-- builtin-checkout-index.c | 4 +--- builtin-checkout.c | 12 ++++-------- builtin-clean.c | 6 ++---- builtin-clone.c | 9 +++------ builtin-commit.c | 15 +++++---------- builtin-fetch--tool.c | 3 +-- builtin-fmt-merge-msg.c | 4 +--- builtin-help.c | 4 +--- builtin-log.c | 13 ++++--------- builtin-merge.c | 27 +++++++++------------------ builtin-remote.c | 8 ++------ builtin-rev-list.c | 3 +-- builtin-rev-parse.c | 4 +--- builtin-show-branch.c | 3 +-- builtin-stripspace.c | 3 +-- builtin-tag.c | 3 +-- builtin-update-index.c | 10 +++------- combine-diff.c | 3 +-- config.c | 6 ++---- convert.c | 3 +-- diff.c | 15 +++++---------- editor.c | 3 +-- exec_cmd.c | 4 +--- fsck.c | 3 +-- git.c | 3 +-- graph.c | 13 ++++--------- hash-object.c | 4 +--- imap-send.c | 3 +-- log-tree.c | 3 +-- merge-recursive.c | 3 +-- mktag.c | 3 +-- mktree.c | 6 ++---- pretty.c | 3 +-- read-cache.c | 3 +-- remote.c | 3 +-- rerere.c | 4 +--- sha1_file.c | 6 ++---- walker.c | 3 +-- ws.c | 3 +-- wt-status.c | 10 +++------- 46 files changed, 91 insertions(+), 197 deletions(-) (limited to 'diff.c') diff --git a/archive-tar.c b/archive-tar.c index 13029619e5..ba890ebdec 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -124,11 +124,10 @@ static int write_tar_entry(struct archiver_args *args, unsigned int mode, void *buffer, unsigned long size) { struct ustar_header header; - struct strbuf ext_header; + struct strbuf ext_header = STRBUF_INIT; int err = 0; memset(&header, 0, sizeof(header)); - strbuf_init(&ext_header, 0); if (!sha1) { *header.typeflag = TYPEFLAG_GLOBAL_HEADER; @@ -211,10 +210,9 @@ static int write_tar_entry(struct archiver_args *args, static int write_global_extended_header(struct archiver_args *args) { const unsigned char *sha1 = args->commit_sha1; - struct strbuf ext_header; + struct strbuf ext_header = STRBUF_INIT; int err; - strbuf_init(&ext_header, 0); strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40); err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf, ext_header.len); diff --git a/archive.c b/archive.c index 44ab008039..849eed553e 100644 --- a/archive.c +++ b/archive.c @@ -29,11 +29,10 @@ static void format_subst(const struct commit *commit, struct strbuf *buf) { char *to_free = NULL; - struct strbuf fmt; + struct strbuf fmt = STRBUF_INIT; if (src == buf->buf) to_free = strbuf_detach(buf, NULL); - strbuf_init(&fmt, 0); for (;;) { const char *b, *c; @@ -65,10 +64,9 @@ static void *sha1_file_to_archive(const char *path, const unsigned char *sha1, buffer = read_sha1_file(sha1, type, sizep); if (buffer && S_ISREG(mode)) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; size_t size = 0; - strbuf_init(&buf, 0); strbuf_attach(&buf, buffer, *sizep, *sizep + 1); convert_to_working_tree(path, buf.buf, buf.len, &buf); if (commit) diff --git a/builtin-apply.c b/builtin-apply.c index bf80610506..f1f675819f 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -321,13 +321,12 @@ static char *find_name(const char *line, char *def, int p_value, int terminate) const char *start = line; if (*line == '"') { - struct strbuf name; + struct strbuf name = STRBUF_INIT; /* * Proposed "new-style" GNU patch/diff format; see * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2 */ - strbuf_init(&name, 0); if (!unquote_c_style(&name, line, NULL)) { char *cp; @@ -675,11 +674,8 @@ static char *git_header_name(char *line, int llen) if (*line == '"') { const char *cp; - struct strbuf first; - struct strbuf sp; - - strbuf_init(&first, 0); - strbuf_init(&sp, 0); + struct strbuf first = STRBUF_INIT; + struct strbuf sp = STRBUF_INIT; if (unquote_c_style(&first, line, &second)) goto free_and_fail1; @@ -741,10 +737,9 @@ static char *git_header_name(char *line, int llen) */ for (second = name; second < line + llen; second++) { if (*second == '"') { - struct strbuf sp; + struct strbuf sp = STRBUF_INIT; const char *np; - strbuf_init(&sp, 0); if (unquote_c_style(&sp, second, NULL)) goto free_and_fail2; @@ -1508,11 +1503,10 @@ static const char minuses[]= static void show_stats(struct patch *patch) { - struct strbuf qname; + struct strbuf qname = STRBUF_INIT; char *cp = patch->new_name ? patch->new_name : patch->old_name; int max, add, del; - strbuf_init(&qname, 0); quote_c_style(cp, &qname, NULL, 0); /* @@ -2292,14 +2286,12 @@ static void add_to_fn_table(struct patch *patch) static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; struct image image; size_t len; char *img; struct patch *tpatch; - strbuf_init(&buf, 0); - if (!(patch->is_copy || patch->is_rename) && ((tpatch = in_fn_table(patch->old_name)) != NULL)) { if (tpatch == (struct patch *) -1) { @@ -2779,7 +2771,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { int fd; - struct strbuf nbuf; + struct strbuf nbuf = STRBUF_INIT; if (S_ISGITLINK(mode)) { struct stat st; @@ -2798,7 +2790,6 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, if (fd < 0) return -1; - strbuf_init(&nbuf, 0); if (convert_to_working_tree(path, buf, size, &nbuf)) { size = nbuf.len; buf = nbuf.buf; @@ -3060,13 +3051,12 @@ static void prefix_patches(struct patch *p) static int apply_patch(int fd, const char *filename, int options) { size_t offset; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; struct patch *list = NULL, **listp = &list; int skipped_patch = 0; /* FIXME - memory leak when using multiple patch files as inputs */ memset(&fn_table, 0, sizeof(struct string_list)); - strbuf_init(&buf, 0); patch_input_file = filename; read_patch_file(&buf, fd); offset = 0; diff --git a/builtin-blame.c b/builtin-blame.c index df537593d0..48cc0c175d 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2062,7 +2062,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con struct commit *commit; struct origin *origin; unsigned char head_sha1[20]; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; const char *ident; time_t now; int size, len; @@ -2082,7 +2082,6 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con origin = make_origin(commit, path); - strbuf_init(&buf, 0); if (!contents_from || strcmp("-", contents_from)) { struct stat st; const char *read_from; diff --git a/builtin-branch.c b/builtin-branch.c index b1a2ad7a6b..8d634ff571 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -334,11 +334,10 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose, } if (verbose) { - struct strbuf subject; + struct strbuf subject = STRBUF_INIT; const char *sub = " **** invalid ref ****"; char stat[128]; - strbuf_init(&subject, 0); stat[0] = '\0'; commit = item->commit; diff --git a/builtin-cat-file.c b/builtin-cat-file.c index 3fba6b9e74..30d00a6664 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -189,9 +189,8 @@ static int batch_one_object(const char *obj_name, int print_contents) static int batch_objects(int print_contents) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; - strbuf_init(&buf, 0); while (strbuf_getline(&buf, stdin, '\n') != EOF) { int error = batch_one_object(buf.buf, print_contents); if (error) diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 55b7aafe06..4ba27024c5 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -268,13 +268,11 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) } if (read_from_stdin) { - struct strbuf buf, nbuf; + struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; if (all) die("git checkout-index: don't mix '--all' and '--stdin'"); - strbuf_init(&buf, 0); - strbuf_init(&nbuf, 0); while (strbuf_getline(&buf, stdin, line_termination) != EOF) { const char *p; if (line_termination && buf.buf[0] == '"') { diff --git a/builtin-checkout.c b/builtin-checkout.c index 3762f71aae..ad04a184a2 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -310,8 +310,7 @@ static void show_local_changes(struct object *head) static void describe_detached_head(char *msg, struct commit *commit) { - struct strbuf sb; - strbuf_init(&sb, 0); + struct strbuf sb = STRBUF_INIT; parse_commit(commit); pretty_print_commit(CMIT_FMT_ONELINE, commit, &sb, 0, NULL, NULL, 0, 0); fprintf(stderr, "%s %s... %s\n", msg, @@ -360,8 +359,7 @@ struct branch_info { static void setup_branch_path(struct branch_info *branch) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; strbuf_addstr(&buf, "refs/heads/"); strbuf_addstr(&buf, branch->name); branch->path = strbuf_detach(&buf, NULL); @@ -484,7 +482,7 @@ static void update_refs_for_switch(struct checkout_opts *opts, struct branch_info *old, struct branch_info *new) { - struct strbuf msg; + struct strbuf msg = STRBUF_INIT; const char *old_desc; if (opts->new_branch) { create_branch(old->name, opts->new_branch, new->name, 0, @@ -493,7 +491,6 @@ static void update_refs_for_switch(struct checkout_opts *opts, setup_branch_path(new); } - strbuf_init(&msg, 0); old_desc = old->name; if (!old_desc) old_desc = sha1_to_hex(old->commit->object.sha1); @@ -738,8 +735,7 @@ no_reference: } if (opts.new_branch) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; strbuf_addstr(&buf, "refs/heads/"); strbuf_addstr(&buf, opts.new_branch); if (!get_sha1(buf.buf, rev)) diff --git a/builtin-clean.c b/builtin-clean.c index 48bf29f40a..f78c2fb108 100644 --- a/builtin-clean.c +++ b/builtin-clean.c @@ -31,11 +31,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix) int i; int show_only = 0, remove_directories = 0, quiet = 0, ignored = 0; int ignored_only = 0, baselen = 0, config_set = 0, errors = 0; - struct strbuf directory; + struct strbuf directory = STRBUF_INIT; struct dir_struct dir; const char *path, *base; static const char **pathspec; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; const char *qname; char *seen = NULL; struct option options[] = { @@ -58,7 +58,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, options, builtin_clean_usage, 0); - strbuf_init(&buf, 0); memset(&dir, 0, sizeof(dir)); if (ignored_only) dir.show_ignored = 1; @@ -88,7 +87,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (baselen) path = base = xmemdupz(*pathspec, baselen); read_directory(&dir, path, base, baselen, pathspec); - strbuf_init(&directory, 0); if (pathspec) seen = xmalloc(argc > 0 ? argc : 1); diff --git a/builtin-clone.c b/builtin-clone.c index 49d2eb9c2b..1ddc14b9c7 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -264,10 +264,9 @@ pid_t junk_pid; static void remove_junk(void) { - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; if (getpid() != junk_pid) return; - strbuf_init(&sb, 0); if (junk_git_dir) { strbuf_addstr(&sb, junk_git_dir); remove_dir_recursively(&sb, 0); @@ -354,7 +353,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) char *path, *dir; const struct ref *refs, *head_points_at, *remote_head, *mapped_refs; char branch_top[256], key[256], value[256]; - struct strbuf reflog_msg; + struct strbuf reflog_msg = STRBUF_INIT; struct transport *transport = NULL; char *src_ref_prefix = "refs/heads/"; @@ -404,7 +403,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (!stat(dir, &buf)) die("destination directory '%s' already exists.", dir); - strbuf_init(&reflog_msg, 0); strbuf_addf(&reflog_msg, "clone: from %s", repo); if (option_bare) @@ -526,7 +524,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) create_symref("HEAD", head_points_at->name, NULL); if (!option_bare) { - struct strbuf head_ref; + struct strbuf head_ref = STRBUF_INIT; const char *head = head_points_at->name; if (!prefixcmp(head, "refs/heads/")) @@ -539,7 +537,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) head_points_at->old_sha1, NULL, 0, DIE_ON_ERR); - strbuf_init(&head_ref, 0); strbuf_addstr(&head_ref, branch_top); strbuf_addstr(&head_ref, "HEAD"); diff --git a/builtin-commit.c b/builtin-commit.c index b920257524..a2755dc3be 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -448,7 +448,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix) { struct stat statbuf; int commitable, saved_color_setting; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; char *buffer; FILE *fp; const char *hook_arg1 = NULL; @@ -458,7 +458,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix) if (!no_verify && run_hook(index_file, "pre-commit", NULL)) return 0; - strbuf_init(&sb, 0); if (message.len) { strbuf_addbuf(&sb, &message); hook_arg1 = "message"; @@ -511,10 +510,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix) stripspace(&sb, 0); if (signoff) { - struct strbuf sob; + struct strbuf sob = STRBUF_INIT; int i; - strbuf_init(&sob, 0); strbuf_addstr(&sob, sign_off_header); strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"), getenv("GIT_COMMITTER_EMAIL"))); @@ -672,7 +670,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix) */ static int message_is_empty(struct strbuf *sb) { - struct strbuf tmpl; + struct strbuf tmpl = STRBUF_INIT; const char *nl; int eol, i, start = 0; @@ -680,7 +678,6 @@ static int message_is_empty(struct strbuf *sb) return 0; /* See if the template is just a prefix of the message. */ - strbuf_init(&tmpl, 0); if (template_file && strbuf_read_file(&tmpl, template_file, 0) > 0) { stripspace(&tmpl, cleanup_mode == CLEANUP_ALL); if (start + tmpl.len <= sb->len && @@ -931,7 +928,7 @@ static const char commit_utf8_warn[] = int cmd_commit(int argc, const char **argv, const char *prefix) { - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; const char *index_file, *reflog_msg; char *nl, *p; unsigned char commit_sha1[20]; @@ -966,12 +963,11 @@ int cmd_commit(int argc, const char **argv, const char *prefix) for (c = commit->parents; c; c = c->next) pptr = &commit_list_insert(c->item, pptr)->next; } else if (in_merge) { - struct strbuf m; + struct strbuf m = STRBUF_INIT; FILE *fp; reflog_msg = "commit (merge)"; pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; - strbuf_init(&m, 0); fp = fopen(git_path("MERGE_HEAD"), "r"); if (fp == NULL) die("could not open %s for reading: %s", @@ -991,7 +987,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix) parents = reduce_heads(parents); /* Finally, get the commit message */ - strbuf_init(&sb, 0); if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) { rollback_index_files(); die("could not read commit message"); diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 7460ab7fce..469b07e240 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -5,8 +5,7 @@ static char *get_stdin(void) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; if (strbuf_read(&buf, 0, 1024) < 0) { die("error reading standard input: %s", strerror(errno)); } diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index c6324dc795..df18f4070f 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -358,7 +358,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) }; FILE *in = stdin; - struct strbuf input, output; + struct strbuf input = STRBUF_INIT, output = STRBUF_INIT; int ret; git_config(fmt_merge_msg_config, NULL); @@ -372,10 +372,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) die("cannot open %s", inpath); } - strbuf_init(&input, 0); if (strbuf_read(&input, fileno(in), 0) < 0) die("could not read input file %s", strerror(errno)); - strbuf_init(&output, 0); ret = fmt_merge_msg(merge_summary, &input, &output); if (ret) diff --git a/builtin-help.c b/builtin-help.c index 64207cbfe9..f076efa921 100644 --- a/builtin-help.c +++ b/builtin-help.c @@ -322,11 +322,9 @@ static const char *cmd_to_page(const char *git_cmd) static void setup_man_path(void) { - struct strbuf new_path; + struct strbuf new_path = STRBUF_INIT; const char *old_path = getenv("MANPATH"); - strbuf_init(&new_path, 0); - /* We should always put ':' after our path. If there is no * old_path, the ':' at the end will let 'man' to try * system-wide paths after ours to find the manual page. If diff --git a/builtin-log.c b/builtin-log.c index fc5e4da822..794821f6bc 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -628,10 +628,9 @@ static void gen_message_id(struct rev_info *info, char *base) const char *committer = git_committer_info(IDENT_WARN_ON_NO_NAME); const char *email_start = strrchr(committer, '<'); const char *email_end = strrchr(committer, '>'); - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; if (!email_start || !email_end || email_start > email_end - 1) die("Could not extract email from committer identity."); - strbuf_init(&buf, 0); strbuf_addf(&buf, "%s.%lu.git.%.*s", base, (unsigned long) time(NULL), (int)(email_end - email_start - 1), email_start + 1); @@ -650,7 +649,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, const char *msg; const char *extra_headers = rev->extra_headers; struct shortlog log; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; int i; const char *encoding = "utf-8"; struct diff_options opts; @@ -671,7 +670,6 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout, committer = git_committer_info(0); msg = body; - strbuf_init(&sb, 0); pp_user_info(NULL, CMIT_FMT_EMAIL, &sb, committer, DATE_RFC2822, encoding); pp_title_line(CMIT_FMT_EMAIL, &msg, &sb, subject_start, extra_headers, @@ -753,7 +751,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) const char *in_reply_to = NULL; struct patch_ids ids; char *add_signoff = NULL; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; git_config(git_format_config, NULL); init_revisions(&rev, prefix); @@ -861,8 +859,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } argc = j; - strbuf_init(&buf, 0); - for (i = 0; i < extra_hdr_nr; i++) { strbuf_addstr(&buf, extra_hdr[i]); strbuf_addch(&buf, '\n'); @@ -1139,8 +1135,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; pretty_print_commit(CMIT_FMT_ONELINE, commit, &buf, 0, NULL, NULL, 0, 0); printf("%c %s %s\n", sign, diff --git a/builtin-merge.c b/builtin-merge.c index 38266baf5f..5e2b7f12c3 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -226,7 +226,7 @@ static void reset_hard(unsigned const char *sha1, int verbose) static void restore_state(void) { - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; const char *args[] = { "stash", "apply", NULL, NULL }; if (is_null_sha1(stash)) @@ -234,7 +234,6 @@ static void restore_state(void) reset_hard(head, 1); - strbuf_init(&sb, 0); args[2] = sha1_to_hex(stash); /* @@ -258,7 +257,7 @@ static void squash_message(void) { struct rev_info rev; struct commit *commit; - struct strbuf out; + struct strbuf out = STRBUF_INIT; struct commit_list *j; int fd; @@ -282,7 +281,6 @@ static void squash_message(void) if (prepare_revision_walk(&rev)) die("revision walk setup failed"); - strbuf_init(&out, 0); strbuf_addstr(&out, "Squashed commit of the following:\n"); while ((commit = get_revision(&rev)) != NULL) { strbuf_addch(&out, '\n'); @@ -327,9 +325,8 @@ static int run_hook(const char *name) static void finish(const unsigned char *new_head, const char *msg) { - struct strbuf reflog_message; + struct strbuf reflog_message = STRBUF_INIT; - strbuf_init(&reflog_message, 0); if (!msg) strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION")); else { @@ -380,7 +377,7 @@ static void merge_name(const char *remote, struct strbuf *msg) { struct object *remote_head; unsigned char branch_head[20], buf_sha[20]; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; const char *ptr; int len, early; @@ -389,7 +386,6 @@ static void merge_name(const char *remote, struct strbuf *msg) if (!remote_head) die("'%s' does not point to a commit", remote); - strbuf_init(&buf, 0); strbuf_addstr(&buf, "refs/heads/"); strbuf_addstr(&buf, remote); resolve_ref(buf.buf, branch_head, 0, 0); @@ -444,10 +440,9 @@ static void merge_name(const char *remote, struct strbuf *msg) if (!strcmp(remote, "FETCH_HEAD") && !access(git_path("FETCH_HEAD"), R_OK)) { FILE *fp; - struct strbuf line; + struct strbuf line = STRBUF_INIT; char *ptr; - strbuf_init(&line, 0); fp = fopen(git_path("FETCH_HEAD"), "r"); if (!fp) die("could not open %s for reading: %s", @@ -545,7 +540,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, const char **args; int i = 0, ret; struct commit_list *j; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; int index_fd; struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); @@ -592,7 +587,6 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, } else { args = xmalloc((4 + commit_list_count(common) + commit_list_count(remoteheads)) * sizeof(char *)); - strbuf_init(&buf, 0); strbuf_addf(&buf, "merge-%s", strategy); args[i++] = buf.buf; for (j = common; j; j = j->next) @@ -847,7 +841,7 @@ static int evaluate_result(void) int cmd_merge(int argc, const char **argv, const char *prefix) { unsigned char result_tree[20]; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; const char *head_arg; int flag, head_invalid = 0, i; int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0; @@ -896,7 +890,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * Traditional format never would have "-m" so it is an * additional safety measure to check for it. */ - strbuf_init(&buf, 0); if (!have_message && is_old_style_invocation(argc, argv)) { strbuf_addstr(&merge_msg, argv[0]); @@ -926,7 +919,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) reset_hard(remote_head->sha1, 0); return 0; } else { - struct strbuf msg; + struct strbuf msg = STRBUF_INIT; /* We are invoked directly as the first-class UI. */ head_arg = "HEAD"; @@ -939,7 +932,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) * codepath so we discard the error in this * loop. */ - strbuf_init(&msg, 0); for (i = 0; i < argc; i++) merge_name(argv[i], &msg); fmt_merge_msg(option_log, &msg, &merge_msg); @@ -1014,7 +1006,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix) !common->next && !hashcmp(common->item->object.sha1, head)) { /* Again the most common case of merging one remote. */ - struct strbuf msg; + struct strbuf msg = STRBUF_INIT; struct object *o; char hex[41]; @@ -1024,7 +1016,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix) hex, find_unique_abbrev(remoteheads->item->object.sha1, DEFAULT_ABBREV)); - strbuf_init(&msg, 0); strbuf_addstr(&msg, "Fast forward"); if (have_message) strbuf_addstr(&msg, diff --git a/builtin-remote.c b/builtin-remote.c index 90a4e35828..6b3325dfa9 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -54,7 +54,7 @@ static int add(int argc, const char **argv) struct string_list track = { NULL, 0, 0 }; const char *master = NULL; struct remote *remote; - struct strbuf buf, buf2; + struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; const char *name, *url; int i; @@ -81,9 +81,6 @@ static int add(int argc, const char **argv) remote->fetch_refspec_nr)) die("remote %s already exists.", name); - strbuf_init(&buf, 0); - strbuf_init(&buf2, 0); - strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name); if (!valid_fetch_refspec(buf2.buf)) die("'%s' is not a valid remote name", name); @@ -352,7 +349,7 @@ static int rm(int argc, const char **argv) OPT_END() }; struct remote *remote; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; struct known_remotes known_remotes = { NULL, NULL }; struct string_list branches = { NULL, 0, 0, 1 }; struct branches_for_remote cb_data = { NULL, &branches, &known_remotes }; @@ -368,7 +365,6 @@ static int rm(int argc, const char **argv) known_remotes.to_delete = remote; for_each_remote(add_known_remote, &known_remotes); - strbuf_init(&buf, 0); strbuf_addf(&buf, "remote.%s", remote->name); if (git_config_rename_section(buf.buf, NULL) < 1) return error("Could not remove config section '%s'", buf.buf); diff --git a/builtin-rev-list.c b/builtin-rev-list.c index facaff288d..06cdeb7ebe 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -107,8 +107,7 @@ static void show_commit(struct commit *commit) putchar('\n'); if (revs.verbose_header && commit->buffer) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; pretty_print_commit(revs.commit_format, commit, &buf, revs.abbrev, NULL, NULL, revs.date_mode, 0); diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 9aa049ec17..81d5a6ffc9 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -307,19 +307,17 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix) OPT_END(), }; - struct strbuf sb, parsed; + struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT; const char **usage = NULL; struct option *opts = NULL; int onb = 0, osz = 0, unb = 0, usz = 0; - strbuf_init(&parsed, 0); strbuf_addstr(&parsed, "set --"); argc = parse_options(argc, argv, parseopt_opts, parseopt_usage, PARSE_OPT_KEEP_DASHDASH); if (argc < 1 || strcmp(argv[0], "--")) usage_with_options(parseopt_usage, parseopt_opts); - strbuf_init(&sb, 0); /* get the usage up to the first line with a -- on it */ for (;;) { if (strbuf_getline(&sb, stdin, '\n') == EOF) diff --git a/builtin-show-branch.c b/builtin-show-branch.c index 233eed499d..306b850c72 100644 --- a/builtin-show-branch.c +++ b/builtin-show-branch.c @@ -259,11 +259,10 @@ static void join_revs(struct commit_list **list_p, static void show_one_commit(struct commit *commit, int no_name) { - struct strbuf pretty; + struct strbuf pretty = STRBUF_INIT; const char *pretty_str = "(unavailable)"; struct commit_name *name = commit->util; - strbuf_init(&pretty, 0); if (commit->object.parsed) { pretty_print_commit(CMIT_FMT_ONELINE, commit, &pretty, 0, NULL, NULL, 0, 0); diff --git a/builtin-stripspace.c b/builtin-stripspace.c index c0b21301ba..d6e3896c00 100644 --- a/builtin-stripspace.c +++ b/builtin-stripspace.c @@ -70,14 +70,13 @@ void stripspace(struct strbuf *sb, int skip_comments) int cmd_stripspace(int argc, const char **argv, const char *prefix) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; int strip_comments = 0; if (argc > 1 && (!strcmp(argv[1], "-s") || !strcmp(argv[1], "--strip-comments"))) strip_comments = 1; - strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 1024) < 0) die("could not read the input"); diff --git a/builtin-tag.c b/builtin-tag.c index f2853d08c7..b13fa34d8c 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -338,7 +338,7 @@ static int parse_msg_arg(const struct option *opt, const char *arg, int unset) int cmd_tag(int argc, const char **argv, const char *prefix) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; unsigned char object[20], prev[20]; char ref[PATH_MAX]; const char *object_ref, *tag; @@ -388,7 +388,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix) if (verify) return for_each_tag_name(argv, verify_tag); - strbuf_init(&buf, 0); if (msg.given || msgfile) { if (msg.given && msgfile) die("only one -F or -m option is allowed."); diff --git a/builtin-update-index.c b/builtin-update-index.c index 3a2291b03e..65d5775107 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -297,11 +297,9 @@ static void update_one(const char *path, const char *prefix, int prefix_length) static void read_index_info(int line_termination) { - struct strbuf buf; - struct strbuf uq; + struct strbuf buf = STRBUF_INIT; + struct strbuf uq = STRBUF_INIT; - strbuf_init(&buf, 0); - strbuf_init(&uq, 0); while (strbuf_getline(&buf, stdin, line_termination) != EOF) { char *ptr, *tab; char *path_name; @@ -717,10 +715,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) free((char*)p); } if (read_from_stdin) { - struct strbuf buf, nbuf; + struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; - strbuf_init(&buf, 0); - strbuf_init(&nbuf, 0); setup_work_tree(); while (strbuf_getline(&buf, stdin, line_termination) != EOF) { const char *p; diff --git a/combine-diff.c b/combine-diff.c index de83c6972e..5aa1104d34 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -742,9 +742,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, /* If not a fake symlink, apply filters, e.g. autocrlf */ if (is_file) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; - strbuf_init(&buf, 0); if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) { free(result); result = strbuf_detach(&buf, &len); diff --git a/config.c b/config.c index 18d305c890..b8d289d217 100644 --- a/config.c +++ b/config.c @@ -753,9 +753,8 @@ static int store_write_section(int fd, const char* key) { const char *dot; int i, success; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; - strbuf_init(&sb, 0); dot = memchr(key, '.', store.baselen); if (dot) { strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key); @@ -780,7 +779,7 @@ static int store_write_pair(int fd, const char* key, const char* value) int i, success; int length = strlen(key + store.baselen + 1); const char *quote = ""; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; /* * Check to see if the value needs to be surrounded with a dq pair. @@ -797,7 +796,6 @@ static int store_write_pair(int fd, const char* key, const char* value) if (i && value[i - 1] == ' ') quote = "\""; - strbuf_init(&sb, 0); strbuf_addf(&sb, "\t%.*s = %s", length, key + store.baselen + 1, quote); diff --git a/convert.c b/convert.c index 78efed800d..1816e977b7 100644 --- a/convert.c +++ b/convert.c @@ -281,7 +281,7 @@ static int apply_filter(const char *path, const char *src, size_t len, * (child --> cmd) --> us */ int ret = 1; - struct strbuf nbuf; + struct strbuf nbuf = STRBUF_INIT; struct async async; struct filter_params params; @@ -299,7 +299,6 @@ static int apply_filter(const char *path, const char *src, size_t len, if (start_async(&async)) return 0; /* error was already reported */ - strbuf_init(&nbuf, 0); if (strbuf_read(&nbuf, async.out, len) < 0) { error("read from external filter %s failed", cmd); ret = 0; diff --git a/diff.c b/diff.c index 2af3a97487..1c6be897b2 100644 --- a/diff.c +++ b/diff.c @@ -217,9 +217,8 @@ static char *quote_two(const char *one, const char *two) { int need_one = quote_c_style(one, NULL, NULL, 1); int need_two = quote_c_style(two, NULL, NULL, 1); - struct strbuf res; + struct strbuf res = STRBUF_INIT; - strbuf_init(&res, 0); if (need_one + need_two) { strbuf_addch(&res, '"'); quote_c_style(one, &res, NULL, 1); @@ -683,7 +682,7 @@ static char *pprint_rename(const char *a, const char *b) { const char *old = a; const char *new = b; - struct strbuf name; + struct strbuf name = STRBUF_INIT; int pfx_length, sfx_length; int len_a = strlen(a); int len_b = strlen(b); @@ -691,7 +690,6 @@ static char *pprint_rename(const char *a, const char *b) int qlen_a = quote_c_style(a, NULL, NULL, 0); int qlen_b = quote_c_style(b, NULL, NULL, 0); - strbuf_init(&name, 0); if (qlen_a || qlen_b) { quote_c_style(a, &name, NULL, 0); strbuf_addstr(&name, " => "); @@ -834,8 +832,7 @@ static void fill_print_name(struct diffstat_file *file) return; if (!file->is_renamed) { - struct strbuf buf; - strbuf_init(&buf, 0); + struct strbuf buf = STRBUF_INIT; if (quote_c_style(file->name, &buf, NULL, 0)) { pname = strbuf_detach(&buf, NULL); } else { @@ -1820,10 +1817,9 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int static int populate_from_stdin(struct diff_filespec *s) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; size_t size = 0; - strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 0) < 0) return error("error while reading from stdin %s", strerror(errno)); @@ -1875,7 +1871,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (!s->sha1_valid || reuse_worktree_file(s->path, s->sha1, 0)) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; struct stat st; int fd; @@ -1918,7 +1914,6 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) /* * Convert from working tree format to canonical git format */ - strbuf_init(&buf, 0); if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) { size_t size = 0; munmap(s->data, s->size); diff --git a/editor.c b/editor.c index eebc3e95fe..4d469d076b 100644 --- a/editor.c +++ b/editor.c @@ -26,9 +26,8 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en int i = 0; int failed; const char *args[6]; - struct strbuf arg0; + struct strbuf arg0 = STRBUF_INIT; - strbuf_init(&arg0, 0); if (strcspn(editor, "$ \t'") != len) { /* there are specials */ strbuf_addf(&arg0, "%s \"$@\"", editor); diff --git a/exec_cmd.c b/exec_cmd.c index ce6741eb68..cdd35f9195 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -59,9 +59,7 @@ static void add_path(struct strbuf *out, const char *path) void setup_path(void) { const char *old_path = getenv("PATH"); - struct strbuf new_path; - - strbuf_init(&new_path, 0); + struct strbuf new_path = STRBUF_INIT; add_path(&new_path, argv_exec_path); add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT)); diff --git a/fsck.c b/fsck.c index 797e3178ae..0cf5f012bd 100644 --- a/fsck.c +++ b/fsck.c @@ -307,9 +307,8 @@ int fsck_error_function(struct object *obj, int type, const char *fmt, ...) { va_list ap; int len; - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; - strbuf_init(&sb, 0); strbuf_addf(&sb, "object %s:", obj->sha1?sha1_to_hex(obj->sha1):"(null)"); va_start(ap, fmt); diff --git a/git.c b/git.c index f4b0cf611b..89feb0b6dc 100644 --- a/git.c +++ b/git.c @@ -389,10 +389,9 @@ static void handle_internal_command(int argc, const char **argv) static void execv_dashed_external(const char **argv) { - struct strbuf cmd; + struct strbuf cmd = STRBUF_INIT; const char *tmp; - strbuf_init(&cmd, 0); strbuf_addf(&cmd, "git-%s", argv[0]); /* diff --git a/graph.c b/graph.c index 5f821706c6..162a516ee1 100644 --- a/graph.c +++ b/graph.c @@ -1010,14 +1010,12 @@ int graph_is_commit_finished(struct git_graph const *graph) void graph_show_commit(struct git_graph *graph) { - struct strbuf msgbuf; + struct strbuf msgbuf = STRBUF_INIT; int shown_commit_line = 0; if (!graph) return; - strbuf_init(&msgbuf, 0); - while (!shown_commit_line) { shown_commit_line = graph_next_line(graph, &msgbuf); fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); @@ -1031,12 +1029,11 @@ void graph_show_commit(struct git_graph *graph) void graph_show_oneline(struct git_graph *graph) { - struct strbuf msgbuf; + struct strbuf msgbuf = STRBUF_INIT; if (!graph) return; - strbuf_init(&msgbuf, 0); graph_next_line(graph, &msgbuf); fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); strbuf_release(&msgbuf); @@ -1044,12 +1041,11 @@ void graph_show_oneline(struct git_graph *graph) void graph_show_padding(struct git_graph *graph) { - struct strbuf msgbuf; + struct strbuf msgbuf = STRBUF_INIT; if (!graph) return; - strbuf_init(&msgbuf, 0); graph_padding_line(graph, &msgbuf); fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); strbuf_release(&msgbuf); @@ -1057,7 +1053,7 @@ void graph_show_padding(struct git_graph *graph) int graph_show_remainder(struct git_graph *graph) { - struct strbuf msgbuf; + struct strbuf msgbuf = STRBUF_INIT; int shown = 0; if (!graph) @@ -1066,7 +1062,6 @@ int graph_show_remainder(struct git_graph *graph) if (graph_is_commit_finished(graph)) return 0; - strbuf_init(&msgbuf, 0); for (;;) { graph_next_line(graph, &msgbuf); fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout); diff --git a/hash-object.c b/hash-object.c index a4d127cf78..20937ff94c 100644 --- a/hash-object.c +++ b/hash-object.c @@ -34,10 +34,8 @@ static void hash_object(const char *path, const char *type, int write_object, static void hash_stdin_paths(const char *type, int write_objects) { - struct strbuf buf, nbuf; + struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; - strbuf_init(&buf, 0); - strbuf_init(&nbuf, 0); while (strbuf_getline(&buf, stdin, '\n') != EOF) { if (buf.buf[0] == '"') { strbuf_reset(&nbuf); diff --git a/imap-send.c b/imap-send.c index af7e08c094..3703dbd1af 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1266,10 +1266,9 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data, int *uid) static int read_message(FILE *f, struct msg_data *msg) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; memset(msg, 0, sizeof(*msg)); - strbuf_init(&buf, 0); do { if (strbuf_fread(&buf, CHUNKSIZE, f) <= 0) diff --git a/log-tree.c b/log-tree.c index 2c1f3e673a..cec3c06136 100644 --- a/log-tree.c +++ b/log-tree.c @@ -252,7 +252,7 @@ void log_write_email_headers(struct rev_info *opt, const char *name, void show_log(struct rev_info *opt) { - struct strbuf msgbuf; + struct strbuf msgbuf = STRBUF_INIT; struct log_info *log = opt->loginfo; struct commit *commit = log->commit, *parent = log->parent; int abbrev = opt->diffopt.abbrev; @@ -381,7 +381,6 @@ void show_log(struct rev_info *opt) /* * And then the pretty-printed message itself */ - strbuf_init(&msgbuf, 0); if (need_8bit_cte >= 0) need_8bit_cte = has_non_ascii(opt->add_signoff); pretty_print_commit(opt->commit_format, commit, &msgbuf, diff --git a/merge-recursive.c b/merge-recursive.c index 6bc3eac85c..245232a408 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -498,8 +498,7 @@ static void update_file_flags(struct merge_options *o, if (type != OBJ_BLOB) die("blob expected for %s '%s'", sha1_to_hex(sha), path); if (S_ISREG(mode)) { - struct strbuf strbuf; - strbuf_init(&strbuf, 0); + struct strbuf strbuf = STRBUF_INIT; if (convert_to_working_tree(path, buf, size, &strbuf)) { free(buf); size = strbuf.len; diff --git a/mktag.c b/mktag.c index 0b34341f71..ba3d495e07 100644 --- a/mktag.c +++ b/mktag.c @@ -153,7 +153,7 @@ static int verify_tag(char *buffer, unsigned long size) int main(int argc, char **argv) { - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; unsigned char result_sha1[20]; if (argc != 1) @@ -161,7 +161,6 @@ int main(int argc, char **argv) setup_git_directory(); - strbuf_init(&buf, 0); if (strbuf_read(&buf, 0, 4096) < 0) { die("could not read from stdin"); } diff --git a/mktree.c b/mktree.c index e0da110a98..514fd9b15a 100644 --- a/mktree.c +++ b/mktree.c @@ -65,8 +65,8 @@ static const char mktree_usage[] = "git-mktree [-z]"; int main(int ac, char **av) { - struct strbuf sb; - struct strbuf p_uq; + struct strbuf sb = STRBUF_INIT; + struct strbuf p_uq = STRBUF_INIT; unsigned char sha1[20]; int line_termination = '\n'; @@ -82,8 +82,6 @@ int main(int ac, char **av) av++; } - strbuf_init(&sb, 0); - strbuf_init(&p_uq, 0); while (strbuf_getline(&sb, stdin, line_termination) != EOF) { char *ptr, *ntr; unsigned mode; diff --git a/pretty.c b/pretty.c index 8beafa08d3..1e79943339 100644 --- a/pretty.c +++ b/pretty.c @@ -234,7 +234,7 @@ static char *get_header(const struct commit *commit, const char *key) static char *replace_encoding_header(char *buf, const char *encoding) { - struct strbuf tmp; + struct strbuf tmp = STRBUF_INIT; size_t start, len; char *cp = buf; @@ -250,7 +250,6 @@ static char *replace_encoding_header(char *buf, const char *encoding) return buf; /* should not happen but be defensive */ len = cp + 1 - (buf + start); - strbuf_init(&tmp, 0); strbuf_attach(&tmp, buf, strlen(buf), strlen(buf) + 1); if (is_encoding_utf8(encoding)) { /* we have re-coded to UTF-8; drop the header */ diff --git a/read-cache.c b/read-cache.c index 6f344f345d..c229fd4d0d 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1467,9 +1467,8 @@ int write_index(const struct index_state *istate, int newfd) /* Write extension data here */ if (istate->cache_tree) { - struct strbuf sb; + struct strbuf sb = STRBUF_INIT; - strbuf_init(&sb, 0); cache_tree_write(&sb, istate->cache_tree); err = write_index_ext_header(&c, newfd, CACHE_EXT_TREE, sb.len) < 0 || ce_write(&c, newfd, sb.buf, sb.len) < 0; diff --git a/remote.c b/remote.c index a2d7ab146e..d5efadd93d 100644 --- a/remote.c +++ b/remote.c @@ -245,7 +245,7 @@ static void read_branches_file(struct remote *remote) { const char *slash = strchr(remote->name, '/'); char *frag; - struct strbuf branch; + struct strbuf branch = STRBUF_INIT; int n = slash ? slash - remote->name : 1000; FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r"); char *s, *p; @@ -283,7 +283,6 @@ static void read_branches_file(struct remote *remote) * #branch specified. The "master" (or specified) branch is * fetched and stored in the local branch of the same name. */ - strbuf_init(&branch, 0); frag = strchr(p, '#'); if (frag) { *(frag++) = '\0'; diff --git a/rerere.c b/rerere.c index 121f911414..5bb5316cda 100644 --- a/rerere.c +++ b/rerere.c @@ -79,7 +79,7 @@ static int handle_file(const char *path, enum { RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL, } hunk = RR_CONTEXT; - struct strbuf one, two; + struct strbuf one = STRBUF_INIT, two = STRBUF_INIT; FILE *f = fopen(path, "r"); FILE *out = NULL; @@ -97,8 +97,6 @@ static int handle_file(const char *path, if (sha1) git_SHA1_Init(&ctx); - strbuf_init(&one, 0); - strbuf_init(&two, 0); while (fgets(buf, sizeof(buf), f)) { if (!prefixcmp(buf, "<<<<<<< ")) { if (hunk != RR_CONTEXT) diff --git a/sha1_file.c b/sha1_file.c index ea6bd996b2..3fbb0820a0 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2386,8 +2386,7 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size, * Convert blobs to git internal format */ if ((type == OBJ_BLOB) && path) { - struct strbuf nbuf; - strbuf_init(&nbuf, 0); + struct strbuf nbuf = STRBUF_INIT; if (convert_to_git(path, buf, size, &nbuf, write_object ? safe_crlf : 0)) { buf = strbuf_detach(&nbuf, &size); @@ -2411,8 +2410,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, size_t size = xsize_t(st->st_size); if (!S_ISREG(st->st_mode)) { - struct strbuf sbuf; - strbuf_init(&sbuf, 0); + struct strbuf sbuf = STRBUF_INIT; if (strbuf_read(&sbuf, fd, 4096) >= 0) ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object, type, path); diff --git a/walker.c b/walker.c index 0e68ee6d2e..6b4cf70c6a 100644 --- a/walker.c +++ b/walker.c @@ -215,9 +215,8 @@ static int mark_complete(const char *path, const unsigned char *sha1, int flag, int walker_targets_stdin(char ***target, const char ***write_ref) { int targets = 0, targets_alloc = 0; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; *target = NULL; *write_ref = NULL; - strbuf_init(&buf, 0); while (1) { char *rf_one = NULL; char *tg_one; diff --git a/ws.c b/ws.c index 7a7ff130a3..b1efcd9d75 100644 --- a/ws.c +++ b/ws.c @@ -99,8 +99,7 @@ unsigned whitespace_rule(const char *pathname) /* The returned string should be freed by the caller. */ char *whitespace_error_string(unsigned ws) { - struct strbuf err; - strbuf_init(&err, 0); + struct strbuf err = STRBUF_INIT; if (ws & WS_TRAILING_SPACE) strbuf_addstr(&err, "trailing whitespace"); if (ws & WS_SPACE_BEFORE_TAB) { diff --git a/wt-status.c b/wt-status.c index 7cf890f243..d2eac36aea 100644 --- a/wt-status.c +++ b/wt-status.c @@ -103,10 +103,8 @@ static void wt_status_print_filepair(struct wt_status *s, { const char *c = color(t); const char *one, *two; - struct strbuf onebuf, twobuf; + struct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT; - strbuf_init(&onebuf, 0); - strbuf_init(&twobuf, 0); one = quote_path(p->one->path, -1, &onebuf, s->prefix); two = quote_path(p->two->path, -1, &twobuf, s->prefix); @@ -190,9 +188,8 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q, static void wt_status_print_initial(struct wt_status *s) { int i; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; - strbuf_init(&buf, 0); if (active_nr) { s->commitable = 1; wt_status_print_cached_header(s); @@ -268,9 +265,8 @@ static void wt_status_print_untracked(struct wt_status *s) struct dir_struct dir; int i; int shown_header = 0; - struct strbuf buf; + struct strbuf buf = STRBUF_INIT; - strbuf_init(&buf, 0); memset(&dir, 0, sizeof(dir)); if (!s->untracked) { -- cgit v1.3 From be58e70dbadf3cb3f4aa5829d513d886ae8bc460 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 5 Oct 2008 17:43:21 -0400 Subject: diff: unify external diff and funcname parsing code Both sets of code assume that one specifies a diff profile as a gitattribute via the "diff=foo" attribute. They then pull information about that profile from the config as diff.foo.*. The code for each is currently completely separate from the other, which has several disadvantages: - there is duplication as we maintain code to create and search the separate lists of external drivers and funcname patterns - it is difficult to add new profile options, since it is unclear where they should go - the code is difficult to follow, as we rely on the "check if this file is binary" code to find the funcname pattern as a side effect. This is the first step in refactoring the binary-checking code. This patch factors out these diff profiles into "userdiff" drivers. A file with "diff=foo" uses the "foo" driver, which is specified by a single struct. Note that one major difference between the two pieces of code is that the funcname patterns are always loaded, whereas external drivers are loaded only for the "git diff" porcelain; the new code takes care to retain that situation. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- Makefile | 2 + diff.c | 251 +++++++------------------------------------------------------ userdiff.c | 160 +++++++++++++++++++++++++++++++++++++++ userdiff.h | 23 ++++++ 4 files changed, 212 insertions(+), 224 deletions(-) create mode 100644 userdiff.c create mode 100644 userdiff.h (limited to 'diff.c') diff --git a/Makefile b/Makefile index 308dc70b5d..d6f3695c97 100644 --- a/Makefile +++ b/Makefile @@ -389,6 +389,7 @@ LIB_H += transport.h LIB_H += tree.h LIB_H += tree-walk.h LIB_H += unpack-trees.h +LIB_H += userdiff.h LIB_H += utf8.h LIB_H += wt-status.h @@ -485,6 +486,7 @@ LIB_OBJS += tree-diff.o LIB_OBJS += tree.o LIB_OBJS += tree-walk.o LIB_OBJS += unpack-trees.o +LIB_OBJS += userdiff.o LIB_OBJS += usage.o LIB_OBJS += utf8.o LIB_OBJS += walker.o diff --git a/diff.c b/diff.c index 1c6be897b2..d50355e842 100644 --- a/diff.c +++ b/diff.c @@ -11,6 +11,7 @@ #include "attr.h" #include "run-command.h" #include "utf8.h" +#include "userdiff.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -56,80 +57,6 @@ static int parse_diff_color_slot(const char *var, int ofs) die("bad config variable '%s'", var); } -static struct ll_diff_driver { - const char *name; - struct ll_diff_driver *next; - const char *cmd; -} *user_diff, **user_diff_tail; - -/* - * Currently there is only "diff..command" variable; - * because there are "diff.color." variables, we are parsing - * this in a bit convoluted way to allow low level diff driver - * called "color". - */ -static int parse_lldiff_command(const char *var, const char *ep, const char *value) -{ - const char *name; - int namelen; - struct ll_diff_driver *drv; - - name = var + 5; - namelen = ep - name; - for (drv = user_diff; drv; drv = drv->next) - if (!strncmp(drv->name, name, namelen) && !drv->name[namelen]) - break; - if (!drv) { - drv = xcalloc(1, sizeof(struct ll_diff_driver)); - drv->name = xmemdupz(name, namelen); - if (!user_diff_tail) - user_diff_tail = &user_diff; - *user_diff_tail = drv; - user_diff_tail = &(drv->next); - } - - return git_config_string(&(drv->cmd), var, value); -} - -/* - * 'diff..funcname' attribute can be specified in the configuration - * to define a customized regexp to find the beginning of a function to - * be used for hunk header lines of "diff -p" style output. - */ -struct funcname_pattern_entry { - char *name; - char *pattern; - int cflags; -}; -static struct funcname_pattern_list { - struct funcname_pattern_list *next; - struct funcname_pattern_entry e; -} *funcname_pattern_list; - -static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags) -{ - const char *name; - int namelen; - struct funcname_pattern_list *pp; - - name = var + 5; /* "diff." */ - namelen = ep - name; - - for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen]) - break; - if (!pp) { - pp = xcalloc(1, sizeof(*pp)); - pp->e.name = xmemdupz(name, namelen); - pp->next = funcname_pattern_list; - funcname_pattern_list = pp; - } - free(pp->e.pattern); - pp->e.pattern = xstrdup(value); - pp->e.cflags = cflags; - return 0; -} - /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should @@ -162,11 +89,11 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "diff.external")) return git_config_string(&external_diff_cmd_cfg, var, value); - if (!prefixcmp(var, "diff.")) { - const char *ep = strrchr(var, '.'); - if (ep != var + 4 && !strcmp(ep, ".command")) - return parse_lldiff_command(var, ep, value); + switch (userdiff_config_porcelain(var, value)) { + case 0: break; + case -1: return -1; + default: return 0; } return git_diff_basic_config(var, value, cb); @@ -193,21 +120,10 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } - if (!prefixcmp(var, "diff.")) { - const char *ep = strrchr(var, '.'); - if (ep != var + 4) { - if (!strcmp(ep, ".funcname")) { - if (!value) - return config_error_nonbool(var); - return parse_funcname_pattern(var, ep, value, - 0); - } else if (!strcmp(ep, ".xfuncname")) { - if (!value) - return config_error_nonbool(var); - return parse_funcname_pattern(var, ep, value, - REG_EXTENDED); - } - } + switch (userdiff_config_basic(var, value)) { + case 0: break; + case -1: return -1; + default: return 0; } return git_color_default_config(var, value, cb); @@ -1352,46 +1268,24 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two) emit_binary_diff_body(file, two, one); } -static void setup_diff_attr_check(struct git_attr_check *check) -{ - static struct git_attr *attr_diff; - - if (!attr_diff) { - attr_diff = git_attr("diff", 4); - } - check[0].attr = attr_diff; -} - static void diff_filespec_check_attr(struct diff_filespec *one) { - struct git_attr_check attr_diff_check; + struct userdiff_driver *drv; int check_from_data = 0; if (one->checked_attr) return; - setup_diff_attr_check(&attr_diff_check); + drv = userdiff_find_by_path(one->path); one->is_binary = 0; - one->funcname_pattern_ident = NULL; - if (!git_checkattr(one->path, 1, &attr_diff_check)) { - const char *value; - - /* binaryness */ - value = attr_diff_check.value; - if (ATTR_TRUE(value)) - ; - else if (ATTR_FALSE(value)) - one->is_binary = 1; - else - check_from_data = 1; - - /* funcname pattern ident */ - if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value)) - ; - else - one->funcname_pattern_ident = value; - } + /* binaryness */ + if (drv == USERDIFF_ATTR_TRUE) + ; + else if (drv == USERDIFF_ATTR_FALSE) + one->is_binary = 1; + else + check_from_data = 1; if (check_from_data) { if (!one->data && DIFF_FILE_VALID(one)) @@ -1408,80 +1302,12 @@ int diff_filespec_is_binary(struct diff_filespec *one) return one->is_binary; } -static const struct funcname_pattern_entry *funcname_pattern(const char *ident) -{ - struct funcname_pattern_list *pp; - - for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strcmp(ident, pp->e.name)) - return &pp->e; - return NULL; -} - -static const struct funcname_pattern_entry builtin_funcname_pattern[] = { - { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", - REG_EXTENDED }, - { "html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", REG_EXTENDED }, - { "java", - "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" - "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", - REG_EXTENDED }, - { "objc", - /* Negate C statements that can look like functions */ - "!^[ \t]*(do|for|if|else|return|switch|while)\n" - /* Objective-C methods */ - "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n" - /* C functions */ - "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n" - /* Objective-C class/protocol definitions */ - "^(@(implementation|interface|protocol)[ \t].*)$", - REG_EXTENDED }, - { "pascal", - "^((procedure|function|constructor|destructor|interface|" - "implementation|initialization|finalization)[ \t]*.*)$" - "\n" - "^(.*=[ \t]*(class|record).*)$", - REG_EXTENDED }, - { "php", "^[\t ]*((function|class).*)", REG_EXTENDED }, - { "python", "^[ \t]*((class|def)[ \t].*)$", REG_EXTENDED }, - { "ruby", "^[ \t]*((class|module|def)[ \t].*)$", - REG_EXTENDED }, - { "tex", - "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", - REG_EXTENDED }, -}; - -static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) +static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one) { - const char *ident; - const struct funcname_pattern_entry *pe; - int i; - - diff_filespec_check_attr(one); - ident = one->funcname_pattern_ident; - - if (!ident) - /* - * If the config file has "funcname.default" defined, that - * regexp is used; otherwise NULL is returned and xemit uses - * the built-in default. - */ - return funcname_pattern("default"); - - /* Look up custom "funcname.$ident" regexp from config. */ - pe = funcname_pattern(ident); - if (pe) - return pe; - - /* - * And define built-in fallback patterns here. Note that - * these can be overridden by the user's config settings. - */ - for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++) - if (!strcmp(ident, builtin_funcname_pattern[i].name)) - return &builtin_funcname_pattern[i]; - - return NULL; + struct userdiff_driver *drv = userdiff_find_by_path(one->path); + if (!drv) + drv = userdiff_find_by_name("default"); + return drv && drv->funcname.pattern ? &drv->funcname : NULL; } void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b) @@ -1579,7 +1405,7 @@ static void builtin_diff(const char *name_a, xdemitconf_t xecfg; xdemitcb_t ecb; struct emit_callback ecbdata; - const struct funcname_pattern_entry *pe; + const struct userdiff_funcname *pe; pe = diff_funcname_pattern(one); if (!pe) @@ -2117,29 +1943,6 @@ static void run_external_diff(const char *pgm, } } -static const char *external_diff_attr(const char *name) -{ - struct git_attr_check attr_diff_check; - - if (!name) - return NULL; - - setup_diff_attr_check(&attr_diff_check); - if (!git_checkattr(name, 1, &attr_diff_check)) { - const char *value = attr_diff_check.value; - if (!ATTR_TRUE(value) && - !ATTR_FALSE(value) && - !ATTR_UNSET(value)) { - struct ll_diff_driver *drv; - - for (drv = user_diff; drv; drv = drv->next) - if (!strcmp(drv->name, value)) - return drv->cmd; - } - } - return NULL; -} - static void run_diff_cmd(const char *pgm, const char *name, const char *other, @@ -2153,9 +1956,9 @@ static void run_diff_cmd(const char *pgm, if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL)) pgm = NULL; else { - const char *cmd = external_diff_attr(attr_path); - if (cmd) - pgm = cmd; + struct userdiff_driver *drv = userdiff_find_by_path(attr_path); + if (drv && drv->external) + pgm = drv->external; } if (pgm) { diff --git a/userdiff.c b/userdiff.c new file mode 100644 index 0000000000..80e2857abb --- /dev/null +++ b/userdiff.c @@ -0,0 +1,160 @@ +#include "userdiff.h" +#include "cache.h" +#include "attr.h" + +static struct userdiff_driver *drivers; +static int ndrivers; +static int drivers_alloc; + +#define FUNCNAME(name, pattern) \ + { name, NULL, { pattern, REG_EXTENDED } } +static struct userdiff_driver builtin_drivers[] = { +FUNCNAME("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$"), +FUNCNAME("java", + "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" + "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$"), +FUNCNAME("objc", + /* Negate C statements that can look like functions */ + "!^[ \t]*(do|for|if|else|return|switch|while)\n" + /* Objective-C methods */ + "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n" + /* C functions */ + "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n" + /* Objective-C class/protocol definitions */ + "^(@(implementation|interface|protocol)[ \t].*)$"), +FUNCNAME("pascal", + "^((procedure|function|constructor|destructor|interface|" + "implementation|initialization|finalization)[ \t]*.*)$" + "\n" + "^(.*=[ \t]*(class|record).*)$"), +FUNCNAME("php", "^[\t ]*((function|class).*)"), +FUNCNAME("python", "^[ \t]*((class|def)[ \t].*)$"), +FUNCNAME("ruby", "^[ \t]*((class|module|def)[ \t].*)$"), +FUNCNAME("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$"), +FUNCNAME("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$"), +}; +#undef FUNCNAME + +static struct userdiff_driver driver_true = { + "diff=true", + NULL, + { NULL, 0 } +}; +struct userdiff_driver *USERDIFF_ATTR_TRUE = &driver_true; + +static struct userdiff_driver driver_false = { + "!diff", + NULL, + { NULL, 0 } +}; +struct userdiff_driver *USERDIFF_ATTR_FALSE = &driver_false; + +static struct userdiff_driver *userdiff_find_by_namelen(const char *k, int len) +{ + int i; + for (i = 0; i < ndrivers; i++) { + struct userdiff_driver *drv = drivers + i; + if (!strncmp(drv->name, k, len) && !drv->name[len]) + return drv; + } + for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) { + struct userdiff_driver *drv = builtin_drivers + i; + if (!strncmp(drv->name, k, len) && !drv->name[len]) + return drv; + } + return NULL; +} + +static struct userdiff_driver *parse_driver(const char *var, + const char *value, const char *type) +{ + struct userdiff_driver *drv; + const char *dot; + const char *name; + int namelen; + + if (prefixcmp(var, "diff.")) + return NULL; + dot = strrchr(var, '.'); + if (dot == var + 4) + return NULL; + if (strcmp(type, dot+1)) + return NULL; + + name = var + 5; + namelen = dot - name; + drv = userdiff_find_by_namelen(name, namelen); + if (!drv) { + ALLOC_GROW(drivers, ndrivers+1, drivers_alloc); + drv = &drivers[ndrivers++]; + memset(drv, 0, sizeof(*drv)); + drv->name = xmemdupz(name, namelen); + } + return drv; +} + +static int parse_funcname(struct userdiff_funcname *f, const char *k, + const char *v, int cflags) +{ + if (git_config_string(&f->pattern, k, v) < 0) + return -1; + f->cflags = cflags; + return 1; +} + +static int parse_string(const char **d, const char *k, const char *v) +{ + if (git_config_string(d, k, v) < 0) + return -1; + return 1; +} + +int userdiff_config_basic(const char *k, const char *v) +{ + struct userdiff_driver *drv; + + if ((drv = parse_driver(k, v, "funcname"))) + return parse_funcname(&drv->funcname, k, v, 0); + if ((drv = parse_driver(k, v, "xfuncname"))) + return parse_funcname(&drv->funcname, k, v, REG_EXTENDED); + + return 0; +} + +int userdiff_config_porcelain(const char *k, const char *v) +{ + struct userdiff_driver *drv; + + if ((drv = parse_driver(k, v, "command"))) + return parse_string(&drv->external, k, v); + + return 0; +} + +struct userdiff_driver *userdiff_find_by_name(const char *name) { + int len = strlen(name); + return userdiff_find_by_namelen(name, len); +} + +struct userdiff_driver *userdiff_find_by_path(const char *path) +{ + static struct git_attr *attr; + struct git_attr_check check; + + if (!attr) + attr = git_attr("diff", 4); + check.attr = attr; + + if (!path) + return NULL; + if (git_checkattr(path, 1, &check)) + return NULL; + + if (ATTR_TRUE(check.value)) + return &driver_true; + if (ATTR_FALSE(check.value)) + return &driver_false; + if (ATTR_UNSET(check.value)) + return NULL; + return userdiff_find_by_name(check.value); +} diff --git a/userdiff.h b/userdiff.h new file mode 100644 index 0000000000..c64c5f5669 --- /dev/null +++ b/userdiff.h @@ -0,0 +1,23 @@ +#ifndef USERDIFF_H +#define USERDIFF_H + +struct userdiff_funcname { + const char *pattern; + int cflags; +}; + +struct userdiff_driver { + const char *name; + const char *external; + struct userdiff_funcname funcname; +}; + +extern struct userdiff_driver *USERDIFF_ATTR_TRUE; +extern struct userdiff_driver *USERDIFF_ATTR_FALSE; + +int userdiff_config_basic(const char *k, const char *v); +int userdiff_config_porcelain(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); + +#endif /* USERDIFF */ -- cgit v1.3 From 122aa6f9c000d0d286898e2eb7b3504ac6cb9ebd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 5 Oct 2008 17:43:36 -0400 Subject: diff: introduce diff..binary The "diff" gitattribute is somewhat overloaded right now. It can say one of three things: 1. this file is definitely binary, or definitely not (i.e., diff or !diff) 2. this file should use an external diff engine (i.e., diff=foo, diff.foo.command = custom-script) 3. this file should use particular funcname patterns (i.e., diff=foo, diff.foo.(x?)funcname = some-regex) Most of the time, there is no conflict between these uses, since using one implies that the other is irrelevant (e.g., an external diff engine will decide for itself whether the file is binary). However, there is at least one conflicting situation: there is no way to say "use the regular rules to determine whether this file is binary, but if we do diff it textually, use this funcname pattern." That is, currently setting diff=foo indicates that the file is definitely text. This patch introduces a "binary" config option for a diff driver, so that one can explicitly set diff.foo.binary. We default this value to "don't know". That is, setting a diff attribute to "foo" and using "diff.foo.funcname" will have no effect on the binaryness of a file. To get the current behavior, one can set diff.foo.binary to true. This patch also has one additional advantage: it cleans up the interface to the userdiff code a bit. Before, calling code had to know more about whether attributes were false, true, or unset to determine binaryness. Now that binaryness is a property of a driver, we can represent these situations just by passing back a driver struct. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- diff.c | 52 ++++++++++++++++++++++------------------------------ diffcore.h | 8 ++++++-- userdiff.c | 19 ++++++++++++++++--- userdiff.h | 4 +--- 4 files changed, 45 insertions(+), 38 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d50355e842..dabd7f50ec 100644 --- a/diff.c +++ b/diff.c @@ -1268,46 +1268,37 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two) emit_binary_diff_body(file, two, one); } -static void diff_filespec_check_attr(struct diff_filespec *one) +void diff_filespec_load_driver(struct diff_filespec *one) { - struct userdiff_driver *drv; - int check_from_data = 0; - - if (one->checked_attr) - return; - - drv = userdiff_find_by_path(one->path); - one->is_binary = 0; - - /* binaryness */ - if (drv == USERDIFF_ATTR_TRUE) - ; - else if (drv == USERDIFF_ATTR_FALSE) - one->is_binary = 1; - else - check_from_data = 1; - - if (check_from_data) { - if (!one->data && DIFF_FILE_VALID(one)) - diff_populate_filespec(one, 0); - - if (one->data) - one->is_binary = buffer_is_binary(one->data, one->size); - } + if (!one->driver) + one->driver = userdiff_find_by_path(one->path); + if (!one->driver) + one->driver = userdiff_find_by_name("default"); } int diff_filespec_is_binary(struct diff_filespec *one) { - diff_filespec_check_attr(one); + if (one->is_binary == -1) { + diff_filespec_load_driver(one); + if (one->driver->binary != -1) + one->is_binary = one->driver->binary; + else { + if (!one->data && DIFF_FILE_VALID(one)) + diff_populate_filespec(one, 0); + if (one->data) + one->is_binary = buffer_is_binary(one->data, + one->size); + if (one->is_binary == -1) + one->is_binary = 0; + } + } return one->is_binary; } static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one) { - struct userdiff_driver *drv = userdiff_find_by_path(one->path); - if (!drv) - drv = userdiff_find_by_name("default"); - return drv && drv->funcname.pattern ? &drv->funcname : NULL; + diff_filespec_load_driver(one); + return one->driver->funcname.pattern ? &one->driver->funcname : NULL; } void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b) @@ -1559,6 +1550,7 @@ struct diff_filespec *alloc_filespec(const char *path) spec->path = (char *)(spec + 1); memcpy(spec->path, path, namelen+1); spec->count = 1; + spec->is_binary = -1; return spec; } diff --git a/diffcore.h b/diffcore.h index 8ae35785fd..713cca785c 100644 --- a/diffcore.h +++ b/diffcore.h @@ -22,6 +22,8 @@ #define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */ +struct userdiff_driver; + struct diff_filespec { unsigned char sha1[20]; char *path; @@ -40,8 +42,10 @@ struct diff_filespec { #define DIFF_FILE_VALID(spec) (((spec)->mode) != 0) unsigned should_free : 1; /* data should be free()'ed */ unsigned should_munmap : 1; /* data should be munmap()'ed */ - unsigned checked_attr : 1; - unsigned is_binary : 1; /* data should be considered "binary" */ + + struct userdiff_driver *driver; + /* data should be considered "binary"; -1 means "don't know yet" */ + int is_binary; }; extern struct diff_filespec *alloc_filespec(const char *); diff --git a/userdiff.c b/userdiff.c index 80e2857abb..58478a6912 100644 --- a/userdiff.c +++ b/userdiff.c @@ -7,7 +7,7 @@ static int ndrivers; static int drivers_alloc; #define FUNCNAME(name, pattern) \ - { name, NULL, { pattern, REG_EXTENDED } } + { name, NULL, -1, { pattern, REG_EXTENDED } } static struct userdiff_driver builtin_drivers[] = { FUNCNAME("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$"), FUNCNAME("java", @@ -32,22 +32,23 @@ FUNCNAME("python", "^[ \t]*((class|def)[ \t].*)$"), FUNCNAME("ruby", "^[ \t]*((class|module|def)[ \t].*)$"), FUNCNAME("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$"), FUNCNAME("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$"), +{ "default", NULL, -1, { NULL, 0 } }, }; #undef FUNCNAME static struct userdiff_driver driver_true = { "diff=true", NULL, + 0, { NULL, 0 } }; -struct userdiff_driver *USERDIFF_ATTR_TRUE = &driver_true; static struct userdiff_driver driver_false = { "!diff", NULL, + 1, { NULL, 0 } }; -struct userdiff_driver *USERDIFF_ATTR_FALSE = &driver_false; static struct userdiff_driver *userdiff_find_by_namelen(const char *k, int len) { @@ -89,6 +90,7 @@ static struct userdiff_driver *parse_driver(const char *var, drv = &drivers[ndrivers++]; memset(drv, 0, sizeof(*drv)); drv->name = xmemdupz(name, namelen); + drv->binary = -1; } return drv; } @@ -109,6 +111,15 @@ static int parse_string(const char **d, const char *k, const char *v) return 1; } +static int parse_tristate(int *b, const char *k, const char *v) +{ + if (v && !strcasecmp(v, "auto")) + *b = -1; + else + *b = git_config_bool(k, v); + return 1; +} + int userdiff_config_basic(const char *k, const char *v) { struct userdiff_driver *drv; @@ -117,6 +128,8 @@ int userdiff_config_basic(const char *k, const char *v) return parse_funcname(&drv->funcname, k, v, 0); if ((drv = parse_driver(k, v, "xfuncname"))) return parse_funcname(&drv->funcname, k, v, REG_EXTENDED); + if ((drv = parse_driver(k, v, "binary"))) + return parse_tristate(&drv->binary, k, v); return 0; } diff --git a/userdiff.h b/userdiff.h index c64c5f5669..1c1eb042b4 100644 --- a/userdiff.h +++ b/userdiff.h @@ -9,12 +9,10 @@ struct userdiff_funcname { struct userdiff_driver { const char *name; const char *external; + int binary; struct userdiff_funcname funcname; }; -extern struct userdiff_driver *USERDIFF_ATTR_TRUE; -extern struct userdiff_driver *USERDIFF_ATTR_FALSE; - int userdiff_config_basic(const char *k, const char *v); int userdiff_config_porcelain(const char *k, const char *v); struct userdiff_driver *userdiff_find_by_name(const char *name); -- cgit v1.3 From 9cb92c390cefd3bf3f71bbda12eb04893c861361 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 5 Oct 2008 17:43:45 -0400 Subject: diff: add filter for converting binary to text When diffing binary files, it is sometimes nice to see the differences of a canonical text form rather than either a binary patch or simply "binary files differ." Until now, the only option for doing this was to define an external diff command to perform the diff. This was a lot of work, since the external command needed to take care of doing the diff itself (including mode changes), and lost the benefit of git's colorization and other options. This patch adds a text conversion option, which converts a file to its canonical format before performing the diff. This is less flexible than an arbitrary external diff, but is much less work to set up. For example: $ echo '*.jpg diff=exif' >>.gitattributes $ git config diff.exif.textconv exiftool $ git config diff.exif.binary false allows one to see jpg diffs represented by the text output of exiftool. Signed-off-by: Jeff King Signed-off-by: Shawn O. Pearce --- diff.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- userdiff.c | 2 ++ userdiff.h | 1 + 3 files changed, 50 insertions(+), 2 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index dabd7f50ec..e368fef14f 100644 --- a/diff.c +++ b/diff.c @@ -38,6 +38,9 @@ static char diff_colors[][COLOR_MAXLEN] = { "\033[41m", /* WHITESPACE (red background) */ }; +static void diff_filespec_load_driver(struct diff_filespec *one); +static char *run_textconv(const char *, struct diff_filespec *, size_t *); + static int parse_diff_color_slot(const char *var, int ofs) { if (!strcasecmp(var+ofs, "plain")) @@ -290,8 +293,19 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) } else if (diff_populate_filespec(one, 0)) return -1; - mf->ptr = one->data; - mf->size = one->size; + + diff_filespec_load_driver(one); + if (one->driver->textconv) { + size_t size; + mf->ptr = run_textconv(one->driver->textconv, one, &size); + if (!mf->ptr) + return -1; + mf->size = size; + } + else { + mf->ptr = one->data; + mf->size = one->size; + } return 0; } @@ -3373,3 +3387,34 @@ void diff_unmerge(struct diff_options *options, fill_filespec(one, sha1, mode); diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1; } + +static char *run_textconv(const char *pgm, struct diff_filespec *spec, + size_t *outsize) +{ + struct diff_tempfile temp; + const char *argv[3]; + const char **arg = argv; + struct child_process child; + struct strbuf buf = STRBUF_INIT; + + prepare_temp_file(spec->path, &temp, spec); + *arg++ = pgm; + *arg++ = temp.name; + *arg = NULL; + + memset(&child, 0, sizeof(child)); + child.argv = argv; + child.out = -1; + if (start_command(&child) != 0 || + strbuf_read(&buf, child.out, 0) < 0 || + finish_command(&child) != 0) { + if (temp.name == temp.tmp_path) + unlink(temp.name); + error("error running textconv command '%s'", pgm); + return NULL; + } + if (temp.name == temp.tmp_path) + unlink(temp.name); + + return strbuf_detach(&buf, outsize); +} diff --git a/userdiff.c b/userdiff.c index 58478a6912..d95257ab3b 100644 --- a/userdiff.c +++ b/userdiff.c @@ -140,6 +140,8 @@ int userdiff_config_porcelain(const char *k, const char *v) if ((drv = parse_driver(k, v, "command"))) return parse_string(&drv->external, k, v); + if ((drv = parse_driver(k, v, "textconv"))) + return parse_string(&drv->textconv, k, v); return 0; } diff --git a/userdiff.h b/userdiff.h index 1c1eb042b4..f29c18ffb3 100644 --- a/userdiff.h +++ b/userdiff.h @@ -11,6 +11,7 @@ struct userdiff_driver { const char *external; int binary; struct userdiff_funcname funcname; + const char *textconv; }; int userdiff_config_basic(const char *k, const char *v); -- cgit v1.3 From 9ccd0a88ac3ea13ac2df4630bfd01c02084f965e Mon Sep 17 00:00:00 2001 From: Brian Downing Date: Sat, 25 Oct 2008 15:30:37 +0200 Subject: Always initialize xpparam_t to 0 We're going to be adding some parameters to this, so we can't have any uninitialized data in it. Signed-off-by: Brian Downing Signed-off-by: Junio C Hamano --- builtin-blame.c | 1 + builtin-rerere.c | 1 + combine-diff.c | 1 + diff.c | 5 +++++ merge-file.c | 1 + 5 files changed, 9 insertions(+) (limited to 'diff.c') diff --git a/builtin-blame.c b/builtin-blame.c index 593b539f1e..5ca7065171 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -523,6 +523,7 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xpp, 0, sizeof(xpp)); xpp.flags = xdl_opts; memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = context; diff --git a/builtin-rerere.c b/builtin-rerere.c index dd4573fe8d..d4dec6b715 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -98,6 +98,7 @@ static int diff_two(const char *file1, const char *label1, printf("--- a/%s\n+++ b/%s\n", label1, label2); fflush(stdout); + memset(&xpp, 0, sizeof(xpp)); xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; diff --git a/combine-diff.c b/combine-diff.c index 5aa1104d34..ec8df39bb0 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -213,6 +213,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file, parent_file.ptr = grab_blob(parent, &sz); parent_file.size = sz; + memset(&xpp, 0, sizeof(xpp)); xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); memset(&state, 0, sizeof(state)); diff --git a/diff.c b/diff.c index 1c6be897b2..f141e7c8ff 100644 --- a/diff.c +++ b/diff.c @@ -470,6 +470,7 @@ static void diff_words_show(struct diff_words_data *diff_words) mmfile_t minus, plus; int i; + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); minus.size = diff_words->minus.text.size; minus.ptr = xmalloc(minus.size); @@ -1585,6 +1586,7 @@ static void builtin_diff(const char *name_a, if (!pe) pe = diff_funcname_pattern(two); + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); ecbdata.label_path = lbl; @@ -1658,6 +1660,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, @@ -1704,6 +1707,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 1; /* at least one context line */ xpp.flags = XDF_NEED_MINIMAL; @@ -3149,6 +3153,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) struct diff_filepair *p = q->queue[i]; int len1, len2; + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); if (p->status == 0) return error("internal diff status error"); diff --git a/merge-file.c b/merge-file.c index 2a939c9dd8..3120a95f78 100644 --- a/merge-file.c +++ b/merge-file.c @@ -61,6 +61,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2) xdemitconf_t xecfg; xdemitcb_t ecb; + memset(&xpp, 0, sizeof(xpp)); xpp.flags = XDF_NEED_MINIMAL; memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; -- cgit v1.3 From 72cf48414071636546eddfbfc828eda81649cb48 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 26 Oct 2008 00:41:28 -0400 Subject: diff: add missing static declaration This function isn't used outside of diff.c; the 'static' was simply overlooked in the original writing. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index e368fef14f..d1fd594ba3 100644 --- a/diff.c +++ b/diff.c @@ -1282,7 +1282,7 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two) emit_binary_diff_body(file, two, one); } -void diff_filespec_load_driver(struct diff_filespec *one) +static void diff_filespec_load_driver(struct diff_filespec *one) { if (!one->driver) one->driver = userdiff_find_by_path(one->path); -- cgit v1.3 From 04427ac8483f61dcb01a48c78a821f5042c88195 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 26 Oct 2008 00:44:53 -0400 Subject: refactor userdiff textconv code The original implementation of textconv put the conversion into fill_mmfile. This was a bad idea for a number of reasons: - it made the semantics of fill_mmfile unclear. In some cases, it was allocating data (if a text conversion occurred), and in some cases not (if we could use the data directly from the filespec). But the caller had no idea which had happened, and so didn't know whether the memory should be freed - similarly, the caller had no idea if a text conversion had occurred, and so didn't know whether the contents should be treated as binary or not. This meant that we incorrectly guessed that text-converted content was binary and didn't actually show it (unless the user overrode us with "diff.foo.binary = false", which then created problems in plumbing where the text conversion did _not_ occur) - not all callers of fill_mmfile want the text contents. In particular, we don't really want diffstat, whitespace checks, patch id generation, etc, to look at the converted contents. This patch pulls the conversion code directly into builtin_diff, so that we only see the conversion when generating an actual patch. We also then know whether we are doing a conversion, so we can check the binary-ness and free the data from the mmfile appropriately (the previous version leaked quite badly when text conversion was used) Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 48 +++++++++++++++++++++++++++++++++++------------- t/t4030-diff-textconv.sh | 6 +++--- 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d1fd594ba3..6f01595ece 100644 --- a/diff.c +++ b/diff.c @@ -294,18 +294,8 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) else if (diff_populate_filespec(one, 0)) return -1; - diff_filespec_load_driver(one); - if (one->driver->textconv) { - size_t size; - mf->ptr = run_textconv(one->driver->textconv, one, &size); - if (!mf->ptr) - return -1; - mf->size = size; - } - else { - mf->ptr = one->data; - mf->size = one->size; - } + mf->ptr = one->data; + mf->size = one->size; return 0; } @@ -1323,6 +1313,14 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const options->b_prefix = b; } +static const char *get_textconv(struct diff_filespec *one) +{ + if (!DIFF_FILE_VALID(one)) + return NULL; + diff_filespec_load_driver(one); + return one->driver->textconv; +} + static void builtin_diff(const char *name_a, const char *name_b, struct diff_filespec *one, @@ -1337,6 +1335,7 @@ static void builtin_diff(const char *name_a, const char *set = diff_get_color_opt(o, DIFF_METAINFO); const char *reset = diff_get_color_opt(o, DIFF_RESET); const char *a_prefix, *b_prefix; + const char *textconv_one, *textconv_two; diff_set_mnemonic_prefix(o, "a/", "b/"); if (DIFF_OPT_TST(o, REVERSE_DIFF)) { @@ -1390,8 +1389,12 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); + textconv_one = get_textconv(one); + textconv_two = get_textconv(two); + if (!DIFF_OPT_TST(o, TEXT) && - (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) { + ( (diff_filespec_is_binary(one) && !textconv_one) || + (diff_filespec_is_binary(two) && !textconv_two) )) { /* Quite common confusing case */ if (mf1.size == mf2.size && !memcmp(mf1.ptr, mf2.ptr, mf1.size)) @@ -1412,6 +1415,21 @@ static void builtin_diff(const char *name_a, struct emit_callback ecbdata; const struct userdiff_funcname *pe; + if (textconv_one) { + size_t size; + mf1.ptr = run_textconv(textconv_one, one, &size); + if (!mf1.ptr) + die("unable to read files to diff"); + mf1.size = size; + } + if (textconv_two) { + size_t size; + mf2.ptr = run_textconv(textconv_two, two, &size); + if (!mf2.ptr) + die("unable to read files to diff"); + mf2.size = size; + } + pe = diff_funcname_pattern(one); if (!pe) pe = diff_funcname_pattern(two); @@ -1443,6 +1461,10 @@ static void builtin_diff(const char *name_a, &xpp, &xecfg, &ecb); if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) free_diff_words_data(&ecbdata); + if (textconv_one) + free(mf1.ptr); + if (textconv_two) + free(mf2.ptr); } free_ab_and_return: diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 1b0964843e..090a21d0b5 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -52,7 +52,7 @@ test_expect_success 'setup textconv filters' ' git config diff.fail.textconv false ' -test_expect_failure 'diff produces text' ' +test_expect_success 'diff produces text' ' git diff HEAD^ HEAD >diff && find_diff actual && test_cmp expect.text actual @@ -64,7 +64,7 @@ test_expect_success 'diff-tree produces binary' ' test_cmp expect.binary actual ' -test_expect_failure 'log produces text' ' +test_expect_success 'log produces text' ' git log -1 -p >log && find_diff actual && test_cmp expect.text actual @@ -80,7 +80,7 @@ cat >expect.stat <<'EOF' file | Bin 2 -> 4 bytes 1 files changed, 0 insertions(+), 0 deletions(-) EOF -test_expect_failure 'diffstat does not run textconv' ' +test_expect_success 'diffstat does not run textconv' ' echo file diff=fail >.gitattributes && git diff --stat HEAD^ HEAD >actual && test_cmp expect.stat actual -- cgit v1.3 From c7534ef4a12bb44806d522fc8e3961e390f9169b Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 26 Oct 2008 00:45:55 -0400 Subject: userdiff: require explicitly allowing textconv Diffs that have been produced with textconv almost certainly cannot be applied, so we want to be careful not to generate them in things like format-patch. This introduces a new diff options, ALLOW_TEXTCONV, which controls this behavior. It is off by default, but is explicitly turned on for the "log" family of commands, as well as the "diff" porcelain (but not diff-* plumbing). Because both text conversion and external diffing are controlled by these diff options, we can get rid of the "plumbing versus porcelain" distinction when reading the config. This was an attempt to control the same thing, but suffered from being too coarse-grained. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-diff.c | 1 + builtin-log.c | 1 + diff.c | 26 +++++++++++--------------- diff.h | 1 + t/t4030-diff-textconv.sh | 2 +- userdiff.c | 10 +--------- userdiff.h | 3 +-- 7 files changed, 17 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/builtin-diff.c b/builtin-diff.c index 9c8c295732..2de5834c11 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -300,6 +300,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL); DIFF_OPT_SET(&rev.diffopt, RECURSIVE); + DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV); /* * If the user asked for our exit code then don't start a diff --git a/builtin-log.c b/builtin-log.c index a0944f70a4..75d698f0ce 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -59,6 +59,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, } else die("unrecognized argument: %s", arg); } + DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV); } /* diff --git a/diff.c b/diff.c index 6f01595ece..608223ab56 100644 --- a/diff.c +++ b/diff.c @@ -93,12 +93,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) if (!strcmp(var, "diff.external")) return git_config_string(&external_diff_cmd_cfg, var, value); - switch (userdiff_config_porcelain(var, value)) { - case 0: break; - case -1: return -1; - default: return 0; - } - return git_diff_basic_config(var, value, cb); } @@ -109,6 +103,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } + switch (userdiff_config(var, value)) { + case 0: break; + case -1: return -1; + default: return 0; + } + if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) { int slot = parse_diff_color_slot(var, 11); if (!value) @@ -123,12 +123,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return 0; } - switch (userdiff_config_basic(var, value)) { - case 0: break; - case -1: return -1; - default: return 0; - } - return git_color_default_config(var, value, cb); } @@ -1335,7 +1329,7 @@ static void builtin_diff(const char *name_a, const char *set = diff_get_color_opt(o, DIFF_METAINFO); const char *reset = diff_get_color_opt(o, DIFF_RESET); const char *a_prefix, *b_prefix; - const char *textconv_one, *textconv_two; + const char *textconv_one = NULL, *textconv_two = NULL; diff_set_mnemonic_prefix(o, "a/", "b/"); if (DIFF_OPT_TST(o, REVERSE_DIFF)) { @@ -1389,8 +1383,10 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - textconv_one = get_textconv(one); - textconv_two = get_textconv(two); + if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) { + textconv_one = get_textconv(one); + textconv_two = get_textconv(two); + } if (!DIFF_OPT_TST(o, TEXT) && ( (diff_filespec_is_binary(one) && !textconv_one) || diff --git a/diff.h b/diff.h index a49d865bd9..42582edee6 100644 --- a/diff.h +++ b/diff.h @@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_IGNORE_SUBMODULES (1 << 18) #define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19) #define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20) +#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 090a21d0b5..1df48ae12a 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -70,7 +70,7 @@ test_expect_success 'log produces text' ' test_cmp expect.text actual ' -test_expect_failure 'format-patch produces binary' ' +test_expect_success 'format-patch produces binary' ' git format-patch --no-binary --stdout HEAD^ >patch && find_diff actual && test_cmp expect.binary actual diff --git a/userdiff.c b/userdiff.c index d95257ab3b..3681062ebf 100644 --- a/userdiff.c +++ b/userdiff.c @@ -120,7 +120,7 @@ static int parse_tristate(int *b, const char *k, const char *v) return 1; } -int userdiff_config_basic(const char *k, const char *v) +int userdiff_config(const char *k, const char *v) { struct userdiff_driver *drv; @@ -130,14 +130,6 @@ int userdiff_config_basic(const char *k, const char *v) return parse_funcname(&drv->funcname, k, v, REG_EXTENDED); if ((drv = parse_driver(k, v, "binary"))) return parse_tristate(&drv->binary, k, v); - - return 0; -} - -int userdiff_config_porcelain(const char *k, const char *v) -{ - struct userdiff_driver *drv; - if ((drv = parse_driver(k, v, "command"))) return parse_string(&drv->external, k, v); if ((drv = parse_driver(k, v, "textconv"))) diff --git a/userdiff.h b/userdiff.h index f29c18ffb3..ba2945770b 100644 --- a/userdiff.h +++ b/userdiff.h @@ -14,8 +14,7 @@ struct userdiff_driver { const char *textconv; }; -int userdiff_config_basic(const char *k, const char *v); -int userdiff_config_porcelain(const char *k, const char *v); +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); -- cgit v1.3 From 2675773af893ae81f9b09f18c1f2ec86ca2158e7 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 26 Oct 2008 00:46:21 -0400 Subject: only textconv regular files We treat symlinks as text containing the results of the symlink, so it doesn't make much sense to text-convert them. Similarly gitlink components just end up as the text "Subproject commit $sha1", which we should leave intact. Note that a typechange may be broken into two parts: the removal of the old part and the addition of the new. In that case, we _do_ show the textconv for any part which is the addition or removal of a file we would ordinarily textconv, since it is purely acting on the file contents. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 2 ++ t/t4030-diff-textconv.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 608223ab56..23d454e71d 100644 --- a/diff.c +++ b/diff.c @@ -1311,6 +1311,8 @@ static const char *get_textconv(struct diff_filespec *one) { if (!DIFF_FILE_VALID(one)) return NULL; + if (!S_ISREG(one->mode)) + return NULL; diff_filespec_load_driver(one); return one->driver->textconv; } diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh index 1df48ae12a..3945731e9a 100755 --- a/t/t4030-diff-textconv.sh +++ b/t/t4030-diff-textconv.sh @@ -104,7 +104,7 @@ index ad8b3d2..67be421 \ No newline at end of file EOF # make a symlink the hard way that works on symlink-challenged file systems -test_expect_failure 'textconv does not act on symlinks' ' +test_expect_success 'textconv does not act on symlinks' ' echo -n frotz > file && git add file && git ls-files -s | sed -e s/100644/120000/ | -- cgit v1.3 From e10ea8126c27b079e81932ca487747b4961d0604 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 7 Dec 2008 21:57:01 -0500 Subject: diff: allow turning on textconv explicitly for plumbing Some history viewers use the diff plumbing to generate diffs rather than going through the "git diff" porcelain. Currently, there is no way for them to specify that they would like to see the text-converted version of the diff. This patch adds a "--textconv" option to allow such a plumbing user to allow text conversion. The user can then tell the viewer whether or not they would like text conversion enabled. While it may be tempting add a configuration option rather than requiring each plumbing user to be configured to pass --textconv, that is somewhat dangerous. Text-converted diffs generally cannot be applied directly, so each plumbing user should "opt in" to generating such a diff, either by explicit request of the user or by confirming that their output will not be fed to patch. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f644947c82..e21af3b7ee 100644 --- a/diff.c +++ b/diff.c @@ -2477,6 +2477,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, ALLOW_EXTERNAL); else if (!strcmp(arg, "--no-ext-diff")) DIFF_OPT_CLR(options, ALLOW_EXTERNAL); + else if (!strcmp(arg, "--textconv")) + DIFF_OPT_SET(options, ALLOW_TEXTCONV); + else if (!strcmp(arg, "--no-textconv")) + DIFF_OPT_CLR(options, ALLOW_TEXTCONV); else if (!strcmp(arg, "--ignore-submodules")) DIFF_OPT_SET(options, IGNORE_SUBMODULES); -- cgit v1.3 From 0c01857df57fe8723714e49459e0c061fcaf056b Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 9 Dec 2008 03:12:28 -0500 Subject: diff: fix handling of binary rewrite diffs The current emit_rewrite_diff code always writes a text patch without checking whether the content is binary. This means that if you end up with a rewrite diff for a binary file, you get lots of raw binary goo in your patch. Instead, if we have binary files, then let's just skip emit_rewrite_diff altogether. We will already have shown the "dissimilarity index" line, so it is really about the diff contents. If binary diffs are turned off, the "Binary files a/file and b/file differ" message should be the same in either case. If we do have binary patches turned on, there isn't much point in making a less-efficient binary patch that does a total rewrite; no human is going to read it, and since binary patches don't apply with any fuzz anyway, the result of application should be the same. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 4 +++- t/t4031-diff-rewrite-binary.sh | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100755 t/t4031-diff-rewrite-binary.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index e21af3b7ee..50277b82b2 100644 --- a/diff.c +++ b/diff.c @@ -1376,7 +1376,9 @@ static void builtin_diff(const char *name_a, */ if ((one->mode ^ two->mode) & S_IFMT) goto free_ab_and_return; - if (complete_rewrite) { + if (complete_rewrite && + !diff_filespec_is_binary(one) && + !diff_filespec_is_binary(two)) { emit_rewrite_diff(name_a, name_b, one, two, o); o->found_changes = 1; goto free_ab_and_return; diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh new file mode 100755 index 0000000000..e16c355103 --- /dev/null +++ b/t/t4031-diff-rewrite-binary.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +test_description='rewrite diff on binary file' + +. ./test-lib.sh + +# We must be large enough to meet the MINIMUM_BREAK_SIZE +# requirement. +make_file() { + for i in 1 2 3 4 5 6 7 8 9 10 + do + for j in 1 2 3 4 5 6 7 8 9 + do + for k in 1 2 3 4 5 + do + printf "$1\n" + done + done + done >file +} + +test_expect_success 'create binary file with changes' ' + make_file "\\0" && + git add file && + make_file "\\01" +' + +test_expect_success 'vanilla diff is binary' ' + git diff >diff && + grep "Binary files a/file and b/file differ" diff +' + +test_expect_success 'rewrite diff is binary' ' + git diff -B >diff && + grep "dissimilarity index" diff && + grep "Binary files a/file and b/file differ" diff +' + +test_expect_success 'rewrite diff can show binary patch' ' + git diff -B --binary >diff && + grep "dissimilarity index" diff && + grep "GIT binary patch" diff +' + +test_done -- cgit v1.3 From 3aa1f7ca3779f73164b285c070b71abcdd7397c1 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 9 Dec 2008 03:13:21 -0500 Subject: diff: respect textconv in rewrite diffs Currently we just skip rewrite diffs for binary files; this patch makes an exception for files which will be textconv'd, and actually performs the textconv before generating the diff. Conceptually, rewrite diffs should be in the exact same format as the a non-rewrite diff, except that we refuse to share any context. Thus it makes very little sense for "git diff" to show a textconv'd diff, but for "git diff -B" to show "Binary files differ". Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 48 +++++++++++++++++++++++++++++++----------- t/t4031-diff-rewrite-binary.sh | 24 ++++++++++++++++++++- 2 files changed, 59 insertions(+), 13 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 50277b82b2..afefe087bb 100644 --- a/diff.c +++ b/diff.c @@ -229,6 +229,8 @@ static void emit_rewrite_diff(const char *name_a, const char *name_b, struct diff_filespec *one, struct diff_filespec *two, + const char *textconv_one, + const char *textconv_two, struct diff_options *o) { int lc_a, lc_b; @@ -241,6 +243,8 @@ static void emit_rewrite_diff(const char *name_a, const char *reset = diff_get_color(color_diff, DIFF_RESET); static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT; const char *a_prefix, *b_prefix; + const char *data_one, *data_two; + size_t size_one, size_two; if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) { a_prefix = o->b_prefix; @@ -262,8 +266,27 @@ static void emit_rewrite_diff(const char *name_a, diff_populate_filespec(one, 0); diff_populate_filespec(two, 0); - lc_a = count_lines(one->data, one->size); - lc_b = count_lines(two->data, two->size); + if (textconv_one) { + data_one = run_textconv(textconv_one, one, &size_one); + if (!data_one) + die("unable to read files to diff"); + } + else { + data_one = one->data; + size_one = one->size; + } + if (textconv_two) { + data_two = run_textconv(textconv_two, two, &size_two); + if (!data_two) + die("unable to read files to diff"); + } + else { + data_two = two->data; + size_two = two->size; + } + + lc_a = count_lines(data_one, size_one); + lc_b = count_lines(data_two, size_two); fprintf(o->file, "%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -", metainfo, a_name.buf, name_a_tab, reset, @@ -273,9 +296,9 @@ static void emit_rewrite_diff(const char *name_a, print_line_count(o->file, lc_b); fprintf(o->file, " @@%s\n", reset); if (lc_a) - copy_file_with_prefix(o->file, '-', one->data, one->size, old, reset); + copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset); if (lc_b) - copy_file_with_prefix(o->file, '+', two->data, two->size, new, reset); + copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset); } static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) @@ -1334,6 +1357,11 @@ static void builtin_diff(const char *name_a, const char *a_prefix, *b_prefix; const char *textconv_one = NULL, *textconv_two = NULL; + if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) { + textconv_one = get_textconv(one); + textconv_two = get_textconv(two); + } + diff_set_mnemonic_prefix(o, "a/", "b/"); if (DIFF_OPT_TST(o, REVERSE_DIFF)) { a_prefix = o->b_prefix; @@ -1377,9 +1405,10 @@ static void builtin_diff(const char *name_a, if ((one->mode ^ two->mode) & S_IFMT) goto free_ab_and_return; if (complete_rewrite && - !diff_filespec_is_binary(one) && - !diff_filespec_is_binary(two)) { - emit_rewrite_diff(name_a, name_b, one, two, o); + (textconv_one || !diff_filespec_is_binary(one)) && + (textconv_two || !diff_filespec_is_binary(two))) { + emit_rewrite_diff(name_a, name_b, one, two, + textconv_one, textconv_two, o); o->found_changes = 1; goto free_ab_and_return; } @@ -1388,11 +1417,6 @@ static void builtin_diff(const char *name_a, if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0) die("unable to read files to diff"); - if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) { - textconv_one = get_textconv(one); - textconv_two = get_textconv(two); - } - if (!DIFF_OPT_TST(o, TEXT) && ( (diff_filespec_is_binary(one) && !textconv_one) || (diff_filespec_is_binary(two) && !textconv_two) )) { diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh index e16c355103..157ed85a79 100755 --- a/t/t4031-diff-rewrite-binary.sh +++ b/t/t4031-diff-rewrite-binary.sh @@ -7,6 +7,8 @@ test_description='rewrite diff on binary file' # We must be large enough to meet the MINIMUM_BREAK_SIZE # requirement. make_file() { + # common first line to help identify rewrite versus regular diff + printf "=\n" >file for i in 1 2 3 4 5 6 7 8 9 10 do for j in 1 2 3 4 5 6 7 8 9 @@ -16,7 +18,7 @@ make_file() { printf "$1\n" done done - done >file + done >>file } test_expect_success 'create binary file with changes' ' @@ -42,4 +44,24 @@ test_expect_success 'rewrite diff can show binary patch' ' grep "GIT binary patch" diff ' +{ + echo "#!$SHELL_PATH" + cat >dump <<'EOF' +perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1" +EOF +} >dump +chmod +x dump + +test_expect_success 'setup textconv' ' + echo file diff=foo >.gitattributes && + git config diff.foo.textconv "$PWD"/dump +' + +test_expect_success 'rewrite diff respects textconv' ' + git diff -B >diff && + grep "dissimilarity index" diff && + grep "^-61" diff && + grep "^-0" diff +' + test_done -- cgit v1.3 From cf219d8c68ada1aa2855f4862f15753a32d09641 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 17 Dec 2008 10:26:13 -0800 Subject: Make 'diff_populate_filespec()' use the new 'strbuf_readlink()' This makes all tests pass on a system where 'lstat()' has been hacked to return bogus data in st_size for symlinks. Of course, the test coverage isn't complete, but it's a good baseline. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index afefe087bb..4b2029caa1 100644 --- a/diff.c +++ b/diff.c @@ -1773,19 +1773,17 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) s->size = xsize_t(st.st_size); if (!s->size) goto empty; - if (size_only) - return 0; if (S_ISLNK(st.st_mode)) { - int ret; - s->data = xmalloc(s->size); - s->should_free = 1; - ret = readlink(s->path, s->data, s->size); - if (ret < 0) { - free(s->data); + struct strbuf sb = STRBUF_INIT; + + if (strbuf_readlink(&sb, s->path, s->size)) goto err_empty; - } + s->data = strbuf_detach(&sb, &s->size); + s->should_free = 1; return 0; } + if (size_only) + return 0; fd = open(s->path, O_RDONLY); if (fd < 0) goto err_empty; -- cgit v1.3 From dfab6aaecfe9df67123efc778f6aea4e9814715a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 17 Dec 2008 10:31:36 -0800 Subject: Make 'prepare_temp_file()' ignore st_size for symlinks The code was already set up to not really need it, so this just massages it a bit to remove the use entirely. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 4b2029caa1..f160c1a35b 100644 --- a/diff.c +++ b/diff.c @@ -1881,13 +1881,12 @@ static void prepare_temp_file(const char *name, if (S_ISLNK(st.st_mode)) { int ret; char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */ - size_t sz = xsize_t(st.st_size); - if (sizeof(buf) <= st.st_size) - die("symlink too long: %s", name); - ret = readlink(name, buf, sz); + ret = readlink(name, buf, sizeof(buf)); if (ret < 0) die("readlink(%s)", name); - prep_temp_blob(temp, buf, sz, + if (ret == sizeof(buf)) + die("symlink too long: %s", name); + prep_temp_blob(temp, buf, ret, (one->sha1_valid ? one->sha1 : null_sha1), (one->sha1_valid ? -- cgit v1.3 From 0956a6db7ae3a93c7bce62c1e3a6e0795055ad9f Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Thu, 18 Dec 2008 17:56:51 +0100 Subject: Fix type-mismatch compiler warning from diff_populate_filespec() The type of the size member of filespec is ulong, while strbuf_detach expects a size_t pointer. This patch should fix the warning: Signed-off-by: Junio C Hamano --- diff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f160c1a35b..0484601f42 100644 --- a/diff.c +++ b/diff.c @@ -1778,7 +1778,8 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) if (strbuf_readlink(&sb, s->path, s->size)) goto err_empty; - s->data = strbuf_detach(&sb, &s->size); + s->size = sb.len; + s->data = strbuf_detach(&sb, NULL); s->should_free = 1; return 0; } -- cgit v1.3 From 6d0e674a575421347abe5749e645ca6dc78c8207 Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Sun, 28 Dec 2008 19:45:32 +0100 Subject: diff: add option to show context between close hunks Merge two hunks if there is only the specified number of otherwise unshown context between them. For --inter-hunk-context=1, the resulting patch has the same number of lines but shows uninterrupted context instead of a context header line in between. Patches generated with this option are easier to read but are also more likely to conflict if the file to be patched contains other changes. This patch keeps the default for this option at 0. It is intended to just make the feature available in order to see its advantages and downsides. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 4 ++ contrib/completion/git-completion.bash | 2 + diff.c | 4 ++ diff.h | 1 + t/t4032-diff-inter-hunk-context.sh | 92 ++++++++++++++++++++++++++++++++++ xdiff/xdiff.h | 1 + xdiff/xemit.c | 3 +- 7 files changed, 106 insertions(+), 1 deletion(-) create mode 100755 t/t4032-diff-inter-hunk-context.sh (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index c62b45cdba..c7fcc8007a 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -215,6 +215,10 @@ endif::git-format-patch[] -w:: Shorthand for "--ignore-all-space". +--inter-hunk-context=:: + Show the context between diff hunks, up to the specified number + of lines, thereby fusing hunks that are close to each other. + --exit-code:: Make the program exit with codes similar to diff(1). That is, it exits with 1 if there were differences and diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index e00454983e..a046441974 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -776,6 +776,7 @@ _git_diff () --no-ext-diff --no-prefix --src-prefix= --dst-prefix= --base --ours --theirs + --inter-hunk-context= " return ;; @@ -967,6 +968,7 @@ _git_log () --color-words --walk-reflogs --parents --children --full-history --merge + --inter-hunk-context= " return ;; diff --git a/diff.c b/diff.c index 0484601f42..56b80f9609 100644 --- a/diff.c +++ b/diff.c @@ -1469,6 +1469,7 @@ static void builtin_diff(const char *name_a, ecbdata.file = o->file; xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; + xecfg.interhunkctxlen = o->interhunkcontext; xecfg.flags = XDL_EMIT_FUNCNAMES; if (pe) xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); @@ -2538,6 +2539,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->b_prefix = arg + 13; else if (!strcmp(arg, "--no-prefix")) options->a_prefix = options->b_prefix = ""; + else if (opt_arg(arg, '\0', "inter-hunk-context", + &options->interhunkcontext)) + ; else if (!prefixcmp(arg, "--output=")) { options->file = fopen(arg + strlen("--output="), "w"); options->close_file = 1; diff --git a/diff.h b/diff.h index 42582edee6..4d5a32781d 100644 --- a/diff.h +++ b/diff.h @@ -78,6 +78,7 @@ struct diff_options { const char *a_prefix, *b_prefix; unsigned flags; int context; + int interhunkcontext; int break_opt; int detect_rename; int skip_stat_unmatch; diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh new file mode 100755 index 0000000000..e4e3e28fc7 --- /dev/null +++ b/t/t4032-diff-inter-hunk-context.sh @@ -0,0 +1,92 @@ +#!/bin/sh + +test_description='diff hunk fusing' + +. ./test-lib.sh + +f() { + echo $1 + i=1 + while test $i -le $2 + do + echo $i + i=$(expr $i + 1) + done + echo $3 +} + +t() { + case $# in + 4) hunks=$4; cmd="diff -U$3";; + 5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";; + esac + label="$cmd, $1 common $2" + file=f$1 + expected=expected.$file.$3.$hunks + + if ! test -f $file + then + f A $1 B >$file + git add $file + git commit -q -m. $file + f X $1 Y >$file + fi + + test_expect_success "$label: count hunks ($hunks)" " + test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks + " + + test -f $expected && + test_expect_success "$label: check output" " + git $cmd $file | grep -v '^index ' >actual && + test_cmp $expected actual + " +} + +cat <expected.f1.0.1 || exit 1 +diff --git a/f1 b/f1 +--- a/f1 ++++ b/f1 +@@ -1,3 +1,3 @@ +-A ++X + 1 +-B ++Y +EOF + +cat <expected.f1.0.2 || exit 1 +diff --git a/f1 b/f1 +--- a/f1 ++++ b/f1 +@@ -1 +1 @@ +-A ++X +@@ -3 +3 @@ A +-B ++Y +EOF + +# common lines ctx intrctx hunks +t 1 line 0 2 +t 1 line 0 0 2 +t 1 line 0 1 1 +t 1 line 0 2 1 +t 1 line 1 1 + +t 2 lines 0 2 +t 2 lines 0 0 2 +t 2 lines 0 1 2 +t 2 lines 0 2 1 +t 2 lines 1 1 + +t 3 lines 1 2 +t 3 lines 1 0 2 +t 3 lines 1 1 1 +t 3 lines 1 2 1 + +t 9 lines 3 2 +t 9 lines 3 2 2 +t 9 lines 3 3 1 + +test_done diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h index 84fff583e2..361f802319 100644 --- a/xdiff/xdiff.h +++ b/xdiff/xdiff.h @@ -84,6 +84,7 @@ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long typedef struct s_xdemitconf { long ctxlen; + long interhunkctxlen; unsigned long flags; find_func_t find_func; void *find_func_priv; diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 4625c1b421..05bfa41f10 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -59,9 +59,10 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t * */ xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) { xdchange_t *xch, *xchp; + long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen; for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next) - if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen) + if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common) break; return xchp; -- cgit v1.3 From d75307084da5f89329de190bb9b4a3196cec1d0e Mon Sep 17 00:00:00 2001 From: Alexander Potashev Date: Sun, 4 Jan 2009 21:38:41 +0300 Subject: remove trailing LF in die() messages LF at the end of format strings given to die() is redundant because die already adds one on its own. Signed-off-by: Alexander Potashev Signed-off-by: Junio C Hamano --- builtin-cat-file.c | 2 +- builtin-clone.c | 14 +++++++------- builtin-fetch.c | 2 +- builtin-init-db.c | 2 +- builtin-log.c | 2 +- builtin-mailinfo.c | 2 +- builtin-merge-recursive.c | 2 +- builtin-update-index.c | 2 +- connect.c | 2 +- daemon.c | 2 +- diff.c | 2 +- git.c | 2 +- grep.c | 2 +- imap-send.c | 6 +++--- index-pack.c | 2 +- pack-redundant.c | 8 ++++---- 16 files changed, 27 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/builtin-cat-file.c b/builtin-cat-file.c index 30d00a6664..8fad19daed 100644 --- a/builtin-cat-file.c +++ b/builtin-cat-file.c @@ -137,7 +137,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name) break; default: - die("git cat-file: unknown option: %s\n", exp_type); + die("git cat-file: unknown option: %s", exp_type); } if (!buf) diff --git a/builtin-clone.c b/builtin-clone.c index 2feac9c5cb..f1a1a0c365 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -192,15 +192,15 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) dir = opendir(src->buf); if (!dir) - die("failed to open %s\n", src->buf); + die("failed to open %s", src->buf); if (mkdir(dest->buf, 0777)) { if (errno != EEXIST) - die("failed to create directory %s\n", dest->buf); + die("failed to create directory %s", dest->buf); else if (stat(dest->buf, &buf)) - die("failed to stat %s\n", dest->buf); + die("failed to stat %s", dest->buf); else if (!S_ISDIR(buf.st_mode)) - die("%s exists and is not a directory\n", dest->buf); + die("%s exists and is not a directory", dest->buf); } strbuf_addch(src, '/'); @@ -224,16 +224,16 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) } if (unlink(dest->buf) && errno != ENOENT) - die("failed to unlink %s\n", dest->buf); + die("failed to unlink %s", dest->buf); if (!option_no_hardlinks) { if (!link(src->buf, dest->buf)) continue; if (option_local) - die("failed to create link %s\n", dest->buf); + die("failed to create link %s", dest->buf); option_no_hardlinks = 1; } if (copy_file(dest->buf, src->buf, 0666)) - die("failed to copy file to %s\n", dest->buf); + die("failed to copy file to %s", dest->buf); } closedir(dir); } diff --git a/builtin-fetch.c b/builtin-fetch.c index 7568163af2..de6f3074b1 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -607,7 +607,7 @@ static void set_option(const char *name, const char *value) { int r = transport_set_option(transport, name, value); if (r < 0) - die("Option \"%s\" value \"%s\" is not valid for %s\n", + die("Option \"%s\" value \"%s\" is not valid for %s", name, value, transport->url); if (r > 0) warning("Option \"%s\" is ignored for %s\n", diff --git a/builtin-init-db.c b/builtin-init-db.c index d30c3fe2ca..ee3911f8ee 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -29,7 +29,7 @@ static void safe_create_dir(const char *dir, int share) } } else if (share && adjust_shared_perm(dir)) - die("Could not make %s writable by group\n", dir); + die("Could not make %s writable by group", dir); } static void copy_templates_1(char *path, int baselen, diff --git a/builtin-log.c b/builtin-log.c index bc4e1e9654..4a02ee987a 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -815,7 +815,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) committer = git_committer_info(IDENT_ERROR_ON_NO_NAME); endpos = strchr(committer, '>'); if (!endpos) - die("bogus committer info %s\n", committer); + die("bogus committer info %s", committer); add_signoff = xmemdupz(committer, endpos - committer + 1); } else if (!strcmp(argv[i], "--attach")) { diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index e890f7a6d1..f7c8c08b32 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -494,7 +494,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset) return; out = reencode_string(line->buf, metainfo_charset, charset); if (!out) - die("cannot convert from %s to %s\n", + die("cannot convert from %s to %s", charset, metainfo_charset); strbuf_attach(line, out, strlen(out), strlen(out)); } diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index 6b534c1a66..703045bfc8 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -33,7 +33,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) } if (argc < 4) - die("Usage: %s ... -- ...\n", argv[0]); + die("Usage: %s ... -- ...", argv[0]); for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--")) diff --git a/builtin-update-index.c b/builtin-update-index.c index 65d5775107..5604977505 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -486,7 +486,7 @@ static int unresolve_one(const char *path) static void read_head_pointers(void) { if (read_ref("HEAD", head_sha1)) - die("No HEAD -- no initial commit yet?\n"); + die("No HEAD -- no initial commit yet?"); if (read_ref("MERGE_HEAD", merge_head_sha1)) { fprintf(stderr, "Not in the middle of a merge.\n"); exit(0); diff --git a/connect.c b/connect.c index 2f55ad2c25..2f23ab3b87 100644 --- a/connect.c +++ b/connect.c @@ -315,7 +315,7 @@ static int git_tcp_connect_sock(char *host, int flags) /* Not numeric */ struct servent *se = getservbyname(port,"tcp"); if ( !se ) - die("Unknown port %s\n", port); + die("Unknown port %s", port); nport = se->s_port; } diff --git a/daemon.c b/daemon.c index 60bf6c743c..540700ee84 100644 --- a/daemon.c +++ b/daemon.c @@ -716,7 +716,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p) gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0); if (gai) - die("getaddrinfo() failed: %s\n", gai_strerror(gai)); + die("getaddrinfo() failed: %s", gai_strerror(gai)); for (ai = ai0; ai; ai = ai->ai_next) { int sockfd; diff --git a/diff.c b/diff.c index 0484601f42..c159a5fc65 100644 --- a/diff.c +++ b/diff.c @@ -2039,7 +2039,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one) if (lstat(one->path, &st) < 0) die("stat %s", one->path); if (index_path(one->sha1, one->path, &st, 0)) - die("cannot hash %s\n", one->path); + die("cannot hash %s", one->path); } } else diff --git a/git.c b/git.c index e0d9071358..a53e24feae 100644 --- a/git.c +++ b/git.c @@ -158,7 +158,7 @@ static int handle_alias(int *argcp, const char ***argv) if (ret >= 0 && WIFEXITED(ret) && WEXITSTATUS(ret) != 127) exit(WEXITSTATUS(ret)); - die("Failed to run '%s' when expanding alias '%s'\n", + die("Failed to run '%s' when expanding alias '%s'", alias_string + 1, alias_command); } count = split_cmdline(alias_string, &new_argv); diff --git a/grep.c b/grep.c index 600f69f2fe..49e9319965 100644 --- a/grep.c +++ b/grep.c @@ -395,7 +395,7 @@ static int match_expr_eval(struct grep_opt *o, h |= match_expr_eval(o, x->u.binary.right, bol, eol, ctx, 1); break; default: - die("Unexpected node type (internal error) %d\n", x->node); + die("Unexpected node type (internal error) %d", x->node); } if (collect_hits) x->hit |= h; diff --git a/imap-send.c b/imap-send.c index 3703dbd1af..c3fa0df855 100644 --- a/imap-send.c +++ b/imap-send.c @@ -115,9 +115,9 @@ static int nfvasprintf(char **strp, const char *fmt, va_list ap) len = vsnprintf(tmp, sizeof(tmp), fmt, ap); if (len < 0) - die("Fatal: Out of memory\n"); + die("Fatal: Out of memory"); if (len >= sizeof(tmp)) - die("imap command overflow !\n"); + die("imap command overflow!"); *strp = xmemdupz(tmp, len); return len; } @@ -482,7 +482,7 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...) va_start(va, fmt); if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen) - die("Fatal: buffer too small. Please report a bug.\n"); + die("Fatal: buffer too small. Please report a bug."); va_end(va); return ret; } diff --git a/index-pack.c b/index-pack.c index 60ed41a993..2931511e8c 100644 --- a/index-pack.c +++ b/index-pack.c @@ -178,7 +178,7 @@ static char *open_pack_file(char *pack_name) } else output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600); if (output_fd < 0) - die("unable to create %s: %s\n", pack_name, strerror(errno)); + die("unable to create %s: %s", pack_name, strerror(errno)); pack_fd = output_fd; } else { input_fd = open(pack_name, O_RDONLY); diff --git a/pack-redundant.c b/pack-redundant.c index 25b81a445c..e93eb966e2 100644 --- a/pack-redundant.c +++ b/pack-redundant.c @@ -463,7 +463,7 @@ static void minimize(struct pack_list **min) pll_free(perm_all); } if (perm_ok == NULL) - die("Internal error: No complete sets found!\n"); + die("Internal error: No complete sets found!"); /* find the permutation with the smallest size */ perm = perm_ok; @@ -573,14 +573,14 @@ static struct pack_list * add_pack_file(char *filename) struct packed_git *p = packed_git; if (strlen(filename) < 40) - die("Bad pack filename: %s\n", filename); + die("Bad pack filename: %s", filename); while (p) { if (strstr(p->pack_name, filename)) return add_pack(p); p = p->next; } - die("Filename %s not found in packed_git\n", filename); + die("Filename %s not found in packed_git", filename); } static void load_all(void) @@ -636,7 +636,7 @@ int main(int argc, char **argv) add_pack_file(*(argv + i++)); if (local_packs == NULL) - die("Zero packs found!\n"); + die("Zero packs found!"); load_all_objects(); -- cgit v1.3 From 34292bddb861f3cb52a524fdce67234430a744fe Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 1 Jan 2009 17:39:17 +0100 Subject: Introduce the diff option '--patience' This commit teaches Git to produce diff output using the patience diff algorithm with the diff option '--patience'. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 3 + Makefile | 2 +- diff.c | 2 + t/t4033-diff-patience.sh | 168 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 1 deletion(-) create mode 100755 t/t4033-diff-patience.sh (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index c62b45cdba..808bf87277 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -40,6 +40,9 @@ endif::git-format-patch[] --patch-with-raw:: Synonym for "-p --raw". +--patience: + Generate a diff using the "patience diff" algorithm. + --stat[=width[,name-width]]:: Generate a diffstat. You can override the default output width for 80-column terminal by "--stat=width". diff --git a/Makefile b/Makefile index aabf0130b9..33e6fa403e 100644 --- a/Makefile +++ b/Makefile @@ -1287,7 +1287,7 @@ $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \ - xdiff/xmerge.o + xdiff/xmerge.o xdiff/xpatience.o $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \ xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h diff --git a/diff.c b/diff.c index 0484601f42..4aeab7746c 100644 --- a/diff.c +++ b/diff.c @@ -2471,6 +2471,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; else if (!strcmp(arg, "--ignore-space-at-eol")) options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL; + else if (!strcmp(arg, "--patience")) + options->xdl_opts |= XDF_PATIENCE_DIFF; /* flags options */ else if (!strcmp(arg, "--binary")) { diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh new file mode 100755 index 0000000000..1eb14989df --- /dev/null +++ b/t/t4033-diff-patience.sh @@ -0,0 +1,168 @@ +#!/bin/sh + +test_description='patience diff algorithm' + +. ./test-lib.sh + +cat >file1 <<\EOF +#include + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("Your answer is: "); + printf("%d\n", foo); + } +} + +int fact(int n) +{ + if(n > 1) + { + return fact(n-1) * n; + } + return 1; +} + +int main(int argc, char **argv) +{ + frobnitz(fact(10)); +} +EOF + +cat >file2 <<\EOF +#include + +int fib(int n) +{ + if(n > 2) + { + return fib(n-1) + fib(n-2); + } + return 1; +} + +// Frobs foo heartily +int frobnitz(int foo) +{ + int i; + for(i = 0; i < 10; i++) + { + printf("%d\n", foo); + } +} + +int main(int argc, char **argv) +{ + frobnitz(fib(10)); +} +EOF + +cat >expect <<\EOF +diff --git a/file1 b/file2 +index 6faa5a3..e3af329 100644 +--- a/file1 ++++ b/file2 +@@ -1,26 +1,25 @@ + #include + ++int fib(int n) ++{ ++ if(n > 2) ++ { ++ return fib(n-1) + fib(n-2); ++ } ++ return 1; ++} ++ + // Frobs foo heartily + int frobnitz(int foo) + { + int i; + for(i = 0; i < 10; i++) + { +- printf("Your answer is: "); + printf("%d\n", foo); + } + } + +-int fact(int n) +-{ +- if(n > 1) +- { +- return fact(n-1) * n; +- } +- return 1; +-} +- + int main(int argc, char **argv) + { +- frobnitz(fact(10)); ++ frobnitz(fib(10)); + } +EOF + +test_expect_success 'patience diff' ' + + test_must_fail git diff --no-index --patience file1 file2 > output && + test_cmp expect output + +' + +test_expect_success 'patience diff output is valid' ' + + mv file2 expect && + git apply < output && + test_cmp expect file2 + +' + +cat >uniq1 <<\EOF +1 +2 +3 +4 +5 +6 +EOF + +cat >uniq2 <<\EOF +a +b +c +d +e +f +EOF + +cat >expect <<\EOF +diff --git a/uniq1 b/uniq2 +index b414108..0fdf397 100644 +--- a/uniq1 ++++ b/uniq2 +@@ -1,6 +1,6 @@ +-1 +-2 +-3 +-4 +-5 +-6 ++a ++b ++c ++d ++e ++f +EOF + +test_expect_success 'completely different files' ' + + test_must_fail git diff --no-index --patience uniq1 uniq2 > output && + test_cmp expect output + +' + +test_done -- cgit v1.3 From 23c1575f747393f9847874fd1ed72a44557459d1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 17 Jan 2009 17:29:43 +0100 Subject: color-words: refactor word splitting and use ALLOC_GROW() Word splitting is now performed by the function diff_words_fill(), avoiding having the same code twice. In the same spirit, avoid duplicating the code of ALLOC_GROW(). Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d23548292a..c111eef13e 100644 --- a/diff.c +++ b/diff.c @@ -326,10 +326,7 @@ struct diff_words_buffer { static void diff_words_append(char *line, unsigned long len, struct diff_words_buffer *buffer) { - if (buffer->text.size + len > buffer->alloc) { - buffer->alloc = (buffer->text.size + len) * 3 / 2; - buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc); - } + ALLOC_GROW(buffer->text.ptr, buffer->text.size + len, buffer->alloc); line++; len--; memcpy(buffer->text.ptr + buffer->text.size, line, len); @@ -398,6 +395,22 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) } } +/* + * This function splits the words in buffer->text, and stores the list with + * newline separator into out. + */ +static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out) +{ + int i; + out->size = buffer->text.size; + out->ptr = xmalloc(out->size); + memcpy(out->ptr, buffer->text.ptr, out->size); + for (i = 0; i < out->size; i++) + if (isspace(out->ptr[i])) + out->ptr[i] = '\n'; + buffer->current = 0; +} + /* this executes the word diff on the accumulated buffers */ static void diff_words_show(struct diff_words_data *diff_words) { @@ -405,26 +418,11 @@ static void diff_words_show(struct diff_words_data *diff_words) xdemitconf_t xecfg; xdemitcb_t ecb; mmfile_t minus, plus; - int i; memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); - minus.size = diff_words->minus.text.size; - minus.ptr = xmalloc(minus.size); - memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size); - for (i = 0; i < minus.size; i++) - if (isspace(minus.ptr[i])) - minus.ptr[i] = '\n'; - diff_words->minus.current = 0; - - plus.size = diff_words->plus.text.size; - plus.ptr = xmalloc(plus.size); - memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size); - for (i = 0; i < plus.size; i++) - if (isspace(plus.ptr[i])) - plus.ptr[i] = '\n'; - diff_words->plus.current = 0; - + diff_words_fill(&diff_words->minus, &minus); + diff_words_fill(&diff_words->plus, &plus); xpp.flags = XDF_NEED_MINIMAL; xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc; xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, -- cgit v1.3 From 2e5d2003b28820f88296e47a79eb440ca0295000 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 17 Jan 2009 17:29:44 +0100 Subject: color-words: change algorithm to allow for 0-character word boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up until now, the color-words code assumed that word boundaries are identical to white space characters. Therefore, it could get away with a very simple scheme: it copied the hunks, substituted newlines for each white space character, called libxdiff with the processed text, and then identified the text to output by the offsets (which agreed since the original text had the same length). This code was ugly, for a number of reasons: - it was impossible to introduce 0-character word boundaries, - we had to print everything word by word, and - the code needed extra special handling of newlines in the removed part. Fix all of these issues by processing the text such that - we build word lists, separated by newlines, - we remember the original offsets for every word, and - after calling libxdiff on the wordlists, we parse the hunk headers, and find the corresponding offsets, and then - we print the removed/added parts in one go. The pre and post samples in the test were provided by Santi Béjar. Note that there is some strange special handling of hunk headers where one line range is 0 due to POSIX: in this case, the start is one too low. In other words a hunk header '@@ -1,0 +2 @@' actually means that the line must be added after the _second_ line of the pre text, _not_ the first. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 157 +++++++++++++++++++++++++++++--------------------- t/t4034-diff-words.sh | 66 +++++++++++++++++++++ 2 files changed, 157 insertions(+), 66 deletions(-) create mode 100755 t/t4034-diff-words.sh (limited to 'diff.c') diff --git a/diff.c b/diff.c index c111eef13e..37c886a815 100644 --- a/diff.c +++ b/diff.c @@ -319,8 +319,10 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one) struct diff_words_buffer { mmfile_t text; long alloc; - long current; /* output pointer */ - int suppressed_newline; + struct diff_words_orig { + const char *begin, *end; + } *orig; + int orig_nr, orig_alloc; }; static void diff_words_append(char *line, unsigned long len, @@ -335,80 +337,89 @@ static void diff_words_append(char *line, unsigned long len, struct diff_words_data { struct diff_words_buffer minus, plus; + const char *current_plus; FILE *file; }; -static void print_word(FILE *file, struct diff_words_buffer *buffer, int len, int color, - int suppress_newline) +static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) { - const char *ptr; - int eol = 0; + struct diff_words_data *diff_words = priv; + int minus_first, minus_len, plus_first, plus_len; + const char *minus_begin, *minus_end, *plus_begin, *plus_end; - if (len == 0) + if (line[0] != '@' || parse_hunk_header(line, len, + &minus_first, &minus_len, &plus_first, &plus_len)) return; - ptr = buffer->text.ptr + buffer->current; - buffer->current += len; + /* POSIX requires that first be decremented by one if len == 0... */ + if (minus_len) { + minus_begin = diff_words->minus.orig[minus_first].begin; + minus_end = + diff_words->minus.orig[minus_first + minus_len - 1].end; + } else + minus_begin = minus_end = + diff_words->minus.orig[minus_first].end; - if (ptr[len - 1] == '\n') { - eol = 1; - len--; - } + if (plus_len) { + plus_begin = diff_words->plus.orig[plus_first].begin; + plus_end = diff_words->plus.orig[plus_first + plus_len - 1].end; + } else + plus_begin = plus_end = diff_words->plus.orig[plus_first].end; - fputs(diff_get_color(1, color), file); - fwrite(ptr, len, 1, file); - fputs(diff_get_color(1, DIFF_RESET), file); + if (diff_words->current_plus != plus_begin) + fwrite(diff_words->current_plus, + plus_begin - diff_words->current_plus, 1, + diff_words->file); + if (minus_begin != minus_end) + color_fwrite_lines(diff_words->file, + diff_get_color(1, DIFF_FILE_OLD), + minus_end - minus_begin, minus_begin); + if (plus_begin != plus_end) + color_fwrite_lines(diff_words->file, + diff_get_color(1, DIFF_FILE_NEW), + plus_end - plus_begin, plus_begin); - if (eol) { - if (suppress_newline) - buffer->suppressed_newline = 1; - else - putc('\n', file); - } -} - -static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) -{ - struct diff_words_data *diff_words = priv; - - if (diff_words->minus.suppressed_newline) { - if (line[0] != '+') - putc('\n', diff_words->file); - diff_words->minus.suppressed_newline = 0; - } - - len--; - switch (line[0]) { - case '-': - print_word(diff_words->file, - &diff_words->minus, len, DIFF_FILE_OLD, 1); - break; - case '+': - print_word(diff_words->file, - &diff_words->plus, len, DIFF_FILE_NEW, 0); - break; - case ' ': - print_word(diff_words->file, - &diff_words->plus, len, DIFF_PLAIN, 0); - diff_words->minus.current += len; - break; - } + diff_words->current_plus = plus_end; } /* - * This function splits the words in buffer->text, and stores the list with - * newline separator into out. + * This function splits the words in buffer->text, stores the list with + * newline separator into out, and saves the offsets of the original words + * in buffer->orig. */ static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out) { - int i; - out->size = buffer->text.size; - out->ptr = xmalloc(out->size); - memcpy(out->ptr, buffer->text.ptr, out->size); - for (i = 0; i < out->size; i++) - if (isspace(out->ptr[i])) - out->ptr[i] = '\n'; - buffer->current = 0; + int i, j; + + out->size = 0; + out->ptr = xmalloc(buffer->text.size); + + /* fake an empty "0th" word */ + ALLOC_GROW(buffer->orig, 1, buffer->orig_alloc); + buffer->orig[0].begin = buffer->orig[0].end = buffer->text.ptr; + buffer->orig_nr = 1; + + for (i = 0; i < buffer->text.size; i++) { + if (isspace(buffer->text.ptr[i])) + continue; + for (j = i + 1; j < buffer->text.size && + !isspace(buffer->text.ptr[j]); j++) + ; /* find the end of the word */ + + /* store original boundaries */ + ALLOC_GROW(buffer->orig, buffer->orig_nr + 1, + buffer->orig_alloc); + buffer->orig[buffer->orig_nr].begin = buffer->text.ptr + i; + buffer->orig[buffer->orig_nr].end = buffer->text.ptr + j; + buffer->orig_nr++; + + /* store one word */ + memcpy(out->ptr + out->size, buffer->text.ptr + i, j - i); + out->ptr[out->size + j - i] = '\n'; + out->size += j - i + 1; + + i = j - 1; + } } /* this executes the word diff on the accumulated buffers */ @@ -419,22 +430,34 @@ static void diff_words_show(struct diff_words_data *diff_words) xdemitcb_t ecb; mmfile_t minus, plus; + /* special case: only removal */ + if (!diff_words->plus.text.size) { + color_fwrite_lines(diff_words->file, + diff_get_color(1, DIFF_FILE_OLD), + diff_words->minus.text.size, diff_words->minus.text.ptr); + diff_words->minus.text.size = 0; + return; + } + + diff_words->current_plus = diff_words->plus.text.ptr; + memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); diff_words_fill(&diff_words->minus, &minus); diff_words_fill(&diff_words->plus, &plus); xpp.flags = XDF_NEED_MINIMAL; - xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc; + xecfg.ctxlen = 0; xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); + if (diff_words->current_plus != diff_words->plus.text.ptr + + diff_words->plus.text.size) + fwrite(diff_words->current_plus, + diff_words->plus.text.ptr + diff_words->plus.text.size + - diff_words->current_plus, 1, + diff_words->file); diff_words->minus.text.size = diff_words->plus.text.size = 0; - - if (diff_words->minus.suppressed_newline) { - putc('\n', diff_words->file); - diff_words->minus.suppressed_newline = 0; - } } typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len); @@ -458,7 +481,9 @@ static void free_diff_words_data(struct emit_callback *ecbdata) diff_words_show(ecbdata->diff_words); free (ecbdata->diff_words->minus.text.ptr); + free (ecbdata->diff_words->minus.orig); free (ecbdata->diff_words->plus.text.ptr); + free (ecbdata->diff_words->plus.orig); free(ecbdata->diff_words); ecbdata->diff_words = NULL; } diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh new file mode 100755 index 0000000000..b22195f8bb --- /dev/null +++ b/t/t4034-diff-words.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +test_description='word diff colors' + +. ./test-lib.sh + +test_expect_success setup ' + + git config diff.color.old red + git config diff.color.new green + +' + +decrypt_color () { + sed \ + -e 's/.\[1m//g' \ + -e 's/.\[31m//g' \ + -e 's/.\[32m//g' \ + -e 's/.\[36m//g' \ + -e 's/.\[m//g' +} + +word_diff () { + test_must_fail git diff --no-index "$@" pre post > output && + decrypt_color < output > output.decrypted && + test_cmp expect output.decrypted +} + +cat > pre <<\EOF +h(4) + +a = b + c +EOF + +cat > post <<\EOF +h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +cat > expect <<\EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +h(4)h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +test_expect_success 'word diff with runs of whitespace' ' + + word_diff --color-words + +' + +test_done -- cgit v1.3 From 2b6a5417d750d086d1da906e46de2b3ad8df6753 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 17 Jan 2009 17:29:45 +0100 Subject: color-words: take an optional regular expression describing words In some applications, words are not delimited by white space. To allow for that, you can specify a regular expression describing what makes a word with git diff --color-words='[A-Za-z0-9]+' Note that words cannot contain newline characters. As suggested by Thomas Rast, the words are the exact matches of the regular expression. Note that a regular expression beginning with a '^' will match only a word at the beginning of the hunk, not a word at the beginning of a line, and is probably not what you want. This commit contains a quoting fix by Thomas Rast. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 6 +++- diff.c | 64 ++++++++++++++++++++++++++++++++++++------ diff.h | 1 + t/t4034-diff-words.sh | 57 +++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 10 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 43793d7500..2c1fa4b102 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -91,8 +91,12 @@ endif::git-format-patch[] Turn off colored diff, even when the configuration file gives the default to color output. ---color-words:: +--color-words[=regex]:: Show colored word diff, i.e. color words which have changed. ++ +Optionally, you can pass a regular expression that tells Git what the +words are that you are looking for; The default is to interpret any +stretch of non-whitespace as a word. --no-renames:: Turn off rename detection, even when the configuration diff --git a/diff.c b/diff.c index 37c886a815..9fb3d0df31 100644 --- a/diff.c +++ b/diff.c @@ -333,12 +333,14 @@ static void diff_words_append(char *line, unsigned long len, len--; memcpy(buffer->text.ptr + buffer->text.size, line, len); buffer->text.size += len; + buffer->text.ptr[buffer->text.size] = '\0'; } struct diff_words_data { struct diff_words_buffer minus, plus; const char *current_plus; FILE *file; + regex_t *word_regex; }; static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) @@ -382,17 +384,49 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len) diff_words->current_plus = plus_end; } +/* This function starts looking at *begin, and returns 0 iff a word was found. */ +static int find_word_boundaries(mmfile_t *buffer, regex_t *word_regex, + int *begin, int *end) +{ + if (word_regex && *begin < buffer->size) { + regmatch_t match[1]; + if (!regexec(word_regex, buffer->ptr + *begin, 1, match, 0)) { + char *p = memchr(buffer->ptr + *begin + match[0].rm_so, + '\n', match[0].rm_eo - match[0].rm_so); + *end = p ? p - buffer->ptr : match[0].rm_eo + *begin; + *begin += match[0].rm_so; + return *begin >= *end; + } + return -1; + } + + /* find the next word */ + while (*begin < buffer->size && isspace(buffer->ptr[*begin])) + (*begin)++; + if (*begin >= buffer->size) + return -1; + + /* find the end of the word */ + *end = *begin + 1; + while (*end < buffer->size && !isspace(buffer->ptr[*end])) + (*end)++; + + return 0; +} + /* * This function splits the words in buffer->text, stores the list with * newline separator into out, and saves the offsets of the original words * in buffer->orig. */ -static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out) +static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out, + regex_t *word_regex) { int i, j; + long alloc = 0; out->size = 0; - out->ptr = xmalloc(buffer->text.size); + out->ptr = NULL; /* fake an empty "0th" word */ ALLOC_GROW(buffer->orig, 1, buffer->orig_alloc); @@ -400,11 +434,8 @@ static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out) buffer->orig_nr = 1; for (i = 0; i < buffer->text.size; i++) { - if (isspace(buffer->text.ptr[i])) - continue; - for (j = i + 1; j < buffer->text.size && - !isspace(buffer->text.ptr[j]); j++) - ; /* find the end of the word */ + if (find_word_boundaries(&buffer->text, word_regex, &i, &j)) + return; /* store original boundaries */ ALLOC_GROW(buffer->orig, buffer->orig_nr + 1, @@ -414,6 +445,7 @@ static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out) buffer->orig_nr++; /* store one word */ + ALLOC_GROW(out->ptr, out->size + j - i + 1, alloc); memcpy(out->ptr + out->size, buffer->text.ptr + i, j - i); out->ptr[out->size + j - i] = '\n'; out->size += j - i + 1; @@ -443,9 +475,10 @@ static void diff_words_show(struct diff_words_data *diff_words) memset(&xpp, 0, sizeof(xpp)); memset(&xecfg, 0, sizeof(xecfg)); - diff_words_fill(&diff_words->minus, &minus); - diff_words_fill(&diff_words->plus, &plus); + diff_words_fill(&diff_words->minus, &minus, diff_words->word_regex); + diff_words_fill(&diff_words->plus, &plus, diff_words->word_regex); xpp.flags = XDF_NEED_MINIMAL; + /* as only the hunk header will be parsed, we need a 0-context */ xecfg.ctxlen = 0; xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, &xpp, &xecfg, &ecb); @@ -484,6 +517,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata) free (ecbdata->diff_words->minus.orig); free (ecbdata->diff_words->plus.text.ptr); free (ecbdata->diff_words->plus.orig); + free(ecbdata->diff_words->word_regex); free(ecbdata->diff_words); ecbdata->diff_words = NULL; } @@ -1506,6 +1540,14 @@ static void builtin_diff(const char *name_a, ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); ecbdata.diff_words->file = o->file; + if (o->word_regex) { + ecbdata.diff_words->word_regex = (regex_t *) + xmalloc(sizeof(regex_t)); + if (regcomp(ecbdata.diff_words->word_regex, + o->word_regex, REG_EXTENDED)) + die ("Invalid regular expression: %s", + o->word_regex); + } } xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, &xpp, &xecfg, &ecb); @@ -2517,6 +2559,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_CLR(options, COLOR_DIFF); else if (!strcmp(arg, "--color-words")) options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; + else if (!prefixcmp(arg, "--color-words=")) { + options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; + options->word_regex = arg + 14; + } else if (!strcmp(arg, "--exit-code")) DIFF_OPT_SET(options, EXIT_WITH_STATUS); else if (!strcmp(arg, "--quiet")) diff --git a/diff.h b/diff.h index 4d5a32781d..23cd90c2e6 100644 --- a/diff.h +++ b/diff.h @@ -98,6 +98,7 @@ struct diff_options { int stat_width; int stat_name_width; + const char *word_regex; /* this is set by diffcore for DIFF_FORMAT_PATCH */ int found_changes; diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index b22195f8bb..4873486301 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -63,4 +63,61 @@ test_expect_success 'word diff with runs of whitespace' ' ' +cat > expect <<\EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +test_expect_success 'word diff with a regular expression' ' + + word_diff --color-words="[a-z]+" + +' + +echo 'aaa (aaa)' > pre +echo 'aaa (aaa) aaa' > post + +cat > expect <<\EOF +diff --git a/pre b/post +index c29453b..be22f37 100644 +--- a/pre ++++ b/post +@@ -1 +1 @@ +aaa (aaa) aaa +EOF + +test_expect_success 'test parsing words for newline' ' + + word_diff --color-words="a+" + +' + +echo '(:' > pre +echo '(' > post + +cat > expect <<\EOF +diff --git a/pre b/post +index 289cb9d..2d06f37 100644 +--- a/pre ++++ b/post +@@ -1 +1 @@ +(: +EOF + +test_expect_success 'test when words are only removed at the end' ' + + word_diff --color-words=. + +' + test_done -- cgit v1.3 From bf82940dbf12f066ba42a2a03a5bb626ba22c067 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 17 Jan 2009 17:29:46 +0100 Subject: color-words: enable REG_NEWLINE to help user We silently truncate a match at the newline, which may lead to unexpected behaviour, e.g., when matching "<[^>]*>" against since then "" doesn't!) even though the regex said only angle-bracket-delimited things can be words. To alleviate the problem slightly, use REG_NEWLINE so that negated classes can't match a newline. Of course newlines can still be matched explicitly. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- diff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 9fb3d0df31..00c661f82e 100644 --- a/diff.c +++ b/diff.c @@ -1544,7 +1544,8 @@ static void builtin_diff(const char *name_a, ecbdata.diff_words->word_regex = (regex_t *) xmalloc(sizeof(regex_t)); if (regcomp(ecbdata.diff_words->word_regex, - o->word_regex, REG_EXTENDED)) + o->word_regex, + REG_EXTENDED | REG_NEWLINE)) die ("Invalid regular expression: %s", o->word_regex); } -- cgit v1.3 From 80c49c3de2d5a3aa12b0980a65f1163c8aef0c16 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 17 Jan 2009 17:29:48 +0100 Subject: color-words: make regex configurable via attributes Make the --color-words splitting regular expression configurable via the diff driver's 'wordregex' attribute. The user can then set the driver on a file in .gitattributes. If a regex is given on the command line, it overrides the driver's setting. We also provide built-in regexes for the languages that already had funcname patterns, and add an appropriate diff driver entry for C/++. (The patterns are designed to run UTF-8 sequences into a single chunk to make sure they remain readable.) Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 4 +++ Documentation/gitattributes.txt | 21 +++++++++++ diff.c | 10 ++++++ t/t4034-diff-words.sh | 36 +++++++++++++++++++ userdiff.c | 78 +++++++++++++++++++++++++++++++++-------- userdiff.h | 1 + 6 files changed, 135 insertions(+), 15 deletions(-) (limited to 'diff.c') diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 8689a92d8d..1edb82e8e1 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -102,6 +102,10 @@ differences. You may want to append `|[^[:space:]]` to your regular expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline. ++ +The regex can also be set via a diff driver, see +linkgit:gitattributes[1]; giving it explicitly overrides any diff +driver setting. --no-renames:: Turn off rename detection, even when the configuration diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 8af22eccac..ba3ba12730 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -317,6 +317,8 @@ patterns are available: - `bibtex` suitable for files with BibTeX coded references. +- `cpp` suitable for source code in the C and C++ languages. + - `html` suitable for HTML/XHTML documents. - `java` suitable for source code in the Java language. @@ -334,6 +336,25 @@ patterns are available: - `tex` suitable for source code for LaTeX documents. +Customizing word diff +^^^^^^^^^^^^^^^^^^^^^ + +You can customize the rules that `git diff --color-words` uses to +split words in a line, by specifying an appropriate regular expression +in the "diff.*.wordregex" configuration variable. For example, in TeX +a backslash followed by a sequence of letters forms a command, but +several such commands can be run together without intervening +whitespace. To separate them, use a regular expression such as + +------------------------ +[diff "tex"] + wordregex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+" +------------------------ + +A built-in pattern is provided for all languages listed in the +previous section. + + Performing text diffs of binary files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/diff.c b/diff.c index 00c661f82e..9fcde963db 100644 --- a/diff.c +++ b/diff.c @@ -1380,6 +1380,12 @@ static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespe return one->driver->funcname.pattern ? &one->driver->funcname : NULL; } +static const char *userdiff_word_regex(struct diff_filespec *one) +{ + diff_filespec_load_driver(one); + return one->driver->word_regex; +} + void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b) { if (!options->a_prefix) @@ -1540,6 +1546,10 @@ static void builtin_diff(const char *name_a, ecbdata.diff_words = xcalloc(1, sizeof(struct diff_words_data)); ecbdata.diff_words->file = o->file; + if (!o->word_regex) + o->word_regex = userdiff_word_regex(one); + if (!o->word_regex) + o->word_regex = userdiff_word_regex(two); if (o->word_regex) { ecbdata.diff_words->word_regex = (regex_t *) xmalloc(sizeof(regex_t)); diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 4873486301..744221bef9 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -84,6 +84,41 @@ test_expect_success 'word diff with a regular expression' ' ' +test_expect_success 'set a diff driver' ' + git config diff.testdriver.wordregex "[^[:space:]]" && + cat < .gitattributes +pre diff=testdriver +post diff=testdriver +EOF +' + +test_expect_success 'option overrides default' ' + + word_diff --color-words="[a-z]+" + +' + +cat > expect <<\EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +test_expect_success 'use default supplied by driver' ' + + word_diff --color-words + +' + echo 'aaa (aaa)' > pre echo 'aaa (aaa) aaa' > post @@ -100,6 +135,7 @@ test_expect_success 'test parsing words for newline' ' word_diff --color-words="a+" + ' echo '(:' > pre diff --git a/userdiff.c b/userdiff.c index 3681062ebf..2b55509485 100644 --- a/userdiff.c +++ b/userdiff.c @@ -6,14 +6,20 @@ static struct userdiff_driver *drivers; static int ndrivers; static int drivers_alloc; -#define FUNCNAME(name, pattern) \ - { name, NULL, -1, { pattern, REG_EXTENDED } } +#define PATTERNS(name, pattern, wordregex) \ + { name, NULL, -1, { pattern, REG_EXTENDED }, wordregex } static struct userdiff_driver builtin_drivers[] = { -FUNCNAME("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$"), -FUNCNAME("java", +PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", + "[^<>= \t]+|[^[:space:]]|[\x80-\xff]+"), +PATTERNS("java", "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n" - "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$"), -FUNCNAME("objc", + "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$", + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" + "|[-+*/<>%&^|=!]=" + "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|" + "|[^[:space:]]|[\x80-\xff]+"), +PATTERNS("objc", /* Negate C statements that can look like functions */ "!^[ \t]*(do|for|if|else|return|switch|while)\n" /* Objective-C methods */ @@ -21,20 +27,60 @@ FUNCNAME("objc", /* C functions */ "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n" /* Objective-C class/protocol definitions */ - "^(@(implementation|interface|protocol)[ \t].*)$"), -FUNCNAME("pascal", + "^(@(implementation|interface|protocol)[ \t].*)$", + /* -- */ + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" + "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->" + "|[^[:space:]]|[\x80-\xff]+"), +PATTERNS("pascal", "^((procedure|function|constructor|destructor|interface|" "implementation|initialization|finalization)[ \t]*.*)$" "\n" - "^(.*=[ \t]*(class|record).*)$"), -FUNCNAME("php", "^[\t ]*((function|class).*)"), -FUNCNAME("python", "^[ \t]*((class|def)[ \t].*)$"), -FUNCNAME("ruby", "^[ \t]*((class|module|def)[ \t].*)$"), -FUNCNAME("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$"), -FUNCNAME("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$"), + "^(.*=[ \t]*(class|record).*)$", + /* -- */ + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+" + "|<>|<=|>=|:=|\\.\\." + "|[^[:space:]]|[\x80-\xff]+"), +PATTERNS("php", "^[\t ]*((function|class).*)", + /* -- */ + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+" + "|[-+*/<>%&^|=!.]=|--|\\+\\+|<<=?|>>=?|===|&&|\\|\\||::|->" + "|[^[:space:]]|[\x80-\xff]+"), +PATTERNS("python", "^[ \t]*((class|def)[ \t].*)$", + /* -- */ + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+[jJlL]?|0[xX]?[0-9a-fA-F]+[lL]?" + "|[-+*/<>%&^|=!]=|//=?|<<=?|>>=?|\\*\\*=?" + "|[^[:space:]|[\x80-\xff]+"), + /* -- */ +PATTERNS("ruby", "^[ \t]*((class|module|def)[ \t].*)$", + /* -- */ + "(@|@@|\\$)?[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?." + "|//=?|[-+*/<>%&^|=!]=|<<=?|>>=?|===|\\.{1,3}|::|[!=]~" + "|[^[:space:]|[\x80-\xff]+"), +PATTERNS("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$", + "[={}\"]|[^={}\" \t]+"), +PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$", + "\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+|[^[:space:]]"), +PATTERNS("cpp", + /* Jump targets or access declarations */ + "!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:.*$\n" + /* C/++ functions/methods at top level */ + "^([A-Za-z_][A-Za-z_0-9]*([ \t]+[A-Za-z_][A-Za-z_0-9]*([ \t]*::[ \t]*[^[:space:]]+)?){1,}[ \t]*\\([^;]*)$\n" + /* compound type at top level */ + "^((struct|class|enum)[^;]*)$", + /* -- */ + "[a-zA-Z_][a-zA-Z0-9_]*" + "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?" + "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->" + "|[^[:space:]]|[\x80-\xff]+"), { "default", NULL, -1, { NULL, 0 } }, }; -#undef FUNCNAME +#undef PATTERNS static struct userdiff_driver driver_true = { "diff=true", @@ -134,6 +180,8 @@ int userdiff_config(const char *k, const char *v) return parse_string(&drv->external, k, v); if ((drv = parse_driver(k, v, "textconv"))) return parse_string(&drv->textconv, k, v); + if ((drv = parse_driver(k, v, "wordregex"))) + return parse_string(&drv->word_regex, k, v); return 0; } diff --git a/userdiff.h b/userdiff.h index ba2945770b..c3151594f5 100644 --- a/userdiff.h +++ b/userdiff.h @@ -11,6 +11,7 @@ struct userdiff_driver { const char *external; int binary; struct userdiff_funcname funcname; + const char *word_regex; const char *textconv; }; -- cgit v1.3 From 950db8798d51cb183c858938263425b367b21dfd Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 20 Jan 2009 22:08:33 +0100 Subject: Rename diff.suppress-blank-empty to diff.suppressBlankEmpty All the other config variables use CamelCase. This config variable should not be an exception. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/config.txt | 2 +- diff.c | 4 +++- t/t4029-diff-trailing-space.sh | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 52786c7df5..26551ea6e1 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -635,7 +635,7 @@ diff.renames:: will enable basic rename detection. If set to "copies" or "copy", it will detect copies, as well. -diff.suppress-blank-empty:: +diff.suppressBlankEmpty:: A boolean to inhibit the standard behavior of printing a space before each empty output line. Defaults to false. diff --git a/diff.c b/diff.c index 0484601f42..5b85b4077a 100644 --- a/diff.c +++ b/diff.c @@ -118,7 +118,9 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) } /* like GNU diff's --suppress-blank-empty option */ - if (!strcmp(var, "diff.suppress-blank-empty")) { + if (!strcmp(var, "diff.suppressblankempty") || + /* for backwards compatibility */ + !strcmp(var, "diff.suppress-blank-empty")) { diff_suppress_blank_empty = git_config_bool(var, value); return 0; } diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh index 4ca65e0332..9ddbbcde57 100755 --- a/t/t4029-diff-trailing-space.sh +++ b/t/t4029-diff-trailing-space.sh @@ -2,7 +2,7 @@ # # Copyright (c) Jim Meyering # -test_description='diff honors config option, diff.suppress-blank-empty' +test_description='diff honors config option, diff.suppressBlankEmpty' . ./test-lib.sh @@ -24,14 +24,14 @@ test_expect_success \ git add f && git commit -q -m. f && printf "\ny\n" > f && - git config --bool diff.suppress-blank-empty true && + git config --bool diff.suppressBlankEmpty true && git diff f > actual && test_cmp exp actual && perl -i.bak -p -e "s/^\$/ /" exp && - git config --bool diff.suppress-blank-empty false && + git config --bool diff.suppressBlankEmpty false && git diff f > actual && test_cmp exp actual && - git config --bool --unset diff.suppress-blank-empty && + git config --bool --unset diff.suppressBlankEmpty && git diff f > actual && test_cmp exp actual ' -- cgit v1.3 From 98a4d87b87e9846eafd21ba232cc2b7ba3f718fc Mon Sep 17 00:00:00 2001 From: Boyd Stephen Smith Jr Date: Tue, 20 Jan 2009 21:46:57 -0600 Subject: color-words: Support diff.wordregex config option When diff is invoked with --color-words (w/o =regex), use the regular expression the user has configured as diff.wordregex. diff drivers configured via attributes take precedence over the diff.wordregex-words setting. If the user wants to change them, they have their own configuration variables. Signed-off-by: Boyd Stephen Smith Jr Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++++ Documentation/diff-options.txt | 7 ++++--- diff.c | 5 +++++ t/t4034-diff-words.sh | 45 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 58 insertions(+), 5 deletions(-) (limited to 'diff.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 7408bb2d34..0ca983ac3b 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -639,6 +639,12 @@ diff.suppress-blank-empty:: A boolean to inhibit the standard behavior of printing a space before each empty output line. Defaults to false. +diff.wordregex:: + A POSIX Extended Regular Expression used to determine what is a "word" + when performing word-by-word difference calculations. Character + sequences that match the regular expression are "words", all other + characters are *ignorable* whitespace. + fetch.unpackLimit:: If the number of objects fetched over the git native transfer is below this diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 1edb82e8e1..164e2c5348 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -103,9 +103,10 @@ expression to make sure that it matches all non-whitespace characters. A match that contains a newline is silently truncated(!) at the newline. + -The regex can also be set via a diff driver, see -linkgit:gitattributes[1]; giving it explicitly overrides any diff -driver setting. +The regex can also be set via a diff driver or configuration option, see +linkgit:gitattributes[1] or linkgit:git-config[1]. Giving it explicitly +overrides any diff driver or configuration setting. Diff drivers +override configuration settings. --no-renames:: Turn off rename detection, even when the configuration diff --git a/diff.c b/diff.c index 9fcde963db..ed8b83c68f 100644 --- a/diff.c +++ b/diff.c @@ -23,6 +23,7 @@ static int diff_detect_rename_default; static int diff_rename_limit_default = 200; static int diff_suppress_blank_empty; int diff_use_color_default = -1; +static const char *diff_word_regex_cfg; static const char *external_diff_cmd_cfg; int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; @@ -92,6 +93,8 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) } if (!strcmp(var, "diff.external")) return git_config_string(&external_diff_cmd_cfg, var, value); + if (!strcmp(var, "diff.wordregex")) + return git_config_string(&diff_word_regex_cfg, var, value); return git_diff_basic_config(var, value, cb); } @@ -1550,6 +1553,8 @@ static void builtin_diff(const char *name_a, o->word_regex = userdiff_word_regex(one); if (!o->word_regex) o->word_regex = userdiff_word_regex(two); + if (!o->word_regex) + o->word_regex = diff_word_regex_cfg; if (o->word_regex) { ecbdata.diff_words->word_regex = (regex_t *) xmalloc(sizeof(regex_t)); diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 744221bef9..6bcc153084 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -77,6 +77,7 @@ a = b + c aeff = aeff * ( aaa ) EOF +cp expect expect.letter-runs-are-words test_expect_success 'word diff with a regular expression' ' @@ -92,7 +93,7 @@ post diff=testdriver EOF ' -test_expect_success 'option overrides default' ' +test_expect_success 'option overrides .gitattributes' ' word_diff --color-words="[a-z]+" @@ -112,13 +113,53 @@ a = b + c aeff = aeff * ( aaa ) EOF +cp expect expect.non-whitespace-is-word -test_expect_success 'use default supplied by driver' ' +test_expect_success 'use regex supplied by driver' ' word_diff --color-words ' +test_expect_success 'set diff.wordregex option' ' + git config diff.wordregex "[[:alnum:]]+" +' + +cp expect.letter-runs-are-words expect + +test_expect_success 'command-line overrides config' ' + word_diff --color-words="[a-z]+" +' + +cp expect.non-whitespace-is-word expect + +test_expect_success '.gitattributes override config' ' + word_diff --color-words +' + +test_expect_success 'remove diff driver regex' ' + git config --unset diff.testdriver.wordregex +' + +cat > expect <<\EOF +diff --git a/pre b/post +index 330b04f..5ed8eff 100644 +--- a/pre ++++ b/post +@@ -1,3 +1,7 @@ +h(4),hh[44] + +a = b + c + +aa = a + +aeff = aeff * ( aaa ) +EOF + +test_expect_success 'use configured regex' ' + word_diff --color-words +' + echo 'aaa (aaa)' > pre echo 'aaa (aaa) aaa' > post -- cgit v1.3 From 479b0ae81c9291a8bb8d7b2347cc58eeaa701304 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 22 Jan 2009 00:59:56 -0500 Subject: diff: refactor tempfile cleanup handling There are two pieces of code that create tempfiles for diff: run_external_diff and run_textconv. The former cleans up its tempfiles in the face of premature death (i.e., by die() or by signal), but the latter does not. After this patch, they will both use the same cleanup routines. To make clear what the change is, let me first explain what happens now: - run_external_diff uses a static global array of 2 diff_tempfile structs (since it knows it will always need exactly 2 tempfiles). It calls prepare_temp_file (which doesn't know anything about the global array) on each of the structs, creating the tempfiles that need to be cleaned up. It then registers atexit and signal handlers to look through the global array and remove the tempfiles. If it succeeds, it calls the handler manually (which marks the tempfile structs as unused). - textconv has its own tempfile struct, which it allocates using prepare_temp_file and cleans up manually. No signal or atexit handlers. The new code moves the installation of cleanup handlers into the prepare_temp_file function. Which means that that function now has to understand that there is static tempfile storage. So what happens now is: - run_external_diff calls prepare_temp_file - prepare_temp_file calls claim_diff_tempfile, which allocates an unused slot from our global array - prepare_temp_file installs (if they have not already been installed) atexit and signal handlers for cleanup - prepare_temp_file sets up the tempfile as usual - prepare_temp_file returns a pointer to the allocated tempfile The advantage being that run_external_diff no longer has to care about setting up cleanup handlers. Now by virtue of calling prepare_temp_file, run_textconv gets the same benefit, as will any future users of prepare_temp_file. There are also a few side benefits to the specific implementation: - we now install cleanup handlers _before_ allocating the tempfile, closing a race which could leave temp cruft - when allocating a slot in the global array, we will now detect a situation where the old slots were not properly vacated (i.e., somebody forgot to call remove upon leaving the function). In the old code, such a situation would silently overwrite the tempfile names, meaning we would forget to clean them up. The new code dies with a bug warning. - we make sure only to install the signal handler once. This isn't a big deal, since we are just overwriting the old handler, but will become an issue when a later patch converts the code to use sigchain Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 107 +++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 55 insertions(+), 52 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d23548292a..3cfc0b636c 100644 --- a/diff.c +++ b/diff.c @@ -165,6 +165,33 @@ static struct diff_tempfile { char tmp_path[PATH_MAX]; } diff_temp[2]; +static struct diff_tempfile *claim_diff_tempfile(void) { + int i; + for (i = 0; i < ARRAY_SIZE(diff_temp); i++) + if (!diff_temp[i].name) + return diff_temp + i; + die("BUG: diff is failing to clean up its tempfiles"); +} + +static int remove_tempfile_installed; + +static void remove_tempfile(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(diff_temp); i++) + if (diff_temp[i].name == diff_temp[i].tmp_path) { + unlink(diff_temp[i].name); + diff_temp[i].name = NULL; + } +} + +static void remove_tempfile_on_signal(int signo) +{ + remove_tempfile(); + signal(SIGINT, SIG_DFL); + raise(signo); +} + static int count_lines(const char *data, int size) { int count, ch, completely_empty = 1, nl_just_seen = 0; @@ -1857,10 +1884,11 @@ static void prep_temp_blob(struct diff_tempfile *temp, sprintf(temp->mode, "%06o", mode); } -static void prepare_temp_file(const char *name, - struct diff_tempfile *temp, - struct diff_filespec *one) +static struct diff_tempfile *prepare_temp_file(const char *name, + struct diff_filespec *one) { + struct diff_tempfile *temp = claim_diff_tempfile(); + if (!DIFF_FILE_VALID(one)) { not_a_valid_file: /* A '-' entry produces this for file-2, and @@ -1869,7 +1897,13 @@ static void prepare_temp_file(const char *name, temp->name = "/dev/null"; strcpy(temp->hex, "."); strcpy(temp->mode, "."); - return; + return temp; + } + + if (!remove_tempfile_installed) { + atexit(remove_tempfile); + signal(SIGINT, remove_tempfile_on_signal); + remove_tempfile_installed = 1; } if (!one->sha1_valid || @@ -1909,7 +1943,7 @@ static void prepare_temp_file(const char *name, */ sprintf(temp->mode, "%06o", one->mode); } - return; + return temp; } else { if (diff_populate_filespec(one, 0)) @@ -1917,24 +1951,7 @@ static void prepare_temp_file(const char *name, prep_temp_blob(temp, one->data, one->size, one->sha1, one->mode); } -} - -static void remove_tempfile(void) -{ - int i; - - for (i = 0; i < 2; i++) - if (diff_temp[i].name == diff_temp[i].tmp_path) { - unlink(diff_temp[i].name); - diff_temp[i].name = NULL; - } -} - -static void remove_tempfile_on_signal(int signo) -{ - remove_tempfile(); - signal(SIGINT, SIG_DFL); - raise(signo); + return temp; } /* An external diff command takes: @@ -1952,34 +1969,22 @@ static void run_external_diff(const char *pgm, int complete_rewrite) { const char *spawn_arg[10]; - struct diff_tempfile *temp = diff_temp; int retval; - static int atexit_asked = 0; - const char *othername; const char **arg = &spawn_arg[0]; - othername = (other? other : name); - if (one && two) { - prepare_temp_file(name, &temp[0], one); - prepare_temp_file(othername, &temp[1], two); - if (! atexit_asked && - (temp[0].name == temp[0].tmp_path || - temp[1].name == temp[1].tmp_path)) { - atexit_asked = 1; - atexit(remove_tempfile); - } - signal(SIGINT, remove_tempfile_on_signal); - } - if (one && two) { + struct diff_tempfile *temp_one, *temp_two; + const char *othername = (other ? other : name); + temp_one = prepare_temp_file(name, one); + temp_two = prepare_temp_file(othername, two); *arg++ = pgm; *arg++ = name; - *arg++ = temp[0].name; - *arg++ = temp[0].hex; - *arg++ = temp[0].mode; - *arg++ = temp[1].name; - *arg++ = temp[1].hex; - *arg++ = temp[1].mode; + *arg++ = temp_one->name; + *arg++ = temp_one->hex; + *arg++ = temp_one->mode; + *arg++ = temp_two->name; + *arg++ = temp_two->hex; + *arg++ = temp_two->mode; if (other) { *arg++ = other; *arg++ = xfrm_msg; @@ -3448,15 +3453,15 @@ void diff_unmerge(struct diff_options *options, static char *run_textconv(const char *pgm, struct diff_filespec *spec, size_t *outsize) { - struct diff_tempfile temp; + struct diff_tempfile *temp; const char *argv[3]; const char **arg = argv; struct child_process child; struct strbuf buf = STRBUF_INIT; - prepare_temp_file(spec->path, &temp, spec); + temp = prepare_temp_file(spec->path, spec); *arg++ = pgm; - *arg++ = temp.name; + *arg++ = temp->name; *arg = NULL; memset(&child, 0, sizeof(child)); @@ -3465,13 +3470,11 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec, if (start_command(&child) != 0 || strbuf_read(&buf, child.out, 0) < 0 || finish_command(&child) != 0) { - if (temp.name == temp.tmp_path) - unlink(temp.name); + remove_tempfile(); error("error running textconv command '%s'", pgm); return NULL; } - if (temp.name == temp.tmp_path) - unlink(temp.name); + remove_tempfile(); return strbuf_detach(&buf, outsize); } -- cgit v1.3 From 4a16d072723b48699ea162da24eff05eba298834 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 22 Jan 2009 01:02:35 -0500 Subject: chain kill signals for cleanup functions If a piece of code wanted to do some cleanup before exiting (e.g., cleaning up a lockfile or a tempfile), our usual strategy was to install a signal handler that did something like this: do_cleanup(); /* actual work */ signal(signo, SIG_DFL); /* restore previous behavior */ raise(signo); /* deliver signal, killing ourselves */ For a single handler, this works fine. However, if we want to clean up two _different_ things, we run into a problem. The most recently installed handler will run, but when it removes itself as a handler, it doesn't put back the first handler. This patch introduces sigchain, a tiny library for handling a stack of signal handlers. You sigchain_push each handler, and use sigchain_pop to restore whoever was before you in the stack. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- .gitignore | 1 + Makefile | 3 +++ builtin-clone.c | 5 +++-- builtin-fetch--tool.c | 5 +++-- builtin-fetch.c | 5 +++-- diff.c | 5 +++-- http-push.c | 11 ++++++----- lockfile.c | 13 +++++++------ sigchain.c | 43 +++++++++++++++++++++++++++++++++++++++++++ sigchain.h | 9 +++++++++ t/t0005-signals.sh | 22 ++++++++++++++++++++++ test-sigchain.c | 22 ++++++++++++++++++++++ 12 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 sigchain.c create mode 100644 sigchain.h create mode 100755 t/t0005-signals.sh create mode 100644 test-sigchain.c (limited to 'diff.c') diff --git a/.gitignore b/.gitignore index d9adce585a..f28a54d262 100644 --- a/.gitignore +++ b/.gitignore @@ -152,6 +152,7 @@ test-match-trees test-parse-options test-path-utils test-sha1 +test-sigchain common-cmds.h *.tar.gz *.dsc diff --git a/Makefile b/Makefile index 2b873fa99f..fd02decc01 100644 --- a/Makefile +++ b/Makefile @@ -388,6 +388,7 @@ LIB_H += revision.h LIB_H += run-command.h LIB_H += sha1-lookup.h LIB_H += sideband.h +LIB_H += sigchain.h LIB_H += strbuf.h LIB_H += tag.h LIB_H += transport.h @@ -481,6 +482,7 @@ LIB_OBJS += sha1-lookup.o LIB_OBJS += sha1_name.o LIB_OBJS += shallow.o LIB_OBJS += sideband.o +LIB_OBJS += sigchain.o LIB_OBJS += strbuf.o LIB_OBJS += symlinks.o LIB_OBJS += tag.o @@ -1364,6 +1366,7 @@ TEST_PROGRAMS += test-match-trees$X TEST_PROGRAMS += test-parse-options$X TEST_PROGRAMS += test-path-utils$X TEST_PROGRAMS += test-sha1$X +TEST_PROGRAMS += test-sigchain$X all:: $(TEST_PROGRAMS) diff --git a/builtin-clone.c b/builtin-clone.c index f1a1a0c365..18b9392334 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -19,6 +19,7 @@ #include "strbuf.h" #include "dir.h" #include "pack-refs.h" +#include "sigchain.h" /* * Overall FIXMEs: @@ -288,7 +289,7 @@ static void remove_junk(void) static void remove_junk_on_signal(int signo) { remove_junk(); - signal(SIGINT, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -438,7 +439,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } junk_git_dir = git_dir; atexit(remove_junk); - signal(SIGINT, remove_junk_on_signal); + sigchain_push(SIGINT, remove_junk_on_signal); setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 469b07e240..b1d7f8fb32 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -2,6 +2,7 @@ #include "cache.h" #include "refs.h" #include "commit.h" +#include "sigchain.h" static char *get_stdin(void) { @@ -186,7 +187,7 @@ static void remove_keep(void) static void remove_keep_on_signal(int signo) { remove_keep(); - signal(SIGINT, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -245,7 +246,7 @@ static int fetch_native_store(FILE *fp, char buffer[1024]; int err = 0; - signal(SIGINT, remove_keep_on_signal); + sigchain_push(SIGINT, remove_keep_on_signal); atexit(remove_keep); while (fgets(buffer, sizeof(buffer), stdin)) { diff --git a/builtin-fetch.c b/builtin-fetch.c index de6f3074b1..8c86974cbe 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -10,6 +10,7 @@ #include "transport.h" #include "run-command.h" #include "parse-options.h" +#include "sigchain.h" static const char * const builtin_fetch_usage[] = { "git fetch [options] [ ...]", @@ -58,7 +59,7 @@ static void unlock_pack(void) static void unlock_pack_on_signal(int signo) { unlock_pack(); - signal(SIGINT, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -672,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) ref_nr = j; } - signal(SIGINT, unlock_pack_on_signal); + sigchain_push(SIGINT, unlock_pack_on_signal); atexit(unlock_pack); exit_code = do_fetch(transport, parse_fetch_refspec(ref_nr, refs), ref_nr); diff --git a/diff.c b/diff.c index 3cfc0b636c..9c9977d892 100644 --- a/diff.c +++ b/diff.c @@ -12,6 +12,7 @@ #include "run-command.h" #include "utf8.h" #include "userdiff.h" +#include "sigchain.h" #ifdef NO_FAST_WORKING_DIRECTORY #define FAST_WORKING_DIRECTORY 0 @@ -188,7 +189,7 @@ static void remove_tempfile(void) static void remove_tempfile_on_signal(int signo) { remove_tempfile(); - signal(SIGINT, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -1902,7 +1903,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (!remove_tempfile_installed) { atexit(remove_tempfile); - signal(SIGINT, remove_tempfile_on_signal); + sigchain_push(SIGINT, remove_tempfile_on_signal); remove_tempfile_installed = 1; } diff --git a/http-push.c b/http-push.c index a4b7d08663..dec395deed 100644 --- a/http-push.c +++ b/http-push.c @@ -10,6 +10,7 @@ #include "exec_cmd.h" #include "remote.h" #include "list-objects.h" +#include "sigchain.h" #include @@ -1363,7 +1364,7 @@ static void remove_locks(void) static void remove_locks_on_signal(int signo) { remove_locks(); - signal(signo, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -2261,10 +2262,10 @@ int main(int argc, char **argv) goto cleanup; } - signal(SIGINT, remove_locks_on_signal); - signal(SIGHUP, remove_locks_on_signal); - signal(SIGQUIT, remove_locks_on_signal); - signal(SIGTERM, remove_locks_on_signal); + sigchain_push(SIGINT, remove_locks_on_signal); + sigchain_push(SIGHUP, remove_locks_on_signal); + sigchain_push(SIGQUIT, remove_locks_on_signal); + sigchain_push(SIGTERM, remove_locks_on_signal); /* Check whether the remote has server info files */ remote->can_update_info_refs = 0; diff --git a/lockfile.c b/lockfile.c index 8589155532..3cd57dc385 100644 --- a/lockfile.c +++ b/lockfile.c @@ -2,6 +2,7 @@ * Copyright (c) 2005, Junio C Hamano */ #include "cache.h" +#include "sigchain.h" static struct lock_file *lock_file_list; static const char *alternate_index_output; @@ -24,7 +25,7 @@ static void remove_lock_file(void) static void remove_lock_file_on_signal(int signo) { remove_lock_file(); - signal(signo, SIG_DFL); + sigchain_pop(signo); raise(signo); } @@ -136,11 +137,11 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666); if (0 <= lk->fd) { if (!lock_file_list) { - signal(SIGINT, remove_lock_file_on_signal); - signal(SIGHUP, remove_lock_file_on_signal); - signal(SIGTERM, remove_lock_file_on_signal); - signal(SIGQUIT, remove_lock_file_on_signal); - signal(SIGPIPE, remove_lock_file_on_signal); + sigchain_push(SIGINT, remove_lock_file_on_signal); + sigchain_push(SIGHUP, remove_lock_file_on_signal); + sigchain_push(SIGTERM, remove_lock_file_on_signal); + sigchain_push(SIGQUIT, remove_lock_file_on_signal); + sigchain_push(SIGPIPE, remove_lock_file_on_signal); atexit(remove_lock_file); } lk->owner = getpid(); diff --git a/sigchain.c b/sigchain.c new file mode 100644 index 0000000000..a18d505e56 --- /dev/null +++ b/sigchain.c @@ -0,0 +1,43 @@ +#include "sigchain.h" +#include "cache.h" + +#define SIGCHAIN_MAX_SIGNALS 32 + +struct sigchain_signal { + sigchain_fun *old; + int n; + int alloc; +}; +static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS]; + +static void check_signum(int sig) +{ + if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS) + die("BUG: signal out of range: %d", sig); +} + +int sigchain_push(int sig, sigchain_fun f) +{ + struct sigchain_signal *s = signals + sig; + check_signum(sig); + + ALLOC_GROW(s->old, s->n + 1, s->alloc); + s->old[s->n] = signal(sig, f); + if (s->old[s->n] == SIG_ERR) + return -1; + s->n++; + return 0; +} + +int sigchain_pop(int sig) +{ + struct sigchain_signal *s = signals + sig; + check_signum(sig); + if (s->n < 1) + return 0; + + if (signal(sig, s->old[s->n - 1]) == SIG_ERR) + return -1; + s->n--; + return 0; +} diff --git a/sigchain.h b/sigchain.h new file mode 100644 index 0000000000..254ebb0fa6 --- /dev/null +++ b/sigchain.h @@ -0,0 +1,9 @@ +#ifndef SIGCHAIN_H +#define SIGCHAIN_H + +typedef void (*sigchain_fun)(int); + +int sigchain_push(int sig, sigchain_fun f); +int sigchain_pop(int sig); + +#endif /* SIGCHAIN_H */ diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh new file mode 100755 index 0000000000..9707af7d03 --- /dev/null +++ b/t/t0005-signals.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +test_description='signals work as we expect' +. ./test-lib.sh + +cat >expect <actual + case "$?" in + 130) true ;; # POSIX w/ SIGINT=2 + 3) true ;; # Windows + *) false ;; + esac && + test_cmp expect actual +' + +test_done diff --git a/test-sigchain.c b/test-sigchain.c new file mode 100644 index 0000000000..8747deac62 --- /dev/null +++ b/test-sigchain.c @@ -0,0 +1,22 @@ +#include "sigchain.h" +#include "cache.h" + +#define X(f) \ +static void f(int sig) { \ + puts(#f); \ + fflush(stdout); \ + sigchain_pop(sig); \ + raise(sig); \ +} +X(one) +X(two) +X(three) +#undef X + +int main(int argc, char **argv) { + sigchain_push(SIGINT, one); + sigchain_push(SIGINT, two); + sigchain_push(SIGINT, three); + raise(SIGINT); + return 0; +} -- cgit v1.3 From 57b235a4bc8884a57c6f863605a54b7bfceb0997 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 22 Jan 2009 01:03:08 -0500 Subject: refactor signal handling for cleanup functions The current code is very inconsistent about which signals are caught for doing cleanup of temporary files and lock files. Some callsites checked only SIGINT, while others checked a variety of death-dealing signals. This patch factors out those signals to a single function, and then calls it everywhere. For some sites, that means this is a simple clean up. For others, it is an improvement in that they will now properly clean themselves up after a larger variety of signals. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-clone.c | 2 +- builtin-fetch--tool.c | 2 +- builtin-fetch.c | 2 +- diff.c | 2 +- http-push.c | 5 +---- lockfile.c | 6 +----- sigchain.c | 9 +++++++++ sigchain.h | 2 ++ 8 files changed, 17 insertions(+), 13 deletions(-) (limited to 'diff.c') diff --git a/builtin-clone.c b/builtin-clone.c index 18b9392334..44c80734b7 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -439,7 +439,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) } junk_git_dir = git_dir; atexit(remove_junk); - sigchain_push(SIGINT, remove_junk_on_signal); + sigchain_push_common(remove_junk_on_signal); setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1); diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index b1d7f8fb32..29356d25db 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -246,7 +246,7 @@ static int fetch_native_store(FILE *fp, char buffer[1024]; int err = 0; - sigchain_push(SIGINT, remove_keep_on_signal); + sigchain_push_common(remove_keep_on_signal); atexit(remove_keep); while (fgets(buffer, sizeof(buffer), stdin)) { diff --git a/builtin-fetch.c b/builtin-fetch.c index 8c86974cbe..1e4a3d9c51 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -673,7 +673,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) ref_nr = j; } - sigchain_push(SIGINT, unlock_pack_on_signal); + sigchain_push_common(unlock_pack_on_signal); atexit(unlock_pack); exit_code = do_fetch(transport, parse_fetch_refspec(ref_nr, refs), ref_nr); diff --git a/diff.c b/diff.c index 9c9977d892..8ce898a6b0 100644 --- a/diff.c +++ b/diff.c @@ -1903,7 +1903,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (!remove_tempfile_installed) { atexit(remove_tempfile); - sigchain_push(SIGINT, remove_tempfile_on_signal); + sigchain_push_common(remove_tempfile_on_signal); remove_tempfile_installed = 1; } diff --git a/http-push.c b/http-push.c index dec395deed..7d5c23edc4 100644 --- a/http-push.c +++ b/http-push.c @@ -2262,10 +2262,7 @@ int main(int argc, char **argv) goto cleanup; } - sigchain_push(SIGINT, remove_locks_on_signal); - sigchain_push(SIGHUP, remove_locks_on_signal); - sigchain_push(SIGQUIT, remove_locks_on_signal); - sigchain_push(SIGTERM, remove_locks_on_signal); + sigchain_push_common(remove_locks_on_signal); /* Check whether the remote has server info files */ remote->can_update_info_refs = 0; diff --git a/lockfile.c b/lockfile.c index 3cd57dc385..021c3375c1 100644 --- a/lockfile.c +++ b/lockfile.c @@ -137,11 +137,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666); if (0 <= lk->fd) { if (!lock_file_list) { - sigchain_push(SIGINT, remove_lock_file_on_signal); - sigchain_push(SIGHUP, remove_lock_file_on_signal); - sigchain_push(SIGTERM, remove_lock_file_on_signal); - sigchain_push(SIGQUIT, remove_lock_file_on_signal); - sigchain_push(SIGPIPE, remove_lock_file_on_signal); + sigchain_push_common(remove_lock_file_on_signal); atexit(remove_lock_file); } lk->owner = getpid(); diff --git a/sigchain.c b/sigchain.c index a18d505e56..1118b99e57 100644 --- a/sigchain.c +++ b/sigchain.c @@ -41,3 +41,12 @@ int sigchain_pop(int sig) s->n--; return 0; } + +void sigchain_push_common(sigchain_fun f) +{ + sigchain_push(SIGINT, f); + sigchain_push(SIGHUP, f); + sigchain_push(SIGTERM, f); + sigchain_push(SIGQUIT, f); + sigchain_push(SIGPIPE, f); +} diff --git a/sigchain.h b/sigchain.h index 254ebb0fa6..618083bce0 100644 --- a/sigchain.h +++ b/sigchain.h @@ -6,4 +6,6 @@ typedef void (*sigchain_fun)(int); int sigchain_push(int sig, sigchain_fun f); int sigchain_pop(int sig); +void sigchain_push_common(sigchain_fun f); + #endif /* SIGCHAIN_H */ -- cgit v1.3 From b67b9612e1a90ae093445abeaeff930e9f4cf936 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 26 Jan 2009 00:08:24 -0800 Subject: diff.c: output correct index lines for a split diff A patch that changes the filetype (e.g. regular file to symlink) of a path must be split into a deletion event followed by a creation event, which means that we need to have two independent metainfo lines for each. However, the code reused the single set of metainfo lines. As the blob object names recorded on the index lines are usually not used nor validated on the receiving end, this is not an issue with normal use of the resulting patch. However, when accepting a binary patch to delete a blob, git-apply verified that the postimage blob object name on the index line is 0{40}, hence a patch that deletes a regular file blob that records binary contents to create a blob with different filetype (e.g. a symbolic link) failed to apply. "git am -3" also uses the blob object names recorded on the index line, so it would also misbehave when synthesizing a preimage tree. This moves the code to generate metainfo lines around, so that two independent sets of metainfo lines are used for the split halves. Additional tests by Jeff King. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 146 ++++++++++++++++++++++++-------------------- t/t4114-apply-typechange.sh | 18 ++++++ 2 files changed, 98 insertions(+), 66 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f91f256c56..6fea3c0347 100644 --- a/diff.c +++ b/diff.c @@ -2096,16 +2096,86 @@ static const char *external_diff_attr(const char *name) return NULL; } +static int similarity_index(struct diff_filepair *p) +{ + return p->score * 100 / MAX_SCORE; +} + +static void fill_metainfo(struct strbuf *msg, + const char *name, + const char *other, + struct diff_filespec *one, + struct diff_filespec *two, + struct diff_options *o, + struct diff_filepair *p) +{ + strbuf_init(msg, PATH_MAX * 2 + 300); + switch (p->status) { + case DIFF_STATUS_COPIED: + strbuf_addf(msg, "similarity index %d%%", similarity_index(p)); + strbuf_addstr(msg, "\ncopy from "); + quote_c_style(name, msg, NULL, 0); + strbuf_addstr(msg, "\ncopy to "); + quote_c_style(other, msg, NULL, 0); + strbuf_addch(msg, '\n'); + break; + case DIFF_STATUS_RENAMED: + strbuf_addf(msg, "similarity index %d%%", similarity_index(p)); + strbuf_addstr(msg, "\nrename from "); + quote_c_style(name, msg, NULL, 0); + strbuf_addstr(msg, "\nrename to "); + quote_c_style(other, msg, NULL, 0); + strbuf_addch(msg, '\n'); + break; + case DIFF_STATUS_MODIFIED: + if (p->score) { + strbuf_addf(msg, "dissimilarity index %d%%\n", + similarity_index(p)); + break; + } + /* fallthru */ + default: + /* nothing */ + ; + } + if (one && two && hashcmp(one->sha1, two->sha1)) { + int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV; + + if (DIFF_OPT_TST(o, BINARY)) { + mmfile_t mf; + if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) || + (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) + abbrev = 40; + } + strbuf_addf(msg, "index %.*s..%.*s", + abbrev, sha1_to_hex(one->sha1), + abbrev, sha1_to_hex(two->sha1)); + if (one->mode == two->mode) + strbuf_addf(msg, " %06o", one->mode); + strbuf_addch(msg, '\n'); + } + if (msg->len) + strbuf_setlen(msg, msg->len - 1); +} + static void run_diff_cmd(const char *pgm, const char *name, const char *other, const char *attr_path, struct diff_filespec *one, struct diff_filespec *two, - const char *xfrm_msg, + struct strbuf *msg, struct diff_options *o, - int complete_rewrite) + struct diff_filepair *p) { + const char *xfrm_msg = NULL; + int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score; + + if (msg) { + fill_metainfo(msg, name, other, one, two, o, p); + xfrm_msg = msg->len ? msg->buf : NULL; + } + if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL)) pgm = NULL; else { @@ -2145,11 +2215,6 @@ static void diff_fill_sha1_info(struct diff_filespec *one) hashclr(one->sha1); } -static int similarity_index(struct diff_filepair *p) -{ - return p->score * 100 / MAX_SCORE; -} - static void strip_prefix(int prefix_length, const char **namep, const char **otherp) { /* Strip the prefix but do not molest /dev/null and absolute paths */ @@ -2163,13 +2228,11 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) { const char *pgm = external_diff(); struct strbuf msg; - char *xfrm_msg; struct diff_filespec *one = p->one; struct diff_filespec *two = p->two; const char *name; const char *other; const char *attr_path; - int complete_rewrite = 0; name = p->one->path; other = (strcmp(name, p->two->path) ? p->two->path : NULL); @@ -2179,83 +2242,34 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o) if (DIFF_PAIR_UNMERGED(p)) { run_diff_cmd(pgm, name, NULL, attr_path, - NULL, NULL, NULL, o, 0); + NULL, NULL, NULL, o, p); return; } diff_fill_sha1_info(one); diff_fill_sha1_info(two); - strbuf_init(&msg, PATH_MAX * 2 + 300); - switch (p->status) { - case DIFF_STATUS_COPIED: - strbuf_addf(&msg, "similarity index %d%%", similarity_index(p)); - strbuf_addstr(&msg, "\ncopy from "); - quote_c_style(name, &msg, NULL, 0); - strbuf_addstr(&msg, "\ncopy to "); - quote_c_style(other, &msg, NULL, 0); - strbuf_addch(&msg, '\n'); - break; - case DIFF_STATUS_RENAMED: - strbuf_addf(&msg, "similarity index %d%%", similarity_index(p)); - strbuf_addstr(&msg, "\nrename from "); - quote_c_style(name, &msg, NULL, 0); - strbuf_addstr(&msg, "\nrename to "); - quote_c_style(other, &msg, NULL, 0); - strbuf_addch(&msg, '\n'); - break; - case DIFF_STATUS_MODIFIED: - if (p->score) { - strbuf_addf(&msg, "dissimilarity index %d%%\n", - similarity_index(p)); - complete_rewrite = 1; - break; - } - /* fallthru */ - default: - /* nothing */ - ; - } - - if (hashcmp(one->sha1, two->sha1)) { - int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV; - - if (DIFF_OPT_TST(o, BINARY)) { - mmfile_t mf; - if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) || - (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two))) - abbrev = 40; - } - strbuf_addf(&msg, "index %.*s..%.*s", - abbrev, sha1_to_hex(one->sha1), - abbrev, sha1_to_hex(two->sha1)); - if (one->mode == two->mode) - strbuf_addf(&msg, " %06o", one->mode); - strbuf_addch(&msg, '\n'); - } - - if (msg.len) - strbuf_setlen(&msg, msg.len - 1); - xfrm_msg = msg.len ? msg.buf : NULL; - if (!pgm && DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) && (S_IFMT & one->mode) != (S_IFMT & two->mode)) { - /* a filepair that changes between file and symlink + /* + * a filepair that changes between file and symlink * needs to be split into deletion and creation. */ struct diff_filespec *null = alloc_filespec(two->path); run_diff_cmd(NULL, name, other, attr_path, - one, null, xfrm_msg, o, 0); + one, null, &msg, o, p); free(null); + strbuf_release(&msg); + null = alloc_filespec(one->path); run_diff_cmd(NULL, name, other, attr_path, - null, two, xfrm_msg, o, 0); + null, two, &msg, o, p); free(null); } else run_diff_cmd(pgm, name, other, attr_path, - one, two, xfrm_msg, o, complete_rewrite); + one, two, &msg, o, p); strbuf_release(&msg); } diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh index 55334927ab..0f185caa44 100755 --- a/t/t4114-apply-typechange.sh +++ b/t/t4114-apply-typechange.sh @@ -25,6 +25,10 @@ test_expect_success 'setup repository and commits' ' git update-index foo && git commit -m "foo back to file" && git branch foo-back-to-file && + printf "\0" > foo && + git update-index foo && + git commit -m "foo becomes binary" && + git branch foo-becomes-binary && rm -f foo && git update-index --remove foo && mkdir foo && @@ -85,6 +89,20 @@ test_expect_success 'symlink becomes file' ' ' test_debug 'cat patch' +test_expect_success 'binary file becomes symlink' ' + git checkout -f foo-becomes-binary && + git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch && + git apply --index < patch + ' +test_debug 'cat patch' + +test_expect_success 'symlink becomes binary file' ' + git checkout -f foo-symlinked-to-bar && + git diff-tree -p --binary HEAD foo-becomes-binary > patch && + git apply --index < patch + ' +test_debug 'cat patch' + test_expect_success 'symlink becomes directory' ' git checkout -f foo-symlinked-to-bar && -- cgit v1.3 From a8344abe0f70f9fc629ee055d73ffa65fbc58311 Mon Sep 17 00:00:00 2001 From: Nazri Ramliy Date: Thu, 12 Feb 2009 21:36:14 +0800 Subject: Bugfix: GIT_EXTERNAL_DIFF with more than one changed files When there is more than one file that are changed, running git diff with GIT_EXTERNAL_DIFF incorrectly diagnoses an programming error and dies. The check introduced in 479b0ae (diff: refactor tempfile cleanup handling, 2009-01-22) to detect a temporary file slot that forgot to remove its temporary file was inconsistent with the way the codepath to remove the temporary to mark the slot that it is done with it. This patch fixes this problem and adds a test case for it. Signed-off-by: Nazri Ramliy Acked-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 8 ++++---- t/t4020-diff-external.sh | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index a5a540fd38..be3859e0a7 100644 --- a/diff.c +++ b/diff.c @@ -184,11 +184,11 @@ static int remove_tempfile_installed; static void remove_tempfile(void) { int i; - for (i = 0; i < ARRAY_SIZE(diff_temp); i++) - if (diff_temp[i].name == diff_temp[i].tmp_path) { + for (i = 0; i < ARRAY_SIZE(diff_temp); i++) { + if (diff_temp[i].name == diff_temp[i].tmp_path) unlink(diff_temp[i].name); - diff_temp[i].name = NULL; - } + diff_temp[i].name = NULL; + } } static void remove_tempfile_on_signal(int signo) diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index caea292f15..281680d95a 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -128,4 +128,12 @@ test_expect_success 'force diff with "diff"' ' test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual ' +test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' ' + echo anotherfile > file2 && + git add file2 && + git commit -m "added 2nd file" && + echo modified >file2 && + GIT_EXTERNAL_DIFF=echo git diff +' + test_done -- cgit v1.3 From dc6ebd4cc5028d59146e02e30f7945ee91974e6e Mon Sep 17 00:00:00 2001 From: Arjen Laarhoven Date: Fri, 13 Feb 2009 22:53:40 +0100 Subject: Clean up use of ANSI color sequences Remove the literal ANSI escape sequences and replace them by readable constants. Signed-off-by: Arjen Laarhoven Signed-off-by: Junio C Hamano --- builtin-branch.c | 10 +++++----- color.c | 8 +++----- color.h | 10 ++++++++++ diff.c | 16 ++++++++-------- pretty.c | 8 ++++---- wt-status.c | 10 +++++----- 6 files changed, 35 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/builtin-branch.c b/builtin-branch.c index 56a1971d69..fe139e1f05 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -32,11 +32,11 @@ static unsigned char head_sha1[20]; static int branch_use_color = -1; static char branch_colors[][COLOR_MAXLEN] = { - "\033[m", /* reset */ - "", /* PLAIN (normal) */ - "\033[31m", /* REMOTE (red) */ - "", /* LOCAL (normal) */ - "\033[32m", /* CURRENT (green) */ + GIT_COLOR_RESET, + GIT_COLOR_NORMAL, /* PLAIN */ + GIT_COLOR_RED, /* REMOTE */ + GIT_COLOR_NORMAL, /* LOCAL */ + GIT_COLOR_GREEN, /* CURRENT */ }; enum color_branch { COLOR_BRANCH_RESET = 0, diff --git a/color.c b/color.c index db4dccfb77..62977f4808 100644 --- a/color.c +++ b/color.c @@ -1,8 +1,6 @@ #include "cache.h" #include "color.h" -#define COLOR_RESET "\033[m" - int git_use_color_default = 0; static int parse_color(const char *name, int len) @@ -54,7 +52,7 @@ void color_parse_mem(const char *value, int value_len, const char *var, int bg = -2; if (!strncasecmp(value, "reset", len)) { - strcpy(dst, "\033[m"); + strcpy(dst, GIT_COLOR_RESET); return; } @@ -175,7 +173,7 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt, r += fprintf(fp, "%s", color); r += vfprintf(fp, fmt, args); if (*color) - r += fprintf(fp, "%s", COLOR_RESET); + r += fprintf(fp, "%s", GIT_COLOR_RESET); if (trail) r += fprintf(fp, "%s", trail); return r; @@ -217,7 +215,7 @@ int color_fwrite_lines(FILE *fp, const char *color, char *p = memchr(buf, '\n', count); if (p != buf && (fputs(color, fp) < 0 || fwrite(buf, p ? p - buf : count, 1, fp) != 1 || - fputs(COLOR_RESET, fp) < 0)) + fputs(GIT_COLOR_RESET, fp) < 0)) return -1; if (!p) return 0; diff --git a/color.h b/color.h index 5019df82f7..6846be1706 100644 --- a/color.h +++ b/color.h @@ -4,6 +4,16 @@ /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */ #define COLOR_MAXLEN 24 +#define GIT_COLOR_NORMAL "" +#define GIT_COLOR_RESET "\033[m" +#define GIT_COLOR_BOLD "\033[1m" +#define GIT_COLOR_RED "\033[31m" +#define GIT_COLOR_GREEN "\033[32m" +#define GIT_COLOR_YELLOW "\033[33m" +#define GIT_COLOR_BLUE "\033[34m" +#define GIT_COLOR_CYAN "\033[36m" +#define GIT_COLOR_BG_RED "\033[41m" + /* * This variable stores the value of color.ui */ diff --git a/diff.c b/diff.c index be3859e0a7..a3db16ea66 100644 --- a/diff.c +++ b/diff.c @@ -30,14 +30,14 @@ int diff_auto_refresh_index = 1; static int diff_mnemonic_prefix; static char diff_colors[][COLOR_MAXLEN] = { - "\033[m", /* reset */ - "", /* PLAIN (normal) */ - "\033[1m", /* METAINFO (bold) */ - "\033[36m", /* FRAGINFO (cyan) */ - "\033[31m", /* OLD (red) */ - "\033[32m", /* NEW (green) */ - "\033[33m", /* COMMIT (yellow) */ - "\033[41m", /* WHITESPACE (red background) */ + GIT_COLOR_RESET, + GIT_COLOR_NORMAL, /* PLAIN */ + GIT_COLOR_BOLD, /* METAINFO */ + GIT_COLOR_CYAN, /* FRAGINFO */ + GIT_COLOR_RED, /* OLD */ + GIT_COLOR_GREEN, /* NEW */ + GIT_COLOR_YELLOW, /* COMMIT */ + GIT_COLOR_BG_RED, /* WHITESPACE */ }; static void diff_filespec_load_driver(struct diff_filespec *one); diff --git a/pretty.c b/pretty.c index cc460b5697..66bae42f99 100644 --- a/pretty.c +++ b/pretty.c @@ -567,16 +567,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, return end - placeholder + 1; } if (!prefixcmp(placeholder + 1, "red")) { - strbuf_addstr(sb, "\033[31m"); + strbuf_addstr(sb, GIT_COLOR_RED); return 4; } else if (!prefixcmp(placeholder + 1, "green")) { - strbuf_addstr(sb, "\033[32m"); + strbuf_addstr(sb, GIT_COLOR_GREEN); return 6; } else if (!prefixcmp(placeholder + 1, "blue")) { - strbuf_addstr(sb, "\033[34m"); + strbuf_addstr(sb, GIT_COLOR_BLUE); return 5; } else if (!prefixcmp(placeholder + 1, "reset")) { - strbuf_addstr(sb, "\033[m"); + strbuf_addstr(sb, GIT_COLOR_RESET); return 6; } else return 0; diff --git a/wt-status.c b/wt-status.c index 96ff2f8f56..dd87339ff7 100644 --- a/wt-status.c +++ b/wt-status.c @@ -15,11 +15,11 @@ int wt_status_relative_paths = 1; int wt_status_use_color = -1; int wt_status_submodule_summary; static char wt_status_colors[][COLOR_MAXLEN] = { - "", /* WT_STATUS_HEADER: normal */ - "\033[32m", /* WT_STATUS_UPDATED: green */ - "\033[31m", /* WT_STATUS_CHANGED: red */ - "\033[31m", /* WT_STATUS_UNTRACKED: red */ - "\033[31m", /* WT_STATUS_NOBRANCH: red */ + GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */ + GIT_COLOR_GREEN, /* WT_STATUS_UPDATED */ + GIT_COLOR_RED, /* WT_STATUS_CHANGED */ + GIT_COLOR_RED, /* WT_STATUS_UNTRACKED */ + GIT_COLOR_RED, /* WT_STATUS_NOBRANCH */ }; enum untracked_status_type show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; -- cgit v1.3 From 4b15b4ab5f9b19caff6d4a910ecc3e1d4f0e13f0 Mon Sep 17 00:00:00 2001 From: Keith Cascio Date: Fri, 13 Feb 2009 09:33:34 -0800 Subject: Remove redundant bit clears from diff_setup() All bits already clear after memset(0). Signed-off-by: Junio C Hamano --- diff.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index be3859e0a7..006aa017e2 100644 --- a/diff.c +++ b/diff.c @@ -2326,15 +2326,12 @@ void diff_setup(struct diff_options *options) options->break_opt = -1; options->rename_limit = -1; options->dirstat_percent = 3; - DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE); options->context = 3; options->change = diff_change; options->add_remove = diff_addremove; if (diff_use_color_default > 0) DIFF_OPT_SET(options, COLOR_DIFF); - else - DIFF_OPT_CLR(options, COLOR_DIFF); options->detect_rename = diff_detect_rename_default; if (!diff_mnemonic_prefix) { -- cgit v1.3 From cd673c1f17228d272c4b7f81fbb28bc31cf0cac6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 27 Feb 2009 23:15:53 -0800 Subject: has_sha1_pack(): refactor "pretend these packs do not exist" interface Most of the callers of this function except only one pass NULL to its last parameter, ignore_packed. Introduce has_sha1_kept_pack() function that has the function signature and the semantics of this function, and convert the sole caller that does not pass NULL to call this new function. All other callers and has_sha1_pack() lose the ignore_packed parameter. Signed-off-by: Junio C Hamano --- builtin-count-objects.c | 2 +- builtin-fsck.c | 2 +- builtin-prune-packed.c | 2 +- cache.h | 3 ++- diff.c | 2 +- revision.c | 3 ++- sha1_file.c | 32 +++++++++++++++++++++++++------- 7 files changed, 33 insertions(+), 13 deletions(-) (limited to 'diff.c') diff --git a/builtin-count-objects.c b/builtin-count-objects.c index 91b5487478..c095e8dd2b 100644 --- a/builtin-count-objects.c +++ b/builtin-count-objects.c @@ -61,7 +61,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose, hex[40] = 0; if (get_sha1_hex(hex, sha1)) die("internal error"); - if (has_sha1_pack(sha1, NULL)) + if (has_sha1_pack(sha1)) (*packed_loose)++; } } diff --git a/builtin-fsck.c b/builtin-fsck.c index 30971ce0ad..491375dc59 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -158,7 +158,7 @@ static void check_reachable_object(struct object *obj) * do a full fsck */ if (!obj->parsed) { - if (has_sha1_pack(obj->sha1, NULL)) + if (has_sha1_pack(obj->sha1)) return; /* it is in pack - forget about it */ printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1)); errors_found |= ERROR_REACHABLE; diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 10cb8df845..2d5b2cd353 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -23,7 +23,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) memcpy(hex+2, de->d_name, 38); if (get_sha1_hex(hex, sha1)) continue; - if (!has_sha1_pack(sha1, NULL)) + if (!has_sha1_pack(sha1)) continue; memcpy(pathname + len, de->d_name, 38); if (opts & DRY_RUN) diff --git a/cache.h b/cache.h index 42f2f2754b..c1539bf89a 100644 --- a/cache.h +++ b/cache.h @@ -565,7 +565,8 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l extern int move_temp_to_file(const char *tmpfile, const char *filename); -extern int has_sha1_pack(const unsigned char *sha1, const char **ignore); +extern int has_sha1_pack(const unsigned char *sha1); +extern int has_sha1_kept_pack(const unsigned char *sha1, const char **ignore); extern int has_sha1_file(const unsigned char *sha1); extern int has_loose_object_nonlocal(const unsigned char *sha1); diff --git a/diff.c b/diff.c index f91f256c56..a34d26c23f 100644 --- a/diff.c +++ b/diff.c @@ -1743,7 +1743,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int * objects however would tend to be slower as they need * to be individually opened and inflated. */ - if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1, NULL)) + if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1)) return 0; len = strlen(name); diff --git a/revision.c b/revision.c index 45fd7a3660..746eeed972 100644 --- a/revision.c +++ b/revision.c @@ -1485,7 +1485,8 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) { if (commit->object.flags & SHOWN) return commit_ignore; - if (revs->unpacked && has_sha1_pack(commit->object.sha1, revs->ignore_packed)) + if (revs->unpacked && + has_sha1_kept_pack(commit->object.sha1, revs->ignore_packed)) return commit_ignore; if (revs->show_all) return commit_show; diff --git a/sha1_file.c b/sha1_file.c index 88035a0cd1..ac4375d298 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1874,7 +1874,8 @@ int matches_pack_name(struct packed_git *p, const char *name) return 0; } -static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed) +static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e, + const char **ignore_packed) { static struct packed_git *last_found = (void *)1; struct packed_git *p; @@ -1934,6 +1935,17 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons return 0; } +static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e) +{ + return find_pack_ent(sha1, e, NULL); +} + +static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e, + const char **ignore_packed) +{ + return find_pack_ent(sha1, e, ignore_packed); +} + struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs) { @@ -1975,7 +1987,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep) struct pack_entry e; int status; - if (!find_pack_entry(sha1, &e, NULL)) { + if (!find_pack_entry(sha1, &e)) { /* Most likely it's a loose object. */ status = sha1_loose_object_info(sha1, sizep); if (status >= 0) @@ -1983,7 +1995,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep) /* Not a loose object; someone else may have just packed it. */ reprepare_packed_git(); - if (!find_pack_entry(sha1, &e, NULL)) + if (!find_pack_entry(sha1, &e)) return status; } return packed_object_info(e.p, e.offset, sizep); @@ -1995,7 +2007,7 @@ static void *read_packed_sha1(const unsigned char *sha1, struct pack_entry e; void *data; - if (!find_pack_entry(sha1, &e, NULL)) + if (!find_pack_entry(sha1, &e)) return NULL; data = cache_or_unpack_entry(e.p, e.offset, size, type, 1); if (!data) { @@ -2395,17 +2407,23 @@ int has_pack_file(const unsigned char *sha1) return 1; } -int has_sha1_pack(const unsigned char *sha1, const char **ignore_packed) +int has_sha1_pack(const unsigned char *sha1) +{ + struct pack_entry e; + return find_pack_entry(sha1, &e); +} + +int has_sha1_kept_pack(const unsigned char *sha1, const char **ignore_packed) { struct pack_entry e; - return find_pack_entry(sha1, &e, ignore_packed); + return find_kept_pack_entry(sha1, &e, ignore_packed); } int has_sha1_file(const unsigned char *sha1) { struct pack_entry e; - if (find_pack_entry(sha1, &e, NULL)) + if (find_pack_entry(sha1, &e)) return 1; return has_loose_object(sha1); } -- cgit v1.3 From 628d5c2b707db207e47c42ca112b182aa171cfaa Mon Sep 17 00:00:00 2001 From: Keith Cascio Date: Mon, 16 Feb 2009 19:26:49 -0800 Subject: Use DIFF_XDL_SET/DIFF_OPT_SET instead of raw bit-masking Signed-off-by: Keith Cascio Signed-off-by: Junio C Hamano --- diff.c | 17 ++++++++++------- diff.h | 3 +++ 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 006aa017e2..ff3624e9f6 100644 --- a/diff.c +++ b/diff.c @@ -2567,13 +2567,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) /* xdiff options */ else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE; + DIFF_XDL_SET(options, IGNORE_WHITESPACE); else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE; + DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE); else if (!strcmp(arg, "--ignore-space-at-eol")) - options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL; + DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL); else if (!strcmp(arg, "--patience")) - options->xdl_opts |= XDF_PATIENCE_DIFF; + DIFF_XDL_SET(options, PATIENCE_DIFF); /* flags options */ else if (!strcmp(arg, "--binary")) { @@ -2594,10 +2594,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, COLOR_DIFF); else if (!strcmp(arg, "--no-color")) DIFF_OPT_CLR(options, COLOR_DIFF); - else if (!strcmp(arg, "--color-words")) - options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; + else if (!strcmp(arg, "--color-words")) { + DIFF_OPT_SET(options, COLOR_DIFF); + DIFF_OPT_SET(options, COLOR_DIFF_WORDS); + } else if (!prefixcmp(arg, "--color-words=")) { - options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS; + DIFF_OPT_SET(options, COLOR_DIFF); + DIFF_OPT_SET(options, COLOR_DIFF_WORDS); options->word_regex = arg + 14; } else if (!strcmp(arg, "--exit-code")) diff --git a/diff.h b/diff.h index 6703a4fb4f..6616877ee5 100644 --- a/diff.h +++ b/diff.h @@ -69,6 +69,9 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag) #define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag) +#define DIFF_XDL_TST(opts, flag) ((opts)->xdl_opts & XDF_##flag) +#define DIFF_XDL_SET(opts, flag) ((opts)->xdl_opts |= XDF_##flag) +#define DIFF_XDL_CLR(opts, flag) ((opts)->xdl_opts &= ~XDF_##flag) struct diff_options { const char *filter; -- cgit v1.3 From eb3a9dd3279fe4b05f286665986ebf6d43a6ccc0 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 7 Mar 2009 21:02:10 +0100 Subject: Remove unused function scope local variables These variables were unused and can be removed safely: builtin-clone.c::cmd_clone(): use_local_hardlinks, use_separate_remote builtin-fetch-pack.c::find_common(): len builtin-remote.c::mv(): symref diff.c::show_stats():show_stats(): total diffcore-break.c::should_break(): base_size fast-import.c::validate_raw_date(): date, sign fsck.c::fsck_tree(): o_sha1, sha1 xdiff-interface.c::parse_num(): read_some Signed-off-by: Benjamin Kramer Signed-off-by: Junio C Hamano --- builtin-clone.c | 6 ------ builtin-fetch-pack.c | 3 +-- builtin-remote.c | 3 +-- diff.c | 4 +--- diffcore-break.c | 3 +-- fast-import.c | 8 +++----- fsck.c | 6 +----- xdiff-interface.c | 3 +-- 8 files changed, 9 insertions(+), 27 deletions(-) (limited to 'diff.c') diff --git a/builtin-clone.c b/builtin-clone.c index c338910b1c..92826cd14c 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -365,8 +365,6 @@ static void install_branch_config(const char *local, int cmd_clone(int argc, const char **argv, const char *prefix) { - int use_local_hardlinks = 1; - int use_separate_remote = 1; int is_bundle = 0; struct stat buf; const char *repo_name, *repo, *work_tree, *git_dir; @@ -388,9 +386,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (argc == 0) die("You must specify a repository to clone."); - if (option_no_hardlinks) - use_local_hardlinks = 0; - if (option_mirror) option_bare = 1; @@ -399,7 +394,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix) die("--bare and --origin %s options are incompatible.", option_origin); option_no_checkout = 1; - use_separate_remote = 0; } if (!option_origin) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 67fb80ec48..c2e5adc884 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -216,9 +216,8 @@ static int find_common(int fd[2], unsigned char *result_sha1, if (args.depth > 0) { char line[1024]; unsigned char sha1[20]; - int len; - while ((len = packet_read_line(fd[0], line, sizeof(line)))) { + while (packet_read_line(fd[0], line, sizeof(line))) { if (!prefixcmp(line, "shallow ")) { if (get_sha1_hex(line + 8, sha1)) die("invalid shallow line: %s", line); diff --git a/builtin-remote.c b/builtin-remote.c index ac69d37c8a..e171096ece 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -484,9 +484,8 @@ static int mv(int argc, const char **argv) struct string_list_item *item = remote_branches.items + i; int flag = 0; unsigned char sha1[20]; - const char *symref; - symref = resolve_ref(item->string, sha1, 1, &flag); + resolve_ref(item->string, sha1, 1, &flag); if (!(flag & REF_ISSYMREF)) continue; if (delete_ref(item->string, NULL, REF_NODEREF)) diff --git a/diff.c b/diff.c index 3feca1b173..e06c93707f 100644 --- a/diff.c +++ b/diff.c @@ -875,7 +875,7 @@ static void fill_print_name(struct diffstat_file *file) static void show_stats(struct diffstat_t* data, struct diff_options *options) { - int i, len, add, del, total, adds = 0, dels = 0; + int i, len, add, del, adds = 0, dels = 0; int max_change = 0, max_len = 0; int total_files = data->nr; int width, name_width; @@ -978,14 +978,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) */ add = added; del = deleted; - total = add + del; adds += add; dels += del; if (width <= max_change) { add = scale_linear(add, width, max_change); del = scale_linear(del, width, max_change); - total = add + del; } show_name(options->file, prefix, name, len, reset, set); fprintf(options->file, "%5d%s", added + deleted, diff --git a/diffcore-break.c b/diffcore-break.c index 31cdcfe8bc..d7097bb576 100644 --- a/diffcore-break.c +++ b/diffcore-break.c @@ -45,7 +45,7 @@ static int should_break(struct diff_filespec *src, * The value we return is 1 if we want the pair to be broken, * or 0 if we do not. */ - unsigned long delta_size, base_size, max_size; + unsigned long delta_size, max_size; unsigned long src_copied, literal_added, src_removed; *merge_score_p = 0; /* assume no deletion --- "do not break" @@ -64,7 +64,6 @@ static int should_break(struct diff_filespec *src, if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0)) return 0; /* error but caught downstream */ - base_size = ((src->size < dst->size) ? src->size : dst->size); max_size = ((src->size > dst->size) ? src->size : dst->size); if (max_size < MINIMUM_BREAK_SIZE) return 0; /* we do not break too small filepair */ diff --git a/fast-import.c b/fast-import.c index 3748ddf48d..beeac0d004 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1745,21 +1745,19 @@ static void parse_data(struct strbuf *sb) static int validate_raw_date(const char *src, char *result, int maxlen) { const char *orig_src = src; - char *endp, sign; - unsigned long date; + char *endp; errno = 0; - date = strtoul(src, &endp, 10); + strtoul(src, &endp, 10); if (errno || endp == src || *endp != ' ') return -1; src = endp + 1; if (*src != '-' && *src != '+') return -1; - sign = *src; - date = strtoul(src + 1, &endp, 10); + strtoul(src + 1, &endp, 10); if (errno || endp == src || *endp || (endp - orig_src) >= maxlen) return -1; diff --git a/fsck.c b/fsck.c index 97f76c5815..511b82cba9 100644 --- a/fsck.c +++ b/fsck.c @@ -148,20 +148,17 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) struct tree_desc desc; unsigned o_mode; const char *o_name; - const unsigned char *o_sha1; init_tree_desc(&desc, item->buffer, item->size); o_mode = 0; o_name = NULL; - o_sha1 = NULL; while (desc.size) { unsigned mode; const char *name; - const unsigned char *sha1; - sha1 = tree_entry_extract(&desc, &name, &mode); + tree_entry_extract(&desc, &name, &mode); if (strchr(name, '/')) has_full_path = 1; @@ -207,7 +204,6 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func) o_mode = mode; o_name = name; - o_sha1 = sha1; } retval = 0; diff --git a/xdiff-interface.c b/xdiff-interface.c index d782f06d99..b9b0db8d86 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -15,11 +15,10 @@ static int parse_num(char **cp_p, int *num_p) { char *cp = *cp_p; int num = 0; - int read_some; while ('0' <= *cp && *cp <= '9') num = num * 10 + *cp++ - '0'; - if (!(read_some = cp - *cp_p)) + if (!(cp - *cp_p)) return -1; *cp_p = cp; *num_p = num; -- cgit v1.3 From 4e218f54b3de6aa8ef7d15020c4507031a519f7d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 21 Mar 2009 12:42:52 +0100 Subject: Smudge the files fed to external diff and textconv When preparing temporary files for an external diff or textconv, it is easier on the external tools, especially when they are implemented using platform tools, if they are fed the input after convert_to_working_tree(). This fixes msysGit issue 177. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff.c | 13 ++++++++++--- t/t4020-diff-external.sh | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 006aa017e2..11798af0c1 100644 --- a/diff.c +++ b/diff.c @@ -1948,17 +1948,23 @@ void diff_free_filespec_data(struct diff_filespec *s) s->cnt_data = NULL; } -static void prep_temp_blob(struct diff_tempfile *temp, +static void prep_temp_blob(const char *path, struct diff_tempfile *temp, void *blob, unsigned long size, const unsigned char *sha1, int mode) { int fd; + struct strbuf buf = STRBUF_INIT; fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX"); if (fd < 0) die("unable to create temp-file: %s", strerror(errno)); + if (convert_to_working_tree(path, + (const char *)blob, (size_t)size, &buf)) { + blob = buf.buf; + size = buf.len; + } if (write_in_full(fd, blob, size) != size) die("unable to write temp-file"); close(fd); @@ -1966,6 +1972,7 @@ static void prep_temp_blob(struct diff_tempfile *temp, strcpy(temp->hex, sha1_to_hex(sha1)); temp->hex[40] = 0; sprintf(temp->mode, "%06o", mode); + strbuf_release(&buf); } static struct diff_tempfile *prepare_temp_file(const char *name, @@ -2006,7 +2013,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, die("readlink(%s)", name); if (ret == sizeof(buf)) die("symlink too long: %s", name); - prep_temp_blob(temp, buf, ret, + prep_temp_blob(name, temp, buf, ret, (one->sha1_valid ? one->sha1 : null_sha1), (one->sha1_valid ? @@ -2032,7 +2039,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, else { if (diff_populate_filespec(one, 0)) die("cannot read data blob for %s", one->path); - prep_temp_blob(temp, one->data, one->size, + prep_temp_blob(name, temp, one->data, one->size, one->sha1, one->mode); } return temp; diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 281680d95a..f8c99f1a98 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -136,4 +136,20 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' ' GIT_EXTERNAL_DIFF=echo git diff ' +echo "#!$SHELL_PATH" >fake-diff.sh +cat >> fake-diff.sh <<\EOF +cat $2 >> crlfed.txt +EOF +chmod a+x fake-diff.sh + +keep_only_cr () { + tr -dc '\015' +} + +test_expect_success 'external diff with autocrlf = true' ' + git config core.autocrlf true && + GIT_EXTERNAL_DIFF=./fake-diff.sh git diff && + test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c) +' + test_done -- cgit v1.3 From 150115aded2e1e0a83db7366f59e4b5bf1aa8135 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 22 Mar 2009 15:26:07 -0700 Subject: diff --cached: do not borrow from a work tree when a path is marked as assume-unchanged When the index says that the file in the work tree that corresponds to the blob object that is used for comparison is known to be unchanged, "diff" reads from the file and applies convert_to_git(), instead of inflating the object, to feed the internal diff engine with, because an earlier benchnark found that it tends to be faster to use this optimization. However, the index can lie when the path is marked as assume-unchanged. Disable the optimization for such paths. Signed-off-by: Junio C Hamano --- diff.c | 10 +++++++++- t/t4020-diff-external.sh | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index bf5d5f15a3..c2d277a52d 100644 --- a/diff.c +++ b/diff.c @@ -1687,7 +1687,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int struct stat st; int pos, len; - /* We do not read the cache ourselves here, because the + /* + * We do not read the cache ourselves here, because the * benchmark with my previous version that always reads cache * shows that it makes things worse for diff-tree comparing * two linux-2.6 kernel trees in an already checked out work @@ -1727,6 +1728,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode)) return 0; + /* + * If ce is marked as "assume unchanged", there is no + * guarantee that work tree matches what we are looking for. + */ + if (ce->ce_flags & CE_VALID) + return 0; + /* * If ce matches the file in the work tree, we can reuse it. */ diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 637b4e19d5..f853b8a894 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -107,4 +107,12 @@ test_expect_success 'force diff with "diff"' ' test_cmp ../t4020/diff.NUL actual ' +test_expect_success 'diff --cached' ' + git add file && + git update-index --assume-unchanged file && + echo second >file && + git diff --cached >actual && + test_cmp ../t4020/diff.NUL actual +' + test_done -- cgit v1.3 From cced5fbc241f1274ba532040b985f38c15bbf555 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 9 Apr 2009 11:46:15 -0700 Subject: Allow users to un-configure rename detection I told people on the kernel mailing list to please use "-M" when sending me rename patches, so that I can see what they do while reading email rather than having to apply the patch and then look at the end result. I also told them that if they want to make it the default, they can just add [diff] renames to their ~/.gitconfig file. And while I was thinking about that, I wanted to also check whether you can then mark individual projects to _not_ have that default in the per-repository .git/config file. And you can't. Currently you cannot have a global "enable renames by default" and then a local ".. but not for _this_ project". Why? Because if somebody writes [diff] renames = no we simply ignore it, rather than resetting "diff_detect_rename_default" back to zero. Fixed thusly. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- diff.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index e0fa78c84d..3ac71686eb 100644 --- a/diff.c +++ b/diff.c @@ -62,6 +62,15 @@ static int parse_diff_color_slot(const char *var, int ofs) die("bad config variable '%s'", var); } +static int git_config_rename(const char *var, const char *value) +{ + if (!value) + return DIFF_DETECT_RENAME; + if (!strcasecmp(value, "copies") || !strcasecmp(value, "copy")) + return DIFF_DETECT_COPY; + return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0; +} + /* * These are to give UI layer defaults. * The core-level commands such as git-diff-files should @@ -75,13 +84,7 @@ int git_diff_ui_config(const char *var, const char *value, void *cb) return 0; } if (!strcmp(var, "diff.renames")) { - if (!value) - diff_detect_rename_default = DIFF_DETECT_RENAME; - else if (!strcasecmp(value, "copies") || - !strcasecmp(value, "copy")) - diff_detect_rename_default = DIFF_DETECT_COPY; - else if (git_config_bool(var,value)) - diff_detect_rename_default = DIFF_DETECT_RENAME; + diff_detect_rename_default = git_config_rename(var, value); return 0; } if (!strcmp(var, "diff.autorefreshindex")) { -- cgit v1.3 From a408e0e649b79ede7422bf837a31d281e4188cef Mon Sep 17 00:00:00 2001 From: Markus Heidelberg Date: Sat, 25 Apr 2009 00:06:47 +0200 Subject: diff: do not color --stat output like patch context The diffstat used the color.diff.plain slot (context text) for coloring filenames and the whole summary line. This didn't look nice and the affected text isn't patch context at all. Signed-off-by: Markus Heidelberg Signed-off-by: Junio C Hamano --- diff.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 3ac71686eb..d581d4d9ff 100644 --- a/diff.c +++ b/diff.c @@ -839,10 +839,9 @@ static int scale_linear(int it, int width, int max_change) } static void show_name(FILE *file, - const char *prefix, const char *name, int len, - const char *reset, const char *set) + const char *prefix, const char *name, int len) { - fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset); + fprintf(file, " %s%-*s |", prefix, len, name); } static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset) @@ -956,7 +955,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) } if (data->files[i]->is_binary) { - show_name(options->file, prefix, name, len, reset, set); + show_name(options->file, prefix, name, len); fprintf(options->file, " Bin "); fprintf(options->file, "%s%d%s", del_c, deleted, reset); fprintf(options->file, " -> "); @@ -966,7 +965,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) continue; } else if (data->files[i]->is_unmerged) { - show_name(options->file, prefix, name, len, reset, set); + show_name(options->file, prefix, name, len); fprintf(options->file, " Unmerged\n"); continue; } @@ -988,7 +987,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) add = scale_linear(add, width, max_change); del = scale_linear(del, width, max_change); } - show_name(options->file, prefix, name, len, reset, set); + show_name(options->file, prefix, name, len); fprintf(options->file, "%5d%s", added + deleted, added + deleted ? " " : ""); show_graph(options->file, '+', add, add_c, reset); @@ -996,8 +995,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options) fprintf(options->file, "\n"); } fprintf(options->file, - "%s %d files changed, %d insertions(+), %d deletions(-)%s\n", - set, total_files, adds, dels, reset); + " %d files changed, %d insertions(+), %d deletions(-)\n", + total_files, adds, dels); } static void show_shortstats(struct diffstat_t* data, struct diff_options *options) -- cgit v1.3 From 691f1a28bf57618d8b44a193b1d28013c858aba6 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Wed, 29 Apr 2009 23:22:56 +0200 Subject: replace direct calls to unlink(2) with unlink_or_warn This helps to notice when something's going wrong, especially on systems which lock open files. I used the following criteria when selecting the code for replacement: - it was already printing a warning for the unlink failures - it is in a function which already printing something or is called from such a function - it is in a static function, returning void and the function is only called from a builtin main function (cmd_) - it is in a function which handles emergency exit (signal handlers) - it is in a function which is obvously cleaning up the lockfiles Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- builtin-apply.c | 4 ++-- builtin-fetch-pack.c | 2 +- builtin-prune-packed.c | 4 ++-- builtin-prune.c | 4 ++-- builtin-receive-pack.c | 2 +- builtin-remote.c | 4 ++-- builtin-rerere.c | 2 +- builtin-tag.c | 2 +- builtin-verify-tag.c | 2 +- diff.c | 2 +- entry.c | 2 +- fast-import.c | 4 ++-- http-push.c | 12 ++++++------ http-walker.c | 14 +++++++------- ll-merge.c | 2 +- lockfile.c | 4 ++-- pack-refs.c | 2 +- refs.c | 15 +++++---------- rerere.c | 2 +- server-info.c | 2 +- sha1_file.c | 2 +- transport.c | 2 +- unpack-trees.c | 2 +- 23 files changed, 44 insertions(+), 49 deletions(-) (limited to 'diff.c') diff --git a/builtin-apply.c b/builtin-apply.c index 7b404ef660..8a3771e87e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2781,7 +2781,7 @@ static void remove_file(struct patch *patch, int rmdir_empty) if (rmdir(patch->old_name)) warning("unable to remove submodule %s", patch->old_name); - } else if (!unlink(patch->old_name) && rmdir_empty) { + } else if (!unlink_or_warn(patch->old_name) && rmdir_empty) { remove_path(patch->old_name); } } @@ -2891,7 +2891,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned if (!try_create_file(newpath, mode, buf, size)) { if (!rename(newpath, path)) return; - unlink(newpath); + unlink_or_warn(newpath); break; } if (errno != EEXIST) diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 5d134be47c..bd97cfd9bf 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -814,7 +814,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, fd = hold_lock_file_for_update(&lock, shallow, LOCK_DIE_ON_ERROR); if (!write_shallow_commits(fd, 0)) { - unlink(shallow); + unlink_or_warn(shallow); rollback_lock_file(&lock); } else { commit_lock_file(&lock); diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c index 4942892e9f..00590b1c3c 100644 --- a/builtin-prune-packed.c +++ b/builtin-prune-packed.c @@ -28,8 +28,8 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts) memcpy(pathname + len, de->d_name, 38); if (opts & DRY_RUN) printf("rm -f %s\n", pathname); - else if (unlink(pathname) < 0) - error("unable to unlink %s", pathname); + else + unlink_or_warn(pathname); display_progress(progress, i + 1); } pathname[len] = 0; diff --git a/builtin-prune.c b/builtin-prune.c index 545e9c1f94..145ba83651 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -27,7 +27,7 @@ static int prune_tmp_object(const char *path, const char *filename) } printf("Removing stale temporary file %s\n", fullpath); if (!show_only) - unlink(fullpath); + unlink_or_warn(fullpath); return 0; } @@ -47,7 +47,7 @@ static int prune_object(char *path, const char *filename, const unsigned char *s (type > 0) ? typename(type) : "unknown"); } if (!show_only) - unlink(fullpath); + unlink_or_warn(fullpath); return 0; } diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c index a970b39505..035b723e50 100644 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@ -702,7 +702,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix) unpack_status = unpack(); execute_commands(unpack_status); if (pack_lockfile) - unlink(pack_lockfile); + unlink_or_warn(pack_lockfile); if (report_status) report(unpack_status); run_receive_hook(post_receive_hook); diff --git a/builtin-remote.c b/builtin-remote.c index 2ed752cbf1..71abf68404 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -525,8 +525,8 @@ static int migrate_file(struct remote *remote) path = git_path("remotes/%s", remote->name); else if (remote->origin == REMOTE_BRANCHES) path = git_path("branches/%s", remote->name); - if (path && unlink(path)) - warning("failed to remove '%s'", path); + if (path) + unlink_or_warn(path); return 0; } diff --git a/builtin-rerere.c b/builtin-rerere.c index 020af7377b..adfb7b5f48 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -116,7 +116,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) if (!has_rerere_resolution(name)) unlink_rr_item(name); } - unlink(git_path("rr-cache/MERGE_RR")); + unlink_or_warn(git_path("rr-cache/MERGE_RR")); } else if (!strcmp(argv[1], "gc")) garbage_collect(&merge_rr); else if (!strcmp(argv[1], "status")) diff --git a/builtin-tag.c b/builtin-tag.c index 01e73747d0..e544430094 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -338,7 +338,7 @@ static void create_tag(const unsigned char *object, const char *tag, exit(128); } if (path) { - unlink(path); + unlink_or_warn(path); free(path); } } diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c index 729a1593e6..7f7fda42f9 100644 --- a/builtin-verify-tag.c +++ b/builtin-verify-tag.c @@ -55,7 +55,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose) close(gpg.in); ret = finish_command(&gpg); - unlink(path); + unlink_or_warn(path); return ret; } diff --git a/diff.c b/diff.c index 3ac71686eb..6802f5ac12 100644 --- a/diff.c +++ b/diff.c @@ -189,7 +189,7 @@ static void remove_tempfile(void) int i; for (i = 0; i < ARRAY_SIZE(diff_temp); i++) { if (diff_temp[i].name == diff_temp[i].tmp_path) - unlink(diff_temp[i].name); + unlink_or_warn(diff_temp[i].name); diff_temp[i].name = NULL; } } diff --git a/entry.c b/entry.c index 915514aa5c..cc841edf90 100644 --- a/entry.c +++ b/entry.c @@ -35,7 +35,7 @@ static void create_directories(const char *path, int path_len, */ if (mkdir(buf, 0777)) { if (errno == EEXIST && state->force && - !unlink(buf) && !mkdir(buf, 0777)) + !unlink_or_warn(buf) && !mkdir(buf, 0777)) continue; die("cannot create directory at %s", buf); } diff --git a/fast-import.c b/fast-import.c index 8d959af3b2..6a618e9163 100644 --- a/fast-import.c +++ b/fast-import.c @@ -931,7 +931,7 @@ static void unkeep_all_packs(void) struct packed_git *p = all_packs[k]; snprintf(name, sizeof(name), "%s/pack/pack-%s.keep", get_object_directory(), sha1_to_hex(p->sha1)); - unlink(name); + unlink_or_warn(name); } } @@ -981,7 +981,7 @@ static void end_packfile(void) } else { close(old_p->pack_fd); - unlink(old_p->pack_name); + unlink_or_warn(old_p->pack_name); } free(old_p); diff --git a/http-push.c b/http-push.c index 5138224cc3..29e8ebfebb 100644 --- a/http-push.c +++ b/http-push.c @@ -315,9 +315,9 @@ static void start_fetch_loose(struct transfer_request *request) "%s.temp", filename); snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename); - unlink(prevfile); + unlink_or_warn(prevfile); rename(request->tmpfile, prevfile); - unlink(request->tmpfile); + unlink_or_warn(request->tmpfile); if (request->local_fileno != -1) error("fd leakage in start: %d", request->local_fileno); @@ -372,7 +372,7 @@ static void start_fetch_loose(struct transfer_request *request) } while (prev_read > 0); close(prevlocal); } - unlink(prevfile); + unlink_or_warn(prevfile); /* Reset inflate/SHA1 if there was an error reading the previous temp file; also rewind to the beginning of the local file. */ @@ -784,7 +784,7 @@ static void finish_request(struct transfer_request *request) request->http_code != 416) { if (stat(request->tmpfile, &st) == 0) { if (st.st_size == 0) - unlink(request->tmpfile); + unlink_or_warn(request->tmpfile); } } else { if (request->http_code == 416) @@ -793,9 +793,9 @@ static void finish_request(struct transfer_request *request) git_inflate_end(&request->stream); git_SHA1_Final(request->real_sha1, &request->c); if (request->zret != Z_STREAM_END) { - unlink(request->tmpfile); + unlink_or_warn(request->tmpfile); } else if (hashcmp(request->obj->sha1, request->real_sha1)) { - unlink(request->tmpfile); + unlink_or_warn(request->tmpfile); } else { request->rename = move_temp_to_file( diff --git a/http-walker.c b/http-walker.c index c5a3ea3b31..7321ccc9fe 100644 --- a/http-walker.c +++ b/http-walker.c @@ -111,9 +111,9 @@ static void start_object_request(struct walker *walker, struct walker_data *data = walker->data; snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename); - unlink(prevfile); + unlink_or_warn(prevfile); rename(obj_req->tmpfile, prevfile); - unlink(obj_req->tmpfile); + unlink_or_warn(obj_req->tmpfile); if (obj_req->local != -1) error("fd leakage in start: %d", obj_req->local); @@ -177,7 +177,7 @@ static void start_object_request(struct walker *walker, } while (prev_read > 0); close(prevlocal); } - unlink(prevfile); + unlink_or_warn(prevfile); /* Reset inflate/SHA1 if there was an error reading the previous temp file; also rewind to the beginning of the local file. */ @@ -238,18 +238,18 @@ static void finish_object_request(struct object_request *obj_req) } else if (obj_req->curl_result != CURLE_OK) { if (stat(obj_req->tmpfile, &st) == 0) if (st.st_size == 0) - unlink(obj_req->tmpfile); + unlink_or_warn(obj_req->tmpfile); return; } git_inflate_end(&obj_req->stream); git_SHA1_Final(obj_req->real_sha1, &obj_req->c); if (obj_req->zret != Z_STREAM_END) { - unlink(obj_req->tmpfile); + unlink_or_warn(obj_req->tmpfile); return; } if (hashcmp(obj_req->sha1, obj_req->real_sha1)) { - unlink(obj_req->tmpfile); + unlink_or_warn(obj_req->tmpfile); return; } obj_req->rename = @@ -809,7 +809,7 @@ static void abort_object_request(struct object_request *obj_req) close(obj_req->local); obj_req->local = -1; } - unlink(obj_req->tmpfile); + unlink_or_warn(obj_req->tmpfile); if (obj_req->slot) { release_active_slot(obj_req->slot); obj_req->slot = NULL; diff --git a/ll-merge.c b/ll-merge.c index fa2ca5250c..81c02ad053 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -219,7 +219,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn, close(fd); bad: for (i = 0; i < 3; i++) - unlink(temp[i]); + unlink_or_warn(temp[i]); strbuf_release(&cmd); return status; } diff --git a/lockfile.c b/lockfile.c index 3dbb2d1ff9..984eb320fc 100644 --- a/lockfile.c +++ b/lockfile.c @@ -16,7 +16,7 @@ static void remove_lock_file(void) lock_file_list->filename[0]) { if (lock_file_list->fd >= 0) close(lock_file_list->fd); - unlink(lock_file_list->filename); + unlink_or_warn(lock_file_list->filename); } lock_file_list = lock_file_list->next; } @@ -259,7 +259,7 @@ void rollback_lock_file(struct lock_file *lk) if (lk->filename[0]) { if (lk->fd >= 0) close(lk->fd); - unlink(lk->filename); + unlink_or_warn(lk->filename); } lk->filename[0] = 0; } diff --git a/pack-refs.c b/pack-refs.c index 2c76fb181f..301fc60eae 100644 --- a/pack-refs.c +++ b/pack-refs.c @@ -66,7 +66,7 @@ static void prune_ref(struct ref_to_prune *r) struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1); if (lock) { - unlink(git_path("%s", r->name)); + unlink_or_warn(git_path("%s", r->name)); unlock_ref(lock); } } diff --git a/refs.c b/refs.c index e65a3b4c4e..2b1f0f0e6e 100644 --- a/refs.c +++ b/refs.c @@ -1002,12 +1002,10 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) } else { path = git_path("%s", refname); } - err = unlink(path); - if (err && errno != ENOENT) { + err = unlink_or_warn(path); + if (err && errno != ENOENT) ret = 1; - error("unlink(%s) failed: %s", - path, strerror(errno)); - } + if (!(delopt & REF_NODEREF)) lock->lk->filename[i] = '.'; } @@ -1017,10 +1015,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt) */ ret |= repack_without_ref(refname); - err = unlink(git_path("logs/%s", lock->ref_name)); - if (err && errno != ENOENT) - warning("unlink(%s) failed: %s", - git_path("logs/%s", lock->ref_name), strerror(errno)); + unlink_or_warn(git_path("logs/%s", lock->ref_name)); invalidate_cached_refs(); unlock_ref(lock); return ret; @@ -1381,7 +1376,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master, if (adjust_shared_perm(git_HEAD)) { error("Unable to fix permissions on %s", lockpath); error_unlink_return: - unlink(lockpath); + unlink_or_warn(lockpath); error_free_return: free(git_HEAD); return -1; diff --git a/rerere.c b/rerere.c index 713c6e16ac..87360dc23e 100644 --- a/rerere.c +++ b/rerere.c @@ -173,7 +173,7 @@ static int handle_file(const char *path, git_SHA1_Final(sha1, &ctx); if (hunk != RR_CONTEXT) { if (output) - unlink(output); + unlink_or_warn(output); return error("Could not parse conflict hunks in %s", path); } if (wrerror) diff --git a/server-info.c b/server-info.c index 66b0d9d878..d096dc7718 100644 --- a/server-info.c +++ b/server-info.c @@ -246,7 +246,7 @@ int update_server_info(int force) errs = errs | update_info_packs(force); /* remove leftover rev-cache file if there is any */ - unlink(git_path("info/rev-cache")); + unlink_or_warn(git_path("info/rev-cache")); return errs; } diff --git a/sha1_file.c b/sha1_file.c index f708cf4f67..dd474116a8 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2247,7 +2247,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename) goto out; ret = errno; } - unlink(tmpfile); + unlink_or_warn(tmpfile); if (ret) { if (ret != EEXIST) { return error("unable to write sha1 filename %s: %s\n", filename, strerror(ret)); diff --git a/transport.c b/transport.c index 3dfb03c06e..efecb65258 100644 --- a/transport.c +++ b/transport.c @@ -1069,7 +1069,7 @@ int transport_fetch_refs(struct transport *transport, const struct ref *refs) void transport_unlock_pack(struct transport *transport) { if (transport->pack_lockfile) { - unlink(transport->pack_lockfile); + unlink_or_warn(transport->pack_lockfile); free(transport->pack_lockfile); transport->pack_lockfile = NULL; } diff --git a/unpack-trees.c b/unpack-trees.c index e4eb8fa3af..aaacaf1015 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -61,7 +61,7 @@ static void unlink_entry(struct cache_entry *ce) { if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce))) return; - if (unlink(ce->name)) + if (unlink_or_warn(ce->name)) return; schedule_dir_for_removal(ce->name, ce_namelen(ce)); } -- cgit v1.3 From 4b25d091ba53c758fae0096b8c0662371857b9d9 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Fri, 1 May 2009 12:06:36 +0300 Subject: Fix a bunch of pointer declarations (codestyle) Essentially; s/type* /type */ as per the coding guidelines. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- alias.c | 4 ++-- alloc.c | 2 +- attr.c | 4 ++-- builtin-blame.c | 8 ++++---- builtin-checkout-index.c | 4 ++-- builtin-describe.c | 4 ++-- builtin-fetch-pack.c | 2 +- builtin-help.c | 6 +++--- builtin-update-index.c | 6 +++--- cache.h | 2 +- combine-diff.c | 4 ++-- compat/mingw.c | 2 +- config.c | 30 +++++++++++++++--------------- contrib/convert-objects/convert-objects.c | 6 +++--- diff-no-index.c | 2 +- diff.c | 4 ++-- dir.c | 2 +- fast-import.c | 14 +++++++------- git.c | 8 ++++---- lockfile.c | 2 +- reflog-walk.c | 2 +- run-command.c | 2 +- server-info.c | 4 ++-- sha1_file.c | 2 +- wt-status.c | 2 +- 25 files changed, 64 insertions(+), 64 deletions(-) (limited to 'diff.c') diff --git a/alias.c b/alias.c index ccb1108c94..e687fe54c1 100644 --- a/alias.c +++ b/alias.c @@ -27,7 +27,7 @@ int split_cmdline(char *cmdline, const char ***argv) int src, dst, count = 0, size = 16; char quoted = 0; - *argv = xmalloc(sizeof(char*) * size); + *argv = xmalloc(sizeof(char *) * size); /* split alias_string */ (*argv)[count++] = cmdline; @@ -40,7 +40,7 @@ int split_cmdline(char *cmdline, const char ***argv) ; /* skip */ if (count >= size) { size += 16; - *argv = xrealloc(*argv, sizeof(char*) * size); + *argv = xrealloc(*argv, sizeof(char *) * size); } (*argv)[count++] = cmdline + dst; } else if (!quoted && (c == '\'' || c == '"')) { diff --git a/alloc.c b/alloc.c index 216c23a6f8..6ef6753d18 100644 --- a/alloc.c +++ b/alloc.c @@ -57,7 +57,7 @@ DEFINE_ALLOCATOR(object, union any_object) #define SZ_FMT "%zu" #endif -static void report(const char* name, unsigned int count, size_t size) +static void report(const char *name, unsigned int count, size_t size) { fprintf(stderr, "%10s: %8u (" SZ_FMT " kB)\n", name, count, size); } diff --git a/attr.c b/attr.c index f1ca4f5859..98eb636f13 100644 --- a/attr.c +++ b/attr.c @@ -224,7 +224,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, if (is_macro) res->u.attr = git_attr(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; } @@ -275,7 +275,7 @@ static void free_attr_elem(struct attr_stack *e) setto == ATTR__UNKNOWN) ; else - free((char*) setto); + free((char *) setto); } free(a); } diff --git a/builtin-blame.c b/builtin-blame.c index 83141fc84e..cf74a92614 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -873,7 +873,7 @@ static void find_copy_in_blob(struct scoreboard *sb, * Prepare mmfile that contains only the lines in ent. */ cp = nth_line(sb, ent->lno); - file_o.ptr = (char*) cp; + file_o.ptr = (char *) cp; cnt = ent->num_lines; while (cnt && cp < sb->final_buf + sb->final_buf_size) { @@ -1704,7 +1704,7 @@ static int prepare_lines(struct scoreboard *sb) while (len--) { if (bol) { sb->lineno = xrealloc(sb->lineno, - sizeof(int* ) * (num + 1)); + sizeof(int *) * (num + 1)); sb->lineno[num] = buf - sb->final_buf; bol = 0; } @@ -1714,7 +1714,7 @@ static int prepare_lines(struct scoreboard *sb) } } sb->lineno = xrealloc(sb->lineno, - sizeof(int* ) * (num + incomplete + 1)); + sizeof(int *) * (num + incomplete + 1)); sb->lineno[num + incomplete] = buf - sb->final_buf; sb->num_lines = num + incomplete; return sb->num_lines; @@ -1889,7 +1889,7 @@ static const char *parse_loc(const char *spec, return spec; /* it could be a regexp of form /.../ */ - for (term = (char*) spec + 1; *term && *term != '/'; term++) { + for (term = (char *) spec + 1; *term && *term != '/'; term++) { if (*term == '\\') term++; } diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 0d534bc023..afe35e246c 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -124,7 +124,7 @@ static int checkout_file(const char *name, int prefix_length) static void checkout_all(const char *prefix, int prefix_length) { int i, errs = 0; - struct cache_entry* last_ce = NULL; + struct cache_entry *last_ce = NULL; for (i = 0; i < active_nr ; i++) { struct cache_entry *ce = active_cache[i]; @@ -278,7 +278,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix) p = prefix_path(prefix, prefix_length, arg); checkout_file(p, prefix_length); if (p < arg || p > arg + strlen(arg)) - free((char*)p); + free((char *)p); } if (read_from_stdin) { diff --git a/builtin-describe.c b/builtin-describe.c index 3a007ed1ca..63c6a19da5 100644 --- a/builtin-describe.c +++ b/builtin-describe.c @@ -334,7 +334,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) die("--long is incompatible with --abbrev=0"); if (contains) { - const char **args = xmalloc((7 + argc) * sizeof(char*)); + const char **args = xmalloc((7 + argc) * sizeof(char *)); int i = 0; args[i++] = "name-rev"; args[i++] = "--name-only"; @@ -349,7 +349,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix) args[i++] = s; } } - memcpy(args + i, argv, argc * sizeof(char*)); + memcpy(args + i, argv, argc * sizeof(char *)); args[i + argc] = NULL; return cmd_name_rev(i + argc, args, prefix); } diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 5d134be47c..cbe5f206f5 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -111,7 +111,7 @@ static void mark_common(struct commit *commit, Get the next rev to send, ignoring the common. */ -static const unsigned char* get_rev(void) +static const unsigned char *get_rev(void) { struct commit *commit = NULL; diff --git a/builtin-help.c b/builtin-help.c index e7fbe9af63..67dda3e6e6 100644 --- a/builtin-help.c +++ b/builtin-help.c @@ -114,7 +114,7 @@ static int check_emacsclient_version(void) return 0; } -static void exec_woman_emacs(const char* path, const char *page) +static void exec_woman_emacs(const char *path, const char *page) { if (!check_emacsclient_version()) { /* This works only with emacsclient version >= 22. */ @@ -128,7 +128,7 @@ static void exec_woman_emacs(const char* path, const char *page) } } -static void exec_man_konqueror(const char* path, const char *page) +static void exec_man_konqueror(const char *path, const char *page) { const char *display = getenv("DISPLAY"); if (display && *display) { @@ -156,7 +156,7 @@ static void exec_man_konqueror(const char* path, const char *page) } } -static void exec_man_man(const char* path, const char *page) +static void exec_man_man(const char *path, const char *page) { if (!path) path = "man"; diff --git a/builtin-update-index.c b/builtin-update-index.c index 1fde893cfa..92beaaf4b3 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -292,7 +292,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length) report("add '%s'", path); free_return: if (p < path || p > path + strlen(path)) - free((char*)p); + free((char *)p); } static void read_index_info(int line_termination) @@ -509,7 +509,7 @@ static int do_unresolve(int ac, const char **av, const char *p = prefix_path(prefix, prefix_length, arg); err |= unresolve_one(p); if (p < arg || p > arg + strlen(arg)) - free((char*)p); + free((char *)p); } return err; } @@ -712,7 +712,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) if (set_executable_bit) chmod_path(set_executable_bit, p); if (p < path || p > path + strlen(path)) - free((char*)p); + free((char *)p); } if (read_from_stdin) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; diff --git a/cache.h b/cache.h index d0d48b4c88..b8503ad91c 100644 --- a/cache.h +++ b/cache.h @@ -846,7 +846,7 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1, extern void pack_report(void); extern int open_pack_index(struct packed_git *); -extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *); +extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *); extern void close_pack_windows(struct packed_git *); extern void unuse_pack(struct pack_window **); extern void free_pack_by_name(const char *); diff --git a/combine-diff.c b/combine-diff.c index d210656861..60d03676bb 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -24,7 +24,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, path = q->queue[i]->two->path; len = strlen(path); p = xmalloc(combine_diff_path_size(num_parent, len)); - p->path = (char*) &(p->parent[num_parent]); + p->path = (char *) &(p->parent[num_parent]); memcpy(p->path, path, len); p->path[len] = 0; p->len = len; @@ -1063,7 +1063,7 @@ void diff_tree_combined_merge(const unsigned char *sha1, for (parents = commit->parents, num_parent = 0; parents; parents = parents->next, num_parent++) - hashcpy((unsigned char*)(parent + num_parent), + hashcpy((unsigned char *)(parent + num_parent), parents->item->object.sha1); diff_tree_combined(sha1, parent, num_parent, dense, rev); } diff --git a/compat/mingw.c b/compat/mingw.c index 2a047019e8..cdeda1d985 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -562,7 +562,7 @@ static char **get_path_split(void) if (!n) return NULL; - path = xmalloc((n+1)*sizeof(char*)); + path = xmalloc((n+1)*sizeof(char *)); p = envpath; i = 0; do { diff --git a/config.c b/config.c index f76a78311e..1682273c12 100644 --- a/config.c +++ b/config.c @@ -724,16 +724,16 @@ int git_config(config_fn_t fn, void *data) static struct { int baselen; - char* key; + char *key; int do_not_match; - regex_t* value_regex; + regex_t *value_regex; int multi_replace; size_t offset[MAX_MATCHES]; enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state; int seen; } store; -static int matches(const char* key, const char* value) +static int matches(const char *key, const char *value) { return !strcmp(key, store.key) && (store.value_regex == NULL || @@ -741,7 +741,7 @@ static int matches(const char* key, const char* value) !regexec(store.value_regex, value, 0, NULL, 0))); } -static int store_aux(const char* key, const char* value, void *cb) +static int store_aux(const char *key, const char *value, void *cb) { const char *ep; size_t section_len; @@ -810,7 +810,7 @@ static int write_error(const char *filename) return 4; } -static int store_write_section(int fd, const char* key) +static int store_write_section(int fd, const char *key) { const char *dot; int i, success; @@ -835,7 +835,7 @@ static int store_write_section(int fd, const char* key) return success; } -static int store_write_pair(int fd, const char* key, const char* value) +static int store_write_pair(int fd, const char *key, const char *value) { int i, success; int length = strlen(key + store.baselen + 1); @@ -883,8 +883,8 @@ static int store_write_pair(int fd, const char* key, const char* value) return success; } -static ssize_t find_beginning_of_line(const char* contents, size_t size, - size_t offset_, int* found_bracket) +static ssize_t find_beginning_of_line(const char *contents, size_t size, + size_t offset_, int *found_bracket) { size_t equal_offset = size, bracket_offset = size; ssize_t offset; @@ -909,7 +909,7 @@ contline: return offset; } -int git_config_set(const char* key, const char* value) +int git_config_set(const char *key, const char *value) { return git_config_set_multivar(key, value, NULL, 0); } @@ -937,15 +937,15 @@ int git_config_set(const char* key, const char* value) * - the config file is removed and the lock file rename()d to it. * */ -int git_config_set_multivar(const char* key, const char* value, - const char* value_regex, int multi_replace) +int git_config_set_multivar(const char *key, const char *value, + const char *value_regex, int multi_replace) { int i, dot; int fd = -1, in_fd; int ret; - char* config_filename; + char *config_filename; struct lock_file *lock = NULL; - const char* last_dot = strrchr(key, '.'); + const char *last_dot = strrchr(key, '.'); if (config_exclusive_filename) config_filename = xstrdup(config_exclusive_filename); @@ -1026,13 +1026,13 @@ int git_config_set_multivar(const char* key, const char* value, goto out_free; } - store.key = (char*)key; + store.key = (char *)key; if (!store_write_section(fd, key) || !store_write_pair(fd, key, value)) goto write_err_out; } else { struct stat st; - char* contents; + char *contents; size_t contents_sz, copy_begin, copy_end; int i, new_line = 0; diff --git a/contrib/convert-objects/convert-objects.c b/contrib/convert-objects/convert-objects.c index 90e7900e6d..f3b57bf1d2 100644 --- a/contrib/convert-objects/convert-objects.c +++ b/contrib/convert-objects/convert-objects.c @@ -59,7 +59,7 @@ static void convert_ascii_sha1(void *buffer) struct entry *entry; if (get_sha1_hex(buffer, sha1)) - die("expected sha1, got '%s'", (char*) buffer); + die("expected sha1, got '%s'", (char *) buffer); entry = convert_entry(sha1); memcpy(buffer, sha1_to_hex(entry->new_sha1), 40); } @@ -100,7 +100,7 @@ static int write_subdirectory(void *buffer, unsigned long size, const char *base if (!slash) { newlen += sprintf(new + newlen, "%o %s", mode, path); new[newlen++] = '\0'; - hashcpy((unsigned char*)new + newlen, (unsigned char *) buffer + len - 20); + hashcpy((unsigned char *)new + newlen, (unsigned char *) buffer + len - 20); newlen += 20; used += len; @@ -271,7 +271,7 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu unsigned long orig_size = size; if (memcmp(buffer, "tree ", 5)) - die("Bad commit '%s'", (char*) buffer); + die("Bad commit '%s'", (char *) buffer); convert_ascii_sha1((char *) buffer + 5); buffer = (char *) buffer + 46; /* "tree " + "hex sha1" + "\n" */ while (!memcmp(buffer, "parent ", 7)) { diff --git a/diff-no-index.c b/diff-no-index.c index 42c1dd8ad3..4ebc1dbd87 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -233,7 +233,7 @@ void diff_no_index(struct rev_info *revs, if (prefix) { int len = strlen(prefix); - revs->diffopt.paths = xcalloc(2, sizeof(char*)); + revs->diffopt.paths = xcalloc(2, sizeof(char *)); for (i = 0; i < 2; i++) { const char *p = argv[argc - 2 + i]; /* diff --git a/diff.c b/diff.c index 3ac71686eb..363dcb9613 100644 --- a/diff.c +++ b/diff.c @@ -876,7 +876,7 @@ static void fill_print_name(struct diffstat_file *file) file->print_name = pname; } -static void show_stats(struct diffstat_t* data, struct diff_options *options) +static void show_stats(struct diffstat_t *data, struct diff_options *options) { int i, len, add, del, adds = 0, dels = 0; int max_change = 0, max_len = 0; @@ -1025,7 +1025,7 @@ static void show_shortstats(struct diffstat_t* data, struct diff_options *option total_files, adds, dels); } -static void show_numstat(struct diffstat_t* data, struct diff_options *options) +static void show_numstat(struct diffstat_t *data, struct diff_options *options) { int i; diff --git a/dir.c b/dir.c index c91ebfb46f..15677da47c 100644 --- a/dir.c +++ b/dir.c @@ -156,7 +156,7 @@ void add_exclude(const char *string, const char *base, if (len && string[len - 1] == '/') { char *s; x = xmalloc(sizeof(*x) + len); - s = (char*)(x+1); + s = (char *)(x+1); memcpy(s, string, len - 1); s[len - 1] = '\0'; string = s; diff --git a/fast-import.c b/fast-import.c index 8d959af3b2..e9d23ffb2f 100644 --- a/fast-import.c +++ b/fast-import.c @@ -212,7 +212,7 @@ struct tree_content; struct tree_entry { struct tree_content *tree; - struct atom_str* name; + struct atom_str *name; struct tree_entry_ms { uint16_t mode; @@ -313,7 +313,7 @@ static unsigned int object_entry_alloc = 5000; static struct object_entry_pool *blocks; static struct object_entry *object_table[1 << 16]; static struct mark_set *marks; -static const char* mark_file; +static const char *mark_file; /* Our last blob */ static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 }; @@ -672,7 +672,7 @@ static struct branch *lookup_branch(const char *name) static struct branch *new_branch(const char *name) { unsigned int hc = hc_str(name, strlen(name)) % branch_table_sz; - struct branch* b = lookup_branch(name); + struct branch *b = lookup_branch(name); if (b) die("Invalid attempt to create duplicate branch: %s", name); @@ -1035,7 +1035,7 @@ static int store_object( git_SHA_CTX c; z_stream s; - hdrlen = sprintf((char*)hdr,"%s %lu", typename(type), + hdrlen = sprintf((char *)hdr,"%s %lu", typename(type), (unsigned long)dat->len) + 1; git_SHA1_Init(&c); git_SHA1_Update(&c, hdr, hdrlen); @@ -1217,7 +1217,7 @@ static const char *get_mode(const char *str, uint16_t *modep) static void load_tree(struct tree_entry *root) { - unsigned char* sha1 = root->versions[1].sha1; + unsigned char *sha1 = root->versions[1].sha1; struct object_entry *myoe; struct tree_content *t; unsigned long size; @@ -1258,8 +1258,8 @@ static void load_tree(struct tree_entry *root) e->versions[0].mode = e->versions[1].mode; e->name = to_atom(c, strlen(c)); c += e->name->str_len + 1; - hashcpy(e->versions[0].sha1, (unsigned char*)c); - hashcpy(e->versions[1].sha1, (unsigned char*)c); + hashcpy(e->versions[0].sha1, (unsigned char *)c); + hashcpy(e->versions[1].sha1, (unsigned char *)c); c += 20; } free(buf); diff --git a/git.c b/git.c index cc5aaa76f1..5a00726d09 100644 --- a/git.c +++ b/git.c @@ -47,7 +47,7 @@ static void commit_pager_choice(void) { } } -static int handle_options(const char*** argv, int* argc, int* envchanged) +static int handle_options(const char ***argv, int *argc, int *envchanged) { int handled = 0; @@ -136,7 +136,7 @@ static int handle_alias(int *argcp, const char ***argv) int envchanged = 0, ret = 0, saved_errno = errno; const char *subdir; int count, option_count; - const char** new_argv; + const char **new_argv; const char *alias_command; char *alias_string; int unused_nongit; @@ -187,10 +187,10 @@ static int handle_alias(int *argcp, const char ***argv) "trace: alias expansion: %s =>", alias_command); - new_argv = xrealloc(new_argv, sizeof(char*) * + new_argv = xrealloc(new_argv, sizeof(char *) * (count + *argcp + 1)); /* insert after command name */ - memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp); + memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp); new_argv[count+*argcp] = NULL; *argv = new_argv; diff --git a/lockfile.c b/lockfile.c index 3dbb2d1ff9..828d19f452 100644 --- a/lockfile.c +++ b/lockfile.c @@ -109,7 +109,7 @@ static char *resolve_symlink(char *p, size_t s) * link is a relative path, so I must replace the * last element of p with it. */ - char *r = (char*)last_path_elm(p); + char *r = (char *)last_path_elm(p); if (r - p + link_len < s) strcpy(r, link); else { diff --git a/reflog-walk.c b/reflog-walk.c index fd065f4e1a..5623ea6b48 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -241,7 +241,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->object.flags &= ~(ADDED | SEEN | SHOWN); } -void show_reflog_message(struct reflog_walk_info* info, int oneline, +void show_reflog_message(struct reflog_walk_info *info, int oneline, enum date_mode dmode) { if (info && info->last_commit_reflog) { diff --git a/run-command.c b/run-command.c index b05c734d05..eb2efc3307 100644 --- a/run-command.c +++ b/run-command.c @@ -106,7 +106,7 @@ int start_command(struct child_process *cmd) if (cmd->env) { for (; *cmd->env; cmd->env++) { if (strchr(*cmd->env, '=')) - putenv((char*)*cmd->env); + putenv((char *)*cmd->env); else unsetenv(*cmd->env); } diff --git a/server-info.c b/server-info.c index 66b0d9d878..906ce5b272 100644 --- a/server-info.c +++ b/server-info.c @@ -132,8 +132,8 @@ static int read_pack_info_file(const char *infofile) static int compare_info(const void *a_, const void *b_) { - struct pack_info * const* a = a_; - struct pack_info * const* b = b_; + struct pack_info *const *a = a_; + struct pack_info *const *b = b_; if (0 <= (*a)->old_num && 0 <= (*b)->old_num) /* Keep the order in the original */ diff --git a/sha1_file.c b/sha1_file.c index f708cf4f67..28bd9082fc 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -791,7 +791,7 @@ static int in_window(struct pack_window *win, off_t offset) && (offset + 20) <= (win_off + win->len); } -unsigned char* use_pack(struct packed_git *p, +unsigned char *use_pack(struct packed_git *p, struct pack_window **w_cursor, off_t offset, unsigned int *left) diff --git a/wt-status.c b/wt-status.c index 929b00f592..1b6df45450 100644 --- a/wt-status.c +++ b/wt-status.c @@ -40,7 +40,7 @@ static int parse_status_slot(const char *var, int offset) die("bad config variable '%s'", var); } -static const char* color(int slot) +static const char *color(int slot) { return wt_status_use_color > 0 ? wt_status_colors[slot] : ""; } -- cgit v1.3 From 3cd7388d57db4f4a29949e8de96493fb77059484 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 25 May 2009 06:46:09 -0400 Subject: convert bare readlink to strbuf_readlink This particular readlink call never NUL-terminated its result, making it a potential source of bugs (though there is no bug now, as it currently always respects the length field). Let's just switch it to strbuf_readlink which is shorter and less error-prone. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index f06876be67..dcfbcb0215 100644 --- a/diff.c +++ b/diff.c @@ -2014,18 +2014,15 @@ static struct diff_tempfile *prepare_temp_file(const char *name, die("stat(%s): %s", name, strerror(errno)); } if (S_ISLNK(st.st_mode)) { - int ret; - char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */ - ret = readlink(name, buf, sizeof(buf)); - if (ret < 0) + struct strbuf sb = STRBUF_INIT; + if (strbuf_readlink(&sb, name, st.st_size) < 0) die("readlink(%s)", name); - if (ret == sizeof(buf)) - die("symlink too long: %s", name); - prep_temp_blob(name, temp, buf, ret, + prep_temp_blob(name, temp, sb.buf, sb.len, (one->sha1_valid ? one->sha1 : null_sha1), (one->sha1_valid ? one->mode : S_IFLNK)); + strbuf_release(&sb); } else { /* we can borrow from the file in the work tree */ -- cgit v1.3 From 003b33a8ad686ee4a0d0b36635bfd6aba940b24a Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Sun, 31 May 2009 01:35:52 -0700 Subject: diff: generate pretty filenames in prep_temp_blob() Naturally, prep_temp_blob() did not care about filenames. As a result, GIT_EXTERNAL_DIFF and textconv generated filenames such as ".diff_XXXXXX". This modifies prep_temp_blob() to generate user-friendly filenames when creating temporary files. Diffing "name.ext" now generates "XXXXXX_name.ext". Signed-off-by: David Aguilar Signed-off-by: Junio C Hamano --- cache.h | 2 ++ diff.c | 12 +++++++++++- path.c | 16 ++++++++++++++++ t/t4020-diff-external.sh | 9 +++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) (limited to 'diff.c') diff --git a/cache.h b/cache.h index b8503ad91c..871c9844e8 100644 --- a/cache.h +++ b/cache.h @@ -614,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1); int git_mkstemp(char *path, size_t n, const char *template); +int git_mkstemps(char *path, size_t n, const char *template, int suffix_len); + /* * NOTE NOTE NOTE!! * diff --git a/diff.c b/diff.c index dcfbcb0215..4d0a5b9ae6 100644 --- a/diff.c +++ b/diff.c @@ -1964,8 +1964,16 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, { int fd; struct strbuf buf = STRBUF_INIT; + struct strbuf template = STRBUF_INIT; + char *path_dup = xstrdup(path); + const char *base = basename(path_dup); - fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX"); + /* Generate "XXXXXX_basename.ext" */ + strbuf_addstr(&template, "XXXXXX_"); + strbuf_addstr(&template, base); + + fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf, + strlen(base) + 1); if (fd < 0) die("unable to create temp-file: %s", strerror(errno)); if (convert_to_working_tree(path, @@ -1981,6 +1989,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, temp->hex[40] = 0; sprintf(temp->mode, "%06o", mode); strbuf_release(&buf); + strbuf_release(&template); + free(path_dup); } static struct diff_tempfile *prepare_temp_file(const char *name, diff --git a/path.c b/path.c index 8a0a6741fd..047fdb0a1f 100644 --- a/path.c +++ b/path.c @@ -139,6 +139,22 @@ int git_mkstemp(char *path, size_t len, const char *template) return mkstemp(path); } +/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */ +int git_mkstemps(char *path, size_t len, const char *template, int suffix_len) +{ + const char *tmp; + size_t n; + + tmp = getenv("TMPDIR"); + if (!tmp) + tmp = "/tmp"; + n = snprintf(path, len, "%s/%s", tmp, template); + if (len <= n) { + errno = ENAMETOOLONG; + return -1; + } + return mkstemps(path, suffix_len); +} int validate_headref(const char *path) { diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index 0720001281..4ea42e00da 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -136,6 +136,15 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' ' GIT_EXTERNAL_DIFF=echo git diff ' +test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' ' + touch file.ext && + git add file.ext && + echo with extension > file.ext && + GIT_EXTERNAL_DIFF=echo git diff file.ext | grep ......_file\.ext && + git update-index --force-remove file.ext && + rm file.ext +' + echo "#!$SHELL_PATH" >fake-diff.sh cat >> fake-diff.sh <<\EOF cat $2 >> crlfed.txt -- cgit v1.3 From 802f9c9cb21321d3ffe7576e01bbe31c51bd4c70 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Mon, 8 Jun 2009 22:34:30 +0200 Subject: diff.c: plug a memory leak in an error path Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- diff.c | 1 + 1 file changed, 1 insertion(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index d24bff1e46..f0b580c150 100644 --- a/diff.c +++ b/diff.c @@ -3590,6 +3590,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec, if (start_command(&child) != 0 || strbuf_read(&buf, child.out, 0) < 0 || finish_command(&child) != 0) { + strbuf_release(&buf); remove_tempfile(); error("error running textconv command '%s'", pgm); return NULL; -- cgit v1.3 From d824cbba02a4061400a0e382f9bd241fbbff34f0 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 27 Jun 2009 17:58:46 +0200 Subject: Convert existing die(..., strerror(errno)) to die_errno() Change calls to die(..., strerror(errno)) to use the new die_errno(). In the process, also make slight style adjustments: at least state _something_ about the function that failed (instead of just printing the pathname), and put paths in single quotes. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- bisect.c | 5 ++--- branch.c | 4 ++-- builtin-apply.c | 6 +++--- builtin-blame.c | 7 +++---- builtin-clone.c | 11 +++++------ builtin-commit-tree.c | 2 +- builtin-commit.c | 23 ++++++++++------------- builtin-config.c | 4 ++-- builtin-diff.c | 2 +- builtin-fast-export.c | 2 +- builtin-fetch--tool.c | 2 +- builtin-fmt-merge-msg.c | 3 +-- builtin-fsck.c | 8 ++++---- builtin-grep.c | 2 +- builtin-merge.c | 8 ++++---- builtin-mv.c | 2 +- builtin-pack-objects.c | 14 +++++--------- builtin-rm.c | 2 +- builtin-send-pack.c | 2 +- builtin-tag.c | 7 +++---- builtin-unpack-objects.c | 2 +- csum-file.c | 5 ++--- daemon.c | 15 +++++++-------- diff.c | 4 ++-- dir.c | 2 +- entry.c | 8 ++++---- fast-import.c | 4 ++-- git.c | 6 +++--- index-pack.c | 21 ++++++++++----------- merge-recursive.c | 6 +++--- pack-refs.c | 7 +++---- pack-write.c | 10 +++++----- pkt-line.c | 4 ++-- read-cache.c | 6 +++--- refs.c | 2 +- run-command.c | 4 ++-- setup.c | 8 ++++---- sha1_file.c | 2 +- shell.c | 2 +- test-sha1.c | 2 +- wrapper.c | 8 ++++---- write_or_die.c | 6 +++--- 42 files changed, 117 insertions(+), 133 deletions(-) (limited to 'diff.c') diff --git a/bisect.c b/bisect.c index c43c120bde..281e16ad19 100644 --- a/bisect.c +++ b/bisect.c @@ -461,7 +461,7 @@ void read_bisect_paths(struct argv_array *array) FILE *fp = fopen(filename, "r"); if (!fp) - die("Could not open file '%s': %s", filename, strerror(errno)); + die_errno("Could not open file '%s'", filename); while (strbuf_getline(&str, fp, '\n') != EOF) { char *quoted; @@ -632,8 +632,7 @@ static void mark_expected_rev(char *bisect_rev_hex) int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (fd < 0) - die("could not create file '%s': %s", - filename, strerror(errno)); + die_errno("could not create file '%s'", filename); bisect_rev_hex[len] = '\n'; write_or_die(fd, bisect_rev_hex, len + 1); diff --git a/branch.c b/branch.c index 62030af4b5..05ef3f5c9c 100644 --- a/branch.c +++ b/branch.c @@ -172,7 +172,7 @@ void create_branch(const char *head, lock = lock_any_ref_for_update(ref.buf, NULL, 0); if (!lock) - die("Failed to lock ref for update: %s.", strerror(errno)); + die_errno("Failed to lock ref for update"); if (reflog) log_all_ref_updates = 1; @@ -188,7 +188,7 @@ void create_branch(const char *head, setup_tracking(name, real_ref, track); if (write_ref_sha1(lock, sha1, msg) < 0) - die("Failed to write ref: %s.", strerror(errno)); + die_errno("Failed to write ref"); strbuf_release(&ref); free(real_ref); diff --git a/builtin-apply.c b/builtin-apply.c index 94ba2bdd5b..6526c087b9 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -280,7 +280,7 @@ static void say_patch_name(FILE *output, const char *pre, static void read_patch_file(struct strbuf *sb, int fd) { if (strbuf_read(sb, fd, 0) < 0) - die("git apply: read returned %s", strerror(errno)); + die_errno("git apply: failed to read"); /* * Make sure that we have some slop in the buffer @@ -2864,7 +2864,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, strbuf_release(&nbuf); if (close(fd) < 0) - die("closing file %s: %s", path, strerror(errno)); + die_errno("closing file '%s'", path); return 0; } @@ -3354,7 +3354,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix) fd = open(arg, O_RDONLY); if (fd < 0) - die("can't open patch '%s': %s", arg, strerror(errno)); + die_errno("can't open patch '%s'", arg); read_stdin = 0; set_default_whitespace_mode(whitespace_option); errs |= apply_patch(fd, arg, options); diff --git a/builtin-blame.c b/builtin-blame.c index 0c2d29a430..7d8fbd5919 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2035,7 +2035,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con contents_from = "standard input"; mode = 0; if (strbuf_read(&buf, 0, 0) < 0) - die("read error %s from stdin", strerror(errno)); + die_errno("failed to read from stdin"); } convert_to_git(path, buf.buf, buf.len, &buf, 0); origin->file.ptr = buf.buf; @@ -2261,8 +2261,7 @@ parse_done: argc = parse_options_end(&ctx); if (revs_file && read_ancestry(revs_file)) - die("reading graft file %s failed: %s", - revs_file, strerror(errno)); + die_errno("reading graft file '%s' failed", revs_file); if (cmd_is_annotate) { output_option |= OUTPUT_ANNOTATE_COMPAT; @@ -2350,7 +2349,7 @@ parse_done: setup_work_tree(); if (!has_string_in_work_tree(path)) - die("cannot stat path %s: %s", path, strerror(errno)); + die_errno("cannot stat path '%s'", path); } setup_revisions(argc, argv, &revs, NULL); diff --git a/builtin-clone.c b/builtin-clone.c index 5c46496a43..5f34414ff7 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -252,8 +252,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) } if (unlink(dest->buf) && errno != ENOENT) - die("failed to unlink %s: %s", - dest->buf, strerror(errno)); + die_errno("failed to unlink '%s'", dest->buf); if (!option_no_hardlinks) { if (!link(src->buf, dest->buf)) continue; @@ -420,11 +419,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix) if (!option_bare) { junk_work_tree = work_tree; if (safe_create_leading_directories_const(work_tree) < 0) - die("could not create leading directories of '%s': %s", - work_tree, strerror(errno)); + die_errno("could not create leading directories of '%s'", + work_tree); if (!dest_exists && mkdir(work_tree, 0755)) - die("could not create work tree dir '%s': %s.", - work_tree, strerror(errno)); + die_errno("could not create work tree dir '%s'.", + work_tree); set_git_work_tree(work_tree); } junk_git_dir = git_dir; diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 0453425c47..6467077731 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -124,7 +124,7 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) } if (strbuf_read(&buffer, 0, 0) < 0) - die("git commit-tree: read returned %s", strerror(errno)); + die_errno("git commit-tree: failed to read"); if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) { printf("%s\n", sha1_to_hex(commit_sha1)); diff --git a/builtin-commit.c b/builtin-commit.c index 41e222d267..88c51bdd3a 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -438,8 +438,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix) hook_arg1 = "message"; } else if (logfile) { if (strbuf_read_file(&sb, logfile, 0) < 0) - die("could not read log file '%s': %s", - logfile, strerror(errno)); + die_errno("could not read log file '%s'", + logfile); hook_arg1 = "message"; } else if (use_message) { buffer = strstr(use_message_buffer, "\n\n"); @@ -450,16 +450,15 @@ static int prepare_to_commit(const char *index_file, const char *prefix) hook_arg2 = use_message; } else if (!stat(git_path("MERGE_MSG"), &statbuf)) { if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0) - die("could not read MERGE_MSG: %s", strerror(errno)); + die_errno("could not read MERGE_MSG"); hook_arg1 = "merge"; } else if (!stat(git_path("SQUASH_MSG"), &statbuf)) { if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0) - die("could not read SQUASH_MSG: %s", strerror(errno)); + die_errno("could not read SQUASH_MSG"); hook_arg1 = "squash"; } else if (template_file && !stat(template_file, &statbuf)) { if (strbuf_read_file(&sb, template_file, 0) < 0) - die("could not read %s: %s", - template_file, strerror(errno)); + die_errno("could not read '%s'", template_file); hook_arg1 = "template"; } @@ -472,8 +471,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix) fp = fopen(git_path(commit_editmsg), "w"); if (fp == NULL) - die("could not open %s: %s", - git_path(commit_editmsg), strerror(errno)); + die_errno("could not open '%s'", git_path(commit_editmsg)); if (cleanup_mode != CLEANUP_NONE) stripspace(&sb, 0); @@ -497,7 +495,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix) } if (fwrite(sb.buf, 1, sb.len, fp) < sb.len) - die("could not write commit template: %s", strerror(errno)); + die_errno("could not write commit template"); strbuf_release(&sb); @@ -940,8 +938,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix) pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next; fp = fopen(git_path("MERGE_HEAD"), "r"); if (fp == NULL) - die("could not open %s for reading: %s", - git_path("MERGE_HEAD"), strerror(errno)); + die_errno("could not open '%s' for reading", + git_path("MERGE_HEAD")); while (strbuf_getline(&m, fp, '\n') != EOF) { unsigned char sha1[20]; if (get_sha1_hex(m.buf, sha1) < 0) @@ -952,8 +950,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix) strbuf_release(&m); if (!stat(git_path("MERGE_MODE"), &statbuf)) { if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0) - die("could not read MERGE_MODE: %s", - strerror(errno)); + die_errno("could not read MERGE_MODE"); if (!strcmp(sb.buf, "no-ff")) allow_fast_forward = 0; } diff --git a/builtin-config.c b/builtin-config.c index 60915f91ca..a2d656edb3 100644 --- a/builtin-config.c +++ b/builtin-config.c @@ -383,8 +383,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix) check_argc(argc, 0, 0); if (git_config(show_all_config, NULL) < 0) { if (config_exclusive_filename) - die("unable to read config file %s: %s", - config_exclusive_filename, strerror(errno)); + die_errno("unable to read config file '%s'", + config_exclusive_filename); else die("error processing config file(s)"); } diff --git a/builtin-diff.c b/builtin-diff.c index d75d69bf57..2e51f408f9 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -70,7 +70,7 @@ static int builtin_diff_b_f(struct rev_info *revs, usage(builtin_diff_usage); if (lstat(path, &st)) - die("'%s': %s", path, strerror(errno)); + die_errno("failed to stat '%s'", path); if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) die("'%s': not a regular file or symlink", path); diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 6cef810312..333d43894a 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -451,7 +451,7 @@ static void import_marks(char *input_file) char line[512]; FILE *f = fopen(input_file, "r"); if (!f) - die("cannot read %s: %s", input_file, strerror(errno)); + die_errno("cannot read '%s'", input_file); while (fgets(line, sizeof(line), f)) { uint32_t mark; diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 29356d25db..3dbdf7a288 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -8,7 +8,7 @@ static char *get_stdin(void) { struct strbuf buf = STRBUF_INIT; if (strbuf_read(&buf, 0, 1024) < 0) { - die("error reading standard input: %s", strerror(errno)); + die_errno("error reading standard input"); } return strbuf_detach(&buf, NULL); } diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index fbf9582e66..1248d5e3a3 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -372,8 +372,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) } if (strbuf_read(&input, fileno(in), 0) < 0) - die("could not read input file %s", strerror(errno)); - + die_errno("could not read input file"); ret = fmt_merge_msg(merge_summary, &input, &output); if (ret) return ret; diff --git a/builtin-fsck.c b/builtin-fsck.c index 7da706cac3..a49dbe14c7 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -225,15 +225,15 @@ static void check_unreachable_object(struct object *obj) &type, &size); if (buf) { if (fwrite(buf, size, 1, f) != 1) - die("Could not write %s: %s", - filename, strerror(errno)); + die_errno("Could not write '%s'", + filename); free(buf); } } else fprintf(f, "%s\n", sha1_to_hex(obj->sha1)); if (fclose(f)) - die("Could not finish %s: %s", - filename, strerror(errno)); + die_errno("Could not finish '%s'", + filename); } return; } diff --git a/builtin-grep.c b/builtin-grep.c index 73fc922c49..e5583686a2 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -594,7 +594,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset) patterns = fopen(arg, "r"); if (!patterns) - die("'%s': %s", arg, strerror(errno)); + die_errno("cannot open '%s'", arg); while (strbuf_getline(&sb, patterns, '\n') == 0) { /* ignore empty line like grep does */ if (sb.len == 0) diff --git a/builtin-merge.c b/builtin-merge.c index 8d101eff0b..436263bc19 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -294,9 +294,9 @@ static void squash_message(void) NULL, NULL, rev.date_mode, 0); } if (write(fd, out.buf, out.len) < 0) - die("Writing SQUASH_MSG: %s", strerror(errno)); + die_errno("Writing SQUASH_MSG"); if (close(fd)) - die("Finishing SQUASH_MSG: %s", strerror(errno)); + die_errno("Finishing SQUASH_MSG"); strbuf_release(&out); } @@ -428,8 +428,8 @@ static void merge_name(const char *remote, struct strbuf *msg) fp = fopen(git_path("FETCH_HEAD"), "r"); if (!fp) - die("could not open %s for reading: %s", - git_path("FETCH_HEAD"), strerror(errno)); + die_errno("could not open '%s' for reading", + git_path("FETCH_HEAD")); strbuf_getline(&line, fp, '\n'); fclose(fp); ptr = strstr(line.buf, "\tnot-for-merge\t"); diff --git a/builtin-mv.c b/builtin-mv.c index 8b81d4b51d..024dfebf7e 100644 --- a/builtin-mv.c +++ b/builtin-mv.c @@ -209,7 +209,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix) printf("Renaming %s to %s\n", src, dst); if (!show_only && mode != INDEX && rename(src, dst) < 0 && !ignore_errors) - die ("renaming %s failed: %s", src, strerror(errno)); + die_errno ("renaming '%s' failed", src); if (mode == WORKING_DIRECTORY) continue; diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 9742b45c4d..60355d41fd 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -536,11 +536,9 @@ static void write_pack_file(void) base_name, sha1_to_hex(sha1)); free_pack_by_name(tmpname); if (adjust_perm(pack_tmp_name, mode)) - die("unable to make temporary pack file readable: %s", - strerror(errno)); + die_errno("unable to make temporary pack file readable"); if (rename(pack_tmp_name, tmpname)) - die("unable to rename temporary pack file: %s", - strerror(errno)); + die_errno("unable to rename temporary pack file"); /* * Packs are runtime accessed in their mtime @@ -566,11 +564,9 @@ static void write_pack_file(void) snprintf(tmpname, sizeof(tmpname), "%s-%s.idx", base_name, sha1_to_hex(sha1)); if (adjust_perm(idx_tmp_name, mode)) - die("unable to make temporary index file readable: %s", - strerror(errno)); + die_errno("unable to make temporary index file readable"); if (rename(idx_tmp_name, tmpname)) - die("unable to rename temporary index file: %s", - strerror(errno)); + die_errno("unable to rename temporary index file"); free(idx_tmp_name); free(pack_tmp_name); @@ -1880,7 +1876,7 @@ static void read_object_list_from_stdin(void) if (!ferror(stdin)) die("fgets returned NULL, not EOF, not error!"); if (errno != EINTR) - die("fgets: %s", strerror(errno)); + die_errno("fgets"); clearerr(stdin); continue; } diff --git a/builtin-rm.c b/builtin-rm.c index 0cc4912718..57975dbcfd 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -257,7 +257,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix) continue; } if (!removed) - die("git rm: %s: %s", path, strerror(errno)); + die_errno("git rm: '%s'", path); } } diff --git a/builtin-send-pack.c b/builtin-send-pack.c index be3b0926de..8fe5ab90b6 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -59,7 +59,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext po.out = fd; po.git_cmd = 1; if (start_command(&po)) - die("git pack-objects failed (%s)", strerror(errno)); + die_errno("git pack-objects failed"); /* * We feed the pack-objects we just spawned with revision diff --git a/builtin-tag.c b/builtin-tag.c index dc3db62811..7b51095c80 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -308,8 +308,7 @@ static void create_tag(const unsigned char *object, const char *tag, path = git_pathdup("TAG_EDITMSG"); fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); if (fd < 0) - die("could not create file '%s': %s", - path, strerror(errno)); + die_errno("could not create file '%s'", path); if (!is_null_sha1(prev)) write_tag_body(fd, prev); @@ -446,8 +445,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) die("cannot read %s", msgfile); } else { if (strbuf_read_file(&buf, msgfile, 1024) < 0) - die("could not open or read '%s': %s", - msgfile, strerror(errno)); + die_errno("could not open or read '%s'", + msgfile); } } } diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index 9a773239ca..41e9ac526c 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -68,7 +68,7 @@ static void *fill(int min) if (ret <= 0) { if (!ret) die("early EOF"); - die("read error on input: %s", strerror(errno)); + die_errno("read error on input"); } len += ret; } while (len < min); diff --git a/csum-file.c b/csum-file.c index 2ddb12a0b7..4d50cc5ce1 100644 --- a/csum-file.c +++ b/csum-file.c @@ -26,7 +26,7 @@ static void flush(struct sha1file *f, void * buf, unsigned int count) } if (!ret) die("sha1 file '%s' write error. Out of diskspace", f->name); - die("sha1 file '%s' write error (%s)", f->name, strerror(errno)); + die_errno("sha1 file '%s' write error", f->name); } } @@ -55,8 +55,7 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags) if (flags & CSUM_FSYNC) fsync_or_die(f->fd, f->name); if (close(f->fd)) - die("%s: sha1 file error on close (%s)", - f->name, strerror(errno)); + die_errno("%s: sha1 file error on close", f->name); fd = 0; } else fd = f->fd; diff --git a/daemon.c b/daemon.c index b2babcc076..0c2f32635a 100644 --- a/daemon.c +++ b/daemon.c @@ -862,7 +862,7 @@ static int service_loop(int socknum, int *socklist) case ECONNABORTED: continue; default: - die("accept returned %s", strerror(errno)); + die_errno("accept returned"); } } handle(incoming, (struct sockaddr *)&ss, sslen); @@ -878,7 +878,7 @@ static void sanitize_stdfds(void) while (fd != -1 && fd < 2) fd = dup(fd); if (fd == -1) - die("open /dev/null or dup failed: %s", strerror(errno)); + die_errno("open /dev/null or dup failed"); if (fd > 2) close(fd); } @@ -889,12 +889,12 @@ static void daemonize(void) case 0: break; case -1: - die("fork failed: %s", strerror(errno)); + die_errno("fork failed"); default: exit(0); } if (setsid() == -1) - die("setsid failed: %s", strerror(errno)); + die_errno("setsid failed"); close(0); close(1); close(2); @@ -905,9 +905,9 @@ static void store_pid(const char *path) { FILE *f = fopen(path, "w"); if (!f) - die("cannot open pid file %s: %s", path, strerror(errno)); + die_errno("cannot open pid file '%s'", path); if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0) - die("failed to write pid file %s: %s", path, strerror(errno)); + die_errno("failed to write pid file '%s'", path); } static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid) @@ -1107,8 +1107,7 @@ int main(int argc, char **argv) socklen_t slen = sizeof(ss); if (!freopen("/dev/null", "w", stderr)) - die("failed to redirect stderr to /dev/null: %s", - strerror(errno)); + die_errno("failed to redirect stderr to /dev/null"); if (getpeername(0, peer, &slen)) peer = NULL; diff --git a/diff.c b/diff.c index 4d0a5b9ae6..48043f5bdb 100644 --- a/diff.c +++ b/diff.c @@ -1975,7 +1975,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf, strlen(base) + 1); if (fd < 0) - die("unable to create temp-file: %s", strerror(errno)); + die_errno("unable to create temp-file"); if (convert_to_working_tree(path, (const char *)blob, (size_t)size, &buf)) { blob = buf.buf; @@ -2021,7 +2021,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (lstat(name, &st) < 0) { if (errno == ENOENT) goto not_a_valid_file; - die("stat(%s): %s", name, strerror(errno)); + die_errno("stat(%s)", name); } if (S_ISLNK(st.st_mode)) { struct strbuf sb = STRBUF_INIT; diff --git a/dir.c b/dir.c index bbfcb566e6..74b3bbf6fd 100644 --- a/dir.c +++ b/dir.c @@ -759,7 +759,7 @@ char *get_relative_cwd(char *buffer, int size, const char *dir) if (!dir) return NULL; if (!getcwd(buffer, size)) - die("can't find the current directory: %s", strerror(errno)); + die_errno("can't find the current directory"); if (!is_absolute_path(dir)) dir = make_absolute_path(dir); diff --git a/entry.c b/entry.c index cc841edf90..8ec880bdbd 100644 --- a/entry.c +++ b/entry.c @@ -51,7 +51,7 @@ static void remove_subtree(const char *path) char *name; if (!dir) - die("cannot opendir %s (%s)", path, strerror(errno)); + die_errno("cannot opendir '%s'", path); strcpy(pathbuf, path); name = pathbuf + strlen(path); *name++ = '/'; @@ -61,15 +61,15 @@ static void remove_subtree(const char *path) continue; strcpy(name, de->d_name); if (lstat(pathbuf, &st)) - die("cannot lstat %s (%s)", pathbuf, strerror(errno)); + die_errno("cannot lstat '%s'", pathbuf); if (S_ISDIR(st.st_mode)) remove_subtree(pathbuf); else if (unlink(pathbuf)) - die("cannot unlink %s (%s)", pathbuf, strerror(errno)); + die_errno("cannot unlink '%s'", pathbuf); } closedir(dir); if (rmdir(path)) - die("cannot rmdir %s (%s)", path, strerror(errno)); + die_errno("cannot rmdir '%s'", path); } static int create_file(const char *path, unsigned int mode) diff --git a/fast-import.c b/fast-import.c index a2a24588a9..d31a4e8217 100644 --- a/fast-import.c +++ b/fast-import.c @@ -2342,7 +2342,7 @@ static void import_marks(const char *input_file) char line[512]; FILE *f = fopen(input_file, "r"); if (!f) - die("cannot read %s: %s", input_file, strerror(errno)); + die_errno("cannot read '%s'", input_file); while (fgets(line, sizeof(line), f)) { uintmax_t mark; char *end; @@ -2448,7 +2448,7 @@ int main(int argc, const char **argv) fclose(pack_edges); pack_edges = fopen(a + 20, "a"); if (!pack_edges) - die("Cannot open %s: %s", a + 20, strerror(errno)); + die_errno("Cannot open '%s'", a + 20); } else if (!strcmp(a, "--force")) force_update = 1; else if (!strcmp(a, "--quiet")) diff --git a/git.c b/git.c index 7d7f949f0d..b035676e93 100644 --- a/git.c +++ b/git.c @@ -200,7 +200,7 @@ static int handle_alias(int *argcp, const char ***argv) } if (subdir && chdir(subdir)) - die("Cannot change to %s: %s", subdir, strerror(errno)); + die_errno("Cannot change to '%s'", subdir); errno = saved_errno; @@ -257,11 +257,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) /* Check for ENOSPC and EIO errors.. */ if (fflush(stdout)) - die("write failure on standard output: %s", strerror(errno)); + die_errno("write failure on standard output"); if (ferror(stdout)) die("unknown write failure on standard output"); if (fclose(stdout)) - die("close failed on standard output: %s", strerror(errno)); + die_errno("close failed on standard output"); return 0; } diff --git a/index-pack.c b/index-pack.c index 6e93ee6af6..cf6446fc43 100644 --- a/index-pack.c +++ b/index-pack.c @@ -143,7 +143,7 @@ static void *fill(int min) if (ret <= 0) { if (!ret) die("early EOF"); - die("read error on input: %s", strerror(errno)); + die_errno("read error on input"); } input_len += ret; if (from_stdin) @@ -178,13 +178,12 @@ static char *open_pack_file(char *pack_name) } else output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600); if (output_fd < 0) - die("unable to create %s: %s", pack_name, strerror(errno)); + die_errno("unable to create '%s'", pack_name); pack_fd = output_fd; } else { input_fd = open(pack_name, O_RDONLY); if (input_fd < 0) - die("cannot open packfile '%s': %s", - pack_name, strerror(errno)); + die_errno("cannot open packfile '%s'", pack_name); output_fd = -1; pack_fd = input_fd; } @@ -370,7 +369,7 @@ static void *get_data_from_pack(struct object_entry *obj) do { ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy); if (n < 0) - die("cannot pread pack file: %s", strerror(errno)); + die_errno("cannot pread pack file"); if (!n) die("premature end of pack file, %lu bytes missing", len - rdy); @@ -631,7 +630,7 @@ static void parse_pack_objects(unsigned char *sha1) /* If input_fd is a file, we should have reached its end now. */ if (fstat(input_fd, &st)) - die("cannot fstat packfile: %s", strerror(errno)); + die_errno("cannot fstat packfile"); if (S_ISREG(st.st_mode) && lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size) die("pack has junk at the end"); @@ -788,7 +787,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name, fsync_or_die(output_fd, curr_pack_name); err = close(output_fd); if (err) - die("error while closing pack file: %s", strerror(errno)); + die_errno("error while closing pack file"); } if (keep_msg) { @@ -801,16 +800,16 @@ static void final(const char *final_pack_name, const char *curr_pack_name, if (keep_fd < 0) { if (errno != EEXIST) - die("cannot write keep file '%s' (%s)", - keep_name, strerror(errno)); + die_errno("cannot write keep file '%s'", + keep_name); } else { if (keep_msg_len > 0) { write_or_die(keep_fd, keep_msg, keep_msg_len); write_or_die(keep_fd, "\n", 1); } if (close(keep_fd) != 0) - die("cannot close written keep file '%s' (%s)", - keep_name, strerror(errno)); + die_errno("cannot close written keep file '%s'", + keep_name); report = "keep"; } } diff --git a/merge-recursive.c b/merge-recursive.c index f5df9b961b..5d9140b8d6 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -438,7 +438,7 @@ static void flush_buffer(int fd, const char *buf, unsigned long size) /* Ignore epipe */ if (errno == EPIPE) break; - die("merge-recursive: %s", strerror(errno)); + die_errno("merge-recursive"); } else if (!ret) { die("merge-recursive: disk full?"); } @@ -554,7 +554,7 @@ static void update_file_flags(struct merge_options *o, mode = 0666; fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); if (fd < 0) - die("failed to open %s: %s", path, strerror(errno)); + die_errno("failed to open '%s'", path); flush_buffer(fd, buf, size); close(fd); } else if (S_ISLNK(mode)) { @@ -562,7 +562,7 @@ static void update_file_flags(struct merge_options *o, safe_create_leading_directories_const(path); unlink(path); if (symlink(lnk, path)) - die("failed to symlink %s: %s", path, strerror(errno)); + die_errno("failed to symlink '%s'", path); free(lnk); } else die("do not know what to do with %06o %s '%s'", diff --git a/pack-refs.c b/pack-refs.c index 301fc60eae..7f43f8ac33 100644 --- a/pack-refs.c +++ b/pack-refs.c @@ -93,8 +93,7 @@ int pack_refs(unsigned int flags) LOCK_DIE_ON_ERROR); cbdata.refs_file = fdopen(fd, "w"); if (!cbdata.refs_file) - die("unable to create ref-pack file structure (%s)", - strerror(errno)); + die_errno("unable to create ref-pack file structure"); /* perhaps other traits later as well */ fprintf(cbdata.refs_file, "# pack-refs with: peeled \n"); @@ -103,7 +102,7 @@ int pack_refs(unsigned int flags) if (ferror(cbdata.refs_file)) die("failed to write ref-pack file"); if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file)) - die("failed to write ref-pack file (%s)", strerror(errno)); + die_errno("failed to write ref-pack file"); /* * Since the lock file was fdopen()'ed and then fclose()'ed above, * assign -1 to the lock file descriptor so that commit_lock_file() @@ -111,7 +110,7 @@ int pack_refs(unsigned int flags) */ packed.fd = -1; if (commit_lock_file(&packed) < 0) - die("unable to overwrite old ref-pack file (%s)", strerror(errno)); + die_errno("unable to overwrite old ref-pack file"); if (cbdata.flags & PACK_REFS_PRUNE) prune_refs(cbdata.ref_to_prune); return 0; diff --git a/pack-write.c b/pack-write.c index 7053538f4c..741efcd93b 100644 --- a/pack-write.c +++ b/pack-write.c @@ -51,7 +51,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects, fd = open(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600); } if (fd < 0) - die("unable to create %s: %s", index_name, strerror(errno)); + die_errno("unable to create '%s'", index_name); f = sha1fd(fd, index_name); /* if last object's offset is >= 2^31 we should use index V2 */ @@ -174,11 +174,11 @@ void fixup_pack_header_footer(int pack_fd, git_SHA1_Init(&new_sha1_ctx); if (lseek(pack_fd, 0, SEEK_SET) != 0) - die("Failed seeking to start of %s: %s", pack_name, strerror(errno)); + die_errno("Failed seeking to start of '%s'", pack_name); if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - die("Unable to reread header of %s: %s", pack_name, strerror(errno)); + die_errno("Unable to reread header of '%s'", pack_name); if (lseek(pack_fd, 0, SEEK_SET) != 0) - die("Failed seeking to start of %s: %s", pack_name, strerror(errno)); + die_errno("Failed seeking to start of '%s'", pack_name); git_SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr)); hdr.hdr_entries = htonl(object_count); git_SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr)); @@ -195,7 +195,7 @@ void fixup_pack_header_footer(int pack_fd, if (!n) break; if (n < 0) - die("Failed to checksum %s: %s", pack_name, strerror(errno)); + die_errno("Failed to checksum '%s'", pack_name); git_SHA1_Update(&new_sha1_ctx, buf, n); aligned_sz -= n; diff --git a/pkt-line.c b/pkt-line.c index f5d00863a6..b691abebd7 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -28,7 +28,7 @@ ssize_t safe_write(int fd, const void *buf, ssize_t n) } if (!ret) die("write error (disk full?)"); - die("write error (%s)", strerror(errno)); + die_errno("write error"); } return nn; } @@ -67,7 +67,7 @@ static void safe_read(int fd, void *buffer, unsigned size) { ssize_t ret = read_in_full(fd, buffer, size); if (ret < 0) - die("read error (%s)", strerror(errno)); + die_errno("read error"); else if (ret < size) die("The remote end hung up unexpectedly"); } diff --git a/read-cache.c b/read-cache.c index 3f587110cb..f76b5bb2e1 100644 --- a/read-cache.c +++ b/read-cache.c @@ -638,7 +638,7 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags) { struct stat st; if (lstat(path, &st)) - die("%s: unable to stat (%s)", path, strerror(errno)); + die_errno("unable to stat '%s'", path); return add_to_index(istate, path, &st, flags); } @@ -1251,11 +1251,11 @@ int read_index_from(struct index_state *istate, const char *path) if (fd < 0) { if (errno == ENOENT) return 0; - die("index file open failed (%s)", strerror(errno)); + die_errno("index file open failed"); } if (fstat(fd, &st)) - die("cannot stat the open index (%s)", strerror(errno)); + die_errno("cannot stat the open index"); errno = EINVAL; mmap_size = xsize_t(st.st_size); diff --git a/refs.c b/refs.c index 24438c652f..dffe395a97 100644 --- a/refs.c +++ b/refs.c @@ -1418,7 +1418,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char * logfile = git_path("logs/%s", ref); logfd = open(logfile, O_RDONLY, 0); if (logfd < 0) - die("Unable to read log %s: %s", logfile, strerror(errno)); + die_errno("Unable to read log '%s'", logfile); fstat(logfd, &st); if (!st.st_size) die("Log %s is empty.", logfile); diff --git a/run-command.c b/run-command.c index eb2efc3307..ff3d8e2d8b 100644 --- a/run-command.c +++ b/run-command.c @@ -101,8 +101,8 @@ int start_command(struct child_process *cmd) } if (cmd->dir && chdir(cmd->dir)) - die("exec %s: cd to %s failed (%s)", cmd->argv[0], - cmd->dir, strerror(errno)); + die_errno("exec '%s': cd to '%s' failed", cmd->argv[0], + cmd->dir); if (cmd->env) { for (; *cmd->env; cmd->env++) { if (strchr(*cmd->env, '=')) diff --git a/setup.c b/setup.c index ebd60de9ce..4d27f28c8f 100644 --- a/setup.c +++ b/setup.c @@ -81,7 +81,7 @@ void verify_filename(const char *prefix, const char *arg) if (errno == ENOENT) die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" "Use '--' to separate paths from revisions", arg); - die("'%s': %s", arg, strerror(errno)); + die_errno("failed to stat '%s'", arg); } /* @@ -103,7 +103,7 @@ void verify_non_filename(const char *prefix, const char *arg) die("ambiguous argument '%s': both revision and filename\n" "Use '--' to separate filenames from revisions", arg); if (errno != ENOENT && errno != ENOTDIR) - die("'%s': %s", arg, strerror(errno)); + die_errno("failed to stat '%s'", arg); } const char **get_pathspec(const char *prefix, const char **pathspec) @@ -257,7 +257,7 @@ const char *read_gitfile_gently(const char *path) return NULL; fd = open(path, O_RDONLY); if (fd < 0) - die("Error opening %s: %s", path, strerror(errno)); + die_errno("Error opening '%s'", path); buf = xmalloc(st.st_size + 1); len = read_in_full(fd, buf, st.st_size); close(fd); @@ -389,7 +389,7 @@ const char *setup_git_directory_gently(int *nongit_ok) die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT); } if (chdir("..")) - die("Cannot change to %s/..: %s", cwd, strerror(errno)); + die_errno("Cannot change to '%s/..'", cwd); } inside_git_dir = 0; diff --git a/sha1_file.c b/sha1_file.c index e73cd4fc0b..1964a6d39b 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2287,7 +2287,7 @@ static void close_sha1_file(int fd) if (fsync_object_files) fsync_or_die(fd, "sha1 file"); if (close(fd) != 0) - die("error when closing sha1 file (%s)", strerror(errno)); + die_errno("error when closing sha1 file"); } /* Size of directory component, including the ending '/' */ diff --git a/shell.c b/shell.c index b968be79f4..e4864e04da 100644 --- a/shell.c +++ b/shell.c @@ -60,7 +60,7 @@ int main(int argc, char **argv) while (devnull_fd >= 0 && devnull_fd <= 2) devnull_fd = dup(devnull_fd); if (devnull_fd == -1) - die("opening /dev/null failed (%s)", strerror(errno)); + die_errno("opening /dev/null failed"); close (devnull_fd); /* diff --git a/test-sha1.c b/test-sha1.c index 9b98d07c78..80daba980e 100644 --- a/test-sha1.c +++ b/test-sha1.c @@ -32,7 +32,7 @@ int main(int ac, char **av) if (sz == 0) break; if (sz < 0) - die("test-sha1: %s", strerror(errno)); + die_errno("test-sha1"); this_sz += sz; cp += sz; room -= sz; diff --git a/wrapper.c b/wrapper.c index 7eb3218ee9..c9be1400c0 100644 --- a/wrapper.c +++ b/wrapper.c @@ -96,7 +96,7 @@ void *xmmap(void *start, size_t length, release_pack_memory(length, fd); ret = mmap(start, length, prot, flags, fd, offset); if (ret == MAP_FAILED) - die("Out of memory? mmap failed: %s", strerror(errno)); + die_errno("Out of memory? mmap failed"); } return ret; } @@ -175,7 +175,7 @@ int xdup(int fd) { int ret = dup(fd); if (ret < 0) - die("dup failed: %s", strerror(errno)); + die_errno("dup failed"); return ret; } @@ -183,7 +183,7 @@ FILE *xfdopen(int fd, const char *mode) { FILE *stream = fdopen(fd, mode); if (stream == NULL) - die("Out of memory? fdopen failed: %s", strerror(errno)); + die_errno("Out of memory? fdopen failed"); return stream; } @@ -193,7 +193,7 @@ int xmkstemp(char *template) fd = mkstemp(template); if (fd < 0) - die("Unable to create temporary file: %s", strerror(errno)); + die_errno("Unable to create temporary file"); return fd; } diff --git a/write_or_die.c b/write_or_die.c index 4c29255df1..d45b536021 100644 --- a/write_or_die.c +++ b/write_or_die.c @@ -41,14 +41,14 @@ void maybe_flush_or_die(FILE *f, const char *desc) */ if (errno == EPIPE || errno == EINVAL) exit(0); - die("write failure on %s: %s", desc, strerror(errno)); + die_errno("write failure on '%s'", desc); } } void fsync_or_die(int fd, const char *msg) { if (fsync(fd) < 0) { - die("%s: fsync error (%s)", msg, strerror(errno)); + die_errno("fsync error on '%s'", msg); } } @@ -57,7 +57,7 @@ void write_or_die(int fd, const void *buf, size_t count) if (write_in_full(fd, buf, count) < 0) { if (errno == EPIPE) exit(0); - die("write error (%s)", strerror(errno)); + die_errno("write error"); } } -- cgit v1.3 From 0721c314a5c8fddc877140ab5a333c42c62f780d Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Sat, 27 Jun 2009 17:58:47 +0200 Subject: Use die_errno() instead of die() when checking syscalls Lots of die() calls did not actually report the kind of error, which can leave the user confused as to the real problem. Use die_errno() where we check a system/library call that sets errno on failure, or one of the following that wrap such calls: Function Passes on error from -------- -------------------- odb_pack_keep open read_ancestry fopen read_in_full xread strbuf_read xread strbuf_read_file open or strbuf_read_file strbuf_readlink readlink write_in_full xwrite Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- abspath.c | 12 ++++++------ builtin-add.c | 2 +- builtin-apply.c | 6 +++--- builtin-archive.c | 4 ++-- builtin-blame.c | 8 ++++---- builtin-clone.c | 10 +++++----- builtin-commit.c | 5 +++-- builtin-fast-export.c | 2 +- builtin-fmt-merge-msg.c | 2 +- builtin-fsck.c | 2 +- builtin-init-db.c | 21 +++++++++++---------- builtin-log.c | 4 ++-- builtin-mailsplit.c | 6 +++--- builtin-merge.c | 21 ++++++++++++--------- builtin-rev-parse.c | 2 +- builtin-revert.c | 2 +- builtin-stripspace.c | 2 +- builtin-tag.c | 2 +- builtin-tar-tree.c | 2 +- combine-diff.c | 2 +- diff.c | 6 +++--- entry.c | 2 +- fast-import.c | 4 ++-- hash-object.c | 2 +- ll-merge.c | 2 +- mktag.c | 2 +- read-cache.c | 2 +- setup.c | 10 +++++----- transport.c | 4 ++-- unpack-file.c | 2 +- 30 files changed, 79 insertions(+), 74 deletions(-) (limited to 'diff.c') diff --git a/abspath.c b/abspath.c index 649f34f833..4bee0ba1ec 100644 --- a/abspath.c +++ b/abspath.c @@ -41,13 +41,13 @@ const char *make_absolute_path(const char *path) if (*buf) { if (!*cwd && !getcwd(cwd, sizeof(cwd))) - die ("Could not get current working directory"); + die_errno ("Could not get current working directory"); if (chdir(buf)) - die ("Could not switch to '%s'", buf); + die_errno ("Could not switch to '%s'", buf); } if (!getcwd(buf, PATH_MAX)) - die ("Could not get current working directory"); + die_errno ("Could not get current working directory"); if (last_elem) { int len = strlen(buf); @@ -63,7 +63,7 @@ const char *make_absolute_path(const char *path) if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) { len = readlink(buf, next_buf, PATH_MAX); if (len < 0) - die ("Invalid symlink: %s", buf); + die_errno ("Invalid symlink '%s'", buf); if (PATH_MAX <= len) die("symbolic link too long: %s", buf); next_buf[len] = '\0'; @@ -75,7 +75,7 @@ const char *make_absolute_path(const char *path) } if (*cwd && chdir(cwd)) - die ("Could not change back to '%s'", cwd); + die_errno ("Could not change back to '%s'", cwd); return buf; } @@ -109,7 +109,7 @@ const char *make_nonrelative_path(const char *path) } else { const char *cwd = get_pwd_cwd(); if (!cwd) - die("Cannot determine the current working directory"); + die_errno("Cannot determine the current working directory"); if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX) die("Too long path: %.*s", 60, path); } diff --git a/builtin-add.c b/builtin-add.c index c1b229a9d8..8f651c137a 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -220,7 +220,7 @@ int edit_patch(int argc, const char **argv, const char *prefix) launch_editor(file, NULL, NULL); if (stat(file, &st)) - die("Could not stat '%s'", file); + die_errno("Could not stat '%s'", file); if (!st.st_size) die("Empty patch. Aborted."); diff --git a/builtin-apply.c b/builtin-apply.c index 6526c087b9..dbc7f2165d 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2823,8 +2823,8 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned } else { if (!cached) { if (lstat(path, &st) < 0) - die("unable to stat newly created file %s", - path); + die_errno("unable to stat newly created file '%s'", + path); fill_stat_cache_info(ce, &st); } if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0) @@ -2913,7 +2913,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned ++nr; } } - die("unable to write file %s mode %o", path, mode); + die_errno("unable to write file '%s' mode %o", path, mode); } static void create_file(struct patch *patch) diff --git a/builtin-archive.c b/builtin-archive.c index 3c5a5a7822..f9a4bea41e 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -13,10 +13,10 @@ static void create_output_file(const char *output_file) { int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666); if (output_fd < 0) - die("could not create archive file: %s ", output_file); + die_errno("could not create archive file '%s'", output_file); if (output_fd != 1) { if (dup2(output_fd, 1) < 0) - die("could not redirect output"); + die_errno("could not redirect output"); else close(output_fd); } diff --git a/builtin-blame.c b/builtin-blame.c index 7d8fbd5919..fd6ca51eeb 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2008,23 +2008,23 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con if (contents_from) { if (stat(contents_from, &st) < 0) - die("Cannot stat %s", contents_from); + die_errno("Cannot stat '%s'", contents_from); read_from = contents_from; } else { if (lstat(path, &st) < 0) - die("Cannot lstat %s", path); + die_errno("Cannot lstat '%s'", path); read_from = path; } mode = canon_mode(st.st_mode); switch (st.st_mode & S_IFMT) { case S_IFREG: if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size) - die("cannot open or read %s", read_from); + die_errno("cannot open or read '%s'", read_from); break; case S_IFLNK: if (strbuf_readlink(&buf, read_from, st.st_size) < 0) - die("cannot readlink %s", read_from); + die_errno("cannot readlink '%s'", read_from); break; default: die("unsupported file type %s", read_from); diff --git a/builtin-clone.c b/builtin-clone.c index 5f34414ff7..d2b0757e53 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -220,13 +220,13 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) dir = opendir(src->buf); if (!dir) - die("failed to open %s", src->buf); + die_errno("failed to open '%s'", src->buf); if (mkdir(dest->buf, 0777)) { if (errno != EEXIST) - die("failed to create directory %s", dest->buf); + die_errno("failed to create directory '%s'", dest->buf); else if (stat(dest->buf, &buf)) - die("failed to stat %s", dest->buf); + die_errno("failed to stat '%s'", dest->buf); else if (!S_ISDIR(buf.st_mode)) die("%s exists and is not a directory", dest->buf); } @@ -257,11 +257,11 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest) if (!link(src->buf, dest->buf)) continue; if (option_local) - die("failed to create link %s", dest->buf); + die_errno("failed to create link '%s'", dest->buf); option_no_hardlinks = 1; } if (copy_file(dest->buf, src->buf, 0666)) - die("failed to copy file to %s", dest->buf); + die_errno("failed to copy file to '%s'", dest->buf); } closedir(dir); } diff --git a/builtin-commit.c b/builtin-commit.c index 88c51bdd3a..4bcce06fbf 100644 --- a/builtin-commit.c +++ b/builtin-commit.c @@ -434,7 +434,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix) if (isatty(0)) fprintf(stderr, "(reading log message from standard input)\n"); if (strbuf_read(&sb, 0, 0) < 0) - die("could not read log from standard input"); + die_errno("could not read log from standard input"); hook_arg1 = "message"; } else if (logfile) { if (strbuf_read_file(&sb, logfile, 0) < 0) @@ -964,8 +964,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix) /* Finally, get the commit message */ strbuf_reset(&sb); if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) { + int saved_errno = errno; rollback_index_files(); - die("could not read commit message"); + die("could not read commit message: %s", strerror(saved_errno)); } /* Truncate the message just before the diff, if any. */ diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 333d43894a..9a8a6fc6b1 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -119,7 +119,7 @@ static void handle_object(const unsigned char *sha1) printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size); if (size && fwrite(buf, size, 1, stdout) != 1) - die ("Could not write blob %s", sha1_to_hex(sha1)); + die_errno ("Could not write blob '%s'", sha1_to_hex(sha1)); printf("\n"); show_progress(); diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c index 1248d5e3a3..9d524000b5 100644 --- a/builtin-fmt-merge-msg.c +++ b/builtin-fmt-merge-msg.c @@ -368,7 +368,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix) if (inpath && strcmp(inpath, "-")) { in = fopen(inpath, "r"); if (!in) - die("cannot open %s", inpath); + die_errno("cannot open '%s'", inpath); } if (strbuf_read(&input, fileno(in), 0) < 0) diff --git a/builtin-fsck.c b/builtin-fsck.c index a49dbe14c7..d0f48cdd2a 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -217,7 +217,7 @@ static void check_unreachable_object(struct object *obj) return; } if (!(f = fopen(filename, "w"))) - die("Could not open %s", filename); + die_errno("Could not open '%s'", filename); if (obj->type == OBJ_BLOB) { enum object_type type; unsigned long size; diff --git a/builtin-init-db.c b/builtin-init-db.c index d1fa12a59e..4a5600631c 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -61,20 +61,20 @@ static void copy_templates_1(char *path, int baselen, memcpy(template + template_baselen, de->d_name, namelen+1); if (lstat(path, &st_git)) { if (errno != ENOENT) - die("cannot stat %s", path); + die_errno("cannot stat '%s'", path); } else exists = 1; if (lstat(template, &st_template)) - die("cannot stat template %s", template); + die_errno("cannot stat template '%s'", template); if (S_ISDIR(st_template.st_mode)) { DIR *subdir = opendir(template); int baselen_sub = baselen + namelen; int template_baselen_sub = template_baselen + namelen; if (!subdir) - die("cannot opendir %s", template); + die_errno("cannot opendir '%s'", template); path[baselen_sub++] = template[template_baselen_sub++] = '/'; path[baselen_sub] = @@ -91,16 +91,17 @@ static void copy_templates_1(char *path, int baselen, int len; len = readlink(template, lnk, sizeof(lnk)); if (len < 0) - die("cannot readlink %s", template); + die_errno("cannot readlink '%s'", template); if (sizeof(lnk) <= len) die("insanely long symlink %s", template); lnk[len] = 0; if (symlink(lnk, path)) - die("cannot symlink %s %s", lnk, path); + die_errno("cannot symlink '%s' '%s'", lnk, path); } else if (S_ISREG(st_template.st_mode)) { if (copy_file(path, template, st_template.st_mode)) - die("cannot copy %s to %s", template, path); + die_errno("cannot copy '%s' to '%s'", template, + path); } else error("ignoring template %s", template); @@ -350,7 +351,7 @@ static int guess_repository_type(const char *git_dir) if (!strcmp(".", git_dir)) return 1; if (!getcwd(cwd, sizeof(cwd))) - die("cannot tell cwd"); + die_errno("cannot tell cwd"); if (!strcmp(git_dir, cwd)) return 1; /* @@ -440,11 +441,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) if (!git_work_tree_cfg) { git_work_tree_cfg = xcalloc(PATH_MAX, 1); if (!getcwd(git_work_tree_cfg, PATH_MAX)) - die ("Cannot access current working directory."); + die_errno ("Cannot access current working directory"); } if (access(get_git_work_tree(), X_OK)) - die ("Cannot access work tree '%s'", - get_git_work_tree()); + die_errno ("Cannot access work tree '%s'", + get_git_work_tree()); } set_git_dir(make_absolute_path(git_dir)); diff --git a/builtin-log.c b/builtin-log.c index 0d34050556..750957cfa9 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1013,8 +1013,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (use_stdout) die("standard output, or directory, which one?"); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) - die("Could not create directory %s", - output_directory); + die_errno("Could not create directory '%s'", + output_directory); } if (rev.pending.nr == 1) { diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c index 71f3b3b874..ad5f6b593d 100644 --- a/builtin-mailsplit.c +++ b/builtin-mailsplit.c @@ -81,7 +81,7 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) - die("cannot open output file %s", name); + die_errno("cannot open output file '%s'", name); output = fdopen(fd, "w"); /* Copy it out, while searching for a line that begins with @@ -91,7 +91,7 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) int is_partial = len && buf[len-1] != '\n'; if (fwrite(buf, 1, len, output) != len) - die("cannot write output"); + die_errno("cannot write output"); len = read_line_with_nul(buf, sizeof(buf), mbox); if (len == 0) { @@ -99,7 +99,7 @@ static int split_one(FILE *mbox, const char *name, int allow_bare) status = 1; break; } - die("cannot read mbox"); + die_errno("cannot read mbox"); } if (!is_partial && !is_bare && is_from_line(buf, len)) break; /* done with one message */ diff --git a/builtin-merge.c b/builtin-merge.c index 436263bc19..82335b09ed 100644 --- a/builtin-merge.c +++ b/builtin-merge.c @@ -268,7 +268,7 @@ static void squash_message(void) printf("Squash commit -- not updating HEAD\n"); fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die("Could not write to %s", git_path("SQUASH_MSG")); + die_errno("Could not write to '%s'", git_path("SQUASH_MSG")); init_revisions(&rev, NULL); rev.ignore_merges = 1; @@ -764,7 +764,8 @@ static int suggest_conflicts(void) fp = fopen(git_path("MERGE_MSG"), "a"); if (!fp) - die("Could not open %s for writing", git_path("MERGE_MSG")); + die_errno("Could not open '%s' for writing", + git_path("MERGE_MSG")); fprintf(fp, "\nConflicts:\n"); for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; @@ -1186,27 +1187,29 @@ int cmd_merge(int argc, const char **argv, const char *prefix) sha1_to_hex(j->item->object.sha1)); fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die("Could open %s for writing", - git_path("MERGE_HEAD")); + die_errno("Could not open '%s' for writing", + git_path("MERGE_HEAD")); if (write_in_full(fd, buf.buf, buf.len) != buf.len) - die("Could not write to %s", git_path("MERGE_HEAD")); + die_errno("Could not write to '%s'", git_path("MERGE_HEAD")); close(fd); strbuf_addch(&merge_msg, '\n'); fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666); if (fd < 0) - die("Could open %s for writing", git_path("MERGE_MSG")); + die_errno("Could not open '%s' for writing", + git_path("MERGE_MSG")); if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len) - die("Could not write to %s", git_path("MERGE_MSG")); + die_errno("Could not write to '%s'", git_path("MERGE_MSG")); close(fd); fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) - die("Could open %s for writing", git_path("MERGE_MODE")); + die_errno("Could not open '%s' for writing", + git_path("MERGE_MODE")); strbuf_reset(&buf); if (!allow_fast_forward) strbuf_addf(&buf, "no-ff"); if (write_in_full(fd, buf.buf, buf.len) != buf.len) - die("Could not write to %s", git_path("MERGE_MODE")); + die_errno("Could not write to '%s'", git_path("MERGE_MODE")); close(fd); } diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 112d622cda..da26dbc020 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -592,7 +592,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!getcwd(cwd, PATH_MAX)) - die("unable to get current working directory"); + die_errno("unable to get current working directory"); printf("%s/.git\n", cwd); continue; } diff --git a/builtin-revert.c b/builtin-revert.c index c87115af30..151aa6a981 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -135,7 +135,7 @@ static void add_to_msg(const char *string) { int len = strlen(string); if (write_in_full(msg_fd, string, len) < 0) - die ("Could not write to MERGE_MSG"); + die_errno ("Could not write to MERGE_MSG"); } static void add_message_to_msg(const char *message) diff --git a/builtin-stripspace.c b/builtin-stripspace.c index d6e3896c00..1fd2205d53 100644 --- a/builtin-stripspace.c +++ b/builtin-stripspace.c @@ -78,7 +78,7 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix) strip_comments = 1; if (strbuf_read(&buf, 0, 1024) < 0) - die("could not read the input"); + die_errno("could not read the input"); stripspace(&buf, strip_comments); diff --git a/builtin-tag.c b/builtin-tag.c index 7b51095c80..165bec3069 100644 --- a/builtin-tag.c +++ b/builtin-tag.c @@ -442,7 +442,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) else { if (!strcmp(msgfile, "-")) { if (strbuf_read(&buf, 0, 1024) < 0) - die("cannot read %s", msgfile); + die_errno("cannot read '%s'", msgfile); } else { if (strbuf_read_file(&buf, msgfile, 1024) < 0) die_errno("could not open or read '%s'", diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index f88e721936..8b3a35e12d 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -91,7 +91,7 @@ int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix) n = write_in_full(1, content + 11, 41); if (n < 41) - die("git get-tar-commit-id: write error"); + die_errno("git get-tar-commit-id: write error"); return 0; } diff --git a/combine-diff.c b/combine-diff.c index 60d03676bb..bbf74fc42e 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -746,7 +746,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, done = read_in_full(fd, result, len); if (done < 0) - die("read error '%s'", elem->path); + die_errno("read error '%s'", elem->path); else if (done < len) die("early EOF '%s'", elem->path); diff --git a/diff.c b/diff.c index 48043f5bdb..aec613f85a 100644 --- a/diff.c +++ b/diff.c @@ -1982,7 +1982,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, size = buf.len; } if (write_in_full(fd, blob, size) != size) - die("unable to write temp-file"); + die_errno("unable to write temp-file"); close(fd); temp->name = temp->tmp_path; strcpy(temp->hex, sha1_to_hex(sha1)); @@ -2026,7 +2026,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name, if (S_ISLNK(st.st_mode)) { struct strbuf sb = STRBUF_INIT; if (strbuf_readlink(&sb, name, st.st_size) < 0) - die("readlink(%s)", name); + die_errno("readlink(%s)", name); prep_temp_blob(name, temp, sb.buf, sb.len, (one->sha1_valid ? one->sha1 : null_sha1), @@ -2219,7 +2219,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one) return; } if (lstat(one->path, &st) < 0) - die("stat %s", one->path); + die_errno("stat '%s'", one->path); if (index_path(one->sha1, one->path, &st, 0)) die("cannot hash %s", one->path); } diff --git a/entry.c b/entry.c index 8ec880bdbd..d3e86c722a 100644 --- a/entry.c +++ b/entry.c @@ -37,7 +37,7 @@ static void create_directories(const char *path, int path_len, if (errno == EEXIST && state->force && !unlink_or_warn(buf) && !mkdir(buf, 0777)) continue; - die("cannot create directory at %s", buf); + die_errno("cannot create directory at '%s'", buf); } } free(buf); diff --git a/fast-import.c b/fast-import.c index d31a4e8217..7ef9865aa6 100644 --- a/fast-import.c +++ b/fast-import.c @@ -905,10 +905,10 @@ static char *keep_pack(char *curr_index_name) keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1); if (keep_fd < 0) - die("cannot create keep file"); + die_errno("cannot create keep file"); write_or_die(keep_fd, keep_msg, strlen(keep_msg)); if (close(keep_fd)) - die("failed to write keep file"); + die_errno("failed to write keep file"); snprintf(name, sizeof(name), "%s/pack/pack-%s.pack", get_object_directory(), sha1_to_hex(pack_data->sha1)); diff --git a/hash-object.c b/hash-object.c index 47cf43c3cd..9455dd0709 100644 --- a/hash-object.c +++ b/hash-object.c @@ -29,7 +29,7 @@ static void hash_object(const char *path, const char *type, int write_object, int fd; fd = open(path, O_RDONLY); if (fd < 0) - die("Cannot open %s", path); + die_errno("Cannot open '%s'", path); hash_fd(fd, type, write_object, vpath); } diff --git a/ll-merge.c b/ll-merge.c index 81c02ad053..caf22be927 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -152,7 +152,7 @@ static void create_temp(mmfile_t *src, char *path) strcpy(path, ".merge_file_XXXXXX"); fd = xmkstemp(path); if (write_in_full(fd, src->ptr, src->size) != src->size) - die("unable to write temp-file"); + die_errno("unable to write temp-file"); close(fd); } diff --git a/mktag.c b/mktag.c index 99a356e9ee..a609e3ebd1 100644 --- a/mktag.c +++ b/mktag.c @@ -165,7 +165,7 @@ int main(int argc, char **argv) setup_git_directory(); if (strbuf_read(&buf, 0, 4096) < 0) { - die("could not read from stdin"); + die_errno("could not read from stdin"); } /* Verify it for some basic sanity: it needs to start with diff --git a/read-cache.c b/read-cache.c index f76b5bb2e1..4e3e272ee4 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1265,7 +1265,7 @@ int read_index_from(struct index_state *istate, const char *path) mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (mmap == MAP_FAILED) - die("unable to map index file"); + die_errno("unable to map index file"); hdr = mmap; if (verify_hdr(hdr, mmap_size) < 0) diff --git a/setup.c b/setup.c index 4d27f28c8f..e3781b656d 100644 --- a/setup.c +++ b/setup.c @@ -327,7 +327,7 @@ const char *setup_git_directory_gently(int *nongit_ok) return NULL; set_git_dir(make_absolute_path(gitdirenv)); if (chdir(work_tree_env) < 0) - die ("Could not chdir to %s", work_tree_env); + die_errno ("Could not chdir to '%s'", work_tree_env); strcat(buffer, "/"); return retval; } @@ -339,7 +339,7 @@ const char *setup_git_directory_gently(int *nongit_ok) } if (!getcwd(cwd, sizeof(cwd)-1)) - die("Unable to read current working directory"); + die_errno("Unable to read current working directory"); ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs); if (ceil_offset < 0 && has_dos_drive_prefix(cwd)) @@ -382,7 +382,7 @@ const char *setup_git_directory_gently(int *nongit_ok) if (offset <= ceil_offset) { if (nongit_ok) { if (chdir(cwd)) - die("Cannot come back to cwd"); + die_errno("Cannot come back to cwd"); *nongit_ok = 1; return NULL; } @@ -493,10 +493,10 @@ const char *setup_git_directory(void) static char buffer[PATH_MAX + 1]; char *rel; if (retval && chdir(retval)) - die ("Could not jump back into original cwd"); + die_errno ("Could not jump back into original cwd"); rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree()); if (rel && *rel && chdir(get_git_work_tree())) - die ("Could not jump to working directory"); + die_errno ("Could not jump to working directory"); return rel && *rel ? strcat(rel, "/") : NULL; } diff --git a/transport.c b/transport.c index 17891d5149..8decd663f1 100644 --- a/transport.c +++ b/transport.c @@ -158,7 +158,7 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push) strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX")); if (!mkdtemp(temp_dir.buf)) - die ("Could not make temporary directory"); + die_errno ("Could not make temporary directory"); temp_dir_len = temp_dir.len; strbuf_addstr(&buf, rsync_url(transport->url)); @@ -321,7 +321,7 @@ static int rsync_transport_push(struct transport *transport, strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX")); if (!mkdtemp(temp_dir.buf)) - die ("Could not make temporary directory"); + die_errno ("Could not make temporary directory"); strbuf_addch(&temp_dir, '/'); if (flags & TRANSPORT_PUSH_ALL) { diff --git a/unpack-file.c b/unpack-file.c index 75cd2f1a6a..ac9cbf7cd8 100644 --- a/unpack-file.c +++ b/unpack-file.c @@ -17,7 +17,7 @@ static char *create_temp_file(unsigned char *sha1) strcpy(path, ".merge_file_XXXXXX"); fd = xmkstemp(path); if (write_in_full(fd, buf, size) != size) - die("unable to write temp-file"); + die_errno("unable to write temp-file"); close(fd); return path; } -- cgit v1.3 From 8cfe5f1cd5dabc3a21bc792327747deefeff6dff Mon Sep 17 00:00:00 2001 From: René Scharfe Date: Thu, 2 Jul 2009 00:01:43 +0200 Subject: userdiff: add xdiff_clear_find_func() xdiff_set_find_func() is used to set user defined regular expressions for finding function signatures. Add xdiff_clear_find_func(), which frees the memory allocated by the former, making the API complete. Also, use the new function in diff.c (the only call site of xdiff_set_find_func()) to clean up after ourselves. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- diff.c | 1 + xdiff-interface.c | 15 +++++++++++++++ xdiff-interface.h | 1 + 3 files changed, 17 insertions(+) (limited to 'diff.c') diff --git a/diff.c b/diff.c index 43835d756c..892921cdc7 100644 --- a/diff.c +++ b/diff.c @@ -1603,6 +1603,7 @@ static void builtin_diff(const char *name_a, free(mf1.ptr); if (textconv_two) free(mf2.ptr); + xdiff_clear_find_func(&xecfg); } free_ab_and_return: diff --git a/xdiff-interface.c b/xdiff-interface.c index b9b0db8d86..01f14fb50f 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -309,6 +309,21 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags) } } +void xdiff_clear_find_func(xdemitconf_t *xecfg) +{ + if (xecfg->find_func) { + int i; + struct ff_regs *regs = xecfg->find_func_priv; + + for (i = 0; i < regs->nr; i++) + regfree(®s->array[i].re); + free(regs->array); + free(regs); + xecfg->find_func = NULL; + xecfg->find_func_priv = NULL; + } +} + int git_xmerge_style = -1; int git_xmerge_config(const char *var, const char *value, void *cb) diff --git a/xdiff-interface.h b/xdiff-interface.h index 7352b9a9c2..55572c39a1 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -21,6 +21,7 @@ int read_mmfile(mmfile_t *ptr, const char *filename); int buffer_is_binary(const char *ptr, unsigned long size); extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags); +extern void xdiff_clear_find_func(xdemitconf_t *xecfg); extern int git_xmerge_config(const char *var, const char *value, void *cb); extern int git_xmerge_style; -- cgit v1.3