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
@@ -34,10 +34,19 @@ typedef enum {
|
|
34
34
|
GIT_ITERATOR_DONT_AUTOEXPAND = (1u << 3),
|
35
35
|
/** convert precomposed unicode to decomposed unicode */
|
36
36
|
GIT_ITERATOR_PRECOMPOSE_UNICODE = (1u << 4),
|
37
|
+
/** never convert precomposed unicode to decomposed unicode */
|
38
|
+
GIT_ITERATOR_DONT_PRECOMPOSE_UNICODE = (1u << 5),
|
37
39
|
/** include conflicts */
|
38
|
-
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u <<
|
40
|
+
GIT_ITERATOR_INCLUDE_CONFLICTS = (1u << 6),
|
39
41
|
} git_iterator_flag_t;
|
40
42
|
|
43
|
+
typedef enum {
|
44
|
+
GIT_ITERATOR_STATUS_NORMAL = 0,
|
45
|
+
GIT_ITERATOR_STATUS_IGNORED = 1,
|
46
|
+
GIT_ITERATOR_STATUS_EMPTY = 2,
|
47
|
+
GIT_ITERATOR_STATUS_FILTERED = 3
|
48
|
+
} git_iterator_status_t;
|
49
|
+
|
41
50
|
typedef struct {
|
42
51
|
const char *start;
|
43
52
|
const char *end;
|
@@ -57,23 +66,33 @@ typedef struct {
|
|
57
66
|
int (*current)(const git_index_entry **, git_iterator *);
|
58
67
|
int (*advance)(const git_index_entry **, git_iterator *);
|
59
68
|
int (*advance_into)(const git_index_entry **, git_iterator *);
|
60
|
-
int (*
|
61
|
-
|
62
|
-
int (*
|
69
|
+
int (*advance_over)(
|
70
|
+
const git_index_entry **, git_iterator_status_t *, git_iterator *);
|
71
|
+
int (*reset)(git_iterator *);
|
63
72
|
void (*free)(git_iterator *);
|
64
73
|
} git_iterator_callbacks;
|
65
74
|
|
66
75
|
struct git_iterator {
|
67
76
|
git_iterator_type_t type;
|
68
77
|
git_iterator_callbacks *cb;
|
78
|
+
|
69
79
|
git_repository *repo;
|
80
|
+
git_index *index;
|
81
|
+
|
70
82
|
char *start;
|
83
|
+
size_t start_len;
|
84
|
+
|
71
85
|
char *end;
|
86
|
+
size_t end_len;
|
87
|
+
|
88
|
+
bool started;
|
89
|
+
bool ended;
|
72
90
|
git_vector pathlist;
|
73
91
|
size_t pathlist_walk_idx;
|
74
92
|
int (*strcomp)(const char *a, const char *b);
|
75
93
|
int (*strncomp)(const char *a, const char *b, size_t n);
|
76
94
|
int (*prefixcomp)(const char *str, const char *prefix);
|
95
|
+
int (*entry_srch)(const void *key, const void *array_member);
|
77
96
|
size_t stat_calls;
|
78
97
|
unsigned int flags;
|
79
98
|
};
|
@@ -181,54 +200,38 @@ GIT_INLINE(int) git_iterator_advance_into(
|
|
181
200
|
return iter->cb->advance_into(entry, iter);
|
182
201
|
}
|
183
202
|
|
184
|
-
|
185
|
-
*
|
203
|
+
/* Advance over a directory and check if it contains no files or just
|
204
|
+
* ignored files.
|
186
205
|
*
|
187
|
-
*
|
188
|
-
* directory is
|
189
|
-
*
|
190
|
-
*
|
206
|
+
* In a tree or the index, all directories will contain files, but in the
|
207
|
+
* working directory it is possible to have an empty directory tree or a
|
208
|
+
* tree that only contains ignored files. Many Git operations treat these
|
209
|
+
* cases specially. This advances over a directory (presumably an
|
210
|
+
* untracked directory) but checks during the scan if there are any files
|
211
|
+
* and any non-ignored files.
|
191
212
|
*/
|
192
|
-
GIT_INLINE(int)
|
193
|
-
const git_index_entry **entry,
|
194
|
-
|
195
|
-
|
196
|
-
if (error == GIT_ENOTFOUND) {
|
197
|
-
giterr_clear();
|
198
|
-
error = iter->cb->advance(entry, iter);
|
199
|
-
}
|
200
|
-
return error;
|
201
|
-
}
|
202
|
-
|
203
|
-
/* Seek is currently unimplemented */
|
204
|
-
GIT_INLINE(int) git_iterator_seek(
|
205
|
-
git_iterator *iter, const char *prefix)
|
213
|
+
GIT_INLINE(int) git_iterator_advance_over(
|
214
|
+
const git_index_entry **entry,
|
215
|
+
git_iterator_status_t *status,
|
216
|
+
git_iterator *iter)
|
206
217
|
{
|
207
|
-
return iter->cb->
|
218
|
+
return iter->cb->advance_over(entry, status, iter);
|
208
219
|
}
|
209
220
|
|
210
221
|
/**
|
211
222
|
* Go back to the start of the iteration.
|
212
|
-
*
|
213
|
-
* This resets the iterator to the start of the iteration. It also allows
|
214
|
-
* you to reset the `start` and `end` pathname boundaries of the iteration
|
215
|
-
* when doing so.
|
216
223
|
*/
|
217
|
-
GIT_INLINE(int) git_iterator_reset(
|
218
|
-
git_iterator *iter, const char *start, const char *end)
|
224
|
+
GIT_INLINE(int) git_iterator_reset(git_iterator *iter)
|
219
225
|
{
|
220
|
-
return iter->cb->reset(iter
|
226
|
+
return iter->cb->reset(iter);
|
221
227
|
}
|
222
228
|
|
223
229
|
/**
|
224
|
-
*
|
225
|
-
*
|
226
|
-
* @return 0 if not at end, >0 if at end
|
230
|
+
* Go back to the start of the iteration after updating the `start` and
|
231
|
+
* `end` pathname boundaries of the iteration.
|
227
232
|
*/
|
228
|
-
|
229
|
-
|
230
|
-
return iter->cb->at_end(iter);
|
231
|
-
}
|
233
|
+
extern int git_iterator_reset_range(
|
234
|
+
git_iterator *iter, const char *start, const char *end);
|
232
235
|
|
233
236
|
GIT_INLINE(git_iterator_type_t) git_iterator_type(git_iterator *iter)
|
234
237
|
{
|
@@ -240,6 +243,11 @@ GIT_INLINE(git_repository *) git_iterator_owner(git_iterator *iter)
|
|
240
243
|
return iter->repo;
|
241
244
|
}
|
242
245
|
|
246
|
+
GIT_INLINE(git_index *) git_iterator_index(git_iterator *iter)
|
247
|
+
{
|
248
|
+
return iter->index;
|
249
|
+
}
|
250
|
+
|
243
251
|
GIT_INLINE(git_iterator_flag_t) git_iterator_flags(git_iterator *iter)
|
244
252
|
{
|
245
253
|
return iter->flags;
|
@@ -250,21 +258,19 @@ GIT_INLINE(bool) git_iterator_ignore_case(git_iterator *iter)
|
|
250
258
|
return ((iter->flags & GIT_ITERATOR_IGNORE_CASE) != 0);
|
251
259
|
}
|
252
260
|
|
253
|
-
extern
|
261
|
+
extern void git_iterator_set_ignore_case(
|
262
|
+
git_iterator *iter, bool ignore_case);
|
254
263
|
|
255
264
|
extern int git_iterator_current_tree_entry(
|
256
265
|
const git_tree_entry **entry_out, git_iterator *iter);
|
257
266
|
|
258
267
|
extern int git_iterator_current_parent_tree(
|
259
|
-
const git_tree **tree_out, git_iterator *iter,
|
268
|
+
const git_tree **tree_out, git_iterator *iter, size_t depth);
|
260
269
|
|
261
270
|
extern bool git_iterator_current_is_ignored(git_iterator *iter);
|
262
271
|
|
263
272
|
extern bool git_iterator_current_tree_is_ignored(git_iterator *iter);
|
264
273
|
|
265
|
-
extern int git_iterator_cmp(
|
266
|
-
git_iterator *iter, const char *path_prefix);
|
267
|
-
|
268
274
|
/**
|
269
275
|
* Get full path of the current item from a workdir iterator. This will
|
270
276
|
* return NULL for a non-workdir iterator. The git_buf is still owned by
|
@@ -273,35 +279,12 @@ extern int git_iterator_cmp(
|
|
273
279
|
extern int git_iterator_current_workdir_path(
|
274
280
|
git_buf **path, git_iterator *iter);
|
275
281
|
|
276
|
-
/* Return index pointer if index iterator, else NULL */
|
277
|
-
extern git_index *git_iterator_get_index(git_iterator *iter);
|
278
|
-
|
279
|
-
typedef enum {
|
280
|
-
GIT_ITERATOR_STATUS_NORMAL = 0,
|
281
|
-
GIT_ITERATOR_STATUS_IGNORED = 1,
|
282
|
-
GIT_ITERATOR_STATUS_EMPTY = 2,
|
283
|
-
GIT_ITERATOR_STATUS_FILTERED = 3
|
284
|
-
} git_iterator_status_t;
|
285
|
-
|
286
|
-
/* Advance over a directory and check if it contains no files or just
|
287
|
-
* ignored files.
|
288
|
-
*
|
289
|
-
* In a tree or the index, all directories will contain files, but in the
|
290
|
-
* working directory it is possible to have an empty directory tree or a
|
291
|
-
* tree that only contains ignored files. Many Git operations treat these
|
292
|
-
* cases specially. This advances over a directory (presumably an
|
293
|
-
* untracked directory) but checks during the scan if there are any files
|
294
|
-
* and any non-ignored files.
|
295
|
-
*/
|
296
|
-
extern int git_iterator_advance_over_with_status(
|
297
|
-
const git_index_entry **entry, git_iterator_status_t *status, git_iterator *iter);
|
298
|
-
|
299
282
|
/**
|
300
283
|
* Retrieve the index stored in the iterator.
|
301
284
|
*
|
302
|
-
* Only implemented for the workdir
|
285
|
+
* Only implemented for the workdir and index iterators.
|
303
286
|
*/
|
304
|
-
extern
|
287
|
+
extern git_index *git_iterator_index(git_iterator *iter);
|
305
288
|
|
306
289
|
typedef int (*git_iterator_walk_cb)(
|
307
290
|
const git_index_entry **entries,
|
data/vendor/libgit2/src/merge.c
CHANGED
@@ -29,6 +29,7 @@
|
|
29
29
|
#include "annotated_commit.h"
|
30
30
|
#include "commit.h"
|
31
31
|
#include "oidarray.h"
|
32
|
+
#include "merge_driver.h"
|
32
33
|
|
33
34
|
#include "git2/types.h"
|
34
35
|
#include "git2/repository.h"
|
@@ -50,18 +51,6 @@
|
|
50
51
|
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
|
51
52
|
|
52
53
|
|
53
|
-
/** Internal merge flags. */
|
54
|
-
enum {
|
55
|
-
/** The merge is for a virtual base in a recursive merge. */
|
56
|
-
GIT_MERGE__VIRTUAL_BASE = (1 << 31),
|
57
|
-
};
|
58
|
-
|
59
|
-
enum {
|
60
|
-
/** Accept the conflict file, staging it as the merge result. */
|
61
|
-
GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
|
62
|
-
};
|
63
|
-
|
64
|
-
|
65
54
|
typedef enum {
|
66
55
|
TREE_IDX_ANCESTOR = 0,
|
67
56
|
TREE_IDX_OURS = 1,
|
@@ -273,7 +262,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const
|
|
273
262
|
int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
|
274
263
|
{
|
275
264
|
int error;
|
276
|
-
|
265
|
+
git_revwalk *walk;
|
277
266
|
git_commit_list *result, *list;
|
278
267
|
git_array_oid_t array;
|
279
268
|
|
@@ -810,76 +799,158 @@ static int merge_conflict_resolve_one_renamed(
|
|
810
799
|
return error;
|
811
800
|
}
|
812
801
|
|
813
|
-
static
|
814
|
-
|
815
|
-
git_merge_diff_list *diff_list,
|
816
|
-
const git_merge_diff *conflict,
|
817
|
-
const git_merge_file_options *file_opts)
|
802
|
+
static bool merge_conflict_can_resolve_contents(
|
803
|
+
const git_merge_diff *conflict)
|
818
804
|
{
|
819
|
-
const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
|
820
|
-
git_merge_file_result result = {0};
|
821
|
-
git_index_entry *index_entry;
|
822
|
-
git_odb *odb = NULL;
|
823
|
-
git_oid automerge_oid;
|
824
|
-
int error = 0;
|
825
|
-
|
826
|
-
assert(resolved && diff_list && conflict);
|
827
|
-
|
828
|
-
*resolved = 0;
|
829
|
-
|
830
805
|
if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
|
831
806
|
!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
|
832
|
-
return
|
807
|
+
return false;
|
833
808
|
|
834
809
|
/* Reject D/F conflicts */
|
835
810
|
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
|
836
|
-
return
|
811
|
+
return false;
|
837
812
|
|
838
813
|
/* Reject submodules. */
|
839
814
|
if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
|
840
815
|
S_ISGITLINK(conflict->our_entry.mode) ||
|
841
816
|
S_ISGITLINK(conflict->their_entry.mode))
|
842
|
-
return
|
817
|
+
return false;
|
843
818
|
|
844
819
|
/* Reject link/file conflicts. */
|
845
|
-
if ((S_ISLNK(conflict->ancestor_entry.mode) ^
|
846
|
-
|
847
|
-
|
820
|
+
if ((S_ISLNK(conflict->ancestor_entry.mode) ^
|
821
|
+
S_ISLNK(conflict->our_entry.mode)) ||
|
822
|
+
(S_ISLNK(conflict->ancestor_entry.mode) ^
|
823
|
+
S_ISLNK(conflict->their_entry.mode)))
|
824
|
+
return false;
|
848
825
|
|
849
826
|
/* Reject name conflicts */
|
850
827
|
if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
|
851
828
|
conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
|
852
|
-
return
|
829
|
+
return false;
|
853
830
|
|
854
831
|
if ((conflict->our_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
|
855
832
|
(conflict->their_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
|
856
833
|
strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
|
834
|
+
return false;
|
835
|
+
|
836
|
+
return true;
|
837
|
+
}
|
838
|
+
|
839
|
+
static int merge_conflict_invoke_driver(
|
840
|
+
git_index_entry **out,
|
841
|
+
const char *name,
|
842
|
+
git_merge_driver *driver,
|
843
|
+
git_merge_diff_list *diff_list,
|
844
|
+
git_merge_driver_source *src)
|
845
|
+
{
|
846
|
+
git_index_entry *result;
|
847
|
+
git_buf buf = GIT_BUF_INIT;
|
848
|
+
const char *path;
|
849
|
+
uint32_t mode;
|
850
|
+
git_odb *odb = NULL;
|
851
|
+
git_oid oid;
|
852
|
+
int error;
|
853
|
+
|
854
|
+
*out = NULL;
|
855
|
+
|
856
|
+
if ((error = driver->apply(driver, &path, &mode, &buf, name, src)) < 0 ||
|
857
|
+
(error = git_repository_odb(&odb, src->repo)) < 0 ||
|
858
|
+
(error = git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJ_BLOB)) < 0)
|
859
|
+
goto done;
|
860
|
+
|
861
|
+
result = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry));
|
862
|
+
GITERR_CHECK_ALLOC(result);
|
863
|
+
|
864
|
+
git_oid_cpy(&result->id, &oid);
|
865
|
+
result->mode = mode;
|
866
|
+
result->file_size = buf.size;
|
867
|
+
|
868
|
+
result->path = git_pool_strdup(&diff_list->pool, path);
|
869
|
+
GITERR_CHECK_ALLOC(result->path);
|
870
|
+
|
871
|
+
*out = result;
|
872
|
+
|
873
|
+
done:
|
874
|
+
git_buf_free(&buf);
|
875
|
+
git_odb_free(odb);
|
876
|
+
|
877
|
+
return error;
|
878
|
+
}
|
879
|
+
|
880
|
+
static int merge_conflict_resolve_contents(
|
881
|
+
int *resolved,
|
882
|
+
git_merge_diff_list *diff_list,
|
883
|
+
const git_merge_diff *conflict,
|
884
|
+
const git_merge_options *merge_opts,
|
885
|
+
const git_merge_file_options *file_opts)
|
886
|
+
{
|
887
|
+
git_merge_driver_source source = {0};
|
888
|
+
git_merge_file_result result = {0};
|
889
|
+
git_merge_driver *driver;
|
890
|
+
git_merge_driver__builtin builtin = {{0}};
|
891
|
+
git_index_entry *merge_result;
|
892
|
+
git_odb *odb = NULL;
|
893
|
+
const char *name;
|
894
|
+
bool fallback = false;
|
895
|
+
int error;
|
896
|
+
|
897
|
+
assert(resolved && diff_list && conflict);
|
898
|
+
|
899
|
+
*resolved = 0;
|
900
|
+
|
901
|
+
if (!merge_conflict_can_resolve_contents(conflict))
|
857
902
|
return 0;
|
858
903
|
|
859
|
-
|
904
|
+
source.repo = diff_list->repo;
|
905
|
+
source.default_driver = merge_opts->default_driver;
|
906
|
+
source.file_opts = file_opts;
|
907
|
+
source.ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
|
860
908
|
&conflict->ancestor_entry : NULL;
|
861
|
-
ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
|
909
|
+
source.ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
|
862
910
|
&conflict->our_entry : NULL;
|
863
|
-
theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
|
911
|
+
source.theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
|
864
912
|
&conflict->their_entry : NULL;
|
865
913
|
|
866
|
-
if (
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
914
|
+
if (file_opts->favor != GIT_MERGE_FILE_FAVOR_NORMAL) {
|
915
|
+
/* if the user requested a particular type of resolution (via the
|
916
|
+
* favor flag) then let that override the gitattributes and use
|
917
|
+
* the builtin driver.
|
918
|
+
*/
|
919
|
+
name = "text";
|
920
|
+
builtin.base.apply = git_merge_driver__builtin_apply;
|
921
|
+
builtin.favor = file_opts->favor;
|
922
|
+
|
923
|
+
driver = &builtin.base;
|
924
|
+
} else {
|
925
|
+
/* find the merge driver for this file */
|
926
|
+
if ((error = git_merge_driver_for_source(&name, &driver, &source)) < 0)
|
927
|
+
goto done;
|
928
|
+
|
929
|
+
if (driver == NULL)
|
930
|
+
fallback = true;
|
931
|
+
}
|
871
932
|
|
872
|
-
if (
|
873
|
-
|
933
|
+
if (driver) {
|
934
|
+
error = merge_conflict_invoke_driver(&merge_result, name, driver,
|
935
|
+
diff_list, &source);
|
874
936
|
|
875
|
-
|
876
|
-
|
937
|
+
if (error == GIT_PASSTHROUGH)
|
938
|
+
fallback = true;
|
939
|
+
}
|
877
940
|
|
878
|
-
|
879
|
-
|
880
|
-
|
941
|
+
if (fallback) {
|
942
|
+
error = merge_conflict_invoke_driver(&merge_result, "text",
|
943
|
+
&git_merge_driver__text.base, diff_list, &source);
|
944
|
+
}
|
881
945
|
|
882
|
-
|
946
|
+
if (error < 0) {
|
947
|
+
if (error == GIT_EMERGECONFLICT)
|
948
|
+
error = 0;
|
949
|
+
|
950
|
+
goto done;
|
951
|
+
}
|
952
|
+
|
953
|
+
git_vector_insert(&diff_list->staged, merge_result);
|
883
954
|
git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
|
884
955
|
|
885
956
|
*resolved = 1;
|
@@ -895,6 +966,7 @@ static int merge_conflict_resolve(
|
|
895
966
|
int *out,
|
896
967
|
git_merge_diff_list *diff_list,
|
897
968
|
const git_merge_diff *conflict,
|
969
|
+
const git_merge_options *merge_opts,
|
898
970
|
const git_merge_file_options *file_opts)
|
899
971
|
{
|
900
972
|
int resolved = 0;
|
@@ -902,16 +974,20 @@ static int merge_conflict_resolve(
|
|
902
974
|
|
903
975
|
*out = 0;
|
904
976
|
|
905
|
-
if ((error = merge_conflict_resolve_trivial(
|
977
|
+
if ((error = merge_conflict_resolve_trivial(
|
978
|
+
&resolved, diff_list, conflict)) < 0)
|
906
979
|
goto done;
|
907
980
|
|
908
|
-
if (!resolved && (error = merge_conflict_resolve_one_removed(
|
981
|
+
if (!resolved && (error = merge_conflict_resolve_one_removed(
|
982
|
+
&resolved, diff_list, conflict)) < 0)
|
909
983
|
goto done;
|
910
984
|
|
911
|
-
if (!resolved && (error = merge_conflict_resolve_one_renamed(
|
985
|
+
if (!resolved && (error = merge_conflict_resolve_one_renamed(
|
986
|
+
&resolved, diff_list, conflict)) < 0)
|
912
987
|
goto done;
|
913
988
|
|
914
|
-
if (!resolved && (error =
|
989
|
+
if (!resolved && (error = merge_conflict_resolve_contents(
|
990
|
+
&resolved, diff_list, conflict, merge_opts, file_opts)) < 0)
|
915
991
|
goto done;
|
916
992
|
|
917
993
|
*out = resolved;
|
@@ -1627,6 +1703,7 @@ static int merge_normalize_opts(
|
|
1627
1703
|
const git_merge_options *given)
|
1628
1704
|
{
|
1629
1705
|
git_config *cfg = NULL;
|
1706
|
+
git_config_entry *entry = NULL;
|
1630
1707
|
int error = 0;
|
1631
1708
|
|
1632
1709
|
assert(repo && opts);
|
@@ -1644,6 +1721,22 @@ static int merge_normalize_opts(
|
|
1644
1721
|
opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
|
1645
1722
|
}
|
1646
1723
|
|
1724
|
+
if (given && given->default_driver) {
|
1725
|
+
opts->default_driver = git__strdup(given->default_driver);
|
1726
|
+
GITERR_CHECK_ALLOC(opts->default_driver);
|
1727
|
+
} else {
|
1728
|
+
error = git_config_get_entry(&entry, cfg, "merge.default");
|
1729
|
+
|
1730
|
+
if (error == 0) {
|
1731
|
+
opts->default_driver = git__strdup(entry->value);
|
1732
|
+
GITERR_CHECK_ALLOC(opts->default_driver);
|
1733
|
+
} else if (error == GIT_ENOTFOUND) {
|
1734
|
+
error = 0;
|
1735
|
+
} else {
|
1736
|
+
goto done;
|
1737
|
+
}
|
1738
|
+
}
|
1739
|
+
|
1647
1740
|
if (!opts->target_limit) {
|
1648
1741
|
int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
|
1649
1742
|
|
@@ -1666,7 +1759,9 @@ static int merge_normalize_opts(
|
|
1666
1759
|
opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
|
1667
1760
|
}
|
1668
1761
|
|
1669
|
-
|
1762
|
+
done:
|
1763
|
+
git_config_entry_free(entry);
|
1764
|
+
return error;
|
1670
1765
|
}
|
1671
1766
|
|
1672
1767
|
|
@@ -1878,7 +1973,7 @@ int git_merge__iterators(
|
|
1878
1973
|
int resolved = 0;
|
1879
1974
|
|
1880
1975
|
if ((error = merge_conflict_resolve(
|
1881
|
-
&resolved, diff_list, conflict, &file_opts)) < 0)
|
1976
|
+
&resolved, diff_list, conflict, &opts, &file_opts)) < 0)
|
1882
1977
|
goto done;
|
1883
1978
|
|
1884
1979
|
if (!resolved) {
|
@@ -1899,6 +1994,8 @@ done:
|
|
1899
1994
|
if (!given_opts || !given_opts->metric)
|
1900
1995
|
git__free(opts.metric);
|
1901
1996
|
|
1997
|
+
git__free((char *)opts.default_driver);
|
1998
|
+
|
1902
1999
|
git_merge_diff_list__free(diff_list);
|
1903
2000
|
git_iterator_free(empty_ancestor);
|
1904
2001
|
git_iterator_free(empty_ours);
|
@@ -2111,14 +2208,14 @@ static int merge_annotated_commits(
|
|
2111
2208
|
git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
|
2112
2209
|
int error;
|
2113
2210
|
|
2114
|
-
|
2211
|
+
if ((error = compute_base(&base, repo, ours, theirs, opts,
|
2115
2212
|
recursion_level)) < 0) {
|
2116
2213
|
|
2117
|
-
|
2118
|
-
|
2214
|
+
if (error != GIT_ENOTFOUND)
|
2215
|
+
goto done;
|
2119
2216
|
|
2120
|
-
|
2121
|
-
|
2217
|
+
giterr_clear();
|
2218
|
+
}
|
2122
2219
|
|
2123
2220
|
if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
|
2124
2221
|
(error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
|