From: Rene Scharfe <rene.scharfe@xxxxxxxxxxxxxx> Signed-off-by: Rene Scharfe <rene.scharfe@xxxxxxxxxxxxxx> Signed-off-by: Franck Bui-Huu <vagabon.xyz@xxxxxxxxx> --- archive.h | 4 +++ builtin-archive.c | 4 ++- builtin-tar-tree.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletions(-) diff --git a/archive.h b/archive.h index f33398e..3690c53 100644 --- a/archive.h +++ b/archive.h @@ -37,5 +37,9 @@ extern void parse_treeish_arg(const char extern void parse_pathspec_arg(const char **pathspec, struct archiver_args *args); +/* + * + */ +extern int write_tar_archive(struct archiver_args *); #endif /* ARCHIVE_H */ diff --git a/builtin-archive.c b/builtin-archive.c index 6064358..214ec5d 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -15,7 +15,9 @@ static const char archive_usage[] = \ "git-archive --format=<fmt> [--prefix=<prefix>/] [<extra>] <tree-ish> [path...]"; -struct archiver archivers[] = { }; +struct archiver archivers[] = { + { .name = "tar", .write_archive = write_tar_archive }, +}; static int run_remote_archiver(struct archiver *ar, int argc, diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 61a4135..1134730 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -9,6 +9,7 @@ #include "strbuf.h" #include "tar.h" #include "builtin.h" #include "pkt-line.h" +#include "archive.h" #define RECORDSIZE (512) #define BLOCKSIZE (RECORDSIZE * 20) @@ -338,6 +339,72 @@ static int generate_tar(int argc, const return 0; } +static int write_tar_entry(const unsigned char *sha1, + const char *base, int baselen, + const char *filename, unsigned mode, int stage) +{ + static struct strbuf path; + int filenamelen = strlen(filename); + void *buffer; + char type[20]; + unsigned long size; + + if (!path.alloc) { + path.buf = xmalloc(PATH_MAX); + path.alloc = PATH_MAX; + path.len = path.eof = 0; + } + if (path.alloc < baselen + filenamelen) { + free(path.buf); + path.buf = xmalloc(baselen + filenamelen); + path.alloc = baselen + filenamelen; + } + memcpy(path.buf, base, baselen); + memcpy(path.buf + baselen, filename, filenamelen); + path.len = baselen + filenamelen; + if (S_ISDIR(mode)) { + strbuf_append_string(&path, "/"); + buffer = NULL; + size = 0; + } else { + buffer = read_sha1_file(sha1, type, &size); + if (!buffer) + die("cannot read %s", sha1_to_hex(sha1)); + } + + write_entry(sha1, &path, mode, buffer, size); + free(buffer); + + return READ_TREE_RECURSIVE; +} + +int write_tar_archive(struct archiver_args *args) +{ + int plen = strlen(args->base); + + git_config(git_tar_config); + + archive_time = args->time; + + if (args->commit_sha1) + write_global_extended_header(args->commit_sha1); + + if (args->base && plen > 0 && args->base[plen - 1] == '/') { + char *base = strdup(args->base); + int baselen = strlen(base); + + while (baselen > 0 && base[baselen - 1] == '/') + base[--baselen] = '\0'; + write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0); + free(base); + } + read_tree_recursive(args->tree, args->base, plen, 0, + args->pathspec, write_tar_entry); + write_trailer(); + + return 0; +} + static const char *exec = "git-upload-tar"; static int remote_tar(int argc, const char **argv) -- 1.4.2 - 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