Beispiel #1
0
int not_pushed(struct commit *current_head){
  struct commit *remote_head;
  unsigned char sha1[20];
  const struct name_decoration decoration;
  int decoration_style=1;
  if (decoration_style) {
    load_ref_decorations(decoration_style);
  }

  decoration = get_name_decoration(&current_head->object);
  const char* upstream = (branch_get(NULL)->merge)?branch_get(NULL)->merge[0]->dst : NULL;
  if (upstream==NULL)
    return (int)true;

  if (get_sha1(upstream, sha1))
    remote_head = NULL;
  else {
    remote_head = lookup_commit_or_die(sha1, upstream);
    if (parse_commit(remote_head))
      die(_("could not parse remote head commit"));
  }

  struct commit *old_ci=remote_head,*new_ci=current_head;
  if (old_ci->date > new_ci->date){
    struct commit *tmp = old_ci;
    old_ci=new_ci;
    new_ci=tmp;
  }

}
Beispiel #2
0
static void cmd_log_init(int argc, const char **argv, const char *prefix,
		      struct rev_info *rev)
{
	int i;
	int decoration_style = 0;

	rev->abbrev = DEFAULT_ABBREV;
	rev->commit_format = CMIT_FMT_DEFAULT;
	if (fmt_pretty)
		get_commit_format(fmt_pretty, rev);
	rev->verbose_header = 1;
	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
	rev->show_root_diff = default_show_root;
	rev->subject_prefix = fmt_patch_subject_prefix;
	DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);

	if (default_date_mode)
		rev->date_mode = parse_date_format(default_date_mode);

	/*
	 * Check for -h before setup_revisions(), or "git log -h" will
	 * fail when run without a git directory.
	 */
	if (argc == 2 && !strcmp(argv[1], "-h"))
		usage(builtin_log_usage);
	argc = setup_revisions(argc, argv, rev, "HEAD");

	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
	if (DIFF_OPT_TST(&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 (!strcmp(arg, "--decorate")) {
			decoration_style = DECORATE_SHORT_REFS;
		} else if (!prefixcmp(arg, "--decorate=")) {
			const char *v = skip_prefix(arg, "--decorate=");
			if (!strcmp(v, "full"))
				decoration_style = DECORATE_FULL_REFS;
			else if (!strcmp(v, "short"))
				decoration_style = DECORATE_SHORT_REFS;
			else
				die("invalid --decorate option: %s", arg);
		} else if (!strcmp(arg, "--source")) {
			rev->show_source = 1;
		} else if (!strcmp(arg, "-h")) {
			usage(builtin_log_usage);
		} else
			die("unrecognized argument: %s", arg);
	}
	if (decoration_style) {
		rev->show_decorations = 1;
		load_ref_decorations(decoration_style);
	}
}
Beispiel #3
0
static void format_decoration(struct strbuf *sb, const struct commit *commit)
{
	struct name_decoration *d;
	const char *prefix = " (";

	load_ref_decorations(DECORATE_SHORT_REFS);
	d = lookup_decoration(&name_decoration, &commit->object);
	while (d) {
		strbuf_addstr(sb, prefix);
		prefix = ", ";
		strbuf_addstr(sb, d->name);
		d = d->next;
	}
	if (prefix[0] == ',')
		strbuf_addch(sb, ')');
}
Beispiel #4
0
static void cmd_log_init(int argc, const char **argv, const char *prefix,
		      struct rev_info *rev)
{
	int i;

	rev->abbrev = DEFAULT_ABBREV;
	rev->commit_format = CMIT_FMT_DEFAULT;
	if (fmt_pretty)
		get_commit_format(fmt_pretty, rev);
	rev->verbose_header = 1;
	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
	rev->show_root_diff = default_show_root;
	rev->subject_prefix = fmt_patch_subject_prefix;
	DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);

	if (default_date_mode)
		rev->date_mode = parse_date_format(default_date_mode);

	argc = setup_revisions(argc, argv, rev, "HEAD");

	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
	if (DIFF_OPT_TST(&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 (!strcmp(arg, "--decorate")) {
			load_ref_decorations();
			rev->show_decorations = 1;
		} else if (!strcmp(arg, "--source")) {
			rev->show_source = 1;
		} else
			die("unrecognized argument: %s", arg);
	}
}
Beispiel #5
0
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
			 struct rev_info *rev, struct setup_revision_opt *opt)
{
	struct userformat_want w;
	int quiet = 0, source = 0;

	const struct option builtin_log_options[] = {
		OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")),
		OPT_BOOLEAN(0, "source", &source, N_("show source")),
		{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
		  PARSE_OPT_OPTARG, decorate_callback},
		OPT_END()
	};

	argc = parse_options(argc, argv, prefix,
			     builtin_log_options, builtin_log_usage,
			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
			     PARSE_OPT_KEEP_DASHDASH);

	argc = setup_revisions(argc, argv, rev, opt);
	if (quiet)
		rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;

	/* Any arguments at this point are not recognized */
	if (argc > 1)
		die("unrecognized argument: %s", argv[1]);

	memset(&w, 0, sizeof(w));
	userformat_find_requirements(NULL, &w);

	if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
		rev->show_notes = 1;
	if (rev->show_notes)
		init_display_notes(&rev->notes_opt);

	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
	if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
		rev->always_show_header = 0;
		if (rev->diffopt.pathspec.nr != 1)
			usage("git logs can only follow renames on one pathname at a time");
	}

	if (source)
		rev->show_source = 1;

	if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
		/*
		 * "log --pretty=raw" is special; ignore UI oriented
		 * configuration variables such as decoration.
		 */
		if (!decoration_given)
			decoration_style = 0;
		if (!rev->abbrev_commit_given)
			rev->abbrev_commit = 0;
	}

	if (decoration_style) {
		rev->show_decorations = 1;
		load_ref_decorations(decoration_style);
	}
	setup_pager();
}
Beispiel #6
0
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
			 struct rev_info *rev, struct setup_revision_opt *opt)
{
	struct userformat_want w;
	int quiet = 0, source = 0, mailmap = 0;
	static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};

	const struct option builtin_log_options[] = {
		OPT__QUIET(&quiet, N_("suppress diff output")),
		OPT_BOOL(0, "source", &source, N_("show source")),
		OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
		{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
		  PARSE_OPT_OPTARG, decorate_callback},
		OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
			     N_("Process line range n,m in file, counting from 1"),
			     log_line_range_callback),
		OPT_END()
	};

	line_cb.rev = rev;
	line_cb.prefix = prefix;

	mailmap = use_mailmap_config;
	argc = parse_options(argc, argv, prefix,
			     builtin_log_options, builtin_log_usage,
			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
			     PARSE_OPT_KEEP_DASHDASH);

	if (quiet)
		rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;
	argc = setup_revisions(argc, argv, rev, opt);

	/* Any arguments at this point are not recognized */
	if (argc > 1)
		die(_("unrecognized argument: %s"), argv[1]);

	memset(&w, 0, sizeof(w));
	userformat_find_requirements(NULL, &w);

	if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
		rev->show_notes = 1;
	if (rev->show_notes)
		init_display_notes(&rev->notes_opt);

	if (rev->diffopt.pickaxe || rev->diffopt.filter ||
	    DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES))
		rev->always_show_header = 0;

	if (source)
		rev->show_source = 1;

	if (mailmap) {
		rev->mailmap = xcalloc(1, sizeof(struct string_list));
		read_mailmap(rev->mailmap, NULL);
	}

	if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {
		/*
		 * "log --pretty=raw" is special; ignore UI oriented
		 * configuration variables such as decoration.
		 */
		if (!decoration_given)
			decoration_style = 0;
		if (!rev->abbrev_commit_given)
			rev->abbrev_commit = 0;
	}

	if (decoration_style) {
		rev->show_decorations = 1;
		load_ref_decorations(decoration_style);
	}

	if (rev->line_level_traverse)
		line_log_init(rev, line_cb.prefix, &line_cb.args);

	setup_pager();
}
Beispiel #7
0
static void cmd_log_init(int argc, const char **argv, const char *prefix,
			 struct rev_info *rev, struct setup_revision_opt *opt)
{
	int i;
	int decoration_given = 0;
	struct userformat_want w;

	rev->abbrev = DEFAULT_ABBREV;
	rev->commit_format = CMIT_FMT_DEFAULT;
	if (fmt_pretty)
		get_commit_format(fmt_pretty, rev);
	rev->verbose_header = 1;
	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
	rev->show_root_diff = default_show_root;
	rev->subject_prefix = fmt_patch_subject_prefix;
	DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);

	if (default_date_mode)
		rev->date_mode = parse_date_format(default_date_mode);

	/*
	 * Check for -h before setup_revisions(), or "git log -h" will
	 * fail when run without a git directory.
	 */
	if (argc == 2 && !strcmp(argv[1], "-h"))
		usage(builtin_log_usage);
	argc = setup_revisions(argc, argv, rev, opt);

	memset(&w, 0, sizeof(w));
	userformat_find_requirements(NULL, &w);

	if (!rev->show_notes_given && (!rev->pretty_given || w.notes))
		rev->show_notes = 1;
	if (rev->show_notes)
		init_display_notes(&rev->notes_opt);

	if (rev->diffopt.pickaxe || rev->diffopt.filter)
		rev->always_show_header = 0;
	if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
		rev->always_show_header = 0;
		if (rev->diffopt.pathspec.nr != 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 (!strcmp(arg, "--decorate")) {
			decoration_style = DECORATE_SHORT_REFS;
			decoration_given = 1;
		} else if (!prefixcmp(arg, "--decorate=")) {
			const char *v = skip_prefix(arg, "--decorate=");
			decoration_style = parse_decoration_style(arg, v);
			if (decoration_style < 0)
				die("invalid --decorate option: %s", arg);
			decoration_given = 1;
		} else if (!strcmp(arg, "--no-decorate")) {
			decoration_style = 0;
		} else if (!strcmp(arg, "--source")) {
			rev->show_source = 1;
		} else if (!strcmp(arg, "-h")) {
			usage(builtin_log_usage);
		} else
			die("unrecognized argument: %s", arg);
	}

	/*
	 * defeat log.decorate configuration interacting with --pretty=raw
	 * from the command line.
	 */
	if (!decoration_given && rev->pretty_given
	    && rev->commit_format == CMIT_FMT_RAW)
		decoration_style = 0;

	if (decoration_style) {
		rev->show_decorations = 1;
		load_ref_decorations(decoration_style);
	}
	setup_pager();
}
Beispiel #8
0
void cgit_print_commit(char *hex, const char *prefix)
{
	struct commit *commit, *parent;
	struct commitinfo *info, *parent_info;
	struct commit_list *p;
	struct strbuf notes = STRBUF_INIT;
	unsigned char sha1[20];
	char *tmp, *tmp2;
	int parents = 0;

	if (!hex)
		hex = ctx.qry.head;

	if (get_sha1(hex, sha1)) {
		cgit_print_error("Bad object id: %s", hex);
		return;
	}
	commit = lookup_commit_reference(sha1);
	if (!commit) {
		cgit_print_error("Bad commit reference: %s", hex);
		return;
	}
	info = cgit_parse_commit(commit);

	format_display_notes(sha1, &notes, PAGE_ENCODING, 0);

	load_ref_decorations(DECORATE_FULL_REFS);

	cgit_print_diff_ctrls();
	html("<table summary='commit info' class='commit-info'>\n");
	html("<tr><th>author</th><td>");
	html_txt(info->author);
	if (!ctx.cfg.noplainemail) {
		html(" ");
		html_txt(info->author_email);
	}
	html("</td><td class='right'>");
	cgit_print_date(info->author_date, FMT_LONGDATE, ctx.cfg.local_time);
	html("</td></tr>\n");
	html("<tr><th>committer</th><td>");
	html_txt(info->committer);
	if (!ctx.cfg.noplainemail) {
		html(" ");
		html_txt(info->committer_email);
	}
	html("</td><td class='right'>");
	cgit_print_date(info->committer_date, FMT_LONGDATE, ctx.cfg.local_time);
	html("</td></tr>\n");
	html("<tr><th>commit</th><td colspan='2' class='sha1'>");
	tmp = sha1_to_hex(commit->object.sha1);
	cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
	html(" (");
	cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
	html(")</td></tr>\n");
	html("<tr><th>tree</th><td colspan='2' class='sha1'>");
	tmp = xstrdup(hex);
	cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL,
		       ctx.qry.head, tmp, NULL);
	if (prefix) {
		html(" /");
		cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tmp, prefix);
	}
	free(tmp);
	html("</td></tr>\n");
	for (p = commit->parents; p; p = p->next) {
		parent = lookup_commit_reference(p->item->object.sha1);
		if (!parent) {
			html("<tr><td colspan='3'>");
			cgit_print_error("Error reading parent commit");
			html("</td></tr>");
			continue;
		}
		html("<tr><th>parent</th>"
		     "<td colspan='2' class='sha1'>");
		tmp = tmp2 = sha1_to_hex(p->item->object.sha1);
		if (ctx.repo->enable_subject_links) {
			parent_info = cgit_parse_commit(parent);
			tmp2 = parent_info->subject;
		}
		cgit_commit_link(tmp2, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
		html(" (");
		cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex,
			       sha1_to_hex(p->item->object.sha1), prefix, 0);
		html(")</td></tr>");
		parents++;
	}
	if (ctx.repo->snapshots) {
		html("<tr><th>download</th><td colspan='2' class='sha1'>");
		cgit_print_snapshot_links(ctx.qry.repo, ctx.qry.head,
					  hex, ctx.repo->snapshots);
		html("</td></tr>");
	}
	html("</table>\n");
	html("<div class='commit-subject'>");
	if (ctx.repo->commit_filter)
		cgit_open_filter(ctx.repo->commit_filter);
	html_txt(info->subject);
	if (ctx.repo->commit_filter)
		cgit_close_filter(ctx.repo->commit_filter);
	show_commit_decorations(commit);
	html("</div>");
	html("<div class='commit-msg'>");
	if (ctx.repo->commit_filter)
		cgit_open_filter(ctx.repo->commit_filter);
	html_txt(info->msg);
	if (ctx.repo->commit_filter)
		cgit_close_filter(ctx.repo->commit_filter);
	html("</div>");
	if (notes.len != 0) {
		html("<div class='notes-header'>Notes</div>");
		html("<div class='notes'>");
		if (ctx.repo->commit_filter)
			cgit_open_filter(ctx.repo->commit_filter);
		html_txt(notes.buf);
		if (ctx.repo->commit_filter)
			cgit_close_filter(ctx.repo->commit_filter);
		html("</div>");
		html("<div class='notes-footer'></div>");
	}
	if (parents < 3) {
		if (parents)
			tmp = sha1_to_hex(commit->parents->item->object.sha1);
		else
			tmp = NULL;
		cgit_print_diff(ctx.qry.sha1, tmp, prefix, 0);
	}
	strbuf_release(&notes);
	cgit_free_commitinfo(info);
}
Beispiel #9
0
void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
		    char *path, int pager, int commit_graph, int log_order)
{
	struct rev_info rev;
	struct commit *commit;
	struct vector vec = VECTOR_INIT(char *);
	int i, columns = 3;
	char *arg;

	/* First argv is NULL */
	vector_push(&vec, NULL, 0);

	if (!tip)
		tip = ctx.qry.head;
	tip = disambiguate_ref(tip);
	vector_push(&vec, &tip, 0);

	if (grep && pattern && *pattern) {
		pattern = xstrdup(pattern);
		if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
		    !strcmp(grep, "committer")) {
			arg = fmt("--%s=%s", grep, pattern);
			vector_push(&vec, &arg, 0);
		}
		if (!strcmp(grep, "range")) {
			/* Split the pattern at whitespace and add each token
			 * as a revision expression. Do not accept other
			 * rev-list options. Also, replace the previously
			 * pushed tip (it's no longer relevant).
			 */
			vec.count--;
			while ((arg = next_token(&pattern))) {
				if (*arg == '-') {
					fprintf(stderr, "Bad range expr: %s\n",
						arg);
					break;
				}
				vector_push(&vec, &arg, 0);
			}
		}
	}
	if (commit_graph) {
		static const char *graph_arg = "--graph";
		static const char *color_arg = "--color";
		vector_push(&vec, &graph_arg, 0);
		vector_push(&vec, &color_arg, 0);
		graph_set_column_colors(column_colors_html,
					COLUMN_COLORS_HTML_MAX);
	}

	if (log_order == 1) {
		static const char *date_order_arg = "--date-order";
		vector_push(&vec, &date_order_arg, 0);
	} else if (log_order == 2) {
		static const char *topo_order_arg = "--topo-order";
		vector_push(&vec, &topo_order_arg, 0);
	}

	if (path) {
		arg = "--";
		vector_push(&vec, &arg, 0);
		vector_push(&vec, &path, 0);
	}

	/* Make sure the vector is NULL-terminated */
	vector_push(&vec, NULL, 0);
	vec.count--;

	init_revisions(&rev, NULL);
	rev.abbrev = DEFAULT_ABBREV;
	rev.commit_format = CMIT_FMT_DEFAULT;
	rev.verbose_header = 1;
	rev.show_root_diff = 0;
	setup_revisions(vec.count, vec.data, &rev, NULL);
	load_ref_decorations(DECORATE_FULL_REFS);
	rev.show_decorations = 1;
	rev.grep_filter.regflags |= REG_ICASE;
	compile_grep_patterns(&rev.grep_filter);
	prepare_revision_walk(&rev);

	if (pager)
		html("<table class='list nowrap'>");

	html("<tr class='nohover'>");
	if (commit_graph)
		html("<th></th>");
	else
		html("<th class='left'>Age</th>");
	html("<th class='left'>Commit message");
	if (pager) {
		html(" (");
		cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
			      NULL, ctx.qry.head, ctx.qry.sha1,
			      ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
			      ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
		html(")");
	}
	html("</th><th class='left'>Author</th>");
	if (commit_graph)
		html("<th class='left'>Age</th>");
	if (ctx.repo->enable_log_filecount) {
		html("<th class='left'>Files</th>");
		columns++;
	}
	if (ctx.repo->enable_log_linecount) {
		html("<th class='left'>Lines</th>");
		columns++;
	}
	html("</tr>\n");

	if (ofs<0)
		ofs = 0;

	for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) {
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}

	for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) {
		print_commit(commit, &rev);
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}
	if (pager) {
		html("</table><div class='pager'>");
		if (ofs > 0) {
			cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs - cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
			html("&nbsp;");
		}
		if ((commit = get_revision(&rev)) != NULL) {
			cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs + cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
		}
		html("</div>");
	} else if ((commit = get_revision(&rev)) != NULL) {
		html("<tr class='nohover'><td colspan='3'>");
		cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
			      ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
		html("</td></tr>\n");
	}
}
Beispiel #10
0
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
				const char *placeholder,
				void *context)
{
	struct format_commit_context *c = context;
	const struct commit *commit = c->commit;
	const char *msg = c->message;
	struct commit_list *p;
	int h1, h2;

	/* these are independent of the commit */
	switch (placeholder[0]) {
	case 'C':
		if (starts_with(placeholder + 1, "(auto)")) {
			c->auto_color = 1;
			return 7; /* consumed 7 bytes, "C(auto)" */
		} else {
			int ret = parse_color(sb, placeholder, c);
			if (ret)
				c->auto_color = 0;
			/*
			 * Otherwise, we decided to treat %C<unknown>
			 * as a literal string, and the previous
			 * %C(auto) is still valid.
			 */
			return ret;
		}
	case 'n':		/* newline */
		strbuf_addch(sb, '\n');
		return 1;
	case 'x':
		/* %x00 == NUL, %x0a == LF, etc. */
		if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) &&
		    h1 <= 16 &&
		    0 <= (h2 = hexval_table[0xff & placeholder[2]]) &&
		    h2 <= 16) {
			strbuf_addch(sb, (h1<<4)|h2);
			return 3;
		} else
			return 0;
	case 'w':
		if (placeholder[1] == '(') {
			unsigned long width = 0, indent1 = 0, indent2 = 0;
			char *next;
			const char *start = placeholder + 2;
			const char *end = strchr(start, ')');
			if (!end)
				return 0;
			if (end > start) {
				width = strtoul(start, &next, 10);
				if (*next == ',') {
					indent1 = strtoul(next + 1, &next, 10);
					if (*next == ',') {
						indent2 = strtoul(next + 1,
								 &next, 10);
					}
				}
				if (*next != ')')
					return 0;
			}
			rewrap_message_tail(sb, c, width, indent1, indent2);
			return end - placeholder + 1;
		} else
			return 0;

	case '<':
	case '>':
		return parse_padding_placeholder(sb, placeholder, c);
	}

	/* these depend on the commit */
	if (!commit->object.parsed)
		parse_object(commit->object.sha1);

	switch (placeholder[0]) {
	case 'H':		/* commit hash */
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
		strbuf_addstr(sb, sha1_to_hex(commit->object.sha1));
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
		return 1;
	case 'h':		/* abbreviated commit hash */
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
		if (add_again(sb, &c->abbrev_commit_hash)) {
			strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
			return 1;
		}
		strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1,
						     c->pretty_ctx->abbrev));
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
		c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
		return 1;
	case 'T':		/* tree hash */
		strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1));
		return 1;
	case 't':		/* abbreviated tree hash */
		if (add_again(sb, &c->abbrev_tree_hash))
			return 1;
		strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1,
						     c->pretty_ctx->abbrev));
		c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
		return 1;
	case 'P':		/* parent hashes */
		for (p = commit->parents; p; p = p->next) {
			if (p != commit->parents)
				strbuf_addch(sb, ' ');
			strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1));
		}
		return 1;
	case 'p':		/* abbreviated parent hashes */
		if (add_again(sb, &c->abbrev_parent_hashes))
			return 1;
		for (p = commit->parents; p; p = p->next) {
			if (p != commit->parents)
				strbuf_addch(sb, ' ');
			strbuf_addstr(sb, find_unique_abbrev(
					p->item->object.sha1,
					c->pretty_ctx->abbrev));
		}
		c->abbrev_parent_hashes.len = sb->len -
		                              c->abbrev_parent_hashes.off;
		return 1;
	case 'm':		/* left/right/bottom */
		strbuf_addstr(sb, get_revision_mark(NULL, commit));
		return 1;
	case 'd':
		load_ref_decorations(DECORATE_SHORT_REFS);
		format_decorations(sb, commit, c->auto_color);
		return 1;
	case 'g':		/* reflog info */
		switch(placeholder[1]) {
		case 'd':	/* reflog selector */
		case 'D':
			if (c->pretty_ctx->reflog_info)
				get_reflog_selector(sb,
						    c->pretty_ctx->reflog_info,
						    c->pretty_ctx->date_mode,
						    c->pretty_ctx->date_mode_explicit,
						    (placeholder[1] == 'd'));
			return 2;
		case 's':	/* reflog message */
			if (c->pretty_ctx->reflog_info)
				get_reflog_message(sb, c->pretty_ctx->reflog_info);
			return 2;
		case 'n':
		case 'N':
		case 'e':
		case 'E':
			return format_reflog_person(sb,
						    placeholder[1],
						    c->pretty_ctx->reflog_info,
						    c->pretty_ctx->date_mode);
		}
		return 0;	/* unknown %g placeholder */
	case 'N':
		if (c->pretty_ctx->notes_message) {
			strbuf_addstr(sb, c->pretty_ctx->notes_message);
			return 1;
		}
		return 0;
	}

	if (placeholder[0] == 'G') {
		if (!c->signature_check.result)
			check_commit_signature(c->commit, &(c->signature_check));
		switch (placeholder[1]) {
		case 'G':
			if (c->signature_check.gpg_output)
				strbuf_addstr(sb, c->signature_check.gpg_output);
			break;
		case '?':
			switch (c->signature_check.result) {
			case 'G':
			case 'B':
			case 'U':
			case 'N':
				strbuf_addch(sb, c->signature_check.result);
			}
			break;
		case 'S':
			if (c->signature_check.signer)
				strbuf_addstr(sb, c->signature_check.signer);
			break;
		case 'K':
			if (c->signature_check.key)
				strbuf_addstr(sb, c->signature_check.key);
			break;
		default:
			return 0;
		}
		return 2;
	}


	/* For the rest we have to parse the commit header. */
	if (!c->commit_header_parsed)
		parse_commit_header(c);

	switch (placeholder[0]) {
	case 'a':	/* author ... */
		return format_person_part(sb, placeholder[1],
				   msg + c->author.off, c->author.len,
				   c->pretty_ctx->date_mode);
	case 'c':	/* committer ... */
		return format_person_part(sb, placeholder[1],
				   msg + c->committer.off, c->committer.len,
				   c->pretty_ctx->date_mode);
	case 'e':	/* encoding */
		if (c->commit_encoding)
			strbuf_addstr(sb, c->commit_encoding);
		return 1;
	case 'B':	/* raw body */
		/* message_off is always left at the initial newline */
		strbuf_addstr(sb, msg + c->message_off + 1);
		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 'f':	/* sanitized subject */
		format_sanitized_subject(sb, msg + c->subject_off);
		return 1;
	case 'b':	/* body */
		strbuf_addstr(sb, msg + c->body_off);
		return 1;
	}
	return 0;	/* unknown placeholder */
}
Beispiel #11
0
static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
			       int *unkc, const char **unkv)
{
	const char *arg = argv[0];

	/* pseudo revision arguments */
	if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
	    !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
	    !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
	    !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk"))
	{
		unkv[(*unkc)++] = arg;
		return 1;
	}

	if (!prefixcmp(arg, "--max-count=")) {
		revs->max_count = atoi(arg + 12);
	} else if (!prefixcmp(arg, "--skip=")) {
		revs->skip_count = atoi(arg + 7);
	} else if ((*arg == '-') && isdigit(arg[1])) {
	/* accept -<digit>, like traditional "head" */
		revs->max_count = atoi(arg + 1);
	} else if (!strcmp(arg, "-n")) {
		if (argc <= 1)
			return error("-n requires an argument");
		revs->max_count = atoi(argv[1]);
		return 2;
	} else if (!prefixcmp(arg, "-n")) {
		revs->max_count = atoi(arg + 2);
	} else if (!prefixcmp(arg, "--max-age=")) {
		revs->max_age = atoi(arg + 10);
	} else if (!prefixcmp(arg, "--since=")) {
		revs->max_age = approxidate(arg + 8);
	} else if (!prefixcmp(arg, "--after=")) {
		revs->max_age = approxidate(arg + 8);
	} else if (!prefixcmp(arg, "--min-age=")) {
		revs->min_age = atoi(arg + 10);
	} else if (!prefixcmp(arg, "--before=")) {
		revs->min_age = approxidate(arg + 9);
	} else if (!prefixcmp(arg, "--until=")) {
		revs->min_age = approxidate(arg + 8);
	} else if (!strcmp(arg, "--first-parent")) {
		revs->first_parent_only = 1;
	} else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
		init_reflog_walk(&revs->reflog_info);
	} else if (!strcmp(arg, "--default")) {
		if (argc <= 1)
			return error("bad --default argument");
		revs->def = argv[1];
		return 2;
	} else if (!strcmp(arg, "--merge")) {
		revs->show_merge = 1;
	} else if (!strcmp(arg, "--topo-order")) {
		revs->lifo = 1;
		revs->topo_order = 1;
	} else if (!strcmp(arg, "--simplify-merges")) {
		revs->simplify_merges = 1;
		revs->rewrite_parents = 1;
		revs->simplify_history = 0;
		revs->limited = 1;
	} else if (!strcmp(arg, "--simplify-by-decoration")) {
		revs->simplify_merges = 1;
		revs->rewrite_parents = 1;
		revs->simplify_history = 0;
		revs->simplify_by_decoration = 1;
		revs->limited = 1;
		revs->prune = 1;
		load_ref_decorations();
	} else if (!strcmp(arg, "--date-order")) {
		revs->lifo = 0;
		revs->topo_order = 1;
	} else if (!prefixcmp(arg, "--early-output")) {
		int count = 100;
		switch (arg[14]) {
		case '=':
			count = atoi(arg+15);
			/* Fallthrough */
		case 0:
			revs->topo_order = 1;
		       revs->early_output = count;
		}
	} else if (!strcmp(arg, "--parents")) {
		revs->rewrite_parents = 1;
		revs->print_parents = 1;
	} else if (!strcmp(arg, "--dense")) {
		revs->dense = 1;
	} else if (!strcmp(arg, "--sparse")) {
		revs->dense = 0;
	} else if (!strcmp(arg, "--show-all")) {
		revs->show_all = 1;
	} else if (!strcmp(arg, "--remove-empty")) {
		revs->remove_empty_trees = 1;
	} else if (!strcmp(arg, "--merges")) {
		revs->merges_only = 1;
	} else if (!strcmp(arg, "--no-merges")) {
		revs->no_merges = 1;
	} else if (!strcmp(arg, "--boundary")) {
		revs->boundary = 1;
	} else if (!strcmp(arg, "--left-right")) {
		revs->left_right = 1;
	} else if (!strcmp(arg, "--cherry-pick")) {
		revs->cherry_pick = 1;
		revs->limited = 1;
	} else if (!strcmp(arg, "--objects")) {
		revs->tag_objects = 1;
		revs->tree_objects = 1;
		revs->blob_objects = 1;
	} else if (!strcmp(arg, "--objects-edge")) {
		revs->tag_objects = 1;
		revs->tree_objects = 1;
		revs->blob_objects = 1;
		revs->edge_hint = 1;
	} else if (!strcmp(arg, "--unpacked")) {
		revs->unpacked = 1;
	} else if (!prefixcmp(arg, "--unpacked=")) {
		die("--unpacked=<packfile> no longer supported.");
	} else if (!strcmp(arg, "-r")) {
		revs->diff = 1;
		DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
	} else if (!strcmp(arg, "-t")) {
		revs->diff = 1;
		DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
		DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
	} else if (!strcmp(arg, "-m")) {
		revs->ignore_merges = 0;
	} else if (!strcmp(arg, "-c")) {
		revs->diff = 1;
		revs->dense_combined_merges = 0;
		revs->combine_merges = 1;
	} else if (!strcmp(arg, "--cc")) {
		revs->diff = 1;
		revs->dense_combined_merges = 1;
		revs->combine_merges = 1;
	} else if (!strcmp(arg, "-v")) {
		revs->verbose_header = 1;
	} else if (!strcmp(arg, "--pretty")) {
		revs->verbose_header = 1;
		get_commit_format(arg+8, revs);
	} else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) {
		revs->verbose_header = 1;
		get_commit_format(arg+9, revs);
	} else if (!strcmp(arg, "--oneline")) {
		revs->verbose_header = 1;
		get_commit_format("oneline", revs);
		revs->abbrev_commit = 1;
	} else if (!strcmp(arg, "--graph")) {
		revs->topo_order = 1;
		revs->rewrite_parents = 1;
		revs->graph = graph_init(revs);
	} else if (!strcmp(arg, "--root")) {
		revs->show_root_diff = 1;
	} else if (!strcmp(arg, "--no-commit-id")) {
		revs->no_commit_id = 1;
	} else if (!strcmp(arg, "--always")) {
		revs->always_show_header = 1;
	} else if (!strcmp(arg, "--no-abbrev")) {
		revs->abbrev = 0;
	} else if (!strcmp(arg, "--abbrev")) {
		revs->abbrev = DEFAULT_ABBREV;
	} else if (!prefixcmp(arg, "--abbrev=")) {
		revs->abbrev = strtoul(arg + 9, NULL, 10);
		if (revs->abbrev < MINIMUM_ABBREV)
			revs->abbrev = MINIMUM_ABBREV;
		else if (revs->abbrev > 40)
			revs->abbrev = 40;
	} else if (!strcmp(arg, "--abbrev-commit")) {
		revs->abbrev_commit = 1;
	} else if (!strcmp(arg, "--full-diff")) {
		revs->diff = 1;
		revs->full_diff = 1;
	} else if (!strcmp(arg, "--full-history")) {
		revs->simplify_history = 0;
	} else if (!strcmp(arg, "--relative-date")) {
		revs->date_mode = DATE_RELATIVE;
	} else if (!strncmp(arg, "--date=", 7)) {
		revs->date_mode = parse_date_format(arg + 7);
	} else if (!strcmp(arg, "--log-size")) {
		revs->show_log_size = 1;
	}
	/*
	 * Grepping the commit log
	 */
	else if (!prefixcmp(arg, "--author=")) {
		add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
	} else if (!prefixcmp(arg, "--committer=")) {
		add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
	} else if (!prefixcmp(arg, "--grep=")) {
		add_message_grep(revs, arg+7);
	} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
		revs->grep_filter.regflags |= REG_EXTENDED;
	} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
		revs->grep_filter.regflags |= REG_ICASE;
	} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
		revs->grep_filter.fixed = 1;
	} else if (!strcmp(arg, "--all-match")) {
		revs->grep_filter.all_match = 1;
	} else 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, "--reverse")) {
		revs->reverse ^= 1;
	} else if (!strcmp(arg, "--children")) {
		revs->children.name = "children";
		revs->limited = 1;
	} else {
		int opts = diff_opt_parse(&revs->diffopt, argv, argc);
		if (!opts)
			unkv[(*unkc)++] = arg;
		return opts;
	}

	return 1;
}
Beispiel #12
0
void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
		    char *path, int pager)
{
	struct rev_info rev;
	struct commit *commit;
	const char *argv[] = {NULL, NULL, NULL, NULL, NULL};
	int argc = 2;
	int i, columns = 3;

	if (!tip)
		tip = ctx.qry.head;

	argv[1] = disambiguate_ref(tip);

	if (grep && pattern) {
		if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
		    !strcmp(grep, "committer"))
			argv[argc++] = fmt("--%s=%s", grep, pattern);
		if (!strcmp(grep, "range"))
			argv[1] = pattern;
	}

	if (path) {
		argv[argc++] = "--";
		argv[argc++] = path;
	}
	init_revisions(&rev, NULL);
	rev.abbrev = DEFAULT_ABBREV;
	rev.commit_format = CMIT_FMT_DEFAULT;
	rev.verbose_header = 1;
	rev.show_root_diff = 0;
	setup_revisions(argc, argv, &rev, NULL);
	load_ref_decorations(DECORATE_FULL_REFS);
	rev.show_decorations = 1;
	rev.grep_filter.regflags |= REG_ICASE;
	compile_grep_patterns(&rev.grep_filter);
	prepare_revision_walk(&rev);

	if (pager)
		html("<table class='list nowrap'>");

	html("<tr class='nohover'><th class='left'>Age</th>"
	      "<th class='left'>Commit message");
	if (pager) {
		html(" (");
		cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
			      NULL, ctx.qry.head, ctx.qry.sha1,
			      ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
			      ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
		html(")");
	}
	html("</th><th class='left'>Author</th>");
	if (ctx.repo->enable_log_filecount) {
		html("<th class='left'>Files</th>");
		columns++;
		if (ctx.repo->enable_log_linecount) {
			html("<th class='left'>Lines</th>");
			columns++;
		}
	}
	html("</tr>\n");

	if (ofs<0)
		ofs = 0;

	for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) {
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}

	for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) {
		print_commit(commit);
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}
	if (pager) {
		htmlf("</table><div class='pager'>",
		     columns);
		if (ofs > 0) {
			cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs - cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
			html("&nbsp;");
		}
		if ((commit = get_revision(&rev)) != NULL) {
			cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs + cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
		}
		html("</div>");
	} else if ((commit = get_revision(&rev)) != NULL) {
		html("<tr class='nohover'><td colspan='3'>");
		cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
			      ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
		html("</td></tr>\n");
	}
}
Beispiel #13
0
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
				const char *placeholder,
				void *context)
{
	struct format_commit_context *c = context;
	const struct commit *commit = c->commit;
	const char *msg = c->message;
	struct commit_list *p;
	const char *arg;
	int ch;

	/* these are independent of the commit */
	switch (placeholder[0]) {
	case 'C':
		if (starts_with(placeholder + 1, "(auto)")) {
			c->auto_color = want_color(c->pretty_ctx->color);
			if (c->auto_color && sb->len)
				strbuf_addstr(sb, GIT_COLOR_RESET);
			return 7; /* consumed 7 bytes, "C(auto)" */
		} else {
			int ret = parse_color(sb, placeholder, c);
			if (ret)
				c->auto_color = 0;
			/*
			 * Otherwise, we decided to treat %C<unknown>
			 * as a literal string, and the previous
			 * %C(auto) is still valid.
			 */
			return ret;
		}
	case 'n':		/* newline */
		strbuf_addch(sb, '\n');
		return 1;
	case 'x':
		/* %x00 == NUL, %x0a == LF, etc. */
		ch = hex2chr(placeholder + 1);
		if (ch < 0)
			return 0;
		strbuf_addch(sb, ch);
		return 3;
	case 'w':
		if (placeholder[1] == '(') {
			unsigned long width = 0, indent1 = 0, indent2 = 0;
			char *next;
			const char *start = placeholder + 2;
			const char *end = strchr(start, ')');
			if (!end)
				return 0;
			if (end > start) {
				width = strtoul(start, &next, 10);
				if (*next == ',') {
					indent1 = strtoul(next + 1, &next, 10);
					if (*next == ',') {
						indent2 = strtoul(next + 1,
								 &next, 10);
					}
				}
				if (*next != ')')
					return 0;
			}
			rewrap_message_tail(sb, c, width, indent1, indent2);
			return end - placeholder + 1;
		} else
			return 0;

	case '<':
	case '>':
		return parse_padding_placeholder(sb, placeholder, c);
	}

	/* these depend on the commit */
	if (!commit->object.parsed)
		parse_object(&commit->object.oid);

	switch (placeholder[0]) {
	case 'H':		/* commit hash */
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
		strbuf_addstr(sb, oid_to_hex(&commit->object.oid));
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
		return 1;
	case 'h':		/* abbreviated commit hash */
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT));
		strbuf_add_unique_abbrev(sb, &commit->object.oid,
					 c->pretty_ctx->abbrev);
		strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
		return 1;
	case 'T':		/* tree hash */
		strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit)));
		return 1;
	case 't':		/* abbreviated tree hash */
		strbuf_add_unique_abbrev(sb,
					 get_commit_tree_oid(commit),
					 c->pretty_ctx->abbrev);
		return 1;
	case 'P':		/* parent hashes */
		for (p = commit->parents; p; p = p->next) {
			if (p != commit->parents)
				strbuf_addch(sb, ' ');
			strbuf_addstr(sb, oid_to_hex(&p->item->object.oid));
		}
		return 1;
	case 'p':		/* abbreviated parent hashes */
		for (p = commit->parents; p; p = p->next) {
			if (p != commit->parents)
				strbuf_addch(sb, ' ');
			strbuf_add_unique_abbrev(sb, &p->item->object.oid,
						 c->pretty_ctx->abbrev);
		}
		return 1;
	case 'm':		/* left/right/bottom */
		strbuf_addstr(sb, get_revision_mark(NULL, commit));
		return 1;
	case 'd':
		load_ref_decorations(NULL, DECORATE_SHORT_REFS);
		format_decorations(sb, commit, c->auto_color);
		return 1;
	case 'D':
		load_ref_decorations(NULL, DECORATE_SHORT_REFS);
		format_decorations_extended(sb, commit, c->auto_color, "", ", ", "");
		return 1;
	case 'g':		/* reflog info */
		switch(placeholder[1]) {
		case 'd':	/* reflog selector */
		case 'D':
			if (c->pretty_ctx->reflog_info)
				get_reflog_selector(sb,
						    c->pretty_ctx->reflog_info,
						    &c->pretty_ctx->date_mode,
						    c->pretty_ctx->date_mode_explicit,
						    (placeholder[1] == 'd'));
			return 2;
		case 's':	/* reflog message */
			if (c->pretty_ctx->reflog_info)
				get_reflog_message(sb, c->pretty_ctx->reflog_info);
			return 2;
		case 'n':
		case 'N':
		case 'e':
		case 'E':
			return format_reflog_person(sb,
						    placeholder[1],
						    c->pretty_ctx->reflog_info,
						    &c->pretty_ctx->date_mode);
		}
		return 0;	/* unknown %g placeholder */
	case 'N':
		if (c->pretty_ctx->notes_message) {
			strbuf_addstr(sb, c->pretty_ctx->notes_message);
			return 1;
		}
		return 0;
	}

	if (placeholder[0] == 'G') {
		if (!c->signature_check.result)
			check_commit_signature(c->commit, &(c->signature_check));
		switch (placeholder[1]) {
		case 'G':
			if (c->signature_check.gpg_output)
				strbuf_addstr(sb, c->signature_check.gpg_output);
			break;
		case '?':
			switch (c->signature_check.result) {
			case 'G':
			case 'B':
			case 'E':
			case 'U':
			case 'N':
			case 'X':
			case 'Y':
			case 'R':
				strbuf_addch(sb, c->signature_check.result);
			}
			break;
		case 'S':
			if (c->signature_check.signer)
				strbuf_addstr(sb, c->signature_check.signer);
			break;
		case 'K':
			if (c->signature_check.key)
				strbuf_addstr(sb, c->signature_check.key);
			break;
		default:
			return 0;
		}
		return 2;
	}


	/* For the rest we have to parse the commit header. */
	if (!c->commit_header_parsed)
		parse_commit_header(c);

	switch (placeholder[0]) {
	case 'a':	/* author ... */
		return format_person_part(sb, placeholder[1],
				   msg + c->author.off, c->author.len,
				   &c->pretty_ctx->date_mode);
	case 'c':	/* committer ... */
		return format_person_part(sb, placeholder[1],
				   msg + c->committer.off, c->committer.len,
				   &c->pretty_ctx->date_mode);
	case 'e':	/* encoding */
		if (c->commit_encoding)
			strbuf_addstr(sb, c->commit_encoding);
		return 1;
	case 'B':	/* raw body */
		/* message_off is always left at the initial newline */
		strbuf_addstr(sb, msg + c->message_off + 1);
		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 'f':	/* sanitized subject */
		format_sanitized_subject(sb, msg + c->subject_off);
		return 1;
	case 'b':	/* body */
		strbuf_addstr(sb, msg + c->body_off);
		return 1;
	}

	if (skip_prefix(placeholder, "(trailers", &arg)) {
		struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
		if (*arg == ':') {
			arg++;
			for (;;) {
				if (match_placeholder_arg(arg, "only", &arg))
					opts.only_trailers = 1;
				else if (match_placeholder_arg(arg, "unfold", &arg))
					opts.unfold = 1;
				else
					break;
			}
		}
		if (*arg == ')') {
			format_trailers_from_commit(sb, msg + c->subject_off, &opts);
			return arg - placeholder + 1;
		}
	}

	return 0;	/* unknown placeholder */
}
Beispiel #14
0
void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
		    char *path, int pager, int commit_graph, int commit_sort)
{
	struct rev_info rev;
	struct commit *commit;
	struct argv_array rev_argv = ARGV_ARRAY_INIT;
	int i, columns = commit_graph ? 4 : 3;
	int must_free_tip = 0;

	/* rev_argv.argv[0] will be ignored by setup_revisions */
	argv_array_push(&rev_argv, "log_rev_setup");

	if (!tip)
		tip = ctx.qry.head;
	tip = disambiguate_ref(tip, &must_free_tip);
	argv_array_push(&rev_argv, tip);

	if (grep && pattern && *pattern) {
		pattern = xstrdup(pattern);
		if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
		    !strcmp(grep, "committer")) {
			argv_array_pushf(&rev_argv, "--%s=%s", grep, pattern);
		} else if (!strcmp(grep, "range")) {
			char *arg;
			/* Split the pattern at whitespace and add each token
			 * as a revision expression. Do not accept other
			 * rev-list options. Also, replace the previously
			 * pushed tip (it's no longer relevant).
			 */
			argv_array_pop(&rev_argv);
			while ((arg = next_token(&pattern))) {
				if (*arg == '-') {
					fprintf(stderr, "Bad range expr: %s\n",
						arg);
					break;
				}
				argv_array_push(&rev_argv, arg);
			}
		}
	}
	if (commit_graph) {
		argv_array_push(&rev_argv, "--graph");
		argv_array_push(&rev_argv, "--color");
		graph_set_column_colors(column_colors_html,
					COLUMN_COLORS_HTML_MAX);
	}

	if (commit_sort == 1)
		argv_array_push(&rev_argv, "--date-order");
	else if (commit_sort == 2)
		argv_array_push(&rev_argv, "--topo-order");

	if (path) {
		argv_array_push(&rev_argv, "--");
		argv_array_push(&rev_argv, path);
	}

	init_revisions(&rev, NULL);
	rev.abbrev = DEFAULT_ABBREV;
	rev.commit_format = CMIT_FMT_DEFAULT;
	rev.verbose_header = 1;
	rev.show_root_diff = 0;
	setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL);
	load_ref_decorations(DECORATE_FULL_REFS);
	rev.show_decorations = 1;
	rev.grep_filter.regflags |= REG_ICASE;
	compile_grep_patterns(&rev.grep_filter);
	prepare_revision_walk(&rev);

	if (pager)
		html("<table class='list nowrap'>");

	html("<tr class='nohover'>");
	if (commit_graph)
		html("<th></th>");
	else
		html("<th class='left'>Age</th>");
	html("<th class='left'>Commit message");
	if (pager) {
		html(" (");
		cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
			      NULL, ctx.qry.head, ctx.qry.sha1,
			      ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
			      ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
		html(")");
	}
	html("</th><th class='left'>Author</th>");
	if (commit_graph)
		html("<th class='left'>Age</th>");
	if (ctx.repo->enable_log_filecount) {
		html("<th class='left'>Files</th>");
		columns++;
	}
	if (ctx.repo->enable_log_linecount) {
		html("<th class='left'>Lines</th>");
		columns++;
	}
	html("</tr>\n");

	if (ofs<0)
		ofs = 0;

	for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) {
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}

	for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) {
		print_commit(commit, &rev);
		free(commit->buffer);
		commit->buffer = NULL;
		free_commit_list(commit->parents);
		commit->parents = NULL;
	}
	if (pager) {
		html("</table><ul class='pager'>");
		if (ofs > 0) {
			html("<li>");
			cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs - cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
			html("</li>");
		}
		if ((commit = get_revision(&rev)) != NULL) {
			html("<li>");
			cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
				      ctx.qry.sha1, ctx.qry.vpath,
				      ofs + cnt, ctx.qry.grep,
				      ctx.qry.search, ctx.qry.showmsg);
			html("</li>");
		}
		html("</ul>");
	} else if ((commit = get_revision(&rev)) != NULL) {
		htmlf("<tr class='nohover'><td colspan='%d'>", columns);
		cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
			      ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
		html("</td></tr>\n");
	}

	/* If we allocated tip then it is safe to cast away const. */
	if (must_free_tip)
		free((char*) tip);
}