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 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).