git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Johan Herland <johan@herland.net>
Cc: git@vger.kernel.org, bebarino@gmail.com, gitster@pobox.com
Subject: Re: [PATCH 08/18] git notes merge: Initial implementation handling trivial merges only
Date: Thu, 7 Oct 2010 01:24:33 -0500	[thread overview]
Message-ID: <20101007062433.GF2285@burratino> (raw)
In-Reply-To: <1285719811-10871-9-git-send-email-johan@herland.net>

Johan Herland wrote:

> This initial implementation of 'git notes merge' only handles the trivial
> merge cases (i.e. where the merge is either a no-op, or a fast-forward).

This alone should already be a nice UI improvement: in the
fast-forward case, with this patch applied, in place of

	git fetch . refs/notes/x:refs/notes/commits

one could write

	git notes merge x

This reminds me: it would be nice if non-builtin scripts could use

	git notes --get-notes-ref $refarg

to learn the configured notes ref.  In other words, shouldn't the
default_notes_ref() exposed in patch 2 also be exposed to scripted
callers?  If someone else doesn't get around to it, I can mock
something up in the next few days.

[...]
> +++ b/notes-merge.h
> @@ -0,0 +1,30 @@
> +#ifndef NOTES_MERGE_H
> +#define NOTES_MERGE_H
> +
> +struct notes_merge_options {
> +	const char *local_ref;
> +	const char *remote_ref;
> +	int verbosity;
> +};
> +
> +void init_notes_merge_options(struct notes_merge_options *o);
[...]
> +int notes_merge(struct notes_merge_options *o,
> +		unsigned char *result_sha1);

So the command is usable as-is from other builtins.  Nice.

> +++ b/notes-merge.c
> @@ -0,0 +1,103 @@
[...]
> +#include "cache.h"
> +#include "commit.h"
> +#include "notes-merge.h"
> +
> +void init_notes_merge_options(struct notes_merge_options *o)
> +{
> +	memset(o, 0, sizeof(struct notes_merge_options));
> +	o->verbosity = 2;
> +}
> +
> +static int show(struct notes_merge_options *o, int v)
> +{
> +	return (o->verbosity >= v) || o->verbosity >= 5;
> +}

Should the verbosities be of enum type?

	enum notes_merge_verbosity {
		DEFAULT_VERBOSITY = 2,
		MAX_VERBOSITY = 5,
		etc
	};

> +
> +#define OUTPUT(o, v, ...) \
> +	do { if (show((o), (v))) { printf(__VA_ARGS__); puts(""); } } while (0)

I would find it easier to read

	if (o->verbosity >= DEFAULT_VERBOSITY)
		fprintf(stderr, ...)

unless there are going to be a huge number of messages.

> +
> +int notes_merge(struct notes_merge_options *o,
> +		unsigned char *result_sha1)
> +{
> +	unsigned char local_sha1[20], remote_sha1[20];
> +	struct commit *local, *remote;
> +	struct commit_list *bases = NULL;
> +	const unsigned char *base_sha1;
> +	int result = 0;
> +
> +	hashclr(result_sha1);
> +
> +	OUTPUT(o, 5, "notes_merge(o->local_ref = %s, o->remote_ref = %s)",
> +	       o->local_ref, o->remote_ref);

Would trace_printf be a good fit for messages like this one?  If not,
any idea about how it could be made to fit some day?

(It is especially nice to be able to direct the trace somewhere other
than stdout and stderr when running tests.)

> +
> +	if (!o->local_ref || get_sha1(o->local_ref, local_sha1)) {
> +		/* empty notes ref => assume empty notes tree */

Can an empty ref be distinguished from a missing ref?  It would be
nice to error out when breakage is detected.

[...]
> +	/* Find merge bases */
> +	bases = get_merge_bases(local, remote, 1);
> +	if (!bases) {
> +		base_sha1 = null_sha1;
> +		OUTPUT(o, 4, "No merge base found; doing history-less merge");
> +	} else if (!bases->next) {
> +		base_sha1 = bases->item->object.sha1;
> +		OUTPUT(o, 4, "One merge base found (%.7s)",
> +		       sha1_to_hex(base_sha1));
> +	} else {
> +		/* TODO: How to handle multiple merge-bases? */

With a recursive merge of the ancestors, of course. :)

The difficult part is what to do when a merge of ancestors results in
conflicts.

[...]
> +++ b/builtin/notes.c
> @@ -772,6 +779,50 @@ static int show(int argc, const char **argv, const char *prefix)
>  	return retval;
>  }
>  
> +static int merge(int argc, const char **argv, const char *prefix)
> +{
> +	struct strbuf remote_ref = STRBUF_INIT, msg = STRBUF_INIT;
> +	unsigned char result_sha1[20];
> +	struct notes_merge_options o;
> +	int verbosity = 0, result;
> +	struct option options[] = {
> +		OPT__VERBOSITY(&verbosity),
> +		OPT_END()
> +	};
> +
> +	argc = parse_options(argc, argv, prefix, options,
> +			     git_notes_merge_usage, 0);
> +
> +	if (argc != 1) {
> +		error("Must specify a notes ref to merge");
> +		usage_with_options(git_notes_merge_usage, options);
> +	}
> +
> +	init_notes_merge_options(&o);
> +	o.verbosity = verbosity + 2; // default verbosity level is 2

Maybe

	o.verbosity += verbosity;

or

	o.verbosity = DEFAULT_NOTES_MERGE_VERBOSITY + verbosity;

to allow the default verbosity to be set in one place?

> +	o.local_ref = default_notes_ref();
> +	strbuf_addstr(&remote_ref, argv[0]);
> +	expand_notes_ref(&remote_ref);
> +	o.remote_ref = remote_ref.buf;
> +
> +	result = notes_merge(&o, result_sha1);
> +
> +	strbuf_addf(&msg, "notes: Merged notes from %s into %s",
> +		    remote_ref.buf, default_notes_ref());
> +	if (result == 0) { /* Merge resulted (trivially) in result_sha1 */
> +		/* Update default notes ref with new commit */
> +		update_ref(msg.buf, default_notes_ref(), result_sha1, NULL,
> +			   0, DIE_ON_ERR);
> +	} else {
> +		/* TODO: */
> +		die("'git notes merge' cannot yet handle non-trivial merges!");

Mm.  In the long run, will (result != 0) mean "merge conflict"?

> @@ -865,6 +916,8 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
>  		result = append_edit(argc, argv, prefix);
>  	else if (!strcmp(argv[0], "show"))
>  		result = show(argc, argv, prefix);
> +	else if (!strcmp(argv[0], "merge"))
> +		result = merge(argc, argv, prefix);

Thanks for a pleasant read.

  parent reply	other threads:[~2010-10-07  6:27 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-29  0:23 [PATCH 00/18] git notes merge Johan Herland
2010-09-29  0:23 ` [PATCH 01/18] (trivial) notes.h: Minor documentation fixes to copy_notes() Johan Herland
2010-10-05 14:55   ` Jonathan Nieder
2010-10-05 15:22     ` Johan Herland
2010-10-05 15:26       ` Jonathan Nieder
2010-09-29  0:23 ` [PATCH 02/18] notes.h: Make default_notes_ref() available in notes API Johan Herland
2010-09-29  0:23 ` [PATCH 03/18] notes.h/c: Clarify the handling of notes objects that are == null_sha1 Johan Herland
2010-10-05 15:21   ` Jonathan Nieder
2010-10-05 22:30     ` Johan Herland
2010-09-29  0:23 ` [PATCH 04/18] notes.h/c: Propagate combine_notes_fn return value to add_note() and beyond Johan Herland
2010-10-05 15:38   ` Jonathan Nieder
2010-10-06 19:40     ` Johan Herland
2010-09-29  0:23 ` [PATCH 05/18] (trivial) t3303: Indent with tabs instead of spaces for consistency Johan Herland
2010-09-29  0:23 ` [PATCH 06/18] notes.c: Use two newlines (instead of one) when concatenating notes Johan Herland
2010-09-29  0:23 ` [PATCH 07/18] builtin/notes.c: Split notes ref DWIMmery into a separate function Johan Herland
2010-10-05 15:50   ` Jonathan Nieder
2010-10-07 13:56     ` Johan Herland
2010-09-29  0:23 ` [PATCH 08/18] git notes merge: Initial implementation handling trivial merges only Johan Herland
2010-10-07  4:37   ` Test script style (Re: [PATCH 08/18] git notes merge: Initial implementation handling trivial merges only) Jonathan Nieder
2010-10-07  4:57     ` Junio C Hamano
2010-10-07  6:24   ` Jonathan Nieder [this message]
2010-10-08 23:55     ` [PATCH 08/18] git notes merge: Initial implementation handling trivial merges only Johan Herland
2010-10-09 17:29       ` Jonathan Nieder
2010-10-21  2:12         ` Johan Herland
2010-09-29  0:23 ` [PATCH 09/18] builtin/notes.c: Refactor creation of notes commits Johan Herland
2010-09-29  0:23 ` [PATCH 10/18] git notes merge: Handle real, non-conflicting notes merges Johan Herland
2010-09-29 16:20   ` Ævar Arnfjörð Bjarmason
2010-09-29 23:25     ` Johan Herland
2010-09-29  0:23 ` [PATCH 11/18] git notes merge: Add automatic conflict resolvers (ours, theirs, union) Johan Herland
2010-10-02  9:14   ` Stephen Boyd
2010-10-04 15:10     ` Johan Herland
2010-09-29  0:23 ` [PATCH 12/18] Documentation: Preliminary docs on 'git notes merge' Johan Herland
2010-10-02  8:55   ` Stephen Boyd
2010-10-04 15:15     ` Johan Herland
2010-09-29  0:23 ` [PATCH 13/18] git notes merge: Manual conflict resolution, part 1/2 Johan Herland
2010-09-29  0:23 ` [PATCH 14/18] git notes merge: Manual conflict resolution, part 2/2 Johan Herland
2010-09-29 16:19   ` Ævar Arnfjörð Bjarmason
2010-09-29 23:37     ` Johan Herland
2010-09-29  0:23 ` [PATCH 15/18] git notes merge: List conflicting notes in notes merge commit message Johan Herland
2010-09-29  0:23 ` [PATCH 16/18] git notes merge: --commit should fail if underlying notes ref has moved Johan Herland
2010-09-29  0:23 ` [PATCH 17/18] git notes merge: Add another auto-resolving strategy: "cat_sort_uniq" Johan Herland
2010-09-29  0:23 ` [PATCH 18/18] git notes merge: Add testcases for merging notes trees at different fanouts Johan Herland
2010-09-29 14:56 ` [PATCH 00/18] git notes merge Sverre Rabbelier
2010-09-29 15:16   ` Johan Herland
2010-09-29 15:20     ` Sverre Rabbelier
2010-09-29 16:04       ` Johan Herland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101007062433.GF2285@burratino \
    --to=jrnieder@gmail.com \
    --cc=bebarino@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johan@herland.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).