]> git.proxmox.com Git - libgit2.git/blame - src/repository.c
Fix formatting
[libgit2.git] / src / repository.c
CommitLineData
3315782c 1/*
359fc2d2 2 * Copyright (C) the libgit2 contributors. All rights reserved.
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 */
7784bcbb 7#include <ctype.h>
3315782c 8
44908fe7 9#include "git2/object.h"
d00d5464 10#include "git2/refdb.h"
1384b688 11#include "git2/sys/repository.h"
d12299fe 12
3315782c
VM
13#include "common.h"
14#include "repository.h"
15#include "commit.h"
16#include "tag.h"
237da401 17#include "blob.h"
6fd195d7 18#include "fileops.h"
83634d38 19#include "sysdir.h"
114f5a6c
RB
20#include "filebuf.h"
21#include "index.h"
b22d1479 22#include "config.h"
9282e921 23#include "refs.h"
47bfa0be
RB
24#include "filter.h"
25#include "odb.h"
096d9e94 26#include "remote.h"
632d8b23 27#include "merge.h"
114f5a6c 28#include "diff_driver.h"
62d38a1d 29#include "annotated_commit.h"
9282e921 30
c2c81615
PK
31#ifdef GIT_WIN32
32# include "win32/w32_util.h"
33#endif
34
16c73d38
CMN
35static int check_repositoryformatversion(git_config *config);
36
7784bcbb 37#define GIT_FILE_CONTENT_PREFIX "gitdir:"
6a01b6bd 38
28990938 39#define GIT_BRANCH_MASTER "master"
40
29e948de 41#define GIT_REPO_VERSION 0
691aa968 42
4196dd8e
ET
43git_buf git_repository__reserved_names_win32[] = {
44 { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
45 { GIT_DIR_SHORTNAME, 0, CONST_STRLEN(GIT_DIR_SHORTNAME) }
46};
47size_t git_repository__reserved_names_win32_len = 2;
48
49git_buf git_repository__reserved_names_posix[] = {
50 { DOT_GIT, 0, CONST_STRLEN(DOT_GIT) },
51};
52size_t git_repository__reserved_names_posix_len = 1;
a64119e3 53
e976b56d 54static void set_odb(git_repository *repo, git_odb *odb)
9462c471 55{
e976b56d
RB
56 if (odb) {
57 GIT_REFCOUNT_OWN(odb, repo);
58 GIT_REFCOUNT_INC(odb);
59 }
60
61 if ((odb = git__swap(repo->_odb, odb)) != NULL) {
62 GIT_REFCOUNT_OWN(odb, NULL);
63 git_odb_free(odb);
eb2f3b47 64 }
9462c471 65}
691aa968 66
e976b56d 67static void set_refdb(git_repository *repo, git_refdb *refdb)
d00d5464 68{
e976b56d
RB
69 if (refdb) {
70 GIT_REFCOUNT_OWN(refdb, repo);
71 GIT_REFCOUNT_INC(refdb);
72 }
73
74 if ((refdb = git__swap(repo->_refdb, refdb)) != NULL) {
75 GIT_REFCOUNT_OWN(refdb, NULL);
76 git_refdb_free(refdb);
d00d5464
ET
77 }
78}
79
e976b56d 80static void set_config(git_repository *repo, git_config *config)
9462c471 81{
e976b56d
RB
82 if (config) {
83 GIT_REFCOUNT_OWN(config, repo);
84 GIT_REFCOUNT_INC(config);
85 }
86
87 if ((config = git__swap(repo->_config, config)) != NULL) {
88 GIT_REFCOUNT_OWN(config, NULL);
89 git_config_free(config);
eb2f3b47 90 }
e976b56d
RB
91
92 git_repository__cvar_cache_clear(repo);
691aa968
VM
93}
94
e976b56d 95static void set_index(git_repository *repo, git_index *index)
6fd195d7 96{
e976b56d
RB
97 if (index) {
98 GIT_REFCOUNT_OWN(index, repo);
99 GIT_REFCOUNT_INC(index);
100 }
101
102 if ((index = git__swap(repo->_index, index)) != NULL) {
103 GIT_REFCOUNT_OWN(index, NULL);
104 git_index_free(index);
9462c471 105 }
e0011be3
VM
106}
107
879458e7 108void git_repository__cleanup(git_repository *repo)
e0011be3 109{
879458e7 110 assert(repo);
6fd195d7 111
879458e7 112 git_cache_clear(&repo->objects);
73b51450 113 git_attr_cache_flush(repo);
6fd195d7 114
e976b56d
RB
115 set_config(repo, NULL);
116 set_index(repo, NULL);
117 set_odb(repo, NULL);
118 set_refdb(repo, NULL);
879458e7
VM
119}
120
121void git_repository_free(git_repository *repo)
122{
4196dd8e
ET
123 size_t i;
124
879458e7
VM
125 if (repo == NULL)
126 return;
127
128 git_repository__cleanup(repo);
129
130 git_cache_free(&repo->objects);
3eadfecd 131
114f5a6c 132 git_diff_driver_registry_free(repo->diff_drivers);
3eadfecd 133 repo->diff_drivers = NULL;
9462c471 134
4196dd8e
ET
135 for (i = 0; i < repo->reserved_names.size; i++)
136 git_buf_free(git_array_get(repo->reserved_names, i));
78db0239 137 git_array_clear(repo->reserved_names);
4196dd8e 138
78db0239 139 git__free(repo->path_gitlink);
53607868
RB
140 git__free(repo->path_repository);
141 git__free(repo->workdir);
bade5194 142 git__free(repo->namespace);
659cf202
CMN
143 git__free(repo->ident_name);
144 git__free(repo->ident_email);
53607868 145
6de9b2ee 146 git__memzero(repo, sizeof(*repo));
9462c471 147 git__free(repo);
6fd195d7
VM
148}
149
9462c471
VM
150/*
151 * Git repository open methods
152 *
153 * Open a repository object from its path
154 */
cb8a7961 155static bool valid_repository_path(git_buf *repository_path)
5ad739e8 156{
97769280 157 /* Check OBJECTS_DIR first, since it will generate the longest path name */
1a481123 158 if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false)
cb8a7961 159 return false;
5ad739e8 160
97769280 161 /* Ensure HEAD file exists */
1a481123 162 if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false)
cb8a7961 163 return false;
5ad739e8 164
1a481123 165 if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false)
cb8a7961 166 return false;
5ad739e8 167
cb8a7961 168 return true;
5ad739e8
VM
169}
170
51d00446 171static git_repository *repository_alloc(void)
3315782c 172{
3e9e6cda 173 git_repository *repo = git__calloc(1, sizeof(git_repository));
3315782c 174
4196dd8e
ET
175 if (repo == NULL ||
176 git_cache_init(&repo->objects) < 0)
177 goto on_error;
178
179 git_array_init_to_size(repo->reserved_names, 4);
180 if (!repo->reserved_names.ptr)
181 goto on_error;
3315782c 182
f2c25d18
VM
183 /* set all the entries in the cvar cache to `unset` */
184 git_repository__cvar_cache_clear(repo);
185
6fd195d7 186 return repo;
4196dd8e
ET
187
188on_error:
189 if (repo)
190 git_cache_free(&repo->objects);
191
192 git__free(repo);
193 return NULL;
6fd195d7
VM
194}
195
7cc3c920
JW
196int git_repository_new(git_repository **out)
197{
770aca94
ET
198 git_repository *repo;
199
200 *out = repo = repository_alloc();
201 GITERR_CHECK_ALLOC(repo);
202
203 repo->is_bare = 1;
204
7cc3c920
JW
205 return 0;
206}
207
29c4cb09 208static int load_config_data(git_repository *repo, const git_config *config)
ec3c7a16 209{
cb8a7961 210 int is_bare;
ec3c7a16 211
d3e9c4a5 212 /* Try to figure out if it's bare, default to non-bare if it's not set */
29e948de 213 if (git_config_get_bool(&is_bare, config, "core.bare") < 0)
d3e9c4a5
CMN
214 repo->is_bare = 0;
215 else
216 repo->is_bare = is_bare;
c94785a9 217
cb8a7961 218 return 0;
9462c471 219}
ec3c7a16 220
29c4cb09 221static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path)
9462c471 222{
7784bcbb 223 int error;
9a97f49e 224 git_config_entry *ce;
9f77b3f6 225 git_buf worktree = GIT_BUF_INIT;
ec3c7a16 226
97769280 227 if (repo->is_bare)
cb8a7961 228 return 0;
ec3c7a16 229
9f77b3f6
RB
230 if ((error = git_config__lookup_entry(
231 &ce, config, "core.worktree", false)) < 0)
232 return error;
ec3c7a16 233
9f77b3f6
RB
234 if (ce && ce->value) {
235 if ((error = git_path_prettify_dir(
236 &worktree, ce->value, repo->path_repository)) < 0)
9a97f49e 237 goto cleanup;
9f77b3f6
RB
238
239 repo->workdir = git_buf_detach(&worktree);
5f4a61ae 240 }
9f77b3f6
RB
241 else if (parent_path && git_path_isdir(parent_path->ptr))
242 repo->workdir = git_buf_detach(parent_path);
7784bcbb 243 else {
9f77b3f6 244 if (git_path_dirname_r(&worktree, repo->path_repository) < 0 ||
9a97f49e
CMN
245 git_path_to_dir(&worktree) < 0) {
246 error = -1;
247 goto cleanup;
248 }
9f77b3f6
RB
249
250 repo->workdir = git_buf_detach(&worktree);
7784bcbb
RB
251 }
252
253 GITERR_CHECK_ALLOC(repo->workdir);
9a97f49e
CMN
254cleanup:
255 git_config_entry_free(ce);
256 return error;
ec3c7a16
VM
257}
258
7784bcbb
RB
259/*
260 * This function returns furthest offset into path where a ceiling dir
261 * is found, so we can stop processing the path at that point.
262 *
263 * Note: converting this to use git_bufs instead of GIT_PATH_MAX buffers on
264 * the stack could remove directories name limits, but at the cost of doing
265 * repeated malloc/frees inside the loop below, so let's not do it now.
266 */
b118f647 267static size_t find_ceiling_dir_offset(
7784bcbb
RB
268 const char *path,
269 const char *ceiling_directories)
270{
271 char buf[GIT_PATH_MAX + 1];
272 char buf2[GIT_PATH_MAX + 1];
273 const char *ceil, *sep;
44ef8b1b 274 size_t len, max_len = 0, min_len;
7784bcbb
RB
275
276 assert(path);
277
44ef8b1b 278 min_len = (size_t)(git_path_root(path) + 1);
7784bcbb
RB
279
280 if (ceiling_directories == NULL || min_len == 0)
b118f647 281 return min_len;
7784bcbb
RB
282
283 for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
284 for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
285 len = sep - ceil;
286
44ef8b1b 287 if (len == 0 || len >= sizeof(buf) || git_path_root(ceil) == -1)
7784bcbb
RB
288 continue;
289
290 strncpy(buf, ceil, len);
291 buf[len] = '\0';
292
293 if (p_realpath(buf, buf2) == NULL)
294 continue;
295
296 len = strlen(buf2);
297 if (len > 0 && buf2[len-1] == '/')
298 buf[--len] = '\0';
299
300 if (!strncmp(path, buf2, len) &&
3fe046cf 301 (path[len] == '/' || !path[len]) &&
7784bcbb
RB
302 len > max_len)
303 {
304 max_len = len;
305 }
306 }
307
b118f647 308 return (max_len <= min_len ? min_len : max_len);
7784bcbb
RB
309}
310
311/*
312 * Read the contents of `file_path` and set `path_out` to the repo dir that
313 * it points to. Before calling, set `path_out` to the base directory that
314 * should be used if the contents of `file_path` are a relative path.
315 */
316static int read_gitfile(git_buf *path_out, const char *file_path)
317{
318 int error = 0;
319 git_buf file = GIT_BUF_INIT;
320 size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX);
321
322 assert(path_out && file_path);
323
324 if (git_futils_readbuffer(&file, file_path) < 0)
325 return -1;
326
327 git_buf_rtrim(&file);
6b415f62
RB
328 /* apparently on Windows, some people use backslashes in paths */
329 git_path_mkposix(file.ptr);
7784bcbb 330
662880ca
RB
331 if (git_buf_len(&file) <= prefix_len ||
332 memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0)
7784bcbb 333 {
6b415f62 334 giterr_set(GITERR_REPOSITORY,
909d5494 335 "the `.git` file at '%s' is malformed", file_path);
7784bcbb
RB
336 error = -1;
337 }
338 else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) {
662880ca 339 const char *gitlink = git_buf_cstr(&file) + prefix_len;
0f49200c 340 while (*gitlink && git__isspace(*gitlink)) gitlink++;
6b415f62 341
662880ca
RB
342 error = git_path_prettify_dir(
343 path_out, gitlink, git_buf_cstr(path_out));
7784bcbb
RB
344 }
345
346 git_buf_free(&file);
347 return error;
348}
349
350static int find_repo(
351 git_buf *repo_path,
352 git_buf *parent_path,
4196dd8e 353 git_buf *link_path,
7784bcbb
RB
354 const char *start_path,
355 uint32_t flags,
356 const char *ceiling_dirs)
691aa968 357{
7784bcbb
RB
358 int error;
359 git_buf path = GIT_BUF_INIT;
2b490284 360 git_buf repo_link = GIT_BUF_INIT;
7784bcbb
RB
361 struct stat st;
362 dev_t initial_device = 0;
ed577134
JT
363 int min_iterations;
364 bool in_dot_git;
b118f647 365 size_t ceiling_offset = 0;
7784bcbb
RB
366
367 git_buf_free(repo_path);
368
2b490284
JT
369 error = git_path_prettify(&path, start_path, NULL);
370 if (error < 0)
7784bcbb
RB
371 return error;
372
ed577134
JT
373 /* in_dot_git toggles each loop:
374 * /a/b/c/.git, /a/b/c, /a/b/.git, /a/b, /a/.git, /a
39c6fca3
JT
375 * With GIT_REPOSITORY_OPEN_BARE or GIT_REPOSITORY_OPEN_NO_DOTGIT, we
376 * assume we started with /a/b/c.git and don't append .git the first
377 * time through.
ed577134
JT
378 * min_iterations indicates the number of iterations left before going
379 * further counts as a search. */
39c6fca3 380 if (flags & (GIT_REPOSITORY_OPEN_BARE | GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
ed577134
JT
381 in_dot_git = true;
382 min_iterations = 1;
383 } else {
384 in_dot_git = false;
385 min_iterations = 2;
386 }
7784bcbb 387
2b490284 388 for (;;) {
39c6fca3 389 if (!(flags & GIT_REPOSITORY_OPEN_NO_DOTGIT)) {
2b490284
JT
390 if (!in_dot_git) {
391 error = git_buf_joinpath(&path, path.ptr, DOT_GIT);
392 if (error < 0)
39c6fca3 393 break;
2b490284 394 }
39c6fca3
JT
395 in_dot_git = !in_dot_git;
396 }
7784bcbb 397
7784bcbb
RB
398 if (p_stat(path.ptr, &st) == 0) {
399 /* check that we have not crossed device boundaries */
400 if (initial_device == 0)
401 initial_device = st.st_dev;
402 else if (st.st_dev != initial_device &&
2b490284 403 !(flags & GIT_REPOSITORY_OPEN_CROSS_FS))
7784bcbb
RB
404 break;
405
406 if (S_ISDIR(st.st_mode)) {
407 if (valid_repository_path(&path)) {
408 git_path_to_dir(&path);
409 git_buf_set(repo_path, path.ptr, path.size);
410 break;
411 }
412 }
0f316096 413 else if (S_ISREG(st.st_mode) && git__suffixcmp(path.ptr, "/" DOT_GIT) == 0) {
2b490284
JT
414 error = read_gitfile(&repo_link, path.ptr);
415 if (error < 0)
7784bcbb 416 break;
2b490284
JT
417 if (valid_repository_path(&repo_link)) {
418 git_buf_swap(repo_path, &repo_link);
419
420 if (link_path)
421 error = git_buf_put(link_path, path.ptr, path.size);
7784bcbb 422 }
2b490284 423 break;
7784bcbb
RB
424 }
425 }
426
2b490284
JT
427 /* Move up one directory. If we're in_dot_git, we'll search the
428 * parent itself next. If we're !in_dot_git, we'll search .git
429 * in the parent directory next (added at the top of the loop). */
7784bcbb
RB
430 if (git_path_dirname_r(&path, path.ptr) < 0) {
431 error = -1;
432 break;
433 }
434
ed577134
JT
435 /* Once we've checked the directory (and .git if applicable),
436 * find the ceiling for a search. */
437 if (min_iterations && (--min_iterations == 0))
438 ceiling_offset = find_ceiling_dir_offset(path.ptr, ceiling_dirs);
2b490284
JT
439
440 /* Check if we should stop searching here. */
441 if (min_iterations == 0
442 && (path.ptr[ceiling_offset] == 0
443 || (flags & GIT_REPOSITORY_OPEN_NO_SEARCH)))
444 break;
7784bcbb
RB
445 }
446
3fe046cf 447 if (!error && parent_path && !(flags & GIT_REPOSITORY_OPEN_BARE)) {
fa6420f7 448 if (!git_buf_len(repo_path))
7784bcbb
RB
449 git_buf_clear(parent_path);
450 else {
451 git_path_dirname_r(parent_path, path.ptr);
452 git_path_to_dir(parent_path);
453 }
454 if (git_buf_oom(parent_path))
455 return -1;
456 }
457
2b490284
JT
458 /* If we didn't find the repository, and we don't have any other error
459 * to report, report that. */
fa6420f7 460 if (!git_buf_len(repo_path) && !error) {
cb8a7961 461 giterr_set(GITERR_REPOSITORY,
909d5494 462 "could not find repository from '%s'", start_path);
904b67e6 463 error = GIT_ENOTFOUND;
97769280 464 }
691aa968 465
2b490284
JT
466 git_buf_free(&path);
467 git_buf_free(&repo_link);
7784bcbb
RB
468 return error;
469}
470
a442ed68
VM
471int git_repository_open_bare(
472 git_repository **repo_ptr,
473 const char *bare_path)
474{
475 int error;
476 git_buf path = GIT_BUF_INIT;
477 git_repository *repo = NULL;
478
479 if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0)
480 return error;
481
482 if (!valid_repository_path(&path)) {
483 git_buf_free(&path);
909d5494 484 giterr_set(GITERR_REPOSITORY, "path is not a repository: %s", bare_path);
a442ed68
VM
485 return GIT_ENOTFOUND;
486 }
487
488 repo = repository_alloc();
489 GITERR_CHECK_ALLOC(repo);
490
491 repo->path_repository = git_buf_detach(&path);
492 GITERR_CHECK_ALLOC(repo->path_repository);
493
494 /* of course we're bare! */
495 repo->is_bare = 1;
496 repo->workdir = NULL;
497
498 *repo_ptr = repo;
499 return 0;
500}
501
0dd98b69
JT
502static int _git_repository_open_ext_from_env(
503 git_repository **out,
504 const char *start_path)
505{
506 git_repository *repo = NULL;
507 git_index *index = NULL;
508 git_odb *odb = NULL;
509 git_buf dir_buf = GIT_BUF_INIT;
510 git_buf ceiling_dirs_buf = GIT_BUF_INIT;
511 git_buf across_fs_buf = GIT_BUF_INIT;
512 git_buf index_file_buf = GIT_BUF_INIT;
513 git_buf namespace_buf = GIT_BUF_INIT;
514 git_buf object_dir_buf = GIT_BUF_INIT;
515 git_buf alts_buf = GIT_BUF_INIT;
516 git_buf work_tree_buf = GIT_BUF_INIT;
517 git_buf common_dir_buf = GIT_BUF_INIT;
518 const char *ceiling_dirs = NULL;
519 unsigned flags = 0;
520 int error;
521
522 if (!start_path) {
523 error = git__getenv(&dir_buf, "GIT_DIR");
524 if (error == GIT_ENOTFOUND) {
525 giterr_clear();
526 start_path = ".";
527 } else if (error < 0)
528 goto error;
529 else {
530 start_path = git_buf_cstr(&dir_buf);
531 flags |= GIT_REPOSITORY_OPEN_NO_SEARCH;
532 flags |= GIT_REPOSITORY_OPEN_NO_DOTGIT;
533 }
534 }
535
536 error = git__getenv(&ceiling_dirs_buf, "GIT_CEILING_DIRECTORIES");
537 if (error == GIT_ENOTFOUND)
538 giterr_clear();
539 else if (error < 0)
540 goto error;
541 else
542 ceiling_dirs = git_buf_cstr(&ceiling_dirs_buf);
543
544 error = git__getenv(&across_fs_buf, "GIT_DISCOVERY_ACROSS_FILESYSTEM");
545 if (error == GIT_ENOTFOUND)
546 giterr_clear();
547 else if (error < 0)
548 goto error;
549 else {
550 int across_fs = 0;
551 error = git_config_parse_bool(&across_fs, git_buf_cstr(&across_fs_buf));
552 if (error < 0)
553 goto error;
554 if (across_fs)
555 flags |= GIT_REPOSITORY_OPEN_CROSS_FS;
556 }
557
558 error = git__getenv(&index_file_buf, "GIT_INDEX_FILE");
559 if (error == GIT_ENOTFOUND)
560 giterr_clear();
561 else if (error < 0)
562 goto error;
563 else {
564 error = git_index_open(&index, git_buf_cstr(&index_file_buf));
565 if (error < 0)
566 goto error;
567 }
568
569 error = git__getenv(&namespace_buf, "GIT_NAMESPACE");
570 if (error == GIT_ENOTFOUND)
571 giterr_clear();
572 else if (error < 0)
573 goto error;
574
575 error = git__getenv(&object_dir_buf, "GIT_OBJECT_DIRECTORY");
576 if (error == GIT_ENOTFOUND)
577 giterr_clear();
578 else if (error < 0)
579 goto error;
580 else {
581 error = git_odb_open(&odb, git_buf_cstr(&object_dir_buf));
582 if (error < 0)
583 goto error;
584 }
585
586 error = git__getenv(&work_tree_buf, "GIT_WORK_TREE");
587 if (error == GIT_ENOTFOUND)
588 giterr_clear();
589 else if (error < 0)
590 goto error;
591 else {
592 giterr_set(GITERR_INVALID, "GIT_WORK_TREE unimplemented");
593 error = GIT_ERROR;
594 goto error;
595 }
596
597 error = git__getenv(&work_tree_buf, "GIT_COMMON_DIR");
598 if (error == GIT_ENOTFOUND)
599 giterr_clear();
600 else if (error < 0)
601 goto error;
602 else {
603 giterr_set(GITERR_INVALID, "GIT_COMMON_DIR unimplemented");
604 error = GIT_ERROR;
605 goto error;
606 }
607
608 error = git_repository_open_ext(&repo, start_path, flags, ceiling_dirs);
609 if (error < 0)
610 goto error;
611
612 if (odb)
613 git_repository_set_odb(repo, odb);
614
615 error = git__getenv(&alts_buf, "GIT_ALTERNATE_OBJECT_DIRECTORIES");
c9e967a1 616 if (error == GIT_ENOTFOUND) {
0dd98b69 617 giterr_clear();
c9e967a1
JT
618 error = 0;
619 } else if (error < 0)
0dd98b69
JT
620 goto error;
621 else {
622 const char *end;
623 char *alt, *sep;
624 if (!odb) {
625 error = git_repository_odb(&odb, repo);
626 if (error < 0)
627 goto error;
628 }
629
630 end = git_buf_cstr(&alts_buf) + git_buf_len(&alts_buf);
631 for (sep = alt = alts_buf.ptr; sep != end; alt = sep+1) {
632 for (sep = alt; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++)
633 ;
634 if (*sep)
635 *sep = '\0';
636 error = git_odb_add_disk_alternate(odb, alt);
637 if (error < 0)
638 goto error;
639 }
640 }
641
c9e967a1
JT
642 if (git_buf_len(&namespace_buf)) {
643 error = git_repository_set_namespace(repo, git_buf_cstr(&namespace_buf));
644 if (error < 0)
645 goto error;
646 }
0dd98b69
JT
647
648 git_repository_set_index(repo, index);
649
650 if (out) {
651 *out = repo;
652 goto success;
653 }
654error:
655 git_repository_free(repo);
656success:
657 git_odb_free(odb);
658 git_index_free(index);
659 git_buf_free(&common_dir_buf);
660 git_buf_free(&work_tree_buf);
661 git_buf_free(&alts_buf);
662 git_buf_free(&object_dir_buf);
663 git_buf_free(&namespace_buf);
664 git_buf_free(&index_file_buf);
665 git_buf_free(&across_fs_buf);
666 git_buf_free(&ceiling_dirs_buf);
667 git_buf_free(&dir_buf);
668 return error;
669}
670
7784bcbb
RB
671int git_repository_open_ext(
672 git_repository **repo_ptr,
673 const char *start_path,
c9fc4a6f 674 unsigned int flags,
7784bcbb
RB
675 const char *ceiling_dirs)
676{
677 int error;
4196dd8e
ET
678 git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT,
679 link_path = GIT_BUF_INIT;
7784bcbb 680 git_repository *repo;
16c73d38 681 git_config *config = NULL;
7784bcbb 682
0dd98b69
JT
683 if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
684 return _git_repository_open_ext_from_env(repo_ptr, start_path);
685
662880ca
RB
686 if (repo_ptr)
687 *repo_ptr = NULL;
7784bcbb 688
4196dd8e
ET
689 error = find_repo(
690 &path, &parent, &link_path, start_path, flags, ceiling_dirs);
691
662880ca 692 if (error < 0 || !repo_ptr)
7784bcbb
RB
693 return error;
694
e52ed7a5 695 repo = repository_alloc();
cb8a7961 696 GITERR_CHECK_ALLOC(repo);
691aa968 697
7784bcbb 698 repo->path_repository = git_buf_detach(&path);
cb8a7961 699 GITERR_CHECK_ALLOC(repo->path_repository);
691aa968 700
4196dd8e
ET
701 if (link_path.size) {
702 repo->path_gitlink = git_buf_detach(&link_path);
703 GITERR_CHECK_ALLOC(repo->path_gitlink);
704 }
705
16c73d38
CMN
706 /*
707 * We'd like to have the config, but git doesn't particularly
708 * care if it's not there, so we need to deal with that.
709 */
710
711 error = git_repository_config_snapshot(&config, repo);
712 if (error < 0 && error != GIT_ENOTFOUND)
713 goto cleanup;
714
715 if (config && (error = check_repositoryformatversion(config)) < 0)
716 goto cleanup;
717
3fe046cf
RB
718 if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
719 repo->is_bare = 1;
2b52a0bf 720 else {
2b52a0bf 721
16c73d38
CMN
722 if (config &&
723 ((error = load_config_data(repo, config)) < 0 ||
6a8f3fa8 724 (error = load_workdir(repo, config, &parent)) < 0))
16c73d38 725 goto cleanup;
7784bcbb 726 }
691aa968 727
16c73d38 728cleanup:
146f5c75 729 git_buf_free(&parent);
16c73d38
CMN
730 git_config_free(config);
731
732 if (error < 0)
733 git_repository_free(repo);
734 else
735 *repo_ptr = repo;
2b52a0bf
RB
736
737 return error;
7784bcbb 738}
97769280 739
7784bcbb
RB
740int git_repository_open(git_repository **repo_out, const char *path)
741{
742 return git_repository_open_ext(
743 repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL);
744}
745
6782245e
CMN
746int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb)
747{
748 git_repository *repo;
749
750 repo = repository_alloc();
751 GITERR_CHECK_ALLOC(repo);
752
753 git_repository_set_odb(repo, odb);
754 *repo_out = repo;
755
756 return 0;
757}
758
7784bcbb 759int git_repository_discover(
7a3bd1e7 760 git_buf *out,
7784bcbb
RB
761 const char *start_path,
762 int across_fs,
763 const char *ceiling_dirs)
764{
7784bcbb 765 uint32_t flags = across_fs ? GIT_REPOSITORY_OPEN_CROSS_FS : 0;
7784bcbb 766
7a3bd1e7 767 assert(start_path);
7784bcbb 768
7a3bd1e7 769 git_buf_sanitize(out);
7784bcbb 770
4196dd8e 771 return find_repo(out, NULL, NULL, start_path, flags, ceiling_dirs);
691aa968
VM
772}
773
9462c471 774static int load_config(
7784bcbb
RB
775 git_config **out,
776 git_repository *repo,
777 const char *global_config_path,
4258d483 778 const char *xdg_config_path,
8c7c5fa5
CMN
779 const char *system_config_path,
780 const char *programdata_path)
b22d1479 781{
cc6b4162 782 int error;
97769280 783 git_buf config_path = GIT_BUF_INIT;
9462c471 784 git_config *cfg = NULL;
b22d1479 785
9462c471 786 assert(repo && out);
07ff8817 787
cc6b4162
RB
788 if ((error = git_config_new(&cfg)) < 0)
789 return error;
b22d1479 790
cc6b4162
RB
791 error = git_buf_joinpath(
792 &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
793 if (error < 0)
cb8a7961 794 goto on_error;
97769280 795
cc6b4162
RB
796 if ((error = git_config_add_file_ondisk(
797 cfg, config_path.ptr, GIT_CONFIG_LEVEL_LOCAL, 0)) < 0 &&
798 error != GIT_ENOTFOUND)
cb8a7961
VM
799 goto on_error;
800
801 git_buf_free(&config_path);
b22d1479 802
cc6b4162
RB
803 if (global_config_path != NULL &&
804 (error = git_config_add_file_ondisk(
805 cfg, global_config_path, GIT_CONFIG_LEVEL_GLOBAL, 0)) < 0 &&
806 error != GIT_ENOTFOUND)
807 goto on_error;
8b4f9b17 808
cc6b4162
RB
809 if (xdg_config_path != NULL &&
810 (error = git_config_add_file_ondisk(
811 cfg, xdg_config_path, GIT_CONFIG_LEVEL_XDG, 0)) < 0 &&
812 error != GIT_ENOTFOUND)
813 goto on_error;
b22d1479 814
cc6b4162
RB
815 if (system_config_path != NULL &&
816 (error = git_config_add_file_ondisk(
817 cfg, system_config_path, GIT_CONFIG_LEVEL_SYSTEM, 0)) < 0 &&
818 error != GIT_ENOTFOUND)
819 goto on_error;
9ba9e513 820
8c7c5fa5
CMN
821 if (programdata_path != NULL &&
822 (error = git_config_add_file_ondisk(
823 cfg, programdata_path, GIT_CONFIG_LEVEL_PROGRAMDATA, 0)) < 0 &&
824 error != GIT_ENOTFOUND)
825 goto on_error;
826
38f7d026
RB
827 giterr_clear(); /* clear any lingering ENOTFOUND errors */
828
9462c471 829 *out = cfg;
cb8a7961 830 return 0;
b22d1479 831
cb8a7961
VM
832on_error:
833 git_buf_free(&config_path);
9462c471
VM
834 git_config_free(cfg);
835 *out = NULL;
cc6b4162 836 return error;
b22d1479
CMN
837}
838
53607868 839static const char *path_unless_empty(git_buf *buf)
40fe5fbe 840{
53607868
RB
841 return git_buf_len(buf) > 0 ? git_buf_cstr(buf) : NULL;
842}
8b4f9b17 843
53607868
RB
844int git_repository_config__weakptr(git_config **out, git_repository *repo)
845{
846 int error = 0;
40fe5fbe 847
53607868
RB
848 if (repo->_config == NULL) {
849 git_buf global_buf = GIT_BUF_INIT;
850 git_buf xdg_buf = GIT_BUF_INIT;
851 git_buf system_buf = GIT_BUF_INIT;
8c7c5fa5 852 git_buf programdata_buf = GIT_BUF_INIT;
53607868
RB
853 git_config *config;
854
ee550477
CMN
855 git_config_find_global(&global_buf);
856 git_config_find_xdg(&xdg_buf);
857 git_config_find_system(&system_buf);
8c7c5fa5 858 git_config_find_programdata(&programdata_buf);
53607868 859
a4b75dcf
CMN
860 /* If there is no global file, open a backend for it anyway */
861 if (git_buf_len(&global_buf) == 0)
862 git_config__global_location(&global_buf);
863
53607868
RB
864 error = load_config(
865 &config, repo,
866 path_unless_empty(&global_buf),
867 path_unless_empty(&xdg_buf),
8c7c5fa5
CMN
868 path_unless_empty(&system_buf),
869 path_unless_empty(&programdata_buf));
53607868
RB
870 if (!error) {
871 GIT_REFCOUNT_OWN(config, repo);
872
e976b56d 873 config = git__compare_and_swap(&repo->_config, NULL, config);
53607868
RB
874 if (config != NULL) {
875 GIT_REFCOUNT_OWN(config, NULL);
876 git_config_free(config);
877 }
878 }
97769280
RB
879
880 git_buf_free(&global_buf);
a8918418 881 git_buf_free(&xdg_buf);
97769280 882 git_buf_free(&system_buf);
4f971852 883 git_buf_free(&programdata_buf);
9462c471 884 }
40fe5fbe 885
9462c471 886 *out = repo->_config;
53607868 887 return error;
40fe5fbe
CMN
888}
889
9462c471 890int git_repository_config(git_config **out, git_repository *repo)
fd0574e5 891{
cb8a7961
VM
892 if (git_repository_config__weakptr(out, repo) < 0)
893 return -1;
fd0574e5 894
cb8a7961
VM
895 GIT_REFCOUNT_INC(*out);
896 return 0;
9462c471
VM
897}
898
ac99d86b
CMN
899int git_repository_config_snapshot(git_config **out, git_repository *repo)
900{
b1914c36 901 int error;
ac99d86b
CMN
902 git_config *weak;
903
b1914c36
RB
904 if ((error = git_repository_config__weakptr(&weak, repo)) < 0)
905 return error;
ac99d86b
CMN
906
907 return git_config_snapshot(out, weak);
908}
909
9462c471
VM
910void git_repository_set_config(git_repository *repo, git_config *config)
911{
912 assert(repo && config);
e976b56d 913 set_config(repo, config);
9462c471
VM
914}
915
916int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
917{
53607868
RB
918 int error = 0;
919
9462c471
VM
920 assert(repo && out);
921
922 if (repo->_odb == NULL) {
97769280 923 git_buf odb_path = GIT_BUF_INIT;
53607868 924 git_odb *odb;
9462c471 925
3dbd9a0e
JG
926 if ((error = git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR)) < 0)
927 return error;
9462c471 928
53607868
RB
929 error = git_odb_open(&odb, odb_path.ptr);
930 if (!error) {
931 GIT_REFCOUNT_OWN(odb, repo);
cb8a7961 932
e976b56d 933 odb = git__compare_and_swap(&repo->_odb, NULL, odb);
53607868
RB
934 if (odb != NULL) {
935 GIT_REFCOUNT_OWN(odb, NULL);
936 git_odb_free(odb);
937 }
938 }
9462c471 939
53607868 940 git_buf_free(&odb_path);
9462c471 941 }
fd0574e5 942
9462c471 943 *out = repo->_odb;
53607868 944 return error;
fd0574e5
RG
945}
946
9462c471 947int git_repository_odb(git_odb **out, git_repository *repo)
6fd195d7 948{
cb8a7961
VM
949 if (git_repository_odb__weakptr(out, repo) < 0)
950 return -1;
1795f879 951
cb8a7961
VM
952 GIT_REFCOUNT_INC(*out);
953 return 0;
9462c471 954}
6fd195d7 955
9462c471
VM
956void git_repository_set_odb(git_repository *repo, git_odb *odb)
957{
958 assert(repo && odb);
e976b56d 959 set_odb(repo, odb);
9462c471
VM
960}
961
d00d5464
ET
962int git_repository_refdb__weakptr(git_refdb **out, git_repository *repo)
963{
53607868
RB
964 int error = 0;
965
d00d5464
ET
966 assert(out && repo);
967
968 if (repo->_refdb == NULL) {
53607868 969 git_refdb *refdb;
d00d5464 970
53607868
RB
971 error = git_refdb_open(&refdb, repo);
972 if (!error) {
973 GIT_REFCOUNT_OWN(refdb, repo);
d00d5464 974
e976b56d 975 refdb = git__compare_and_swap(&repo->_refdb, NULL, refdb);
53607868
RB
976 if (refdb != NULL) {
977 GIT_REFCOUNT_OWN(refdb, NULL);
978 git_refdb_free(refdb);
979 }
980 }
d00d5464
ET
981 }
982
983 *out = repo->_refdb;
53607868 984 return error;
d00d5464
ET
985}
986
987int git_repository_refdb(git_refdb **out, git_repository *repo)
988{
989 if (git_repository_refdb__weakptr(out, repo) < 0)
990 return -1;
991
992 GIT_REFCOUNT_INC(*out);
993 return 0;
994}
995
996void git_repository_set_refdb(git_repository *repo, git_refdb *refdb)
997{
53607868 998 assert(repo && refdb);
e976b56d 999 set_refdb(repo, refdb);
d00d5464
ET
1000}
1001
9462c471
VM
1002int git_repository_index__weakptr(git_index **out, git_repository *repo)
1003{
53607868
RB
1004 int error = 0;
1005
9462c471
VM
1006 assert(out && repo);
1007
9462c471 1008 if (repo->_index == NULL) {
97769280 1009 git_buf index_path = GIT_BUF_INIT;
53607868 1010 git_index *index;
9462c471 1011
3dbd9a0e
JG
1012 if ((error = git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE)) < 0)
1013 return error;
9462c471 1014
53607868
RB
1015 error = git_index_open(&index, index_path.ptr);
1016 if (!error) {
1017 GIT_REFCOUNT_OWN(index, repo);
cb8a7961 1018
e976b56d 1019 index = git__compare_and_swap(&repo->_index, NULL, index);
53607868
RB
1020 if (index != NULL) {
1021 GIT_REFCOUNT_OWN(index, NULL);
1022 git_index_free(index);
1023 }
9462c471 1024
53607868
RB
1025 error = git_index_set_caps(repo->_index, GIT_INDEXCAP_FROM_OWNER);
1026 }
da825c92 1027
53607868 1028 git_buf_free(&index_path);
9462c471
VM
1029 }
1030
9462c471 1031 *out = repo->_index;
53607868 1032 return error;
9462c471 1033}
1795f879 1034
9462c471
VM
1035int git_repository_index(git_index **out, git_repository *repo)
1036{
cb8a7961
VM
1037 if (git_repository_index__weakptr(out, repo) < 0)
1038 return -1;
9462c471 1039
cb8a7961
VM
1040 GIT_REFCOUNT_INC(*out);
1041 return 0;
3315782c
VM
1042}
1043
9462c471
VM
1044void git_repository_set_index(git_repository *repo, git_index *index)
1045{
fa8ca519 1046 assert(repo);
e976b56d 1047 set_index(repo, index);
9462c471
VM
1048}
1049
bade5194
VM
1050int git_repository_set_namespace(git_repository *repo, const char *namespace)
1051{
1052 git__free(repo->namespace);
1053
1054 if (namespace == NULL) {
1055 repo->namespace = NULL;
1056 return 0;
1057 }
1058
1059 return (repo->namespace = git__strdup(namespace)) ? 0 : -1;
1060}
1061
1062const char *git_repository_get_namespace(git_repository *repo)
1063{
1064 return repo->namespace;
1065}
1066
4196dd8e
ET
1067#ifdef GIT_WIN32
1068static int reserved_names_add8dot3(git_repository *repo, const char *path)
a64119e3 1069{
4196dd8e
ET
1070 char *name = git_win32_path_8dot3_name(path);
1071 const char *def = GIT_DIR_SHORTNAME;
526f91f5 1072 const char *def_dot_git = DOT_GIT;
4196dd8e 1073 size_t name_len, def_len = CONST_STRLEN(GIT_DIR_SHORTNAME);
526f91f5 1074 size_t def_dot_git_len = CONST_STRLEN(DOT_GIT);
4196dd8e 1075 git_buf *buf;
a64119e3 1076
4196dd8e
ET
1077 if (!name)
1078 return 0;
1079
1080 name_len = strlen(name);
1081
526f91f5
L
1082 if ((name_len == def_len && memcmp(name, def, def_len) == 0) ||
1083 (name_len == def_dot_git_len && memcmp(name, def_dot_git, def_dot_git_len) == 0)) {
4196dd8e
ET
1084 git__free(name);
1085 return 0;
1086 }
1087
1088 if ((buf = git_array_alloc(repo->reserved_names)) == NULL)
1089 return -1;
1090
1091 git_buf_attach(buf, name, name_len);
1092 return true;
1093}
1094
1095bool git_repository__reserved_names(
1096 git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
1097{
1098 GIT_UNUSED(include_ntfs);
1099
1100 if (repo->reserved_names.size == 0) {
1101 git_buf *buf;
1102 size_t i;
1103
1104 /* Add the static defaults */
1105 for (i = 0; i < git_repository__reserved_names_win32_len; i++) {
1106 if ((buf = git_array_alloc(repo->reserved_names)) == NULL)
1107 goto on_error;
1108
1109 buf->ptr = git_repository__reserved_names_win32[i].ptr;
1110 buf->size = git_repository__reserved_names_win32[i].size;
1111 }
1112
538dfc88
ET
1113 /* Try to add any repo-specific reserved names - the gitlink file
1114 * within a submodule or the repository (if the repository directory
1115 * is beneath the workdir). These are typically `.git`, but should
1116 * be protected in case they are not. Note, repo and workdir paths
1117 * are always prettified to end in `/`, so a prefixcmp is safe.
1118 */
a64119e3 1119 if (!repo->is_bare) {
538dfc88
ET
1120 int (*prefixcmp)(const char *, const char *);
1121 int error, ignorecase;
a64119e3 1122
538dfc88
ET
1123 error = git_repository__cvar(
1124 &ignorecase, repo, GIT_CVAR_IGNORECASE);
1125 prefixcmp = (error || ignorecase) ? git__prefixcmp_icase :
1126 git__prefixcmp;
1127
1128 if (repo->path_gitlink &&
1129 reserved_names_add8dot3(repo, repo->path_gitlink) < 0)
1130 goto on_error;
1131
1132 if (repo->path_repository &&
1133 prefixcmp(repo->path_repository, repo->workdir) == 0 &&
1134 reserved_names_add8dot3(repo, repo->path_repository) < 0)
4196dd8e 1135 goto on_error;
a64119e3 1136 }
a64119e3
ET
1137 }
1138
4196dd8e
ET
1139 *out = repo->reserved_names.ptr;
1140 *outlen = repo->reserved_names.size;
1141
1142 return true;
1143
1144 /* Always give good defaults, even on OOM */
1145on_error:
1146 *out = git_repository__reserved_names_win32;
1147 *outlen = git_repository__reserved_names_win32_len;
1148
1149 return false;
a64119e3 1150}
4196dd8e
ET
1151#else
1152bool git_repository__reserved_names(
1153 git_buf **out, size_t *outlen, git_repository *repo, bool include_ntfs)
1154{
1155 GIT_UNUSED(repo);
1156
1157 if (include_ntfs) {
1158 *out = git_repository__reserved_names_win32;
1159 *outlen = git_repository__reserved_names_win32_len;
1160 } else {
1161 *out = git_repository__reserved_names_posix;
1162 *outlen = git_repository__reserved_names_posix_len;
1163 }
1164
1165 return true;
1166}
1167#endif
a64119e3 1168
2c227b8b 1169static int check_repositoryformatversion(git_config *config)
40c44d2f 1170{
99e11cdd 1171 int version, error;
5663e61a 1172
99e11cdd
CMN
1173 error = git_config_get_int32(&version, config, "core.repositoryformatversion");
1174 /* git ignores this if the config variable isn't there */
1175 if (error == GIT_ENOTFOUND)
1176 return 0;
1177
1178 if (error < 0)
cb8a7961 1179 return -1;
5663e61a 1180
29e948de 1181 if (GIT_REPO_VERSION < version) {
cb8a7961 1182 giterr_set(GITERR_REPOSITORY,
909d5494 1183 "unsupported repository version %d. Only versions up to %d are supported.",
29e948de 1184 version, GIT_REPO_VERSION);
cb8a7961
VM
1185 return -1;
1186 }
5663e61a 1187
cb8a7961 1188 return 0;
5663e61a 1189}
1190
662880ca 1191static int repo_init_create_head(const char *git_dir, const char *ref_name)
e1f8cad0 1192{
97769280 1193 git_buf ref_path = GIT_BUF_INIT;
9462c471 1194 git_filebuf ref = GIT_FILEBUF_INIT;
662880ca 1195 const char *fmt;
9462c471 1196
cb8a7961 1197 if (git_buf_joinpath(&ref_path, git_dir, GIT_HEAD_FILE) < 0 ||
1d3a8aeb 1198 git_filebuf_open(&ref, ref_path.ptr, 0, GIT_REFS_FILE_MODE) < 0)
662880ca
RB
1199 goto fail;
1200
1201 if (!ref_name)
1202 ref_name = GIT_BRANCH_MASTER;
1203
74a24005 1204 if (git__prefixcmp(ref_name, GIT_REFS_DIR) == 0)
662880ca
RB
1205 fmt = "ref: %s\n";
1206 else
74a24005 1207 fmt = "ref: " GIT_REFS_HEADS_DIR "%s\n";
662880ca
RB
1208
1209 if (git_filebuf_printf(&ref, fmt, ref_name) < 0 ||
1d3a8aeb 1210 git_filebuf_commit(&ref) < 0)
662880ca 1211 goto fail;
9462c471 1212
97769280 1213 git_buf_free(&ref_path);
cb8a7961 1214 return 0;
662880ca
RB
1215
1216fail:
1217 git_buf_free(&ref_path);
1218 git_filebuf_cleanup(&ref);
1219 return -1;
9462c471
VM
1220}
1221
fac66990 1222static bool is_chmod_supported(const char *file_path)
1223{
1224 struct stat st1, st2;
fac66990 1225
1226 if (p_stat(file_path, &st1) < 0)
1227 return false;
1228
1229 if (p_chmod(file_path, st1.st_mode ^ S_IXUSR) < 0)
1230 return false;
1231
1232 if (p_stat(file_path, &st2) < 0)
1233 return false;
1234
6b7991e2 1235 return (st1.st_mode != st2.st_mode);
fac66990 1236}
1237
693b23c0 1238static bool is_filesystem_case_insensitive(const char *gitdir_path)
1239{
1240 git_buf path = GIT_BUF_INIT;
6b7991e2 1241 int is_insensitive = -1;
693b23c0 1242
6b7991e2
RB
1243 if (!git_buf_joinpath(&path, gitdir_path, "CoNfIg"))
1244 is_insensitive = git_path_exists(git_buf_cstr(&path));
693b23c0 1245
693b23c0 1246 git_buf_free(&path);
6b7991e2 1247 return is_insensitive;
693b23c0 1248}
1249
ca1b6e54
RB
1250static bool are_symlinks_supported(const char *wd_path)
1251{
1252 git_buf path = GIT_BUF_INIT;
1253 int fd;
1254 struct stat st;
6b7991e2 1255 int symlinks_supported = -1;
ca1b6e54 1256
1d3a8aeb 1257 if ((fd = git_futils_mktmp(&path, wd_path, 0666)) < 0 ||
ca1b6e54
RB
1258 p_close(fd) < 0 ||
1259 p_unlink(path.ptr) < 0 ||
1260 p_symlink("testing", path.ptr) < 0 ||
1261 p_lstat(path.ptr, &st) < 0)
6b7991e2 1262 symlinks_supported = false;
ca1b6e54 1263 else
6b7991e2 1264 symlinks_supported = (S_ISLNK(st.st_mode) != 0);
ca1b6e54
RB
1265
1266 (void)p_unlink(path.ptr);
1267 git_buf_free(&path);
1268
6b7991e2
RB
1269 return symlinks_supported;
1270}
1271
270160b9 1272static int create_empty_file(const char *path, mode_t mode)
1273{
1274 int fd;
1275
1276 if ((fd = p_creat(path, mode)) < 0) {
909d5494 1277 giterr_set(GITERR_OS, "error while creating '%s'", path);
270160b9 1278 return -1;
1279 }
1280
1281 if (p_close(fd) < 0) {
909d5494 1282 giterr_set(GITERR_OS, "error while closing '%s'", path);
270160b9 1283 return -1;
1284 }
1285
1286 return 0;
1287}
1288
14997dc5
RB
1289static int repo_local_config(
1290 git_config **out,
1291 git_buf *config_dir,
1292 git_repository *repo,
1293 const char *repo_dir)
9462c471 1294{
ca1b6e54 1295 int error = 0;
14997dc5
RB
1296 git_config *parent;
1297 const char *cfg_path;
9462c471 1298
14997dc5 1299 if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0)
cb8a7961 1300 return -1;
14997dc5 1301 cfg_path = git_buf_cstr(config_dir);
9462c471 1302
14997dc5 1303 /* make LOCAL config if missing */
5173ea92
RB
1304 if (!git_path_isfile(cfg_path) &&
1305 (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0)
14997dc5 1306 return error;
270160b9 1307
14997dc5
RB
1308 /* if no repo, just open that file directly */
1309 if (!repo)
1310 return git_config_open_ondisk(out, cfg_path);
1311
1312 /* otherwise, open parent config and get that level */
1313 if ((error = git_repository_config__weakptr(&parent, repo)) < 0)
1314 return error;
1315
1316 if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) {
5173ea92
RB
1317 giterr_clear();
1318
1319 if (!(error = git_config_add_file_ondisk(
1320 parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false)))
14997dc5 1321 error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL);
cb8a7961 1322 }
9462c471 1323
14997dc5
RB
1324 git_config_free(parent);
1325
1326 return error;
1327}
1328
1329static int repo_init_fs_configs(
1330 git_config *cfg,
1331 const char *cfg_path,
1332 const char *repo_dir,
1333 const char *work_dir,
1334 bool update_ignorecase)
1335{
1336 int error = 0;
1337
1338 if (!work_dir)
1339 work_dir = repo_dir;
1340
1341 if ((error = git_config_set_bool(
1342 cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0)
1343 return error;
1344
1345 if (!are_symlinks_supported(work_dir)) {
1346 if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0)
1347 return error;
1348 } else if (git_config_delete_entry(cfg, "core.symlinks") < 0)
1349 giterr_clear();
2c227b8b 1350
14997dc5
RB
1351 if (update_ignorecase) {
1352 if (is_filesystem_case_insensitive(repo_dir)) {
1353 if ((error = git_config_set_bool(cfg, "core.ignorecase", true)) < 0)
1354 return error;
1355 } else if (git_config_delete_entry(cfg, "core.ignorecase") < 0)
1356 giterr_clear();
1357 }
662880ca 1358
af302aca 1359#ifdef GIT_USE_ICONV
14997dc5
RB
1360 if ((error = git_config_set_bool(
1361 cfg, "core.precomposeunicode",
43a04135 1362 git_path_does_fs_decompose_unicode(work_dir))) < 0)
14997dc5 1363 return error;
43a04135 1364 /* on non-iconv platforms, don't even set core.precomposeunicode */
6b7991e2
RB
1365#endif
1366
14997dc5
RB
1367 return 0;
1368}
7623b1b6 1369
14997dc5
RB
1370static int repo_init_config(
1371 const char *repo_dir,
1372 const char *work_dir,
1373 uint32_t flags,
1374 uint32_t mode)
1375{
1376 int error = 0;
bc737620 1377 git_buf cfg_path = GIT_BUF_INIT, worktree_path = GIT_BUF_INIT;
14997dc5
RB
1378 git_config *config = NULL;
1379 bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0);
1380 bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0);
1381
1382 if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0)
1383 goto cleanup;
1384
1385 if (is_reinit && (error = check_repositoryformatversion(config)) < 0)
1386 goto cleanup;
1387
1388#define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \
1389 if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \
1390 goto cleanup; } while (0)
1391
1392 SET_REPO_CONFIG(bool, "core.bare", is_bare);
1393 SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION);
1394
1395 if ((error = repo_init_fs_configs(
1396 config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0)
1397 goto cleanup;
5173ea92 1398
6b7991e2
RB
1399 if (!is_bare) {
1400 SET_REPO_CONFIG(bool, "core.logallrefupdates", true);
ca1b6e54 1401
bc737620
JM
1402 if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) {
1403 if ((error = git_buf_sets(&worktree_path, work_dir)) < 0)
1404 goto cleanup;
1405
1406 if ((flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK))
1407 if ((error = git_path_make_relative(&worktree_path, repo_dir)) < 0)
1408 goto cleanup;
1409
1410 SET_REPO_CONFIG(string, "core.worktree", worktree_path.ptr);
1411 } else if (is_reinit) {
54b2a37a 1412 if (git_config_delete_entry(config, "core.worktree") < 0)
89cd5708 1413 giterr_clear();
ca1b6e54 1414 }
ca1b6e54
RB
1415 }
1416
5173ea92 1417 if (mode == GIT_REPOSITORY_INIT_SHARED_GROUP) {
662880ca
RB
1418 SET_REPO_CONFIG(int32, "core.sharedrepository", 1);
1419 SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
ca1b6e54 1420 }
5173ea92 1421 else if (mode == GIT_REPOSITORY_INIT_SHARED_ALL) {
662880ca
RB
1422 SET_REPO_CONFIG(int32, "core.sharedrepository", 2);
1423 SET_REPO_CONFIG(bool, "receive.denyNonFastforwards", true);
1424 }
9462c471 1425
ca1b6e54 1426cleanup:
14997dc5 1427 git_buf_free(&cfg_path);
bc737620 1428 git_buf_free(&worktree_path);
9462c471 1429 git_config_free(config);
662880ca 1430
ca1b6e54 1431 return error;
d2d6912e 1432}
e1f8cad0 1433
867f7c9b 1434static int repo_reinit_submodule_fs(git_submodule *sm, const char *n, void *p)
5173ea92 1435{
14997dc5
RB
1436 git_repository *smrepo = NULL;
1437 GIT_UNUSED(n); GIT_UNUSED(p);
5173ea92 1438
14997dc5 1439 if (git_submodule_open(&smrepo, sm) < 0 ||
867f7c9b 1440 git_repository_reinit_filesystem(smrepo, true) < 0)
14997dc5
RB
1441 giterr_clear();
1442 git_repository_free(smrepo);
5173ea92 1443
14997dc5
RB
1444 return 0;
1445}
5173ea92 1446
867f7c9b 1447int git_repository_reinit_filesystem(git_repository *repo, int recurse)
14997dc5
RB
1448{
1449 int error = 0;
1450 git_buf path = GIT_BUF_INIT;
1451 git_config *config = NULL;
1452 const char *repo_dir = git_repository_path(repo);
5173ea92 1453
14997dc5
RB
1454 if (!(error = repo_local_config(&config, &path, repo, repo_dir)))
1455 error = repo_init_fs_configs(
1456 config, path.ptr, repo_dir, git_repository_workdir(repo), true);
5173ea92 1457
14997dc5
RB
1458 git_config_free(config);
1459 git_buf_free(&path);
5173ea92 1460
5173ea92
RB
1461 git_repository__cvar_cache_clear(repo);
1462
14997dc5 1463 if (!repo->is_bare && recurse)
867f7c9b 1464 (void)git_submodule_foreach(repo, repo_reinit_submodule_fs, NULL);
14997dc5 1465
5173ea92
RB
1466 return error;
1467}
1468
dc34da6e 1469static int repo_write_template(
991a56c7
RB
1470 const char *git_dir,
1471 bool allow_overwrite,
1472 const char *file,
1473 mode_t mode,
662880ca 1474 bool hidden,
991a56c7 1475 const char *content)
dc34da6e
RB
1476{
1477 git_buf path = GIT_BUF_INIT;
991a56c7 1478 int fd, error = 0, flags;
dc34da6e
RB
1479
1480 if (git_buf_joinpath(&path, git_dir, file) < 0)
1481 return -1;
1482
991a56c7
RB
1483 if (allow_overwrite)
1484 flags = O_WRONLY | O_CREAT | O_TRUNC;
1485 else
1486 flags = O_WRONLY | O_CREAT | O_EXCL;
1487
1488 fd = p_open(git_buf_cstr(&path), flags, mode);
dc34da6e 1489
db628072
RB
1490 if (fd >= 0) {
1491 error = p_write(fd, content, strlen(content));
dc34da6e 1492
db628072
RB
1493 p_close(fd);
1494 }
1495 else if (errno != EEXIST)
1496 error = fd;
dc34da6e 1497
662880ca
RB
1498#ifdef GIT_WIN32
1499 if (!error && hidden) {
bdec3363 1500 if (git_win32__set_hidden(path.ptr, true) < 0)
662880ca
RB
1501 error = -1;
1502 }
1503#else
1504 GIT_UNUSED(hidden);
1505#endif
1506
dc34da6e 1507 git_buf_free(&path);
db628072
RB
1508
1509 if (error)
1510 giterr_set(GITERR_OS,
909d5494 1511 "failed to initialize repository with template '%s'", file);
db628072
RB
1512
1513 return error;
dc34da6e
RB
1514}
1515
662880ca 1516static int repo_write_gitlink(
bc737620 1517 const char *in_dir, const char *to_repo, bool use_relative_path)
4b8e27c8 1518{
662880ca
RB
1519 int error;
1520 git_buf buf = GIT_BUF_INIT;
bc737620 1521 git_buf path_to_repo = GIT_BUF_INIT;
662880ca
RB
1522 struct stat st;
1523
1524 git_path_dirname_r(&buf, to_repo);
1525 git_path_to_dir(&buf);
1526 if (git_buf_oom(&buf))
cb8a7961 1527 return -1;
a67a096a 1528
662880ca
RB
1529 /* don't write gitlink to natural workdir */
1530 if (git__suffixcmp(to_repo, "/" DOT_GIT "/") == 0 &&
1531 strcmp(in_dir, buf.ptr) == 0)
1532 {
1533 error = GIT_PASSTHROUGH;
1534 goto cleanup;
1535 }
1536
1537 if ((error = git_buf_joinpath(&buf, in_dir, DOT_GIT)) < 0)
1538 goto cleanup;
1539
1540 if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) {
1541 giterr_set(GITERR_REPOSITORY,
909d5494 1542 "cannot overwrite gitlink file into path '%s'", in_dir);
662880ca
RB
1543 error = GIT_EEXISTS;
1544 goto cleanup;
1545 }
1546
1547 git_buf_clear(&buf);
1548
bc737620
JM
1549 error = git_buf_sets(&path_to_repo, to_repo);
1550
1551 if (!error && use_relative_path)
1552 error = git_path_make_relative(&path_to_repo, in_dir);
1553
1554 if (!error)
1555 error = git_buf_join(&buf, ' ', GIT_FILE_CONTENT_PREFIX, path_to_repo.ptr);
662880ca
RB
1556
1557 if (!error)
18f08264 1558 error = repo_write_template(in_dir, true, DOT_GIT, 0666, true, buf.ptr);
662880ca
RB
1559
1560cleanup:
1561 git_buf_free(&buf);
bc737620 1562 git_buf_free(&path_to_repo);
662880ca
RB
1563 return error;
1564}
1565
ca1b6e54
RB
1566static mode_t pick_dir_mode(git_repository_init_options *opts)
1567{
1568 if (opts->mode == GIT_REPOSITORY_INIT_SHARED_UMASK)
18f08264 1569 return 0777;
ca1b6e54
RB
1570 if (opts->mode == GIT_REPOSITORY_INIT_SHARED_GROUP)
1571 return (0775 | S_ISGID);
1572 if (opts->mode == GIT_REPOSITORY_INIT_SHARED_ALL)
1573 return (0777 | S_ISGID);
1574 return opts->mode;
1575}
1576
662880ca
RB
1577#include "repo_template.h"
1578
1579static int repo_init_structure(
1580 const char *repo_dir,
1581 const char *work_dir,
1582 git_repository_init_options *opts)
1583{
ca1b6e54 1584 int error = 0;
662880ca 1585 repo_template_item *tpl;
ca1b6e54
RB
1586 bool external_tpl =
1587 ((opts->flags & GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE) != 0);
1588 mode_t dmode = pick_dir_mode(opts);
bafaf790 1589 bool chmod = opts->mode != GIT_REPOSITORY_INIT_SHARED_UMASK;
662880ca
RB
1590
1591 /* Hide the ".git" directory */
17837602 1592#ifdef GIT_WIN32
2eb4edf5 1593 if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) {
bdec3363 1594 if (git_win32__set_hidden(repo_dir, true) < 0) {
c2c81615 1595 giterr_set(GITERR_OS,
909d5494 1596 "failed to mark Git repository folder as hidden");
cb8a7961
VM
1597 return -1;
1598 }
17837602 1599 }
2eb4edf5
RB
1600#endif
1601
1602 /* Create the .git gitlink if appropriate */
1603 if ((opts->flags & GIT_REPOSITORY_INIT_BARE) == 0 &&
1604 (opts->flags & GIT_REPOSITORY_INIT__NATURAL_WD) == 0)
1605 {
bc737620 1606 if (repo_write_gitlink(work_dir, repo_dir, opts->flags & GIT_REPOSITORY_INIT_RELATIVE_GITLINK) < 0)
cb8a7961 1607 return -1;
97769280 1608 }
1c2c7c0d 1609
ca1b6e54
RB
1610 /* Copy external template if requested */
1611 if (external_tpl) {
0cd1c3bb
L
1612 git_config *cfg = NULL;
1613 const char *tdir = NULL;
1614 bool default_template = false;
a025907e
L
1615 git_buf template_buf = GIT_BUF_INIT;
1616
ca1b6e54
RB
1617 if (opts->template_path)
1618 tdir = opts->template_path;
0cd1c3bb 1619 else if ((error = git_config_open_default(&cfg)) >= 0) {
cc36f424
CMN
1620 if (!git_config_get_path(&template_buf, cfg, "init.templatedir"))
1621 tdir = template_buf.ptr;
ca1b6e54 1622 giterr_clear();
0cd1c3bb
L
1623 }
1624
1625 if (!tdir) {
83634d38 1626 if (!(error = git_sysdir_find_template_dir(&template_buf)))
417472e3 1627 tdir = template_buf.ptr;
0cd1c3bb 1628 default_template = true;
662880ca 1629 }
ca1b6e54 1630
bafaf790 1631 if (tdir) {
62602547
ET
1632 uint32_t cpflags = GIT_CPDIR_COPY_SYMLINKS |
1633 GIT_CPDIR_SIMPLE_TO_MODE |
1634 GIT_CPDIR_COPY_DOTFILES;
517341c5
EL
1635 if (opts->mode != GIT_REPOSITORY_INIT_SHARED_UMASK)
1636 cpflags |= GIT_CPDIR_CHMOD_DIRS;
1637 error = git_futils_cp_r(tdir, repo_dir, cpflags, dmode);
bafaf790 1638 }
ca1b6e54 1639
0cd1c3bb
L
1640 git_buf_free(&template_buf);
1641 git_config_free(cfg);
1ca3e49f 1642
ca1b6e54 1643 if (error < 0) {
0cd1c3bb 1644 if (!default_template)
ca1b6e54
RB
1645 return error;
1646
1647 /* if template was default, ignore error and use internal */
1648 giterr_clear();
1649 external_tpl = false;
b7b1acfd 1650 error = 0;
ca1b6e54
RB
1651 }
1652 }
1653
1654 /* Copy internal template
1655 * - always ensure existence of dirs
1656 * - only create files if no external template was specified
1657 */
1658 for (tpl = repo_template; !error && tpl->path; ++tpl) {
bafaf790 1659 if (!tpl->content) {
517341c5
EL
1660 uint32_t mkdir_flags = GIT_MKDIR_PATH;
1661 if (chmod)
1662 mkdir_flags |= GIT_MKDIR_CHMOD;
1663
ac2fba0e
ET
1664 error = git_futils_mkdir_relative(
1665 tpl->path, repo_dir, dmode, mkdir_flags, NULL);
bafaf790 1666 }
ca1b6e54 1667 else if (!external_tpl) {
662880ca
RB
1668 const char *content = tpl->content;
1669
1670 if (opts->description && strcmp(tpl->path, GIT_DESC_FILE) == 0)
1671 content = opts->description;
1672
ca1b6e54
RB
1673 error = repo_write_template(
1674 repo_dir, false, tpl->path, tpl->mode, false, content);
662880ca 1675 }
dc34da6e
RB
1676 }
1677
ca1b6e54 1678 return error;
4b8e27c8 1679}
1680
3c42e4ef
RB
1681static int mkdir_parent(git_buf *buf, uint32_t mode, bool skip2)
1682{
0d1b094b
RB
1683 /* When making parent directories during repository initialization
1684 * don't try to set gid or grant world write access
1685 */
3c42e4ef 1686 return git_futils_mkdir(
ac2fba0e 1687 buf->ptr, mode & ~(S_ISGID | 0002),
3c42e4ef
RB
1688 GIT_MKDIR_PATH | GIT_MKDIR_VERIFY_DIR |
1689 (skip2 ? GIT_MKDIR_SKIP_LAST2 : GIT_MKDIR_SKIP_LAST));
1690}
1691
662880ca
RB
1692static int repo_init_directories(
1693 git_buf *repo_path,
1694 git_buf *wd_path,
1695 const char *given_repo,
1696 git_repository_init_options *opts)
4b8e27c8 1697{
662880ca 1698 int error = 0;
3c42e4ef 1699 bool is_bare, add_dotgit, has_dotgit, natural_wd;
ca1b6e54 1700 mode_t dirmode;
932d1baf 1701
3c42e4ef
RB
1702 /* There are three possible rules for what we are allowed to create:
1703 * - MKPATH means anything we need
1704 * - MKDIR means just the .git directory and its parent and the workdir
1705 * - Neither means only the .git directory can be created
1706 *
1707 * There are 5 "segments" of path that we might need to deal with:
1708 * 1. The .git directory
1709 * 2. The parent of the .git directory
1710 * 3. Everything above the parent of the .git directory
1711 * 4. The working directory (often the same as #2)
1712 * 5. Everything above the working directory (often the same as #3)
1713 *
1714 * For all directories created, we start with the init_mode value for
1715 * permissions and then strip off bits in some cases:
1716 *
1717 * For MKPATH, we create #3 (and #5) paths without S_ISGID or S_IWOTH
1718 * For MKPATH and MKDIR, we create #2 (and #4) without S_ISGID
1719 * For all rules, we create #1 using the untouched init_mode
1720 */
1721
662880ca 1722 /* set up repo path */
4b8e27c8 1723
3c42e4ef
RB
1724 is_bare = ((opts->flags & GIT_REPOSITORY_INIT_BARE) != 0);
1725
662880ca
RB
1726 add_dotgit =
1727 (opts->flags & GIT_REPOSITORY_INIT_NO_DOTGIT_DIR) == 0 &&
3c42e4ef 1728 !is_bare &&
662880ca
RB
1729 git__suffixcmp(given_repo, "/" DOT_GIT) != 0 &&
1730 git__suffixcmp(given_repo, "/" GIT_DIR) != 0;
4b8e27c8 1731
662880ca
RB
1732 if (git_buf_joinpath(repo_path, given_repo, add_dotgit ? GIT_DIR : "") < 0)
1733 return -1;
693b23c0 1734
662880ca
RB
1735 has_dotgit = (git__suffixcmp(repo_path->ptr, "/" GIT_DIR) == 0);
1736 if (has_dotgit)
1737 opts->flags |= GIT_REPOSITORY_INIT__HAS_DOTGIT;
1738
1739 /* set up workdir path */
1740
3c42e4ef 1741 if (!is_bare) {
662880ca 1742 if (opts->workdir_path) {
ca1b6e54
RB
1743 if (git_path_join_unrooted(
1744 wd_path, opts->workdir_path, repo_path->ptr, NULL) < 0)
1745 return -1;
662880ca
RB
1746 } else if (has_dotgit) {
1747 if (git_path_dirname_r(wd_path, repo_path->ptr) < 0)
1748 return -1;
1749 } else {
909d5494 1750 giterr_set(GITERR_REPOSITORY, "cannot pick working directory"
662880ca
RB
1751 " for non-bare repository that isn't a '.git' directory");
1752 return -1;
1753 }
693b23c0 1754
662880ca
RB
1755 if (git_path_to_dir(wd_path) < 0)
1756 return -1;
1757 } else {
1758 git_buf_clear(wd_path);
1759 }
1760
1761 natural_wd =
1762 has_dotgit &&
1763 wd_path->size > 0 &&
1764 wd_path->size + strlen(GIT_DIR) == repo_path->size &&
1765 memcmp(repo_path->ptr, wd_path->ptr, wd_path->size) == 0;
1766 if (natural_wd)
1767 opts->flags |= GIT_REPOSITORY_INIT__NATURAL_WD;
1768
662880ca
RB
1769 /* create directories as needed / requested */
1770
ca1b6e54 1771 dirmode = pick_dir_mode(opts);
662880ca 1772
3c42e4ef
RB
1773 if ((opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0) {
1774 /* create path #5 */
1775 if (wd_path->size > 0 &&
1776 (error = mkdir_parent(wd_path, dirmode, false)) < 0)
1777 return error;
1778
1779 /* create path #3 (if not the same as #5) */
1780 if (!natural_wd &&
1781 (error = mkdir_parent(repo_path, dirmode, has_dotgit)) < 0)
1782 return error;
1783 }
1784
1785 if ((opts->flags & GIT_REPOSITORY_INIT_MKDIR) != 0 ||
1786 (opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0)
1787 {
1788 /* create path #4 */
1789 if (wd_path->size > 0 &&
1790 (error = git_futils_mkdir(
ac2fba0e 1791 wd_path->ptr, dirmode & ~S_ISGID,
3c42e4ef
RB
1792 GIT_MKDIR_VERIFY_DIR)) < 0)
1793 return error;
1794
1795 /* create path #2 (if not the same as #4) */
1796 if (!natural_wd &&
1797 (error = git_futils_mkdir(
ac2fba0e 1798 repo_path->ptr, dirmode & ~S_ISGID,
3c42e4ef
RB
1799 GIT_MKDIR_VERIFY_DIR | GIT_MKDIR_SKIP_LAST)) < 0)
1800 return error;
662880ca 1801 }
662880ca 1802
ca1b6e54
RB
1803 if ((opts->flags & GIT_REPOSITORY_INIT_MKDIR) != 0 ||
1804 (opts->flags & GIT_REPOSITORY_INIT_MKPATH) != 0 ||
1805 has_dotgit)
1806 {
3c42e4ef 1807 /* create path #1 */
ac2fba0e 1808 error = git_futils_mkdir(repo_path->ptr, dirmode,
18f08264 1809 GIT_MKDIR_VERIFY_DIR | ((dirmode & S_ISGID) ? GIT_MKDIR_CHMOD : 0));
662880ca 1810 }
ca1b6e54 1811
662880ca
RB
1812 /* prettify both directories now that they are created */
1813
1814 if (!error) {
1815 error = git_path_prettify_dir(repo_path, repo_path->ptr, NULL);
1816
1817 if (!error && wd_path->size > 0)
1818 error = git_path_prettify_dir(wd_path, wd_path->ptr, NULL);
1819 }
1820
1821 return error;
1822}
1823
1824static int repo_init_create_origin(git_repository *repo, const char *url)
1825{
1826 int error;
1827 git_remote *remote;
1828
29f27599 1829 if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url))) {
662880ca
RB
1830 git_remote_free(remote);
1831 }
1832
1833 return error;
1834}
1835
1836int git_repository_init(
1837 git_repository **repo_out, const char *path, unsigned is_bare)
1838{
b4d13652 1839 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
662880ca 1840
662880ca
RB
1841 opts.flags = GIT_REPOSITORY_INIT_MKPATH; /* don't love this default */
1842 if (is_bare)
1843 opts.flags |= GIT_REPOSITORY_INIT_BARE;
1844
1845 return git_repository_init_ext(repo_out, path, &opts);
1846}
1847
1848int git_repository_init_ext(
c9fc4a6f 1849 git_repository **out,
662880ca
RB
1850 const char *given_repo,
1851 git_repository_init_options *opts)
1852{
1853 int error;
1854 git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT;
466d2e7a 1855 const char *wd;
662880ca 1856
c9fc4a6f 1857 assert(out && given_repo && opts);
662880ca 1858
c7231c45 1859 GITERR_CHECK_VERSION(opts, GIT_REPOSITORY_INIT_OPTIONS_VERSION, "git_repository_init_options");
b4d13652 1860
662880ca
RB
1861 error = repo_init_directories(&repo_path, &wd_path, given_repo, opts);
1862 if (error < 0)
693b23c0 1863 goto cleanup;
662880ca 1864
466d2e7a 1865 wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path);
662880ca
RB
1866 if (valid_repository_path(&repo_path)) {
1867
1868 if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) {
1869 giterr_set(GITERR_REPOSITORY,
909d5494 1870 "attempt to reinitialize '%s'", given_repo);
662880ca
RB
1871 error = GIT_EEXISTS;
1872 goto cleanup;
1873 }
1874
1875 opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT;
1876
ca1b6e54 1877 error = repo_init_config(
466d2e7a 1878 repo_path.ptr, wd, opts->flags, opts->mode);
662880ca
RB
1879
1880 /* TODO: reinitialize the templates */
1881 }
1882 else {
1883 if (!(error = repo_init_structure(
466d2e7a 1884 repo_path.ptr, wd, opts)) &&
ca1b6e54 1885 !(error = repo_init_config(
466d2e7a 1886 repo_path.ptr, wd, opts->flags, opts->mode)))
662880ca 1887 error = repo_init_create_head(
5173ea92 1888 repo_path.ptr, opts->initial_head);
cb8a7961 1889 }
662880ca
RB
1890 if (error < 0)
1891 goto cleanup;
1892
5173ea92 1893 error = git_repository_open(out, repo_path.ptr);
d2d6912e 1894
662880ca 1895 if (!error && opts->origin_url)
c9fc4a6f 1896 error = repo_init_create_origin(*out, opts->origin_url);
693b23c0 1897
1898cleanup:
662880ca
RB
1899 git_buf_free(&repo_path);
1900 git_buf_free(&wd_path);
1901
1902 return error;
40c44d2f 1903}
35502d2e 1904
c682886e 1905int git_repository_head_detached(git_repository *repo)
35502d2e
CMN
1906{
1907 git_reference *ref;
9462c471 1908 git_odb *odb = NULL;
cb8a7961 1909 int exists;
9462c471 1910
cb8a7961
VM
1911 if (git_repository_odb__weakptr(&odb, repo) < 0)
1912 return -1;
35502d2e 1913
cb8a7961
VM
1914 if (git_reference_lookup(&ref, repo, GIT_HEAD_FILE) < 0)
1915 return -1;
35502d2e 1916
75abd2b9
MS
1917 if (git_reference_type(ref) == GIT_REF_SYMBOLIC) {
1918 git_reference_free(ref);
35502d2e 1919 return 0;
75abd2b9 1920 }
35502d2e 1921
2508cc66 1922 exists = git_odb_exists(odb, git_reference_target(ref));
75abd2b9
MS
1923
1924 git_reference_free(ref);
cb8a7961 1925 return exists;
35502d2e
CMN
1926}
1927
3601c4bf 1928int git_repository_head(git_reference **head_out, git_repository *repo)
35502d2e 1929{
b1a3a70e 1930 git_reference *head;
8b05bea8 1931 int error;
1932
b1a3a70e 1933 if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
1934 return error;
1935
1936 if (git_reference_type(head) == GIT_REF_OID) {
1937 *head_out = head;
1938 return 0;
1939 }
1940
2508cc66 1941 error = git_reference_lookup_resolved(head_out, repo, git_reference_symbolic_target(head), -1);
b1a3a70e 1942 git_reference_free(head);
8b05bea8 1943
605da51a 1944 return error == GIT_ENOTFOUND ? GIT_EUNBORNBRANCH : error;
3601c4bf 1945}
1946
605da51a 1947int git_repository_head_unborn(git_repository *repo)
3601c4bf 1948{
cb8a7961 1949 git_reference *ref = NULL;
3601c4bf 1950 int error;
1951
1952 error = git_repository_head(&ref, repo);
cb8a7961 1953 git_reference_free(ref);
35502d2e 1954
7c9bf891
ET
1955 if (error == GIT_EUNBORNBRANCH) {
1956 giterr_clear();
cb8a7961 1957 return 1;
7c9bf891 1958 }
75abd2b9 1959
cb8a7961
VM
1960 if (error < 0)
1961 return -1;
1962
1963 return 0;
35502d2e 1964}
e0011be3 1965
0066955d 1966static int at_least_one_cb(const char *refname, void *payload)
41233c40 1967{
6091457e 1968 GIT_UNUSED(refname);
1969 GIT_UNUSED(payload);
25e0b157 1970 return GIT_PASSTHROUGH;
6091457e 1971}
41233c40 1972
6091457e 1973static int repo_contains_no_reference(git_repository *repo)
1974{
ec24e542 1975 int error = git_reference_foreach_name(repo, &at_least_one_cb, NULL);
0f489fb2 1976
25e0b157 1977 if (error == GIT_PASSTHROUGH)
0f489fb2 1978 return 0;
ec24e542 1979
e976b56d
RB
1980 if (!error)
1981 return 1;
ec24e542 1982
e976b56d 1983 return error;
6091457e 1984}
75abd2b9 1985
6091457e 1986int git_repository_is_empty(git_repository *repo)
1987{
1988 git_reference *head = NULL;
42181836 1989 int is_empty = 0;
cb8a7961 1990
6091457e 1991 if (git_reference_lookup(&head, repo, GIT_HEAD_FILE) < 0)
cb8a7961
VM
1992 return -1;
1993
42181836
RB
1994 if (git_reference_type(head) == GIT_REF_SYMBOLIC)
1995 is_empty =
1996 (strcmp(git_reference_symbolic_target(head),
1997 GIT_REFS_HEADS_DIR "master") == 0) &&
1998 repo_contains_no_reference(repo);
6091457e 1999
6091457e 2000 git_reference_free(head);
42181836
RB
2001
2002 return is_empty;
41233c40
VM
2003}
2004
9462c471 2005const char *git_repository_path(git_repository *repo)
4a34b3a9 2006{
2007 assert(repo);
9462c471
VM
2008 return repo->path_repository;
2009}
4a34b3a9 2010
9462c471
VM
2011const char *git_repository_workdir(git_repository *repo)
2012{
2013 assert(repo);
602ee38b 2014
9462c471
VM
2015 if (repo->is_bare)
2016 return NULL;
602ee38b 2017
9462c471
VM
2018 return repo->workdir;
2019}
602ee38b 2020
991a56c7
RB
2021int git_repository_set_workdir(
2022 git_repository *repo, const char *workdir, int update_gitlink)
9462c471 2023{
991a56c7 2024 int error = 0;
b78fb64d 2025 git_buf path = GIT_BUF_INIT;
2026
9462c471 2027 assert(repo && workdir);
602ee38b 2028
b78fb64d 2029 if (git_path_prettify_dir(&path, workdir, NULL) < 0)
2030 return -1;
9462c471 2031
991a56c7
RB
2032 if (repo->workdir && strcmp(repo->workdir, path.ptr) == 0)
2033 return 0;
9462c471 2034
991a56c7
RB
2035 if (update_gitlink) {
2036 git_config *config;
2037
2038 if (git_repository_config__weakptr(&config, repo) < 0)
2039 return -1;
2040
bc737620 2041 error = repo_write_gitlink(path.ptr, git_repository_path(repo), false);
991a56c7
RB
2042
2043 /* passthrough error means gitlink is unnecessary */
2044 if (error == GIT_PASSTHROUGH)
54b2a37a 2045 error = git_config_delete_entry(config, "core.worktree");
991a56c7
RB
2046 else if (!error)
2047 error = git_config_set_string(config, "core.worktree", path.ptr);
2048
2049 if (!error)
2050 error = git_config_set_bool(config, "core.bare", false);
2051 }
2052
2053 if (!error) {
2054 char *old_workdir = repo->workdir;
2055
2056 repo->workdir = git_buf_detach(&path);
2057 repo->is_bare = 0;
2058
2059 git__free(old_workdir);
2060 }
2061
2062 return error;
4a34b3a9 2063}
fa9bcd81 2064
2065int git_repository_is_bare(git_repository *repo)
2066{
2067 assert(repo);
2068 return repo->is_bare;
2069}
f917481e 2070
1fbeb2f0
RB
2071int git_repository_set_bare(git_repository *repo)
2072{
2073 int error;
2074 git_config *config;
2075
2076 assert(repo);
2077
2078 if (repo->is_bare)
2079 return 0;
2080
74240afb
T
2081 if ((error = git_repository_config__weakptr(&config, repo)) < 0)
2082 return error;
2083
b2a7bcdb 2084 if ((error = git_config_set_bool(config, "core.bare", true)) < 0)
74240afb 2085 return error;
1fbeb2f0 2086
74240afb
T
2087 if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0)
2088 return error;
1fbeb2f0
RB
2089
2090 git__free(repo->workdir);
2091 repo->workdir = NULL;
1fbeb2f0
RB
2092 repo->is_bare = 1;
2093
74240afb 2094 return 0;
1fbeb2f0
RB
2095}
2096
f917481e
RB
2097int git_repository_head_tree(git_tree **tree, git_repository *repo)
2098{
5cec896a 2099 git_reference *head;
2100 git_object *obj;
2101 int error;
f917481e 2102
5cec896a 2103 if ((error = git_repository_head(&head, repo)) < 0)
2104 return error;
f917481e 2105
5cec896a 2106 if ((error = git_reference_peel(&obj, head, GIT_OBJ_TREE)) < 0)
2107 goto cleanup;
f917481e
RB
2108
2109 *tree = (git_tree *)obj;
5cec896a 2110
2111cleanup:
2112 git_reference_free(head);
2113 return error;
f917481e 2114}
074841ec 2115
867a36f3
ET
2116int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head)
2117{
2118 git_filebuf file = GIT_FILEBUF_INIT;
2119 git_buf file_path = GIT_BUF_INIT;
2120 char orig_head_str[GIT_OID_HEXSZ];
2121 int error = 0;
2122
2123 git_oid_fmt(orig_head_str, orig_head);
2124
2125 if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 &&
2126 (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 &&
2127 (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0)
2128 error = git_filebuf_commit(&file);
2129
2130 if (error < 0)
2131 git_filebuf_cleanup(&file);
2132
2133 git_buf_free(&file_path);
2134
2135 return error;
2136}
2137
3158e2fe 2138int git_repository_message(git_buf *out, git_repository *repo)
074841ec 2139{
7a3bd1e7 2140 git_buf path = GIT_BUF_INIT;
0ac349a9 2141 struct stat st;
0ac349a9 2142 int error;
074841ec 2143
7a3bd1e7 2144 git_buf_sanitize(out);
3d1c9f61 2145
632d8b23 2146 if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
0ac349a9 2147 return -1;
074841ec 2148
e9ca852e 2149 if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) {
074841ec
CMN
2150 if (errno == ENOENT)
2151 error = GIT_ENOTFOUND;
909d5494 2152 giterr_set(GITERR_OS, "could not access message file");
3158e2fe
RB
2153 } else {
2154 error = git_futils_readbuffer(out, git_buf_cstr(&path));
0ac349a9 2155 }
074841ec 2156
7a3bd1e7 2157 git_buf_free(&path);
e9ca852e
RB
2158
2159 return error;
074841ec
CMN
2160}
2161
2162int git_repository_message_remove(git_repository *repo)
2163{
0ac349a9
VM
2164 git_buf path = GIT_BUF_INIT;
2165 int error;
074841ec 2166
632d8b23 2167 if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
0ac349a9 2168 return -1;
074841ec
CMN
2169
2170 error = p_unlink(git_buf_cstr(&path));
2171 git_buf_free(&path);
2172
2173 return error;
2174}
47bfa0be
RB
2175
2176int git_repository_hashfile(
0cb16fe9
L
2177 git_oid *out,
2178 git_repository *repo,
2179 const char *path,
2180 git_otype type,
2181 const char *as_path)
47bfa0be
RB
2182{
2183 int error;
85d54812 2184 git_filter_list *fl = NULL;
b1127a30 2185 git_file fd = -1;
47bfa0be
RB
2186 git_off_t len;
2187 git_buf full_path = GIT_BUF_INIT;
2188
a13fb55a
RB
2189 assert(out && path && repo); /* as_path can be NULL */
2190
2191 /* At some point, it would be nice if repo could be NULL to just
2192 * apply filter rules defined in system and global files, but for
2193 * now that is not possible because git_filters_load() needs it.
2194 */
47bfa0be
RB
2195
2196 error = git_path_join_unrooted(
526182d2 2197 &full_path, path, git_repository_workdir(repo), NULL);
47bfa0be
RB
2198 if (error < 0)
2199 return error;
2200
2201 if (!as_path)
2202 as_path = path;
2203
2204 /* passing empty string for "as_path" indicated --no-filters */
2205 if (strlen(as_path) > 0) {
4b11f25a 2206 error = git_filter_list_load(
5269008c 2207 &fl, repo, NULL, as_path,
795eaccd 2208 GIT_FILTER_TO_ODB, GIT_FILTER_DEFAULT);
47bfa0be
RB
2209 if (error < 0)
2210 return error;
2211 } else {
2212 error = 0;
2213 }
2214
2215 /* at this point, error is a count of the number of loaded filters */
2216
2217 fd = git_futils_open_ro(full_path.ptr);
2218 if (fd < 0) {
2219 error = fd;
2220 goto cleanup;
2221 }
2222
2223 len = git_futils_filesize(fd);
2224 if (len < 0) {
75050223 2225 error = (int)len;
47bfa0be
RB
2226 goto cleanup;
2227 }
2228
2229 if (!git__is_sizet(len)) {
909d5494 2230 giterr_set(GITERR_OS, "file size overflow for 32-bit systems");
47bfa0be
RB
2231 error = -1;
2232 goto cleanup;
2233 }
2234
85d54812 2235 error = git_odb__hashfd_filtered(out, fd, (size_t)len, type, fl);
47bfa0be
RB
2236
2237cleanup:
b1127a30
SS
2238 if (fd >= 0)
2239 p_close(fd);
85d54812 2240 git_filter_list_free(fl);
47bfa0be
RB
2241 git_buf_free(&full_path);
2242
2243 return error;
2244}
2245
4e498646 2246static int checkout_message(git_buf *out, git_reference *old, const char *new)
44af67a8 2247{
4e498646
CMN
2248 git_buf_puts(out, "checkout: moving from ");
2249
2250 if (git_reference_type(old) == GIT_REF_SYMBOLIC)
2251 git_buf_puts(out, git_reference__shorthand(git_reference_symbolic_target(old)));
2252 else
2253 git_buf_puts(out, git_oid_tostr_s(git_reference_target(old)));
2254
2255 git_buf_puts(out, " to ");
2256
2257 if (git_reference__is_branch(new))
2258 git_buf_puts(out, git_reference__shorthand(new));
2259 else
2260 git_buf_puts(out, new);
2261
2262 if (git_buf_oom(out))
2263 return -1;
2264
2265 return 0;
44af67a8 2266}
2267
2268int git_repository_set_head(
2269 git_repository* repo,
4e498646 2270 const char* refname)
44af67a8 2271{
4e498646
CMN
2272 git_reference *ref = NULL, *current = NULL, *new_head = NULL;
2273 git_buf log_message = GIT_BUF_INIT;
44af67a8 2274 int error;
2275
2276 assert(repo && refname);
2277
4e498646
CMN
2278 if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
2279 return error;
2280
2281 if ((error = checkout_message(&log_message, current, refname)) < 0)
2282 goto cleanup;
2283
44af67a8 2284 error = git_reference_lookup(&ref, repo, refname);
2285 if (error < 0 && error != GIT_ENOTFOUND)
4e498646 2286 goto cleanup;
44af67a8 2287
2288 if (!error) {
94f263f5
BS
2289 if (git_reference_is_branch(ref)) {
2290 error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
4e498646 2291 git_reference_name(ref), true, git_buf_cstr(&log_message));
94f263f5 2292 } else {
4e498646 2293 error = git_repository_set_head_detached(repo, git_reference_target(ref));
94f263f5 2294 }
4e498646 2295 } else if (git_reference__is_branch(refname)) {
94f263f5 2296 error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
4e498646 2297 true, git_buf_cstr(&log_message));
94f263f5 2298 }
44af67a8 2299
4e498646 2300cleanup:
fe21d708 2301 git_buf_free(&log_message);
4e498646 2302 git_reference_free(current);
44af67a8 2303 git_reference_free(ref);
2304 git_reference_free(new_head);
2305 return error;
2306}
2307
62d38a1d 2308static int detach(git_repository *repo, const git_oid *id, const char *from)
4ebe38bd 2309{
2310 int error;
4e498646
CMN
2311 git_buf log_message = GIT_BUF_INIT;
2312 git_object *object = NULL, *peeled = NULL;
2313 git_reference *new_head = NULL, *current = NULL;
4ebe38bd 2314
62d38a1d 2315 assert(repo && id);
4ebe38bd 2316
4e498646 2317 if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
4ebe38bd 2318 return error;
2319
62d38a1d 2320 if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
4e498646
CMN
2321 goto cleanup;
2322
4ebe38bd 2323 if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
2324 goto cleanup;
2325
62d38a1d
CMN
2326 if (from == NULL)
2327 from = git_oid_tostr_s(git_object_id(peeled));
2328
2329 if ((error = checkout_message(&log_message, current, from)) < 0)
4e498646
CMN
2330 goto cleanup;
2331
2332 error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
4ebe38bd 2333
2334cleanup:
fe21d708 2335 git_buf_free(&log_message);
4ebe38bd 2336 git_object_free(object);
2337 git_object_free(peeled);
4e498646 2338 git_reference_free(current);
4ebe38bd 2339 git_reference_free(new_head);
2340 return error;
2341}
2342
62d38a1d
CMN
2343int git_repository_set_head_detached(
2344 git_repository* repo,
2345 const git_oid* commitish)
2346{
2347 return detach(repo, commitish, NULL);
2348}
2349
2350int git_repository_set_head_detached_from_annotated(
2351 git_repository *repo,
2352 const git_annotated_commit *commitish)
2353{
2354 assert(repo && commitish);
2355
d5592378 2356 return detach(repo, git_annotated_commit_id(commitish), commitish->description);
62d38a1d
CMN
2357}
2358
4e498646 2359int git_repository_detach_head(git_repository* repo)
3f4c3072 2360{
4e498646 2361 git_reference *old_head = NULL, *new_head = NULL, *current = NULL;
3f4c3072 2362 git_object *object = NULL;
4e498646 2363 git_buf log_message = GIT_BUF_INIT;
8b05bea8 2364 int error;
3f4c3072 2365
2366 assert(repo);
2367
4e498646 2368 if ((error = git_reference_lookup(&current, repo, GIT_HEAD_FILE)) < 0)
8b05bea8 2369 return error;
3f4c3072 2370
4e498646
CMN
2371 if ((error = git_repository_head(&old_head, repo)) < 0)
2372 goto cleanup;
2373
2508cc66 2374 if ((error = git_object_lookup(&object, repo, git_reference_target(old_head), GIT_OBJ_COMMIT)) < 0)
3f4c3072 2375 goto cleanup;
2376
4e498646
CMN
2377 if ((error = checkout_message(&log_message, current, git_oid_tostr_s(git_object_id(object)))) < 0)
2378 goto cleanup;
2379
010cec3a 2380 error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_reference_target(old_head),
4e498646 2381 1, git_buf_cstr(&log_message));
3f4c3072 2382
2383cleanup:
fe21d708 2384 git_buf_free(&log_message);
3f4c3072 2385 git_object_free(object);
2386 git_reference_free(old_head);
2387 git_reference_free(new_head);
4e498646 2388 git_reference_free(current);
3f4c3072 2389 return error;
2390}
632d8b23 2391
31966d20 2392/**
2393 * Loosely ported from git.git
2394 * https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh#L198-289
2395 */
632d8b23
ET
2396int git_repository_state(git_repository *repo)
2397{
2398 git_buf repo_path = GIT_BUF_INIT;
2399 int state = GIT_REPOSITORY_STATE_NONE;
2400
2401 assert(repo);
2402
2403 if (git_buf_puts(&repo_path, repo->path_repository) < 0)
2404 return -1;
2405
31966d20 2406 if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE))
2407 state = GIT_REPOSITORY_STATE_REBASE_INTERACTIVE;
2408 else if (git_path_contains_dir(&repo_path, GIT_REBASE_MERGE_DIR))
2409 state = GIT_REPOSITORY_STATE_REBASE_MERGE;
2410 else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_REBASING_FILE))
2411 state = GIT_REPOSITORY_STATE_REBASE;
2412 else if (git_path_contains_file(&repo_path, GIT_REBASE_APPLY_APPLYING_FILE))
2413 state = GIT_REPOSITORY_STATE_APPLY_MAILBOX;
2414 else if (git_path_contains_dir(&repo_path, GIT_REBASE_APPLY_DIR))
2415 state = GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE;
2416 else if (git_path_contains_file(&repo_path, GIT_MERGE_HEAD_FILE))
632d8b23 2417 state = GIT_REPOSITORY_STATE_MERGE;
2ea40fda 2418 else if (git_path_contains_file(&repo_path, GIT_REVERT_HEAD_FILE)) {
632d8b23 2419 state = GIT_REPOSITORY_STATE_REVERT;
2ea40fda
CMN
2420 if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
2421 state = GIT_REPOSITORY_STATE_REVERT_SEQUENCE;
2422 }
2423 } else if (git_path_contains_file(&repo_path, GIT_CHERRYPICK_HEAD_FILE)) {
0ba4dca5 2424 state = GIT_REPOSITORY_STATE_CHERRYPICK;
2ea40fda
CMN
2425 if (git_path_contains_file(&repo_path, GIT_SEQUENCER_TODO_FILE)) {
2426 state = GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE;
2427 }
2428 } else if (git_path_contains_file(&repo_path, GIT_BISECT_LOG_FILE))
31966d20 2429 state = GIT_REPOSITORY_STATE_BISECT;
632d8b23
ET
2430
2431 git_buf_free(&repo_path);
2432 return state;
2433}
93d8f77f 2434
c3dcbe84
VM
2435int git_repository__cleanup_files(
2436 git_repository *repo, const char *files[], size_t files_len)
bab0b9f2 2437{
c3dcbe84 2438 git_buf buf = GIT_BUF_INIT;
bab0b9f2 2439 size_t i;
c3dcbe84 2440 int error;
bab0b9f2 2441
c3dcbe84
VM
2442 for (error = 0, i = 0; !error && i < files_len; ++i) {
2443 const char *path;
bab0b9f2 2444
c3dcbe84
VM
2445 if (git_buf_joinpath(&buf, repo->path_repository, files[i]) < 0)
2446 return -1;
bab0b9f2 2447
c3dcbe84
VM
2448 path = git_buf_cstr(&buf);
2449
2450 if (git_path_isfile(path)) {
2451 error = p_unlink(path);
2452 } else if (git_path_isdir(path)) {
2453 error = git_futils_rmdir_r(path, NULL,
2454 GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS);
2455 }
2456
2457 git_buf_clear(&buf);
2458 }
bab0b9f2 2459
c3dcbe84 2460 git_buf_free(&buf);
bab0b9f2
ET
2461 return error;
2462}
2463
2464static const char *state_files[] = {
2465 GIT_MERGE_HEAD_FILE,
2466 GIT_MERGE_MODE_FILE,
2467 GIT_MERGE_MSG_FILE,
2468 GIT_REVERT_HEAD_FILE,
0ba4dca5 2469 GIT_CHERRYPICK_HEAD_FILE,
c0311295
JG
2470 GIT_BISECT_LOG_FILE,
2471 GIT_REBASE_MERGE_DIR,
2472 GIT_REBASE_APPLY_DIR,
2ea40fda 2473 GIT_SEQUENCER_DIR,
bab0b9f2
ET
2474};
2475
2476int git_repository_state_cleanup(git_repository *repo)
2477{
2478 assert(repo);
2479
2480 return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
2481}
2482
93d8f77f
BS
2483int git_repository_is_shallow(git_repository *repo)
2484{
2485 git_buf path = GIT_BUF_INIT;
2486 struct stat st;
6f0b8142 2487 int error;
93d8f77f 2488
3dbd9a0e
JG
2489 if ((error = git_buf_joinpath(&path, repo->path_repository, "shallow")) < 0)
2490 return error;
2491
6f0b8142
BS
2492 error = git_path_lstat(path.ptr, &st);
2493 git_buf_free(&path);
93d8f77f 2494
9bda5fb8
BS
2495 if (error == GIT_ENOTFOUND) {
2496 giterr_clear();
93d8f77f 2497 return 0;
9bda5fb8
BS
2498 }
2499
864535cf
BS
2500 if (error < 0)
2501 return error;
2502 return st.st_size == 0 ? 0 : 1;
93d8f77f 2503}
b9f81997 2504
702efc89
RB
2505int git_repository_init_init_options(
2506 git_repository_init_options *opts, unsigned int version)
b9f81997 2507{
702efc89
RB
2508 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
2509 opts, version, git_repository_init_options,
2510 GIT_REPOSITORY_INIT_OPTIONS_INIT);
2511 return 0;
b9f81997 2512}
659cf202
CMN
2513
2514int git_repository_ident(const char **name, const char **email, const git_repository *repo)
2515{
2516 *name = repo->ident_name;
2517 *email = repo->ident_email;
2518
2519 return 0;
2520}
2521
2522int git_repository_set_ident(git_repository *repo, const char *name, const char *email)
2523{
2524 char *tmp_name = NULL, *tmp_email = NULL;
2525
2526 if (name) {
2527 tmp_name = git__strdup(name);
2528 GITERR_CHECK_ALLOC(tmp_name);
2529 }
2530
2531 if (email) {
2532 tmp_email = git__strdup(email);
2533 GITERR_CHECK_ALLOC(tmp_email);
2534 }
2535
2536 tmp_name = git__swap(repo->ident_name, tmp_name);
2537 tmp_email = git__swap(repo->ident_email, tmp_email);
2538
2539 git__free(tmp_name);
2540 git__free(tmp_email);
2541
2542 return 0;
2543}