Revision 43ec55091553658e4cfb1d927ff2a0fb50a8fdba authored by Jeff King on 16 June 2016, 23:37:20 UTC, committed by Junio C Hamano on 17 June 2016, 00:21:48 UTC
init_revisions() initializes the rev_info struct to default
values, and setup_revisions() parses any command-line
arguments and finalizes the struct.

In e22278c (bisect: display first bad commit without forking
a new process, 2009-05-28), a show_diff_tree() was added
that calls the former but not the latter. It doesn't have
any arguments to parse, but it still should do the
finalizing step.

This may have caused other minor bugs over the years, but it
became much more prominent after fe37a9c (pretty: allow
tweaking tabwidth in --expand-tabs, 2016-03-29). That leaves
the expected tab width as "-1", rather than the true default
of "8". When we see a commit with tabs to be expanded, we
end up trying to add (size_t)-1 spaces to a strbuf, which
complains about the integer overflow.

The fix is easy: just call setup_revisions() with no
arguments.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 7654286
Raw File
connected.c
#include "cache.h"
#include "run-command.h"
#include "sigchain.h"
#include "connected.h"
#include "transport.h"

int check_everything_connected(sha1_iterate_fn fn, int quiet, void *cb_data)
{
	return check_everything_connected_with_transport(fn, quiet, cb_data, NULL);
}
/*
 * If we feed all the commits we want to verify to this command
 *
 *  $ git rev-list --objects --stdin --not --all
 *
 * and if it does not error out, that means everything reachable from
 * these commits locally exists and is connected to our existing refs.
 * Note that this does _not_ validate the individual objects.
 *
 * Returns 0 if everything is connected, non-zero otherwise.
 */
static int check_everything_connected_real(sha1_iterate_fn fn,
					   int quiet,
					   void *cb_data,
					   struct transport *transport,
					   const char *shallow_file)
{
	struct child_process rev_list = CHILD_PROCESS_INIT;
	const char *argv[9];
	char commit[41];
	unsigned char sha1[20];
	int err = 0, ac = 0;
	struct packed_git *new_pack = NULL;
	size_t base_len;

	if (fn(cb_data, sha1))
		return err;

	if (transport && transport->smart_options &&
	    transport->smart_options->self_contained_and_connected &&
	    transport->pack_lockfile &&
	    strip_suffix(transport->pack_lockfile, ".keep", &base_len)) {
		struct strbuf idx_file = STRBUF_INIT;
		strbuf_add(&idx_file, transport->pack_lockfile, base_len);
		strbuf_addstr(&idx_file, ".idx");
		new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);
		strbuf_release(&idx_file);
	}

	if (shallow_file) {
		argv[ac++] = "--shallow-file";
		argv[ac++] = shallow_file;
	}
	argv[ac++] = "rev-list";
	argv[ac++] = "--objects";
	argv[ac++] = "--stdin";
	argv[ac++] = "--not";
	argv[ac++] = "--all";
	if (quiet)
		argv[ac++] = "--quiet";
	argv[ac] = NULL;

	rev_list.argv = argv;
	rev_list.git_cmd = 1;
	rev_list.in = -1;
	rev_list.no_stdout = 1;
	rev_list.no_stderr = quiet;
	if (start_command(&rev_list))
		return error(_("Could not run 'git rev-list'"));

	sigchain_push(SIGPIPE, SIG_IGN);

	commit[40] = '\n';
	do {
		/*
		 * If index-pack already checked that:
		 * - there are no dangling pointers in the new pack
		 * - the pack is self contained
		 * Then if the updated ref is in the new pack, then we
		 * are sure the ref is good and not sending it to
		 * rev-list for verification.
		 */
		if (new_pack && find_pack_entry_one(sha1, new_pack))
			continue;

		memcpy(commit, sha1_to_hex(sha1), 40);
		if (write_in_full(rev_list.in, commit, 41) < 0) {
			if (errno != EPIPE && errno != EINVAL)
				error(_("failed write to rev-list: %s"),
				      strerror(errno));
			err = -1;
			break;
		}
	} while (!fn(cb_data, sha1));

	if (close(rev_list.in)) {
		error(_("failed to close rev-list's stdin: %s"), strerror(errno));
		err = -1;
	}

	sigchain_pop(SIGPIPE);
	return finish_command(&rev_list) || err;
}

int check_everything_connected_with_transport(sha1_iterate_fn fn,
					      int quiet,
					      void *cb_data,
					      struct transport *transport)
{
	return check_everything_connected_real(fn, quiet, cb_data,
					       transport, NULL);
}

int check_shallow_connected(sha1_iterate_fn fn, int quiet, void *cb_data,
			    const char *shallow_file)
{
	return check_everything_connected_real(fn, quiet, cb_data,
					       NULL, shallow_file);
}
back to top