diff options
Diffstat (limited to 'log-tree.c')
-rw-r--r-- | log-tree.c | 207 |
1 files changed, 135 insertions, 72 deletions
diff --git a/log-tree.c b/log-tree.c index 923a299e70..6dc4412268 100644 --- a/log-tree.c +++ b/log-tree.c @@ -15,7 +15,6 @@ #include "sequencer.h" #include "line-log.h" #include "help.h" -#include "interdiff.h" #include "range-diff.h" static struct decoration name_decoration = { "object names" }; @@ -81,16 +80,65 @@ const struct name_decoration *get_name_decoration(const struct object *obj) return lookup_decoration(&name_decoration, obj); } +static int match_ref_pattern(const char *refname, + const struct string_list_item *item) +{ + int matched = 0; + if (item->util == NULL) { + if (!wildmatch(item->string, refname, 0)) + matched = 1; + } else { + const char *rest; + if (skip_prefix(refname, item->string, &rest) && + (!*rest || *rest == '/')) + matched = 1; + } + return matched; +} + +static int ref_filter_match(const char *refname, + const struct decoration_filter *filter) +{ + struct string_list_item *item; + const struct string_list *exclude_patterns = filter->exclude_ref_pattern; + const struct string_list *include_patterns = filter->include_ref_pattern; + const struct string_list *exclude_patterns_config = + filter->exclude_ref_config_pattern; + + if (exclude_patterns && exclude_patterns->nr) { + for_each_string_list_item(item, exclude_patterns) { + if (match_ref_pattern(refname, item)) + return 0; + } + } + + if (include_patterns && include_patterns->nr) { + for_each_string_list_item(item, include_patterns) { + if (match_ref_pattern(refname, item)) + return 1; + } + return 0; + } + + if (exclude_patterns_config && exclude_patterns_config->nr) { + for_each_string_list_item(item, exclude_patterns_config) { + if (match_ref_pattern(refname, item)) + return 0; + } + } + + return 1; +} + static int add_ref_decoration(const char *refname, const struct object_id *oid, int flags, void *cb_data) { struct object *obj; - enum decoration_type type = DECORATION_NONE; + enum object_type objtype; + enum decoration_type deco_type = DECORATION_NONE; struct decoration_filter *filter = (struct decoration_filter *)cb_data; - if (filter && !ref_filter_match(refname, - filter->include_ref_pattern, - filter->exclude_ref_pattern)) + if (filter && !ref_filter_match(refname, filter)) return 0; if (starts_with(refname, git_replace_ref_base)) { @@ -108,28 +156,29 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid, return 0; } - obj = parse_object(the_repository, oid); - if (!obj) + objtype = oid_object_info(the_repository, oid, NULL); + if (objtype < 0) return 0; + obj = lookup_object_by_type(the_repository, oid, objtype); if (starts_with(refname, "refs/heads/")) - type = DECORATION_REF_LOCAL; + deco_type = DECORATION_REF_LOCAL; else if (starts_with(refname, "refs/remotes/")) - type = DECORATION_REF_REMOTE; + deco_type = DECORATION_REF_REMOTE; else if (starts_with(refname, "refs/tags/")) - type = DECORATION_REF_TAG; + deco_type = DECORATION_REF_TAG; else if (!strcmp(refname, "refs/stash")) - type = DECORATION_REF_STASH; + deco_type = DECORATION_REF_STASH; else if (!strcmp(refname, "HEAD")) - type = DECORATION_REF_HEAD; + deco_type = DECORATION_REF_HEAD; - add_name_decoration(type, refname, obj); + add_name_decoration(deco_type, refname, obj); while (obj->type == OBJ_TAG) { + if (!obj->parsed) + parse_object(the_repository, &obj->oid); obj = ((struct tag *)obj)->tagged; if (!obj) break; - if (!obj->parsed) - parse_object(the_repository, &obj->oid); add_name_decoration(DECORATION_REF_TAG, refname, obj); } return 0; @@ -155,6 +204,9 @@ void load_ref_decorations(struct decoration_filter *filter, int flags) for_each_string_list_item(item, filter->include_ref_pattern) { normalize_glob_ref(item, NULL, item->string); } + for_each_string_list_item(item, filter->exclude_ref_config_pattern) { + normalize_glob_ref(item, NULL, item->string); + } } decoration_loaded = 1; decoration_flags = flags; @@ -317,10 +369,16 @@ void fmt_output_subject(struct strbuf *filename, const char *suffix = info->patch_suffix; int nr = info->nr; int start_len = filename->len; - int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1); + int max_len = start_len + info->patch_name_max - (strlen(suffix) + 1); + + if (info->reroll_count) { + struct strbuf temp = STRBUF_INIT; - if (0 < info->reroll_count) - strbuf_addf(filename, "v%d-", info->reroll_count); + strbuf_addf(&temp, "v%s", info->reroll_count); + format_sanitized_subject(filename, temp.buf, temp.len); + strbuf_addstr(filename, "-"); + strbuf_release(&temp); + } strbuf_addf(filename, "%04d-%s", nr, subject); if (max_len < filename->len) @@ -363,7 +421,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, { const char *extra_headers = opt->extra_headers; const char *name = oid_to_hex(opt->zero_commit ? - &null_oid : &commit->object.oid); + null_oid() : &commit->object.oid); *need_8bit_cte_p = 0; /* unknown */ @@ -449,22 +507,21 @@ static void show_signature(struct rev_info *opt, struct commit *commit) { struct strbuf payload = STRBUF_INIT; struct strbuf signature = STRBUF_INIT; - struct strbuf gpg_output = STRBUF_INIT; + struct signature_check sigc = { 0 }; int status; - if (parse_signed_commit(commit, &payload, &signature) <= 0) + if (parse_signed_commit(commit, &payload, &signature, the_hash_algo) <= 0) goto out; - status = verify_signed_buffer(payload.buf, payload.len, - signature.buf, signature.len, - &gpg_output, NULL); - if (status && !gpg_output.len) - strbuf_addstr(&gpg_output, "No signature\n"); - - show_sig_lines(opt, status, gpg_output.buf); + status = check_signature(payload.buf, payload.len, signature.buf, + signature.len, &sigc); + if (status && !sigc.gpg_output) + show_sig_lines(opt, status, "No signature\n"); + else + show_sig_lines(opt, status, sigc.gpg_output); + signature_check_clear(&sigc); out: - strbuf_release(&gpg_output); strbuf_release(&payload); strbuf_release(&signature); } @@ -497,10 +554,13 @@ static int show_one_mergetag(struct commit *commit, struct object_id oid; struct tag *tag; struct strbuf verify_message; + struct signature_check sigc = { 0 }; int status, nth; - size_t payload_size, gpg_message_offset; + struct strbuf payload = STRBUF_INIT; + struct strbuf signature = STRBUF_INIT; - hash_object_file(extra->value, extra->len, type_name(OBJ_TAG), &oid); + hash_object_file(the_hash_algo, extra->value, extra->len, + type_name(OBJ_TAG), &oid); tag = lookup_tag(the_repository, &oid); if (!tag) return -1; /* error message already given */ @@ -515,28 +575,28 @@ static int show_one_mergetag(struct commit *commit, "merged tag '%s'\n", tag->tag); else if ((nth = which_parent(&tag->tagged->oid, commit)) < 0) strbuf_addf(&verify_message, "tag %s names a non-parent %s\n", - tag->tag, tag->tagged->oid.hash); + tag->tag, oid_to_hex(&tag->tagged->oid)); else strbuf_addf(&verify_message, "parent #%d, tagged '%s'\n", nth + 1, tag->tag); - gpg_message_offset = verify_message.len; - payload_size = parse_signature(extra->value, extra->len); status = -1; - if (extra->len > payload_size) { + if (parse_signature(extra->value, extra->len, &payload, &signature)) { /* could have a good signature */ - if (!verify_signed_buffer(extra->value, payload_size, - extra->value + payload_size, - extra->len - payload_size, - &verify_message, NULL)) - status = 0; /* good */ - else if (verify_message.len <= gpg_message_offset) + status = check_signature(payload.buf, payload.len, + signature.buf, signature.len, &sigc); + if (sigc.gpg_output) + strbuf_addstr(&verify_message, sigc.gpg_output); + else strbuf_addstr(&verify_message, "No signature\n"); + signature_check_clear(&sigc); /* otherwise we couldn't verify, which is shown as bad */ } show_sig_lines(opt, status, verify_message.buf); strbuf_release(&verify_message); + strbuf_release(&payload); + strbuf_release(&signature); return 0; } @@ -692,6 +752,7 @@ void show_log(struct rev_info *opt) ctx.abbrev = opt->diffopt.abbrev; ctx.after_subject = extra_headers; ctx.preserve_subject = opt->preserve_subject; + ctx.encode_email_headers = opt->encode_email_headers; ctx.reflog_info = opt->reflog_info; ctx.fmt = opt->commit_format; ctx.mailmap = opt->mailmap; @@ -747,7 +808,8 @@ void show_log(struct rev_info *opt) next_commentary_block(opt, NULL); fprintf_ln(opt->diffopt.file, "%s", opt->idiff_title); - show_interdiff(opt, 2); + show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2, + &opt->diffopt); memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff)); } @@ -755,6 +817,11 @@ void show_log(struct rev_info *opt) if (cmit_fmt_is_mail(ctx.fmt) && opt->rdiff1) { struct diff_queue_struct dq; struct diff_options opts; + struct range_diff_options range_diff_opts = { + .creation_factor = opt->creation_factor, + .dual_color = 1, + .diffopt = &opts + }; memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); DIFF_QUEUE_CLEAR(&diff_queued_diff); @@ -769,8 +836,7 @@ void show_log(struct rev_info *opt) opts.file = opt->diffopt.file; opts.use_color = opt->diffopt.use_color; diff_setup_done(&opts); - show_range_diff(opt->rdiff1, opt->rdiff2, - opt->creation_factor, 1, &opts); + show_range_diff(opt->rdiff1, opt->rdiff2, &range_diff_opts); memcpy(&diff_queued_diff, &dq, sizeof(diff_queued_diff)); } @@ -832,7 +898,7 @@ int log_tree_diff_flush(struct rev_info *opt) static int do_diff_combined(struct rev_info *opt, struct commit *commit) { - diff_tree_combined_merge(commit, opt->dense_combined_merges, opt); + diff_tree_combined_merge(commit, opt); return !opt->loginfo; } @@ -846,15 +912,21 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log int showed_log; struct commit_list *parents; struct object_id *oid; + int is_merge; + int all_need_diff = opt->diff || opt->diffopt.flags.exit_with_status; - if (!opt->diff && !opt->diffopt.flags.exit_with_status) + if (!all_need_diff && !opt->merges_need_diff) return 0; parse_commit_or_die(commit); oid = get_commit_tree_oid(commit); - /* Root commit? */ parents = get_saved_parents(opt, commit); + is_merge = parents && parents->next; + if (!is_merge && !all_need_diff) + return 0; + + /* Root commit? */ if (!parents) { if (opt->show_root_diff) { diff_root_tree_oid(oid, "", &opt->diffopt); @@ -863,27 +935,16 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log return !opt->loginfo; } - /* More than one parent? */ - if (parents && parents->next) { - if (opt->ignore_merges) - return 0; - else if (opt->combine_merges) + if (is_merge) { + if (opt->combine_merges) return do_diff_combined(opt, commit); - else if (opt->first_parent_only) { - /* - * Generate merge log entry only for the first - * parent, showing summary diff of the others - * we merged _in_. - */ - parse_commit_or_die(parents->item); - diff_tree_oid(get_commit_tree_oid(parents->item), - oid, "", &opt->diffopt); - log_tree_diff_flush(opt); - return !opt->loginfo; - } - - /* If we show individual diffs, show the parent info */ - log->parent = parents->item; + if (opt->separate_merges) { + if (!opt->first_parent_merges) { + /* Show parent info for multiple diffs */ + log->parent = parents->item; + } + } else + return 0; } showed_log = 0; @@ -899,7 +960,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log /* Set up the log info for the next parent, if any.. */ parents = parents->next; - if (!parents) + if (!parents || opt->first_parent_merges) break; log->parent = parents->item; opt->loginfo = log; @@ -910,12 +971,14 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log int log_tree_commit(struct rev_info *opt, struct commit *commit) { struct log_info log; - int shown, close_file = opt->diffopt.close_file; + int shown; + /* maybe called by e.g. cmd_log_walk(), maybe stand-alone */ + int no_free = opt->diffopt.no_free; log.commit = commit; log.parent = NULL; opt->loginfo = &log; - opt->diffopt.close_file = 0; + opt->diffopt.no_free = 1; if (opt->line_level_traverse) return line_log_print(opt, commit); @@ -932,7 +995,7 @@ int log_tree_commit(struct rev_info *opt, struct commit *commit) fprintf(opt->diffopt.file, "\n%s\n", opt->break_bar); opt->loginfo = NULL; maybe_flush_or_die(opt->diffopt.file, "stdout"); - if (close_file) - fclose(opt->diffopt.file); + opt->diffopt.no_free = no_free; + diff_free(&opt->diffopt); return shown; } |