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
@@ -19,6 +19,7 @@
19
19
  #include "blob.h"
20
20
  #include "idxmap.h"
21
21
  #include "diff.h"
22
+ #include "varint.h"
22
23
 
23
24
  #include "git2/odb.h"
24
25
  #include "git2/oid.h"
@@ -65,8 +66,11 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
65
66
  static const size_t INDEX_FOOTER_SIZE = GIT_OID_RAWSZ;
66
67
  static const size_t INDEX_HEADER_SIZE = 12;
67
68
 
68
- static const unsigned int INDEX_VERSION_NUMBER = 2;
69
+ static const unsigned int INDEX_VERSION_NUMBER_DEFAULT = 2;
70
+ static const unsigned int INDEX_VERSION_NUMBER_LB = 2;
69
71
  static const unsigned int INDEX_VERSION_NUMBER_EXT = 3;
72
+ static const unsigned int INDEX_VERSION_NUMBER_COMP = 4;
73
+ static const unsigned int INDEX_VERSION_NUMBER_UB = 4;
70
74
 
71
75
  static const unsigned int INDEX_HEADER_SIG = 0x44495243;
72
76
  static const char INDEX_EXT_TREECACHE_SIG[] = {'T', 'R', 'E', 'E'};
@@ -434,6 +438,7 @@ int git_index_open(git_index **index_out, const char *index_path)
434
438
  index->entries_search = git_index_entry_srch;
435
439
  index->entries_search_path = index_entry_srch_path;
436
440
  index->reuc_search = reuc_srch;
441
+ index->version = INDEX_VERSION_NUMBER_DEFAULT;
437
442
 
438
443
  if (index_path != NULL && (error = git_index_read(index, true)) < 0)
439
444
  goto fail;
@@ -547,7 +552,7 @@ int git_index_clear(git_index *index)
547
552
 
548
553
  static int create_index_error(int error, const char *msg)
549
554
  {
550
- giterr_set(GITERR_INDEX, msg);
555
+ giterr_set_str(GITERR_INDEX, msg);
551
556
  return error;
552
557
  }
553
558
 
@@ -747,6 +752,28 @@ done:
747
752
  return 0;
748
753
  }
749
754
 
755
+ unsigned git_index_version(git_index *index)
756
+ {
757
+ assert(index);
758
+
759
+ return index->version;
760
+ }
761
+
762
+ int git_index_set_version(git_index *index, unsigned int version)
763
+ {
764
+ assert(index);
765
+
766
+ if (version < INDEX_VERSION_NUMBER_LB ||
767
+ version > INDEX_VERSION_NUMBER_UB) {
768
+ giterr_set(GITERR_INDEX, "Invalid version number");
769
+ return -1;
770
+ }
771
+
772
+ index->version = version;
773
+
774
+ return 0;
775
+ }
776
+
750
777
  int git_index_write(git_index *index)
751
778
  {
752
779
  git_indexwriter writer = GIT_INDEXWRITER_INIT;
@@ -2160,12 +2187,12 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
2160
2187
 
2161
2188
  if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
2162
2189
  !endptr || endptr == buffer || *endptr ||
2163
- tmp < 0) {
2190
+ tmp < 0 || tmp > UINT32_MAX) {
2164
2191
  index_entry_reuc_free(lost);
2165
2192
  return index_error_invalid("reading reuc entry stage");
2166
2193
  }
2167
2194
 
2168
- lost->mode[i] = tmp;
2195
+ lost->mode[i] = (uint32_t)tmp;
2169
2196
 
2170
2197
  len = (endptr + 1) - buffer;
2171
2198
  if (size <= len) {
@@ -2262,12 +2289,15 @@ static size_t read_entry(
2262
2289
  git_index_entry **out,
2263
2290
  git_index *index,
2264
2291
  const void *buffer,
2265
- size_t buffer_size)
2292
+ size_t buffer_size,
2293
+ const char **last)
2266
2294
  {
2267
2295
  size_t path_length, entry_size;
2268
2296
  const char *path_ptr;
2269
2297
  struct entry_short source;
2270
2298
  git_index_entry entry = {{0}};
2299
+ bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP;
2300
+ char *tmp_path = NULL;
2271
2301
 
2272
2302
  if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
2273
2303
  return 0;
@@ -2302,33 +2332,56 @@ static size_t read_entry(
2302
2332
  } else
2303
2333
  path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
2304
2334
 
2305
- path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
2335
+ if (!compressed) {
2336
+ path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
2306
2337
 
2307
- /* if this is a very long string, we must find its
2308
- * real length without overflowing */
2309
- if (path_length == 0xFFF) {
2310
- const char *path_end;
2338
+ /* if this is a very long string, we must find its
2339
+ * real length without overflowing */
2340
+ if (path_length == 0xFFF) {
2341
+ const char *path_end;
2311
2342
 
2312
- path_end = memchr(path_ptr, '\0', buffer_size);
2313
- if (path_end == NULL)
2314
- return 0;
2315
-
2316
- path_length = path_end - path_ptr;
2317
- }
2343
+ path_end = memchr(path_ptr, '\0', buffer_size);
2344
+ if (path_end == NULL)
2345
+ return 0;
2318
2346
 
2319
- if (entry.flags & GIT_IDXENTRY_EXTENDED)
2320
- entry_size = long_entry_size(path_length);
2321
- else
2322
- entry_size = short_entry_size(path_length);
2347
+ path_length = path_end - path_ptr;
2348
+ }
2323
2349
 
2324
- if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2325
- return 0;
2350
+ if (entry.flags & GIT_IDXENTRY_EXTENDED)
2351
+ entry_size = long_entry_size(path_length);
2352
+ else
2353
+ entry_size = short_entry_size(path_length);
2326
2354
 
2327
- entry.path = (char *)path_ptr;
2355
+ if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2356
+ return 0;
2328
2357
 
2329
- if (index_entry_dup(out, index, &entry) < 0)
2358
+ entry.path = (char *)path_ptr;
2359
+ } else {
2360
+ size_t varint_len;
2361
+ size_t shared = git_decode_varint((const unsigned char *)path_ptr,
2362
+ &varint_len);
2363
+ size_t len = strlen(path_ptr + varint_len);
2364
+ size_t last_len = strlen(*last);
2365
+ size_t tmp_path_len;
2366
+
2367
+ if (varint_len == 0)
2368
+ return index_error_invalid("incorrect prefix length");
2369
+
2370
+ GITERR_CHECK_ALLOC_ADD(&tmp_path_len, shared, len + 1);
2371
+ tmp_path = git__malloc(tmp_path_len);
2372
+ GITERR_CHECK_ALLOC(tmp_path);
2373
+ memcpy(tmp_path, last, last_len);
2374
+ memcpy(tmp_path + last_len, path_ptr + varint_len, len);
2375
+ entry_size = long_entry_size(shared + len);
2376
+ entry.path = tmp_path;
2377
+ }
2378
+
2379
+ if (index_entry_dup(out, index, &entry) < 0) {
2380
+ git__free(tmp_path);
2330
2381
  return 0;
2382
+ }
2331
2383
 
2384
+ git__free(tmp_path);
2332
2385
  return entry_size;
2333
2386
  }
2334
2387
 
@@ -2341,8 +2394,8 @@ static int read_header(struct index_header *dest, const void *buffer)
2341
2394
  return index_error_invalid("incorrect header signature");
2342
2395
 
2343
2396
  dest->version = ntohl(source->version);
2344
- if (dest->version != INDEX_VERSION_NUMBER_EXT &&
2345
- dest->version != INDEX_VERSION_NUMBER)
2397
+ if (dest->version < INDEX_VERSION_NUMBER_LB ||
2398
+ dest->version > INDEX_VERSION_NUMBER_UB)
2346
2399
  return index_error_invalid("incorrect header version");
2347
2400
 
2348
2401
  dest->entry_count = ntohl(source->entry_count);
@@ -2395,6 +2448,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2395
2448
  unsigned int i;
2396
2449
  struct index_header header = { 0 };
2397
2450
  git_oid checksum_calculated, checksum_expected;
2451
+ const char **last = NULL;
2452
+ const char *empty = "";
2398
2453
 
2399
2454
  #define seek_forward(_increase) { \
2400
2455
  if (_increase >= buffer_size) { \
@@ -2415,6 +2470,10 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2415
2470
  if ((error = read_header(&header, buffer)) < 0)
2416
2471
  return error;
2417
2472
 
2473
+ index->version = header.version;
2474
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
2475
+ last = &empty;
2476
+
2418
2477
  seek_forward(INDEX_HEADER_SIZE);
2419
2478
 
2420
2479
  assert(!index->entries.length);
@@ -2427,7 +2486,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2427
2486
  /* Parse all the entries */
2428
2487
  for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
2429
2488
  git_index_entry *entry;
2430
- size_t entry_size = read_entry(&entry, index, buffer, buffer_size);
2489
+ size_t entry_size = read_entry(&entry, index, buffer, buffer_size, last);
2431
2490
 
2432
2491
  /* 0 bytes read means an object corruption */
2433
2492
  if (entry_size == 0) {
@@ -2518,15 +2577,31 @@ static bool is_index_extended(git_index *index)
2518
2577
  return (extended > 0);
2519
2578
  }
2520
2579
 
2521
- static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
2580
+ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const char **last)
2522
2581
  {
2523
2582
  void *mem = NULL;
2524
2583
  struct entry_short *ondisk;
2525
2584
  size_t path_len, disk_size;
2526
2585
  char *path;
2586
+ const char *path_start = entry->path;
2587
+ size_t same_len = 0;
2527
2588
 
2528
2589
  path_len = ((struct entry_internal *)entry)->pathlen;
2529
2590
 
2591
+ if (last) {
2592
+ const char *last_c = *last;
2593
+
2594
+ while (*path_start == *last_c) {
2595
+ if (!*path_start || !*last_c)
2596
+ break;
2597
+ ++path_start;
2598
+ ++last_c;
2599
+ ++same_len;
2600
+ }
2601
+ path_len -= same_len;
2602
+ *last = entry->path;
2603
+ }
2604
+
2530
2605
  if (entry->flags & GIT_IDXENTRY_EXTENDED)
2531
2606
  disk_size = long_entry_size(path_len);
2532
2607
  else
@@ -2574,7 +2649,12 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
2574
2649
  else
2575
2650
  path = ondisk->path;
2576
2651
 
2577
- memcpy(path, entry->path, path_len);
2652
+ if (last) {
2653
+ path += git_encode_varint((unsigned char *) path,
2654
+ disk_size,
2655
+ path_len - same_len);
2656
+ }
2657
+ memcpy(path, path_start, path_len);
2578
2658
 
2579
2659
  return 0;
2580
2660
  }
@@ -2585,6 +2665,8 @@ static int write_entries(git_index *index, git_filebuf *file)
2585
2665
  size_t i;
2586
2666
  git_vector case_sorted, *entries;
2587
2667
  git_index_entry *entry;
2668
+ const char **last = NULL;
2669
+ const char *empty = "";
2588
2670
 
2589
2671
  /* If index->entries is sorted case-insensitively, then we need
2590
2672
  * to re-sort it case-sensitively before writing */
@@ -2596,8 +2678,11 @@ static int write_entries(git_index *index, git_filebuf *file)
2596
2678
  entries = &index->entries;
2597
2679
  }
2598
2680
 
2681
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
2682
+ last = &empty;
2683
+
2599
2684
  git_vector_foreach(entries, i, entry)
2600
- if ((error = write_disk_entry(file, entry)) < 0)
2685
+ if ((error = write_disk_entry(file, entry, last)) < 0)
2601
2686
  break;
2602
2687
 
2603
2688
  if (index->ignore_case)
@@ -2762,8 +2847,12 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
2762
2847
 
2763
2848
  assert(index && file);
2764
2849
 
2765
- is_extended = is_index_extended(index);
2766
- index_version_number = is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER;
2850
+ if (index->version <= INDEX_VERSION_NUMBER_EXT) {
2851
+ is_extended = is_index_extended(index);
2852
+ index_version_number = is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER_LB;
2853
+ } else {
2854
+ index_version_number = index->version;
2855
+ }
2767
2856
 
2768
2857
  header.signature = htonl(INDEX_HEADER_SIG);
2769
2858
  header.version = htonl(index_version_number);
@@ -2925,38 +3014,39 @@ cleanup:
2925
3014
  return error;
2926
3015
  }
2927
3016
 
2928
- int git_index_read_index(
3017
+ static int git_index_read_iterator(
2929
3018
  git_index *index,
2930
- const git_index *new_index)
3019
+ git_iterator *new_iterator,
3020
+ size_t new_length_hint)
2931
3021
  {
2932
3022
  git_vector new_entries = GIT_VECTOR_INIT,
2933
3023
  remove_entries = GIT_VECTOR_INIT;
2934
3024
  git_idxmap *new_entries_map = NULL;
2935
3025
  git_iterator *index_iterator = NULL;
2936
- git_iterator *new_iterator = NULL;
2937
3026
  git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2938
3027
  const git_index_entry *old_entry, *new_entry;
2939
3028
  git_index_entry *entry;
2940
3029
  size_t i;
2941
3030
  int error;
2942
3031
 
2943
- if ((error = git_vector_init(&new_entries, new_index->entries.length, index->entries._cmp)) < 0 ||
3032
+ assert((new_iterator->flags & GIT_ITERATOR_DONT_IGNORE_CASE));
3033
+
3034
+ if ((error = git_vector_init(&new_entries, new_length_hint, index->entries._cmp)) < 0 ||
2944
3035
  (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 ||
2945
3036
  (error = git_idxmap_alloc(&new_entries_map)) < 0)
2946
3037
  goto done;
2947
3038
 
2948
- if (index->ignore_case)
2949
- kh_resize(idxicase, (khash_t(idxicase) *) new_entries_map, new_index->entries.length);
2950
- else
2951
- kh_resize(idx, new_entries_map, new_index->entries.length);
3039
+ if (index->ignore_case && new_length_hint)
3040
+ kh_resize(idxicase, (khash_t(idxicase) *) new_entries_map, new_length_hint);
3041
+ else if (new_length_hint)
3042
+ kh_resize(idx, new_entries_map, new_length_hint);
2952
3043
 
2953
- opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
3044
+ opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
3045
+ GIT_ITERATOR_INCLUDE_CONFLICTS;
2954
3046
 
2955
- if ((error = git_iterator_for_index(&index_iterator, git_index_owner(index), index, &opts)) < 0 ||
2956
- (error = git_iterator_for_index(&new_iterator, git_index_owner(new_index), (git_index *)new_index, &opts)) < 0)
2957
- goto done;
2958
-
2959
- if (((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
3047
+ if ((error = git_iterator_for_index(&index_iterator,
3048
+ git_index_owner(index), index, &opts)) < 0 ||
3049
+ ((error = git_iterator_current(&old_entry, index_iterator)) < 0 &&
2960
3050
  error != GIT_ITEROVER) ||
2961
3051
  ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
2962
3052
  error != GIT_ITEROVER))
@@ -3050,6 +3140,8 @@ int git_index_read_index(
3050
3140
  index_entry_free(entry);
3051
3141
  }
3052
3142
 
3143
+ clear_uptodate(index);
3144
+
3053
3145
  error = 0;
3054
3146
 
3055
3147
  done:
@@ -3057,6 +3149,27 @@ done:
3057
3149
  git_vector_free(&new_entries);
3058
3150
  git_vector_free(&remove_entries);
3059
3151
  git_iterator_free(index_iterator);
3152
+ return error;
3153
+ }
3154
+
3155
+ int git_index_read_index(
3156
+ git_index *index,
3157
+ const git_index *new_index)
3158
+ {
3159
+ git_iterator *new_iterator = NULL;
3160
+ git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
3161
+ int error;
3162
+
3163
+ opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
3164
+ GIT_ITERATOR_INCLUDE_CONFLICTS;
3165
+
3166
+ if ((error = git_iterator_for_index(&new_iterator,
3167
+ git_index_owner(new_index), (git_index *)new_index, &opts)) < 0 ||
3168
+ (error = git_index_read_iterator(index, new_iterator,
3169
+ new_index->entries.length)) < 0)
3170
+ goto done;
3171
+
3172
+ done:
3060
3173
  git_iterator_free(new_iterator);
3061
3174
  return error;
3062
3175
  }
@@ -46,6 +46,8 @@ struct git_index {
46
46
  git_vector_cmp entries_search;
47
47
  git_vector_cmp entries_search_path;
48
48
  git_vector_cmp reuc_search;
49
+
50
+ unsigned int version;
49
51
  };
50
52
 
51
53
  struct git_index_conflict_iterator {