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
@@ -107,7 +107,6 @@ typedef struct {
107
107
  git_index_entry their_entry;
108
108
  git_delta_t their_status;
109
109
 
110
- int binary:1;
111
110
  } git_merge_diff;
112
111
 
113
112
  int git_merge__bases_many(
@@ -151,6 +151,19 @@ static int git_merge_file__from_inputs(
151
151
  if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
152
152
  xmparam.style = XDL_MERGE_DIFF3;
153
153
 
154
+ if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE)
155
+ xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE;
156
+ if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE)
157
+ xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_CHANGE;
158
+ if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL)
159
+ xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
160
+
161
+ if (options.flags & GIT_MERGE_FILE_DIFF_PATIENCE)
162
+ xmparam.xpp.flags |= XDF_PATIENCE_DIFF;
163
+
164
+ if (options.flags & GIT_MERGE_FILE_DIFF_MINIMAL)
165
+ xmparam.xpp.flags |= XDF_NEED_MINIMAL;
166
+
154
167
  if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile,
155
168
  &their_mmfile, &xmparam, &mmbuffer)) < 0) {
156
169
  giterr_set(GITERR_MERGE, "Failed to merge files.");
@@ -14,7 +14,7 @@
14
14
  #include "strmap.h"
15
15
  #include "pack.h"
16
16
 
17
- GIT__USE_STRMAP;
17
+ GIT__USE_STRMAP
18
18
 
19
19
  #define DEFAULT_WINDOW_SIZE \
20
20
  (sizeof(void*) >= 8 \
@@ -314,7 +314,7 @@ static int note_new(
314
314
  {
315
315
  git_note *note = NULL;
316
316
 
317
- note = (git_note *)git__malloc(sizeof(git_note));
317
+ note = git__malloc(sizeof(git_note));
318
318
  GITERR_CHECK_ALLOC(note);
319
319
 
320
320
  git_oid_cpy(&note->id, note_oid);
@@ -216,41 +216,43 @@ int git_odb__hashfd_filtered(
216
216
  int git_odb__hashlink(git_oid *out, const char *path)
217
217
  {
218
218
  struct stat st;
219
- git_off_t size;
219
+ int size;
220
220
  int result;
221
221
 
222
222
  if (git_path_lstat(path, &st) < 0)
223
223
  return -1;
224
224
 
225
- size = st.st_size;
226
-
227
- if (!git__is_sizet(size)) {
228
- giterr_set(GITERR_OS, "File size overflow for 32-bit systems");
225
+ if (!git__is_int(st.st_size) || (int)st.st_size < 0) {
226
+ giterr_set(GITERR_FILESYSTEM, "File size overflow for 32-bit systems");
229
227
  return -1;
230
228
  }
231
229
 
230
+ size = (int)st.st_size;
231
+
232
232
  if (S_ISLNK(st.st_mode)) {
233
233
  char *link_data;
234
- ssize_t read_len;
234
+ int read_len;
235
+ size_t alloc_size;
235
236
 
236
- link_data = git__malloc((size_t)(size + 1));
237
+ GITERR_CHECK_ALLOC_ADD(&alloc_size, size, 1);
238
+ link_data = git__malloc(alloc_size);
237
239
  GITERR_CHECK_ALLOC(link_data);
238
240
 
239
- read_len = p_readlink(path, link_data, (size_t)size);
241
+ read_len = p_readlink(path, link_data, size);
240
242
  link_data[size] = '\0';
241
- if (read_len != (ssize_t)size) {
243
+ if (read_len != size) {
242
244
  giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path);
243
245
  git__free(link_data);
244
246
  return -1;
245
247
  }
246
248
 
247
- result = git_odb_hash(out, link_data, (size_t)size, GIT_OBJ_BLOB);
249
+ result = git_odb_hash(out, link_data, size, GIT_OBJ_BLOB);
248
250
  git__free(link_data);
249
251
  } else {
250
252
  int fd = git_futils_open_ro(path);
251
253
  if (fd < 0)
252
254
  return -1;
253
- result = git_odb__hashfd(out, fd, (size_t)size, GIT_OBJ_BLOB);
255
+ result = git_odb__hashfd(out, fd, size, GIT_OBJ_BLOB);
254
256
  p_close(fd);
255
257
  }
256
258
 
@@ -63,8 +63,12 @@ typedef struct {
63
63
  static int object_file_name(
64
64
  git_buf *name, const loose_backend *be, const git_oid *id)
65
65
  {
66
+ size_t alloclen;
67
+
66
68
  /* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
67
- if (git_buf_grow(name, be->objects_dirlen + GIT_OID_HEXSZ + 3) < 0)
69
+ GITERR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
70
+ GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
71
+ if (git_buf_grow(name, alloclen) < 0)
68
72
  return -1;
69
73
 
70
74
  git_buf_set(name, be->objects_dir, be->objects_dirlen);
@@ -261,14 +265,15 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
261
265
  static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
262
266
  {
263
267
  unsigned char *buf, *head = hb;
264
- size_t tail;
268
+ size_t tail, alloc_size;
265
269
 
266
270
  /*
267
271
  * allocate a buffer to hold the inflated data and copy the
268
272
  * initial sequence of inflated data from the tail of the
269
273
  * head buffer, if any.
270
274
  */
271
- if ((buf = git__malloc(hdr->size + 1)) == NULL) {
275
+ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr->size, 1) ||
276
+ (buf = git__malloc(alloc_size)) == NULL) {
272
277
  inflateEnd(s);
273
278
  return NULL;
274
279
  }
@@ -306,7 +311,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
306
311
  {
307
312
  unsigned char *in, *buf;
308
313
  obj_hdr hdr;
309
- size_t len, used;
314
+ size_t len, used, alloclen;
310
315
 
311
316
  /*
312
317
  * read the object header, which is an (uncompressed)
@@ -321,7 +326,8 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj)
321
326
  /*
322
327
  * allocate a buffer and inflate the data into it
323
328
  */
324
- buf = git__malloc(hdr.size + 1);
329
+ GITERR_CHECK_ALLOC_ADD(&alloclen, hdr.size, 1);
330
+ buf = git__malloc(alloclen);
325
331
  GITERR_CHECK_ALLOC(buf);
326
332
 
327
333
  in = ((unsigned char *)obj->ptr) + used;
@@ -515,12 +521,14 @@ static int locate_object_short_oid(
515
521
  size_t len)
516
522
  {
517
523
  char *objects_dir = backend->objects_dir;
518
- size_t dir_len = strlen(objects_dir);
524
+ size_t dir_len = strlen(objects_dir), alloc_len;
519
525
  loose_locate_object_state state;
520
526
  int error;
521
527
 
522
528
  /* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
523
- if (git_buf_grow(object_location, dir_len + 3 + GIT_OID_HEXSZ) < 0)
529
+ GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
530
+ GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
531
+ if (git_buf_grow(object_location, alloc_len) < 0)
524
532
  return -1;
525
533
 
526
534
  git_buf_set(object_location, objects_dir, dir_len);
@@ -563,9 +571,11 @@ static int locate_object_short_oid(
563
571
  return error;
564
572
 
565
573
  /* Update the location according to the oid obtained */
574
+ GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
575
+ GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
566
576
 
567
577
  git_buf_truncate(object_location, dir_len);
568
- if (git_buf_grow(object_location, dir_len + GIT_OID_HEXSZ + 2) < 0)
578
+ if (git_buf_grow(object_location, alloc_len) < 0)
569
579
  return -1;
570
580
 
571
581
  git_oid_pathfmt(object_location->ptr + dir_len, res_oid);
@@ -922,13 +932,15 @@ int git_odb_backend_loose(
922
932
  unsigned int file_mode)
923
933
  {
924
934
  loose_backend *backend;
925
- size_t objects_dirlen;
935
+ size_t objects_dirlen, alloclen;
926
936
 
927
937
  assert(backend_out && objects_dir);
928
938
 
929
939
  objects_dirlen = strlen(objects_dir);
930
940
 
931
- backend = git__calloc(1, sizeof(loose_backend) + objects_dirlen + 2);
941
+ GITERR_CHECK_ALLOC_ADD(&alloclen, sizeof(loose_backend), objects_dirlen);
942
+ GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 2);
943
+ backend = git__calloc(1, alloclen);
932
944
  GITERR_CHECK_ALLOC(backend);
933
945
 
934
946
  backend->parent.version = GIT_ODB_BACKEND_VERSION;
@@ -18,7 +18,7 @@
18
18
  #include "git2/types.h"
19
19
  #include "git2/pack.h"
20
20
 
21
- GIT__USE_OIDMAP;
21
+ GIT__USE_OIDMAP
22
22
 
23
23
  struct memobject {
24
24
  git_oid oid;
@@ -38,6 +38,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
38
38
  struct memory_packer_db *db = (struct memory_packer_db *)_backend;
39
39
  struct memobject *obj = NULL;
40
40
  khiter_t pos;
41
+ size_t alloc_len;
41
42
  int rval;
42
43
 
43
44
  pos = kh_put(oid, db->objects, oid, &rval);
@@ -47,7 +48,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
47
48
  if (rval == 0)
48
49
  return 0;
49
50
 
50
- obj = git__malloc(sizeof(struct memobject) + len);
51
+ GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len);
52
+ obj = git__malloc(alloc_len);
51
53
  GITERR_CHECK_ALLOC(obj);
52
54
 
53
55
  memcpy(obj->data, data, len);
@@ -13,14 +13,15 @@
13
13
  #define kmalloc git__malloc
14
14
  #define kcalloc git__calloc
15
15
  #define krealloc git__realloc
16
+ #define kreallocarray git__reallocarray
16
17
  #define kfree git__free
17
18
  #include "khash.h"
18
19
 
19
- __KHASH_TYPE(off, git_off_t, void *);
20
+ __KHASH_TYPE(off, git_off_t, void *)
20
21
  typedef khash_t(off) git_offmap;
21
22
 
22
23
  #define GIT__USE_OFFMAP \
23
- __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal);
24
+ __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal)
24
25
 
25
26
  #define git_offmap_alloc() kh_init(off)
26
27
  #define git_offmap_free(h) kh_destroy(off, h), h = NULL
@@ -261,7 +261,7 @@ struct git_oid_shorten {
261
261
 
262
262
  static int resize_trie(git_oid_shorten *self, size_t new_size)
263
263
  {
264
- self->nodes = git__realloc(self->nodes, new_size * sizeof(trie_node));
264
+ self->nodes = git__reallocarray(self->nodes, new_size, sizeof(trie_node));
265
265
  GITERR_CHECK_ALLOC(self->nodes);
266
266
 
267
267
  if (new_size > self->size) {
@@ -13,10 +13,11 @@
13
13
  #define kmalloc git__malloc
14
14
  #define kcalloc git__calloc
15
15
  #define krealloc git__realloc
16
+ #define kreallocarray git__reallocarray
16
17
  #define kfree git__free
17
18
  #include "khash.h"
18
19
 
19
- __KHASH_TYPE(oid, const git_oid *, void *);
20
+ __KHASH_TYPE(oid, const git_oid *, void *)
20
21
  typedef khash_t(oid) git_oidmap;
21
22
 
22
23
  GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
@@ -8,9 +8,6 @@
8
8
  #ifdef GIT_SSL
9
9
 
10
10
  #include <ctype.h>
11
- #include <sys/types.h>
12
- #include <sys/socket.h>
13
- #include <netinet/in.h>
14
11
 
15
12
  #include "global.h"
16
13
  #include "posix.h"
@@ -19,6 +16,12 @@
19
16
  #include "netops.h"
20
17
  #include "git2/transport.h"
21
18
 
19
+ #ifndef GIT_WIN32
20
+ # include <sys/types.h>
21
+ # include <sys/socket.h>
22
+ # include <netinet/in.h>
23
+ #endif
24
+
22
25
  #include <openssl/ssl.h>
23
26
  #include <openssl/err.h>
24
27
  #include <openssl/x509v3.h>
@@ -15,6 +15,8 @@
15
15
  #include "thread-utils.h"
16
16
  #include "tree.h"
17
17
  #include "util.h"
18
+ #include "revwalk.h"
19
+ #include "commit_list.h"
18
20
 
19
21
  #include "git2/pack.h"
20
22
  #include "git2/commit.h"
@@ -39,6 +41,8 @@ struct pack_write_context {
39
41
  git_transfer_progress *stats;
40
42
  };
41
43
 
44
+ GIT__USE_OIDMAP;
45
+
42
46
  #ifdef GIT_THREADS
43
47
 
44
48
  #define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \
@@ -124,10 +128,16 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
124
128
  GITERR_CHECK_ALLOC(pb);
125
129
 
126
130
  pb->object_ix = git_oidmap_alloc();
127
-
128
131
  if (!pb->object_ix)
129
132
  goto on_error;
130
133
 
134
+ pb->walk_objects = git_oidmap_alloc();
135
+ if (!pb->walk_objects)
136
+ goto on_error;
137
+
138
+ if (git_pool_init(&pb->object_pool, sizeof(git_walk_object), 0) < 0)
139
+ goto on_error;
140
+
131
141
  pb->repo = repo;
132
142
  pb->nr_threads = 1; /* do not spawn any thread by default */
133
143
 
@@ -190,6 +200,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
190
200
  {
191
201
  git_pobject *po;
192
202
  khiter_t pos;
203
+ size_t newsize;
193
204
  int ret;
194
205
 
195
206
  assert(pb && oid);
@@ -201,9 +212,18 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
201
212
  return 0;
202
213
 
203
214
  if (pb->nr_objects >= pb->nr_alloc) {
204
- pb->nr_alloc = (pb->nr_alloc + 1024) * 3 / 2;
205
- pb->object_list = git__realloc(pb->object_list,
206
- pb->nr_alloc * sizeof(*po));
215
+ GITERR_CHECK_ALLOC_ADD(&newsize, pb->nr_alloc, 1024);
216
+ GITERR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2);
217
+
218
+ if (!git__is_uint32(newsize)) {
219
+ giterr_set(GITERR_NOMEMORY, "Packfile too large to fit in memory.");
220
+ return -1;
221
+ }
222
+
223
+ pb->nr_alloc = (uint32_t)newsize;
224
+
225
+ pb->object_list = git__reallocarray(pb->object_list,
226
+ pb->nr_alloc, sizeof(*po));
207
227
  GITERR_CHECK_ALLOC(pb->object_list);
208
228
  rehash(pb);
209
229
  }
@@ -499,8 +519,10 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data)
499
519
  static git_pobject **compute_write_order(git_packbuilder *pb)
500
520
  {
501
521
  unsigned int i, wo_end, last_untagged;
522
+ git_pobject **wo;
502
523
 
503
- git_pobject **wo = git__malloc(sizeof(*wo) * pb->nr_objects);
524
+ if ((wo = git__mallocarray(pb->nr_objects, sizeof(*wo))) == NULL)
525
+ return NULL;
504
526
 
505
527
  for (i = 0; i < pb->nr_objects; i++) {
506
528
  git_pobject *po = pb->object_list + i;
@@ -770,10 +792,13 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
770
792
  *mem_usage += sz;
771
793
  }
772
794
  if (!src->data) {
773
- if (git_odb_read(&obj, pb->odb, &src_object->id) < 0)
795
+ size_t obj_sz;
796
+
797
+ if (git_odb_read(&obj, pb->odb, &src_object->id) < 0 ||
798
+ !git__is_ulong(obj_sz = git_odb_object_size(obj)))
774
799
  return -1;
775
800
 
776
- sz = (unsigned long)git_odb_object_size(obj);
801
+ sz = (unsigned long)obj_sz;
777
802
  src->data = git__malloc(sz);
778
803
  GITERR_CHECK_ALLOC(src->data);
779
804
  memcpy(src->data, git_odb_object_data(obj), sz);
@@ -817,11 +842,14 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
817
842
  trg_object->delta_data = NULL;
818
843
  }
819
844
  if (delta_cacheable(pb, src_size, trg_size, delta_size)) {
820
- pb->delta_cache_size += delta_size;
845
+ bool overflow = git__add_uint64_overflow(
846
+ &pb->delta_cache_size, pb->delta_cache_size, delta_size);
847
+
821
848
  git_packbuilder__cache_unlock(pb);
822
849
 
823
- trg_object->delta_data = git__realloc(delta_buf, delta_size);
824
- GITERR_CHECK_ALLOC(trg_object->delta_data);
850
+ if (overflow ||
851
+ !(trg_object->delta_data = git__realloc(delta_buf, delta_size)))
852
+ return -1;
825
853
  } else {
826
854
  /* create delta when writing the pack */
827
855
  git_packbuilder__cache_unlock(pb);
@@ -1088,7 +1116,7 @@ static int ll_find_deltas(git_packbuilder *pb, git_pobject **list,
1088
1116
  return 0;
1089
1117
  }
1090
1118
 
1091
- p = git__malloc(pb->nr_threads * sizeof(*p));
1119
+ p = git__mallocarray(pb->nr_threads, sizeof(*p));
1092
1120
  GITERR_CHECK_ALLOC(p);
1093
1121
 
1094
1122
  /* Partition the work among the threads */
@@ -1239,7 +1267,7 @@ static int prepare_pack(git_packbuilder *pb)
1239
1267
  if (pb->progress_cb)
1240
1268
  pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload);
1241
1269
 
1242
- delta_list = git__malloc(pb->nr_objects * sizeof(*delta_list));
1270
+ delta_list = git__mallocarray(pb->nr_objects, sizeof(*delta_list));
1243
1271
  GITERR_CHECK_ALLOC(delta_list);
1244
1272
 
1245
1273
  for (i = 0; i < pb->nr_objects; ++i) {
@@ -1327,6 +1355,7 @@ const git_oid *git_packbuilder_hash(git_packbuilder *pb)
1327
1355
  return &pb->pack_oid;
1328
1356
  }
1329
1357
 
1358
+
1330
1359
  static int cb_tree_walk(
1331
1360
  const char *root, const git_tree_entry *entry, void *payload)
1332
1361
  {
@@ -1385,6 +1414,235 @@ uint32_t git_packbuilder_written(git_packbuilder *pb)
1385
1414
  return pb->nr_written;
1386
1415
  }
1387
1416
 
1417
+ int lookup_walk_object(git_walk_object **out, git_packbuilder *pb, const git_oid *id)
1418
+ {
1419
+ git_walk_object *obj;
1420
+
1421
+ obj = git_pool_mallocz(&pb->object_pool, 1);
1422
+ if (!obj) {
1423
+ giterr_set_oom();
1424
+ return -1;
1425
+ }
1426
+
1427
+ git_oid_cpy(&obj->id, id);
1428
+
1429
+ *out = obj;
1430
+ return 0;
1431
+ }
1432
+
1433
+ static int retrieve_object(git_walk_object **out, git_packbuilder *pb, const git_oid *id)
1434
+ {
1435
+ int error;
1436
+ khiter_t pos;
1437
+ git_walk_object *obj;
1438
+
1439
+ pos = git_oidmap_lookup_index(pb->walk_objects, id);
1440
+ if (git_oidmap_valid_index(pb->walk_objects, pos)) {
1441
+ obj = git_oidmap_value_at(pb->walk_objects, pos);
1442
+ } else {
1443
+ if ((error = lookup_walk_object(&obj, pb, id)) < 0)
1444
+ return error;
1445
+
1446
+ git_oidmap_insert(pb->walk_objects, &obj->id, obj, error);
1447
+ }
1448
+
1449
+ *out = obj;
1450
+ return 0;
1451
+ }
1452
+
1453
+ static int mark_blob_uninteresting(git_packbuilder *pb, const git_oid *id)
1454
+ {
1455
+ int error;
1456
+ git_walk_object *obj;
1457
+
1458
+ if ((error = retrieve_object(&obj, pb, id)) < 0)
1459
+ return error;
1460
+
1461
+ obj->uninteresting = 1;
1462
+
1463
+ return 0;
1464
+ }
1465
+
1466
+ static int mark_tree_uninteresting(git_packbuilder *pb, const git_oid *id)
1467
+ {
1468
+ git_walk_object *obj;
1469
+ git_tree *tree;
1470
+ int error;
1471
+ size_t i;
1472
+
1473
+ if ((error = retrieve_object(&obj, pb, id)) < 0)
1474
+ return error;
1475
+
1476
+ if (obj->uninteresting)
1477
+ return 0;
1478
+
1479
+ obj->uninteresting = 1;
1480
+
1481
+ if ((error = git_tree_lookup(&tree, pb->repo, id)) < 0)
1482
+ return error;
1483
+
1484
+ for (i = 0; i < git_tree_entrycount(tree); i++) {
1485
+ const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
1486
+ const git_oid *entry_id = git_tree_entry_id(entry);
1487
+ switch (git_tree_entry_type(entry)) {
1488
+ case GIT_OBJ_TREE:
1489
+ if ((error = mark_tree_uninteresting(pb, entry_id)) < 0)
1490
+ goto cleanup;
1491
+ break;
1492
+ case GIT_OBJ_BLOB:
1493
+ if ((error = mark_blob_uninteresting(pb, entry_id)) < 0)
1494
+ goto cleanup;
1495
+ break;
1496
+ default:
1497
+ /* it's a submodule or something unknown, we don't want it */
1498
+ ;
1499
+ }
1500
+ }
1501
+
1502
+ cleanup:
1503
+ git_tree_free(tree);
1504
+ return error;
1505
+ }
1506
+
1507
+ /*
1508
+ * Mark the edges of the graph uninteresting. Since we start from a
1509
+ * git_revwalk, the commits are already uninteresting, but we need to
1510
+ * mark the trees and blobs.
1511
+ */
1512
+ static int mark_edges_uninteresting(git_packbuilder *pb, git_commit_list *commits)
1513
+ {
1514
+ int error;
1515
+ git_commit_list *list;
1516
+ git_commit *commit;
1517
+
1518
+ for (list = commits; list; list = list->next) {
1519
+ if (!list->item->uninteresting)
1520
+ continue;
1521
+
1522
+ if ((error = git_commit_lookup(&commit, pb->repo, &list->item->oid)) < 0)
1523
+ return error;
1524
+
1525
+ error = mark_tree_uninteresting(pb, git_commit_tree_id(commit));
1526
+ git_commit_free(commit);
1527
+
1528
+ if (error < 0)
1529
+ return error;
1530
+ }
1531
+
1532
+ return 0;
1533
+ }
1534
+
1535
+ int insert_tree(git_packbuilder *pb, git_tree *tree)
1536
+ {
1537
+ size_t i;
1538
+ int error;
1539
+ git_tree *subtree;
1540
+ git_walk_object *obj;
1541
+ const char *name;
1542
+
1543
+ if ((error = retrieve_object(&obj, pb, git_tree_id(tree))) < 0)
1544
+ return error;
1545
+
1546
+ if (obj->seen)
1547
+ return 0;
1548
+
1549
+ obj->seen = 1;
1550
+
1551
+ if ((error = git_packbuilder_insert(pb, &obj->id, NULL)))
1552
+ return error;
1553
+
1554
+ for (i = 0; i < git_tree_entrycount(tree); i++) {
1555
+ const git_tree_entry *entry = git_tree_entry_byindex(tree, i);
1556
+ const git_oid *entry_id = git_tree_entry_id(entry);
1557
+ switch (git_tree_entry_type(entry)) {
1558
+ case GIT_OBJ_TREE:
1559
+ if ((error = git_tree_lookup(&subtree, pb->repo, entry_id)) < 0)
1560
+ return error;
1561
+
1562
+ error = insert_tree(pb, subtree);
1563
+ git_tree_free(subtree);
1564
+
1565
+ if (error < 0)
1566
+ return error;
1567
+
1568
+ break;
1569
+ case GIT_OBJ_BLOB:
1570
+ name = git_tree_entry_name(entry);
1571
+ if ((error = git_packbuilder_insert(pb, entry_id, name)) < 0)
1572
+ return error;
1573
+ break;
1574
+ default:
1575
+ /* it's a submodule or something unknown, we don't want it */
1576
+ ;
1577
+ }
1578
+ }
1579
+
1580
+
1581
+ return error;
1582
+ }
1583
+
1584
+ int insert_commit(git_packbuilder *pb, git_walk_object *obj)
1585
+ {
1586
+ int error;
1587
+ git_commit *commit = NULL;
1588
+ git_tree *tree = NULL;
1589
+
1590
+ obj->seen = 1;
1591
+
1592
+ if ((error = git_packbuilder_insert(pb, &obj->id, NULL)) < 0)
1593
+ return error;
1594
+
1595
+ if ((error = git_commit_lookup(&commit, pb->repo, &obj->id)) < 0)
1596
+ return error;
1597
+
1598
+ if ((error = git_tree_lookup(&tree, pb->repo, git_commit_tree_id(commit))) < 0)
1599
+ goto cleanup;
1600
+
1601
+ if ((error = insert_tree(pb, tree)) < 0)
1602
+ goto cleanup;
1603
+
1604
+ cleanup:
1605
+ git_commit_free(commit);
1606
+ git_tree_free(tree);
1607
+ return error;
1608
+ }
1609
+
1610
+ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk)
1611
+ {
1612
+ int error;
1613
+ git_oid id;
1614
+ git_walk_object *obj;
1615
+
1616
+ assert(pb && walk);
1617
+
1618
+ if ((error = mark_edges_uninteresting(pb, walk->user_input)) < 0)
1619
+ return error;
1620
+
1621
+ /*
1622
+ * TODO: git marks the parents of the edges
1623
+ * uninteresting. This may provide a speed advantage, but does
1624
+ * seem to assume the remote does not have a single-commit
1625
+ * history on the other end.
1626
+ */
1627
+
1628
+ /* walk down each tree up to the blobs and insert them, stopping when uninteresting */
1629
+ while ((error = git_revwalk_next(&id, walk)) == 0) {
1630
+ if ((error = retrieve_object(&obj, pb, &id)) < 0)
1631
+ return error;
1632
+
1633
+ if (obj->seen || obj->uninteresting)
1634
+ continue;
1635
+
1636
+ if ((error = insert_commit(pb, obj)) < 0)
1637
+ return error;
1638
+ }
1639
+
1640
+ if (error == GIT_ITEROVER)
1641
+ error = 0;
1642
+
1643
+ return 0;
1644
+ }
1645
+
1388
1646
  int git_packbuilder_set_callbacks(git_packbuilder *pb, git_packbuilder_progress progress_cb, void *progress_cb_payload)
1389
1647
  {
1390
1648
  if (!pb)
@@ -1418,6 +1676,9 @@ void git_packbuilder_free(git_packbuilder *pb)
1418
1676
  if (pb->object_list)
1419
1677
  git__free(pb->object_list);
1420
1678
 
1679
+ git_oidmap_free(pb->walk_objects);
1680
+ git_pool_clear(&pb->object_pool);
1681
+
1421
1682
  git_hash_ctx_cleanup(&pb->ctx);
1422
1683
  git_zstream_free(&pb->zstream);
1423
1684