rugged 0.24.0 → 0.24.5

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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rugged/version.rb +1 -1
  3. data/vendor/libgit2/CMakeLists.txt +20 -9
  4. data/vendor/libgit2/deps/http-parser/http_parser.c +5 -2
  5. data/vendor/libgit2/include/git2/checkout.h +7 -0
  6. data/vendor/libgit2/include/git2/common.h +16 -1
  7. data/vendor/libgit2/include/git2/version.h +2 -2
  8. data/vendor/libgit2/src/array.h +40 -0
  9. data/vendor/libgit2/src/blame.c +8 -3
  10. data/vendor/libgit2/src/blame_git.c +20 -9
  11. data/vendor/libgit2/src/checkout.c +13 -5
  12. data/vendor/libgit2/src/commit.c +5 -4
  13. data/vendor/libgit2/src/common.h +1 -1
  14. data/vendor/libgit2/src/config_cache.c +2 -1
  15. data/vendor/libgit2/src/config_file.c +14 -20
  16. data/vendor/libgit2/src/delta-apply.c +36 -5
  17. data/vendor/libgit2/src/delta-apply.h +12 -0
  18. data/vendor/libgit2/src/describe.c +2 -1
  19. data/vendor/libgit2/src/diff_tform.c +5 -3
  20. data/vendor/libgit2/src/filebuf.c +6 -1
  21. data/vendor/libgit2/src/global.c +28 -8
  22. data/vendor/libgit2/src/global.h +1 -0
  23. data/vendor/libgit2/src/ignore.c +56 -19
  24. data/vendor/libgit2/src/index.c +27 -8
  25. data/vendor/libgit2/src/indexer.c +11 -7
  26. data/vendor/libgit2/src/iterator.c +2 -2
  27. data/vendor/libgit2/src/merge.c +1 -0
  28. data/vendor/libgit2/src/mwindow.c +20 -21
  29. data/vendor/libgit2/src/mwindow.h +1 -2
  30. data/vendor/libgit2/src/object.c +3 -6
  31. data/vendor/libgit2/src/odb.c +11 -15
  32. data/vendor/libgit2/src/odb.h +2 -1
  33. data/vendor/libgit2/src/odb_loose.c +13 -9
  34. data/vendor/libgit2/src/odb_pack.c +5 -6
  35. data/vendor/libgit2/src/oid.h +9 -0
  36. data/vendor/libgit2/src/openssl_stream.c +60 -27
  37. data/vendor/libgit2/src/openssl_stream.h +106 -0
  38. data/vendor/libgit2/src/pack-objects.c +4 -2
  39. data/vendor/libgit2/src/pack.c +10 -14
  40. data/vendor/libgit2/src/posix.c +7 -0
  41. data/vendor/libgit2/src/posix.h +1 -0
  42. data/vendor/libgit2/src/push.c +6 -6
  43. data/vendor/libgit2/src/refdb_fs.c +1 -0
  44. data/vendor/libgit2/src/refs.c +3 -0
  45. data/vendor/libgit2/src/refspec.c +4 -2
  46. data/vendor/libgit2/src/remote.c +15 -5
  47. data/vendor/libgit2/src/repository.c +29 -21
  48. data/vendor/libgit2/src/settings.c +23 -1
  49. data/vendor/libgit2/src/stransport_stream.c +15 -9
  50. data/vendor/libgit2/src/submodule.c +3 -2
  51. data/vendor/libgit2/src/sysdir.c +41 -47
  52. data/vendor/libgit2/src/sysdir.h +0 -5
  53. data/vendor/libgit2/src/tag.c +8 -2
  54. data/vendor/libgit2/src/thread-utils.h +5 -51
  55. data/vendor/libgit2/src/transport.c +2 -0
  56. data/vendor/libgit2/src/transports/http.c +2 -1
  57. data/vendor/libgit2/src/transports/smart_pkt.c +1 -0
  58. data/vendor/libgit2/src/transports/smart_protocol.c +72 -17
  59. data/vendor/libgit2/src/transports/ssh.c +32 -17
  60. data/vendor/libgit2/src/tree.c +83 -100
  61. data/vendor/libgit2/src/tree.h +4 -5
  62. data/vendor/libgit2/src/unix/map.c +5 -0
  63. data/vendor/libgit2/src/unix/pthread.h +54 -0
  64. data/vendor/libgit2/src/util.c +3 -3
  65. data/vendor/libgit2/src/win32/map.c +24 -5
  66. data/vendor/libgit2/src/win32/precompiled.h +1 -1
  67. data/vendor/libgit2/src/win32/{pthread.c → thread.c} +50 -80
  68. data/vendor/libgit2/src/win32/thread.h +62 -0
  69. data/vendor/libgit2/src/xdiff/xprepare.c +2 -1
  70. metadata +384 -394
  71. data/vendor/libgit2/src/win32/pthread.h +0 -92
@@ -49,6 +49,37 @@ int git__delta_read_header(
49
49
  return 0;
50
50
  }
51
51
 
52
+ #define DELTA_HEADER_BUFFER_LEN 16
53
+ int git__delta_read_header_fromstream(size_t *base_sz, size_t *res_sz, git_packfile_stream *stream)
54
+ {
55
+ static const size_t buffer_len = DELTA_HEADER_BUFFER_LEN;
56
+ unsigned char buffer[DELTA_HEADER_BUFFER_LEN];
57
+ const unsigned char *delta, *delta_end;
58
+ size_t len;
59
+ ssize_t read;
60
+
61
+ len = read = 0;
62
+ while (len < buffer_len) {
63
+ read = git_packfile_stream_read(stream, &buffer[len], buffer_len - len);
64
+
65
+ if (read == 0)
66
+ break;
67
+
68
+ if (read == GIT_EBUFS)
69
+ continue;
70
+
71
+ len += read;
72
+ }
73
+
74
+ delta = buffer;
75
+ delta_end = delta + len;
76
+ if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
77
+ (hdr_sz(res_sz, &delta, delta_end) < 0))
78
+ return -1;
79
+
80
+ return 0;
81
+ }
82
+
52
83
  int git__delta_apply(
53
84
  git_rawobj *out,
54
85
  const unsigned char *base,
@@ -90,13 +121,13 @@ int git__delta_apply(
90
121
  size_t off = 0, len = 0;
91
122
 
92
123
  if (cmd & 0x01) off = *delta++;
93
- if (cmd & 0x02) off |= *delta++ << 8;
94
- if (cmd & 0x04) off |= *delta++ << 16;
95
- if (cmd & 0x08) off |= *delta++ << 24;
124
+ if (cmd & 0x02) off |= *delta++ << 8UL;
125
+ if (cmd & 0x04) off |= *delta++ << 16UL;
126
+ if (cmd & 0x08) off |= *delta++ << 24UL;
96
127
 
97
128
  if (cmd & 0x10) len = *delta++;
98
- if (cmd & 0x20) len |= *delta++ << 8;
99
- if (cmd & 0x40) len |= *delta++ << 16;
129
+ if (cmd & 0x20) len |= *delta++ << 8UL;
130
+ if (cmd & 0x40) len |= *delta++ << 16UL;
100
131
  if (!len) len = 0x10000;
101
132
 
102
133
  if (base_len < off + len || res_sz < len)
@@ -8,6 +8,7 @@
8
8
  #define INCLUDE_delta_apply_h__
9
9
 
10
10
  #include "odb.h"
11
+ #include "pack.h"
11
12
 
12
13
  /**
13
14
  * Apply a git binary delta to recover the original content.
@@ -47,4 +48,15 @@ extern int git__delta_read_header(
47
48
  size_t *base_sz,
48
49
  size_t *res_sz);
49
50
 
51
+ /**
52
+ * Read the header of a git binary delta
53
+ *
54
+ * This variant reads just enough from the packfile stream to read the
55
+ * delta header.
56
+ */
57
+ extern int git__delta_read_header_fromstream(
58
+ size_t *base_sz,
59
+ size_t *res_sz,
60
+ git_packfile_stream *stream);
61
+
50
62
  #endif
@@ -582,7 +582,8 @@ static int describe(
582
582
  best = (struct possible_tag *)git_vector_get(&all_matches, 0);
583
583
 
584
584
  if (gave_up_on) {
585
- git_pqueue_insert(&list, gave_up_on);
585
+ if ((error = git_pqueue_insert(&list, gave_up_on)) < 0)
586
+ goto cleanup;
586
587
  seen_commits--;
587
588
  }
588
589
  if ((error = finish_depth_computation(
@@ -261,7 +261,7 @@ static int normalize_find_opts(
261
261
  if (!given ||
262
262
  (given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG)
263
263
  {
264
- if (diff->repo) {
264
+ if (cfg) {
265
265
  char *rule =
266
266
  git_config__get_string_force(cfg, "diff.renames", "true");
267
267
  int boolval;
@@ -318,8 +318,10 @@ static int normalize_find_opts(
318
318
  #undef USE_DEFAULT
319
319
 
320
320
  if (!opts->rename_limit) {
321
- opts->rename_limit = git_config__get_int_force(
322
- cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
321
+ if (cfg) {
322
+ opts->rename_limit = git_config__get_int_force(
323
+ cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
324
+ }
323
325
 
324
326
  if (opts->rename_limit <= 0)
325
327
  opts->rename_limit = DEFAULT_RENAME_LIMIT;
@@ -70,6 +70,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
70
70
  git_file source;
71
71
  char buffer[FILEIO_BUFSIZE];
72
72
  ssize_t read_bytes;
73
+ int error = 0;
73
74
 
74
75
  source = p_open(file->path_original, O_RDONLY);
75
76
  if (source < 0) {
@@ -80,7 +81,8 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
80
81
  }
81
82
 
82
83
  while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) {
83
- p_write(file->fd, buffer, read_bytes);
84
+ if ((error = p_write(file->fd, buffer, read_bytes)) < 0)
85
+ break;
84
86
  if (file->compute_digest)
85
87
  git_hash_update(&file->digest, buffer, read_bytes);
86
88
  }
@@ -90,6 +92,9 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
90
92
  if (read_bytes < 0) {
91
93
  giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original);
92
94
  return -1;
95
+ } else if (error < 0) {
96
+ giterr_set(GITERR_OS, "Failed to write file '%s'", file->path_lock);
97
+ return -1;
93
98
  }
94
99
  }
95
100
 
@@ -27,6 +27,7 @@ static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
27
27
  static git_atomic git__n_shutdown_callbacks;
28
28
  static git_atomic git__n_inits;
29
29
  char *git__user_agent;
30
+ char *git__ssl_ciphers;
30
31
 
31
32
  void git__on_shutdown(git_global_shutdown_fn callback)
32
33
  {
@@ -58,8 +59,9 @@ static int init_common(void)
58
59
  if ((ret = git_hash_global_init()) == 0 &&
59
60
  (ret = git_sysdir_global_init()) == 0 &&
60
61
  (ret = git_filter_global_init()) == 0 &&
61
- (ret = git_transport_ssh_global_init()) == 0)
62
- ret = git_openssl_stream_global_init();
62
+ (ret = git_transport_ssh_global_init()) == 0 &&
63
+ (ret = git_openssl_stream_global_init()) == 0)
64
+ ret = git_mwindow_global_init();
63
65
 
64
66
  GIT_MEMORY_BARRIER;
65
67
 
@@ -83,11 +85,7 @@ static void shutdown_common(void)
83
85
  }
84
86
 
85
87
  git__free(git__user_agent);
86
-
87
- #if defined(GIT_MSVC_CRTDBG)
88
- git_win32__crtdbg_stacktrace_cleanup();
89
- git_win32__stack_cleanup();
90
- #endif
88
+ git__free(git__ssl_ciphers);
91
89
  }
92
90
 
93
91
  /**
@@ -135,7 +133,7 @@ static int synchronized_threads_init(void)
135
133
 
136
134
  _tls_index = TlsAlloc();
137
135
 
138
- win32_pthread_initialize();
136
+ git_threads_init();
139
137
 
140
138
  if (git_mutex_init(&git__mwindow_mutex))
141
139
  return -1;
@@ -179,6 +177,11 @@ int git_libgit2_shutdown(void)
179
177
 
180
178
  TlsFree(_tls_index);
181
179
  git_mutex_free(&git__mwindow_mutex);
180
+
181
+ #if defined(GIT_MSVC_CRTDBG)
182
+ git_win32__crtdbg_stacktrace_cleanup();
183
+ git_win32__stack_cleanup();
184
+ #endif
182
185
  }
183
186
 
184
187
  /* Exit the lock */
@@ -222,6 +225,23 @@ void git__free_tls_data(void)
222
225
  TlsSetValue(_tls_index, NULL);
223
226
  }
224
227
 
228
+ BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
229
+ {
230
+ GIT_UNUSED(hInstDll);
231
+ GIT_UNUSED(lpvReserved);
232
+
233
+ /* This is how Windows lets us know our thread is being shut down */
234
+ if (fdwReason == DLL_THREAD_DETACH) {
235
+ git__free_tls_data();
236
+ }
237
+
238
+ /*
239
+ * Windows pays attention to this during library loading. We don't do anything
240
+ * so we trivially succeed.
241
+ */
242
+ return TRUE;
243
+ }
244
+
225
245
  #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
226
246
 
227
247
  static pthread_key_t _tls_key;
@@ -36,5 +36,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback);
36
36
  extern void git__free_tls_data(void);
37
37
 
38
38
  extern const char *git_libgit2__user_agent(void);
39
+ extern const char *git_libgit2__ssl_ciphers(void);
39
40
 
40
41
  #endif
@@ -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;
@@ -263,10 +292,18 @@ int git_ignore__for_path(
263
292
  goto cleanup;
264
293
 
265
294
  /* given a unrooted path in a non-bare repo, resolve it */
266
- if (workdir && git_path_root(path) < 0)
267
- error = git_path_find_dir(&ignores->dir, path, workdir);
268
- else
295
+ if (workdir && git_path_root(path) < 0) {
296
+ git_buf local = GIT_BUF_INIT;
297
+
298
+ if ((error = git_path_dirname_r(&local, path)) < 0 ||
299
+ (error = git_path_resolve_relative(&local, 0)) < 0 ||
300
+ (error = git_path_to_dir(&local)) < 0 ||
301
+ (error = git_buf_joinpath(&ignores->dir, workdir, local.ptr)) < 0)
302
+ {;} /* Nothing, we just want to stop on the first error */
303
+ git_buf_free(&local);
304
+ } else {
269
305
  error = git_buf_joinpath(&ignores->dir, path, "");
306
+ }
270
307
  if (error < 0)
271
308
  goto cleanup;
272
309
 
@@ -505,10 +505,11 @@ static int index_remove_entry(git_index *index, size_t pos)
505
505
  int error = 0;
506
506
  git_index_entry *entry = git_vector_get(&index->entries, pos);
507
507
 
508
- if (entry != NULL)
508
+ if (entry != NULL) {
509
509
  git_tree_cache_invalidate_path(index->tree, entry->path);
510
+ DELETE_IN_MAP(index, entry);
511
+ }
510
512
 
511
- DELETE_IN_MAP(index, entry);
512
513
  error = git_vector_remove(&index->entries, pos);
513
514
 
514
515
  if (!error) {
@@ -963,14 +964,20 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
963
964
  *reuc_out = reuc = reuc_entry_alloc(path);
964
965
  GITERR_CHECK_ALLOC(reuc);
965
966
 
966
- if ((reuc->mode[0] = ancestor_mode) > 0)
967
+ if ((reuc->mode[0] = ancestor_mode) > 0) {
968
+ assert(ancestor_oid);
967
969
  git_oid_cpy(&reuc->oid[0], ancestor_oid);
970
+ }
968
971
 
969
- if ((reuc->mode[1] = our_mode) > 0)
972
+ if ((reuc->mode[1] = our_mode) > 0) {
973
+ assert(our_oid);
970
974
  git_oid_cpy(&reuc->oid[1], our_oid);
975
+ }
971
976
 
972
- if ((reuc->mode[2] = their_mode) > 0)
977
+ if ((reuc->mode[2] = their_mode) > 0) {
978
+ assert(their_oid);
973
979
  git_oid_cpy(&reuc->oid[2], their_oid);
980
+ }
974
981
 
975
982
  return 0;
976
983
  }
@@ -2830,7 +2837,7 @@ static int read_tree_cb(
2830
2837
  return -1;
2831
2838
 
2832
2839
  entry->mode = tentry->attr;
2833
- entry->id = tentry->oid;
2840
+ git_oid_cpy(&entry->id, git_tree_entry_id(tentry));
2834
2841
 
2835
2842
  /* look for corresponding old entry and copy data to new entry */
2836
2843
  if (data->old_entries != NULL &&
@@ -2962,6 +2969,8 @@ int git_index_read_index(
2962
2969
  *remove_entry = NULL;
2963
2970
  int diff;
2964
2971
 
2972
+ error = 0;
2973
+
2965
2974
  if (old_entry && new_entry)
2966
2975
  diff = git_index_entry_cmp(old_entry, new_entry);
2967
2976
  else if (!old_entry && new_entry)
@@ -2979,7 +2988,8 @@ int git_index_read_index(
2979
2988
  /* Path and stage are equal, if the OID is equal, keep it to
2980
2989
  * keep the stat cache data.
2981
2990
  */
2982
- if (git_oid_equal(&old_entry->id, &new_entry->id)) {
2991
+ if (git_oid_equal(&old_entry->id, &new_entry->id) &&
2992
+ old_entry->mode == new_entry->mode) {
2983
2993
  add_entry = (git_index_entry *)old_entry;
2984
2994
  } else {
2985
2995
  dup_entry = (git_index_entry *)new_entry;
@@ -2990,8 +3000,17 @@ int git_index_read_index(
2990
3000
  if (dup_entry) {
2991
3001
  if ((error = index_entry_dup_nocache(&add_entry, index, dup_entry)) < 0)
2992
3002
  goto done;
3003
+
3004
+ index_entry_adjust_namemask(add_entry,
3005
+ ((struct entry_internal *)add_entry)->pathlen);
2993
3006
  }
2994
3007
 
3008
+ /* invalidate this path in the tree cache if this is new (to
3009
+ * invalidate the parent trees)
3010
+ */
3011
+ if (dup_entry && !remove_entry && index->tree)
3012
+ git_tree_cache_invalidate_path(index->tree, dup_entry->path);
3013
+
2995
3014
  if (add_entry) {
2996
3015
  if ((error = git_vector_insert(&new_entries, add_entry)) == 0)
2997
3016
  INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error);
@@ -3002,7 +3021,7 @@ int git_index_read_index(
3002
3021
 
3003
3022
  if (error < 0) {
3004
3023
  giterr_set(GITERR_INDEX, "failed to insert entry");
3005
- return error;
3024
+ goto done;
3006
3025
  }
3007
3026
 
3008
3027
  if (diff <= 0) {
@@ -449,7 +449,7 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
449
449
  static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size)
450
450
  {
451
451
  git_file fd = idx->pack->mwf.fd;
452
- size_t page_size;
452
+ size_t mmap_alignment;
453
453
  size_t page_offset;
454
454
  git_off_t page_start;
455
455
  unsigned char *map_data;
@@ -458,11 +458,11 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
458
458
 
459
459
  assert(data && size);
460
460
 
461
- if ((error = git__page_size(&page_size)) < 0)
461
+ if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
462
462
  return error;
463
463
 
464
- /* the offset needs to be at the beginning of the a page boundary */
465
- page_offset = offset % page_size;
464
+ /* the offset needs to be at the mmap boundary for the platform */
465
+ page_offset = offset % mmap_alignment;
466
466
  page_start = offset - page_offset;
467
467
 
468
468
  if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
@@ -777,7 +777,6 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
777
777
 
778
778
  curpos = delta->delta_off;
779
779
  error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
780
- git_mwindow_close(&w);
781
780
  if (error < 0)
782
781
  return error;
783
782
 
@@ -914,12 +913,17 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
914
913
  git_filebuf index_file = {0};
915
914
  void *packfile_trailer;
916
915
 
916
+ if (!idx->parsed_header) {
917
+ giterr_set(GITERR_INDEXER, "incomplete pack header");
918
+ return -1;
919
+ }
920
+
917
921
  if (git_hash_ctx_init(&ctx) < 0)
918
922
  return -1;
919
923
 
920
924
  /* Test for this before resolve_deltas(), as it plays with idx->off */
921
- if (idx->off < idx->pack->mwf.size - 20) {
922
- giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack");
925
+ if (idx->off + 20 < idx->pack->mwf.size) {
926
+ giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack");
923
927
  return -1;
924
928
  }
925
929