[PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

Subsystems: the rest

DORMANTno replies

5 messages, 4 authors, 2016-06-15 · open the first message on its own page

[PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

From: Matthias Lederhofer <hidden>
Date: 2016-06-15 22:43:19

Now you can do the following to create a repository which
has a separate working tree:

    /tmp/foo$ export GIT_DIR=/tmp/bar
    /tmp/foo$ git --work-tree . init
    Initialized empty Git repository in /tmp/bar/
    /tmp/foo$ git config core.worktree
    /tmp/foo

Signed-off-by: Matthias Lederhofer <redacted>
---
Without this I found it quite complicated to create a non bare
repository which is not in a .git directory.

Some stuff I was wondering about while writing this patch:

 * Should we have a function similar to err(3) which prints
   ": " and strerror(errno) after the supplied error message?
   This function could be used instead of die whenever errno contains
   some meaningful value.

 * Should git init create the whole path to the repository and not
   only the last component?  I.e. git --git-dir /tmp/a init suceeds
   but git --git-dir /tmp/a/b/c init fails (unless /tmp/a/b exists).

 * Should git init create the working tree if it does not exist?

 * Is this something which should have a test?  git init doesn't seem
   to have any tests yet beside basic tests if the created repository
   looks ok.
---
 builtin-init-db.c |   40 +++++++++++++++++++++++++++++++++++++---
 1 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/builtin-init-db.c b/builtin-init-db.c
index 976f47b..ff5c13b 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -174,7 +174,36 @@ static void copy_templates(const char *git_dir, int len, const char *template_di
 	closedir(dir);
 }
 
-static int create_default_files(const char *git_dir, const char *template_path)
+/*
+ * Get the full path to the working tree specified in $GIT_WORK_TREE
+ * or NULL if no working tree is specified.
+ */
+static const char *get_work_tree(void)
+{
+	const char *git_work_tree;
+	char cwd[PATH_MAX];
+	static char worktree[PATH_MAX];
+
+	git_work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT);
+	if (!git_work_tree)
+		return NULL;
+	if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+		die("Unable to read current working directory");
+	if (chdir(git_work_tree))
+		die("Cannot change directory to specified working tree '%s'",
+			git_work_tree);
+	if (git_work_tree[0] != '/') {
+		if (!getcwd(worktree, sizeof(worktree)) || worktree[0] != '/')
+			die("Unable to read current working directory");
+		git_work_tree = worktree;
+	}
+	if (chdir(cwd))
+		die("Cannot come back to cwd");
+	return git_work_tree;
+}
+
+static int create_default_files(const char *git_dir, const char *git_work_tree,
+	const char *template_path)
 {
 	unsigned len = strlen(git_dir);
 	static char path[PATH_MAX];
@@ -253,7 +282,7 @@ static int create_default_files(const char *git_dir, const char *template_path)
 	}
 	git_config_set("core.filemode", filemode ? "true" : "false");
 
-	if (is_bare_repository()) {
+	if (is_bare_repository() && !git_work_tree) {
 		git_config_set("core.bare", "true");
 	}
 	else {
@@ -261,6 +290,8 @@ static int create_default_files(const char *git_dir, const char *template_path)
 		/* allow template config file to override the default */
 		if (log_all_ref_updates == -1)
 		    git_config_set("core.logallrefupdates", "true");
+		if (git_work_tree)
+			git_config_set("core.worktree", git_work_tree);
 	}
 	return reinit;
 }
@@ -277,6 +308,7 @@ static const char init_db_usage[] =
 int cmd_init_db(int argc, const char **argv, const char *prefix)
 {
 	const char *git_dir;
+	const char *git_work_tree;
 	const char *sha1_dir;
 	const char *template_dir = NULL;
 	char *path;
@@ -294,6 +326,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			usage(init_db_usage);
 	}
 
+	git_work_tree = get_work_tree();
+
 	/*
 	 * Set up the default .git directory contents
 	 */
@@ -309,7 +343,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	 */
 	check_repository_format();
 
-	reinit = create_default_files(git_dir, template_dir);
+	reinit = create_default_files(git_dir, git_work_tree, template_dir);
 
 	/*
 	 * And set up the object store.
-- 
1.5.2.2.646.g71e55-dirty

Re: [PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

From: Matthias Lederhofer <hidden>
Date: 2016-06-15 22:43:19

+	if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+		die("Unable to read current working directory");
Dscho just pointed out that this causes problems on windows.  The same
is also in setup_git_directory_gently and was there before I touched
it, introduced by Linus in d288a700.  What was the original reason to
do this?  Are there implementations of getcwd which return a relative
path?

Additionally there are other places which need to check if some user
supplied path is absolute.  Should we have a macro/function for that
which depends on the os and checks for path[0] = '/' on unix and
perhaps path[1] = ':' on windows?

Re: [PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

From: Johannes Sixt <hidden>
Date: 2016-06-15 22:43:19

Matthias Lederhofer wrote:
quoted
+     if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+             die("Unable to read current working directory");
Dscho just pointed out that this causes problems on windows.  The same
is also in setup_git_directory_gently and was there before I touched
it, introduced by Linus in d288a700.  What was the original reason to
do this?  Are there implementations of getcwd which return a relative
path?

Additionally there are other places which need to check if some user
supplied path is absolute.  Should we have a macro/function for that
which depends on the os and checks for path[0] = '/' on unix and
perhaps path[1] = ':' on windows?
I've modified some places (that check for an absolute path) in the MinGW
port to read (path[0] == '/' || path[1] == ':'). I don't think that it's
necessary that you cater for this case in your code - I'll take care of
it in the MinGW port. Of course, a hint that there is another place to
watch out for, or even better a test case in t/, is most appreciated.

I still hope to find some time to rework the MinGW port. Then such
details will be hidden behind a is_path_absolute() function. Or maybe
getcwd_or_die() ;)

-- Hannes

Re: [PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:43:19

Hi,

On Wed, 4 Jul 2007, Johannes Sixt wrote:
Matthias Lederhofer wrote:
quoted
quoted
+     if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+             die("Unable to read current working directory");
Dscho just pointed out that this causes problems on windows.  The same
is also in setup_git_directory_gently and was there before I touched
it, introduced by Linus in d288a700.  What was the original reason to
do this?  Are there implementations of getcwd which return a relative
path?

Additionally there are other places which need to check if some user
supplied path is absolute.  Should we have a macro/function for that
which depends on the os and checks for path[0] = '/' on unix and
perhaps path[1] = ':' on windows?
I've modified some places (that check for an absolute path) in the MinGW
port to read (path[0] == '/' || path[1] == ':'). I don't think that it's
necessary that you cater for this case in your code - I'll take care of
it in the MinGW port. Of course, a hint that there is another place to
watch out for, or even better a test case in t/, is most appreciated.

I still hope to find some time to rework the MinGW port. Then such
details will be hidden behind a is_path_absolute() function. Or maybe
getcwd_or_die() ;)
Yes, but why not start early? is_path_absolute() makes perfect sense.

However, I was asking (out of lack of knowledge): is there any way 
getcwd() does not return an absolute path?

Ciao,
Dscho

Re: [PATCH] git-init: set core.worktree if GIT_WORK_TREE is specified

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:43:19


On Wed, 4 Jul 2007, Matthias Lederhofer wrote:
quoted
+	if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+		die("Unable to read current working directory");
Dscho just pointed out that this causes problems on windows.  The same
is also in setup_git_directory_gently and was there before I touched
it, introduced by Linus in d288a700.  What was the original reason to
do this?  Are there implementations of getcwd which return a relative
path?
Just remove the check for cwd[0] being '/'.

It's just me being too kernel-oriented - inside the kernel, a d_path() 
return value pathname can be either a real path, or something like 
"pipe:[8003]", and the difference is the '/' at the beginning.

In user space, and for getcwd(), the check doesn't make sense. So please 
just remove it, and sorry for my idiotic "I've worked with the kernel for 
too damn long" programming mistakes.

		Linus
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help