rugged 0.25.0b5 → 0.25.0b6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged_patch.c +77 -17
  3. data/lib/rugged/version.rb +1 -1
  4. data/vendor/libgit2/CMakeLists.txt +8 -6
  5. data/vendor/libgit2/include/git2/checkout.h +7 -0
  6. data/vendor/libgit2/include/git2/common.h +1 -0
  7. data/vendor/libgit2/include/git2/diff.h +54 -7
  8. data/vendor/libgit2/include/git2/errors.h +2 -1
  9. data/vendor/libgit2/include/git2/index.h +25 -0
  10. data/vendor/libgit2/include/git2/pack.h +4 -4
  11. data/vendor/libgit2/include/git2/repository.h +20 -1
  12. data/vendor/libgit2/include/git2/submodule.h +11 -3
  13. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  14. data/vendor/libgit2/src/apply.c +369 -0
  15. data/vendor/libgit2/src/apply.h +21 -0
  16. data/vendor/libgit2/src/array.h +0 -1
  17. data/vendor/libgit2/src/blame_git.c +18 -8
  18. data/vendor/libgit2/src/buffer.c +252 -20
  19. data/vendor/libgit2/src/buffer.h +8 -0
  20. data/vendor/libgit2/src/checkout.c +7 -1
  21. data/vendor/libgit2/src/clone.c +0 -8
  22. data/vendor/libgit2/src/common.h +1 -1
  23. data/vendor/libgit2/src/crlf.c +1 -0
  24. data/vendor/libgit2/src/delta.c +238 -62
  25. data/vendor/libgit2/src/delta.h +79 -58
  26. data/vendor/libgit2/src/diff.c +32 -1547
  27. data/vendor/libgit2/src/diff.h +12 -122
  28. data/vendor/libgit2/src/diff_driver.c +1 -2
  29. data/vendor/libgit2/src/diff_file.c +3 -0
  30. data/vendor/libgit2/src/diff_generate.c +1611 -0
  31. data/vendor/libgit2/src/diff_generate.h +123 -0
  32. data/vendor/libgit2/src/diff_parse.c +105 -0
  33. data/vendor/libgit2/src/diff_print.c +259 -142
  34. data/vendor/libgit2/src/diff_stats.c +3 -2
  35. data/vendor/libgit2/src/diff_tform.c +1 -0
  36. data/vendor/libgit2/src/diff_tform.h +22 -0
  37. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  38. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  39. data/vendor/libgit2/src/fileops.c +13 -0
  40. data/vendor/libgit2/src/fileops.h +6 -0
  41. data/vendor/libgit2/src/global.c +9 -8
  42. data/vendor/libgit2/src/ignore.c +45 -16
  43. data/vendor/libgit2/src/index.c +161 -47
  44. data/vendor/libgit2/src/index.h +2 -0
  45. data/vendor/libgit2/src/merge.c +2 -0
  46. data/vendor/libgit2/src/mwindow.c +8 -19
  47. data/vendor/libgit2/src/mwindow.h +1 -2
  48. data/vendor/libgit2/src/odb.c +46 -10
  49. data/vendor/libgit2/src/odb_loose.c +19 -1
  50. data/vendor/libgit2/src/odb_pack.c +27 -4
  51. data/vendor/libgit2/src/pack-objects.c +106 -77
  52. data/vendor/libgit2/src/pack-objects.h +13 -12
  53. data/vendor/libgit2/src/pack.c +4 -3
  54. data/vendor/libgit2/src/pack.h +2 -0
  55. data/vendor/libgit2/src/patch.c +207 -0
  56. data/vendor/libgit2/src/patch.h +66 -0
  57. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +171 -359
  58. data/vendor/libgit2/src/patch_generate.h +66 -0
  59. data/vendor/libgit2/src/patch_parse.c +1121 -0
  60. data/vendor/libgit2/src/patch_parse.h +54 -0
  61. data/vendor/libgit2/src/path.c +19 -0
  62. data/vendor/libgit2/src/path.h +6 -0
  63. data/vendor/libgit2/src/pool.h +5 -0
  64. data/vendor/libgit2/src/remote.c +15 -80
  65. data/vendor/libgit2/src/repository.c +227 -39
  66. data/vendor/libgit2/src/settings.c +11 -5
  67. data/vendor/libgit2/src/stash.c +1 -0
  68. data/vendor/libgit2/src/status.c +1 -0
  69. data/vendor/libgit2/src/stransport_stream.c +14 -9
  70. data/vendor/libgit2/src/submodule.c +16 -4
  71. data/vendor/libgit2/src/sysdir.c +41 -47
  72. data/vendor/libgit2/src/sysdir.h +0 -5
  73. data/vendor/libgit2/src/thread-utils.h +5 -51
  74. data/vendor/libgit2/src/transport.c +3 -5
  75. data/vendor/libgit2/src/transports/http.c +2 -3
  76. data/vendor/libgit2/src/transports/smart_pkt.c +1 -0
  77. data/vendor/libgit2/src/transports/smart_protocol.c +11 -0
  78. data/vendor/libgit2/src/transports/winhttp.c +16 -2
  79. data/vendor/libgit2/src/unix/pthread.h +54 -0
  80. data/vendor/libgit2/src/util.c +23 -5
  81. data/vendor/libgit2/src/util.h +10 -0
  82. data/vendor/libgit2/src/varint.c +44 -0
  83. data/vendor/libgit2/src/varint.h +15 -0
  84. data/vendor/libgit2/src/vector.c +42 -0
  85. data/vendor/libgit2/src/vector.h +3 -0
  86. data/vendor/libgit2/src/win32/precompiled.h +1 -1
  87. data/vendor/libgit2/src/win32/{pthread.c → thread.c} +50 -80
  88. data/vendor/libgit2/src/win32/thread.h +62 -0
  89. data/vendor/libgit2/src/zstream.c +36 -7
  90. data/vendor/libgit2/src/zstream.h +8 -1
  91. metadata +20 -9
  92. data/vendor/libgit2/src/delta-apply.c +0 -166
  93. data/vendor/libgit2/src/delta-apply.h +0 -62
  94. data/vendor/libgit2/src/diff_patch.h +0 -83
  95. data/vendor/libgit2/src/win32/pthread.h +0 -92
@@ -7,7 +7,7 @@
7
7
  #include "common.h"
8
8
  #include "vector.h"
9
9
  #include "diff.h"
10
- #include "diff_patch.h"
10
+ #include "patch_generate.h"
11
11
 
12
12
  #define DIFF_RENAME_FILE_SEPARATOR " => "
13
13
  #define STATS_FULL_MIN_SCALE 7
@@ -190,8 +190,9 @@ int git_diff_get_stats(
190
190
  break;
191
191
 
192
192
  /* keep a count of renames because it will affect formatting */
193
- delta = git_patch_get_delta(patch);
193
+ delta = patch->delta;
194
194
 
195
+ /* TODO ugh */
195
196
  namelen = strlen(delta->new_file.path);
196
197
  if (strcmp(delta->old_file.path, delta->new_file.path) != 0) {
197
198
  namelen += strlen(delta->old_file.path);
@@ -11,6 +11,7 @@
11
11
  #include "git2/sys/hashsig.h"
12
12
 
13
13
  #include "diff.h"
14
+ #include "diff_generate.h"
14
15
  #include "path.h"
15
16
  #include "fileops.h"
16
17
  #include "config.h"
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_diff_tform_h__
8
+ #define INCLUDE_diff_tform_h__
9
+
10
+ extern int git_diff_find_similar__hashsig_for_file(
11
+ void **out, const git_diff_file *f, const char *path, void *p);
12
+
13
+ extern int git_diff_find_similar__hashsig_for_buf(
14
+ void **out, const git_diff_file *f, const char *buf, size_t len, void *p);
15
+
16
+ extern void git_diff_find_similar__hashsig_free(void *sig, void *payload);
17
+
18
+ extern int git_diff_find_similar__calc_similarity(
19
+ int *score, void *siga, void *sigb, void *payload);
20
+
21
+ #endif
22
+
@@ -8,8 +8,8 @@
8
8
  #include "common.h"
9
9
  #include "diff.h"
10
10
  #include "diff_driver.h"
11
- #include "diff_patch.h"
12
11
  #include "diff_xdiff.h"
12
+ #include "patch_generate.h"
13
13
 
14
14
  static int git_xdiff_scan_int(const char **str, int *value)
15
15
  {
@@ -56,7 +56,7 @@ fail:
56
56
 
57
57
  typedef struct {
58
58
  git_xdiff_output *xo;
59
- git_patch *patch;
59
+ git_patch_generated *patch;
60
60
  git_diff_hunk hunk;
61
61
  int old_lineno, new_lineno;
62
62
  mmfile_t xd_old_data, xd_new_data;
@@ -110,9 +110,9 @@ static int diff_update_lines(
110
110
  static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
111
111
  {
112
112
  git_xdiff_info *info = priv;
113
- git_patch *patch = info->patch;
114
- const git_diff_delta *delta = git_patch_get_delta(patch);
115
- git_diff_output *output = &info->xo->output;
113
+ git_patch_generated *patch = info->patch;
114
+ const git_diff_delta *delta = patch->base.delta;
115
+ git_patch_generated_output *output = &info->xo->output;
116
116
  git_diff_line line;
117
117
 
118
118
  if (len == 1) {
@@ -181,7 +181,7 @@ static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len)
181
181
  return output->error;
182
182
  }
183
183
 
184
- static int git_xdiff(git_diff_output *output, git_patch *patch)
184
+ static int git_xdiff(git_patch_generated_output *output, git_patch_generated *patch)
185
185
  {
186
186
  git_xdiff_output *xo = (git_xdiff_output *)output;
187
187
  git_xdiff_info info;
@@ -194,7 +194,7 @@ static int git_xdiff(git_diff_output *output, git_patch *patch)
194
194
  xo->callback.priv = &info;
195
195
 
196
196
  git_diff_find_context_init(
197
- &xo->config.find_func, &findctxt, git_patch__driver(patch));
197
+ &xo->config.find_func, &findctxt, git_patch_generated_driver(patch));
198
198
  xo->config.find_func_priv = &findctxt;
199
199
 
200
200
  if (xo->config.find_func != NULL)
@@ -206,8 +206,8 @@ static int git_xdiff(git_diff_output *output, git_patch *patch)
206
206
  * updates are needed to xo->params.flags
207
207
  */
208
208
 
209
- git_patch__old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch);
210
- git_patch__new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch);
209
+ git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch);
210
+ git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch);
211
211
 
212
212
  if (info.xd_old_data.size > GIT_XDIFF_MAX_SIZE ||
213
213
  info.xd_new_data.size > GIT_XDIFF_MAX_SIZE) {
@@ -8,20 +8,20 @@
8
8
  #define INCLUDE_diff_xdiff_h__
9
9
 
10
10
  #include "diff.h"
11
- #include "diff_patch.h"
12
11
  #include "xdiff/xdiff.h"
12
+ #include "patch_generate.h"
13
13
 
14
14
  /* xdiff cannot cope with large files. these files should not be passed to
15
15
  * xdiff. callers should treat these large files as binary.
16
16
  */
17
17
  #define GIT_XDIFF_MAX_SIZE (1024LL * 1024 * 1023)
18
18
 
19
- /* A git_xdiff_output is a git_diff_output with extra fields necessary
20
- * to use libxdiff. Calling git_xdiff_init() will set the diff_cb field
21
- * of the output to use xdiff to generate the diffs.
19
+ /* A git_xdiff_output is a git_patch_generate_output with extra fields
20
+ * necessary to use libxdiff. Calling git_xdiff_init() will set the diff_cb
21
+ * field of the output to use xdiff to generate the diffs.
22
22
  */
23
23
  typedef struct {
24
- git_diff_output output;
24
+ git_patch_generated_output output;
25
25
 
26
26
  xdemitconf_t config;
27
27
  xpparam_t params;
@@ -837,6 +837,19 @@ int git_futils_cp(const char *from, const char *to, mode_t filemode)
837
837
  return cp_by_fd(ifd, ofd, true);
838
838
  }
839
839
 
840
+ int git_futils_touch(const char *path, time_t *when)
841
+ {
842
+ struct p_timeval times[2];
843
+ int ret;
844
+
845
+ times[0].tv_sec = times[1].tv_sec = when ? *when : time(NULL);
846
+ times[0].tv_usec = times[1].tv_usec = 0;
847
+
848
+ ret = p_utimes(path, times);
849
+
850
+ return (ret < 0) ? git_path_set_error(errno, path, "touch") : 0;
851
+ }
852
+
840
853
  static int cp_link(const char *from, const char *to, size_t link_size)
841
854
  {
842
855
  int error = 0;
@@ -184,6 +184,12 @@ extern int git_futils_cp(
184
184
  const char *to,
185
185
  mode_t filemode);
186
186
 
187
+ /**
188
+ * Set the files atime and mtime to the given time, or the current time
189
+ * if `ts` is NULL.
190
+ */
191
+ extern int git_futils_touch(const char *path, time_t *when);
192
+
187
193
  /**
188
194
  * Flags that can be passed to `git_futils_cp_r`.
189
195
  *
@@ -61,8 +61,9 @@ static int init_common(void)
61
61
  (ret = git_sysdir_global_init()) == 0 &&
62
62
  (ret = git_filter_global_init()) == 0 &&
63
63
  (ret = git_merge_driver_global_init()) == 0 &&
64
- (ret = git_transport_ssh_global_init()) == 0)
65
- ret = git_openssl_stream_global_init();
64
+ (ret = git_transport_ssh_global_init()) == 0 &&
65
+ (ret = git_openssl_stream_global_init()) == 0)
66
+ ret = git_mwindow_global_init();
66
67
 
67
68
  GIT_MEMORY_BARRIER;
68
69
 
@@ -87,11 +88,6 @@ static void shutdown_common(void)
87
88
 
88
89
  git__free(git__user_agent);
89
90
  git__free(git__ssl_ciphers);
90
-
91
- #if defined(GIT_MSVC_CRTDBG)
92
- git_win32__crtdbg_stacktrace_cleanup();
93
- git_win32__stack_cleanup();
94
- #endif
95
91
  }
96
92
 
97
93
  /**
@@ -139,7 +135,7 @@ static int synchronized_threads_init(void)
139
135
 
140
136
  _tls_index = TlsAlloc();
141
137
 
142
- win32_pthread_initialize();
138
+ git_threads_init();
143
139
 
144
140
  if (git_mutex_init(&git__mwindow_mutex))
145
141
  return -1;
@@ -183,6 +179,11 @@ int git_libgit2_shutdown(void)
183
179
 
184
180
  TlsFree(_tls_index);
185
181
  git_mutex_free(&git__mwindow_mutex);
182
+
183
+ #if defined(GIT_MSVC_CRTDBG)
184
+ git_win32__crtdbg_stacktrace_cleanup();
185
+ git_win32__stack_cleanup();
186
+ #endif
186
187
  }
187
188
 
188
189
  /* Exit the lock */
@@ -11,35 +11,64 @@
11
11
  #define GIT_IGNORE_DEFAULT_RULES ".\n..\n.git\n"
12
12
 
13
13
  /**
14
- * A negative ignore pattern can match a positive one without
15
- * wildcards if its pattern equals the tail of the positive
16
- * pattern. Thus
14
+ * A negative ignore pattern can negate a positive one without
15
+ * wildcards if it is a basename only and equals the basename of
16
+ * the positive pattern. Thus
17
17
  *
18
18
  * foo/bar
19
19
  * !bar
20
20
  *
21
- * would result in foo/bar being unignored again.
21
+ * would result in foo/bar being unignored again while
22
+ *
23
+ * moo/foo/bar
24
+ * !foo/bar
25
+ *
26
+ * would do nothing. The reverse also holds true: a positive
27
+ * basename pattern can be negated by unignoring the basename in
28
+ * subdirectories. Thus
29
+ *
30
+ * bar
31
+ * !foo/bar
32
+ *
33
+ * would result in foo/bar being unignored again. As with the
34
+ * first case,
35
+ *
36
+ * foo/bar
37
+ * !moo/foo/bar
38
+ *
39
+ * would do nothing, again.
22
40
  */
23
41
  static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
24
42
  {
43
+ git_attr_fnmatch *longer, *shorter;
25
44
  char *p;
26
45
 
27
46
  if ((rule->flags & GIT_ATTR_FNMATCH_NEGATIVE) == 0
28
47
  && (neg->flags & GIT_ATTR_FNMATCH_NEGATIVE) != 0) {
29
- /*
30
- * no chance of matching if rule is shorter than
31
- * the negated one
32
- */
33
- if (rule->length < neg->length)
48
+
49
+ /* If lengths match we need to have an exact match */
50
+ if (rule->length == neg->length) {
51
+ return strcmp(rule->pattern, neg->pattern) == 0;
52
+ } else if (rule->length < neg->length) {
53
+ shorter = rule;
54
+ longer = neg;
55
+ } else {
56
+ shorter = neg;
57
+ longer = rule;
58
+ }
59
+
60
+ /* Otherwise, we need to check if the shorter
61
+ * rule is a basename only (that is, it contains
62
+ * no path separator) and, if so, if it
63
+ * matches the tail of the longer rule */
64
+ p = longer->pattern + longer->length - shorter->length;
65
+
66
+ if (p[-1] != '/')
67
+ return false;
68
+ if (memchr(shorter->pattern, '/', shorter->length) != NULL)
34
69
  return false;
35
70
 
36
- /*
37
- * shift pattern so its tail aligns with the
38
- * negated pattern
39
- */
40
- p = rule->pattern + rule->length - neg->length;
41
- if (strcmp(p, neg->pattern) == 0)
42
- return true;
71
+ return memcmp(p, shorter->pattern, shorter->length) == 0;
43
72
  }
44
73
 
45
74
  return false;
@@ -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;
@@ -505,10 +510,11 @@ static int index_remove_entry(git_index *index, size_t pos)
505
510
  int error = 0;
506
511
  git_index_entry *entry = git_vector_get(&index->entries, pos);
507
512
 
508
- if (entry != NULL)
513
+ if (entry != NULL) {
509
514
  git_tree_cache_invalidate_path(index->tree, entry->path);
515
+ DELETE_IN_MAP(index, entry);
516
+ }
510
517
 
511
- DELETE_IN_MAP(index, entry);
512
518
  error = git_vector_remove(&index->entries, pos);
513
519
 
514
520
  if (!error) {
@@ -746,6 +752,28 @@ done:
746
752
  return 0;
747
753
  }
748
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
+
749
777
  int git_index_write(git_index *index)
750
778
  {
751
779
  git_indexwriter writer = GIT_INDEXWRITER_INIT;
@@ -2159,12 +2187,12 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
2159
2187
 
2160
2188
  if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
2161
2189
  !endptr || endptr == buffer || *endptr ||
2162
- tmp < 0) {
2190
+ tmp < 0 || tmp > UINT32_MAX) {
2163
2191
  index_entry_reuc_free(lost);
2164
2192
  return index_error_invalid("reading reuc entry stage");
2165
2193
  }
2166
2194
 
2167
- lost->mode[i] = tmp;
2195
+ lost->mode[i] = (uint32_t)tmp;
2168
2196
 
2169
2197
  len = (endptr + 1) - buffer;
2170
2198
  if (size <= len) {
@@ -2261,12 +2289,15 @@ static size_t read_entry(
2261
2289
  git_index_entry **out,
2262
2290
  git_index *index,
2263
2291
  const void *buffer,
2264
- size_t buffer_size)
2292
+ size_t buffer_size,
2293
+ const char **last)
2265
2294
  {
2266
2295
  size_t path_length, entry_size;
2267
2296
  const char *path_ptr;
2268
2297
  struct entry_short source;
2269
2298
  git_index_entry entry = {{0}};
2299
+ bool compressed = index->version >= INDEX_VERSION_NUMBER_COMP;
2300
+ char *tmp_path = NULL;
2270
2301
 
2271
2302
  if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
2272
2303
  return 0;
@@ -2301,33 +2332,56 @@ static size_t read_entry(
2301
2332
  } else
2302
2333
  path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
2303
2334
 
2304
- path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
2335
+ if (!compressed) {
2336
+ path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
2305
2337
 
2306
- /* if this is a very long string, we must find its
2307
- * real length without overflowing */
2308
- if (path_length == 0xFFF) {
2309
- 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;
2310
2342
 
2311
- path_end = memchr(path_ptr, '\0', buffer_size);
2312
- if (path_end == NULL)
2313
- return 0;
2314
-
2315
- path_length = path_end - path_ptr;
2316
- }
2343
+ path_end = memchr(path_ptr, '\0', buffer_size);
2344
+ if (path_end == NULL)
2345
+ return 0;
2317
2346
 
2318
- if (entry.flags & GIT_IDXENTRY_EXTENDED)
2319
- entry_size = long_entry_size(path_length);
2320
- else
2321
- entry_size = short_entry_size(path_length);
2347
+ path_length = path_end - path_ptr;
2348
+ }
2322
2349
 
2323
- if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2324
- 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);
2325
2354
 
2326
- entry.path = (char *)path_ptr;
2355
+ if (INDEX_FOOTER_SIZE + entry_size > buffer_size)
2356
+ return 0;
2327
2357
 
2328
- 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);
2329
2381
  return 0;
2382
+ }
2330
2383
 
2384
+ git__free(tmp_path);
2331
2385
  return entry_size;
2332
2386
  }
2333
2387
 
@@ -2340,8 +2394,8 @@ static int read_header(struct index_header *dest, const void *buffer)
2340
2394
  return index_error_invalid("incorrect header signature");
2341
2395
 
2342
2396
  dest->version = ntohl(source->version);
2343
- if (dest->version != INDEX_VERSION_NUMBER_EXT &&
2344
- dest->version != INDEX_VERSION_NUMBER)
2397
+ if (dest->version < INDEX_VERSION_NUMBER_LB ||
2398
+ dest->version > INDEX_VERSION_NUMBER_UB)
2345
2399
  return index_error_invalid("incorrect header version");
2346
2400
 
2347
2401
  dest->entry_count = ntohl(source->entry_count);
@@ -2394,6 +2448,8 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2394
2448
  unsigned int i;
2395
2449
  struct index_header header = { 0 };
2396
2450
  git_oid checksum_calculated, checksum_expected;
2451
+ const char **last = NULL;
2452
+ const char *empty = "";
2397
2453
 
2398
2454
  #define seek_forward(_increase) { \
2399
2455
  if (_increase >= buffer_size) { \
@@ -2414,6 +2470,10 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2414
2470
  if ((error = read_header(&header, buffer)) < 0)
2415
2471
  return error;
2416
2472
 
2473
+ index->version = header.version;
2474
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
2475
+ last = &empty;
2476
+
2417
2477
  seek_forward(INDEX_HEADER_SIZE);
2418
2478
 
2419
2479
  assert(!index->entries.length);
@@ -2426,7 +2486,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
2426
2486
  /* Parse all the entries */
2427
2487
  for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
2428
2488
  git_index_entry *entry;
2429
- size_t entry_size = read_entry(&entry, index, buffer, buffer_size);
2489
+ size_t entry_size = read_entry(&entry, index, buffer, buffer_size, last);
2430
2490
 
2431
2491
  /* 0 bytes read means an object corruption */
2432
2492
  if (entry_size == 0) {
@@ -2517,15 +2577,31 @@ static bool is_index_extended(git_index *index)
2517
2577
  return (extended > 0);
2518
2578
  }
2519
2579
 
2520
- 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)
2521
2581
  {
2522
2582
  void *mem = NULL;
2523
2583
  struct entry_short *ondisk;
2524
2584
  size_t path_len, disk_size;
2525
2585
  char *path;
2586
+ const char *path_start = entry->path;
2587
+ size_t same_len = 0;
2526
2588
 
2527
2589
  path_len = ((struct entry_internal *)entry)->pathlen;
2528
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
+
2529
2605
  if (entry->flags & GIT_IDXENTRY_EXTENDED)
2530
2606
  disk_size = long_entry_size(path_len);
2531
2607
  else
@@ -2573,7 +2649,12 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
2573
2649
  else
2574
2650
  path = ondisk->path;
2575
2651
 
2576
- 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);
2577
2658
 
2578
2659
  return 0;
2579
2660
  }
@@ -2584,6 +2665,8 @@ static int write_entries(git_index *index, git_filebuf *file)
2584
2665
  size_t i;
2585
2666
  git_vector case_sorted, *entries;
2586
2667
  git_index_entry *entry;
2668
+ const char **last = NULL;
2669
+ const char *empty = "";
2587
2670
 
2588
2671
  /* If index->entries is sorted case-insensitively, then we need
2589
2672
  * to re-sort it case-sensitively before writing */
@@ -2595,8 +2678,11 @@ static int write_entries(git_index *index, git_filebuf *file)
2595
2678
  entries = &index->entries;
2596
2679
  }
2597
2680
 
2681
+ if (index->version >= INDEX_VERSION_NUMBER_COMP)
2682
+ last = &empty;
2683
+
2598
2684
  git_vector_foreach(entries, i, entry)
2599
- if ((error = write_disk_entry(file, entry)) < 0)
2685
+ if ((error = write_disk_entry(file, entry, last)) < 0)
2600
2686
  break;
2601
2687
 
2602
2688
  if (index->ignore_case)
@@ -2761,8 +2847,12 @@ static int write_index(git_oid *checksum, git_index *index, git_filebuf *file)
2761
2847
 
2762
2848
  assert(index && file);
2763
2849
 
2764
- is_extended = is_index_extended(index);
2765
- 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
+ }
2766
2856
 
2767
2857
  header.signature = htonl(INDEX_HEADER_SIG);
2768
2858
  header.version = htonl(index_version_number);
@@ -2924,38 +3014,39 @@ cleanup:
2924
3014
  return error;
2925
3015
  }
2926
3016
 
2927
- int git_index_read_index(
3017
+ static int git_index_read_iterator(
2928
3018
  git_index *index,
2929
- const git_index *new_index)
3019
+ git_iterator *new_iterator,
3020
+ size_t new_length_hint)
2930
3021
  {
2931
3022
  git_vector new_entries = GIT_VECTOR_INIT,
2932
3023
  remove_entries = GIT_VECTOR_INIT;
2933
3024
  git_idxmap *new_entries_map = NULL;
2934
3025
  git_iterator *index_iterator = NULL;
2935
- git_iterator *new_iterator = NULL;
2936
3026
  git_iterator_options opts = GIT_ITERATOR_OPTIONS_INIT;
2937
3027
  const git_index_entry *old_entry, *new_entry;
2938
3028
  git_index_entry *entry;
2939
3029
  size_t i;
2940
3030
  int error;
2941
3031
 
2942
- 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 ||
2943
3035
  (error = git_vector_init(&remove_entries, index->entries.length, NULL)) < 0 ||
2944
3036
  (error = git_idxmap_alloc(&new_entries_map)) < 0)
2945
3037
  goto done;
2946
3038
 
2947
- if (index->ignore_case)
2948
- kh_resize(idxicase, (khash_t(idxicase) *) new_entries_map, new_index->entries.length);
2949
- else
2950
- kh_resize(idx, new_entries_map, new_index->entries.length);
2951
-
2952
- opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
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);
2953
3043
 
2954
- if ((error = git_iterator_for_index(&index_iterator, git_index_owner(index), index, &opts)) < 0 ||
2955
- (error = git_iterator_for_index(&new_iterator, git_index_owner(new_index), (git_index *)new_index, &opts)) < 0)
2956
- goto done;
3044
+ opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE |
3045
+ GIT_ITERATOR_INCLUDE_CONFLICTS;
2957
3046
 
2958
- 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 &&
2959
3050
  error != GIT_ITEROVER) ||
2960
3051
  ((error = git_iterator_current(&new_entry, new_iterator)) < 0 &&
2961
3052
  error != GIT_ITEROVER))
@@ -3049,6 +3140,8 @@ int git_index_read_index(
3049
3140
  index_entry_free(entry);
3050
3141
  }
3051
3142
 
3143
+ clear_uptodate(index);
3144
+
3052
3145
  error = 0;
3053
3146
 
3054
3147
  done:
@@ -3056,6 +3149,27 @@ done:
3056
3149
  git_vector_free(&new_entries);
3057
3150
  git_vector_free(&remove_entries);
3058
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:
3059
3173
  git_iterator_free(new_iterator);
3060
3174
  return error;
3061
3175
  }