rugged 0.25.0b2 → 0.25.0b3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/ext/rugged/extconf.rb +3 -1
- data/ext/rugged/rugged.c +1 -1
- data/ext/rugged/rugged.h +1 -1
- data/ext/rugged/rugged_blob.c +29 -38
- data/ext/rugged/rugged_commit.c +215 -78
- data/ext/rugged/rugged_rebase.c +18 -11
- data/ext/rugged/rugged_remote.c +2 -2
- data/ext/rugged/rugged_tree.c +132 -0
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +11 -3
- data/vendor/libgit2/include/git2.h +1 -0
- data/vendor/libgit2/include/git2/blob.h +39 -28
- data/vendor/libgit2/include/git2/commit.h +30 -0
- data/vendor/libgit2/include/git2/common.h +16 -1
- data/vendor/libgit2/include/git2/merge.h +10 -1
- data/vendor/libgit2/include/git2/proxy.h +92 -0
- data/vendor/libgit2/include/git2/refs.h +11 -0
- data/vendor/libgit2/include/git2/remote.h +17 -4
- data/vendor/libgit2/include/git2/signature.h +13 -0
- data/vendor/libgit2/include/git2/sys/merge.h +177 -0
- data/vendor/libgit2/include/git2/sys/remote.h +16 -0
- data/vendor/libgit2/include/git2/sys/stream.h +2 -1
- data/vendor/libgit2/include/git2/sys/transport.h +3 -1
- data/vendor/libgit2/include/git2/tag.h +9 -0
- data/vendor/libgit2/include/git2/tree.h +55 -0
- data/vendor/libgit2/src/annotated_commit.c +99 -80
- data/vendor/libgit2/src/annotated_commit.h +5 -2
- data/vendor/libgit2/src/array.h +40 -0
- data/vendor/libgit2/src/blame.c +8 -3
- data/vendor/libgit2/src/blame_git.c +2 -1
- data/vendor/libgit2/src/blob.c +71 -39
- data/vendor/libgit2/src/branch.c +2 -1
- data/vendor/libgit2/src/checkout.c +66 -42
- data/vendor/libgit2/src/commit.c +67 -3
- data/vendor/libgit2/src/config_cache.c +2 -1
- data/vendor/libgit2/src/config_file.c +32 -27
- data/vendor/libgit2/src/curl_stream.c +89 -6
- data/vendor/libgit2/src/delta-apply.c +36 -5
- data/vendor/libgit2/src/delta-apply.h +12 -0
- data/vendor/libgit2/src/describe.c +3 -2
- data/vendor/libgit2/src/diff.c +13 -20
- data/vendor/libgit2/src/diff_tform.c +5 -3
- data/vendor/libgit2/src/filebuf.c +12 -2
- data/vendor/libgit2/src/filebuf.h +1 -0
- data/vendor/libgit2/src/fnmatch.c +18 -5
- data/vendor/libgit2/src/global.c +18 -0
- data/vendor/libgit2/src/global.h +1 -0
- data/vendor/libgit2/src/ignore.c +11 -3
- data/vendor/libgit2/src/index.c +11 -5
- data/vendor/libgit2/src/indexer.c +11 -7
- data/vendor/libgit2/src/iterator.c +1575 -1468
- data/vendor/libgit2/src/iterator.h +52 -69
- data/vendor/libgit2/src/merge.c +160 -63
- data/vendor/libgit2/src/merge.h +61 -2
- data/vendor/libgit2/src/merge_driver.c +397 -0
- data/vendor/libgit2/src/merge_driver.h +60 -0
- data/vendor/libgit2/src/merge_file.c +11 -49
- data/vendor/libgit2/src/netops.c +12 -10
- data/vendor/libgit2/src/object.c +3 -6
- data/vendor/libgit2/src/object_api.c +19 -1
- data/vendor/libgit2/src/odb_loose.c +1 -1
- data/vendor/libgit2/src/openssl_stream.c +16 -3
- data/vendor/libgit2/src/pack-objects.c +3 -1
- data/vendor/libgit2/src/pack.c +5 -9
- data/vendor/libgit2/src/path.c +14 -0
- data/vendor/libgit2/src/path.h +12 -0
- data/vendor/libgit2/src/pathspec.c +1 -1
- data/vendor/libgit2/src/posix.c +7 -0
- data/vendor/libgit2/src/posix.h +1 -0
- data/vendor/libgit2/src/proxy.c +32 -0
- data/vendor/libgit2/src/proxy.h +14 -0
- data/vendor/libgit2/src/push.c +7 -7
- data/vendor/libgit2/src/rebase.c +61 -31
- data/vendor/libgit2/src/refdb_fs.c +1 -0
- data/vendor/libgit2/src/refs.c +16 -1
- data/vendor/libgit2/src/remote.c +20 -6
- data/vendor/libgit2/src/repository.c +1 -1
- data/vendor/libgit2/src/reset.c +1 -1
- data/vendor/libgit2/src/settings.c +23 -1
- data/vendor/libgit2/src/signature.c +26 -1
- data/vendor/libgit2/src/stransport_stream.c +5 -2
- data/vendor/libgit2/src/stream.h +2 -2
- data/vendor/libgit2/src/submodule.c +3 -2
- data/vendor/libgit2/src/tag.c +8 -2
- data/vendor/libgit2/src/transports/http.c +32 -9
- data/vendor/libgit2/src/transports/local.c +4 -1
- data/vendor/libgit2/src/transports/smart.c +6 -0
- data/vendor/libgit2/src/transports/smart.h +1 -0
- data/vendor/libgit2/src/transports/smart_protocol.c +61 -17
- data/vendor/libgit2/src/transports/winhttp.c +130 -11
- data/vendor/libgit2/src/tree.c +329 -98
- data/vendor/libgit2/src/tree.h +4 -5
- data/vendor/libgit2/src/unix/map.c +5 -0
- data/vendor/libgit2/src/win32/map.c +24 -5
- data/vendor/libgit2/src/xdiff/xprepare.c +2 -1
- metadata +10 -4
- data/vendor/libgit2/Makefile.embed +0 -60
data/vendor/libgit2/src/merge.h
CHANGED
@@ -12,8 +12,9 @@
|
|
12
12
|
#include "pool.h"
|
13
13
|
#include "iterator.h"
|
14
14
|
|
15
|
-
#include "git2/merge.h"
|
16
15
|
#include "git2/types.h"
|
16
|
+
#include "git2/merge.h"
|
17
|
+
#include "git2/sys/merge.h"
|
17
18
|
|
18
19
|
#define GIT_MERGE_MSG_FILE "MERGE_MSG"
|
19
20
|
#define GIT_MERGE_MODE_FILE "MERGE_MODE"
|
@@ -22,6 +23,19 @@
|
|
22
23
|
#define GIT_MERGE_DEFAULT_RENAME_THRESHOLD 50
|
23
24
|
#define GIT_MERGE_DEFAULT_TARGET_LIMIT 1000
|
24
25
|
|
26
|
+
|
27
|
+
/** Internal merge flags. */
|
28
|
+
enum {
|
29
|
+
/** The merge is for a virtual base in a recursive merge. */
|
30
|
+
GIT_MERGE__VIRTUAL_BASE = (1 << 31),
|
31
|
+
};
|
32
|
+
|
33
|
+
enum {
|
34
|
+
/** Accept the conflict file, staging it as the merge result. */
|
35
|
+
GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
|
36
|
+
};
|
37
|
+
|
38
|
+
|
25
39
|
/** Types of changes when files are merged from branch to branch. */
|
26
40
|
typedef enum {
|
27
41
|
/* No conflict - a change only occurs in one branch. */
|
@@ -70,7 +84,6 @@ typedef enum {
|
|
70
84
|
GIT_MERGE_DIFF_DF_CHILD = (1 << 11),
|
71
85
|
} git_merge_diff_type_t;
|
72
86
|
|
73
|
-
|
74
87
|
typedef struct {
|
75
88
|
git_repository *repo;
|
76
89
|
git_pool pool;
|
@@ -152,4 +165,50 @@ int git_merge__check_result(git_repository *repo, git_index *index_new);
|
|
152
165
|
|
153
166
|
int git_merge__append_conflicts_to_merge_msg(git_repository *repo, git_index *index);
|
154
167
|
|
168
|
+
/* Merge files */
|
169
|
+
|
170
|
+
GIT_INLINE(const char *) git_merge_file__best_path(
|
171
|
+
const char *ancestor,
|
172
|
+
const char *ours,
|
173
|
+
const char *theirs)
|
174
|
+
{
|
175
|
+
if (!ancestor) {
|
176
|
+
if (ours && theirs && strcmp(ours, theirs) == 0)
|
177
|
+
return ours;
|
178
|
+
|
179
|
+
return NULL;
|
180
|
+
}
|
181
|
+
|
182
|
+
if (ours && strcmp(ancestor, ours) == 0)
|
183
|
+
return theirs;
|
184
|
+
else if(theirs && strcmp(ancestor, theirs) == 0)
|
185
|
+
return ours;
|
186
|
+
|
187
|
+
return NULL;
|
188
|
+
}
|
189
|
+
|
190
|
+
GIT_INLINE(uint32_t) git_merge_file__best_mode(
|
191
|
+
uint32_t ancestor, uint32_t ours, uint32_t theirs)
|
192
|
+
{
|
193
|
+
/*
|
194
|
+
* If ancestor didn't exist and either ours or theirs is executable,
|
195
|
+
* assume executable. Otherwise, if any mode changed from the ancestor,
|
196
|
+
* use that one.
|
197
|
+
*/
|
198
|
+
if (!ancestor) {
|
199
|
+
if (ours == GIT_FILEMODE_BLOB_EXECUTABLE ||
|
200
|
+
theirs == GIT_FILEMODE_BLOB_EXECUTABLE)
|
201
|
+
return GIT_FILEMODE_BLOB_EXECUTABLE;
|
202
|
+
|
203
|
+
return GIT_FILEMODE_BLOB;
|
204
|
+
} else if (ours && theirs) {
|
205
|
+
if (ancestor == ours)
|
206
|
+
return theirs;
|
207
|
+
|
208
|
+
return ours;
|
209
|
+
}
|
210
|
+
|
211
|
+
return 0;
|
212
|
+
}
|
213
|
+
|
155
214
|
#endif
|
@@ -0,0 +1,397 @@
|
|
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
|
+
#include "vector.h"
|
10
|
+
#include "global.h"
|
11
|
+
#include "merge.h"
|
12
|
+
#include "merge_driver.h"
|
13
|
+
#include "git2/merge.h"
|
14
|
+
#include "git2/sys/merge.h"
|
15
|
+
|
16
|
+
static const char *merge_driver_name__text = "text";
|
17
|
+
static const char *merge_driver_name__union = "union";
|
18
|
+
static const char *merge_driver_name__binary = "binary";
|
19
|
+
|
20
|
+
struct merge_driver_registry {
|
21
|
+
git_rwlock lock;
|
22
|
+
git_vector drivers;
|
23
|
+
};
|
24
|
+
|
25
|
+
typedef struct {
|
26
|
+
git_merge_driver *driver;
|
27
|
+
int initialized;
|
28
|
+
char name[GIT_FLEX_ARRAY];
|
29
|
+
} git_merge_driver_entry;
|
30
|
+
|
31
|
+
static struct merge_driver_registry merge_driver_registry;
|
32
|
+
|
33
|
+
static void git_merge_driver_global_shutdown(void);
|
34
|
+
|
35
|
+
|
36
|
+
int git_merge_driver__builtin_apply(
|
37
|
+
git_merge_driver *self,
|
38
|
+
const char **path_out,
|
39
|
+
uint32_t *mode_out,
|
40
|
+
git_buf *merged_out,
|
41
|
+
const char *filter_name,
|
42
|
+
const git_merge_driver_source *src)
|
43
|
+
{
|
44
|
+
git_merge_driver__builtin *driver = (git_merge_driver__builtin *)self;
|
45
|
+
git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
|
46
|
+
git_merge_file_result result = {0};
|
47
|
+
int error;
|
48
|
+
|
49
|
+
GIT_UNUSED(filter_name);
|
50
|
+
|
51
|
+
if (src->file_opts)
|
52
|
+
memcpy(&file_opts, src->file_opts, sizeof(git_merge_file_options));
|
53
|
+
|
54
|
+
if (driver->favor)
|
55
|
+
file_opts.favor = driver->favor;
|
56
|
+
|
57
|
+
if ((error = git_merge_file_from_index(&result, src->repo,
|
58
|
+
src->ancestor, src->ours, src->theirs, &file_opts)) < 0)
|
59
|
+
goto done;
|
60
|
+
|
61
|
+
if (!result.automergeable &&
|
62
|
+
!(file_opts.flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) {
|
63
|
+
error = GIT_EMERGECONFLICT;
|
64
|
+
goto done;
|
65
|
+
}
|
66
|
+
|
67
|
+
*path_out = git_merge_file__best_path(
|
68
|
+
src->ancestor ? src->ancestor->path : NULL,
|
69
|
+
src->ours ? src->ours->path : NULL,
|
70
|
+
src->theirs ? src->theirs->path : NULL);
|
71
|
+
|
72
|
+
*mode_out = git_merge_file__best_mode(
|
73
|
+
src->ancestor ? src->ancestor->mode : 0,
|
74
|
+
src->ours ? src->ours->mode : 0,
|
75
|
+
src->theirs ? src->theirs->mode : 0);
|
76
|
+
|
77
|
+
merged_out->ptr = (char *)result.ptr;
|
78
|
+
merged_out->size = result.len;
|
79
|
+
merged_out->asize = result.len;
|
80
|
+
result.ptr = NULL;
|
81
|
+
|
82
|
+
done:
|
83
|
+
git_merge_file_result_free(&result);
|
84
|
+
return error;
|
85
|
+
}
|
86
|
+
|
87
|
+
static int merge_driver_binary_apply(
|
88
|
+
git_merge_driver *self,
|
89
|
+
const char **path_out,
|
90
|
+
uint32_t *mode_out,
|
91
|
+
git_buf *merged_out,
|
92
|
+
const char *filter_name,
|
93
|
+
const git_merge_driver_source *src)
|
94
|
+
{
|
95
|
+
GIT_UNUSED(self);
|
96
|
+
GIT_UNUSED(path_out);
|
97
|
+
GIT_UNUSED(mode_out);
|
98
|
+
GIT_UNUSED(merged_out);
|
99
|
+
GIT_UNUSED(filter_name);
|
100
|
+
GIT_UNUSED(src);
|
101
|
+
|
102
|
+
return GIT_EMERGECONFLICT;
|
103
|
+
}
|
104
|
+
|
105
|
+
static int merge_driver_entry_cmp(const void *a, const void *b)
|
106
|
+
{
|
107
|
+
const git_merge_driver_entry *entry_a = a;
|
108
|
+
const git_merge_driver_entry *entry_b = b;
|
109
|
+
|
110
|
+
return strcmp(entry_a->name, entry_b->name);
|
111
|
+
}
|
112
|
+
|
113
|
+
static int merge_driver_entry_search(const void *a, const void *b)
|
114
|
+
{
|
115
|
+
const char *name_a = a;
|
116
|
+
const git_merge_driver_entry *entry_b = b;
|
117
|
+
|
118
|
+
return strcmp(name_a, entry_b->name);
|
119
|
+
}
|
120
|
+
|
121
|
+
git_merge_driver__builtin git_merge_driver__text = {
|
122
|
+
{
|
123
|
+
GIT_MERGE_DRIVER_VERSION,
|
124
|
+
NULL,
|
125
|
+
NULL,
|
126
|
+
git_merge_driver__builtin_apply,
|
127
|
+
},
|
128
|
+
GIT_MERGE_FILE_FAVOR_NORMAL
|
129
|
+
};
|
130
|
+
|
131
|
+
git_merge_driver__builtin git_merge_driver__union = {
|
132
|
+
{
|
133
|
+
GIT_MERGE_DRIVER_VERSION,
|
134
|
+
NULL,
|
135
|
+
NULL,
|
136
|
+
git_merge_driver__builtin_apply,
|
137
|
+
},
|
138
|
+
GIT_MERGE_FILE_FAVOR_UNION
|
139
|
+
};
|
140
|
+
|
141
|
+
git_merge_driver git_merge_driver__binary = {
|
142
|
+
GIT_MERGE_DRIVER_VERSION,
|
143
|
+
NULL,
|
144
|
+
NULL,
|
145
|
+
merge_driver_binary_apply
|
146
|
+
};
|
147
|
+
|
148
|
+
/* Note: callers must lock the registry before calling this function */
|
149
|
+
static int merge_driver_registry_insert(
|
150
|
+
const char *name, git_merge_driver *driver)
|
151
|
+
{
|
152
|
+
git_merge_driver_entry *entry;
|
153
|
+
|
154
|
+
entry = git__calloc(1, sizeof(git_merge_driver_entry) + strlen(name) + 1);
|
155
|
+
GITERR_CHECK_ALLOC(entry);
|
156
|
+
|
157
|
+
strcpy(entry->name, name);
|
158
|
+
entry->driver = driver;
|
159
|
+
|
160
|
+
return git_vector_insert_sorted(
|
161
|
+
&merge_driver_registry.drivers, entry, NULL);
|
162
|
+
}
|
163
|
+
|
164
|
+
int git_merge_driver_global_init(void)
|
165
|
+
{
|
166
|
+
int error;
|
167
|
+
|
168
|
+
if (git_rwlock_init(&merge_driver_registry.lock) < 0)
|
169
|
+
return -1;
|
170
|
+
|
171
|
+
if ((error = git_vector_init(&merge_driver_registry.drivers, 3,
|
172
|
+
merge_driver_entry_cmp)) < 0)
|
173
|
+
goto done;
|
174
|
+
|
175
|
+
if ((error = merge_driver_registry_insert(
|
176
|
+
merge_driver_name__text, &git_merge_driver__text.base)) < 0 ||
|
177
|
+
(error = merge_driver_registry_insert(
|
178
|
+
merge_driver_name__union, &git_merge_driver__union.base)) < 0 ||
|
179
|
+
(error = merge_driver_registry_insert(
|
180
|
+
merge_driver_name__binary, &git_merge_driver__binary)) < 0)
|
181
|
+
goto done;
|
182
|
+
|
183
|
+
git__on_shutdown(git_merge_driver_global_shutdown);
|
184
|
+
|
185
|
+
done:
|
186
|
+
if (error < 0)
|
187
|
+
git_vector_free_deep(&merge_driver_registry.drivers);
|
188
|
+
|
189
|
+
return error;
|
190
|
+
}
|
191
|
+
|
192
|
+
static void git_merge_driver_global_shutdown(void)
|
193
|
+
{
|
194
|
+
git_merge_driver_entry *entry;
|
195
|
+
size_t i;
|
196
|
+
|
197
|
+
if (git_rwlock_wrlock(&merge_driver_registry.lock) < 0)
|
198
|
+
return;
|
199
|
+
|
200
|
+
git_vector_foreach(&merge_driver_registry.drivers, i, entry) {
|
201
|
+
if (entry->driver->shutdown)
|
202
|
+
entry->driver->shutdown(entry->driver);
|
203
|
+
|
204
|
+
git__free(entry);
|
205
|
+
}
|
206
|
+
|
207
|
+
git_vector_free(&merge_driver_registry.drivers);
|
208
|
+
|
209
|
+
git_rwlock_wrunlock(&merge_driver_registry.lock);
|
210
|
+
git_rwlock_free(&merge_driver_registry.lock);
|
211
|
+
}
|
212
|
+
|
213
|
+
/* Note: callers must lock the registry before calling this function */
|
214
|
+
static int merge_driver_registry_find(size_t *pos, const char *name)
|
215
|
+
{
|
216
|
+
return git_vector_search2(pos, &merge_driver_registry.drivers,
|
217
|
+
merge_driver_entry_search, name);
|
218
|
+
}
|
219
|
+
|
220
|
+
/* Note: callers must lock the registry before calling this function */
|
221
|
+
static git_merge_driver_entry *merge_driver_registry_lookup(
|
222
|
+
size_t *pos, const char *name)
|
223
|
+
{
|
224
|
+
git_merge_driver_entry *entry = NULL;
|
225
|
+
|
226
|
+
if (!merge_driver_registry_find(pos, name))
|
227
|
+
entry = git_vector_get(&merge_driver_registry.drivers, *pos);
|
228
|
+
|
229
|
+
return entry;
|
230
|
+
}
|
231
|
+
|
232
|
+
int git_merge_driver_register(const char *name, git_merge_driver *driver)
|
233
|
+
{
|
234
|
+
int error;
|
235
|
+
|
236
|
+
assert(name && driver);
|
237
|
+
|
238
|
+
if (git_rwlock_wrlock(&merge_driver_registry.lock) < 0) {
|
239
|
+
giterr_set(GITERR_OS, "failed to lock merge driver registry");
|
240
|
+
return -1;
|
241
|
+
}
|
242
|
+
|
243
|
+
if (!merge_driver_registry_find(NULL, name)) {
|
244
|
+
giterr_set(GITERR_MERGE, "attempt to reregister existing driver '%s'",
|
245
|
+
name);
|
246
|
+
error = GIT_EEXISTS;
|
247
|
+
goto done;
|
248
|
+
}
|
249
|
+
|
250
|
+
error = merge_driver_registry_insert(name, driver);
|
251
|
+
|
252
|
+
done:
|
253
|
+
git_rwlock_wrunlock(&merge_driver_registry.lock);
|
254
|
+
return error;
|
255
|
+
}
|
256
|
+
|
257
|
+
int git_merge_driver_unregister(const char *name)
|
258
|
+
{
|
259
|
+
git_merge_driver_entry *entry;
|
260
|
+
size_t pos;
|
261
|
+
int error = 0;
|
262
|
+
|
263
|
+
if (git_rwlock_wrlock(&merge_driver_registry.lock) < 0) {
|
264
|
+
giterr_set(GITERR_OS, "failed to lock merge driver registry");
|
265
|
+
return -1;
|
266
|
+
}
|
267
|
+
|
268
|
+
if ((entry = merge_driver_registry_lookup(&pos, name)) == NULL) {
|
269
|
+
giterr_set(GITERR_MERGE, "cannot find merge driver '%s' to unregister",
|
270
|
+
name);
|
271
|
+
error = GIT_ENOTFOUND;
|
272
|
+
goto done;
|
273
|
+
}
|
274
|
+
|
275
|
+
git_vector_remove(&merge_driver_registry.drivers, pos);
|
276
|
+
|
277
|
+
if (entry->initialized && entry->driver->shutdown) {
|
278
|
+
entry->driver->shutdown(entry->driver);
|
279
|
+
entry->initialized = false;
|
280
|
+
}
|
281
|
+
|
282
|
+
git__free(entry);
|
283
|
+
|
284
|
+
done:
|
285
|
+
git_rwlock_wrunlock(&merge_driver_registry.lock);
|
286
|
+
return error;
|
287
|
+
}
|
288
|
+
|
289
|
+
git_merge_driver *git_merge_driver_lookup(const char *name)
|
290
|
+
{
|
291
|
+
git_merge_driver_entry *entry;
|
292
|
+
size_t pos;
|
293
|
+
int error;
|
294
|
+
|
295
|
+
/* If we've decided the merge driver to use internally - and not
|
296
|
+
* based on user configuration (in merge_driver_name_for_path)
|
297
|
+
* then we can use a hardcoded name to compare instead of bothering
|
298
|
+
* to take a lock and look it up in the vector.
|
299
|
+
*/
|
300
|
+
if (name == merge_driver_name__text)
|
301
|
+
return &git_merge_driver__text.base;
|
302
|
+
else if (name == merge_driver_name__binary)
|
303
|
+
return &git_merge_driver__binary;
|
304
|
+
|
305
|
+
if (git_rwlock_rdlock(&merge_driver_registry.lock) < 0) {
|
306
|
+
giterr_set(GITERR_OS, "failed to lock merge driver registry");
|
307
|
+
return NULL;
|
308
|
+
}
|
309
|
+
|
310
|
+
entry = merge_driver_registry_lookup(&pos, name);
|
311
|
+
|
312
|
+
git_rwlock_rdunlock(&merge_driver_registry.lock);
|
313
|
+
|
314
|
+
if (entry == NULL) {
|
315
|
+
giterr_set(GITERR_MERGE, "cannot use an unregistered filter");
|
316
|
+
return NULL;
|
317
|
+
}
|
318
|
+
|
319
|
+
if (!entry->initialized) {
|
320
|
+
if (entry->driver->initialize &&
|
321
|
+
(error = entry->driver->initialize(entry->driver)) < 0)
|
322
|
+
return NULL;
|
323
|
+
|
324
|
+
entry->initialized = 1;
|
325
|
+
}
|
326
|
+
|
327
|
+
return entry->driver;
|
328
|
+
}
|
329
|
+
|
330
|
+
static int merge_driver_name_for_path(
|
331
|
+
const char **out,
|
332
|
+
git_repository *repo,
|
333
|
+
const char *path,
|
334
|
+
const char *default_driver)
|
335
|
+
{
|
336
|
+
const char *value;
|
337
|
+
int error;
|
338
|
+
|
339
|
+
*out = NULL;
|
340
|
+
|
341
|
+
if ((error = git_attr_get(&value, repo, 0, path, "merge")) < 0)
|
342
|
+
return error;
|
343
|
+
|
344
|
+
/* set: use the built-in 3-way merge driver ("text") */
|
345
|
+
if (GIT_ATTR_TRUE(value))
|
346
|
+
*out = merge_driver_name__text;
|
347
|
+
|
348
|
+
/* unset: do not merge ("binary") */
|
349
|
+
else if (GIT_ATTR_FALSE(value))
|
350
|
+
*out = merge_driver_name__binary;
|
351
|
+
|
352
|
+
else if (GIT_ATTR_UNSPECIFIED(value) && default_driver)
|
353
|
+
*out = default_driver;
|
354
|
+
|
355
|
+
else if (GIT_ATTR_UNSPECIFIED(value))
|
356
|
+
*out = merge_driver_name__text;
|
357
|
+
|
358
|
+
else
|
359
|
+
*out = value;
|
360
|
+
|
361
|
+
return 0;
|
362
|
+
}
|
363
|
+
|
364
|
+
|
365
|
+
GIT_INLINE(git_merge_driver *) merge_driver_lookup_with_wildcard(
|
366
|
+
const char *name)
|
367
|
+
{
|
368
|
+
git_merge_driver *driver = git_merge_driver_lookup(name);
|
369
|
+
|
370
|
+
if (driver == NULL)
|
371
|
+
driver = git_merge_driver_lookup("*");
|
372
|
+
|
373
|
+
return driver;
|
374
|
+
}
|
375
|
+
|
376
|
+
int git_merge_driver_for_source(
|
377
|
+
const char **name_out,
|
378
|
+
git_merge_driver **driver_out,
|
379
|
+
const git_merge_driver_source *src)
|
380
|
+
{
|
381
|
+
const char *path, *driver_name;
|
382
|
+
int error = 0;
|
383
|
+
|
384
|
+
path = git_merge_file__best_path(
|
385
|
+
src->ancestor ? src->ancestor->path : NULL,
|
386
|
+
src->ours ? src->ours->path : NULL,
|
387
|
+
src->theirs ? src->theirs->path : NULL);
|
388
|
+
|
389
|
+
if ((error = merge_driver_name_for_path(
|
390
|
+
&driver_name, src->repo, path, src->default_driver)) < 0)
|
391
|
+
return error;
|
392
|
+
|
393
|
+
*name_out = driver_name;
|
394
|
+
*driver_out = merge_driver_lookup_with_wildcard(driver_name);
|
395
|
+
return error;
|
396
|
+
}
|
397
|
+
|