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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/ext/rugged/extconf.rb +10 -7
- data/ext/rugged/rugged.c +4 -6
- data/ext/rugged/rugged_repo.c +1 -1
- data/ext/rugged/rugged_revwalk.c +4 -4
- data/ext/rugged/rugged_tree.c +2 -2
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +13 -6
- data/vendor/libgit2/COPYING +33 -0
- data/vendor/libgit2/include/git2/branch.h +12 -0
- data/vendor/libgit2/include/git2/commit.h +6 -3
- data/vendor/libgit2/include/git2/common.h +11 -0
- data/vendor/libgit2/include/git2/errors.h +2 -0
- data/vendor/libgit2/include/git2/index.h +7 -6
- data/vendor/libgit2/include/git2/repository.h +91 -0
- data/vendor/libgit2/include/git2/stash.h +2 -2
- data/vendor/libgit2/include/git2/types.h +3 -0
- data/vendor/libgit2/include/git2/worktree.h +161 -0
- data/vendor/libgit2/src/attr.c +24 -16
- data/vendor/libgit2/src/attr_file.h +1 -1
- data/vendor/libgit2/src/attrcache.c +11 -10
- data/vendor/libgit2/src/attrcache.h +1 -4
- data/vendor/libgit2/src/blob.c +2 -2
- data/vendor/libgit2/src/branch.c +63 -0
- data/vendor/libgit2/src/buffer.h +2 -1
- data/vendor/libgit2/src/cache.c +21 -25
- data/vendor/libgit2/src/cache.h +1 -1
- data/vendor/libgit2/src/checkout.c +0 -2
- data/vendor/libgit2/src/cherrypick.c +2 -2
- data/vendor/libgit2/src/clone.c +2 -3
- data/vendor/libgit2/src/commit.c +8 -4
- data/vendor/libgit2/src/config_file.c +1 -3
- data/vendor/libgit2/src/describe.c +1 -3
- data/vendor/libgit2/src/diff_driver.c +2 -4
- data/vendor/libgit2/src/fetchhead.c +2 -2
- data/vendor/libgit2/src/fileops.c +1 -3
- data/vendor/libgit2/src/hash.h +5 -3
- data/vendor/libgit2/src/hash/hash_collisiondetect.h +57 -0
- data/vendor/libgit2/src/hash/sha1dc/sha1.c +1149 -0
- data/vendor/libgit2/src/hash/sha1dc/sha1.h +94 -0
- data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +361 -0
- data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +35 -0
- data/vendor/libgit2/src/idxmap.c +133 -0
- data/vendor/libgit2/src/idxmap.h +22 -60
- data/vendor/libgit2/src/ignore.c +7 -1
- data/vendor/libgit2/src/ignore.h +1 -1
- data/vendor/libgit2/src/index.c +11 -14
- data/vendor/libgit2/src/indexer.c +8 -11
- data/vendor/libgit2/src/merge.c +5 -5
- data/vendor/libgit2/src/mwindow.c +1 -3
- data/vendor/libgit2/src/odb.c +3 -3
- data/vendor/libgit2/src/odb.h +3 -0
- data/vendor/libgit2/src/odb_mempack.c +11 -18
- data/vendor/libgit2/src/offmap.c +83 -0
- data/vendor/libgit2/src/offmap.h +14 -34
- data/vendor/libgit2/src/oidmap.c +105 -0
- data/vendor/libgit2/src/oidmap.h +19 -22
- data/vendor/libgit2/src/pack-objects.c +10 -13
- data/vendor/libgit2/src/pack.c +17 -26
- data/vendor/libgit2/src/path.c +45 -24
- data/vendor/libgit2/src/rebase.c +3 -3
- data/vendor/libgit2/src/refdb_fs.c +81 -46
- data/vendor/libgit2/src/refs.c +13 -3
- data/vendor/libgit2/src/remote.c +6 -2
- data/vendor/libgit2/src/repository.c +318 -46
- data/vendor/libgit2/src/repository.h +5 -2
- data/vendor/libgit2/src/revert.c +2 -2
- data/vendor/libgit2/src/revwalk.c +6 -8
- data/vendor/libgit2/src/settings.c +5 -0
- data/vendor/libgit2/src/sortedcache.c +3 -5
- data/vendor/libgit2/src/strmap.c +95 -0
- data/vendor/libgit2/src/strmap.h +17 -37
- data/vendor/libgit2/src/submodule.c +12 -8
- data/vendor/libgit2/src/thread-utils.h +6 -0
- data/vendor/libgit2/src/transaction.c +5 -17
- data/vendor/libgit2/src/transports/local.c +2 -1
- data/vendor/libgit2/src/transports/smart.h +2 -0
- data/vendor/libgit2/src/transports/smart_protocol.c +3 -1
- data/vendor/libgit2/src/tree.c +2 -4
- data/vendor/libgit2/src/unix/posix.h +1 -1
- data/vendor/libgit2/src/worktree.c +432 -0
- data/vendor/libgit2/src/worktree.h +35 -0
- metadata +13 -2
@@ -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;
|
data/vendor/libgit2/src/tree.c
CHANGED
@@ -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,
|
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
|
+
}
|