int setup_revisions()

in revision.c [2798:2998]


int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *opt)
{
	int i, flags, left, seen_dashdash, revarg_opt;
	struct strvec prune_data = STRVEC_INIT;
	int seen_end_of_options = 0;

	/* First, search for "--" */
	if (opt && opt->assume_dashdash) {
		seen_dashdash = 1;
	} else {
		seen_dashdash = 0;
		for (i = 1; i < argc; i++) {
			const char *arg = argv[i];
			if (strcmp(arg, "--"))
				continue;
			if (opt && opt->free_removed_argv_elements)
				free((char *)argv[i]);
			argv[i] = NULL;
			argc = i;
			if (argv[i + 1])
				strvec_pushv(&prune_data, argv + i + 1);
			seen_dashdash = 1;
			break;
		}
	}

	/* Second, deal with arguments and options */
	flags = 0;
	revarg_opt = opt ? opt->revarg_opt : 0;
	if (seen_dashdash)
		revarg_opt |= REVARG_CANNOT_BE_FILENAME;
	for (left = i = 1; i < argc; i++) {
		const char *arg = argv[i];
		if (!seen_end_of_options && *arg == '-') {
			int opts;

			opts = handle_revision_pseudo_opt(
						revs, argv + i,
						&flags);
			if (opts > 0) {
				i += opts - 1;
				continue;
			}

			if (!strcmp(arg, "--stdin")) {
				if (revs->disable_stdin) {
					argv[left++] = arg;
					continue;
				}
				if (revs->read_from_stdin++)
					die("--stdin given twice?");
				read_revisions_from_stdin(revs, &prune_data);
				continue;
			}

			if (!strcmp(arg, "--end-of-options")) {
				seen_end_of_options = 1;
				continue;
			}

			opts = handle_revision_opt(revs, argc - i, argv + i,
						   &left, argv, opt);
			if (opts > 0) {
				i += opts - 1;
				continue;
			}
			if (opts < 0)
				exit(128);
			continue;
		}


		if (handle_revision_arg(arg, revs, flags, revarg_opt)) {
			int j;
			if (seen_dashdash || *arg == '^')
				die("bad revision '%s'", arg);

			/* If we didn't have a "--":
			 * (1) all filenames must exist;
			 * (2) all rev-args must not be interpretable
			 *     as a valid filename.
			 * but the latter we have checked in the main loop.
			 */
			for (j = i; j < argc; j++)
				verify_filename(revs->prefix, argv[j], j == i);

			strvec_pushv(&prune_data, argv + i);
			break;
		}
	}
	revision_opts_finish(revs);

	if (prune_data.nr) {
		/*
		 * If we need to introduce the magic "a lone ':' means no
		 * pathspec whatsoever", here is the place to do so.
		 *
		 * if (prune_data.nr == 1 && !strcmp(prune_data[0], ":")) {
		 *	prune_data.nr = 0;
		 *	prune_data.alloc = 0;
		 *	free(prune_data.path);
		 *	prune_data.path = NULL;
		 * } else {
		 *	terminate prune_data.alloc with NULL and
		 *	call init_pathspec() to set revs->prune_data here.
		 * }
		 */
		parse_pathspec(&revs->prune_data, 0, 0,
			       revs->prefix, prune_data.v);
	}
	strvec_clear(&prune_data);

	if (!revs->def)
		revs->def = opt ? opt->def : NULL;
	if (opt && opt->tweak)
		opt->tweak(revs, opt);
	if (revs->show_merge)
		prepare_show_merge(revs);
	if (revs->def && !revs->pending.nr && !revs->rev_input_given) {
		struct object_id oid;
		struct object *object;
		struct object_context oc;
		if (get_oid_with_context(revs->repo, revs->def, 0, &oid, &oc))
			diagnose_missing_default(revs->def);
		object = get_reference(revs, revs->def, &oid, 0);
		add_pending_object_with_mode(revs, object, revs->def, oc.mode);
	}

	/* Did the user ask for any diff output? Run the diff! */
	if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT)
		revs->diff = 1;

	/* Pickaxe, diff-filter and rename following need diffs */
	if ((revs->diffopt.pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
	    revs->diffopt.filter ||
	    revs->diffopt.flags.follow_renames)
		revs->diff = 1;

	if (revs->diffopt.objfind)
		revs->simplify_history = 0;

	if (revs->line_level_traverse) {
		if (want_ancestry(revs))
			revs->limited = 1;
		revs->topo_order = 1;
	}

	if (revs->topo_order && !generation_numbers_enabled(the_repository))
		revs->limited = 1;

	if (revs->prune_data.nr) {
		copy_pathspec(&revs->pruning.pathspec, &revs->prune_data);
		/* Can't prune commits with rename following: the paths change.. */
		if (!revs->diffopt.flags.follow_renames)
			revs->prune = 1;
		if (!revs->full_diff)
			copy_pathspec(&revs->diffopt.pathspec,
				      &revs->prune_data);
	}

	diff_merges_setup_revs(revs);

	revs->diffopt.abbrev = revs->abbrev;

	diff_setup_done(&revs->diffopt);

	if (!is_encoding_utf8(get_log_output_encoding()))
		revs->grep_filter.ignore_locale = 1;
	compile_grep_patterns(&revs->grep_filter);

	if (revs->reverse && revs->reflog_info)
		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--walk-reflogs");
	if (revs->reflog_info && revs->limited)
		die("cannot combine --walk-reflogs with history-limiting options");
	if (revs->rewrite_parents && revs->children.name)
		die(_("options '%s' and '%s' cannot be used together"), "--parents", "--children");
	if (revs->filter.choice && !revs->blob_objects)
		die(_("object filtering requires --objects"));

	/*
	 * Limitations on the graph functionality
	 */
	if (revs->reverse && revs->graph)
		die(_("options '%s' and '%s' cannot be used together"), "--reverse", "--graph");

	if (revs->reflog_info && revs->graph)
		die(_("options '%s' and '%s' cannot be used together"), "--walk-reflogs", "--graph");
	if (revs->no_walk && revs->graph)
		die(_("options '%s' and '%s' cannot be used together"), "--no-walk", "--graph");
	if (!revs->reflog_info && revs->grep_filter.use_reflog_filter)
		die(_("the option '%s' requires '%s'"), "--grep-reflog", "--walk-reflogs");

	if (revs->line_level_traverse &&
	    (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
		die(_("-L does not yet support diff formats besides -p and -s"));

	if (revs->expand_tabs_in_log < 0)
		revs->expand_tabs_in_log = revs->expand_tabs_in_log_default;

	return left;
}