rugged 0.22.2 → 0.23.0b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged.c +1 -2
  3. data/ext/rugged/rugged_branch_collection.c +6 -44
  4. data/ext/rugged/rugged_config.c +7 -3
  5. data/ext/rugged/rugged_diff_delta.c +1 -1
  6. data/ext/rugged/rugged_diff_line.c +1 -1
  7. data/ext/rugged/rugged_object.c +2 -2
  8. data/ext/rugged/rugged_reference_collection.c +12 -56
  9. data/ext/rugged/rugged_remote.c +4 -33
  10. data/ext/rugged/rugged_remote_collection.c +1 -1
  11. data/ext/rugged/rugged_repo.c +10 -36
  12. data/ext/rugged/rugged_settings.c +3 -3
  13. data/ext/rugged/rugged_tree.c +1 -1
  14. data/lib/rugged/version.rb +1 -1
  15. data/vendor/libgit2/CMakeLists.txt +10 -3
  16. data/vendor/libgit2/COPYING +15 -21
  17. data/vendor/libgit2/include/git2/annotated_commit.h +20 -3
  18. data/vendor/libgit2/include/git2/branch.h +20 -16
  19. data/vendor/libgit2/include/git2/checkout.h +32 -18
  20. data/vendor/libgit2/include/git2/cherrypick.h +2 -2
  21. data/vendor/libgit2/include/git2/clone.h +4 -10
  22. data/vendor/libgit2/include/git2/config.h +66 -12
  23. data/vendor/libgit2/include/git2/describe.h +3 -2
  24. data/vendor/libgit2/include/git2/diff.h +3 -3
  25. data/vendor/libgit2/include/git2/errors.h +1 -0
  26. data/vendor/libgit2/include/git2/filter.h +21 -5
  27. data/vendor/libgit2/include/git2/index.h +32 -0
  28. data/vendor/libgit2/include/git2/merge.h +20 -3
  29. data/vendor/libgit2/include/git2/oid.h +1 -1
  30. data/vendor/libgit2/include/git2/pack.h +13 -0
  31. data/vendor/libgit2/include/git2/patch.h +3 -6
  32. data/vendor/libgit2/include/git2/rebase.h +8 -12
  33. data/vendor/libgit2/include/git2/refs.h +19 -29
  34. data/vendor/libgit2/include/git2/remote.h +5 -11
  35. data/vendor/libgit2/include/git2/repository.h +44 -15
  36. data/vendor/libgit2/include/git2/reset.h +19 -10
  37. data/vendor/libgit2/include/git2/revert.h +2 -2
  38. data/vendor/libgit2/include/git2/submodule.h +3 -9
  39. data/vendor/libgit2/include/git2/sys/config.h +3 -1
  40. data/vendor/libgit2/include/git2/sys/filter.h +10 -2
  41. data/vendor/libgit2/include/git2/sys/hashsig.h +49 -22
  42. data/vendor/libgit2/include/git2/transport.h +1 -1
  43. data/vendor/libgit2/include/git2/types.h +10 -3
  44. data/vendor/libgit2/include/git2/version.h +3 -2
  45. data/vendor/libgit2/src/annotated_commit.c +28 -0
  46. data/vendor/libgit2/src/array.h +19 -8
  47. data/vendor/libgit2/src/attr.c +95 -35
  48. data/vendor/libgit2/src/attr_file.c +51 -17
  49. data/vendor/libgit2/src/attr_file.h +37 -10
  50. data/vendor/libgit2/src/attrcache.c +13 -7
  51. data/vendor/libgit2/src/attrcache.h +1 -0
  52. data/vendor/libgit2/src/blame.c +26 -2
  53. data/vendor/libgit2/src/blame_git.c +6 -2
  54. data/vendor/libgit2/src/blob.c +6 -8
  55. data/vendor/libgit2/src/branch.c +55 -43
  56. data/vendor/libgit2/src/buf_text.c +13 -6
  57. data/vendor/libgit2/src/buffer.c +110 -25
  58. data/vendor/libgit2/src/buffer.h +18 -0
  59. data/vendor/libgit2/src/checkout.c +164 -92
  60. data/vendor/libgit2/src/checkout.h +0 -7
  61. data/vendor/libgit2/src/cherrypick.c +13 -7
  62. data/vendor/libgit2/src/clone.c +23 -25
  63. data/vendor/libgit2/src/commit.c +3 -3
  64. data/vendor/libgit2/src/common.h +23 -1
  65. data/vendor/libgit2/src/config.c +137 -19
  66. data/vendor/libgit2/src/config.h +2 -2
  67. data/vendor/libgit2/src/config_cache.c +2 -1
  68. data/vendor/libgit2/src/config_file.c +39 -18
  69. data/vendor/libgit2/src/config_file.h +1 -1
  70. data/vendor/libgit2/src/crlf.c +1 -1
  71. data/vendor/libgit2/src/delta-apply.c +3 -2
  72. data/vendor/libgit2/src/delta.c +25 -6
  73. data/vendor/libgit2/src/describe.c +2 -0
  74. data/vendor/libgit2/src/diff.c +8 -5
  75. data/vendor/libgit2/src/diff_driver.c +39 -18
  76. data/vendor/libgit2/src/diff_file.c +1 -1
  77. data/vendor/libgit2/src/diff_patch.c +12 -6
  78. data/vendor/libgit2/src/diff_tform.c +21 -24
  79. data/vendor/libgit2/src/filebuf.c +14 -12
  80. data/vendor/libgit2/src/fileops.c +61 -18
  81. data/vendor/libgit2/src/fileops.h +11 -2
  82. data/vendor/libgit2/src/filter.c +351 -99
  83. data/vendor/libgit2/src/filter.h +17 -0
  84. data/vendor/libgit2/src/global.c +38 -9
  85. data/vendor/libgit2/src/hash/hash_generic.c +1 -1
  86. data/vendor/libgit2/src/hashsig.c +28 -16
  87. data/vendor/libgit2/src/ignore.c +2 -2
  88. data/vendor/libgit2/src/index.c +159 -42
  89. data/vendor/libgit2/src/index.h +29 -0
  90. data/vendor/libgit2/src/indexer.c +11 -2
  91. data/vendor/libgit2/src/integer.h +96 -0
  92. data/vendor/libgit2/src/iterator.c +5 -3
  93. data/vendor/libgit2/src/khash.h +41 -29
  94. data/vendor/libgit2/src/merge.c +48 -35
  95. data/vendor/libgit2/src/merge.h +0 -1
  96. data/vendor/libgit2/src/merge_file.c +13 -0
  97. data/vendor/libgit2/src/mwindow.c +1 -1
  98. data/vendor/libgit2/src/notes.c +1 -1
  99. data/vendor/libgit2/src/odb.c +13 -11
  100. data/vendor/libgit2/src/odb_loose.c +22 -10
  101. data/vendor/libgit2/src/odb_mempack.c +4 -2
  102. data/vendor/libgit2/src/offmap.h +3 -2
  103. data/vendor/libgit2/src/oid.c +1 -1
  104. data/vendor/libgit2/src/oidmap.h +2 -1
  105. data/vendor/libgit2/src/openssl_stream.c +6 -3
  106. data/vendor/libgit2/src/pack-objects.c +273 -12
  107. data/vendor/libgit2/src/pack-objects.h +10 -0
  108. data/vendor/libgit2/src/pack.c +17 -6
  109. data/vendor/libgit2/src/pack.h +1 -3
  110. data/vendor/libgit2/src/path.c +68 -38
  111. data/vendor/libgit2/src/pathspec.c +3 -0
  112. data/vendor/libgit2/src/pool.c +9 -8
  113. data/vendor/libgit2/src/posix.c +11 -1
  114. data/vendor/libgit2/src/push.c +15 -17
  115. data/vendor/libgit2/src/push.h +1 -6
  116. data/vendor/libgit2/src/rebase.c +77 -35
  117. data/vendor/libgit2/src/refdb_fs.c +2 -2
  118. data/vendor/libgit2/src/refs.c +107 -81
  119. data/vendor/libgit2/src/refs.h +2 -2
  120. data/vendor/libgit2/src/refspec.c +3 -0
  121. data/vendor/libgit2/src/remote.c +19 -21
  122. data/vendor/libgit2/src/repository.c +258 -67
  123. data/vendor/libgit2/src/repository.h +31 -16
  124. data/vendor/libgit2/src/reset.c +28 -12
  125. data/vendor/libgit2/src/revert.c +12 -7
  126. data/vendor/libgit2/src/revwalk.c +3 -5
  127. data/vendor/libgit2/src/revwalk.h +1 -1
  128. data/vendor/libgit2/src/sortedcache.c +5 -3
  129. data/vendor/libgit2/src/stash.c +3 -5
  130. data/vendor/libgit2/src/strmap.h +2 -1
  131. data/vendor/libgit2/src/submodule.c +5 -6
  132. data/vendor/libgit2/src/tag.c +7 -5
  133. data/vendor/libgit2/src/transaction.c +1 -1
  134. data/vendor/libgit2/src/transports/cred.c +5 -2
  135. data/vendor/libgit2/src/transports/git.c +2 -3
  136. data/vendor/libgit2/src/transports/local.c +15 -34
  137. data/vendor/libgit2/src/transports/smart.c +1 -1
  138. data/vendor/libgit2/src/transports/smart_pkt.c +58 -18
  139. data/vendor/libgit2/src/transports/smart_protocol.c +2 -2
  140. data/vendor/libgit2/src/transports/winhttp.c +2 -2
  141. data/vendor/libgit2/src/tree.c +7 -5
  142. data/vendor/libgit2/src/tsort.c +3 -1
  143. data/vendor/libgit2/src/util.c +25 -0
  144. data/vendor/libgit2/src/util.h +31 -27
  145. data/vendor/libgit2/src/vector.c +2 -7
  146. data/vendor/libgit2/src/win32/dir.c +5 -3
  147. data/vendor/libgit2/src/win32/git2.rc +8 -4
  148. data/vendor/libgit2/src/win32/mingw-compat.h +7 -0
  149. data/vendor/libgit2/src/win32/msvc-compat.h +3 -0
  150. data/vendor/libgit2/src/win32/posix.h +1 -3
  151. data/vendor/libgit2/src/win32/posix_w32.c +31 -7
  152. data/vendor/libgit2/src/win32/utf-conv.c +1 -3
  153. data/vendor/libgit2/src/zstream.c +1 -1
  154. metadata +5 -5
  155. data/vendor/libgit2/src/bswap.h +0 -97
@@ -8,6 +8,7 @@
8
8
  #define INCLUDE_filter_h__
9
9
 
10
10
  #include "common.h"
11
+ #include "attr_file.h"
11
12
  #include "git2/filter.h"
12
13
 
13
14
  /* Amount of file to examine for NUL byte when checking binary-ness */
@@ -23,8 +24,24 @@ typedef enum {
23
24
  GIT_CRLF_AUTO,
24
25
  } git_crlf_t;
25
26
 
27
+ typedef struct {
28
+ git_attr_session *attr_session;
29
+ git_buf *temp_buf;
30
+ uint32_t flags;
31
+ } git_filter_options;
32
+
33
+ #define GIT_FILTER_OPTIONS_INIT {0}
34
+
26
35
  extern void git_filter_free(git_filter *filter);
27
36
 
37
+ extern int git_filter_list__load_ext(
38
+ git_filter_list **filters,
39
+ git_repository *repo,
40
+ git_blob *blob, /* can be NULL */
41
+ const char *path,
42
+ git_filter_mode_t mode,
43
+ git_filter_options *filter_opts);
44
+
28
45
  /*
29
46
  * Available filters
30
47
  */
@@ -36,16 +36,25 @@ void git__on_shutdown(git_global_shutdown_fn callback)
36
36
  git__shutdown_callbacks[count - 1] = callback;
37
37
  }
38
38
 
39
+ static void git__global_state_cleanup(git_global_st *st)
40
+ {
41
+ if (!st)
42
+ return;
43
+
44
+ git__free(st->error_t.message);
45
+ st->error_t.message = NULL;
46
+ }
47
+
39
48
  static void git__shutdown(void)
40
49
  {
41
50
  int pos;
42
51
 
52
+ /* Shutdown subsystems that have registered */
43
53
  for (pos = git_atomic_get(&git__n_shutdown_callbacks); pos > 0; pos = git_atomic_dec(&git__n_shutdown_callbacks)) {
44
54
  git_global_shutdown_fn cb = git__swap(git__shutdown_callbacks[pos - 1], NULL);
45
55
  if (cb != NULL)
46
56
  cb();
47
57
  }
48
-
49
58
  }
50
59
 
51
60
  #if defined(GIT_THREADS) && defined(GIT_SSL)
@@ -214,8 +223,14 @@ int git_libgit2_init(void)
214
223
 
215
224
  static void synchronized_threads_shutdown(void)
216
225
  {
226
+ void *ptr;
227
+
217
228
  /* Shut down any subsystems that have global state */
218
229
  git__shutdown();
230
+
231
+ ptr = TlsGetValue(_tls_index);
232
+ git__global_state_cleanup(ptr);
233
+
219
234
  TlsFree(_tls_index);
220
235
  git_mutex_free(&git__mwindow_mutex);
221
236
  }
@@ -255,6 +270,17 @@ git_global_st *git__global_state(void)
255
270
  return ptr;
256
271
  }
257
272
 
273
+ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
274
+ {
275
+ if (reason == DLL_THREAD_DETACH) {
276
+ void *ptr = TlsGetValue(_tls_index);
277
+ git__global_state_cleanup(ptr);
278
+ git__free(ptr);
279
+ }
280
+
281
+ return TRUE;
282
+ }
283
+
258
284
  #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
259
285
 
260
286
  static pthread_key_t _tls_key;
@@ -263,9 +289,7 @@ int init_error = 0;
263
289
 
264
290
  static void cb__free_status(void *st)
265
291
  {
266
- git_global_st *state = (git_global_st *) st;
267
- git__free(state->error_t.message);
268
-
292
+ git__global_state_cleanup(st);
269
293
  git__free(st);
270
294
  }
271
295
 
@@ -302,7 +326,7 @@ int git_libgit2_shutdown(void)
302
326
  pthread_once_t new_once = PTHREAD_ONCE_INIT;
303
327
  int ret;
304
328
 
305
- if ((ret = git_atomic_dec(&git__n_inits)) > 0)
329
+ if ((ret = git_atomic_dec(&git__n_inits)) != 0)
306
330
  return ret;
307
331
 
308
332
  /* Shut down any subsystems that have global state */
@@ -310,13 +334,15 @@ int git_libgit2_shutdown(void)
310
334
 
311
335
  ptr = pthread_getspecific(_tls_key);
312
336
  pthread_setspecific(_tls_key, NULL);
337
+
338
+ git__global_state_cleanup(ptr);
313
339
  git__free(ptr);
314
340
 
315
341
  pthread_key_delete(_tls_key);
316
342
  git_mutex_free(&git__mwindow_mutex);
317
343
  _once_init = new_once;
318
344
 
319
- return ret;
345
+ return 0;
320
346
  }
321
347
 
322
348
  git_global_st *git__global_state(void)
@@ -358,10 +384,13 @@ int git_libgit2_shutdown(void)
358
384
  int ret;
359
385
 
360
386
  /* Shut down any subsystems that have global state */
361
- if (ret = git_atomic_dec(&git__n_inits))
362
- git__shutdown();
387
+ if ((ret = git_atomic_dec(&git__n_inits)) != 0)
388
+ return ret;
363
389
 
364
- return ret;
390
+ git__shutdown();
391
+ git__global_state_cleanup(&__state);
392
+
393
+ return 0;
365
394
  }
366
395
 
367
396
  git_global_st *git__global_state(void)
@@ -18,7 +18,7 @@
18
18
  * rotate with a loop.
19
19
  */
20
20
 
21
- #define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
21
+ #define SHA_ASM(op, x, n) (__extension__ ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; }))
22
22
  #define SHA_ROL(x,n) SHA_ASM("rol", x, n)
23
23
  #define SHA_ROR(x,n) SHA_ASM("ror", x, n)
24
24
 
@@ -34,8 +34,8 @@ typedef struct {
34
34
  struct git_hashsig {
35
35
  hashsig_heap mins;
36
36
  hashsig_heap maxs;
37
+ size_t lines;
37
38
  git_hashsig_option_t opt;
38
- int considered;
39
39
  };
40
40
 
41
41
  #define HEAP_LCHILD_OF(I) (((I)<<1)+1)
@@ -135,25 +135,23 @@ static void hashsig_in_progress_init(
135
135
  {
136
136
  int i;
137
137
 
138
- switch (sig->opt) {
139
- case GIT_HASHSIG_IGNORE_WHITESPACE:
138
+ /* no more than one can be set */
139
+ assert(!(sig->opt & GIT_HASHSIG_IGNORE_WHITESPACE) ||
140
+ !(sig->opt & GIT_HASHSIG_SMART_WHITESPACE));
141
+
142
+ if (sig->opt & GIT_HASHSIG_IGNORE_WHITESPACE) {
140
143
  for (i = 0; i < 256; ++i)
141
144
  prog->ignore_ch[i] = git__isspace_nonlf(i);
142
145
  prog->use_ignores = 1;
143
- break;
144
- case GIT_HASHSIG_SMART_WHITESPACE:
146
+ } else if (sig->opt & GIT_HASHSIG_SMART_WHITESPACE) {
145
147
  for (i = 0; i < 256; ++i)
146
148
  prog->ignore_ch[i] = git__isspace(i);
147
149
  prog->use_ignores = 1;
148
- break;
149
- default:
150
+ } else {
150
151
  memset(prog, 0, sizeof(*prog));
151
- break;
152
152
  }
153
153
  }
154
154
 
155
- #define HASHSIG_IN_PROGRESS_INIT { 1 }
156
-
157
155
  static int hashsig_add_hashes(
158
156
  git_hashsig *sig,
159
157
  const uint8_t *data,
@@ -174,12 +172,13 @@ static int hashsig_add_hashes(
174
172
  if (use_ignores)
175
173
  for (; scan < end && git__isspace_nonlf(ch); ch = *scan)
176
174
  ++scan;
177
- else if (sig->opt != GIT_HASHSIG_NORMAL)
175
+ else if (sig->opt &
176
+ (GIT_HASHSIG_IGNORE_WHITESPACE | GIT_HASHSIG_SMART_WHITESPACE))
178
177
  for (; scan < end && ch == '\r'; ch = *scan)
179
178
  ++scan;
180
179
 
181
180
  /* peek at next character to decide what to do next */
182
- if (sig->opt == GIT_HASHSIG_SMART_WHITESPACE)
181
+ if (sig->opt & GIT_HASHSIG_SMART_WHITESPACE)
183
182
  use_ignores = (ch == '\n');
184
183
 
185
184
  if (scan >= end)
@@ -187,8 +186,10 @@ static int hashsig_add_hashes(
187
186
  ++scan;
188
187
 
189
188
  /* check run terminator */
190
- if (ch == '\n' || ch == '\0')
189
+ if (ch == '\n' || ch == '\0') {
190
+ sig->lines++;
191
191
  break;
192
+ }
192
193
 
193
194
  ++len;
194
195
  HASHSIG_HASH_MIX(state, ch);
@@ -198,8 +199,6 @@ static int hashsig_add_hashes(
198
199
  hashsig_heap_insert(&sig->mins, (hashsig_t)state);
199
200
  hashsig_heap_insert(&sig->maxs, (hashsig_t)state);
200
201
 
201
- sig->considered++;
202
-
203
202
  while (scan < end && (*scan == '\n' || !*scan))
204
203
  ++scan;
205
204
  }
@@ -212,7 +211,8 @@ static int hashsig_add_hashes(
212
211
 
213
212
  static int hashsig_finalize_hashes(git_hashsig *sig)
214
213
  {
215
- if (sig->mins.size < HASHSIG_HEAP_MIN_SIZE) {
214
+ if (sig->mins.size < HASHSIG_HEAP_MIN_SIZE &&
215
+ !(sig->opt & GIT_HASHSIG_ALLOW_SMALL_FILES)) {
216
216
  giterr_set(GITERR_INVALID,
217
217
  "File too small for similarity signature calculation");
218
218
  return GIT_EBUFS;
@@ -336,6 +336,18 @@ static int hashsig_heap_compare(const hashsig_heap *a, const hashsig_heap *b)
336
336
 
337
337
  int git_hashsig_compare(const git_hashsig *a, const git_hashsig *b)
338
338
  {
339
+ /* if we have no elements in either file then each file is either
340
+ * empty or blank. if we're ignoring whitespace then the files are
341
+ * similar, otherwise they're dissimilar.
342
+ */
343
+ if (a->mins.size == 0 && b->mins.size == 0) {
344
+ if ((!a->lines && !b->lines) ||
345
+ (a->opt & GIT_HASHSIG_IGNORE_WHITESPACE))
346
+ return HASHSIG_SCALE;
347
+ else
348
+ return 0;
349
+ }
350
+
339
351
  /* if we have fewer than the maximum number of elements, then just use
340
352
  * one array since the two arrays will be the same
341
353
  */
@@ -161,7 +161,7 @@ static int push_ignore_file(
161
161
  git_attr_file *file = NULL;
162
162
 
163
163
  error = git_attr_cache__get(
164
- &file, ignores->repo, GIT_ATTR_FILE__FROM_FILE,
164
+ &file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE,
165
165
  base, filename, parse_ignore_file);
166
166
  if (error < 0)
167
167
  return error;
@@ -189,7 +189,7 @@ static int get_internal_ignores(git_attr_file **out, git_repository *repo)
189
189
  return error;
190
190
 
191
191
  error = git_attr_cache__get(
192
- out, repo, GIT_ATTR_FILE__IN_MEMORY, NULL, GIT_IGNORE_INTERNAL, NULL);
192
+ out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, GIT_IGNORE_INTERNAL, NULL);
193
193
 
194
194
  /* if internal rules list is empty, insert default rules */
195
195
  if (!error && !(*out)->rules.length)
@@ -656,39 +656,15 @@ int git_index__changed_relative_to(
656
656
 
657
657
  int git_index_write(git_index *index)
658
658
  {
659
- git_filebuf file = GIT_FILEBUF_INIT;
659
+ git_indexwriter writer = GIT_INDEXWRITER_INIT;
660
660
  int error;
661
661
 
662
- if (!index->index_file_path)
663
- return create_index_error(-1,
664
- "Failed to read index: The index is in-memory only");
662
+ if ((error = git_indexwriter_init(&writer, index)) == 0)
663
+ error = git_indexwriter_commit(&writer);
665
664
 
666
- if (index_sort_if_needed(index, true) < 0)
667
- return -1;
668
- git_vector_sort(&index->reuc);
665
+ git_indexwriter_cleanup(&writer);
669
666
 
670
- if ((error = git_filebuf_open(
671
- &file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) {
672
- if (error == GIT_ELOCKED)
673
- giterr_set(GITERR_INDEX, "The index is locked. This might be due to a concurrent or crashed process");
674
-
675
- return error;
676
- }
677
-
678
- if ((error = write_index(index, &file)) < 0) {
679
- git_filebuf_cleanup(&file);
680
- return error;
681
- }
682
-
683
- if ((error = git_filebuf_commit(&file)) < 0)
684
- return error;
685
-
686
- if (git_futils_filestamp_check(&index->stamp, index->index_file_path) < 0)
687
- /* index could not be read from disk! */;
688
- else
689
- index->on_disk = 1;
690
-
691
- return 0;
667
+ return error;
692
668
  }
693
669
 
694
670
  const char * git_index_path(const git_index *index)
@@ -770,7 +746,7 @@ static int index_entry_create(
770
746
  git_repository *repo,
771
747
  const char *path)
772
748
  {
773
- size_t pathlen = strlen(path);
749
+ size_t pathlen = strlen(path), alloclen;
774
750
  struct entry_internal *entry;
775
751
 
776
752
  if (!git_path_isvalid(repo, path,
@@ -779,7 +755,9 @@ static int index_entry_create(
779
755
  return -1;
780
756
  }
781
757
 
782
- entry = git__calloc(sizeof(struct entry_internal) + pathlen + 1, 1);
758
+ GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(struct entry_internal), pathlen);
759
+ GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
760
+ entry = git__calloc(1, alloclen);
783
761
  GITERR_CHECK_ALLOC(entry);
784
762
 
785
763
  entry->pathlen = pathlen;
@@ -826,9 +804,16 @@ static int index_entry_init(
826
804
 
827
805
  static git_index_reuc_entry *reuc_entry_alloc(const char *path)
828
806
  {
829
- size_t pathlen = strlen(path);
830
- struct reuc_entry_internal *entry =
831
- git__calloc(sizeof(struct reuc_entry_internal) + pathlen + 1, 1);
807
+ size_t pathlen = strlen(path),
808
+ structlen = sizeof(struct reuc_entry_internal),
809
+ alloclen;
810
+ struct reuc_entry_internal *entry;
811
+
812
+ if (GIT_ADD_SIZET_OVERFLOW(&alloclen, structlen, pathlen) ||
813
+ GIT_ADD_SIZET_OVERFLOW(&alloclen, alloclen, 1))
814
+ return NULL;
815
+
816
+ entry = git__calloc(1, alloclen);
832
817
  if (!entry)
833
818
  return NULL;
834
819
 
@@ -1097,6 +1082,58 @@ static int index_conflict_to_reuc(git_index *index, const char *path)
1097
1082
  return ret;
1098
1083
  }
1099
1084
 
1085
+ static bool valid_filemode(const int filemode)
1086
+ {
1087
+ return (filemode == GIT_FILEMODE_BLOB ||
1088
+ filemode == GIT_FILEMODE_BLOB_EXECUTABLE ||
1089
+ filemode == GIT_FILEMODE_LINK ||
1090
+ filemode == GIT_FILEMODE_COMMIT);
1091
+ }
1092
+
1093
+ int git_index_add_frombuffer(
1094
+ git_index *index, git_index_entry *source_entry,
1095
+ const void *buffer, size_t len)
1096
+ {
1097
+ git_index_entry *entry = NULL;
1098
+ int error = 0;
1099
+ git_oid id;
1100
+
1101
+ assert(index && source_entry->path);
1102
+
1103
+ if (INDEX_OWNER(index) == NULL)
1104
+ return create_index_error(-1,
1105
+ "Could not initialize index entry. "
1106
+ "Index is not backed up by an existing repository.");
1107
+
1108
+ if (!valid_filemode(source_entry->mode)) {
1109
+ giterr_set(GITERR_INDEX, "invalid filemode");
1110
+ return -1;
1111
+ }
1112
+
1113
+ if (index_entry_dup(&entry, INDEX_OWNER(index), source_entry) < 0)
1114
+ return -1;
1115
+
1116
+ error = git_blob_create_frombuffer(&id, INDEX_OWNER(index), buffer, len);
1117
+ if (error < 0) {
1118
+ index_entry_free(entry);
1119
+ return error;
1120
+ }
1121
+
1122
+ git_oid_cpy(&entry->id, &id);
1123
+ entry->file_size = len;
1124
+
1125
+ if ((error = index_insert(index, &entry, 1)) < 0)
1126
+ return error;
1127
+
1128
+ /* Adding implies conflict was resolved, move conflict entries to REUC */
1129
+ if ((error = index_conflict_to_reuc(index, entry->path)) < 0 && error != GIT_ENOTFOUND)
1130
+ return error;
1131
+
1132
+ git_tree_cache_invalidate_path(index->tree, entry->path);
1133
+ return 0;
1134
+ }
1135
+
1136
+
1100
1137
  int git_index_add_bypath(git_index *index, const char *path)
1101
1138
  {
1102
1139
  git_index_entry *entry = NULL;
@@ -1131,14 +1168,6 @@ int git_index_remove_bypath(git_index *index, const char *path)
1131
1168
  return 0;
1132
1169
  }
1133
1170
 
1134
- static bool valid_filemode(const int filemode)
1135
- {
1136
- return (filemode == GIT_FILEMODE_BLOB ||
1137
- filemode == GIT_FILEMODE_BLOB_EXECUTABLE ||
1138
- filemode == GIT_FILEMODE_LINK ||
1139
- filemode == GIT_FILEMODE_COMMIT);
1140
- }
1141
-
1142
1171
 
1143
1172
  int git_index_add(git_index *index, const git_index_entry *source_entry)
1144
1173
  {
@@ -2686,3 +2715,91 @@ int git_index_snapshot_find(
2686
2715
  {
2687
2716
  return index_find_in_entries(out, entries, entry_srch, path, path_len, stage);
2688
2717
  }
2718
+
2719
+ int git_indexwriter_init(
2720
+ git_indexwriter *writer,
2721
+ git_index *index)
2722
+ {
2723
+ int error;
2724
+
2725
+ GIT_REFCOUNT_INC(index);
2726
+
2727
+ writer->index = index;
2728
+
2729
+ if (!index->index_file_path)
2730
+ return create_index_error(-1,
2731
+ "Failed to write index: The index is in-memory only");
2732
+
2733
+ if ((error = git_filebuf_open(
2734
+ &writer->file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) {
2735
+
2736
+ if (error == GIT_ELOCKED)
2737
+ giterr_set(GITERR_INDEX, "The index is locked. This might be due to a concurrent or crashed process");
2738
+
2739
+ return error;
2740
+ }
2741
+
2742
+ writer->should_write = 1;
2743
+
2744
+ return 0;
2745
+ }
2746
+
2747
+ int git_indexwriter_init_for_operation(
2748
+ git_indexwriter *writer,
2749
+ git_repository *repo,
2750
+ unsigned int *checkout_strategy)
2751
+ {
2752
+ git_index *index;
2753
+ int error;
2754
+
2755
+ if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
2756
+ (error = git_indexwriter_init(writer, index)) < 0)
2757
+ return error;
2758
+
2759
+ writer->should_write = (*checkout_strategy & GIT_CHECKOUT_DONT_WRITE_INDEX) == 0;
2760
+ *checkout_strategy |= GIT_CHECKOUT_DONT_WRITE_INDEX;
2761
+
2762
+ return 0;
2763
+ }
2764
+
2765
+ int git_indexwriter_commit(git_indexwriter *writer)
2766
+ {
2767
+ int error;
2768
+
2769
+ if (!writer->should_write)
2770
+ return 0;
2771
+
2772
+ if (index_sort_if_needed(writer->index, true) < 0)
2773
+ return -1;
2774
+
2775
+ git_vector_sort(&writer->index->reuc);
2776
+
2777
+ if ((error = write_index(writer->index, &writer->file)) < 0) {
2778
+ git_indexwriter_cleanup(writer);
2779
+ return error;
2780
+ }
2781
+
2782
+ if ((error = git_filebuf_commit(&writer->file)) < 0)
2783
+ return error;
2784
+
2785
+ if ((error = git_futils_filestamp_check(
2786
+ &writer->index->stamp, writer->index->index_file_path)) < 0) {
2787
+ giterr_set(GITERR_OS, "Could not read index timestamp");
2788
+ return -1;
2789
+ }
2790
+
2791
+ writer->index->on_disk = 1;
2792
+
2793
+ git_index_free(writer->index);
2794
+ writer->index = NULL;
2795
+
2796
+ return 0;
2797
+ }
2798
+
2799
+ void git_indexwriter_cleanup(git_indexwriter *writer)
2800
+ {
2801
+ git_filebuf_cleanup(&writer->file);
2802
+
2803
+ git_index_free(writer->index);
2804
+ writer->index = NULL;
2805
+ }