rugged 0.19.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (668) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/README.md +184 -33
  4. data/ext/rugged/extconf.rb +111 -28
  5. data/ext/rugged/rugged.c +327 -89
  6. data/ext/rugged/rugged.h +64 -28
  7. data/ext/rugged/rugged_allocator.c +89 -0
  8. data/ext/rugged/rugged_backend.c +17 -0
  9. data/ext/rugged/rugged_blame.c +278 -0
  10. data/ext/rugged/rugged_blob.c +301 -75
  11. data/ext/rugged/rugged_branch.c +92 -242
  12. data/ext/rugged/rugged_branch_collection.c +388 -0
  13. data/ext/rugged/rugged_commit.c +575 -79
  14. data/ext/rugged/rugged_config.c +129 -36
  15. data/ext/rugged/rugged_cred.c +131 -0
  16. data/ext/rugged/rugged_diff.c +291 -122
  17. data/ext/rugged/rugged_diff_delta.c +16 -22
  18. data/ext/rugged/rugged_diff_hunk.c +35 -51
  19. data/ext/rugged/rugged_diff_line.c +23 -36
  20. data/ext/rugged/rugged_index.c +289 -152
  21. data/ext/rugged/rugged_note.c +50 -60
  22. data/ext/rugged/rugged_object.c +13 -30
  23. data/ext/rugged/rugged_patch.c +400 -0
  24. data/ext/rugged/rugged_rebase.c +397 -0
  25. data/ext/rugged/rugged_reference.c +76 -346
  26. data/ext/rugged/rugged_reference_collection.c +423 -0
  27. data/ext/rugged/rugged_remote.c +438 -461
  28. data/ext/rugged/rugged_remote_collection.c +435 -0
  29. data/ext/rugged/rugged_repo.c +1548 -365
  30. data/ext/rugged/rugged_revwalk.c +378 -99
  31. data/ext/rugged/rugged_settings.c +86 -23
  32. data/ext/rugged/rugged_signature.c +47 -37
  33. data/ext/rugged/rugged_submodule.c +835 -0
  34. data/ext/rugged/rugged_submodule_collection.c +366 -0
  35. data/ext/rugged/rugged_tag.c +88 -210
  36. data/ext/rugged/rugged_tag_collection.c +326 -0
  37. data/ext/rugged/rugged_tree.c +460 -217
  38. data/lib/rugged/attributes.rb +46 -0
  39. data/lib/rugged/blob.rb +33 -0
  40. data/lib/rugged/branch.rb +12 -16
  41. data/lib/rugged/commit.rb +9 -0
  42. data/lib/rugged/console.rb +5 -0
  43. data/lib/rugged/credentials.rb +48 -0
  44. data/lib/rugged/diff/delta.rb +6 -2
  45. data/lib/rugged/diff/hunk.rb +9 -9
  46. data/lib/rugged/diff/line.rb +28 -5
  47. data/lib/rugged/diff.rb +7 -1
  48. data/lib/rugged/index.rb +120 -0
  49. data/lib/rugged/object.rb +5 -0
  50. data/lib/rugged/patch.rb +41 -0
  51. data/lib/rugged/reference.rb +6 -3
  52. data/lib/rugged/remote.rb +5 -9
  53. data/lib/rugged/repository.rb +126 -14
  54. data/lib/rugged/submodule_collection.rb +53 -0
  55. data/lib/rugged/tag.rb +45 -16
  56. data/lib/rugged/tree.rb +163 -1
  57. data/lib/rugged/version.rb +6 -1
  58. data/lib/rugged/walker.rb +5 -0
  59. data/lib/rugged.rb +16 -1
  60. data/vendor/libgit2/AUTHORS +77 -0
  61. data/vendor/libgit2/CMakeLists.txt +317 -0
  62. data/vendor/libgit2/COPYING +993 -0
  63. data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +30 -0
  64. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.c.in +29 -0
  65. data/vendor/libgit2/cmake/Modules/CheckPrototypeDefinition.cmake +96 -0
  66. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +11 -0
  67. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +26 -0
  68. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  69. data/vendor/libgit2/cmake/Modules/FindHTTP_Parser.cmake +39 -0
  70. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +45 -0
  71. data/vendor/libgit2/cmake/Modules/FindPkgLibraries.cmake +28 -0
  72. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +28 -0
  73. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +20 -0
  74. data/vendor/libgit2/cmake/Modules/FindmbedTLS.cmake +93 -0
  75. data/vendor/libgit2/cmake/Modules/IdeSplitSources.cmake +22 -0
  76. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +5 -0
  77. data/vendor/libgit2/deps/http-parser/COPYING +23 -0
  78. data/vendor/libgit2/deps/http-parser/http_parser.c +5 -2
  79. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  80. data/vendor/libgit2/deps/regex/CMakeLists.txt +2 -0
  81. data/vendor/libgit2/deps/regex/COPYING +502 -0
  82. data/vendor/libgit2/deps/regex/regex.c +10 -3
  83. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +26 -0
  84. data/vendor/libgit2/deps/winhttp/COPYING.GPL +993 -0
  85. data/vendor/libgit2/deps/winhttp/COPYING.LGPL +502 -0
  86. data/vendor/libgit2/deps/winhttp/urlmon.h +45 -0
  87. data/vendor/libgit2/deps/winhttp/winhttp.def +29 -0
  88. data/vendor/libgit2/deps/winhttp/winhttp.h +594 -0
  89. data/vendor/libgit2/deps/winhttp/winhttp64.def +29 -0
  90. data/vendor/libgit2/deps/zlib/CMakeLists.txt +5 -0
  91. data/vendor/libgit2/deps/zlib/COPYING +27 -0
  92. data/vendor/libgit2/deps/zlib/adler32.c +51 -34
  93. data/vendor/libgit2/deps/zlib/crc32.c +61 -61
  94. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  95. data/vendor/libgit2/deps/zlib/deflate.c +681 -352
  96. data/vendor/libgit2/deps/zlib/deflate.h +25 -18
  97. data/vendor/libgit2/deps/zlib/gzguts.h +218 -0
  98. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  99. data/vendor/libgit2/deps/zlib/inffast.c +36 -53
  100. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  101. data/vendor/libgit2/deps/zlib/inflate.c +167 -86
  102. data/vendor/libgit2/deps/zlib/inflate.h +7 -4
  103. data/vendor/libgit2/deps/zlib/inftrees.c +24 -50
  104. data/vendor/libgit2/deps/zlib/trees.c +55 -96
  105. data/vendor/libgit2/deps/zlib/zconf.h +499 -19
  106. data/vendor/libgit2/deps/zlib/zlib.h +526 -227
  107. data/vendor/libgit2/deps/zlib/zutil.c +39 -32
  108. data/vendor/libgit2/deps/zlib/zutil.h +75 -78
  109. data/vendor/libgit2/include/git2/annotated_commit.h +125 -0
  110. data/vendor/libgit2/include/git2/apply.h +129 -0
  111. data/vendor/libgit2/include/git2/attr.h +36 -21
  112. data/vendor/libgit2/include/git2/blame.h +229 -0
  113. data/vendor/libgit2/include/git2/blob.h +81 -44
  114. data/vendor/libgit2/include/git2/branch.h +81 -42
  115. data/vendor/libgit2/include/git2/buffer.h +128 -0
  116. data/vendor/libgit2/include/git2/checkout.h +141 -67
  117. data/vendor/libgit2/include/git2/cherrypick.h +92 -0
  118. data/vendor/libgit2/include/git2/clone.h +157 -58
  119. data/vendor/libgit2/include/git2/commit.h +231 -12
  120. data/vendor/libgit2/include/git2/common.h +216 -30
  121. data/vendor/libgit2/include/git2/config.h +274 -48
  122. data/vendor/libgit2/include/git2/cred_helpers.h +4 -4
  123. data/vendor/libgit2/include/git2/deprecated.h +253 -0
  124. data/vendor/libgit2/include/git2/describe.h +189 -0
  125. data/vendor/libgit2/include/git2/diff.h +985 -575
  126. data/vendor/libgit2/include/git2/errors.h +93 -52
  127. data/vendor/libgit2/include/git2/filter.h +217 -0
  128. data/vendor/libgit2/include/git2/global.h +44 -0
  129. data/vendor/libgit2/include/git2/graph.h +17 -0
  130. data/vendor/libgit2/include/git2/ignore.h +2 -2
  131. data/vendor/libgit2/include/git2/index.h +269 -94
  132. data/vendor/libgit2/include/git2/indexer.h +44 -12
  133. data/vendor/libgit2/include/git2/mailmap.h +115 -0
  134. data/vendor/libgit2/include/git2/merge.h +501 -64
  135. data/vendor/libgit2/include/git2/message.h +52 -17
  136. data/vendor/libgit2/include/git2/net.h +11 -5
  137. data/vendor/libgit2/include/git2/notes.h +120 -16
  138. data/vendor/libgit2/include/git2/object.h +62 -23
  139. data/vendor/libgit2/include/git2/odb.h +140 -24
  140. data/vendor/libgit2/include/git2/odb_backend.h +56 -12
  141. data/vendor/libgit2/include/git2/oid.h +17 -18
  142. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  143. data/vendor/libgit2/include/git2/pack.h +86 -7
  144. data/vendor/libgit2/include/git2/patch.h +274 -0
  145. data/vendor/libgit2/include/git2/pathspec.h +280 -0
  146. data/vendor/libgit2/include/git2/proxy.h +96 -0
  147. data/vendor/libgit2/include/git2/rebase.h +323 -0
  148. data/vendor/libgit2/include/git2/reflog.h +12 -9
  149. data/vendor/libgit2/include/git2/refs.h +241 -46
  150. data/vendor/libgit2/include/git2/refspec.h +20 -4
  151. data/vendor/libgit2/include/git2/remote.h +636 -209
  152. data/vendor/libgit2/include/git2/repository.h +267 -57
  153. data/vendor/libgit2/include/git2/reset.h +36 -6
  154. data/vendor/libgit2/include/git2/revert.h +91 -0
  155. data/vendor/libgit2/include/git2/revparse.h +27 -16
  156. data/vendor/libgit2/include/git2/revwalk.h +78 -35
  157. data/vendor/libgit2/include/git2/signature.h +32 -5
  158. data/vendor/libgit2/include/git2/stash.h +160 -21
  159. data/vendor/libgit2/include/git2/status.h +92 -30
  160. data/vendor/libgit2/include/git2/submodule.h +226 -133
  161. data/vendor/libgit2/include/git2/sys/alloc.h +101 -0
  162. data/vendor/libgit2/include/git2/sys/commit.h +38 -4
  163. data/vendor/libgit2/include/git2/sys/config.h +68 -9
  164. data/vendor/libgit2/include/git2/sys/diff.h +94 -0
  165. data/vendor/libgit2/include/git2/sys/filter.h +332 -0
  166. data/vendor/libgit2/include/git2/sys/hashsig.h +106 -0
  167. data/vendor/libgit2/include/git2/sys/index.h +6 -5
  168. data/vendor/libgit2/include/git2/sys/mempack.h +86 -0
  169. data/vendor/libgit2/include/git2/sys/merge.h +182 -0
  170. data/vendor/libgit2/include/git2/sys/odb_backend.h +66 -28
  171. data/vendor/libgit2/include/git2/sys/openssl.h +38 -0
  172. data/vendor/libgit2/include/git2/sys/path.h +64 -0
  173. data/vendor/libgit2/include/git2/sys/refdb_backend.h +79 -19
  174. data/vendor/libgit2/include/git2/sys/reflog.h +21 -0
  175. data/vendor/libgit2/include/git2/sys/refs.h +13 -2
  176. data/vendor/libgit2/include/git2/sys/repository.h +64 -1
  177. data/vendor/libgit2/include/git2/sys/stream.h +138 -0
  178. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  179. data/vendor/libgit2/include/git2/sys/transport.h +439 -0
  180. data/vendor/libgit2/include/git2/tag.h +11 -2
  181. data/vendor/libgit2/include/git2/trace.h +1 -1
  182. data/vendor/libgit2/include/git2/transaction.h +121 -0
  183. data/vendor/libgit2/include/git2/transport.h +261 -292
  184. data/vendor/libgit2/include/git2/tree.h +111 -21
  185. data/vendor/libgit2/include/git2/types.h +244 -32
  186. data/vendor/libgit2/include/git2/version.h +5 -2
  187. data/vendor/libgit2/include/git2/worktree.h +255 -0
  188. data/vendor/libgit2/include/git2.h +50 -40
  189. data/vendor/libgit2/libgit2.pc.in +13 -0
  190. data/vendor/libgit2/src/CMakeLists.txt +525 -0
  191. data/vendor/libgit2/src/alloc.c +55 -0
  192. data/vendor/libgit2/src/alloc.h +40 -0
  193. data/vendor/libgit2/src/annotated_commit.c +228 -0
  194. data/vendor/libgit2/src/annotated_commit.h +52 -0
  195. data/vendor/libgit2/src/apply.c +855 -0
  196. data/vendor/libgit2/src/apply.h +25 -0
  197. data/vendor/libgit2/src/array.h +74 -16
  198. data/vendor/libgit2/src/attr.c +239 -408
  199. data/vendor/libgit2/src/attr.h +3 -33
  200. data/vendor/libgit2/src/attr_file.c +424 -156
  201. data/vendor/libgit2/src/attr_file.h +95 -23
  202. data/vendor/libgit2/src/attrcache.c +469 -0
  203. data/vendor/libgit2/src/attrcache.h +37 -5
  204. data/vendor/libgit2/src/bitvec.h +75 -0
  205. data/vendor/libgit2/src/blame.c +532 -0
  206. data/vendor/libgit2/src/blame.h +95 -0
  207. data/vendor/libgit2/src/blame_git.c +668 -0
  208. data/vendor/libgit2/src/blame_git.h +22 -0
  209. data/vendor/libgit2/src/blob.c +233 -129
  210. data/vendor/libgit2/src/blob.h +29 -1
  211. data/vendor/libgit2/src/branch.c +295 -197
  212. data/vendor/libgit2/src/branch.h +2 -0
  213. data/vendor/libgit2/src/buf_text.c +52 -27
  214. data/vendor/libgit2/src/buf_text.h +7 -7
  215. data/vendor/libgit2/src/buffer.c +609 -52
  216. data/vendor/libgit2/src/buffer.h +68 -23
  217. data/vendor/libgit2/src/cache.c +48 -51
  218. data/vendor/libgit2/src/cache.h +6 -4
  219. data/vendor/libgit2/src/cc-compat.h +35 -7
  220. data/vendor/libgit2/src/checkout.c +1827 -483
  221. data/vendor/libgit2/src/checkout.h +4 -1
  222. data/vendor/libgit2/src/cherrypick.c +230 -0
  223. data/vendor/libgit2/src/clone.c +338 -258
  224. data/vendor/libgit2/src/{compress.h → clone.h} +5 -5
  225. data/vendor/libgit2/src/commit.c +711 -124
  226. data/vendor/libgit2/src/commit.h +10 -3
  227. data/vendor/libgit2/src/commit_list.c +21 -14
  228. data/vendor/libgit2/src/commit_list.h +9 -3
  229. data/vendor/libgit2/src/common.h +153 -13
  230. data/vendor/libgit2/src/config.c +871 -242
  231. data/vendor/libgit2/src/config.h +58 -14
  232. data/vendor/libgit2/src/config_backend.h +84 -0
  233. data/vendor/libgit2/src/config_cache.c +44 -18
  234. data/vendor/libgit2/src/config_entries.c +259 -0
  235. data/vendor/libgit2/src/config_entries.h +23 -0
  236. data/vendor/libgit2/src/config_file.c +837 -1113
  237. data/vendor/libgit2/src/config_mem.c +224 -0
  238. data/vendor/libgit2/src/config_parse.c +558 -0
  239. data/vendor/libgit2/src/config_parse.h +64 -0
  240. data/vendor/libgit2/src/crlf.c +290 -195
  241. data/vendor/libgit2/src/date.c +35 -7
  242. data/vendor/libgit2/src/delta.c +275 -71
  243. data/vendor/libgit2/src/delta.h +80 -58
  244. data/vendor/libgit2/src/describe.c +893 -0
  245. data/vendor/libgit2/src/diff.c +330 -1128
  246. data/vendor/libgit2/src/diff.h +25 -67
  247. data/vendor/libgit2/src/diff_driver.c +225 -109
  248. data/vendor/libgit2/src/diff_driver.h +5 -2
  249. data/vendor/libgit2/src/diff_file.c +128 -103
  250. data/vendor/libgit2/src/diff_file.h +17 -12
  251. data/vendor/libgit2/src/diff_generate.c +1622 -0
  252. data/vendor/libgit2/src/diff_generate.h +128 -0
  253. data/vendor/libgit2/src/diff_parse.c +108 -0
  254. data/vendor/libgit2/src/diff_parse.h +20 -0
  255. data/vendor/libgit2/src/diff_print.c +578 -218
  256. data/vendor/libgit2/src/diff_stats.c +362 -0
  257. data/vendor/libgit2/src/diff_tform.c +429 -257
  258. data/vendor/libgit2/src/diff_tform.h +25 -0
  259. data/vendor/libgit2/src/diff_xdiff.c +143 -46
  260. data/vendor/libgit2/src/diff_xdiff.h +12 -5
  261. data/vendor/libgit2/src/errors.c +150 -34
  262. data/vendor/libgit2/src/features.h.in +37 -0
  263. data/vendor/libgit2/src/fetch.c +69 -46
  264. data/vendor/libgit2/src/fetch.h +6 -12
  265. data/vendor/libgit2/src/fetchhead.c +40 -33
  266. data/vendor/libgit2/src/fetchhead.h +5 -4
  267. data/vendor/libgit2/src/filebuf.c +163 -61
  268. data/vendor/libgit2/src/filebuf.h +13 -7
  269. data/vendor/libgit2/src/fileops.c +549 -407
  270. data/vendor/libgit2/src/fileops.h +97 -106
  271. data/vendor/libgit2/src/filter.c +989 -46
  272. data/vendor/libgit2/src/filter.h +21 -70
  273. data/vendor/libgit2/src/fnmatch.c +67 -11
  274. data/vendor/libgit2/src/fnmatch.h +27 -7
  275. data/vendor/libgit2/src/global.c +257 -63
  276. data/vendor/libgit2/src/global.h +19 -0
  277. data/vendor/libgit2/src/graph.c +39 -23
  278. data/vendor/libgit2/src/hash/hash_collisiondetect.h +51 -0
  279. data/vendor/libgit2/src/hash/hash_common_crypto.h +61 -0
  280. data/vendor/libgit2/src/hash/hash_generic.c +3 -3
  281. data/vendor/libgit2/src/hash/hash_generic.h +10 -5
  282. data/vendor/libgit2/src/hash/hash_mbedtls.c +38 -0
  283. data/vendor/libgit2/src/hash/hash_mbedtls.h +24 -0
  284. data/vendor/libgit2/src/hash/hash_openssl.h +26 -8
  285. data/vendor/libgit2/src/hash/hash_win32.c +71 -43
  286. data/vendor/libgit2/src/hash/hash_win32.h +4 -3
  287. data/vendor/libgit2/src/hash/sha1dc/sha1.c +1900 -0
  288. data/vendor/libgit2/src/hash/sha1dc/sha1.h +110 -0
  289. data/vendor/libgit2/src/hash/sha1dc/ubc_check.c +372 -0
  290. data/vendor/libgit2/src/hash/sha1dc/ubc_check.h +52 -0
  291. data/vendor/libgit2/src/hash.c +0 -1
  292. data/vendor/libgit2/src/hash.h +13 -6
  293. data/vendor/libgit2/src/hashsig.c +121 -126
  294. data/vendor/libgit2/src/ident.c +129 -0
  295. data/vendor/libgit2/src/idxmap.c +153 -0
  296. data/vendor/libgit2/src/idxmap.h +41 -0
  297. data/vendor/libgit2/src/ignore.c +362 -123
  298. data/vendor/libgit2/src/ignore.h +16 -4
  299. data/vendor/libgit2/src/index.c +2131 -692
  300. data/vendor/libgit2/src/index.h +138 -6
  301. data/vendor/libgit2/src/indexer.c +866 -266
  302. data/vendor/libgit2/src/indexer.h +16 -0
  303. data/vendor/libgit2/src/integer.h +106 -0
  304. data/vendor/libgit2/src/iterator.c +1888 -967
  305. data/vendor/libgit2/src/iterator.h +130 -67
  306. data/vendor/libgit2/src/khash.h +43 -29
  307. data/vendor/libgit2/src/mailmap.c +485 -0
  308. data/vendor/libgit2/src/mailmap.h +35 -0
  309. data/vendor/libgit2/src/map.h +1 -1
  310. data/vendor/libgit2/src/merge.c +1679 -479
  311. data/vendor/libgit2/src/merge.h +89 -22
  312. data/vendor/libgit2/src/merge_driver.c +426 -0
  313. data/vendor/libgit2/src/merge_driver.h +62 -0
  314. data/vendor/libgit2/src/merge_file.c +238 -101
  315. data/vendor/libgit2/src/message.c +4 -28
  316. data/vendor/libgit2/src/message.h +3 -1
  317. data/vendor/libgit2/src/mwindow.c +123 -15
  318. data/vendor/libgit2/src/mwindow.h +10 -1
  319. data/vendor/libgit2/src/netops.c +178 -499
  320. data/vendor/libgit2/src/netops.h +51 -27
  321. data/vendor/libgit2/src/notes.c +251 -94
  322. data/vendor/libgit2/src/notes.h +5 -2
  323. data/vendor/libgit2/src/object.c +253 -67
  324. data/vendor/libgit2/src/object.h +40 -2
  325. data/vendor/libgit2/src/object_api.c +30 -11
  326. data/vendor/libgit2/src/odb.c +765 -201
  327. data/vendor/libgit2/src/odb.h +40 -8
  328. data/vendor/libgit2/src/odb_loose.c +560 -346
  329. data/vendor/libgit2/src/odb_mempack.c +185 -0
  330. data/vendor/libgit2/src/odb_pack.c +117 -73
  331. data/vendor/libgit2/src/offmap.c +113 -0
  332. data/vendor/libgit2/src/offmap.h +32 -42
  333. data/vendor/libgit2/src/oid.c +45 -25
  334. data/vendor/libgit2/src/oid.h +26 -8
  335. data/vendor/libgit2/src/oidarray.c +34 -0
  336. data/vendor/libgit2/src/oidarray.h +20 -0
  337. data/vendor/libgit2/src/oidmap.c +125 -0
  338. data/vendor/libgit2/src/oidmap.h +30 -17
  339. data/vendor/libgit2/src/pack-objects.c +688 -265
  340. data/vendor/libgit2/src/pack-objects.h +27 -13
  341. data/vendor/libgit2/src/pack.c +418 -202
  342. data/vendor/libgit2/src/pack.h +25 -16
  343. data/vendor/libgit2/src/parse.c +124 -0
  344. data/vendor/libgit2/src/parse.h +61 -0
  345. data/vendor/libgit2/src/patch.c +223 -0
  346. data/vendor/libgit2/src/patch.h +68 -0
  347. data/vendor/libgit2/src/patch_generate.c +901 -0
  348. data/vendor/libgit2/src/patch_generate.h +69 -0
  349. data/vendor/libgit2/src/patch_parse.c +1136 -0
  350. data/vendor/libgit2/src/patch_parse.h +51 -0
  351. data/vendor/libgit2/src/path.c +1247 -241
  352. data/vendor/libgit2/src/path.h +353 -57
  353. data/vendor/libgit2/src/pathspec.c +586 -58
  354. data/vendor/libgit2/src/pathspec.h +37 -15
  355. data/vendor/libgit2/src/pool.c +134 -221
  356. data/vendor/libgit2/src/pool.h +38 -50
  357. data/vendor/libgit2/src/posix.c +76 -10
  358. data/vendor/libgit2/src/posix.h +74 -32
  359. data/vendor/libgit2/src/pqueue.c +79 -117
  360. data/vendor/libgit2/src/pqueue.h +38 -82
  361. data/vendor/libgit2/src/proxy.c +39 -0
  362. data/vendor/libgit2/src/proxy.h +17 -0
  363. data/vendor/libgit2/src/push.c +178 -279
  364. data/vendor/libgit2/src/push.h +93 -4
  365. data/vendor/libgit2/src/reader.c +265 -0
  366. data/vendor/libgit2/src/reader.h +107 -0
  367. data/vendor/libgit2/src/rebase.c +1364 -0
  368. data/vendor/libgit2/src/refdb.c +74 -19
  369. data/vendor/libgit2/src/refdb.h +16 -3
  370. data/vendor/libgit2/src/refdb_fs.c +1472 -603
  371. data/vendor/libgit2/src/refdb_fs.h +4 -0
  372. data/vendor/libgit2/src/reflog.c +40 -330
  373. data/vendor/libgit2/src/reflog.h +8 -2
  374. data/vendor/libgit2/src/refs.c +641 -225
  375. data/vendor/libgit2/src/refs.h +53 -6
  376. data/vendor/libgit2/src/refspec.c +175 -62
  377. data/vendor/libgit2/src/refspec.h +10 -25
  378. data/vendor/libgit2/src/remote.c +1741 -723
  379. data/vendor/libgit2/src/remote.h +17 -5
  380. data/vendor/libgit2/src/repository.c +1505 -421
  381. data/vendor/libgit2/src/repository.h +95 -15
  382. data/vendor/libgit2/src/reset.c +63 -26
  383. data/vendor/libgit2/src/revert.c +232 -0
  384. data/vendor/libgit2/src/revparse.c +94 -80
  385. data/vendor/libgit2/src/revwalk.c +427 -194
  386. data/vendor/libgit2/src/revwalk.h +14 -5
  387. data/vendor/libgit2/src/settings.c +290 -0
  388. data/vendor/libgit2/src/sha1_lookup.c +16 -159
  389. data/vendor/libgit2/src/sha1_lookup.h +5 -4
  390. data/vendor/libgit2/src/signature.c +138 -26
  391. data/vendor/libgit2/src/signature.h +5 -0
  392. data/vendor/libgit2/src/sortedcache.c +395 -0
  393. data/vendor/libgit2/src/sortedcache.h +180 -0
  394. data/vendor/libgit2/src/stash.c +629 -168
  395. data/vendor/libgit2/src/status.c +125 -75
  396. data/vendor/libgit2/src/status.h +4 -2
  397. data/vendor/libgit2/src/stdalloc.c +120 -0
  398. data/vendor/libgit2/src/stdalloc.h +17 -0
  399. data/vendor/libgit2/src/stream.h +86 -0
  400. data/vendor/libgit2/src/streams/mbedtls.c +483 -0
  401. data/vendor/libgit2/src/streams/mbedtls.h +23 -0
  402. data/vendor/libgit2/src/streams/openssl.c +789 -0
  403. data/vendor/libgit2/src/streams/openssl.h +23 -0
  404. data/vendor/libgit2/src/streams/registry.c +118 -0
  405. data/vendor/libgit2/src/streams/registry.h +19 -0
  406. data/vendor/libgit2/src/streams/socket.c +235 -0
  407. data/vendor/libgit2/src/streams/socket.h +23 -0
  408. data/vendor/libgit2/src/streams/stransport.c +323 -0
  409. data/vendor/libgit2/src/streams/stransport.h +21 -0
  410. data/vendor/libgit2/src/streams/tls.c +73 -0
  411. data/vendor/libgit2/src/streams/tls.h +31 -0
  412. data/vendor/libgit2/src/strmap.c +147 -0
  413. data/vendor/libgit2/src/strmap.h +46 -51
  414. data/vendor/libgit2/src/strnlen.h +24 -0
  415. data/vendor/libgit2/src/submodule.c +1633 -877
  416. data/vendor/libgit2/src/submodule.h +83 -21
  417. data/vendor/libgit2/src/sysdir.c +355 -0
  418. data/vendor/libgit2/src/sysdir.h +119 -0
  419. data/vendor/libgit2/src/tag.c +87 -62
  420. data/vendor/libgit2/src/tag.h +4 -1
  421. data/vendor/libgit2/src/thread-utils.c +3 -0
  422. data/vendor/libgit2/src/thread-utils.h +71 -35
  423. data/vendor/libgit2/src/trace.c +4 -4
  424. data/vendor/libgit2/src/trace.h +11 -3
  425. data/vendor/libgit2/src/trailer.c +416 -0
  426. data/vendor/libgit2/src/transaction.c +382 -0
  427. data/vendor/libgit2/src/transaction.h +14 -0
  428. data/vendor/libgit2/src/transport.c +133 -67
  429. data/vendor/libgit2/src/transports/auth.c +75 -0
  430. data/vendor/libgit2/src/transports/auth.h +64 -0
  431. data/vendor/libgit2/src/transports/auth_negotiate.c +277 -0
  432. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  433. data/vendor/libgit2/src/transports/cred.c +296 -68
  434. data/vendor/libgit2/src/transports/cred.h +16 -0
  435. data/vendor/libgit2/src/transports/cred_helpers.c +4 -0
  436. data/vendor/libgit2/src/transports/git.c +108 -90
  437. data/vendor/libgit2/src/transports/http.c +803 -258
  438. data/vendor/libgit2/src/transports/http.h +25 -0
  439. data/vendor/libgit2/src/transports/local.c +265 -169
  440. data/vendor/libgit2/src/transports/smart.c +255 -45
  441. data/vendor/libgit2/src/transports/smart.h +42 -22
  442. data/vendor/libgit2/src/transports/smart_pkt.c +250 -159
  443. data/vendor/libgit2/src/transports/smart_protocol.c +414 -196
  444. data/vendor/libgit2/src/transports/ssh.c +645 -236
  445. data/vendor/libgit2/src/transports/ssh.h +14 -0
  446. data/vendor/libgit2/src/transports/winhttp.c +809 -353
  447. data/vendor/libgit2/src/tree-cache.c +138 -52
  448. data/vendor/libgit2/src/tree-cache.h +14 -7
  449. data/vendor/libgit2/src/tree.c +620 -259
  450. data/vendor/libgit2/src/tree.h +12 -19
  451. data/vendor/libgit2/src/tsort.c +3 -2
  452. data/vendor/libgit2/src/unix/map.c +25 -7
  453. data/vendor/libgit2/src/unix/posix.h +77 -12
  454. data/vendor/libgit2/src/unix/pthread.h +56 -0
  455. data/vendor/libgit2/src/unix/realpath.c +12 -8
  456. data/vendor/libgit2/src/userdiff.h +208 -0
  457. data/vendor/libgit2/src/util.c +349 -165
  458. data/vendor/libgit2/src/util.h +167 -85
  459. data/vendor/libgit2/src/varint.c +43 -0
  460. data/vendor/libgit2/src/varint.h +17 -0
  461. data/vendor/libgit2/src/vector.c +156 -33
  462. data/vendor/libgit2/src/vector.h +41 -5
  463. data/vendor/libgit2/src/win32/dir.c +22 -42
  464. data/vendor/libgit2/src/win32/dir.h +7 -5
  465. data/vendor/libgit2/src/win32/error.c +6 -32
  466. data/vendor/libgit2/src/win32/error.h +4 -2
  467. data/vendor/libgit2/src/win32/findfile.c +62 -69
  468. data/vendor/libgit2/src/win32/findfile.h +5 -13
  469. data/vendor/libgit2/src/win32/git2.rc +44 -0
  470. data/vendor/libgit2/src/win32/map.c +39 -11
  471. data/vendor/libgit2/src/win32/mingw-compat.h +10 -11
  472. data/vendor/libgit2/src/win32/msvc-compat.h +10 -33
  473. data/vendor/libgit2/src/win32/path_w32.c +476 -0
  474. data/vendor/libgit2/src/win32/path_w32.h +104 -0
  475. data/vendor/libgit2/src/win32/posix.h +35 -30
  476. data/vendor/libgit2/src/win32/posix_w32.c +659 -327
  477. data/vendor/libgit2/src/win32/precompiled.h +7 -2
  478. data/vendor/libgit2/src/win32/reparse.h +57 -0
  479. data/vendor/libgit2/src/win32/thread.c +258 -0
  480. data/vendor/libgit2/src/win32/thread.h +64 -0
  481. data/vendor/libgit2/src/win32/utf-conv.c +127 -62
  482. data/vendor/libgit2/src/win32/utf-conv.h +47 -6
  483. data/vendor/libgit2/src/win32/version.h +21 -4
  484. data/vendor/libgit2/src/win32/w32_buffer.c +54 -0
  485. data/vendor/libgit2/src/win32/w32_buffer.h +20 -0
  486. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +438 -0
  487. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +129 -0
  488. data/vendor/libgit2/src/win32/w32_stack.c +193 -0
  489. data/vendor/libgit2/src/win32/w32_stack.h +140 -0
  490. data/vendor/libgit2/src/win32/w32_util.c +95 -0
  491. data/vendor/libgit2/src/win32/w32_util.h +170 -0
  492. data/vendor/libgit2/src/win32/win32-compat.h +52 -0
  493. data/vendor/libgit2/src/worktree.c +578 -0
  494. data/vendor/libgit2/src/worktree.h +39 -0
  495. data/vendor/libgit2/src/xdiff/xdiff.h +33 -18
  496. data/vendor/libgit2/src/xdiff/xdiffi.c +578 -88
  497. data/vendor/libgit2/src/xdiff/xdiffi.h +3 -2
  498. data/vendor/libgit2/src/xdiff/xemit.c +106 -45
  499. data/vendor/libgit2/src/xdiff/xemit.h +3 -3
  500. data/vendor/libgit2/src/xdiff/xhistogram.c +5 -4
  501. data/vendor/libgit2/src/xdiff/xinclude.h +3 -2
  502. data/vendor/libgit2/src/xdiff/xmacros.h +2 -2
  503. data/vendor/libgit2/src/xdiff/xmerge.c +167 -48
  504. data/vendor/libgit2/src/xdiff/xpatience.c +42 -10
  505. data/vendor/libgit2/src/xdiff/xprepare.c +14 -14
  506. data/vendor/libgit2/src/xdiff/xprepare.h +2 -2
  507. data/vendor/libgit2/src/xdiff/xtypes.h +2 -2
  508. data/vendor/libgit2/src/xdiff/xutils.c +60 -56
  509. data/vendor/libgit2/src/xdiff/xutils.h +3 -5
  510. data/vendor/libgit2/src/zstream.c +205 -0
  511. data/vendor/libgit2/src/zstream.h +53 -0
  512. metadata +281 -233
  513. data/Rakefile +0 -61
  514. data/ext/rugged/rugged_diff_patch.c +0 -169
  515. data/lib/rugged/diff/patch.rb +0 -28
  516. data/test/blob_test.rb +0 -341
  517. data/test/branch_test.rb +0 -199
  518. data/test/commit_test.rb +0 -104
  519. data/test/config_test.rb +0 -45
  520. data/test/coverage/cover.rb +0 -133
  521. data/test/diff_test.rb +0 -777
  522. data/test/errors_test.rb +0 -34
  523. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  524. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  525. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  526. data/test/fixtures/archive.tar.gz +0 -0
  527. data/test/fixtures/attr/attr0 +0 -1
  528. data/test/fixtures/attr/attr1 +0 -29
  529. data/test/fixtures/attr/attr2 +0 -21
  530. data/test/fixtures/attr/attr3 +0 -4
  531. data/test/fixtures/attr/binfile +0 -1
  532. data/test/fixtures/attr/dir/file +0 -0
  533. data/test/fixtures/attr/file +0 -1
  534. data/test/fixtures/attr/gitattributes +0 -29
  535. data/test/fixtures/attr/gitignore +0 -2
  536. data/test/fixtures/attr/ign +0 -1
  537. data/test/fixtures/attr/macro_bad +0 -1
  538. data/test/fixtures/attr/macro_test +0 -1
  539. data/test/fixtures/attr/root_test1 +0 -1
  540. data/test/fixtures/attr/root_test2 +0 -6
  541. data/test/fixtures/attr/root_test3 +0 -19
  542. data/test/fixtures/attr/root_test4.txt +0 -14
  543. data/test/fixtures/attr/sub/abc +0 -37
  544. data/test/fixtures/attr/sub/dir/file +0 -0
  545. data/test/fixtures/attr/sub/file +0 -1
  546. data/test/fixtures/attr/sub/ign/file +0 -1
  547. data/test/fixtures/attr/sub/ign/sub/file +0 -1
  548. data/test/fixtures/attr/sub/sub/dir +0 -0
  549. data/test/fixtures/attr/sub/sub/file +0 -1
  550. data/test/fixtures/attr/sub/sub/subsub.txt +0 -1
  551. data/test/fixtures/attr/sub/subdir_test1 +0 -2
  552. data/test/fixtures/attr/sub/subdir_test2.txt +0 -1
  553. data/test/fixtures/diff/another.txt +0 -38
  554. data/test/fixtures/diff/readme.txt +0 -36
  555. data/test/fixtures/mergedrepo/conflicts-one.txt +0 -5
  556. data/test/fixtures/mergedrepo/conflicts-two.txt +0 -5
  557. data/test/fixtures/mergedrepo/one.txt +0 -10
  558. data/test/fixtures/mergedrepo/two.txt +0 -12
  559. data/test/fixtures/status/current_file +0 -1
  560. data/test/fixtures/status/ignored_file +0 -1
  561. data/test/fixtures/status/modified_file +0 -2
  562. data/test/fixtures/status/new_file +0 -1
  563. data/test/fixtures/status/staged_changes +0 -2
  564. data/test/fixtures/status/staged_changes_modified_file +0 -3
  565. data/test/fixtures/status/staged_delete_modified_file +0 -1
  566. data/test/fixtures/status/staged_new_file +0 -1
  567. data/test/fixtures/status/staged_new_file_modified_file +0 -2
  568. data/test/fixtures/status/subdir/current_file +0 -1
  569. data/test/fixtures/status/subdir/modified_file +0 -2
  570. data/test/fixtures/status/subdir/new_file +0 -1
  571. data/test/fixtures/status/subdir.txt +0 -2
  572. data/test/fixtures/status//350/277/231 +0 -1
  573. data/test/fixtures/testrepo.git/HEAD +0 -1
  574. data/test/fixtures/testrepo.git/config +0 -13
  575. data/test/fixtures/testrepo.git/description +0 -1
  576. data/test/fixtures/testrepo.git/index +0 -0
  577. data/test/fixtures/testrepo.git/info/exclude +0 -6
  578. data/test/fixtures/testrepo.git/logs/HEAD +0 -3
  579. data/test/fixtures/testrepo.git/logs/refs/heads/master +0 -3
  580. data/test/fixtures/testrepo.git/logs/refs/notes/commits +0 -1
  581. data/test/fixtures/testrepo.git/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d +0 -0
  582. data/test/fixtures/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
  583. data/test/fixtures/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
  584. data/test/fixtures/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
  585. data/test/fixtures/testrepo.git/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 +0 -0
  586. data/test/fixtures/testrepo.git/objects/36/060c58702ed4c2a40832c51758d5344201d89a +0 -2
  587. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +0 -1
  588. data/test/fixtures/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
  589. data/test/fixtures/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +0 -2
  590. data/test/fixtures/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +0 -2
  591. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  592. data/test/fixtures/testrepo.git/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 +0 -0
  593. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +0 -1
  594. data/test/fixtures/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
  595. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  596. data/test/fixtures/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
  597. data/test/fixtures/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
  598. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  599. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  600. data/test/fixtures/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +0 -3
  601. data/test/fixtures/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +0 -2
  602. data/test/fixtures/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
  603. data/test/fixtures/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
  604. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +0 -3
  605. data/test/fixtures/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +0 -3
  606. data/test/fixtures/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +0 -3
  607. data/test/fixtures/testrepo.git/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b +0 -0
  608. data/test/fixtures/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  609. data/test/fixtures/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
  610. data/test/fixtures/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
  611. data/test/fixtures/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
  612. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
  613. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
  614. data/test/fixtures/testrepo.git/packed-refs +0 -2
  615. data/test/fixtures/testrepo.git/refs/heads/master +0 -1
  616. data/test/fixtures/testrepo.git/refs/notes/commits +0 -1
  617. data/test/fixtures/testrepo.git/refs/tags/v0.9 +0 -1
  618. data/test/fixtures/testrepo.git/refs/tags/v1.0 +0 -1
  619. data/test/fixtures/text_file.md +0 -464
  620. data/test/fixtures/unsymlinked.git/HEAD +0 -1
  621. data/test/fixtures/unsymlinked.git/config +0 -6
  622. data/test/fixtures/unsymlinked.git/description +0 -1
  623. data/test/fixtures/unsymlinked.git/info/exclude +0 -2
  624. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  625. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  626. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  627. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  628. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  629. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  630. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  631. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  632. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  633. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +0 -2
  634. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  635. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  636. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  637. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  638. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +0 -1
  639. data/test/fixtures/unsymlinked.git/refs/heads/master +0 -1
  640. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +0 -1
  641. data/test/index_test.rb +0 -333
  642. data/test/lib_test.rb +0 -127
  643. data/test/note_test.rb +0 -158
  644. data/test/object_test.rb +0 -43
  645. data/test/reference_test.rb +0 -207
  646. data/test/remote_test.rb +0 -324
  647. data/test/repo_pack_test.rb +0 -24
  648. data/test/repo_reset_test.rb +0 -82
  649. data/test/repo_test.rb +0 -402
  650. data/test/tag_test.rb +0 -68
  651. data/test/test_helper.rb +0 -92
  652. data/test/tree_test.rb +0 -91
  653. data/test/walker_test.rb +0 -88
  654. data/vendor/libgit2/Makefile.embed +0 -42
  655. data/vendor/libgit2/include/git2/push.h +0 -131
  656. data/vendor/libgit2/include/git2/threads.h +0 -50
  657. data/vendor/libgit2/src/amiga/map.c +0 -48
  658. data/vendor/libgit2/src/bswap.h +0 -97
  659. data/vendor/libgit2/src/compress.c +0 -53
  660. data/vendor/libgit2/src/config_file.h +0 -60
  661. data/vendor/libgit2/src/delta-apply.c +0 -134
  662. data/vendor/libgit2/src/delta-apply.h +0 -50
  663. data/vendor/libgit2/src/diff_patch.c +0 -995
  664. data/vendor/libgit2/src/diff_patch.h +0 -46
  665. data/vendor/libgit2/src/hashsig.h +0 -72
  666. data/vendor/libgit2/src/merge_file.h +0 -71
  667. data/vendor/libgit2/src/win32/pthread.c +0 -144
  668. data/vendor/libgit2/src/win32/pthread.h +0 -50
@@ -5,27 +5,35 @@
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
7
 
8
- #include "common.h"
8
+ #include "merge.h"
9
+
9
10
  #include "posix.h"
10
11
  #include "buffer.h"
11
12
  #include "repository.h"
12
13
  #include "revwalk.h"
13
14
  #include "commit_list.h"
14
- #include "merge.h"
15
15
  #include "path.h"
16
16
  #include "refs.h"
17
17
  #include "object.h"
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
- #include "merge_file.h"
24
25
  #include "blob.h"
25
- #include "hashsig.h"
26
26
  #include "oid.h"
27
27
  #include "index.h"
28
28
  #include "filebuf.h"
29
+ #include "config.h"
30
+ #include "oidarray.h"
31
+ #include "annotated_commit.h"
32
+ #include "commit.h"
33
+ #include "oidarray.h"
34
+ #include "merge_driver.h"
35
+ #include "oidmap.h"
36
+ #include "array.h"
29
37
 
30
38
  #include "git2/types.h"
31
39
  #include "git2/repository.h"
@@ -38,9 +46,14 @@
38
46
  #include "git2/signature.h"
39
47
  #include "git2/config.h"
40
48
  #include "git2/tree.h"
49
+ #include "git2/oidarray.h"
50
+ #include "git2/annotated_commit.h"
41
51
  #include "git2/sys/index.h"
52
+ #include "git2/sys/hashsig.h"
42
53
 
43
54
  #define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
55
+ #define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
56
+
44
57
 
45
58
  typedef enum {
46
59
  TREE_IDX_ANCESTOR = 0,
@@ -55,22 +68,19 @@ struct merge_diff_df_data {
55
68
  git_merge_diff *prev_conflict;
56
69
  };
57
70
 
58
-
59
71
  /* Merge base computation */
60
72
 
61
- int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_array[], size_t length)
73
+ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, size_t length, const git_oid input_array[])
62
74
  {
63
- git_revwalk *walk;
75
+ git_revwalk *walk = NULL;
64
76
  git_vector list;
65
77
  git_commit_list *result = NULL;
78
+ git_commit_list_node *commit;
66
79
  int error = -1;
67
80
  unsigned int i;
68
- git_commit_list_node *commit;
69
-
70
- assert(out && repo && input_array);
71
81
 
72
82
  if (length < 2) {
73
- giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %u.", length);
83
+ git_error_set(GIT_ERROR_INVALID, "at least two commits are required to find an ancestor");
74
84
  return -1;
75
85
  }
76
86
 
@@ -78,41 +88,121 @@ int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_
78
88
  return -1;
79
89
 
80
90
  if (git_revwalk_new(&walk, repo) < 0)
81
- goto cleanup;
91
+ goto on_error;
82
92
 
83
93
  for (i = 1; i < length; i++) {
84
94
  commit = git_revwalk__commit_lookup(walk, &input_array[i]);
85
95
  if (commit == NULL)
86
- goto cleanup;
96
+ goto on_error;
87
97
 
88
98
  git_vector_insert(&list, commit);
89
99
  }
90
100
 
91
101
  commit = git_revwalk__commit_lookup(walk, &input_array[0]);
92
102
  if (commit == NULL)
93
- goto cleanup;
103
+ goto on_error;
94
104
 
95
105
  if (git_merge__bases_many(&result, walk, commit, &list) < 0)
96
- goto cleanup;
106
+ goto on_error;
97
107
 
98
108
  if (!result) {
99
- giterr_set(GITERR_MERGE, "No merge base found");
109
+ git_error_set(GIT_ERROR_MERGE, "no merge base found");
100
110
  error = GIT_ENOTFOUND;
101
- goto cleanup;
111
+ goto on_error;
102
112
  }
103
113
 
114
+ *out = result;
115
+ *walk_out = walk;
116
+
117
+ git_vector_free(&list);
118
+ return 0;
119
+
120
+ on_error:
121
+ git_vector_free(&list);
122
+ git_revwalk_free(walk);
123
+ return error;
124
+ }
125
+
126
+ int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
127
+ {
128
+ git_revwalk *walk;
129
+ git_commit_list *result = NULL;
130
+ int error = 0;
131
+
132
+ assert(out && repo && input_array);
133
+
134
+ if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
135
+ return error;
136
+
104
137
  git_oid_cpy(out, &result->item->oid);
105
138
 
106
- error = 0;
139
+ git_commit_list_free(&result);
140
+ git_revwalk_free(walk);
141
+
142
+ return 0;
143
+ }
144
+
145
+ int git_merge_bases_many(git_oidarray *out, git_repository *repo, size_t length, const git_oid input_array[])
146
+ {
147
+ git_revwalk *walk;
148
+ git_commit_list *list, *result = NULL;
149
+ int error = 0;
150
+ git_array_oid_t array;
151
+
152
+ assert(out && repo && input_array);
153
+
154
+ if ((error = merge_bases_many(&result, &walk, repo, length, input_array)) < 0)
155
+ return error;
156
+
157
+ git_array_init(array);
158
+
159
+ list = result;
160
+ while (list) {
161
+ git_oid *id = git_array_alloc(array);
162
+ if (id == NULL) {
163
+ error = -1;
164
+ goto cleanup;
165
+ }
166
+
167
+ git_oid_cpy(id, &list->item->oid);
168
+ list = list->next;
169
+ }
170
+
171
+ git_oidarray__from_array(out, &array);
107
172
 
108
173
  cleanup:
109
174
  git_commit_list_free(&result);
110
175
  git_revwalk_free(walk);
111
- git_vector_free(&list);
176
+
112
177
  return error;
113
178
  }
114
179
 
115
- int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
180
+ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[])
181
+ {
182
+ git_oid result;
183
+ unsigned int i;
184
+ int error = -1;
185
+
186
+ assert(out && repo && input_array);
187
+
188
+ if (length < 2) {
189
+ git_error_set(GIT_ERROR_INVALID, "at least two commits are required to find an ancestor");
190
+ return -1;
191
+ }
192
+
193
+ result = input_array[0];
194
+ for (i = 1; i < length; i++) {
195
+ error = git_merge_base(&result, repo, &result, &input_array[i]);
196
+ if (error < 0)
197
+ return error;
198
+ }
199
+
200
+ *out = result;
201
+
202
+ return 0;
203
+ }
204
+
205
+ static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_repository *repo, const git_oid *one, const git_oid *two)
116
206
  {
117
207
  git_revwalk *walk;
118
208
  git_vector list;
@@ -142,27 +232,77 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const
142
232
 
143
233
  if (!result) {
144
234
  git_revwalk_free(walk);
145
- giterr_set(GITERR_MERGE, "No merge base found");
235
+ git_error_set(GIT_ERROR_MERGE, "no merge base found");
146
236
  return GIT_ENOTFOUND;
147
237
  }
148
238
 
239
+ *out = result;
240
+ *walk_out = walk;
241
+
242
+ return 0;
243
+
244
+ on_error:
245
+ git_revwalk_free(walk);
246
+ return -1;
247
+
248
+ }
249
+
250
+ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const git_oid *two)
251
+ {
252
+ int error;
253
+ git_revwalk *walk;
254
+ git_commit_list *result;
255
+
256
+ if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
257
+ return error;
258
+
149
259
  git_oid_cpy(out, &result->item->oid);
150
260
  git_commit_list_free(&result);
151
261
  git_revwalk_free(walk);
152
262
 
263
+ return 0;
264
+ }
265
+
266
+ int git_merge_bases(git_oidarray *out, git_repository *repo, const git_oid *one, const git_oid *two)
267
+ {
268
+ int error;
269
+ git_revwalk *walk;
270
+ git_commit_list *result, *list;
271
+ git_array_oid_t array;
272
+
273
+ git_array_init(array);
274
+
275
+ if ((error = merge_bases(&result, &walk, repo, one, two)) < 0)
276
+ return error;
277
+
278
+ list = result;
279
+ while (list) {
280
+ git_oid *id = git_array_alloc(array);
281
+ if (id == NULL)
282
+ goto on_error;
283
+
284
+ git_oid_cpy(id, &list->item->oid);
285
+ list = list->next;
286
+ }
287
+
288
+ git_oidarray__from_array(out, &array);
289
+ git_commit_list_free(&result);
290
+ git_revwalk_free(walk);
291
+
153
292
  return 0;
154
293
 
155
294
  on_error:
295
+ git_commit_list_free(&result);
156
296
  git_revwalk_free(walk);
157
297
  return -1;
158
298
  }
159
299
 
160
300
  static int interesting(git_pqueue *list)
161
301
  {
162
- unsigned int i;
163
- /* element 0 isn't used - we need to start at 1 */
164
- for (i = 1; i < list->size; i++) {
165
- git_commit_list_node *commit = list->d[i];
302
+ size_t i;
303
+
304
+ for (i = 0; i < git_pqueue_size(list); i++) {
305
+ git_commit_list_node *commit = git_pqueue_get(list, i);
166
306
  if ((commit->flags & STALE) == 0)
167
307
  return 1;
168
308
  }
@@ -170,24 +310,59 @@ static int interesting(git_pqueue *list)
170
310
  return 0;
171
311
  }
172
312
 
173
- int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
313
+ static void clear_commit_marks_1(git_commit_list **plist,
314
+ git_commit_list_node *commit, unsigned int mark)
174
315
  {
175
- int error;
316
+ while (commit) {
317
+ unsigned int i;
318
+
319
+ if (!(mark & commit->flags))
320
+ return;
321
+
322
+ commit->flags &= ~mark;
323
+
324
+ for (i = 1; i < commit->out_degree; i++) {
325
+ git_commit_list_node *p = commit->parents[i];
326
+ git_commit_list_insert(p, plist);
327
+ }
328
+
329
+ commit = commit->out_degree ? commit->parents[0] : NULL;
330
+ }
331
+ }
332
+
333
+ static void clear_commit_marks_many(git_vector *commits, unsigned int mark)
334
+ {
335
+ git_commit_list *list = NULL;
336
+ git_commit_list_node *c;
176
337
  unsigned int i;
177
- git_commit_list_node *two;
178
- git_commit_list *result = NULL, *tmp = NULL;
179
- git_pqueue list;
180
338
 
181
- /* if the commit is repeated, we have a our merge base already */
182
- git_vector_foreach(twos, i, two) {
183
- if (one == two)
184
- return git_commit_list_insert(one, out) ? 0 : -1;
339
+ git_vector_foreach(commits, i, c) {
340
+ git_commit_list_insert(c, &list);
185
341
  }
186
342
 
187
- if (git_pqueue_init(&list, twos->length * 2, git_commit_list_time_cmp) < 0)
188
- return -1;
343
+ while (list)
344
+ clear_commit_marks_1(&list, git_commit_list_pop(&list), mark);
345
+ }
189
346
 
190
- if (git_commit_list_parse(walk, one) < 0)
347
+ static void clear_commit_marks(git_commit_list_node *commit, unsigned int mark)
348
+ {
349
+ git_commit_list *list = NULL;
350
+ git_commit_list_insert(commit, &list);
351
+ while (list)
352
+ clear_commit_marks_1(&list, git_commit_list_pop(&list), mark);
353
+ }
354
+
355
+ static int paint_down_to_common(
356
+ git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
357
+ {
358
+ git_pqueue list;
359
+ git_commit_list *result = NULL;
360
+ git_commit_list_node *two;
361
+
362
+ int error;
363
+ unsigned int i;
364
+
365
+ if (git_pqueue_init(&list, 0, twos->length * 2, git_commit_list_time_cmp) < 0)
191
366
  return -1;
192
367
 
193
368
  one->flags |= PARENT1;
@@ -195,18 +370,22 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
195
370
  return -1;
196
371
 
197
372
  git_vector_foreach(twos, i, two) {
198
- git_commit_list_parse(walk, two);
373
+ if (git_commit_list_parse(walk, two) < 0)
374
+ return -1;
375
+
199
376
  two->flags |= PARENT2;
377
+
200
378
  if (git_pqueue_insert(&list, two) < 0)
201
379
  return -1;
202
380
  }
203
381
 
204
382
  /* as long as there are non-STALE commits */
205
383
  while (interesting(&list)) {
206
- git_commit_list_node *commit;
384
+ git_commit_list_node *commit = git_pqueue_pop(&list);
207
385
  int flags;
208
386
 
209
- commit = git_pqueue_pop(&list);
387
+ if (commit == NULL)
388
+ break;
210
389
 
211
390
  flags = commit->flags & (PARENT1 | PARENT2 | STALE);
212
391
  if (flags == (PARENT1 | PARENT2)) {
@@ -234,26 +413,146 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
234
413
  }
235
414
 
236
415
  git_pqueue_free(&list);
416
+ *out = result;
417
+ return 0;
418
+ }
419
+
420
+ static int remove_redundant(git_revwalk *walk, git_vector *commits)
421
+ {
422
+ git_vector work = GIT_VECTOR_INIT;
423
+ unsigned char *redundant;
424
+ unsigned int *filled_index;
425
+ unsigned int i, j;
426
+ int error = 0;
427
+
428
+ redundant = git__calloc(commits->length, 1);
429
+ GIT_ERROR_CHECK_ALLOC(redundant);
430
+ filled_index = git__calloc((commits->length - 1), sizeof(unsigned int));
431
+ GIT_ERROR_CHECK_ALLOC(filled_index);
432
+
433
+ for (i = 0; i < commits->length; ++i) {
434
+ if ((error = git_commit_list_parse(walk, commits->contents[i])) < 0)
435
+ goto done;
436
+ }
437
+
438
+ for (i = 0; i < commits->length; ++i) {
439
+ git_commit_list *common = NULL;
440
+ git_commit_list_node *commit = commits->contents[i];
441
+
442
+ if (redundant[i])
443
+ continue;
444
+
445
+ git_vector_clear(&work);
446
+
447
+ for (j = 0; j < commits->length; j++) {
448
+ if (i == j || redundant[j])
449
+ continue;
450
+
451
+ filled_index[work.length] = j;
452
+ if ((error = git_vector_insert(&work, commits->contents[j])) < 0)
453
+ goto done;
454
+ }
455
+
456
+ error = paint_down_to_common(&common, walk, commit, &work);
457
+ if (error < 0)
458
+ goto done;
459
+
460
+ if (commit->flags & PARENT2)
461
+ redundant[i] = 1;
462
+
463
+ for (j = 0; j < work.length; j++) {
464
+ git_commit_list_node *w = work.contents[j];
465
+ if (w->flags & PARENT1)
466
+ redundant[filled_index[j]] = 1;
467
+ }
468
+
469
+ clear_commit_marks(commit, ALL_FLAGS);
470
+ clear_commit_marks_many(&work, ALL_FLAGS);
471
+
472
+ git_commit_list_free(&common);
473
+ }
474
+
475
+ for (i = 0; i < commits->length; ++i) {
476
+ if (redundant[i])
477
+ commits->contents[i] = NULL;
478
+ }
479
+
480
+ done:
481
+ git__free(redundant);
482
+ git__free(filled_index);
483
+ git_vector_free(&work);
484
+ return error;
485
+ }
486
+
487
+ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_list_node *one, git_vector *twos)
488
+ {
489
+ int error;
490
+ unsigned int i;
491
+ git_commit_list_node *two;
492
+ git_commit_list *result = NULL, *tmp = NULL;
493
+
494
+ /* If there's only the one commit, there can be no merge bases */
495
+ if (twos->length == 0) {
496
+ *out = NULL;
497
+ return 0;
498
+ }
499
+
500
+ /* if the commit is repeated, we have a our merge base already */
501
+ git_vector_foreach(twos, i, two) {
502
+ if (one == two)
503
+ return git_commit_list_insert(one, out) ? 0 : -1;
504
+ }
505
+
506
+ if (git_commit_list_parse(walk, one) < 0)
507
+ return -1;
508
+
509
+ error = paint_down_to_common(&result, walk, one, twos);
510
+ if (error < 0)
511
+ return error;
237
512
 
238
513
  /* filter out any stale commits in the results */
239
514
  tmp = result;
240
515
  result = NULL;
241
516
 
242
517
  while (tmp) {
243
- struct git_commit_list *next = tmp->next;
244
- if (!(tmp->item->flags & STALE))
245
- if (git_commit_list_insert_by_date(tmp->item, &result) == NULL)
518
+ git_commit_list_node *c = git_commit_list_pop(&tmp);
519
+ if (!(c->flags & STALE))
520
+ if (git_commit_list_insert_by_date(c, &result) == NULL)
246
521
  return -1;
522
+ }
523
+
524
+ /*
525
+ * more than one merge base -- see if there are redundant merge
526
+ * bases and remove them
527
+ */
528
+ if (result && result->next) {
529
+ git_vector redundant = GIT_VECTOR_INIT;
530
+
531
+ while (result)
532
+ git_vector_insert(&redundant, git_commit_list_pop(&result));
533
+
534
+ clear_commit_marks(one, ALL_FLAGS);
535
+ clear_commit_marks_many(twos, ALL_FLAGS);
536
+
537
+ if ((error = remove_redundant(walk, &redundant)) < 0) {
538
+ git_vector_free(&redundant);
539
+ return error;
540
+ }
541
+
542
+ git_vector_foreach(&redundant, i, two) {
543
+ if (two != NULL)
544
+ git_commit_list_insert_by_date(two, &result);
545
+ }
247
546
 
248
- git__free(tmp);
249
- tmp = next;
547
+ git_vector_free(&redundant);
250
548
  }
251
549
 
252
550
  *out = result;
253
551
  return 0;
254
552
  }
255
553
 
256
- int git_repository_mergehead_foreach(git_repository *repo,
554
+ int git_repository_mergehead_foreach(
555
+ git_repository *repo,
257
556
  git_repository_mergehead_foreach_cb cb,
258
557
  void *payload)
259
558
  {
@@ -265,7 +564,7 @@ int git_repository_mergehead_foreach(git_repository *repo,
265
564
 
266
565
  assert(repo && cb);
267
566
 
268
- if ((error = git_buf_joinpath(&merge_head_path, repo->path_repository,
567
+ if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir,
269
568
  GIT_MERGE_HEAD_FILE)) < 0)
270
569
  return error;
271
570
 
@@ -277,7 +576,7 @@ int git_repository_mergehead_foreach(git_repository *repo,
277
576
 
278
577
  while ((line = git__strsep(&buffer, "\n")) != NULL) {
279
578
  if (strlen(line) != GIT_OID_HEXSZ) {
280
- giterr_set(GITERR_INVALID, "Unable to parse OID - invalid length");
579
+ git_error_set(GIT_ERROR_INVALID, "unable to parse OID - invalid length");
281
580
  error = -1;
282
581
  goto cleanup;
283
582
  }
@@ -285,8 +584,8 @@ int git_repository_mergehead_foreach(git_repository *repo,
285
584
  if ((error = git_oid_fromstr(&oid, line)) < 0)
286
585
  goto cleanup;
287
586
 
288
- if (cb(&oid, payload) < 0) {
289
- error = GIT_EUSER;
587
+ if ((error = cb(&oid, payload)) != 0) {
588
+ git_error_set_after_callback(error);
290
589
  goto cleanup;
291
590
  }
292
591
 
@@ -294,14 +593,14 @@ int git_repository_mergehead_foreach(git_repository *repo,
294
593
  }
295
594
 
296
595
  if (*buffer) {
297
- giterr_set(GITERR_MERGE, "No EOL at line %d", line_num);
596
+ git_error_set(GIT_ERROR_MERGE, "no EOL at line %"PRIuZ, line_num);
298
597
  error = -1;
299
598
  goto cleanup;
300
599
  }
301
600
 
302
601
  cleanup:
303
- git_buf_free(&merge_head_path);
304
- git_buf_free(&merge_head_file);
602
+ git_buf_dispose(&merge_head_path);
603
+ git_buf_dispose(&merge_head_file);
305
604
 
306
605
  return error;
307
606
  }
@@ -314,7 +613,7 @@ GIT_INLINE(int) index_entry_cmp(const git_index_entry *a, const git_index_entry
314
613
  return (b->path == NULL) ? 0 : 1;
315
614
 
316
615
  if ((value = a->mode - b->mode) == 0 &&
317
- (value = git_oid__cmp(&a->oid, &b->oid)) == 0)
616
+ (value = git_oid__cmp(&a->id, &b->id)) == 0)
318
617
  value = strcmp(a->path, b->path);
319
618
 
320
619
  return value;
@@ -445,7 +744,6 @@ static int merge_conflict_resolve_one_removed(
445
744
  return error;
446
745
  }
447
746
 
448
-
449
747
  static int merge_conflict_resolve_one_renamed(
450
748
  int *resolved,
451
749
  git_merge_diff_list *diff_list,
@@ -476,12 +774,12 @@ static int merge_conflict_resolve_one_renamed(
476
774
  conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
477
775
  return 0;
478
776
 
479
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.oid, &conflict->our_entry.oid) != 0);
480
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.oid, &conflict->their_entry.oid) != 0);
777
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
778
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
481
779
 
482
780
  /* if both are modified (and not to a common target) require a merge */
483
781
  if (ours_changed && theirs_changed &&
484
- git_oid__cmp(&conflict->our_entry.oid, &conflict->their_entry.oid) != 0)
782
+ git_oid__cmp(&conflict->our_entry.id, &conflict->their_entry.id) != 0)
485
783
  return 0;
486
784
 
487
785
  if ((merged = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
@@ -505,75 +803,163 @@ static int merge_conflict_resolve_one_renamed(
505
803
  return error;
506
804
  }
507
805
 
508
- static int merge_conflict_resolve_automerge(
509
- int *resolved,
510
- git_merge_diff_list *diff_list,
511
- const git_merge_diff *conflict,
512
- unsigned int automerge_flags)
806
+ static bool merge_conflict_can_resolve_contents(
807
+ const git_merge_diff *conflict)
513
808
  {
514
- git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
515
- ours = GIT_MERGE_FILE_INPUT_INIT,
516
- theirs = GIT_MERGE_FILE_INPUT_INIT;
517
- git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT;
518
- git_index_entry *index_entry;
519
- git_odb *odb = NULL;
520
- git_oid automerge_oid;
521
- int error = 0;
522
-
523
- assert(resolved && diff_list && conflict);
524
-
525
- *resolved = 0;
526
-
527
- if (automerge_flags == GIT_MERGE_AUTOMERGE_NONE)
528
- return 0;
809
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
810
+ !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
811
+ return false;
529
812
 
530
813
  /* Reject D/F conflicts */
531
814
  if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
532
- return 0;
815
+ return false;
816
+
817
+ /* Reject submodules. */
818
+ if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
819
+ S_ISGITLINK(conflict->our_entry.mode) ||
820
+ S_ISGITLINK(conflict->their_entry.mode))
821
+ return false;
533
822
 
534
823
  /* Reject link/file conflicts. */
535
- if ((S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->our_entry.mode)) ||
536
- (S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->their_entry.mode)))
537
- return 0;
824
+ if ((S_ISLNK(conflict->ancestor_entry.mode) ^
825
+ S_ISLNK(conflict->our_entry.mode)) ||
826
+ (S_ISLNK(conflict->ancestor_entry.mode) ^
827
+ S_ISLNK(conflict->their_entry.mode)))
828
+ return false;
538
829
 
539
830
  /* Reject name conflicts */
540
831
  if (conflict->type == GIT_MERGE_DIFF_BOTH_RENAMED_2_TO_1 ||
541
832
  conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
542
- return 0;
833
+ return false;
543
834
 
544
835
  if ((conflict->our_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
545
836
  (conflict->their_status & GIT_DELTA_RENAMED) == GIT_DELTA_RENAMED &&
546
837
  strcmp(conflict->ancestor_entry.path, conflict->their_entry.path) != 0)
547
- return 0;
838
+ return false;
548
839
 
549
- if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
550
- (error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 ||
551
- (error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 ||
552
- (error = git_merge_file_input_from_index_entry(&theirs, diff_list->repo, &conflict->their_entry)) < 0 ||
553
- (error = git_merge_files(&result, &ancestor, &ours, &theirs, automerge_flags)) < 0 ||
554
- !result.automergeable ||
555
- (error = git_odb_write(&automerge_oid, odb, result.data, result.len, GIT_OBJ_BLOB)) < 0)
556
- goto done;
840
+ return true;
841
+ }
557
842
 
558
- if ((index_entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
559
- GITERR_CHECK_ALLOC(index_entry);
843
+ static int merge_conflict_invoke_driver(
844
+ git_index_entry **out,
845
+ const char *name,
846
+ git_merge_driver *driver,
847
+ git_merge_diff_list *diff_list,
848
+ git_merge_driver_source *src)
849
+ {
850
+ git_index_entry *result;
851
+ git_buf buf = GIT_BUF_INIT;
852
+ const char *path;
853
+ uint32_t mode;
854
+ git_odb *odb = NULL;
855
+ git_oid oid;
856
+ int error;
560
857
 
561
- index_entry->path = git_pool_strdup(&diff_list->pool, result.path);
562
- GITERR_CHECK_ALLOC(index_entry->path);
858
+ *out = NULL;
563
859
 
564
- index_entry->file_size = result.len;
565
- index_entry->mode = result.mode;
566
- git_oid_cpy(&index_entry->oid, &automerge_oid);
860
+ if ((error = driver->apply(driver, &path, &mode, &buf, name, src)) < 0 ||
861
+ (error = git_repository_odb(&odb, src->repo)) < 0 ||
862
+ (error = git_odb_write(&oid, odb, buf.ptr, buf.size, GIT_OBJECT_BLOB)) < 0)
863
+ goto done;
567
864
 
568
- git_vector_insert(&diff_list->staged, index_entry);
569
- git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
865
+ result = git_pool_mallocz(&diff_list->pool, sizeof(git_index_entry));
866
+ GIT_ERROR_CHECK_ALLOC(result);
867
+
868
+ git_oid_cpy(&result->id, &oid);
869
+ result->mode = mode;
870
+ result->file_size = buf.size;
871
+
872
+ result->path = git_pool_strdup(&diff_list->pool, path);
873
+ GIT_ERROR_CHECK_ALLOC(result->path);
874
+
875
+ *out = result;
876
+
877
+ done:
878
+ git_buf_dispose(&buf);
879
+ git_odb_free(odb);
880
+
881
+ return error;
882
+ }
883
+
884
+ static int merge_conflict_resolve_contents(
885
+ int *resolved,
886
+ git_merge_diff_list *diff_list,
887
+ const git_merge_diff *conflict,
888
+ const git_merge_options *merge_opts,
889
+ const git_merge_file_options *file_opts)
890
+ {
891
+ git_merge_driver_source source = {0};
892
+ git_merge_file_result result = {0};
893
+ git_merge_driver *driver;
894
+ git_merge_driver__builtin builtin = {{0}};
895
+ git_index_entry *merge_result;
896
+ git_odb *odb = NULL;
897
+ const char *name;
898
+ bool fallback = false;
899
+ int error;
900
+
901
+ assert(resolved && diff_list && conflict);
902
+
903
+ *resolved = 0;
904
+
905
+ if (!merge_conflict_can_resolve_contents(conflict))
906
+ return 0;
907
+
908
+ source.repo = diff_list->repo;
909
+ source.default_driver = merge_opts->default_driver;
910
+ source.file_opts = file_opts;
911
+ source.ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
912
+ &conflict->ancestor_entry : NULL;
913
+ source.ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
914
+ &conflict->our_entry : NULL;
915
+ source.theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
916
+ &conflict->their_entry : NULL;
917
+
918
+ if (file_opts->favor != GIT_MERGE_FILE_FAVOR_NORMAL) {
919
+ /* if the user requested a particular type of resolution (via the
920
+ * favor flag) then let that override the gitattributes and use
921
+ * the builtin driver.
922
+ */
923
+ name = "text";
924
+ builtin.base.apply = git_merge_driver__builtin_apply;
925
+ builtin.favor = file_opts->favor;
926
+
927
+ driver = &builtin.base;
928
+ } else {
929
+ /* find the merge driver for this file */
930
+ if ((error = git_merge_driver_for_source(&name, &driver, &source)) < 0)
931
+ goto done;
932
+
933
+ if (driver == NULL)
934
+ fallback = true;
935
+ }
936
+
937
+ if (driver) {
938
+ error = merge_conflict_invoke_driver(&merge_result, name, driver,
939
+ diff_list, &source);
940
+
941
+ if (error == GIT_PASSTHROUGH)
942
+ fallback = true;
943
+ }
944
+
945
+ if (fallback) {
946
+ error = merge_conflict_invoke_driver(&merge_result, "text",
947
+ &git_merge_driver__text.base, diff_list, &source);
948
+ }
949
+
950
+ if (error < 0) {
951
+ if (error == GIT_EMERGECONFLICT)
952
+ error = 0;
953
+
954
+ goto done;
955
+ }
956
+
957
+ git_vector_insert(&diff_list->staged, merge_result);
958
+ git_vector_insert(&diff_list->resolved, (git_merge_diff *)conflict);
570
959
 
571
960
  *resolved = 1;
572
961
 
573
962
  done:
574
- git_merge_file_input_free(&ancestor);
575
- git_merge_file_input_free(&ours);
576
- git_merge_file_input_free(&theirs);
577
963
  git_merge_file_result_free(&result);
578
964
  git_odb_free(odb);
579
965
 
@@ -584,26 +970,29 @@ static int merge_conflict_resolve(
584
970
  int *out,
585
971
  git_merge_diff_list *diff_list,
586
972
  const git_merge_diff *conflict,
587
- unsigned int automerge_flags)
973
+ const git_merge_options *merge_opts,
974
+ const git_merge_file_options *file_opts)
588
975
  {
589
976
  int resolved = 0;
590
977
  int error = 0;
591
978
 
592
979
  *out = 0;
593
980
 
594
- if ((error = merge_conflict_resolve_trivial(&resolved, diff_list, conflict)) < 0)
981
+ if ((error = merge_conflict_resolve_trivial(
982
+ &resolved, diff_list, conflict)) < 0)
595
983
  goto done;
596
984
 
597
- if (automerge_flags != GIT_MERGE_AUTOMERGE_NONE) {
598
- if (!resolved && (error = merge_conflict_resolve_one_removed(&resolved, diff_list, conflict)) < 0)
599
- goto done;
985
+ if (!resolved && (error = merge_conflict_resolve_one_removed(
986
+ &resolved, diff_list, conflict)) < 0)
987
+ goto done;
600
988
 
601
- if (!resolved && (error = merge_conflict_resolve_one_renamed(&resolved, diff_list, conflict)) < 0)
602
- goto done;
989
+ if (!resolved && (error = merge_conflict_resolve_one_renamed(
990
+ &resolved, diff_list, conflict)) < 0)
991
+ goto done;
603
992
 
604
- if (!resolved && (error = merge_conflict_resolve_automerge(&resolved, diff_list, conflict, automerge_flags)) < 0)
605
- goto done;
606
- }
993
+ if (!resolved && (error = merge_conflict_resolve_contents(
994
+ &resolved, diff_list, conflict, merge_opts, file_opts)) < 0)
995
+ goto done;
607
996
 
608
997
  *out = resolved;
609
998
 
@@ -618,32 +1007,11 @@ struct merge_diff_similarity {
618
1007
  size_t other_idx;
619
1008
  };
620
1009
 
621
- static int index_entry_similarity_exact(
622
- git_repository *repo,
623
- git_index_entry *a,
624
- size_t a_idx,
625
- git_index_entry *b,
626
- size_t b_idx,
627
- void **cache,
628
- const git_merge_tree_opts *opts)
629
- {
630
- GIT_UNUSED(repo);
631
- GIT_UNUSED(a_idx);
632
- GIT_UNUSED(b_idx);
633
- GIT_UNUSED(cache);
634
- GIT_UNUSED(opts);
635
-
636
- if (git_oid__cmp(&a->oid, &b->oid) == 0)
637
- return 100;
638
-
639
- return 0;
640
- }
641
-
642
1010
  static int index_entry_similarity_calc(
643
1011
  void **out,
644
1012
  git_repository *repo,
645
1013
  git_index_entry *entry,
646
- const git_merge_tree_opts *opts)
1014
+ const git_merge_options *opts)
647
1015
  {
648
1016
  git_blob *blob;
649
1017
  git_diff_file diff_file = {{{0}}};
@@ -652,10 +1020,10 @@ static int index_entry_similarity_calc(
652
1020
 
653
1021
  *out = NULL;
654
1022
 
655
- if ((error = git_blob_lookup(&blob, repo, &entry->oid)) < 0)
1023
+ if ((error = git_blob_lookup(&blob, repo, &entry->id)) < 0)
656
1024
  return error;
657
1025
 
658
- git_oid_cpy(&diff_file.oid, &entry->oid);
1026
+ git_oid_cpy(&diff_file.id, &entry->id);
659
1027
  diff_file.path = entry->path;
660
1028
  diff_file.size = entry->file_size;
661
1029
  diff_file.mode = entry->mode;
@@ -683,12 +1051,12 @@ static int index_entry_similarity_inexact(
683
1051
  git_index_entry *b,
684
1052
  size_t b_idx,
685
1053
  void **cache,
686
- const git_merge_tree_opts *opts)
1054
+ const git_merge_options *opts)
687
1055
  {
688
1056
  int score = 0;
689
1057
  int error = 0;
690
1058
 
691
- if (GIT_MODE_TYPE(a->mode) != GIT_MODE_TYPE(b->mode))
1059
+ if (!GIT_MODE_ISBLOB(a->mode) || !GIT_MODE_ISBLOB(b->mode))
692
1060
  return 0;
693
1061
 
694
1062
  /* update signature cache if needed */
@@ -715,14 +1083,156 @@ static int index_entry_similarity_inexact(
715
1083
  return score;
716
1084
  }
717
1085
 
718
- static int merge_diff_mark_similarity(
1086
+ /* Tracks deletes by oid for merge_diff_mark_similarity_exact(). This is a
1087
+ * non-shrinking queue where next_pos is the next position to dequeue.
1088
+ */
1089
+ typedef struct {
1090
+ git_array_t(size_t) arr;
1091
+ size_t next_pos;
1092
+ size_t first_entry;
1093
+ } deletes_by_oid_queue;
1094
+
1095
+ static void deletes_by_oid_free(git_oidmap *map) {
1096
+ deletes_by_oid_queue *queue;
1097
+
1098
+ if (!map)
1099
+ return;
1100
+
1101
+ git_oidmap_foreach_value(map, queue, {
1102
+ git_array_clear(queue->arr);
1103
+ });
1104
+ git_oidmap_free(map);
1105
+ }
1106
+
1107
+ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx) {
1108
+ size_t pos;
1109
+ deletes_by_oid_queue *queue;
1110
+ size_t *array_entry;
1111
+ int error;
1112
+
1113
+ pos = git_oidmap_lookup_index(map, id);
1114
+ if (!git_oidmap_valid_index(map, pos)) {
1115
+ queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue));
1116
+ GIT_ERROR_CHECK_ALLOC(queue);
1117
+
1118
+ git_array_init(queue->arr);
1119
+ queue->next_pos = 0;
1120
+ queue->first_entry = idx;
1121
+
1122
+ git_oidmap_insert(map, id, queue, &error);
1123
+ if (error < 0)
1124
+ return -1;
1125
+ } else {
1126
+ queue = git_oidmap_value_at(map, pos);
1127
+ array_entry = git_array_alloc(queue->arr);
1128
+ GIT_ERROR_CHECK_ALLOC(array_entry);
1129
+ *array_entry = idx;
1130
+ }
1131
+
1132
+ return 0;
1133
+ }
1134
+
1135
+ static int deletes_by_oid_dequeue(size_t *idx, git_oidmap *map, const git_oid *id) {
1136
+ size_t pos;
1137
+ deletes_by_oid_queue *queue;
1138
+ size_t *array_entry;
1139
+
1140
+ pos = git_oidmap_lookup_index(map, id);
1141
+
1142
+ if (!git_oidmap_valid_index(map, pos))
1143
+ return GIT_ENOTFOUND;
1144
+
1145
+ queue = git_oidmap_value_at(map, pos);
1146
+
1147
+ if (queue->next_pos == 0) {
1148
+ *idx = queue->first_entry;
1149
+ } else {
1150
+ array_entry = git_array_get(queue->arr, queue->next_pos - 1);
1151
+ if (array_entry == NULL)
1152
+ return GIT_ENOTFOUND;
1153
+
1154
+ *idx = *array_entry;
1155
+ }
1156
+
1157
+ queue->next_pos++;
1158
+ return 0;
1159
+ }
1160
+
1161
+ static int merge_diff_mark_similarity_exact(
1162
+ git_merge_diff_list *diff_list,
1163
+ struct merge_diff_similarity *similarity_ours,
1164
+ struct merge_diff_similarity *similarity_theirs)
1165
+ {
1166
+ size_t i, j;
1167
+ git_merge_diff *conflict_src, *conflict_tgt;
1168
+ git_oidmap *ours_deletes_by_oid = NULL, *theirs_deletes_by_oid = NULL;
1169
+ int error = 0;
1170
+
1171
+ if (!(ours_deletes_by_oid = git_oidmap_alloc()) ||
1172
+ !(theirs_deletes_by_oid = git_oidmap_alloc())) {
1173
+ error = -1;
1174
+ goto done;
1175
+ }
1176
+
1177
+ /* Build a map of object ids to conflicts */
1178
+ git_vector_foreach(&diff_list->conflicts, i, conflict_src) {
1179
+ /* Items can be the source of a rename iff they have an item in the
1180
+ * ancestor slot and lack an item in the ours or theirs slot. */
1181
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->ancestor_entry))
1182
+ continue;
1183
+
1184
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
1185
+ error = deletes_by_oid_enqueue(ours_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
1186
+ if (error < 0)
1187
+ goto done;
1188
+ }
1189
+
1190
+ if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
1191
+ error = deletes_by_oid_enqueue(theirs_deletes_by_oid, &diff_list->pool, &conflict_src->ancestor_entry.id, i);
1192
+ if (error < 0)
1193
+ goto done;
1194
+ }
1195
+ }
1196
+
1197
+ git_vector_foreach(&diff_list->conflicts, j, conflict_tgt) {
1198
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->ancestor_entry))
1199
+ continue;
1200
+
1201
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry)) {
1202
+ if (deletes_by_oid_dequeue(&i, ours_deletes_by_oid, &conflict_tgt->our_entry.id) == 0) {
1203
+ similarity_ours[i].similarity = 100;
1204
+ similarity_ours[i].other_idx = j;
1205
+
1206
+ similarity_ours[j].similarity = 100;
1207
+ similarity_ours[j].other_idx = i;
1208
+ }
1209
+ }
1210
+
1211
+ if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry)) {
1212
+ if (deletes_by_oid_dequeue(&i, theirs_deletes_by_oid, &conflict_tgt->their_entry.id) == 0) {
1213
+ similarity_theirs[i].similarity = 100;
1214
+ similarity_theirs[i].other_idx = j;
1215
+
1216
+ similarity_theirs[j].similarity = 100;
1217
+ similarity_theirs[j].other_idx = i;
1218
+ }
1219
+ }
1220
+ }
1221
+
1222
+ done:
1223
+ deletes_by_oid_free(ours_deletes_by_oid);
1224
+ deletes_by_oid_free(theirs_deletes_by_oid);
1225
+
1226
+ return error;
1227
+ }
1228
+
1229
+ static int merge_diff_mark_similarity_inexact(
719
1230
  git_repository *repo,
720
1231
  git_merge_diff_list *diff_list,
721
1232
  struct merge_diff_similarity *similarity_ours,
722
1233
  struct merge_diff_similarity *similarity_theirs,
723
- int (*similarity_fn)(git_repository *, git_index_entry *, size_t, git_index_entry *, size_t, void **, const git_merge_tree_opts *),
724
1234
  void **cache,
725
- const git_merge_tree_opts *opts)
1235
+ const git_merge_options *opts)
726
1236
  {
727
1237
  size_t i, j;
728
1238
  git_merge_diff *conflict_src, *conflict_tgt;
@@ -745,7 +1255,7 @@ static int merge_diff_mark_similarity(
745
1255
 
746
1256
  if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->our_entry) &&
747
1257
  !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->our_entry)) {
748
- similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
1258
+ similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->our_entry, our_idx, cache, opts);
749
1259
 
750
1260
  if (similarity == GIT_EBUFS)
751
1261
  continue;
@@ -771,7 +1281,7 @@ static int merge_diff_mark_similarity(
771
1281
 
772
1282
  if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_tgt->their_entry) &&
773
1283
  !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict_src->their_entry)) {
774
- similarity = similarity_fn(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
1284
+ similarity = index_entry_similarity_inexact(repo, &conflict_src->ancestor_entry, i, &conflict_tgt->their_entry, their_idx, cache, opts);
775
1285
 
776
1286
  if (similarity > similarity_theirs[i].similarity &&
777
1287
  similarity > similarity_theirs[j].similarity) {
@@ -823,7 +1333,7 @@ static void merge_diff_mark_rename_conflict(
823
1333
  bool theirs_renamed,
824
1334
  size_t theirs_source_idx,
825
1335
  git_merge_diff *target,
826
- const git_merge_tree_opts *opts)
1336
+ const git_merge_options *opts)
827
1337
  {
828
1338
  git_merge_diff *ours_source = NULL, *theirs_source = NULL;
829
1339
 
@@ -893,7 +1403,7 @@ static void merge_diff_list_coalesce_renames(
893
1403
  git_merge_diff_list *diff_list,
894
1404
  struct merge_diff_similarity *similarity_ours,
895
1405
  struct merge_diff_similarity *similarity_theirs,
896
- const git_merge_tree_opts *opts)
1406
+ const git_merge_options *opts)
897
1407
  {
898
1408
  size_t i;
899
1409
  bool ours_renamed = 0, theirs_renamed = 0;
@@ -950,10 +1460,12 @@ static void merge_diff_list_coalesce_renames(
950
1460
  }
951
1461
  }
952
1462
 
953
- static int merge_diff_empty(const git_vector *conflicts, size_t idx)
1463
+ static int merge_diff_empty(const git_vector *conflicts, size_t idx, void *p)
954
1464
  {
955
1465
  git_merge_diff *conflict = conflicts->contents[idx];
956
1466
 
1467
+ GIT_UNUSED(p);
1468
+
957
1469
  return (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) &&
958
1470
  !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) &&
959
1471
  !GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry));
@@ -974,16 +1486,16 @@ static void merge_diff_list_count_candidates(
974
1486
  if (GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry) &&
975
1487
  (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->our_entry) ||
976
1488
  !GIT_MERGE_INDEX_ENTRY_EXISTS(entry->their_entry)))
977
- src_count++;
1489
+ (*src_count)++;
978
1490
  else if (!GIT_MERGE_INDEX_ENTRY_EXISTS(entry->ancestor_entry))
979
- tgt_count++;
1491
+ (*tgt_count)++;
980
1492
  }
981
1493
  }
982
1494
 
983
1495
  int git_merge_diff_list__find_renames(
984
1496
  git_repository *repo,
985
1497
  git_merge_diff_list *diff_list,
986
- const git_merge_tree_opts *opts)
1498
+ const git_merge_options *opts)
987
1499
  {
988
1500
  struct merge_diff_similarity *similarity_ours, *similarity_theirs;
989
1501
  void **cache = NULL;
@@ -993,37 +1505,35 @@ int git_merge_diff_list__find_renames(
993
1505
 
994
1506
  assert(diff_list && opts);
995
1507
 
996
- if ((opts->flags & GIT_MERGE_TREE_FIND_RENAMES) == 0)
1508
+ if ((opts->flags & GIT_MERGE_FIND_RENAMES) == 0)
997
1509
  return 0;
998
1510
 
999
1511
  similarity_ours = git__calloc(diff_list->conflicts.length,
1000
1512
  sizeof(struct merge_diff_similarity));
1001
- GITERR_CHECK_ALLOC(similarity_ours);
1513
+ GIT_ERROR_CHECK_ALLOC(similarity_ours);
1002
1514
 
1003
1515
  similarity_theirs = git__calloc(diff_list->conflicts.length,
1004
1516
  sizeof(struct merge_diff_similarity));
1005
- GITERR_CHECK_ALLOC(similarity_theirs);
1517
+ GIT_ERROR_CHECK_ALLOC(similarity_theirs);
1006
1518
 
1007
1519
  /* Calculate similarity between items that were deleted from the ancestor
1008
1520
  * and added in the other branch.
1009
1521
  */
1010
- if ((error = merge_diff_mark_similarity(repo, diff_list, similarity_ours,
1011
- similarity_theirs, index_entry_similarity_exact, NULL, opts)) < 0)
1522
+ if ((error = merge_diff_mark_similarity_exact(diff_list, similarity_ours, similarity_theirs)) < 0)
1012
1523
  goto done;
1013
1524
 
1014
- if (diff_list->conflicts.length <= opts->target_limit) {
1015
- cache_size = diff_list->conflicts.length * 3;
1525
+ if (opts->rename_threshold < 100 && diff_list->conflicts.length <= opts->target_limit) {
1526
+ GIT_ERROR_CHECK_ALLOC_MULTIPLY(&cache_size, diff_list->conflicts.length, 3);
1016
1527
  cache = git__calloc(cache_size, sizeof(void *));
1017
- GITERR_CHECK_ALLOC(cache);
1528
+ GIT_ERROR_CHECK_ALLOC(cache);
1018
1529
 
1019
1530
  merge_diff_list_count_candidates(diff_list, &src_count, &tgt_count);
1020
1531
 
1021
1532
  if (src_count > opts->target_limit || tgt_count > opts->target_limit) {
1022
1533
  /* TODO: report! */
1023
1534
  } else {
1024
- if ((error = merge_diff_mark_similarity(
1025
- repo, diff_list, similarity_ours, similarity_theirs,
1026
- index_entry_similarity_inexact, cache, opts)) < 0)
1535
+ if ((error = merge_diff_mark_similarity_inexact(
1536
+ repo, diff_list, similarity_ours, similarity_theirs, cache, opts)) < 0)
1027
1537
  goto done;
1028
1538
  }
1029
1539
  }
@@ -1034,7 +1544,7 @@ int git_merge_diff_list__find_renames(
1034
1544
  merge_diff_list_coalesce_renames(diff_list, similarity_ours, similarity_theirs, opts);
1035
1545
 
1036
1546
  /* And remove any entries that were merged and are now empty. */
1037
- git_vector_remove_matching(&diff_list->conflicts, merge_diff_empty);
1547
+ git_vector_remove_matching(&diff_list->conflicts, merge_diff_empty, NULL);
1038
1548
 
1039
1549
  done:
1040
1550
  if (cache != NULL) {
@@ -1145,14 +1655,13 @@ GIT_INLINE(int) merge_diff_detect_type(
1145
1655
  return 0;
1146
1656
  }
1147
1657
 
1148
- GIT_INLINE(int) index_entry_dup(
1658
+ GIT_INLINE(int) index_entry_dup_pool(
1149
1659
  git_index_entry *out,
1150
1660
  git_pool *pool,
1151
1661
  const git_index_entry *src)
1152
1662
  {
1153
1663
  if (src != NULL) {
1154
1664
  memcpy(out, src, sizeof(git_index_entry));
1155
-
1156
1665
  if ((out->path = git_pool_strdup(pool, src->path)) == NULL)
1157
1666
  return -1;
1158
1667
  }
@@ -1174,7 +1683,7 @@ GIT_INLINE(int) merge_delta_type_from_index_entries(
1174
1683
  return GIT_DELTA_TYPECHANGE;
1175
1684
  else if(S_ISLNK(ancestor->mode) ^ S_ISLNK(other->mode))
1176
1685
  return GIT_DELTA_TYPECHANGE;
1177
- else if (git_oid__cmp(&ancestor->oid, &other->oid) ||
1686
+ else if (git_oid__cmp(&ancestor->id, &other->id) ||
1178
1687
  ancestor->mode != other->mode)
1179
1688
  return GIT_DELTA_MODIFIED;
1180
1689
 
@@ -1188,12 +1697,12 @@ static git_merge_diff *merge_diff_from_index_entries(
1188
1697
  git_merge_diff *conflict;
1189
1698
  git_pool *pool = &diff_list->pool;
1190
1699
 
1191
- if ((conflict = git_pool_malloc(pool, sizeof(git_merge_diff))) == NULL)
1700
+ if ((conflict = git_pool_mallocz(pool, sizeof(git_merge_diff))) == NULL)
1192
1701
  return NULL;
1193
1702
 
1194
- if (index_entry_dup(&conflict->ancestor_entry, pool, entries[TREE_IDX_ANCESTOR]) < 0 ||
1195
- index_entry_dup(&conflict->our_entry, pool, entries[TREE_IDX_OURS]) < 0 ||
1196
- index_entry_dup(&conflict->their_entry, pool, entries[TREE_IDX_THEIRS]) < 0)
1703
+ if (index_entry_dup_pool(&conflict->ancestor_entry, pool, entries[TREE_IDX_ANCESTOR]) < 0 ||
1704
+ index_entry_dup_pool(&conflict->our_entry, pool, entries[TREE_IDX_OURS]) < 0 ||
1705
+ index_entry_dup_pool(&conflict->their_entry, pool, entries[TREE_IDX_THEIRS]) < 0)
1197
1706
  return NULL;
1198
1707
 
1199
1708
  conflict->our_status = merge_delta_type_from_index_entries(
@@ -1206,7 +1715,7 @@ static git_merge_diff *merge_diff_from_index_entries(
1206
1715
 
1207
1716
  /* Merge trees */
1208
1717
 
1209
- static int merge_index_insert_conflict(
1718
+ static int merge_diff_list_insert_conflict(
1210
1719
  git_merge_diff_list *diff_list,
1211
1720
  struct merge_diff_df_data *merge_df_data,
1212
1721
  const git_index_entry *tree_items[3])
@@ -1222,7 +1731,7 @@ static int merge_index_insert_conflict(
1222
1731
  return 0;
1223
1732
  }
1224
1733
 
1225
- static int merge_index_insert_unmodified(
1734
+ static int merge_diff_list_insert_unmodified(
1226
1735
  git_merge_diff_list *diff_list,
1227
1736
  const git_index_entry *tree_items[3])
1228
1737
  {
@@ -1230,114 +1739,52 @@ static int merge_index_insert_unmodified(
1230
1739
  git_index_entry *entry;
1231
1740
 
1232
1741
  entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry));
1233
- GITERR_CHECK_ALLOC(entry);
1742
+ GIT_ERROR_CHECK_ALLOC(entry);
1234
1743
 
1235
- if ((error = index_entry_dup(entry, &diff_list->pool, tree_items[0])) >= 0)
1744
+ if ((error = index_entry_dup_pool(entry, &diff_list->pool, tree_items[0])) >= 0)
1236
1745
  error = git_vector_insert(&diff_list->staged, entry);
1237
1746
 
1238
1747
  return error;
1239
1748
  }
1240
1749
 
1241
- int git_merge_diff_list__find_differences(
1242
- git_merge_diff_list *diff_list,
1243
- const git_tree *ancestor_tree,
1244
- const git_tree *our_tree,
1245
- const git_tree *their_tree)
1246
- {
1247
- git_iterator *iterators[3] = {0};
1248
- const git_index_entry *items[3] = {0}, *best_cur_item, *cur_items[3];
1249
- git_vector_cmp entry_compare = git_index_entry__cmp;
1250
- struct merge_diff_df_data df_data = {0};
1251
- int cur_item_modified;
1252
- size_t i, j;
1253
- int error = 0;
1254
-
1255
- assert(diff_list && our_tree && their_tree);
1256
-
1257
- if ((error = git_iterator_for_tree(&iterators[TREE_IDX_ANCESTOR], (git_tree *)ancestor_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1258
- (error = git_iterator_for_tree(&iterators[TREE_IDX_OURS], (git_tree *)our_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 ||
1259
- (error = git_iterator_for_tree(&iterators[TREE_IDX_THEIRS], (git_tree *)their_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0)
1260
- goto done;
1261
-
1262
- /* Set up the iterators */
1263
- for (i = 0; i < 3; i++) {
1264
- error = git_iterator_current(&items[i], iterators[i]);
1265
- if (error < 0 && error != GIT_ITEROVER)
1266
- goto done;
1267
- }
1268
-
1269
- while (true) {
1270
- for (i = 0; i < 3; i++)
1271
- cur_items[i] = NULL;
1272
-
1273
- best_cur_item = NULL;
1274
- cur_item_modified = 0;
1750
+ struct merge_diff_find_data {
1751
+ git_merge_diff_list *diff_list;
1752
+ struct merge_diff_df_data df_data;
1753
+ };
1275
1754
 
1276
- /* Find the next path(s) to consume from each iterator */
1277
- for (i = 0; i < 3; i++) {
1278
- if (items[i] == NULL) {
1279
- cur_item_modified = 1;
1280
- continue;
1281
- }
1755
+ static int queue_difference(const git_index_entry **entries, void *data)
1756
+ {
1757
+ struct merge_diff_find_data *find_data = data;
1758
+ bool item_modified = false;
1759
+ size_t i;
1282
1760
 
1283
- if (best_cur_item == NULL) {
1284
- best_cur_item = items[i];
1285
- cur_items[i] = items[i];
1286
- } else {
1287
- int path_diff = entry_compare(items[i], best_cur_item);
1288
-
1289
- if (path_diff < 0) {
1290
- /*
1291
- * Found an item that sorts before our current item, make
1292
- * our current item this one.
1293
- */
1294
- for (j = 0; j < i; j++)
1295
- cur_items[j] = NULL;
1296
-
1297
- cur_item_modified = 1;
1298
- best_cur_item = items[i];
1299
- cur_items[i] = items[i];
1300
- } else if (path_diff > 0) {
1301
- /* No entry for the current item, this is modified */
1302
- cur_item_modified = 1;
1303
- } else if (path_diff == 0) {
1304
- cur_items[i] = items[i];
1305
-
1306
- if (!cur_item_modified)
1307
- cur_item_modified = index_entry_cmp(best_cur_item, items[i]);
1308
- }
1761
+ if (!entries[0] || !entries[1] || !entries[2]) {
1762
+ item_modified = true;
1763
+ } else {
1764
+ for (i = 1; i < 3; i++) {
1765
+ if (index_entry_cmp(entries[0], entries[i]) != 0) {
1766
+ item_modified = true;
1767
+ break;
1309
1768
  }
1310
1769
  }
1311
-
1312
- if (best_cur_item == NULL)
1313
- break;
1314
-
1315
- if (cur_item_modified)
1316
- error = merge_index_insert_conflict(diff_list, &df_data, cur_items);
1317
- else
1318
- error = merge_index_insert_unmodified(diff_list, cur_items);
1319
- if (error < 0)
1320
- goto done;
1321
-
1322
- /* Advance each iterator that participated */
1323
- for (i = 0; i < 3; i++) {
1324
- if (cur_items[i] == NULL)
1325
- continue;
1326
-
1327
- error = git_iterator_advance(&items[i], iterators[i]);
1328
- if (error < 0 && error != GIT_ITEROVER)
1329
- goto done;
1330
- }
1331
1770
  }
1332
1771
 
1333
- done:
1334
- for (i = 0; i < 3; i++)
1335
- git_iterator_free(iterators[i]);
1772
+ return item_modified ?
1773
+ merge_diff_list_insert_conflict(
1774
+ find_data->diff_list, &find_data->df_data, entries) :
1775
+ merge_diff_list_insert_unmodified(find_data->diff_list, entries);
1776
+ }
1336
1777
 
1337
- if (error == GIT_ITEROVER)
1338
- error = 0;
1778
+ int git_merge_diff_list__find_differences(
1779
+ git_merge_diff_list *diff_list,
1780
+ git_iterator *ancestor_iter,
1781
+ git_iterator *our_iter,
1782
+ git_iterator *their_iter)
1783
+ {
1784
+ git_iterator *iterators[3] = { ancestor_iter, our_iter, their_iter };
1785
+ struct merge_diff_find_data find_data = { diff_list };
1339
1786
 
1340
- return error;
1787
+ return git_iterator_walk(iterators, 3, queue_difference, &find_data);
1341
1788
  }
1342
1789
 
1343
1790
  git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
@@ -1349,11 +1796,14 @@ git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
1349
1796
 
1350
1797
  diff_list->repo = repo;
1351
1798
 
1799
+ git_pool_init(&diff_list->pool, 1);
1800
+
1352
1801
  if (git_vector_init(&diff_list->staged, 0, NULL) < 0 ||
1353
1802
  git_vector_init(&diff_list->conflicts, 0, NULL) < 0 ||
1354
- git_vector_init(&diff_list->resolved, 0, NULL) < 0 ||
1355
- git_pool_init(&diff_list->pool, 1, 0) < 0)
1803
+ git_vector_init(&diff_list->resolved, 0, NULL) < 0) {
1804
+ git_merge_diff_list__free(diff_list);
1356
1805
  return NULL;
1806
+ }
1357
1807
 
1358
1808
  return diff_list;
1359
1809
  }
@@ -1370,12 +1820,13 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list)
1370
1820
  git__free(diff_list);
1371
1821
  }
1372
1822
 
1373
- static int merge_tree_normalize_opts(
1823
+ static int merge_normalize_opts(
1374
1824
  git_repository *repo,
1375
- git_merge_tree_opts *opts,
1376
- const git_merge_tree_opts *given)
1825
+ git_merge_options *opts,
1826
+ const git_merge_options *given)
1377
1827
  {
1378
1828
  git_config *cfg = NULL;
1829
+ git_config_entry *entry = NULL;
1379
1830
  int error = 0;
1380
1831
 
1381
1832
  assert(repo && opts);
@@ -1383,51 +1834,57 @@ static int merge_tree_normalize_opts(
1383
1834
  if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
1384
1835
  return error;
1385
1836
 
1386
- if (given != NULL)
1387
- memcpy(opts, given, sizeof(git_merge_tree_opts));
1388
- else {
1389
- git_merge_tree_opts init = GIT_MERGE_TREE_OPTS_INIT;
1837
+ if (given != NULL) {
1838
+ memcpy(opts, given, sizeof(git_merge_options));
1839
+ } else {
1840
+ git_merge_options init = GIT_MERGE_OPTIONS_INIT;
1390
1841
  memcpy(opts, &init, sizeof(init));
1391
-
1392
- opts->flags = GIT_MERGE_TREE_FIND_RENAMES;
1393
- opts->rename_threshold = GIT_MERGE_TREE_RENAME_THRESHOLD;
1394
1842
  }
1395
1843
 
1396
- if (!opts->target_limit) {
1397
- int32_t limit = 0;
1398
-
1399
- opts->target_limit = GIT_MERGE_TREE_TARGET_LIMIT;
1844
+ if ((opts->flags & GIT_MERGE_FIND_RENAMES) && !opts->rename_threshold)
1845
+ opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD;
1400
1846
 
1401
- if (git_config_get_int32(&limit, cfg, "merge.renameLimit") < 0) {
1402
- giterr_clear();
1847
+ if (given && given->default_driver) {
1848
+ opts->default_driver = git__strdup(given->default_driver);
1849
+ GIT_ERROR_CHECK_ALLOC(opts->default_driver);
1850
+ } else {
1851
+ error = git_config_get_entry(&entry, cfg, "merge.default");
1403
1852
 
1404
- if (git_config_get_int32(&limit, cfg, "diff.renameLimit") < 0)
1405
- giterr_clear();
1853
+ if (error == 0) {
1854
+ opts->default_driver = git__strdup(entry->value);
1855
+ GIT_ERROR_CHECK_ALLOC(opts->default_driver);
1856
+ } else if (error == GIT_ENOTFOUND) {
1857
+ error = 0;
1858
+ } else {
1859
+ goto done;
1406
1860
  }
1861
+ }
1407
1862
 
1408
- if (limit > 0)
1409
- opts->target_limit = limit;
1863
+ if (!opts->target_limit) {
1864
+ int limit = git_config__get_int_force(cfg, "merge.renamelimit", 0);
1865
+
1866
+ if (!limit)
1867
+ limit = git_config__get_int_force(cfg, "diff.renamelimit", 0);
1868
+
1869
+ opts->target_limit = (limit <= 0) ?
1870
+ GIT_MERGE_DEFAULT_TARGET_LIMIT : (unsigned int)limit;
1410
1871
  }
1411
1872
 
1412
1873
  /* assign the internal metric with whitespace flag as payload */
1413
1874
  if (!opts->metric) {
1414
1875
  opts->metric = git__malloc(sizeof(git_diff_similarity_metric));
1415
- GITERR_CHECK_ALLOC(opts->metric);
1876
+ GIT_ERROR_CHECK_ALLOC(opts->metric);
1416
1877
 
1417
1878
  opts->metric->file_signature = git_diff_find_similar__hashsig_for_file;
1418
1879
  opts->metric->buffer_signature = git_diff_find_similar__hashsig_for_buf;
1419
1880
  opts->metric->free_signature = git_diff_find_similar__hashsig_free;
1420
1881
  opts->metric->similarity = git_diff_find_similar__calc_similarity;
1421
-
1422
- if (opts->flags & GIT_DIFF_FIND_IGNORE_WHITESPACE)
1423
- opts->metric->payload = (void *)GIT_HASHSIG_IGNORE_WHITESPACE;
1424
- else if (opts->flags & GIT_DIFF_FIND_DONT_IGNORE_WHITESPACE)
1425
- opts->metric->payload = (void *)GIT_HASHSIG_NORMAL;
1426
- else
1427
- opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
1882
+ opts->metric->payload = (void *)GIT_HASHSIG_SMART_WHITESPACE;
1428
1883
  }
1429
1884
 
1430
- return 0;
1885
+ done:
1886
+ git_config_entry_free(entry);
1887
+ return error;
1431
1888
  }
1432
1889
 
1433
1890
 
@@ -1452,17 +1909,54 @@ static int merge_index_insert_reuc(
1452
1909
  }
1453
1910
 
1454
1911
  mode[idx] = entry->mode;
1455
- oid[idx] = &entry->oid;
1912
+ oid[idx] = &entry->id;
1456
1913
 
1457
1914
  return git_index_reuc_add(index, entry->path,
1458
1915
  mode[0], oid[0], mode[1], oid[1], mode[2], oid[2]);
1459
1916
  }
1460
1917
 
1461
- int index_from_diff_list(git_index **out, git_merge_diff_list *diff_list)
1918
+ static int index_update_reuc(git_index *index, git_merge_diff_list *diff_list)
1919
+ {
1920
+ int error;
1921
+ size_t i;
1922
+ git_merge_diff *conflict;
1923
+
1924
+ /* Add each entry in the resolved conflict to the REUC independently, since
1925
+ * the paths may differ due to renames. */
1926
+ git_vector_foreach(&diff_list->resolved, i, conflict) {
1927
+ const git_index_entry *ancestor =
1928
+ GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
1929
+ &conflict->ancestor_entry : NULL;
1930
+
1931
+ const git_index_entry *ours =
1932
+ GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
1933
+ &conflict->our_entry : NULL;
1934
+
1935
+ const git_index_entry *theirs =
1936
+ GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
1937
+ &conflict->their_entry : NULL;
1938
+
1939
+ if (ancestor != NULL &&
1940
+ (error = merge_index_insert_reuc(index, TREE_IDX_ANCESTOR, ancestor)) < 0)
1941
+ return error;
1942
+
1943
+ if (ours != NULL &&
1944
+ (error = merge_index_insert_reuc(index, TREE_IDX_OURS, ours)) < 0)
1945
+ return error;
1946
+
1947
+ if (theirs != NULL &&
1948
+ (error = merge_index_insert_reuc(index, TREE_IDX_THEIRS, theirs)) < 0)
1949
+ return error;
1950
+ }
1951
+
1952
+ return 0;
1953
+ }
1954
+
1955
+ static int index_from_diff_list(git_index **out,
1956
+ git_merge_diff_list *diff_list, bool skip_reuc)
1462
1957
  {
1463
1958
  git_index *index;
1464
1959
  size_t i;
1465
- git_index_entry *entry;
1466
1960
  git_merge_diff *conflict;
1467
1961
  int error = 0;
1468
1962
 
@@ -1471,10 +1965,8 @@ int index_from_diff_list(git_index **out, git_merge_diff_list *diff_list)
1471
1965
  if ((error = git_index_new(&index)) < 0)
1472
1966
  return error;
1473
1967
 
1474
- git_vector_foreach(&diff_list->staged, i, entry) {
1475
- if ((error = git_index_add(index, entry)) < 0)
1476
- goto on_error;
1477
- }
1968
+ if ((error = git_index__fill(index, &diff_list->staged)) < 0)
1969
+ goto on_error;
1478
1970
 
1479
1971
  git_vector_foreach(&diff_list->conflicts, i, conflict) {
1480
1972
  const git_index_entry *ancestor =
@@ -1517,31 +2009,8 @@ int index_from_diff_list(git_index **out, git_merge_diff_list *diff_list)
1517
2009
  }
1518
2010
  }
1519
2011
 
1520
- /* Add each entry in the resolved conflict to the REUC independently, since
1521
- * the paths may differ due to renames. */
1522
- git_vector_foreach(&diff_list->resolved, i, conflict) {
1523
- const git_index_entry *ancestor =
1524
- GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
1525
- &conflict->ancestor_entry : NULL;
1526
-
1527
- const git_index_entry *ours =
1528
- GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
1529
- &conflict->our_entry : NULL;
1530
-
1531
- const git_index_entry *theirs =
1532
- GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
1533
- &conflict->their_entry : NULL;
1534
-
1535
- if (ancestor != NULL &&
1536
- (error = merge_index_insert_reuc(index, TREE_IDX_ANCESTOR, ancestor)) < 0)
1537
- goto on_error;
1538
-
1539
- if (ours != NULL &&
1540
- (error = merge_index_insert_reuc(index, TREE_IDX_OURS, ours)) < 0)
1541
- goto on_error;
1542
-
1543
- if (theirs != NULL &&
1544
- (error = merge_index_insert_reuc(index, TREE_IDX_THEIRS, theirs)) < 0)
2012
+ if (!skip_reuc) {
2013
+ if ((error = index_update_reuc(index, diff_list)) < 0)
1545
2014
  goto on_error;
1546
2015
  }
1547
2016
 
@@ -1550,36 +2019,74 @@ int index_from_diff_list(git_index **out, git_merge_diff_list *diff_list)
1550
2019
 
1551
2020
  on_error:
1552
2021
  git_index_free(index);
1553
-
1554
2022
  return error;
1555
2023
  }
1556
2024
 
1557
- int git_merge_trees(
2025
+ static git_iterator *iterator_given_or_empty(git_iterator **empty, git_iterator *given)
2026
+ {
2027
+ git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2028
+
2029
+ if (given)
2030
+ return given;
2031
+
2032
+ opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2033
+
2034
+ if (git_iterator_for_nothing(empty, &opts) < 0)
2035
+ return NULL;
2036
+
2037
+ return *empty;
2038
+ }
2039
+
2040
+ int git_merge__iterators(
1558
2041
  git_index **out,
1559
2042
  git_repository *repo,
1560
- const git_tree *ancestor_tree,
1561
- const git_tree *our_tree,
1562
- const git_tree *their_tree,
1563
- const git_merge_tree_opts *given_opts)
2043
+ git_iterator *ancestor_iter,
2044
+ git_iterator *our_iter,
2045
+ git_iterator *theirs_iter,
2046
+ const git_merge_options *given_opts)
1564
2047
  {
2048
+ git_iterator *empty_ancestor = NULL,
2049
+ *empty_ours = NULL,
2050
+ *empty_theirs = NULL;
1565
2051
  git_merge_diff_list *diff_list;
1566
- git_merge_tree_opts opts;
2052
+ git_merge_options opts;
2053
+ git_merge_file_options file_opts = GIT_MERGE_FILE_OPTIONS_INIT;
1567
2054
  git_merge_diff *conflict;
1568
2055
  git_vector changes;
1569
2056
  size_t i;
1570
2057
  int error = 0;
1571
2058
 
1572
- assert(out && repo && our_tree && their_tree);
2059
+ assert(out && repo);
1573
2060
 
1574
2061
  *out = NULL;
1575
2062
 
1576
- if ((error = merge_tree_normalize_opts(repo, &opts, given_opts)) < 0)
2063
+ GIT_ERROR_CHECK_VERSION(
2064
+ given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
2065
+
2066
+ if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
1577
2067
  return error;
1578
2068
 
2069
+ file_opts.favor = opts.file_favor;
2070
+ file_opts.flags = opts.file_flags;
2071
+
2072
+ /* use the git-inspired labels when virtual base building */
2073
+ if (opts.flags & GIT_MERGE__VIRTUAL_BASE) {
2074
+ file_opts.ancestor_label = "merged common ancestors";
2075
+ file_opts.our_label = "Temporary merge branch 1";
2076
+ file_opts.their_label = "Temporary merge branch 2";
2077
+ file_opts.flags |= GIT_MERGE_FILE_FAVOR__CONFLICTED;
2078
+ file_opts.marker_size = GIT_MERGE_CONFLICT_MARKER_SIZE + 2;
2079
+ }
2080
+
1579
2081
  diff_list = git_merge_diff_list__alloc(repo);
1580
- GITERR_CHECK_ALLOC(diff_list);
2082
+ GIT_ERROR_CHECK_ALLOC(diff_list);
2083
+
2084
+ ancestor_iter = iterator_given_or_empty(&empty_ancestor, ancestor_iter);
2085
+ our_iter = iterator_given_or_empty(&empty_ours, our_iter);
2086
+ theirs_iter = iterator_given_or_empty(&empty_theirs, theirs_iter);
1581
2087
 
1582
- if ((error = git_merge_diff_list__find_differences(diff_list, ancestor_tree, our_tree, their_tree)) < 0 ||
2088
+ if ((error = git_merge_diff_list__find_differences(
2089
+ diff_list, ancestor_iter, our_iter, theirs_iter)) < 0 ||
1583
2090
  (error = git_merge_diff_list__find_renames(repo, diff_list, &opts)) < 0)
1584
2091
  goto done;
1585
2092
 
@@ -1589,115 +2096,387 @@ int git_merge_trees(
1589
2096
  git_vector_foreach(&changes, i, conflict) {
1590
2097
  int resolved = 0;
1591
2098
 
1592
- if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.automerge_flags)) < 0)
2099
+ if ((error = merge_conflict_resolve(
2100
+ &resolved, diff_list, conflict, &opts, &file_opts)) < 0)
1593
2101
  goto done;
1594
2102
 
1595
- if (!resolved)
2103
+ if (!resolved) {
2104
+ if ((opts.flags & GIT_MERGE_FAIL_ON_CONFLICT)) {
2105
+ git_error_set(GIT_ERROR_MERGE, "merge conflicts exist");
2106
+ error = GIT_EMERGECONFLICT;
2107
+ goto done;
2108
+ }
2109
+
1596
2110
  git_vector_insert(&diff_list->conflicts, conflict);
2111
+ }
1597
2112
  }
1598
2113
 
2114
+ error = index_from_diff_list(out, diff_list,
2115
+ (opts.flags & GIT_MERGE_SKIP_REUC));
2116
+
2117
+ done:
1599
2118
  if (!given_opts || !given_opts->metric)
1600
2119
  git__free(opts.metric);
1601
2120
 
1602
- error = index_from_diff_list(out, diff_list);
2121
+ git__free((char *)opts.default_driver);
1603
2122
 
1604
- done:
1605
2123
  git_merge_diff_list__free(diff_list);
2124
+ git_iterator_free(empty_ancestor);
2125
+ git_iterator_free(empty_ours);
2126
+ git_iterator_free(empty_theirs);
1606
2127
 
1607
2128
  return error;
1608
2129
  }
1609
2130
 
1610
- /* Merge setup / cleanup */
2131
+ int git_merge_trees(
2132
+ git_index **out,
2133
+ git_repository *repo,
2134
+ const git_tree *ancestor_tree,
2135
+ const git_tree *our_tree,
2136
+ const git_tree *their_tree,
2137
+ const git_merge_options *merge_opts)
2138
+ {
2139
+ git_iterator *ancestor_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2140
+ git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2141
+ int error;
2142
+
2143
+ assert(out && repo);
2144
+
2145
+ /* if one side is treesame to the ancestor, take the other side */
2146
+ if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
2147
+ const git_tree *result = NULL;
2148
+ const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree);
2149
+
2150
+ if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree)))
2151
+ result = their_tree;
2152
+ else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree)))
2153
+ result = our_tree;
2154
+
2155
+ if (result) {
2156
+ if ((error = git_index_new(out)) == 0)
2157
+ error = git_index_read_tree(*out, result);
2158
+
2159
+ return error;
2160
+ }
2161
+ }
2162
+
2163
+ iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2164
+
2165
+ if ((error = git_iterator_for_tree(
2166
+ &ancestor_iter, (git_tree *)ancestor_tree, &iter_opts)) < 0 ||
2167
+ (error = git_iterator_for_tree(
2168
+ &our_iter, (git_tree *)our_tree, &iter_opts)) < 0 ||
2169
+ (error = git_iterator_for_tree(
2170
+ &their_iter, (git_tree *)their_tree, &iter_opts)) < 0)
2171
+ goto done;
1611
2172
 
1612
- static int write_orig_head(
2173
+ error = git_merge__iterators(
2174
+ out, repo, ancestor_iter, our_iter, their_iter, merge_opts);
2175
+
2176
+ done:
2177
+ git_iterator_free(ancestor_iter);
2178
+ git_iterator_free(our_iter);
2179
+ git_iterator_free(their_iter);
2180
+
2181
+ return error;
2182
+ }
2183
+
2184
+ static int merge_annotated_commits(
2185
+ git_index **index_out,
2186
+ git_annotated_commit **base_out,
1613
2187
  git_repository *repo,
1614
- const git_merge_head *our_head)
2188
+ git_annotated_commit *our_commit,
2189
+ git_annotated_commit *their_commit,
2190
+ size_t recursion_level,
2191
+ const git_merge_options *opts);
2192
+
2193
+ GIT_INLINE(int) insert_head_ids(
2194
+ git_array_oid_t *ids,
2195
+ const git_annotated_commit *annotated_commit)
1615
2196
  {
1616
- git_filebuf file = GIT_FILEBUF_INIT;
1617
- git_buf file_path = GIT_BUF_INIT;
1618
- char orig_oid_str[GIT_OID_HEXSZ + 1];
1619
- int error = 0;
2197
+ git_oid *id;
2198
+ size_t i;
1620
2199
 
1621
- assert(repo && our_head);
2200
+ if (annotated_commit->type == GIT_ANNOTATED_COMMIT_REAL) {
2201
+ id = git_array_alloc(*ids);
2202
+ GIT_ERROR_CHECK_ALLOC(id);
1622
2203
 
1623
- git_oid_tostr(orig_oid_str, GIT_OID_HEXSZ+1, &our_head->oid);
2204
+ git_oid_cpy(id, git_commit_id(annotated_commit->commit));
2205
+ } else {
2206
+ for (i = 0; i < annotated_commit->parents.size; i++) {
2207
+ id = git_array_alloc(*ids);
2208
+ GIT_ERROR_CHECK_ALLOC(id);
1624
2209
 
1625
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 &&
1626
- (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) == 0 &&
1627
- (error = git_filebuf_printf(&file, "%s\n", orig_oid_str)) == 0)
1628
- error = git_filebuf_commit(&file, 0666);
2210
+ git_oid_cpy(id, &annotated_commit->parents.ptr[i]);
2211
+ }
2212
+ }
1629
2213
 
1630
- if (error < 0)
1631
- git_filebuf_cleanup(&file);
2214
+ return 0;
2215
+ }
2216
+
2217
+ static int create_virtual_base(
2218
+ git_annotated_commit **out,
2219
+ git_repository *repo,
2220
+ git_annotated_commit *one,
2221
+ git_annotated_commit *two,
2222
+ const git_merge_options *opts,
2223
+ size_t recursion_level)
2224
+ {
2225
+ git_annotated_commit *result = NULL;
2226
+ git_index *index = NULL;
2227
+ git_merge_options virtual_opts = GIT_MERGE_OPTIONS_INIT;
2228
+
2229
+ /* Conflicts in the merge base creation do not propagate to conflicts
2230
+ * in the result; the conflicted base will act as the common ancestor.
2231
+ */
2232
+ if (opts)
2233
+ memcpy(&virtual_opts, opts, sizeof(git_merge_options));
2234
+
2235
+ virtual_opts.flags &= ~GIT_MERGE_FAIL_ON_CONFLICT;
2236
+ virtual_opts.flags |= GIT_MERGE__VIRTUAL_BASE;
2237
+
2238
+ if ((merge_annotated_commits(&index, NULL, repo, one, two,
2239
+ recursion_level + 1, &virtual_opts)) < 0)
2240
+ return -1;
2241
+
2242
+ result = git__calloc(1, sizeof(git_annotated_commit));
2243
+ GIT_ERROR_CHECK_ALLOC(result);
2244
+ result->type = GIT_ANNOTATED_COMMIT_VIRTUAL;
2245
+ result->index = index;
2246
+
2247
+ insert_head_ids(&result->parents, one);
2248
+ insert_head_ids(&result->parents, two);
2249
+
2250
+ *out = result;
2251
+ return 0;
2252
+ }
2253
+
2254
+ static int compute_base(
2255
+ git_annotated_commit **out,
2256
+ git_repository *repo,
2257
+ const git_annotated_commit *one,
2258
+ const git_annotated_commit *two,
2259
+ const git_merge_options *given_opts,
2260
+ size_t recursion_level)
2261
+ {
2262
+ git_array_oid_t head_ids = GIT_ARRAY_INIT;
2263
+ git_oidarray bases = {0};
2264
+ git_annotated_commit *base = NULL, *other = NULL, *new_base = NULL;
2265
+ git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
2266
+ size_t i, base_count;
2267
+ int error;
2268
+
2269
+ *out = NULL;
2270
+
2271
+ if (given_opts)
2272
+ memcpy(&opts, given_opts, sizeof(git_merge_options));
2273
+
2274
+ /* With more than two commits, merge_bases_many finds the base of
2275
+ * the first commit and a hypothetical merge of the others. Since
2276
+ * "one" may itself be a virtual commit, which insert_head_ids
2277
+ * substitutes multiple ancestors for, it needs to be added
2278
+ * after "two" which is always a single real commit.
2279
+ */
2280
+ if ((error = insert_head_ids(&head_ids, two)) < 0 ||
2281
+ (error = insert_head_ids(&head_ids, one)) < 0 ||
2282
+ (error = git_merge_bases_many(&bases, repo,
2283
+ head_ids.size, head_ids.ptr)) < 0)
2284
+ goto done;
2285
+
2286
+ base_count = (opts.flags & GIT_MERGE_NO_RECURSIVE) ? 0 : bases.count;
2287
+
2288
+ if (base_count)
2289
+ git_oidarray__reverse(&bases);
2290
+
2291
+ if ((error = git_annotated_commit_lookup(&base, repo, &bases.ids[0])) < 0)
2292
+ goto done;
2293
+
2294
+ for (i = 1; i < base_count; i++) {
2295
+ recursion_level++;
2296
+
2297
+ if (opts.recursion_limit && recursion_level > opts.recursion_limit)
2298
+ break;
2299
+
2300
+ if ((error = git_annotated_commit_lookup(&other, repo,
2301
+ &bases.ids[i])) < 0 ||
2302
+ (error = create_virtual_base(&new_base, repo, base, other, &opts,
2303
+ recursion_level)) < 0)
2304
+ goto done;
2305
+
2306
+ git_annotated_commit_free(base);
2307
+ git_annotated_commit_free(other);
2308
+
2309
+ base = new_base;
2310
+ new_base = NULL;
2311
+ other = NULL;
2312
+ }
2313
+
2314
+ done:
2315
+ if (error == 0)
2316
+ *out = base;
2317
+ else
2318
+ git_annotated_commit_free(base);
1632
2319
 
1633
- git_buf_free(&file_path);
2320
+ git_annotated_commit_free(other);
2321
+ git_annotated_commit_free(new_base);
2322
+ git_oidarray_free(&bases);
2323
+ git_array_clear(head_ids);
2324
+ return error;
2325
+ }
2326
+
2327
+ static int iterator_for_annotated_commit(
2328
+ git_iterator **out,
2329
+ git_annotated_commit *commit)
2330
+ {
2331
+ git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2332
+ int error;
2333
+
2334
+ opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
1634
2335
 
2336
+ if (commit == NULL) {
2337
+ error = git_iterator_for_nothing(out, &opts);
2338
+ } else if (commit->type == GIT_ANNOTATED_COMMIT_VIRTUAL) {
2339
+ error = git_iterator_for_index(out, git_index_owner(commit->index), commit->index, &opts);
2340
+ } else {
2341
+ if (!commit->tree &&
2342
+ (error = git_commit_tree(&commit->tree, commit->commit)) < 0)
2343
+ goto done;
2344
+
2345
+ error = git_iterator_for_tree(out, commit->tree, &opts);
2346
+ }
2347
+
2348
+ done:
1635
2349
  return error;
1636
2350
  }
1637
2351
 
2352
+ static int merge_annotated_commits(
2353
+ git_index **index_out,
2354
+ git_annotated_commit **base_out,
2355
+ git_repository *repo,
2356
+ git_annotated_commit *ours,
2357
+ git_annotated_commit *theirs,
2358
+ size_t recursion_level,
2359
+ const git_merge_options *opts)
2360
+ {
2361
+ git_annotated_commit *base = NULL;
2362
+ git_iterator *base_iter = NULL, *our_iter = NULL, *their_iter = NULL;
2363
+ int error;
2364
+
2365
+ if ((error = compute_base(&base, repo, ours, theirs, opts,
2366
+ recursion_level)) < 0) {
2367
+
2368
+ if (error != GIT_ENOTFOUND)
2369
+ goto done;
2370
+
2371
+ git_error_clear();
2372
+ }
2373
+
2374
+ if ((error = iterator_for_annotated_commit(&base_iter, base)) < 0 ||
2375
+ (error = iterator_for_annotated_commit(&our_iter, ours)) < 0 ||
2376
+ (error = iterator_for_annotated_commit(&their_iter, theirs)) < 0 ||
2377
+ (error = git_merge__iterators(index_out, repo, base_iter, our_iter,
2378
+ their_iter, opts)) < 0)
2379
+ goto done;
2380
+
2381
+ if (base_out) {
2382
+ *base_out = base;
2383
+ base = NULL;
2384
+ }
2385
+
2386
+ done:
2387
+ git_annotated_commit_free(base);
2388
+ git_iterator_free(base_iter);
2389
+ git_iterator_free(our_iter);
2390
+ git_iterator_free(their_iter);
2391
+ return error;
2392
+ }
2393
+
2394
+
2395
+ int git_merge_commits(
2396
+ git_index **out,
2397
+ git_repository *repo,
2398
+ const git_commit *our_commit,
2399
+ const git_commit *their_commit,
2400
+ const git_merge_options *opts)
2401
+ {
2402
+ git_annotated_commit *ours = NULL, *theirs = NULL, *base = NULL;
2403
+ int error = 0;
2404
+
2405
+ if ((error = git_annotated_commit_from_commit(&ours, (git_commit *)our_commit)) < 0 ||
2406
+ (error = git_annotated_commit_from_commit(&theirs, (git_commit *)their_commit)) < 0)
2407
+ goto done;
2408
+
2409
+ error = merge_annotated_commits(out, &base, repo, ours, theirs, 0, opts);
2410
+
2411
+ done:
2412
+ git_annotated_commit_free(ours);
2413
+ git_annotated_commit_free(theirs);
2414
+ git_annotated_commit_free(base);
2415
+ return error;
2416
+ }
2417
+
2418
+ /* Merge setup / cleanup */
2419
+
1638
2420
  static int write_merge_head(
1639
2421
  git_repository *repo,
1640
- const git_merge_head *heads[],
2422
+ const git_annotated_commit *heads[],
1641
2423
  size_t heads_len)
1642
2424
  {
1643
2425
  git_filebuf file = GIT_FILEBUF_INIT;
1644
2426
  git_buf file_path = GIT_BUF_INIT;
1645
- char merge_oid_str[GIT_OID_HEXSZ + 1];
1646
2427
  size_t i;
1647
2428
  int error = 0;
1648
2429
 
1649
2430
  assert(repo && heads);
1650
2431
 
1651
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_HEAD_FILE)) < 0 ||
1652
- (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0)
2432
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 ||
2433
+ (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
1653
2434
  goto cleanup;
1654
2435
 
1655
2436
  for (i = 0; i < heads_len; i++) {
1656
- git_oid_tostr(merge_oid_str, GIT_OID_HEXSZ+1, &heads[i]->oid);
1657
-
1658
- if ((error = git_filebuf_printf(&file, "%s\n", merge_oid_str)) < 0)
2437
+ if ((error = git_filebuf_printf(&file, "%s\n", heads[i]->id_str)) < 0)
1659
2438
  goto cleanup;
1660
2439
  }
1661
2440
 
1662
- error = git_filebuf_commit(&file, 0666);
2441
+ error = git_filebuf_commit(&file);
1663
2442
 
1664
2443
  cleanup:
1665
2444
  if (error < 0)
1666
2445
  git_filebuf_cleanup(&file);
1667
2446
 
1668
- git_buf_free(&file_path);
2447
+ git_buf_dispose(&file_path);
1669
2448
 
1670
2449
  return error;
1671
2450
  }
1672
2451
 
1673
- static int write_merge_mode(git_repository *repo, unsigned int flags)
2452
+ static int write_merge_mode(git_repository *repo)
1674
2453
  {
1675
2454
  git_filebuf file = GIT_FILEBUF_INIT;
1676
2455
  git_buf file_path = GIT_BUF_INIT;
1677
2456
  int error = 0;
1678
2457
 
1679
- /* For future expansion */
1680
- GIT_UNUSED(flags);
1681
-
1682
2458
  assert(repo);
1683
2459
 
1684
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 ||
1685
- (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0)
2460
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 ||
2461
+ (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
1686
2462
  goto cleanup;
1687
2463
 
1688
- error = git_filebuf_commit(&file, 0666);
2464
+ if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0)
2465
+ goto cleanup;
2466
+
2467
+ error = git_filebuf_commit(&file);
1689
2468
 
1690
2469
  cleanup:
1691
2470
  if (error < 0)
1692
2471
  git_filebuf_cleanup(&file);
1693
2472
 
1694
- git_buf_free(&file_path);
2473
+ git_buf_dispose(&file_path);
1695
2474
 
1696
2475
  return error;
1697
2476
  }
1698
2477
 
1699
2478
  struct merge_msg_entry {
1700
- const git_merge_head *merge_head;
2479
+ const git_annotated_commit *merge_head;
1701
2480
  bool written;
1702
2481
  };
1703
2482
 
@@ -1885,12 +2664,11 @@ static int merge_msg_write_remotes(
1885
2664
 
1886
2665
  static int write_merge_msg(
1887
2666
  git_repository *repo,
1888
- const git_merge_head *heads[],
2667
+ const git_annotated_commit *heads[],
1889
2668
  size_t heads_len)
1890
2669
  {
1891
2670
  git_filebuf file = GIT_FILEBUF_INIT;
1892
2671
  git_buf file_path = GIT_BUF_INIT;
1893
- char oid_str[GIT_OID_HEXSZ + 1];
1894
2672
  struct merge_msg_entry *entries;
1895
2673
  git_vector matching = GIT_VECTOR_INIT;
1896
2674
  size_t i;
@@ -1900,16 +2678,18 @@ static int write_merge_msg(
1900
2678
  assert(repo && heads);
1901
2679
 
1902
2680
  entries = git__calloc(heads_len, sizeof(struct merge_msg_entry));
1903
- GITERR_CHECK_ALLOC(entries);
2681
+ GIT_ERROR_CHECK_ALLOC(entries);
1904
2682
 
1905
- if (git_vector_init(&matching, heads_len, NULL) < 0)
2683
+ if (git_vector_init(&matching, heads_len, NULL) < 0) {
2684
+ git__free(entries);
1906
2685
  return -1;
2686
+ }
1907
2687
 
1908
2688
  for (i = 0; i < heads_len; i++)
1909
2689
  entries[i].merge_head = heads[i];
1910
2690
 
1911
- if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
1912
- (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0 ||
2691
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
2692
+ (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0 ||
1913
2693
  (error = git_filebuf_write(&file, "Merge ", 6)) < 0)
1914
2694
  goto cleanup;
1915
2695
 
@@ -1928,10 +2708,9 @@ static int write_merge_msg(
1928
2708
  if (!msg_entry_is_oid(&entries[i]))
1929
2709
  break;
1930
2710
 
1931
- git_oid_fmt(oid_str, &entries[i].merge_head->oid);
1932
- oid_str[GIT_OID_HEXSZ] = '\0';
1933
-
1934
- if ((error = git_filebuf_printf(&file, "%scommit '%s'", (i > 0) ? "; " : "", oid_str)) < 0)
2711
+ if ((error = git_filebuf_printf(&file,
2712
+ "%scommit '%s'", (i > 0) ? "; " : "",
2713
+ entries[i].merge_head->id_str)) < 0)
1935
2714
  goto cleanup;
1936
2715
 
1937
2716
  entries[i].written = 1;
@@ -1953,7 +2732,7 @@ static int write_merge_msg(
1953
2732
 
1954
2733
  if (matching.length)
1955
2734
  sep =',';
1956
-
2735
+
1957
2736
  if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tag)) < 0 ||
1958
2737
  (error = merge_msg_write_tags(&file, &matching, sep)) < 0)
1959
2738
  goto cleanup;
@@ -1978,22 +2757,20 @@ static int write_merge_msg(
1978
2757
  if (merge_msg_entry_written(&entries[i]))
1979
2758
  continue;
1980
2759
 
1981
- git_oid_fmt(oid_str, &entries[i].merge_head->oid);
1982
- oid_str[GIT_OID_HEXSZ] = '\0';
1983
-
1984
- if ((error = git_filebuf_printf(&file, "; commit '%s'", oid_str)) < 0)
2760
+ if ((error = git_filebuf_printf(&file, "; commit '%s'",
2761
+ entries[i].merge_head->id_str)) < 0)
1985
2762
  goto cleanup;
1986
2763
  }
1987
2764
 
1988
2765
  if ((error = git_filebuf_printf(&file, "\n")) < 0 ||
1989
- (error = git_filebuf_commit(&file, 0666)) < 0)
2766
+ (error = git_filebuf_commit(&file)) < 0)
1990
2767
  goto cleanup;
1991
2768
 
1992
2769
  cleanup:
1993
2770
  if (error < 0)
1994
2771
  git_filebuf_cleanup(&file);
1995
2772
 
1996
- git_buf_free(&file_path);
2773
+ git_buf_dispose(&file_path);
1997
2774
 
1998
2775
  git_vector_free(&matching);
1999
2776
  git__free(entries);
@@ -2003,154 +2780,577 @@ cleanup:
2003
2780
 
2004
2781
  int git_merge__setup(
2005
2782
  git_repository *repo,
2006
- const git_merge_head *our_head,
2007
- const git_merge_head *heads[],
2008
- size_t heads_len,
2009
- unsigned int flags)
2783
+ const git_annotated_commit *our_head,
2784
+ const git_annotated_commit *heads[],
2785
+ size_t heads_len)
2010
2786
  {
2011
2787
  int error = 0;
2012
2788
 
2013
2789
  assert (repo && our_head && heads);
2014
-
2015
- if ((error = write_orig_head(repo, our_head)) == 0 &&
2790
+
2791
+ if ((error = git_repository__set_orig_head(repo, git_annotated_commit_id(our_head))) == 0 &&
2016
2792
  (error = write_merge_head(repo, heads, heads_len)) == 0 &&
2017
- (error = write_merge_mode(repo, flags)) == 0) {
2793
+ (error = write_merge_mode(repo)) == 0) {
2018
2794
  error = write_merge_msg(repo, heads, heads_len);
2019
2795
  }
2020
2796
 
2021
2797
  return error;
2022
2798
  }
2023
2799
 
2024
- int git_repository_merge_cleanup(git_repository *repo)
2800
+ /* Merge branches */
2801
+
2802
+ static int merge_ancestor_head(
2803
+ git_annotated_commit **ancestor_head,
2804
+ git_repository *repo,
2805
+ const git_annotated_commit *our_head,
2806
+ const git_annotated_commit **their_heads,
2807
+ size_t their_heads_len)
2025
2808
  {
2809
+ git_oid *oids, ancestor_oid;
2810
+ size_t i, alloc_len;
2026
2811
  int error = 0;
2027
- git_buf merge_head_path = GIT_BUF_INIT,
2028
- merge_mode_path = GIT_BUF_INIT,
2029
- merge_msg_path = GIT_BUF_INIT;
2030
2812
 
2031
- assert(repo);
2813
+ assert(repo && our_head && their_heads);
2032
2814
 
2033
- if (git_buf_joinpath(&merge_head_path, repo->path_repository, GIT_MERGE_HEAD_FILE) < 0 ||
2034
- git_buf_joinpath(&merge_mode_path, repo->path_repository, GIT_MERGE_MODE_FILE) < 0 ||
2035
- git_buf_joinpath(&merge_msg_path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
2036
- return -1;
2815
+ GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, their_heads_len, 1);
2816
+ oids = git__calloc(alloc_len, sizeof(git_oid));
2817
+ GIT_ERROR_CHECK_ALLOC(oids);
2037
2818
 
2038
- if (git_path_isfile(merge_head_path.ptr)) {
2039
- if ((error = p_unlink(merge_head_path.ptr)) < 0)
2040
- goto cleanup;
2041
- }
2819
+ git_oid_cpy(&oids[0], git_commit_id(our_head->commit));
2042
2820
 
2043
- if (git_path_isfile(merge_mode_path.ptr))
2044
- (void)p_unlink(merge_mode_path.ptr);
2821
+ for (i = 0; i < their_heads_len; i++)
2822
+ git_oid_cpy(&oids[i + 1], git_annotated_commit_id(their_heads[i]));
2045
2823
 
2046
- if (git_path_isfile(merge_msg_path.ptr))
2047
- (void)p_unlink(merge_msg_path.ptr);
2824
+ if ((error = git_merge_base_many(&ancestor_oid, repo, their_heads_len + 1, oids)) < 0)
2825
+ goto on_error;
2048
2826
 
2049
- cleanup:
2050
- git_buf_free(&merge_msg_path);
2051
- git_buf_free(&merge_mode_path);
2052
- git_buf_free(&merge_head_path);
2827
+ error = git_annotated_commit_lookup(ancestor_head, repo, &ancestor_oid);
2053
2828
 
2829
+ on_error:
2830
+ git__free(oids);
2054
2831
  return error;
2055
2832
  }
2056
2833
 
2057
- /* Merge heads are the input to merge */
2834
+ const char *merge_their_label(const char *branchname)
2835
+ {
2836
+ const char *slash;
2837
+
2838
+ if ((slash = strrchr(branchname, '/')) == NULL)
2839
+ return branchname;
2840
+
2841
+ if (*(slash+1) == '\0')
2842
+ return "theirs";
2843
+
2844
+ return slash+1;
2845
+ }
2058
2846
 
2059
- static int merge_head_init(
2060
- git_merge_head **out,
2847
+ static int merge_normalize_checkout_opts(
2848
+ git_checkout_options *out,
2061
2849
  git_repository *repo,
2062
- const char *ref_name,
2063
- const char *remote_url,
2064
- const git_oid *oid)
2850
+ const git_checkout_options *given_checkout_opts,
2851
+ unsigned int checkout_strategy,
2852
+ git_annotated_commit *ancestor,
2853
+ const git_annotated_commit *our_head,
2854
+ const git_annotated_commit **their_heads,
2855
+ size_t their_heads_len)
2065
2856
  {
2066
- git_merge_head *head;
2857
+ git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
2067
2858
  int error = 0;
2068
2859
 
2069
- assert(out && oid);
2860
+ GIT_UNUSED(repo);
2070
2861
 
2071
- *out = NULL;
2862
+ if (given_checkout_opts != NULL)
2863
+ memcpy(out, given_checkout_opts, sizeof(git_checkout_options));
2864
+ else
2865
+ memcpy(out, &default_checkout_opts, sizeof(git_checkout_options));
2072
2866
 
2073
- head = git__calloc(1, sizeof(git_merge_head));
2074
- GITERR_CHECK_ALLOC(head);
2867
+ out->checkout_strategy = checkout_strategy;
2075
2868
 
2076
- if (ref_name) {
2077
- head->ref_name = git__strdup(ref_name);
2078
- GITERR_CHECK_ALLOC(head->ref_name);
2869
+ if (!out->ancestor_label) {
2870
+ if (ancestor && ancestor->type == GIT_ANNOTATED_COMMIT_REAL)
2871
+ out->ancestor_label = git_commit_summary(ancestor->commit);
2872
+ else if (ancestor)
2873
+ out->ancestor_label = "merged common ancestors";
2874
+ else
2875
+ out->ancestor_label = "empty base";
2079
2876
  }
2080
2877
 
2081
- if (remote_url) {
2082
- head->remote_url = git__strdup(remote_url);
2083
- GITERR_CHECK_ALLOC(head->remote_url);
2878
+ if (!out->our_label) {
2879
+ if (our_head && our_head->ref_name)
2880
+ out->our_label = our_head->ref_name;
2881
+ else
2882
+ out->our_label = "ours";
2084
2883
  }
2085
2884
 
2086
- git_oid_cpy(&head->oid, oid);
2885
+ if (!out->their_label) {
2886
+ if (their_heads_len == 1 && their_heads[0]->ref_name)
2887
+ out->their_label = merge_their_label(their_heads[0]->ref_name);
2888
+ else if (their_heads_len == 1)
2889
+ out->their_label = their_heads[0]->id_str;
2890
+ else
2891
+ out->their_label = "theirs";
2892
+ }
2087
2893
 
2088
- if ((error = git_commit_lookup(&head->commit, repo, &head->oid)) < 0) {
2089
- git_merge_head_free(head);
2090
- return error;
2894
+ return error;
2895
+ }
2896
+
2897
+ static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
2898
+ {
2899
+ git_tree *head_tree = NULL;
2900
+ git_index *index_repo = NULL;
2901
+ git_iterator *iter_repo = NULL, *iter_new = NULL;
2902
+ git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
2903
+ git_diff *staged_diff_list = NULL, *index_diff_list = NULL;
2904
+ git_diff_delta *delta;
2905
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
2906
+ git_vector staged_paths = GIT_VECTOR_INIT;
2907
+ size_t i;
2908
+ int error = 0;
2909
+
2910
+ GIT_UNUSED(merged_paths);
2911
+
2912
+ *conflicts = 0;
2913
+
2914
+ /* No staged changes may exist unless the change staged is identical to
2915
+ * the result of the merge. This allows one to apply to merge manually,
2916
+ * then run merge. Any other staged change would be overwritten by
2917
+ * a reset merge.
2918
+ */
2919
+ if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
2920
+ (error = git_repository_index(&index_repo, repo)) < 0 ||
2921
+ (error = git_diff_tree_to_index(&staged_diff_list, repo, head_tree, index_repo, &opts)) < 0)
2922
+ goto done;
2923
+
2924
+ if (staged_diff_list->deltas.length == 0)
2925
+ goto done;
2926
+
2927
+ git_vector_foreach(&staged_diff_list->deltas, i, delta) {
2928
+ if ((error = git_vector_insert(&staged_paths, (char *)delta->new_file.path)) < 0)
2929
+ goto done;
2091
2930
  }
2092
2931
 
2093
- *out = head;
2932
+ iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
2933
+ iter_opts.pathlist.strings = (char **)staged_paths.contents;
2934
+ iter_opts.pathlist.count = staged_paths.length;
2935
+
2936
+ if ((error = git_iterator_for_index(&iter_repo, repo, index_repo, &iter_opts)) < 0 ||
2937
+ (error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
2938
+ (error = git_diff__from_iterators(&index_diff_list, repo, iter_repo, iter_new, &opts)) < 0)
2939
+ goto done;
2940
+
2941
+ *conflicts = index_diff_list->deltas.length;
2942
+
2943
+ done:
2944
+ git_tree_free(head_tree);
2945
+ git_index_free(index_repo);
2946
+ git_iterator_free(iter_repo);
2947
+ git_iterator_free(iter_new);
2948
+ git_diff_free(staged_diff_list);
2949
+ git_diff_free(index_diff_list);
2950
+ git_vector_free(&staged_paths);
2951
+
2094
2952
  return error;
2095
2953
  }
2096
2954
 
2097
- int git_merge_head_from_ref(
2098
- git_merge_head **out,
2955
+ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
2956
+ {
2957
+ git_diff *wd_diff_list = NULL;
2958
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
2959
+ int error = 0;
2960
+
2961
+ GIT_UNUSED(index_new);
2962
+
2963
+ *conflicts = 0;
2964
+
2965
+ /* We need to have merged at least 1 file for the possibility to exist to
2966
+ * have conflicts with the workdir. Passing 0 as the pathspec count paramter
2967
+ * will consider all files in the working directory, that is, we may detect
2968
+ * a conflict if there were untracked files in the workdir prior to starting
2969
+ * the merge. This typically happens when cherry-picking a commmit whose
2970
+ * changes have already been applied.
2971
+ */
2972
+ if (merged_paths->length == 0)
2973
+ return 0;
2974
+
2975
+ opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
2976
+
2977
+ /* Workdir changes may exist iff they do not conflict with changes that
2978
+ * will be applied by the merge (including conflicts). Ensure that there
2979
+ * are no changes in the workdir to these paths.
2980
+ */
2981
+ opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
2982
+ opts.pathspec.count = merged_paths->length;
2983
+ opts.pathspec.strings = (char **)merged_paths->contents;
2984
+ opts.ignore_submodules = GIT_SUBMODULE_IGNORE_ALL;
2985
+
2986
+ if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
2987
+ goto done;
2988
+
2989
+ *conflicts = wd_diff_list->deltas.length;
2990
+
2991
+ done:
2992
+ git_diff_free(wd_diff_list);
2993
+
2994
+ return error;
2995
+ }
2996
+
2997
+ int git_merge__check_result(git_repository *repo, git_index *index_new)
2998
+ {
2999
+ git_tree *head_tree = NULL;
3000
+ git_iterator *iter_head = NULL, *iter_new = NULL;
3001
+ git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
3002
+ git_diff *merged_list = NULL;
3003
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
3004
+ git_diff_delta *delta;
3005
+ git_vector paths = GIT_VECTOR_INIT;
3006
+ size_t i, index_conflicts = 0, wd_conflicts = 0, conflicts;
3007
+ const git_index_entry *e;
3008
+ int error = 0;
3009
+
3010
+ iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
3011
+
3012
+ if ((error = git_repository_head_tree(&head_tree, repo)) < 0 ||
3013
+ (error = git_iterator_for_tree(&iter_head, head_tree, &iter_opts)) < 0 ||
3014
+ (error = git_iterator_for_index(&iter_new, repo, index_new, &iter_opts)) < 0 ||
3015
+ (error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0)
3016
+ goto done;
3017
+
3018
+ git_vector_foreach(&merged_list->deltas, i, delta) {
3019
+ if ((error = git_vector_insert(&paths, (char *)delta->new_file.path)) < 0)
3020
+ goto done;
3021
+ }
3022
+
3023
+ for (i = 0; i < git_index_entrycount(index_new); i++) {
3024
+ e = git_index_get_byindex(index_new, i);
3025
+
3026
+ if (git_index_entry_is_conflict(e) &&
3027
+ (git_vector_last(&paths) == NULL ||
3028
+ strcmp(git_vector_last(&paths), e->path) != 0)) {
3029
+
3030
+ if ((error = git_vector_insert(&paths, (char *)e->path)) < 0)
3031
+ goto done;
3032
+ }
3033
+ }
3034
+
3035
+ /* Make sure the index and workdir state do not prevent merging */
3036
+ if ((error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 ||
3037
+ (error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0)
3038
+ goto done;
3039
+
3040
+ if ((conflicts = index_conflicts + wd_conflicts) > 0) {
3041
+ git_error_set(GIT_ERROR_MERGE, "%" PRIuZ " uncommitted change%s would be overwritten by merge",
3042
+ conflicts, (conflicts != 1) ? "s" : "");
3043
+ error = GIT_ECONFLICT;
3044
+ }
3045
+
3046
+ done:
3047
+ git_vector_free(&paths);
3048
+ git_tree_free(head_tree);
3049
+ git_iterator_free(iter_head);
3050
+ git_iterator_free(iter_new);
3051
+ git_diff_free(merged_list);
3052
+
3053
+ return error;
3054
+ }
3055
+
3056
+ int git_merge__append_conflicts_to_merge_msg(
3057
+ git_repository *repo,
3058
+ git_index *index)
3059
+ {
3060
+ git_filebuf file = GIT_FILEBUF_INIT;
3061
+ git_buf file_path = GIT_BUF_INIT;
3062
+ const char *last = NULL;
3063
+ size_t i;
3064
+ int error;
3065
+
3066
+ if (!git_index_has_conflicts(index))
3067
+ return 0;
3068
+
3069
+ if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 ||
3070
+ (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0)
3071
+ goto cleanup;
3072
+
3073
+ git_filebuf_printf(&file, "\nConflicts:\n");
3074
+
3075
+ for (i = 0; i < git_index_entrycount(index); i++) {
3076
+ const git_index_entry *e = git_index_get_byindex(index, i);
3077
+
3078
+ if (!git_index_entry_is_conflict(e))
3079
+ continue;
3080
+
3081
+ if (last == NULL || strcmp(e->path, last) != 0)
3082
+ git_filebuf_printf(&file, "\t%s\n", e->path);
3083
+
3084
+ last = e->path;
3085
+ }
3086
+
3087
+ error = git_filebuf_commit(&file);
3088
+
3089
+ cleanup:
3090
+ if (error < 0)
3091
+ git_filebuf_cleanup(&file);
3092
+
3093
+ git_buf_dispose(&file_path);
3094
+
3095
+ return error;
3096
+ }
3097
+
3098
+ static int merge_state_cleanup(git_repository *repo)
3099
+ {
3100
+ const char *state_files[] = {
3101
+ GIT_MERGE_HEAD_FILE,
3102
+ GIT_MERGE_MODE_FILE,
3103
+ GIT_MERGE_MSG_FILE,
3104
+ };
3105
+
3106
+ return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
3107
+ }
3108
+
3109
+ static int merge_heads(
3110
+ git_annotated_commit **ancestor_head_out,
3111
+ git_annotated_commit **our_head_out,
2099
3112
  git_repository *repo,
2100
- git_reference *ref)
3113
+ git_reference *our_ref,
3114
+ const git_annotated_commit **their_heads,
3115
+ size_t their_heads_len)
2101
3116
  {
2102
- git_reference *resolved;
3117
+ git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
2103
3118
  int error = 0;
2104
3119
 
2105
- assert(out && repo && ref);
3120
+ *ancestor_head_out = NULL;
3121
+ *our_head_out = NULL;
2106
3122
 
2107
- *out = NULL;
3123
+ if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
3124
+ goto done;
2108
3125
 
2109
- if ((error = git_reference_resolve(&resolved, ref)) < 0)
2110
- return error;
2111
-
2112
- error = merge_head_init(out, repo, git_reference_name(ref), NULL,
2113
- git_reference_target(resolved));
3126
+ if ((error = git_annotated_commit_from_ref(&our_head, repo, our_ref)) < 0)
3127
+ goto done;
3128
+
3129
+ if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0) {
3130
+ if (error != GIT_ENOTFOUND)
3131
+ goto done;
3132
+
3133
+ git_error_clear();
3134
+ error = 0;
3135
+ }
3136
+
3137
+ *ancestor_head_out = ancestor_head;
3138
+ *our_head_out = our_head;
3139
+
3140
+ done:
3141
+ if (error < 0) {
3142
+ git_annotated_commit_free(ancestor_head);
3143
+ git_annotated_commit_free(our_head);
3144
+ }
2114
3145
 
2115
- git_reference_free(resolved);
2116
3146
  return error;
2117
3147
  }
2118
3148
 
2119
- int git_merge_head_from_oid(
2120
- git_merge_head **out,
3149
+ static int merge_preference(git_merge_preference_t *out, git_repository *repo)
3150
+ {
3151
+ git_config *config;
3152
+ const char *value;
3153
+ int bool_value, error = 0;
3154
+
3155
+ *out = GIT_MERGE_PREFERENCE_NONE;
3156
+
3157
+ if ((error = git_repository_config_snapshot(&config, repo)) < 0)
3158
+ goto done;
3159
+
3160
+ if ((error = git_config_get_string(&value, config, "merge.ff")) < 0) {
3161
+ if (error == GIT_ENOTFOUND) {
3162
+ git_error_clear();
3163
+ error = 0;
3164
+ }
3165
+
3166
+ goto done;
3167
+ }
3168
+
3169
+ if (git_config_parse_bool(&bool_value, value) == 0) {
3170
+ if (!bool_value)
3171
+ *out |= GIT_MERGE_PREFERENCE_NO_FASTFORWARD;
3172
+ } else {
3173
+ if (strcasecmp(value, "only") == 0)
3174
+ *out |= GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY;
3175
+ }
3176
+
3177
+ done:
3178
+ git_config_free(config);
3179
+ return error;
3180
+ }
3181
+
3182
+ int git_merge_analysis_for_ref(
3183
+ git_merge_analysis_t *analysis_out,
3184
+ git_merge_preference_t *preference_out,
2121
3185
  git_repository *repo,
2122
- const git_oid *oid)
3186
+ git_reference *our_ref,
3187
+ const git_annotated_commit **their_heads,
3188
+ size_t their_heads_len)
2123
3189
  {
2124
- assert(out && repo && oid);
3190
+ git_annotated_commit *ancestor_head = NULL, *our_head = NULL;
3191
+ int error = 0;
3192
+ bool unborn;
3193
+
3194
+ assert(analysis_out && preference_out && repo && their_heads && their_heads_len > 0);
2125
3195
 
2126
- return merge_head_init(out, repo, NULL, NULL, oid);
3196
+ if (their_heads_len != 1) {
3197
+ git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
3198
+ error = -1;
3199
+ goto done;
3200
+ }
3201
+
3202
+ *analysis_out = GIT_MERGE_ANALYSIS_NONE;
3203
+
3204
+ if ((error = merge_preference(preference_out, repo)) < 0)
3205
+ goto done;
3206
+
3207
+ if ((error = git_reference__is_unborn_head(&unborn, our_ref, repo)) < 0)
3208
+ goto done;
3209
+
3210
+ if (unborn) {
3211
+ *analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_UNBORN;
3212
+ error = 0;
3213
+ goto done;
3214
+ }
3215
+
3216
+ if ((error = merge_heads(&ancestor_head, &our_head, repo, our_ref, their_heads, their_heads_len)) < 0)
3217
+ goto done;
3218
+
3219
+ /* We're up-to-date if we're trying to merge our own common ancestor. */
3220
+ if (ancestor_head && git_oid_equal(
3221
+ git_annotated_commit_id(ancestor_head), git_annotated_commit_id(their_heads[0])))
3222
+ *analysis_out |= GIT_MERGE_ANALYSIS_UP_TO_DATE;
3223
+
3224
+ /* We're fastforwardable if we're our own common ancestor. */
3225
+ else if (ancestor_head && git_oid_equal(
3226
+ git_annotated_commit_id(ancestor_head), git_annotated_commit_id(our_head)))
3227
+ *analysis_out |= GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
3228
+
3229
+ /* Otherwise, just a normal merge is possible. */
3230
+ else
3231
+ *analysis_out |= GIT_MERGE_ANALYSIS_NORMAL;
3232
+
3233
+ done:
3234
+ git_annotated_commit_free(ancestor_head);
3235
+ git_annotated_commit_free(our_head);
3236
+ return error;
2127
3237
  }
2128
3238
 
2129
- int git_merge_head_from_fetchhead(
2130
- git_merge_head **out,
3239
+ int git_merge_analysis(
3240
+ git_merge_analysis_t *analysis_out,
3241
+ git_merge_preference_t *preference_out,
2131
3242
  git_repository *repo,
2132
- const char *branch_name,
2133
- const char *remote_url,
2134
- const git_oid *oid)
3243
+ const git_annotated_commit **their_heads,
3244
+ size_t their_heads_len)
2135
3245
  {
2136
- assert(repo && branch_name && remote_url && oid);
3246
+ git_reference *head_ref = NULL;
3247
+ int error = 0;
2137
3248
 
2138
- return merge_head_init(out, repo, branch_name, remote_url, oid);
3249
+ if ((error = git_reference_lookup(&head_ref, repo, GIT_HEAD_FILE)) < 0) {
3250
+ git_error_set(GIT_ERROR_MERGE, "failed to lookup HEAD reference");
3251
+ return error;
3252
+ }
3253
+
3254
+ error = git_merge_analysis_for_ref(analysis_out, preference_out, repo, head_ref, their_heads, their_heads_len);
3255
+
3256
+ git_reference_free(head_ref);
3257
+
3258
+ return error;
2139
3259
  }
2140
3260
 
2141
- void git_merge_head_free(git_merge_head *head)
3261
+ int git_merge(
3262
+ git_repository *repo,
3263
+ const git_annotated_commit **their_heads,
3264
+ size_t their_heads_len,
3265
+ const git_merge_options *merge_opts,
3266
+ const git_checkout_options *given_checkout_opts)
2142
3267
  {
2143
- if (head == NULL)
2144
- return;
3268
+ git_reference *our_ref = NULL;
3269
+ git_checkout_options checkout_opts;
3270
+ git_annotated_commit *our_head = NULL, *base = NULL;
3271
+ git_index *repo_index = NULL, *index = NULL;
3272
+ git_indexwriter indexwriter = GIT_INDEXWRITER_INIT;
3273
+ unsigned int checkout_strategy;
3274
+ int error = 0;
3275
+
3276
+ assert(repo && their_heads && their_heads_len > 0);
3277
+
3278
+ if (their_heads_len != 1) {
3279
+ git_error_set(GIT_ERROR_MERGE, "can only merge a single branch");
3280
+ return -1;
3281
+ }
3282
+
3283
+ if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
3284
+ goto done;
3285
+
3286
+ checkout_strategy = given_checkout_opts ?
3287
+ given_checkout_opts->checkout_strategy :
3288
+ GIT_CHECKOUT_SAFE;
3289
+
3290
+ if ((error = git_indexwriter_init_for_operation(&indexwriter, repo,
3291
+ &checkout_strategy)) < 0)
3292
+ goto done;
3293
+
3294
+ if ((error = git_repository_index(&repo_index, repo) < 0) ||
3295
+ (error = git_index_read(repo_index, 0) < 0))
3296
+ goto done;
3297
+
3298
+ /* Write the merge setup files to the repository. */
3299
+ if ((error = git_annotated_commit_from_head(&our_head, repo)) < 0 ||
3300
+ (error = git_merge__setup(repo, our_head, their_heads,
3301
+ their_heads_len)) < 0)
3302
+ goto done;
2145
3303
 
2146
- if (head->commit != NULL)
2147
- git_object_free((git_object *)head->commit);
3304
+ /* TODO: octopus */
2148
3305
 
2149
- if (head->ref_name != NULL)
2150
- git__free(head->ref_name);
3306
+ if ((error = merge_annotated_commits(&index, &base, repo, our_head,
3307
+ (git_annotated_commit *)their_heads[0], 0, merge_opts)) < 0 ||
3308
+ (error = git_merge__check_result(repo, index)) < 0 ||
3309
+ (error = git_merge__append_conflicts_to_merge_msg(repo, index)) < 0)
3310
+ goto done;
3311
+
3312
+ /* check out the merge results */
3313
+
3314
+ if ((error = merge_normalize_checkout_opts(&checkout_opts, repo,
3315
+ given_checkout_opts, checkout_strategy,
3316
+ base, our_head, their_heads, their_heads_len)) < 0 ||
3317
+ (error = git_checkout_index(repo, index, &checkout_opts)) < 0)
3318
+ goto done;
3319
+
3320
+ error = git_indexwriter_commit(&indexwriter);
3321
+
3322
+ done:
3323
+ if (error < 0)
3324
+ merge_state_cleanup(repo);
3325
+
3326
+ git_indexwriter_cleanup(&indexwriter);
3327
+ git_index_free(index);
3328
+ git_annotated_commit_free(our_head);
3329
+ git_annotated_commit_free(base);
3330
+ git_reference_free(our_ref);
3331
+ git_index_free(repo_index);
3332
+
3333
+ return error;
3334
+ }
2151
3335
 
2152
- if (head->remote_url != NULL)
2153
- git__free(head->remote_url);
3336
+ int git_merge_init_options(git_merge_options *opts, unsigned int version)
3337
+ {
3338
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3339
+ opts, version, git_merge_options, GIT_MERGE_OPTIONS_INIT);
3340
+ return 0;
3341
+ }
2154
3342
 
2155
- git__free(head);
3343
+ int git_merge_file_init_input(git_merge_file_input *input, unsigned int version)
3344
+ {
3345
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3346
+ input, version, git_merge_file_input, GIT_MERGE_FILE_INPUT_INIT);
3347
+ return 0;
3348
+ }
3349
+
3350
+ int git_merge_file_init_options(
3351
+ git_merge_file_options *opts, unsigned int version)
3352
+ {
3353
+ GIT_INIT_STRUCTURE_FROM_TEMPLATE(
3354
+ opts, version, git_merge_file_options, GIT_MERGE_FILE_OPTIONS_INIT);
3355
+ return 0;
2156
3356
  }