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