Imported Upstream version 2.23.0
[platform/upstream/git.git] / path.c
diff --git a/path.c b/path.c
index 43b16aa..25e97b8 100644 (file)
--- a/path.c
+++ b/path.c
@@ -9,6 +9,8 @@
 #include "worktree.h"
 #include "submodule-config.h"
 #include "path.h"
+#include "packfile.h"
+#include "object-store.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -106,16 +108,21 @@ struct common_dir {
 
 static struct common_dir common_list[] = {
        { 0, 1, 0, "branches" },
+       { 0, 1, 0, "common" },
        { 0, 1, 0, "hooks" },
        { 0, 1, 0, "info" },
        { 0, 0, 1, "info/sparse-checkout" },
        { 1, 1, 0, "logs" },
        { 1, 1, 1, "logs/HEAD" },
        { 0, 1, 1, "logs/refs/bisect" },
+       { 0, 1, 1, "logs/refs/rewritten" },
+       { 0, 1, 1, "logs/refs/worktree" },
        { 0, 1, 0, "lost-found" },
        { 0, 1, 0, "objects" },
        { 0, 1, 0, "refs" },
        { 0, 1, 1, "refs/bisect" },
+       { 0, 1, 1, "refs/rewritten" },
+       { 0, 1, 1, "refs/worktree" },
        { 0, 1, 0, "remotes" },
        { 0, 1, 0, "worktrees" },
        { 0, 1, 0, "rr-cache" },
@@ -191,7 +198,7 @@ static void *add_to_trie(struct trie *root, const char *key, void *value)
                 * Split this node: child will contain this node's
                 * existing children.
                 */
-               child = malloc(sizeof(*child));
+               child = xmalloc(sizeof(*child));
                memcpy(child->children, root->children, sizeof(root->children));
 
                child->len = root->len - i - 1;
@@ -381,7 +388,7 @@ static void adjust_git_path(const struct repository *repo,
                strbuf_splice(buf, 0, buf->len,
                              repo->index_file, strlen(repo->index_file));
        else if (dir_prefix(base, "objects"))
-               replace_dir(buf, git_dir_len + 7, repo->objectdir);
+               replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
        else if (git_hooks_path && dir_prefix(base, "hooks"))
                replace_dir(buf, git_dir_len + 5, git_hooks_path);
        else if (repo->different_commondir)
@@ -716,7 +723,7 @@ char *expand_user_path(const char *path, int real_home)
                        if (!home)
                                goto return_null;
                        if (real_home)
-                               strbuf_addstr(&user_path, real_path(home));
+                               strbuf_add_real_path(&user_path, home);
                        else
                                strbuf_addstr(&user_path, home);
 #ifdef GIT_WINDOWS_NATIVE
@@ -1288,77 +1295,37 @@ int daemon_avoid_alias(const char *p)
        }
 }
 
-/*
- * On NTFS, we need to be careful to disallow certain synonyms of the `.git/`
- * directory:
- *
- * - For historical reasons, file names that end in spaces or periods are
- *   automatically trimmed. Therefore, `.git . . ./` is a valid way to refer
- *   to `.git/`.
- *
- * - For other historical reasons, file names that do not conform to the 8.3
- *   format (up to eight characters for the basename, three for the file
- *   extension, certain characters not allowed such as `+`, etc) are associated
- *   with a so-called "short name", at least on the `C:` drive by default.
- *   Which means that `git~1/` is a valid way to refer to `.git/`.
- *
- *   Note: Technically, `.git/` could receive the short name `git~2` if the
- *   short name `git~1` were already used. In Git, however, we guarantee that
- *   `.git` is the first item in a directory, therefore it will be associated
- *   with the short name `git~1` (unless short names are disabled).
- *
- * - For yet other historical reasons, NTFS supports so-called "Alternate Data
- *   Streams", i.e. metadata associated with a given file, referred to via
- *   `<filename>:<stream-name>:<stream-type>`. There exists a default stream
- *   type for directories, allowing `.git/` to be accessed via
- *   `.git::$INDEX_ALLOCATION/`.
- *
- * When this function returns 1, it indicates that the specified file/directory
- * name refers to a `.git` file or directory, or to any of these synonyms, and
- * Git should therefore not track it.
- *
- * For performance reasons, _all_ Alternate Data Streams of `.git/` are
- * forbidden, not just `::$INDEX_ALLOCATION`.
- *
- * This function is intended to be used by `git fsck` even on platforms where
- * the backslash is a regular filename character, therefore it needs to handle
- * backlash characters in the provided `name` specially: they are interpreted
- * as directory separators.
- */
-int is_ntfs_dotgit(const char *name)
+static int only_spaces_and_periods(const char *path, size_t len, size_t skip)
 {
-       char c;
-
-       /*
-        * Note that when we don't find `.git` or `git~1` we end up with `name`
-        * advanced partway through the string. That's okay, though, as we
-        * return immediately in those cases, without looking at `name` any
-        * further.
-        */
-       c = *(name++);
-       if (c == '.') {
-               /* .git */
-               if (((c = *(name++)) != 'g' && c != 'G') ||
-                   ((c = *(name++)) != 'i' && c != 'I') ||
-                   ((c = *(name++)) != 't' && c != 'T'))
-                       return 0;
-       } else if (c == 'g' || c == 'G') {
-               /* git ~1 */
-               if (((c = *(name++)) != 'i' && c != 'I') ||
-                   ((c = *(name++)) != 't' && c != 'T') ||
-                   *(name++) != '~' ||
-                   *(name++) != '1')
-                       return 0;
-       } else
+       if (len < skip)
                return 0;
-
-       for (;;) {
-               c = *(name++);
-               if (!c || c == '\\' || c == '/' || c == ':')
-                       return 1;
-               if (c != '.' && c != ' ')
+       len -= skip;
+       path += skip;
+       while (len-- > 0) {
+               char c = *(path++);
+               if (c != ' ' && c != '.')
                        return 0;
        }
+       return 1;
+}
+
+int is_ntfs_dotgit(const char *name)
+{
+       size_t len;
+
+       for (len = 0; ; len++)
+               if (!name[len] || name[len] == '\\' || is_dir_sep(name[len])) {
+                       if (only_spaces_and_periods(name, len, 4) &&
+                                       !strncasecmp(name, ".git", 4))
+                               return 1;
+                       if (only_spaces_and_periods(name, len, 5) &&
+                                       !strncasecmp(name, "git~1", 5))
+                               return 1;
+                       if (name[len] != '\\')
+                               return 0;
+                       name += len + 1;
+                       len = -1;
+               }
 }
 
 static int is_ntfs_dot_generic(const char *name,
@@ -1374,7 +1341,7 @@ static int is_ntfs_dot_generic(const char *name,
 only_spaces_and_periods:
                for (;;) {
                        char c = name[i++];
-                       if (!c || c == ':')
+                       if (!c)
                                return 1;
                        if (c != ' ' && c != '.')
                                return 0;
@@ -1407,7 +1374,7 @@ only_spaces_and_periods:
                        saw_tilde = 1;
                } else if (i >= 6)
                        return 0;
-               else if (name[i] 0) {
+               else if (name[i] & 0x80) {
                        /*
                         * We know our needles contain only ASCII, so we clamp
                         * here to make the results of tolower() sane.
@@ -1480,12 +1447,12 @@ char *xdg_cache_home(const char *filename)
        return NULL;
 }
 
-GIT_PATH_FUNC(git_path_cherry_pick_head, "CHERRY_PICK_HEAD")
-GIT_PATH_FUNC(git_path_revert_head, "REVERT_HEAD")
-GIT_PATH_FUNC(git_path_squash_msg, "SQUASH_MSG")
-GIT_PATH_FUNC(git_path_merge_msg, "MERGE_MSG")
-GIT_PATH_FUNC(git_path_merge_rr, "MERGE_RR")
-GIT_PATH_FUNC(git_path_merge_mode, "MERGE_MODE")
-GIT_PATH_FUNC(git_path_merge_head, "MERGE_HEAD")
-GIT_PATH_FUNC(git_path_fetch_head, "FETCH_HEAD")
-GIT_PATH_FUNC(git_path_shallow, "shallow")
+REPO_GIT_PATH_FUNC(cherry_pick_head, "CHERRY_PICK_HEAD")
+REPO_GIT_PATH_FUNC(revert_head, "REVERT_HEAD")
+REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
+REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
+REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
+REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
+REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
+REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
+REPO_GIT_PATH_FUNC(shallow, "shallow")