git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH] archive: fix setup to work in bare repositories

From
Deskin Miller <deskinm@umich.edu>
Date
Oct 22, 2008, 20:37 UTC
Message-ID
<20081022203722.GD2015@riemann.deskinm.fdns.net>
In-Reply-To
<gdnsca$92r$2@ger.gmane.org>

cmd_archive was calling git_config -> setup_git_env prior to write_archive calling setup_git_directory. In a bare repository, the former will set git_dir to be '.git' since the latter has not determined that it's operating in a bare repository yet.

Things are complicated, however, by the fact that git archive --list should work from anywhere, not just in git repositories, so that argument needs to be checked for before setup_git_directory is called. --- On Wed, Oct 22, 2008 at 06:45:30PM +0000, kenneth johansson wrote:

Show 31 quoted lines
> On Wed, 22 Oct 2008 09:08:29 -0400, Deskin Miller wrote:
> 
> > On Wed, Oct 22, 2008 at 08:42:01AM +0000, kenneth johansson wrote:
> >> I was going to make a tar of the latest stable linux kernel. Done it
> >> before but now I got a strange problem.
> >> 
> >> >git archive --format=tar v2.6.27.2
> >> fatal: Not a valid object name
> > 
> > I had the same thing happen to me, while trying to make an archive of
> > Git. Were you perchance working in a bare repository, as I was?  I spent
> > some time looking at it and I think git archive sets up the environment
> > in the wrong order, though of course I never finished a patch so I'm
> > going from memory:
> 
> Yes it was a bare repository.
> 
> > 
> > After looking at the code again, I think the issue is that git_config is
> > called in builtin-archive.c:cmd_archive before setup_git_directory is
> > called in archive.c:write_archive.  The former ends up setting GIT_DIR
> > to be '.git' even if you're in a bare repository.  My coding skills
> > weren't up to fixing it easily; moving setup_git_directory before
> > git_config in builtin-archive caused last test of t5000 to fail:
> > GIT_DIR=some/nonexistent/path git archive --list should still display
> > the archive formats.
> 
> if I do
> GIT_DIR=. git  archive --format=tar v2.6.27.2
> 
> it does work so it looks like you are on the right track.

Looks like this works, but I think it's really ugly; let me know if you have any suggestions for improvement.

 archive.c           |   13 +++++++++++++
 archive.h           |    1 +
 builtin-archive.c   |    4 +++-
 t/t5000-tar-tree.sh |    9 +++++++++
 4 files changed, 26 insertions(+), 1 deletions(-)
diff --git a/archive.c b/archive.c
index e2280df..d8e4373 100644
--- a/archive.c
+++ b/archive.c
@@ -325,6 +325,19 @@ static int parse_archive_args(int argc, const char **argv,
 	return argc;
 }
 
+int archive_parse_options_early(int argc, const char **argv)
+{
+	int i;
+	for (i = 1; i < argc; ++i) {
+		if (!strcmp(argv[i], "--list")) {
+			for (i = 0; i < ARRAY_SIZE(archivers); i++)
+				printf("%s\n", archivers[i].name);
+			exit(0);
+		}
+	}
+	return 0;
+}
+
 int write_archive(int argc, const char **argv, const char *prefix,
 		int setup_prefix)
 {
diff --git a/archive.h b/archive.h
index 0b15b35..ff5b6cf 100644
--- a/archive.h
+++ b/archive.h
@@ -24,6 +24,7 @@ extern int write_tar_archive(struct archiver_args *);
 extern int write_zip_archive(struct archiver_args *);
 
 extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
+extern int archive_parse_options_early(int argc, const char **argv);
 extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);
 
 #endif	/* ARCHIVE_H */
diff --git a/builtin-archive.c b/builtin-archive.c
index 432ce2a..e518113 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -111,6 +111,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 {
 	const char *remote = NULL;
 
+	archive_parse_options_early(argc, argv);
+	prefix = setup_git_directory();
 	git_config(git_default_config, NULL);
 
 	remote = extract_remote_arg(&argc, argv);
@@ -119,5 +121,5 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 
 	setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
-	return write_archive(argc, argv, prefix, 1);
+	return write_archive(argc, argv, prefix, 0);
 }
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index e395ff4..53fe25c 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -192,4 +192,13 @@ test_expect_success \
     'git archive --list outside of a git repo' \
     'GIT_DIR=some/non-existing/directory git archive --list'
 
+test_expect_success \
+    'git archive inside bare repository' \
+    'git clone --bare "$(pwd)"/.git trash-bare &&
+    cd trash-bare &&
+    git archive --format=tar HEAD >/dev/null &&
+    cd .. &&
+    rm -rf trash-bare
+    '
+
 test_done
-- 
1.6.0.2.554.g3041b
Previous: kenneth johanssonNext: Jeff King
Message 4 of 14 in “git archive”
  1. kenneth johanssonOct 22, 2008
  2. Deskin MillerOct 22, 2008
  3. kenneth johanssonOct 22, 2008
  4. archive: fix setup to work in bare repositoriesDeskin Miller, Oct 22, 2008
  5. Jeff KingOct 22, 2008
  6. Charles BaileyOct 22, 2008
  7. Fixed git archive for bare reposCharles Bailey, Oct 22, 2008
  8. Deskin MillerOct 23, 2008
  9. René ScharfeOct 24, 2008
  10. Fixed git archive for bare reposDeskin Miller, Oct 25, 2008
  11. Junio C HamanoOct 25, 2008
  12. Nguyen Thai Ngoc DuyOct 23, 2008
  13. Deskin MillerOct 23, 2008
  14. Nguyen Thai Ngoc DuyOct 24, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.