Re: [PATCH v3 2/3] builtin: introduce diff-pairs command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 25/02/27 01:56PM, Patrick Steinhardt wrote:
> > +static void flush_diff_queue(struct diff_options *options)
> > +{
> > +	/*
> > +	 * If rename detection is not requested, use rename information from the
> > +	 * raw diff formatted input. Setting found_follow ensures diffcore_std()
> > +	 * does not mess with rename information already present in queued
> > +	 * filepairs.
> > +	 */
> > +	if (!options->detect_rename)
> > +		options->found_follow = 1;
> 
> It's a bit weird that we set this over here. Shouldn't we have set it up
> in the main function already?

Everytime diffcore_std() is invoked found_follow gets reset. This was
included here to ensure the correct value is always set.

In the next version I am going to move away from using found_follow in
favor of a new diff_options field to avoid some of this awkwardness
altogether.

> > +	diffcore_std(options);
> > +	diff_flush(options);
> > +}
> > +
> > +int cmd_diff_pairs(int argc, const char **argv, const char *prefix,
> > +		   struct repository *repo)
> > +{
> > +	struct strbuf path_dst = STRBUF_INIT;
> > +	struct strbuf path = STRBUF_INIT;
> > +	struct strbuf meta = STRBUF_INIT;
> > +	struct rev_info revs;
> > +	int ret;
> > +
> > +	const char * const usage[] = {
> > +		N_("git diff-pairs -z [<diff-options>]"),
> > +		NULL
> > +	};
> > +	struct option options[] = {
> > +		OPT_END()
> > +	};
> > +	struct option *parseopts = add_diff_options(options, &revs.diffopt);
> > +
> > +	show_usage_with_options_if_asked(argc, argv, usage, parseopts);
> 
> Don't we also have to call `parse_options()` even though we don't have
> our own options yet? Or is this all handled by `setup_revisions()`?

In the current implementation, the diff options that get appended are
only really used so that the usage message prints with the diff option
info. It still relies on setup_revisions() to actually parse the
options. Since there are not any real options that need parsing,
parse_options() was not invoked.

This is fairly confusing though. I plan to instead parse the diff
options upfront with parse_options(). The diff options parsing through
setup_revisions() becomes effectively a no-op. I think this makes more
sense to read and still lets us print the common diff options is the
usage message.

> > +	repo_init_revisions(repo, &revs, prefix);
> > +	repo_config(repo, git_diff_basic_config, NULL);
> > +	revs.disable_stdin = 1;
> > +	revs.abbrev = 0;
> > +	revs.diff = 1;
> > +
> > +	if (setup_revisions(argc, argv, &revs, NULL) > 1)
> > +		usage_with_options(usage, parseopts);
> 
> I think it's discouraged nowadays to use `usage_with_options()` as it
> generates a ton of noise while hiding the actual error message. It is
> instead recommended to directly call `usage()` with an error message.
> 
> In this case here we would say e.g. `usage(_("unrecognized argument:
> %s"), argv[0])`, in the cases below we'd use the error messages you
> already have.

Good to know. I'll avoid printing the usage options message in all these
failure scenarios in favor of what you suggested.

> > +	if (!revs.diffopt.output_format)
> > +		revs.diffopt.output_format = DIFF_FORMAT_PATCH;
> 
> Instead of setting this conditionally, can we already set it up as a
> default before calling `setup_revisions()`?

The diff output format is set via OPT_BITOP() and thus can have multiple
values at the same time. For example:

  $ git diff-tree --raw --patch HEAD

will render both patch and raw output. If we unconditionally set
DIFF_FORMAT_PATCH, it will always be included in the output which is not
what we want. We only want to set DIFF_FORMAT_PATCH if there is still no
value after all options parsing has occurred.

> > +	while (1) {
> > +		struct object_id oid_a, oid_b;
> > +		struct diff_filepair *pair;
> > +		unsigned mode_a, mode_b;
> > +		const char *p;
> > +		char status;
> > +
> > +		if (strbuf_getline_nul(&meta, stdin) == EOF)
> > +			break;
> > +
> > +		p = meta.buf;
> > +		if (*p != ':')
> > +			die(_("invalid raw diff input"));
> > +		p++;
> > +
> > +		mode_a = parse_mode_or_die(p, &p);
> > +		mode_b = parse_mode_or_die(p, &p);
> > +
> > +		if (S_ISDIR(mode_a) || S_ISDIR(mode_b))
> > +			die(_("tree objects not supported"));
> 
> I assume submodules aren't supported either, are they? If so, do we also
> have to check for `S_ISGITLINK()`? It would be nice to have a test for
> them.

Submodules should actually be supported as I believe all the info
present in the raw formatted input should be enough to properly display
patch output. I'll add a submodule to the existing test setup to
validate.

Thanks
-Justin




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux