* [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