1
#include "builtin.h"
2
3
-static void flush_current_id(int patchlen, unsigned char *id, git_SHA_CTX *c)
3
+static void flush_current_id(int patchlen, unsigned char *id, unsigned char *result)
4
{
5
- unsigned char result[20];
5
char name[50];
6
7
if (!patchlen)
8
return;
9
11
- git_SHA1_Final(result, c);
10
memcpy(name, sha1_to_hex(id), 41);
11
printf("%s %s\n", sha1_to_hex(result), name);
14
- git_SHA1_Init(c);
12
}
13
14
static int remove_space(char *line)
53
return 1;
54
}
55
59
-static int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx, struct strbuf *line_buf)
56
+static void flush_one_hunk(unsigned char *result, git_SHA_CTX *ctx)
57
+{
58
+ unsigned char hash[20];
59
+ unsigned short carry = 0;
60
+ int i;
61
+
62
+ git_SHA1_Final(hash, ctx);
63
+ git_SHA1_Init(ctx);
64
+ /* 20-byte sum, with carry */
65
+ for (i = 0; i < 20; ++i) {
66
+ carry += result[i] + hash[i];
67
+ result[i] = carry;
68
+ carry >>= 8;
69
+ }
70
+}
71
+
72
+static int get_one_patchid(unsigned char *next_sha1, unsigned char *result,
73
+ struct strbuf *line_buf, int stable)
74
{
75
int patchlen = 0, found_next = 0;
76
int before = -1, after = -1;
77
+ git_SHA_CTX ctx;
78
+
79
+ git_SHA1_Init(&ctx);
80
+ hashclr(result);
81
82
while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) {
83
char *line = line_buf->buf;
125
break;
126
127
/* Else we're parsing another header. */
128
+ if (stable)
129
+ flush_one_hunk(result, &ctx);
130
before = after = -1;
131
}
132
139
/* Compute the sha without whitespace */
140
len = remove_space(line);
141
patchlen += len;
122
- git_SHA1_Update(ctx, line, len);
142
+ git_SHA1_Update(&ctx, line, len);
143
}
144
145
if (!found_next)
146
hashclr(next_sha1);
147
148
+ flush_one_hunk(result, &ctx);
149
+
150
return patchlen;
151
}
152
131
-static void generate_id_list(void)
153
+static void generate_id_list(int stable)
154
{
133
- unsigned char sha1[20], n[20];
134
- git_SHA_CTX ctx;
155
+ unsigned char sha1[20], n[20], result[20];
156
int patchlen;
157
struct strbuf line_buf = STRBUF_INIT;
158
138
- git_SHA1_Init(&ctx);
159
hashclr(sha1);
160
while (!feof(stdin)) {
141
- patchlen = get_one_patchid(n, &ctx, &line_buf);
142
- flush_current_id(patchlen, sha1, &ctx);
161
+ patchlen = get_one_patchid(n, result, &line_buf, stable);
162
+ flush_current_id(patchlen, sha1, result);
163
hashcpy(sha1, n);
164
}
165
strbuf_release(&line_buf);
166
}
167
148
-static const char patch_id_usage[] = "git patch-id < patch";
168
+static const char patch_id_usage[] = "git patch-id [--stable | --unstable] < patch";
169
+
170
+static int git_patch_id_config(const char *var, const char *value, void *cb)
171
+{
172
+ int *stable = cb;
173
+
174
+ if (!strcmp(var, "patchid.stable")) {
175
+ *stable = git_config_bool(var, value);
176
+ return 0;
177
+ }
178
+
179
+ return git_default_config(var, value, cb);
180
+}
181
182
int cmd_patch_id(int argc, const char **argv, const char *prefix)
183
{
152
- if (argc != 1)
184
+ int stable = -1;
185
+
186
+ git_config(git_patch_id_config, &stable);
187
+
188
+ /* If nothing is set, default to unstable. */
189
+ if (stable < 0)
190
+ stable = 0;
191
+
192
+ if (argc == 2 && !strcmp(argv[1], "--stable"))
193
+ stable = 1;
194
+ else if (argc == 2 && !strcmp(argv[1], "--unstable"))
195
+ stable = 0;
196
+ else if (argc != 1)
197
usage(patch_id_usage);
198
155
- generate_id_list();
199
+ generate_id_list(stable);
200
return 0;
201
}