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
13 static char const * const builtin_mktag_usage[] = {
14 "git mktag",
15 NULL
16 };
17 static int option_strict = 1;
18
19 static struct fsck_options fsck_options;
20
21 static 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
49 static 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
75 int cmd_mktag(int argc,
76 const char **argv,
77 const char *prefix,
78 struct repository *repo)
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_init(&fsck_options, repo, FSCK_OPTIONS_STRICT);
98 fsck_options.error_func = mktag_fsck_error_func;
99 fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
100 FSCK_WARN);
101 /* config might set fsck.extraHeaderEntry=* again */
102 repo_config(the_repository, git_fsck_config, &fsck_options);
103 if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
104 &tagged_oid, &tagged_type))
105 die(_("tag on stdin did not pass our strict fsck check"));
106
107 if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0)
108 die(_("tag on stdin did not refer to a valid object"));
109
110 if (odb_write_object(the_repository->objects, buf.buf, buf.len, OBJ_TAG, &result) < 0)
111 die(_("unable to write tag file"));
112
113 strbuf_release(&buf);
114 puts(oid_to_hex(&result));
115 return 0;
116 }