summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1ef9e05)
raw | patch | inline | side by side (parent: 1ef9e05)
author | Johannes Schindelin <Johannes.Schindelin@gmx.de> | |
Sun, 25 Jun 2006 01:51:08 +0000 (03:51 +0200) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Mon, 26 Jun 2006 21:44:03 +0000 (14:44 -0700) |
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));
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
unsigned char id[20];
if (diff_flush_patch_id(diff_options, id))
printf("And the patch id is: %s\n", sha1_to_hex(id));
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
diff.c | patch | blob | history | |
diff.h | patch | blob | history |
index fbb6c26cd9266e0ae453bb6c321f52d4996446a6..afb629e613e0bcd8034e1701e77f7e16229139d4 100644 (file)
--- a/diff.c
+++ b/diff.c
}
}
+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 */
+static int diff_get_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;
+}
+
+int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
+{
+ struct diff_queue_struct *q = &diff_queued_diff;
+ int i;
+ int result = diff_get_patch_id(options, sha1);
+
+ for (i = 0; i < q->nr; i++)
+ diff_free_filepair(q->queue[i]);
+
+ free(q->queue);
+ q->queue = NULL;
+ q->nr = q->alloc = 0;
+
+ return result;
+}
+
void diff_flush(struct diff_options *options)
{
struct diff_queue_struct *q = &diff_queued_diff;