rugged 0.24.6.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +9 -2
  4. data/ext/rugged/rugged.c +85 -21
  5. data/ext/rugged/rugged.h +7 -21
  6. data/ext/rugged/rugged_backend.c +3 -20
  7. data/ext/rugged/rugged_blame.c +7 -24
  8. data/ext/rugged/rugged_blob.c +136 -59
  9. data/ext/rugged/rugged_branch.c +3 -20
  10. data/ext/rugged/rugged_branch_collection.c +3 -20
  11. data/ext/rugged/rugged_commit.c +251 -101
  12. data/ext/rugged/rugged_config.c +3 -20
  13. data/ext/rugged/rugged_cred.c +3 -20
  14. data/ext/rugged/rugged_diff.c +3 -20
  15. data/ext/rugged/rugged_diff_delta.c +3 -20
  16. data/ext/rugged/rugged_diff_hunk.c +3 -20
  17. data/ext/rugged/rugged_diff_line.c +3 -20
  18. data/ext/rugged/rugged_index.c +46 -229
  19. data/ext/rugged/rugged_note.c +3 -20
  20. data/ext/rugged/rugged_object.c +3 -20
  21. data/ext/rugged/rugged_patch.c +192 -34
  22. data/ext/rugged/rugged_rebase.c +90 -48
  23. data/ext/rugged/rugged_reference.c +4 -21
  24. data/ext/rugged/rugged_reference_collection.c +3 -20
  25. data/ext/rugged/rugged_remote.c +70 -42
  26. data/ext/rugged/rugged_remote_collection.c +3 -20
  27. data/ext/rugged/rugged_repo.c +50 -59
  28. data/ext/rugged/rugged_revwalk.c +4 -21
  29. data/ext/rugged/rugged_settings.c +3 -20
  30. data/ext/rugged/rugged_signature.c +3 -20
  31. data/ext/rugged/rugged_submodule.c +4 -21
  32. data/ext/rugged/rugged_submodule_collection.c +3 -20
  33. data/ext/rugged/rugged_tag.c +3 -20
  34. data/ext/rugged/rugged_tag_collection.c +3 -20
  35. data/ext/rugged/rugged_tree.c +189 -184
  36. data/lib/rugged/attributes.rb +5 -0
  37. data/lib/rugged/blob.rb +5 -0
  38. data/lib/rugged/branch.rb +6 -1
  39. data/lib/rugged/commit.rb +5 -0
  40. data/lib/rugged/console.rb +5 -0
  41. data/lib/rugged/credentials.rb +5 -0
  42. data/lib/rugged/diff/delta.rb +5 -0
  43. data/lib/rugged/diff/hunk.rb +5 -0
  44. data/lib/rugged/diff/line.rb +5 -0
  45. data/lib/rugged/diff.rb +5 -0
  46. data/lib/rugged/index.rb +120 -0
  47. data/lib/rugged/object.rb +5 -0
  48. data/lib/rugged/patch.rb +5 -0
  49. data/lib/rugged/reference.rb +5 -0
  50. data/lib/rugged/remote.rb +5 -0
  51. data/lib/rugged/repository.rb +9 -4
  52. data/lib/rugged/submodule_collection.rb +5 -0
  53. data/lib/rugged/tag.rb +5 -0
  54. data/lib/rugged/tree.rb +156 -1
  55. data/lib/rugged/version.rb +6 -1
  56. data/lib/rugged/walker.rb +5 -0
  57. data/lib/rugged.rb +5 -0
  58. data/vendor/libgit2/CMakeLists.txt +12 -2
  59. data/vendor/libgit2/include/git2/blob.h +39 -28
  60. data/vendor/libgit2/include/git2/commit.h +76 -0
  61. data/vendor/libgit2/include/git2/common.h +21 -1
  62. data/vendor/libgit2/include/git2/describe.h +5 -2
  63. data/vendor/libgit2/include/git2/diff.h +62 -7
  64. data/vendor/libgit2/include/git2/errors.h +2 -1
  65. data/vendor/libgit2/include/git2/index.h +25 -0
  66. data/vendor/libgit2/include/git2/merge.h +10 -1
  67. data/vendor/libgit2/include/git2/odb.h +47 -1
  68. data/vendor/libgit2/include/git2/pack.h +4 -4
  69. data/vendor/libgit2/include/git2/patch.h +1 -1
  70. data/vendor/libgit2/include/git2/proxy.h +92 -0
  71. data/vendor/libgit2/include/git2/refs.h +11 -0
  72. data/vendor/libgit2/include/git2/remote.h +21 -8
  73. data/vendor/libgit2/include/git2/repository.h +20 -1
  74. data/vendor/libgit2/include/git2/revwalk.h +4 -6
  75. data/vendor/libgit2/include/git2/signature.h +13 -0
  76. data/vendor/libgit2/include/git2/submodule.h +11 -3
  77. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  78. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  79. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  80. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  81. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  82. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  83. data/vendor/libgit2/include/git2/tag.h +9 -0
  84. data/vendor/libgit2/include/git2/transaction.h +9 -0
  85. data/vendor/libgit2/include/git2/tree.h +55 -0
  86. data/vendor/libgit2/include/git2/version.h +4 -4
  87. data/vendor/libgit2/include/git2.h +1 -0
  88. data/vendor/libgit2/src/annotated_commit.c +99 -80
  89. data/vendor/libgit2/src/annotated_commit.h +5 -2
  90. data/vendor/libgit2/src/apply.c +377 -0
  91. data/vendor/libgit2/src/apply.h +21 -0
  92. data/vendor/libgit2/src/array.h +0 -1
  93. data/vendor/libgit2/src/blob.c +71 -39
  94. data/vendor/libgit2/src/branch.c +7 -5
  95. data/vendor/libgit2/src/buffer.c +252 -20
  96. data/vendor/libgit2/src/buffer.h +8 -0
  97. data/vendor/libgit2/src/checkout.c +69 -42
  98. data/vendor/libgit2/src/clone.c +0 -8
  99. data/vendor/libgit2/src/commit.c +193 -49
  100. data/vendor/libgit2/src/commit_list.c +8 -3
  101. data/vendor/libgit2/src/commit_list.h +1 -0
  102. data/vendor/libgit2/src/common.h +2 -1
  103. data/vendor/libgit2/src/config.c +3 -3
  104. data/vendor/libgit2/src/config_file.c +20 -10
  105. data/vendor/libgit2/src/crlf.c +1 -0
  106. data/vendor/libgit2/src/curl_stream.c +106 -6
  107. data/vendor/libgit2/src/delta.c +238 -62
  108. data/vendor/libgit2/src/delta.h +79 -58
  109. data/vendor/libgit2/src/describe.c +1 -1
  110. data/vendor/libgit2/src/diff.c +32 -1554
  111. data/vendor/libgit2/src/diff.h +14 -122
  112. data/vendor/libgit2/src/diff_driver.c +4 -6
  113. data/vendor/libgit2/src/diff_file.c +3 -0
  114. data/vendor/libgit2/src/diff_generate.c +1613 -0
  115. data/vendor/libgit2/src/diff_generate.h +123 -0
  116. data/vendor/libgit2/src/diff_parse.c +101 -0
  117. data/vendor/libgit2/src/diff_parse.h +18 -0
  118. data/vendor/libgit2/src/diff_print.c +263 -144
  119. data/vendor/libgit2/src/diff_stats.c +21 -12
  120. data/vendor/libgit2/src/diff_tform.c +1 -0
  121. data/vendor/libgit2/src/diff_tform.h +22 -0
  122. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  123. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  124. data/vendor/libgit2/src/fetchhead.c +8 -8
  125. data/vendor/libgit2/src/filebuf.c +6 -1
  126. data/vendor/libgit2/src/filebuf.h +1 -0
  127. data/vendor/libgit2/src/fileops.c +22 -1
  128. data/vendor/libgit2/src/fileops.h +8 -2
  129. data/vendor/libgit2/src/fnmatch.c +18 -5
  130. data/vendor/libgit2/src/global.c +21 -4
  131. data/vendor/libgit2/src/global.h +6 -0
  132. data/vendor/libgit2/src/graph.c +1 -1
  133. data/vendor/libgit2/src/index.c +159 -46
  134. data/vendor/libgit2/src/index.h +2 -0
  135. data/vendor/libgit2/src/iterator.c +1573 -1468
  136. data/vendor/libgit2/src/iterator.h +52 -69
  137. data/vendor/libgit2/src/merge.c +163 -64
  138. data/vendor/libgit2/src/merge.h +61 -2
  139. data/vendor/libgit2/src/merge_driver.c +397 -0
  140. data/vendor/libgit2/src/merge_driver.h +60 -0
  141. data/vendor/libgit2/src/merge_file.c +11 -49
  142. data/vendor/libgit2/src/netops.c +12 -10
  143. data/vendor/libgit2/src/object_api.c +19 -1
  144. data/vendor/libgit2/src/odb.c +228 -52
  145. data/vendor/libgit2/src/odb_loose.c +19 -1
  146. data/vendor/libgit2/src/odb_mempack.c +1 -1
  147. data/vendor/libgit2/src/odb_pack.c +27 -1
  148. data/vendor/libgit2/src/openssl_stream.c +4 -5
  149. data/vendor/libgit2/src/pack-objects.c +105 -76
  150. data/vendor/libgit2/src/pack-objects.h +13 -12
  151. data/vendor/libgit2/src/pack.c +16 -10
  152. data/vendor/libgit2/src/pack.h +2 -0
  153. data/vendor/libgit2/src/patch.c +216 -0
  154. data/vendor/libgit2/src/patch.h +66 -0
  155. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +203 -376
  156. data/vendor/libgit2/src/patch_generate.h +68 -0
  157. data/vendor/libgit2/src/patch_parse.c +1159 -0
  158. data/vendor/libgit2/src/patch_parse.h +56 -0
  159. data/vendor/libgit2/src/path.c +38 -2
  160. data/vendor/libgit2/src/path.h +18 -0
  161. data/vendor/libgit2/src/pathspec.c +1 -1
  162. data/vendor/libgit2/src/pool.h +5 -0
  163. data/vendor/libgit2/src/pqueue.c +12 -5
  164. data/vendor/libgit2/src/pqueue.h +1 -0
  165. data/vendor/libgit2/src/proxy.c +32 -0
  166. data/vendor/libgit2/src/proxy.h +14 -0
  167. data/vendor/libgit2/src/push.c +1 -1
  168. data/vendor/libgit2/src/rebase.c +63 -36
  169. data/vendor/libgit2/src/refdb.c +4 -2
  170. data/vendor/libgit2/src/refdb_fs.c +82 -54
  171. data/vendor/libgit2/src/refs.c +13 -1
  172. data/vendor/libgit2/src/remote.c +20 -81
  173. data/vendor/libgit2/src/repository.c +212 -29
  174. data/vendor/libgit2/src/reset.c +1 -1
  175. data/vendor/libgit2/src/revparse.c +1 -1
  176. data/vendor/libgit2/src/revwalk.c +260 -184
  177. data/vendor/libgit2/src/settings.c +11 -3
  178. data/vendor/libgit2/src/signature.c +27 -2
  179. data/vendor/libgit2/src/sortedcache.c +14 -5
  180. data/vendor/libgit2/src/stash.c +1 -0
  181. data/vendor/libgit2/src/status.c +1 -0
  182. data/vendor/libgit2/src/stransport_stream.c +4 -2
  183. data/vendor/libgit2/src/stream.h +2 -2
  184. data/vendor/libgit2/src/submodule.c +16 -4
  185. data/vendor/libgit2/src/sysdir.c +1 -1
  186. data/vendor/libgit2/src/transport.c +3 -5
  187. data/vendor/libgit2/src/transports/http.c +38 -13
  188. data/vendor/libgit2/src/transports/local.c +4 -1
  189. data/vendor/libgit2/src/transports/smart.c +6 -0
  190. data/vendor/libgit2/src/transports/smart.h +1 -0
  191. data/vendor/libgit2/src/transports/smart_pkt.c +5 -13
  192. data/vendor/libgit2/src/transports/smart_protocol.c +22 -7
  193. data/vendor/libgit2/src/transports/winhttp.c +144 -11
  194. data/vendor/libgit2/src/tree.c +267 -2
  195. data/vendor/libgit2/src/unix/posix.h +10 -0
  196. data/vendor/libgit2/src/unix/pthread.h +2 -0
  197. data/vendor/libgit2/src/util.c +25 -2
  198. data/vendor/libgit2/src/util.h +10 -0
  199. data/vendor/libgit2/src/varint.c +44 -0
  200. data/vendor/libgit2/src/varint.h +15 -0
  201. data/vendor/libgit2/src/vector.c +58 -0
  202. data/vendor/libgit2/src/vector.h +8 -0
  203. data/vendor/libgit2/src/win32/posix.h +3 -0
  204. data/vendor/libgit2/src/win32/thread.c +18 -0
  205. data/vendor/libgit2/src/win32/thread.h +2 -0
  206. data/vendor/libgit2/src/win32/w32_util.h +1 -1
  207. data/vendor/libgit2/src/zstream.c +37 -8
  208. data/vendor/libgit2/src/zstream.h +8 -1
  209. metadata +100 -82
  210. data/vendor/libgit2/Makefile.embed +0 -60
  211. data/vendor/libgit2/src/delta-apply.c +0 -166
  212. data/vendor/libgit2/src/delta-apply.h +0 -62
  213. data/vendor/libgit2/src/diff_patch.h +0 -83
@@ -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,
@@ -18,6 +18,8 @@
18
18
  #include "iterator.h"
19
19
  #include "refs.h"
20
20
  #include "diff.h"
21
+ #include "diff_generate.h"
22
+ #include "diff_tform.h"
21
23
  #include "checkout.h"
22
24
  #include "tree.h"
23
25
  #include "blob.h"
@@ -29,6 +31,7 @@
29
31
  #include "annotated_commit.h"
30
32
  #include "commit.h"
31
33
  #include "oidarray.h"
34
+ #include "merge_driver.h"
32
35
 
33
36
  #include "git2/types.h"
34
37
  #include "git2/repository.h"
@@ -50,18 +53,6 @@
50
53
  #define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
51
54
 
52
55
 
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
56
  typedef enum {
66
57
  TREE_IDX_ANCESTOR = 0,
67
58
  TREE_IDX_OURS = 1,
@@ -273,7 +264,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const
273
264
  int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
274
265
  {
275
266
  int error;
276
- git_revwalk *walk;
267
+ git_revwalk *walk;
277
268
  git_commit_list *result, *list;
278
269
  git_array_oid_t array;
279
270
 
@@ -600,7 +591,7 @@ int git_repository_mergehead_foreach(
600
591
  }
601
592
 
602
593
  if (*buffer) {
603
- giterr_set(GITERR_MERGE, "No EOL at line %d", line_num);
594
+ giterr_set(GITERR_MERGE, "No EOL at line %"PRIuZ, line_num);
604
595
  error = -1;
605
596
  goto cleanup;
606
597
  }
@@ -810,76 +801,158 @@ static int merge_conflict_resolve_one_renamed(
810
801
  return error;
811
802
  }
812
803
 
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)
804
+ static bool merge_conflict_can_resolve_contents(
805
+ const git_merge_diff *conflict)
818
806
  {
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
807
  if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
831
808
  !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
832
- return 0;
809
+ return false;
833
810
 
834
811
  /* Reject D/F conflicts */
835
812
  if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
836
- return 0;
813
+ return false;
837
814
 
838
815
  /* Reject submodules. */
839
816
  if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
840
817
  S_ISGITLINK(conflict->our_entry.mode) ||
841
818
  S_ISGITLINK(conflict->their_entry.mode))
842
- return 0;
819
+ return false;
843
820
 
844
821
  /* 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;
822
+ if ((S_ISLNK(conflict->ancestor_entry.mode) ^
823
+ S_ISLNK(conflict->our_entry.mode)) ||
824
+ (S_ISLNK(conflict->ancestor_entry.mode) ^
825
+ S_ISLNK(conflict->their_entry.mode)))
826
+ return false;
848
827
 
849
828
  /* Reject name conflicts */
850
829
  if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
851
830
  conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
852
- return 0;
831
+ return false;
853
832
 
854
833
  if ((conflict->our_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
855
834
  (conflict->their_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
856
835
  strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
836
+ return false;
837
+
838
+ return true;
839
+ }
840
+
841
+ static int merge_conflict_invoke_driver(
842
+ git_index_entry **out,
843
+ const char *name,
844
+ git_merge_driver *driver,
845
+ git_merge_diff_list *diff_list,
846
+ git_merge_driver_source *src)
847
+ {
848
+ git_index_entry *result;
849
+ git_buf buf = GIT_BUF_INIT;
850
+ const char *path;
851
+ uint32_t mode;
852
+ git_odb *odb = NULL;
853
+ git_oid oid;
854
+ int error;
855
+
856
+ *out = NULL;
857
+
858
+ if ((error = driver->apply(driver, &path, &mode, &buf, name, src)) < 0 ||
859
+ (error = git_repository_odb(&odb, src->repo)) < 0 ||
860
+ (error = git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJ_BLOB)) < 0)
861
+ goto done;
862
+
863
+ result = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry));
864
+ GITERR_CHECK_ALLOC(result);
865
+
866
+ git_oid_cpy(&result->id, &oid);
867
+ result->mode = mode;
868
+ result->file_size = buf.size;
869
+
870
+ result->path = git_pool_strdup(&diff_list->pool, path);
871
+ GITERR_CHECK_ALLOC(result->path);
872
+
873
+ *out = result;
874
+
875
+ done:
876
+ git_buf_free(&buf);
877
+ git_odb_free(odb);
878
+
879
+ return error;
880
+ }
881
+
882
+ static int merge_conflict_resolve_contents(
883
+ int *resolved,
884
+ git_merge_diff_list *diff_list,
885
+ const git_merge_diff *conflict,
886
+ const git_merge_options *merge_opts,
887
+ const git_merge_file_options *file_opts)
888
+ {
889
+ git_merge_driver_source source = {0};
890
+ git_merge_file_result result = {0};
891
+ git_merge_driver *driver;
892
+ git_merge_driver__builtin builtin = {{0}};
893
+ git_index_entry *merge_result;
894
+ git_odb *odb = NULL;
895
+ const char *name;
896
+ bool fallback = false;
897
+ int error;
898
+
899
+ assert(resolved && diff_list && conflict);
900
+
901
+ *resolved = 0;
902
+
903
+ if (!merge_conflict_can_resolve_contents(conflict))
857
904
  return 0;
858
905
 
859
- ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
906
+ source.repo = diff_list->repo;
907
+ source.default_driver = merge_opts->default_driver;
908
+ source.file_opts = file_opts;
909
+ source.ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
860
910
  &conflict->ancestor_entry : NULL;
861
- ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
911
+ source.ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
862
912
  &conflict->our_entry : NULL;
863
- theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
913
+ source.theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
864
914
  &conflict->their_entry : NULL;
865
915
 
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;
916
+ if (file_opts->favor != GIT_MERGE_FILE_FAVOR_NORMAL) {
917
+ /* if the user requested a particular type of resolution (via the
918
+ * favor flag) then let that override the gitattributes and use
919
+ * the builtin driver.
920
+ */
921
+ name = "text";
922
+ builtin.base.apply = git_merge_driver__builtin_apply;
923
+ builtin.favor = file_opts->favor;
924
+
925
+ driver = &builtin.base;
926
+ } else {
927
+ /* find the merge driver for this file */
928
+ if ((error = git_merge_driver_for_source(&name, &driver, &source)) < 0)
929
+ goto done;
930
+
931
+ if (driver == NULL)
932
+ fallback = true;
933
+ }
871
934
 
872
- if ((index_entry = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry))) == NULL)
873
- GITERR_CHECK_ALLOC(index_entry);
935
+ if (driver) {
936
+ error = merge_conflict_invoke_driver(&merge_result, name, driver,
937
+ diff_list, &source);
874
938
 
875
- index_entry->path = git_pool_strdup(&diff_list->pool, result.path);
876
- GITERR_CHECK_ALLOC(index_entry->path);
939
+ if (error == GIT_PASSTHROUGH)
940
+ fallback = true;
941
+ }
877
942
 
878
- index_entry->file_size = result.len;
879
- index_entry->mode = result.mode;
880
- git_oid_cpy(&index_entry->id, &automerge_oid);
943
+ if (fallback) {
944
+ error = merge_conflict_invoke_driver(&merge_result, "text",
945
+ &git_merge_driver__text.base, diff_list, &source);
946
+ }
881
947
 
882
- git_vector_insert(&diff_list->staged, index_entry);
948
+ if (error < 0) {
949
+ if (error == GIT_EMERGECONFLICT)
950
+ error = 0;
951
+
952
+ goto done;
953
+ }
954
+
955
+ git_vector_insert(&diff_list->staged, merge_result);
883
956
  git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
884
957
 
885
958
  *resolved = 1;
@@ -895,6 +968,7 @@ static int merge_conflict_resolve(
895
968
  int *out,
896
969
  git_merge_diff_list *diff_list,
897
970
  const git_merge_diff *conflict,
971
+ const git_merge_options *merge_opts,
898
972
  const git_merge_file_options *file_opts)
899
973
  {
900
974
  int resolved = 0;
@@ -902,16 +976,20 @@ static int merge_conflict_resolve(
902
976
 
903
977
  *out = 0;
904
978
 
905
- if ((error = merge_conflict_resolve_trivial(&resolved, diff_list, conflict)) < 0)
979
+ if ((error = merge_conflict_resolve_trivial(
980
+ &resolved, diff_list, conflict)) < 0)
906
981
  goto done;
907
982
 
908
- if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
983
+ if (!resolved && (error = merge_conflict_resolve_one_removed(
984
+ &resolved, diff_list, conflict)) < 0)
909
985
  goto done;
910
986
 
911
- if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
987
+ if (!resolved && (error = merge_conflict_resolve_one_renamed(
988
+ &resolved, diff_list, conflict)) < 0)
912
989
  goto done;
913
990
 
914
- if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, file_opts)) < 0)
991
+ if (!resolved && (error = merge_conflict_resolve_contents(
992
+ &resolved, diff_list, conflict, merge_opts, file_opts)) < 0)
915
993
  goto done;
916
994
 
917
995
  *out = resolved;
@@ -1627,6 +1705,7 @@ static int merge_normalize_opts(
1627
1705
  const git_merge_options *given)
1628
1706
  {
1629
1707
  git_config *cfg = NULL;
1708
+ git_config_entry *entry = NULL;
1630
1709
  int error = 0;
1631
1710
 
1632
1711
  assert(repo && opts);
@@ -1644,6 +1723,22 @@ static int merge_normalize_opts(
1644
1723
  opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
1645
1724
  }
1646
1725
 
1726
+ if (given && given->default_driver) {
1727
+ opts->default_driver = git__strdup(given->default_driver);
1728
+ GITERR_CHECK_ALLOC(opts->default_driver);
1729
+ } else {
1730
+ error = git_config_get_entry(&entry, cfg, "merge.default");
1731
+
1732
+ if (error == 0) {
1733
+ opts->default_driver = git__strdup(entry->value);
1734
+ GITERR_CHECK_ALLOC(opts->default_driver);
1735
+ } else if (error == GIT_ENOTFOUND) {
1736
+ error = 0;
1737
+ } else {
1738
+ goto done;
1739
+ }
1740
+ }
1741
+
1647
1742
  if (!opts->target_limit) {
1648
1743
  int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
1649
1744
 
@@ -1666,7 +1761,9 @@ static int merge_normalize_opts(
1666
1761
  opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
1667
1762
  }
1668
1763
 
1669
- return 0;
1764
+ done:
1765
+ git_config_entry_free(entry);
1766
+ return error;
1670
1767
  }
1671
1768
 
1672
1769
 
@@ -1878,7 +1975,7 @@ int git_merge__iterators(
1878
1975
  int resolved = 0;
1879
1976
 
1880
1977
  if ((error = merge_conflict_resolve(
1881
- &resolved, diff_list, conflict, &file_opts)) < 0)
1978
+ &resolved, diff_list, conflict, &opts, &file_opts)) < 0)
1882
1979
  goto done;
1883
1980
 
1884
1981
  if (!resolved) {
@@ -1899,6 +1996,8 @@ done:
1899
1996
  if (!given_opts || !given_opts->metric)
1900
1997
  git__free(opts.metric);
1901
1998
 
1999
+ git__free((char *)opts.default_driver);
2000
+
1902
2001
  git_merge_diff_list__free(diff_list);
1903
2002
  git_iterator_free(empty_ancestor);
1904
2003
  git_iterator_free(empty_ours);
@@ -2111,14 +2210,14 @@ static int merge_annotated_commits(
2111
2210
  git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2112
2211
  int error;
2113
2212
 
2114
- if ((error = compute_base(&base, repo, ours, theirs, opts,
2213
+ if ((error = compute_base(&base, repo, ours, theirs, opts,
2115
2214
  recursion_level)) < 0) {
2116
2215
 
2117
- if (error != GIT_ENOTFOUND)
2118
- goto done;
2216
+ if (error != GIT_ENOTFOUND)
2217
+ goto done;
2119
2218
 
2120
- giterr_clear();
2121
- }
2219
+ giterr_clear();
2220
+ }
2122
2221
 
2123
2222
  if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
2124
2223
  (error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
@@ -12,8 +12,9 @@
12
12
  #include "pool.h"
13
13
  #include "iterator.h"
14
14
 
15
- #include "git2/merge.h"
16
15
  #include "git2/types.h"
16
+ #include "git2/merge.h"
17
+ #include "git2/sys/merge.h"
17
18
 
18
19
  #define GIT_MERGE_MSG_FILE "MERGE_MSG"
19
20
  #define GIT_MERGE_MODE_FILE "MERGE_MODE"
@@ -22,6 +23,19 @@
22
23
  #define GIT_MERGE_DEFAULT_RENAME_THRESHOLD 50
23
24
  #define GIT_MERGE_DEFAULT_TARGET_LIMIT 1000
24
25
 
26
+
27
+ /** Internal merge flags. */
28
+ enum {
29
+ /** The merge is for a virtual base in a recursive merge. */
30
+ GIT_MERGE__VIRTUAL_BASE = (1 << 31),
31
+ };
32
+
33
+ enum {
34
+ /** Accept the conflict file, staging it as the merge result. */
35
+ GIT_MERGE_FILE_FAVOR__CONFLICTED = 4,
36
+ };
37
+
38
+
25
39
  /** Types of changes when files are merged from branch to branch. */
26
40
  typedef enum {
27
41
  /* No conflict - a change only occurs in one branch. */
@@ -70,7 +84,6 @@ typedef enum {
70
84
  GIT_MERGE_DIFF_DF_CHILD = (1 << 11),
71
85
  } git_merge_diff_type_t;
72
86
 
73
-
74
87
  typedef struct {
75
88
  git_repository *repo;
76
89
  git_pool pool;
@@ -152,4 +165,50 @@ int git_merge__check_result(git_repository *repo, git_index *index_new);
152
165
 
153
166
  int git_merge__append_conflicts_to_merge_msg(git_repository *repo, git_index *index);
154
167
 
168
+ /* Merge files */
169
+
170
+ GIT_INLINE(const char *) git_merge_file__best_path(
171
+ const char *ancestor,
172
+ const char *ours,
173
+ const char *theirs)
174
+ {
175
+ if (!ancestor) {
176
+ if (ours && theirs && strcmp(ours, theirs) == 0)
177
+ return ours;
178
+
179
+ return NULL;
180
+ }
181
+
182
+ if (ours && strcmp(ancestor, ours) == 0)
183
+ return theirs;
184
+ else if(theirs && strcmp(ancestor, theirs) == 0)
185
+ return ours;
186
+
187
+ return NULL;
188
+ }
189
+
190
+ GIT_INLINE(uint32_t) git_merge_file__best_mode(
191
+ uint32_t ancestor, uint32_t ours, uint32_t theirs)
192
+ {
193
+ /*
194
+ * If ancestor didn't exist and either ours or theirs is executable,
195
+ * assume executable. Otherwise, if any mode changed from the ancestor,
196
+ * use that one.
197
+ */
198
+ if (!ancestor) {
199
+ if (ours == GIT_FILEMODE_BLOB_EXECUTABLE ||
200
+ theirs == GIT_FILEMODE_BLOB_EXECUTABLE)
201
+ return GIT_FILEMODE_BLOB_EXECUTABLE;
202
+
203
+ return GIT_FILEMODE_BLOB;
204
+ } else if (ours && theirs) {
205
+ if (ancestor == ours)
206
+ return theirs;
207
+
208
+ return ours;
209
+ }
210
+
211
+ return 0;
212
+ }
213
+
155
214
  #endif