{"thread":{"id":"4660","subject":"[PATCH 1/2] add diff_flush_patch_id() to calculate the patch id","startedAt":"2006-06-25T01:51:08Z","lastAt":"2006-06-25T01:51:08Z","messageCount":1,"participants":["Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"22500","messageId":"Pine.LNX.4.63.0606250350530.29667@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"4660","inReplyTo":null,"subject":"[PATCH 1/2] add diff_flush_patch_id() to calculate the patch id","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-06-25T01:51:08Z","receivedAt":"2006-06-25T01:51:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nCall it like this:\n\nunsigned char id[20];\nif (diff_flush_patch_id(diff_options, id))\n\tprintf(\"And the patch id is: %s\\n\", sha1_to_hex(id));\n\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n diff.c |  139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n diff.h |    2 +\n 2 files changed, 141 insertions(+), 0 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex 5b34f73..3beecb9 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -2027,6 +2027,145 @@ static void diff_summary(struct diff_fil\n \t}\n }\n \n+struct patch_id_t {\n+\tstruct xdiff_emit_state xm;\n+\tSHA_CTX *ctx;\n+\tint patchlen;\n+};\n+\n+static int remove_space(char *line, int len)\n+{\n+\tint i;\n+        char *dst = line;\n+        unsigned char c;\n+\n+        for (i = 0; i < len; i++)\n+                if (!isspace((c = line[i])))\n+                        *dst++ = c;\n+\n+        return dst - line;\n+}\n+\n+static void patch_id_consume(void *priv, char *line, unsigned long len)\n+{\n+\tstruct patch_id_t *data = priv;\n+\tint new_len;\n+\n+\t/* Ignore line numbers when computing the SHA1 of the patch */\n+\tif (!strncmp(line, \"@@ -\", 4))\n+\t\treturn;\n+\n+\tnew_len = remove_space(line, len);\n+\n+\tSHA1_Update(data->ctx, line, new_len);\n+\tdata->patchlen += new_len;\n+}\n+\n+/* returns 0 upon success, and writes result into sha1 */\n+static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)\n+{\n+\tstruct diff_queue_struct *q = &diff_queued_diff;\n+\tint i;\n+\tSHA_CTX ctx;\n+\tstruct patch_id_t data;\n+\tchar buffer[PATH_MAX * 4 + 20];\n+\n+\tSHA1_Init(&ctx);\n+\tmemset(&data, 0, sizeof(struct patch_id_t));\n+\tdata.ctx = &ctx;\n+\tdata.xm.consume = patch_id_consume;\n+\t\n+\tfor (i = 0; i < q->nr; i++) {\n+\t\txpparam_t xpp;\n+\t\txdemitconf_t xecfg;\n+\t\txdemitcb_t ecb;\n+\t\tmmfile_t mf1, mf2;\n+\t\tstruct diff_filepair *p = q->queue[i];\n+\t\tint len1, len2;\n+\n+\t\tif (p->status == 0)\n+\t\t\treturn error(\"internal diff status error\");\n+\t\tif (p->status == DIFF_STATUS_UNKNOWN)\n+\t\t\tcontinue;\n+\t\tif (diff_unmodified_pair(p))\n+\t\t\tcontinue;\n+\t\tif ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||\n+\t\t    (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))\n+\t\t\tcontinue;\n+\t\tif (DIFF_PAIR_UNMERGED(p))\n+\t\t\tcontinue;\n+\n+\t\tdiff_fill_sha1_info(p->one);\n+\t\tdiff_fill_sha1_info(p->two);\n+\t\tif (fill_mmfile(&mf1, p->one) < 0 ||\n+\t\t\t\tfill_mmfile(&mf2, p->two) < 0)\n+\t\t\treturn error(\"unable to read files to diff\");\n+\n+\t\t/* Maybe hash p->two? into the patch id? */\n+\t\tif (mmfile_is_binary(&mf2))\n+\t\t\tcontinue;\n+\n+\t\tlen1 = remove_space(p->one->path, strlen(p->one->path));\n+\t\tlen2 = remove_space(p->two->path, strlen(p->two->path));\n+\t\tif (p->one->mode == 0)\n+\t\t\tlen1 = snprintf(buffer, sizeof(buffer),\n+\t\t\t\t\t\"diff--gita/%.*sb/%.*s\"\n+\t\t\t\t\t\"newfilemode%06o\"\n+\t\t\t\t\t\"---/dev/null\"\n+\t\t\t\t\t\"+++b/%.*s\",\n+\t\t\t\t\tlen1, p->one->path,\n+\t\t\t\t\tlen2, p->two->path,\n+\t\t\t\t\tp->two->mode,\n+\t\t\t\t\tlen2, p->two->path);\n+\t\telse if (p->two->mode == 0)\n+\t\t\tlen1 = snprintf(buffer, sizeof(buffer),\n+\t\t\t\t\t\"diff--gita/%.*sb/%.*s\"\n+\t\t\t\t\t\"deletedfilemode%06o\"\n+\t\t\t\t\t\"---a/%.*s\"\n+\t\t\t\t\t\"+++/dev/null\",\n+\t\t\t\t\tlen1, p->one->path,\n+\t\t\t\t\tlen2, p->two->path,\n+\t\t\t\t\tp->one->mode,\n+\t\t\t\t\tlen1, p->one->path);\n+\t\telse\n+\t\t\tlen1 = snprintf(buffer, sizeof(buffer),\n+\t\t\t\t\t\"diff--gita/%.*sb/%.*s\"\n+\t\t\t\t\t\"---a/%.*s\"\n+\t\t\t\t\t\"+++b/%.*s\",\n+\t\t\t\t\tlen1, p->one->path,\n+\t\t\t\t\tlen2, p->two->path,\n+\t\t\t\t\tlen1, p->one->path,\n+\t\t\t\t\tlen2, p->two->path);\n+\t\tSHA1_Update(&ctx, buffer, len1);\n+\n+\t\txpp.flags = XDF_NEED_MINIMAL;\n+\t\txecfg.ctxlen = 3;\n+\t\txecfg.flags = 3;\n+\t\tecb.outf = xdiff_outf;\n+\t\tecb.priv = &data;\n+\t\txdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);\n+\t}\n+\n+\tSHA1_Final(sha1, &ctx);\n+\treturn 0;\n+}\n+\n+int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)\n+{\n+\tstruct diff_queue_struct *q = &diff_queued_diff;\n+\tint i;\n+\tint result = diff_get_patch_id(options, sha1);\n+\n+\tfor (i = 0; i < q->nr; i++)\n+\t\tdiff_free_filepair(q->queue[i]);\n+\n+\tfree(q->queue);\n+\tq->queue = NULL;\n+\tq->nr = q->alloc = 0;\n+\n+\treturn result;\n+}\n+\n void diff_flush(struct diff_options *options)\n {\n \tstruct diff_queue_struct *q = &diff_queued_diff;\ndiff --git a/diff.h b/diff.h\nindex 7d7b6cd..850c15f 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -185,4 +185,6 @@ extern int run_diff_files(struct rev_inf\n \n extern int run_diff_index(struct rev_info *revs, int cached);\n \n+extern int diff_flush_patch_id(struct diff_options *, unsigned char *);\n+\n #endif /* DIFF_H */\n-- \n1.4.0.g7a200-dirty\n"}]}