X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-log.c;h=e8b982db7cf7c98bff9d64affcb573b3d9676cb1;hb=b4833a2c62578bdbfd300e296702214cb1b9a601;hp=37447123f924149f012a298eaf31dacb0c87b724;hpb=31c74ca67162674e3ff8fcc294b75881c3e7cc15;p=git.git diff --git a/builtin-log.c b/builtin-log.c index 37447123f..e8b982db7 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -16,6 +16,7 @@ #include "refs.h" static int default_show_root = 1; +static const char *fmt_patch_subject_prefix = "PATCH"; /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); @@ -54,19 +55,20 @@ 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; 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) { + 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 (!prefixcmp(arg, "--encoding=")) { - arg += 11; - if (strcmp(arg, "none")) - git_log_output_encoding = xstrdup(arg); - else - git_log_output_encoding = ""; - } else if (!strcmp(arg, "--decorate")) { + if (!strcmp(arg, "--decorate")) { if (!decorate) for_each_ref(add_ref_decoration, NULL); decorate = 1; @@ -95,6 +97,12 @@ static int cmd_log_walk(struct rev_info *rev) static int git_log_config(const char *var, const char *value) { + if (!strcmp(var, "format.subjectprefix")) { + if (!value) + die("format.subjectprefix without value"); + fmt_patch_subject_prefix = xstrdup(value); + return 0; + } if (!strcmp(var, "log.showroot")) { default_show_root = git_config_bool(var, value); return 0; @@ -109,7 +117,6 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.simplify_history = 0; cmd_log_init(argc, argv, prefix, &rev); if (!rev.diffopt.output_format) @@ -158,7 +165,6 @@ int cmd_show(int argc, const char **argv, const char *prefix) git_config(git_log_config); init_revisions(&rev, prefix); rev.diff = 1; - rev.diffopt.recursive = 1; rev.combine_merges = 1; rev.dense_combined_merges = 1; rev.always_show_header = 1; @@ -291,6 +297,7 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) { return 0; } + return git_log_config(var, value); } @@ -298,7 +305,8 @@ static int git_format_config(const char *var, const char *value) static FILE *realstdout = NULL; static const char *output_directory = NULL; -static int reopen_stdout(struct commit *commit, int nr, int keep_subject) +static int reopen_stdout(struct commit *commit, int nr, int keep_subject, + int numbered_files) { char filename[PATH_MAX]; char *sol; @@ -315,53 +323,61 @@ static int reopen_stdout(struct commit *commit, int nr, int keep_subject) filename[len++] = '/'; } - sprintf(filename + len, "%04d", nr); - len = strlen(filename); - - sol = strstr(commit->buffer, "\n\n"); - if (sol) { - int j, space = 1; - - sol += 2; - /* strip [PATCH] or [PATCH blabla] */ - if (!keep_subject && !prefixcmp(sol, "[PATCH")) { - char *eos = strchr(sol + 6, ']'); - if (eos) { - while (isspace(*eos)) - eos++; - sol = eos; - } - } + if (numbered_files) { + sprintf(filename + len, "%d", nr); + len = strlen(filename); - for (j = 0; - j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 && - len < sizeof(filename) - suffix_len && - sol[j] && sol[j] != '\n'; - j++) { - if (istitlechar(sol[j])) { - if (space) { - filename[len++] = '-'; - space = 0; + } else { + sprintf(filename + len, "%04d", nr); + len = strlen(filename); + + sol = strstr(commit->buffer, "\n\n"); + if (sol) { + int j, space = 1; + + sol += 2; + /* strip [PATCH] or [PATCH blabla] */ + if (!keep_subject && !prefixcmp(sol, "[PATCH")) { + char *eos = strchr(sol + 6, ']'); + if (eos) { + while (isspace(*eos)) + eos++; + sol = eos; } - filename[len++] = sol[j]; - if (sol[j] == '.') - while (sol[j + 1] == '.') - j++; - } else - space = 1; + } + + for (j = 0; + j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 && + len < sizeof(filename) - suffix_len && + sol[j] && sol[j] != '\n'; + j++) { + if (istitlechar(sol[j])) { + if (space) { + filename[len++] = '-'; + space = 0; + } + filename[len++] = sol[j]; + if (sol[j] == '.') + while (sol[j + 1] == '.') + j++; + } else + space = 1; + } + while (filename[len - 1] == '.' + || filename[len - 1] == '-') + len--; + filename[len] = 0; } - while (filename[len - 1] == '.' || filename[len - 1] == '-') - len--; - filename[len] = 0; + if (len + suffix_len >= sizeof(filename)) + return error("Patch pathname too long"); + strcpy(filename + len, fmt_patch_suffix); } - if (len + suffix_len >= sizeof(filename)) - return error("Patch pathname too long"); - strcpy(filename + len, fmt_patch_suffix); + fprintf(realstdout, "%s\n", filename); if (freopen(filename, "w", stdout) == NULL) return error("Cannot open patch file %s",filename); - return 0; + return 0; } static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix) @@ -421,6 +437,28 @@ static void gen_message_id(char *dest, unsigned int length, char *base) (int)(email_end - email_start - 1), email_start + 1); } +static const char *clean_message_id(const char *msg_id) +{ + char ch; + const char *a, *z, *m; + + m = msg_id; + while ((ch = *m) && (isspace(ch) || (ch == '<'))) + m++; + a = m; + z = NULL; + while ((ch = *m)) { + if (!isspace(ch) && (ch != '>')) + z = m; + m++; + } + if (!z) + die("insane in-reply-to: %s", msg_id); + if (++z == m) + return a; + return xmemdupz(a, z - a); +} + int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; @@ -431,6 +469,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered = 0; int start_number = -1; int keep_subject = 0; + int numbered_files = 0; /* _just_ numbers */ int subject_prefix = 0; int ignore_if_in_upstream = 0; int thread = 0; @@ -450,6 +489,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.diffopt.msg_sep = ""; rev.diffopt.recursive = 1; + rev.subject_prefix = fmt_patch_subject_prefix; rev.extra_headers = extra_headers; /* @@ -465,6 +505,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) numbered = 1; else if (!prefixcmp(argv[i], "--start-number=")) start_number = strtol(argv[i] + 15, NULL, 10); + else if (!strcmp(argv[i], "--numbered-files")) + numbered_files = 1; else if (!strcmp(argv[i], "--start-number")) { i++; if (i == argc) @@ -493,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; @@ -540,6 +580,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) die ("-n and -k are mutually exclusive."); if (keep_subject && subject_prefix) die ("--subject-prefix and -k are mutually exclusive."); + if (numbered_files && use_stdout) + die ("--numbered-files and --stdout are mutually exclusive."); argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) @@ -563,12 +605,19 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (rev.pending.nr == 1) { - if (rev.max_count < 0) { + if (rev.max_count < 0 && !rev.show_root_diff) { + /* + * This is traditional behaviour of "git format-patch + * origin" that prepares what the origin side still + * does not have. + */ rev.pending.objects[0].item->flags |= UNINTERESTING; add_head(&rev); } - /* Otherwise, it is "format-patch -22 HEAD", and - * get_revision() would return only the specified count. + /* + * Otherwise, it is "format-patch -22 HEAD", and/or + * "format-patch --root HEAD". The user wants + * get_revision() to do the usual traversal. */ } @@ -576,7 +625,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) get_patch_ids(&rev, &ids, prefix); if (!use_stdout) - realstdout = fdopen(dup(1), "w"); + realstdout = xfdopen(xdup(1), "w"); prepare_revision_walk(&rev); while ((commit = get_revision(&rev)) != NULL) { @@ -596,7 +645,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) if (numbered) rev.total = total + start_number - 1; rev.add_signoff = add_signoff; - rev.ref_message_id = in_reply_to; + if (in_reply_to) + rev.ref_message_id = clean_message_id(in_reply_to); while (0 <= --nr) { int shown; commit = list[nr]; @@ -614,7 +664,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.message_id = message_id; } if (!use_stdout) - if (reopen_stdout(commit, rev.nr, keep_subject)) + if (reopen_stdout(commit, rev.nr, keep_subject, + numbered_files)) die("Failed to create output files"); shown = log_tree_commit(&rev, commit); free(commit->buffer); @@ -733,11 +784,13 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) sign = '-'; if (verbose) { - static char buf[16384]; - pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, - buf, sizeof(buf), 0, NULL, NULL, 0); + struct strbuf buf; + strbuf_init(&buf, 0); + pretty_print_commit(CMIT_FMT_ONELINE, commit, + &buf, 0, NULL, NULL, 0); printf("%c %s %s\n", sign, - sha1_to_hex(commit->object.sha1), buf); + sha1_to_hex(commit->object.sha1), buf.buf); + strbuf_release(&buf); } else { printf("%c %s\n", sign,