Merge branch 'mv/pull-r-for-rebase' into maint-1.7.11
[git.git] / setup.c
diff --git a/setup.c b/setup.c
index d121b6ab77cb40afff69cb9003be62033a12802f..e11497720e01dd14a66e152883e675669fc3b548 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -4,7 +4,7 @@
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
 
-char *prefix_path(const char *prefix, int len, const char *path)
+static char *prefix_path_gently(const char *prefix, int len, const char *path)
 {
        const char *orig = path;
        char *sanitized;
@@ -31,7 +31,8 @@ char *prefix_path(const char *prefix, int len, const char *path)
                if (strncmp(sanitized, work_tree, len) ||
                    (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
                error_out:
-                       die("'%s' is outside repository", orig);
+                       free(sanitized);
+                       return NULL;
                }
                if (sanitized[len] == '/')
                        len++;
@@ -40,6 +41,25 @@ char *prefix_path(const char *prefix, int len, const char *path)
        return sanitized;
 }
 
+char *prefix_path(const char *prefix, int len, const char *path)
+{
+       char *r = prefix_path_gently(prefix, len, path);
+       if (!r)
+               die("'%s' is outside repository", path);
+       return r;
+}
+
+int path_inside_repo(const char *prefix, const char *path)
+{
+       int len = prefix ? strlen(prefix) : 0;
+       char *r = prefix_path_gently(prefix, len, path);
+       if (r) {
+               free(r);
+               return 1;
+       }
+       return 0;
+}
+
 int check_filename(const char *prefix, const char *arg)
 {
        const char *name;
@@ -268,7 +288,7 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
  *    a proper "ref:", or a regular file HEAD that has a properly
  *    formatted sha1 object name.
  */
-static int is_git_directory(const char *suspect)
+int is_git_directory(const char *suspect)
 {
        char path[PATH_MAX];
        size_t len = strlen(suspect);
@@ -590,13 +610,15 @@ static const char *setup_nongit(const char *cwd, int *nongit_ok)
        return NULL;
 }
 
-static dev_t get_device_or_die(const char *path, const char *prefix)
+static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_len)
 {
        struct stat buf;
-       if (stat(path, &buf))
-               die_errno("failed to stat '%s%s%s'",
+       if (stat(path, &buf)) {
+               die_errno("failed to stat '%*s%s%s'",
+                               prefix_len,
                                prefix ? prefix : "",
                                prefix ? "/" : "", path);
+       }
        return buf.st_dev;
 }
 
@@ -610,7 +632,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
        static char cwd[PATH_MAX+1];
        const char *gitdirenv, *ret;
        char *gitfile;
-       int len, offset, ceil_offset;
+       int len, offset, offset_parent, ceil_offset;
        dev_t current_device = 0;
        int one_filesystem = 1;
 
@@ -652,7 +674,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
         */
        one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
        if (one_filesystem)
-               current_device = get_device_or_die(".", NULL);
+               current_device = get_device_or_die(".", NULL, 0);
        for (;;) {
                gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
                if (gitfile)
@@ -674,11 +696,12 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                if (is_git_directory("."))
                        return setup_bare_git_dir(cwd, offset, len, nongit_ok);
 
-               while (--offset > ceil_offset && cwd[offset] != '/');
-               if (offset <= ceil_offset)
+               offset_parent = offset;
+               while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
+               if (offset_parent <= ceil_offset)
                        return setup_nongit(cwd, nongit_ok);
                if (one_filesystem) {
-                       dev_t parent_device = get_device_or_die("..", cwd);
+                       dev_t parent_device = get_device_or_die("..", cwd, offset);
                        if (parent_device != current_device) {
                                if (nongit_ok) {
                                        if (chdir(cwd))
@@ -687,7 +710,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                                        return NULL;
                                }
                                cwd[offset] = '\0';
-                               die("Not a git repository (or any parent up to mount parent %s)\n"
+                               die("Not a git repository (or any parent up to mount point %s)\n"
                                "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
                        }
                }
@@ -695,6 +718,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                        cwd[offset] = '\0';
                        die_errno("Cannot change to '%s/..'", cwd);
                }
+               offset = offset_parent;
        }
 }