rugged 1.9.0 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/extconf.rb +4 -4
  3. data/ext/rugged/rugged.c +12 -1
  4. data/ext/rugged/rugged_blame.c +22 -6
  5. data/ext/rugged/rugged_blob.c +24 -9
  6. data/ext/rugged/rugged_branch.c +10 -7
  7. data/ext/rugged/rugged_branch_collection.c +8 -6
  8. data/ext/rugged/rugged_commit.c +7 -6
  9. data/ext/rugged/rugged_config.c +20 -11
  10. data/ext/rugged/rugged_diff.c +26 -12
  11. data/ext/rugged/rugged_diff_hunk.c +2 -1
  12. data/ext/rugged/rugged_index.c +39 -29
  13. data/ext/rugged/rugged_note.c +7 -6
  14. data/ext/rugged/rugged_object.c +3 -2
  15. data/ext/rugged/rugged_patch.c +23 -9
  16. data/ext/rugged/rugged_rebase.c +22 -10
  17. data/ext/rugged/rugged_reference.c +22 -13
  18. data/ext/rugged/rugged_reference_collection.c +9 -7
  19. data/ext/rugged/rugged_remote.c +23 -12
  20. data/ext/rugged/rugged_remote_collection.c +11 -9
  21. data/ext/rugged/rugged_repo.c +60 -45
  22. data/ext/rugged/rugged_revwalk.c +22 -12
  23. data/ext/rugged/rugged_submodule.c +23 -20
  24. data/ext/rugged/rugged_submodule_collection.c +20 -9
  25. data/ext/rugged/rugged_tag.c +6 -4
  26. data/ext/rugged/rugged_tag_collection.c +7 -5
  27. data/ext/rugged/rugged_tree.c +27 -15
  28. data/lib/rugged/version.rb +1 -1
  29. data/vendor/libgit2/AUTHORS +2 -0
  30. data/vendor/libgit2/CMakeLists.txt +1 -1
  31. data/vendor/libgit2/cmake/DefaultCFlags.cmake +4 -1
  32. data/vendor/libgit2/cmake/SelectSSH.cmake +9 -3
  33. data/vendor/libgit2/deps/pcre/CMakeLists.txt +2 -3
  34. data/vendor/libgit2/deps/xdiff/CMakeLists.txt +1 -1
  35. data/vendor/libgit2/deps/xdiff/xmerge.c +14 -10
  36. data/vendor/libgit2/include/git2/deprecated.h +1 -1
  37. data/vendor/libgit2/include/git2/index.h +1 -1
  38. data/vendor/libgit2/include/git2/merge.h +4 -2
  39. data/vendor/libgit2/include/git2/oid.h +0 -1
  40. data/vendor/libgit2/include/git2/proxy.h +2 -3
  41. data/vendor/libgit2/include/git2/remote.h +19 -7
  42. data/vendor/libgit2/include/git2/stdint.h +1 -1
  43. data/vendor/libgit2/include/git2/sys/transport.h +1 -1
  44. data/vendor/libgit2/include/git2/version.h +4 -2
  45. data/vendor/libgit2/src/cli/CMakeLists.txt +1 -2
  46. data/vendor/libgit2/src/cli/opt.c +3 -3
  47. data/vendor/libgit2/src/cli/opt_usage.c +1 -1
  48. data/vendor/libgit2/src/libgit2/CMakeLists.txt +32 -16
  49. data/vendor/libgit2/src/libgit2/attr_file.c +10 -3
  50. data/vendor/libgit2/src/libgit2/clone.c +6 -0
  51. data/vendor/libgit2/src/libgit2/commit.c +1 -1
  52. data/vendor/libgit2/src/libgit2/commit_graph.c +1 -2
  53. data/vendor/libgit2/src/libgit2/config.c +1 -1
  54. data/vendor/libgit2/src/libgit2/config_file.c +2 -1
  55. data/vendor/libgit2/src/libgit2/config_mem.c +1 -0
  56. data/vendor/libgit2/src/libgit2/config_parse.c +2 -1
  57. data/vendor/libgit2/src/libgit2/delta.c +5 -1
  58. data/vendor/libgit2/src/libgit2/diff_driver.c +1 -1
  59. data/vendor/libgit2/src/libgit2/diff_stats.c +19 -12
  60. data/vendor/libgit2/src/libgit2/fetchhead.c +1 -1
  61. data/vendor/libgit2/src/libgit2/index.c +8 -8
  62. data/vendor/libgit2/src/libgit2/index.h +3 -0
  63. data/vendor/libgit2/src/libgit2/indexer.c +2 -2
  64. data/vendor/libgit2/src/libgit2/merge.c +1 -1
  65. data/vendor/libgit2/src/libgit2/merge.h +4 -0
  66. data/vendor/libgit2/src/libgit2/merge_file.c +43 -30
  67. data/vendor/libgit2/src/libgit2/message.c +1 -1
  68. data/vendor/libgit2/src/libgit2/midx.c +2 -3
  69. data/vendor/libgit2/src/libgit2/odb.c +2 -6
  70. data/vendor/libgit2/src/libgit2/odb_loose.c +24 -14
  71. data/vendor/libgit2/src/libgit2/oid.c +4 -5
  72. data/vendor/libgit2/src/libgit2/pack-objects.c +2 -4
  73. data/vendor/libgit2/src/libgit2/pack.c +3 -0
  74. data/vendor/libgit2/src/libgit2/refs.c +15 -6
  75. data/vendor/libgit2/src/libgit2/remote.c +4 -1
  76. data/vendor/libgit2/src/libgit2/remote.h +0 -1
  77. data/vendor/libgit2/src/libgit2/repository.c +5 -4
  78. data/vendor/libgit2/src/libgit2/streams/socket.c +30 -0
  79. data/vendor/libgit2/src/libgit2/submodule.c +12 -5
  80. data/vendor/libgit2/src/libgit2/tag.c +3 -1
  81. data/vendor/libgit2/src/libgit2/transports/auth_sspi.c +2 -0
  82. data/vendor/libgit2/src/libgit2/transports/credential.c +1 -1
  83. data/vendor/libgit2/src/libgit2/transports/git.c +1 -1
  84. data/vendor/libgit2/src/libgit2/transports/httpclient.c +12 -9
  85. data/vendor/libgit2/src/libgit2/transports/local.c +8 -1
  86. data/vendor/libgit2/src/libgit2/transports/smart.c +5 -5
  87. data/vendor/libgit2/src/libgit2/transports/smart_pkt.c +3 -3
  88. data/vendor/libgit2/src/libgit2/transports/ssh_exec.c +57 -18
  89. data/vendor/libgit2/src/libgit2/transports/ssh_libssh2.c +3 -3
  90. data/vendor/libgit2/src/util/CMakeLists.txt +3 -4
  91. data/vendor/libgit2/src/util/fs_path.c +66 -6
  92. data/vendor/libgit2/src/util/fs_path.h +6 -0
  93. data/vendor/libgit2/src/util/futils.h +11 -3
  94. data/vendor/libgit2/src/util/hash/builtin.c +14 -4
  95. data/vendor/libgit2/src/util/hash/openssl.c +0 -4
  96. data/vendor/libgit2/src/util/hash/rfc6234/sha224-256.c +8 -6
  97. data/vendor/libgit2/src/util/hashmap.h +1 -0
  98. data/vendor/libgit2/src/util/net.c +5 -5
  99. data/vendor/libgit2/src/util/process.h +2 -1
  100. data/vendor/libgit2/src/util/runtime.c +2 -2
  101. data/vendor/libgit2/src/util/str.c +18 -6
  102. data/vendor/libgit2/src/util/str.h +5 -3
  103. data/vendor/libgit2/src/util/unix/process.c +92 -15
  104. data/vendor/libgit2/src/util/util.c +16 -3
  105. data/vendor/libgit2/src/util/util.h +1 -0
  106. data/vendor/libgit2/src/util/win32/path_w32.c +81 -5
  107. data/vendor/libgit2/src/util/win32/process.c +22 -6
  108. metadata +17 -6
@@ -1225,7 +1225,7 @@ static int canonicalize_directory_path(
1225
1225
  {
1226
1226
  const git_index_entry *match, *best = NULL;
1227
1227
  char *search, *sep;
1228
- size_t pos, search_len, best_len;
1228
+ size_t pos, search_len, best_len = 0;
1229
1229
 
1230
1230
  if (!index->ignore_case)
1231
1231
  return 0;
@@ -1448,7 +1448,7 @@ out:
1448
1448
  return error;
1449
1449
  }
1450
1450
 
1451
- static int index_conflict_to_reuc(git_index *index, const char *path)
1451
+ int git_index__conflict_to_reuc(git_index *index, const char *path)
1452
1452
  {
1453
1453
  const git_index_entry *conflict_entries[3];
1454
1454
  int ancestor_mode, our_mode, their_mode;
@@ -1528,7 +1528,7 @@ int git_index_add_from_buffer(
1528
1528
  return error;
1529
1529
 
1530
1530
  /* Adding implies conflict was resolved, move conflict entries to REUC */
1531
- if ((error = index_conflict_to_reuc(index, entry->path)) < 0 && error != GIT_ENOTFOUND)
1531
+ if ((error = git_index__conflict_to_reuc(index, entry->path)) < 0 && error != GIT_ENOTFOUND)
1532
1532
  return error;
1533
1533
 
1534
1534
  git_tree_cache_invalidate_path(index->tree, entry->path);
@@ -1624,7 +1624,7 @@ int git_index_add_bypath(git_index *index, const char *path)
1624
1624
  }
1625
1625
 
1626
1626
  /* Adding implies conflict was resolved, move conflict entries to REUC */
1627
- if ((ret = index_conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND)
1627
+ if ((ret = git_index__conflict_to_reuc(index, path)) < 0 && ret != GIT_ENOTFOUND)
1628
1628
  return ret;
1629
1629
 
1630
1630
  git_tree_cache_invalidate_path(index->tree, entry->path);
@@ -1640,7 +1640,7 @@ int git_index_remove_bypath(git_index *index, const char *path)
1640
1640
 
1641
1641
  if (((ret = git_index_remove(index, path, 0)) < 0 &&
1642
1642
  ret != GIT_ENOTFOUND) ||
1643
- ((ret = index_conflict_to_reuc(index, path)) < 0 &&
1643
+ ((ret = git_index__conflict_to_reuc(index, path)) < 0 &&
1644
1644
  ret != GIT_ENOTFOUND))
1645
1645
  return ret;
1646
1646
 
@@ -2525,7 +2525,7 @@ static int read_entry(
2525
2525
  {
2526
2526
  size_t path_length, path_offset, entry_size;
2527
2527
  const char *path_ptr;
2528
- struct entry_common *source_common;
2528
+ struct entry_common *source_common = NULL;
2529
2529
  index_entry_short_sha1 source_sha1;
2530
2530
  #ifdef GIT_EXPERIMENTAL_SHA256
2531
2531
  index_entry_short_sha256 source_sha256;
@@ -2877,7 +2877,7 @@ static int write_disk_entry(
2877
2877
  const char *last)
2878
2878
  {
2879
2879
  void *mem = NULL;
2880
- struct entry_common *ondisk_common;
2880
+ struct entry_common *ondisk_common = NULL;
2881
2881
  size_t path_len, path_offset, disk_size;
2882
2882
  int varint_len = 0;
2883
2883
  char *path;
@@ -2966,7 +2966,7 @@ static int write_disk_entry(
2966
2966
  path_offset = index_entry_path_offset(index->oid_type, entry->flags);
2967
2967
 
2968
2968
  if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
2969
- struct entry_common *ondisk_ext;
2969
+ struct entry_common *ondisk_ext = NULL;
2970
2970
  uint16_t flags_extended = htons(entry->flags_extended &
2971
2971
  GIT_INDEX_ENTRY_EXTENDED_FLAGS);
2972
2972
 
@@ -154,6 +154,9 @@ extern int git_index__open(
154
154
  const char *index_path,
155
155
  git_oid_t oid_type);
156
156
 
157
+ /* If the path is conflicted, move it from the index to reuc. */
158
+ int git_index__conflict_to_reuc(git_index *index, const char *path);
159
+
157
160
  /* Copy the current entries vector *and* increment the index refcount.
158
161
  * Call `git_index__release_snapshot` when done.
159
162
  */
@@ -921,12 +921,12 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_inde
921
921
  if (git_vector_init(&idx->deltas, total_objects / 2, NULL) < 0)
922
922
  return -1;
923
923
 
924
+ stats->total_objects = total_objects;
925
+ stats->indexed_objects = 0;
924
926
  stats->received_objects = 0;
925
927
  stats->local_objects = 0;
926
928
  stats->total_deltas = 0;
927
929
  stats->indexed_deltas = 0;
928
- stats->indexed_objects = 0;
929
- stats->total_objects = total_objects;
930
930
 
931
931
  if ((error = do_progress_callback(idx, stats)) != 0)
932
932
  return error;
@@ -936,7 +936,7 @@ static int merge_conflict_resolve_contents(
936
936
  git_merge_file_result result = {0};
937
937
  git_merge_driver *driver;
938
938
  git_merge_driver__builtin builtin = {{0}};
939
- git_index_entry *merge_result;
939
+ git_index_entry *merge_result = NULL;
940
940
  git_odb *odb = NULL;
941
941
  const char *name;
942
942
  bool fallback = false;
@@ -165,6 +165,10 @@ GIT_INLINE(const char *) git_merge_file__best_path(
165
165
  if (!ancestor) {
166
166
  if (ours && theirs && strcmp(ours, theirs) == 0)
167
167
  return ours;
168
+ if (ours && !theirs)
169
+ return ours;
170
+ if (theirs && !ours)
171
+ return theirs;
168
172
 
169
173
  return NULL;
170
174
  }
@@ -84,30 +84,34 @@ static int merge_file__xdiff(
84
84
 
85
85
  memset(&xmparam, 0x0, sizeof(xmparam_t));
86
86
 
87
- if (ours->size > LONG_MAX ||
88
- theirs->size > LONG_MAX ||
87
+ if ((ours && ours->size > LONG_MAX) ||
88
+ (theirs && theirs->size > LONG_MAX) ||
89
89
  (ancestor && ancestor->size > LONG_MAX)) {
90
90
  git_error_set(GIT_ERROR_MERGE, "failed to merge files");
91
91
  error = -1;
92
92
  goto done;
93
93
  }
94
94
 
95
- if (ancestor) {
95
+ if (ancestor && ancestor->size) {
96
96
  xmparam.ancestor = (options.ancestor_label) ?
97
97
  options.ancestor_label : ancestor->path;
98
98
  ancestor_mmfile.ptr = (char *)ancestor->ptr;
99
99
  ancestor_mmfile.size = (long)ancestor->size;
100
100
  }
101
101
 
102
- xmparam.file1 = (options.our_label) ?
103
- options.our_label : ours->path;
104
- our_mmfile.ptr = (char *)ours->ptr;
105
- our_mmfile.size = (long)ours->size;
102
+ if (ours && ours->size) {
103
+ xmparam.file1 = (options.our_label) ?
104
+ options.our_label : ours->path;
105
+ our_mmfile.ptr = (char *)ours->ptr;
106
+ our_mmfile.size = (long)ours->size;
107
+ }
106
108
 
107
- xmparam.file2 = (options.their_label) ?
108
- options.their_label : theirs->path;
109
- their_mmfile.ptr = (char *)theirs->ptr;
110
- their_mmfile.size = (long)theirs->size;
109
+ if (theirs && theirs->size) {
110
+ xmparam.file2 = (options.their_label) ?
111
+ options.their_label : theirs->path;
112
+ their_mmfile.ptr = (char *)theirs->ptr;
113
+ their_mmfile.size = (long)theirs->size;
114
+ }
111
115
 
112
116
  if (options.favor == GIT_MERGE_FILE_FAVOR_OURS)
113
117
  xmparam.favor = XDL_MERGE_FAVOR_OURS;
@@ -148,8 +152,8 @@ static int merge_file__xdiff(
148
152
 
149
153
  path = git_merge_file__best_path(
150
154
  ancestor ? ancestor->path : NULL,
151
- ours->path,
152
- theirs->path);
155
+ ours ? ours->path : NULL,
156
+ theirs ? theirs->path : NULL);
153
157
 
154
158
  if (path != NULL && (out->path = git__strdup(path)) == NULL) {
155
159
  error = -1;
@@ -161,8 +165,8 @@ static int merge_file__xdiff(
161
165
  out->len = mmbuffer.size;
162
166
  out->mode = git_merge_file__best_mode(
163
167
  ancestor ? ancestor->mode : 0,
164
- ours->mode,
165
- theirs->mode);
168
+ ours ? ours->mode : 0,
169
+ theirs ? theirs->mode : 0);
166
170
 
167
171
  done:
168
172
  if (error < 0)
@@ -201,7 +205,7 @@ static int merge_file__binary(
201
205
  goto done;
202
206
 
203
207
  if ((out->path = git__strdup(favored->path)) == NULL ||
204
- (out->ptr = git__malloc(favored->size)) == NULL)
208
+ (out->ptr = git__malloc(favored->size)) == NULL)
205
209
  goto done;
206
210
 
207
211
  memcpy((char *)out->ptr, favored->ptr, favored->size);
@@ -221,8 +225,8 @@ static int merge_file__from_inputs(
221
225
  const git_merge_file_options *given_opts)
222
226
  {
223
227
  if (merge_file__is_binary(ancestor) ||
224
- merge_file__is_binary(ours) ||
225
- merge_file__is_binary(theirs))
228
+ merge_file__is_binary(ours) ||
229
+ merge_file__is_binary(theirs))
226
230
  return merge_file__binary(out, ours, theirs, given_opts);
227
231
 
228
232
  return merge_file__xdiff(out, ancestor, ours, theirs, given_opts);
@@ -261,8 +265,11 @@ int git_merge_file(
261
265
  if (ancestor)
262
266
  ancestor = git_merge_file__normalize_inputs(&inputs[0], ancestor);
263
267
 
264
- ours = git_merge_file__normalize_inputs(&inputs[1], ours);
265
- theirs = git_merge_file__normalize_inputs(&inputs[2], theirs);
268
+ if (ours)
269
+ ours = git_merge_file__normalize_inputs(&inputs[1], ours);
270
+
271
+ if (theirs)
272
+ theirs = git_merge_file__normalize_inputs(&inputs[2], theirs);
266
273
 
267
274
  return merge_file__from_inputs(out, ancestor, ours, theirs, options);
268
275
  }
@@ -275,16 +282,16 @@ int git_merge_file_from_index(
275
282
  const git_index_entry *theirs,
276
283
  const git_merge_file_options *options)
277
284
  {
278
- git_merge_file_input *ancestor_ptr = NULL,
279
- ancestor_input = {0}, our_input = {0}, their_input = {0};
280
- git_odb *odb = NULL;
285
+ git_merge_file_input ancestor_input = {0};
286
+ git_merge_file_input our_input = {0};
287
+ git_merge_file_input their_input = {0};
288
+ git_odb *odb;
281
289
  git_odb_object *odb_object[3] = { 0 };
282
290
  int error = 0;
283
291
 
284
292
  GIT_ASSERT_ARG(out);
285
293
  GIT_ASSERT_ARG(repo);
286
- GIT_ASSERT_ARG(ours);
287
- GIT_ASSERT_ARG(theirs);
294
+ GIT_ASSERT_ARG(ancestor || ours || theirs);
288
295
 
289
296
  memset(out, 0x0, sizeof(git_merge_file_result));
290
297
 
@@ -295,16 +302,22 @@ int git_merge_file_from_index(
295
302
  if ((error = merge_file_input_from_index(
296
303
  &ancestor_input, &odb_object[0], odb, ancestor)) < 0)
297
304
  goto done;
305
+ }
298
306
 
299
- ancestor_ptr = &ancestor_input;
307
+ if (ours) {
308
+ if ((error = merge_file_input_from_index(
309
+ &our_input, &odb_object[1], odb, ours)) < 0)
310
+ goto done;
300
311
  }
301
312
 
302
- if ((error = merge_file_input_from_index(&our_input, &odb_object[1], odb, ours)) < 0 ||
303
- (error = merge_file_input_from_index(&their_input, &odb_object[2], odb, theirs)) < 0)
304
- goto done;
313
+ if (theirs) {
314
+ if ((error = merge_file_input_from_index(
315
+ &their_input, &odb_object[2], odb, theirs)) < 0)
316
+ goto done;
317
+ }
305
318
 
306
319
  error = merge_file__from_inputs(out,
307
- ancestor_ptr, &our_input, &their_input, options);
320
+ &ancestor_input, &our_input, &their_input, options);
308
321
 
309
322
  done:
310
323
  git_odb_object_free(odb_object[0]);
@@ -33,7 +33,7 @@ static int git_message__prettify(
33
33
 
34
34
  int consecutive_empty_lines = 0;
35
35
  size_t i, line_length, rtrimmed_line_length;
36
- char *next_newline;
36
+ const char *next_newline;
37
37
 
38
38
  for (i = 0; i < strlen(message); i += line_length) {
39
39
  next_newline = memchr(message + i, '\n', message_len - i);
@@ -460,7 +460,7 @@ int git_midx_foreach_entry(
460
460
  {
461
461
  git_oid oid;
462
462
  size_t oid_size, i;
463
- int error;
463
+ int error = 0;
464
464
 
465
465
  GIT_ASSERT_ARG(idx);
466
466
 
@@ -579,8 +579,7 @@ int git_midx_writer_add(
579
579
  if (error < 0)
580
580
  return error;
581
581
 
582
- /* TODO: SHA256 */
583
- error = git_mwindow_get_pack(&p, git_str_cstr(&idx_path_buf), 0);
582
+ error = git_mwindow_get_pack(&p, git_str_cstr(&idx_path_buf), w->oid_type);
584
583
  git_str_dispose(&idx_path_buf);
585
584
  if (error < 0)
586
585
  return error;
@@ -790,12 +790,8 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
790
790
  if (*alternate == '\0' || *alternate == '#')
791
791
  continue;
792
792
 
793
- /*
794
- * Relative path: build based on the current `objects`
795
- * folder. However, relative paths are only allowed in
796
- * the current repository.
797
- */
798
- if (*alternate == '.' && !alternate_depth) {
793
+ /* Relative path: build based on the current `objects` folder. */
794
+ if (*alternate == '.') {
799
795
  if ((result = git_str_joinpath(&alternates_path, objects_dir, alternate)) < 0)
800
796
  break;
801
797
  alternate = git_str_cstr(&alternates_path);
@@ -276,8 +276,8 @@ done:
276
276
  static int read_loose_standard(git_rawobj *out, git_str *obj)
277
277
  {
278
278
  git_zstream zstream = GIT_ZSTREAM_INIT;
279
- unsigned char head[MAX_HEADER_LEN], *body = NULL;
280
- size_t decompressed, head_len, body_len, alloc_size;
279
+ unsigned char head[MAX_HEADER_LEN], *body = NULL, *body_out;
280
+ size_t decompressed, head_len, body_remain, alloc_size;
281
281
  obj_hdr hdr;
282
282
  int error;
283
283
 
@@ -285,16 +285,16 @@ static int read_loose_standard(git_rawobj *out, git_str *obj)
285
285
  (error = git_zstream_set_input(&zstream, git_str_cstr(obj), git_str_len(obj))) < 0)
286
286
  goto done;
287
287
 
288
- decompressed = sizeof(head);
289
-
290
288
  /*
291
289
  * inflate the initial part of the compressed buffer in order to
292
- * parse the header; read the largest header possible, then push the
293
- * remainder into the body buffer.
290
+ * parse the header and read the largest header possible. later, we'll
291
+ * push the remainder into the body buffer.
294
292
  */
293
+ decompressed = sizeof(head);
295
294
  if ((error = git_zstream_get_output(head, &decompressed, &zstream)) < 0 ||
296
295
  (error = parse_header(&hdr, &head_len, head, decompressed)) < 0)
297
296
  goto done;
297
+ GIT_ASSERT(head_len <= decompressed);
298
298
 
299
299
  if (!git_object_typeisloose(hdr.type)) {
300
300
  git_error_set(GIT_ERROR_ODB, "failed to inflate disk object");
@@ -311,16 +311,24 @@ static int read_loose_standard(git_rawobj *out, git_str *obj)
311
311
  error = -1;
312
312
  goto done;
313
313
  }
314
+ body_out = body;
315
+ body_remain = hdr.size;
314
316
 
315
- GIT_ASSERT(decompressed >= head_len);
316
- body_len = decompressed - head_len;
317
-
318
- if (body_len)
319
- memcpy(body, head + head_len, body_len);
317
+ decompressed -= head_len;
318
+ if (decompressed > body_remain) {
319
+ git_error_set(GIT_ERROR_ODB, "malformed object: body was longer than specified in header");
320
+ error = -1;
321
+ goto done;
322
+ }
323
+ if (decompressed)
324
+ memcpy(body_out, head + head_len, decompressed);
325
+ body_out += decompressed;
326
+ body_remain -= decompressed;
320
327
 
321
- decompressed = hdr.size - body_len;
322
- if ((error = git_zstream_get_output(body + body_len, &decompressed, &zstream)) < 0)
328
+ decompressed = body_remain;
329
+ if ((error = git_zstream_get_output(body_out, &decompressed, &zstream)) < 0)
323
330
  goto done;
331
+ body_out += decompressed;
324
332
 
325
333
  if (!git_zstream_done(&zstream)) {
326
334
  git_error_set(GIT_ERROR_ZLIB, "failed to finish zlib inflation: stream aborted prematurely");
@@ -328,7 +336,9 @@ static int read_loose_standard(git_rawobj *out, git_str *obj)
328
336
  goto done;
329
337
  }
330
338
 
331
- body[hdr.size] = '\0';
339
+ /* object bodies that are too short are silently zero-padded */
340
+ GIT_ASSERT(body_out <= body + hdr.size);
341
+ *body_out = '\0';
332
342
 
333
343
  out->data = body;
334
344
  out->len = hdr.size;
@@ -22,6 +22,8 @@ const git_oid git_oid__empty_tree_sha1 =
22
22
  { 0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
23
23
  0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 });
24
24
 
25
+ static const unsigned char git_oid_zero[GIT_OID_MAX_SIZE] = {0};
26
+
25
27
  static int oid_error_invalid(const char *msg)
26
28
  {
27
29
  git_error_set(GIT_ERROR_INVALID, "unable to parse OID - %s", msg);
@@ -318,7 +320,7 @@ int git_oid_streq(const git_oid *oid_a, const char *str)
318
320
  int git_oid_is_zero(const git_oid *oid_a)
319
321
  {
320
322
  const unsigned char *a = oid_a->id;
321
- size_t size = git_oid_size(git_oid_type(oid_a)), i;
323
+ size_t size = git_oid_size(git_oid_type(oid_a));
322
324
 
323
325
  #ifdef GIT_EXPERIMENTAL_SHA256
324
326
  if (!oid_a->type)
@@ -327,10 +329,7 @@ int git_oid_is_zero(const git_oid *oid_a)
327
329
  return 0;
328
330
  #endif
329
331
 
330
- for (i = 0; i < size; ++i, ++a)
331
- if (*a != 0)
332
- return 0;
333
- return 1;
332
+ return git_oid_raw_cmp(a, git_oid_zero, size) == 0 ? 1 : 0;
334
333
  }
335
334
 
336
335
  #ifndef GIT_DEPRECATE_HARD
@@ -1420,7 +1420,7 @@ int git_packbuilder_write(
1420
1420
  git_str object_path = GIT_STR_INIT;
1421
1421
  git_indexer_options opts = GIT_INDEXER_OPTIONS_INIT;
1422
1422
  git_indexer *indexer = NULL;
1423
- git_indexer_progress stats;
1423
+ git_indexer_progress stats = { 0 };
1424
1424
  struct pack_write_context ctx;
1425
1425
  int t;
1426
1426
 
@@ -1437,12 +1437,10 @@ int git_packbuilder_write(
1437
1437
  opts.progress_cb = progress_cb;
1438
1438
  opts.progress_cb_payload = progress_cb_payload;
1439
1439
 
1440
- /* TODO: SHA256 */
1441
-
1442
1440
  #ifdef GIT_EXPERIMENTAL_SHA256
1443
1441
  opts.mode = mode;
1444
1442
  opts.odb = pb->odb;
1445
- opts.oid_type = GIT_OID_SHA1;
1443
+ opts.oid_type = pb->oid_type;
1446
1444
 
1447
1445
  error = git_indexer_new(&indexer, path, &opts);
1448
1446
  #else
@@ -941,6 +941,9 @@ static int packfile_unpack_compressed(
941
941
  goto out;
942
942
  }
943
943
 
944
+ /* zlib may have garbled the trailing buffer */
945
+ data[size] = '\0';
946
+
944
947
  obj->type = type;
945
948
  obj->len = size;
946
949
  obj->data = data;
@@ -819,7 +819,7 @@ int git_reference_list(
819
819
 
820
820
  static int is_valid_ref_char(char ch)
821
821
  {
822
- if ((unsigned) ch <= ' ')
822
+ if ((unsigned) ch <= ' ' || ch == '\177') /* ASCII control characters */
823
823
  return 0;
824
824
 
825
825
  switch (ch) {
@@ -894,6 +894,9 @@ static bool is_valid_normalized_name(const char *name, size_t len)
894
894
  if (i == 0 && c == '^')
895
895
  continue; /* The first character is allowed to be "^" for negative refspecs */
896
896
 
897
+ if (len == 1 && c == '@')
898
+ return true; /* Abbreviation for HEAD */
899
+
897
900
  if ((c < 'A' || c > 'Z') && c != '_')
898
901
  return false;
899
902
  }
@@ -965,11 +968,16 @@ int git_reference__normalize_name(
965
968
  process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN;
966
969
 
967
970
  if (normalize) {
968
- size_t cur_len = git_str_len(buf);
969
-
970
- git_str_joinpath(buf, git_str_cstr(buf), current);
971
- git_str_truncate(buf,
972
- cur_len + segment_len + (segments_count ? 1 : 0));
971
+ /* `<empty>@` (i.e. just `@`) is an alias for `HEAD` */
972
+ if (segments_count == 0 && segment_len == 1 && current[0] == '@') {
973
+ git_str_sets(buf, GIT_HEAD_FILE);
974
+ } else {
975
+ size_t cur_len = git_str_len(buf);
976
+
977
+ git_str_joinpath(buf, git_str_cstr(buf), current);
978
+ git_str_truncate(buf,
979
+ cur_len + segment_len + (segments_count ? 1 : 0));
980
+ }
973
981
 
974
982
  if (git_str_oom(buf)) {
975
983
  error = -1;
@@ -1018,6 +1026,7 @@ int git_reference__normalize_name(
1018
1026
  goto cleanup;
1019
1027
 
1020
1028
  if ((segments_count > 1)
1029
+ && !(flags & GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND)
1021
1030
  && (is_valid_normalized_name(name, strchr(name, '/') - name)))
1022
1031
  goto cleanup;
1023
1032
 
@@ -236,6 +236,9 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
236
236
  if (opts->repository) {
237
237
  if ((error = git_repository_config_snapshot(&config_ro, opts->repository)) < 0)
238
238
  goto on_error;
239
+ } else if (!(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
240
+ if ((error = git_config_open_default(&config_ro)) < 0)
241
+ goto on_error;
239
242
  }
240
243
 
241
244
  remote = git__calloc(1, sizeof(git_remote));
@@ -247,7 +250,7 @@ int git_remote_create_with_opts(git_remote **out, const char *url, const git_rem
247
250
  (error = canonicalize_url(&canonical_url, url)) < 0)
248
251
  goto on_error;
249
252
 
250
- if (opts->repository && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
253
+ if (config_ro && !(opts->flags & GIT_REMOTE_CREATE_SKIP_INSTEADOF)) {
251
254
  if ((error = apply_insteadof(&remote->url, config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH, true)) < 0 ||
252
255
  (error = apply_insteadof(&remote->pushurl, config_ro, canonical_url.ptr, GIT_DIRECTION_PUSH, false)) < 0)
253
256
  goto on_error;
@@ -58,7 +58,6 @@ int git_remote_connect_options_normalize(
58
58
  const git_remote_connect_options *src);
59
59
 
60
60
  int git_remote_capabilities(unsigned int *out, git_remote *remote);
61
- int git_remote_oid_type(git_oid_t *out, git_remote *remote);
62
61
 
63
62
 
64
63
  #define git_remote_connect_options__copy_opts(out, in) \
@@ -562,7 +562,7 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload)
562
562
  validate_ownership_data *data = payload;
563
563
  const char *test_path;
564
564
 
565
- if (strcmp(entry->value, "") == 0) {
565
+ if (!entry->value || strcmp(entry->value, "") == 0) {
566
566
  *data->is_safe = false;
567
567
  } else if (strcmp(entry->value, "*") == 0) {
568
568
  *data->is_safe = true;
@@ -667,7 +667,7 @@ static int validate_ownership_path(bool *is_safe, const char *path)
667
667
 
668
668
  static int validate_ownership(git_repository *repo)
669
669
  {
670
- const char *validation_paths[3] = { NULL }, *path;
670
+ const char *validation_paths[3] = { NULL }, *path = NULL;
671
671
  size_t validation_len = 0, i;
672
672
  bool is_safe = false;
673
673
  int error = 0;
@@ -1410,7 +1410,7 @@ int git_repository_config__weakptr(git_config **out, git_repository *repo)
1410
1410
  git_str xdg_buf = GIT_STR_INIT;
1411
1411
  git_str programdata_buf = GIT_STR_INIT;
1412
1412
  bool use_env = repo->use_env;
1413
- git_config *config;
1413
+ git_config *config = NULL;
1414
1414
 
1415
1415
  if (!(error = config_path_system(&system_buf, use_env)) &&
1416
1416
  !(error = config_path_global(&global_buf, use_env))) {
@@ -1865,7 +1865,8 @@ static const char *builtin_extensions[] = {
1865
1865
  "noop",
1866
1866
  "objectformat",
1867
1867
  "worktreeconfig",
1868
- "preciousobjects"
1868
+ "preciousobjects",
1869
+ "relativeworktrees"
1869
1870
  };
1870
1871
 
1871
1872
  static git_vector user_extensions = { 0, git__strcmp_cb };
@@ -20,6 +20,10 @@
20
20
  # include <netdb.h>
21
21
  # include <netinet/in.h>
22
22
  # include <arpa/inet.h>
23
+ # include <netinet/tcp.h>
24
+ # ifdef __APPLE__
25
+ # include <sys/socket.h>
26
+ # endif
23
27
  #else
24
28
  # include <winsock2.h>
25
29
  # include <ws2tcpip.h>
@@ -188,6 +192,32 @@ static int socket_connect(git_stream *stream)
188
192
  for (p = info; p != NULL; p = p->ai_next) {
189
193
  s = socket(p->ai_family, p->ai_socktype | SOCK_CLOEXEC, p->ai_protocol);
190
194
 
195
+ /* Enable TCP keepalive to detect dead connections */
196
+ if (s != INVALID_SOCKET && p->ai_family == AF_INET) {
197
+ int keepalive = 1;
198
+ if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
199
+ (const char *)&keepalive, sizeof(keepalive)) == 0) {
200
+ #ifdef __APPLE__
201
+ /* macOS: Set idle time to 60 seconds */
202
+ int keepidle = 60;
203
+ setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE,
204
+ &keepidle, sizeof(keepidle));
205
+ /* Note: TCP_CONNECTIONTIMEOUT (0x20) could also be set */
206
+ #elif defined(__linux__)
207
+ /* Linux: Set idle, interval, and count */
208
+ int keepidle = 60; /* Start probes after 60 seconds */
209
+ int keepintvl = 10; /* 10 seconds between probes */
210
+ int keepcnt = 3; /* 3 probes before giving up */
211
+ setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE,
212
+ &keepidle, sizeof(keepidle));
213
+ setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL,
214
+ &keepintvl, sizeof(keepintvl));
215
+ setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT,
216
+ &keepcnt, sizeof(keepcnt));
217
+ #endif
218
+ }
219
+ }
220
+
191
221
  if (s == INVALID_SOCKET)
192
222
  continue;
193
223
 
@@ -1075,16 +1075,23 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
1075
1075
  git_commit_free(head);
1076
1076
 
1077
1077
  /* add it */
1078
- error = git_index_add(index, &entry);
1078
+ if ((error = git_index_add(index, &entry)) < 0)
1079
+ goto cleanup;
1080
+
1081
+ /* Adding implies conflict was resolved, move conflict entries to REUC */
1082
+ if ((error = git_index__conflict_to_reuc(index, entry.path)) < 0 && error != GIT_ENOTFOUND)
1083
+ goto cleanup;
1079
1084
 
1080
1085
  /* write it, if requested */
1081
- if (!error && write_index) {
1082
- error = git_index_write(index);
1086
+ if (write_index) {
1087
+ if ((error = git_index_write(index)) < 0)
1088
+ goto cleanup;
1083
1089
 
1084
- if (!error)
1085
- git_oid_cpy(&sm->index_oid, &sm->wd_oid);
1090
+ git_oid_cpy(&sm->index_oid, &sm->wd_oid);
1086
1091
  }
1087
1092
 
1093
+ error = 0;
1094
+
1088
1095
  cleanup:
1089
1096
  git_repository_free(sm_repo);
1090
1097
  git_str_dispose(&path);
@@ -263,8 +263,10 @@ static bool tag_name_is_valid(const char *tag_name)
263
263
  /*
264
264
  * Discourage tag name starting with dash,
265
265
  * https://github.com/git/git/commit/4f0accd638b8d2
266
+ * and refuse to use HEAD as a tagname,
267
+ * https://github.com/git/git/commit/bbd445d5efd415
266
268
  */
267
- return tag_name[0] != '-';
269
+ return tag_name[0] != '-' && git__strcmp(tag_name, "HEAD");
268
270
  }
269
271
 
270
272
  static int git_tag_create__internal(
@@ -324,12 +324,14 @@ static int sspi_init_context(
324
324
  return 0;
325
325
  }
326
326
 
327
+ #if defined(GIT_GSSAPI) || defined(GIT_GSSFRAMEWORK) || defined(GIT_WIN32)
327
328
  int git_http_auth_negotiate(
328
329
  git_http_auth_context **out,
329
330
  const git_net_url *url)
330
331
  {
331
332
  return sspi_init_context(out, GIT_HTTP_AUTH_NEGOTIATE, url);
332
333
  }
334
+ #endif
333
335
 
334
336
  int git_http_auth_ntlm(
335
337
  git_http_auth_context **out,