rugged 0.25.0b2 → 0.25.0b3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +3 -1
  4. data/ext/rugged/rugged.c +1 -1
  5. data/ext/rugged/rugged.h +1 -1
  6. data/ext/rugged/rugged_blob.c +29 -38
  7. data/ext/rugged/rugged_commit.c +215 -78
  8. data/ext/rugged/rugged_rebase.c +18 -11
  9. data/ext/rugged/rugged_remote.c +2 -2
  10. data/ext/rugged/rugged_tree.c +132 -0
  11. data/lib/rugged/version.rb +1 -1
  12. data/vendor/libgit2/CMakeLists.txt +11 -3
  13. data/vendor/libgit2/include/git2.h +1 -0
  14. data/vendor/libgit2/include/git2/blob.h +39 -28
  15. data/vendor/libgit2/include/git2/commit.h +30 -0
  16. data/vendor/libgit2/include/git2/common.h +16 -1
  17. data/vendor/libgit2/include/git2/merge.h +10 -1
  18. data/vendor/libgit2/include/git2/proxy.h +92 -0
  19. data/vendor/libgit2/include/git2/refs.h +11 -0
  20. data/vendor/libgit2/include/git2/remote.h +17 -4
  21. data/vendor/libgit2/include/git2/signature.h +13 -0
  22. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  23. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  24. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  25. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  26. data/vendor/libgit2/include/git2/tag.h +9 -0
  27. data/vendor/libgit2/include/git2/tree.h +55 -0
  28. data/vendor/libgit2/src/annotated_commit.c +99 -80
  29. data/vendor/libgit2/src/annotated_commit.h +5 -2
  30. data/vendor/libgit2/src/array.h +40 -0
  31. data/vendor/libgit2/src/blame.c +8 -3
  32. data/vendor/libgit2/src/blame_git.c +2 -1
  33. data/vendor/libgit2/src/blob.c +71 -39
  34. data/vendor/libgit2/src/branch.c +2 -1
  35. data/vendor/libgit2/src/checkout.c +66 -42
  36. data/vendor/libgit2/src/commit.c +67 -3
  37. data/vendor/libgit2/src/config_cache.c +2 -1
  38. data/vendor/libgit2/src/config_file.c +32 -27
  39. data/vendor/libgit2/src/curl_stream.c +89 -6
  40. data/vendor/libgit2/src/delta-apply.c +36 -5
  41. data/vendor/libgit2/src/delta-apply.h +12 -0
  42. data/vendor/libgit2/src/describe.c +3 -2
  43. data/vendor/libgit2/src/diff.c +13 -20
  44. data/vendor/libgit2/src/diff_tform.c +5 -3
  45. data/vendor/libgit2/src/filebuf.c +12 -2
  46. data/vendor/libgit2/src/filebuf.h +1 -0
  47. data/vendor/libgit2/src/fnmatch.c +18 -5
  48. data/vendor/libgit2/src/global.c +18 -0
  49. data/vendor/libgit2/src/global.h +1 -0
  50. data/vendor/libgit2/src/ignore.c +11 -3
  51. data/vendor/libgit2/src/index.c +11 -5
  52. data/vendor/libgit2/src/indexer.c +11 -7
  53. data/vendor/libgit2/src/iterator.c +1575 -1468
  54. data/vendor/libgit2/src/iterator.h +52 -69
  55. data/vendor/libgit2/src/merge.c +160 -63
  56. data/vendor/libgit2/src/merge.h +61 -2
  57. data/vendor/libgit2/src/merge_driver.c +397 -0
  58. data/vendor/libgit2/src/merge_driver.h +60 -0
  59. data/vendor/libgit2/src/merge_file.c +11 -49
  60. data/vendor/libgit2/src/netops.c +12 -10
  61. data/vendor/libgit2/src/object.c +3 -6
  62. data/vendor/libgit2/src/object_api.c +19 -1
  63. data/vendor/libgit2/src/odb_loose.c +1 -1
  64. data/vendor/libgit2/src/openssl_stream.c +16 -3
  65. data/vendor/libgit2/src/pack-objects.c +3 -1
  66. data/vendor/libgit2/src/pack.c +5 -9
  67. data/vendor/libgit2/src/path.c +14 -0
  68. data/vendor/libgit2/src/path.h +12 -0
  69. data/vendor/libgit2/src/pathspec.c +1 -1
  70. data/vendor/libgit2/src/posix.c +7 -0
  71. data/vendor/libgit2/src/posix.h +1 -0
  72. data/vendor/libgit2/src/proxy.c +32 -0
  73. data/vendor/libgit2/src/proxy.h +14 -0
  74. data/vendor/libgit2/src/push.c +7 -7
  75. data/vendor/libgit2/src/rebase.c +61 -31
  76. data/vendor/libgit2/src/refdb_fs.c +1 -0
  77. data/vendor/libgit2/src/refs.c +16 -1
  78. data/vendor/libgit2/src/remote.c +20 -6
  79. data/vendor/libgit2/src/repository.c +1 -1
  80. data/vendor/libgit2/src/reset.c +1 -1
  81. data/vendor/libgit2/src/settings.c +23 -1
  82. data/vendor/libgit2/src/signature.c +26 -1
  83. data/vendor/libgit2/src/stransport_stream.c +5 -2
  84. data/vendor/libgit2/src/stream.h +2 -2
  85. data/vendor/libgit2/src/submodule.c +3 -2
  86. data/vendor/libgit2/src/tag.c +8 -2
  87. data/vendor/libgit2/src/transports/http.c +32 -9
  88. data/vendor/libgit2/src/transports/local.c +4 -1
  89. data/vendor/libgit2/src/transports/smart.c +6 -0
  90. data/vendor/libgit2/src/transports/smart.h +1 -0
  91. data/vendor/libgit2/src/transports/smart_protocol.c +61 -17
  92. data/vendor/libgit2/src/transports/winhttp.c +130 -11
  93. data/vendor/libgit2/src/tree.c +329 -98
  94. data/vendor/libgit2/src/tree.h +4 -5
  95. data/vendor/libgit2/src/unix/map.c +5 -0
  96. data/vendor/libgit2/src/win32/map.c +24 -5
  97. data/vendor/libgit2/src/xdiff/xprepare.c +2 -1
  98. metadata +10 -4
  99. 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 << 5),
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 (*seek)(git_iterator *, const char *prefix);
61
- int (*reset)(git_iterator *, const char *start, const char *end);
62
- int (*at_end)(git_iterator *);
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
- * Advance into a tree or skip over it if it is empty.
203
+ /* Advance over a directory and check if it contains no files or just
204
+ * ignored files.
186
205
  *
187
- * Because `git_iterator_advance_into` may return GIT_ENOTFOUND if the
188
- * directory is empty (only with filesystem and working directory
189
- * iterators) and a common response is to just call `git_iterator_advance`
190
- * when that happens, this bundles the two into a single simple call.
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) git_iterator_advance_into_or_over(
193
- const git_index_entry **entry, git_iterator *iter)
194
- {
195
- int error = iter->cb->advance_into(entry, iter);
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->seek(iter, prefix);
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, start, end);
226
+ return iter->cb->reset(iter);
221
227
  }
222
228
 
223
229
  /**
224
- * Check if the iterator is at the end
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
- GIT_INLINE(int) git_iterator_at_end(git_iterator *iter)
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 int git_iterator_set_ignore_case(git_iterator *iter, bool ignore_case);
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, const char *parent_path);
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 iterator
285
+ * Only implemented for the workdir and index iterators.
303
286
  */
304
- extern int git_iterator_index(git_index **out, git_iterator *iter);
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,
@@ -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
- git_revwalk *walk;
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 int merge_conflict_resolve_automerge(
814
- int *resolved,
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 0;
807
+ return false;
833
808
 
834
809
  /* Reject D/F conflicts */
835
810
  if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
836
- return 0;
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 0;
817
+ return false;
843
818
 
844
819
  /* Reject link/file conflicts. */
845
- if ((S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->our_entry.mode)) ||
846
- (S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->their_entry.mode)))
847
- return 0;
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 0;
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
- ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
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 ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
867
- (error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, file_opts)) < 0 ||
868
- (!result.automergeable && !(file_opts->flags & GIT_MERGE_FILE_FAVOR__CONFLICTED)) ||
869
- (error = git_odb_write(&automerge_oid, odb, result.ptr, result.len, GIT_OBJ_BLOB)) < 0)
870
- goto done;
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 ((index_entry = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry))) == NULL)
873
- GITERR_CHECK_ALLOC(index_entry);
933
+ if (driver) {
934
+ error = merge_conflict_invoke_driver(&merge_result, name, driver,
935
+ diff_list, &source);
874
936
 
875
- index_entry->path = git_pool_strdup(&diff_list->pool, result.path);
876
- GITERR_CHECK_ALLOC(index_entry->path);
937
+ if (error == GIT_PASSTHROUGH)
938
+ fallback = true;
939
+ }
877
940
 
878
- index_entry->file_size = result.len;
879
- index_entry->mode = result.mode;
880
- git_oid_cpy(&index_entry->id, &automerge_oid);
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
- git_vector_insert(&diff_list->staged, index_entry);
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(&resolved, diff_list, conflict)) < 0)
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(&resolved, diff_list, conflict)) < 0)
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(&resolved, diff_list, conflict)) < 0)
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 = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, file_opts)) < 0)
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
- return 0;
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
- if ((error = compute_base(&base, repo, ours, theirs, opts,
2211
+ if ((error = compute_base(&base, repo, ours, theirs, opts,
2115
2212
  recursion_level)) < 0) {
2116
2213
 
2117
- if (error != GIT_ENOTFOUND)
2118
- goto done;
2214
+ if (error != GIT_ENOTFOUND)
2215
+ goto done;
2119
2216
 
2120
- giterr_clear();
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 ||