* [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; 6+ 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] 6+ 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; 6+ 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] 6+ 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; 6+ 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] 6+ 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; 6+ 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] 6+ 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; 6+ 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] 6+ messages in thread
* [PATCH 0/4] Introduce the .git-file @ 2008-02-04 20:59 Lars Hjemli 2008-02-04 20:59 ` [PATCH 1/4] Add platform-independent .git "symlink" Lars Hjemli 0 siblings, 1 reply; 6+ messages in thread From: Lars Hjemli @ 2008-02-04 20:59 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Schindelin, Shawn O. Pearce, git This is a resend of my previous patches + an update to make git-submodule work with the .git-file + a litte documentation. PS: Regarding the color of the bikeshed, it seems that everyone can live with "gitdir:" so that's what I ended up using. Diffstat: Documentation/repository-layout.txt | 5 ++- git-submodule.sh | 4 +- setup.c | 40 +++++++++++++++++++ t/t0002-gitfile.sh | 71 +++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 3 deletions(-) ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] Add platform-independent .git "symlink" 2008-02-04 20:59 [PATCH 0/4] Introduce the .git-file Lars Hjemli @ 2008-02-04 20:59 ` Lars Hjemli 0 siblings, 0 replies; 6+ messages in thread From: Lars Hjemli @ 2008-02-04 20:59 UTC (permalink / raw) To: Junio C Hamano; +Cc: Johannes Schindelin, Shawn O. Pearce, git 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 | 40 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-) diff --git a/setup.c b/setup.c index adede16..2cbda91 100644 --- a/setup.c +++ b/setup.c @@ -239,6 +239,40 @@ 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 + 9]; /* "gitdir: " + "\n" */ + 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 || buf[len - 1] != '\n') + return NULL; + buf[len - 1] = '\0'; + if (prefixcmp(buf, "gitdir: ")) + return NULL; + 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 +281,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 +337,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.5.g25d066 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-02-20 22:38 UTC | newest] Thread overview: 6+ 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 -- strict thread matches above, loose matches on Subject: below -- 2008-02-04 20:59 [PATCH 0/4] Introduce the .git-file Lars Hjemli 2008-02-04 20:59 ` [PATCH 1/4] Add platform-independent .git "symlink" Lars Hjemli
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.