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