@@ -28,49 +28,118 @@ static int remove_space(char *line)
28
28
return dst - line ;
29
29
}
30
30
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 )
32
61
{
33
- static unsigned char sha1 [20 ];
34
62
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 ;
37
65
38
- git_SHA1_Init (& ctx );
39
66
while (fgets (line , sizeof (line ), stdin ) != NULL ) {
40
- unsigned char n [20 ];
41
67
char * p = line ;
42
68
int len ;
43
69
44
70
if (!memcmp (line , "diff-tree " , 10 ))
45
71
p += 10 ;
46
72
else if (!memcmp (line , "commit " , 7 ))
47
73
p += 7 ;
74
+ else if (!memcmp (line , "From " , 5 ))
75
+ p += 5 ;
48
76
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 ;
54
80
}
55
81
56
82
/* Ignore commit comments */
57
83
if (!patchlen && memcmp (line , "diff " , 5 ))
58
84
continue ;
59
85
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
+ }
63
95
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 -- ;
67
117
68
118
/* Compute the sha without whitespace */
69
119
len = remove_space (line );
70
120
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 );
72
142
}
73
- flush_current_id (patchlen , sha1 , & ctx );
74
143
}
75
144
76
145
static const char patch_id_usage [] = "git patch-id < patch" ;
0 commit comments