From 81dc223deba84341be9681d7a1a4a183e02e41d6 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 26 Dec 2008 14:02:01 -0800 Subject: [PATCH 01/10] describe: Avoid unnecessary warning when using --all MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 212945d4 ("Teach git-describe to verify annotated tag names before output") git-describe learned how to output a warning if an annotated tag object was matched but its internal name doesn't match the local ref name. However, "git describe --all" causes the local ref name to be prefixed with "tags/", so we need to skip over this prefix before comparing the local ref name with the name recorded inside of the tag object. Patch-by: René Scharfe Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-describe.c | 2 +- t/t6120-describe.sh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/builtin-describe.c b/builtin-describe.c index 3da99c1d0..22b989fd7 100644 --- a/builtin-describe.c +++ b/builtin-describe.c @@ -160,7 +160,7 @@ static void display_name(struct commit_name *n) n->tag = lookup_tag(n->sha1); if (!n->tag || parse_tag(n->tag) || !n->tag->tag) die("annotated tag %s not available", n->path); - if (strcmp(n->tag->tag, n->path)) + if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) warning("tag '%s' is really '%s' here", n->tag->tag, n->path); } diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index c6bfef5f4..113a085cb 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -100,6 +100,12 @@ check_describe B --tags HEAD^^2^ check_describe B-0-* --long HEAD^^2^ check_describe A-3-* --long HEAD^^2 +: >err.expect +check_describe A --all A^0 +test_expect_success 'no warning was displayed for A' ' + test_cmp err.expect err.actual +' + test_expect_success 'rename tag A to Q locally' ' mv .git/refs/tags/A .git/refs/tags/Q ' From c569b1fee151e467854ca268997f4f3baaf73564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Fri, 26 Dec 2008 10:46:25 +0100 Subject: [PATCH 02/10] daemon: handle freopen() failure Die if stderr couldn't be sent to /dev/null when operating in inetd mode and report the error message from the OS. This fixes a compiler warning about the return value of freopen() being ignored on Ubuntu 8.10. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- daemon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/daemon.c b/daemon.c index 1cef3098d..8c317bed4 100644 --- a/daemon.c +++ b/daemon.c @@ -1118,7 +1118,9 @@ int main(int argc, char **argv) struct sockaddr *peer = (struct sockaddr *)&ss; socklen_t slen = sizeof(ss); - freopen("/dev/null", "w", stderr); + if (!freopen("/dev/null", "w", stderr)) + die("failed to redirect stderr to /dev/null: %s", + strerror(errno)); if (getpeername(0, peer, &slen)) peer = NULL; From a583971f15e520c8cb5f9967383903e13c353c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Fri, 26 Dec 2008 11:01:57 +0100 Subject: [PATCH 03/10] daemon: cleanup: replace loop with if Replace a loop around an enter_repo() call, which was used to retry a single time with a different parameter in case the first call fails, with two calls and an if. This is shorter and cleaner. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- daemon.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/daemon.c b/daemon.c index 8c317bed4..4468fb9d3 100644 --- a/daemon.c +++ b/daemon.c @@ -150,7 +150,6 @@ static char *path_ok(char *directory) { static char rpath[PATH_MAX]; static char interp_path[PATH_MAX]; - int retried_path = 0; char *path; char *dir; @@ -219,22 +218,15 @@ static char *path_ok(char *directory) dir = rpath; } - do { - path = enter_repo(dir, strict_paths); - if (path) - break; - + path = enter_repo(dir, strict_paths); + if (!path && base_path && base_path_relaxed) { /* * if we fail and base_path_relaxed is enabled, try without * prefixing the base path */ - if (base_path && base_path_relaxed && !retried_path) { - dir = directory; - retried_path = 1; - continue; - } - break; - } while (1); + dir = directory; + path = enter_repo(dir, strict_paths); + } if (!path) { logerror("'%s': unable to chdir or not a git archive", dir); From 6720e95b305737fddc776f2904c339a0701e6ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Fri, 26 Dec 2008 11:12:15 +0100 Subject: [PATCH 04/10] daemon: cleanup: factor out xstrdup_tolower() Add xstrdup_tolower(), a helper to get a lower case copy of a string, and use it in two cases. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- daemon.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/daemon.c b/daemon.c index 4468fb9d3..60bf6c743 100644 --- a/daemon.c +++ b/daemon.c @@ -397,6 +397,14 @@ static void make_service_overridable(const char *name, int ena) die("No such service %s", name); } +static char *xstrdup_tolower(const char *str) +{ + char *p, *dup = xstrdup(str); + for (p = dup; *p; p++) + *p = tolower(*p); + return dup; +} + /* * Separate the "extra args" information as supplied by the client connection. */ @@ -405,7 +413,6 @@ static void parse_extra_args(char *extra_args, int buflen) char *val; int vallen; char *end = extra_args + buflen; - char *hp; while (extra_args < end && *extra_args) { saw_extended_args = 1; @@ -423,7 +430,7 @@ static void parse_extra_args(char *extra_args, int buflen) tcp_port = xstrdup(port); } free(hostname); - hostname = xstrdup(host); + hostname = xstrdup_tolower(host); } /* On to the next one */ @@ -431,20 +438,11 @@ static void parse_extra_args(char *extra_args, int buflen) } } - /* - * Replace literal host with lowercase-ized hostname. - */ - hp = hostname; - if (!hp) - return; - for ( ; *hp; hp++) - *hp = tolower(*hp); - /* * Locate canonical hostname and its IP address. */ + if (hostname) { #ifndef NO_IPV6 - { struct addrinfo hints; struct addrinfo *ai, *ai0; int gai; @@ -468,9 +466,7 @@ static void parse_extra_args(char *extra_args, int buflen) } freeaddrinfo(ai0); } - } #else - { struct hostent *hent; struct sockaddr_in sa; char **ap; @@ -491,8 +487,8 @@ static void parse_extra_args(char *extra_args, int buflen) canon_hostname = xstrdup(hent->h_name); free(ip_address); ip_address = xstrdup(addrbuf); - } #endif + } } @@ -945,12 +941,8 @@ int main(int argc, char **argv) char *arg = argv[i]; if (!prefixcmp(arg, "--listen=")) { - char *p = arg + 9; - char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1); - while (*p) - *ph++ = tolower(*p++); - *ph = 0; - continue; + listen_addr = xstrdup_tolower(arg + 9); + continue; } if (!prefixcmp(arg, "--port=")) { char *end; From 4deba8b7798aac52e33aa8e1c49a8cdc0940ac36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Fri, 26 Dec 2008 11:17:04 +0100 Subject: [PATCH 05/10] merge-file: handle freopen() failure Report the error if redirection of stderr to /dev/null failed. This silences a compiler warning about ignoring the return value of freopen() on Ubuntu 8.10. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- builtin-merge-file.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/builtin-merge-file.c b/builtin-merge-file.c index 9d4e87480..96edb97a8 100644 --- a/builtin-merge-file.c +++ b/builtin-merge-file.c @@ -51,8 +51,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, options, merge_file_usage, 0); if (argc != 3) usage_with_options(merge_file_usage, options); - if (quiet) - freopen("/dev/null", "w", stderr); + if (quiet) { + if (!freopen("/dev/null", "w", stderr)) + return error("failed to redirect stderr to /dev/null: " + "%s\n", strerror(errno)); + } for (i = 0; i < 3; i++) { if (!names[i]) From a010966844221ea14f1de26fdab8fe37332ff928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:32:49 +0100 Subject: [PATCH 06/10] pretty: factor out skip_empty_lines() The patch after the next one will use it. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pretty.c b/pretty.c index f6ff31264..c43497bb2 100644 --- a/pretty.c +++ b/pretty.c @@ -181,6 +181,20 @@ static int is_empty_line(const char *line, int *len_p) return !len; } +static const char *skip_empty_lines(const char *msg) +{ + for (;;) { + int linelen = get_one_line(msg); + int ll = linelen; + if (!linelen) + break; + if (!is_empty_line(msg, &ll)) + break; + msg += linelen; + } + return msg; +} + static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb, const struct commit *commit, int abbrev) { @@ -850,15 +864,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, } /* Skip excess blank lines at the beginning of body, if any... */ - for (;;) { - int linelen = get_one_line(msg); - int ll = linelen; - if (!linelen) - break; - if (!is_empty_line(msg, &ll)) - break; - msg += linelen; - } + msg = skip_empty_lines(msg); /* These formats treat the title line specially. */ if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL) From 88c44735ab24aea3e669501c4491f7c9ca745ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:39:35 +0100 Subject: [PATCH 07/10] pretty: factor out format_subject() The next patch will use it. In the version that was factored out, we can't rely on the len of the struct strbuf to find out if a line separator needs to be added, as it might already contain something. Add a guard variable ("first") instead. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/pretty.c b/pretty.c index c43497bb2..632abc523 100644 --- a/pretty.c +++ b/pretty.c @@ -495,6 +495,28 @@ static void parse_commit_header(struct format_commit_context *context) context->commit_header_parsed = 1; } +static const char *format_subject(struct strbuf *sb, const char *msg, + const char *line_separator) +{ + int first = 1; + + for (;;) { + const char *line = msg; + int linelen = get_one_line(line); + + msg += linelen; + if (!linelen || is_empty_line(line, &linelen)) + break; + + strbuf_grow(sb, linelen + 2); + if (!first) + strbuf_addstr(sb, line_separator); + strbuf_add(sb, line, linelen); + first = 0; + } + return msg; +} + static void format_decoration(struct strbuf *sb, const struct commit *commit) { struct name_decoration *d; @@ -718,27 +740,11 @@ void pp_title_line(enum cmit_fmt fmt, const char *encoding, int need_8bit_cte) { + const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " "; struct strbuf title; strbuf_init(&title, 80); - - for (;;) { - const char *line = *msg_p; - int linelen = get_one_line(line); - - *msg_p += linelen; - if (!linelen || is_empty_line(line, &linelen)) - break; - - strbuf_grow(&title, linelen + 2); - if (title.len) { - if (fmt == CMIT_FMT_EMAIL) { - strbuf_addch(&title, '\n'); - } - strbuf_addch(&title, ' '); - } - strbuf_add(&title, line, linelen); - } + *msg_p = format_subject(&title, *msg_p, line_separator); strbuf_grow(sb, title.len + 1024); if (subject) { From f53bd743ff713f6507f28f8e730ac3e27858ab43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Scharfe?= Date: Sat, 27 Dec 2008 01:49:21 +0100 Subject: [PATCH 08/10] pretty: support multiline subjects with format: git log --pretty=format:%s (and tformat:) used to display the first line of the subject, unlike the other --pretty options, which would construct a subject line from all lines of the first paragraph of the commit message. For consistency and increased code reuse, change format: to do the same as the other options. Before: $ git log --pretty=oneline v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - $ git log --pretty=tformat:"%H %s" v1.6.1 | md5sum 298903b1c065002e15daa5329213c51f - After: $ git log --pretty=tformat:"%H %s" v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - $ git log --pretty=oneline v1.6.1 | md5sum 7c0896d2a94fc3315a0372b9b3373a8f - Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- pretty.c | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/pretty.c b/pretty.c index 632abc523..343dca556 100644 --- a/pretty.c +++ b/pretty.c @@ -424,13 +424,15 @@ struct chunk { struct format_commit_context { const struct commit *commit; enum date_mode dmode; + unsigned commit_header_parsed:1; + unsigned commit_message_parsed:1; /* These offsets are relative to the start of the commit message. */ - int commit_header_parsed; - struct chunk subject; struct chunk author; struct chunk committer; struct chunk encoding; + size_t message_off; + size_t subject_off; size_t body_off; /* The following ones are relative to the result struct strbuf. */ @@ -460,23 +462,14 @@ static void parse_commit_header(struct format_commit_context *context) { const char *msg = context->commit->buffer; int i; - enum { HEADER, SUBJECT, BODY } state; - for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { + for (i = 0; msg[i]; i++) { int eol; for (eol = i; msg[eol] && msg[eol] != '\n'; eol++) ; /* do nothing */ - if (state == SUBJECT) { - context->subject.off = i; - context->subject.len = eol - i; - i = eol; - } if (i == eol) { - state++; - /* strip empty lines */ - while (msg[eol] == '\n' && msg[eol + 1] == '\n') - eol++; + break; } else if (!prefixcmp(msg + i, "author ")) { context->author.off = i + 7; context->author.len = eol - i - 7; @@ -488,10 +481,8 @@ static void parse_commit_header(struct format_commit_context *context) context->encoding.len = eol - i - 9; } i = eol; - if (!msg[i]) - break; } - context->body_off = i; + context->message_off = i; context->commit_header_parsed = 1; } @@ -508,6 +499,8 @@ static const char *format_subject(struct strbuf *sb, const char *msg, if (!linelen || is_empty_line(line, &linelen)) break; + if (!sb) + continue; strbuf_grow(sb, linelen + 2); if (!first) strbuf_addstr(sb, line_separator); @@ -517,6 +510,21 @@ static const char *format_subject(struct strbuf *sb, const char *msg, return msg; } +static void parse_commit_message(struct format_commit_context *c) +{ + const char *msg = c->commit->buffer + c->message_off; + const char *start = c->commit->buffer; + + msg = skip_empty_lines(msg); + c->subject_off = msg - start; + + msg = format_subject(NULL, msg, NULL); + msg = skip_empty_lines(msg); + c->body_off = msg - start; + + c->commit_message_parsed = 1; +} + static void format_decoration(struct strbuf *sb, const struct commit *commit) { struct name_decoration *d; @@ -636,9 +644,6 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, parse_commit_header(c); switch (placeholder[0]) { - case 's': /* subject */ - strbuf_add(sb, msg + c->subject.off, c->subject.len); - return 1; case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, @@ -650,6 +655,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder, case 'e': /* encoding */ strbuf_add(sb, msg + c->encoding.off, c->encoding.len); return 1; + } + + /* Now we need to parse the commit message. */ + if (!c->commit_message_parsed) + parse_commit_message(c); + + switch (placeholder[0]) { + case 's': /* subject */ + format_subject(sb, msg + c->subject_off, " "); + return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; From 3a882d9696ba2ba46adc107b92b4721e59bb60b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adeodato=20Sim=C3=B3?= Date: Sat, 27 Dec 2008 19:23:30 +0100 Subject: [PATCH 09/10] git-shortlog.txt: improve documentation about .mailmap files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The description on .mailmap made it seem like they are only useful for commits with a wrong address for an author, but they are about fixing the real name. Explain this better in the text, and replace the existing example with a new one that hopefully makes things clearer. Signed-off-by: Adeodato Simó Signed-off-by: Junio C Hamano --- Documentation/git-shortlog.txt | 40 ++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index 7ccf31ccc..8f7c0e226 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -48,15 +48,41 @@ OPTIONS FILES ----- -If the file `.mailmap` exists, it will be used for mapping author -email addresses to a real author name. One mapping per line, first -the author name followed by the email address enclosed by -'<' and '>'. Use hash '#' for comments. Example: +If a file `.mailmap` exists at the toplevel of the repository, +it is used to map an author email address to a canonical real name. This +can be used to coalesce together commits by the same person where their +name was spelled differently (whether with the same email address or +not). + +Each line in the file consists, in this order, of the canonical real name +of an author, whitespace, and an email address (enclosed by '<' and '>') +to map to the name. Use hash '#' for comments, either on their own line, +or after the email address. + +A canonical name may appear in more than one line, associated with +different email addresses, but it doesn't make sense for a given address +to appear more than once (if that happens, a later line overrides the +earlier ones). + +So, for example, if your history contains commits by two authors, Jane +and Joe, whose names appear in the repository under several forms: + +------------ +Joe Developer +Joe R. Developer +Jane Doe +Jane Doe +Jane D. +------------ + +Then, supposing Joe wants his middle name initial used, and Jane prefers +her family name fully spelled out, a proper `.mailmap` file would look like: ------------ -# Keep alphabetized -Adam Morrow -Eve Jones +# Note how we don't need an entry for , because the +# real name of that author is correct already, and coalesced directly. +Jane Doe +Joe R. Developer ------------ Author From f83b9ba20973472f64699e1e2707b74da211a89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adeodato=20Sim=C3=B3?= Date: Sat, 27 Dec 2008 09:50:30 +0100 Subject: [PATCH 10/10] git-send-email.txt: move --format-patch paragraph to a proper location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When introducing --format-patch, its documentation was accidentally inserted in the middle of documentation for --validate. Signed-off-by: Adeodato Simó Signed-off-by: Junio C Hamano --- Documentation/git-send-email.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 12788667d..b69846e52 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -197,12 +197,6 @@ Administering --[no-]validate:: Perform sanity checks on patches. Currently, validation means the following: - ---[no-]format-patch:: - When an argument may be understood either as a reference or as a file name, - choose to understand it as a format-patch argument ('--format-patch') - or as a file name ('--no-format-patch'). By default, when such a conflict - occurs, git send-email will fail. + -- * Warn of patches that contain lines longer than 998 characters; this @@ -212,6 +206,12 @@ Administering Default is the value of 'sendemail.validate'; if this is not set, default to '--validate'. +--[no-]format-patch:: + When an argument may be understood either as a reference or as a file name, + choose to understand it as a format-patch argument ('--format-patch') + or as a file name ('--no-format-patch'). By default, when such a conflict + occurs, git send-email will fail. + CONFIGURATION -------------