Hi, 2006/9/2, Rene Scharfe <rene.scharfe@xxxxxxxxxxxxxx>:
git-archive-tree is a command to make tar and ZIP archives of a git tree. It helps prevent a proliferation of git-{format}-tree commands. This is useful e.g. for remote archive fetching because we only need to write a single upload and a single download program that simply pass on the format option to git-archive-tree.
OK, Rene you beat me. I started to cook up something this morning but had no time to go further. I sent a starting implementation just because it seems complementary to the one you sent a couple hours ago: it supports '--remote' option. But it does _not_ have path spec support you introduced. I think it's cool feature but I would have to dig into git's internal to implement it, which would have taken me a while.
From now, do you think we should import my work into your version or
'vice verca' ? -- >8 -- Subject: [PATCH] Add git-archive (other implementation) Signed-off-by: Franck Bui-Huu <vagabon.xyz@xxxxxxxxx> --- .gitignore | 1 Makefile | 1 builtin-archive.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++ builtin.h | 1 generate-cmdlist.sh | 1 git.c | 1 6 files changed, 176 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 78cb671..a3e7ca1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ git-apply git-applymbox git-applypatch git-archimport +git-archive git-bisect git-branch git-cat-file diff --git a/Makefile b/Makefile index 164dbcf..8d963e0 100644 --- a/Makefile +++ b/Makefile @@ -266,6 +266,7 @@ LIB_OBJS = \ BUILTIN_OBJS = \ builtin-add.o \ builtin-apply.o \ + builtin-archive.o \ builtin-cat-file.o \ builtin-checkout-index.o \ builtin-check-ref-format.o \ diff --git a/builtin-archive.c b/builtin-archive.c new file mode 100644 index 0000000..47898ee --- /dev/null +++ b/builtin-archive.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2006 Franck Bui-Huu + */ +#include "cache.h" +#include "builtin.h" +#include "exec_cmd.h" +#include "pkt-line.h" + +#define MAX_ARGS 32 + +static const char *extra_argv[MAX_ARGS]; +static int extra_argc = 1; +static const char *base; +static const char *remote; + +static const char archive_usage[] = \ +"git-archive -f <format> [extra] [--remote=<repo>] [--prefix=<base>] <tree-ish>"; + +/* archiver's options */ +#define NEED_BASE (1<<0) + +struct archiver_info { + const char *name; + int (*fn)(int argc, const char **argv, const char *prefix); + int options; +}; + +static struct archiver_info archivers[] = { + { "tar", cmd_tar_tree, NEED_BASE }, + { "zip", cmd_zip_tree, NEED_BASE }, +}; + +static int run_remote_archiver(struct archiver_info *ar, char *url) +{ + int fd[2], len, rv; + char buf[1024]; + pid_t pid; + + /* + * For now, remote operations does not support extra options + */ + if (extra_argc > 2) + die("Remote operation does not support extra options yet."); + + sprintf(buf, "git-upload-%s", ar->name); + pid = git_connect(fd, url, buf); + if (pid < 0) + return pid; + + packet_write(fd[1], "want %s\n", extra_argv[1]); + if (base) + packet_write(fd[1], "base %s\n", base); + packet_flush(fd[1]); + + len = packet_read_line(fd[0], buf, sizeof(buf)); + if (!len) + die("git-archive: expected ACK/NAK, got EOF"); + if (buf[len-1] == '\n') + buf[--len] = 0; + if (strcmp(buf, "ACK")) { + if (len > 5 && !strncmp(buf, "NACK ", 5)) + die("git-archive: NACK %s", buf + 5); + die("git-archive: protocol error"); + } + if (packet_read_line(fd[0], buf, sizeof(buf))) + die("git-archive: expected a flush"); + + /* Now, start reading from fd[0] and spit it out to stdout */ + rv = copy_fd(fd[0], 1); + close(fd[0]); + + return !!(rv | finish_connect(pid)); +} + +void insert_extra_option(const char *option, int idx) +{ + const char **argv = extra_argv; /* some shortcuts... */ + int argc = extra_argc; + + if (argc > MAX_ARGS - 2) + die("Too many args"); + if (idx > MAX_ARGS - 1) + die("idx overflow extra_argv buffer !"); + + /* insert at last position ? */ + if (idx < 0) { + argv[argc++] = option; + argv[argc] = NULL; + } else { + argv += idx; + memmove(argv + 1, argv, argc * sizeof(*argv)); + *argv = option; + } + extra_argc++; +} + +int run_archiver(const char *format) +{ + struct archiver_info *ar; + char buf[32]; + int i; + + for (i = 0; i < ARRAY_SIZE(archivers); i++) { + ar = &archivers[i]; + if (strcmp(format, ar->name)) + continue; + goto found; + } + return error("Unknown archive format '%s'\n", format); +found: + if (remote) { + char *url = strdup(remote+9); /* --remote=<repo> */ + return run_remote_archiver(ar, url); + } + if (base) { + i = 1; + if (ar->options & NEED_BASE) { + base += 9; /* --prefix=<base> */ + i = -1; + } + insert_extra_option(base, i); + } + sprintf(buf, "%s-tree", ar->name); + extra_argv[0] = buf; + + return ar->fn(extra_argc, extra_argv, setup_git_directory()); +} + +static int show_list_formats(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(archivers); i++) { + printf("%s\n", archivers[i].name); + } + return 0; +} + +int cmd_archive(int argc, const char **argv, const char *prefix) +{ + static const char *format; + int i; + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + + if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) { + return show_list_formats(); + } + if (!strncmp(arg, "--format=", 9)) { + format = arg+9; + continue; + } + if (!strncmp(arg, "--prefix=", 9)) { + base = arg; + continue; + } + if (!strncmp(arg, "--remote=", 9)) { + remote = arg; + continue; + } + if (extra_argc > MAX_ARGS - 2) + die("Too many options"); + extra_argv[extra_argc++] = arg; + } + + if (!format) + die("You must specify an archive format"); + + return run_archiver(format); +} diff --git a/builtin.h b/builtin.h index 25431d7..50852cd 100644 --- a/builtin.h +++ b/builtin.h @@ -15,6 +15,7 @@ extern int write_tree(unsigned char *sha extern int cmd_add(int argc, const char **argv, const char *prefix); extern int cmd_apply(int argc, const char **argv, const char *prefix); +extern int cmd_archive(int argc, const char **argv, const char *prefix); extern int cmd_cat_file(int argc, const char **argv, const char *prefix); extern int cmd_checkout_index(int argc, const char **argv, const char *prefix); extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix); diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh index ec1eda2..5450918 100755 --- a/generate-cmdlist.sh +++ b/generate-cmdlist.sh @@ -12,6 +12,7 @@ struct cmdname_help common_cmds[] = {" sort <<\EOF | add apply +archive bisect branch checkout diff --git a/git.c b/git.c index 403fb3a..ddb1620 100644 --- a/git.c +++ b/git.c @@ -218,6 +218,7 @@ static void handle_internal_command(int } commands[] = { { "add", cmd_add, RUN_SETUP }, { "apply", cmd_apply }, + { "archive", cmd_archive }, { "cat-file", cmd_cat_file, RUN_SETUP }, { "checkout-index", cmd_checkout_index, RUN_SETUP }, { "check-ref-format", cmd_check_ref_format }, -- 1.4.2.g8ed9-dirty -- VGER BF report: U 0.5 - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html