[PATCH] Add --pretty=changelog

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This outputs the log in GNU ChangeLog format.

Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx>
---
 commit.c   |   18 +++++++++++---
 commit.h   |    1 +
 diff.c     |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 diff.h     |    1 +
 log-tree.c |   17 ++++++++++++-
 revision.c |    6 ++++
 6 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/commit.c b/commit.c
index fb75ae5..64ddb56 100644
--- a/commit.c
+++ b/commit.c
@@ -38,6 +38,7 @@ struct cmt_fmt_map {
 	{ "fuller",	5,	CMIT_FMT_FULLER },
 	{ "oneline",	1,	CMIT_FMT_ONELINE },
 	{ "format:",	7,	CMIT_FMT_USERFORMAT},
+	{ "changelog",	9,	CMIT_FMT_CHANGELOG}
 };
 
 static char *user_format;
@@ -563,6 +564,8 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,
 		ret += namelen - display_name_length;
 		buf[ret++] = '\n';
 	}
+	else if (fmt == CMIT_FMT_CHANGELOG)
+		ret = 0;
 	else {
 		ret = sprintf(buf, "%s: %.*s%.*s\n", what,
 			      (fmt == CMIT_FMT_FULLER) ? 4 : 0,
@@ -581,6 +584,11 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,
 		ret += sprintf(buf + ret, "%sDate: %s\n", what,
 			       show_date(time, tz, relative_date));
 		break;
+	case CMIT_FMT_CHANGELOG:
+		ret += sprintf(buf + ret, "%s  %.*s\n",
+				show_date(time, tz, DATE_SHORT),
+				namelen, line);
+		break;
 	default:
 		/* notin' */
 		break;
@@ -603,7 +611,7 @@ static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *com
 	int offset;
 
 	if ((fmt == CMIT_FMT_ONELINE) || (fmt == CMIT_FMT_EMAIL) ||
-	    !parent || !parent->next)
+	    fmt == CMIT_FMT_CHANGELOG || !parent || !parent->next)
 		return 0;
 
 	offset = sprintf(buf, "Merge:");
@@ -931,7 +939,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 	if (reencoded)
 		msg = reencoded;
 
-	if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
+	if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL ||
+	    fmt == CMIT_FMT_CHANGELOG)
 		indent = 0;
 
 	/* After-subject is used to pass in Content-Type: multipart
@@ -982,7 +991,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 		if (hdr) {
 			if (linelen == 1) {
 				hdr = 0;
-				if ((fmt != CMIT_FMT_ONELINE) && !subject)
+				if (fmt != CMIT_FMT_ONELINE &&
+				    fmt != CMIT_FMT_CHANGELOG && !subject)
 					buf[offset++] = '\n';
 				continue;
 			}
@@ -1052,7 +1062,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 			offset += linelen + indent;
 		}
 		buf[offset++] = '\n';
-		if (fmt == CMIT_FMT_ONELINE)
+		if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_CHANGELOG)
 			break;
 		if (subject && plain_non_ascii) {
 			int sz;
diff --git a/commit.h b/commit.h
index 83507a0..9d59e0f 100644
--- a/commit.h
+++ b/commit.h
@@ -48,6 +48,7 @@ enum cmit_fmt {
 	CMIT_FMT_ONELINE,
 	CMIT_FMT_EMAIL,
 	CMIT_FMT_USERFORMAT,
+	CMIT_FMT_CHANGELOG,
 
 	CMIT_FMT_UNSPECIFIED,
 };
diff --git a/diff.c b/diff.c
index 5651152..aed5388 100644
--- a/diff.c
+++ b/diff.c
@@ -8,6 +8,7 @@
 #include "delta.h"
 #include "xdiff-interface.h"
 #include "color.h"
+#include "utf8.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -1845,6 +1846,59 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
 	builtin_checkdiff(name, other, p->one, p->two, o);
 }
 
+#define CHANGELOG_TAB_SIZE 8
+#define CHANGELOG_WIDTH 76
+
+struct changelog_t {
+	int offset, seen_first;
+};
+
+static void run_changelog(struct diff_filepair *p, struct diff_options *o,
+	struct changelog_t *changelog)
+{
+	const char *name;
+	const char *other;
+	static char buffer[1024];
+
+	if (DIFF_PAIR_UNMERGED(p)) {
+		/* unmerged */
+		return;
+	}
+
+	if (changelog->seen_first)
+		buffer[0] = ',';
+	else {
+		buffer[0] = '*';
+		changelog->offset = -CHANGELOG_TAB_SIZE;
+		changelog->seen_first = 1;
+	}
+
+	name = p->one->path;
+	other = p->two->path;
+
+	if (!name) {
+		if (!other)
+			return;
+		snprintf(buffer + 1, sizeof(buffer) - 1, " %s", other);
+	} else if (!other || !strcmp(name, other))
+		snprintf(buffer + 1, sizeof(buffer) - 1, " %s", name);
+	else
+		snprintf(buffer + 1, sizeof(buffer) - 1, " %s => %s",
+				name, other);
+	changelog->offset = print_wrapped_text(buffer, -changelog->offset,
+		CHANGELOG_TAB_SIZE + 2, CHANGELOG_WIDTH);
+}
+
+static void finalize_changelog(struct diff_options *options,
+		struct changelog_t *changelog)
+{
+	changelog->offset = print_wrapped_text(": ", -changelog->offset,
+		CHANGELOG_TAB_SIZE + 2, CHANGELOG_WIDTH);
+	changelog->offset = print_wrapped_text(options->stat_sep,
+			-changelog->offset,
+			CHANGELOG_TAB_SIZE + 2, CHANGELOG_WIDTH);
+}
+
 void diff_setup(struct diff_options *options)
 {
 	memset(options, 0, sizeof(*options));
@@ -2366,6 +2420,19 @@ static void diff_flush_checkdiff(struct diff_filepair *p,
 	run_checkdiff(p, o);
 }
 
+static void diff_flush_changelog(struct diff_filepair *p,
+		struct diff_options *o, struct changelog_t *changelog)
+{
+	if (diff_unmodified_pair(p))
+		return;
+
+	if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
+	    (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
+		return; /* no tree diffs in patch format */
+
+	run_changelog(p, o, changelog);
+}
+
 int diff_queue_is_empty(void)
 {
 	struct diff_queue_struct *q = &diff_queued_diff;
@@ -2752,6 +2819,16 @@ void diff_flush(struct diff_options *options)
 		separator++;
 	}
 
+	if (output_format & DIFF_FORMAT_CHANGELOG) {
+		struct changelog_t changelog;
+		memset(&changelog, 0, sizeof(struct changelog_t));
+		for (i = 0; i < q->nr; i++) {
+			struct diff_filepair *p = q->queue[i];
+			if (check_pair_status(p))
+				diff_flush_changelog(p, options, &changelog);
+		}
+		finalize_changelog(options, &changelog);
+	}
 	if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) {
 		struct diffstat_t diffstat;
 
diff --git a/diff.h b/diff.h
index 4043cec..df3b512 100644
--- a/diff.h
+++ b/diff.h
@@ -30,6 +30,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_FORMAT_SUMMARY	0x0008
 #define DIFF_FORMAT_PATCH	0x0010
 #define DIFF_FORMAT_SHORTSTAT	0x0020
+#define DIFF_FORMAT_CHANGELOG	0x0040
 
 /* These override all above */
 #define DIFF_FORMAT_NAME	0x0100
diff --git a/log-tree.c b/log-tree.c
index 6ce239d..b7006bf 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -211,7 +211,8 @@ void show_log(struct rev_info *opt, const char *sep)
 				 sha1, sha1);
 			opt->diffopt.stat_sep = buffer;
 		}
-	} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
+	} else if (opt->commit_format != CMIT_FMT_USERFORMAT &&
+			opt->commit_format != CMIT_FMT_CHANGELOG) {
 		fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
 		      stdout);
 		if (opt->commit_format != CMIT_FMT_ONELINE)
@@ -253,6 +254,20 @@ void show_log(struct rev_info *opt, const char *sep)
 				  sizeof(this_header), abbrev, subject,
 				  extra_headers, opt->relative_date);
 
+	if (opt->commit_format == CMIT_FMT_CHANGELOG) {
+		static char *oneline = NULL;
+		char *eol = strchr(this_header, '\n');
+
+		if (oneline)
+			free(oneline);
+		if (eol) {
+			oneline = xstrdup(eol + 1);
+			eol[1] = '\0';
+		} else
+			oneline = NULL;
+		opt->diffopt.stat_sep = oneline;
+	}
+
 	if (opt->add_signoff)
 		len = append_signoff(this_header, sizeof(this_header), len,
 				     opt->add_signoff);
diff --git a/revision.c b/revision.c
index 823bbd1..5bdc1fc 100644
--- a/revision.c
+++ b/revision.c
@@ -1119,6 +1119,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 		if (revs->dense_combined_merges && !revs->diffopt.output_format)
 			revs->diffopt.output_format = DIFF_FORMAT_PATCH;
 	}
+	if (revs->commit_format == CMIT_FMT_CHANGELOG) {
+		revs->diffopt.output_format |= DIFF_FORMAT_CHANGELOG;
+		revs->diff = 1;
+		revs->diffopt.recursive = 1;
+		revs->no_merges = 1;
+	}
 	revs->diffopt.abbrev = revs->abbrev;
 	if (diff_setup_done(&revs->diffopt) < 0)
 		die("diff_setup_done failed");
-- 
1.5.0.2.2410.g737b

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]