|
6 | 6 | #include "commit.h"
|
7 | 7 | #include "tag.h"
|
8 | 8 | #include "fsck.h"
|
| 9 | +#include "refs.h" |
9 | 10 |
|
10 | 11 | static int fsck_walk_tree(struct tree *tree, fsck_walk_func walk, void *data)
|
11 | 12 | {
|
@@ -355,14 +356,97 @@ static int fsck_commit(struct commit *commit, const char *data,
|
355 | 356 | return ret;
|
356 | 357 | }
|
357 | 358 |
|
| 359 | +static int fsck_tag_buffer(struct tag *tag, const char *data, |
| 360 | + unsigned long size, fsck_error error_func) |
| 361 | +{ |
| 362 | + unsigned char sha1[20]; |
| 363 | + int ret = 0; |
| 364 | + const char *buffer; |
| 365 | + char *to_free = NULL, *eol; |
| 366 | + struct strbuf sb = STRBUF_INIT; |
| 367 | + |
| 368 | + if (data) |
| 369 | + buffer = data; |
| 370 | + else { |
| 371 | + enum object_type type; |
| 372 | + |
| 373 | + buffer = to_free = |
| 374 | + read_sha1_file(tag->object.sha1, &type, &size); |
| 375 | + if (!buffer) |
| 376 | + return error_func(&tag->object, FSCK_ERROR, |
| 377 | + "cannot read tag object"); |
| 378 | + |
| 379 | + if (type != OBJ_TAG) { |
| 380 | + ret = error_func(&tag->object, FSCK_ERROR, |
| 381 | + "expected tag got %s", |
| 382 | + typename(type)); |
| 383 | + goto done; |
| 384 | + } |
| 385 | + } |
| 386 | + |
| 387 | + if (require_end_of_header(buffer, size, &tag->object, error_func)) |
| 388 | + goto done; |
| 389 | + |
| 390 | + if (!skip_prefix(buffer, "object ", &buffer)) { |
| 391 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'object' line"); |
| 392 | + goto done; |
| 393 | + } |
| 394 | + if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') { |
| 395 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid 'object' line format - bad sha1"); |
| 396 | + goto done; |
| 397 | + } |
| 398 | + buffer += 41; |
| 399 | + |
| 400 | + if (!skip_prefix(buffer, "type ", &buffer)) { |
| 401 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'type' line"); |
| 402 | + goto done; |
| 403 | + } |
| 404 | + eol = strchr(buffer, '\n'); |
| 405 | + if (!eol) { |
| 406 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line"); |
| 407 | + goto done; |
| 408 | + } |
| 409 | + if (type_from_string_gently(buffer, eol - buffer, 1) < 0) |
| 410 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid 'type' value"); |
| 411 | + if (ret) |
| 412 | + goto done; |
| 413 | + buffer = eol + 1; |
| 414 | + |
| 415 | + if (!skip_prefix(buffer, "tag ", &buffer)) { |
| 416 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - expected 'tag' line"); |
| 417 | + goto done; |
| 418 | + } |
| 419 | + eol = strchr(buffer, '\n'); |
| 420 | + if (!eol) { |
| 421 | + ret = error_func(&tag->object, FSCK_ERROR, "invalid format - unexpected end after 'type' line"); |
| 422 | + goto done; |
| 423 | + } |
| 424 | + strbuf_addf(&sb, "refs/tags/%.*s", (int)(eol - buffer), buffer); |
| 425 | + if (check_refname_format(sb.buf, 0)) |
| 426 | + error_func(&tag->object, FSCK_WARN, "invalid 'tag' name: %s", buffer); |
| 427 | + buffer = eol + 1; |
| 428 | + |
| 429 | + if (!skip_prefix(buffer, "tagger ", &buffer)) |
| 430 | + /* early tags do not contain 'tagger' lines; warn only */ |
| 431 | + error_func(&tag->object, FSCK_WARN, "invalid format - expected 'tagger' line"); |
| 432 | + else |
| 433 | + ret = fsck_ident(&buffer, &tag->object, error_func); |
| 434 | + |
| 435 | +done: |
| 436 | + strbuf_release(&sb); |
| 437 | + free(to_free); |
| 438 | + return ret; |
| 439 | +} |
| 440 | + |
358 | 441 | static int fsck_tag(struct tag *tag, const char *data,
|
359 | 442 | unsigned long size, fsck_error error_func)
|
360 | 443 | {
|
361 | 444 | struct object *tagged = tag->tagged;
|
362 | 445 |
|
363 | 446 | if (!tagged)
|
364 | 447 | return error_func(&tag->object, FSCK_ERROR, "could not load tagged object");
|
365 |
| - return 0; |
| 448 | + |
| 449 | + return fsck_tag_buffer(tag, data, size, error_func); |
366 | 450 | }
|
367 | 451 |
|
368 | 452 | int fsck_object(struct object *obj, void *data, unsigned long size,
|
|
0 commit comments