112 lines
3.0 KiB
C
112 lines
3.0 KiB
C
#include "builtin.h"
|
|
#include "gettext.h"
|
|
#include "hex.h"
|
|
#include "parse-options.h"
|
|
#include "strbuf.h"
|
|
#include "replace-object.h"
|
|
#include "object-file.h"
|
|
#include "object-store-ll.h"
|
|
#include "fsck.h"
|
|
#include "config.h"
|
|
|
|
static char const * const builtin_mktag_usage[] = {
|
|
"git mktag",
|
|
NULL
|
|
};
|
|
static int option_strict = 1;
|
|
|
|
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
|
|
|
|
static int mktag_fsck_error_func(struct fsck_options *o UNUSED,
|
|
void *fsck_report UNUSED,
|
|
enum fsck_msg_type msg_type,
|
|
enum fsck_msg_id msg_id UNUSED,
|
|
const char *message)
|
|
{
|
|
switch (msg_type) {
|
|
case FSCK_WARN:
|
|
if (!option_strict) {
|
|
fprintf_ln(stderr, _("warning: tag input does not pass fsck: %s"), message);
|
|
return 0;
|
|
|
|
}
|
|
/* fallthrough */
|
|
case FSCK_ERROR:
|
|
/*
|
|
* We treat both warnings and errors as errors, things
|
|
* like missing "tagger" lines are "only" warnings
|
|
* under fsck, we've always considered them an error.
|
|
*/
|
|
fprintf_ln(stderr, _("error: tag input does not pass fsck: %s"), message);
|
|
return 1;
|
|
default:
|
|
BUG(_("%d (FSCK_IGNORE?) should never trigger this callback"),
|
|
msg_type);
|
|
}
|
|
}
|
|
|
|
static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
|
|
{
|
|
int ret;
|
|
enum object_type type;
|
|
unsigned long size;
|
|
void *buffer;
|
|
const struct object_id *repl;
|
|
|
|
buffer = repo_read_object_file(the_repository, tagged_oid, &type,
|
|
&size);
|
|
if (!buffer)
|
|
die(_("could not read tagged object '%s'"),
|
|
oid_to_hex(tagged_oid));
|
|
if (type != *tagged_type)
|
|
die(_("object '%s' tagged as '%s', but is a '%s' type"),
|
|
oid_to_hex(tagged_oid),
|
|
type_name(*tagged_type), type_name(type));
|
|
|
|
repl = lookup_replace_object(the_repository, tagged_oid);
|
|
ret = check_object_signature(the_repository, repl, buffer, size,
|
|
*tagged_type);
|
|
free(buffer);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int cmd_mktag(int argc, const char **argv, const char *prefix)
|
|
{
|
|
static struct option builtin_mktag_options[] = {
|
|
OPT_BOOL(0, "strict", &option_strict,
|
|
N_("enable more strict checking")),
|
|
OPT_END(),
|
|
};
|
|
struct strbuf buf = STRBUF_INIT;
|
|
struct object_id tagged_oid;
|
|
int tagged_type;
|
|
struct object_id result;
|
|
|
|
argc = parse_options(argc, argv, prefix,
|
|
builtin_mktag_options,
|
|
builtin_mktag_usage, 0);
|
|
|
|
if (strbuf_read(&buf, 0, 0) < 0)
|
|
die_errno(_("could not read from stdin"));
|
|
|
|
fsck_options.error_func = mktag_fsck_error_func;
|
|
fsck_set_msg_type_from_ids(&fsck_options, FSCK_MSG_EXTRA_HEADER_ENTRY,
|
|
FSCK_WARN);
|
|
/* config might set fsck.extraHeaderEntry=* again */
|
|
git_config(git_fsck_config, &fsck_options);
|
|
if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
|
|
&tagged_oid, &tagged_type))
|
|
die(_("tag on stdin did not pass our strict fsck check"));
|
|
|
|
if (verify_object_in_tag(&tagged_oid, &tagged_type) < 0)
|
|
die(_("tag on stdin did not refer to a valid object"));
|
|
|
|
if (write_object_file(buf.buf, buf.len, OBJ_TAG, &result) < 0)
|
|
die(_("unable to write tag file"));
|
|
|
|
strbuf_release(&buf);
|
|
puts(oid_to_hex(&result));
|
|
return 0;
|
|
}
|