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.
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 ||