Git development
 help / color / mirror / Atom feed
* [PATCH 7/9] init: use get_git_work_tree() instead of rolling our own
From: Johannes Schindelin @ 2007-07-29 23:25 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin-init-db.c |   48 +++++++++++-------------------------------------
 1 files changed, 11 insertions(+), 37 deletions(-)

diff --git a/builtin-init-db.c b/builtin-init-db.c
index 66ddaeb..0d9b1e0 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -174,36 +174,7 @@ static void copy_templates(const char *git_dir, int len, const char *template_di
 	closedir(dir);
 }
 
-/*
- * 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)))
-		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)))
-			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)
+static int create_default_files(const char *git_dir, const char *template_path)
 {
 	unsigned len = strlen(git_dir);
 	static char path[PATH_MAX];
@@ -282,16 +253,16 @@ static int create_default_files(const char *git_dir, const char *git_work_tree,
 	}
 	git_config_set("core.filemode", filemode ? "true" : "false");
 
-	if (is_bare_repository() && !git_work_tree) {
+	if (is_bare_repository())
 		git_config_set("core.bare", "true");
-	}
 	else {
+		const char *work_tree = get_git_work_tree();
 		git_config_set("core.bare", "false");
 		/* 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);
+		if (work_tree != git_work_tree_cfg)
+			git_config_set("core.worktree", work_tree);
 	}
 	return reinit;
 }
@@ -308,7 +279,6 @@ 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;
@@ -329,7 +299,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			usage(init_db_usage);
 	}
 
-	git_work_tree = get_work_tree();
+	git_work_tree_cfg = xcalloc(PATH_MAX, 1);
+	if (!getcwd(git_work_tree_cfg, PATH_MAX))
+		die ("Cannot access current working directory.");
+	if (access(get_git_work_tree(), X_OK))
+		die ("Cannot access work tree '%s'", get_git_work_tree());
 
 	/*
 	 * Set up the default .git directory contents
@@ -346,7 +320,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	 */
 	check_repository_format();
 
-	reinit = create_default_files(git_dir, git_work_tree, template_dir);
+	reinit = create_default_files(git_dir, template_dir);
 
 	/*
 	 * And set up the object store.
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 6/9] work-trees are allowed inside a git-dir
From: Johannes Schindelin @ 2007-07-29 23:25 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


It is allowed to call

	$ git --git-dir=../ --work-tree=. bla

when you really want to.  In this case, you are both in the git directory
and in the working tree.

The earlier handling of this situation was seriously bogus.  For regular
working tree operations, it checked if inside git dir.  That makes no
sense, of course, since the check should be for a work tree, and nothing
else.

Fix that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin-ls-files.c |    8 +++++---
 git-sh-setup.sh    |    3 +--
 git.c              |   11 ++++++++---
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 61577ea..d36181a 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -469,9 +469,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
 		break;
 	}
 
-	if (require_work_tree &&
-			(!is_inside_work_tree() || is_inside_git_dir()))
-		die("This operation must be run in a work tree");
+	if (require_work_tree && !is_inside_work_tree()) {
+		const char *work_tree = get_git_work_tree();
+		if (!work_tree || chdir(work_tree))
+			die("This operation must be run in a work tree");
+	}
 
 	pathspec = get_pathspec(prefix, argv + i);
 
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index c51985e..7bef43f 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -59,8 +59,7 @@ cd_to_toplevel () {
 }
 
 require_work_tree () {
-	test $(git rev-parse --is-inside-work-tree) = true &&
-	test $(git rev-parse --is-inside-git-dir) = false ||
+	test $(git rev-parse --is-inside-work-tree) = true ||
 	die "fatal: $0 cannot be used without a working tree."
 }
 
diff --git a/git.c b/git.c
index a647f9c..2433355 100644
--- a/git.c
+++ b/git.c
@@ -272,9 +272,14 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)
 		prefix = setup_git_directory();
 	if (p->option & USE_PAGER)
 		setup_pager();
-	if ((p->option & NEED_WORK_TREE) &&
-	    (!is_inside_work_tree() || is_inside_git_dir()))
-		die("%s must be run in a work tree", p->cmd);
+	if (p->option & NEED_WORK_TREE) {
+		const char *work_tree = get_git_work_tree();
+		const char *git_dir = get_git_dir();
+		if (!is_absolute_path(git_dir))
+			set_git_dir(make_absolute_path(git_dir));
+		if (!work_tree || chdir(work_tree))
+			die("%s must be run in a work tree", p->cmd);
+	}
 	trace_argv_printf(argv, argc, "trace: built-in: git");
 
 	status = p->fn(argc, argv, prefix);
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 5/9] Add set_git_dir() function
From: Johannes Schindelin @ 2007-07-29 23:25 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


With the function set_git_dir() you can reset the path that will
be used for git_path(), git_dir() and friends.

The responsibility to close files and throw away information from the
old git_dir lies with the caller.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 cache.h       |    1 +
 environment.c |    8 ++++++++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/cache.h b/cache.h
index c0cab34..36963f2 100644
--- a/cache.h
+++ b/cache.h
@@ -216,6 +216,7 @@ extern char *get_refs_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern const char *get_git_work_tree(void);
+extern int set_git_dir(const char *path);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
diff --git a/environment.c b/environment.c
index 26f41af..2af12fd 100644
--- a/environment.c
+++ b/environment.c
@@ -124,3 +124,11 @@ char *get_graft_file(void)
 		setup_git_env();
 	return git_graft_file;
 }
+
+int set_git_dir(const char *path)
+{
+	if (setenv(GIT_DIR_ENVIRONMENT, path, 1))
+		return error("Could not set GIT_DIR to '%s'", path);
+	setup_git_env();
+	return 0;
+}
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 4/9] Clean up work-tree handling
From: Johannes Schindelin @ 2007-07-29 23:25 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


The old version of work-tree support was an unholy mess, barely readable,
and not to the point.

For example, why do you have to provide a worktree, when it is not used?
As in "git status".  Now it works.

Another riddle was: if you can have work trees inside the git dir, why
are some programs complaining that they need a work tree?

IOW when inside repo.git/work, where GIT_DIR points to repo.git
and GIT_WORK_TREE to work, and cwd is work, --is-inside-git-dir _must_
return true, because it is _in the git dir_, but scripts _must_ test
for the right thing.

Also, GIT_DIR=../.git should behave the same as if no GIT_DIR was
specified, unless there is a repository in the current working directory.
It does now.

The logic to determine if a repository is bare, or has a work tree
(tertium non datur), is this:

--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.

In related news, a long standing bug was fixed: when in .git/bla/x.git/,
which is a bare repository, git formerly assumed ../.. to be the
appropriate git dir.  This problem was reported by Shawn Pearce to have
caused much pain, where a colleague mistakenly ran "git init" in "/" a
long time ago, and bare repositories just would not work.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	This version no longer removes more lines than it adds, but it
	adds a lot more documentation than it removes.  IMHO it is also
	easier to follow, implements a sane logic, and stands a chance
	to be fixed by somebody else than the original author.

 builtin-rev-parse.c |    7 ++
 cache.h             |    2 +
 environment.c       |   35 +++++--
 setup.c             |  279 +++++++++++++++++++++++----------------------------
 4 files changed, 162 insertions(+), 161 deletions(-)

diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 497903a..15bdb72 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -320,6 +320,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 				continue;
 			}
 			if (!strcmp(arg, "--show-cdup")) {
+				if (!is_inside_work_tree()) {
+					const char *work_tree =
+						get_git_work_tree();
+					if (work_tree)
+						printf("%s\n", work_tree);
+					continue;
+				}
 				const char *pfx = prefix;
 				while (pfx) {
 					pfx = strchr(pfx, '/');
diff --git a/cache.h b/cache.h
index 98af530..c0cab34 100644
--- a/cache.h
+++ b/cache.h
@@ -208,12 +208,14 @@ enum object_type {
 extern int is_bare_repository_cfg;
 extern int is_bare_repository(void);
 extern int is_inside_git_dir(void);
+extern char *git_work_tree_cfg;
 extern int is_inside_work_tree(void);
 extern const char *get_git_dir(void);
 extern char *get_object_directory(void);
 extern char *get_refs_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
+extern const char *get_git_work_tree(void);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
diff --git a/environment.c b/environment.c
index f83fb9e..26f41af 100644
--- a/environment.c
+++ b/environment.c
@@ -35,6 +35,10 @@ int pager_in_use;
 int pager_use_color = 1;
 int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
 
+/* This is set by setup_git_dir_gently() and/or git_default_config() */
+char *git_work_tree_cfg;
+static const char *work_tree;
+
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
 
@@ -62,15 +66,8 @@ static void setup_git_env(void)
 
 int is_bare_repository(void)
 {
-	const char *dir, *s;
-	if (0 <= is_bare_repository_cfg)
-		return is_bare_repository_cfg;
-
-	dir = get_git_dir();
-	if (!strcmp(dir, DEFAULT_GIT_DIR_ENVIRONMENT))
-		return 0;
-	s = strrchr(dir, '/');
-	return !s || strcmp(s + 1, DEFAULT_GIT_DIR_ENVIRONMENT);
+	/* if core.bare is not 'false', let's see if there is a work tree */
+	return is_bare_repository_cfg && !get_git_work_tree();
 }
 
 const char *get_git_dir(void)
@@ -80,6 +77,26 @@ const char *get_git_dir(void)
 	return git_dir;
 }
 
+const char *get_git_work_tree(void)
+{
+	static int initialized = 0;
+	if (!initialized) {
+		work_tree = getenv(GIT_WORK_TREE_ENVIRONMENT);
+		/* core.bare = true overrides implicit and config work tree */
+		if (!work_tree && is_bare_repository_cfg < 1) {
+			work_tree = git_work_tree_cfg;
+			/* make_absolute_path also normalizes the path */
+			if (work_tree && !is_absolute_path(work_tree))
+				work_tree = xstrdup(make_absolute_path(git_path(work_tree)));
+		} else if (work_tree)
+			work_tree = xstrdup(make_absolute_path(work_tree));
+		initialized = 1;
+		if (work_tree)
+			is_bare_repository_cfg = 0;
+	}
+	return work_tree;
+}
+
 char *get_object_directory(void)
 {
 	if (!git_object_dir)
diff --git a/setup.c b/setup.c
index b54d65f..8237fe3 100644
--- a/setup.c
+++ b/setup.c
@@ -1,4 +1,8 @@
 #include "cache.h"
+#include "dir.h"
+
+static int inside_git_dir = -1;
+static int inside_work_tree = -1;
 
 const char *prefix_path(const char *prefix, int len, const char *path)
 {
@@ -170,100 +174,89 @@ static int is_git_directory(const char *suspect)
 	return 1;
 }
 
-static int inside_git_dir = -1;
-
 int is_inside_git_dir(void)
 {
-	if (inside_git_dir >= 0)
-		return inside_git_dir;
-	die("BUG: is_inside_git_dir called before setup_git_directory");
+	if (inside_git_dir < 0)
+		inside_git_dir = is_inside_dir(get_git_dir());
+	return inside_git_dir;
 }
 
-static int inside_work_tree = -1;
-
 int is_inside_work_tree(void)
 {
-	if (inside_git_dir >= 0)
-		return inside_work_tree;
-	die("BUG: is_inside_work_tree called before setup_git_directory");
+	if (inside_work_tree < 0)
+		inside_work_tree = is_inside_dir(get_git_work_tree());
+	return inside_work_tree;
 }
 
-static char *gitworktree_config;
-
-static int git_setup_config(const char *var, const char *value)
+/*
+ * If no worktree was given, and we are outside of a default work tree,
+ * now is the time to set it.
+ *
+ * In other words, if the user calls git with something like
+ *
+ *	git --git-dir=/some/where/else/.git bla
+ *
+ * default to /some/where/else as working directory; if the specified
+ * git-dir does not end in "/.git", the cwd is used as working directory.
+ */
+const char* set_work_tree(const char *dir)
 {
-	if (!strcmp(var, "core.worktree")) {
-		if (gitworktree_config)
-			strlcpy(gitworktree_config, value, PATH_MAX);
-		return 0;
+	char dir_buffer[PATH_MAX];
+	static char buffer[PATH_MAX + 1], *rel = NULL;
+	int len, postfix_len = strlen(DEFAULT_GIT_DIR_ENVIRONMENT) + 1;
+
+	/* strip the variable 'dir' of the postfix "/.git" if it has it */
+	len = strlen(dir);
+	if (len > postfix_len && !strcmp(dir + len - postfix_len,
+				"/" DEFAULT_GIT_DIR_ENVIRONMENT)) {
+			strncpy(dir_buffer, dir, len - postfix_len);
+
+		/* are we inside the default work tree? */
+		rel = get_relative_cwd(buffer, sizeof(buffer), dir_buffer);
+	}
+	/* if rel is set, the cwd is _not_ the current working tree */
+	if (rel && *rel) {
+		if (!is_absolute_path(dir))
+			set_git_dir(make_absolute_path(dir));
+		dir = dir_buffer;
+		chdir(dir);
+		strcat(rel, "/");
+		inside_git_dir = 0;
+	} else {
+		rel = NULL;
+		dir = getcwd(buffer, sizeof(buffer));
 	}
-	return git_default_config(var, value);
+	git_work_tree_cfg = xstrdup(dir);
+	inside_work_tree = 1;
+
+	return rel;
 }
 
+/*
+ * We cannot decide in this function whether we are in the work tree or
+ * not, since the config can only be read _after_ this function was called.
+ */
 const char *setup_git_directory_gently(int *nongit_ok)
 {
+	const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
 	static char cwd[PATH_MAX+1];
-	char worktree[PATH_MAX+1], gitdir[PATH_MAX+1];
-	const char *gitdirenv, *gitworktree;
-	int wt_rel_gitdir = 0;
+	const char *gitdirenv;
+	int len, offset;
 
+	/*
+	 * If GIT_DIR is set explicitly, we're not going
+	 * to do any discovery, but we still do repository
+	 * validation.
+	 */
 	gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
-	if (!gitdirenv) {
-		int len, offset;
-
-		if (!getcwd(cwd, sizeof(cwd)-1))
-			die("Unable to read current working directory");
-
-		offset = len = strlen(cwd);
-		for (;;) {
-			if (is_git_directory(".git"))
-				break;
-			if (offset == 0) {
-				offset = -1;
-				break;
-			}
-			chdir("..");
-			while (cwd[--offset] != '/')
-				; /* do nothing */
-		}
-
-		if (offset >= 0) {
-			inside_work_tree = 1;
-			git_config(git_default_config);
-			if (offset == len) {
-				inside_git_dir = 0;
-				return NULL;
-			}
-
-			cwd[len++] = '/';
-			cwd[len] = '\0';
-			inside_git_dir = !prefixcmp(cwd + offset + 1, ".git/");
-			return cwd + offset + 1;
-		}
-
-		if (chdir(cwd))
-			die("Cannot come back to cwd");
-		if (!is_git_directory(".")) {
-			if (nongit_ok) {
-				*nongit_ok = 1;
-				return NULL;
-			}
-			die("Not a git repository");
-		}
-		setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
-		gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
-		if (!gitdirenv)
-			die("getenv after setenv failed");
-	}
-
-	if (PATH_MAX - 40 < strlen(gitdirenv)) {
-		if (nongit_ok) {
-			*nongit_ok = 1;
+	if (gitdirenv) {
+		if (PATH_MAX - 40 < strlen(gitdirenv))
+			die("'$%s' too big", GIT_DIR_ENVIRONMENT);
+		if (is_git_directory(gitdirenv)) {
+			if (!work_tree_env)
+				return set_work_tree(gitdirenv);
 			return NULL;
 		}
-		die("$%s too big", GIT_DIR_ENVIRONMENT);
-	}
-	if (!is_git_directory(gitdirenv)) {
 		if (nongit_ok) {
 			*nongit_ok = 1;
 			return NULL;
@@ -273,92 +266,53 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
 	if (!getcwd(cwd, sizeof(cwd)-1))
 		die("Unable to read current working directory");
-	if (chdir(gitdirenv)) {
-		if (nongit_ok) {
-			*nongit_ok = 1;
-			return NULL;
-		}
-		die("Cannot change directory to $%s '%s'",
-			GIT_DIR_ENVIRONMENT, gitdirenv);
-	}
-	if (!getcwd(gitdir, sizeof(gitdir)-1))
-		die("Unable to read current working directory");
-	if (chdir(cwd))
-		die("Cannot come back to cwd");
 
 	/*
-	 * In case there is a work tree we may change the directory,
-	 * therefore make GIT_DIR an absolute path.
+	 * Test in the following order (relative to the cwd):
+	 * - .git/
+	 * - ./ (bare)
+	 * - ../.git/
+	 * - ../ (bare)
+	 * - ../../.git/
+	 *   etc.
 	 */
-	if (gitdirenv[0] != '/') {
-		setenv(GIT_DIR_ENVIRONMENT, gitdir, 1);
-		gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
-		if (!gitdirenv)
-			die("getenv after setenv failed");
-		if (PATH_MAX - 40 < strlen(gitdirenv)) {
-			if (nongit_ok) {
-				*nongit_ok = 1;
-				return NULL;
-			}
-			die("$%s too big after expansion to absolute path",
-				GIT_DIR_ENVIRONMENT);
-		}
-	}
-
-	strcat(cwd, "/");
-	strcat(gitdir, "/");
-	inside_git_dir = !prefixcmp(cwd, gitdir);
-
-	gitworktree = getenv(GIT_WORK_TREE_ENVIRONMENT);
-	if (!gitworktree) {
-		gitworktree_config = worktree;
-		worktree[0] = '\0';
-	}
-	git_config(git_setup_config);
-	if (!gitworktree) {
-		gitworktree_config = NULL;
-		if (worktree[0])
-			gitworktree = worktree;
-		if (gitworktree && gitworktree[0] != '/')
-			wt_rel_gitdir = 1;
-	}
-
-	if (wt_rel_gitdir && chdir(gitdirenv))
-		die("Cannot change directory to $%s '%s'",
-			GIT_DIR_ENVIRONMENT, gitdirenv);
-	if (gitworktree && chdir(gitworktree)) {
-		if (nongit_ok) {
-			if (wt_rel_gitdir && chdir(cwd))
-				die("Cannot come back to cwd");
-			*nongit_ok = 1;
+	offset = len = strlen(cwd);
+	for (;;) {
+		if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
+			break;
+		if (is_git_directory(".")) {
+			inside_git_dir = 1;
+			if (!work_tree_env)
+				inside_work_tree = 0;
+			setenv(GIT_DIR_ENVIRONMENT, ".", 1);
 			return NULL;
 		}
-		if (wt_rel_gitdir)
-			die("Cannot change directory to working tree '%s'"
-				" from $%s", gitworktree, GIT_DIR_ENVIRONMENT);
-		else
-			die("Cannot change directory to working tree '%s'",
-				gitworktree);
-	}
-	if (!getcwd(worktree, sizeof(worktree)-1))
-		die("Unable to read current working directory");
-	strcat(worktree, "/");
-	inside_work_tree = !prefixcmp(cwd, worktree);
-
-	if (gitworktree && inside_work_tree && !prefixcmp(worktree, gitdir) &&
-	    strcmp(worktree, gitdir)) {
-		inside_git_dir = 0;
+		chdir("..");
+		do {
+			if (!offset) {
+				if (nongit_ok) {
+					if (chdir(cwd))
+						die("Cannot come back to cwd");
+					*nongit_ok = 1;
+					return NULL;
+				}
+				die("Not a git repository");
+			}
+		} while (cwd[--offset] != '/');
 	}
 
-	if (!inside_work_tree) {
-		if (chdir(cwd))
-			die("Cannot come back to cwd");
+	inside_git_dir = 0;
+	if (!work_tree_env)
+		inside_work_tree = 1;
+	git_work_tree_cfg = xstrndup(cwd, offset);
+	if (offset == len)
 		return NULL;
-	}
 
-	if (!strcmp(cwd, worktree))
-		return NULL;
-	return cwd+strlen(worktree);
+	/* Make "offset" point to past the '/', and add a '/' at the end */
+	offset++;
+	cwd[len++] = '/';
+	cwd[len] = 0;
+	return cwd + offset;
 }
 
 int git_config_perm(const char *var, const char *value)
@@ -386,6 +340,16 @@ int check_repository_format_version(const char *var, const char *value)
 		repository_format_version = git_config_int(var, value);
 	else if (strcmp(var, "core.sharedrepository") == 0)
 		shared_repository = git_config_perm(var, value);
+	else if (strcmp(var, "core.bare") == 0) {
+		is_bare_repository_cfg = git_config_bool(var, value);
+		if (is_bare_repository_cfg == 1)
+			inside_work_tree = -1;
+	} else if (strcmp(var, "core.worktree") == 0) {
+		if (git_work_tree_cfg)
+			free(git_work_tree_cfg);
+		git_work_tree_cfg = xstrdup(value);
+		inside_work_tree = -1;
+	}
 	return 0;
 }
 
@@ -402,5 +366,16 @@ const char *setup_git_directory(void)
 {
 	const char *retval = setup_git_directory_gently(NULL);
 	check_repository_format();
+
+	/* If the work tree is not the default one, recompute prefix */
+	if (inside_work_tree < 0) {
+		static char buffer[PATH_MAX + 1];
+		if (retval && chdir(retval))
+			die ("Could not jump back into original cwd");
+		char *rel = get_relative_cwd(buffer, PATH_MAX,
+				get_git_work_tree());
+		return rel && *rel ? strcat(rel, "/") : NULL;
+	}
+
 	return retval;
 }
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 3/9] white space fixes in setup.c
From: Johannes Schindelin @ 2007-07-29 23:24 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


Some lines were not indented by tabs but by spaces.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	Just to make the next patch look nicer.

 setup.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/setup.c b/setup.c
index 7b07144..b54d65f 100644
--- a/setup.c
+++ b/setup.c
@@ -382,11 +382,11 @@ int git_config_perm(const char *var, const char *value)
 
 int check_repository_format_version(const char *var, const char *value)
 {
-       if (strcmp(var, "core.repositoryformatversion") == 0)
-               repository_format_version = git_config_int(var, value);
+	if (strcmp(var, "core.repositoryformatversion") == 0)
+		repository_format_version = git_config_int(var, value);
 	else if (strcmp(var, "core.sharedrepository") == 0)
 		shared_repository = git_config_perm(var, value);
-       return 0;
+	return 0;
 }
 
 int check_repository_format(void)
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 2/9] Add functions get_relative_cwd() and is_inside_dir()
From: Johannes Schindelin @ 2007-07-29 23:24 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


The function get_relative_cwd() works just as getcwd(), only that it
takes an absolute path as additional parameter, returning the prefix
of the current working directory relative to the given path.  If the
cwd is no subdirectory of the given path, it returns NULL.

is_inside_dir() is just a trivial wrapper over get_relative_cwd().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 dir.c |   30 ++++++++++++++++++++++++++++++
 dir.h |    3 +++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/dir.c b/dir.c
index 8d8faf5..ef67d6f 100644
--- a/dir.c
+++ b/dir.c
@@ -642,3 +642,33 @@ file_exists(const char *f)
   struct stat sb;
   return stat(f, &sb) == 0;
 }
+
+char *get_relative_cwd(char *buffer, int size, const char *dir)
+{
+	char *cwd = buffer;
+
+	if (!dir)
+		return 0;
+
+	if (!getcwd(buffer, size))
+		return 0;
+
+	if (!is_absolute_path(dir))
+		dir = make_absolute_path(dir);
+
+	while (*dir && *dir == *cwd) {
+		dir++;
+		cwd++;
+	}
+	if (*dir)
+		return NULL;
+	if (*cwd == '/')
+		return cwd + 1;
+	return cwd;
+}
+
+int is_inside_dir(const char *dir)
+{
+	char buffer[PATH_MAX];
+	return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
+}
diff --git a/dir.h b/dir.h
index ec0e8ab..f55a87b 100644
--- a/dir.h
+++ b/dir.h
@@ -61,4 +61,7 @@ extern void add_exclude(const char *string, const char *base,
 extern int file_exists(const char *);
 extern struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len);
 
+extern char *get_relative_cwd(char *buffer, int size, const char *dir);
+extern int is_inside_dir(const char *dir);
+
 #endif
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 1/9] Add is_absolute_path() and make_absolute_path()
From: Johannes Schindelin @ 2007-07-29 23:24 UTC (permalink / raw)
  To: gitster, git, matled
In-Reply-To: <Pine.LNX.4.64.0707300016470.14781@racer.site>


This patch adds convenience functions to work with absolute paths.
The function is_absolute_path() should help the efforts to integrate
the MinGW fork.

Note that make_absolute_path() returns a pointer to a static buffer.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Makefile             |    2 +-
 cache.h              |    5 ++++
 path.c               |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 t/t0000-basic.sh     |   16 ++++++++++++
 test-absolute-path.c |   11 ++++++++
 5 files changed, 98 insertions(+), 1 deletions(-)
 create mode 100644 test-absolute-path.c

diff --git a/Makefile b/Makefile
index d8100ad..546e008 100644
--- a/Makefile
+++ b/Makefile
@@ -936,7 +936,7 @@ endif
 
 ### Testing rules
 
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X
+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X
 
 all:: $(TEST_PROGRAMS)
 
diff --git a/cache.h b/cache.h
index 53801b8..98af530 100644
--- a/cache.h
+++ b/cache.h
@@ -358,6 +358,11 @@ int git_config_perm(const char *var, const char *value);
 int adjust_shared_perm(const char *path);
 int safe_create_leading_directories(char *path);
 char *enter_repo(char *path, int strict);
+static inline int is_absolute_path(const char *path)
+{
+	return path[0] == '/';
+}
+const char *make_absolute_path(const char *path);
 
 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 extern int sha1_object_info(const unsigned char *, unsigned long *);
diff --git a/path.c b/path.c
index dfff41f..dfa6ce0 100644
--- a/path.c
+++ b/path.c
@@ -288,3 +288,68 @@ int adjust_shared_perm(const char *path)
 		return -2;
 	return 0;
 }
+
+/* We allow "recursive" symbolic links. Only within reason, though. */
+#define MAXDEPTH 5
+
+const char *make_absolute_path(const char *path)
+{
+	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+	char cwd[1024] = "";
+	int buf_index = 1, len;
+
+	int depth = MAXDEPTH;
+	char *last_elem = NULL;
+	struct stat st;
+
+	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+		die ("Too long path: %.*s", 60, path);
+
+	while (depth--) {
+		if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
+			char *last_slash = strrchr(buf, '/');
+			if (last_slash) {
+				*last_slash = '\0';
+				last_elem = xstrdup(last_slash + 1);
+			} else
+				last_elem = xstrdup(buf);
+		}
+
+		if (*buf) {
+			if (!*cwd && getcwd(cwd, sizeof(cwd)) < 0)
+				die ("Could not get current working directory");
+
+			if (chdir(buf))
+				die ("Could not switch to '%s'", buf);
+		}
+		if (getcwd(buf, PATH_MAX) < 0)
+			die ("Could not get current working directory");
+
+		if (last_elem) {
+			int len = strlen(buf);
+			if (len + strlen(last_elem) + 2 > PATH_MAX)
+				die ("Too long path name: '%s/%s'",
+						buf, last_elem);
+			buf[len] = '/';
+			strcpy(buf + len + 1, last_elem);
+			free(last_elem);
+			last_elem = NULL;
+		}
+
+		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
+			len = readlink(buf, next_buf, PATH_MAX);
+			if (len < 0)
+				die ("Invalid symlink: %s", buf);
+			next_buf[len] = '\0';
+			buf = next_buf;
+			buf_index = 1 - buf_index;
+			next_buf = bufs[buf_index];
+		} else
+			break;
+	}
+
+	if (*cwd && chdir(cwd))
+		die ("Could not change back to '%s'", cwd);
+
+	return buf;
+}
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 4bba9c0..4e49d59 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -281,4 +281,20 @@ test_expect_success 'update-index D/F conflict' '
 	test $numpath0 = 1
 '
 
+test_expect_success 'absolute path works as expected' '
+	mkdir first &&
+	ln -s ../.git first/.git &&
+	mkdir second &&
+	ln -s ../first second/other &&
+	mkdir third &&
+	dir="$(cd .git; pwd -P)" &&
+	dir2=third/../second/other/.git &&
+	test "$dir" = "$(test-absolute-path $dir2)" &&
+	file="$dir"/index &&
+	test "$file" = "$(test-absolute-path $dir2/index)" &&
+	ln -s ../first/file .git/syml &&
+	sym="$(cd first; pwd -P)"/file &&
+	test "$sym" = "$(test-absolute-path $dir2/syml)"
+'
+
 test_done
diff --git a/test-absolute-path.c b/test-absolute-path.c
new file mode 100644
index 0000000..c959ea2
--- /dev/null
+++ b/test-absolute-path.c
@@ -0,0 +1,11 @@
+#include "cache.h"
+
+int main(int argc, char **argv)
+{
+	while (argc > 1) {
+		puts(make_absolute_path(argv[1]));
+		argc--;
+		argv++;
+	}
+	return 0;
+}
-- 
1.5.3.rc3.28.g1406

^ permalink raw reply related

* [PATCH 0/9] work-tree clean ups
From: Johannes Schindelin @ 2007-07-29 23:23 UTC (permalink / raw)
  To: gitster, git, matled

Hi,

this is the 3rd revision of the work-tree clean up series.  Unlike the 1st 
revision, this passes all the tests.  Unlike the 2nd revision, it has a 
concise and precise logic:

--work-tree=bla overrides GIT_WORK_TREE, which overrides core.bare = true,
which overrides core.worktree, which overrides GIT_DIR/.. when GIT_DIR
ends in /.git, which overrides the directory in which .git/ was found.

The distinction between git_dir and work_tree is much clearer now: you can 
have a work_tree which is inside a git_dir, and programs needing a 
work_tree will no longer complain.

The work tree information is no longer just thrown away.  Instead, you can 
run git from the git_dir and it will work on the work tree without you 
having to cd back and forth.

The wrong distinction between a non-bare repository and a repository with 
a work_tree is no longer there.  A repository is either bare, or it has a 
working directory.  There is no third option.

Ciao,
Dscho

^ permalink raw reply

* Re: merge time
From: Jakub Narebski @ 2007-07-29 23:19 UTC (permalink / raw)
  To: git
In-Reply-To: <630183.45851.qm@web51001.mail.re2.yahoo.com>

[Cc: Matthew L Foster <mfoster167@yahoo.com>, git@vger.kernel.org]

Please, word wrap lines around 70 - 76 column.

Matthew L Foster wrote:

> Sorry to bring up the time issue again [that I am perhaps still confused
> about] but I have been playing around with git more and I think I can
> phrase my question/observation better. 
> 
> From viewing gitweb.cgi I have observed a situation where Linus creates
> a tag, say rc1, and then he later merges changes but some subset of those
> changes/commits show up in the list in time order as taking place _before_
> the rc1 tag was made even though they were merged after.

Of course. The time ordering is by the time commits were _created_,
not when they were merged.

In git, you can try tu use --topo-order parameter to git-log. In gitweb,
not yet.

> Do I describe a real or possible phenomenon?

Real phenomenon.

> And does this happen because the developer that made the subset of changes
> in question commit them to his/her local repository in time order before
> the rc1 tag was made? So an external repository had the change before the
> rc1 tag was made but Linus' repository didn't?

That's correct. Well, Linus' repository might have had change, but just
not merged in, but that is just small detail.

> But internally git on Linus' machine knows that the 
> gitweb.cgi displayed time order is wrong as far as the state is concerned
> because each repository's index file keeps local track of the true local
> state [just time isn't reconcilable], or am I missing something(s)? 

Git does not know, and git proper has no utility to show for each commit
when it was merged to given branch. And that is even more complicated by
the fast-forward merges. Reflog (local matter, not displayed in gitweb,
available as "git reflog show <branch>" or "git log --show-reflog
[<branch>]" in git) keeps track of the branch tip history; it doesn't offer
information [you think] you want.

> Is it possible for gitweb.cgi to have a new view mode that sorts/displays
> the list based on merge time for commits (the time merged into Linus' or
> whatever repository) so the above situation doesn't happen?  The actual
> time of a local commit should be the time it was merged locally not the  
> time it was created externally/originally, right?

I don't think that it is possible, but you are welcome to try...

> Where can I find the gitweb.cgi source/package?
> I could maybe hack gitweb.cgi myself.

Gitweb is now in the git.git repository, in gitweb/gitweb.perl
(see also gitweb/README and gitweb/INSTALL).
 
> Please CC me on any replies since I am not subscribed to the list.

Please Cc: list.
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* MinGW build environment for Git
From: Dmitry Kakurin @ 2007-07-29 23:14 UTC (permalink / raw)
  To: git

    I want to be able to build MinGW port of Git on Windows.
I've tried to follow steps in README.MinGW to setup this environment
myself (install MinGW, MSys, ZLib etc.) but after wasting a lot of
time with no result I give up.
   So, could somebody please just pkzip their environment (everything
required) and share the zip file with me (privately or publicly)?
   I also think that an even better idea is to create a new Git
repository with MinGW build environment. This will make contributing
to MinGW port of Git MUCH easier.

- Dmitry

^ permalink raw reply

* Re: git-gui blame: show previous commit
From: Jakub Narebski @ 2007-07-29 22:53 UTC (permalink / raw)
  To: git
In-Reply-To: <87myxfzhk6.fsf@mid.deneb.enyo.de>

Florian Weimer wrote:

> How can I view the previous commit touching a specific line, so that I
> can see what was there before?  For instance, the change could be
> whitespace-only, so that I want to dig deeper.

You can always use "git blame -L<lineno>,+1 <revision> -- <file>". Or use
pickaxe search, i.e. "git log -S'<fragment>' <revision> -- <file>".

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: git diff with add/modified codes
From: Jakub Narebski @ 2007-07-29 21:36 UTC (permalink / raw)
  To: Jon Smirl; +Cc: git
In-Reply-To: <9e4733910707281107w6aff86f5sf746ca3f2c74d098@mail.gmail.com>

On Sat, 28 July 2007, Jon Smirl wrote:
> On 7/28/07, Jakub Narebski <jnareb@gmail.com> wrote:
>> Jeff King wrote:
>>
>>> On Fri, Jul 27, 2007 at 08:17:54PM -0400, Jon Smirl wrote:
>>>
>>>> That's not what I want. I'm looking a report that indicates new files
>>>> vs modified ones in a single list. These old patches I am working with
>>>> often create 100 files and modify another 200.
>>>>
>>>> Adding a code like (Added (A), Copied (C), Deleted (D), Modified (M),
>>>> Renamed (R))  to --stat would be perfect.
>>>
>>> How about --name-status?
>>
>> Or -r --name-status?
> 
> -r is not in the git diff doc but it is used in the examples.
> http://www.kernel.org/pub/software/scm/git/docs/git-diff.html

<quote>
  <2> show only names and the nature of change, but not actual
  diff output.  --name-status disables usual patch generation
  which in turn also disables recursive behavior, so without -r
  you would only see the directory name if there is a change in a
  file in a subdirectory.
</quote>

"Of course" one knows that "git diff <tree-ish> <tree-ish>" is
git-diff-tree in disguise, and accepts git-diff-tree options.

By the way, I was thinking about extending --numstat output to include
also status. Current --numstat output is ill fitted to deal with renames
and copies, at least ill fitted for machine consumption of renames
output; it uses "old_name => new_name" as a filename for renames. While
it would be fairly easy to put pre- and after-rename names separated
by TAB, and quoted if needed (including embedded TAB character in
the filename, which would be quoted as \t instead) without breaking
anu current --numstat output parsers (although I don't think any of
them uses -M/-C), it would be hard to do the same for --numstat -z output.
A solution (not best, I admit) would be to use NUL NUL to separate pre-
and post-image filename, but I think it would be best to add new
--numstat-extended format to git-diff.

P.S. Is binary diff output described somewhere?
-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: [Untested! proposal] git-mergetool.sh: introduce ediff option
From: Theodore Tso @ 2007-07-29 20:52 UTC (permalink / raw)
  To: David Kastrup; +Cc: git
In-Reply-To: <85hcnnwblu.fsf@lola.goethe.zz>

On Sun, Jul 29, 2007 at 03:51:34PM +0200, David Kastrup wrote:
> 
> Most actual Emacs users prefer ediff to emerge concerning the
> consolidation of versions.  In general, people habitually using Emacs
> will have this preference reflected in the EDITOR/VISUAL environment
> variables.

Proof, please?  Do you have any polls?  What evidence do you have?
For the past two decades, I have EDITOR set to emacs, but I am not an
ediff fan.  Yes, that's anecdotal evidence, but so are your assertions.

> If such a preference can be found there, ediff will be used/offered in
> preference of emerge (which retains its previous behavior).

Ediff is currently far more confusing for someone who just uses emacs
as an editor.  There are plenty of users who never learned the vi
commands, but who use emacs as a reasonably easy-to-use text editor.
Not everyone who uses emacs is a power-user.....

> In ediff mode, success or failure of the merge will be discerned by
> Emacs either having written or not written the merge buffer; no
> attempt of interpreting the exit code is made.

Sometimes resolving the merge file results in no changes.  So the fact
that ediff is buggy in that it doesn't return an exit code is a real
problem.  We could possibly work around the problem saving and then
checking the modtime --- but only if ediff actually ends up rewriting
the file.

> In order to bypass things like desktop files being loaded, emerge mode
> now passes the "-q" option to Emacs.  This will make it work in more
> situations likely to occur, at the price of excluding possibly
> harmless user customizations with the rest.

But that screws over users who want their customizations, but who
don't use the desktop package.  (And I have a news flash for you; the
desktop package is *not* include as part of emacs21.  It's not part of
Debian's emacs21 package, version 21.4.)  So do not believe your claim
that emacs's desktop package is commonly used.   

Probably a better choice is a config parameter which allows users to
specify a set of options to be passed to emacs when git fires up an
emacs program.  That would allow some people to specfy --no-desktop if
they are using a new enough emacs program that supports it.  It would
also allow users to use other emacs command-line options that they
might like, i.e., -nw, or --title, etc.

> +	ediff)
> +	    case "${EDITOR:-${VISUAL:-emacs}}" in
> +		*/emacs*|*/gnuclient*|*/xemacs*)
> +		    emacs_candidate="${EDITOR:-${VISUAL:-emacs}}";;
> +		*)
> +		    emacs_candidate=emacs;;
> +	    esac
> +	    if base_present ; then
> +		${emacs_candidate} --eval "(ediff-merge-files-with-ancestor (pop command-line-args-left) (pop command-line-args-left) (pop command-line-args-left) nil (pop-command-line-args-left))" "$LOCAL" "$REMOTE" "$BASE" "$path"

... and this will blow up if EMACS is set to emacsclient, and emacs
version is 21.  (And BTW, Debian stable and the current Ubuntu, Edgy
Eft, are still shipping emacs21.  So are a number of current major
distro's.  So if you think the vast majority of users are using
emacs22, you are either on drugs, and have a very skewed view of what
are "normal" emacs users.)

There is a reason why git-mergetool currently hardcodes the use of
"emacs", instead of just blindly using the value of $EDITOR or
$VISUAL.  So what you're doing here in your patch is completely
busted.  If you insist on using emacs_candidate, we need to run emacs
--version and parse the output, and only using the value of EMACS or
VISUAL if the major version number of emacs is at least 22.

(It would probably be a good idea to do this once and cache the
result, so we don't have to repeatedly for each file that git
mergetool needs to process.)

> -    if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
> -        merge_tool_candidates="$merge_tool_candidates emerge"
> -    fi
> +    case "${EDITOR:-${VISUAL}}" in
> +	*/emacs*|*/gnuclient*|*/xemacs*)
> +            merge_tool_candidates="$merge_tool_candidates ediff"
> +    esac

Changing the default from emerge to ediff is a non-starter, sorry.  If
you really want to use ediff, you can set a config parameter to
explicitly request it.

						- Ted

^ permalink raw reply

* Re: [PATCH] Makefile: create an install-symlinks target
From: David Kastrup @ 2007-07-29 22:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vk5sin9g0.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <gitster@pobox.com> writes:

> I thought we already rejected the "install symlink" in the
> earlier round.  Am I mistaken, or are there any compelling new
> reasons to revisit it?

Uh, perhaps I have a patchy recollection, but what I remember is that
Scho argued that one might use something like xstow or a package
manager instead, and I replied that

a) this required the installation of additional software for a simple
   task.

b) if the software worked using symbolic links, it would not know at
   what level to make the links (namely create
   /usr/local/share/man/man1 and link every file from
   /opt/git/share/man/man1, but link the directory
   /usr/local/share/git-core directly to /opt/git/share/git-core).

I don't remember a conclusive reply to that.  Not seeing the patch
appear either, I decided to clean it up, remove the objection of using
the GNU-specific -mindepth option, and properly document the usage.

Since the stuff is strictly an additional convenience not impacting
any of the existing targets, I would not have thought it terribly
controversial.

If I have misinterpreted or misremembered part of the discussion, I
apologize.  No harm was intended.

In any case, some people might want to make use of the polished patch
series even if it is not applied to git.git.

Is there a place other than the git list where one can provide patches
that are not likely to end up in git.git?

Thanks,

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply

* Re: [PATCH] Makefile: create an install-symlinks target
From: Peter Baumann @ 2007-07-29 22:26 UTC (permalink / raw)
  To: David Kastrup; +Cc: git
In-Reply-To: <85lkcyvr4f.fsf@lola.goethe.zz>

On Sun, Jul 29, 2007 at 11:26:08PM +0200, David Kastrup wrote:
> [commit text mostly pinched from INSTALL]
> 
> An alternative global installation method making it much easier to
> uninstall is to use a package-specific prefix like /opt/git, then
> create symlinks from /usr/local into that hierarchy.  Uninstalling can
> then be achieved by
> 
> 	# rm -rf /opt/git; find /usr/local -xtype l -delete
> 
> You can create a setup like that after having used one of the above
> install recipes with prefix=/opt/git by writing
> 
> 	# make prefix=/opt/git symlinkprefix=/usr/local install-symlinks
> 
> This works by copying the directory hierarchy of $prefix to
> $symlinkprefix (not copying or descending to any directories of the
> name git* matched case-insensitively), then linking all the rest.
> 
> Signed-off-by: David Kastrup <dak@gnu.org>

AFAIR I suggested this the last time this came up, but in case you
missed it:

Use (x)stow for this. It does exactly what you want. No need to hack the
Makefile.

-Peter

^ permalink raw reply

* Re: [PATCH] Makefile: use $(FIND) instead of find
From: Junio C Hamano @ 2007-07-29 22:22 UTC (permalink / raw)
  To: David Kastrup; +Cc: git
In-Reply-To: <85ir82vr1v.fsf@lola.goethe.zz>

Will apply excluding the install-symlinks bit.  The $(FIND)
thing is a good idea independently.  Thanks.

^ permalink raw reply

* Re: [PATCH] Makefile: create an install-symlinks target
From: Junio C Hamano @ 2007-07-29 22:15 UTC (permalink / raw)
  To: David Kastrup; +Cc: git
In-Reply-To: <85lkcyvr4f.fsf@lola.goethe.zz>

I thought we already rejected the "install symlink" in the
earlier round.  Am I mistaken, or are there any compelling new
reasons to revisit it?

^ permalink raw reply

* [PATCH] Makefile: use $(FIND) instead of find
From: David Kastrup @ 2007-07-29 21:27 UTC (permalink / raw)
  To: git
In-Reply-To: <85lkcyvr4f.fsf@lola.goethe.zz>

Some people might prefer to be able to specify the find utility to
use, in particular for the more complicated usage in the
install-symlinks target.

Signed-off-by: David Kastrup <dak@gnu.org>
---
 Makefile |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 87b317f..29dfdeb 100644
--- a/Makefile
+++ b/Makefile
@@ -178,6 +178,7 @@ AR = ar
 RM = rm -f
 TAR = tar
 INSTALL = install
+FIND = find
 RPMBUILD = rpmbuild
 TCL_PATH = tclsh
 TCLTK_PATH = wish
@@ -905,11 +906,11 @@ doc:
 
 TAGS:
 	$(RM) TAGS
-	find . -name '*.[hcS]' -print | xargs etags -a
+	$(FIND) . -name '*.[hcS]' -print | xargs etags -a
 
 tags:
 	$(RM) tags
-	find . -name '*.[hcS]' -print | xargs ctags -a
+	$(FIND) . -name '*.[hcS]' -print | xargs ctags -a
 
 ### Detect prefix changes
 TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
@@ -1001,10 +1002,10 @@ quick-install-doc:
 # The somewhat strange looking lines start with an ignored $(MAKE) in
 # order to be executed also in make -n calls.
 install-symlinks:
-	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && find . -type d ! \( -iname 'git*' -prune \) -exec echo $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
-	@cd '$(prefix_SQ)' && find . -type d ! \( -iname 'git*' -prune \) -exec $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
-	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && find . \( -type d -iname 'git*' -prune -o ! -type d \) -exec echo $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec echo ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
-	@cd '$(prefix_SQ)' && find . \( -type d -iname 'git*' -prune -o ! -type d \) -exec $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
+	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && $(FIND) . -type d ! \( -iname 'git*' -prune \) -exec echo $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
+	@cd '$(prefix_SQ)' && $(FIND) . -type d ! \( -iname 'git*' -prune \) -exec $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
+	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && $(FIND) . \( -type d -iname 'git*' -prune -o ! -type d \) -exec echo $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec echo ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
+	@cd '$(prefix_SQ)' && $(FIND) . \( -type d -iname 'git*' -prune -o ! -type d \) -exec $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
 
 ### Maintainer's dist rules
 
-- 
1.5.3.rc2.84.g6497

^ permalink raw reply related

* [PATCH] Makefile: create an install-symlinks target
From: David Kastrup @ 2007-07-29 21:26 UTC (permalink / raw)
  To: git

[commit text mostly pinched from INSTALL]

An alternative global installation method making it much easier to
uninstall is to use a package-specific prefix like /opt/git, then
create symlinks from /usr/local into that hierarchy.  Uninstalling can
then be achieved by

	# rm -rf /opt/git; find /usr/local -xtype l -delete

You can create a setup like that after having used one of the above
install recipes with prefix=/opt/git by writing

	# make prefix=/opt/git symlinkprefix=/usr/local install-symlinks

This works by copying the directory hierarchy of $prefix to
$symlinkprefix (not copying or descending to any directories of the
name git* matched case-insensitively), then linking all the rest.

Signed-off-by: David Kastrup <dak@gnu.org>
---
 INSTALL  |   12 ++++++++++++
 Makefile |   10 +++++++++-
 2 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/INSTALL b/INSTALL
index 79e71b6..22df145 100644
--- a/INSTALL
+++ b/INSTALL
@@ -21,6 +21,18 @@ set up install paths (via config.mak.autogen), so you can write instead
 	$ make all doc ;# as yourself
 	# make install install-doc ;# as root
 
+An alternative global installation method making it much easier to
+uninstall is to use a package-specific prefix like /opt/git, then
+create symlinks from /usr/local into that hierarchy.  Uninstalling can
+then be achieved by
+
+	# rm -rf /opt/git; find /usr/local -xtype l -delete
+
+You can create a setup like that after having used one of the above
+install recipes with prefix=/opt/git by writing
+
+	# make prefix=/opt/git symlinkprefix=/usr/local install-symlinks
+
 
 Issues of note:
 
diff --git a/Makefile b/Makefile
index 73b487f..87b317f 100644
--- a/Makefile
+++ b/Makefile
@@ -142,6 +142,7 @@ ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
 prefix = $(HOME)
+symlinkprefix = /usr/local
 bindir = $(prefix)/bin
 gitexecdir = $(bindir)
 sharedir = $(prefix)/share
@@ -692,6 +693,7 @@ bindir_SQ = $(subst ','\'',$(bindir))
 gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
 template_dir_SQ = $(subst ','\'',$(template_dir))
 prefix_SQ = $(subst ','\'',$(prefix))
+symlinkprefix_SQ = $(subst ','\'',$(symlinkprefix))
 
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
@@ -996,7 +998,13 @@ install-doc:
 quick-install-doc:
 	$(MAKE) -C Documentation quick-install
 
-
+# The somewhat strange looking lines start with an ignored $(MAKE) in
+# order to be executed also in make -n calls.
+install-symlinks:
+	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && find . -type d ! \( -iname 'git*' -prune \) -exec echo $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
+	@cd '$(prefix_SQ)' && find . -type d ! \( -iname 'git*' -prune \) -exec $(INSTALL) -m 755 -d '$(symlinkprefix_SQ)/{}' \;
+	@: $(MAKE) && echo cd '$(prefix_SQ)' && cd '$(prefix_SQ)' && find . \( -type d -iname 'git*' -prune -o ! -type d \) -exec echo $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec echo ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
+	@cd '$(prefix_SQ)' && find . \( -type d -iname 'git*' -prune -o ! -type d \) -exec $(RM) -r '$(symlinkprefix_SQ)/{}' \; -exec ln -s '$(prefix_SQ)/{}' '$(symlinkprefix_SQ)/{}' \;
 
 ### Maintainer's dist rules
 
-- 
1.5.3.rc2.84.g6497

^ permalink raw reply related

* [PATCH] Show an error and exit if started in a directory where no .git could be found
From: Alex Riesen @ 2007-07-29 20:29 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git

This is to help people starting gitk from graphical file managers where
the stderr output is hidden.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
 gitk |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/gitk b/gitk
index fc7cc8c..f5949a2 100755
--- a/gitk
+++ b/gitk
@@ -7575,7 +7575,10 @@ catch {source ~/.gitk}
 font create optionfont -family sans-serif -size -12
 
 # check that we can find a .git directory somewhere...
-set gitdir [gitdir]
+if {[ catch { set gitdir [gitdir] } ]} {
+    show_error {} . "Cannot find a git repository here."
+    exit 1
+}
 if {![file isdirectory $gitdir]} {
     show_error {} . "Cannot find the git directory \"$gitdir\"."
     exit 1
-- 
1.5.3.rc3.48.g5b618

^ permalink raw reply related

* [PATCH] Allow gitk to continue and show error message in new repos
From: Alex Riesen @ 2007-07-29 20:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git

If there is no commit made yet, gitk just dumps a Tcl error on stderr,
which sometimes is hard to see. Noticed when gitk was run from Xfce
file manager (thunar's custom action).

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
 gitk |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/gitk b/gitk
index f74ce51..fc7cc8c 100755
--- a/gitk
+++ b/gitk
@@ -427,7 +427,7 @@ proc readrefs {} {
 	    lappend idotherrefs($id) $name
 	}
     }
-    close $refd
+    catch { close $refd }
     set mainhead {}
     set mainheadid {}
     catch {
-- 
1.5.3.rc3.48.g5b618

^ permalink raw reply related

* Re: [PATCH 3/8] Clean up work-tree handling
From: Johannes Schindelin @ 2007-07-29 20:02 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, matled
In-Reply-To: <7vodhvm1dg.fsf@assigned-by-dhcp.cox.net>

Hi,

On Sun, 29 Jul 2007, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > I still have a problem with what should happen if both "core.bare == true" 
> > and "core.worktree = /some/where/over/the/rainbow".  Should it be bare, or 
> > should it have a working tree?
> 
> They sound contradicting with each other to me.  Isn't that a
> clear configuration error?

Yes.  But why not play nice?

Okay, the real reason I do not want to catch this error is because it 
complicates my code.

But really, why not say "worktree takes precedence"?

BTW I realised that callers of setup_git_directory_gently() might forget 
the check for the repository format version...

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 3/8] Clean up work-tree handling
From: Junio C Hamano @ 2007-07-29 19:54 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, matled
In-Reply-To: <Pine.LNX.4.64.0707291645580.14781@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> I still have a problem with what should happen if both "core.bare == true" 
> and "core.worktree = /some/where/over/the/rainbow".  Should it be bare, or 
> should it have a working tree?

They sound contradicting with each other to me.  Isn't that a
clear configuration error?

^ permalink raw reply

* Re: [PATCH 1/3] log_ref_write() -- do not chomp reflog message at the first LF
From: Johannes Schindelin @ 2007-07-29 19:02 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Sean, Benoit SIGOURE, git
In-Reply-To: <7vsl77m4i1.fsf@assigned-by-dhcp.cox.net>

Hi,

On Sun, 29 Jul 2007, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > It is not like the reflog messages have to be very verbose; they only have 
> > to give a hint what the commit was about, and the commit name is the 
> > important information.
> 
> I've considered it, but decided against it because:
> 
>  (1) I did not like the information lossage;
> 
>  (2) this is solely to help log messages coming from outside the
>      recommended convention, and having excess will not hurt the
>      normal usage;
> 
>  (3) it is not known if messages from outside the recommended
>      convention have enough information on its first line of the
>      first paragraph; the result of s/\n.*/.../ may not be
>      sufficient "hint";

Good catch.  Didn't think of that.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 1/3] log_ref_write() -- do not chomp reflog message at the first LF
From: Junio C Hamano @ 2007-07-29 18:47 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Sean, Benoit SIGOURE, git
In-Reply-To: <Pine.LNX.4.64.0707291248560.14781@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> It is not like the reflog messages have to be very verbose; they only have 
> to give a hint what the commit was about, and the commit name is the 
> important information.

I've considered it, but decided against it because:

 (1) I did not like the information lossage;

 (2) this is solely to help log messages coming from outside the
     recommended convention, and having excess will not hurt the
     normal usage;

 (3) it is not known if messages from outside the recommended
     convention have enough information on its first line of the
     first paragraph; the result of s/\n.*/.../ may not be
     sufficient "hint";

 (4) log output are by default piped to "less -S" so extra
     output gives the user chance to inspect more if he chosses
     to, without hurting the end user display; and

 (5) the code was simpler and less error prone to go wrong.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox