From: Lars Hjemli <hjemli@gmail.com>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <Johannes.Schindelin@gmx.de>
Subject: [PATCH 2/5] Add platform-independent .git "symlink"
Date: Mon, 18 Feb 2008 11:44:20 +0100 [thread overview]
Message-ID: <1203331463-13857-3-git-send-email-hjemli@gmail.com> (raw)
In-Reply-To: <1203331463-13857-2-git-send-email-hjemli@gmail.com>
This patch allows .git to be a regular textfile containing the path of
the real git directory (prefixed with "gitdir: "), which can be useful on
platforms lacking support for real symlinks.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
Documentation/repository-layout.txt | 5 ++-
cache.h | 1 +
environment.c | 2 +
setup.c | 47 ++++++++++++++++++++++
t/t0002-gitfile.sh | 74 +++++++++++++++++++++++++++++++++++
5 files changed, 128 insertions(+), 1 deletions(-)
create mode 100755 t/t0002-gitfile.sh
diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index 6939130..bbaed2e 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -3,7 +3,10 @@ git repository layout
You may find these things in your git repository (`.git`
directory for a repository associated with your working tree, or
-`'project'.git` directory for a public 'bare' repository).
+`'project'.git` directory for a public 'bare' repository. It is
+also possible to have a working tree where `.git` is a plain
+ascii file containing `gitdir: <path>`, i.e. the path to the
+real git repository).
objects::
Object store associated with this repository. Usually
diff --git a/cache.h b/cache.h
index e1000bc..1ad822a 100644
--- a/cache.h
+++ b/cache.h
@@ -277,6 +277,7 @@ extern char *get_index_file(void);
extern char *get_graft_file(void);
extern int set_git_dir(const char *path);
extern const char *get_git_work_tree(void);
+extern const char *read_gitfile_gently(const char *path);
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
diff --git a/environment.c b/environment.c
index 3527f16..8058e7b 100644
--- a/environment.c
+++ b/environment.c
@@ -49,6 +49,8 @@ static void setup_git_env(void)
{
git_dir = getenv(GIT_DIR_ENVIRONMENT);
if (!git_dir)
+ git_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
+ if (!git_dir)
git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
git_object_dir = getenv(DB_ENVIRONMENT);
if (!git_object_dir) {
diff --git a/setup.c b/setup.c
index 4509598..20502be 100644
--- a/setup.c
+++ b/setup.c
@@ -239,6 +239,44 @@ 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.
+ */
+const char *read_gitfile_gently(const char *path)
+{
+ char *buf;
+ struct stat st;
+ int fd;
+ size_t len;
+
+ if (stat(path, &st))
+ return NULL;
+ if (!S_ISREG(st.st_mode))
+ return NULL;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ die("Error opening %s: %s", path, strerror(errno));
+ buf = xmalloc(st.st_size + 1);
+ len = read_in_full(fd, buf, st.st_size);
+ close(fd);
+ if (len != st.st_size)
+ die("Error reading %s", path);
+ buf[len] = '\0';
+ if (prefixcmp(buf, "gitdir: "))
+ die("Invalid gitfile format: %s", path);
+ while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
+ len--;
+ if (len < 9)
+ die("No path in gitfile: %s", path);
+ buf[len] = '\0';
+ if (!is_git_directory(buf + 8))
+ die("Not a git repository: %s", buf + 8);
+ path = make_absolute_path(buf + 8);
+ free(buf);
+ return path;
+}
+
+/*
* 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 +285,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;
/*
@@ -293,8 +332,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
/*
* Test in the following order (relative to the cwd):
+ * - .git (file containing "gitdir: <path>")
* - .git/
* - ./ (bare)
+ * - ../.git
* - ../.git/
* - ../ (bare)
* - ../../.git/
@@ -302,6 +343,12 @@ 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) {
+ if (set_git_dir(gitfile_dir))
+ die("Repository setup failed");
+ break;
+ }
if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
break;
if (is_git_directory(".")) {
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
new file mode 100755
index 0000000..d280663
--- /dev/null
+++ b/t/t0002-gitfile.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+test_description='.git file
+
+Verify that plumbing commands work when .git is a file
+'
+. ./test-lib.sh
+
+objpath() {
+ echo "$1" | sed -e 's|\(..\)|\1/|'
+}
+
+objck() {
+ p=$(objpath "$1")
+ if test ! -f "$REAL/objects/$p"
+ then
+ echo "Object not found: $REAL/objects/$p"
+ 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) &&
+ objck $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 -f "$REAL/objects/$(objpath $SHA)" &&
+ git update-index --add bar &&
+ if ! test -f "$REAL/index"
+ then
+ echo "$REAL/index not found"
+ false
+ fi &&
+ objck $SHA
+'
+
+test_expect_success 'check write-tree' '
+ SHA=$(git write-tree) &&
+ objck $SHA
+'
+
+test_expect_success 'check commit-tree' '
+ SHA=$(echo "commit bar" | git commit-tree $SHA) &&
+ objck $SHA
+'
+
+test_expect_success 'check rev-list' '
+ echo $SHA >"$REAL/HEAD" &&
+ test "$SHA" = "$(git rev-list HEAD)"
+'
+
+test_done
--
1.5.4.1.188.g3ea1f5
next prev parent reply other threads:[~2008-02-18 10:46 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-02-18 10:44 [PATCH 0/5 v2] Introduce the .gitfile Lars Hjemli
2008-02-18 10:44 ` [PATCH 1/5] Simplify setup of $GIT_DIR in git-sh-setup.sh Lars Hjemli
2008-02-18 10:44 ` Lars Hjemli [this message]
2008-02-18 10:44 ` [PATCH 3/5] Teach resolve_gitlink_ref() about the .git file Lars Hjemli
2008-02-18 10:44 ` [PATCH 4/5] git-submodule: prepare for the .git-file Lars Hjemli
2008-02-18 10:44 ` [PATCH 5/5] Teach GIT-VERSION-GEN about the .git file Lars Hjemli
2008-02-18 12:34 ` [PATCH 2/5] Add platform-independent .git "symlink" Johannes Schindelin
2008-02-18 13:18 ` Lars Hjemli
2008-02-18 13:34 ` Jakub Narebski
2008-02-18 13:35 ` Johannes Schindelin
2008-02-18 14:04 ` Lars Hjemli
2008-02-18 14:44 ` Lars Hjemli
2008-02-18 14:54 ` Johannes Schindelin
2008-02-18 12:17 ` [PATCH 0/5 v2] Introduce the .gitfile Johannes Schindelin
2008-02-18 12:56 ` Lars Hjemli
2008-02-18 13:31 ` Johannes Schindelin
2008-02-18 14:01 ` Lars Hjemli
2008-02-18 14:12 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1203331463-13857-3-git-send-email-hjemli@gmail.com \
--to=hjemli@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).