X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-log.c;h=1c9f7d02a8746d1d33347b7baaa85e4153a61bbb;hb=d1c7c27ea3d9c92be2c7a9c5fc72ba5f228c424a;hp=af2de54371cf7fc294c17431622f759e8e6066db;hpb=67c7575947b06a2a9bbdb355357895149bdbd8e5;p=git.git diff --git a/builtin-log.c b/builtin-log.c index af2de5437..37447123f 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -12,16 +12,44 @@ #include "builtin.h" #include "tag.h" #include "reflog-walk.h" +#include "patch-ids.h" +#include "refs.h" static int default_show_root = 1; /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); +static void add_name_decoration(const char *prefix, const char *name, struct object *obj) +{ + int plen = strlen(prefix); + int nlen = strlen(name); + struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen); + memcpy(res->name, prefix, plen); + memcpy(res->name + plen, name, nlen + 1); + res->next = add_decoration(&name_decoration, obj, res); +} + +static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data) +{ + struct object *obj = parse_object(sha1); + if (!obj) + return 0; + add_name_decoration("", refname, obj); + while (obj->type == OBJ_TAG) { + obj = ((struct tag *)obj)->tagged; + if (!obj) + break; + add_name_decoration("tag: ", refname, obj); + } + return 0; +} + static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; + int decorate = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -32,14 +60,17 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, rev->always_show_header = 0; for (i = 1; i < argc; i++) { const char *arg = argv[i]; - if (!strncmp(arg, "--encoding=", 11)) { + if (!prefixcmp(arg, "--encoding=")) { arg += 11; if (strcmp(arg, "none")) - git_log_output_encoding = strdup(arg); + git_log_output_encoding = xstrdup(arg); else git_log_output_encoding = ""; - } - else + } else if (!strcmp(arg, "--decorate")) { + if (!decorate) + for_each_ref(add_ref_decoration, NULL); + decorate = 1; + } else die("unrecognized argument: %s", arg); } } @@ -89,8 +120,8 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix) static int show_object(const unsigned char *sha1, int suppress_header) { unsigned long size; - char type[20]; - char *buf = read_sha1_file(sha1, type, &size); + enum object_type type; + char *buf = read_sha1_file(sha1, &type, &size); int offset = 0; if (!buf) @@ -224,6 +255,9 @@ int cmd_log(int argc, const char **argv, const char *prefix) return cmd_log_walk(&rev); } +/* format-patch */ +#define FORMAT_PATCH_NAME_MAX 64 + static int istitlechar(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || @@ -264,15 +298,18 @@ static int git_format_config(const char *var, const char *value) static FILE *realstdout = NULL; static const char *output_directory = NULL; -static void reopen_stdout(struct commit *commit, int nr, int keep_subject) +static int reopen_stdout(struct commit *commit, int nr, int keep_subject) { - char filename[1024]; + char filename[PATH_MAX]; char *sol; int len = 0; - int suffix_len = strlen(fmt_patch_suffix) + 10; /* ., NUL and slop */ + int suffix_len = strlen(fmt_patch_suffix) + 1; if (output_directory) { - strlcpy(filename, output_directory, 1000); + if (strlen(output_directory) >= + sizeof(filename) - FORMAT_PATCH_NAME_MAX - suffix_len) + return error("name of output directory is too long"); + strlcpy(filename, output_directory, sizeof(filename) - suffix_len); len = strlen(filename); if (filename[len - 1] != '/') filename[len++] = '/'; @@ -287,7 +324,7 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject) sol += 2; /* strip [PATCH] or [PATCH blabla] */ - if (!keep_subject && !strncmp(sol, "[PATCH", 6)) { + if (!keep_subject && !prefixcmp(sol, "[PATCH")) { char *eos = strchr(sol + 6, ']'); if (eos) { while (isspace(*eos)) @@ -297,7 +334,8 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject) } for (j = 0; - len < sizeof(filename) - suffix_len && + j < FORMAT_PATCH_NAME_MAX - suffix_len - 5 && + len < sizeof(filename) - suffix_len && sol[j] && sol[j] != '\n'; j++) { if (istitlechar(sol[j])) { @@ -314,31 +352,24 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject) } 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); fprintf(realstdout, "%s\n", filename); - freopen(filename, "w", stdout); -} + if (freopen(filename, "w", stdout) == NULL) + return error("Cannot open patch file %s",filename); + return 0; -static int get_patch_id(struct commit *commit, struct diff_options *options, - unsigned char *sha1) -{ - if (commit->parents) - diff_tree_sha1(commit->parents->item->object.sha1, - commit->object.sha1, "", options); - else - diff_root_tree_sha1(commit->object.sha1, "", options); - diffcore_std(options); - return diff_flush_patch_id(options, sha1); } -static void get_patch_ids(struct rev_info *rev, struct diff_options *options, const char *prefix) +static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix) { struct rev_info check_rev; struct commit *commit; struct object *o1, *o2; unsigned flags1, flags2; - unsigned char sha1[20]; if (rev->pending.nr != 2) die("Need exactly one range."); @@ -351,10 +382,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options, co if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING)) die("Not a range."); - diff_setup(options); - options->recursive = 1; - if (diff_setup_done(options) < 0) - die("diff_setup_done failed"); + init_patch_ids(ids); /* given a range a..b get all patch ids for b..a */ init_revisions(&check_rev, prefix); @@ -369,8 +397,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options, co if (commit->parents && commit->parents->next) continue; - if (!get_patch_id(commit, options, sha1)) - created_object(sha1, xcalloc(1, sizeof(struct object))); + add_commit_patch_id(commit, ids); } /* reset for next revision walk */ @@ -404,10 +431,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) int numbered = 0; int start_number = -1; int keep_subject = 0; + int subject_prefix = 0; int ignore_if_in_upstream = 0; int thread = 0; const char *in_reply_to = NULL; - struct diff_options patch_id_opts; + struct patch_ids ids; char *add_signoff = NULL; char message_id[1024]; char ref_message_id[1024]; @@ -426,7 +454,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) /* * Parse the arguments before setup_revisions(), or something - * like "git fmt-patch -o a123 HEAD^.." may fail; a123 is + * like "git format-patch -o a123 HEAD^.." may fail; a123 is * possibly a valid SHA1. */ for (i = 1, j = 1; i < argc; i++) { @@ -435,7 +463,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--numbered")) numbered = 1; - else if (!strncmp(argv[i], "--start-number=", 15)) + else if (!prefixcmp(argv[i], "--start-number=")) start_number = strtol(argv[i] + 15, NULL, 10); else if (!strcmp(argv[i], "--start-number")) { i++; @@ -469,23 +497,37 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) memcpy(add_signoff, committer, endpos - committer + 1); add_signoff[endpos - committer + 1] = 0; } - else if (!strcmp(argv[i], "--attach")) + else if (!strcmp(argv[i], "--attach")) { rev.mime_boundary = git_version_string; - else if (!strncmp(argv[i], "--attach=", 9)) + rev.no_inline = 1; + } + else if (!prefixcmp(argv[i], "--attach=")) { rev.mime_boundary = argv[i] + 9; + rev.no_inline = 1; + } + else if (!strcmp(argv[i], "--inline")) { + rev.mime_boundary = git_version_string; + rev.no_inline = 0; + } + else if (!prefixcmp(argv[i], "--inline=")) { + rev.mime_boundary = argv[i] + 9; + rev.no_inline = 0; + } else if (!strcmp(argv[i], "--ignore-if-in-upstream")) ignore_if_in_upstream = 1; else if (!strcmp(argv[i], "--thread")) thread = 1; - else if (!strncmp(argv[i], "--in-reply-to=", 14)) + else if (!prefixcmp(argv[i], "--in-reply-to=")) in_reply_to = argv[i] + 14; else if (!strcmp(argv[i], "--in-reply-to")) { i++; if (i == argc) die("Need a Message-Id for --in-reply-to"); in_reply_to = argv[i]; - } - else if (!strncmp(argv[i], "--suffix=", 9)) + } else if (!prefixcmp(argv[i], "--subject-prefix=")) { + subject_prefix = 1; + rev.subject_prefix = argv[i] + 17; + } else if (!prefixcmp(argv[i], "--suffix=")) fmt_patch_suffix = argv[i] + 9; else argv[j++] = argv[i]; @@ -496,6 +538,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) start_number = 1; if (numbered && keep_subject) die ("-n and -k are mutually exclusive."); + if (keep_subject && subject_prefix) + die ("--subject-prefix and -k are mutually exclusive."); argc = setup_revisions(argc, argv, &rev, "HEAD"); if (argc > 1) @@ -529,22 +573,19 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) } if (ignore_if_in_upstream) - get_patch_ids(&rev, &patch_id_opts, prefix); + get_patch_ids(&rev, &ids, prefix); if (!use_stdout) realstdout = fdopen(dup(1), "w"); prepare_revision_walk(&rev); while ((commit = get_revision(&rev)) != NULL) { - unsigned char sha1[20]; - /* ignore merges */ if (commit->parents && commit->parents->next) continue; if (ignore_if_in_upstream && - !get_patch_id(commit, &patch_id_opts, sha1) && - lookup_object(sha1)) + has_commit_patch_id(commit, &ids)) continue; nr++; @@ -573,7 +614,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) rev.message_id = message_id; } if (!use_stdout) - reopen_stdout(commit, rev.nr, keep_subject); + if (reopen_stdout(commit, rev.nr, keep_subject)) + die("Failed to create output files"); shown = log_tree_commit(&rev, commit); free(commit->buffer); commit->buffer = NULL; @@ -598,6 +640,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) fclose(stdout); } free(list); + if (ignore_if_in_upstream) + free_patch_ids(&ids); return 0; } @@ -620,7 +664,7 @@ static const char cherry_usage[] = int cmd_cherry(int argc, const char **argv, const char *prefix) { struct rev_info revs; - struct diff_options patch_id_opts; + struct patch_ids ids; struct commit *commit; struct commit_list *list = NULL; const char *upstream; @@ -666,7 +710,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) return 0; } - get_patch_ids(&revs, &patch_id_opts, prefix); + get_patch_ids(&revs, &ids, prefix); if (limit && add_pending_commit(limit, &revs, UNINTERESTING)) die("Unknown commit %s", limit); @@ -682,12 +726,10 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) } while (list) { - unsigned char sha1[20]; char sign = '+'; commit = list->item; - if (!get_patch_id(commit, &patch_id_opts, sha1) && - lookup_object(sha1)) + if (has_commit_patch_id(commit, &ids)) sign = '-'; if (verbose) { @@ -705,5 +747,6 @@ int cmd_cherry(int argc, const char **argv, const char *prefix) list = list->next; } + free_patch_ids(&ids); return 0; }