Skip to content

Commit 0e07c1c

Browse files
committed
Merge branch 'jk/cleanup-object-parsing-and-fsck'
Crufty code and logic accumulated over time around the object parsing and low-level object access used in "git fsck" have been cleaned up. * jk/cleanup-object-parsing-and-fsck: (23 commits) fsck: accept an oid instead of a "struct tree" for fsck_tree() fsck: accept an oid instead of a "struct commit" for fsck_commit() fsck: accept an oid instead of a "struct tag" for fsck_tag() fsck: rename vague "oid" local variables fsck: don't require an object struct in verify_headers() fsck: don't require an object struct for fsck_ident() fsck: drop blob struct from fsck_finish() fsck: accept an oid instead of a "struct blob" for fsck_blob() fsck: don't require an object struct for report() fsck: only require an oid for skiplist functions fsck: only provide oid/type in fsck_error callback fsck: don't require object structs for display functions fsck: use oids rather than objects for object_name API fsck_describe_object(): build on our get_object_name() primitive fsck: unify object-name code fsck: require an actual buffer for non-blobs fsck: stop checking tag->tagged fsck: stop checking commit->parent counts fsck: stop checking commit->tree value commit, tag: don't set parsed bit for parse failures ...
2 parents d9f6f3b + b2f2039 commit 0e07c1c

9 files changed

+312
-302
lines changed

builtin/fsck.c

Lines changed: 55 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -50,40 +50,20 @@ static int name_objects;
5050
#define ERROR_REFS 010
5151
#define ERROR_COMMIT_GRAPH 020
5252

53-
static const char *describe_object(struct object *obj)
53+
static const char *describe_object(const struct object_id *oid)
5454
{
55-
static struct strbuf bufs[] = {
56-
STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
57-
};
58-
static int b = 0;
59-
struct strbuf *buf;
60-
char *name = NULL;
61-
62-
if (name_objects)
63-
name = lookup_decoration(fsck_walk_options.object_names, obj);
64-
65-
buf = bufs + b;
66-
b = (b + 1) % ARRAY_SIZE(bufs);
67-
strbuf_reset(buf);
68-
strbuf_addstr(buf, oid_to_hex(&obj->oid));
69-
if (name)
70-
strbuf_addf(buf, " (%s)", name);
71-
72-
return buf->buf;
55+
return fsck_describe_object(&fsck_walk_options, oid);
7356
}
7457

75-
static const char *printable_type(struct object *obj)
58+
static const char *printable_type(const struct object_id *oid,
59+
enum object_type type)
7660
{
7761
const char *ret;
7862

79-
if (obj->type == OBJ_NONE) {
80-
enum object_type type = oid_object_info(the_repository,
81-
&obj->oid, NULL);
82-
if (type > 0)
83-
object_as_type(the_repository, obj, type, 0);
84-
}
63+
if (type == OBJ_NONE)
64+
type = oid_object_info(the_repository, oid, NULL);
8565

86-
ret = type_name(obj->type);
66+
ret = type_name(type);
8767
if (!ret)
8868
ret = _("unknown");
8969

@@ -118,26 +98,32 @@ static int objerror(struct object *obj, const char *err)
11898
errors_found |= ERROR_OBJECT;
11999
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
120100
fprintf_ln(stderr, _("error in %s %s: %s"),
121-
printable_type(obj), describe_object(obj), err);
101+
printable_type(&obj->oid, obj->type),
102+
describe_object(&obj->oid), err);
122103
return -1;
123104
}
124105

125106
static int fsck_error_func(struct fsck_options *o,
126-
struct object *obj, int type, const char *message)
107+
const struct object_id *oid,
108+
enum object_type object_type,
109+
int msg_type, const char *message)
127110
{
128-
switch (type) {
111+
switch (msg_type) {
129112
case FSCK_WARN:
130113
/* TRANSLATORS: e.g. warning in tree 01bfda: <more explanation> */
131114
fprintf_ln(stderr, _("warning in %s %s: %s"),
132-
printable_type(obj), describe_object(obj), message);
115+
printable_type(oid, object_type),
116+
describe_object(oid), message);
133117
return 0;
134118
case FSCK_ERROR:
135119
/* TRANSLATORS: e.g. error in tree 01bfda: <more explanation> */
136120
fprintf_ln(stderr, _("error in %s %s: %s"),
137-
printable_type(obj), describe_object(obj), message);
121+
printable_type(oid, object_type),
122+
describe_object(oid), message);
138123
return 1;
139124
default:
140-
BUG("%d (FSCK_IGNORE?) should never trigger this callback", type);
125+
BUG("%d (FSCK_IGNORE?) should never trigger this callback",
126+
msg_type);
141127
}
142128
}
143129

@@ -155,7 +141,8 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
155141
if (!obj) {
156142
/* ... these references to parent->fld are safe here */
157143
printf_ln(_("broken link from %7s %s"),
158-
printable_type(parent), describe_object(parent));
144+
printable_type(&parent->oid, parent->type),
145+
describe_object(&parent->oid));
159146
printf_ln(_("broken link from %7s %s"),
160147
(type == OBJ_ANY ? _("unknown") : type_name(type)),
161148
_("unknown"));
@@ -183,10 +170,10 @@ static int mark_object(struct object *obj, int type, void *data, struct fsck_opt
183170
if (parent && !has_object_file(&obj->oid)) {
184171
printf_ln(_("broken link from %7s %s\n"
185172
" to %7s %s"),
186-
printable_type(parent),
187-
describe_object(parent),
188-
printable_type(obj),
189-
describe_object(obj));
173+
printable_type(&parent->oid, parent->type),
174+
describe_object(&parent->oid),
175+
printable_type(&obj->oid, obj->type),
176+
describe_object(&obj->oid));
190177
errors_found |= ERROR_REACHABLE;
191178
}
192179
return 1;
@@ -292,8 +279,9 @@ static void check_reachable_object(struct object *obj)
292279
return;
293280
if (has_object_pack(&obj->oid))
294281
return; /* it is in pack - forget about it */
295-
printf_ln(_("missing %s %s"), printable_type(obj),
296-
describe_object(obj));
282+
printf_ln(_("missing %s %s"),
283+
printable_type(&obj->oid, obj->type),
284+
describe_object(&obj->oid));
297285
errors_found |= ERROR_REACHABLE;
298286
return;
299287
}
@@ -318,8 +306,9 @@ static void check_unreachable_object(struct object *obj)
318306
* since this is something that is prunable.
319307
*/
320308
if (show_unreachable) {
321-
printf_ln(_("unreachable %s %s"), printable_type(obj),
322-
describe_object(obj));
309+
printf_ln(_("unreachable %s %s"),
310+
printable_type(&obj->oid, obj->type),
311+
describe_object(&obj->oid));
323312
return;
324313
}
325314

@@ -337,12 +326,13 @@ static void check_unreachable_object(struct object *obj)
337326
*/
338327
if (!(obj->flags & USED)) {
339328
if (show_dangling)
340-
printf_ln(_("dangling %s %s"), printable_type(obj),
341-
describe_object(obj));
329+
printf_ln(_("dangling %s %s"),
330+
printable_type(&obj->oid, obj->type),
331+
describe_object(&obj->oid));
342332
if (write_lost_and_found) {
343333
char *filename = git_pathdup("lost-found/%s/%s",
344334
obj->type == OBJ_COMMIT ? "commit" : "other",
345-
describe_object(obj));
335+
describe_object(&obj->oid));
346336
FILE *f;
347337

348338
if (safe_create_leading_directories_const(filename)) {
@@ -355,7 +345,7 @@ static void check_unreachable_object(struct object *obj)
355345
if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
356346
die_errno(_("could not write '%s'"), filename);
357347
} else
358-
fprintf(f, "%s\n", describe_object(obj));
348+
fprintf(f, "%s\n", describe_object(&obj->oid));
359349
if (fclose(f))
360350
die_errno(_("could not finish '%s'"),
361351
filename);
@@ -374,7 +364,7 @@ static void check_unreachable_object(struct object *obj)
374364
static void check_object(struct object *obj)
375365
{
376366
if (verbose)
377-
fprintf_ln(stderr, _("Checking %s"), describe_object(obj));
367+
fprintf_ln(stderr, _("Checking %s"), describe_object(&obj->oid));
378368

379369
if (obj->flags & REACHABLE)
380370
check_reachable_object(obj);
@@ -432,7 +422,8 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
432422

433423
if (verbose)
434424
fprintf_ln(stderr, _("Checking %s %s"),
435-
printable_type(obj), describe_object(obj));
425+
printable_type(&obj->oid, obj->type),
426+
describe_object(&obj->oid));
436427

437428
if (fsck_walk(obj, NULL, &fsck_obj_options))
438429
objerror(obj, _("broken links"));
@@ -445,18 +436,18 @@ static int fsck_obj(struct object *obj, void *buffer, unsigned long size)
445436

446437
if (!commit->parents && show_root)
447438
printf_ln(_("root %s"),
448-
describe_object(&commit->object));
439+
describe_object(&commit->object.oid));
449440
}
450441

451442
if (obj->type == OBJ_TAG) {
452443
struct tag *tag = (struct tag *) obj;
453444

454445
if (show_tags && tag->tagged) {
455446
printf_ln(_("tagged %s %s (%s) in %s"),
456-
printable_type(tag->tagged),
457-
describe_object(tag->tagged),
447+
printable_type(&tag->tagged->oid, tag->tagged->type),
448+
describe_object(&tag->tagged->oid),
458449
tag->tag,
459-
describe_object(&tag->object));
450+
describe_object(&tag->object.oid));
460451
}
461452
}
462453

@@ -499,10 +490,10 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
499490
if (!is_null_oid(oid)) {
500491
obj = lookup_object(the_repository, oid);
501492
if (obj && (obj->flags & HAS_OBJ)) {
502-
if (timestamp && name_objects)
503-
add_decoration(fsck_walk_options.object_names,
504-
obj,
505-
xstrfmt("%s@{%"PRItime"}", refname, timestamp));
493+
if (timestamp)
494+
fsck_put_object_name(&fsck_walk_options, oid,
495+
"%s@{%"PRItime"}",
496+
refname, timestamp);
506497
obj->flags |= USED;
507498
mark_object_reachable(obj);
508499
} else if (!is_promisor_object(oid)) {
@@ -566,9 +557,8 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
566557
}
567558
default_refs++;
568559
obj->flags |= USED;
569-
if (name_objects)
570-
add_decoration(fsck_walk_options.object_names,
571-
obj, xstrdup(refname));
560+
fsck_put_object_name(&fsck_walk_options,
561+
oid, "%s", refname);
572562
mark_object_reachable(obj);
573563

574564
return 0;
@@ -742,9 +732,7 @@ static int fsck_cache_tree(struct cache_tree *it)
742732
return 1;
743733
}
744734
obj->flags |= USED;
745-
if (name_objects)
746-
add_decoration(fsck_walk_options.object_names,
747-
obj, xstrdup(":"));
735+
fsck_put_object_name(&fsck_walk_options, &it->oid, ":");
748736
mark_object_reachable(obj);
749737
if (obj->type != OBJ_TREE)
750738
err |= objerror(obj, _("non-tree in cache-tree"));
@@ -830,8 +818,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
830818
}
831819

832820
if (name_objects)
833-
fsck_walk_options.object_names =
834-
xcalloc(1, sizeof(struct decoration));
821+
fsck_enable_object_names(&fsck_walk_options);
835822

836823
git_config(fsck_config, NULL);
837824

@@ -890,9 +877,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
890877
}
891878

892879
obj->flags |= USED;
893-
if (name_objects)
894-
add_decoration(fsck_walk_options.object_names,
895-
obj, xstrdup(arg));
880+
fsck_put_object_name(&fsck_walk_options, &oid,
881+
"%s", arg);
896882
mark_object_reachable(obj);
897883
continue;
898884
}
@@ -928,10 +914,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
928914
continue;
929915
obj = &blob->object;
930916
obj->flags |= USED;
931-
if (name_objects)
932-
add_decoration(fsck_walk_options.object_names,
933-
obj,
934-
xstrfmt(":%s", active_cache[i]->name));
917+
fsck_put_object_name(&fsck_walk_options, &obj->oid,
918+
":%s", active_cache[i]->name);
935919
mark_object_reachable(obj);
936920
}
937921
if (active_cache_tree)

commit-graph.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -858,9 +858,6 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
858858
die(_("unable to parse commit %s"),
859859
oid_to_hex(&(*list)->object.oid));
860860
tree = get_commit_tree_oid(*list);
861-
if (!tree)
862-
die(_("unable to get tree for %s"),
863-
oid_to_hex(&(*list)->object.oid));
864861
hashwrite(f, tree->hash, hash_len);
865862

866863
parent = (*list)->parents;

commit.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,18 +402,35 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
402402
struct commit_graft *graft;
403403
const int tree_entry_len = the_hash_algo->hexsz + 5;
404404
const int parent_entry_len = the_hash_algo->hexsz + 7;
405+
struct tree *tree;
405406

406407
if (item->object.parsed)
407408
return 0;
408-
item->object.parsed = 1;
409+
410+
if (item->parents) {
411+
/*
412+
* Presumably this is leftover from an earlier failed parse;
413+
* clear it out in preparation for us re-parsing (we'll hit the
414+
* same error, but that's good, since it lets our caller know
415+
* the result cannot be trusted.
416+
*/
417+
free_commit_list(item->parents);
418+
item->parents = NULL;
419+
}
420+
409421
tail += size;
410422
if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) ||
411423
bufptr[tree_entry_len] != '\n')
412424
return error("bogus commit object %s", oid_to_hex(&item->object.oid));
413425
if (get_oid_hex(bufptr + 5, &parent) < 0)
414426
return error("bad tree pointer in commit %s",
415427
oid_to_hex(&item->object.oid));
416-
set_commit_tree(item, lookup_tree(r, &parent));
428+
tree = lookup_tree(r, &parent);
429+
if (!tree)
430+
return error("bad tree pointer %s in commit %s",
431+
oid_to_hex(&parent),
432+
oid_to_hex(&item->object.oid));
433+
set_commit_tree(item, tree);
417434
bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */
418435
pptr = &item->parents;
419436

@@ -433,8 +450,11 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
433450
if (graft && (graft->nr_parent < 0 || grafts_replace_parents))
434451
continue;
435452
new_parent = lookup_commit(r, &parent);
436-
if (new_parent)
437-
pptr = &commit_list_insert(new_parent, pptr)->next;
453+
if (!new_parent)
454+
return error("bad parent %s in commit %s",
455+
oid_to_hex(&parent),
456+
oid_to_hex(&item->object.oid));
457+
pptr = &commit_list_insert(new_parent, pptr)->next;
438458
}
439459
if (graft) {
440460
int i;
@@ -443,7 +463,9 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
443463
new_parent = lookup_commit(r,
444464
&graft->parent[i]);
445465
if (!new_parent)
446-
continue;
466+
return error("bad graft parent %s in commit %s",
467+
oid_to_hex(&graft->parent[i]),
468+
oid_to_hex(&item->object.oid));
447469
pptr = &commit_list_insert(new_parent, pptr)->next;
448470
}
449471
}
@@ -452,6 +474,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
452474
if (check_graph)
453475
load_commit_graph_info(r, item);
454476

477+
item->object.parsed = 1;
455478
return 0;
456479
}
457480

0 commit comments

Comments
 (0)