rugged 0.24.6.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +9 -2
  4. data/ext/rugged/rugged.c +85 -21
  5. data/ext/rugged/rugged.h +7 -21
  6. data/ext/rugged/rugged_backend.c +3 -20
  7. data/ext/rugged/rugged_blame.c +7 -24
  8. data/ext/rugged/rugged_blob.c +136 -59
  9. data/ext/rugged/rugged_branch.c +3 -20
  10. data/ext/rugged/rugged_branch_collection.c +3 -20
  11. data/ext/rugged/rugged_commit.c +251 -101
  12. data/ext/rugged/rugged_config.c +3 -20
  13. data/ext/rugged/rugged_cred.c +3 -20
  14. data/ext/rugged/rugged_diff.c +3 -20
  15. data/ext/rugged/rugged_diff_delta.c +3 -20
  16. data/ext/rugged/rugged_diff_hunk.c +3 -20
  17. data/ext/rugged/rugged_diff_line.c +3 -20
  18. data/ext/rugged/rugged_index.c +46 -229
  19. data/ext/rugged/rugged_note.c +3 -20
  20. data/ext/rugged/rugged_object.c +3 -20
  21. data/ext/rugged/rugged_patch.c +192 -34
  22. data/ext/rugged/rugged_rebase.c +90 -48
  23. data/ext/rugged/rugged_reference.c +4 -21
  24. data/ext/rugged/rugged_reference_collection.c +3 -20
  25. data/ext/rugged/rugged_remote.c +70 -42
  26. data/ext/rugged/rugged_remote_collection.c +3 -20
  27. data/ext/rugged/rugged_repo.c +50 -59
  28. data/ext/rugged/rugged_revwalk.c +4 -21
  29. data/ext/rugged/rugged_settings.c +3 -20
  30. data/ext/rugged/rugged_signature.c +3 -20
  31. data/ext/rugged/rugged_submodule.c +4 -21
  32. data/ext/rugged/rugged_submodule_collection.c +3 -20
  33. data/ext/rugged/rugged_tag.c +3 -20
  34. data/ext/rugged/rugged_tag_collection.c +3 -20
  35. data/ext/rugged/rugged_tree.c +189 -184
  36. data/lib/rugged/attributes.rb +5 -0
  37. data/lib/rugged/blob.rb +5 -0
  38. data/lib/rugged/branch.rb +6 -1
  39. data/lib/rugged/commit.rb +5 -0
  40. data/lib/rugged/console.rb +5 -0
  41. data/lib/rugged/credentials.rb +5 -0
  42. data/lib/rugged/diff/delta.rb +5 -0
  43. data/lib/rugged/diff/hunk.rb +5 -0
  44. data/lib/rugged/diff/line.rb +5 -0
  45. data/lib/rugged/diff.rb +5 -0
  46. data/lib/rugged/index.rb +120 -0
  47. data/lib/rugged/object.rb +5 -0
  48. data/lib/rugged/patch.rb +5 -0
  49. data/lib/rugged/reference.rb +5 -0
  50. data/lib/rugged/remote.rb +5 -0
  51. data/lib/rugged/repository.rb +9 -4
  52. data/lib/rugged/submodule_collection.rb +5 -0
  53. data/lib/rugged/tag.rb +5 -0
  54. data/lib/rugged/tree.rb +156 -1
  55. data/lib/rugged/version.rb +6 -1
  56. data/lib/rugged/walker.rb +5 -0
  57. data/lib/rugged.rb +5 -0
  58. data/vendor/libgit2/CMakeLists.txt +12 -2
  59. data/vendor/libgit2/include/git2/blob.h +39 -28
  60. data/vendor/libgit2/include/git2/commit.h +76 -0
  61. data/vendor/libgit2/include/git2/common.h +21 -1
  62. data/vendor/libgit2/include/git2/describe.h +5 -2
  63. data/vendor/libgit2/include/git2/diff.h +62 -7
  64. data/vendor/libgit2/include/git2/errors.h +2 -1
  65. data/vendor/libgit2/include/git2/index.h +25 -0
  66. data/vendor/libgit2/include/git2/merge.h +10 -1
  67. data/vendor/libgit2/include/git2/odb.h +47 -1
  68. data/vendor/libgit2/include/git2/pack.h +4 -4
  69. data/vendor/libgit2/include/git2/patch.h +1 -1
  70. data/vendor/libgit2/include/git2/proxy.h +92 -0
  71. data/vendor/libgit2/include/git2/refs.h +11 -0
  72. data/vendor/libgit2/include/git2/remote.h +21 -8
  73. data/vendor/libgit2/include/git2/repository.h +20 -1
  74. data/vendor/libgit2/include/git2/revwalk.h +4 -6
  75. data/vendor/libgit2/include/git2/signature.h +13 -0
  76. data/vendor/libgit2/include/git2/submodule.h +11 -3
  77. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  78. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  79. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  80. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  81. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  82. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  83. data/vendor/libgit2/include/git2/tag.h +9 -0
  84. data/vendor/libgit2/include/git2/transaction.h +9 -0
  85. data/vendor/libgit2/include/git2/tree.h +55 -0
  86. data/vendor/libgit2/include/git2/version.h +4 -4
  87. data/vendor/libgit2/include/git2.h +1 -0
  88. data/vendor/libgit2/src/annotated_commit.c +99 -80
  89. data/vendor/libgit2/src/annotated_commit.h +5 -2
  90. data/vendor/libgit2/src/apply.c +377 -0
  91. data/vendor/libgit2/src/apply.h +21 -0
  92. data/vendor/libgit2/src/array.h +0 -1
  93. data/vendor/libgit2/src/blob.c +71 -39
  94. data/vendor/libgit2/src/branch.c +7 -5
  95. data/vendor/libgit2/src/buffer.c +252 -20
  96. data/vendor/libgit2/src/buffer.h +8 -0
  97. data/vendor/libgit2/src/checkout.c +69 -42
  98. data/vendor/libgit2/src/clone.c +0 -8
  99. data/vendor/libgit2/src/commit.c +193 -49
  100. data/vendor/libgit2/src/commit_list.c +8 -3
  101. data/vendor/libgit2/src/commit_list.h +1 -0
  102. data/vendor/libgit2/src/common.h +2 -1
  103. data/vendor/libgit2/src/config.c +3 -3
  104. data/vendor/libgit2/src/config_file.c +20 -10
  105. data/vendor/libgit2/src/crlf.c +1 -0
  106. data/vendor/libgit2/src/curl_stream.c +106 -6
  107. data/vendor/libgit2/src/delta.c +238 -62
  108. data/vendor/libgit2/src/delta.h +79 -58
  109. data/vendor/libgit2/src/describe.c +1 -1
  110. data/vendor/libgit2/src/diff.c +32 -1554
  111. data/vendor/libgit2/src/diff.h +14 -122
  112. data/vendor/libgit2/src/diff_driver.c +4 -6
  113. data/vendor/libgit2/src/diff_file.c +3 -0
  114. data/vendor/libgit2/src/diff_generate.c +1613 -0
  115. data/vendor/libgit2/src/diff_generate.h +123 -0
  116. data/vendor/libgit2/src/diff_parse.c +101 -0
  117. data/vendor/libgit2/src/diff_parse.h +18 -0
  118. data/vendor/libgit2/src/diff_print.c +263 -144
  119. data/vendor/libgit2/src/diff_stats.c +21 -12
  120. data/vendor/libgit2/src/diff_tform.c +1 -0
  121. data/vendor/libgit2/src/diff_tform.h +22 -0
  122. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  123. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  124. data/vendor/libgit2/src/fetchhead.c +8 -8
  125. data/vendor/libgit2/src/filebuf.c +6 -1
  126. data/vendor/libgit2/src/filebuf.h +1 -0
  127. data/vendor/libgit2/src/fileops.c +22 -1
  128. data/vendor/libgit2/src/fileops.h +8 -2
  129. data/vendor/libgit2/src/fnmatch.c +18 -5
  130. data/vendor/libgit2/src/global.c +21 -4
  131. data/vendor/libgit2/src/global.h +6 -0
  132. data/vendor/libgit2/src/graph.c +1 -1
  133. data/vendor/libgit2/src/index.c +159 -46
  134. data/vendor/libgit2/src/index.h +2 -0
  135. data/vendor/libgit2/src/iterator.c +1573 -1468
  136. data/vendor/libgit2/src/iterator.h +52 -69
  137. data/vendor/libgit2/src/merge.c +163 -64
  138. data/vendor/libgit2/src/merge.h +61 -2
  139. data/vendor/libgit2/src/merge_driver.c +397 -0
  140. data/vendor/libgit2/src/merge_driver.h +60 -0
  141. data/vendor/libgit2/src/merge_file.c +11 -49
  142. data/vendor/libgit2/src/netops.c +12 -10
  143. data/vendor/libgit2/src/object_api.c +19 -1
  144. data/vendor/libgit2/src/odb.c +228 -52
  145. data/vendor/libgit2/src/odb_loose.c +19 -1
  146. data/vendor/libgit2/src/odb_mempack.c +1 -1
  147. data/vendor/libgit2/src/odb_pack.c +27 -1
  148. data/vendor/libgit2/src/openssl_stream.c +4 -5
  149. data/vendor/libgit2/src/pack-objects.c +105 -76
  150. data/vendor/libgit2/src/pack-objects.h +13 -12
  151. data/vendor/libgit2/src/pack.c +16 -10
  152. data/vendor/libgit2/src/pack.h +2 -0
  153. data/vendor/libgit2/src/patch.c +216 -0
  154. data/vendor/libgit2/src/patch.h +66 -0
  155. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +203 -376
  156. data/vendor/libgit2/src/patch_generate.h +68 -0
  157. data/vendor/libgit2/src/patch_parse.c +1159 -0
  158. data/vendor/libgit2/src/patch_parse.h +56 -0
  159. data/vendor/libgit2/src/path.c +38 -2
  160. data/vendor/libgit2/src/path.h +18 -0
  161. data/vendor/libgit2/src/pathspec.c +1 -1
  162. data/vendor/libgit2/src/pool.h +5 -0
  163. data/vendor/libgit2/src/pqueue.c +12 -5
  164. data/vendor/libgit2/src/pqueue.h +1 -0
  165. data/vendor/libgit2/src/proxy.c +32 -0
  166. data/vendor/libgit2/src/proxy.h +14 -0
  167. data/vendor/libgit2/src/push.c +1 -1
  168. data/vendor/libgit2/src/rebase.c +63 -36
  169. data/vendor/libgit2/src/refdb.c +4 -2
  170. data/vendor/libgit2/src/refdb_fs.c +82 -54
  171. data/vendor/libgit2/src/refs.c +13 -1
  172. data/vendor/libgit2/src/remote.c +20 -81
  173. data/vendor/libgit2/src/repository.c +212 -29
  174. data/vendor/libgit2/src/reset.c +1 -1
  175. data/vendor/libgit2/src/revparse.c +1 -1
  176. data/vendor/libgit2/src/revwalk.c +260 -184
  177. data/vendor/libgit2/src/settings.c +11 -3
  178. data/vendor/libgit2/src/signature.c +27 -2
  179. data/vendor/libgit2/src/sortedcache.c +14 -5
  180. data/vendor/libgit2/src/stash.c +1 -0
  181. data/vendor/libgit2/src/status.c +1 -0
  182. data/vendor/libgit2/src/stransport_stream.c +4 -2
  183. data/vendor/libgit2/src/stream.h +2 -2
  184. data/vendor/libgit2/src/submodule.c +16 -4
  185. data/vendor/libgit2/src/sysdir.c +1 -1
  186. data/vendor/libgit2/src/transport.c +3 -5
  187. data/vendor/libgit2/src/transports/http.c +38 -13
  188. data/vendor/libgit2/src/transports/local.c +4 -1
  189. data/vendor/libgit2/src/transports/smart.c +6 -0
  190. data/vendor/libgit2/src/transports/smart.h +1 -0
  191. data/vendor/libgit2/src/transports/smart_pkt.c +5 -13
  192. data/vendor/libgit2/src/transports/smart_protocol.c +22 -7
  193. data/vendor/libgit2/src/transports/winhttp.c +144 -11
  194. data/vendor/libgit2/src/tree.c +267 -2
  195. data/vendor/libgit2/src/unix/posix.h +10 -0
  196. data/vendor/libgit2/src/unix/pthread.h +2 -0
  197. data/vendor/libgit2/src/util.c +25 -2
  198. data/vendor/libgit2/src/util.h +10 -0
  199. data/vendor/libgit2/src/varint.c +44 -0
  200. data/vendor/libgit2/src/varint.h +15 -0
  201. data/vendor/libgit2/src/vector.c +58 -0
  202. data/vendor/libgit2/src/vector.h +8 -0
  203. data/vendor/libgit2/src/win32/posix.h +3 -0
  204. data/vendor/libgit2/src/win32/thread.c +18 -0
  205. data/vendor/libgit2/src/win32/thread.h +2 -0
  206. data/vendor/libgit2/src/win32/w32_util.h +1 -1
  207. data/vendor/libgit2/src/zstream.c +37 -8
  208. data/vendor/libgit2/src/zstream.h +8 -1
  209. metadata +100 -82
  210. data/vendor/libgit2/Makefile.embed +0 -60
  211. data/vendor/libgit2/src/delta-apply.c +0 -166
  212. data/vendor/libgit2/src/delta-apply.h +0 -62
  213. data/vendor/libgit2/src/diff_patch.h +0 -83
@@ -273,42 +273,51 @@ int git_buf_encode_base64(git_buf *buf, const char *data, size_t len)
273
273
  return 0;
274
274
  }
275
275
 
276
- /* The inverse of base64_encode, offset by '+' == 43. */
276
+ /* The inverse of base64_encode */
277
277
  static const int8_t base64_decode[] = {
278
- 62,
279
- -1, -1, -1,
280
- 63,
281
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
282
- -1, -1, -1, 0, -1, -1, -1,
283
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
284
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
285
- -1, -1, -1, -1, -1, -1,
286
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
287
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
278
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
279
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
280
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
281
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1,
282
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
283
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
284
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
285
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
286
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
287
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
288
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
289
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
290
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
291
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
292
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
288
294
  };
289
295
 
290
- #define BASE64_DECODE_VALUE(c) (((c) < 43 || (c) > 122) ? -1 : base64_decode[c - 43])
291
-
292
296
  int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len)
293
297
  {
294
298
  size_t i;
295
299
  int8_t a, b, c, d;
296
300
  size_t orig_size = buf->size, new_size;
297
301
 
302
+ if (len % 4) {
303
+ giterr_set(GITERR_INVALID, "invalid base64 input");
304
+ return -1;
305
+ }
306
+
298
307
  assert(len % 4 == 0);
299
308
  GITERR_CHECK_ALLOC_ADD(&new_size, (len / 4 * 3), buf->size);
300
309
  GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
301
310
  ENSURE_SIZE(buf, new_size);
302
311
 
303
312
  for (i = 0; i < len; i += 4) {
304
- if ((a = BASE64_DECODE_VALUE(base64[i])) < 0 ||
305
- (b = BASE64_DECODE_VALUE(base64[i+1])) < 0 ||
306
- (c = BASE64_DECODE_VALUE(base64[i+2])) < 0 ||
307
- (d = BASE64_DECODE_VALUE(base64[i+3])) < 0) {
313
+ if ((a = base64_decode[(unsigned char)base64[i]]) < 0 ||
314
+ (b = base64_decode[(unsigned char)base64[i+1]]) < 0 ||
315
+ (c = base64_decode[(unsigned char)base64[i+2]]) < 0 ||
316
+ (d = base64_decode[(unsigned char)base64[i+3]]) < 0) {
308
317
  buf->size = orig_size;
309
318
  buf->ptr[buf->size] = '\0';
310
319
 
311
- giterr_set(GITERR_INVALID, "Invalid base64 input");
320
+ giterr_set(GITERR_INVALID, "invalid base64 input");
312
321
  return -1;
313
322
  }
314
323
 
@@ -321,7 +330,7 @@ int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len)
321
330
  return 0;
322
331
  }
323
332
 
324
- static const char b85str[] =
333
+ static const char base85_encode[] =
325
334
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
326
335
 
327
336
  int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
@@ -351,7 +360,7 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
351
360
  int val = acc % 85;
352
361
  acc /= 85;
353
362
 
354
- b85[i] = b85str[val];
363
+ b85[i] = base85_encode[val];
355
364
  }
356
365
 
357
366
  for (i = 0; i < 5; i++)
@@ -363,6 +372,88 @@ int git_buf_encode_base85(git_buf *buf, const char *data, size_t len)
363
372
  return 0;
364
373
  }
365
374
 
375
+ /* The inverse of base85_encode */
376
+ static const int8_t base85_decode[] = {
377
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
378
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
379
+ -1, 63, -1, 64, 65, 66, 67, -1, 68, 69, 70, 71, -1, 72, -1, -1,
380
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 73, 74, 75, 76, 77,
381
+ 78, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
382
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, -1, -1, 79, 80,
383
+ 81, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
384
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 82, 83, 84, 85, -1,
385
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
386
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
387
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
388
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
389
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
390
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
391
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
392
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
393
+ };
394
+
395
+ int git_buf_decode_base85(
396
+ git_buf *buf,
397
+ const char *base85,
398
+ size_t base85_len,
399
+ size_t output_len)
400
+ {
401
+ size_t orig_size = buf->size, new_size;
402
+
403
+ if (base85_len % 5 ||
404
+ output_len > base85_len * 4 / 5) {
405
+ giterr_set(GITERR_INVALID, "invalid base85 input");
406
+ return -1;
407
+ }
408
+
409
+ GITERR_CHECK_ALLOC_ADD(&new_size, output_len, buf->size);
410
+ GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);
411
+ ENSURE_SIZE(buf, new_size);
412
+
413
+ while (output_len) {
414
+ unsigned acc = 0;
415
+ int de, cnt = 4;
416
+ unsigned char ch;
417
+ do {
418
+ ch = *base85++;
419
+ de = base85_decode[ch];
420
+ if (--de < 0)
421
+ goto on_error;
422
+
423
+ acc = acc * 85 + de;
424
+ } while (--cnt);
425
+ ch = *base85++;
426
+ de = base85_decode[ch];
427
+ if (--de < 0)
428
+ goto on_error;
429
+
430
+ /* Detect overflow. */
431
+ if (0xffffffff / 85 < acc ||
432
+ 0xffffffff - de < (acc *= 85))
433
+ goto on_error;
434
+
435
+ acc += de;
436
+
437
+ cnt = (output_len < 4) ? output_len : 4;
438
+ output_len -= cnt;
439
+ do {
440
+ acc = (acc << 8) | (acc >> 24);
441
+ buf->ptr[buf->size++] = acc;
442
+ } while (--cnt);
443
+ }
444
+
445
+ buf->ptr[buf->size] = 0;
446
+
447
+ return 0;
448
+
449
+ on_error:
450
+ buf->size = orig_size;
451
+ buf->ptr[buf->size] = '\0';
452
+
453
+ giterr_set(GITERR_INVALID, "invalid base85 input");
454
+ return -1;
455
+ }
456
+
366
457
  int git_buf_vprintf(git_buf *buf, const char *format, va_list ap)
367
458
  {
368
459
  size_t expected_size, new_size;
@@ -766,3 +857,144 @@ int git_buf_splice(
766
857
  buf->ptr[buf->size] = '\0';
767
858
  return 0;
768
859
  }
860
+
861
+ /* Quote per http://marc.info/?l=git&m=112927316408690&w=2 */
862
+ int git_buf_quote(git_buf *buf)
863
+ {
864
+ const char whitespace[] = { 'a', 'b', 't', 'n', 'v', 'f', 'r' };
865
+ git_buf quoted = GIT_BUF_INIT;
866
+ size_t i = 0;
867
+ bool quote = false;
868
+ int error = 0;
869
+
870
+ /* walk to the first char that needs quoting */
871
+ if (buf->size && buf->ptr[0] == '!')
872
+ quote = true;
873
+
874
+ for (i = 0; !quote && i < buf->size; i++) {
875
+ if (buf->ptr[i] == '"' || buf->ptr[i] == '\\' ||
876
+ buf->ptr[i] < ' ' || buf->ptr[i] > '~') {
877
+ quote = true;
878
+ break;
879
+ }
880
+ }
881
+
882
+ if (!quote)
883
+ goto done;
884
+
885
+ git_buf_putc(&quoted, '"');
886
+ git_buf_put(&quoted, buf->ptr, i);
887
+
888
+ for (; i < buf->size; i++) {
889
+ /* whitespace - use the map above, which is ordered by ascii value */
890
+ if (buf->ptr[i] >= '\a' && buf->ptr[i] <= '\r') {
891
+ git_buf_putc(&quoted, '\\');
892
+ git_buf_putc(&quoted, whitespace[buf->ptr[i] - '\a']);
893
+ }
894
+
895
+ /* double quote and backslash must be escaped */
896
+ else if (buf->ptr[i] == '"' || buf->ptr[i] == '\\') {
897
+ git_buf_putc(&quoted, '\\');
898
+ git_buf_putc(&quoted, buf->ptr[i]);
899
+ }
900
+
901
+ /* escape anything unprintable as octal */
902
+ else if (buf->ptr[i] != ' ' &&
903
+ (buf->ptr[i] < '!' || buf->ptr[i] > '~')) {
904
+ git_buf_printf(&quoted, "\\%03o", (unsigned char)buf->ptr[i]);
905
+ }
906
+
907
+ /* yay, printable! */
908
+ else {
909
+ git_buf_putc(&quoted, buf->ptr[i]);
910
+ }
911
+ }
912
+
913
+ git_buf_putc(&quoted, '"');
914
+
915
+ if (git_buf_oom(&quoted)) {
916
+ error = -1;
917
+ goto done;
918
+ }
919
+
920
+ git_buf_swap(&quoted, buf);
921
+
922
+ done:
923
+ git_buf_free(&quoted);
924
+ return error;
925
+ }
926
+
927
+ /* Unquote per http://marc.info/?l=git&m=112927316408690&w=2 */
928
+ int git_buf_unquote(git_buf *buf)
929
+ {
930
+ size_t i, j;
931
+ char ch;
932
+
933
+ git_buf_rtrim(buf);
934
+
935
+ if (buf->size < 2 || buf->ptr[0] != '"' || buf->ptr[buf->size-1] != '"')
936
+ goto invalid;
937
+
938
+ for (i = 0, j = 1; j < buf->size-1; i++, j++) {
939
+ ch = buf->ptr[j];
940
+
941
+ if (ch == '\\') {
942
+ if (j == buf->size-2)
943
+ goto invalid;
944
+
945
+ ch = buf->ptr[++j];
946
+
947
+ switch (ch) {
948
+ /* \" or \\ simply copy the char in */
949
+ case '"': case '\\':
950
+ break;
951
+
952
+ /* add the appropriate escaped char */
953
+ case 'a': ch = '\a'; break;
954
+ case 'b': ch = '\b'; break;
955
+ case 'f': ch = '\f'; break;
956
+ case 'n': ch = '\n'; break;
957
+ case 'r': ch = '\r'; break;
958
+ case 't': ch = '\t'; break;
959
+ case 'v': ch = '\v'; break;
960
+
961
+ /* \xyz digits convert to the char*/
962
+ case '0': case '1': case '2': case '3':
963
+ if (j == buf->size-3) {
964
+ giterr_set(GITERR_INVALID,
965
+ "Truncated quoted character \\%c", ch);
966
+ return -1;
967
+ }
968
+
969
+ if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' ||
970
+ buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') {
971
+ giterr_set(GITERR_INVALID,
972
+ "Truncated quoted character \\%c%c%c",
973
+ buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]);
974
+ return -1;
975
+ }
976
+
977
+ ch = ((buf->ptr[j] - '0') << 6) |
978
+ ((buf->ptr[j+1] - '0') << 3) |
979
+ (buf->ptr[j+2] - '0');
980
+ j += 2;
981
+ break;
982
+
983
+ default:
984
+ giterr_set(GITERR_INVALID, "Invalid quoted character \\%c", ch);
985
+ return -1;
986
+ }
987
+ }
988
+
989
+ buf->ptr[i] = ch;
990
+ }
991
+
992
+ buf->ptr[i] = '\0';
993
+ buf->size = i;
994
+
995
+ return 0;
996
+
997
+ invalid:
998
+ giterr_set(GITERR_INVALID, "Invalid quoted line");
999
+ return -1;
1000
+ }
@@ -173,6 +173,12 @@ void git_buf_rtrim(git_buf *buf);
173
173
 
174
174
  int git_buf_cmp(const git_buf *a, const git_buf *b);
175
175
 
176
+ /* Quote and unquote a buffer as specified in
177
+ * http://marc.info/?l=git&m=112927316408690&w=2
178
+ */
179
+ int git_buf_quote(git_buf *buf);
180
+ int git_buf_unquote(git_buf *buf);
181
+
176
182
  /* Write data as base64 encoded in buffer */
177
183
  int git_buf_encode_base64(git_buf *buf, const char *data, size_t len);
178
184
  /* Decode the given bas64 and write the result to the buffer */
@@ -180,6 +186,8 @@ int git_buf_decode_base64(git_buf *buf, const char *base64, size_t len);
180
186
 
181
187
  /* Write data as "base85" encoded in buffer */
182
188
  int git_buf_encode_base85(git_buf *buf, const char *data, size_t len);
189
+ /* Decode the given "base85" and write the result to the buffer */
190
+ int git_buf_decode_base85(git_buf *buf, const char *base64, size_t len, size_t output_len);
183
191
 
184
192
  /*
185
193
  * Insert, remove or replace a portion of the buffer.
@@ -26,6 +26,7 @@
26
26
  #include "filter.h"
27
27
  #include "blob.h"
28
28
  #include "diff.h"
29
+ #include "diff_generate.h"
29
30
  #include "pathspec.h"
30
31
  #include "buf_text.h"
31
32
  #include "diff_xdiff.h"
@@ -66,8 +67,8 @@ typedef struct {
66
67
  git_vector update_conflicts;
67
68
  git_vector *update_reuc;
68
69
  git_vector *update_names;
69
- git_buf path;
70
- size_t workdir_len;
70
+ git_buf target_path;
71
+ size_t target_len;
71
72
  git_buf tmp;
72
73
  unsigned int strategy;
73
74
  int can_symlink;
@@ -211,6 +212,10 @@ static bool checkout_is_workdir_modified(
211
212
  if (baseitem->size && wditem->file_size != baseitem->size)
212
213
  return true;
213
214
 
215
+ /* if the workdir item is a directory, it cannot be a modified file */
216
+ if (S_ISDIR(wditem->mode))
217
+ return false;
218
+
214
219
  if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
215
220
  return false;
216
221
 
@@ -294,14 +299,30 @@ static int checkout_action_no_wd(
294
299
  return checkout_action_common(action, data, delta, NULL);
295
300
  }
296
301
 
297
- static bool wd_item_is_removable(git_iterator *iter, const git_index_entry *wd)
302
+ static int checkout_target_fullpath(
303
+ git_buf **out, checkout_data *data, const char *path)
298
304
  {
299
- git_buf *full = NULL;
305
+ git_buf_truncate(&data->target_path, data->target_len);
306
+
307
+ if (path && git_buf_puts(&data->target_path, path) < 0)
308
+ return -1;
309
+
310
+ *out = &data->target_path;
311
+
312
+ return 0;
313
+ }
314
+
315
+ static bool wd_item_is_removable(
316
+ checkout_data *data, const git_index_entry *wd)
317
+ {
318
+ git_buf *full;
300
319
 
301
320
  if (wd->mode != GIT_FILEMODE_TREE)
302
321
  return true;
303
- if (git_iterator_current_workdir_path(&full, iter) < 0)
304
- return true;
322
+
323
+ if (checkout_target_fullpath(&full, data, wd->path) < 0)
324
+ return false;
325
+
305
326
  return !full || !git_path_contains(full, DOT_GIT);
306
327
  }
307
328
 
@@ -363,14 +384,14 @@ static int checkout_action_wd_only(
363
384
  if ((error = checkout_notify(data, notify, NULL, wd)) != 0)
364
385
  return error;
365
386
 
366
- if (remove && wd_item_is_removable(workdir, wd))
387
+ if (remove && wd_item_is_removable(data, wd))
367
388
  error = checkout_queue_remove(data, wd->path);
368
389
 
369
390
  if (!error)
370
391
  error = git_iterator_advance(wditem, workdir);
371
392
  } else {
372
393
  /* untracked or ignored - can't know which until we advance through */
373
- bool over = false, removable = wd_item_is_removable(workdir, wd);
394
+ bool over = false, removable = wd_item_is_removable(data, wd);
374
395
  git_iterator_status_t untracked_state;
375
396
 
376
397
  /* copy the entry for issuing notification callback later */
@@ -378,7 +399,7 @@ static int checkout_action_wd_only(
378
399
  git_buf_sets(&data->tmp, wd->path);
379
400
  saved_wd.path = data->tmp.ptr;
380
401
 
381
- error = git_iterator_advance_over_with_status(
402
+ error = git_iterator_advance_over(
382
403
  wditem, &untracked_state, workdir);
383
404
  if (error == GIT_ITEROVER)
384
405
  over = true;
@@ -428,10 +449,12 @@ static bool submodule_is_config_only(
428
449
 
429
450
  static bool checkout_is_empty_dir(checkout_data *data, const char *path)
430
451
  {
431
- git_buf_truncate(&data->path, data->workdir_len);
432
- if (git_buf_puts(&data->path, path) < 0)
452
+ git_buf *fullpath;
453
+
454
+ if (checkout_target_fullpath(&fullpath, data, path) < 0)
433
455
  return false;
434
- return git_path_is_empty_dir(data->path.ptr);
456
+
457
+ return git_path_is_empty_dir(fullpath->ptr);
435
458
  }
436
459
 
437
460
  static int checkout_action_with_wd(
@@ -640,7 +663,7 @@ static int checkout_action(
640
663
  if (cmp == 0) {
641
664
  if (wd->mode == GIT_FILEMODE_TREE) {
642
665
  /* case 2 - entry prefixed by workdir tree */
643
- error = git_iterator_advance_into_or_over(wditem, workdir);
666
+ error = git_iterator_advance_into(wditem, workdir);
644
667
  if (error < 0 && error != GIT_ITEROVER)
645
668
  goto done;
646
669
  continue;
@@ -913,7 +936,7 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
913
936
  git_index *index;
914
937
 
915
938
  /* Only write conficts from sources that have them: indexes. */
916
- if ((index = git_iterator_get_index(data->target)) == NULL)
939
+ if ((index = git_iterator_index(data->target)) == NULL)
917
940
  return 0;
918
941
 
919
942
  data->update_conflicts._cmp = checkout_conflictdata_cmp;
@@ -1063,7 +1086,7 @@ static int checkout_conflicts_coalesce_renames(
1063
1086
  size_t i, names;
1064
1087
  int error = 0;
1065
1088
 
1066
- if ((index = git_iterator_get_index(data->target)) == NULL)
1089
+ if ((index = git_iterator_index(data->target)) == NULL)
1067
1090
  return 0;
1068
1091
 
1069
1092
  /* Juggle entries based on renames */
@@ -1121,7 +1144,7 @@ static int checkout_conflicts_mark_directoryfile(
1121
1144
  const char *path;
1122
1145
  int prefixed, error = 0;
1123
1146
 
1124
- if ((index = git_iterator_get_index(data->target)) == NULL)
1147
+ if ((index = git_iterator_index(data->target)) == NULL)
1125
1148
  return 0;
1126
1149
 
1127
1150
  len = git_index_entrycount(index);
@@ -1585,18 +1608,18 @@ static int checkout_submodule_update_index(
1585
1608
  checkout_data *data,
1586
1609
  const git_diff_file *file)
1587
1610
  {
1611
+ git_buf *fullpath;
1588
1612
  struct stat st;
1589
1613
 
1590
1614
  /* update the index unless prevented */
1591
1615
  if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) != 0)
1592
1616
  return 0;
1593
1617
 
1594
- git_buf_truncate(&data->path, data->workdir_len);
1595
- if (git_buf_puts(&data->path, file->path) < 0)
1618
+ if (checkout_target_fullpath(&fullpath, data, file->path) < 0)
1596
1619
  return -1;
1597
1620
 
1598
1621
  data->perfdata.stat_calls++;
1599
- if (p_stat(git_buf_cstr(&data->path), &st) < 0) {
1622
+ if (p_stat(fullpath->ptr, &st) < 0) {
1600
1623
  giterr_set(
1601
1624
  GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path);
1602
1625
  return GIT_ENOTFOUND;
@@ -1721,22 +1744,23 @@ static int checkout_blob(
1721
1744
  checkout_data *data,
1722
1745
  const git_diff_file *file)
1723
1746
  {
1724
- int error = 0;
1747
+ git_buf *fullpath;
1725
1748
  struct stat st;
1749
+ int error = 0;
1726
1750
 
1727
- git_buf_truncate(&data->path, data->workdir_len);
1728
- if (git_buf_puts(&data->path, file->path) < 0)
1751
+ if (checkout_target_fullpath(&fullpath, data, file->path) < 0)
1729
1752
  return -1;
1730
1753
 
1731
1754
  if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) {
1732
1755
  int rval = checkout_safe_for_update_only(
1733
- data, git_buf_cstr(&data->path), file->mode);
1756
+ data, fullpath->ptr, file->mode);
1757
+
1734
1758
  if (rval <= 0)
1735
1759
  return rval;
1736
1760
  }
1737
1761
 
1738
1762
  error = checkout_write_content(
1739
- data, &file->id, git_buf_cstr(&data->path), NULL, file->mode, &st);
1763
+ data, &file->id, fullpath->ptr, NULL, file->mode, &st);
1740
1764
 
1741
1765
  /* update the index unless prevented */
1742
1766
  if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
@@ -1757,18 +1781,21 @@ static int checkout_remove_the_old(
1757
1781
  git_diff_delta *delta;
1758
1782
  const char *str;
1759
1783
  size_t i;
1760
- const char *workdir = git_buf_cstr(&data->path);
1784
+ git_buf *fullpath;
1761
1785
  uint32_t flg = GIT_RMDIR_EMPTY_PARENTS |
1762
1786
  GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS;
1763
1787
 
1764
1788
  if (data->opts.checkout_strategy & GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES)
1765
1789
  flg |= GIT_RMDIR_SKIP_NONEMPTY;
1766
1790
 
1767
- git_buf_truncate(&data->path, data->workdir_len);
1791
+ if (checkout_target_fullpath(&fullpath, data, NULL) < 0)
1792
+ return -1;
1768
1793
 
1769
1794
  git_vector_foreach(&data->diff->deltas, i, delta) {
1770
1795
  if (actions[i] & CHECKOUT_ACTION__REMOVE) {
1771
- error = git_futils_rmdir_r(delta->old_file.path, workdir, flg);
1796
+ error = git_futils_rmdir_r(
1797
+ delta->old_file.path, fullpath->ptr, flg);
1798
+
1772
1799
  if (error < 0)
1773
1800
  return error;
1774
1801
 
@@ -1785,7 +1812,7 @@ static int checkout_remove_the_old(
1785
1812
  }
1786
1813
 
1787
1814
  git_vector_foreach(&data->removes, i, str) {
1788
- error = git_futils_rmdir_r(str, workdir, flg);
1815
+ error = git_futils_rmdir_r(str, fullpath->ptr, flg);
1789
1816
  if (error < 0)
1790
1817
  return error;
1791
1818
 
@@ -1939,7 +1966,7 @@ static int checkout_path_suffixed(git_buf *path, const char *suffix)
1939
1966
  if (i == INT_MAX) {
1940
1967
  git_buf_truncate(path, path_len);
1941
1968
 
1942
- giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path);
1969
+ giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path->ptr);
1943
1970
  return GIT_EEXISTS;
1944
1971
  }
1945
1972
 
@@ -1952,13 +1979,13 @@ static int checkout_write_entry(
1952
1979
  const git_index_entry *side)
1953
1980
  {
1954
1981
  const char *hint_path = NULL, *suffix;
1982
+ git_buf *fullpath;
1955
1983
  struct stat st;
1956
1984
  int error;
1957
1985
 
1958
1986
  assert (side == conflict->ours || side == conflict->theirs);
1959
1987
 
1960
- git_buf_truncate(&data->path, data->workdir_len);
1961
- if (git_buf_puts(&data->path, side->path) < 0)
1988
+ if (checkout_target_fullpath(&fullpath, data, side->path) < 0)
1962
1989
  return -1;
1963
1990
 
1964
1991
  if ((conflict->name_collision || conflict->directoryfile) &&
@@ -1972,18 +1999,18 @@ static int checkout_write_entry(
1972
1999
  suffix = data->opts.their_label ? data->opts.their_label :
1973
2000
  "theirs";
1974
2001
 
1975
- if (checkout_path_suffixed(&data->path, suffix) < 0)
2002
+ if (checkout_path_suffixed(fullpath, suffix) < 0)
1976
2003
  return -1;
1977
2004
 
1978
2005
  hint_path = side->path;
1979
2006
  }
1980
2007
 
1981
2008
  if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
1982
- (error = checkout_safe_for_update_only(data, git_buf_cstr(&data->path), side->mode)) <= 0)
2009
+ (error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0)
1983
2010
  return error;
1984
2011
 
1985
2012
  return checkout_write_content(data,
1986
- &side->id, git_buf_cstr(&data->path), hint_path, side->mode, &st);
2013
+ &side->id, fullpath->ptr, hint_path, side->mode, &st);
1987
2014
  }
1988
2015
 
1989
2016
  static int checkout_write_entries(
@@ -2296,7 +2323,7 @@ static void checkout_data_clear(checkout_data *data)
2296
2323
 
2297
2324
  git_strmap_free(data->mkdir_map);
2298
2325
 
2299
- git_buf_free(&data->path);
2326
+ git_buf_free(&data->target_path);
2300
2327
  git_buf_free(&data->tmp);
2301
2328
 
2302
2329
  git_index_free(data->index);
@@ -2359,7 +2386,7 @@ static int checkout_data_init(
2359
2386
  if ((error = git_repository_index(&data->index, data->repo)) < 0)
2360
2387
  goto cleanup;
2361
2388
 
2362
- if (data->index != git_iterator_get_index(target)) {
2389
+ if (data->index != git_iterator_index(target)) {
2363
2390
  if ((error = git_index_read(data->index, true)) < 0)
2364
2391
  goto cleanup;
2365
2392
 
@@ -2442,7 +2469,7 @@ static int checkout_data_init(
2442
2469
  data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
2443
2470
  else {
2444
2471
  giterr_set(GITERR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
2445
- conflict_style);
2472
+ conflict_style->value);
2446
2473
  error = -1;
2447
2474
  git_config_entry_free(conflict_style);
2448
2475
  goto cleanup;
@@ -2455,12 +2482,12 @@ static int checkout_data_init(
2455
2482
  if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
2456
2483
  (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 ||
2457
2484
  (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 ||
2458
- (error = git_buf_puts(&data->path, data->opts.target_directory)) < 0 ||
2459
- (error = git_path_to_dir(&data->path)) < 0 ||
2485
+ (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 ||
2486
+ (error = git_path_to_dir(&data->target_path)) < 0 ||
2460
2487
  (error = git_strmap_alloc(&data->mkdir_map)) < 0)
2461
2488
  goto cleanup;
2462
2489
 
2463
- data->workdir_len = git_buf_len(&data->path);
2490
+ data->target_len = git_buf_len(&data->target_path);
2464
2491
 
2465
2492
  git_attr_session__init(&data->attr_session, data->repo);
2466
2493
 
@@ -2516,7 +2543,7 @@ int git_checkout_iterator(
2516
2543
  workdir_opts.start = data.pfx;
2517
2544
  workdir_opts.end = data.pfx;
2518
2545
 
2519
- if ((error = git_iterator_reset(target, data.pfx, data.pfx)) < 0 ||
2546
+ if ((error = git_iterator_reset_range(target, data.pfx, data.pfx)) < 0 ||
2520
2547
  (error = git_iterator_for_workdir_ext(
2521
2548
  &workdir, data.repo, data.opts.target_directory, index, NULL,
2522
2549
  &workdir_opts)) < 0)
@@ -2586,7 +2613,7 @@ int git_checkout_iterator(
2586
2613
  (error = checkout_create_conflicts(&data)) < 0)
2587
2614
  goto cleanup;
2588
2615
 
2589
- if (data.index != git_iterator_get_index(target) &&
2616
+ if (data.index != git_iterator_index(target) &&
2590
2617
  (error = checkout_extensions_update_index(&data)) < 0)
2591
2618
  goto cleanup;
2592
2619
 
@@ -461,14 +461,6 @@ int git_clone_init_options(git_clone_options *opts, unsigned int version)
461
461
  return 0;
462
462
  }
463
463
 
464
- static const char *repository_base(git_repository *repo)
465
- {
466
- if (git_repository_is_bare(repo))
467
- return git_repository_path(repo);
468
-
469
- return git_repository_workdir(repo);
470
- }
471
-
472
464
  static bool can_link(const char *src, const char *dst, int link)
473
465
  {
474
466
  #ifdef GIT_WIN32