From: "René Scharfe" <rene.scharfe@lsrfire.ath.cx>
To: Junio C Hamano <junkio@cox.net>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: [PATCH] git-archive: recursive prefix directory creation
Date: Sat, 19 May 2007 13:37:13 +0200 [thread overview]
Message-ID: <464EE169.30306@lsrfire.ath.cx> (raw)
Currently git-archive only adds a single directory entry for prefixes,
e.g. for --prefix=a/b/c/ only the directory a/b/c/ would be added to
the archive, not a/ nor a/b/. While tar and unzip don't seem to have
a problem handling these missing entries, their omission was not
intended.
This patch replaces the prefix path creation code in git-archive with
calls to a new path walker similar to read_tree_recursive, named
descend_leading_dirs. It calls a read_tree_fn_t function for each
leading directory while descending deeper into the path (e.g. first
a/, then a/b/ etc.).
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
archive-tar.c | 11 ++---------
archive-zip.c | 11 ++---------
tree.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
tree.h | 5 +++++
4 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/archive-tar.c b/archive-tar.c
index 33e7657..7ea396d 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -308,15 +308,8 @@ int write_tar_archive(struct archiver_args *args)
if (args->commit_sha1)
write_global_extended_header(args->commit_sha1);
- if (args->base && plen > 0 && args->base[plen - 1] == '/') {
- char *base = xstrdup(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);
- }
+ descend_leading_dirs(args->tree->object.sha1, args->base, plen,
+ 040777, 0, write_tar_entry);
read_tree_recursive(args->tree, args->base, plen, 0,
args->pathspec, write_tar_entry);
write_trailer();
diff --git a/archive-zip.c b/archive-zip.c
index 3cbf6bb..2fc22ff 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -317,15 +317,8 @@ int write_zip_archive(struct archiver_args *args)
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
verbose = args->verbose;
- if (args->base && plen > 0 && args->base[plen - 1] == '/') {
- char *base = xstrdup(args->base);
- int baselen = strlen(base);
-
- while (baselen > 0 && base[baselen - 1] == '/')
- base[--baselen] = '\0';
- write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
- free(base);
- }
+ descend_leading_dirs(args->tree->object.sha1, args->base, plen,
+ 040777, 0, write_zip_entry);
read_tree_recursive(args->tree, args->base, plen, 0,
args->pathspec, write_zip_entry);
write_zip_trailer(args->commit_sha1);
diff --git a/tree.c b/tree.c
index e4a39aa..5cd1f90 100644
--- a/tree.c
+++ b/tree.c
@@ -231,3 +231,48 @@ struct tree *parse_tree_indirect(const unsigned char *sha1)
parse_object(obj->sha1);
} while (1);
}
+
+int descend_leading_dirs(const unsigned char *sha1,
+ const char *path, size_t pathlen,
+ unsigned int mode, int stage, read_tree_fn_t fn)
+{
+ int err;
+ size_t baselen;
+
+ if (!path)
+ return 0;
+
+ /* Discard file name part. */
+ while (pathlen > 0 && path[pathlen - 1] != '/')
+ pathlen--;
+ while (pathlen > 0 && path[pathlen - 1] == '/')
+ pathlen--;
+ if (pathlen == 0)
+ return 0;
+
+ /* Now separate base and current directory name. */
+ baselen = pathlen;
+ while (baselen > 0 && path[baselen - 1] != '/')
+ baselen--;
+
+ err = descend_leading_dirs(null_sha1, path, baselen, mode, stage, fn);
+
+ if (!err) {
+ /* We need a NUL-terminated version of the directory name. */
+ char *dirname = xstrndup(path + baselen, pathlen - baselen);
+ switch (fn(sha1, path, baselen, dirname, mode, stage)) {
+ case 0:
+ err = 1;
+ break;
+ case READ_TREE_RECURSIVE:
+ err = 0;
+ break;
+ default:
+ err = -1;
+ break;
+ }
+ free(dirname);
+ }
+
+ return err;
+}
diff --git a/tree.h b/tree.h
index dd25c53..6b0f5d9 100644
--- a/tree.h
+++ b/tree.h
@@ -30,4 +30,9 @@ extern int read_tree_recursive(struct tree *tree,
extern int read_tree(struct tree *tree, int stage, const char **paths);
+extern int descend_leading_dirs(const unsigned char *sha1,
+ const char *path, size_t pathlen,
+ unsigned int mode, int stage,
+ read_tree_fn_t fn);
+
#endif /* TREE_H */
next reply other threads:[~2007-05-19 11:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-19 11:37 René Scharfe [this message]
2007-05-19 18:17 ` [PATCH] git-archive: recursive prefix directory creation Junio C Hamano
2007-05-19 19:56 ` René Scharfe
2007-05-19 20:22 ` Junio C Hamano
2007-05-20 10:51 ` René 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=464EE169.30306@lsrfire.ath.cx \
--to=rene.scharfe@lsrfire.ath.cx \
--cc=git@vger.kernel.org \
--cc=junkio@cox.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.