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