Add platform-independent .git "symlink"
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
2a5fe25458
commit
b44ebb19e3
47
setup.c
47
setup.c
@ -314,6 +314,44 @@ static int check_repository_format_gently(int *nongit_ok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -323,6 +361,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;
|
||||
|
||||
/*
|
||||
@ -377,8 +416,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/
|
||||
@ -386,6 +427,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(".")) {
|
||||
|
||||
Reference in New Issue
Block a user