Skip to content

Commit 4d54494

Browse files
committed
Merge branch 'pb/patch-id-plus'
* pb/patch-id-plus: patch-id: Add support for mbox format patch-id: extract parsing one diff out of generate_id_list
2 parents c00cf45 + 580fb25 commit 4d54494

File tree

2 files changed

+116
-19
lines changed

2 files changed

+116
-19
lines changed

builtin/patch-id.c

Lines changed: 88 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,49 +28,118 @@ static int remove_space(char *line)
2828
return dst - line;
2929
}
3030

31-
static void generate_id_list(void)
31+
static int scan_hunk_header(const char *p, int *p_before, int *p_after)
32+
{
33+
static const char digits[] = "0123456789";
34+
const char *q, *r;
35+
int n;
36+
37+
q = p + 4;
38+
n = strspn(q, digits);
39+
if (q[n] == ',') {
40+
q += n + 1;
41+
n = strspn(q, digits);
42+
}
43+
if (n == 0 || q[n] != ' ' || q[n+1] != '+')
44+
return 0;
45+
46+
r = q + n + 2;
47+
n = strspn(r, digits);
48+
if (r[n] == ',') {
49+
r += n + 1;
50+
n = strspn(r, digits);
51+
}
52+
if (n == 0)
53+
return 0;
54+
55+
*p_before = atoi(q);
56+
*p_after = atoi(r);
57+
return 1;
58+
}
59+
60+
int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx)
3261
{
33-
static unsigned char sha1[20];
3462
static char line[1000];
35-
git_SHA_CTX ctx;
36-
int patchlen = 0;
63+
int patchlen = 0, found_next = 0;
64+
int before = -1, after = -1;
3765

38-
git_SHA1_Init(&ctx);
3966
while (fgets(line, sizeof(line), stdin) != NULL) {
40-
unsigned char n[20];
4167
char *p = line;
4268
int len;
4369

4470
if (!memcmp(line, "diff-tree ", 10))
4571
p += 10;
4672
else if (!memcmp(line, "commit ", 7))
4773
p += 7;
74+
else if (!memcmp(line, "From ", 5))
75+
p += 5;
4876

49-
if (!get_sha1_hex(p, n)) {
50-
flush_current_id(patchlen, sha1, &ctx);
51-
hashcpy(sha1, n);
52-
patchlen = 0;
53-
continue;
77+
if (!get_sha1_hex(p, next_sha1)) {
78+
found_next = 1;
79+
break;
5480
}
5581

5682
/* Ignore commit comments */
5783
if (!patchlen && memcmp(line, "diff ", 5))
5884
continue;
5985

60-
/* Ignore git-diff index header */
61-
if (!memcmp(line, "index ", 6))
62-
continue;
86+
/* Parsing diff header? */
87+
if (before == -1) {
88+
if (!memcmp(line, "index ", 6))
89+
continue;
90+
else if (!memcmp(line, "--- ", 4))
91+
before = after = 1;
92+
else if (!isalpha(line[0]))
93+
break;
94+
}
6395

64-
/* Ignore line numbers when computing the SHA1 of the patch */
65-
if (!memcmp(line, "@@ -", 4))
66-
continue;
96+
/* Looking for a valid hunk header? */
97+
if (before == 0 && after == 0) {
98+
if (!memcmp(line, "@@ -", 4)) {
99+
/* Parse next hunk, but ignore line numbers. */
100+
scan_hunk_header(line, &before, &after);
101+
continue;
102+
}
103+
104+
/* Split at the end of the patch. */
105+
if (memcmp(line, "diff ", 5))
106+
break;
107+
108+
/* Else we're parsing another header. */
109+
before = after = -1;
110+
}
111+
112+
/* If we get here, we're inside a hunk. */
113+
if (line[0] == '-' || line[0] == ' ')
114+
before--;
115+
if (line[0] == '+' || line[0] == ' ')
116+
after--;
67117

68118
/* Compute the sha without whitespace */
69119
len = remove_space(line);
70120
patchlen += len;
71-
git_SHA1_Update(&ctx, line, len);
121+
git_SHA1_Update(ctx, line, len);
122+
}
123+
124+
if (!found_next)
125+
hashclr(next_sha1);
126+
127+
return patchlen;
128+
}
129+
130+
static void generate_id_list(void)
131+
{
132+
unsigned char sha1[20], n[20];
133+
git_SHA_CTX ctx;
134+
int patchlen;
135+
136+
git_SHA1_Init(&ctx);
137+
hashclr(sha1);
138+
while (!feof(stdin)) {
139+
patchlen = get_one_patchid(n, &ctx);
140+
flush_current_id(patchlen, sha1, &ctx);
141+
hashcpy(sha1, n);
72142
}
73-
flush_current_id(patchlen, sha1, &ctx);
74143
}
75144

76145
static const char patch_id_usage[] = "git patch-id < patch";

t/t4204-patch-id.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ test_expect_success 'patch-id output is well-formed' '
1818
grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output
1919
'
2020

21+
calc_patch_id () {
22+
git patch-id |
23+
sed "s# .*##" > patch-id_"$1"
24+
}
25+
2126
get_patch_id () {
2227
git log -p -1 "$1" | git patch-id |
2328
sed "s# .*##" > patch-id_"$1"
@@ -35,4 +40,27 @@ test_expect_success 'patch-id detects inequality' '
3540
! test_cmp patch-id_master patch-id_notsame
3641
'
3742

43+
test_expect_success 'patch-id supports git-format-patch output' '
44+
get_patch_id master &&
45+
git checkout same &&
46+
git format-patch -1 --stdout | calc_patch_id same &&
47+
test_cmp patch-id_master patch-id_same &&
48+
set `git format-patch -1 --stdout | git patch-id` &&
49+
test "$2" = `git rev-parse HEAD`
50+
'
51+
52+
test_expect_success 'whitespace is irrelevant in footer' '
53+
get_patch_id master &&
54+
git checkout same &&
55+
git format-patch -1 --stdout | sed "s/ \$//" | calc_patch_id same &&
56+
test_cmp patch-id_master patch-id_same
57+
'
58+
59+
test_expect_success 'patch-id supports git-format-patch MIME output' '
60+
get_patch_id master &&
61+
git checkout same &&
62+
git format-patch -1 --attach --stdout | calc_patch_id same &&
63+
test_cmp patch-id_master patch-id_same
64+
'
65+
3866
test_done

0 commit comments

Comments
 (0)