rugged 0.26.7 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/rugged/rugged_blame.c +6 -3
  4. data/ext/rugged/rugged_branch_collection.c +3 -6
  5. data/ext/rugged/rugged_commit.c +56 -0
  6. data/ext/rugged/rugged_config.c +44 -9
  7. data/ext/rugged/rugged_diff.c +3 -14
  8. data/ext/rugged/rugged_diff_hunk.c +1 -3
  9. data/ext/rugged/rugged_index.c +1 -5
  10. data/ext/rugged/rugged_note.c +1 -4
  11. data/ext/rugged/rugged_patch.c +1 -4
  12. data/ext/rugged/rugged_reference_collection.c +1 -7
  13. data/ext/rugged/rugged_remote.c +5 -8
  14. data/ext/rugged/rugged_remote_collection.c +1 -6
  15. data/ext/rugged/rugged_repo.c +16 -48
  16. data/ext/rugged/rugged_revwalk.c +7 -16
  17. data/ext/rugged/rugged_settings.c +28 -0
  18. data/ext/rugged/rugged_submodule_collection.c +3 -4
  19. data/ext/rugged/rugged_tag_collection.c +1 -5
  20. data/ext/rugged/rugged_tree.c +2 -3
  21. data/lib/rugged/repository.rb +43 -0
  22. data/lib/rugged/version.rb +1 -1
  23. data/vendor/libgit2/AUTHORS +1 -0
  24. data/vendor/libgit2/CMakeLists.txt +61 -510
  25. data/vendor/libgit2/cmake/Modules/EnableWarnings.cmake +14 -0
  26. data/vendor/libgit2/cmake/Modules/FindCoreFoundation.cmake +25 -8
  27. data/vendor/libgit2/cmake/Modules/FindSecurity.cmake +27 -8
  28. data/vendor/libgit2/cmake/Modules/FindStatNsec.cmake +20 -0
  29. data/vendor/libgit2/cmake/Modules/IdeSplitSources.cmake +22 -0
  30. data/vendor/libgit2/deps/http-parser/CMakeLists.txt +3 -0
  31. data/vendor/libgit2/deps/regex/CMakeLists.txt +2 -0
  32. data/vendor/libgit2/deps/winhttp/CMakeLists.txt +26 -0
  33. data/vendor/libgit2/deps/zlib/CMakeLists.txt +4 -0
  34. data/vendor/libgit2/include/git2/config.h +29 -2
  35. data/vendor/libgit2/include/git2/describe.h +1 -1
  36. data/vendor/libgit2/include/git2/diff.h +59 -8
  37. data/vendor/libgit2/include/git2/graph.h +3 -0
  38. data/vendor/libgit2/include/git2/merge.h +6 -0
  39. data/vendor/libgit2/include/git2/message.h +43 -3
  40. data/vendor/libgit2/include/git2/notes.h +89 -0
  41. data/vendor/libgit2/include/git2/odb.h +8 -1
  42. data/vendor/libgit2/include/git2/patch.h +2 -2
  43. data/vendor/libgit2/include/git2/pathspec.h +35 -18
  44. data/vendor/libgit2/include/git2/refs.h +3 -0
  45. data/vendor/libgit2/include/git2/remote.h +34 -4
  46. data/vendor/libgit2/include/git2/repository.h +6 -6
  47. data/vendor/libgit2/include/git2/reset.h +4 -4
  48. data/vendor/libgit2/include/git2/status.h +4 -0
  49. data/vendor/libgit2/include/git2/sys/config.h +4 -1
  50. data/vendor/libgit2/include/git2/sys/odb_backend.h +2 -1
  51. data/vendor/libgit2/include/git2/tree.h +4 -3
  52. data/vendor/libgit2/include/git2/types.h +1 -0
  53. data/vendor/libgit2/include/git2/version.h +4 -4
  54. data/vendor/libgit2/include/git2/worktree.h +1 -1
  55. data/vendor/libgit2/src/CMakeLists.txt +463 -0
  56. data/vendor/libgit2/src/annotated_commit.c +1 -1
  57. data/vendor/libgit2/src/annotated_commit.h +2 -0
  58. data/vendor/libgit2/src/apply.c +2 -1
  59. data/vendor/libgit2/src/apply.h +2 -0
  60. data/vendor/libgit2/src/attr.c +24 -4
  61. data/vendor/libgit2/src/attr.h +2 -0
  62. data/vendor/libgit2/src/attr_file.c +9 -2
  63. data/vendor/libgit2/src/attr_file.h +2 -0
  64. data/vendor/libgit2/src/attrcache.c +9 -1
  65. data/vendor/libgit2/src/attrcache.h +2 -0
  66. data/vendor/libgit2/src/blame.c +1 -0
  67. data/vendor/libgit2/src/blame.h +2 -1
  68. data/vendor/libgit2/src/blame_git.c +1 -0
  69. data/vendor/libgit2/src/blame_git.h +2 -0
  70. data/vendor/libgit2/src/blob.c +2 -2
  71. data/vendor/libgit2/src/blob.h +2 -0
  72. data/vendor/libgit2/src/branch.c +8 -1
  73. data/vendor/libgit2/src/branch.h +2 -0
  74. data/vendor/libgit2/src/buf_text.c +7 -7
  75. data/vendor/libgit2/src/buf_text.h +3 -3
  76. data/vendor/libgit2/src/buffer.c +31 -1
  77. data/vendor/libgit2/src/buffer.h +3 -0
  78. data/vendor/libgit2/src/cache.c +2 -2
  79. data/vendor/libgit2/src/cache.h +2 -0
  80. data/vendor/libgit2/src/cc-compat.h +3 -3
  81. data/vendor/libgit2/src/checkout.c +30 -19
  82. data/vendor/libgit2/src/checkout.h +2 -0
  83. data/vendor/libgit2/src/cherrypick.c +1 -0
  84. data/vendor/libgit2/src/clone.c +2 -1
  85. data/vendor/libgit2/src/clone.h +4 -0
  86. data/vendor/libgit2/src/commit.c +2 -1
  87. data/vendor/libgit2/src/commit.h +2 -0
  88. data/vendor/libgit2/src/commit_list.c +1 -1
  89. data/vendor/libgit2/src/commit_list.h +2 -0
  90. data/vendor/libgit2/src/common.h +11 -5
  91. data/vendor/libgit2/src/config.c +12 -10
  92. data/vendor/libgit2/src/config.h +2 -0
  93. data/vendor/libgit2/src/config_cache.c +1 -0
  94. data/vendor/libgit2/src/config_file.c +287 -786
  95. data/vendor/libgit2/src/config_file.h +4 -3
  96. data/vendor/libgit2/src/config_parse.c +525 -0
  97. data/vendor/libgit2/src/config_parse.h +64 -0
  98. data/vendor/libgit2/src/crlf.c +2 -1
  99. data/vendor/libgit2/src/delta.c +28 -30
  100. data/vendor/libgit2/src/delta.h +1 -0
  101. data/vendor/libgit2/src/describe.c +3 -1
  102. data/vendor/libgit2/src/diff.c +148 -2
  103. data/vendor/libgit2/src/diff.h +3 -1
  104. data/vendor/libgit2/src/diff_driver.c +12 -9
  105. data/vendor/libgit2/src/diff_driver.h +4 -1
  106. data/vendor/libgit2/src/diff_file.c +7 -4
  107. data/vendor/libgit2/src/diff_file.h +1 -0
  108. data/vendor/libgit2/src/diff_generate.c +6 -3
  109. data/vendor/libgit2/src/diff_generate.h +6 -1
  110. data/vendor/libgit2/src/diff_parse.c +5 -4
  111. data/vendor/libgit2/src/diff_parse.h +2 -0
  112. data/vendor/libgit2/src/diff_print.c +2 -0
  113. data/vendor/libgit2/src/diff_stats.c +2 -0
  114. data/vendor/libgit2/src/diff_tform.c +2 -1
  115. data/vendor/libgit2/src/diff_tform.h +4 -1
  116. data/vendor/libgit2/src/diff_xdiff.c +5 -2
  117. data/vendor/libgit2/src/diff_xdiff.h +2 -0
  118. data/vendor/libgit2/src/errors.c +2 -0
  119. data/vendor/libgit2/src/features.h.in +36 -0
  120. data/vendor/libgit2/src/fetch.c +2 -2
  121. data/vendor/libgit2/src/fetch.h +4 -0
  122. data/vendor/libgit2/src/fetchhead.c +3 -3
  123. data/vendor/libgit2/src/fetchhead.h +3 -0
  124. data/vendor/libgit2/src/filebuf.c +2 -1
  125. data/vendor/libgit2/src/filebuf.h +2 -0
  126. data/vendor/libgit2/src/fileops.c +12 -1
  127. data/vendor/libgit2/src/fileops.h +7 -1
  128. data/vendor/libgit2/src/filter.c +2 -1
  129. data/vendor/libgit2/src/filter.h +1 -0
  130. data/vendor/libgit2/src/fnmatch.c +2 -2
  131. data/vendor/libgit2/src/fnmatch.h +3 -4
  132. data/vendor/libgit2/src/global.c +4 -3
  133. data/vendor/libgit2/src/global.h +1 -5
  134. data/vendor/libgit2/src/graph.c +2 -0
  135. data/vendor/libgit2/src/hash.c +0 -1
  136. data/vendor/libgit2/src/hash.h +3 -1
  137. data/vendor/libgit2/src/hash/hash_collisiondetect.h +3 -3
  138. data/vendor/libgit2/src/hash/hash_common_crypto.h +18 -5
  139. data/vendor/libgit2/src/hash/hash_generic.c +2 -2
  140. data/vendor/libgit2/src/hash/hash_generic.h +5 -3
  141. data/vendor/libgit2/src/hash/hash_openssl.h +3 -3
  142. data/vendor/libgit2/src/hash/hash_win32.c +57 -14
  143. data/vendor/libgit2/src/hash/hash_win32.h +4 -3
  144. data/vendor/libgit2/src/hashsig.c +3 -0
  145. data/vendor/libgit2/src/ident.c +2 -0
  146. data/vendor/libgit2/src/idxmap.h +2 -1
  147. data/vendor/libgit2/src/ignore.c +14 -2
  148. data/vendor/libgit2/src/ignore.h +2 -0
  149. data/vendor/libgit2/src/index.c +20 -40
  150. data/vendor/libgit2/src/index.h +2 -0
  151. data/vendor/libgit2/src/indexer.c +13 -5
  152. data/vendor/libgit2/src/indexer.h +5 -1
  153. data/vendor/libgit2/src/integer.h +1 -1
  154. data/vendor/libgit2/src/iterator.c +44 -3
  155. data/vendor/libgit2/src/iterator.h +3 -0
  156. data/vendor/libgit2/src/map.h +1 -1
  157. data/vendor/libgit2/src/merge.c +155 -33
  158. data/vendor/libgit2/src/merge.h +2 -0
  159. data/vendor/libgit2/src/merge_driver.c +2 -2
  160. data/vendor/libgit2/src/merge_driver.h +2 -0
  161. data/vendor/libgit2/src/merge_file.c +3 -0
  162. data/vendor/libgit2/src/message.h +3 -1
  163. data/vendor/libgit2/src/mwindow.c +1 -1
  164. data/vendor/libgit2/src/mwindow.h +2 -0
  165. data/vendor/libgit2/src/netops.c +75 -62
  166. data/vendor/libgit2/src/netops.h +2 -1
  167. data/vendor/libgit2/src/notes.c +164 -48
  168. data/vendor/libgit2/src/notes.h +1 -1
  169. data/vendor/libgit2/src/object.c +14 -3
  170. data/vendor/libgit2/src/object.h +4 -0
  171. data/vendor/libgit2/src/object_api.c +3 -2
  172. data/vendor/libgit2/src/odb.c +104 -38
  173. data/vendor/libgit2/src/odb.h +3 -1
  174. data/vendor/libgit2/src/odb_loose.c +414 -267
  175. data/vendor/libgit2/src/odb_mempack.c +1 -0
  176. data/vendor/libgit2/src/odb_pack.c +2 -1
  177. data/vendor/libgit2/src/offmap.h +1 -0
  178. data/vendor/libgit2/src/oid.c +2 -1
  179. data/vendor/libgit2/src/oid.h +3 -8
  180. data/vendor/libgit2/src/oidarray.c +2 -1
  181. data/vendor/libgit2/src/oidarray.h +1 -0
  182. data/vendor/libgit2/src/oidmap.h +1 -0
  183. data/vendor/libgit2/src/pack-objects.c +5 -1
  184. data/vendor/libgit2/src/pack-objects.h +1 -1
  185. data/vendor/libgit2/src/pack.c +2 -6
  186. data/vendor/libgit2/src/pack.h +2 -1
  187. data/vendor/libgit2/src/parse.c +121 -0
  188. data/vendor/libgit2/src/parse.h +61 -0
  189. data/vendor/libgit2/src/patch.c +9 -2
  190. data/vendor/libgit2/src/patch.h +2 -0
  191. data/vendor/libgit2/src/patch_generate.c +6 -5
  192. data/vendor/libgit2/src/patch_generate.h +1 -0
  193. data/vendor/libgit2/src/patch_parse.c +265 -276
  194. data/vendor/libgit2/src/patch_parse.h +6 -11
  195. data/vendor/libgit2/src/path.c +24 -181
  196. data/vendor/libgit2/src/path.h +14 -73
  197. data/vendor/libgit2/src/pathspec.c +2 -1
  198. data/vendor/libgit2/src/pathspec.h +2 -1
  199. data/vendor/libgit2/src/pool.c +8 -0
  200. data/vendor/libgit2/src/pool.h +1 -0
  201. data/vendor/libgit2/src/posix.c +2 -1
  202. data/vendor/libgit2/src/posix.h +1 -0
  203. data/vendor/libgit2/src/pqueue.c +1 -0
  204. data/vendor/libgit2/src/pqueue.h +2 -0
  205. data/vendor/libgit2/src/proxy.c +2 -1
  206. data/vendor/libgit2/src/proxy.h +3 -1
  207. data/vendor/libgit2/src/push.c +4 -171
  208. data/vendor/libgit2/src/push.h +2 -0
  209. data/vendor/libgit2/src/rebase.c +1 -0
  210. data/vendor/libgit2/src/refdb.c +2 -3
  211. data/vendor/libgit2/src/refdb.h +2 -0
  212. data/vendor/libgit2/src/refdb_fs.c +5 -3
  213. data/vendor/libgit2/src/refdb_fs.h +4 -0
  214. data/vendor/libgit2/src/reflog.c +1 -0
  215. data/vendor/libgit2/src/reflog.h +2 -1
  216. data/vendor/libgit2/src/refs.c +1 -0
  217. data/vendor/libgit2/src/refs.h +2 -1
  218. data/vendor/libgit2/src/refspec.c +2 -2
  219. data/vendor/libgit2/src/refspec.h +2 -0
  220. data/vendor/libgit2/src/remote.c +56 -10
  221. data/vendor/libgit2/src/remote.h +2 -0
  222. data/vendor/libgit2/src/repository.c +16 -14
  223. data/vendor/libgit2/src/repository.h +2 -0
  224. data/vendor/libgit2/src/reset.c +6 -5
  225. data/vendor/libgit2/src/revert.c +1 -0
  226. data/vendor/libgit2/src/revparse.c +3 -5
  227. data/vendor/libgit2/src/revwalk.c +2 -2
  228. data/vendor/libgit2/src/revwalk.h +2 -0
  229. data/vendor/libgit2/src/settings.c +6 -8
  230. data/vendor/libgit2/src/sha1_lookup.c +2 -216
  231. data/vendor/libgit2/src/sha1_lookup.h +2 -6
  232. data/vendor/libgit2/src/signature.c +8 -3
  233. data/vendor/libgit2/src/signature.h +2 -0
  234. data/vendor/libgit2/src/sortedcache.c +7 -0
  235. data/vendor/libgit2/src/sortedcache.h +2 -0
  236. data/vendor/libgit2/src/stash.c +1 -0
  237. data/vendor/libgit2/src/status.c +14 -9
  238. data/vendor/libgit2/src/status.h +2 -0
  239. data/vendor/libgit2/src/{curl_stream.c → streams/curl.c} +2 -0
  240. data/vendor/libgit2/src/{curl_stream.h → streams/curl.h} +4 -2
  241. data/vendor/libgit2/src/{openssl_stream.c → streams/openssl.c} +47 -18
  242. data/vendor/libgit2/src/{openssl_stream.h → streams/openssl.h} +6 -2
  243. data/vendor/libgit2/src/{socket_stream.c → streams/socket.c} +2 -2
  244. data/vendor/libgit2/src/{socket_stream.h → streams/socket.h} +4 -2
  245. data/vendor/libgit2/src/{stransport_stream.c → streams/stransport.c} +4 -2
  246. data/vendor/libgit2/src/{stransport_stream.h → streams/stransport.h} +4 -2
  247. data/vendor/libgit2/src/{tls_stream.c → streams/tls.c} +4 -3
  248. data/vendor/libgit2/src/{tls_stream.h → streams/tls.h} +4 -2
  249. data/vendor/libgit2/src/submodule.c +28 -80
  250. data/vendor/libgit2/src/submodule.h +2 -13
  251. data/vendor/libgit2/src/sysdir.c +75 -8
  252. data/vendor/libgit2/src/sysdir.h +2 -1
  253. data/vendor/libgit2/src/tag.c +2 -2
  254. data/vendor/libgit2/src/tag.h +2 -0
  255. data/vendor/libgit2/src/thread-utils.c +1 -0
  256. data/vendor/libgit2/src/thread-utils.h +1 -1
  257. data/vendor/libgit2/src/trace.c +2 -2
  258. data/vendor/libgit2/src/trace.h +2 -0
  259. data/vendor/libgit2/src/trailer.c +416 -0
  260. data/vendor/libgit2/src/transaction.c +2 -1
  261. data/vendor/libgit2/src/transport.c +2 -0
  262. data/vendor/libgit2/src/transports/auth.c +2 -1
  263. data/vendor/libgit2/src/transports/auth.h +4 -3
  264. data/vendor/libgit2/src/transports/auth_negotiate.c +2 -1
  265. data/vendor/libgit2/src/transports/auth_negotiate.h +3 -3
  266. data/vendor/libgit2/src/transports/cred.c +2 -0
  267. data/vendor/libgit2/src/transports/cred.h +4 -2
  268. data/vendor/libgit2/src/transports/cred_helpers.c +1 -0
  269. data/vendor/libgit2/src/transports/git.c +3 -1
  270. data/vendor/libgit2/src/transports/http.c +10 -14
  271. data/vendor/libgit2/src/transports/http.h +23 -0
  272. data/vendor/libgit2/src/transports/local.c +23 -5
  273. data/vendor/libgit2/src/transports/smart.c +3 -1
  274. data/vendor/libgit2/src/transports/smart.h +23 -16
  275. data/vendor/libgit2/src/transports/smart_pkt.c +114 -130
  276. data/vendor/libgit2/src/transports/smart_protocol.c +26 -22
  277. data/vendor/libgit2/src/transports/ssh.c +12 -7
  278. data/vendor/libgit2/src/transports/ssh.h +4 -2
  279. data/vendor/libgit2/src/transports/winhttp.c +19 -21
  280. data/vendor/libgit2/src/tree-cache.c +1 -0
  281. data/vendor/libgit2/src/tree-cache.h +1 -0
  282. data/vendor/libgit2/src/tree.c +20 -14
  283. data/vendor/libgit2/src/tree.h +2 -0
  284. data/vendor/libgit2/src/tsort.c +0 -1
  285. data/vendor/libgit2/src/unix/map.c +4 -1
  286. data/vendor/libgit2/src/unix/posix.h +8 -4
  287. data/vendor/libgit2/src/unix/pthread.h +1 -1
  288. data/vendor/libgit2/src/unix/realpath.c +4 -1
  289. data/vendor/libgit2/src/util.c +6 -5
  290. data/vendor/libgit2/src/util.h +39 -111
  291. data/vendor/libgit2/src/varint.c +0 -1
  292. data/vendor/libgit2/src/varint.h +2 -0
  293. data/vendor/libgit2/src/vector.c +1 -1
  294. data/vendor/libgit2/src/win32/dir.c +3 -0
  295. data/vendor/libgit2/src/win32/dir.h +4 -3
  296. data/vendor/libgit2/src/win32/error.c +1 -1
  297. data/vendor/libgit2/src/win32/error.h +4 -2
  298. data/vendor/libgit2/src/win32/findfile.c +2 -1
  299. data/vendor/libgit2/src/win32/findfile.h +4 -2
  300. data/vendor/libgit2/src/win32/map.c +2 -0
  301. data/vendor/libgit2/src/win32/mingw-compat.h +3 -3
  302. data/vendor/libgit2/src/win32/msvc-compat.h +3 -3
  303. data/vendor/libgit2/src/win32/path_w32.c +7 -12
  304. data/vendor/libgit2/src/win32/path_w32.h +3 -2
  305. data/vendor/libgit2/src/win32/posix.h +2 -2
  306. data/vendor/libgit2/src/win32/posix_w32.c +11 -5
  307. data/vendor/libgit2/src/win32/precompiled.h +2 -1
  308. data/vendor/libgit2/src/win32/reparse.h +2 -2
  309. data/vendor/libgit2/src/win32/thread.c +1 -0
  310. data/vendor/libgit2/src/win32/thread.h +2 -2
  311. data/vendor/libgit2/src/win32/utf-conv.c +0 -1
  312. data/vendor/libgit2/src/win32/utf-conv.h +4 -3
  313. data/vendor/libgit2/src/win32/w32_buffer.c +1 -1
  314. data/vendor/libgit2/src/win32/w32_buffer.h +4 -2
  315. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +2 -1
  316. data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +85 -2
  317. data/vendor/libgit2/src/win32/w32_stack.c +2 -1
  318. data/vendor/libgit2/src/win32/w32_stack.h +5 -3
  319. data/vendor/libgit2/src/win32/w32_util.h +4 -2
  320. data/vendor/libgit2/src/win32/win32-compat.h +3 -3
  321. data/vendor/libgit2/src/worktree.c +4 -5
  322. data/vendor/libgit2/src/worktree.h +2 -0
  323. data/vendor/libgit2/src/xdiff/xdiff.h +22 -13
  324. data/vendor/libgit2/src/xdiff/xdiffi.c +523 -81
  325. data/vendor/libgit2/src/xdiff/xdiffi.h +2 -2
  326. data/vendor/libgit2/src/xdiff/xemit.c +63 -39
  327. data/vendor/libgit2/src/xdiff/xemit.h +2 -2
  328. data/vendor/libgit2/src/xdiff/xhistogram.c +0 -1
  329. data/vendor/libgit2/src/xdiff/xinclude.h +3 -2
  330. data/vendor/libgit2/src/xdiff/xmacros.h +2 -2
  331. data/vendor/libgit2/src/xdiff/xmerge.c +80 -20
  332. data/vendor/libgit2/src/xdiff/xpatience.c +41 -9
  333. data/vendor/libgit2/src/xdiff/xprepare.c +2 -2
  334. data/vendor/libgit2/src/xdiff/xprepare.h +2 -2
  335. data/vendor/libgit2/src/xdiff/xtypes.h +2 -2
  336. data/vendor/libgit2/src/xdiff/xutils.c +47 -27
  337. data/vendor/libgit2/src/xdiff/xutils.h +2 -5
  338. data/vendor/libgit2/src/zstream.c +65 -45
  339. data/vendor/libgit2/src/zstream.h +9 -2
  340. metadata +27 -13
  341. data/vendor/libgit2/include/git2/sys/remote.h +0 -16
@@ -13,15 +13,14 @@
13
13
  * Lesser General Public License for more details.
14
14
  *
15
15
  * You should have received a copy of the GNU Lesser General Public
16
- * License along with this library; if not, write to the Free Software
17
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
+ * License along with this library; if not, see
17
+ * <http://www.gnu.org/licenses/>.
18
18
  *
19
19
  * Davide Libenzi <davidel@xmailserver.org>
20
20
  *
21
21
  */
22
22
 
23
23
  #include "xinclude.h"
24
- #include "common.h"
25
24
  #include "integer.h"
26
25
 
27
26
 
@@ -31,7 +30,12 @@
31
30
  #define XDL_SNAKE_CNT 20
32
31
  #define XDL_K_HEUR 4
33
32
 
34
-
33
+ /** Declare a function as always inlined. */
34
+ #if defined(_MSC_VER)
35
+ # define XDL_INLINE(type) static __inline type
36
+ #else
37
+ # define XDL_INLINE(type) static inline type
38
+ #endif
35
39
 
36
40
  typedef struct s_xdpsplit {
37
41
  long i1, i2;
@@ -404,106 +408,544 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1,
404
408
  }
405
409
 
406
410
 
407
- int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
408
- long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec;
409
- char *rchg = xdf->rchg, *rchgo = xdfo->rchg;
410
- xrecord_t **recs = xdf->recs;
411
+ static int recs_match(xrecord_t *rec1, xrecord_t *rec2, long flags)
412
+ {
413
+ return (rec1->ha == rec2->ha &&
414
+ xdl_recmatch(rec1->ptr, rec1->size,
415
+ rec2->ptr, rec2->size,
416
+ flags));
417
+ }
418
+
419
+ /*
420
+ * If a line is indented more than this, get_indent() just returns this value.
421
+ * This avoids having to do absurd amounts of work for data that are not
422
+ * human-readable text, and also ensures that the output of get_indent fits within
423
+ * an int.
424
+ */
425
+ #define MAX_INDENT 200
426
+
427
+ /*
428
+ * Return the amount of indentation of the specified line, treating TAB as 8
429
+ * columns. Return -1 if line is empty or contains only whitespace. Clamp the
430
+ * output value at MAX_INDENT.
431
+ */
432
+ static int get_indent(xrecord_t *rec)
433
+ {
434
+ long i;
435
+ int ret = 0;
436
+
437
+ for (i = 0; i < rec->size; i++) {
438
+ char c = rec->ptr[i];
439
+
440
+ if (!XDL_ISSPACE(c))
441
+ return ret;
442
+ else if (c == ' ')
443
+ ret += 1;
444
+ else if (c == '\t')
445
+ ret += 8 - ret % 8;
446
+ /* ignore other whitespace characters */
447
+
448
+ if (ret >= MAX_INDENT)
449
+ return MAX_INDENT;
450
+ }
411
451
 
452
+ /* The line contains only whitespace. */
453
+ return -1;
454
+ }
455
+
456
+ /*
457
+ * If more than this number of consecutive blank rows are found, just return this
458
+ * value. This avoids requiring O(N^2) work for pathological cases, and also
459
+ * ensures that the output of score_split fits in an int.
460
+ */
461
+ #define MAX_BLANKS 20
462
+
463
+ /* Characteristics measured about a hypothetical split position. */
464
+ struct split_measurement {
412
465
  /*
413
- * This is the same of what GNU diff does. Move back and forward
414
- * change groups for a consistent and pretty diff output. This also
415
- * helps in finding joinable change groups and reduce the diff size.
466
+ * Is the split at the end of the file (aside from any blank lines)?
416
467
  */
417
- for (ix = ixo = 0;;) {
418
- /*
419
- * Find the first changed line in the to-be-compacted file.
420
- * We need to keep track of both indexes, so if we find a
421
- * changed lines group on the other file, while scanning the
422
- * to-be-compacted file, we need to skip it properly. Note
423
- * that loops that are testing for changed lines on rchg* do
424
- * not need index bounding since the array is prepared with
425
- * a zero at position -1 and N.
426
- */
427
- for (; ix < nrec && !rchg[ix]; ix++)
428
- while (rchgo[ixo++]);
429
- if (ix == nrec)
468
+ int end_of_file;
469
+
470
+ /*
471
+ * How much is the line immediately following the split indented (or -1 if
472
+ * the line is blank):
473
+ */
474
+ int indent;
475
+
476
+ /*
477
+ * How many consecutive lines above the split are blank?
478
+ */
479
+ int pre_blank;
480
+
481
+ /*
482
+ * How much is the nearest non-blank line above the split indented (or -1
483
+ * if there is no such line)?
484
+ */
485
+ int pre_indent;
486
+
487
+ /*
488
+ * How many lines after the line following the split are blank?
489
+ */
490
+ int post_blank;
491
+
492
+ /*
493
+ * How much is the nearest non-blank line after the line following the
494
+ * split indented (or -1 if there is no such line)?
495
+ */
496
+ int post_indent;
497
+ };
498
+
499
+ struct split_score {
500
+ /* The effective indent of this split (smaller is preferred). */
501
+ int effective_indent;
502
+
503
+ /* Penalty for this split (smaller is preferred). */
504
+ int penalty;
505
+ };
506
+
507
+ /*
508
+ * Fill m with information about a hypothetical split of xdf above line split.
509
+ */
510
+ static void measure_split(const xdfile_t *xdf, long split,
511
+ struct split_measurement *m)
512
+ {
513
+ long i;
514
+
515
+ if (split >= xdf->nrec) {
516
+ m->end_of_file = 1;
517
+ m->indent = -1;
518
+ } else {
519
+ m->end_of_file = 0;
520
+ m->indent = get_indent(xdf->recs[split]);
521
+ }
522
+
523
+ m->pre_blank = 0;
524
+ m->pre_indent = -1;
525
+ for (i = split - 1; i >= 0; i--) {
526
+ m->pre_indent = get_indent(xdf->recs[i]);
527
+ if (m->pre_indent != -1)
528
+ break;
529
+ m->pre_blank += 1;
530
+ if (m->pre_blank == MAX_BLANKS) {
531
+ m->pre_indent = 0;
430
532
  break;
533
+ }
534
+ }
431
535
 
536
+ m->post_blank = 0;
537
+ m->post_indent = -1;
538
+ for (i = split + 1; i < xdf->nrec; i++) {
539
+ m->post_indent = get_indent(xdf->recs[i]);
540
+ if (m->post_indent != -1)
541
+ break;
542
+ m->post_blank += 1;
543
+ if (m->post_blank == MAX_BLANKS) {
544
+ m->post_indent = 0;
545
+ break;
546
+ }
547
+ }
548
+ }
549
+
550
+ /*
551
+ * The empirically-determined weight factors used by score_split() below.
552
+ * Larger values means that the position is a less favorable place to split.
553
+ *
554
+ * Note that scores are only ever compared against each other, so multiplying
555
+ * all of these weight/penalty values by the same factor wouldn't change the
556
+ * heuristic's behavior. Still, we need to set that arbitrary scale *somehow*.
557
+ * In practice, these numbers are chosen to be large enough that they can be
558
+ * adjusted relative to each other with sufficient precision despite using
559
+ * integer math.
560
+ */
561
+
562
+ /* Penalty if there are no non-blank lines before the split */
563
+ #define START_OF_FILE_PENALTY 1
564
+
565
+ /* Penalty if there are no non-blank lines after the split */
566
+ #define END_OF_FILE_PENALTY 21
567
+
568
+ /* Multiplier for the number of blank lines around the split */
569
+ #define TOTAL_BLANK_WEIGHT (-30)
570
+
571
+ /* Multiplier for the number of blank lines after the split */
572
+ #define POST_BLANK_WEIGHT 6
573
+
574
+ /*
575
+ * Penalties applied if the line is indented more than its predecessor
576
+ */
577
+ #define RELATIVE_INDENT_PENALTY (-4)
578
+ #define RELATIVE_INDENT_WITH_BLANK_PENALTY 10
579
+
580
+ /*
581
+ * Penalties applied if the line is indented less than both its predecessor and
582
+ * its successor
583
+ */
584
+ #define RELATIVE_OUTDENT_PENALTY 24
585
+ #define RELATIVE_OUTDENT_WITH_BLANK_PENALTY 17
586
+
587
+ /*
588
+ * Penalties applied if the line is indented less than its predecessor but not
589
+ * less than its successor
590
+ */
591
+ #define RELATIVE_DEDENT_PENALTY 23
592
+ #define RELATIVE_DEDENT_WITH_BLANK_PENALTY 17
593
+
594
+ /*
595
+ * We only consider whether the sum of the effective indents for splits are
596
+ * less than (-1), equal to (0), or greater than (+1) each other. The resulting
597
+ * value is multiplied by the following weight and combined with the penalty to
598
+ * determine the better of two scores.
599
+ */
600
+ #define INDENT_WEIGHT 60
601
+
602
+ /*
603
+ * Compute a badness score for the hypothetical split whose measurements are
604
+ * stored in m. The weight factors were determined empirically using the tools and
605
+ * corpus described in
606
+ *
607
+ * https://github.com/mhagger/diff-slider-tools
608
+ *
609
+ * Also see that project if you want to improve the weights based on, for example,
610
+ * a larger or more diverse corpus.
611
+ */
612
+ static void score_add_split(const struct split_measurement *m, struct split_score *s)
613
+ {
614
+ /*
615
+ * A place to accumulate penalty factors (positive makes this index more
616
+ * favored):
617
+ */
618
+ int post_blank, total_blank, indent, any_blanks;
619
+
620
+ if (m->pre_indent == -1 && m->pre_blank == 0)
621
+ s->penalty += START_OF_FILE_PENALTY;
622
+
623
+ if (m->end_of_file)
624
+ s->penalty += END_OF_FILE_PENALTY;
625
+
626
+ /*
627
+ * Set post_blank to the number of blank lines following the split,
628
+ * including the line immediately after the split:
629
+ */
630
+ post_blank = (m->indent == -1) ? 1 + m->post_blank : 0;
631
+ total_blank = m->pre_blank + post_blank;
632
+
633
+ /* Penalties based on nearby blank lines: */
634
+ s->penalty += TOTAL_BLANK_WEIGHT * total_blank;
635
+ s->penalty += POST_BLANK_WEIGHT * post_blank;
636
+
637
+ if (m->indent != -1)
638
+ indent = m->indent;
639
+ else
640
+ indent = m->post_indent;
641
+
642
+ any_blanks = (total_blank != 0);
643
+
644
+ /* Note that the effective indent is -1 at the end of the file: */
645
+ s->effective_indent += indent;
646
+
647
+ if (indent == -1) {
648
+ /* No additional adjustments needed. */
649
+ } else if (m->pre_indent == -1) {
650
+ /* No additional adjustments needed. */
651
+ } else if (indent > m->pre_indent) {
652
+ /*
653
+ * The line is indented more than its predecessor.
654
+ */
655
+ s->penalty += any_blanks ?
656
+ RELATIVE_INDENT_WITH_BLANK_PENALTY :
657
+ RELATIVE_INDENT_PENALTY;
658
+ } else if (indent == m->pre_indent) {
659
+ /*
660
+ * The line has the same indentation level as its predecessor.
661
+ * No additional adjustments needed.
662
+ */
663
+ } else {
432
664
  /*
433
- * Record the start of a changed-group in the to-be-compacted file
434
- * and find the end of it, on both to-be-compacted and other file
435
- * indexes (ix and ixo).
665
+ * The line is indented less than its predecessor. It could be
666
+ * the block terminator of the previous block, but it could
667
+ * also be the start of a new block (e.g., an "else" block, or
668
+ * maybe the previous block didn't have a block terminator).
669
+ * Try to distinguish those cases based on what comes next:
436
670
  */
437
- ixs = ix;
438
- for (ix++; rchg[ix]; ix++);
439
- for (; rchgo[ixo]; ixo++);
671
+ if (m->post_indent != -1 && m->post_indent > indent) {
672
+ /*
673
+ * The following line is indented more. So it is likely
674
+ * that this line is the start of a block.
675
+ */
676
+ s->penalty += any_blanks ?
677
+ RELATIVE_OUTDENT_WITH_BLANK_PENALTY :
678
+ RELATIVE_OUTDENT_PENALTY;
679
+ } else {
680
+ /*
681
+ * That was probably the end of a block.
682
+ */
683
+ s->penalty += any_blanks ?
684
+ RELATIVE_DEDENT_WITH_BLANK_PENALTY :
685
+ RELATIVE_DEDENT_PENALTY;
686
+ }
687
+ }
688
+ }
689
+
690
+ static int score_cmp(struct split_score *s1, struct split_score *s2)
691
+ {
692
+ /* -1 if s1.effective_indent < s2->effective_indent, etc. */
693
+ int cmp_indents = ((s1->effective_indent > s2->effective_indent) -
694
+ (s1->effective_indent < s2->effective_indent));
695
+
696
+ return INDENT_WEIGHT * cmp_indents + (s1->penalty - s2->penalty);
697
+ }
698
+
699
+ /*
700
+ * Represent a group of changed lines in an xdfile_t (i.e., a contiguous group
701
+ * of lines that was inserted or deleted from the corresponding version of the
702
+ * file). We consider there to be such a group at the beginning of the file, at
703
+ * the end of the file, and between any two unchanged lines, though most such
704
+ * groups will usually be empty.
705
+ *
706
+ * If the first line in a group is equal to the line following the group, then
707
+ * the group can be slid down. Similarly, if the last line in a group is equal
708
+ * to the line preceding the group, then the group can be slid up. See
709
+ * group_slide_down() and group_slide_up().
710
+ *
711
+ * Note that loops that are testing for changed lines in xdf->rchg do not need
712
+ * index bounding since the array is prepared with a zero at position -1 and N.
713
+ */
714
+ struct xdlgroup {
715
+ /*
716
+ * The index of the first changed line in the group, or the index of
717
+ * the unchanged line above which the (empty) group is located.
718
+ */
719
+ long start;
720
+
721
+ /*
722
+ * The index of the first unchanged line after the group. For an empty
723
+ * group, end is equal to start.
724
+ */
725
+ long end;
726
+ };
727
+
728
+ /*
729
+ * Initialize g to point at the first group in xdf.
730
+ */
731
+ static void group_init(xdfile_t *xdf, struct xdlgroup *g)
732
+ {
733
+ g->start = g->end = 0;
734
+ while (xdf->rchg[g->end])
735
+ g->end++;
736
+ }
737
+
738
+ /*
739
+ * Move g to describe the next (possibly empty) group in xdf and return 0. If g
740
+ * is already at the end of the file, do nothing and return -1.
741
+ */
742
+ XDL_INLINE(int) group_next(xdfile_t *xdf, struct xdlgroup *g)
743
+ {
744
+ if (g->end == xdf->nrec)
745
+ return -1;
746
+
747
+ g->start = g->end + 1;
748
+ for (g->end = g->start; xdf->rchg[g->end]; g->end++)
749
+ ;
750
+
751
+ return 0;
752
+ }
753
+
754
+ /*
755
+ * Move g to describe the previous (possibly empty) group in xdf and return 0.
756
+ * If g is already at the beginning of the file, do nothing and return -1.
757
+ */
758
+ XDL_INLINE(int) group_previous(xdfile_t *xdf, struct xdlgroup *g)
759
+ {
760
+ if (g->start == 0)
761
+ return -1;
762
+
763
+ g->end = g->start - 1;
764
+ for (g->start = g->end; xdf->rchg[g->start - 1]; g->start--)
765
+ ;
766
+
767
+ return 0;
768
+ }
769
+
770
+ /*
771
+ * If g can be slid toward the end of the file, do so, and if it bumps into a
772
+ * following group, expand this group to include it. Return 0 on success or -1
773
+ * if g cannot be slid down.
774
+ */
775
+ static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g, long flags)
776
+ {
777
+ if (g->end < xdf->nrec &&
778
+ recs_match(xdf->recs[g->start], xdf->recs[g->end], flags)) {
779
+ xdf->rchg[g->start++] = 0;
780
+ xdf->rchg[g->end++] = 1;
781
+
782
+ while (xdf->rchg[g->end])
783
+ g->end++;
784
+
785
+ return 0;
786
+ } else {
787
+ return -1;
788
+ }
789
+ }
790
+
791
+ /*
792
+ * If g can be slid toward the beginning of the file, do so, and if it bumps
793
+ * into a previous group, expand this group to include it. Return 0 on success
794
+ * or -1 if g cannot be slid up.
795
+ */
796
+ static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g, long flags)
797
+ {
798
+ if (g->start > 0 &&
799
+ recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1], flags)) {
800
+ xdf->rchg[--g->start] = 1;
801
+ xdf->rchg[--g->end] = 0;
802
+
803
+ while (xdf->rchg[g->start - 1])
804
+ g->start--;
805
+
806
+ return 0;
807
+ } else {
808
+ return -1;
809
+ }
810
+ }
811
+
812
+ static void xdl_bug(const char *msg)
813
+ {
814
+ fprintf(stderr, "BUG: %s\n", msg);
815
+ exit(1);
816
+ }
817
+
818
+ /*
819
+ * Move back and forward change groups for a consistent and pretty diff output.
820
+ * This also helps in finding joinable change groups and reducing the diff
821
+ * size.
822
+ */
823
+ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
824
+ struct xdlgroup g, go;
825
+ long earliest_end, end_matching_other;
826
+ long groupsize;
440
827
 
828
+ group_init(xdf, &g);
829
+ group_init(xdfo, &go);
830
+
831
+ while (1) {
832
+ /* If the group is empty in the to-be-compacted file, skip it: */
833
+ if (g.end == g.start)
834
+ goto next;
835
+
836
+ /*
837
+ * Now shift the change up and then down as far as possible in
838
+ * each direction. If it bumps into any other changes, merge them.
839
+ */
441
840
  do {
442
- grpsiz = ix - ixs;
841
+ groupsize = g.end - g.start;
443
842
 
444
843
  /*
445
- * If the line before the current change group, is equal to
446
- * the last line of the current change group, shift backward
447
- * the group.
844
+ * Keep track of the last "end" index that causes this
845
+ * group to align with a group of changed lines in the
846
+ * other file. -1 indicates that we haven't found such
847
+ * a match yet:
448
848
  */
449
- while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha &&
450
- xdl_recmatch(recs[ixs - 1]->ptr, recs[ixs - 1]->size, recs[ix - 1]->ptr, recs[ix - 1]->size, flags)) {
451
- rchg[--ixs] = 1;
452
- rchg[--ix] = 0;
453
-
454
- /*
455
- * This change might have joined two change groups,
456
- * so we try to take this scenario in account by moving
457
- * the start index accordingly (and so the other-file
458
- * end-of-group index).
459
- */
460
- for (; rchg[ixs - 1]; ixs--);
461
- while (rchgo[--ixo]);
462
- }
849
+ end_matching_other = -1;
463
850
 
464
- /*
465
- * Record the end-of-group position in case we are matched
466
- * with a group of changes in the other file (that is, the
467
- * change record before the end-of-group index in the other
468
- * file is set).
469
- */
470
- ixref = rchgo[ixo - 1] ? ix: nrec;
851
+ /* Shift the group backward as much as possible: */
852
+ while (!group_slide_up(xdf, &g, flags))
853
+ if (group_previous(xdfo, &go))
854
+ xdl_bug("group sync broken sliding up");
471
855
 
472
856
  /*
473
- * If the first line of the current change group, is equal to
474
- * the line next of the current change group, shift forward
475
- * the group.
857
+ * This is this highest that this group can be shifted.
858
+ * Record its end index:
476
859
  */
477
- while (ix < nrec && recs[ixs]->ha == recs[ix]->ha &&
478
- xdl_recmatch(recs[ixs]->ptr, recs[ixs]->size, recs[ix]->ptr, recs[ix]->size, flags)) {
479
- rchg[ixs++] = 0;
480
- rchg[ix++] = 1;
481
-
482
- /*
483
- * This change might have joined two change groups,
484
- * so we try to take this scenario in account by moving
485
- * the start index accordingly (and so the other-file
486
- * end-of-group index). Keep tracking the reference
487
- * index in case we are shifting together with a
488
- * corresponding group of changes in the other file.
489
- */
490
- for (; rchg[ix]; ix++);
491
- while (rchgo[++ixo])
492
- ixref = ix;
860
+ earliest_end = g.end;
861
+
862
+ if (go.end > go.start)
863
+ end_matching_other = g.end;
864
+
865
+ /* Now shift the group forward as far as possible: */
866
+ while (1) {
867
+ if (group_slide_down(xdf, &g, flags))
868
+ break;
869
+ if (group_next(xdfo, &go))
870
+ xdl_bug("group sync broken sliding down");
871
+
872
+ if (go.end > go.start)
873
+ end_matching_other = g.end;
493
874
  }
494
- } while (grpsiz != ix - ixs);
875
+ } while (groupsize != g.end - g.start);
495
876
 
496
877
  /*
497
- * Try to move back the possibly merged group of changes, to match
498
- * the recorded position in the other file.
878
+ * If the group can be shifted, then we can possibly use this
879
+ * freedom to produce a more intuitive diff.
880
+ *
881
+ * The group is currently shifted as far down as possible, so the
882
+ * heuristics below only have to handle upwards shifts.
499
883
  */
500
- while (ixref < ix) {
501
- rchg[--ixs] = 1;
502
- rchg[--ix] = 0;
503
- while (rchgo[--ixo]);
884
+
885
+ if (g.end == earliest_end) {
886
+ /* no shifting was possible */
887
+ } else if (end_matching_other != -1) {
888
+ /*
889
+ * Move the possibly merged group of changes back to line
890
+ * up with the last group of changes from the other file
891
+ * that it can align with.
892
+ */
893
+ while (go.end == go.start) {
894
+ if (group_slide_up(xdf, &g, flags))
895
+ xdl_bug("match disappeared");
896
+ if (group_previous(xdfo, &go))
897
+ xdl_bug("group sync broken sliding to match");
898
+ }
899
+ } else if (flags & XDF_INDENT_HEURISTIC) {
900
+ /*
901
+ * Indent heuristic: a group of pure add/delete lines
902
+ * implies two splits, one between the end of the "before"
903
+ * context and the start of the group, and another between
904
+ * the end of the group and the beginning of the "after"
905
+ * context. Some splits are aesthetically better and some
906
+ * are worse. We compute a badness "score" for each split,
907
+ * and add the scores for the two splits to define a
908
+ * "score" for each position that the group can be shifted
909
+ * to. Then we pick the shift with the lowest score.
910
+ */
911
+ long shift, best_shift = -1;
912
+ struct split_score best_score;
913
+
914
+ for (shift = earliest_end; shift <= g.end; shift++) {
915
+ struct split_measurement m;
916
+ struct split_score score = {0, 0};
917
+
918
+ measure_split(xdf, shift, &m);
919
+ score_add_split(&m, &score);
920
+ measure_split(xdf, shift - groupsize, &m);
921
+ score_add_split(&m, &score);
922
+ if (best_shift == -1 ||
923
+ score_cmp(&score, &best_score) <= 0) {
924
+ best_score.effective_indent = score.effective_indent;
925
+ best_score.penalty = score.penalty;
926
+ best_shift = shift;
927
+ }
928
+ }
929
+
930
+ while (g.end > best_shift) {
931
+ if (group_slide_up(xdf, &g, flags))
932
+ xdl_bug("best shift unreached");
933
+ if (group_previous(xdfo, &go))
934
+ xdl_bug("group sync broken sliding to blank line");
935
+ }
504
936
  }
937
+
938
+ next:
939
+ /* Move past the just-processed group: */
940
+ if (group_next(xdf, &g))
941
+ break;
942
+ if (group_next(xdfo, &go))
943
+ xdl_bug("group sync broken moving to next group");
505
944
  }
506
945
 
946
+ if (!group_next(xdfo, &go))
947
+ xdl_bug("group sync broken at end of file");
948
+
507
949
  return 0;
508
950
  }
509
951