git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Florian Achleitner <florian.achleitner.2.6.31@gmail.com>
Cc: git@vger.kernel.org, David Michael Barr <davidbarr@google.com>,
	Sverre Rabbelier <srabbelier@gmail.com>,
	Jeff King <peff@peff.net>, Johannes Sixt <j.sixt@viscovery.net>
Subject: Re: [RFC 1/4 v2] Implement a basic remote helper for svn in C.
Date: Mon, 2 Jul 2012 06:07:41 -0500	[thread overview]
Message-ID: <20120702110741.GA3527@burratino> (raw)
In-Reply-To: <23122876.7xH9dZiP4M@flobuntu>

Hi,

Florian Achleitner wrote:

> Experimental implementation.

Ok, so this adds a new program named "remote-svn".  How do I build it?
What does it do?  Will it make my life better?

[...]
> diff: Use fifo instead of pipe: Retrieve the name of the pipe from env and open it
> for svndump.

I'd prefer to avoid this if possible, since it means having to decide
where the pipe goes on the filesystem.  Can you summarize the
discussion in the commit message so future readers understand why
we're doing it?

[...]
> --- /dev/null
> +++ b/contrib/svn-fe/remote-svn.c
> @@ -0,0 +1,207 @@
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>

git-compat-util.h (or some header that includes it) must be the first
header included so the appropriate feature test macros can be defined.
See Documentation/CodingGuidelines for more on that.

> +#include "cache.h"
> +#include "remote.h"
> +#include "strbuf.h"
> +#include "url.h"
> +#include "exec_cmd.h"
> +#include "run-command.h"
> +#include "svndump.h"
> +
> +static int debug = 0;

Small nit: please drop the redundant "= 0" here.  Or:

> +
> +static inline void printd(const char* fmt, ...)
> +{
> +	if(debug) {
> +		va_list vargs;
> +		va_start(vargs, fmt);
> +		fprintf(stderr, "rhsvn debug: ");
> +		vfprintf(stderr, fmt, vargs);
> +		fprintf(stderr, "\n");
> +		va_end(vargs);
> +	}
> +}

Why not use trace_printf and avoid the complication?

[...]

> +
> +static struct remote* remote;
> +static const char* url;
> +const char* private_refs = "refs/remote-svn/";		/* + remote->name. */
> +const char* remote_ref = "refs/heads/master";

Style: '*' attaches to the variable name, to avoid making declarations
like

	char *p, c;

confusing.

> +
> +enum cmd_result cmd_capabilities(struct strbuf* line);
> +enum cmd_result cmd_import(struct strbuf* line);
> +enum cmd_result cmd_list(struct strbuf* line);

What's a cmd_result?  '*' sticks to variable name.

> +
> +enum cmd_result { SUCCESS, NOT_HANDLED, ERROR };

Oh, that's what a cmd_result is. :)  Why not define the type before
using it to avoid keeping the reader in suspense?

What does each result represent?  If this is a convention like

 1: handled
 0: not handled
 -1: error, callee takes care of printing the error message

then please document it in a comment near the caller so the reader can
understand what is happening without too much confusion.  Given such a
comment, does the enum add clarity?

> +typedef enum cmd_result (*command)(struct strbuf*);

When I first read this, I wonder what is being commanded.  Are these
commands passed on the remote helper's standard input, commands passed
on its output, or commands run at some point in the process?  What is
the effect and return value of associated function?  Does the function
always return some success/failure value, or does it sometimes exit?

Maybe a more specific type name would be clearer?

[...]
> +
> +const command command_list[] = {
> +		cmd_capabilities, cmd_import, cmd_list, NULL
> +};

First association is to functions like cmd_fetch() which implement git
subcommands.  So I thought these were going to implement subcommands
like "git remote-svn capabilities", "git remote-svn import" and would
use the same cmd_foo(argc, argv, prefix) calling convention that git
subcommands do.  Maybe a different naming convention could avoid
confusion.

[...]
> +enum cmd_result cmd_capabilities(struct strbuf* line)
> +{
> +	if(strcmp(line->buf, "capabilities"))
> +		return NOT_HANDLED;

Style: missing SP after keyword.

> +
> +	printf("import\n");
> +	printf("\n");
> +	fflush(stdout);
> +	return SUCCESS;
> +}

Why the multiple printf?  Is the flush needed?

[...]
> +
> +enum cmd_result cmd_import(struct strbuf* line)
> +{
> +	const char* revs = "-r0:HEAD";

Style: * goes with ... (I won't point out the rest of these.

> +	int code, report_fd;
> +	char* back_pipe_env;
> +	struct child_process svndump_proc = {
> +			.argv = NULL,		/* comes later .. */

I don't understand this comment.

> +			/* we want a pipe to the child's stdout, but stdin, stderr inherited.
> +			 The user can be asked for e.g. a password */
> +			.in = 0, .out = -1, .err = 0,

Style: comments in git are spelled like this:

			/*
			 * Here I put a sentence or two explaining some
			 * relevant design decision or fact about the world
			 * that will provide useful context for
			 * understanding the following code.
			 */
> +			.no_stdin = 0, .no_stdout = 0, .no_stderr = 0,

I couldn't parse the above comment, so I'm skipping it for now.

[...]
> +			.git_cmd = 0,
> +			.silent_exec_failure = 0,
> +			.stdout_to_stderr = 0,
> +			.use_shell = 0,
> +			.clean_on_exit = 0,
> +			.preexec_cb = NULL,
> +			.env = NULL,
> +			.dir = NULL

Style: C99-style initializers are (unfortunately) not supported in
some compilers we want to support.

No need to initialize all fields --- any trailing unlisted fields
are automatically initialized to zero.

> +	};
> +
> +	if(prefixcmp(line->buf, "import"))

Style: missing SP after keyword (I won't point out the rest of these).

> +		return NOT_HANDLED;
> +
> +	back_pipe_env = getenv("GIT_REPORT_FIFO");
> +	if(!back_pipe_env) {
> +		die("Cannot get cat-blob-pipe from environment!");
> +	}

Does this mean that expected usage is something like

	GIT_REPORT_FIFO=/tmp/foo/bar git clone svn::foo/bar/baz

?  And if I don't do that, I get

	fatal: Cannot get cat-blob-pipe from environment!

and am somehow supposed to understand what to do?

> +
> +	/* opening a fifo for usually reading blocks until a writer has opened it too.
> +	 * Therefore, we open with RDWR.
> +	 */
> +	report_fd = open(back_pipe_env, O_RDWR);
> +	if(report_fd < 0) {
> +		die("Unable to open fast-import back-pipe! %s", strerror(errno));
> +	}

Is this necessary?  Why shouldn't we fork the writer first and wait
for it here?

> +
> +	printd("Opened fast-import back-pipe %s for reading.", back_pipe_env);
> +
> +	svndump_proc.argv = xcalloc(5, sizeof(char*));
> +	svndump_proc.argv[0] = "svnrdump";
> +	svndump_proc.argv[1] = "dump";
> +	svndump_proc.argv[2] = url;
> +	svndump_proc.argv[3] = revs;

Style: could simplify by using struct argv_array.

> +
> +	code = start_command(&svndump_proc);
> +	if(code)
> +		die("Unable to start %s, code %d", svndump_proc.argv[0], code);

start_command() is supposed to have printed a message already when it
fails, unless errno == ENOENT and silent_exec_failure was set.

> +
> +
> +

Style: looks like some stray carriage returns snuck in.

> +	svndump_init_fd(svndump_proc.out, report_fd);
> +	svndump_read(url);
> +	svndump_deinit();
> +	svndump_reset();

Not your fault: this API looks a little overcomplicated.

> +
> +	close(svndump_proc.out);

Important?  Wouldn't finish_command do this?

> +	close(report_fd);

What is the purpose of this step?

> +
> +	code = finish_command(&svndump_proc);
> +	if(code)
> +		warning("Something went wrong with termination of %s, code %d", svndump_proc.argv[0], code);

finish_command() is supposed to print a message when it fails.

> +	free(svndump_proc.argv);
> +
> +	printf("done\n");
> +	return SUCCESS;

Success even if it failed?

> +
> +
> +

Blank lines seem to have snuck in.

> +}
> +
> +enum cmd_result cmd_list(struct strbuf* line)
> +{
> +	if(strcmp(line->buf, "list"))
> +		return NOT_HANDLED;
> +
> +	printf("? HEAD\n");
> +	printf("? %s\n", remote_ref);

Why is this variable?

> +	printf("\n");
> +	fflush(stdout);

Why the flush?

> +	return SUCCESS;
> +}
> +
> +enum cmd_result do_command(struct strbuf* line)
> +{
> +	const command* p = command_list;
> +	enum cmd_result ret;
> +	printd("command line '%s'", line->buf);
> +	while(*p) {
> +		ret = (*p)(line);
> +		if(ret != NOT_HANDLED)
> +			return ret;
> +		p++;
> +	}

If possible, matching commands by name (like git.c does) would make
the behavior easier to predict.

[...]
> +	if (argc < 2) {
> +		fprintf(stderr, "Remote needed\n");
> +		return 1;
> +	}

usage() can be used to write a clearer error message.

[...]
> +
> +	remote = remote_get(argv[1]);
> +	if (argc == 3) {
> +		end_url_with_slash(&buf, argv[2]);
> +	} else if (argc == 2) {
> +		end_url_with_slash(&buf, remote->url[0]);
> +	} else {
> +		warning("Excess arguments!");
> +	}

Style: no need for these braces.  usage() could be used to make it
clearer to the user what she can do next.

[...]
> +	/* build private ref namespace path for this svn remote. */
> +	strbuf_init(&buf, 0);
> +	strbuf_addstr(&buf, private_refs);
> +	strbuf_addstr(&buf, remote->name);
> +	strbuf_addch(&buf, '/');
> +	private_refs = strbuf_detach(&buf, NULL);

What is a private ref namespace path?  An example would make the comment
clearer.

> +
> +	while(1) {
> +		if (strbuf_getline(&buf, stdin, '\n') == EOF) {
> +			if (ferror(stdin))
> +				fprintf(stderr, "Error reading command stream\n");

errno will be meaningful; the message can be made clearer by using it.

Maybe this could use error() or die().

[...]
> +	free((void*)url);
> +	free((void*)private_refs);

Won't this crash?

It would also be nice to add a test case to the t/ directory to make others
changing this code do not accidentally break your new functionality.

Hope that helps,
Jonathan

  reply	other threads:[~2012-07-02 11:07 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-04 17:20 [RFC 0/4] Florian Achleitner
2012-06-04 17:20 ` [RFC 1/4] Implement a basic remote helper vor svn in C Florian Achleitner
2012-06-04 17:20   ` [RFC 2/4] Integrate remote-svn into svn-fe/Makefile Florian Achleitner
2012-06-04 17:20     ` [RFC 3/4] Add svndump_init_fd to allow reading dumps from arbitrary FDs Florian Achleitner
2012-06-04 17:20       ` [RFC 4/4] Add cat-blob report pipe from fast-import to remote-helper Florian Achleitner
2012-06-05  1:33         ` David Michael Barr
2012-06-05  6:56         ` Jeff King
2012-06-05  7:07           ` David Michael Barr
2012-06-05  8:14             ` Jeff King
2012-06-05 22:16               ` Florian Achleitner
2012-06-06 13:43                 ` Jeff King
2012-06-06 21:04                   ` Florian Achleitner
2012-06-05  8:51           ` Johannes Sixt
2012-06-05  9:07             ` Jeff King
2012-06-05 22:17               ` Florian Achleitner
2012-06-05  9:09             ` Johannes Sixt
2012-06-05  1:21       ` [RFC 3/4] Add svndump_init_fd to allow reading dumps from arbitrary FDs David Michael Barr
2012-06-29  7:49 ` [RFC 0/4 v2] Florian Achleitner
2012-06-29  7:54   ` [RFC 1/4 v2] Implement a basic remote helper for svn in C Florian Achleitner
2012-07-02 11:07     ` Jonathan Nieder [this message]
2012-07-06  0:30       ` Jonathan Nieder
2012-07-06 10:39         ` Florian Achleitner
2012-07-26  8:31       ` Florian Achleitner
2012-07-26  9:08         ` Jonathan Nieder
2012-07-26 16:16           ` Florian Achleitner
2012-07-28  7:00             ` Jonathan Nieder
2012-07-30  8:12               ` Florian Achleitner
2012-07-30  8:29                 ` Jonathan Nieder
2012-07-30 13:55                   ` Florian Achleitner
2012-07-30 16:55                     ` Jonathan Nieder
2012-07-31 19:31                       ` Florian Achleitner
2012-07-31 22:43                         ` Jonathan Nieder
2012-08-01  8:25                           ` Florian Achleitner
2012-08-01 19:42                             ` Jonathan Nieder
2012-08-12 10:06                               ` Florian Achleitner
2012-08-12 16:12                                 ` Jonathan Nieder
2012-08-12 19:39                                   ` Florian Achleitner
2012-08-12 20:10                                     ` Jonathan Nieder
2012-08-12 19:36                                 ` Jonathan Nieder
2012-07-26 17:29           ` Junio C Hamano
2012-07-30  8:12             ` Florian Achleitner
2012-07-26  9:45       ` Steven Michalske
     [not found]       ` <358E6F1E-8BAD-4F82-B270-0233AB86EF66@gmail.com>
2012-07-26 11:40         ` Jonathan Nieder
2012-07-26 14:28           ` Florian Achleitner
2012-07-26 14:54             ` Jonathan Nieder
2012-07-27  7:23               ` Florian Achleitner
2012-07-28  6:54                 ` Jonathan Nieder
2012-06-29  7:58   ` [RFC 2/4 v2] Integrate remote-svn into svn-fe/Makefile Florian Achleitner
2012-06-29  7:59   ` [RFC 3/4 v2] Add svndump_init_fd to allow reading dumps from arbitrary FDs Florian Achleitner
2012-06-29  8:00   ` [RFC 4/4 v2] Add cat-blob report fifo from fast-import to remote-helper Florian Achleitner
2012-07-21 12:45     ` [RFC 4/4 v3] " Florian Achleitner
2012-07-21 14:48       ` Jonathan Nieder
2012-07-21 15:24         ` Florian Achleitner
2012-07-21 15:44           ` Jonathan Nieder
2012-07-22 21:03             ` Florian Achleitner
2012-07-22 21:24               ` Jonathan Nieder
2012-07-21 15:58           ` Jonathan Nieder

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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=20120702110741.GA3527@burratino \
    --to=jrnieder@gmail.com \
    --cc=davidbarr@google.com \
    --cc=florian.achleitner.2.6.31@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=j.sixt@viscovery.net \
    --cc=peff@peff.net \
    --cc=srabbelier@gmail.com \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).