git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: "Franck Bui-Huu" <vagabon.xyz@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH 1/2] Add git-archive
Date: Tue, 05 Sep 2006 12:23:58 -0700	[thread overview]
Message-ID: <7vfyf6ce29.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: cda58cb80609050516v699338b9y57fd54f50c66e49e@mail.gmail.com

"Franck Bui-Huu" <vagabon.xyz@gmail.com> writes:

> git-archive is a command to make TAR and ZIP archives of a git tree.
> It helps prevent a proliferation of git-{format}-tree commands.

Thanks.  I like the overall structure, at least mostly.
Also dropping -tree suffix from the command name is nice, short
and sweet.

Obviously I cannot apply this patch because it is totally
whitespace damaged, but here are some comments.

> diff --git a/archive.h b/archive.h
> new file mode 100644
> index 0000000..6c69953
> --- /dev/null
> +++ b/archive.h
> @@ -0,0 +1,43 @@
> +#ifndef ARCHIVE_H
> +#define ARCHIVE_H
> +
> +typedef int (*write_archive_fn_t)(struct tree *tree,
> +				  const unsigned char *commit_sha1,
> +				  const char *prefix,
> +				  time_t time,
> +				  const char **pathspec);

The type of the first argument might have to be different,
depending on performance analysis by Rene on struct tree vs
struct tree_desc.

> +typedef int (*parse_extra_args_fn_t)(int argc,
> +				     const char **argv,
> +				     const char **reason);
> +

I do not see a way for parse_extra to record the parameter it
successfully parsed, other than in a source-file-global, static
variable.  Not a very nice design for a library, if we are
building one from scratch.

Also, you are passing "reason" around from everywhere, but that
is used by the caller to pass it to error(), so it might be
simpler to just call error() when you want to assign to *reason,
and make an error return.  The caller does not have to do
anything if you do that.  Your way might interact with the
remote protocol better, though -- I haven't thought this part
through yet so do not take this as a serious objection, but just
a comment.

> +struct archiver_struct {
> +	const char *name;
> +	write_archive_fn_t write_archive;
> +	parse_extra_args_fn_t parse_extra;
> +	const char *remote;
> +	const char *prefix;
> +};

Somehow "struct foo_struct" makes me feel uneasy, when I do not
see the reason to call it "struct foo".

Also, the first three fields are permanent property of the
archiver while two are to wrap runtime arguments of one
particular invocation.  I would have liked...

> +extern struct archiver_struct archivers[];

... this array to have only the former, and a separate structure
"struct archive_args" to be defined.

	struct archive_args {
        	const char *remote;
                const char *prefix;
	};

After parse_archive_args finds the archiver specified with
--format=*, it can call its parse_extra to retrieve a suitable
struct that has struct archive_args embedded at the beginning,
and then set remote and prefix on the returned structure.

Then a specific parse_extra implementation can be written like this:

	static struct tar_archive_args {
        	struct archive_args a;
                int z_compress;
                ...
	};

	struct archive_args *
        tar_archive_parse_extra(int ac, const char **av)
	{
        	struct tar_archive_args *args = xcalloc(1, sizeof(*args));

		while (ac--) {
			const char *arg = *++av;
                	if (arg[0] == '-' &&
                            '0' <= arg[1] && arg[1] <= '9')
				args->z_compress = arg[1] - '0';
			...
		}
		return (struct archive_args *)args;
	}

and this can be passed to tar_archive_write_archive as an
argument.

> +extern int parse_treeish_arg(const char **argv,
> +			     struct tree **tree,
> +			     const unsigned char **commit_sha1,
> +			     time_t *archive_time,
> +			     const char *prefix,
> +			     const char **reason);
> +extern int write_tar_archive(struct tree *tree,
> +			     const unsigned char *commit_sha1,
> +			     const char *prefix,
> +			     time_t time,
> +			     const char **pathspec);

I suspect we would want "struct tree_desc" based interface,
instead of "struct tree".

> +static const char archive_usage[] = \
> +"git-archive --format=<fmt> [--prefix=<prefix>/] [-0|...|-9]
> <tree-ish> [path...]";

I do not think "-[0-9]" belongs to generic "git-archive".  It
does not make much sense to run compress on zip output.  More
like:

git-archive --format=<fmt> [--prefix=<prefix>] [format specific options] <tree-ish> [path...]

It has one potential advantage, though -- git-daemon _could_
look at it and notice that the client asks for too expensive
compression level.  But I do not think it is the only way to
achive that to make "-[0-9]" a generic option.

> +static int run_remote_archiver(struct archiver_struct *ar, int argc,
> +			       const char **argv)
> +{
> +	char *url, buf[1024];
> +	pid_t pid;
> +	int fd[2];
> +	int len, rv;
> +
> +	sprintf(buf, "git-upload-%s", ar->name);

Are you calling git-upload-{tar,zip,rar,...} here?

> +	url = strdup(ar->remote);
> +	pid = git_connect(fd, url, buf);
> +	if (pid < 0)
> +		return pid;
> +
> +	concat_argv(argc, argv, buf, sizeof(buf));
> +	packet_write(fd[1], "arguments %s\n", buf);
> +	packet_flush(fd[1]);

Parameter concatenation with SP is a bad idea for two reasons.
You cannot have SP in argument.  Also packet_write() may not
like the length of the arguments.

A sequence of one argument per packet, with prefix "argument "
for future extension so that we can send other stuff if/when
needed, followed by a flush would be preferred.

> +	/* Now, start reading from fd[0] and spit it out to stdout */
> +	rv = copy_fd(fd[0], 1);
> +	close(fd[0]);
> +	rv |= finish_connect(pid);

It was painful to bolt progress indicator support onto original
upload-pack protocol, while making sure that older and newer
clients and servers interoperate with each other.  Since this is
a new protocol, we should start with the side-band support from
the beginning (see upload-pack and look for use_sideband).

Instead of sending the payload straight out, upload-archive side
would read from the underlying archiver, and send it with
one-byte prefix to say if it is a normal payload (band 1),
message to stderr used to show progress indicator and error
messages (band 2), or error exit situation (band 3).  The client
side here would receive the packetized data and do the reverse.

> +int parse_treeish_arg(const char **argv, struct tree **tree,
> +		      const unsigned char **commit_sha1,
> +		      time_t *archive_time, const char *prefix,
> +		      const char **reason)
> +{
>...
> +	if (prefix) {
> +		unsigned char tree_sha1[20];
> +		unsigned int mode;
> +		int err;
> +
> +		err = get_tree_entry((*tree)->object.sha1, prefix,
> +				     tree_sha1, &mode);
> +		if (err || !S_ISDIR(mode)) {
> +			*reason = "current working directory is untracked";
> +			goto out;
> +		}
> +		free(*tree);
> +		*tree = parse_tree_indirect(tree_sha1);
> +	}

I like the simplicity of just optionally sending one subtree (or
the whole thing), but I think this part would be made more
efficient if we go with "struct tree_desc" based interface.

Also I wonder how this interacts with the pathspec you take from
the command line.  Personally I think this single subtree
support is good enough and limiting with pathspec is not needed.

> +int parse_archive_args(int argc, const char **argv,
> +		       struct archiver_struct **ar,
> +		       const char **reason)
> +{
>...
> +		if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') {
> +			zlib_compression_level = arg[1] - '0';
> +			continue;
> +		}

Commented on this part already.

> +	if (list) {
> +		if (!remote) {
> +			int i;
> +
> +			for (i = 0; i < ARRAY_SIZE(archivers); i++)
> +				printf("%s\n", archivers[i].name);
> +			exit(0);
> +		}

You do not need a different "i" that shadows the outer one here.

> +	(*ar)->remote = remote;
> +	(*ar)->prefix = prefix ? : "";

Please be nicer to other people by staying away from GNU
extension "A ? : B", especially when A is so simple.

  reply	other threads:[~2006-09-05 19:23 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-05 12:16 [PATCH 1/2] Add git-archive Franck Bui-Huu
2006-09-05 19:23 ` Junio C Hamano [this message]
2006-09-06 13:46   ` Franck Bui-Huu
2006-09-06 20:14     ` Rene Scharfe
2006-09-06 20:29       ` Jakub Narebski
2006-09-08 20:21         ` Rene Scharfe
2006-09-06 21:42     ` Junio C Hamano
2006-09-07  6:32       ` Franck Bui-Huu
2006-09-07  7:19         ` Junio C Hamano
2006-09-07  7:53           ` Franck Bui-Huu
2006-09-07  8:16             ` Junio C Hamano
2006-09-07 13:08               ` Add git-archive [take #2] Franck Bui-Huu
2006-09-07 13:12                 ` [PATCH 1/4] Add git-archive Franck Bui-Huu
2006-09-08  2:35                   ` Junio C Hamano
2006-09-08  9:00                     ` Franck Bui-Huu
2006-09-08 20:21                       ` Rene Scharfe
2006-09-09 14:31                         ` Franck Bui-Huu
2006-09-09 15:02                           ` Rene Scharfe
2006-09-09 15:25                             ` Franck Bui-Huu
2006-09-07 13:12                 ` [PATCH 2/4] git-archive: wire up TAR format Franck Bui-Huu
2006-09-08 20:21                   ` Rene Scharfe
2006-09-08 21:42                     ` Junio C Hamano
2006-09-09  1:53                       ` Junio C Hamano
2006-09-09 15:02                         ` Rene Scharfe
2006-09-09 15:10                         ` Franck Bui-Huu
2006-09-09 19:42                           ` Junio C Hamano
2006-09-10 16:10                             ` [PATCH] Use xstrdup instead of strdup in builtin-{tar,zip}-tree.c Rene Scharfe
2006-09-09 14:38                     ` [PATCH 2/4] git-archive: wire up TAR format Franck Bui-Huu
2006-09-07 13:12                 ` [PATCH 3/4] git-archive: wire up ZIP format Franck Bui-Huu
2006-09-07 13:12                 ` [PATCH 4/4] Add git-upload-archive Franck Bui-Huu
2006-09-07 17:26                 ` Add git-archive [take #2] Franck Bui-Huu
2006-09-08  0:37                 ` Junio C Hamano
2006-09-08  8:18                   ` Franck Bui-Huu
2006-09-08  8:47                     ` Jakub Narebski
2006-09-08  8:58                     ` Junio C Hamano
2006-09-08  9:43                       ` Franck Bui-Huu
2006-09-08 21:42                         ` Junio C Hamano
2006-09-08 20:21                   ` Rene Scharfe
2006-09-08 21:42                     ` Junio C Hamano
2006-09-06 20:17 ` [PATCH 1/2] Add git-archive Rene Scharfe

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=7vfyf6ce29.fsf@assigned-by-dhcp.cox.net \
    --to=junkio@cox.net \
    --cc=git@vger.kernel.org \
    --cc=vagabon.xyz@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.
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).