add diff_flush_patch_id() to calculate the patch id
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>
This commit is contained in:
parent
1ef9e05dbf
commit
fcb3d0adc1
139
diff.c
139
diff.c
@ -2104,6 +2104,145 @@ static void diff_summary(struct diff_filepair *p)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user