Imported Upstream version 2.22.1
[platform/upstream/git.git] / path.c
diff --git a/path.c b/path.c
index 335d4dd..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
@@ -1304,7 +1311,7 @@ static int only_spaces_and_periods(const char *path, size_t len, size_t skip)
 
 int is_ntfs_dotgit(const char *name)
 {
-       int len;
+       size_t len;
 
        for (len = 0; ; len++)
                if (!name[len] || name[len] == '\\' || is_dir_sep(name[len])) {
@@ -1321,6 +1328,90 @@ int is_ntfs_dotgit(const char *name)
                }
 }
 
+static int is_ntfs_dot_generic(const char *name,
+                              const char *dotgit_name,
+                              size_t len,
+                              const char *dotgit_ntfs_shortname_prefix)
+{
+       int saw_tilde;
+       size_t i;
+
+       if ((name[0] == '.' && !strncasecmp(name + 1, dotgit_name, len))) {
+               i = len + 1;
+only_spaces_and_periods:
+               for (;;) {
+                       char c = name[i++];
+                       if (!c)
+                               return 1;
+                       if (c != ' ' && c != '.')
+                               return 0;
+               }
+       }
+
+       /*
+        * Is it a regular NTFS short name, i.e. shortened to 6 characters,
+        * followed by ~1, ... ~4?
+        */
+       if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
+           name[7] >= '1' && name[7] <= '4') {
+               i = 8;
+               goto only_spaces_and_periods;
+       }
+
+       /*
+        * Is it a fall-back NTFS short name (for details, see
+        * https://en.wikipedia.org/wiki/8.3_filename?
+        */
+       for (i = 0, saw_tilde = 0; i < 8; i++)
+               if (name[i] == '\0')
+                       return 0;
+               else if (saw_tilde) {
+                       if (name[i] < '0' || name[i] > '9')
+                               return 0;
+               } else if (name[i] == '~') {
+                       if (name[++i] < '1' || name[i] > '9')
+                               return 0;
+                       saw_tilde = 1;
+               } else if (i >= 6)
+                       return 0;
+               else if (name[i] & 0x80) {
+                       /*
+                        * We know our needles contain only ASCII, so we clamp
+                        * here to make the results of tolower() sane.
+                        */
+                       return 0;
+               } else if (tolower(name[i]) != dotgit_ntfs_shortname_prefix[i])
+                       return 0;
+
+       goto only_spaces_and_periods;
+}
+
+/*
+ * Inline helper to make sure compiler resolves strlen() on literals at
+ * compile time.
+ */
+static inline int is_ntfs_dot_str(const char *name, const char *dotgit_name,
+                                 const char *dotgit_ntfs_shortname_prefix)
+{
+       return is_ntfs_dot_generic(name, dotgit_name, strlen(dotgit_name),
+                                  dotgit_ntfs_shortname_prefix);
+}
+
+int is_ntfs_dotgitmodules(const char *name)
+{
+       return is_ntfs_dot_str(name, "gitmodules", "gi7eba");
+}
+
+int is_ntfs_dotgitignore(const char *name)
+{
+       return is_ntfs_dot_str(name, "gitignore", "gi250a");
+}
+
+int is_ntfs_dotgitattributes(const char *name)
+{
+       return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
+}
+
 int looks_like_command_line_option(const char *str)
 {
        return str && str[0] == '-';
@@ -1356,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")