fsck_object(): allow passing object data separately from the object itself

When fsck'ing an incoming pack, we need to fsck objects that cannot be read via read_sha1_file() because they are not local yet (and might even be rejected if transfer.fsckobjects is set to 'true'). For commits, there is a hack in place: we basically cache commit objects' buffers anyway, but the same is not true, say, for tag objects. By refactoring fsck_object() to take the object buffer and size as optional arguments -- optional, because we still fall back to the previous method to look at the cached commit objects if the caller passes NULL -- we prepare the machinery for the upcoming handling of tag objects. The assumption that such buffers are inherently NUL terminated is now wrong, of course, hence we pass the size of the buffer so that we can add a sanity check later, to prevent running past the end of the buffer. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Sep 10, 2014 at 15:52 UTC 90a398bbd72477d5d228818db5665fdfcf13431b
5 files changed +31 -16
builtin/fsck.c
+1 -1
@@ -298,7 +298,7 @@ static int fsck_obj(struct object *obj)
298
299 if (fsck_walk(obj, mark_used, NULL))
300 objerror(obj, "broken links");
301 - if (fsck_object(obj, check_strict, fsck_error_func))
301 + if (fsck_object(obj, NULL, 0, check_strict, fsck_error_func))
302 return -1;
303
304 if (obj->type == OBJ_TREE) {
builtin/index-pack.c
+2 -1
@@ -773,7 +773,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
773 if (!obj)
774 die(_("invalid %s"), typename(type));
775 if (do_fsck_object &&
776 - fsck_object(obj, 1, fsck_error_function))
776 + fsck_object(obj, buf, size, 1,
777 + fsck_error_function))
778 die(_("Error in object"));
779 if (fsck_walk(obj, mark_link, NULL))
780 die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1));
builtin/unpack-objects.c
+10 -4
@@ -164,10 +164,10 @@ static unsigned nr_objects;
164 * Called only from check_object() after it verified this object
165 * is Ok.
166 */
167 -static void write_cached_object(struct object *obj)
167 +static void write_cached_object(struct object *obj, struct obj_buffer *obj_buf)
168 {
169 unsigned char sha1[20];
170 - struct obj_buffer *obj_buf = lookup_object_buffer(obj);
170 +
171 if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), sha1) < 0)
172 die("failed to write object %s", sha1_to_hex(obj->sha1));
173 obj->flags |= FLAG_WRITTEN;
@@ -180,6 +180,8 @@ static void write_cached_object(struct object *obj)
180 */
181 static int check_object(struct object *obj, int type, void *data)
182 {
183 + struct obj_buffer *obj_buf;
184 +
185 if (!obj)
186 return 1;
187
@@ -198,11 +200,15 @@ static int check_object(struct object *obj, int type, void *data)
200 return 0;
201 }
202
201 - if (fsck_object(obj, 1, fsck_error_function))
203 + obj_buf = lookup_object_buffer(obj);
204 + if (!obj_buf)
205 + die("Whoops! Cannot find object '%s'", sha1_to_hex(obj->sha1));
206 + if (fsck_object(obj, obj_buf->buffer, obj_buf->size, 1,
207 + fsck_error_function))
208 die("Error in object");
209 if (fsck_walk(obj, check_object, NULL))
210 die("Error on reachable objects of %s", sha1_to_hex(obj->sha1));
205 - write_cached_object(obj);
211 + write_cached_object(obj, obj_buf);
212 return 0;
213 }
214
fsck.c
+15 -9
@@ -277,7 +277,7 @@ static int fsck_ident(const char **ident, struct object *obj, fsck_error error_f
277 }
278
279 static int fsck_commit_buffer(struct commit *commit, const char *buffer,
280 - fsck_error error_func)
280 + unsigned long size, fsck_error error_func)
281 {
282 unsigned char tree_sha1[20], sha1[20];
283 struct commit_graft *graft;
@@ -322,15 +322,18 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer,
322 return 0;
323 }
324
325 -static int fsck_commit(struct commit *commit, fsck_error error_func)
325 +static int fsck_commit(struct commit *commit, const char *data,
326 + unsigned long size, fsck_error error_func)
327 {
327 - const char *buffer = get_commit_buffer(commit, NULL);
328 - int ret = fsck_commit_buffer(commit, buffer, error_func);
329 - unuse_commit_buffer(commit, buffer);
328 + const char *buffer = data ? data : get_commit_buffer(commit, &size);
329 + int ret = fsck_commit_buffer(commit, buffer, size, error_func);
330 + if (!data)
331 + unuse_commit_buffer(commit, buffer);
332 return ret;
333 }
334
333 -static int fsck_tag(struct tag *tag, fsck_error error_func)
335 +static int fsck_tag(struct tag *tag, const char *data,
336 + unsigned long size, fsck_error error_func)
337 {
338 struct object *tagged = tag->tagged;
339
@@ -339,7 +342,8 @@ static int fsck_tag(struct tag *tag, fsck_error error_func)
342 return 0;
343 }
344
342 -int fsck_object(struct object *obj, int strict, fsck_error error_func)
345 +int fsck_object(struct object *obj, void *data, unsigned long size,
346 + int strict, fsck_error error_func)
347 {
348 if (!obj)
349 return error_func(obj, FSCK_ERROR, "no valid object to fsck");
@@ -349,9 +353,11 @@ int fsck_object(struct object *obj, int strict, fsck_error error_func)
353 if (obj->type == OBJ_TREE)
354 return fsck_tree((struct tree *) obj, strict, error_func);
355 if (obj->type == OBJ_COMMIT)
352 - return fsck_commit((struct commit *) obj, error_func);
356 + return fsck_commit((struct commit *) obj, (const char *) data,
357 + size, error_func);
358 if (obj->type == OBJ_TAG)
354 - return fsck_tag((struct tag *) obj, error_func);
359 + return fsck_tag((struct tag *) obj, (const char *) data,
360 + size, error_func);
361
362 return error_func(obj, FSCK_ERROR, "unknown type '%d' (internal fsck error)",
363 obj->type);
fsck.h
+3 -1
@@ -28,6 +28,8 @@ int fsck_error_function(struct object *obj, int type, const char *fmt, ...);
28 * 0 everything OK
29 */
30 int fsck_walk(struct object *obj, fsck_walk_func walk, void *data);
31 -int fsck_object(struct object *obj, int strict, fsck_error error_func);
31 +/* If NULL is passed for data, we assume the object is local and read it. */
32 +int fsck_object(struct object *obj, void *data, unsigned long size,
33 + int strict, fsck_error error_func);
34
35 #endif