We allow the user to relocate certain paths out of $GIT_DIR via
environment variables, e.g. GIT_OBJECT_DIRECTORY, GIT_INDEX_FILE and
GIT_GRAFT_FILE. All callers are not supposed to use git_path() or
git_pathdup() to get those paths. Instead they must use
get_object_directory(), get_index_file() and get_graft_file()
respectively. This is inconvenient and could be missed in review
(there's git_path("objects/info/alternates") somewhere in
sha1_file.c).
This patch makes git_path() and git_pathdup() understand those
environment variables. So if you set GIT_OBJECT_DIRECTORY to /foo/bar,
git_path("objects/abc") should return /tmp/bar/abc. The same is done
for the two remaining env variables.
XXX trim consecutive slashes
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]>
---
cache.h | 1 +
environment.c | 9 +++++++--
path.c | 35 ++++++++++++++++++++++++++++++++---
t/t0060-path-utils.sh | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
test-path-utils.c | 7 +++++++
5 files changed, 95 insertions(+), 5 deletions(-)
diff --git a/cache.h b/cache.h
index ce377e1..cdafbd7 100644
--- a/cache.h
+++ b/cache.h
@@ -584,6 +584,7 @@ extern int fsync_object_files;
extern int core_preload_index;
extern int core_apply_sparse_checkout;
extern int precomposed_unicode;
+extern int git_db_env, git_index_env, git_graft_env;
/*
* The character that begins a commented line in user-editable file
diff --git a/environment.c b/environment.c
index 0a15349..1d74dde 100644
--- a/environment.c
+++ b/environment.c
@@ -81,6 +81,7 @@ static size_t namespace_len;
static const char *git_dir;
static char *git_object_dir, *git_index_file, *git_graft_file;
+int git_db_env, git_index_env, git_graft_env;
/*
* Repository-local GIT_* environment variables; see cache.h for details.
@@ -134,15 +135,19 @@ static void setup_git_env(void)
if (!git_object_dir) {
git_object_dir = xmalloc(strlen(git_dir) + 9);
sprintf(git_object_dir, "%s/objects", git_dir);
- }
+ } else
+ git_db_env = 1;
git_index_file = getenv(INDEX_ENVIRONMENT);
if (!git_index_file) {
git_index_file = xmalloc(strlen(git_dir) + 7);
sprintf(git_index_file, "%s/index", git_dir);
- }
+ } else
+ git_index_env = 1;
git_graft_file = getenv(GRAFT_ENVIRONMENT);
if (!git_graft_file)
git_graft_file = git_pathdup("info/grafts");
+ else
+ git_graft_env = 1;
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
read_replace_refs = 0;
namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
diff --git a/path.c b/path.c
index 24594c4..eda9176 100644
--- a/path.c
+++ b/path.c
@@ -49,10 +49,38 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
return cleanup_path(buf);
}
+static int dir_prefix(const char *buf, const char *dir)
+{
+ int len = strlen(dir);
+ return !strncmp(buf, dir, len) &&
+ (is_dir_sep(buf[len]) || buf[len] == '\0');
+}
+
+static void replace_dir(char *buf, int len, const char *newdir)
+{
+ int newlen = strlen(newdir);
+ int buflen = strlen(buf);
+ memmove(buf + newlen + 1, buf + len, buflen - len + 1);
+ memcpy(buf, newdir, newlen);
+ buf[newlen] = '/';
+}
+
+static void adjust_git_path(char *buf, int git_dir_len)
+{
+ /* XXX buffer overflow */
+ char *base = buf + git_dir_len;
+ if (git_graft_env && !strcmp(base, "info/grafts"))
+ strcpy(buf, get_graft_file());
+ else if (git_index_env && !strcmp(base, "index"))
+ strcpy(buf, get_index_file());
+ else if (git_db_env && dir_prefix(base, "objects"))
+ replace_dir(buf, git_dir_len + 7, get_object_directory());
+}
+
static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
{
const char *git_dir = get_git_dir();
- size_t len;
+ size_t len, total_len;
len = strlen(git_dir);
if (n < len + 1)
@@ -60,9 +88,10 @@ static char *vsnpath(char *buf, size_t n, const char *fmt,
va_list args)
memcpy(buf, git_dir, len);
if (len && !is_dir_sep(git_dir[len-1]))
buf[len++] = '/';
- len += vsnprintf(buf + len, n - len, fmt, args);
- if (len >= n)
+ total_len = len + vsnprintf(buf + len, n - len, fmt, args);
+ if (total_len >= n)
goto bad;
+ adjust_git_path(buf, len);
return cleanup_path(buf);
bad:
strlcpy(buf, bad_path, n);
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 07c10c8..7ad2730 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -223,4 +223,52 @@ relative_path "<null>" "<empty>" ./
relative_path "<null>" "<null>" ./
relative_path "<null>" /foo/a/b ./
+test_expect_success 'git_path info/grafts without GIT_GRAFT_FILE' '
+ test-path-utils git_path info/grafts >actual1 &&
+ echo .git/info/grafts >expect1 &&
+ test_cmp expect1 actual1
+'
+
+test_expect_success 'git_path info/grafts with GIT_GRAFT_FILE' '
+ GIT_GRAFT_FILE=foo test-path-utils git_path info/grafts >actual2 &&
+ echo foo >expect2 &&
+ test_cmp expect2 actual2
+'
+
+test_expect_success 'git_path index' '
+ GIT_INDEX_FILE=foo test-path-utils git_path index >actual &&
+ echo foo >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git_path index/foo' '
+ GIT_INDEX_FILE=foo test-path-utils git_path index/foo >actual &&
+ echo .git/index/foo >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git_path index2' '
+ GIT_INDEX_FILE=foo test-path-utils git_path index2 >actual &&
+ echo .git/index2 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git_path objects' '
+ GIT_OBJECT_DIRECTORY=foo test-path-utils git_path objects >actual &&
+ echo foo/ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git_path objects/foo' '
+ GIT_OBJECT_DIRECTORY=foo test-path-utils git_path objects/foo >actual &&
+ echo foo//foo >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git_path objects2' '
+ GIT_OBJECT_DIRECTORY=foo test-path-utils git_path objects2 >actual &&
+ echo .git/objects2 >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/test-path-utils.c b/test-path-utils.c
index 3dd3744..55e4fe0 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -135,6 +135,13 @@ int main(int argc, char **argv)
return 0;
}
+ if (argc == 3 && !strcmp(argv[1], "git_path")) {
+ int nongit_ok = 0;
+ setup_git_directory_gently(&nongit_ok);
+ puts(git_path("%s", argv[2]));
+ return 0;
+ }
+
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
argv[1] ? argv[1] : "(there was none)");
return 1;
--
1.8.5.1.77.g42c48fa
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html