rugged 0.26.0b3 → 0.26.0b4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/ext/rugged/extconf.rb +10 -7
  4. data/ext/rugged/rugged.c +4 -6
  5. data/ext/rugged/rugged_repo.c +1 -1
  6. data/ext/rugged/rugged_revwalk.c +4 -4
  7. data/ext/rugged/rugged_tree.c +2 -2
  8. data/lib/rugged/version.rb +1 -1
  9. data/vendor/libgit2/CMakeLists.txt +13 -6
  10. data/vendor/libgit2/COPYING +33 -0
  11. data/vendor/libgit2/include/git2/branch.h +12 -0
  12. data/vendor/libgit2/include/git2/commit.h +6 -3
  13. data/vendor/libgit2/include/git2/common.h +11 -0
  14. data/vendor/libgit2/include/git2/errors.h +2 -0
  15. data/vendor/libgit2/include/git2/index.h +7 -6
  16. data/vendor/libgit2/include/git2/repository.h +91 -0
  17. data/vendor/libgit2/include/git2/stash.h +2 -2
  18. data/vendor/libgit2/include/git2/types.h +3 -0
  19. data/vendor/libgit2/include/git2/worktree.h +161 -0
  20. data/vendor/libgit2/src/attr.c +24 -16
  21. data/vendor/libgit2/src/attr_file.h +1 -1
  22. data/vendor/libgit2/src/attrcache.c +11 -10
  23. data/vendor/libgit2/src/attrcache.h +1 -4
  24. data/vendor/libgit2/src/blob.c +2 -2
  25. data/vendor/libgit2/src/branch.c +63 -0
  26. data/vendor/libgit2/src/buffer.h +2 -1
  27. data/vendor/libgit2/src/cache.c +21 -25
  28. data/vendor/libgit2/src/cache.h +1 -1
  29. data/vendor/libgit2/src/checkout.c +0 -2
  30. data/vendor/libgit2/src/cherrypick.c +2 -2
  31. data/vendor/libgit2/src/clone.c +2 -3
  32. data/vendor/libgit2/src/commit.c +8 -4
  33. data/vendor/libgit2/src/config_file.c +1 -3
  34. data/vendor/libgit2/src/describe.c +1 -3
  35. data/vendor/libgit2/src/diff_driver.c +2 -4
  36. data/vendor/libgit2/src/fetchhead.c +2 -2
  37. data/vendor/libgit2/src/fileops.c +1 -3
  38. data/vendor/libgit2/src/hash.h +5 -3
  39. data/vendor/libgit2/src/hash/hash_collisiondetect.h +57 -0
  40. data/vendor/libgit2/src/hash/sha1dc/sha1.c +1149 -0
  41. data/vendor/libgit2/src/hash/sha1dc/sha1.h +94 -0
  42. data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +361 -0
  43. data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +35 -0
  44. data/vendor/libgit2/src/idxmap.c +133 -0
  45. data/vendor/libgit2/src/idxmap.h +22 -60
  46. data/vendor/libgit2/src/ignore.c +7 -1
  47. data/vendor/libgit2/src/ignore.h +1 -1
  48. data/vendor/libgit2/src/index.c +11 -14
  49. data/vendor/libgit2/src/indexer.c +8 -11
  50. data/vendor/libgit2/src/merge.c +5 -5
  51. data/vendor/libgit2/src/mwindow.c +1 -3
  52. data/vendor/libgit2/src/odb.c +3 -3
  53. data/vendor/libgit2/src/odb.h +3 -0
  54. data/vendor/libgit2/src/odb_mempack.c +11 -18
  55. data/vendor/libgit2/src/offmap.c +83 -0
  56. data/vendor/libgit2/src/offmap.h +14 -34
  57. data/vendor/libgit2/src/oidmap.c +105 -0
  58. data/vendor/libgit2/src/oidmap.h +19 -22
  59. data/vendor/libgit2/src/pack-objects.c +10 -13
  60. data/vendor/libgit2/src/pack.c +17 -26
  61. data/vendor/libgit2/src/path.c +45 -24
  62. data/vendor/libgit2/src/rebase.c +3 -3
  63. data/vendor/libgit2/src/refdb_fs.c +81 -46
  64. data/vendor/libgit2/src/refs.c +13 -3
  65. data/vendor/libgit2/src/remote.c +6 -2
  66. data/vendor/libgit2/src/repository.c +318 -46
  67. data/vendor/libgit2/src/repository.h +5 -2
  68. data/vendor/libgit2/src/revert.c +2 -2
  69. data/vendor/libgit2/src/revwalk.c +6 -8
  70. data/vendor/libgit2/src/settings.c +5 -0
  71. data/vendor/libgit2/src/sortedcache.c +3 -5
  72. data/vendor/libgit2/src/strmap.c +95 -0
  73. data/vendor/libgit2/src/strmap.h +17 -37
  74. data/vendor/libgit2/src/submodule.c +12 -8
  75. data/vendor/libgit2/src/thread-utils.h +6 -0
  76. data/vendor/libgit2/src/transaction.c +5 -17
  77. data/vendor/libgit2/src/transports/local.c +2 -1
  78. data/vendor/libgit2/src/transports/smart.h +2 -0
  79. data/vendor/libgit2/src/transports/smart_protocol.c +3 -1
  80. data/vendor/libgit2/src/tree.c +2 -4
  81. data/vendor/libgit2/src/unix/posix.h +1 -1
  82. data/vendor/libgit2/src/worktree.c +432 -0
  83. data/vendor/libgit2/src/worktree.h +35 -0
  84. metadata +13 -2
@@ -26,6 +26,8 @@
26
26
  #define GIT_CAP_THIN_PACK "thin-pack"
27
27
  #define GIT_CAP_SYMREF "symref"
28
28
 
29
+ extern bool git_smart__ofs_delta_enabled;
30
+
29
31
  enum git_pkt_type {
30
32
  GIT_PKT_CMD,
31
33
  GIT_PKT_FLUSH,
@@ -19,6 +19,8 @@
19
19
  /* The minimal interval between progress updates (in seconds). */
20
20
  #define MIN_PROGRESS_UPDATE_INTERVAL 0.5
21
21
 
22
+ bool git_smart__ofs_delta_enabled = true;
23
+
22
24
  int git_smart__store_refs(transport_smart *t, int flushes)
23
25
  {
24
26
  gitno_buffer *buf = &t->buffer;
@@ -138,7 +140,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec
138
140
  if (*ptr == ' ')
139
141
  ptr++;
140
142
 
141
- if (!git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) {
143
+ if (git_smart__ofs_delta_enabled && !git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) {
142
144
  caps->common = caps->ofs_delta = 1;
143
145
  ptr += strlen(GIT_CAP_OFS_DELTA);
144
146
  continue;
@@ -20,8 +20,6 @@
20
20
  #define TREE_ENTRY_CHECK_NAMELEN(n) \
21
21
  if (n > UINT16_MAX) { giterr_set(GITERR_INVALID, "tree entry path too long"); }
22
22
 
23
- GIT__USE_STRMAP
24
-
25
23
  static bool valid_filemode(const int filemode)
26
24
  {
27
25
  return (filemode == GIT_FILEMODE_TREE
@@ -505,7 +503,7 @@ static int append_entry(
505
503
 
506
504
  entry->attr = (uint16_t)filemode;
507
505
 
508
- git_strmap_insert(bld->map, entry->filename, entry, error);
506
+ git_strmap_insert(bld->map, entry->filename, entry, &error);
509
507
  if (error < 0) {
510
508
  git_tree_entry_free(entry);
511
509
  giterr_set(GITERR_TREE, "failed to append entry %s to the tree builder", filename);
@@ -754,7 +752,7 @@ int git_treebuilder_insert(
754
752
  entry = alloc_entry(filename, strlen(filename), id);
755
753
  GITERR_CHECK_ALLOC(entry);
756
754
 
757
- git_strmap_insert(bld->map, entry->filename, entry, error);
755
+ git_strmap_insert(bld->map, entry->filename, entry, &error);
758
756
 
759
757
  if (error < 0) {
760
758
  git_tree_entry_free(entry);
@@ -50,7 +50,7 @@ extern char *p_realpath(const char *, char *);
50
50
  #define p_strcasecmp(s1, s2) strcasecmp(s1, s2)
51
51
  #define p_strncasecmp(s1, s2, c) strncasecmp(s1, s2, c)
52
52
  #define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a)
53
- #define p_snprintf(b, c, f, ...) snprintf(b, c, f, __VA_ARGS__)
53
+ #define p_snprintf(b, c, ...) snprintf(b, c, __VA_ARGS__)
54
54
  #define p_mkstemp(p) mkstemp(p)
55
55
  #define p_chdir(p) chdir(p)
56
56
  #define p_chmod(p,m) chmod(p, m)
@@ -0,0 +1,432 @@
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 "common.h"
9
+
10
+ #include "git2/branch.h"
11
+ #include "git2/commit.h"
12
+ #include "git2/worktree.h"
13
+
14
+ #include "repository.h"
15
+ #include "worktree.h"
16
+
17
+ static bool is_worktree_dir(git_buf *dir)
18
+ {
19
+ return git_path_contains_file(dir, "commondir")
20
+ && git_path_contains_file(dir, "gitdir")
21
+ && git_path_contains_file(dir, "HEAD");
22
+ }
23
+
24
+ int git_worktree_list(git_strarray *wts, git_repository *repo)
25
+ {
26
+ git_vector worktrees = GIT_VECTOR_INIT;
27
+ git_buf path = GIT_BUF_INIT;
28
+ char *worktree;
29
+ unsigned i, len;
30
+ int error;
31
+
32
+ assert(wts && repo);
33
+
34
+ wts->count = 0;
35
+ wts->strings = NULL;
36
+
37
+ if ((error = git_buf_printf(&path, "%s/worktrees/", repo->commondir)) < 0)
38
+ goto exit;
39
+ if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr))
40
+ goto exit;
41
+ if ((error = git_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0)
42
+ goto exit;
43
+
44
+ len = path.size;
45
+
46
+ git_vector_foreach(&worktrees, i, worktree) {
47
+ git_buf_truncate(&path, len);
48
+ git_buf_puts(&path, worktree);
49
+
50
+ if (!is_worktree_dir(&path)) {
51
+ git_vector_remove(&worktrees, i);
52
+ git__free(worktree);
53
+ }
54
+ }
55
+
56
+ wts->strings = (char **)git_vector_detach(&wts->count, NULL, &worktrees);
57
+
58
+ exit:
59
+ git_buf_free(&path);
60
+
61
+ return error;
62
+ }
63
+
64
+ char *git_worktree__read_link(const char *base, const char *file)
65
+ {
66
+ git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
67
+
68
+ assert(base && file);
69
+
70
+ if (git_buf_joinpath(&path, base, file) < 0)
71
+ goto err;
72
+ if (git_futils_readbuffer(&buf, path.ptr) < 0)
73
+ goto err;
74
+ git_buf_free(&path);
75
+
76
+ git_buf_rtrim(&buf);
77
+
78
+ if (!git_path_is_relative(buf.ptr))
79
+ return git_buf_detach(&buf);
80
+
81
+ if (git_buf_sets(&path, base) < 0)
82
+ goto err;
83
+ if (git_path_apply_relative(&path, buf.ptr) < 0)
84
+ goto err;
85
+ git_buf_free(&buf);
86
+
87
+ return git_buf_detach(&path);
88
+
89
+ err:
90
+ git_buf_free(&buf);
91
+ git_buf_free(&path);
92
+
93
+ return NULL;
94
+ }
95
+
96
+ static int write_wtfile(const char *base, const char *file, const git_buf *buf)
97
+ {
98
+ git_buf path = GIT_BUF_INIT;
99
+ int err;
100
+
101
+ assert(base && file && buf);
102
+
103
+ if ((err = git_buf_joinpath(&path, base, file)) < 0)
104
+ goto out;
105
+
106
+ if ((err = git_futils_writebuffer(buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
107
+ goto out;
108
+
109
+ out:
110
+ git_buf_free(&path);
111
+
112
+ return err;
113
+ }
114
+
115
+ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
116
+ {
117
+ git_buf path = GIT_BUF_INIT;
118
+ git_worktree *wt = NULL;
119
+ int error;
120
+
121
+ assert(repo && name);
122
+
123
+ *out = NULL;
124
+
125
+ if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
126
+ goto out;
127
+
128
+ if (!is_worktree_dir(&path)) {
129
+ error = -1;
130
+ goto out;
131
+ }
132
+
133
+ if ((wt = git__malloc(sizeof(struct git_repository))) == NULL) {
134
+ error = -1;
135
+ goto out;
136
+ }
137
+
138
+ if ((wt->name = git__strdup(name)) == NULL
139
+ || (wt->commondir_path = git_worktree__read_link(path.ptr, "commondir")) == NULL
140
+ || (wt->gitlink_path = git_worktree__read_link(path.ptr, "gitdir")) == NULL
141
+ || (wt->parent_path = git__strdup(git_repository_path(repo))) == NULL) {
142
+ error = -1;
143
+ goto out;
144
+ }
145
+ wt->gitdir_path = git_buf_detach(&path);
146
+ wt->locked = !!git_worktree_is_locked(NULL, wt);
147
+
148
+ (*out) = wt;
149
+
150
+ out:
151
+ git_buf_free(&path);
152
+
153
+ if (error)
154
+ git_worktree_free(wt);
155
+
156
+ return error;
157
+ }
158
+
159
+ void git_worktree_free(git_worktree *wt)
160
+ {
161
+ if (!wt)
162
+ return;
163
+
164
+ git__free(wt->commondir_path);
165
+ git__free(wt->gitlink_path);
166
+ git__free(wt->gitdir_path);
167
+ git__free(wt->parent_path);
168
+ git__free(wt->name);
169
+ git__free(wt);
170
+ }
171
+
172
+ int git_worktree_validate(const git_worktree *wt)
173
+ {
174
+ git_buf buf = GIT_BUF_INIT;
175
+ int err = 0;
176
+
177
+ assert(wt);
178
+
179
+ git_buf_puts(&buf, wt->gitdir_path);
180
+ if (!is_worktree_dir(&buf)) {
181
+ giterr_set(GITERR_WORKTREE,
182
+ "Worktree gitdir ('%s') is not valid",
183
+ wt->gitlink_path);
184
+ err = -1;
185
+ goto out;
186
+ }
187
+
188
+ if (!git_path_exists(wt->parent_path)) {
189
+ giterr_set(GITERR_WORKTREE,
190
+ "Worktree parent directory ('%s') does not exist ",
191
+ wt->parent_path);
192
+ err = -2;
193
+ goto out;
194
+ }
195
+
196
+ if (!git_path_exists(wt->commondir_path)) {
197
+ giterr_set(GITERR_WORKTREE,
198
+ "Worktree common directory ('%s') does not exist ",
199
+ wt->commondir_path);
200
+ err = -3;
201
+ goto out;
202
+ }
203
+
204
+ out:
205
+ git_buf_free(&buf);
206
+
207
+ return err;
208
+ }
209
+
210
+ int git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *worktree)
211
+ {
212
+ git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
213
+ git_reference *ref = NULL, *head = NULL;
214
+ git_commit *commit = NULL;
215
+ git_repository *wt = NULL;
216
+ git_checkout_options coopts = GIT_CHECKOUT_OPTIONS_INIT;
217
+ int err;
218
+
219
+ assert(out && repo && name && worktree);
220
+
221
+ *out = NULL;
222
+
223
+ /* Create worktree related files in commondir */
224
+ if ((err = git_buf_joinpath(&path, repo->commondir, "worktrees")) < 0)
225
+ goto out;
226
+ if (!git_path_exists(path.ptr))
227
+ if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
228
+ goto out;
229
+ if ((err = git_buf_joinpath(&path, path.ptr, name)) < 0)
230
+ goto out;
231
+ if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
232
+ goto out;
233
+
234
+ /* Create worktree work dir */
235
+ if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0)
236
+ goto out;
237
+
238
+ /* Create worktree .git file */
239
+ if ((err = git_buf_printf(&buf, "gitdir: %s\n", path.ptr)) < 0)
240
+ goto out;
241
+ if ((err = write_wtfile(worktree, ".git", &buf)) < 0)
242
+ goto out;
243
+
244
+ /* Create commondir files */
245
+ if ((err = git_buf_sets(&buf, repo->commondir)) < 0
246
+ || (err = git_buf_putc(&buf, '\n')) < 0
247
+ || (err = write_wtfile(path.ptr, "commondir", &buf)) < 0)
248
+ goto out;
249
+ if ((err = git_buf_joinpath(&buf, worktree, ".git")) < 0
250
+ || (err = git_buf_putc(&buf, '\n')) < 0
251
+ || (err = write_wtfile(path.ptr, "gitdir", &buf)) < 0)
252
+ goto out;
253
+
254
+ /* Create new branch */
255
+ if ((err = git_repository_head(&head, repo)) < 0)
256
+ goto out;
257
+ if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0)
258
+ goto out;
259
+ if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0)
260
+ goto out;
261
+
262
+ /* Set worktree's HEAD */
263
+ if ((err = git_repository_create_head(path.ptr, name)) < 0)
264
+ goto out;
265
+ if ((err = git_repository_open(&wt, worktree)) < 0)
266
+ goto out;
267
+
268
+ /* Checkout worktree's HEAD */
269
+ coopts.checkout_strategy = GIT_CHECKOUT_FORCE;
270
+ if ((err = git_checkout_head(wt, &coopts)) < 0)
271
+ goto out;
272
+
273
+ /* Load result */
274
+ if ((err = git_worktree_lookup(out, repo, name)) < 0)
275
+ goto out;
276
+
277
+ out:
278
+ git_buf_free(&path);
279
+ git_buf_free(&buf);
280
+ git_reference_free(ref);
281
+ git_reference_free(head);
282
+ git_commit_free(commit);
283
+ git_repository_free(wt);
284
+
285
+ return err;
286
+ }
287
+
288
+ int git_worktree_lock(git_worktree *wt, char *creason)
289
+ {
290
+ git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
291
+ int err;
292
+
293
+ assert(wt);
294
+
295
+ if ((err = git_worktree_is_locked(NULL, wt)) < 0)
296
+ goto out;
297
+
298
+ if ((err = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
299
+ goto out;
300
+
301
+ if (creason)
302
+ git_buf_attach_notowned(&buf, creason, strlen(creason));
303
+
304
+ if ((err = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0)
305
+ goto out;
306
+
307
+ wt->locked = 1;
308
+
309
+ out:
310
+ git_buf_free(&path);
311
+
312
+ return err;
313
+ }
314
+
315
+ int git_worktree_unlock(git_worktree *wt)
316
+ {
317
+ git_buf path = GIT_BUF_INIT;
318
+
319
+ assert(wt);
320
+
321
+ if (!git_worktree_is_locked(NULL, wt))
322
+ return 0;
323
+
324
+ if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0)
325
+ return -1;
326
+
327
+ if (p_unlink(path.ptr) != 0) {
328
+ git_buf_free(&path);
329
+ return -1;
330
+ }
331
+
332
+ wt->locked = 0;
333
+
334
+ git_buf_free(&path);
335
+
336
+ return 0;
337
+ }
338
+
339
+ int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
340
+ {
341
+ git_buf path = GIT_BUF_INIT;
342
+ int ret;
343
+
344
+ assert(wt);
345
+
346
+ if (reason)
347
+ git_buf_clear(reason);
348
+
349
+ if ((ret = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0)
350
+ goto out;
351
+ if ((ret = git_path_exists(path.ptr)) && reason)
352
+ git_futils_readbuffer(reason, path.ptr);
353
+
354
+ out:
355
+ git_buf_free(&path);
356
+
357
+ return ret;
358
+ }
359
+
360
+ int git_worktree_is_prunable(git_worktree *wt, unsigned flags)
361
+ {
362
+ git_buf reason = GIT_BUF_INIT;
363
+
364
+ if ((flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
365
+ git_worktree_is_locked(&reason, wt))
366
+ {
367
+ if (!reason.size)
368
+ git_buf_attach_notowned(&reason, "no reason given", 15);
369
+ giterr_set(GITERR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr);
370
+ git_buf_free(&reason);
371
+
372
+ return 0;
373
+ }
374
+
375
+ if ((flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
376
+ git_worktree_validate(wt) == 0)
377
+ {
378
+ giterr_set(GITERR_WORKTREE, "Not pruning valid working tree");
379
+ return 0;
380
+ }
381
+
382
+ return 1;
383
+ }
384
+
385
+ int git_worktree_prune(git_worktree *wt, unsigned flags)
386
+ {
387
+ git_buf path = GIT_BUF_INIT;
388
+ char *wtpath;
389
+ int err;
390
+
391
+ if (!git_worktree_is_prunable(wt, flags)) {
392
+ err = -1;
393
+ goto out;
394
+ }
395
+
396
+ /* Delete gitdir in parent repository */
397
+ if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->parent_path, wt->name)) < 0)
398
+ goto out;
399
+ if (!git_path_exists(path.ptr))
400
+ {
401
+ giterr_set(GITERR_WORKTREE, "Worktree gitdir '%s' does not exist", path.ptr);
402
+ err = -1;
403
+ goto out;
404
+ }
405
+ if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
406
+ goto out;
407
+
408
+ /* Skip deletion of the actual working tree if it does
409
+ * not exist or deletion was not requested */
410
+ if ((flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
411
+ !git_path_exists(wt->gitlink_path))
412
+ {
413
+ goto out;
414
+ }
415
+
416
+ if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL)
417
+ goto out;
418
+ git_buf_attach(&path, wtpath, 0);
419
+ if (!git_path_exists(path.ptr))
420
+ {
421
+ giterr_set(GITERR_WORKTREE, "Working tree '%s' does not exist", path.ptr);
422
+ err = -1;
423
+ goto out;
424
+ }
425
+ if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
426
+ goto out;
427
+
428
+ out:
429
+ git_buf_free(&path);
430
+
431
+ return err;
432
+ }