git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Nick Townsend <nick.townsend@mac.com>
To: gitster@pobox.com, git@vger.kernel.org
Cc: Jens Lehmann <Jens.Lehmann@web.de>, Jeff King <peff@peff.net>
Subject: [PATCH] submodule recursion in git-archive
Date: Mon, 25 Nov 2013 16:04:14 -0800	[thread overview]
Message-ID: <2E636B58-47EB-4712-93CA-39E8D1BA3DB9@mac.com> (raw)

All,
My first git patch - so shout out if I’ve got the etiquette wrong! Or of course if I’ve missed something.
I googled around looking for solutions to my problem but just came up with a few shell-scripts
that didn’t quite get the functionality I needed.
The first patch fixes some typos that crept in to existing doc and declarations. It is required
for the second which actually implements the changes.

All comments gratefully received!

Regards
Nick Townsend

Subject: [PATCH 1/2] submodule: add_submodule_odb() usability

Although add_submodule_odb() is documented as being
externally usable, it is declared static and also
has incorrect documentation.

This commit fixes those and makes no changes to
existing code using them. All tests still pass.
---
 Documentation/technical/api-ref-iteration.txt | 4 ++--
 submodule.c                                   | 2 +-
 submodule.h                                   | 1 +
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/Documentation/technical/api-ref-iteration.txt b/Documentation/technical/api-ref-iteration.txt
index aa1c50f..cbee624 100644
--- a/Documentation/technical/api-ref-iteration.txt
+++ b/Documentation/technical/api-ref-iteration.txt
@@ -50,10 +50,10 @@ submodules object database. You can do this by a code-snippet like
 this:
 
 	const char *path = "path/to/submodule"
-	if (!add_submodule_odb(path))
+	if (add_submodule_odb(path))
 		die("Error submodule '%s' not populated.", path);
 
-`add_submodule_odb()` will return an non-zero value on success. If you
+`add_submodule_odb()` will return a zero value on success. If you
 do not do this you will get an error for each ref that it does not point
 to a valid object.
 
diff --git a/submodule.c b/submodule.c
index 1905d75..1ea46be 100644
--- a/submodule.c
+++ b/submodule.c
@@ -143,7 +143,7 @@ void stage_updated_gitmodules(void)
 		die(_("staging updated .gitmodules failed"));
 }
 
-static int add_submodule_odb(const char *path)
+int add_submodule_odb(const char *path)
 {
 	struct strbuf objects_directory = STRBUF_INIT;
 	struct alternate_object_database *alt_odb;
diff --git a/submodule.h b/submodule.h
index 7beec48..3e3cdca 100644
--- a/submodule.h
+++ b/submodule.h
@@ -41,5 +41,6 @@ int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_nam
 		struct string_list *needs_pushing);
 int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
 void connect_work_tree_and_git_dir(const char *work_tree, const char *git_dir);
+int add_submodule_odb(const char *path);
 
 #endif
-- 
1.8.3.4 (Apple Git-47)

Subject: [PATCH 2/2] archive: allow submodule recursion on git-archive

When using git-archive to produce a dump of a
repository, the existing code does not recurse
into a submodule when it encounters it in the tree
traversal. These changes add a command line flag
that permits this.

Note that the submodules must be updated in the
repository, otherwise this cannot take place.

The feature is disabled for remote repositories as
the git_work_tree fails. This is a possible future
enhancement.

Two additional fields are added to archiver_args:
  * recurse  - a boolean indicator
  * treepath - the path part of the tree-ish
               eg. the 'www' in HEAD:www

The latter is used within the archive writer to
determin the correct path for the submodule .git
file.

Signed-off-by: Nick Townsend <nick.townsend@mac.com>
---
 Documentation/git-archive.txt |  9 +++++++++
 archive.c                     | 38 ++++++++++++++++++++++++++++++++++++--
 archive.h                     |  2 ++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index b97aaab..b4df735 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git archive' [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
 	      [-o <file> | --output=<file>] [--worktree-attributes]
+	      [--recursive|--recurse-submodules]
 	      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
 	      [<path>...]
 
@@ -51,6 +52,14 @@ OPTIONS
 --prefix=<prefix>/::
 	Prepend <prefix>/ to each filename in the archive.
 
+--recursive::
+--recurse-submodules::
+	Archive entries in submodules. Errors occur if the submodules
+	have not been initialized and updated.
+	Run `git submodule update --init --recursive` immediately after
+	the clone is finished to avoid this.
+	This option is not available with remote repositories.
+
 -o <file>::
 --output=<file>::
 	Write the archive to <file> instead of stdout.
diff --git a/archive.c b/archive.c
index 346f3b2..f6313c9 100644
--- a/archive.c
+++ b/archive.c
@@ -5,6 +5,7 @@
 #include "archive.h"
 #include "parse-options.h"
 #include "unpack-trees.h"
+#include "submodule.h"
 
 static char const * const archive_usage[] = {
 	N_("git archive [options] <tree-ish> [<path>...]"),
@@ -131,13 +132,32 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
 		args->convert = ATTR_TRUE(check[1].value);
 	}
 
+	if (S_ISGITLINK(mode) && args->recurse) {
+		const char *work_tree = get_git_work_tree();
+		if (!work_tree) {
+			  die("Can't go recursive when no work dir");
+		}
+		static struct strbuf dotgit = STRBUF_INIT;
+		strbuf_reset(&dotgit);
+		strbuf_grow(&dotgit, PATH_MAX);
+		strbuf_addstr(&dotgit, work_tree);
+		strbuf_addch(&dotgit, '/');
+		if (args->treepath) {
+			  strbuf_addstr(&dotgit, args->treepath);
+			  strbuf_addch(&dotgit, '/');
+		}
+		strbuf_add(&dotgit, path_without_prefix,strlen(path_without_prefix)-1);
+		if (add_submodule_odb(dotgit.buf))
+			  die("Can't add submodule: %s", dotgit.buf);
+		strbuf_release(&dotgit);
+	}
 	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 		if (args->verbose)
 			fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
 		err = write_entry(args, sha1, path.buf, path.len, mode);
 		if (err)
 			return err;
-		return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
+		return (S_ISGITLINK(mode) && !args->recurse) ? 0: READ_TREE_RECURSIVE;
 	}
 
 	if (args->verbose)
@@ -256,10 +276,16 @@ static void parse_treeish_arg(const char **argv,
 	const struct commit *commit;
 	unsigned char sha1[20];
 
+	const char *colon = strchr(name, ':');
+
+	/* Store the path on the ref for later (required for --recursive) */
+	char *treepath = NULL;
+	if (colon) {
+		treepath = strdup(colon+1);
+	}
 	/* Remotes are only allowed to fetch actual refs */
 	if (remote) {
 		char *ref = NULL;
-		const char *colon = strchr(name, ':');
 		int refnamelen = colon ? colon - name : strlen(name);
 
 		if (!dwim_ref(name, refnamelen, sha1, &ref))
@@ -296,9 +322,11 @@ static void parse_treeish_arg(const char **argv,
 		tree = parse_tree_indirect(tree_sha1);
 	}
 	ar_args->tree = tree;
+	ar_args->treepath = treepath;
 	ar_args->commit_sha1 = commit_sha1;
 	ar_args->commit = commit;
 	ar_args->time = archive_time;
+
 }
 
 #define OPT__COMPR(s, v, h, p) \
@@ -318,6 +346,7 @@ static int parse_archive_args(int argc, const char **argv,
 	const char *exec = NULL;
 	const char *output = NULL;
 	int compression_level = -1;
+	int recurse = 0;
 	int verbose = 0;
 	int i;
 	int list = 0;
@@ -331,6 +360,8 @@ static int parse_archive_args(int argc, const char **argv,
 			N_("write the archive to this file")),
 		OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
 			N_("read .gitattributes in working directory")),
+		OPT_BOOL(0, "recursive", &recurse, N_("include submodules in archive")),
+		OPT_BOOL(0, "recurse-submodules", &recurse, N_("include submodules in archive")),
 		OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
 		OPT__COMPR('0', &compression_level, N_("store only"), 0),
 		OPT__COMPR('1', &compression_level, N_("compress faster"), 1),
@@ -355,6 +386,8 @@ static int parse_archive_args(int argc, const char **argv,
 
 	argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
 
+	if (is_remote && recurse)
+		die("Cannot include submodules with option --remote");
 	if (remote)
 		die("Unexpected option --remote");
 	if (exec)
@@ -393,6 +426,7 @@ static int parse_archive_args(int argc, const char **argv,
 					format, compression_level);
 		}
 	}
+	args->recurse = recurse;
 	args->verbose = verbose;
 	args->base = base;
 	args->baselen = strlen(base);
diff --git a/archive.h b/archive.h
index 4a791e1..577238d 100644
--- a/archive.h
+++ b/archive.h
@@ -7,10 +7,12 @@ struct archiver_args {
 	const char *base;
 	size_t baselen;
 	struct tree *tree;
+	const char *treepath;
 	const unsigned char *commit_sha1;
 	const struct commit *commit;
 	time_t time;
 	struct pathspec pathspec;
+	unsigned int recurse : 1;
 	unsigned int verbose : 1;
 	unsigned int worktree_attributes : 1;
 	unsigned int convert : 1;
-- 
1.8.3.4 (Apple Git-47)

             reply	other threads:[~2013-11-26  1:04 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-26  0:04 Nick Townsend [this message]
2013-11-26 15:17 ` [PATCH] submodule recursion in git-archive René Scharfe
2013-11-26 18:57   ` Jens Lehmann
2013-11-26 22:18   ` Junio C Hamano
2013-11-27  0:28     ` René Scharfe
2013-11-27  3:28       ` Nick Townsend
2013-11-27 19:05       ` Junio C Hamano
2013-11-27  3:55     ` Nick Townsend
2013-11-27 19:43       ` Junio C Hamano
2013-11-29 22:38         ` Heiko Voigt
     [not found]           ` <3C71BC83-4DD0-43F8-9E36-88594CA63FC5@mac.com>
2013-12-03  0:05             ` Nick Townsend
2013-12-03 18:33             ` Heiko Voigt
2013-12-09 20:55               ` [RFC/WIP PATCH] implement reading of submodule .gitmodules configuration into cache Heiko Voigt
2013-12-09 23:37                 ` Junio C Hamano
2013-12-12 13:03                   ` Heiko Voigt
2013-12-03  0:00         ` [PATCH] submodule recursion in git-archive Nick Townsend
2013-12-03  0:03           ` Fwd: " Nick Townsend
2013-11-26 22:38   ` Heiko Voigt
2013-11-27  3:33     ` Nick Townsend
     [not found] <0MWW00M0GODZPV00@nk11p03mm-asmtp002.mac.com>
2013-11-27  5:03 ` Nick Townsend

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2E636B58-47EB-4712-93CA-39E8D1BA3DB9@mac.com \
    --to=nick.townsend@mac.com \
    --cc=Jens.Lehmann@web.de \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).