9
#include "refs.h"
10
#include "utf8.h"
11
#include "sha1-array.h"
12
+#include "decorate.h"
13
14
#define FSCK_FATAL -1
15
#define FSCK_INFO -2
298
return result;
299
}
300
301
+static char *get_object_name(struct fsck_options *options, struct object *obj)
302
+{
303
+ if (!options->object_names)
304
+ return NULL;
305
+ return lookup_decoration(options->object_names, obj);
306
+}
307
+
308
+static void put_object_name(struct fsck_options *options, struct object *obj,
309
+ const char *fmt, ...)
310
+{
311
+ va_list ap;
312
+ struct strbuf buf = STRBUF_INIT;
313
+ char *existing;
314
+
315
+ if (!options->object_names)
316
+ return;
317
+ existing = lookup_decoration(options->object_names, obj);
318
+ if (existing)
319
+ return;
320
+ va_start(ap, fmt);
321
+ strbuf_vaddf(&buf, fmt, ap);
322
+ add_decoration(options->object_names, obj, strbuf_detach(&buf, NULL));
323
+ va_end(ap);
324
+}
325
+
326
static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *options)
327
{
328
struct tree_desc desc;
329
struct name_entry entry;
330
int res = 0;
331
+ const char *name;
332
333
if (parse_tree(tree))
334
return -1;
335
336
+ name = get_object_name(options, &tree->object);
337
init_tree_desc(&desc, tree->buffer, tree->size);
338
while (tree_entry(&desc, &entry)) {
339
+ struct object *obj;
340
int result;
341
342
if (S_ISGITLINK(entry.mode))
343
continue;
315
- if (S_ISDIR(entry.mode))
316
- result = options->walk(&lookup_tree(entry.oid->hash)->object, OBJ_TREE, data, options);
317
- else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode))
318
- result = options->walk(&lookup_blob(entry.oid->hash)->object, OBJ_BLOB, data, options);
344
+
345
+ if (S_ISDIR(entry.mode)) {
346
+ obj = &lookup_tree(entry.oid->hash)->object;
347
+ if (name)
348
+ put_object_name(options, obj, "%s%s/", name,
349
+ entry.path);
350
+ result = options->walk(obj, OBJ_TREE, data, options);
351
+ }
352
+ else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
353
+ obj = &lookup_blob(entry.oid->hash)->object;
354
+ if (name)
355
+ put_object_name(options, obj, "%s%s", name,
356
+ entry.path);
357
+ result = options->walk(obj, OBJ_BLOB, data, options);
358
+ }
359
else {
360
result = error("in tree %s: entry %s has bad mode %.6o",
361
oid_to_hex(&tree->object.oid), entry.path, entry.mode);
370
371
static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_options *options)
372
{
373
+ int counter = 0, generation = 0, name_prefix_len = 0;
374
struct commit_list *parents;
375
int res;
376
int result;
377
+ const char *name;
378
379
if (parse_commit(commit))
380
return -1;
381
382
+ name = get_object_name(options, &commit->object);
383
+ if (name)
384
+ put_object_name(options, &commit->tree->object, "%s:", name);
385
+
386
result = options->walk((struct object *)commit->tree, OBJ_TREE, data, options);
387
if (result < 0)
388
return result;
389
res = result;
390
391
parents = commit->parents;
392
+ if (name && parents) {
393
+ int len = strlen(name), power;
394
+
395
+ if (len && name[len - 1] == '^') {
396
+ generation = 1;
397
+ name_prefix_len = len - 1;
398
+ }
399
+ else { /* parse ~<generation> suffix */
400
+ for (generation = 0, power = 1;
401
+ len && isdigit(name[len - 1]);
402
+ power *= 10)
403
+ generation += power * (name[--len] - '0');
404
+ if (power > 1 && len && name[len - 1] == '~')
405
+ name_prefix_len = len - 1;
406
+ }
407
+ }
408
+
409
while (parents) {
410
+ if (name) {
411
+ struct object *obj = &parents->item->object;
412
+
413
+ if (++counter > 1)
414
+ put_object_name(options, obj, "%s^%d",
415
+ name, counter);
416
+ else if (generation > 0)
417
+ put_object_name(options, obj, "%.*s~%d",
418
+ name_prefix_len, name, generation + 1);
419
+ else
420
+ put_object_name(options, obj, "%s^", name);
421
+ }
422
result = options->walk((struct object *)parents->item, OBJ_COMMIT, data, options);
423
if (result < 0)
424
return result;
431
432
static int fsck_walk_tag(struct tag *tag, void *data, struct fsck_options *options)
433
{
434
+ char *name = get_object_name(options, &tag->object);
435
+
436
if (parse_tag(tag))
437
return -1;
438
+ if (name)
439
+ put_object_name(options, tag->tagged, "%s", name);
440
return options->walk(tag->tagged, OBJ_ANY, data, options);
441
}
442