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 "worktree.h"
9 -
10 - #include "git2/branch.h"
11 - #include "git2/commit.h"
12 - #include "git2/worktree.h"
13 -
14 - #include "repository.h"
15 -
16 80 2 static bool is_worktree_dir(const char *dir)
17 - {
18 80 2 git_buf buf = GIT_BUF_INIT;
19 - int error;
20 -
21 80 2,3 if (git_buf_sets(&buf, dir) < 0)
22 ##### 4 return -1;
23 -
24 80 5,13 error = git_path_contains_file(&buf, "commondir")
25 77 7,8 && git_path_contains_file(&buf, "gitdir")
26 80 6,9-12 && git_path_contains_file(&buf, "HEAD");
27 -
28 80 13 git_buf_dispose(&buf);
29 80 14 return error;
30 - }
31 -
32 101 2 int git_worktree_list(git_strarray *wts, git_repository *repo)
33 - {
34 101 2 git_vector worktrees = GIT_VECTOR_INIT;
35 101 2 git_buf path = GIT_BUF_INIT;
36 - char *worktree;
37 - size_t i, len;
38 - int error;
39 -
40 101 2-4 assert(wts && repo);
41 -
42 101 5 wts->count = 0;
43 101 5 wts->strings = NULL;
44 -
45 101 5,6 if ((error = git_buf_printf(&path, "%s/worktrees/", repo->commondir)) < 0)
46 ##### 7 goto exit;
47 101 8-11 if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr))
48 - goto exit;
49 40 12,13 if ((error = git_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0)
50 ##### 14 goto exit;
51 -
52 40 15 len = path.size;
53 -
54 80 15,22-24 git_vector_foreach(&worktrees, i, worktree) {
55 40 16 git_buf_truncate(&path, len);
56 40 17 git_buf_puts(&path, worktree);
57 -
58 40 18,19 if (!is_worktree_dir(path.ptr)) {
59 3 20 git_vector_remove(&worktrees, i);
60 3 21 git__free(worktree);
61 - }
62 - }
63 -
64 40 25,26 wts->strings = (char **)git_vector_detach(&wts->count, NULL, &worktrees);
65 -
66 - exit:
67 101 27 git_buf_dispose(&path);
68 -
69 101 28 return error;
70 - }
71 -
72 3503 2 char *git_worktree__read_link(const char *base, const char *file)
73 - {
74 3503 2 git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
75 -
76 3503 2-4 assert(base && file);
77 -
78 3503 5,6 if (git_buf_joinpath(&path, base, file) < 0)
79 ##### 7 goto err;
80 3503 8,9 if (git_futils_readbuffer(&buf, path.ptr) < 0)
81 3336 10 goto err;
82 167 11 git_buf_dispose(&path);
83 -
84 167 12 git_buf_rtrim(&buf);
85 -
86 167 13,14 if (!git_path_is_relative(buf.ptr))
87 32 15 return git_buf_detach(&buf);
88 -
89 135 16,17 if (git_buf_sets(&path, base) < 0)
90 ##### 18 goto err;
91 135 19,20 if (git_path_apply_relative(&path, buf.ptr) < 0)
92 ##### 21 goto err;
93 135 22 git_buf_dispose(&buf);
94 -
95 135 23 return git_buf_detach(&path);
96 -
97 - err:
98 3336 24 git_buf_dispose(&buf);
99 3336 25 git_buf_dispose(&path);
100 -
101 3336 26 return NULL;
102 - }
103 -
104 21 2 static int write_wtfile(const char *base, const char *file, const git_buf *buf)
105 - {
106 21 2 git_buf path = GIT_BUF_INIT;
107 - int err;
108 -
109 21 2-5 assert(base && file && buf);
110 -
111 21 6,7 if ((err = git_buf_joinpath(&path, base, file)) < 0)
112 ##### 8 goto out;
113 -
114 21 9,10 if ((err = git_futils_writebuffer(buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
115 ##### 11 goto out;
116 -
117 - out:
118 21 12 git_buf_dispose(&path);
119 -
120 21 13 return err;
121 - }
122 -
123 34 2 static int open_worktree_dir(git_worktree **out, const char *parent, const char *dir, const char *name)
124 - {
125 34 2 git_buf gitdir = GIT_BUF_INIT;
126 34 2 git_worktree *wt = NULL;
127 34 2 int error = 0;
128 -
129 34 2,3 if (!is_worktree_dir(dir)) {
130 1 4 error = -1;
131 1 4 goto out;
132 - }
133 -
134 33 5,6 if ((wt = git__calloc(1, sizeof(*wt))) == NULL) {
135 ##### 7 error = -1;
136 ##### 7 goto out;
137 - }
138 -
139 33 8,9,11 if ((wt->name = git__strdup(name)) == NULL ||
140 33 10,13 (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL ||
141 33 12,14 (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL ||
142 33 15,16,18 (parent && (wt->parent_path = git__strdup(parent)) == NULL) ||
143 33 17 (wt->worktree_path = git_path_dirname(wt->gitlink_path)) == NULL) {
144 ##### 19 error = -1;
145 ##### 19 goto out;
146 - }
147 -
148 33 20,21 if ((error = git_path_prettify_dir(&gitdir, dir, NULL)) < 0)
149 ##### 22 goto out;
150 33 23 wt->gitdir_path = git_buf_detach(&gitdir);
151 -
152 33 24,25 if ((error = git_worktree_is_locked(NULL, wt)) < 0)
153 ##### 26 goto out;
154 33 27 wt->locked = !!error;
155 33 27 error = 0;
156 -
157 33 27 *out = wt;
158 -
159 - out:
160 34 28 if (error)
161 1 29 git_worktree_free(wt);
162 34 30 git_buf_dispose(&gitdir);
163 -
164 34 31 return error;
165 - }
166 -
167 31 2 int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
168 - {
169 31 2 git_buf path = GIT_BUF_INIT;
170 31 2 git_worktree *wt = NULL;
171 - int error;
172 -
173 31 2-4 assert(repo && name);
174 -
175 31 5 *out = NULL;
176 -
177 31 5,6 if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
178 ##### 7 goto out;
179 -
180 31 8-10 if ((error = (open_worktree_dir(out, git_repository_workdir(repo), path.ptr, name))) < 0)
181 1 11 goto out;
182 -
183 - out:
184 31 12 git_buf_dispose(&path);
185 -
186 31 13 if (error)
187 1 14 git_worktree_free(wt);
188 -
189 31 15 return error;
190 - }
191 -
192 4 2 int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
193 - {
194 4 2 git_buf parent = GIT_BUF_INIT;
195 - const char *gitdir, *commondir;
196 4 2 char *name = NULL;
197 4 2 int error = 0;
198 -
199 4 2,3 if (!git_repository_is_worktree(repo)) {
200 1 4 git_error_set(GIT_ERROR_WORKTREE, "cannot open worktree of a non-worktree repo");
201 1 5 error = -1;
202 1 5 goto out;
203 - }
204 -
205 3 6 gitdir = git_repository_path(repo);
206 3 7 commondir = git_repository_commondir(repo);
207 -
208 3 8,9 if ((error = git_path_prettify_dir(&parent, "..", commondir)) < 0)
209 ##### 10 goto out;
210 -
211 - /* The name is defined by the last component in '.git/worktree/%s' */
212 3 11 name = git_path_basename(gitdir);
213 -
214 3 12,13 if ((error = open_worktree_dir(out, parent.ptr, gitdir, name)) < 0)
215 ##### 14 goto out;
216 -
217 - out:
218 4 15 git__free(name);
219 4 16 git_buf_dispose(&parent);
220 -
221 4 17 return error;
222 - }
223 -
224 51 2 void git_worktree_free(git_worktree *wt)
225 - {
226 51 2 if (!wt)
227 51 3,11 return;
228 -
229 33 4 git__free(wt->commondir_path);
230 33 5 git__free(wt->worktree_path);
231 33 6 git__free(wt->gitlink_path);
232 33 7 git__free(wt->gitdir_path);
233 33 8 git__free(wt->parent_path);
234 33 9 git__free(wt->name);
235 33 10 git__free(wt);
236 - }
237 -
238 6 2 int git_worktree_validate(const git_worktree *wt)
239 - {
240 6 2,3 assert(wt);
241 -
242 6 4,5 if (!is_worktree_dir(wt->gitdir_path)) {
243 1 6 git_error_set(GIT_ERROR_WORKTREE,
244 - "worktree gitdir ('%s') is not valid",
245 - wt->gitlink_path);
246 1 7 return GIT_ERROR;
247 - }
248 -
249 5 8-10 if (wt->parent_path && !git_path_exists(wt->parent_path)) {
250 1 11 git_error_set(GIT_ERROR_WORKTREE,
251 - "worktree parent directory ('%s') does not exist ",
252 - wt->parent_path);
253 1 12 return GIT_ERROR;
254 - }
255 -
256 4 13,14 if (!git_path_exists(wt->commondir_path)) {
257 1 15 git_error_set(GIT_ERROR_WORKTREE,
258 - "worktree common directory ('%s') does not exist ",
259 - wt->commondir_path);
260 1 16 return GIT_ERROR;
261 - }
262 -
263 3 17 return 0;
264 - }
265 -
266 ##### 2 int git_worktree_add_options_init(git_worktree_add_options *opts,
267 - unsigned int version)
268 - {
269 ##### 2-4 GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
270 - git_worktree_add_options, GIT_WORKTREE_ADD_OPTIONS_INIT);
271 ##### 5 return 0;
272 - }
273 -
274 - #ifndef GIT_DEPRECATE_HARD
275 ##### 2 int git_worktree_add_init_options(git_worktree_add_options *opts,
276 - unsigned int version)
277 - {
278 ##### 2 return git_worktree_add_options_init(opts, version);
279 - }
280 - #endif
281 -
282 10 2 int git_worktree_add(git_worktree **out, git_repository *repo,
283 - const char *name, const char *worktree,
284 - const git_worktree_add_options *opts)
285 - {
286 10 2 git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT, buf = GIT_BUF_INIT;
287 10 2 git_reference *ref = NULL, *head = NULL;
288 10 2 git_commit *commit = NULL;
289 10 2 git_repository *wt = NULL;
290 10 2 git_checkout_options coopts = GIT_CHECKOUT_OPTIONS_INIT;
291 10 2 git_worktree_add_options wtopts = GIT_WORKTREE_ADD_OPTIONS_INIT;
292 - int err;
293 -
294 10 2-4 GIT_ERROR_CHECK_VERSION(
295 - opts, GIT_WORKTREE_ADD_OPTIONS_VERSION, "git_worktree_add_options");
296 -
297 10 5 if (opts)
298 2 6 memcpy(&wtopts, opts, sizeof(wtopts));
299 -
300 10 7-11 assert(out && repo && name && worktree);
301 -
302 10 12 *out = NULL;
303 -
304 10 12 if (wtopts.ref) {
305 1 13,14 if (!git_reference_is_branch(wtopts.ref)) {
306 ##### 15 git_error_set(GIT_ERROR_WORKTREE, "reference is not a branch");
307 ##### 16 err = -1;
308 ##### 16 goto out;
309 - }
310 -
311 1 17,18 if (git_branch_is_checked_out(wtopts.ref)) {
312 ##### 19 git_error_set(GIT_ERROR_WORKTREE, "reference is already checked out");
313 ##### 20 err = -1;
314 ##### 20 goto out;
315 - }
316 - }
317 -
318 - /* Create gitdir directory ".git/worktrees/<name>" */
319 10 21,22 if ((err = git_buf_joinpath(&gitdir, repo->commondir, "worktrees")) < 0)
320 ##### 23 goto out;
321 10 24,25 if (!git_path_exists(gitdir.ptr))
322 3 26,27 if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
323 ##### 28 goto out;
324 10 29,30 if ((err = git_buf_joinpath(&gitdir, gitdir.ptr, name)) < 0)
325 ##### 31 goto out;
326 10 32,33 if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
327 1 34 goto out;
328 9 35,36 if ((err = git_path_prettify_dir(&gitdir, gitdir.ptr, NULL)) < 0)
329 ##### 37 goto out;
330 -
331 - /* Create worktree work dir */
332 9 38,39 if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0)
333 2 40 goto out;
334 7 41,42 if ((err = git_path_prettify_dir(&wddir, worktree, NULL)) < 0)
335 ##### 43 goto out;
336 -
337 7 44 if (wtopts.lock) {
338 - int fd;
339 -
340 1 45,46 if ((err = git_buf_joinpath(&buf, gitdir.ptr, "locked")) < 0)
341 ##### 47 goto out;
342 -
343 1 48,49 if ((fd = p_creat(buf.ptr, 0644)) < 0) {
344 ##### 50 err = fd;
345 ##### 50 goto out;
346 - }
347 -
348 1 51 p_close(fd);
349 1 52 git_buf_clear(&buf);
350 - }
351 -
352 - /* Create worktree .git file */
353 7 53,54 if ((err = git_buf_printf(&buf, "gitdir: %s\n", gitdir.ptr)) < 0)
354 ##### 55 goto out;
355 7 56,57 if ((err = write_wtfile(wddir.ptr, ".git", &buf)) < 0)
356 ##### 58 goto out;
357 -
358 - /* Create gitdir files */
359 7 59,60 if ((err = git_path_prettify_dir(&buf, repo->commondir, NULL) < 0)
360 7 61,62 || (err = git_buf_putc(&buf, '\n')) < 0
361 7 63,64 || (err = write_wtfile(gitdir.ptr, "commondir", &buf)) < 0)
362 - goto out;
363 7 65,66 if ((err = git_buf_joinpath(&buf, wddir.ptr, ".git")) < 0
364 7 67,68 || (err = git_buf_putc(&buf, '\n')) < 0
365 7 69,70 || (err = write_wtfile(gitdir.ptr, "gitdir", &buf)) < 0)
366 - goto out;
367 -
368 - /* Set up worktree reference */
369 7 71 if (wtopts.ref) {
370 1 72,73 if ((err = git_reference_dup(&ref, wtopts.ref)) < 0)
371 ##### 74 goto out;
372 - } else {
373 6 75,76 if ((err = git_repository_head(&head, repo)) < 0)
374 ##### 77 goto out;
375 6 78,79 if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0)
376 ##### 80 goto out;
377 6 81,82 if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0)
378 ##### 83 goto out;
379 - }
380 -
381 - /* Set worktree's HEAD */
382 7 84-86 if ((err = git_repository_create_head(gitdir.ptr, git_reference_name(ref))) < 0)
383 ##### 87 goto out;
384 7 88,89 if ((err = git_repository_open(&wt, wddir.ptr)) < 0)
385 ##### 90 goto out;
386 -
387 - /* Checkout worktree's HEAD */
388 7 91 coopts.checkout_strategy = GIT_CHECKOUT_FORCE;
389 7 91,92 if ((err = git_checkout_head(wt, &coopts)) < 0)
390 ##### 93 goto out;
391 -
392 - /* Load result */
393 7 94,95 if ((err = git_worktree_lookup(out, repo, name)) < 0)
394 ##### 96 goto out;
395 -
396 - out:
397 10 97 git_buf_dispose(&gitdir);
398 10 98 git_buf_dispose(&wddir);
399 10 99 git_buf_dispose(&buf);
400 10 100 git_reference_free(ref);
401 10 101 git_reference_free(head);
402 10 102 git_commit_free(commit);
403 10 103 git_repository_free(wt);
404 -
405 10 104 return err;
406 - }
407 -
408 4 2 int git_worktree_lock(git_worktree *wt, const char *reason)
409 - {
410 4 2 git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
411 - int error;
412 -
413 4 2,3 assert(wt);
414 -
415 4 4,5 if ((error = git_worktree_is_locked(NULL, wt)) < 0)
416 ##### 6 goto out;
417 4 7 if (error) {
418 ##### 8 error = GIT_ELOCKED;
419 ##### 8 goto out;
420 - }
421 -
422 4 9,10 if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
423 ##### 11 goto out;
424 -
425 4 12 if (reason)
426 1 13 git_buf_attach_notowned(&buf, reason, strlen(reason));
427 -
428 4 14,15 if ((error = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
429 ##### 16 goto out;
430 -
431 4 17 wt->locked = 1;
432 -
433 - out:
434 4 18 git_buf_dispose(&path);
435 -
436 4 19 return error;
437 - }
438 -
439 2 2 int git_worktree_unlock(git_worktree *wt)
440 - {
441 2 2 git_buf path = GIT_BUF_INIT;
442 - int error;
443 -
444 2 2,3 assert(wt);
445 -
446 2 4,5 if ((error = git_worktree_is_locked(NULL, wt)) < 0)
447 ##### 6 return error;
448 2 7 if (!error)
449 1 8 return 1;
450 -
451 1 9,10 if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
452 ##### 11 return -1;
453 -
454 1 12,13 if (p_unlink(path.ptr) != 0) {
455 ##### 14 git_buf_dispose(&path);
456 ##### 15 return -1;
457 - }
458 -
459 1 16 wt->locked = 0;
460 -
461 1 16 git_buf_dispose(&path);
462 -
463 1 17 return 0;
464 - }
465 -
466 52 2 int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
467 - {
468 52 2 git_buf path = GIT_BUF_INIT;
469 - int error, locked;
470 -
471 52 2,3 assert(wt);
472 -
473 52 4 if (reason)
474 8 5 git_buf_clear(reason);
475 -
476 52 6,7 if ((error = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
477 ##### 8 goto out;
478 52 9 locked = git_path_exists(path.ptr);
479 52 10-13 if (locked && reason &&
480 3 12 (error = git_futils_readbuffer(reason, path.ptr)) < 0)
481 ##### 14 goto out;
482 -
483 52 15 error = locked;
484 - out:
485 52 16 git_buf_dispose(&path);
486 -
487 52 17 return error;
488 - }
489 -
490 1 2 const char *git_worktree_name(const git_worktree *wt)
491 - {
492 1 2,3 assert(wt);
493 1 4 return wt->name;
494 - }
495 -
496 2 2 const char *git_worktree_path(const git_worktree *wt)
497 - {
498 2 2,3 assert(wt);
499 2 4 return wt->worktree_path;
500 - }
501 -
502 ##### 2 int git_worktree_prune_options_init(
503 - git_worktree_prune_options *opts,
504 - unsigned int version)
505 - {
506 ##### 2-4 GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
507 - git_worktree_prune_options, GIT_WORKTREE_PRUNE_OPTIONS_INIT);
508 ##### 5 return 0;
509 - }
510 -
511 - #ifndef GIT_DEPRECATE_HARD
512 ##### 2 int git_worktree_prune_init_options(git_worktree_prune_options *opts,
513 - unsigned int version)
514 - {
515 ##### 2 return git_worktree_prune_options_init(opts, version);
516 - }
517 - #endif
518 -
519 7 2 int git_worktree_is_prunable(git_worktree *wt,
520 - git_worktree_prune_options *opts)
521 - {
522 7 2 git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
523 -
524 7 2-4 GIT_ERROR_CHECK_VERSION(
525 - opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
526 - "git_worktree_prune_options");
527 -
528 7 5 if (opts)
529 7 6 memcpy(&popts, opts, sizeof(popts));
530 -
531 7 7 if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0) {
532 6 8 git_buf reason = GIT_BUF_INIT;
533 - int error;
534 -
535 6 8,9 if ((error = git_worktree_is_locked(&reason, wt)) < 0)
536 1 10,18 return error;
537 -
538 6 11 if (error) {
539 1 12 if (!reason.size)
540 1 13 git_buf_attach_notowned(&reason, "no reason given", 15);
541 1 14 git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr);
542 1 15 git_buf_dispose(&reason);
543 5 16,17 return 0;
544 - }
545 - }
546 -
547 6 19,21 if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
548 1 20 git_worktree_validate(wt) == 0) {
549 1 22 git_error_set(GIT_ERROR_WORKTREE, "not pruning valid working tree");
550 1 23 return 0;
551 - }
552 -
553 5 24 return 1;
554 - }
555 -
556 7 2 int git_worktree_prune(git_worktree *wt,
557 - git_worktree_prune_options *opts)
558 - {
559 7 2 git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
560 7 2 git_buf path = GIT_BUF_INIT;
561 - char *wtpath;
562 - int err;
563 -
564 7 2-4 GIT_ERROR_CHECK_VERSION(
565 - opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
566 - "git_worktree_prune_options");
567 -
568 7 5 if (opts)
569 6 6 memcpy(&popts, opts, sizeof(popts));
570 -
571 7 7,8 if (!git_worktree_is_prunable(wt, &popts)) {
572 2 9 err = -1;
573 2 9 goto out;
574 - }
575 -
576 - /* Delete gitdir in parent repository */
577 5 10,11 if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->commondir_path, wt->name)) < 0)
578 ##### 12 goto out;
579 5 13,14 if (!git_path_exists(path.ptr))
580 - {
581 ##### 15 git_error_set(GIT_ERROR_WORKTREE, "worktree gitdir '%s' does not exist", path.ptr);
582 ##### 16 err = -1;
583 ##### 16 goto out;
584 - }
585 5 17,18 if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
586 ##### 19 goto out;
587 -
588 - /* Skip deletion of the actual working tree if it does
589 - * not exist or deletion was not requested */
590 5 20,22 if ((popts.flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
591 1 21 !git_path_exists(wt->gitlink_path))
592 - {
593 - goto out;
594 - }
595 -
596 1 23,24 if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL)
597 ##### 25 goto out;
598 1 26 git_buf_attach(&path, wtpath, 0);
599 1 27,28 if (!git_path_exists(path.ptr))
600 - {
601 ##### 29 git_error_set(GIT_ERROR_WORKTREE, "working tree '%s' does not exist", path.ptr);
602 ##### 30 err = -1;
603 ##### 30 goto out;
604 - }
605 1 31,32 if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
606 ##### 33 goto out;
607 -
608 - out:
609 7 34 git_buf_dispose(&path);
610 -
611 7 35 return err;
612 - }