git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* git-format-patch builtin isn't using git-cherry?
@ 2006-06-23  0:32 Martin Langhoff
  2006-06-23 12:05 ` Johannes Schindelin
  0 siblings, 1 reply; 5+ messages in thread
From: Martin Langhoff @ 2006-06-23  0:32 UTC (permalink / raw)
  To: git

I used to rely on git-format-patch to be calling git-cherry in the bg,
so that I'd know that the obviously merged patches were upstream
alredy. It doesn't seem to do it any more.

Reading cmd_format_patch() in builtin-log.c, it seems to have lost
that magic that made it so useful... :( Can a kind soul that speaks C
fluently help me out here?

(The new format-patch gives me 180 patches to merge/rebase, where the
old one tells me there's only 51. guess which one I prefer ;-) )

cheers,



m

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: git-format-patch builtin isn't using git-cherry?
  2006-06-23  0:32 git-format-patch builtin isn't using git-cherry? Martin Langhoff
@ 2006-06-23 12:05 ` Johannes Schindelin
  2006-06-23 12:23   ` Timo Hirvonen
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-23 12:05 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: git

Hi,

On Fri, 23 Jun 2006, Martin Langhoff wrote:

> Reading cmd_format_patch() in builtin-log.c, it seems to have lost that 
> magic that made it so useful... :( Can a kind soul that speaks C 
> fluently help me out here?

My fault. But note that it is much faster now, too! I think I can trick it 
back into doing something like the old script, but I'll do that only with 
an option (in order to not slow down the now-common case). And it will 
take a while. So if anybody wants to give it a try...

Basically, it will involve the following recipe:

	- add a DIFF_FORMAT_PATCH_ID
	- calculate _all_ the patch ids in upstream since branch point
	- in cmd_format_patch, in the get_revision() loop, skip those
	  commits which have the same patch id

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: git-format-patch builtin isn't using git-cherry?
  2006-06-23 12:05 ` Johannes Schindelin
@ 2006-06-23 12:23   ` Timo Hirvonen
  2006-06-23 12:33     ` Johannes Schindelin
  0 siblings, 1 reply; 5+ messages in thread
From: Timo Hirvonen @ 2006-06-23 12:23 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: martin.langhoff, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

> Basically, it will involve the following recipe:
> 
> 	- add a DIFF_FORMAT_PATCH_ID

Please don't add any DIFF_FORMAT_*.  I'm cleaning the diff output code
and replacing diff_options.output_format with one-bit flags.

-- 
http://onion.dynserv.net/~timo/

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: git-format-patch builtin isn't using git-cherry?
  2006-06-23 12:23   ` Timo Hirvonen
@ 2006-06-23 12:33     ` Johannes Schindelin
  2006-06-23 15:44       ` [FYI/PATCH] diff: add diff_flush_patch_id() Johannes Schindelin
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-23 12:33 UTC (permalink / raw)
  To: Timo Hirvonen; +Cc: martin.langhoff, git

Hi,

On Fri, 23 Jun 2006, Timo Hirvonen wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> 
> > Basically, it will involve the following recipe:
> > 
> > 	- add a DIFF_FORMAT_PATCH_ID
> 
> Please don't add any DIFF_FORMAT_*.  I'm cleaning the diff output code
> and replacing diff_options.output_format with one-bit flags.

Okay. For the purposes of git-format-patch, this is not needed anyway, but 
rather a function which takes two tree objects and returns the patch id. 
When you are finished it should be easy to add this as a display format.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [FYI/PATCH] diff: add diff_flush_patch_id()
  2006-06-23 12:33     ` Johannes Schindelin
@ 2006-06-23 15:44       ` Johannes Schindelin
  0 siblings, 0 replies; 5+ messages in thread
From: Johannes Schindelin @ 2006-06-23 15:44 UTC (permalink / raw)
  To: Timo Hirvonen; +Cc: martin.langhoff, git


Call it like this:

unsigned char id[20];
if (diff_flush_patch_id(diff_options, id))
	printf("And the patch id is: %s\n", sha1_to_hex(id));

This patch also adds a switch "--with-patch-id" to the diff family, to
print out the patch id before each patch.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

---


	> > > 	- add a DIFF_FORMAT_PATCH_ID
	> > 
	> > Please don't add any DIFF_FORMAT_*.  I'm cleaning the diff output code
	> > and replacing diff_options.output_format with one-bit flags.
	> 
	> Okay. For the purposes of git-format-patch, this is not needed 
	> anyway, but rather a function which takes two tree objects and 
	> returns the patch id. When you are finished it should be easy to 
	> add this as a display format.

	Timo, I am prepared to redo this patch when you finished
	the cleanup.

 diff.c |  129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 diff.h |    3 +
 2 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/diff.c b/diff.c
index 5b34f73..1140d54 100644
--- a/diff.c
+++ b/diff.c
@@ -1460,6 +1460,8 @@ int diff_opt_parse(struct diff_options *
 		options->output_format = DIFF_FORMAT_PATCH;
 		options->with_stat = 1;
 	}
+	else if (!strcmp(arg, "--with-patch-id"))
+		options->with_patch_id = 1;
 	else if (!strcmp(arg, "-z"))
 		options->line_termination = 0;
 	else if (!strncmp(arg, "-l", 2))
@@ -2027,12 +2029,139 @@ static void diff_summary(struct diff_fil
 	}
 }
 
+struct patch_id_t {
+	struct xdiff_emit_state xm;
+	SHA_CTX *ctx;
+	int patchlen;
+};
+
+static int remove_space(char *line, int len)
+{
+	int i;
+        char *dst = line;
+        unsigned char c;
+
+        for (i = 0; i < len; i++)
+                if (!isspace((c = line[i])))
+                        *dst++ = c;
+
+        return dst - line;
+}
+
+static void patch_id_consume(void *priv, char *line, unsigned long len)
+{
+	struct patch_id_t *data = priv;
+	int new_len;
+
+	/* Ignore line numbers when computing the SHA1 of the patch */
+	if (!strncmp(line, "@@ -", 4))
+		return;
+
+	new_len = remove_space(line, len);
+
+	SHA1_Update(data->ctx, line, new_len);
+	data->patchlen += new_len;
+}
+
+/* returns 0 upon success, and writes result into sha1 */
+int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
+{
+	struct diff_queue_struct *q = &diff_queued_diff;
+	int i;
+	SHA_CTX ctx;
+	struct patch_id_t data;
+	char buffer[PATH_MAX * 4 + 20];
+
+	SHA1_Init(&ctx);
+	memset(&data, 0, sizeof(struct patch_id_t));
+	data.ctx = &ctx;
+	data.xm.consume = patch_id_consume;
+	
+	for (i = 0; i < q->nr; i++) {
+		xpparam_t xpp;
+		xdemitconf_t xecfg;
+		xdemitcb_t ecb;
+		mmfile_t mf1, mf2;
+		struct diff_filepair *p = q->queue[i];
+		int len1, len2;
+
+		if (p->status == 0)
+			return error("internal diff status error");
+		if (p->status == DIFF_STATUS_UNKNOWN)
+			continue;
+		if (diff_unmodified_pair(p))
+			continue;
+		if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
+		    (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
+			continue;
+		if (DIFF_PAIR_UNMERGED(p))
+			continue;
+
+		diff_fill_sha1_info(p->one);
+		diff_fill_sha1_info(p->two);
+		if (fill_mmfile(&mf1, p->one) < 0 ||
+				fill_mmfile(&mf2, p->two) < 0)
+			return error("unable to read files to diff");
+
+		/* Maybe hash p->two? into the patch id? */
+		if (mmfile_is_binary(&mf2))
+			continue;
+
+		len1 = remove_space(p->one->path, strlen(p->one->path));
+		len2 = remove_space(p->two->path, strlen(p->two->path));
+		if (p->one->mode == 0)
+			len1 = snprintf(buffer, sizeof(buffer),
+					"diff--gita/%.*sb/%.*s"
+					"newfilemode%06o"
+					"---/dev/null"
+					"+++b/%.*s",
+					len1, p->one->path,
+					len2, p->two->path,
+					p->two->mode,
+					len2, p->two->path);
+		else if (p->two->mode == 0)
+			len1 = snprintf(buffer, sizeof(buffer),
+					"diff--gita/%.*sb/%.*s"
+					"deletedfilemode%06o"
+					"---a/%.*s"
+					"+++/dev/null",
+					len1, p->one->path,
+					len2, p->two->path,
+					p->one->mode,
+					len1, p->one->path);
+		else
+			len1 = snprintf(buffer, sizeof(buffer),
+					"diff--gita/%.*sb/%.*s"
+					"---a/%.*s"
+					"+++b/%.*s",
+					len1, p->one->path,
+					len2, p->two->path,
+					len1, p->one->path,
+					len2, p->two->path);
+		SHA1_Update(&ctx, buffer, len1);
+
+		xpp.flags = XDF_NEED_MINIMAL;
+		xecfg.ctxlen = 3;
+		xecfg.flags = 3;
+		ecb.outf = xdiff_outf;
+		ecb.priv = &data;
+		xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+	}
+
+	SHA1_Final(sha1, &ctx);
+	return 0;
+}
+
 void diff_flush(struct diff_options *options)
 {
 	struct diff_queue_struct *q = &diff_queued_diff;
 	int i;
 	int diff_output_format = options->output_format;
 	struct diffstat_t *diffstat = NULL;
+	unsigned char sha1[20];
+
+	if (options->with_patch_id && !diff_flush_patch_id(options, sha1))
+		printf("patch-id %s\n", sha1_to_hex(sha1));
 
 	if (diff_output_format == DIFF_FORMAT_DIFFSTAT || options->with_stat) {
 		diffstat = xcalloc(sizeof (struct diffstat_t), 1);
diff --git a/diff.h b/diff.h
index 7d7b6cd..29aac52 100644
--- a/diff.h
+++ b/diff.h
@@ -27,6 +27,7 @@ struct diff_options {
 	unsigned recursive:1,
 		 with_raw:1,
 		 with_stat:1,
+		 with_patch_id:1,
 		 tree_in_recursive:1,
 		 binary:1,
 		 full_index:1,
@@ -185,4 +186,6 @@ extern int run_diff_files(struct rev_inf
 
 extern int run_diff_index(struct rev_info *revs, int cached);
 
+extern int diff_flush_patch_id(struct diff_options *, unsigned char *);
+
 #endif /* DIFF_H */
-- 
1.4.0.g319e-dirty

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-06-23 15:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-23  0:32 git-format-patch builtin isn't using git-cherry? Martin Langhoff
2006-06-23 12:05 ` Johannes Schindelin
2006-06-23 12:23   ` Timo Hirvonen
2006-06-23 12:33     ` Johannes Schindelin
2006-06-23 15:44       ` [FYI/PATCH] diff: add diff_flush_patch_id() Johannes Schindelin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).