Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			113 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			113 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,
 | 
						|
				 const struct object_id *oid UNUSED,
 | 
						|
				 enum object_type object_type 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;
 | 
						|
}
 |