* [PATCH 0/4 v3] Introducing the .git file
@ 2008-02-20 22:13 Lars Hjemli
2008-02-20 22:13 ` [PATCH 1/4] Add platform-independent .git "symlink" Lars Hjemli
0 siblings, 1 reply; 5+ messages in thread
From: Lars Hjemli @ 2008-02-20 22:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
This is a resend of my previous series implementing the .git file,
rebased on top of todays master (e3c58f8b). The patches are identical
to the final suggestions in http://thread.gmane.org/gmane.comp.version-control.git/74258
except for the previous 1/5 which is dropped from the series (since it
already appears in master). There are also some minor touch-ups to the
commit messages.
Shortlog:
Add platform-independent .git "symlink"
Teach resolve_gitlink_ref() about the .git file
Teach git-submodule.sh about the .git file
Teach GIT-VERSION-GEN about the .git file
Diffstat:
Documentation/repository-layout.txt | 5 ++-
GIT-VERSION-GEN | 2 +-
cache.h | 1 +
environment.c | 2 +
git-submodule.sh | 4 +-
refs.c | 17 +++++-
setup.c | 47 ++++++++++++++++
t/t0002-gitfile.sh | 103 +++++++++++++++++++++++++++++++++++
8 files changed, 174 insertions(+), 7 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] Add platform-independent .git "symlink"
2008-02-20 22:13 [PATCH 0/4 v3] Introducing the .git file Lars Hjemli
@ 2008-02-20 22:13 ` Lars Hjemli
2008-02-20 22:13 ` [PATCH 2/4] Teach resolve_gitlink_ref() about the .git file Lars Hjemli
0 siblings, 1 reply; 5+ messages in thread
From: Lars Hjemli @ 2008-02-20 22:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
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 | 103 +++++++++++++++++++++++++++++++++++
5 files changed, 157 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..c5dbc72
--- /dev/null
+++ b/t/t0002-gitfile.sh
@@ -0,0 +1,103 @@
+#!/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 'initial setup' '
+ REAL="$(pwd)/.real" &&
+ mv .git "$REAL"
+'
+
+test_expect_success 'bad setup: invalid .git file format' '
+ echo "gitdir $REAL" >.git &&
+ if git rev-parse 2>.err
+ then
+ echo "git rev-parse accepted an invalid .git file"
+ false
+ fi &&
+ if ! grep -qe "Invalid gitfile format" .err
+ then
+ echo "git rev-parse returned wrong error"
+ false
+ fi
+'
+
+test_expect_success 'bad setup: invalid .git file path' '
+ echo "gitdir: $REAL.not" >.git &&
+ if git rev-parse 2>.err
+ then
+ echo "git rev-parse accepted an invalid .git file path"
+ false
+ fi &&
+ if ! grep -qe "Not a git repository" .err
+ then
+ echo "git rev-parse returned wrong error"
+ false
+ fi
+'
+
+test_expect_success 'final setup + check rev-parse --git-dir' '
+ echo "gitdir: $REAL" >.git &&
+ 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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] Teach resolve_gitlink_ref() about the .git file
2008-02-20 22:13 ` [PATCH 1/4] Add platform-independent .git "symlink" Lars Hjemli
@ 2008-02-20 22:13 ` Lars Hjemli
2008-02-20 22:13 ` [PATCH 3/4] Teach git-submodule.sh " Lars Hjemli
0 siblings, 1 reply; 5+ messages in thread
From: Lars Hjemli @ 2008-02-20 22:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
When .git in a submodule is a file, resolve_gitlink_ref() needs to pick up
the real GIT_DIR of the submodule from that file.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
refs.c | 17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/refs.c b/refs.c
index 67d2a50..56de5cf 100644
--- a/refs.c
+++ b/refs.c
@@ -351,6 +351,7 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
{
int len = strlen(path), retval;
char *gitdir;
+ const char *tmp;
while (len && path[len-1] == '/')
len--;
@@ -358,9 +359,19 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
return -1;
gitdir = xmalloc(len + MAXREFLEN + 8);
memcpy(gitdir, path, len);
- memcpy(gitdir + len, "/.git/", 7);
-
- retval = resolve_gitlink_ref_recursive(gitdir, len+6, refname, result, 0);
+ memcpy(gitdir + len, "/.git", 6);
+ len += 5;
+
+ tmp = read_gitfile_gently(gitdir);
+ if (tmp) {
+ free(gitdir);
+ len = strlen(tmp);
+ gitdir = xmalloc(len + MAXREFLEN + 3);
+ memcpy(gitdir, tmp, len);
+ }
+ gitdir[len] = '/';
+ gitdir[++len] = '\0';
+ retval = resolve_gitlink_ref_recursive(gitdir, len, refname, result, 0);
free(gitdir);
return retval;
}
--
1.5.4.1.188.g3ea1f5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] Teach git-submodule.sh about the .git file
2008-02-20 22:13 ` [PATCH 2/4] Teach resolve_gitlink_ref() about the .git file Lars Hjemli
@ 2008-02-20 22:13 ` Lars Hjemli
2008-02-20 22:13 ` [PATCH 4/4] Teach GIT-VERSION-GEN " Lars Hjemli
0 siblings, 1 reply; 5+ messages in thread
From: Lars Hjemli @ 2008-02-20 22:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
When git-submodule tries to detect 'active' submodules, it checks for the
existence of a directory named '.git'. This isn't good enough now that .git
can be a file pointing to the real $GIT_DIR so the tests are changed to
reflect this.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
git-submodule.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index a6aaf40..e7c08b5 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -288,7 +288,7 @@ cmd_update()
continue
fi
- if ! test -d "$path"/.git
+ if ! test -d "$path"/.git -o -f "$path"/.git
then
module_clone "$path" "$url" || exit
subsha1=
@@ -362,7 +362,7 @@ cmd_status()
do
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
- if test -z "url" || ! test -d "$path"/.git
+ if test -z "url" || ! test -d "$path"/.git -o -f "$path"/.git
then
say "-$sha1 $path"
continue;
--
1.5.4.1.188.g3ea1f5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] Teach GIT-VERSION-GEN about the .git file
2008-02-20 22:13 ` [PATCH 3/4] Teach git-submodule.sh " Lars Hjemli
@ 2008-02-20 22:13 ` Lars Hjemli
0 siblings, 0 replies; 5+ messages in thread
From: Lars Hjemli @ 2008-02-20 22:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
The presence of a .git directory used to be good enough evidence that
GIT-VERSION-GEN could use 'git describe' to get a version number. But
now .git might as well be a file so the test must be extended to cater for
such setups.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
GIT-VERSION-GEN | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 1ad324e..10fe488 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -11,7 +11,7 @@ LF='
if test -f version
then
VN=$(cat version) || VN="$DEF_VER"
-elif test -d .git &&
+elif test -d .git -o -f .git &&
VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
case "$VN" in
*$LF*) (exit 1) ;;
--
1.5.4.1.188.g3ea1f5
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-02-20 22:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-20 22:13 [PATCH 0/4 v3] Introducing the .git file Lars Hjemli
2008-02-20 22:13 ` [PATCH 1/4] Add platform-independent .git "symlink" Lars Hjemli
2008-02-20 22:13 ` [PATCH 2/4] Teach resolve_gitlink_ref() about the .git file Lars Hjemli
2008-02-20 22:13 ` [PATCH 3/4] Teach git-submodule.sh " Lars Hjemli
2008-02-20 22:13 ` [PATCH 4/4] Teach GIT-VERSION-GEN " Lars Hjemli
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).