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