Git fork
at reftables-rust 115 lines 3.2 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#include "builtin.h" 3#include "gettext.h" 4#include "hex.h" 5#include "parse-options.h" 6#include "strbuf.h" 7#include "replace-object.h" 8#include "object-file.h" 9#include "odb.h" 10#include "fsck.h" 11#include "config.h" 12 13static char const * const builtin_mktag_usage[] = { 14 "git mktag", 15 NULL 16}; 17static int option_strict = 1; 18 19static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; 20 21static int mktag_fsck_error_func(struct fsck_options *o UNUSED, 22 void *fsck_report UNUSED, 23 enum fsck_msg_type msg_type, 24 enum fsck_msg_id msg_id UNUSED, 25 const char *message) 26{ 27 switch (msg_type) { 28 case FSCK_WARN: 29 if (!option_strict) { 30 fprintf_ln(stderr, _("warning: tag input does not pass fsck: %s"), message); 31 return 0; 32 33 } 34 /* fallthrough */ 35 case FSCK_ERROR: 36 /* 37 * We treat both warnings and errors as errors, things 38 * like missing "tagger" lines are "only" warnings 39 * under fsck, we've always considered them an error. 40 */ 41 fprintf_ln(stderr, _("error: tag input does not pass fsck: %s"), message); 42 return 1; 43 default: 44 BUG("%d (FSCK_IGNORE?) should never trigger this callback", 45 msg_type); 46 } 47} 48 49static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type) 50{ 51 int ret; 52 enum object_type type; 53 unsigned long size; 54 void *buffer; 55 const struct object_id *repl; 56 57 buffer = odb_read_object(the_repository->objects, tagged_oid, 58 &type, &size); 59 if (!buffer) 60 die(_("could not read tagged object '%s'"), 61 oid_to_hex(tagged_oid)); 62 if (type != *tagged_type) 63 die(_("object '%s' tagged as '%s', but is a '%s' type"), 64 oid_to_hex(tagged_oid), 65 type_name(*tagged_type), type_name(type)); 66 67 repl = lookup_replace_object(the_repository, tagged_oid); 68 ret = check_object_signature(the_repository, repl, buffer, size, 69 *tagged_type); 70 free(buffer); 71 72 return ret; 73} 74 75int cmd_mktag(int argc, 76 const char **argv, 77 const char *prefix, 78 struct repository *repo UNUSED) 79{ 80 static struct option builtin_mktag_options[] = { 81 OPT_BOOL(0, "strict", &option_strict, 82 N_("enable more strict checking")), 83 OPT_END(), 84 }; 85 struct strbuf buf = STRBUF_INIT; 86 struct object_id tagged_oid; 87 int tagged_type; 88 struct object_id result; 89 90 argc = parse_options(argc, argv, prefix, 91 builtin_mktag_options, 92 builtin_mktag_usage, 0); 93 94 if (strbuf_read(&buf, 0, 0) < 0) 95 die_errno(_("could not read from stdin")); 96 97 fsck_options.error_func = mktag_fsck_error_func; 98 fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY, 99 FSCK_WARN); 100 /* config might set fsck.extraHeaderEntry=* again */ 101 repo_config(the_repository, git_fsck_config, &fsck_options); 102 if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options, 103 &tagged_oid, &tagged_type)) 104 die(_("tag on stdin did not pass our strict fsck check")); 105 106 if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0) 107 die(_("tag on stdin did not refer to a valid object")); 108 109 if (odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TAG, &result) < 0) 110 die(_("unable to write tag file")); 111 112 strbuf_release(&buf); 113 puts(oid_to_hex(&result)); 114 return 0; 115}