X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-log.c;h=fedb0137bc5e3ba50ecb90ce560ce9ce9290d8df;hb=45bd0c808d2a89254ee50807a99b7cf1147aa6d7;hp=52064cd178c2b705d6eec16de9f9a40eb4f5272b;hpb=db6296a566eb1a8007a84330a911b38055720743;p=git.git diff --git a/builtin-log.c b/builtin-log.c index 52064cd17..fedb0137b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -16,7 +16,7 @@ /* this is in builtin-diff.c */ void add_head(struct rev_info *revs); -static void cmd_log_init(int argc, const char **argv, char **envp, +static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { rev->abbrev = DEFAULT_ABBREV; @@ -34,7 +34,6 @@ static int cmd_log_walk(struct rev_info *rev) struct commit *commit; prepare_revision_walk(rev); - setup_pager(); while ((commit = get_revision(rev)) != NULL) { log_tree_commit(rev, commit); free(commit->buffer); @@ -45,26 +44,24 @@ static int cmd_log_walk(struct rev_info *rev) return 0; } -int cmd_whatchanged(int argc, const char **argv, char **envp) +int cmd_whatchanged(int argc, const char **argv, const char *prefix) { struct rev_info rev; - const char *prefix = setup_git_directory(); git_config(git_diff_ui_config); init_revisions(&rev, prefix); rev.diff = 1; rev.diffopt.recursive = 1; rev.simplify_history = 0; - cmd_log_init(argc, argv, envp, &rev); + cmd_log_init(argc, argv, prefix, &rev); if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_RAW; return cmd_log_walk(&rev); } -int cmd_show(int argc, const char **argv, char **envp) +int cmd_show(int argc, const char **argv, const char *prefix) { struct rev_info rev; - const char *prefix = setup_git_directory(); git_config(git_diff_ui_config); init_revisions(&rev, prefix); @@ -75,19 +72,18 @@ int cmd_show(int argc, const char **argv, char **envp) rev.always_show_header = 1; rev.ignore_merges = 0; rev.no_walk = 1; - cmd_log_init(argc, argv, envp, &rev); + cmd_log_init(argc, argv, prefix, &rev); return cmd_log_walk(&rev); } -int cmd_log(int argc, const char **argv, char **envp) +int cmd_log(int argc, const char **argv, const char *prefix) { struct rev_info rev; - const char *prefix = setup_git_directory(); git_config(git_diff_ui_config); init_revisions(&rev, prefix); rev.always_show_header = 1; - cmd_log_init(argc, argv, envp, &rev); + cmd_log_init(argc, argv, prefix, &rev); return cmd_log_walk(&rev); } @@ -105,7 +101,7 @@ static int git_format_config(const char *var, const char *value) if (!strcmp(var, "format.headers")) { int len = strlen(value); extra_headers_size += len + 1; - extra_headers = realloc(extra_headers, extra_headers_size); + extra_headers = xrealloc(extra_headers, extra_headers_size); extra_headers[extra_headers_size - len - 1] = 0; strcat(extra_headers, value); return 0; @@ -175,20 +171,22 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject) static int get_patch_id(struct commit *commit, struct diff_options *options, unsigned char *sha1) { - diff_tree_sha1(commit->parents->item->object.sha1, commit->object.sha1, - "", options); + 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) +static void get_patch_ids(struct rev_info *rev, struct diff_options *options, const char *prefix) { struct rev_info check_rev; struct commit *commit; struct object *o1, *o2; unsigned flags1, flags2; unsigned char sha1[20]; - const char *prefix = setup_git_directory(); if (rev->pending.nr != 2) die("Need exactly one range."); @@ -244,7 +242,7 @@ static void gen_message_id(char *dest, unsigned int length, char *base) (int)(email_end - email_start - 1), email_start + 1); } -int cmd_format_patch(int argc, const char **argv, char **envp) +int cmd_format_patch(int argc, const char **argv, const char *prefix) { struct commit *commit; struct commit **list = NULL; @@ -261,8 +259,8 @@ int cmd_format_patch(int argc, const char **argv, char **envp) char *add_signoff = NULL; char message_id[1024]; char ref_message_id[1024]; - const char *prefix = setup_git_directory(); + setup_ident(); git_config(git_format_config); init_revisions(&rev, prefix); rev.commit_format = CMIT_FMT_EMAIL; @@ -312,7 +310,6 @@ int cmd_format_patch(int argc, const char **argv, char **envp) !strcmp(argv[i], "-s")) { const char *committer; const char *endpos; - setup_ident(); committer = git_committer_info(1); endpos = strchr(committer, '>'); if (!endpos) @@ -354,6 +351,9 @@ int cmd_format_patch(int argc, const char **argv, char **envp) if (!rev.diffopt.output_format) rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH; + if (!output_directory) + output_directory = prefix; + if (output_directory) { if (use_stdout) die("standard output, or directory, which one?"); @@ -368,7 +368,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp) } if (ignore_if_in_upstream) - get_patch_ids(&rev, &patch_id_opts); + get_patch_ids(&rev, &patch_id_opts, prefix); if (!use_stdout) realstdout = fdopen(dup(1), "w"); @@ -387,7 +387,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp) continue; nr++; - list = realloc(list, nr * sizeof(list[0])); + list = xrealloc(list, nr * sizeof(list[0])); list[nr - 1] = commit; } total = nr; @@ -440,3 +440,109 @@ int cmd_format_patch(int argc, const char **argv, char **envp) return 0; } +static int add_pending_commit(const char *arg, struct rev_info *revs, int flags) +{ + unsigned char sha1[20]; + if (get_sha1(arg, sha1) == 0) { + struct commit *commit = lookup_commit_reference(sha1); + if (commit) { + commit->object.flags |= flags; + add_pending_object(revs, &commit->object, arg); + return 0; + } + } + return -1; +} + +static const char cherry_usage[] = +"git-cherry [-v] [] []"; +int cmd_cherry(int argc, const char **argv, const char *prefix) +{ + struct rev_info revs; + struct diff_options patch_id_opts; + struct commit *commit; + struct commit_list *list = NULL; + const char *upstream; + const char *head = "HEAD"; + const char *limit = NULL; + int verbose = 0; + + if (argc > 1 && !strcmp(argv[1], "-v")) { + verbose = 1; + argc--; + argv++; + } + + switch (argc) { + case 4: + limit = argv[3]; + /* FALLTHROUGH */ + case 3: + head = argv[2]; + /* FALLTHROUGH */ + case 2: + upstream = argv[1]; + break; + default: + usage(cherry_usage); + } + + init_revisions(&revs, prefix); + revs.diff = 1; + revs.combine_merges = 0; + revs.ignore_merges = 1; + revs.diffopt.recursive = 1; + + if (add_pending_commit(head, &revs, 0)) + die("Unknown commit %s", head); + if (add_pending_commit(upstream, &revs, UNINTERESTING)) + die("Unknown commit %s", upstream); + + /* Don't say anything if head and upstream are the same. */ + if (revs.pending.nr == 2) { + struct object_array_entry *o = revs.pending.objects; + if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0) + return 0; + } + + get_patch_ids(&revs, &patch_id_opts, prefix); + + if (limit && add_pending_commit(limit, &revs, UNINTERESTING)) + die("Unknown commit %s", limit); + + /* reverse the list of commits */ + prepare_revision_walk(&revs); + while ((commit = get_revision(&revs)) != NULL) { + /* ignore merges */ + if (commit->parents && commit->parents->next) + continue; + + commit_list_insert(commit, &list); + } + + while (list) { + unsigned char sha1[20]; + char sign = '+'; + + commit = list->item; + if (!get_patch_id(commit, &patch_id_opts, sha1) && + lookup_object(sha1)) + sign = '-'; + + if (verbose) { + static char buf[16384]; + pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0, + buf, sizeof(buf), 0, NULL, NULL, 0); + printf("%c %s %s\n", sign, + sha1_to_hex(commit->object.sha1), buf); + } + else { + printf("%c %s\n", sign, + sha1_to_hex(commit->object.sha1)); + } + + list = list->next; + } + + return 0; +}