All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Reiss <dreiss@facebook.com>
To: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] Add support for GIT_CEILING_DIRECTORIES
Date: Thu, 15 May 2008 14:09:39 -0700	[thread overview]
Message-ID: <482CA693.3060602@facebook.com> (raw)
In-Reply-To: <alpine.DEB.1.00.0805152055280.30431@racer>

longest_prefix is just a textual check.  It doesn't verify that the prefix
is actually a full directory component of the cwd.  For example...

dreiss@dreiss-vmware:/tmp$ mkdir test
dreiss@dreiss-vmware:/tmp$ cd test
dreiss@dreiss-vmware:/tmp/test$ git init
Initialized empty Git repository in .git/
dreiss@dreiss-vmware:master:test$ mkdir abcd
dreiss@dreiss-vmware:master:test$ cd abcd
dreiss@dreiss-vmware:master:test/abcd$ git rev-parse --show-prefix
abcd/
dreiss@dreiss-vmware:master:test/abcd$ ~/git-ceil/git rev-parse --show-prefix
abcd/
dreiss@dreiss-vmware:master:test/abcd$ GIT_CEILING_DIRECTORIES=/tmp/test/ab ~/git-ceil/git rev-parse --show-prefix
fatal: Not a git repository
dreiss@dreiss-vmware:master:test/abcd:128$ 

"/tmp/test/ab" is a textual prefix of the cwd, but it should not prevent
"/tmp/test/.git" from being discovered.  For what it's worth, my test cases
check this behavior.  Ironically, I think this could be fixed by requiring
the ceiling directories to have trailing slashes.

Also, I think it is better to move the 'chdir("..")' after the do loop,
so that git won't even chdir up into the ceiling directory.  This actually
doesn't matter to me, but I figured that it might be nice for someone.

Finally, just a small thing.  The documentation still says "GIT_CEILING_DIRS".

--David

Johannes Schindelin wrote:
> 
> In certain setups, trying to access a non-existing .git/ can take quite
> some time, for example when the directory is an automount directory.
> 
> Allow the user to specify directories where Git should stop looking for
> a .git/ directory: GIT_CEILING_DIRECTORIES, if set, is expected to be
> a colon delimited list of such barrier directories.
> 
> Note: if GIT_CEILING_DIRECTORIES=/a/b and your current working directory
> is /a, Git will _not_ stop looking.
> 
> Note2: you must not specify the directories with trailing slashes.
> 
> Initial implementation by David Reiss.
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
> 
>         Show me the bugs!
> 
>         I just checked: the "/" issue you were referring to is most likely
>         the fact that "git rev-parse --git-dir" would return "//.git"
>         instead of "/.git" (if that is the appropriate GIT_DIR).
> 
>         This is the original behavior (without this patch), and IMO a
>         separate issue, which might not even need fixing.
> 
>  Documentation/git.txt          |    6 +++++
>  cache.h                        |    2 +
>  path.c                         |   19 ++++++++++++++++
>  setup.c                        |   11 +++++++-
>  t/t1504-ceiling-directories.sh |   46
> ++++++++++++++++++++++++++++++++++++++++
>  t/test-lib.sh                  |    1 +
>  6 files changed, 83 insertions(+), 2 deletions(-)
>  create mode 100644 t/t1504-ceiling-directories.sh
> 
> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index adcd3e0..a12d1f8 100644
> --- a/Documentation/git.txt
> +++ b/Documentation/git.txt
> @@ -415,6 +415,12 @@ git so take care if using Cogito etc.
>         This can also be controlled by the '--work-tree' command line
>         option and the core.worktree configuration variable.
> 
> +'GIT_CEILING_DIRS'::
> +       If set (to a colon delimited list of absolute directories), Git
> +       will refuse to look for the .git/ directory further when hitting
> +       one of those directories (otherwise it would traverse the parent
> +       directories until hitting the root directory).
> +
>  git Commits
>  ~~~~~~~~~~~
>  'GIT_AUTHOR_NAME'::
> diff --git a/cache.h b/cache.h
> index a8638b1..c31b4c7 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -300,6 +300,7 @@ static inline enum object_type object_type(unsigned
> int mode)
>  #define CONFIG_ENVIRONMENT "GIT_CONFIG"
>  #define CONFIG_LOCAL_ENVIRONMENT "GIT_CONFIG_LOCAL"
>  #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
> +#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
>  #define GITATTRIBUTES_FILE ".gitattributes"
>  #define INFOATTRIBUTES_FILE "info/attributes"
>  #define ATTRIBUTE_MACRO_PREFIX "[attr]"
> @@ -522,6 +523,7 @@ static inline int is_absolute_path(const char *path)
>         return path[0] == '/';
>  }
>  const char *make_absolute_path(const char *path);
> +int longest_prefix(const char *path, const char *prefix_list);
> 
>  /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
>  extern int sha1_object_info(const unsigned char *, unsigned long *);
> diff --git a/path.c b/path.c
> index b7c24a2..c0d7364 100644
> --- a/path.c
> +++ b/path.c
> @@ -357,3 +357,22 @@ const char *make_absolute_path(const char *path)
> 
>         return buf;
>  }
> +
> +int longest_prefix(const char *path, const char *prefix_list)
> +{
> +       int max_length = 0, length = 0, i;
> +
> +       for (i = 0; prefix_list[i]; i++)
> +               if (prefix_list[i] == ':') {
> +                       if (length > max_length)
> +                               max_length = length;
> +                       length = 0;
> +               }
> +               else if (length >= 0) {
> +                       if (prefix_list[i] == path[length])
> +                               length++;
> +                       else
> +                               length = -1;
> +               }
> +       return max_length > length ? max_length : length;
> +}
> diff --git a/setup.c b/setup.c
> index 9e9a2b1..cece3e4 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -365,10 +365,13 @@ const char *read_gitfile_gently(const char *path)
>  const char *setup_git_directory_gently(int *nongit_ok)
>  {
>         const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
> +       const char *ceiling_directories =
> +               getenv(CEILING_DIRECTORIES_ENVIRONMENT);
>         static char cwd[PATH_MAX+1];
>         const char *gitdirenv;
>         const char *gitfile_dir;
>         int len, offset;
> +       int min_offset = 0;
> 
>         /*
>          * Let's assume that we are in a git repository.
> @@ -422,6 +425,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
>         if (!getcwd(cwd, sizeof(cwd)-1))
>                 die("Unable to read current working directory");
> 
> +       if (ceiling_directories)
> +               min_offset = longest_prefix(cwd, ceiling_directories);
> +
>         /*
>          * Test in the following order (relative to the cwd):
>          * - .git (file containing "gitdir: <path>")
> @@ -453,7 +459,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
>                 }
>                 chdir("..");
>                 do {
> -                       if (!offset) {
> +                       if (offset <= min_offset) {
>                                 if (nongit_ok) {
>                                         if (chdir(cwd))
>                                                 die("Cannot come back to
> cwd");
> @@ -462,7 +468,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
>                                 }
>                                 die("Not a git repository");
>                         }
> -               } while (cwd[--offset] != '/');
> +               } while (offset > min_offset &&
> +                               --offset >=0 && cwd[offset] != '/');
>         }
> 
>         inside_git_dir = 0;
> diff --git a/t/t1504-ceiling-directories.sh b/t/t1504-ceiling-directories.sh
> new file mode 100644
> index 0000000..1d8ef0b
> --- /dev/null
> +++ b/t/t1504-ceiling-directories.sh
> @@ -0,0 +1,46 @@
> +#!/bin/sh
> +#
> +# Copyright (c) 2007 Johannes E. Schindelin
> +#
> +
> +test_description='test limiting with GIT_CEILING_DIRECTORIES'
> +
> +. ./test-lib.sh
> +
> +test_expect_success 'setup' '
> +
> +       CWD="$(pwd -P)" &&
> +       mkdir subdir
> +
> +'
> +
> +test_expect_success 'without GIT_CEILING_DIRECTORIES' '
> +
> +       test .git = "$(git rev-parse --git-dir)" &&
> +       (cd subdir && git rev-parse --git-dir) &&
> +       echo "$CWD" &&
> +       test "$CWD/.git" = "$(cd subdir && git rev-parse --git-dir)"
> +
> +'
> +
> +test_expect_success 'with non-matching ceiling directory' '
> +
> +       test "$(GIT_CEILING_DIRECTORIES="$CWD/X" \
> +               git rev-parse --git-dir)" = .git
> +
> +'
> +
> +test_expect_success 'with matching ceiling directories' '
> +
> +       GIT_CEILING_DIRECTORIES="$CWD/X:$CWD/subdir" &&
> +       export GIT_CEILING_DIRECTORIES &&
> +       (cd subdir && test_must_fail git rev-parse --git-dir) &&
> +       git rev-parse --git-dir &&
> +       GIT_CEILING_DIRECTORIES="$CWD/subdir:$CWD/X" &&
> +       export GIT_CEILING_DIRECTORIES &&
> +       (cd subdir && test_must_fail git rev-parse --git-dir) &&
> +       git rev-parse --git-dir
> +
> +'
> +
> +test_done
> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index 5002fb0..c3a3167 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -35,6 +35,7 @@ unset GIT_WORK_TREE
>  unset GIT_EXTERNAL_DIFF
>  unset GIT_INDEX_FILE
>  unset GIT_OBJECT_DIRECTORY
> +unset GIT_CEILING_DIRECTORIES
>  unset SHA1_FILE_DIRECTORIES
>  unset SHA1_FILE_DIRECTORY
>  GIT_MERGE_VERBOSITY=5
> --
> 1.5.5.1.425.g5f464
> 

  reply	other threads:[~2008-05-15 21:10 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-15 18:49 [PATCH v3] Add support for GIT_CEILING_DIRS David Reiss
2008-05-15 19:03 ` Johannes Schindelin
2008-05-15 19:40   ` David Reiss
2008-05-15 20:27   ` [PATCH] Add support for GIT_CEILING_DIRECTORIES Johannes Schindelin
2008-05-15 21:09     ` David Reiss [this message]
2008-05-15 22:29       ` Johannes Schindelin
2008-05-15 22:45         ` David Reiss
2008-05-15 23:27           ` [SQUASHED PATCH] " Johannes Schindelin
2008-05-16  6:54             ` Johannes Sixt
2008-05-16 10:20               ` Johannes Schindelin
2008-05-16 10:50                 ` Johannes Sixt
2008-05-16 17:43                   ` David Reiss
2008-05-17  0:19                     ` Johannes Schindelin
2008-05-17  0:20                       ` [2nd SQUASHED " Johannes Schindelin
2008-05-19  7:55                       ` [SQUASHED " Johannes Sixt
2008-05-19 10:49                         ` Johannes Schindelin
2008-05-15 19:46 ` [PATCH v3] Add support for GIT_CEILING_DIRS Junio C Hamano
2008-05-15 20:34   ` Johannes Schindelin
2008-05-16  7:03     ` Johannes Sixt
2008-05-16 10:21       ` Johannes Schindelin

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=482CA693.3060602@facebook.com \
    --to=dreiss@facebook.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    /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.