format-patch: improve head calculation for cover-letter
[gitweb.git] / setup.c
diff --git a/setup.c b/setup.c
index 2e1521b09e5e6a0de585225293805b1d30a03cd4..94c1e61bda747ed5c664bbbf8431234dc8276d29 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -207,10 +207,11 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
                     *copyfrom && *copyfrom != ')';
                     copyfrom = nextat) {
                        size_t len = strcspn(copyfrom, ",)");
-                       if (copyfrom[len] == ')')
-                               nextat = copyfrom + len;
-                       else
+                       if (copyfrom[len] == ',')
                                nextat = copyfrom + len + 1;
+                       else
+                               /* handle ')' and '\0' */
+                               nextat = copyfrom + len;
                        if (!len)
                                continue;
                        for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
@@ -223,8 +224,9 @@ static const char *prefix_pathspec(const char *prefix, int prefixlen, const char
                                die("Invalid pathspec magic '%.*s' in '%s'",
                                    (int) len, copyfrom, elt);
                }
-               if (*copyfrom == ')')
-                       copyfrom++;
+               if (*copyfrom != ')')
+                       die("Missing ')' at the end of pathspec magic in '%s'", elt);
+               copyfrom++;
        } else {
                /* shorthand */
                for (copyfrom = elt + 1;
@@ -523,6 +525,12 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
                        set_git_work_tree(core_worktree);
                }
        }
+       else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
+               /* #16d */
+               set_git_dir(gitdirenv);
+               free(gitfile);
+               return NULL;
+       }
        else /* #2, #10 */
                set_git_work_tree(".");
 
@@ -601,6 +609,8 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
        if (check_repository_format_gently(".", nongit_ok))
                return NULL;
 
+       setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
+
        /* --work-tree is set without --git-dir; use discovered one */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
                const char *gitdir;
@@ -650,22 +660,32 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
 /*
  * A "string_list_each_func_t" function that canonicalizes an entry
  * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
- * discards it if unusable.
+ * discards it if unusable.  The presence of an empty entry in
+ * GIT_CEILING_DIRECTORIES turns off canonicalization for all
+ * subsequent entries.
  */
 static int canonicalize_ceiling_entry(struct string_list_item *item,
-                                     void *unused)
+                                     void *cb_data)
 {
+       int *empty_entry_found = cb_data;
        char *ceil = item->string;
-       const char *real_path;
 
-       if (!*ceil || !is_absolute_path(ceil))
+       if (!*ceil) {
+               *empty_entry_found = 1;
                return 0;
-       real_path = real_path_if_valid(ceil);
-       if (!real_path)
+       } else if (!is_absolute_path(ceil)) {
                return 0;
-       free(item->string);
-       item->string = xstrdup(real_path);
-       return 1;
+       } else if (*empty_entry_found) {
+               /* Keep entry but do not canonicalize it */
+               return 1;
+       } else {
+               const char *real_path = real_path_if_valid(ceil);
+               if (!real_path)
+                       return 0;
+               free(item->string);
+               item->string = xstrdup(real_path);
+               return 1;
+       }
 }
 
 /*
@@ -705,9 +725,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
 
        if (env_ceiling_dirs) {
+               int empty_entry_found = 0;
+
                string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
                filter_string_list(&ceiling_dirs, 0,
-                                  canonicalize_ceiling_entry, NULL);
+                                  canonicalize_ceiling_entry, &empty_entry_found);
                ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
                string_list_clear(&ceiling_dirs, 0);
        }
@@ -782,9 +804,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
        prefix = setup_git_directory_gently_1(nongit_ok);
        if (prefix)
-               setenv("GIT_PREFIX", prefix, 1);
+               setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
        else
-               setenv("GIT_PREFIX", "", 1);
+               setenv(GIT_PREFIX_ENVIRONMENT, "", 1);
 
        if (startup_info) {
                startup_info->have_repository = !nongit_ok || !*nongit_ok;