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