rugged 0.25.0b2 → 0.25.0b3
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/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 ||
|