From mboxrd@z Thu Jan 1 00:00:00 1970 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Subject: [PATCH v5 06/28] Make git_path() aware of file relocation in $GIT_DIR Date: Sat, 8 Mar 2014 09:47:58 +0700 Message-ID: <1394246900-31535-7-git-send-email-pclouds@gmail.com> References: <1393675983-3232-1-git-send-email-pclouds@gmail.com> <1394246900-31535-1-git-send-email-pclouds@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: Junio C Hamano , =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= To: git@vger.kernel.org X-From: git-owner@vger.kernel.org Sat Mar 08 03:49:01 2014 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1WM7Jr-000599-T9 for gcvg-git-2@plane.gmane.org; Sat, 08 Mar 2014 03:49:00 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753198AbaCHCss convert rfc822-to-quoted-printable (ORCPT ); Fri, 7 Mar 2014 21:48:48 -0500 Received: from mail-pa0-f48.google.com ([209.85.220.48]:54612 "EHLO mail-pa0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752305AbaCHCsb (ORCPT ); Fri, 7 Mar 2014 21:48:31 -0500 Received: by mail-pa0-f48.google.com with SMTP id hz1so4936243pad.21 for ; Fri, 07 Mar 2014 18:48:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=840zRN/Gf7oTeEjjViZm6UWKacKLjTRWJ3XAL41N1/E=; b=ZkP77CxbOKuxMQh6BMP4v6GEX4lfWn/zL+GlPC644zV4J7IP3zFbOCkKNiPwIhD2tI cnxmcronKcsSDHN7XwKZcdh+wi38HSuZt4Hm5o9auOj0MkBS9leloe6A2XywOTZgFt1l SnpK2pPQHyVGad8v7OPH9/lgsPU++DppDKhyqxgmlT90+cg6aAknkzb6orXrXe82Cf5d Yt/FkDfRwMqNWF6wVQy3/+imQB+jhwC3ipg+KlVbuIBxnR021lqPqAIzz/EkPHz/8l4D sPg8hcq+xVqaRd9Tf4qcWYAMU+jiJNO/dcx8lOLTerI6ENTTXq0ZrORBPBdBNiUolp2K y3Vw== X-Received: by 10.68.40.138 with SMTP id x10mr26330683pbk.8.1394246910604; Fri, 07 Mar 2014 18:48:30 -0800 (PST) Received: from lanh ([115.73.205.153]) by mx.google.com with ESMTPSA id my6sm42447148pbc.36.2014.03.07.18.48.27 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 07 Mar 2014 18:48:29 -0800 (PST) Received: by lanh (sSMTP sendmail emulation); Sat, 08 Mar 2014 09:49:03 +0700 X-Mailer: git-send-email 1.9.0.40.gaa8c3ea In-Reply-To: <1394246900-31535-1-git-send-email-pclouds@gmail.com> Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: 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. 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 (for example, 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 /foo/bar/abc. The same is done for the two remaining env variables. "git rev-parse --git-path" is the wrapper for script use. Signed-off-by: Nguy=E1=BB=85n Th=C3=A1i Ng=E1=BB=8Dc Duy --- Documentation/git-rev-parse.txt | 7 ++++++ builtin/rev-parse.c | 7 ++++++ cache.h | 1 + environment.c | 9 ++++++-- path.c | 49 +++++++++++++++++++++++++++++++++= ++++++-- t/t0060-path-utils.sh | 19 ++++++++++++++++ 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-pa= rse.txt index 0d2cdcd..46020d9 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -232,6 +232,13 @@ print a message to stderr and exit with nonzero st= atus. repository. If is a gitfile then the resolved path to the real repository is printed. =20 +--git-path :: + Resolve "$GIT_DIR/" and takes other path relocation + variables such as $GIT_OBJECT_DIRECTORY, + $GIT_INDEX_FILE... into account. For example, if + $GIT_OBJECT_DIRECTORY is set to /foo/bar then "git rev-parse + --git-path objects/abc" returns /tmp/bar/abc. + --show-cdup:: When the command is invoked from a subdirectory, show the path of the top-level directory relative to the current diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index aaeb611..e50bc65 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -518,6 +518,13 @@ int cmd_rev_parse(int argc, const char **argv, con= st char *prefix) for (i =3D 1; i < argc; i++) { const char *arg =3D argv[i]; =20 + if (!strcmp(arg, "--git-path")) { + if (!argv[i + 1]) + die("--git-path requires an argument"); + puts(git_path("%s", argv[i + 1])); + i++; + continue; + } if (as_is) { if (show_file(arg, output_prefix) && as_is < 2) verify_filename(prefix, arg, 0); diff --git a/cache.h b/cache.h index 0fae730..0f5f44f 100644 --- a/cache.h +++ b/cache.h @@ -585,6 +585,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; =20 /* * The character that begins a commented line in user-editable file diff --git a/environment.c b/environment.c index 4a3437d..f513479 100644 --- a/environment.c +++ b/environment.c @@ -82,6 +82,7 @@ static size_t namespace_len; =20 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; =20 /* * Repository-local GIT_* environment variables; see cache.h for detai= ls. @@ -137,15 +138,19 @@ static void setup_git_env(void) if (!git_object_dir) { git_object_dir =3D xmalloc(strlen(git_dir) + 9); sprintf(git_object_dir, "%s/objects", git_dir); - } + } else + git_db_env =3D 1; git_index_file =3D getenv(INDEX_ENVIRONMENT); if (!git_index_file) { git_index_file =3D xmalloc(strlen(git_dir) + 7); sprintf(git_index_file, "%s/index", git_dir); - } + } else + git_index_env =3D 1; git_graft_file =3D getenv(GRAFT_ENVIRONMENT); if (!git_graft_file) git_graft_file =3D git_pathdup("info/grafts"); + else + git_graft_env =3D 1; if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) read_replace_refs =3D 0; namespace =3D expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT)); diff --git a/path.c b/path.c index 1c0f160..1069ae0 100644 --- a/path.c +++ b/path.c @@ -60,13 +60,58 @@ char *mksnpath(char *buf, size_t n, const char *fmt= , ...) return cleanup_path(buf); } =20 +static int dir_prefix(const char *buf, const char *dir) +{ + int len =3D strlen(dir); + return !strncmp(buf, dir, len) && + (is_dir_sep(buf[len]) || buf[len] =3D=3D '\0'); +} + +/* $buf =3D~ m|$dir/+$file| but without regex */ +static int is_dir_file(const char *buf, const char *dir, const char *f= ile) +{ + int len =3D 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(struct strbuf *buf, int len, const char *newdi= r) +{ + int newlen =3D strlen(newdir); + int need_sep =3D (buf->buf[len] && !is_dir_sep(buf->buf[len])) && + !is_dir_sep(newdir[newlen - 1]); + if (need_sep) + len--; /* keep one char, to be replaced with '/' */ + strbuf_splice(buf, 0, len, newdir, newlen); + if (need_sep) + buf->buf[newlen] =3D '/'; +} + +static void adjust_git_path(struct strbuf *buf, int git_dir_len) +{ + const char *base =3D buf->buf + git_dir_len; + if (git_graft_env && is_dir_file(base, "info", "grafts")) + strbuf_splice(buf, 0, buf->len, + get_graft_file(), strlen(get_graft_file())); + else if (git_index_env && !strcmp(base, "index")) + strbuf_splice(buf, 0, buf->len, + get_index_file(), strlen(get_index_file())); + else if (git_db_env && dir_prefix(base, "objects")) + replace_dir(buf, git_dir_len + 7, get_object_directory()); +} + static void do_git_path(struct strbuf *buf, const char *fmt, va_list a= rgs) { - const char *git_dir =3D get_git_dir(); - strbuf_addstr(buf, git_dir); + int gitdir_len; + strbuf_addstr(buf, get_git_dir()); if (buf->len && !is_dir_sep(buf->buf[buf->len - 1])) strbuf_addch(buf, '/'); + gitdir_len =3D buf->len; strbuf_vaddf(buf, fmt, args); + adjust_git_path(buf, gitdir_len); strbuf_cleanup_path(buf); } =20 diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 07c10c8..1d29901 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -19,6 +19,14 @@ relative_path() { "test \"\$(test-path-utils relative_path '$1' '$2')\" =3D '$expected'= " } =20 +test_git_path() { + test_expect_success "git-path $1 $2 =3D> $3" " + $1 git rev-parse --git-path $2 >actual && + echo $3 >expect && + test_cmp expect actual + " +} + # On Windows, we are using MSYS's bash, which mangles the paths. # Absolute paths are anchored at the MSYS installation directory, # which means that the path / accounts for this many characters: @@ -223,4 +231,15 @@ relative_path "" "" ./ relative_path "" "" ./ relative_path "" /foo/a/b ./ =20 +test_git_path A=3DB info/grafts .git/info/grafts +test_git_path GIT_GRAFT_FILE=3Dfoo info/grafts foo +test_git_path GIT_GRAFT_FILE=3Dfoo info/////grafts foo +test_git_path GIT_INDEX_FILE=3Dfoo index foo +test_git_path GIT_INDEX_FILE=3Dfoo index/foo .git/index/foo +test_git_path GIT_INDEX_FILE=3Dfoo index2 .git/index2 +test_expect_success 'setup fake objects directory foo' 'mkdir foo' +test_git_path GIT_OBJECT_DIRECTORY=3Dfoo objects foo +test_git_path GIT_OBJECT_DIRECTORY=3Dfoo objects/foo foo/foo +test_git_path GIT_OBJECT_DIRECTORY=3Dfoo objects2 .git/objects2 + test_done --=20 1.9.0.40.gaa8c3ea