Added
Link Here
|
1 |
--- convert.c.orig 2021-06-06 05:13:45.000000000 -0700 |
2 |
+++ convert.c 2021-08-20 11:05:22.792030000 -0700 |
3 |
@@ -1054,7 +1054,12 @@ |
4 |
return 0; |
5 |
} |
6 |
|
7 |
-static int count_ident(const char *cp, unsigned long size) |
8 |
+#define ID_STR "Id" |
9 |
+ |
10 |
+#define GIT_MAX_IDENT_LEN 255 |
11 |
+ |
12 |
+static int count_ident(const char *cp, unsigned long size, |
13 |
+ const struct ident_action *idact) |
14 |
{ |
15 |
/* |
16 |
* "$Id: 0000000000000000000000000000000000000000 $" <=> "$Id$" |
17 |
@@ -1067,13 +1072,13 @@ |
18 |
size--; |
19 |
if (ch != '$') |
20 |
continue; |
21 |
- if (size < 3) |
22 |
+ if (size < idact->id_len + 1) |
23 |
break; |
24 |
- if (memcmp("Id", cp, 2)) |
25 |
+ if (memcmp(idact->id, cp, idact->id_len)) |
26 |
continue; |
27 |
- ch = cp[2]; |
28 |
- cp += 3; |
29 |
- size -= 3; |
30 |
+ ch = cp[idact->id_len]; |
31 |
+ cp += idact->id_len + 1; |
32 |
+ size -= idact->id_len + 1; |
33 |
if (ch == '$') |
34 |
cnt++; /* $Id$ */ |
35 |
if (ch != ':') |
36 |
@@ -1097,11 +1102,11 @@ |
37 |
} |
38 |
|
39 |
static int ident_to_git(const char *src, size_t len, |
40 |
- struct strbuf *buf, int ident) |
41 |
+ struct strbuf *buf, const struct ident_action *idact) |
42 |
{ |
43 |
char *dst, *dollar; |
44 |
|
45 |
- if (!ident || (src && !count_ident(src, len))) |
46 |
+ if (!idact->id || (src && !count_ident(src, len, idact))) |
47 |
return 0; |
48 |
|
49 |
if (!buf) |
50 |
@@ -1120,17 +1125,18 @@ |
51 |
len -= dollar + 1 - src; |
52 |
src = dollar + 1; |
53 |
|
54 |
- if (len > 3 && !memcmp(src, "Id:", 3)) { |
55 |
- dollar = memchr(src + 3, '$', len - 3); |
56 |
+ if (len > idact->id_len + 1 && !memcmp(src, idact->id, idact->id_len) && src[idact->id_len + 1] == ':') { |
57 |
+ dollar = memchr(src + idact->id_len + 1, '$', len - (idact->id_len + 1)); |
58 |
if (!dollar) |
59 |
break; |
60 |
- if (memchr(src + 3, '\n', dollar - src - 3)) { |
61 |
+ if (memchr(src + idact->id_len + 1, '\n', dollar - src - (idact->id_len + 1))) { |
62 |
/* Line break before the next dollar. */ |
63 |
continue; |
64 |
} |
65 |
|
66 |
- memcpy(dst, "Id$", 3); |
67 |
- dst += 3; |
68 |
+ memcpy(dst, idact->id, idact->id_len); |
69 |
+ dst[idact->id_len] = '$'; |
70 |
+ dst += idact->id_len + 1; |
71 |
len -= dollar + 1 - src; |
72 |
src = dollar + 1; |
73 |
} |
74 |
@@ -1141,16 +1147,16 @@ |
75 |
} |
76 |
|
77 |
static int ident_to_worktree(const char *src, size_t len, |
78 |
- struct strbuf *buf, int ident) |
79 |
+ struct strbuf *buf, const struct ident_action *idact) |
80 |
{ |
81 |
struct object_id oid; |
82 |
char *to_free = NULL, *dollar, *spc; |
83 |
int cnt; |
84 |
|
85 |
- if (!ident) |
86 |
+ if (!idact->id) |
87 |
return 0; |
88 |
|
89 |
- cnt = count_ident(src, len); |
90 |
+ cnt = count_ident(src, len, idact); |
91 |
if (!cnt) |
92 |
return 0; |
93 |
|
94 |
@@ -1159,7 +1165,7 @@ |
95 |
to_free = strbuf_detach(buf, NULL); |
96 |
hash_object_file(the_hash_algo, src, len, "blob", &oid); |
97 |
|
98 |
- strbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + 3)); |
99 |
+ strbuf_grow(buf, len + cnt * (the_hash_algo->hexsz + idact->id_len + 1)); |
100 |
for (;;) { |
101 |
/* step 1: run to the next '$' */ |
102 |
dollar = memchr(src, '$', len); |
103 |
@@ -1170,14 +1176,14 @@ |
104 |
src = dollar + 1; |
105 |
|
106 |
/* step 2: does it looks like a bit like Id:xxx$ or Id$ ? */ |
107 |
- if (len < 3 || memcmp("Id", src, 2)) |
108 |
+ if (len < idact->id_len + 1 || memcmp(idact->id, src, idact->id_len)) |
109 |
continue; |
110 |
|
111 |
/* step 3: skip over Id$ or Id:xxxxx$ */ |
112 |
- if (src[2] == '$') { |
113 |
- src += 3; |
114 |
- len -= 3; |
115 |
- } else if (src[2] == ':') { |
116 |
+ if (src[idact->id_len] == '$') { |
117 |
+ src += idact->id_len + 1; |
118 |
+ len -= idact->id_len + 1; |
119 |
+ } else if (src[idact->id_len] == ':') { |
120 |
/* |
121 |
* It's possible that an expanded Id has crept its way into the |
122 |
* repository, we cope with that by stripping the expansion out. |
123 |
@@ -1185,18 +1191,18 @@ |
124 |
* on checkout, which won't go away by stash, but let's keep it |
125 |
* for git-style ids. |
126 |
*/ |
127 |
- dollar = memchr(src + 3, '$', len - 3); |
128 |
+ dollar = memchr(src + idact->id_len + 1, '$', len - (idact->id_len + 1)); |
129 |
if (!dollar) { |
130 |
/* incomplete keyword, no more '$', so just quit the loop */ |
131 |
break; |
132 |
} |
133 |
|
134 |
- if (memchr(src + 3, '\n', dollar - src - 3)) { |
135 |
+ if (memchr(src + idact->id_len + 1, '\n', dollar - src - (idact->id_len + 1))) { |
136 |
/* Line break before the next dollar. */ |
137 |
continue; |
138 |
} |
139 |
|
140 |
- spc = memchr(src + 4, ' ', dollar - src - 4); |
141 |
+ spc = memchr(src + idact->id_len + 2, ' ', dollar - src - (idact->id_len + 2)); |
142 |
if (spc && spc < dollar-1) { |
143 |
/* There are spaces in unexpected places. |
144 |
* This is probably an id from some other |
145 |
@@ -1213,7 +1219,8 @@ |
146 |
} |
147 |
|
148 |
/* step 4: substitute */ |
149 |
- strbuf_addstr(buf, "Id: "); |
150 |
+ strbuf_addstr(buf, idact->id); |
151 |
+ strbuf_addstr(buf, ": "); |
152 |
strbuf_addstr(buf, oid_to_hex(&oid)); |
153 |
strbuf_addstr(buf, " $"); |
154 |
} |
155 |
@@ -1284,11 +1291,21 @@ |
156 |
return NULL; |
157 |
} |
158 |
|
159 |
-static int git_path_check_ident(struct attr_check_item *check) |
160 |
+static struct ident_action git_path_check_ident(struct attr_check_item *check) |
161 |
{ |
162 |
+ struct ident_action idact = {.id = NULL, .id_len = 0}; |
163 |
const char *value = check->value; |
164 |
|
165 |
- return !!ATTR_TRUE(value); |
166 |
+ if (!ATTR_UNSET(value) && !ATTR_FALSE(value)) { |
167 |
+ if (ATTR_TRUE(value)) |
168 |
+ idact.id = ID_STR; |
169 |
+ else |
170 |
+ idact.id = value; |
171 |
+ idact.id_len = strlen(idact.id); |
172 |
+ if (idact.id_len > GIT_MAX_IDENT_LEN) |
173 |
+ die(_("ident value length exceeds GIT_MAX_IDENT_LEN")); |
174 |
+ } |
175 |
+ return idact; |
176 |
} |
177 |
|
178 |
static struct attr_check *check; |
179 |
@@ -1311,7 +1328,7 @@ |
180 |
ca->crlf_action = git_path_check_crlf(ccheck + 4); |
181 |
if (ca->crlf_action == CRLF_UNDEFINED) |
182 |
ca->crlf_action = git_path_check_crlf(ccheck + 0); |
183 |
- ca->ident = git_path_check_ident(ccheck + 1); |
184 |
+ ca->ident_action = git_path_check_ident(ccheck + 1); |
185 |
ca->drv = git_path_check_convert(ccheck + 2); |
186 |
if (ca->crlf_action != CRLF_BINARY) { |
187 |
enum eol eol_attr = git_path_check_eol(ccheck + 3); |
188 |
@@ -1431,7 +1448,7 @@ |
189 |
len = dst->len; |
190 |
} |
191 |
} |
192 |
- return ret | ident_to_git(src, len, dst, ca.ident); |
193 |
+ return ret | ident_to_git(src, len, dst, &ca.ident_action); |
194 |
} |
195 |
|
196 |
void convert_to_git_filter_fd(struct index_state *istate, |
197 |
@@ -1448,7 +1465,7 @@ |
198 |
|
199 |
encode_to_git(path, dst->buf, dst->len, dst, ca.working_tree_encoding, conv_flags); |
200 |
crlf_to_git(istate, path, dst->buf, dst->len, dst, ca.crlf_action, conv_flags); |
201 |
- ident_to_git(dst->buf, dst->len, dst, ca.ident); |
202 |
+ ident_to_git(dst->buf, dst->len, dst, &ca.ident_action); |
203 |
} |
204 |
|
205 |
static int convert_to_working_tree_ca_internal(const struct conv_attrs *ca, |
206 |
@@ -1460,7 +1477,7 @@ |
207 |
{ |
208 |
int ret = 0, ret_filter = 0; |
209 |
|
210 |
- ret |= ident_to_worktree(src, len, dst, ca->ident); |
211 |
+ ret |= ident_to_worktree(src, len, dst, &(ca->ident_action)); |
212 |
if (ret) { |
213 |
src = dst->buf; |
214 |
len = dst->len; |
215 |
@@ -1808,7 +1825,8 @@ |
216 |
struct stream_filter filter; |
217 |
struct strbuf left; |
218 |
int state; |
219 |
- char ident[GIT_MAX_HEXSZ + 5]; /* ": x40 $" */ |
220 |
+ const struct ident_action *idact; |
221 |
+ char ident[GIT_MAX_HEXSZ + GIT_MAX_IDENT_LEN + 3]; /* ": x40 $" */ |
222 |
}; |
223 |
|
224 |
static int is_foreign_ident(const char *str) |
225 |
@@ -1845,13 +1863,16 @@ |
226 |
char *output, size_t *osize_p) |
227 |
{ |
228 |
struct ident_filter *ident = (struct ident_filter *)filter; |
229 |
- static const char head[] = "$Id"; |
230 |
+ const struct ident_action *idact = ident->idact; |
231 |
|
232 |
if (!input) { |
233 |
/* drain upon eof */ |
234 |
switch (ident->state) { |
235 |
default: |
236 |
- strbuf_add(&ident->left, head, ident->state); |
237 |
+ if (ident->state > 0) |
238 |
+ strbuf_addch(&ident->left, '$'); |
239 |
+ if (ident->state > 1) |
240 |
+ strbuf_add(&ident->left, idact->id, ident->state - 1); |
241 |
/* fallthrough */ |
242 |
case IDENT_SKIPPING: |
243 |
/* fallthrough */ |
244 |
@@ -1883,22 +1904,26 @@ |
245 |
if (ch != '\n' && ch != '$') |
246 |
continue; |
247 |
if (ch == '$' && !is_foreign_ident(ident->left.buf)) { |
248 |
- strbuf_setlen(&ident->left, sizeof(head) - 1); |
249 |
+ strbuf_setlen(&ident->left, idact->id_len + 1); |
250 |
strbuf_addstr(&ident->left, ident->ident); |
251 |
} |
252 |
ident->state = IDENT_DRAINING; |
253 |
continue; |
254 |
} |
255 |
|
256 |
- if (ident->state < sizeof(head) && |
257 |
- head[ident->state] == ch) { |
258 |
+ if ((ident->state == 0 && ch == '$') || |
259 |
+ (ident->state > 0 && ident->state < idact->id_len + 1 && |
260 |
+ idact->id[ident->state - 1] == ch)) { |
261 |
ident->state++; |
262 |
continue; |
263 |
} |
264 |
|
265 |
- if (ident->state) |
266 |
- strbuf_add(&ident->left, head, ident->state); |
267 |
- if (ident->state == sizeof(head) - 1) { |
268 |
+ if (ident->state) { |
269 |
+ strbuf_addch(&ident->left, '$'); |
270 |
+ if (ident->state > 1) |
271 |
+ strbuf_add(&ident->left, idact->id, ident->state - 1); |
272 |
+ } |
273 |
+ if (ident->state == idact->id_len + 1) { |
274 |
if (ch != ':' && ch != '$') { |
275 |
strbuf_addch(&ident->left, ch); |
276 |
ident->state = 0; |
277 |
@@ -1933,7 +1958,7 @@ |
278 |
ident_free_fn, |
279 |
}; |
280 |
|
281 |
-static struct stream_filter *ident_filter(const struct object_id *oid) |
282 |
+static struct stream_filter *ident_filter(const struct object_id *oid, const struct ident_action *idact) |
283 |
{ |
284 |
struct ident_filter *ident = xmalloc(sizeof(*ident)); |
285 |
|
286 |
@@ -1942,6 +1967,7 @@ |
287 |
strbuf_init(&ident->left, 0); |
288 |
ident->filter.vtbl = &ident_vtbl; |
289 |
ident->state = 0; |
290 |
+ ident->idact = idact; |
291 |
return (struct stream_filter *)ident; |
292 |
} |
293 |
|
294 |
@@ -1961,8 +1987,8 @@ |
295 |
if (classify_conv_attrs(ca) != CA_CLASS_STREAMABLE) |
296 |
return NULL; |
297 |
|
298 |
- if (ca->ident) |
299 |
- filter = ident_filter(oid); |
300 |
+ if (ca->ident_action.id) |
301 |
+ filter = ident_filter(oid, &(ca->ident_action)); |
302 |
|
303 |
if (output_eol(ca->crlf_action) == EOL_CRLF) |
304 |
filter = cascade_filter(filter, lf_to_crlf_filter()); |