threads / patch / 11835

patchAdd platform-independent .git "symlink"

Subject: [PATCH] Add platform-independent .git "symlink"

## tl;dr

29 messages between Feb 2, 2008 and Feb 5, 2008. Diffs are folded; open one to read it.

replies: 28people: 5as markdown or json

Lars Hjemli· Feb 2, 2008, 10:36 UTC · lore

This patch allows .git to be a regular textfile containing the path of the real git directory (formatted like "GITDIR: <path>\n"), which is useful on platforms lacking support for real symlinks.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---

All tests pass, but git-submodule needs to be updated to handle this feature. Incidentally, git-submodule might also be the first command wanting to use this feature; it probably should clone submodules into a bare repository in GIT_DIR/submodules/<modulename> of the containing repository to prevent dataloss during submodule update etc.

 setup.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
Show changes to setup.c +38 −0
diff --git a/setup.c b/setup.c
index adede16..87d6115 100644
--- a/setup.c
+++ b/setup.c
@@ -239,6 +239,38 @@ static int check_repository_format_gently(int *nongit_ok)
 }
 
 /*
+ * Try to read the location of the git directory from the .git file,
+ * return path to git directory if found.
+ * Format of the .git file is
+ *    GITDIR: <path>\n
+ */
+static const char *read_gitfile_gently(const char *path)
+{
+	static char buf[PATH_MAX + 10];  /* "GITDIR: " + "\n" + "\0" */
+	struct stat st;
+	FILE *f;
+	size_t len;
+
+	if (stat(path, &st))
+		return NULL;
+	if (!S_ISREG(st.st_mode) || st.st_size > PATH_MAX + 9)
+		return NULL;
+	f = fopen(path, "r");
+	if (!f)
+		return NULL;
+	len = fread(buf, 1, st.st_size, f);
+	fclose(f);
+	if (len != st.st_size)
+		return NULL;
+	if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
+		return NULL;
+	buf[len - 1] = '\0';
+	if (!is_git_directory(buf + 8))
+		return NULL;
+	return buf + 8;
+}
+
+/*
  * 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.
  */
@@ -247,6 +279,7 @@ 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];
 	const char *gitdirenv;
+	const char *gitfile_dir;
 	int len, offset;
 
 	/*
@@ -302,6 +335,11 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	 */
 	offset = len = strlen(cwd);
 	for (;;) {
+		gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
+		if (gitfile_dir) {
+			setenv(GIT_DIR_ENVIRONMENT, gitfile_dir, 1);
+			break;
+		}
 		if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
 			break;
 		if (is_git_directory(".")) {
-- 
1.5.4.GIT-dirty
Lars Hjemli· Feb 2, 2008, 15:02 UTC · re: Lars Hjemli · lore

[PATCH] Add tests for .git file

Verify that the basic plumbing works when .git is a file pointing at the real git directory.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 t/t0002-gitfile.sh |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)
 create mode 100755 t/t0002-gitfile.sh
Show changes to t/t0002-gitfile.sh +71 −0
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
new file mode 100755
index 0000000..55276c6
--- /dev/null
+++ b/t/t0002-gitfile.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='.git file
+
+Verify that plumbing commands work when .git is a file
+'
+. ./test-lib.sh
+
+chkfile() {
+	D=$(echo $1 | cut -b 1-2) &&
+	F=$(echo $1 | cut -b 3-40) &&
+	if test ! -f $REAL/objects/$D/$F
+	then
+		echo "Object not found: $REAL/objects/$D/$F"
+		false
+	fi
+}
+
+test_expect_success 'setup' '
+	REAL=$(pwd)/.real &&
+	mv .git $REAL &&
+	echo "GITDIR: $REAL" >.git
+'
+
+test_expect_success 'check rev-parse --git-dir' '
+	test "$REAL" = "$(git rev-parse --git-dir)"
+'
+
+test_expect_success 'check hash-object' '
+	echo "foo" >bar &&
+	SHA=$(cat bar | git hash-object -w --stdin) &&
+	chkfile $SHA
+'
+
+test_expect_success 'check cat-file' '
+	git cat-file blob $SHA >actual &&
+	diff -u bar actual
+'
+
+test_expect_success 'check update-index' '
+	if test -f $REAL/index
+	then
+		echo "Hmm, $REAL/index exists?"
+		false
+	fi &&
+	rm -rf $REAL/objects/* &&
+	git update-index --add bar &&
+	if ! test -f $REAL/index
+	then
+		echo "$REAL/index not found"
+		false
+	fi &&
+	chkfile $SHA
+'
+
+test_expect_success 'check write-tree' '
+	SHA=$(git write-tree) &&
+	chkfile $SHA
+'
+
+test_expect_success 'check commit-tree' '
+	SHA=$(echo "commit bar" | git commit-tree $SHA) &&
+	chkfile $SHA
+'
+
+test_expect_success 'check rev-list' '
+	echo $SHA >$REAL/HEAD &&
+	test "$SHA" = "$(git rev-list HEAD)"
+'
+
+test_done
-- 
1.5.4.GIT-dirty
Johannes Schindelin· Feb 2, 2008, 15:56 UTC · re: Lars Hjemli · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Sat, 2 Feb 2008, Lars Hjemli wrote:
> This patch allows .git to be a regular textfile containing the path of 
> the real git directory (formatted like "GITDIR: <path>\n"), which is 
> useful on platforms lacking support for real symlinks.
Wow, that looks easier than I thought...
> +static const char *read_gitfile_gently(const char *path)
> +{
> +	static char buf[PATH_MAX + 10];  /* "GITDIR: " + "\n" + "\0" */

Why say "GITDIR:"? Do you want to be able to set other things there, too, like GITWORKDIR?

Show 7 quoted lines
> +	struct stat st;
> +	FILE *f;
> +	size_t len;
> +
> +	if (stat(path, &st))
> +		return NULL;
> +	if (!S_ISREG(st.st_mode) || st.st_size > PATH_MAX + 9)

Why make it complicated? You could just test for st.st_size >= sizeof(buf).

Show 8 quoted lines
> +		return NULL;
> +	f = fopen(path, "r");
> +	if (!f)
> +		return NULL;
> +	len = fread(buf, 1, st.st_size, f);
> +	fclose(f);
> +	if (len != st.st_size)
> +		return NULL;
Should this not rather use read_in_full()?
Show 7 quoted lines
> +	if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
> +		return NULL;
> +	buf[len - 1] = '\0';
> +	if (!is_git_directory(buf + 8))
> +		return NULL;
> +	return buf + 8;
> +}
Should this not make the git directory absolute, just in case?

Thanks, Dscho

Lars Hjemli· Feb 2, 2008, 17:59 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

On Feb 2, 2008 4:56 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 8 quoted lines
> On Sat, 2 Feb 2008, Lars Hjemli wrote:
>
> > +static const char *read_gitfile_gently(const char *path)
> > +{
> > +     static char buf[PATH_MAX + 10];  /* "GITDIR: " + "\n" + "\0" */
>
> Why say "GITDIR:"?  Do you want to be able to set other things there, too,
> like GITWORKDIR?

Not ATM, but it might become useful to specify some other bits of configuration in this file (especially if one uses multiple workdirs).

Your other comments also made perfect sense so I'll send a reworked patch.

-- larsh

Lars Hjemli· Feb 2, 2008, 18:09 UTC · re: Lars Hjemli · lore

This patch allows .git to be a regular textfile containing the path of the real git directory (formatted like "GITDIR: <path>\n"), which is useful on platforms lacking support for real symlinks.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 setup.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
Show changes to setup.c +38 −0
diff --git a/setup.c b/setup.c
index adede16..45a78c4 100644
--- a/setup.c
+++ b/setup.c
@@ -239,6 +239,38 @@ static int check_repository_format_gently(int *nongit_ok)
 }
 
 /*
+ * Try to read the location of the git directory from the .git file,
+ * return path to git directory if found.
+ * Format of the .git file is
+ *    GITDIR: <path>\n
+ */
+static const char *read_gitfile_gently(const char *path)
+{
+	static char buf[PATH_MAX + 10];  /* "GITDIR: " + "\n" + "\0" */
+	struct stat st;
+	int fd;
+	size_t len;
+
+	if (stat(path, &st))
+		return NULL;
+	if (!S_ISREG(st.st_mode) || st.st_size >= sizeof(buf))
+		return NULL;
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+	len = read_in_full(fd, buf, sizeof(buf));
+	close(fd);
+	if (len != st.st_size)
+		return NULL;
+	if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
+		return NULL;
+	buf[len - 1] = '\0';
+	if (!is_git_directory(buf + 8))
+		return NULL;
+	return make_absolute_path(buf + 8);
+}
+
+/*
  * 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.
  */
@@ -247,6 +279,7 @@ 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];
 	const char *gitdirenv;
+	const char *gitfile_dir;
 	int len, offset;
 
 	/*
@@ -302,6 +335,11 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	 */
 	offset = len = strlen(cwd);
 	for (;;) {
+		gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
+		if (gitfile_dir) {
+			setenv(GIT_DIR_ENVIRONMENT, gitfile_dir, 1);
+			break;
+		}
 		if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
 			break;
 		if (is_git_directory(".")) {
-- 
1.5.4.4.gd2e29
Johannes Schindelin· Feb 2, 2008, 18:19 UTC · re: Lars Hjemli · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Sat, 2 Feb 2008, Lars Hjemli wrote:
> +	if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
Sorry, missed that earlier: How about
	if (!len || buf[len-1] != '\n' || prefixcmp(buf, "GITDIR: "))

instead? (buf does not need be NUL terminated for the prefixcmp(), since we just made sure it is LF terminated)

Thanks, Dscho

Johannes Schindelin· Feb 2, 2008, 18:34 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,

BTW just to tell you why I am so excited with your patch: I have a patch to git-branch in my tree, which implements the git-new-workdir functionality (it's a patch to git-branch, not git-checkout, mainly because git-checkout is no builtin yet).

Now, git-new-workdir works by having symlinks _in_ .git/, but not for everything. .git/HEAD is specific to the workdir, of course.

But your patch made me realise that this is the wrong way to go about it. Sure, you do not need to change core git, and can use a script to make the new working directory. But there is no lock preventing the same ref being checked out twice.

Howver, having .git a file pointing to another git directory allows you to have locks there. And they can be actually pretty sensible locks, like

	.git/HEAD.<mangled-path>

actually containing the symbolic ref describing which branch we're on in that working directory. Likewise, .git/index.<mangled-path> needs to hold the current index.

Of course, for this to work, you need to use different HEADs and indexes only if .git was a file originally.

BTW <mangled-path> could be a hash of the path, and for convenience, we could store the path in .git/workdir.<mangled-path>.

Food for thought.

Ciao, Dscho

Shawn O. Pearce· Feb 4, 2008, 01:57 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 14 quoted lines
> Howver, having .git a file pointing to another git directory allows you to 
> have locks there.  And they can be actually pretty sensible locks, like
> 
> 	.git/HEAD.<mangled-path>
> 
> actually containing the symbolic ref describing which branch we're on in 
> that working directory.  Likewise, .git/index.<mangled-path> needs to hold 
> the current index.
> 
> Of course, for this to work, you need to use different HEADs and indexes 
> only if .git was a file originally.
> 
> BTW <mangled-path> could be a hash of the path, and for convenience, we 
> could store the path in .git/workdir.<mangled-path>.

This I like. Because my day-job coworkers and I make very heavy use of git-new-workdir to manage our compile areas/working directories. :)

The biggest problem with new-workdir is the master repository cannot see the HEAD, index or logs/HEAD of the working directories. Consequently it is possible for prune (or repack -a -d) to remove objects that some workdir is still referring to. Its not uncommon for my HEAD reflogs to have stale commits in them. Every once in a while a user looses their HEAD entirely when it gets pruned away, as they had a workdir checked out on a detached HEAD.

The second biggest problem is checking out the same branch in two different directories at once. This becomes a problem only if you modify the branch, but still, its a problem.

I was thinking that we could add a WORKDIR_HASH to the .git file Lars was proposing. This hash would be the <mangled-path> suffix you are talking about above, and would avoid the need to compute the absolute path for the working directory every time we run a Git command.

The hash could be something simple, like the SHA-1 hash of the absolute path at the time of workdir creation. But it would be nice if we could recommend a specific value during workdir creation, so that the WORKDIR_HASH could start with a value that matches something the user would readily recognize.

-- 
Shawn.
Junio C Hamano· Feb 4, 2008, 03:05 UTC · re: Shawn O. Pearce · lore

Re: [PATCH] Add platform-independent .git "symlink"

"Shawn O. Pearce" <spearce@spearce.org> writes:
> The second biggest problem is checking out the same branch in two
> different directories at once.  This becomes a problem only if you
> modify the branch, but still, its a problem.

I agree. The biggest benefit I am getting out of the workdir layout is that it allows me to check out the same branch in two directories, and let me work further on one while the other one is compiling and running the testsuite. The other "compile and test tree" needs to be reset with --hard once I commit in the "edit tree", but by definition "reset --hard" is always a safe operation in a "compile and test tree".

In short, you need to know what you are doing.
Johannes Schindelin· Feb 4, 2008, 14:34 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Sun, 3 Feb 2008, Junio C Hamano wrote:
Show 14 quoted lines
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> 
> > The second biggest problem is checking out the same branch in two 
> > different directories at once.  This becomes a problem only if you 
> > modify the branch, but still, its a problem.
> 
> I agree.  The biggest benefit I am getting out of the workdir layout is 
> that it allows me to check out the same branch in two directories, and 
> let me work further on one while the other one is compiling and running 
> the testsuite.  The other "compile and test tree" needs to be reset with 
> --hard once I commit in the "edit tree", but by definition "reset 
> --hard" is always a safe operation in a "compile and test tree".
> 
> In short, you need to know what you are doing.
But that's exactly what you can use throw-away branches for.  I do.

Ciao, Dscho

Brandon Casey· Feb 4, 2008, 21:17 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin wrote:
Show 6 quoted lines
> Hi,
> 
> BTW just to tell you why I am so excited with your patch: I have a patch 
> to git-branch in my tree, which implements the git-new-workdir 
> functionality (it's a patch to git-branch, not git-checkout, mainly 
> because git-checkout is no builtin yet).
Are you planning something that works like:
  $ cd <my_repo>
  $ git branch
    * master
      other_branch
  $ git checkout --new-workdir ../<other_work_dir> other_branch
(not sure how it would work using git-branch).
Have you thought about using git-clone instead?

It seems a good fit but would require a new option to specify a branch to checkout (which I believe is a requested feature for clone). --shared seems like a good option name*, too bad it's already taken. But how about --conjoined to communicate that the new repo and the original repo are "attached at the hip"?

  $ git clone --conjoined -b other_branch <my_repo> <other_work_dir>
-brandon
* I really do think "shared" is the most appropriate since _both_
  repos would be sharing, rather than the current meaning or shared which
  is just a short-hand for --reference and in which the original repo gets
  nothing from the selfish "sharer".
Johannes Schindelin· Feb 4, 2008, 21:31 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Brandon Casey wrote:
Show 16 quoted lines
> Johannes Schindelin wrote:
> 
> > BTW just to tell you why I am so excited with your patch: I have a 
> > patch to git-branch in my tree, which implements the git-new-workdir 
> > functionality (it's a patch to git-branch, not git-checkout, mainly 
> > because git-checkout is no builtin yet).
> 
> Are you planning something that works like:
> 
>   $ cd <my_repo>
>   $ git branch
>     * master
>       other_branch
>   $ git checkout --new-workdir ../<other_work_dir> other_branch
> 
> (not sure how it would work using git-branch).

Something like this, yes. In my local version of git, you can say "git branch --new-workdir=../bla new-branch [branch-point]".

> Have you thought about using git-clone instead?

Briefly. But this is not about cloning the repository. It is about having an additional working directory for the current repository.

> It seems a good fit but would require a new option to specify a branch 
> to checkout (which I believe is a requested feature for clone).

It is an often-requested feature for clone, but we have "clone -n" for now, and nobody seemed to care deeply enough to actually do something about it.

But really, clone is something different. I _want_ the original repository to know that there is another working directory.

Ciao, Dscho

Brandon Casey· Feb 4, 2008, 22:08 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin wrote:
> Hi,
> 
> On Mon, 4 Feb 2008, Brandon Casey wrote:
> In my local version of git, you can say "git 
> branch --new-workdir=../bla new-branch [branch-point]".
Ah, I see, you are creating a new branch too.
>> Have you thought about using git-clone instead?
> 
> Briefly.  But this is not about cloning the repository.  It is about 
> having an additional working directory for the current repository.

I think that is true at the low level, but from a high level it feels similar to me.

After your "git branch --new-workdir=..." you have something that acts exactly like a full-fledged repository. It is very much dependent on the original repo, similarly to how a --shared repo is, and it now has new semantics in that operations within the new repo have an effect in the original repo (and vice-versa). Making new repositories from existing repositories is what git-clone does.

  git-branch: makes new branches, or generally handles modifying branches.
git-checkout: modifies the contents of the working directory.
   git-clone: makes new repositories from existing repositories.

Also, of the three, git-clone is the only one allowed to operate outside of the repo. The other two are required to be called from within a repo (or have GIT_DIR set), and currently only modify data within that repo. So, allowing them to have an effect outside of the repo would extend their current scope of operation.

Show 6 quoted lines
>> It seems a good fit but would require a new option to specify a branch 
>> to checkout (which I believe is a requested feature for clone).
> 
> It is an often-requested feature for clone, but we have "clone -n" for 
> now, and nobody seemed to care deeply enough to actually do something 
> about it.
I'll probably do it if it is not beyond me.
> I _want_ the original 
> repository to know that there is another working directory.

Yes, your ideas are much better than simply adding the functionality of the git-new-workdir script (which is what I was planning on doing btw :)

-brandon
Johannes Schindelin· Feb 4, 2008, 22:19 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Brandon Casey wrote:
Show 19 quoted lines
> Johannes Schindelin wrote:
> > 
> > On Mon, 4 Feb 2008, Brandon Casey wrote:
> 
> >> Have you thought about using git-clone instead?
> > 
> > Briefly.  But this is not about cloning the repository.  It is about 
> > having an additional working directory for the current repository.
> 
> I think that is true at the low level, but from a high level it feels 
> similar to me.
> 
> [...]
> 
> > I _want_ the original repository to know that there is another working 
> > directory.
> 
> Yes, your ideas are much better than simply adding the functionality of 
> the git-new-workdir script (which is what I was planning on doing btw :)

Somehow these two statements do not work together. Either you have a clone, or you accept that a new working directory is actually working on the _same_ repository.

Ciao, Dscho

Brandon Casey· Feb 4, 2008, 22:44 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin wrote:
Show 22 quoted lines
> Hi,
> 
> On Mon, 4 Feb 2008, Brandon Casey wrote:
> 
>> Johannes Schindelin wrote:
>>> On Mon, 4 Feb 2008, Brandon Casey wrote:
>>>> Have you thought about using git-clone instead?
>>> Briefly.  But this is not about cloning the repository.  It is about 
>>> having an additional working directory for the current repository.
>> I think that is true at the low level, but from a high level it feels 
>> similar to me.
>>
>> [...]
>>
>>> I _want_ the original repository to know that there is another working 
>>> directory.
>> Yes, your ideas are much better than simply adding the functionality of 
>> the git-new-workdir script (which is what I was planning on doing btw :)
> 
> Somehow these two statements do not work together.  Either you have a 
> clone, or you accept that a new working directory is actually working on 
> the _same_ repository.

When we talk about clones we are not always talking about a strict "full" clone. We have at least:

	1) Full clone repository (with/without hardlinks, each is completely
	   independent)
	2) --shared/--reference (dependent on original repo, fragile)
	3) shallow repository (mostly independent)

If your statement above is rephrased to "I _want_ the original repository to know that it has conjoined siblings.", then we have a new repository type:

	4) conjoined repository (it has multiple sibling repositories each
	   with their own working directory, but they all share and modify the
	   same .git directory)
-brandon
Brandon Casey· Feb 4, 2008, 22:56 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Brandon Casey wrote:
> Johannes Schindelin wrote:
Show 6 quoted lines
> If your statement above is rephrased to "I _want_ the original repository to
> know that it has conjoined siblings.", then we have a new repository type:
> 
> 	4) conjoined repository (it has multiple sibling repositories each
> 	   with their own working directory, but they all share and modify the
> 	   same .git directory)

By the way, none of the repositories has to "own" the .git directory. This is made much easier by Lars's new changes. All of the repos could contain a .git symlink file which points to some other directory.

I'm not saying this would be the common case, just with the .git directory not residing within _any_ of the repositories/work-dirs it really blurs any difference between them. They would all be equals, even though some may have been created _from_ the others. (if that makes sense)

-brandon
Johannes Schindelin· Feb 5, 2008, 00:51 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Brandon Casey wrote:
> By the way, none of the repositories has to "own" the .git directory. 
> This is made much easier by Lars's new changes. All of the repos could 
> contain a .git symlink file which points to some other directory.

First, the repository _is_ the .git directory. Second, we already had GIT_DIR and --git-dir, which made it as easy...

Ciao,
Dscho
 
Johannes Schindelin· Feb 5, 2008, 00:49 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Brandon Casey wrote:
> When we talk about clones we are not always talking about a strict 
> "full" clone.

Here, sir, we disagree. I tend to like the fact that a clone is a clone is a clone. Which BTW is the reason why I do not like requests to "clone" only one branch: this is not a clone.

Show 7 quoted lines
> If your statement above is rephrased to "I _want_ the original 
> repository to know that it has conjoined siblings.", then we have a new 
> repository type:
> 
> 	4) conjoined repository (it has multiple sibling repositories each
> 	   with their own working directory, but they all share and modify the
> 	   same .git directory)

No. The repository does not even need a working directory (in which case we call it "bare"). Up until now, it _can_ have _one_ working directory. With my plans, it can have more than one.

Ciao, Dscho

Brandon Casey· Feb 5, 2008, 02:42 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin wrote:
Show 10 quoted lines
> Hi,
> 
> On Mon, 4 Feb 2008, Brandon Casey wrote:
> 
>> When we talk about clones we are not always talking about a strict 
>> "full" clone.
> 
> Here, sir, we disagree.  I tend to like the fact that a clone is a clone 
> is a clone.  Which BTW is the reason why I do not like requests to "clone" 
> only one branch: this is not a clone.

It seems the git-clone utility has been extended to create more than just clones in that case.

My use of the term "clone" with respect to git, is to refer to the product of the git-clone utility. With that in mind, git-clone produces all of the repo/work-dir combinations I described.

The strict (or precise) definition of "clone" seems like a subset of the more generic "create new repository/workdir from existing repository". The different options then allow you to control how the new repo/workdir is structured.

We don't currently have a generic "create new repository/workdir from existing repository" command. So people have been using git-clone to create new repository/workdir's and calling the result clones, even though they could have produced the same result by running some sequence of mkdir, git init, and git pull.

Show 10 quoted lines
>> If your statement above is rephrased to "I _want_ the original 
>> repository to know that it has conjoined siblings.", then we have a new 
>> repository type:
>>
>> 	4) conjoined repository (it has multiple sibling repositories each
>> 	   with their own working directory, but they all share and modify the
>> 	   same .git directory)
> 
> No.  The repository does not even need a working directory (in which case 
> we call it "bare").

The additional term "bare" that is used with such a repository without a working directory implies to me that this is a "special" or "uncommon" repository configuration.

I think in many places in the documentation and it seems in common use on the mailing list, the contents of the directory created by git-clone is informally referred to as the repository. This is even though most people understand that the precise definition of repository is the .git directory and the rest of the contents are the working directory.

So I hope you excuse me for referring to the result of git-clone as a repository. I'll try to think of something else to call it (above I used repo/workdir).

None of that changes my opinion that a descent model for the user interface is to have two high-level commands that create repo/workdir's.

     git-init: creates a new repo/workdir from scratch.
    git-clone: creates a new repo/workdir from an existing repository.

Or the opinion that git-clone is a closer operation to creating a new working directory and associating it with a repository than either git-branch or git-checkout, which in normal usage (i.e. _not_ setting GIT_DIR or using --git-dir) operate within a working directory.

With that, I think I have described my thinking well enough, so I won't continue any more unless you really ask a question.

>  Up until now, it _can_ have _one_ working directory.  
> With my plans, it can have more than one.

I'm looking forward to your plans, since I find the git-new-workdir script very useful.

-brandon
Johannes Schindelin· Feb 5, 2008, 12:57 UTC · re: Brandon Casey · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Brandon Casey wrote:
Show 18 quoted lines
> Johannes Schindelin wrote:
> 
> > On Mon, 4 Feb 2008, Brandon Casey wrote:
> > 
> >> If your statement above is rephrased to "I _want_ the original 
> >> repository to know that it has conjoined siblings.", then we have a 
> >> new repository type:
> >>
> >> 	4) conjoined repository (it has multiple sibling repositories each
> >> 	   with their own working directory, but they all share and modify the
> >> 	   same .git directory)
> > 
> > No.  The repository does not even need a working directory (in which case 
> > we call it "bare").
> 
> The additional term "bare" that is used with such a repository without a 
> working directory implies to me that this is a "special" or "uncommon" 
> repository configuration.

By the same reasoning, a "good day" would be a "special" or "uncommon" day.

> So I hope you excuse me for referring to the result of git-clone as a 
> repository. I'll try to think of something else to call it (above I used 
> repo/workdir).

But that's what I am saying: a git-clone clones a repository. If you happen to clone without the "--bare" option, it will additionally create a working directory.

Hth, Dscho

Lars Hjemli· Feb 2, 2008, 18:47 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

On Feb 2, 2008 7:19 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 12 quoted lines
> Hi,
>
> On Sat, 2 Feb 2008, Lars Hjemli wrote:
>
> > +     if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
>
> Sorry, missed that earlier: How about
>
>         if (!len || buf[len-1] != '\n' || prefixcmp(buf, "GITDIR: "))
>
> instead?  (buf does not need be NUL terminated for the prefixcmp(), since
> we just made sure it is LF terminated)
That's true, although it feels a bit too clever for me ;-)
Maybe this as a compromise?
	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
...
	if (!len || buf[len - 1] != '\n')
		return NULL;
	buf[len - 1] = '\0';
	if (prefixcmp(buf, "GITDIR: "))
		return NULL;

-- larsh

Johannes Schindelin· Feb 3, 2008, 01:55 UTC · re: Lars Hjemli · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Sat, 2 Feb 2008, Lars Hjemli wrote:
Show 14 quoted lines
> On Feb 2, 2008 7:19 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > On Sat, 2 Feb 2008, Lars Hjemli wrote:
> >
> > > +     if (len < 10 || buf[len - 1] != '\n' || strncmp(buf, "GITDIR: ", 8))
> >
> > Sorry, missed that earlier: How about
> >
> >         if (!len || buf[len-1] != '\n' || prefixcmp(buf, "GITDIR: "))
> >
> > instead?  (buf does not need be NUL terminated for the prefixcmp(), since
> > we just made sure it is LF terminated)
> 
> That's true, although it feels a bit too clever for me ;-)
:-)
Show 9 quoted lines
> Maybe this as a compromise?
> 
> 	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
> ...
> 	if (!len || buf[len - 1] != '\n')
> 		return NULL;
> 	buf[len - 1] = '\0';
> 	if (prefixcmp(buf, "GITDIR: "))
> 		return NULL;
Sure!

Thanks, Dscho

Junio C Hamano· Feb 4, 2008, 00:07 UTC · re: Lars Hjemli · lore

Re: [PATCH] Add platform-independent .git "symlink"

"Lars Hjemli" <hjemli@gmail.com> writes:
Show 9 quoted lines
> Maybe this as a compromise?
>
> 	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
> ...
> 	if (!len || buf[len - 1] != '\n')
> 		return NULL;
> 	buf[len - 1] = '\0';
> 	if (prefixcmp(buf, "GITDIR: "))
> 		return NULL;
Perhaps that is easier to read.

For now I haven't picked up any of the "how about this way" revisions.

Johannes Schindelin· Feb 4, 2008, 00:24 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Sun, 3 Feb 2008, Junio C Hamano wrote:
Show 16 quoted lines
> "Lars Hjemli" <hjemli@gmail.com> writes:
> 
> > Maybe this as a compromise?
> >
> > 	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
> > ...
> > 	if (!len || buf[len - 1] != '\n')
> > 		return NULL;
> > 	buf[len - 1] = '\0';
> > 	if (prefixcmp(buf, "GITDIR: "))
> > 		return NULL;
> 
> Perhaps that is easier to read.
> 
> For now I haven't picked up any of the "how about this way"
> revisions.

Yeah, I think all my comments have been addressed... Lars, care to send a new version?

Thanks, Dscho

Shawn O. Pearce· Feb 4, 2008, 01:35 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 21 quoted lines
> On Sun, 3 Feb 2008, Junio C Hamano wrote:
> 
> > "Lars Hjemli" <hjemli@gmail.com> writes:
> > 
> > > Maybe this as a compromise?
> > >
> > > 	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
> > > ...
> > > 	if (!len || buf[len - 1] != '\n')
> > > 		return NULL;
> > > 	buf[len - 1] = '\0';
> > > 	if (prefixcmp(buf, "GITDIR: "))
> > > 		return NULL;
> > 
> > Perhaps that is easier to read.
> > 
> > For now I haven't picked up any of the "how about this way"
> > revisions.
> 
> Yeah, I think all my comments have been addressed...  Lars, care to send a 
> new version?

I would suggest a slightly different name, "GIT_DIR: ", as the line prefix, because the environment variable is also GIT_DIR.

But that's just me.
-- 
Shawn.
Junio C Hamano· Feb 4, 2008, 01:45 UTC · re: Shawn O. Pearce · lore

Re: [PATCH] Add platform-independent .git "symlink"

"Shawn O. Pearce" <spearce@spearce.org> writes:
Show 27 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>> On Sun, 3 Feb 2008, Junio C Hamano wrote:
>> 
>> > "Lars Hjemli" <hjemli@gmail.com> writes:
>> > 
>> > > Maybe this as a compromise?
>> > >
>> > > 	static char buf[PATH_MAX + 9];  /* "GITDIR: " + "\n"  */
>> > > ...
>> > > 	if (!len || buf[len - 1] != '\n')
>> > > 		return NULL;
>> > > 	buf[len - 1] = '\0';
>> > > 	if (prefixcmp(buf, "GITDIR: "))
>> > > 		return NULL;
>> > 
>> > Perhaps that is easier to read.
>> > 
>> > For now I haven't picked up any of the "how about this way"
>> > revisions.
>> 
>> Yeah, I think all my comments have been addressed...  Lars, care to send a 
>> new version?
>
> I would suggest a slightly different name, "GIT_DIR: ", as the
> line prefix, because the environment variable is also GIT_DIR.
>
> But that's just me.

I think that was modelled after symref HEAD that would point at the real ref with "ref: refs/heads/master", as if you have a symlink whose value is "refs/heads/master". So reusing "ref: " might be Ok, and saying "directory: " or "gitdir: " would be also Ok.

If we would want to reuse the mechanism in the future to allow symlink challenged systems to use it in contrib/workdir/, we may want to keep the name a bit more generic than "gitdir: ".

Shawn O. Pearce· Feb 4, 2008, 02:00 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add platform-independent .git "symlink"

Junio C Hamano <gitster@pobox.com> wrote:
Show 16 quoted lines
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> >
> > I would suggest a slightly different name, "GIT_DIR: ", as the
> > line prefix, because the environment variable is also GIT_DIR.
> >
> > But that's just me.
> 
> I think that was modelled after symref HEAD that would point at
> the real ref with "ref: refs/heads/master", as if you have a
> symlink whose value is "refs/heads/master".  So reusing "ref: "
> might be Ok, and saying "directory: " or "gitdir: " would be
> also Ok.
> 
> If we would want to reuse the mechanism in the future to allow
> symlink challenged systems to use it in contrib/workdir/, we may
> want to keep the name a bit more generic than "gitdir: ".

I could easily get behind "gitdir: " or "directory: ". Both are all lowercase, and thus look a lot like "ref: ", which already has been in heavy use for quite some time.

But "GITDIR: " isn't very close to GIT_DIR (its environment based sister) or "ref: " (its file based very-distant cousin).

As a bike-shed painter I like to keep colors matching when possible.
:-)
-- 
Shawn.
Lars Hjemli· Feb 4, 2008, 11:59 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add platform-independent .git "symlink"

On Feb 4, 2008 1:24 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 6 quoted lines
> On Sun, 3 Feb 2008, Junio C Hamano wrote:
> > For now I haven't picked up any of the "how about this way"
> > revisions.
>
> Yeah, I think all my comments have been addressed...  Lars, care to send a
> new version?

Sure, but we should come to a conclusion on "GITDIR" vs. "GIT_DIR" vs. "gitdir" vs. "directory" vs. "ref". The reason I used "GITDIR" was to keep the door open for additional parameters in the "gitfile" (but it should obviously have been "GIT_DIR" for that usage since its value is used to specify $GIT_DIR). If it's more likely that we'll use this as a general substitute for symlinks, I think "ref" is better due to the existing symbolic refs.

My preference would be "GIT_DIR" (or "git_dir") since we also might want the "WORKDIR_HASH" Shawn mentioned.

-- 
larsh
Johannes Schindelin· Feb 4, 2008, 14:36 UTC · re: Lars Hjemli · lore

Re: [PATCH] Add platform-independent .git "symlink"

Hi,
On Mon, 4 Feb 2008, Lars Hjemli wrote:
Show 18 quoted lines
> On Feb 4, 2008 1:24 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > On Sun, 3 Feb 2008, Junio C Hamano wrote:
> > > For now I haven't picked up any of the "how about this way" 
> > > revisions.
> >
> > Yeah, I think all my comments have been addressed...  Lars, care to 
> > send a new version?
> 
> Sure, but we should come to a conclusion on "GITDIR" vs. "GIT_DIR" vs. 
> "gitdir" vs. "directory" vs. "ref". The reason I used "GITDIR" was to 
> keep the door open for additional parameters in the "gitfile" (but it 
> should obviously have been "GIT_DIR" for that usage since its value is 
> used to specify $GIT_DIR). If it's more likely that we'll use this as a 
> general substitute for symlinks, I think "ref" is better due to the 
> existing symbolic refs.
> 
> My preference would be "GIT_DIR" (or "git_dir") since we also might want 
> the "WORKDIR_HASH" Shawn mentioned.
FWIW I like "gitdir" or "git-dir" best.

Ciao, Dscho

← back to recent threads