]> git.proxmox.com Git - libgit2.git/blame - src/repository.c
Remove old and unused error codes
[libgit2.git] / src / repository.c
CommitLineData
3315782c 1/*
5e0de328 2 * Copyright (C) 2009-2012 the libgit2 contributors
3315782c 3 *
bb742ede
VM
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
3315782c 6 */
e802d8cc 7#include <stdarg.h>
7784bcbb 8#include <ctype.h>
3315782c 9
44908fe7 10#include "git2/object.h"
d12299fe 11
3315782c
VM
12#include "common.h"
13#include "repository.h"
14#include "commit.h"
15#include "tag.h"
237da401 16#include "blob.h"
6fd195d7 17#include "fileops.h"
b22d1479 18#include "config.h"
9282e921 19#include "refs.h"
20
f2d6a23a 21#define GIT_OBJECTS_INFO_DIR GIT_OBJECTS_DIR "info/"
22#define GIT_OBJECTS_PACK_DIR GIT_OBJECTS_DIR "pack/"
40c44d2f 23
7784bcbb 24#define GIT_FILE_CONTENT_PREFIX "gitdir:"
6a01b6bd 25
28990938 26#define GIT_BRANCH_MASTER "master"
27
5663e61a 28#define GIT_CONFIG_CORE_REPOSITORYFORMATVERSION "core.repositoryformatversion"
29#define GIT_REPOSITORYFORMATVERSION 0
691aa968 30
9462c471
VM
31static void drop_odb(git_repository *repo)
32{
33 if (repo->_odb != NULL) {
34 GIT_REFCOUNT_OWN(repo->_odb, NULL);
35 git_odb_free(repo->_odb);
36 repo->_odb = NULL;
eb2f3b47 37 }
9462c471 38}
691aa968 39
9462c471
VM
40static void drop_config(git_repository *repo)
41{
42 if (repo->_config != NULL) {
43 GIT_REFCOUNT_OWN(repo->_config, NULL);
44 git_config_free(repo->_config);
45 repo->_config = NULL;
eb2f3b47 46 }
f2c25d18
VM
47
48 git_repository__cvar_cache_clear(repo);
691aa968
VM
49}
50
9462c471 51static void drop_index(git_repository *repo)
6fd195d7 52{
9462c471
VM
53 if (repo->_index != NULL) {
54 GIT_REFCOUNT_OWN(repo->_index, NULL);
55 git_index_free(repo->_index);
56 repo->_index = NULL;
57 }
e0011be3
VM
58}
59
9462c471 60void git_repository_free(git_repository *repo)
e0011be3 61{
9462c471
VM
62 if (repo == NULL)
63 return;
6fd195d7 64
9462c471
VM
65 git_cache_free(&repo->objects);
66 git_repository__refcache_free(&repo->references);
73b51450 67 git_attr_cache_flush(repo);
bfc9ca59 68 git_submodule_config_free(repo);
6fd195d7 69
9462c471
VM
70 git__free(repo->path_repository);
71 git__free(repo->workdir);
6fd195d7 72
9462c471
VM
73 drop_config(repo);
74 drop_index(repo);
75 drop_odb(repo);
76
77 git__free(repo);
6fd195d7
VM
78}
79
9462c471
VM
80/*
81 * Git repository open methods
82 *
83 * Open a repository object from its path
84 */
cb8a7961 85static bool valid_repository_path(git_buf *repository_path)
5ad739e8 86{
97769280 87 /* Check OBJECTS_DIR first, since it will generate the longest path name */
1a481123 88 if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
cb8a7961 89 return false;
5ad739e8 90
97769280 91 /* Ensure HEAD file exists */
1a481123 92 if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
cb8a7961 93 return false;
5ad739e8 94
1a481123 95 if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
cb8a7961 96 return false;
5ad739e8 97
cb8a7961 98 return true;
5ad739e8
VM
99}
100
51d00446 101static git_repository *repository_alloc(void)
3315782c
VM
102{
103 git_repository *repo = git__malloc(sizeof(git_repository));
104 if (!repo)
105 return NULL;
106
107 memset(repo, 0x0, sizeof(git_repository));
108
cb8a7961 109 if (git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free) < 0) {
3286c408 110 git__free(repo);
81201a4c 111 return NULL;
112 }
3315782c 113
f2c25d18
VM
114 /* set all the entries in the cvar cache to `unset` */
115 git_repository__cvar_cache_clear(repo);
116
6fd195d7
VM
117 return repo;
118}
119
9462c471 120static int load_config_data(git_repository *repo)
ec3c7a16 121{
cb8a7961 122 int is_bare;
9462c471 123 git_config *config;
ec3c7a16 124
cb8a7961
VM
125 if (git_repository_config__weakptr(&config, repo) < 0)
126 return -1;
ec3c7a16 127
cb8a7961
VM
128 if (git_config_get_bool(config, "core.bare", &is_bare) < 0)
129 return -1; /* FIXME: We assume that a missing core.bare
130 variable is an error. Is this right? */
c94785a9 131
cb8a7961
VM
132 repo->is_bare = is_bare;
133 return 0;
9462c471 134}
ec3c7a16 135
7784bcbb 136static int load_workdir(git_repository *repo, git_buf *parent_path)
9462c471 137{
7784bcbb
RB
138 int error;
139 git_config *config;
140 const char *worktree;
141 git_buf worktree_buf = GIT_BUF_INIT;
ec3c7a16 142
97769280 143 if (repo->is_bare)
cb8a7961 144 return 0;
ec3c7a16 145
7784bcbb 146 if (git_repository_config__weakptr(&config, repo) < 0)
cb8a7961 147 return -1;
ec3c7a16 148
7784bcbb
RB
149 error = git_config_get_string(config, "core.worktree", &worktree);
150 if (!error && worktree != NULL)
151 repo->workdir = git__strdup(worktree);
152 else if (error != GIT_ENOTFOUND)
153 return error;
154 else {
155 giterr_clear();
156
157 if (parent_path && git_path_isdir(parent_path->ptr))
158 repo->workdir = git_buf_detach(parent_path);
159 else {
160 git_path_dirname_r(&worktree_buf, repo->path_repository);
161 git_path_to_dir(&worktree_buf);
162 repo->workdir = git_buf_detach(&worktree_buf);
163 }
164 }
165
166 GITERR_CHECK_ALLOC(repo->workdir);
97769280 167
cb8a7961 168 return 0;
ec3c7a16
VM
169}
170
7784bcbb
RB
171/*
172 * This function returns furthest offset into path where a ceiling dir
173 * is found, so we can stop processing the path at that point.
174 *
175 * Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
176 * the stack could remove directories name limits, but at the cost of doing
177 * repeated malloc/frees inside the loop below, so let's not do it now.
178 */
179static int find_ceiling_dir_offset(
180 const char *path,
181 const char *ceiling_directories)
182{
183 char buf[GIT_PATH_MAX + 1];
184 char buf2[GIT_PATH_MAX + 1];
185 const char *ceil, *sep;
44ef8b1b 186 size_t len, max_len = 0, min_len;
7784bcbb
RB
187
188 assert(path);
189
44ef8b1b 190 min_len = (size_t)(git_path_root(path) + 1);
7784bcbb
RB
191
192 if (ceiling_directories == NULL || min_len == 0)
44ef8b1b 193 return (int)min_len;
7784bcbb
RB
194
195 for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
196 for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
197 len = sep - ceil;
198
44ef8b1b 199 if (len == 0 || len >= sizeof(buf) || git_path_root(ceil) == -1)
7784bcbb
RB
200 continue;
201
202 strncpy(buf, ceil, len);
203 buf[len] = '\0';
204
205 if (p_realpath(buf, buf2) == NULL)
206 continue;
207
208 len = strlen(buf2);
209 if (len > 0 && buf2[len-1] == '/')
210 buf[--len] = '\0';
211
212 if (!strncmp(path, buf2, len) &&
213 path[len] == '/' &&
214 len > max_len)
215 {
216 max_len = len;
217 }
218 }
219
44ef8b1b 220 return (int)(max_len <= min_len ? min_len : max_len);
7784bcbb
RB
221}
222
223/*
224 * Read the contents of `file_path` and set `path_out` to the repo dir that
225 * it points to. Before calling, set `path_out` to the base directory that
226 * should be used if the contents of `file_path` are a relative path.
227 */
228static int read_gitfile(git_buf *path_out, const char *file_path)
229{
230 int error = 0;
231 git_buf file = GIT_BUF_INIT;
232 size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX);
233
234 assert(path_out && file_path);
235
236 if (git_futils_readbuffer(&file, file_path) < 0)
237 return -1;
238
239 git_buf_rtrim(&file);
240
241 if (file.size <= prefix_len ||
242 memcmp(file.ptr, GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
243 {
244 giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path);
245 error = -1;
246 }
247 else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
248 const char *gitlink = ((const char *)file.ptr) + prefix_len;
249 while (*gitlink && isspace(*gitlink)) gitlink++;
250 error = git_path_prettify_dir(path_out, gitlink, path_out->ptr);
251 }
252
253 git_buf_free(&file);
254 return error;
255}
256
257static int find_repo(
258 git_buf *repo_path,
259 git_buf *parent_path,
260 const char *start_path,
261 uint32_t flags,
262 const char *ceiling_dirs)
691aa968 263{
7784bcbb
RB
264 int error;
265 git_buf path = GIT_BUF_INIT;
266 struct stat st;
267 dev_t initial_device = 0;
268 bool try_with_dot_git = false;
269 int ceiling_offset;
270
271 git_buf_free(repo_path);
272
273 if ((error = git_path_prettify_dir(&path, start_path, NULL)) < 0)
274 return error;
275
276 ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
277
278 if ((error = git_buf_joinpath(&path, path.ptr, DOT_GIT)) < 0)
279 return error;
280
fa6420f7 281 while (!error && !git_buf_len(repo_path)) {
7784bcbb
RB
282 if (p_stat(path.ptr, &st) == 0) {
283 /* check that we have not crossed device boundaries */
284 if (initial_device == 0)
285 initial_device = st.st_dev;
286 else if (st.st_dev != initial_device &&
287 (flags & GIT_REPOSITORY_OPEN_CROSS_FS) == 0)
288 break;
289
290 if (S_ISDIR(st.st_mode)) {
291 if (valid_repository_path(&path)) {
292 git_path_to_dir(&path);
293 git_buf_set(repo_path, path.ptr, path.size);
294 break;
295 }
296 }
297 else if (S_ISREG(st.st_mode)) {
298 git_buf repo_link = GIT_BUF_INIT;
299
300 if (!(error = read_gitfile(&repo_link, path.ptr))) {
301 if (valid_repository_path(&repo_link))
302 git_buf_swap(repo_path, &repo_link);
146f5c75
CMN
303
304 git_buf_free(&repo_link);
7784bcbb
RB
305 break;
306 }
307 git_buf_free(&repo_link);
308 }
309 }
310
311 /* move up one directory level */
312 if (git_path_dirname_r(&path, path.ptr) < 0) {
313 error = -1;
314 break;
315 }
316
317 if (try_with_dot_git) {
318 /* if we tried original dir with and without .git AND either hit
319 * directory ceiling or NO_SEARCH was requested, then be done.
320 */
321 if (path.ptr[ceiling_offset] == '\0' ||
322 (flags & GIT_REPOSITORY_OPEN_NO_SEARCH) != 0)
323 break;
324 /* otherwise look first for .git item */
325 error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
326 }
327 try_with_dot_git = !try_with_dot_git;
328 }
329
330 if (!error && parent_path != NULL) {
fa6420f7 331 if (!git_buf_len(repo_path))
7784bcbb
RB
332 git_buf_clear(parent_path);
333 else {
334 git_path_dirname_r(parent_path, path.ptr);
335 git_path_to_dir(parent_path);
336 }
337 if (git_buf_oom(parent_path))
338 return -1;
339 }
340
341 git_buf_free(&path);
342
fa6420f7 343 if (!git_buf_len(repo_path) && !error) {
cb8a7961 344 giterr_set(GITERR_REPOSITORY,
7784bcbb
RB
345 "Could not find repository from '%s'", start_path);
346 error = GIT_ENOTFOUND;
97769280 347 }
691aa968 348
7784bcbb
RB
349 return error;
350}
351
352int git_repository_open_ext(
353 git_repository **repo_ptr,
354 const char *start_path,
355 uint32_t flags,
356 const char *ceiling_dirs)
357{
358 int error;
359 git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT;
360 git_repository *repo;
361
362 *repo_ptr = NULL;
363
364 if ((error = find_repo(&path, &parent, start_path, flags, ceiling_dirs)) < 0)
365 return error;
366
e52ed7a5 367 repo = repository_alloc();
cb8a7961 368 GITERR_CHECK_ALLOC(repo);
691aa968 369
7784bcbb 370 repo->path_repository = git_buf_detach(&path);
cb8a7961 371 GITERR_CHECK_ALLOC(repo->path_repository);
691aa968 372
7784bcbb
RB
373 if ((error = load_config_data(repo)) < 0 ||
374 (error = load_workdir(repo, &parent)) < 0)
375 {
376 git_repository_free(repo);
377 return error;
378 }
691aa968 379
146f5c75 380 git_buf_free(&parent);
7784bcbb 381 *repo_ptr = repo;
cb8a7961 382 return 0;
7784bcbb 383}
97769280 384
7784bcbb
RB
385int git_repository_open(git_repository **repo_out, const char *path)
386{
387 return git_repository_open_ext(
388 repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL);
389}
390
391int git_repository_discover(
392 char *repository_path,
393 size_t size,
394 const char *start_path,
395 int across_fs,
396 const char *ceiling_dirs)
397{
398 git_buf path = GIT_BUF_INIT;
399 uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
400
401 assert(start_path && repository_path && size > 0);
402
403 *repository_path = '\0';
404
405 if (find_repo(&path, NULL, start_path, flags, ceiling_dirs) < 0)
406 return -1;
407
408 if (size < (size_t)(path.size + 1)) {
409 giterr_set(GITERR_REPOSITORY,
410 "The given buffer is too long to store the discovered path");
411 git_buf_free(&path);
412 return -1;
413 }
414
415 /* success: we discovered a repository */
416 git_buf_copy_cstr(repository_path, size, &path);
417 git_buf_free(&path);
418 return 0;
691aa968
VM
419}
420
9462c471 421static int load_config(
7784bcbb
RB
422 git_config **out,
423 git_repository *repo,
424 const char *global_config_path,
425 const char *system_config_path)
b22d1479 426{
97769280 427 git_buf config_path = GIT_BUF_INIT;
9462c471 428 git_config *cfg = NULL;
b22d1479 429
9462c471 430 assert(repo && out);
07ff8817 431
cb8a7961
VM
432 if (git_config_new(&cfg) < 0)
433 return -1;
b22d1479 434
cb8a7961
VM
435 if (git_buf_joinpath(
436 &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO) < 0)
437 goto on_error;
97769280 438
cb8a7961
VM
439 if (git_config_add_file_ondisk(cfg, config_path.ptr, 3) < 0)
440 goto on_error;
441
442 git_buf_free(&config_path);
b22d1479 443
40fe5fbe 444 if (global_config_path != NULL) {
cb8a7961
VM
445 if (git_config_add_file_ondisk(cfg, global_config_path, 2) < 0)
446 goto on_error;
b22d1479
CMN
447 }
448
07ff8817 449 if (system_config_path != NULL) {
cb8a7961
VM
450 if (git_config_add_file_ondisk(cfg, system_config_path, 1) < 0)
451 goto on_error;
9ba9e513
CMN
452 }
453
9462c471 454 *out = cfg;
cb8a7961 455 return 0;
b22d1479 456
cb8a7961
VM
457on_error:
458 git_buf_free(&config_path);
9462c471
VM
459 git_config_free(cfg);
460 *out = NULL;
cb8a7961 461 return -1;
b22d1479
CMN
462}
463
9462c471 464int git_repository_config__weakptr(git_config **out, git_repository *repo)
40fe5fbe 465{
9462c471 466 if (repo->_config == NULL) {
97769280 467 git_buf global_buf = GIT_BUF_INIT, system_buf = GIT_BUF_INIT;
cb8a7961 468 int res;
9462c471
VM
469
470 const char *global_config_path = NULL;
471 const char *system_config_path = NULL;
40fe5fbe 472
cb8a7961 473 if (git_config_find_global_r(&global_buf) == 0)
97769280 474 global_config_path = global_buf.ptr;
40fe5fbe 475
cb8a7961 476 if (git_config_find_system_r(&system_buf) == 0)
97769280 477 system_config_path = system_buf.ptr;
40fe5fbe 478
cb8a7961 479 res = load_config(&repo->_config, repo, global_config_path, system_config_path);
97769280
RB
480
481 git_buf_free(&global_buf);
482 git_buf_free(&system_buf);
483
cb8a7961
VM
484 if (res < 0)
485 return -1;
9462c471
VM
486
487 GIT_REFCOUNT_OWN(repo->_config, repo);
488 }
40fe5fbe 489
9462c471 490 *out = repo->_config;
cb8a7961 491 return 0;
40fe5fbe
CMN
492}
493
9462c471 494int git_repository_config(git_config **out, git_repository *repo)
fd0574e5 495{
cb8a7961
VM
496 if (git_repository_config__weakptr(out, repo) < 0)
497 return -1;
fd0574e5 498
cb8a7961
VM
499 GIT_REFCOUNT_INC(*out);
500 return 0;
9462c471
VM
501}
502
503void git_repository_set_config(git_repository *repo, git_config *config)
504{
505 assert(repo && config);
506
507 drop_config(repo);
508
509 repo->_config = config;
510 GIT_REFCOUNT_OWN(repo->_config, repo);
511}
512
513int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
514{
515 assert(repo && out);
516
517 if (repo->_odb == NULL) {
97769280 518 git_buf odb_path = GIT_BUF_INIT;
cb8a7961 519 int res;
9462c471 520
cb8a7961
VM
521 if (git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR) < 0)
522 return -1;
9462c471 523
cb8a7961 524 res = git_odb_open(&repo->_odb, odb_path.ptr);
97769280 525 git_buf_free(&odb_path); /* done with path */
cb8a7961
VM
526
527 if (res < 0)
528 return -1;
9462c471
VM
529
530 GIT_REFCOUNT_OWN(repo->_odb, repo);
531 }
fd0574e5 532
9462c471 533 *out = repo->_odb;
cb8a7961 534 return 0;
fd0574e5
RG
535}
536
9462c471 537int git_repository_odb(git_odb **out, git_repository *repo)
6fd195d7 538{
cb8a7961
VM
539 if (git_repository_odb__weakptr(out, repo) < 0)
540 return -1;
1795f879 541
cb8a7961
VM
542 GIT_REFCOUNT_INC(*out);
543 return 0;
9462c471 544}
6fd195d7 545
9462c471
VM
546void git_repository_set_odb(git_repository *repo, git_odb *odb)
547{
548 assert(repo && odb);
3315782c 549
9462c471 550 drop_odb(repo);
1795f879 551
9462c471
VM
552 repo->_odb = odb;
553 GIT_REFCOUNT_OWN(repo->_odb, repo);
baf861a5 554 GIT_REFCOUNT_INC(odb);
9462c471
VM
555}
556
557int git_repository_index__weakptr(git_index **out, git_repository *repo)
558{
559 assert(out && repo);
560
9462c471 561 if (repo->_index == NULL) {
cb8a7961 562 int res;
97769280 563 git_buf index_path = GIT_BUF_INIT;
9462c471 564
cb8a7961
VM
565 if (git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE) < 0)
566 return -1;
9462c471 567
cb8a7961 568 res = git_index_open(&repo->_index, index_path.ptr);
97769280 569 git_buf_free(&index_path); /* done with path */
cb8a7961
VM
570
571 if (res < 0)
572 return -1;
9462c471
VM
573
574 GIT_REFCOUNT_OWN(repo->_index, repo);
575 }
576
9462c471 577 *out = repo->_index;
cb8a7961 578 return 0;
9462c471 579}
1795f879 580
9462c471
VM
581int git_repository_index(git_index **out, git_repository *repo)
582{
cb8a7961
VM
583 if (git_repository_index__weakptr(out, repo) < 0)
584 return -1;
9462c471 585
cb8a7961
VM
586 GIT_REFCOUNT_INC(*out);
587 return 0;
3315782c
VM
588}
589
9462c471
VM
590void git_repository_set_index(git_repository *repo, git_index *index)
591{
592 assert(repo && index);
593
594 drop_index(repo);
595
596 repo->_index = index;
597 GIT_REFCOUNT_OWN(repo->_index, repo);
c1aefb35 598 GIT_REFCOUNT_INC(index);
9462c471
VM
599}
600
5663e61a 601static int check_repositoryformatversion(git_repository *repo)
40c44d2f 602{
5663e61a 603 git_config *config;
cb8a7961 604 int version;
5663e61a 605
cb8a7961
VM
606 if (git_repository_config__weakptr(&config, repo) < 0)
607 return -1;
5663e61a 608
cb8a7961
VM
609 if (git_config_get_int32(config, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, &version) < 0)
610 return -1;
5663e61a 611
cb8a7961
VM
612 if (GIT_REPOSITORYFORMATVERSION < version) {
613 giterr_set(GITERR_REPOSITORY,
614 "Unsupported repository version %d. Only versions up to %d are supported.",
615 version, GIT_REPOSITORYFORMATVERSION);
616 return -1;
617 }
5663e61a 618
cb8a7961 619 return 0;
5663e61a 620}
621
622static int repo_init_reinit(git_repository **repo_out, const char *repository_path, int is_bare)
623{
5663e61a 624 git_repository *repo = NULL;
625
cb8a7961 626 GIT_UNUSED(is_bare);
5663e61a 627
cb8a7961
VM
628 if (git_repository_open(&repo, repository_path) < 0)
629 return -1;
630
631 if (check_repositoryformatversion(repo) < 0) {
632 git_repository_free(repo);
633 return -1;
634 }
5663e61a 635
636 /* TODO: reinitialize the templates */
637
638 *repo_out = repo;
cb8a7961 639 return 0;
4b8e27c8 640}
641
9462c471 642static int repo_init_createhead(const char *git_dir)
e1f8cad0 643{
97769280 644 git_buf ref_path = GIT_BUF_INIT;
9462c471
VM
645 git_filebuf ref = GIT_FILEBUF_INIT;
646
cb8a7961
VM
647 if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
648 git_filebuf_open(&ref, ref_path.ptr, 0) < 0 ||
649 git_filebuf_printf(&ref, "ref: refs/heads/master\n") < 0 ||
650 git_filebuf_commit(&ref, GIT_REFS_FILE_MODE) < 0)
651 return -1;
9462c471 652
97769280 653 git_buf_free(&ref_path);
cb8a7961 654 return 0;
9462c471
VM
655}
656
657static int repo_init_config(const char *git_dir, int is_bare)
658{
97769280
RB
659 git_buf cfg_path = GIT_BUF_INIT;
660 git_config *config = NULL;
9462c471
VM
661
662#define SET_REPO_CONFIG(type, name, val) {\
cb8a7961
VM
663 if (git_config_set_##type(config, name, val) < 0) { \
664 git_buf_free(&cfg_path); \
665 git_config_free(config); \
666 return -1; } \
9462c471
VM
667}
668
cb8a7961
VM
669 if (git_buf_joinpath(&cfg_path, git_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
670 return -1;
9462c471 671
cb8a7961
VM
672 if (git_config_open_ondisk(&config, cfg_path.ptr) < 0) {
673 git_buf_free(&cfg_path);
674 return -1;
675 }
9462c471
VM
676
677 SET_REPO_CONFIG(bool, "core.bare", is_bare);
5663e61a 678 SET_REPO_CONFIG(int32, GIT_CONFIG_CORE_REPOSITORYFORMATVERSION, GIT_REPOSITORYFORMATVERSION);
9462c471
VM
679 /* TODO: what other defaults? */
680
97769280 681 git_buf_free(&cfg_path);
9462c471 682 git_config_free(config);
cb8a7961 683 return 0;
d2d6912e 684}
e1f8cad0 685
ed72182b 686static int repo_init_structure(const char *git_dir, int is_bare)
4b8e27c8 687{
cb8a7961 688 int i;
97769280
RB
689 struct { const char *dir; mode_t mode; } dirs[] = {
690 { GIT_OBJECTS_INFO_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/info/' */
691 { GIT_OBJECTS_PACK_DIR, GIT_OBJECT_DIR_MODE }, /* '/objects/pack/' */
692 { GIT_REFS_HEADS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/heads/' */
693 { GIT_REFS_TAGS_DIR, GIT_REFS_DIR_MODE }, /* '/refs/tags/' */
694 { NULL, 0 }
695 };
696
697 /* Make the base directory */
cb8a7961
VM
698 if (git_futils_mkdir_r(git_dir, NULL, is_bare ? GIT_BARE_DIR_MODE : GIT_DIR_MODE) < 0)
699 return -1;
a67a096a 700
6ac91dfe 701 /* Hides the ".git" directory */
ed72182b 702 if (!is_bare) {
17837602 703#ifdef GIT_WIN32
cb8a7961
VM
704 if (p_hide_directory__w32(git_dir) < 0) {
705 giterr_set(GITERR_REPOSITORY,
706 "Failed to mark Git repository folder as hidden");
707 return -1;
708 }
6ac91dfe 709#endif
17837602 710 }
6ac91dfe 711
97769280
RB
712 /* Make subdirectories as needed */
713 for (i = 0; dirs[i].dir != NULL; ++i) {
cb8a7961
VM
714 if (git_futils_mkdir_r(dirs[i].dir, git_dir, dirs[i].mode) < 0)
715 return -1;
97769280 716 }
1c2c7c0d 717
40c44d2f 718 /* TODO: what's left? templates? */
cb8a7961 719 return 0;
4b8e27c8 720}
721
40c44d2f 722int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare)
4b8e27c8 723{
97769280 724 git_buf repository_path = GIT_BUF_INIT;
932d1baf 725
4b8e27c8 726 assert(repo_out && path);
727
cb8a7961
VM
728 if (git_buf_joinpath(&repository_path, path, is_bare ? "" : GIT_DIR) < 0)
729 return -1;
4b8e27c8 730
1a481123 731 if (git_path_isdir(repository_path.ptr) == true) {
cb8a7961
VM
732 if (valid_repository_path(&repository_path) == true) {
733 int res = repo_init_reinit(repo_out, repository_path.ptr, is_bare);
97769280 734 git_buf_free(&repository_path);
cb8a7961 735 return res;
97769280 736 }
1bc83ff1 737 }
d2d6912e 738
cb8a7961
VM
739 if (repo_init_structure(repository_path.ptr, is_bare) < 0 ||
740 repo_init_config(repository_path.ptr, is_bare) < 0 ||
741 repo_init_createhead(repository_path.ptr) < 0 ||
742 git_repository_open(repo_out, repository_path.ptr) < 0) {
743 git_buf_free(&repository_path);
744 return -1;
745 }
d2d6912e 746
97769280 747 git_buf_free(&repository_path);
cb8a7961 748 return 0;
40c44d2f 749}
35502d2e 750
c682886e 751int git_repository_head_detached(git_repository *repo)
35502d2e
CMN
752{
753 git_reference *ref;
9462c471 754 git_odb *odb = NULL;
cb8a7961 755 int exists;
9462c471 756
cb8a7961
VM
757 if (git_repository_odb__weakptr(&odb, repo) < 0)
758 return -1;
35502d2e 759
cb8a7961
VM
760 if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
761 return -1;
35502d2e 762
75abd2b9
MS
763 if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
764 git_reference_free(ref);
35502d2e 765 return 0;
75abd2b9 766 }
35502d2e 767
cb8a7961 768 exists = git_odb_exists(odb, git_reference_oid(ref));
75abd2b9
MS
769
770 git_reference_free(ref);
cb8a7961 771 return exists;
35502d2e
CMN
772}
773
3601c4bf 774int git_repository_head(git_reference **head_out, git_repository *repo)
35502d2e 775{
f201d613 776 return git_reference_lookup_resolved(head_out, repo, GIT_HEAD_FILE, -1);
3601c4bf 777}
778
779int git_repository_head_orphan(git_repository *repo)
780{
cb8a7961 781 git_reference *ref = NULL;
3601c4bf 782 int error;
783
784 error = git_repository_head(&ref, repo);
cb8a7961 785 git_reference_free(ref);
35502d2e 786
cb8a7961
VM
787 if (error == GIT_ENOTFOUND)
788 return 1;
75abd2b9 789
cb8a7961
VM
790 if (error < 0)
791 return -1;
792
793 return 0;
35502d2e 794}
e0011be3 795
41233c40
VM
796int git_repository_is_empty(git_repository *repo)
797{
d4a0b124 798 git_reference *head = NULL, *branch = NULL;
41233c40
VM
799 int error;
800
cb8a7961
VM
801 if (git_reference_lookup(&head, repo, "HEAD") < 0)
802 return -1;
41233c40 803
75abd2b9
MS
804 if (git_reference_type(head) != GIT_REF_SYMBOLIC) {
805 git_reference_free(head);
0f489fb2 806 return 0;
75abd2b9 807 }
0f489fb2 808
75abd2b9
MS
809 if (strcmp(git_reference_target(head), "refs/heads/master") != 0) {
810 git_reference_free(head);
0f489fb2 811 return 0;
75abd2b9 812 }
41233c40 813
0f489fb2 814 error = git_reference_resolve(&branch, head);
75abd2b9
MS
815
816 git_reference_free(head);
817 git_reference_free(branch);
818
cb8a7961
VM
819 if (error == GIT_ENOTFOUND)
820 return 1;
821
822 if (error < 0)
823 return -1;
824
825 return 0;
41233c40
VM
826}
827
9462c471 828const char *git_repository_path(git_repository *repo)
4a34b3a9 829{
830 assert(repo);
9462c471
VM
831 return repo->path_repository;
832}
4a34b3a9 833
9462c471
VM
834const char *git_repository_workdir(git_repository *repo)
835{
836 assert(repo);
602ee38b 837
9462c471
VM
838 if (repo->is_bare)
839 return NULL;
602ee38b 840
9462c471
VM
841 return repo->workdir;
842}
602ee38b 843
9462c471
VM
844int git_repository_set_workdir(git_repository *repo, const char *workdir)
845{
b78fb64d 846 git_buf path = GIT_BUF_INIT;
847
9462c471 848 assert(repo && workdir);
602ee38b 849
b78fb64d 850 if (git_path_prettify_dir(&path, workdir, NULL) < 0)
851 return -1;
9462c471 852
2bc8fa02 853 git__free(repo->workdir);
9462c471 854
b78fb64d 855 repo->workdir = git_buf_detach(&path);
9462c471 856 repo->is_bare = 0;
0d0fa7c3 857 return 0;
4a34b3a9 858}
fa9bcd81 859
860int git_repository_is_bare(git_repository *repo)
861{
862 assert(repo);
863 return repo->is_bare;
864}