[PATCH] use $GIT_DIR/workdir as working directory with $GIT_DIR
$GIT_DIR/workdir will be used as fallback if $GIT_WORK_DIR is not set
Signed-off-by: Matthias Lederhofer <matled@gmx.net>
---
Documentation/repository-layout.txt | 4 ++
setup.c | 64 ++++++++++++++++++++++++++++++++---
2 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index 0459bd9..8a88080 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -179,3 +179,7 @@ shallow::
and maintained by shallow clone mechanism. See `--depth`
option to gitlink:git-clone[1] and gitlink:git-fetch[1].
+workdir::
+ Directory to be used as toplevel working directory when GIT_DIR
+ is set. If this is a file the first line will be used as the
+ name of the directory. This can be overriden by GIT_WORK_DIR.
diff --git a/setup.c b/setup.c
index ebf628e..a8b9fae 100644
--- a/setup.c
+++ b/setup.c
@@ -192,6 +192,64 @@ int is_inside_git_dir(void)
return inside_git_dir;
}
+static int stat_git_work_dir(struct stat *st)
+{
+ char workdir[PATH_MAX], cwd[PATH_MAX];
+ const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
+ const char *gitwd = getenv(GIT_WORKING_DIR_ENVIRONMENT);
+ int offset;
+ FILE *fp;
+
+ if (gitwd) {
+ if (!stat(gitwd, st))
+ return 1;
+ die("Unable to stat git working directory '%s'", gitwd);
+ }
+
+ /* setup_git_directory_gently: PATH_MAX - 40 >= strlen(gitdirenv) */
+ strcpy(workdir, gitdir);
+ strcat(workdir, "/workdir");
+
+ if (stat(workdir, st))
+ return 0;
+ if (st->st_mode & S_IFDIR)
+ return 1;
+ if (!(st->st_mode & S_IFREG))
+ die("GIT_DIR/workdir is neither a file nor a directory");
+
+ /* GIT_DIR/workdir is a file */
+ fp = fopen(workdir, "r");
+ if (!fp)
+ die("Unable to open '%s'", workdir);
+ if (!fgets(workdir, sizeof(workdir), fp))
+ die("Reading working directory from '%s' failed", workdir);
+ fclose(fp);
+ /* remove newline character(s) */
+ offset = strlen(workdir)-1;
+ while (offset >= 0 && (workdir[offset] == '\r' ||
+ workdir[offset] == '\n'))
+ --offset;
+ workdir[offset+1] = '\0';
+
+ /* relative path: change to gitdir for stat */
+ if (workdir[0] != '/') {
+ if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+ die("Unable to read current working directory");
+ if (chdir(gitdir))
+ die("Cannot change directory to '%s'", gitdir);
+ }
+
+ if (stat(workdir, st))
+ die("Unable to stat directory from GIT_DIR/workdir");
+ if (!(st->st_mode & S_IFDIR))
+ die("GIT_DIR/workdir does not point to a directory");
+
+ if (workdir[0] != '/' && chdir(cwd))
+ die("Cannot come back to cwd");
+
+ return 1;
+}
+
int has_working_directory = -1;
const char *setup_git_directory_gently(int *nongit_ok)
@@ -203,7 +261,6 @@ const char *setup_git_directory_gently(int *nongit_ok)
gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
if (gitdirenv) {
struct stat st, st_work, st_git;
- const char *gitwd;
char *prefix;
char c;
int len;
@@ -219,11 +276,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
/* check for working directory */
- gitwd = getenv(GIT_WORKING_DIR_ENVIRONMENT);
- if (!gitwd)
+ if (!stat_git_work_dir(&st_work))
return NULL;
- if (stat(gitwd, &st_work))
- die("Unable to stat git working directory '%s'", gitwd);
if (inside_git_dir == -1 && stat(gitdirenv, &st_git))
die("Unable to stat git directory");
if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/')
--
1.5.0.3.357.g0b2cd