rugged 0.19.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (453) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/README.md +151 -25
  4. data/ext/rugged/extconf.rb +48 -27
  5. data/ext/rugged/rugged.c +107 -35
  6. data/ext/rugged/rugged.h +44 -8
  7. data/ext/rugged/rugged_blame.c +292 -0
  8. data/ext/rugged/rugged_blob.c +84 -31
  9. data/ext/rugged/rugged_branch.c +90 -223
  10. data/ext/rugged/rugged_branch_collection.c +445 -0
  11. data/ext/rugged/rugged_commit.c +190 -9
  12. data/ext/rugged/rugged_config.c +1 -1
  13. data/ext/rugged/rugged_cred.c +125 -0
  14. data/ext/rugged/rugged_diff.c +267 -94
  15. data/ext/rugged/rugged_diff_delta.c +14 -3
  16. data/ext/rugged/rugged_diff_hunk.c +31 -28
  17. data/ext/rugged/rugged_diff_line.c +21 -17
  18. data/ext/rugged/rugged_index.c +326 -6
  19. data/ext/rugged/rugged_note.c +39 -34
  20. data/ext/rugged/rugged_object.c +9 -9
  21. data/ext/rugged/rugged_patch.c +245 -0
  22. data/ext/rugged/rugged_reference.c +67 -332
  23. data/ext/rugged/rugged_reference_collection.c +490 -0
  24. data/ext/rugged/rugged_remote.c +447 -351
  25. data/ext/rugged/rugged_remote_collection.c +285 -0
  26. data/ext/rugged/rugged_repo.c +752 -203
  27. data/ext/rugged/rugged_revwalk.c +119 -27
  28. data/ext/rugged/rugged_settings.c +48 -1
  29. data/ext/rugged/rugged_signature.c +30 -16
  30. data/ext/rugged/rugged_tag.c +86 -191
  31. data/ext/rugged/rugged_tag_collection.c +279 -0
  32. data/ext/rugged/rugged_tree.c +159 -22
  33. data/lib/rugged/branch.rb +8 -17
  34. data/lib/rugged/credentials.rb +43 -0
  35. data/lib/rugged/diff/delta.rb +1 -2
  36. data/lib/rugged/diff/hunk.rb +4 -9
  37. data/lib/rugged/diff/line.rb +23 -3
  38. data/lib/rugged/diff.rb +3 -1
  39. data/lib/rugged/patch.rb +26 -0
  40. data/lib/rugged/reference.rb +1 -3
  41. data/lib/rugged/remote.rb +0 -9
  42. data/lib/rugged/repository.rb +70 -13
  43. data/lib/rugged/tag.rb +23 -18
  44. data/lib/rugged/tree.rb +7 -0
  45. data/lib/rugged/version.rb +1 -1
  46. data/lib/rugged.rb +8 -1
  47. data/vendor/libgit2/AUTHORS +75 -0
  48. data/vendor/libgit2/CMakeLists.txt +490 -0
  49. data/vendor/libgit2/COPYING +920 -0
  50. data/vendor/libgit2/Makefile.embed +25 -7
  51. data/vendor/libgit2/cmake/Modules/AddCFlagIfSupported.cmake +16 -0
  52. data/vendor/libgit2/cmake/Modules/FindHTTP_Parser.cmake +39 -0
  53. data/vendor/libgit2/cmake/Modules/FindIconv.cmake +43 -0
  54. data/vendor/libgit2/cmake/Modules/FindLIBSSH2.cmake +44 -0
  55. data/vendor/libgit2/deps/http-parser/LICENSE-MIT +23 -0
  56. data/vendor/libgit2/deps/regex/regex.c +10 -3
  57. data/vendor/libgit2/include/git2/attr.h +2 -1
  58. data/vendor/libgit2/include/git2/blame.h +213 -0
  59. data/vendor/libgit2/include/git2/blob.h +57 -29
  60. data/vendor/libgit2/include/git2/branch.h +56 -44
  61. data/vendor/libgit2/include/git2/buffer.h +112 -0
  62. data/vendor/libgit2/include/git2/checkout.h +72 -37
  63. data/vendor/libgit2/include/git2/cherrypick.h +87 -0
  64. data/vendor/libgit2/include/git2/clone.h +153 -56
  65. data/vendor/libgit2/include/git2/commit.h +82 -12
  66. data/vendor/libgit2/include/git2/common.h +31 -19
  67. data/vendor/libgit2/include/git2/config.h +124 -19
  68. data/vendor/libgit2/include/git2/cred_helpers.h +1 -1
  69. data/vendor/libgit2/include/git2/diff.h +636 -494
  70. data/vendor/libgit2/include/git2/errors.h +48 -15
  71. data/vendor/libgit2/include/git2/filter.h +149 -0
  72. data/vendor/libgit2/include/git2/graph.h +14 -0
  73. data/vendor/libgit2/include/git2/index.h +95 -54
  74. data/vendor/libgit2/include/git2/indexer.h +15 -9
  75. data/vendor/libgit2/include/git2/merge.h +402 -39
  76. data/vendor/libgit2/include/git2/message.h +9 -14
  77. data/vendor/libgit2/include/git2/net.h +5 -0
  78. data/vendor/libgit2/include/git2/notes.h +6 -6
  79. data/vendor/libgit2/include/git2/object.h +34 -2
  80. data/vendor/libgit2/include/git2/odb.h +77 -14
  81. data/vendor/libgit2/include/git2/odb_backend.h +50 -6
  82. data/vendor/libgit2/include/git2/oid.h +4 -8
  83. data/vendor/libgit2/include/git2/pack.h +58 -4
  84. data/vendor/libgit2/include/git2/patch.h +277 -0
  85. data/vendor/libgit2/include/git2/pathspec.h +263 -0
  86. data/vendor/libgit2/include/git2/push.h +55 -5
  87. data/vendor/libgit2/include/git2/reflog.h +11 -8
  88. data/vendor/libgit2/include/git2/refs.h +219 -33
  89. data/vendor/libgit2/include/git2/refspec.h +3 -4
  90. data/vendor/libgit2/include/git2/remote.h +216 -76
  91. data/vendor/libgit2/include/git2/repository.h +85 -40
  92. data/vendor/libgit2/include/git2/reset.h +15 -4
  93. data/vendor/libgit2/include/git2/revert.h +86 -0
  94. data/vendor/libgit2/include/git2/revparse.h +27 -16
  95. data/vendor/libgit2/include/git2/revwalk.h +44 -6
  96. data/vendor/libgit2/include/git2/signature.h +17 -3
  97. data/vendor/libgit2/include/git2/stash.h +8 -12
  98. data/vendor/libgit2/include/git2/status.h +67 -18
  99. data/vendor/libgit2/include/git2/submodule.h +100 -85
  100. data/vendor/libgit2/include/git2/sys/commit.h +38 -4
  101. data/vendor/libgit2/include/git2/sys/config.h +44 -3
  102. data/vendor/libgit2/include/git2/sys/diff.h +91 -0
  103. data/vendor/libgit2/include/git2/sys/filter.h +301 -0
  104. data/vendor/libgit2/include/git2/sys/index.h +0 -2
  105. data/vendor/libgit2/include/git2/sys/mempack.h +85 -0
  106. data/vendor/libgit2/include/git2/sys/odb_backend.h +33 -11
  107. data/vendor/libgit2/include/git2/sys/refdb_backend.h +51 -5
  108. data/vendor/libgit2/include/git2/sys/reflog.h +21 -0
  109. data/vendor/libgit2/include/git2/sys/refs.h +2 -2
  110. data/vendor/libgit2/include/git2/sys/repository.h +19 -1
  111. data/vendor/libgit2/include/git2/transport.h +216 -75
  112. data/vendor/libgit2/include/git2/tree.h +32 -11
  113. data/vendor/libgit2/include/git2/types.h +124 -10
  114. data/vendor/libgit2/include/git2/version.h +4 -2
  115. data/vendor/libgit2/include/git2.h +41 -40
  116. data/vendor/libgit2/libgit2.pc.in +10 -0
  117. data/vendor/libgit2/src/array.h +16 -8
  118. data/vendor/libgit2/src/attr.c +140 -402
  119. data/vendor/libgit2/src/attr.h +1 -33
  120. data/vendor/libgit2/src/attr_file.c +298 -135
  121. data/vendor/libgit2/src/attr_file.h +61 -22
  122. data/vendor/libgit2/src/attrcache.c +449 -0
  123. data/vendor/libgit2/src/attrcache.h +38 -6
  124. data/vendor/libgit2/src/bitvec.h +75 -0
  125. data/vendor/libgit2/src/blame.c +488 -0
  126. data/vendor/libgit2/src/blame.h +93 -0
  127. data/vendor/libgit2/src/blame_git.c +624 -0
  128. data/vendor/libgit2/src/blame_git.h +20 -0
  129. data/vendor/libgit2/src/blob.c +137 -92
  130. data/vendor/libgit2/src/blob.h +9 -0
  131. data/vendor/libgit2/src/branch.c +175 -156
  132. data/vendor/libgit2/src/buf_text.c +29 -14
  133. data/vendor/libgit2/src/buf_text.h +5 -4
  134. data/vendor/libgit2/src/buffer.c +158 -15
  135. data/vendor/libgit2/src/buffer.h +33 -20
  136. data/vendor/libgit2/src/cc-compat.h +8 -2
  137. data/vendor/libgit2/src/checkout.c +1081 -287
  138. data/vendor/libgit2/src/checkout.h +1 -1
  139. data/vendor/libgit2/src/cherrypick.c +226 -0
  140. data/vendor/libgit2/src/clone.c +297 -245
  141. data/vendor/libgit2/src/{compress.h → clone.h} +4 -8
  142. data/vendor/libgit2/src/commit.c +313 -101
  143. data/vendor/libgit2/src/commit.h +6 -3
  144. data/vendor/libgit2/src/commit_list.c +3 -3
  145. data/vendor/libgit2/src/commit_list.h +1 -1
  146. data/vendor/libgit2/src/common.h +74 -1
  147. data/vendor/libgit2/src/config.c +570 -145
  148. data/vendor/libgit2/src/config.h +39 -6
  149. data/vendor/libgit2/src/config_cache.c +32 -18
  150. data/vendor/libgit2/src/config_file.c +711 -424
  151. data/vendor/libgit2/src/config_file.h +4 -3
  152. data/vendor/libgit2/src/crlf.c +149 -109
  153. data/vendor/libgit2/src/date.c +35 -7
  154. data/vendor/libgit2/src/delta.c +1 -1
  155. data/vendor/libgit2/src/diff.c +719 -414
  156. data/vendor/libgit2/src/diff.h +52 -7
  157. data/vendor/libgit2/src/diff_driver.c +183 -85
  158. data/vendor/libgit2/src/diff_driver.h +1 -1
  159. data/vendor/libgit2/src/diff_file.c +65 -84
  160. data/vendor/libgit2/src/diff_file.h +12 -10
  161. data/vendor/libgit2/src/diff_patch.c +274 -333
  162. data/vendor/libgit2/src/diff_patch.h +10 -9
  163. data/vendor/libgit2/src/diff_print.c +381 -179
  164. data/vendor/libgit2/src/diff_stats.c +336 -0
  165. data/vendor/libgit2/src/diff_tform.c +393 -215
  166. data/vendor/libgit2/src/diff_xdiff.c +117 -42
  167. data/vendor/libgit2/src/errors.c +59 -4
  168. data/vendor/libgit2/src/fetch.c +40 -34
  169. data/vendor/libgit2/src/fetch.h +2 -5
  170. data/vendor/libgit2/src/fetchhead.c +14 -7
  171. data/vendor/libgit2/src/filebuf.c +13 -24
  172. data/vendor/libgit2/src/filebuf.h +3 -3
  173. data/vendor/libgit2/src/fileops.c +104 -296
  174. data/vendor/libgit2/src/fileops.h +23 -94
  175. data/vendor/libgit2/src/filter.c +642 -43
  176. data/vendor/libgit2/src/filter.h +7 -66
  177. data/vendor/libgit2/src/fnmatch.c +46 -3
  178. data/vendor/libgit2/src/fnmatch.h +24 -3
  179. data/vendor/libgit2/src/global.c +158 -42
  180. data/vendor/libgit2/src/global.h +9 -0
  181. data/vendor/libgit2/src/graph.c +34 -20
  182. data/vendor/libgit2/src/hash/hash_generic.h +0 -1
  183. data/vendor/libgit2/src/hash/hash_openssl.h +0 -1
  184. data/vendor/libgit2/src/hash/hash_win32.c +14 -29
  185. data/vendor/libgit2/src/hash.h +0 -2
  186. data/vendor/libgit2/src/hashsig.c +97 -117
  187. data/vendor/libgit2/src/ident.c +125 -0
  188. data/vendor/libgit2/src/ignore.c +159 -110
  189. data/vendor/libgit2/src/ignore.h +13 -3
  190. data/vendor/libgit2/src/index.c +803 -445
  191. data/vendor/libgit2/src/index.h +43 -6
  192. data/vendor/libgit2/src/indexer.c +475 -157
  193. data/vendor/libgit2/src/iterator.c +198 -55
  194. data/vendor/libgit2/src/iterator.h +28 -4
  195. data/vendor/libgit2/src/map.h +1 -0
  196. data/vendor/libgit2/src/merge.c +849 -142
  197. data/vendor/libgit2/src/merge.h +11 -4
  198. data/vendor/libgit2/src/merge_file.c +183 -78
  199. data/vendor/libgit2/src/merge_file.h +0 -57
  200. data/vendor/libgit2/src/message.c +4 -28
  201. data/vendor/libgit2/src/mwindow.c +117 -8
  202. data/vendor/libgit2/src/mwindow.h +9 -1
  203. data/vendor/libgit2/src/netops.c +164 -59
  204. data/vendor/libgit2/src/netops.h +37 -1
  205. data/vendor/libgit2/src/notes.c +9 -18
  206. data/vendor/libgit2/src/notes.h +1 -1
  207. data/vendor/libgit2/src/object.c +78 -2
  208. data/vendor/libgit2/src/odb.c +191 -59
  209. data/vendor/libgit2/src/odb.h +2 -1
  210. data/vendor/libgit2/src/odb_loose.c +66 -51
  211. data/vendor/libgit2/src/odb_mempack.c +182 -0
  212. data/vendor/libgit2/src/odb_pack.c +151 -61
  213. data/vendor/libgit2/src/oid.c +30 -19
  214. data/vendor/libgit2/src/oid.h +13 -10
  215. data/vendor/libgit2/src/pack-objects.c +198 -147
  216. data/vendor/libgit2/src/pack-objects.h +7 -0
  217. data/vendor/libgit2/src/pack.c +272 -101
  218. data/vendor/libgit2/src/pack.h +15 -1
  219. data/vendor/libgit2/src/path.c +359 -117
  220. data/vendor/libgit2/src/path.h +110 -20
  221. data/vendor/libgit2/src/pathspec.c +583 -57
  222. data/vendor/libgit2/src/pathspec.h +36 -15
  223. data/vendor/libgit2/src/pool.c +4 -5
  224. data/vendor/libgit2/src/posix.c +45 -2
  225. data/vendor/libgit2/src/posix.h +13 -5
  226. data/vendor/libgit2/src/pqueue.c +73 -119
  227. data/vendor/libgit2/src/pqueue.h +35 -82
  228. data/vendor/libgit2/src/push.c +116 -48
  229. data/vendor/libgit2/src/push.h +5 -0
  230. data/vendor/libgit2/src/refdb.c +45 -6
  231. data/vendor/libgit2/src/refdb.h +13 -3
  232. data/vendor/libgit2/src/refdb_fs.c +1130 -551
  233. data/vendor/libgit2/src/reflog.c +36 -327
  234. data/vendor/libgit2/src/reflog.h +6 -1
  235. data/vendor/libgit2/src/refs.c +345 -142
  236. data/vendor/libgit2/src/refs.h +9 -2
  237. data/vendor/libgit2/src/refspec.c +90 -62
  238. data/vendor/libgit2/src/refspec.h +7 -24
  239. data/vendor/libgit2/src/remote.c +815 -415
  240. data/vendor/libgit2/src/remote.h +3 -4
  241. data/vendor/libgit2/src/repository.c +360 -207
  242. data/vendor/libgit2/src/repository.h +16 -10
  243. data/vendor/libgit2/src/reset.c +28 -13
  244. data/vendor/libgit2/src/revert.c +228 -0
  245. data/vendor/libgit2/src/revparse.c +29 -30
  246. data/vendor/libgit2/src/revwalk.c +141 -96
  247. data/vendor/libgit2/src/revwalk.h +6 -1
  248. data/vendor/libgit2/src/settings.c +140 -0
  249. data/vendor/libgit2/src/sha1_lookup.c +71 -0
  250. data/vendor/libgit2/src/sha1_lookup.h +5 -0
  251. data/vendor/libgit2/src/signature.c +38 -10
  252. data/vendor/libgit2/src/sortedcache.c +378 -0
  253. data/vendor/libgit2/src/sortedcache.h +178 -0
  254. data/vendor/libgit2/src/stash.c +98 -116
  255. data/vendor/libgit2/src/status.c +88 -60
  256. data/vendor/libgit2/src/status.h +2 -2
  257. data/vendor/libgit2/src/strmap.c +32 -0
  258. data/vendor/libgit2/src/strmap.h +14 -1
  259. data/vendor/libgit2/src/strnlen.h +23 -0
  260. data/vendor/libgit2/src/submodule.c +1073 -615
  261. data/vendor/libgit2/src/submodule.h +89 -21
  262. data/vendor/libgit2/src/sysdir.c +252 -0
  263. data/vendor/libgit2/src/sysdir.h +101 -0
  264. data/vendor/libgit2/src/tag.c +31 -20
  265. data/vendor/libgit2/src/thread-utils.h +98 -17
  266. data/vendor/libgit2/src/trace.h +0 -2
  267. data/vendor/libgit2/src/transport.c +76 -6
  268. data/vendor/libgit2/src/transports/cred.c +164 -61
  269. data/vendor/libgit2/src/transports/git.c +41 -48
  270. data/vendor/libgit2/src/transports/http.c +65 -109
  271. data/vendor/libgit2/src/transports/local.c +88 -65
  272. data/vendor/libgit2/src/transports/smart.c +91 -19
  273. data/vendor/libgit2/src/transports/smart.h +13 -5
  274. data/vendor/libgit2/src/transports/smart_pkt.c +24 -14
  275. data/vendor/libgit2/src/transports/smart_protocol.c +268 -113
  276. data/vendor/libgit2/src/transports/ssh.c +284 -186
  277. data/vendor/libgit2/src/transports/winhttp.c +279 -198
  278. data/vendor/libgit2/src/tree-cache.c +21 -23
  279. data/vendor/libgit2/src/tree-cache.h +1 -0
  280. data/vendor/libgit2/src/tree.c +109 -92
  281. data/vendor/libgit2/src/tree.h +2 -3
  282. data/vendor/libgit2/src/unix/map.c +7 -1
  283. data/vendor/libgit2/src/unix/posix.h +0 -1
  284. data/vendor/libgit2/src/userdiff.h +208 -0
  285. data/vendor/libgit2/src/util.c +16 -112
  286. data/vendor/libgit2/src/util.h +107 -3
  287. data/vendor/libgit2/src/vector.c +72 -17
  288. data/vendor/libgit2/src/vector.h +32 -5
  289. data/vendor/libgit2/src/win32/dir.c +15 -40
  290. data/vendor/libgit2/src/win32/dir.h +3 -2
  291. data/vendor/libgit2/src/win32/error.c +5 -31
  292. data/vendor/libgit2/src/win32/findfile.c +47 -66
  293. data/vendor/libgit2/src/win32/findfile.h +1 -12
  294. data/vendor/libgit2/src/win32/git2.rc +40 -0
  295. data/vendor/libgit2/src/win32/map.c +7 -1
  296. data/vendor/libgit2/src/win32/mingw-compat.h +3 -0
  297. data/vendor/libgit2/src/win32/posix.h +17 -11
  298. data/vendor/libgit2/src/win32/posix_w32.c +424 -292
  299. data/vendor/libgit2/src/win32/precompiled.h +6 -2
  300. data/vendor/libgit2/src/win32/pthread.c +141 -18
  301. data/vendor/libgit2/src/win32/pthread.h +50 -8
  302. data/vendor/libgit2/src/win32/reparse.h +57 -0
  303. data/vendor/libgit2/src/win32/utf-conv.c +117 -60
  304. data/vendor/libgit2/src/win32/utf-conv.h +81 -6
  305. data/vendor/libgit2/src/win32/version.h +21 -4
  306. data/vendor/libgit2/src/win32/w32_util.c +139 -0
  307. data/vendor/libgit2/src/win32/w32_util.h +54 -0
  308. data/vendor/libgit2/src/zstream.c +156 -0
  309. data/vendor/libgit2/src/zstream.h +39 -0
  310. metadata +84 -167
  311. data/Rakefile +0 -61
  312. data/ext/rugged/rugged_diff_patch.c +0 -169
  313. data/lib/rugged/diff/patch.rb +0 -28
  314. data/test/blob_test.rb +0 -341
  315. data/test/branch_test.rb +0 -199
  316. data/test/commit_test.rb +0 -104
  317. data/test/config_test.rb +0 -45
  318. data/test/coverage/cover.rb +0 -133
  319. data/test/diff_test.rb +0 -777
  320. data/test/errors_test.rb +0 -34
  321. data/test/fixtures/alternate/objects/14/6ae76773c91e3b1d00cf7a338ec55ae58297e2 +0 -0
  322. data/test/fixtures/alternate/objects/14/9c32d47e99d0a3572ff1e70a2e0051bbf347a9 +0 -0
  323. data/test/fixtures/alternate/objects/14/fb3108588f9421bf764041e5e3ac305eb6277f +0 -0
  324. data/test/fixtures/archive.tar.gz +0 -0
  325. data/test/fixtures/attr/attr0 +0 -1
  326. data/test/fixtures/attr/attr1 +0 -29
  327. data/test/fixtures/attr/attr2 +0 -21
  328. data/test/fixtures/attr/attr3 +0 -4
  329. data/test/fixtures/attr/binfile +0 -1
  330. data/test/fixtures/attr/dir/file +0 -0
  331. data/test/fixtures/attr/file +0 -1
  332. data/test/fixtures/attr/gitattributes +0 -29
  333. data/test/fixtures/attr/gitignore +0 -2
  334. data/test/fixtures/attr/ign +0 -1
  335. data/test/fixtures/attr/macro_bad +0 -1
  336. data/test/fixtures/attr/macro_test +0 -1
  337. data/test/fixtures/attr/root_test1 +0 -1
  338. data/test/fixtures/attr/root_test2 +0 -6
  339. data/test/fixtures/attr/root_test3 +0 -19
  340. data/test/fixtures/attr/root_test4.txt +0 -14
  341. data/test/fixtures/attr/sub/abc +0 -37
  342. data/test/fixtures/attr/sub/dir/file +0 -0
  343. data/test/fixtures/attr/sub/file +0 -1
  344. data/test/fixtures/attr/sub/ign/file +0 -1
  345. data/test/fixtures/attr/sub/ign/sub/file +0 -1
  346. data/test/fixtures/attr/sub/sub/dir +0 -0
  347. data/test/fixtures/attr/sub/sub/file +0 -1
  348. data/test/fixtures/attr/sub/sub/subsub.txt +0 -1
  349. data/test/fixtures/attr/sub/subdir_test1 +0 -2
  350. data/test/fixtures/attr/sub/subdir_test2.txt +0 -1
  351. data/test/fixtures/diff/another.txt +0 -38
  352. data/test/fixtures/diff/readme.txt +0 -36
  353. data/test/fixtures/mergedrepo/conflicts-one.txt +0 -5
  354. data/test/fixtures/mergedrepo/conflicts-two.txt +0 -5
  355. data/test/fixtures/mergedrepo/one.txt +0 -10
  356. data/test/fixtures/mergedrepo/two.txt +0 -12
  357. data/test/fixtures/status/current_file +0 -1
  358. data/test/fixtures/status/ignored_file +0 -1
  359. data/test/fixtures/status/modified_file +0 -2
  360. data/test/fixtures/status/new_file +0 -1
  361. data/test/fixtures/status/staged_changes +0 -2
  362. data/test/fixtures/status/staged_changes_modified_file +0 -3
  363. data/test/fixtures/status/staged_delete_modified_file +0 -1
  364. data/test/fixtures/status/staged_new_file +0 -1
  365. data/test/fixtures/status/staged_new_file_modified_file +0 -2
  366. data/test/fixtures/status/subdir/current_file +0 -1
  367. data/test/fixtures/status/subdir/modified_file +0 -2
  368. data/test/fixtures/status/subdir/new_file +0 -1
  369. data/test/fixtures/status/subdir.txt +0 -2
  370. data/test/fixtures/status//350/277/231 +0 -1
  371. data/test/fixtures/testrepo.git/HEAD +0 -1
  372. data/test/fixtures/testrepo.git/config +0 -13
  373. data/test/fixtures/testrepo.git/description +0 -1
  374. data/test/fixtures/testrepo.git/index +0 -0
  375. data/test/fixtures/testrepo.git/info/exclude +0 -6
  376. data/test/fixtures/testrepo.git/logs/HEAD +0 -3
  377. data/test/fixtures/testrepo.git/logs/refs/heads/master +0 -3
  378. data/test/fixtures/testrepo.git/logs/refs/notes/commits +0 -1
  379. data/test/fixtures/testrepo.git/objects/0c/37a5391bbff43c37f0d0371823a5509eed5b1d +0 -0
  380. data/test/fixtures/testrepo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
  381. data/test/fixtures/testrepo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
  382. data/test/fixtures/testrepo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
  383. data/test/fixtures/testrepo.git/objects/2d/2eff63372b08adf0a9eb84109ccf7d19e2f3a2 +0 -0
  384. data/test/fixtures/testrepo.git/objects/36/060c58702ed4c2a40832c51758d5344201d89a +0 -2
  385. data/test/fixtures/testrepo.git/objects/44/1034f860c1d5d90e4188d11ae0d325176869a8 +0 -1
  386. data/test/fixtures/testrepo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
  387. data/test/fixtures/testrepo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +0 -2
  388. data/test/fixtures/testrepo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +0 -2
  389. data/test/fixtures/testrepo.git/objects/60/d415052a33de2150bf68757f6461df4f563ae4 +0 -0
  390. data/test/fixtures/testrepo.git/objects/61/9f9935957e010c419cb9d15621916ddfcc0b96 +0 -0
  391. data/test/fixtures/testrepo.git/objects/68/8a8f4ef7496901d15322972f96e212a9e466cc +0 -1
  392. data/test/fixtures/testrepo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
  393. data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
  394. data/test/fixtures/testrepo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
  395. data/test/fixtures/testrepo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
  396. data/test/fixtures/testrepo.git/objects/94/eca2de348d5f672faf56b0decafa5937e3235e +0 -0
  397. data/test/fixtures/testrepo.git/objects/9b/7384fe1676186192842f5d3e129457b62db9e3 +0 -0
  398. data/test/fixtures/testrepo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +0 -3
  399. data/test/fixtures/testrepo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +0 -2
  400. data/test/fixtures/testrepo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
  401. data/test/fixtures/testrepo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
  402. data/test/fixtures/testrepo.git/objects/b7/4713326bc972cc15751ed504dca6f6f3b91f7a +0 -3
  403. data/test/fixtures/testrepo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +0 -3
  404. data/test/fixtures/testrepo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +0 -3
  405. data/test/fixtures/testrepo.git/objects/c4/dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b +0 -0
  406. data/test/fixtures/testrepo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  407. data/test/fixtures/testrepo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
  408. data/test/fixtures/testrepo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
  409. data/test/fixtures/testrepo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
  410. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
  411. data/test/fixtures/testrepo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
  412. data/test/fixtures/testrepo.git/packed-refs +0 -2
  413. data/test/fixtures/testrepo.git/refs/heads/master +0 -1
  414. data/test/fixtures/testrepo.git/refs/notes/commits +0 -1
  415. data/test/fixtures/testrepo.git/refs/tags/v0.9 +0 -1
  416. data/test/fixtures/testrepo.git/refs/tags/v1.0 +0 -1
  417. data/test/fixtures/text_file.md +0 -464
  418. data/test/fixtures/unsymlinked.git/HEAD +0 -1
  419. data/test/fixtures/unsymlinked.git/config +0 -6
  420. data/test/fixtures/unsymlinked.git/description +0 -1
  421. data/test/fixtures/unsymlinked.git/info/exclude +0 -2
  422. data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
  423. data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
  424. data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
  425. data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
  426. data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
  427. data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
  428. data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
  429. data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
  430. data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
  431. data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +0 -2
  432. data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
  433. data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
  434. data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
  435. data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
  436. data/test/fixtures/unsymlinked.git/refs/heads/exe-file +0 -1
  437. data/test/fixtures/unsymlinked.git/refs/heads/master +0 -1
  438. data/test/fixtures/unsymlinked.git/refs/heads/reg-file +0 -1
  439. data/test/index_test.rb +0 -333
  440. data/test/lib_test.rb +0 -127
  441. data/test/note_test.rb +0 -158
  442. data/test/object_test.rb +0 -43
  443. data/test/reference_test.rb +0 -207
  444. data/test/remote_test.rb +0 -324
  445. data/test/repo_pack_test.rb +0 -24
  446. data/test/repo_reset_test.rb +0 -82
  447. data/test/repo_test.rb +0 -402
  448. data/test/tag_test.rb +0 -68
  449. data/test/test_helper.rb +0 -92
  450. data/test/tree_test.rb +0 -91
  451. data/test/walker_test.rb +0 -88
  452. data/vendor/libgit2/src/amiga/map.c +0 -48
  453. data/vendor/libgit2/src/compress.c +0 -53
@@ -9,17 +9,74 @@
9
9
  #include "path.h"
10
10
  #include "utf-conv.h"
11
11
  #include "repository.h"
12
+ #include "reparse.h"
12
13
  #include <errno.h>
13
14
  #include <io.h>
14
15
  #include <fcntl.h>
15
16
  #include <ws2tcpip.h>
16
17
 
18
+ #ifndef FILE_NAME_NORMALIZED
19
+ # define FILE_NAME_NORMALIZED 0
20
+ #endif
21
+
22
+ /* Options which we always provide to _wopen.
23
+ *
24
+ * _O_BINARY - Raw access; no translation of CR or LF characters
25
+ * _O_NOINHERIT - Do not mark the created handle as inheritable by child processes.
26
+ * The Windows default is 'not inheritable', but the CRT's default (following
27
+ * POSIX convention) is 'inheritable'. We have no desire for our handles to be
28
+ * inheritable on Windows, so specify the flag to get default behavior back. */
29
+ #define STANDARD_OPEN_FLAGS (_O_BINARY | _O_NOINHERIT)
30
+
31
+ /* GetFinalPathNameByHandleW signature */
32
+ typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
33
+
34
+ /* Helper function which converts UTF-8 paths to UTF-16.
35
+ * On failure, errno is set. */
36
+ static int utf8_to_16_with_errno(git_win32_path dest, const char *src)
37
+ {
38
+ int len = git_win32_path_from_utf8(dest, src);
39
+
40
+ if (len < 0) {
41
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
42
+ errno = ENAMETOOLONG;
43
+ else
44
+ errno = EINVAL; /* Bad code point, presumably */
45
+ }
46
+
47
+ return len;
48
+ }
49
+
50
+ int p_mkdir(const char *path, mode_t mode)
51
+ {
52
+ git_win32_path buf;
53
+
54
+ GIT_UNUSED(mode);
55
+
56
+ if (utf8_to_16_with_errno(buf, path) < 0)
57
+ return -1;
58
+
59
+ return _wmkdir(buf);
60
+ }
61
+
17
62
  int p_unlink(const char *path)
18
63
  {
19
- wchar_t buf[GIT_WIN_PATH];
20
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
21
- _wchmod(buf, 0666);
22
- return _wunlink(buf);
64
+ git_win32_path buf;
65
+ int error;
66
+
67
+ if (utf8_to_16_with_errno(buf, path) < 0)
68
+ return -1;
69
+
70
+ error = _wunlink(buf);
71
+
72
+ /* If the file could not be deleted because it was
73
+ * read-only, clear the bit and try again */
74
+ if (error == -1 && errno == EACCES) {
75
+ _wchmod(buf, 0666);
76
+ error = _wunlink(buf);
77
+ }
78
+
79
+ return error;
23
80
  }
24
81
 
25
82
  int p_fsync(int fd)
@@ -53,27 +110,79 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
53
110
  return (time_t)winTime;
54
111
  }
55
112
 
56
- #define WIN32_IS_WSEP(CH) ((CH) == L'/' || (CH) == L'\\')
57
-
58
- static int do_lstat(
59
- const char *file_name, struct stat *buf, int posix_enotdir)
113
+ /* On success, returns the length, in characters, of the path stored in dest.
114
+ * On failure, returns a negative value. */
115
+ static int readlink_w(
116
+ git_win32_path dest,
117
+ const git_win32_path path)
60
118
  {
61
- WIN32_FILE_ATTRIBUTE_DATA fdata;
62
- wchar_t fbuf[GIT_WIN_PATH], lastch;
63
- int flen;
119
+ BYTE buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
120
+ GIT_REPARSE_DATA_BUFFER *reparse_buf = (GIT_REPARSE_DATA_BUFFER *)buf;
121
+ HANDLE handle = NULL;
122
+ DWORD ioctl_ret;
123
+ wchar_t *target;
124
+ size_t target_len;
64
125
 
65
- flen = git__utf8_to_16(fbuf, GIT_WIN_PATH, file_name);
126
+ int error = -1;
66
127
 
67
- /* truncate trailing slashes */
68
- for (; flen > 0; --flen) {
69
- lastch = fbuf[flen - 1];
70
- if (WIN32_IS_WSEP(lastch))
71
- fbuf[flen - 1] = L'\0';
72
- else if (lastch != L'\0')
73
- break;
128
+ handle = CreateFileW(path, GENERIC_READ,
129
+ FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
130
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
131
+
132
+ if (handle == INVALID_HANDLE_VALUE) {
133
+ errno = ENOENT;
134
+ return -1;
135
+ }
136
+
137
+ if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
138
+ reparse_buf, sizeof(buf), &ioctl_ret, NULL)) {
139
+ errno = EINVAL;
140
+ goto on_error;
141
+ }
142
+
143
+ switch (reparse_buf->ReparseTag) {
144
+ case IO_REPARSE_TAG_SYMLINK:
145
+ target = reparse_buf->SymbolicLinkReparseBuffer.PathBuffer +
146
+ (reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
147
+ target_len = reparse_buf->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
148
+ break;
149
+ case IO_REPARSE_TAG_MOUNT_POINT:
150
+ target = reparse_buf->MountPointReparseBuffer.PathBuffer +
151
+ (reparse_buf->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
152
+ target_len = reparse_buf->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
153
+ break;
154
+ default:
155
+ errno = EINVAL;
156
+ goto on_error;
157
+ }
158
+
159
+ if (target_len) {
160
+ /* The path may need to have a prefix removed. */
161
+ target_len = git_win32__canonicalize_path(target, target_len);
162
+
163
+ /* Need one additional character in the target buffer
164
+ * for the terminating NULL. */
165
+ if (GIT_WIN_PATH_UTF16 > target_len) {
166
+ wcscpy(dest, target);
167
+ error = (int)target_len;
168
+ }
74
169
  }
75
170
 
76
- if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
171
+ on_error:
172
+ CloseHandle(handle);
173
+ return error;
174
+ }
175
+
176
+ #define WIN32_IS_WSEP(CH) ((CH) == L'/' || (CH) == L'\\')
177
+
178
+ static int lstat_w(
179
+ wchar_t *path,
180
+ struct stat *buf,
181
+ bool posix_enotdir)
182
+ {
183
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
184
+
185
+ if (GetFileAttributesExW(path, GetFileExInfoStandard, &fdata)) {
77
186
  int fMode = S_IREAD;
78
187
 
79
188
  if (!buf)
@@ -87,12 +196,6 @@ static int do_lstat(
87
196
  if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
88
197
  fMode |= S_IWRITE;
89
198
 
90
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
91
- fMode |= S_IFLNK;
92
-
93
- if ((fMode & (S_IFDIR | S_IFLNK)) == (S_IFDIR | S_IFLNK)) // junction
94
- fMode ^= S_IFLNK;
95
-
96
199
  buf->st_ino = 0;
97
200
  buf->st_gid = 0;
98
201
  buf->st_uid = 0;
@@ -104,19 +207,17 @@ static int do_lstat(
104
207
  buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
105
208
  buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
106
209
 
107
- /* Windows symlinks have zero file size, call readlink to determine
108
- * the length of the path pointed to, which we expect everywhere else
109
- */
110
- if (S_ISLNK(fMode)) {
111
- char target[GIT_WIN_PATH];
112
- int readlink_result;
210
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
211
+ git_win32_path target;
113
212
 
114
- readlink_result = p_readlink(file_name, target, GIT_WIN_PATH);
213
+ if (readlink_w(target, path) >= 0) {
214
+ buf->st_mode = (buf->st_mode & ~S_IFMT) | S_IFLNK;
115
215
 
116
- if (readlink_result == -1)
117
- return -1;
118
-
119
- buf->st_size = strlen(target);
216
+ /* st_size gets the UTF-8 length of the target name, in bytes,
217
+ * not counting the NULL terminator */
218
+ if ((buf->st_size = git__utf16_to_8(NULL, 0, target)) < 0)
219
+ return -1;
220
+ }
120
221
  }
121
222
 
122
223
  return 0;
@@ -124,22 +225,27 @@ static int do_lstat(
124
225
 
125
226
  errno = ENOENT;
126
227
 
127
- /* We need POSIX behavior, then ENOTDIR must set when any of the folders in the
128
- * file path is a regular file,otherwise ENOENT must be set.
228
+ /* To match POSIX behavior, set ENOTDIR when any of the folders in the
229
+ * file path is a regular file, otherwise set ENOENT.
129
230
  */
130
231
  if (posix_enotdir) {
232
+ size_t path_len = wcslen(path);
233
+
131
234
  /* scan up path until we find an existing item */
132
235
  while (1) {
236
+ DWORD attrs;
237
+
133
238
  /* remove last directory component */
134
- for (--flen; flen > 0 && !WIN32_IS_WSEP(fbuf[flen]); --flen);
239
+ for (path_len--; path_len > 0 && !WIN32_IS_WSEP(path[path_len]); path_len--);
135
240
 
136
- if (flen <= 0)
241
+ if (path_len <= 0)
137
242
  break;
138
243
 
139
- fbuf[flen] = L'\0';
244
+ path[path_len] = L'\0';
245
+ attrs = GetFileAttributesW(path);
140
246
 
141
- if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
142
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
247
+ if (attrs != INVALID_FILE_ATTRIBUTES) {
248
+ if (!(attrs & FILE_ATTRIBUTE_DIRECTORY))
143
249
  errno = ENOTDIR;
144
250
  break;
145
251
  }
@@ -149,99 +255,51 @@ static int do_lstat(
149
255
  return -1;
150
256
  }
151
257
 
258
+ static int do_lstat(const char *path, struct stat *buf, bool posixly_correct)
259
+ {
260
+ git_win32_path path_w;
261
+ int len;
262
+
263
+ if ((len = utf8_to_16_with_errno(path_w, path)) < 0)
264
+ return -1;
265
+
266
+ git_win32__path_trim_end(path_w, len);
267
+
268
+ return lstat_w(path_w, buf, posixly_correct);
269
+ }
270
+
152
271
  int p_lstat(const char *filename, struct stat *buf)
153
272
  {
154
- return do_lstat(filename, buf, 0);
273
+ return do_lstat(filename, buf, false);
155
274
  }
156
275
 
157
276
  int p_lstat_posixly(const char *filename, struct stat *buf)
158
277
  {
159
- return do_lstat(filename, buf, 1);
278
+ return do_lstat(filename, buf, true);
160
279
  }
161
280
 
162
- int p_readlink(const char *link, char *target, size_t target_len)
281
+ int p_readlink(const char *path, char *buf, size_t bufsiz)
163
282
  {
164
- typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD);
165
- static fpath_func pGetFinalPath = NULL;
166
- HANDLE hFile;
167
- DWORD dwRet;
168
- wchar_t link_w[GIT_WIN_PATH];
169
- wchar_t* target_w;
170
- int error = 0;
171
-
172
- assert(link && target && target_len > 0);
173
-
174
- /*
175
- * Try to load the pointer to pGetFinalPath dynamically, because
176
- * it is not available in platforms older than Vista
177
- */
178
- if (pGetFinalPath == NULL) {
179
- HMODULE module = GetModuleHandle("kernel32");
180
-
181
- if (module != NULL)
182
- pGetFinalPath = (fpath_func)GetProcAddress(module, "GetFinalPathNameByHandleW");
183
-
184
- if (pGetFinalPath == NULL) {
185
- giterr_set(GITERR_OS,
186
- "'GetFinalPathNameByHandleW' is not available in this platform");
187
- return -1;
188
- }
189
- }
190
-
191
- git__utf8_to_16(link_w, GIT_WIN_PATH, link);
283
+ git_win32_path path_w, target_w;
284
+ git_win32_utf8_path target;
285
+ int len;
192
286
 
193
- hFile = CreateFileW(link_w, // file to open
194
- GENERIC_READ, // open for reading
195
- FILE_SHARE_READ, // share for reading
196
- NULL, // default security
197
- OPEN_EXISTING, // existing file only
198
- FILE_FLAG_BACKUP_SEMANTICS, // normal file
199
- NULL); // no attr. template
287
+ /* readlink(2) does not NULL-terminate the string written
288
+ * to the target buffer. Furthermore, the target buffer need
289
+ * not be large enough to hold the entire result. A truncated
290
+ * result should be written in this case. Since this truncation
291
+ * could occur in the middle of the encoding of a code point,
292
+ * we need to buffer the result on the stack. */
200
293
 
201
- if (hFile == INVALID_HANDLE_VALUE) {
202
- giterr_set(GITERR_OS, "Cannot open '%s' for reading", link);
294
+ if (utf8_to_16_with_errno(path_w, path) < 0 ||
295
+ readlink_w(target_w, path_w) < 0 ||
296
+ (len = git_win32_path_to_utf8(target, target_w)) < 0)
203
297
  return -1;
204
- }
205
-
206
- target_w = (wchar_t*)git__malloc(target_len * sizeof(wchar_t));
207
- GITERR_CHECK_ALLOC(target_w);
208
-
209
- dwRet = pGetFinalPath(hFile, target_w, (DWORD)target_len, 0x0);
210
- if (dwRet == 0 ||
211
- dwRet >= target_len ||
212
- !WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target,
213
- (int)(target_len * sizeof(char)), NULL, NULL))
214
- error = -1;
215
298
 
216
- git__free(target_w);
217
- CloseHandle(hFile);
218
-
219
- if (error)
220
- return error;
221
-
222
- /* Skip first 4 characters if they are "\\?\" */
223
- if (dwRet > 4 &&
224
- target[0] == '\\' && target[1] == '\\' &&
225
- target[2] == '?' && target[3] == '\\')
226
- {
227
- unsigned int offset = 4;
228
- dwRet -= 4;
229
-
230
- /* \??\UNC\ */
231
- if (dwRet > 7 &&
232
- target[4] == 'U' && target[5] == 'N' && target[6] == 'C')
233
- {
234
- offset += 2;
235
- dwRet -= 2;
236
- target[offset] = '\\';
237
- }
299
+ bufsiz = min((size_t)len, bufsiz);
300
+ memcpy(buf, target, bufsiz);
238
301
 
239
- memmove(target, target + offset, dwRet);
240
- }
241
-
242
- target[dwRet] = '\0';
243
-
244
- return dwRet;
302
+ return (int)bufsiz;
245
303
  }
246
304
 
247
305
  int p_symlink(const char *old, const char *new)
@@ -254,10 +312,11 @@ int p_symlink(const char *old, const char *new)
254
312
 
255
313
  int p_open(const char *path, int flags, ...)
256
314
  {
257
- wchar_t buf[GIT_WIN_PATH];
315
+ git_win32_path buf;
258
316
  mode_t mode = 0;
259
317
 
260
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
318
+ if (utf8_to_16_with_errno(buf, path) < 0)
319
+ return -1;
261
320
 
262
321
  if (flags & O_CREAT) {
263
322
  va_list arg_list;
@@ -267,131 +326,217 @@ int p_open(const char *path, int flags, ...)
267
326
  va_end(arg_list);
268
327
  }
269
328
 
270
- return _wopen(buf, flags | _O_BINARY, mode);
329
+ return _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode);
271
330
  }
272
331
 
273
332
  int p_creat(const char *path, mode_t mode)
274
333
  {
275
- wchar_t buf[GIT_WIN_PATH];
276
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
277
- return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
334
+ git_win32_path buf;
335
+
336
+ if (utf8_to_16_with_errno(buf, path) < 0)
337
+ return -1;
338
+
339
+ return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | STANDARD_OPEN_FLAGS, mode);
278
340
  }
279
341
 
280
342
  int p_getcwd(char *buffer_out, size_t size)
281
343
  {
282
- int ret;
283
- wchar_t *buf;
344
+ git_win32_path buf;
345
+ wchar_t *cwd = _wgetcwd(buf, GIT_WIN_PATH_UTF16);
284
346
 
285
- if ((size_t)((int)size) != size)
347
+ if (!cwd)
286
348
  return -1;
287
349
 
288
- buf = (wchar_t*)git__malloc(sizeof(wchar_t) * (int)size);
289
- GITERR_CHECK_ALLOC(buf);
350
+ /* Convert the working directory back to UTF-8 */
351
+ if (git__utf16_to_8(buffer_out, size, cwd) < 0) {
352
+ DWORD code = GetLastError();
290
353
 
291
- _wgetcwd(buf, (int)size);
354
+ if (code == ERROR_INSUFFICIENT_BUFFER)
355
+ errno = ERANGE;
356
+ else
357
+ errno = EINVAL;
292
358
 
293
- ret = WideCharToMultiByte(
294
- CP_UTF8, 0, buf, -1, buffer_out, (int)size, NULL, NULL);
359
+ return -1;
360
+ }
295
361
 
296
- git__free(buf);
297
- return !ret ? -1 : 0;
362
+ return 0;
363
+ }
364
+
365
+ /*
366
+ * Returns the address of the GetFinalPathNameByHandleW function.
367
+ * This function is available on Windows Vista and higher.
368
+ */
369
+ static PFGetFinalPathNameByHandleW get_fpnbyhandle(void)
370
+ {
371
+ static PFGetFinalPathNameByHandleW pFunc = NULL;
372
+ PFGetFinalPathNameByHandleW toReturn = pFunc;
373
+
374
+ if (!toReturn) {
375
+ HMODULE hModule = GetModuleHandleW(L"kernel32");
376
+
377
+ if (hModule)
378
+ toReturn = (PFGetFinalPathNameByHandleW)GetProcAddress(hModule, "GetFinalPathNameByHandleW");
379
+
380
+ pFunc = toReturn;
381
+ }
382
+
383
+ assert(toReturn);
384
+
385
+ return toReturn;
386
+ }
387
+
388
+ static int getfinalpath_w(
389
+ git_win32_path dest,
390
+ const wchar_t *path)
391
+ {
392
+ PFGetFinalPathNameByHandleW pgfp = get_fpnbyhandle();
393
+ HANDLE hFile;
394
+ DWORD dwChars;
395
+
396
+ if (!pgfp)
397
+ return -1;
398
+
399
+ /* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
400
+ * specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
401
+ * target of the link. */
402
+ hFile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
403
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
404
+
405
+ if (INVALID_HANDLE_VALUE == hFile)
406
+ return -1;
407
+
408
+ /* Call GetFinalPathNameByHandle */
409
+ dwChars = pgfp(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED);
410
+ CloseHandle(hFile);
411
+
412
+ if (!dwChars || dwChars >= GIT_WIN_PATH_UTF16)
413
+ return -1;
414
+
415
+ /* The path may be delivered to us with a prefix; canonicalize */
416
+ return (int)git_win32__canonicalize_path(dest, dwChars);
417
+ }
418
+
419
+ static int follow_and_lstat_link(git_win32_path path, struct stat* buf)
420
+ {
421
+ git_win32_path target_w;
422
+
423
+ if (getfinalpath_w(target_w, path) < 0)
424
+ return -1;
425
+
426
+ return lstat_w(target_w, buf, false);
298
427
  }
299
428
 
300
429
  int p_stat(const char* path, struct stat* buf)
301
430
  {
302
- char target[GIT_WIN_PATH];
303
- int error = 0;
431
+ git_win32_path path_w;
432
+ int len;
304
433
 
305
- error = do_lstat(path, buf, 0);
434
+ if ((len = utf8_to_16_with_errno(path_w, path)) < 0)
435
+ return -1;
306
436
 
307
- /* We need not do this in a loop to unwind chains of symlinks since
308
- * p_readlink calls GetFinalPathNameByHandle which does it for us. */
309
- if (error >= 0 && S_ISLNK(buf->st_mode) &&
310
- (error = p_readlink(path, target, GIT_WIN_PATH)) >= 0)
311
- error = do_lstat(target, buf, 0);
437
+ git_win32__path_trim_end(path_w, len);
312
438
 
313
- return error;
439
+ if (lstat_w(path_w, buf, false) < 0)
440
+ return -1;
441
+
442
+ /* The item is a symbolic link or mount point. No need to iterate
443
+ * to follow multiple links; use GetFinalPathNameFromHandle. */
444
+ if (S_ISLNK(buf->st_mode))
445
+ return follow_and_lstat_link(path_w, buf);
446
+
447
+ return 0;
314
448
  }
315
449
 
316
450
  int p_chdir(const char* path)
317
451
  {
318
- wchar_t buf[GIT_WIN_PATH];
319
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
452
+ git_win32_path buf;
453
+
454
+ if (utf8_to_16_with_errno(buf, path) < 0)
455
+ return -1;
456
+
320
457
  return _wchdir(buf);
321
458
  }
322
459
 
323
460
  int p_chmod(const char* path, mode_t mode)
324
461
  {
325
- wchar_t buf[GIT_WIN_PATH];
326
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
462
+ git_win32_path buf;
463
+
464
+ if (utf8_to_16_with_errno(buf, path) < 0)
465
+ return -1;
466
+
327
467
  return _wchmod(buf, mode);
328
468
  }
329
469
 
330
470
  int p_rmdir(const char* path)
331
471
  {
472
+ git_win32_path buf;
332
473
  int error;
333
- wchar_t buf[GIT_WIN_PATH];
334
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
474
+
475
+ if (utf8_to_16_with_errno(buf, path) < 0)
476
+ return -1;
335
477
 
336
478
  error = _wrmdir(buf);
337
479
 
338
- /* _wrmdir() is documented to return EACCES if "A program has an open
339
- * handle to the directory." This sounds like what everybody else calls
340
- * EBUSY. Let's convert appropriate error codes.
341
- */
342
- if (GetLastError() == ERROR_SHARING_VIOLATION)
343
- errno = EBUSY;
480
+ if (error == -1) {
481
+ switch (GetLastError()) {
482
+ /* _wrmdir() is documented to return EACCES if "A program has an open
483
+ * handle to the directory." This sounds like what everybody else calls
484
+ * EBUSY. Let's convert appropriate error codes.
485
+ */
486
+ case ERROR_SHARING_VIOLATION:
487
+ errno = EBUSY;
488
+ break;
344
489
 
345
- return error;
346
- }
490
+ /* This error can be returned when trying to rmdir an extant file. */
491
+ case ERROR_DIRECTORY:
492
+ errno = ENOTDIR;
493
+ break;
494
+ }
495
+ }
347
496
 
348
- int p_hide_directory__w32(const char *path)
349
- {
350
- wchar_t buf[GIT_WIN_PATH];
351
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
352
- return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1;
497
+ return error;
353
498
  }
354
499
 
355
500
  char *p_realpath(const char *orig_path, char *buffer)
356
501
  {
357
- int ret;
358
- wchar_t orig_path_w[GIT_WIN_PATH];
359
- wchar_t buffer_w[GIT_WIN_PATH];
502
+ git_win32_path orig_path_w, buffer_w;
360
503
 
361
- git__utf8_to_16(orig_path_w, GIT_WIN_PATH, orig_path);
504
+ if (utf8_to_16_with_errno(orig_path_w, orig_path) < 0)
505
+ return NULL;
362
506
 
363
- /* Implicitly use GetCurrentDirectory which can be a threading issue */
364
- ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH, buffer_w, NULL);
507
+ /* Note that if the path provided is a relative path, then the current directory
508
+ * is used to resolve the path -- which is a concurrency issue because the current
509
+ * directory is a process-wide variable. */
510
+ if (!GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL)) {
511
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
512
+ errno = ENAMETOOLONG;
513
+ else
514
+ errno = EINVAL;
365
515
 
366
- /* According to MSDN, a return value equals to zero means a failure. */
367
- if (ret == 0 || ret > GIT_WIN_PATH)
368
- buffer = NULL;
516
+ return NULL;
517
+ }
369
518
 
370
- else if (GetFileAttributesW(buffer_w) == INVALID_FILE_ATTRIBUTES) {
371
- buffer = NULL;
519
+ /* The path must exist. */
520
+ if (GetFileAttributesW(buffer_w) == INVALID_FILE_ATTRIBUTES) {
372
521
  errno = ENOENT;
522
+ return NULL;
373
523
  }
374
524
 
375
- else if (buffer == NULL) {
376
- int buffer_sz = WideCharToMultiByte(
377
- CP_UTF8, 0, buffer_w, -1, NULL, 0, NULL, NULL);
378
-
379
- if (!buffer_sz ||
380
- !(buffer = (char *)git__malloc(buffer_sz)) ||
381
- !WideCharToMultiByte(
382
- CP_UTF8, 0, buffer_w, -1, buffer, buffer_sz, NULL, NULL))
383
- {
384
- git__free(buffer);
385
- buffer = NULL;
386
- }
525
+ /* Convert the path to UTF-8. */
526
+ if (buffer) {
527
+ /* If the caller provided a buffer, then it is assumed to be GIT_WIN_PATH_UTF8
528
+ * characters in size. If it isn't, then we may overflow. */
529
+ if (git__utf16_to_8(buffer, GIT_WIN_PATH_UTF8, buffer_w) < 0)
530
+ return NULL;
531
+ } else {
532
+ /* If the caller did not provide a buffer, then we allocate one for the caller
533
+ * from the heap. */
534
+ if (git__utf16_to_8_alloc(&buffer, buffer_w) < 0)
535
+ return NULL;
387
536
  }
388
537
 
389
- else if (!WideCharToMultiByte(
390
- CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL))
391
- buffer = NULL;
392
-
393
- if (buffer)
394
- git_path_mkposix(buffer);
538
+ /* Convert backslashes to forward slashes */
539
+ git_path_mkposix(buffer);
395
540
 
396
541
  return buffer;
397
542
  }
@@ -423,8 +568,6 @@ int p_snprintf(char *buffer, size_t count, const char *format, ...)
423
568
  return r;
424
569
  }
425
570
 
426
- extern int p_creat(const char *path, mode_t mode);
427
-
428
571
  int p_mkstemp(char *tmp_path)
429
572
  {
430
573
  #if defined(_MSC_VER)
@@ -435,32 +578,75 @@ int p_mkstemp(char *tmp_path)
435
578
  return -1;
436
579
  #endif
437
580
 
438
- return p_creat(tmp_path, 0744); //-V536
581
+ return p_open(tmp_path, O_RDWR | O_CREAT | O_EXCL, 0744); //-V536
439
582
  }
440
583
 
441
- int p_setenv(const char* name, const char* value, int overwrite)
584
+ int p_access(const char* path, mode_t mode)
442
585
  {
443
- if (overwrite != 1)
586
+ git_win32_path buf;
587
+
588
+ if (utf8_to_16_with_errno(buf, path) < 0)
444
589
  return -1;
445
590
 
446
- return (SetEnvironmentVariableA(name, value) == 0 ? -1 : 0);
591
+ return _waccess(buf, mode);
447
592
  }
448
593
 
449
- int p_access(const char* path, mode_t mode)
594
+ static int ensure_writable(wchar_t *fpath)
450
595
  {
451
- wchar_t buf[GIT_WIN_PATH];
452
- git__utf8_to_16(buf, GIT_WIN_PATH, path);
453
- return _waccess(buf, mode);
596
+ DWORD attrs;
597
+
598
+ attrs = GetFileAttributesW(fpath);
599
+ if (attrs == INVALID_FILE_ATTRIBUTES) {
600
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
601
+ return 0;
602
+
603
+ giterr_set(GITERR_OS, "failed to get attributes");
604
+ return -1;
605
+ }
606
+
607
+ if (!(attrs & FILE_ATTRIBUTE_READONLY))
608
+ return 0;
609
+
610
+ attrs &= ~FILE_ATTRIBUTE_READONLY;
611
+ if (!SetFileAttributesW(fpath, attrs)) {
612
+ giterr_set(GITERR_OS, "failed to set attributes");
613
+ return -1;
614
+ }
615
+
616
+ return 0;
454
617
  }
455
618
 
456
619
  int p_rename(const char *from, const char *to)
457
620
  {
458
- wchar_t wfrom[GIT_WIN_PATH];
459
- wchar_t wto[GIT_WIN_PATH];
621
+ git_win32_path wfrom;
622
+ git_win32_path wto;
623
+ int rename_tries;
624
+ int rename_succeeded;
625
+ int error;
626
+
627
+ if (utf8_to_16_with_errno(wfrom, from) < 0 ||
628
+ utf8_to_16_with_errno(wto, to) < 0)
629
+ return -1;
460
630
 
461
- git__utf8_to_16(wfrom, GIT_WIN_PATH, from);
462
- git__utf8_to_16(wto, GIT_WIN_PATH, to);
463
- return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1;
631
+ /* wait up to 50ms if file is locked by another thread or process */
632
+ rename_tries = 0;
633
+ rename_succeeded = 0;
634
+ while (rename_tries < 10) {
635
+ if (ensure_writable(wto) == 0 &&
636
+ MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
637
+ rename_succeeded = 1;
638
+ break;
639
+ }
640
+
641
+ error = GetLastError();
642
+ if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
643
+ Sleep(5);
644
+ rename_tries++;
645
+ } else
646
+ break;
647
+ }
648
+
649
+ return rename_succeeded ? 0 : -1;
464
650
  }
465
651
 
466
652
  int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
@@ -508,94 +694,40 @@ p_gmtime_r (const time_t *timer, struct tm *result)
508
694
  return result;
509
695
  }
510
696
 
511
- #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
512
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
513
- #else
514
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
515
- #endif
516
-
517
- #ifndef _TIMEZONE_DEFINED
518
- #define _TIMEZONE_DEFINED
519
- struct timezone
520
- {
521
- int tz_minuteswest; /* minutes W of Greenwich */
522
- int tz_dsttime; /* type of dst correction */
523
- };
524
- #endif
525
-
526
- int p_gettimeofday(struct timeval *tv, struct timezone *tz)
697
+ int p_inet_pton(int af, const char *src, void *dst)
527
698
  {
528
- FILETIME ft;
529
- unsigned __int64 tmpres = 0;
530
- static int tzflag;
531
-
532
- if (NULL != tv)
533
- {
534
- GetSystemTimeAsFileTime(&ft);
535
-
536
- tmpres |= ft.dwHighDateTime;
537
- tmpres <<= 32;
538
- tmpres |= ft.dwLowDateTime;
539
-
540
- /*converting file time to unix epoch*/
541
- tmpres /= 10; /*convert into microseconds*/
542
- tmpres -= DELTA_EPOCH_IN_MICROSECS;
543
- tv->tv_sec = (long)(tmpres / 1000000UL);
544
- tv->tv_usec = (long)(tmpres % 1000000UL);
545
- }
699
+ struct sockaddr_storage sin;
700
+ void *addr;
701
+ int sin_len = sizeof(struct sockaddr_storage), addr_len;
702
+ int error = 0;
546
703
 
547
- if (NULL != tz)
548
- {
549
- if (!tzflag)
550
- {
551
- _tzset();
552
- tzflag++;
553
- }
554
- tz->tz_minuteswest = _timezone / 60;
555
- tz->tz_dsttime = _daylight;
704
+ if (af == AF_INET) {
705
+ addr = &((struct sockaddr_in *)&sin)->sin_addr;
706
+ addr_len = sizeof(struct in_addr);
707
+ } else if (af == AF_INET6) {
708
+ addr = &((struct sockaddr_in6 *)&sin)->sin6_addr;
709
+ addr_len = sizeof(struct in6_addr);
710
+ } else {
711
+ errno = EAFNOSUPPORT;
712
+ return -1;
556
713
  }
557
714
 
558
- return 0;
559
- }
560
-
561
- int p_inet_pton(int af, const char* src, void* dst)
562
- {
563
- union {
564
- struct sockaddr_in6 sin6;
565
- struct sockaddr_in sin;
566
- } sa;
567
- int srcsize;
568
-
569
- switch(af)
570
- {
571
- case AF_INET:
572
- sa.sin.sin_family = AF_INET;
573
- srcsize = (int)sizeof(sa.sin);
574
- break;
575
- case AF_INET6:
576
- sa.sin6.sin6_family = AF_INET6;
577
- srcsize = (int)sizeof(sa.sin6);
578
- break;
579
- default:
580
- errno = WSAEPFNOSUPPORT;
581
- return -1;
715
+ if ((error = WSAStringToAddressA((LPSTR)src, af, NULL, (LPSOCKADDR)&sin, &sin_len)) == 0) {
716
+ memcpy(dst, addr, addr_len);
717
+ return 1;
582
718
  }
583
719
 
584
- if (WSAStringToAddress((LPSTR)src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
585
- {
586
- errno = WSAGetLastError();
720
+ switch(WSAGetLastError()) {
721
+ case WSAEINVAL:
722
+ return 0;
723
+ case WSAEFAULT:
724
+ errno = ENOSPC;
725
+ return -1;
726
+ case WSA_NOT_ENOUGH_MEMORY:
727
+ errno = ENOMEM;
587
728
  return -1;
588
729
  }
589
730
 
590
- switch(af)
591
- {
592
- case AF_INET:
593
- memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
594
- break;
595
- case AF_INET6:
596
- memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
597
- break;
598
- }
599
-
600
- return 1;
731
+ errno = EINVAL;
732
+ return -1;
601
733
  }