Merge branch 'dr/ceiling'
[git/git.git] / setup.c
diff --git a/setup.c b/setup.c
index 045ca20..6cf9094 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -6,11 +6,17 @@ static int inside_work_tree = -1;
 
 static int sanitary_path_copy(char *dst, const char *src)
 {
-       char *dst0 = dst;
+       char *dst0;
 
-       if (*src == '/') {
+       if (has_dos_drive_prefix(src)) {
+               *dst++ = *src++;
+               *dst++ = *src++;
+       }
+       dst0 = dst;
+
+       if (is_dir_sep(*src)) {
                *dst++ = '/';
-               while (*src == '/')
+               while (is_dir_sep(*src))
                        src++;
        }
 
@@ -26,27 +32,24 @@ static int sanitary_path_copy(char *dst, const char *src)
                 * (4) "../"          -- strip one, eat slash and continue.
                 */
                if (c == '.') {
-                       switch (src[1]) {
-                       case '\0':
+                       if (!src[1]) {
                                /* (1) */
                                src++;
-                               break;
-                       case '/':
+                       } else if (is_dir_sep(src[1])) {
                                /* (2) */
                                src += 2;
-                               while (*src == '/')
+                               while (is_dir_sep(*src))
                                        src++;
                                continue;
-                       case '.':
-                               switch (src[2]) {
-                               case '\0':
+                       } else if (src[1] == '.') {
+                               if (!src[2]) {
                                        /* (3) */
                                        src += 2;
                                        goto up_one;
-                               case '/':
+                               } else if (is_dir_sep(src[2])) {
                                        /* (4) */
                                        src += 3;
-                                       while (*src == '/')
+                                       while (is_dir_sep(*src))
                                                src++;
                                        goto up_one;
                                }
@@ -54,11 +57,11 @@ static int sanitary_path_copy(char *dst, const char *src)
                }
 
                /* copy up to the next '/', and eat all '/' */
-               while ((c = *src++) != '\0' && c != '/')
+               while ((c = *src++) != '\0' && !is_dir_sep(c))
                        *dst++ = c;
-               if (c == '/') {
-                       *dst++ = c;
-                       while (c == '/')
+               if (is_dir_sep(c)) {
+                       *dst++ = '/';
+                       while (is_dir_sep(c))
                                c = *src++;
                        src--;
                } else if (!c)
@@ -77,7 +80,7 @@ static int sanitary_path_copy(char *dst, const char *src)
                        if (dst <= dst0)
                                break;
                        c = *dst--;
-                       if (c == '/') {
+                       if (c == '/') { /* MinGW: cannot be '\\' anymore */
                                dst += 2;
                                break;
                        }
@@ -126,10 +129,23 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
        static char path[PATH_MAX];
+#ifndef __MINGW32__
        if (!pfx || !*pfx || is_absolute_path(arg))
                return arg;
        memcpy(path, pfx, pfx_len);
        strcpy(path + pfx_len, arg);
+#else
+       char *p;
+       /* don't add prefix to absolute paths, but still replace '\' by '/' */
+       if (is_absolute_path(arg))
+               pfx_len = 0;
+       else
+               memcpy(path, pfx, pfx_len);
+       strcpy(path + pfx_len, arg);
+       for (p = path + pfx_len; *p; p++)
+               if (*p == '\\')
+                       *p = '/';
+#endif
        return path;
 }
 
@@ -292,15 +308,16 @@ void setup_work_tree(void)
        work_tree = get_git_work_tree();
        git_dir = get_git_dir();
        if (!is_absolute_path(git_dir))
-               set_git_dir(make_absolute_path(git_dir));
+               git_dir = make_absolute_path(git_dir);
        if (!work_tree || chdir(work_tree))
                die("This operation must be run in a work tree");
+       set_git_dir(make_relative_path(git_dir, work_tree));
        initialized = 1;
 }
 
 static int check_repository_format_gently(int *nongit_ok)
 {
-       git_config(check_repository_format_version);
+       git_config(check_repository_format_version, NULL);
        if (GIT_REPO_VERSION < repository_format_version) {
                if (!nongit_ok)
                        die ("Expected git repo version <= %d, found %d",
@@ -416,6 +433,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
                die("Unable to read current working directory");
 
        ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+       if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+               ceil_offset = 1;
 
        /*
         * Test in the following order (relative to the cwd):
@@ -526,7 +545,7 @@ int git_config_perm(const char *var, const char *value)
        return i & 0666;
 }
 
-int check_repository_format_version(const char *var, const char *value)
+int check_repository_format_version(const char *var, const char *value, void *cb)
 {
        if (strcmp(var, "core.repositoryformatversion") == 0)
                repository_format_version = git_config_int(var, value);