1
+#include "cache.h"
2
+#include "repository.h"
3
+
4
+/* The main repository */
5
+static struct repository the_repo;
6
+struct repository *the_repository = &the_repo;
7
+
8
+static char *git_path_from_env(const char *envvar, const char *git_dir,
9
+ const char *path, int fromenv)
10
+{
11
+ if (fromenv) {
12
+ const char *value = getenv(envvar);
13
+ if (value)
14
+ return xstrdup(value);
15
+ }
16
+
17
+ return xstrfmt("%s/%s", git_dir, path);
18
+}
19
+
20
+static int find_common_dir(struct strbuf *sb, const char *gitdir, int fromenv)
21
+{
22
+ if (fromenv) {
23
+ const char *value = getenv(GIT_COMMON_DIR_ENVIRONMENT);
24
+ if (value) {
25
+ strbuf_addstr(sb, value);
26
+ return 1;
27
+ }
28
+ }
29
+
30
+ return get_common_dir_noenv(sb, gitdir);
31
+}
32
+
33
+static void repo_setup_env(struct repository *repo)
34
+{
35
+ struct strbuf sb = STRBUF_INIT;
36
+
37
+ repo->different_commondir = find_common_dir(&sb, repo->gitdir,
38
+ !repo->ignore_env);
39
+ repo->commondir = strbuf_detach(&sb, NULL);
40
+ repo->objectdir = git_path_from_env(DB_ENVIRONMENT, repo->commondir,
41
+ "objects", !repo->ignore_env);
42
+ repo->graft_file = git_path_from_env(GRAFT_ENVIRONMENT, repo->commondir,
43
+ "info/grafts", !repo->ignore_env);
44
+ repo->index_file = git_path_from_env(INDEX_ENVIRONMENT, repo->gitdir,
45
+ "index", !repo->ignore_env);
46
+}
47
+
48
+void repo_set_gitdir(struct repository *repo, const char *path)
49
+{
50
+ const char *gitfile = read_gitfile(path);
51
+
52
+ /*
53
+ * NEEDSWORK: Eventually we want to be able to free gitdir and the rest
54
+ * of the environment before reinitializing it again, but we have some
55
+ * crazy code paths where we try to set gitdir with the current gitdir
56
+ * and we don't want to free gitdir before copying the passed in value.
57
+ */
58
+ repo->gitdir = xstrdup(gitfile ? gitfile : path);
59
+
60
+ repo_setup_env(repo);
61
+}
62
+
63
+/*
64
+ * Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
65
+ * Return 0 upon success and a non-zero value upon failure.
66
+ */
67
+static int repo_init_gitdir(struct repository *repo, const char *gitdir)
68
+{
69
+ int ret = 0;
70
+ int error = 0;
71
+ char *abspath = NULL;
72
+ const char *resolved_gitdir;
73
+
74
+ abspath = real_pathdup(gitdir, 0);
75
+ if (!abspath) {
76
+ ret = -1;
77
+ goto out;
78
+ }
79
+
80
+ /* 'gitdir' must reference the gitdir directly */
81
+ resolved_gitdir = resolve_gitdir_gently(abspath, &error);
82
+ if (!resolved_gitdir) {
83
+ ret = -1;
84
+ goto out;
85
+ }
86
+
87
+ repo_set_gitdir(repo, resolved_gitdir);
88
+
89
+out:
90
+ free(abspath);
91
+ return ret;
92
+}
93
+
94
+void repo_set_worktree(struct repository *repo, const char *path)
95
+{
96
+ repo->worktree = real_pathdup(path, 1);
97
+}
98
+
99
+static int read_and_verify_repository_format(struct repository_format *format,
100
+ const char *commondir)
101
+{
102
+ int ret = 0;
103
+ struct strbuf sb = STRBUF_INIT;
104
+
105
+ strbuf_addf(&sb, "%s/config", commondir);
106
+ read_repository_format(format, sb.buf);
107
+ strbuf_reset(&sb);
108
+
109
+ if (verify_repository_format(format, &sb) < 0) {
110
+ warning("%s", sb.buf);
111
+ ret = -1;
112
+ }
113
+
114
+ strbuf_release(&sb);
115
+ return ret;
116
+}
117
+
118
+/*
119
+ * Initialize 'repo' based on the provided 'gitdir'.
120
+ * Return 0 upon success and a non-zero value upon failure.
121
+ */
122
+int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
123
+{
124
+ struct repository_format format;
125
+ memset(repo, 0, sizeof(*repo));
126
+
127
+ repo->ignore_env = 1;
128
+
129
+ if (repo_init_gitdir(repo, gitdir))
130
+ goto error;
131
+
132
+ if (read_and_verify_repository_format(&format, repo->commondir))
133
+ goto error;
134
+
135
+ if (worktree)
136
+ repo_set_worktree(repo, worktree);
137
+
138
+ return 0;
139
+
140
+error:
141
+ repo_clear(repo);
142
+ return -1;
143
+}
144
+
145
+void repo_clear(struct repository *repo)
146
+{
147
+ free(repo->gitdir);
148
+ repo->gitdir = NULL;
149
+ free(repo->commondir);
150
+ repo->commondir = NULL;
151
+ free(repo->objectdir);
152
+ repo->objectdir = NULL;
153
+ free(repo->graft_file);
154
+ repo->graft_file = NULL;
155
+ free(repo->index_file);
156
+ repo->index_file = NULL;
157
+ free(repo->worktree);
158
+ repo->worktree = NULL;
159
+}