author | Lars Hjemli <hjemli@gmail.com> | 2009-01-31 16:45:48 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2009-01-31 16:45:48 (UTC) |
commit | ae1d4d75b2a2eb3534ff4b3685cc5c0b80007ef7 (patch) (unidiff) | |
tree | 89b745555c6c47b63868bc6aa15d5e5d5d294b34 | |
parent | c495cf02bac16e459f7c9e1740798646f12c00c5 (diff) | |
download | cgit-ae1d4d75b2a2eb3534ff4b3685cc5c0b80007ef7.zip cgit-ae1d4d75b2a2eb3534ff4b3685cc5c0b80007ef7.tar.gz cgit-ae1d4d75b2a2eb3534ff4b3685cc5c0b80007ef7.tar.bz2 |
ui-tree: show hexdump of binary blobs
This teaches ui-tree to detect binary blobs and display them similar
to `hexdump -C` (only wider).
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.css | 19 | ||||
-rw-r--r-- | ui-tree.c | 71 |
2 files changed, 67 insertions, 23 deletions
@@ -170,192 +170,211 @@ img { | |||
170 | border: none; | 170 | border: none; |
171 | } | 171 | } |
172 | 172 | ||
173 | input#switch-btn { | 173 | input#switch-btn { |
174 | margin: 2px 0px 0px 0px; | 174 | margin: 2px 0px 0px 0px; |
175 | } | 175 | } |
176 | 176 | ||
177 | td#sidebar input.txt { | 177 | td#sidebar input.txt { |
178 | width: 100%; | 178 | width: 100%; |
179 | margin: 2px 0px 0px 0px; | 179 | margin: 2px 0px 0px 0px; |
180 | } | 180 | } |
181 | 181 | ||
182 | table#grid { | 182 | table#grid { |
183 | margin: 0px; | 183 | margin: 0px; |
184 | } | 184 | } |
185 | 185 | ||
186 | td#content { | 186 | td#content { |
187 | vertical-align: top; | 187 | vertical-align: top; |
188 | padding: 1em 2em 1em 1em; | 188 | padding: 1em 2em 1em 1em; |
189 | border: none; | 189 | border: none; |
190 | } | 190 | } |
191 | 191 | ||
192 | div#summary { | 192 | div#summary { |
193 | vertical-align: top; | 193 | vertical-align: top; |
194 | margin-bottom: 1em; | 194 | margin-bottom: 1em; |
195 | } | 195 | } |
196 | 196 | ||
197 | table#downloads { | 197 | table#downloads { |
198 | float: right; | 198 | float: right; |
199 | border-collapse: collapse; | 199 | border-collapse: collapse; |
200 | border: solid 1px #777; | 200 | border: solid 1px #777; |
201 | margin-left: 0.5em; | 201 | margin-left: 0.5em; |
202 | margin-bottom: 0.5em; | 202 | margin-bottom: 0.5em; |
203 | } | 203 | } |
204 | 204 | ||
205 | table#downloads th { | 205 | table#downloads th { |
206 | background-color: #ccc; | 206 | background-color: #ccc; |
207 | } | 207 | } |
208 | 208 | ||
209 | div#blob { | 209 | div#blob { |
210 | border: solid 1px black; | 210 | border: solid 1px black; |
211 | } | 211 | } |
212 | 212 | ||
213 | div.error { | 213 | div.error { |
214 | color: red; | 214 | color: red; |
215 | font-weight: bold; | 215 | font-weight: bold; |
216 | margin: 1em 2em; | 216 | margin: 1em 2em; |
217 | } | 217 | } |
218 | 218 | ||
219 | a.ls-blob, a.ls-dir, a.ls-mod { | 219 | a.ls-blob, a.ls-dir, a.ls-mod { |
220 | font-family: monospace; | 220 | font-family: monospace; |
221 | } | 221 | } |
222 | 222 | ||
223 | td.ls-size { | 223 | td.ls-size { |
224 | text-align: right; | 224 | text-align: right; |
225 | font-family: monospace; | 225 | font-family: monospace; |
226 | width: 10em; | 226 | width: 10em; |
227 | } | 227 | } |
228 | 228 | ||
229 | td.ls-mode { | 229 | td.ls-mode { |
230 | font-family: monospace; | 230 | font-family: monospace; |
231 | width: 10em; | 231 | width: 10em; |
232 | } | 232 | } |
233 | 233 | ||
234 | table.blob { | 234 | table.blob { |
235 | margin-top: 0.5em; | 235 | margin-top: 0.5em; |
236 | border-top: solid 1px black; | 236 | border-top: solid 1px black; |
237 | } | 237 | } |
238 | 238 | ||
239 | table.blob td.lines { | 239 | table.blob td.lines { |
240 | margin: 0; padding: 0; | 240 | margin: 0; padding: 0; |
241 | vertical-align: top; | 241 | vertical-align: top; |
242 | color: black; | 242 | color: black; |
243 | } | 243 | } |
244 | 244 | ||
245 | table.blob td.linenumbers { | 245 | table.blob td.linenumbers { |
246 | margin: 0; padding: 0; | 246 | margin: 0; padding: 0; |
247 | vertical-align: top; | 247 | vertical-align: top; |
248 | border-right: 1px solid gray; | 248 | border-right: 1px solid gray; |
249 | background-color: #eee; | 249 | background-color: #eee; |
250 | } | 250 | } |
251 | 251 | ||
252 | table.blob pre { | 252 | table.blob pre { |
253 | padding: 0; margin: 0; | 253 | padding: 0; margin: 0; |
254 | } | 254 | } |
255 | 255 | ||
256 | table.blob a.no { | 256 | table.blob a.no { |
257 | color: gray; | 257 | color: gray; |
258 | text-align: right; | 258 | text-align: right; |
259 | text-decoration: none; | 259 | text-decoration: none; |
260 | } | 260 | } |
261 | 261 | ||
262 | table.blob a.no a:hover { | 262 | table.blob a.no a:hover { |
263 | color: black; | 263 | color: black; |
264 | } | 264 | } |
265 | 265 | ||
266 | table.bin-blob { | ||
267 | margin-top: 0.5em; | ||
268 | border: solid 1px black; | ||
269 | } | ||
270 | |||
271 | table.bin-blob th { | ||
272 | font-family: monospace; | ||
273 | white-space: pre; | ||
274 | border: solid 1px #777; | ||
275 | padding: 0.5em 1em; | ||
276 | } | ||
277 | |||
278 | table.bin-blob td { | ||
279 | font-family: monospace; | ||
280 | white-space: pre; | ||
281 | border-left: solid 1px #777; | ||
282 | padding: 0em 1em; | ||
283 | } | ||
284 | |||
266 | table.nowrap td { | 285 | table.nowrap td { |
267 | white-space: nowrap; | 286 | white-space: nowrap; |
268 | } | 287 | } |
269 | 288 | ||
270 | table.commit-info { | 289 | table.commit-info { |
271 | border-collapse: collapse; | 290 | border-collapse: collapse; |
272 | margin-top: 1.5em; | 291 | margin-top: 1.5em; |
273 | } | 292 | } |
274 | 293 | ||
275 | table.commit-info th { | 294 | table.commit-info th { |
276 | text-align: left; | 295 | text-align: left; |
277 | font-weight: normal; | 296 | font-weight: normal; |
278 | padding: 0.1em 1em 0.1em 0.1em; | 297 | padding: 0.1em 1em 0.1em 0.1em; |
279 | vertical-align: top; | 298 | vertical-align: top; |
280 | } | 299 | } |
281 | 300 | ||
282 | table.commit-info td { | 301 | table.commit-info td { |
283 | font-weight: normal; | 302 | font-weight: normal; |
284 | padding: 0.1em 1em 0.1em 0.1em; | 303 | padding: 0.1em 1em 0.1em 0.1em; |
285 | } | 304 | } |
286 | 305 | ||
287 | div.commit-subject { | 306 | div.commit-subject { |
288 | font-weight: bold; | 307 | font-weight: bold; |
289 | font-size: 125%; | 308 | font-size: 125%; |
290 | margin: 1.5em 0em 0.5em 0em; | 309 | margin: 1.5em 0em 0.5em 0em; |
291 | padding: 0em; | 310 | padding: 0em; |
292 | } | 311 | } |
293 | 312 | ||
294 | div.commit-msg { | 313 | div.commit-msg { |
295 | white-space: pre; | 314 | white-space: pre; |
296 | font-family: monospace; | 315 | font-family: monospace; |
297 | } | 316 | } |
298 | 317 | ||
299 | div.diffstat-header { | 318 | div.diffstat-header { |
300 | font-weight: bold; | 319 | font-weight: bold; |
301 | padding-top: 1.5em; | 320 | padding-top: 1.5em; |
302 | } | 321 | } |
303 | 322 | ||
304 | table.diffstat { | 323 | table.diffstat { |
305 | border-collapse: collapse; | 324 | border-collapse: collapse; |
306 | border: solid 1px #aaa; | 325 | border: solid 1px #aaa; |
307 | background-color: #eee; | 326 | background-color: #eee; |
308 | } | 327 | } |
309 | 328 | ||
310 | table.diffstat th { | 329 | table.diffstat th { |
311 | font-weight: normal; | 330 | font-weight: normal; |
312 | text-align: left; | 331 | text-align: left; |
313 | text-decoration: underline; | 332 | text-decoration: underline; |
314 | padding: 0.1em 1em 0.1em 0.1em; | 333 | padding: 0.1em 1em 0.1em 0.1em; |
315 | font-size: 100%; | 334 | font-size: 100%; |
316 | } | 335 | } |
317 | 336 | ||
318 | table.diffstat td { | 337 | table.diffstat td { |
319 | padding: 0.2em 0.2em 0.1em 0.1em; | 338 | padding: 0.2em 0.2em 0.1em 0.1em; |
320 | font-size: 100%; | 339 | font-size: 100%; |
321 | border: none; | 340 | border: none; |
322 | } | 341 | } |
323 | 342 | ||
324 | table.diffstat td.mode { | 343 | table.diffstat td.mode { |
325 | white-space: nowrap; | 344 | white-space: nowrap; |
326 | } | 345 | } |
327 | 346 | ||
328 | table.diffstat td span.modechange { | 347 | table.diffstat td span.modechange { |
329 | padding-left: 1em; | 348 | padding-left: 1em; |
330 | color: red; | 349 | color: red; |
331 | } | 350 | } |
332 | 351 | ||
333 | table.diffstat td.add a { | 352 | table.diffstat td.add a { |
334 | color: green; | 353 | color: green; |
335 | } | 354 | } |
336 | 355 | ||
337 | table.diffstat td.del a { | 356 | table.diffstat td.del a { |
338 | color: red; | 357 | color: red; |
339 | } | 358 | } |
340 | 359 | ||
341 | table.diffstat td.upd a { | 360 | table.diffstat td.upd a { |
342 | color: blue; | 361 | color: blue; |
343 | } | 362 | } |
344 | 363 | ||
345 | table.diffstat td.graph { | 364 | table.diffstat td.graph { |
346 | width: 500px; | 365 | width: 500px; |
347 | vertical-align: middle; | 366 | vertical-align: middle; |
348 | } | 367 | } |
349 | 368 | ||
350 | table.diffstat td.graph table { | 369 | table.diffstat td.graph table { |
351 | border: none; | 370 | border: none; |
352 | } | 371 | } |
353 | 372 | ||
354 | table.diffstat td.graph td { | 373 | table.diffstat td.graph td { |
355 | padding: 0px; | 374 | padding: 0px; |
356 | border: 0px; | 375 | border: 0px; |
357 | height: 7pt; | 376 | height: 7pt; |
358 | } | 377 | } |
359 | 378 | ||
360 | table.diffstat td.graph td.add { | 379 | table.diffstat td.graph td.add { |
361 | background-color: #5c5; | 380 | background-color: #5c5; |
@@ -1,159 +1,184 @@ | |||
1 | /* ui-tree.c: functions for tree output | 1 | /* ui-tree.c: functions for tree output |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <ctype.h> | ||
9 | #include "cgit.h" | 10 | #include "cgit.h" |
10 | #include "html.h" | 11 | #include "html.h" |
11 | #include "ui-shared.h" | 12 | #include "ui-shared.h" |
12 | 13 | ||
13 | char *curr_rev; | 14 | char *curr_rev; |
14 | char *match_path; | 15 | char *match_path; |
15 | int header = 0; | 16 | int header = 0; |
16 | 17 | ||
18 | static void print_text_buffer(char *buf, unsigned long size) | ||
19 | { | ||
20 | unsigned long lineno, idx; | ||
21 | const char *numberfmt = | ||
22 | "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; | ||
23 | |||
24 | html("<table summary='blob content' class='blob'>\n"); | ||
25 | html("<tr><td class='linenumbers'><pre>"); | ||
26 | idx = 0; | ||
27 | lineno = 0; | ||
28 | htmlf(numberfmt, ++lineno); | ||
29 | while(idx < size - 1) { // skip absolute last newline | ||
30 | if (buf[idx] == '\n') | ||
31 | htmlf(numberfmt, ++lineno); | ||
32 | idx++; | ||
33 | } | ||
34 | html("</pre></td>\n"); | ||
35 | html("<td class='lines'><pre><code>"); | ||
36 | html_txt(buf); | ||
37 | html("</code></pre></td></tr></table>\n"); | ||
38 | } | ||
39 | |||
40 | static void print_binary_buffer(char *buf, unsigned long size) | ||
41 | { | ||
42 | unsigned long ofs, idx; | ||
43 | |||
44 | html("<table summary='blob content' class='bin-blob'>\n"); | ||
45 | html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); | ||
46 | for (ofs = 0; ofs < size; ofs += 32, buf += 32) { | ||
47 | htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); | ||
48 | for (idx = 0; idx < 32 && ofs + idx < size; idx++) | ||
49 | htmlf("%*s%02x", | ||
50 | idx == 16 ? 4 : 1, "", | ||
51 | buf[idx] & 0xff); | ||
52 | html(" </td><td class='hex'>"); | ||
53 | for (idx = 0; idx < 32 && ofs + idx < size; idx++) | ||
54 | htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.'); | ||
55 | html("</td></tr>\n"); | ||
56 | } | ||
57 | html("</table>\n"); | ||
58 | } | ||
59 | |||
17 | static void print_object(const unsigned char *sha1, char *path) | 60 | static void print_object(const unsigned char *sha1, char *path) |
18 | { | 61 | { |
19 | enum object_type type; | 62 | enum object_type type; |
20 | char *buf; | 63 | char *buf; |
21 | unsigned long size, lineno, idx; | 64 | unsigned long size; |
22 | const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n"; | ||
23 | 65 | ||
24 | type = sha1_object_info(sha1, &size); | 66 | type = sha1_object_info(sha1, &size); |
25 | if (type == OBJ_BAD) { | 67 | if (type == OBJ_BAD) { |
26 | cgit_print_error(fmt("Bad object name: %s", | 68 | cgit_print_error(fmt("Bad object name: %s", |
27 | sha1_to_hex(sha1))); | 69 | sha1_to_hex(sha1))); |
28 | return; | 70 | return; |
29 | } | 71 | } |
30 | 72 | ||
31 | buf = read_sha1_file(sha1, &type, &size); | 73 | buf = read_sha1_file(sha1, &type, &size); |
32 | if (!buf) { | 74 | if (!buf) { |
33 | cgit_print_error(fmt("Error reading object %s", | 75 | cgit_print_error(fmt("Error reading object %s", |
34 | sha1_to_hex(sha1))); | 76 | sha1_to_hex(sha1))); |
35 | return; | 77 | return; |
36 | } | 78 | } |
37 | 79 | ||
38 | html(" ("); | 80 | html(" ("); |
39 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, | 81 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, |
40 | curr_rev, path); | 82 | curr_rev, path); |
41 | htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); | 83 | htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); |
42 | 84 | ||
43 | html("<table summary='blob content' class='blob'>\n"); | 85 | if (buffer_is_binary(buf, size)) |
44 | html("<tr>\n"); | 86 | print_binary_buffer(buf, size); |
45 | 87 | else | |
46 | html("<td class='linenumbers'><pre>"); | 88 | print_text_buffer(buf, size); |
47 | idx = 0; | ||
48 | lineno = 0; | ||
49 | htmlf(numberfmt, ++lineno); | ||
50 | while(idx < size - 1) { // skip absolute last newline | ||
51 | if (buf[idx] == '\n') { | ||
52 | htmlf(numberfmt, ++lineno); | ||
53 | } | ||
54 | idx++; | ||
55 | } | ||
56 | html("</pre></td>\n"); | ||
57 | |||
58 | html("<td class='lines'><pre><code>"); | ||
59 | html_txt(buf); | ||
60 | html("</code></pre></td>\n"); | ||
61 | |||
62 | html("</tr>\n"); | ||
63 | html("</table>\n"); | ||
64 | } | 89 | } |
65 | 90 | ||
66 | 91 | ||
67 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, | 92 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
68 | const char *pathname, unsigned int mode, int stage, | 93 | const char *pathname, unsigned int mode, int stage, |
69 | void *cbdata) | 94 | void *cbdata) |
70 | { | 95 | { |
71 | char *name; | 96 | char *name; |
72 | char *fullpath; | 97 | char *fullpath; |
73 | enum object_type type; | 98 | enum object_type type; |
74 | unsigned long size = 0; | 99 | unsigned long size = 0; |
75 | 100 | ||
76 | name = xstrdup(pathname); | 101 | name = xstrdup(pathname); |
77 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", | 102 | fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", |
78 | ctx.qry.path ? "/" : "", name); | 103 | ctx.qry.path ? "/" : "", name); |
79 | 104 | ||
80 | if (!S_ISGITLINK(mode)) { | 105 | if (!S_ISGITLINK(mode)) { |
81 | type = sha1_object_info(sha1, &size); | 106 | type = sha1_object_info(sha1, &size); |
82 | if (type == OBJ_BAD) { | 107 | if (type == OBJ_BAD) { |
83 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", | 108 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
84 | name, | 109 | name, |
85 | sha1_to_hex(sha1)); | 110 | sha1_to_hex(sha1)); |
86 | return 0; | 111 | return 0; |
87 | } | 112 | } |
88 | } | 113 | } |
89 | 114 | ||
90 | html("<tr><td class='ls-mode'>"); | 115 | html("<tr><td class='ls-mode'>"); |
91 | cgit_print_filemode(mode); | 116 | cgit_print_filemode(mode); |
92 | html("</td><td>"); | 117 | html("</td><td>"); |
93 | if (S_ISGITLINK(mode)) { | 118 | if (S_ISGITLINK(mode)) { |
94 | htmlf("<a class='ls-mod' href='"); | 119 | htmlf("<a class='ls-mod' href='"); |
95 | html_attr(fmt(ctx.repo->module_link, | 120 | html_attr(fmt(ctx.repo->module_link, |
96 | name, | 121 | name, |
97 | sha1_to_hex(sha1))); | 122 | sha1_to_hex(sha1))); |
98 | html("'>"); | 123 | html("'>"); |
99 | html_txt(name); | 124 | html_txt(name); |
100 | html("</a>"); | 125 | html("</a>"); |
101 | } else if (S_ISDIR(mode)) { | 126 | } else if (S_ISDIR(mode)) { |
102 | cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, | 127 | cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, |
103 | curr_rev, fullpath); | 128 | curr_rev, fullpath); |
104 | } else { | 129 | } else { |
105 | cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, | 130 | cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, |
106 | curr_rev, fullpath); | 131 | curr_rev, fullpath); |
107 | } | 132 | } |
108 | htmlf("</td><td class='ls-size'>%li</td>", size); | 133 | htmlf("</td><td class='ls-size'>%li</td>", size); |
109 | 134 | ||
110 | html("<td>"); | 135 | html("<td>"); |
111 | cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, | 136 | cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, |
112 | fullpath, 0, NULL, NULL, ctx.qry.showmsg); | 137 | fullpath, 0, NULL, NULL, ctx.qry.showmsg); |
113 | if (ctx.repo->max_stats) | 138 | if (ctx.repo->max_stats) |
114 | cgit_stats_link("stats", NULL, "button", ctx.qry.head, | 139 | cgit_stats_link("stats", NULL, "button", ctx.qry.head, |
115 | fullpath); | 140 | fullpath); |
116 | html("</td></tr>\n"); | 141 | html("</td></tr>\n"); |
117 | free(name); | 142 | free(name); |
118 | return 0; | 143 | return 0; |
119 | } | 144 | } |
120 | 145 | ||
121 | static void ls_head() | 146 | static void ls_head() |
122 | { | 147 | { |
123 | html("<table summary='tree listing' class='list'>\n"); | 148 | html("<table summary='tree listing' class='list'>\n"); |
124 | html("<tr class='nohover'>"); | 149 | html("<tr class='nohover'>"); |
125 | html("<th class='left'>Mode</th>"); | 150 | html("<th class='left'>Mode</th>"); |
126 | html("<th class='left'>Name</th>"); | 151 | html("<th class='left'>Name</th>"); |
127 | html("<th class='right'>Size</th>"); | 152 | html("<th class='right'>Size</th>"); |
128 | html("<th/>"); | 153 | html("<th/>"); |
129 | html("</tr>\n"); | 154 | html("</tr>\n"); |
130 | header = 1; | 155 | header = 1; |
131 | } | 156 | } |
132 | 157 | ||
133 | static void ls_tail() | 158 | static void ls_tail() |
134 | { | 159 | { |
135 | if (!header) | 160 | if (!header) |
136 | return; | 161 | return; |
137 | html("</table>\n"); | 162 | html("</table>\n"); |
138 | header = 0; | 163 | header = 0; |
139 | } | 164 | } |
140 | 165 | ||
141 | static void ls_tree(const unsigned char *sha1, char *path) | 166 | static void ls_tree(const unsigned char *sha1, char *path) |
142 | { | 167 | { |
143 | struct tree *tree; | 168 | struct tree *tree; |
144 | 169 | ||
145 | tree = parse_tree_indirect(sha1); | 170 | tree = parse_tree_indirect(sha1); |
146 | if (!tree) { | 171 | if (!tree) { |
147 | cgit_print_error(fmt("Not a tree object: %s", | 172 | cgit_print_error(fmt("Not a tree object: %s", |
148 | sha1_to_hex(sha1))); | 173 | sha1_to_hex(sha1))); |
149 | return; | 174 | return; |
150 | } | 175 | } |
151 | 176 | ||
152 | ls_head(); | 177 | ls_head(); |
153 | read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); | 178 | read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); |
154 | ls_tail(); | 179 | ls_tail(); |
155 | } | 180 | } |
156 | 181 | ||
157 | 182 | ||
158 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, | 183 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, |
159 | const char *pathname, unsigned mode, int stage, | 184 | const char *pathname, unsigned mode, int stage, |