From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Jonathan Niedier" <jrnieder@gmail.com>,
"Junio C Hamano" <gitster@pobox.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v2 04/21] Make git_path() aware of file relocation in $GIT_DIR
Date: Sat, 14 Dec 2013 17:54:50 +0700 [thread overview]
Message-ID: <1387018507-21999-5-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1387018507-21999-1-git-send-email-pclouds@gmail.com>
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.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
cache.h | 1 +
environment.c | 9 ++++++--
path.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---
t/t0060-path-utils.sh | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
test-path-utils.c | 7 +++++++
5 files changed, 123 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 08aa213..93e3ecc 100644
--- a/path.c
+++ b/path.c
@@ -50,10 +50,60 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
return cleanup_path(buf);
}
+static void copy_path(char *dst, size_t n, const char *src)
+{
+ if (strlen(src) < n)
+ strcpy(dst, src);
+ else
+ strlcpy(dst, bad_path, n);
+}
+
+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');
+}
+
+/* $buf =~ m|$dir/+$file| but without regex */
+static int is_dir_file(const char *buf, const char *dir, const char *file)
+{
+ int len = strlen(dir);
+ if (strncmp(buf, dir, len) || !is_dir_sep(buf[len]))
+ return 0;
+ while (is_dir_sep(buf[len]))
+ len++;
+ return !strcmp(buf + len, file);
+}
+
+static void replace_dir(char *buf, size_t n, int len, const char *newdir)
+{
+ int newlen = strlen(newdir);
+ int buflen = strlen(buf);
+ if (buflen - len + newlen >= n) {
+ strlcpy(buf, bad_path, n);
+ return;
+ }
+ memmove(buf + newlen + 1, buf + len, buflen - len + 1);
+ memcpy(buf, newdir, newlen);
+ buf[newlen] = '/';
+}
+
+static void adjust_git_path(char *buf, size_t n, int git_dir_len)
+{
+ char *base = buf + git_dir_len;
+ if (git_graft_env && is_dir_file(base, "info", "grafts"))
+ copy_path(buf, n, get_graft_file());
+ else if (git_index_env && !strcmp(base, "index"))
+ copy_path(buf, n, get_index_file());
+ else if (git_db_env && dir_prefix(base, "objects"))
+ replace_dir(buf, n, git_dir_len + 7, get_object_directory());
+}
+
static char *git_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)
@@ -61,9 +111,10 @@ static char *git_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, n, 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..bce16f5 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -223,4 +223,58 @@ 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 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
next prev parent reply other threads:[~2013-12-14 10:51 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-11 14:15 [PATCH/POC 0/7] Support multiple worktrees Nguyễn Thái Ngọc Duy
2013-12-11 14:15 ` [PATCH/POC 1/7] Make git_path() beware of file relocation in $GIT_DIR Nguyễn Thái Ngọc Duy
2013-12-13 16:30 ` Junio C Hamano
2013-12-11 14:15 ` [PATCH/POC 2/7] Add new environment variable $GIT_SUPER_DIR Nguyễn Thái Ngọc Duy
2013-12-13 18:12 ` Junio C Hamano
2013-12-14 1:11 ` Duy Nguyen
2013-12-14 19:43 ` Junio C Hamano
2013-12-11 14:15 ` [PATCH/POC 3/7] setup.c: add split-repo support to .git files Nguyễn Thái Ngọc Duy
2013-12-13 18:30 ` Junio C Hamano
2013-12-13 20:43 ` Jonathan Nieder
2013-12-14 1:28 ` Duy Nguyen
2013-12-23 3:38 ` Duy Nguyen
2013-12-11 14:15 ` [PATCH/POC 4/7] setup.c: add split-repo support to is_git_directory() Nguyễn Thái Ngọc Duy
2013-12-11 14:15 ` [PATCH/POC 5/7] setup.c: reduce cleanup sites in setup_explicit_git_dir() Nguyễn Thái Ngọc Duy
2013-12-11 14:15 ` [PATCH/POC 6/7] setup.c: add split-repo support to setup_git_directory* Nguyễn Thái Ngọc Duy
2013-12-11 14:15 ` [PATCH/POC 7/7] init: add --split-repo with the same functionality as git-new-workdir Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 00/21] Support multiple worktrees Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 01/21] path.c: avoid PATH_MAX as buffer size from get_pathname() Nguyễn Thái Ngọc Duy
2013-12-15 8:35 ` Torsten Bögershausen
2013-12-15 9:02 ` Duy Nguyen
2013-12-15 9:33 ` Antoine Pelisse
2013-12-14 10:54 ` [PATCH v2 02/21] path.c: rename vsnpath() to git_vsnpath() Nguyễn Thái Ngọc Duy
2013-12-14 20:23 ` Ramsay Jones
2013-12-15 2:25 ` Duy Nguyen
2013-12-15 21:13 ` Ramsay Jones
2013-12-16 7:21 ` Duy Nguyen
2013-12-16 17:11 ` Jonathan Nieder
2013-12-16 20:16 ` Junio C Hamano
2013-12-16 22:59 ` Ramsay Jones
2013-12-14 10:54 ` [PATCH v2 03/21] path.c: move git_path() closer to similar functions git_pathdup() Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` Nguyễn Thái Ngọc Duy [this message]
2013-12-14 10:54 ` [PATCH v2 05/21] reflog: use avoid constructing .lock path with git_path Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 06/21] fast-import: use git_path() for accessing .git dir instead of get_git_dir() Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 07/21] Add new environment variable $GIT_SUPER_DIR Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 08/21] setup.c: refactor path manipulation out of read_gitfile() Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 09/21] setup.c: add split-repo support to .git files Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 10/21] setup.c: add split-repo support to is_git_directory() Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 11/21] setup.c: reduce cleanup sites in setup_explicit_git_dir() Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 12/21] environment.c: support super .git file specified by $GIT_DIR Nguyễn Thái Ngọc Duy
2013-12-14 10:54 ` [PATCH v2 13/21] setup: support $GIT_SUPER_DIR as well as super .git files Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 14/21] checkout: support checking out into a new working directory Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 15/21] checkout: clean up half-prepared directories in --to mode Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 16/21] setup.c: keep track of the .git file location if read Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 17/21] prune: strategies for split repositories Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 18/21] refs: adjust reflog path for repos/<id>/HEAD Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 19/21] refs: detach split repos' HEAD when the linked ref is updated/deleted Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 20/21] refs.c: refactor do_head_ref(... to do_one_head_ref("HEAD", Nguyễn Thái Ngọc Duy
2013-12-14 10:55 ` [PATCH v2 21/21] revision: include repos/../HEAD in --all Nguyễn Thái Ngọc Duy
2013-12-15 2:29 ` [PATCH v2 00/21] Support multiple worktrees Duy Nguyen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1387018507-21999-5-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.