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
@@ -16,7 +16,7 @@
16
16
  #include "socket_stream.h"
17
17
  #include "curl_stream.h"
18
18
 
19
- int stransport_error(OSStatus ret)
19
+ static int stransport_error(OSStatus ret)
20
20
  {
21
21
  CFStringRef message;
22
22
 
@@ -33,6 +33,7 @@ int stransport_error(OSStatus ret)
33
33
  CFRelease(message);
34
34
  #else
35
35
  giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
36
+ GIT_UNUSED(message);
36
37
  #endif
37
38
 
38
39
  return -1;
@@ -46,7 +47,7 @@ typedef struct {
46
47
  git_cert_x509 cert_info;
47
48
  } stransport_stream;
48
49
 
49
- int stransport_connect(git_stream *stream)
50
+ static int stransport_connect(git_stream *stream)
50
51
  {
51
52
  stransport_stream *st = (stransport_stream *) stream;
52
53
  int error;
@@ -66,6 +67,9 @@ int stransport_connect(git_stream *stream)
66
67
  if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
67
68
  goto on_error;
68
69
 
70
+ if (!trust)
71
+ return GIT_ECERTIFICATE;
72
+
69
73
  if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
70
74
  goto on_error;
71
75
 
@@ -89,7 +93,7 @@ on_error:
89
93
  return stransport_error(ret);
90
94
  }
91
95
 
92
- int stransport_certificate(git_cert **out, git_stream *stream)
96
+ static int stransport_certificate(git_cert **out, git_stream *stream)
93
97
  {
94
98
  stransport_stream *st = (stransport_stream *) stream;
95
99
  SecTrustRef trust = NULL;
@@ -116,7 +120,7 @@ int stransport_certificate(git_cert **out, git_stream *stream)
116
120
  return 0;
117
121
  }
118
122
 
119
- int stransport_set_proxy(git_stream *stream, const char *proxy)
123
+ static int stransport_set_proxy(git_stream *stream, const char *proxy)
120
124
  {
121
125
  stransport_stream *st = (stransport_stream *) stream;
122
126
 
@@ -146,7 +150,7 @@ static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
146
150
  return noErr;
147
151
  }
148
152
 
149
- ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
153
+ static ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
150
154
  {
151
155
  stransport_stream *st = (stransport_stream *) stream;
152
156
  size_t data_len, processed;
@@ -195,7 +199,7 @@ static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len)
195
199
  return error;
196
200
  }
197
201
 
198
- ssize_t stransport_read(git_stream *stream, void *data, size_t len)
202
+ static ssize_t stransport_read(git_stream *stream, void *data, size_t len)
199
203
  {
200
204
  stransport_stream *st = (stransport_stream *) stream;
201
205
  size_t processed;
@@ -207,7 +211,7 @@ ssize_t stransport_read(git_stream *stream, void *data, size_t len)
207
211
  return processed;
208
212
  }
209
213
 
210
- int stransport_close(git_stream *stream)
214
+ static int stransport_close(git_stream *stream)
211
215
  {
212
216
  stransport_stream *st = (stransport_stream *) stream;
213
217
  OSStatus ret;
@@ -219,7 +223,7 @@ int stransport_close(git_stream *stream)
219
223
  return git_stream_close(st->io);
220
224
  }
221
225
 
222
- void stransport_free(git_stream *stream)
226
+ static void stransport_free(git_stream *stream)
223
227
  {
224
228
  stransport_stream *st = (stransport_stream *) stream;
225
229
 
@@ -255,6 +259,7 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
255
259
  st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
256
260
  if (!st->ctx) {
257
261
  giterr_set(GITERR_NET, "failed to create SSL context");
262
+ git__free(st);
258
263
  return -1;
259
264
  }
260
265
 
@@ -264,7 +269,8 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
264
269
  (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr ||
265
270
  (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr ||
266
271
  (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
267
- git_stream_free((git_stream *)st);
272
+ CFRelease(st->ctx);
273
+ git__free(st);
268
274
  return stransport_error(ret);
269
275
  }
270
276
 
@@ -80,7 +80,8 @@ static kh_inline int str_equal_no_trailing_slash(const char *a, const char *b)
80
80
  if (blen > 0 && b[blen - 1] == '/')
81
81
  blen--;
82
82
 
83
- return (alen == blen && strncmp(a, b, alen) == 0);
83
+ return (alen == 0 && blen == 0) ||
84
+ (alen == blen && strncmp(a, b, alen) == 0);
84
85
  }
85
86
 
86
87
  __KHASH_IMPL(
@@ -1416,7 +1417,7 @@ static int submodule_update_head(git_submodule *submodule)
1416
1417
  git_tree_entry_bypath(&te, head, submodule->path) < 0)
1417
1418
  giterr_clear();
1418
1419
  else
1419
- submodule_update_from_head_data(submodule, te->attr, &te->oid);
1420
+ submodule_update_from_head_data(submodule, te->attr, git_tree_entry_id(te));
1420
1421
 
1421
1422
  git_tree_entry_free(te);
1422
1423
  git_tree_free(head);
@@ -83,45 +83,43 @@ static int git_sysdir_guess_template_dirs(git_buf *out)
83
83
  #endif
84
84
  }
85
85
 
86
- typedef int (*git_sysdir_guess_cb)(git_buf *out);
87
-
88
- static git_buf git_sysdir__dirs[GIT_SYSDIR__MAX] =
89
- { GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT, GIT_BUF_INIT };
86
+ struct git_sysdir__dir {
87
+ git_buf buf;
88
+ int (*guess)(git_buf *out);
89
+ };
90
90
 
91
- static git_sysdir_guess_cb git_sysdir__dir_guess[GIT_SYSDIR__MAX] = {
92
- git_sysdir_guess_system_dirs,
93
- git_sysdir_guess_global_dirs,
94
- git_sysdir_guess_xdg_dirs,
95
- git_sysdir_guess_programdata_dirs,
96
- git_sysdir_guess_template_dirs,
91
+ static struct git_sysdir__dir git_sysdir__dirs[] = {
92
+ { GIT_BUF_INIT, git_sysdir_guess_system_dirs },
93
+ { GIT_BUF_INIT, git_sysdir_guess_global_dirs },
94
+ { GIT_BUF_INIT, git_sysdir_guess_xdg_dirs },
95
+ { GIT_BUF_INIT, git_sysdir_guess_programdata_dirs },
96
+ { GIT_BUF_INIT, git_sysdir_guess_template_dirs },
97
97
  };
98
98
 
99
- static int git_sysdir__dirs_shutdown_set = 0;
99
+ static void git_sysdir_global_shutdown(void)
100
+ {
101
+ size_t i;
102
+
103
+ for (i = 0; i < ARRAY_SIZE(git_sysdir__dirs); ++i)
104
+ git_buf_free(&git_sysdir__dirs[i].buf);
105
+ }
100
106
 
101
107
  int git_sysdir_global_init(void)
102
108
  {
103
- git_sysdir_t i;
104
- const git_buf *path;
109
+ size_t i;
105
110
  int error = 0;
106
111
 
107
- for (i = 0; !error && i < GIT_SYSDIR__MAX; i++)
108
- error = git_sysdir_get(&path, i);
112
+ for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); i++)
113
+ error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf);
109
114
 
110
- return error;
111
- }
115
+ git__on_shutdown(git_sysdir_global_shutdown);
112
116
 
113
- void git_sysdir_global_shutdown(void)
114
- {
115
- int i;
116
- for (i = 0; i < GIT_SYSDIR__MAX; ++i)
117
- git_buf_free(&git_sysdir__dirs[i]);
118
-
119
- git_sysdir__dirs_shutdown_set = 0;
117
+ return error;
120
118
  }
121
119
 
122
120
  static int git_sysdir_check_selector(git_sysdir_t which)
123
121
  {
124
- if (which < GIT_SYSDIR__MAX)
122
+ if (which < ARRAY_SIZE(git_sysdir__dirs))
125
123
  return 0;
126
124
 
127
125
  giterr_set(GITERR_INVALID, "config directory selector out of range");
@@ -137,18 +135,7 @@ int git_sysdir_get(const git_buf **out, git_sysdir_t which)
137
135
 
138
136
  GITERR_CHECK_ERROR(git_sysdir_check_selector(which));
139
137
 
140
- if (!git_buf_len(&git_sysdir__dirs[which])) {
141
- /* prepare shutdown if we're going to need it */
142
- if (!git_sysdir__dirs_shutdown_set) {
143
- git__on_shutdown(git_sysdir_global_shutdown);
144
- git_sysdir__dirs_shutdown_set = 1;
145
- }
146
-
147
- GITERR_CHECK_ERROR(
148
- git_sysdir__dir_guess[which](&git_sysdir__dirs[which]));
149
- }
150
-
151
- *out = &git_sysdir__dirs[which];
138
+ *out = &git_sysdir__dirs[which].buf;
152
139
  return 0;
153
140
  }
154
141
 
@@ -183,31 +170,38 @@ int git_sysdir_set(git_sysdir_t which, const char *search_path)
183
170
  if (search_path != NULL)
184
171
  expand_path = strstr(search_path, PATH_MAGIC);
185
172
 
186
- /* init with default if not yet done and needed (ignoring error) */
187
- if ((!search_path || expand_path) &&
188
- !git_buf_len(&git_sysdir__dirs[which]))
189
- git_sysdir__dir_guess[which](&git_sysdir__dirs[which]);
173
+ /* reset the default if this path has been cleared */
174
+ if (!search_path || expand_path)
175
+ git_sysdir__dirs[which].guess(&git_sysdir__dirs[which].buf);
190
176
 
191
177
  /* if $PATH is not referenced, then just set the path */
192
- if (!expand_path)
193
- return git_buf_sets(&git_sysdir__dirs[which], search_path);
178
+ if (!expand_path) {
179
+ if (search_path)
180
+ git_buf_sets(&git_sysdir__dirs[which].buf, search_path);
181
+
182
+ goto done;
183
+ }
194
184
 
195
185
  /* otherwise set to join(before $PATH, old value, after $PATH) */
196
186
  if (expand_path > search_path)
197
187
  git_buf_set(&merge, search_path, expand_path - search_path);
198
188
 
199
- if (git_buf_len(&git_sysdir__dirs[which]))
189
+ if (git_buf_len(&git_sysdir__dirs[which].buf))
200
190
  git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR,
201
- merge.ptr, git_sysdir__dirs[which].ptr);
191
+ merge.ptr, git_sysdir__dirs[which].buf.ptr);
202
192
 
203
193
  expand_path += strlen(PATH_MAGIC);
204
194
  if (*expand_path)
205
195
  git_buf_join(&merge, GIT_PATH_LIST_SEPARATOR, merge.ptr, expand_path);
206
196
 
207
- git_buf_swap(&git_sysdir__dirs[which], &merge);
197
+ git_buf_swap(&git_sysdir__dirs[which].buf, &merge);
208
198
  git_buf_free(&merge);
209
199
 
210
- return git_buf_oom(&git_sysdir__dirs[which]) ? -1 : 0;
200
+ done:
201
+ if (git_buf_oom(&git_sysdir__dirs[which].buf))
202
+ return -1;
203
+
204
+ return 0;
211
205
  }
212
206
 
213
207
  static int git_sysdir_find_in_dirlist(
@@ -103,9 +103,4 @@ extern int git_sysdir_get_str(char *out, size_t outlen, git_sysdir_t which);
103
103
  */
104
104
  extern int git_sysdir_set(git_sysdir_t which, const char *paths);
105
105
 
106
- /**
107
- * Free the configuration file search paths.
108
- */
109
- extern void git_sysdir_global_shutdown(void);
110
-
111
106
  #endif /* INCLUDE_sysdir_h__ */
@@ -137,8 +137,14 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
137
137
 
138
138
  tag->message = NULL;
139
139
  if (buffer < buffer_end) {
140
- if( *buffer != '\n' )
141
- return tag_error("No new line before message");
140
+ /* If we're not at the end of the header, search for it */
141
+ if( *buffer != '\n' ) {
142
+ search = strstr(buffer, "\n\n");
143
+ if (search)
144
+ buffer = search + 1;
145
+ else
146
+ return tag_error("tag contains no message");
147
+ }
142
148
 
143
149
  text_len = buffer_end - ++buffer;
144
150
 
@@ -40,58 +40,12 @@ typedef git_atomic git_atomic_ssize;
40
40
 
41
41
  #ifdef GIT_THREADS
42
42
 
43
- #if !defined(GIT_WIN32)
44
-
45
- typedef struct {
46
- pthread_t thread;
47
- } git_thread;
48
-
49
- #define git_thread_create(git_thread_ptr, attr, start_routine, arg) \
50
- pthread_create(&(git_thread_ptr)->thread, attr, start_routine, arg)
51
- #define git_thread_join(git_thread_ptr, status) \
52
- pthread_join((git_thread_ptr)->thread, status)
53
-
54
- #endif
55
-
56
- /* Pthreads Mutex */
57
- #define git_mutex pthread_mutex_t
58
- #define git_mutex_init(a) pthread_mutex_init(a, NULL)
59
- #define git_mutex_lock(a) pthread_mutex_lock(a)
60
- #define git_mutex_unlock(a) pthread_mutex_unlock(a)
61
- #define git_mutex_free(a) pthread_mutex_destroy(a)
62
-
63
- /* Pthreads condition vars */
64
- #define git_cond pthread_cond_t
65
- #define git_cond_init(c) pthread_cond_init(c, NULL)
66
- #define git_cond_free(c) pthread_cond_destroy(c)
67
- #define git_cond_wait(c, l) pthread_cond_wait(c, l)
68
- #define git_cond_signal(c) pthread_cond_signal(c)
69
- #define git_cond_broadcast(c) pthread_cond_broadcast(c)
70
-
71
- /* Pthread (-ish) rwlock
72
- *
73
- * This differs from normal pthreads rwlocks in two ways:
74
- * 1. Separate APIs for releasing read locks and write locks (as
75
- * opposed to the pure POSIX API which only has one unlock fn)
76
- * 2. You should not use recursive read locks (i.e. grabbing a read
77
- * lock in a thread that already holds a read lock) because the
78
- * Windows implementation doesn't support it
79
- */
80
- #define git_rwlock pthread_rwlock_t
81
- #define git_rwlock_init(a) pthread_rwlock_init(a, NULL)
82
- #define git_rwlock_rdlock(a) pthread_rwlock_rdlock(a)
83
- #define git_rwlock_rdunlock(a) pthread_rwlock_rdunlock(a)
84
- #define git_rwlock_wrlock(a) pthread_rwlock_wrlock(a)
85
- #define git_rwlock_wrunlock(a) pthread_rwlock_wrunlock(a)
86
- #define git_rwlock_free(a) pthread_rwlock_destroy(a)
87
- #define GIT_RWLOCK_STATIC_INIT PTHREAD_RWLOCK_INITIALIZER
88
-
89
- #ifndef GIT_WIN32
90
- #define pthread_rwlock_rdunlock pthread_rwlock_unlock
91
- #define pthread_rwlock_wrunlock pthread_rwlock_unlock
43
+ #ifdef GIT_WIN32
44
+ # include "win32/thread.h"
45
+ #else
46
+ # include "unix/pthread.h"
92
47
  #endif
93
48
 
94
-
95
49
  GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
96
50
  {
97
51
  #if defined(GIT_WIN32)
@@ -178,7 +132,7 @@ GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
178
132
  #else
179
133
 
180
134
  #define git_thread unsigned int
181
- #define git_thread_create(thread, attr, start_routine, arg) 0
135
+ #define git_thread_create(thread, start_routine, arg) 0
182
136
  #define git_thread_join(id, status) (void)0
183
137
 
184
138
  /* Pthreads Mutex */
@@ -35,6 +35,8 @@ static transport_definition transports[] = {
35
35
  { "file://", git_transport_local, NULL },
36
36
  #ifdef GIT_SSH
37
37
  { "ssh://", git_transport_smart, &ssh_subtransport_definition },
38
+ { "ssh+git://", git_transport_smart, &ssh_subtransport_definition },
39
+ { "git+ssh://", git_transport_smart, &ssh_subtransport_definition },
38
40
  #endif
39
41
  { NULL, 0, 0 }
40
42
  };
@@ -114,7 +114,7 @@ static bool challenge_match(git_http_auth_scheme *scheme, void *data)
114
114
  size_t scheme_len;
115
115
 
116
116
  scheme_len = strlen(scheme_name);
117
- return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
117
+ return (strncasecmp(challenge, scheme_name, scheme_len) == 0 &&
118
118
  (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
119
119
  }
120
120
 
@@ -569,6 +569,7 @@ static int http_connect(http_subtransport *t)
569
569
  git_stream_close(t->io);
570
570
  git_stream_free(t->io);
571
571
  t->io = NULL;
572
+ t->connected = 0;
572
573
  }
573
574
 
574
575
  if (t->connection_data.use_ssl) {
@@ -433,6 +433,7 @@ int git_pkt_parse_line(
433
433
  * line?
434
434
  */
435
435
  if (len == PKT_LEN_SIZE) {
436
+ *head = NULL;
436
437
  *out = line;
437
438
  return 0;
438
439
  }
@@ -721,32 +721,66 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
721
721
  return 0;
722
722
  }
723
723
 
724
- static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
724
+ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_buf *data_pkt_buf)
725
725
  {
726
726
  git_pkt *pkt;
727
- const char *line = data_pkt->data, *line_end;
728
- size_t line_len = data_pkt->len;
727
+ const char *line, *line_end;
728
+ size_t line_len;
729
729
  int error;
730
+ int reading_from_buf = data_pkt_buf->size > 0;
731
+
732
+ if (reading_from_buf) {
733
+ /* We had an existing partial packet, so add the new
734
+ * packet to the buffer and parse the whole thing */
735
+ git_buf_put(data_pkt_buf, data_pkt->data, data_pkt->len);
736
+ line = data_pkt_buf->ptr;
737
+ line_len = data_pkt_buf->size;
738
+ }
739
+ else {
740
+ line = data_pkt->data;
741
+ line_len = data_pkt->len;
742
+ }
730
743
 
731
744
  while (line_len > 0) {
732
745
  error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
733
746
 
734
- if (error < 0)
735
- return error;
747
+ if (error == GIT_EBUFS) {
748
+ /* Buffer the data when the inner packet is split
749
+ * across multiple sideband packets */
750
+ if (!reading_from_buf)
751
+ git_buf_put(data_pkt_buf, line, line_len);
752
+ error = 0;
753
+ goto done;
754
+ }
755
+ else if (error < 0)
756
+ goto done;
736
757
 
737
758
  /* Advance in the buffer */
738
759
  line_len -= (line_end - line);
739
760
  line = line_end;
740
761
 
762
+ /* When a valid packet with no content has been
763
+ * read, git_pkt_parse_line does not report an
764
+ * error, but the pkt pointer has not been set.
765
+ * Handle this by skipping over empty packets.
766
+ */
767
+ if (pkt == NULL)
768
+ continue;
769
+
741
770
  error = add_push_report_pkt(push, pkt);
742
771
 
743
772
  git_pkt_free(pkt);
744
773
 
745
774
  if (error < 0 && error != GIT_ITEROVER)
746
- return error;
775
+ goto done;
747
776
  }
748
777
 
749
- return 0;
778
+ error = 0;
779
+
780
+ done:
781
+ if (reading_from_buf)
782
+ git_buf_consume(data_pkt_buf, line_end);
783
+ return error;
750
784
  }
751
785
 
752
786
  static int parse_report(transport_smart *transport, git_push *push)
@@ -755,6 +789,7 @@ static int parse_report(transport_smart *transport, git_push *push)
755
789
  const char *line_end = NULL;
756
790
  gitno_buffer *buf = &transport->buffer;
757
791
  int error, recvd;
792
+ git_buf data_pkt_buf = GIT_BUF_INIT;
758
793
 
759
794
  for (;;) {
760
795
  if (buf->offset > 0)
@@ -763,16 +798,21 @@ static int parse_report(transport_smart *transport, git_push *push)
763
798
  else
764
799
  error = GIT_EBUFS;
765
800
 
766
- if (error < 0 && error != GIT_EBUFS)
767
- return -1;
801
+ if (error < 0 && error != GIT_EBUFS) {
802
+ error = -1;
803
+ goto done;
804
+ }
768
805
 
769
806
  if (error == GIT_EBUFS) {
770
- if ((recvd = gitno_recv(buf)) < 0)
771
- return recvd;
807
+ if ((recvd = gitno_recv(buf)) < 0) {
808
+ error = recvd;
809
+ goto done;
810
+ }
772
811
 
773
812
  if (recvd == 0) {
774
813
  giterr_set(GITERR_NET, "early EOF");
775
- return GIT_EEOF;
814
+ error = GIT_EEOF;
815
+ goto done;
776
816
  }
777
817
  continue;
778
818
  }
@@ -781,10 +821,13 @@ static int parse_report(transport_smart *transport, git_push *push)
781
821
 
782
822
  error = 0;
783
823
 
824
+ if (pkt == NULL)
825
+ continue;
826
+
784
827
  switch (pkt->type) {
785
828
  case GIT_PKT_DATA:
786
829
  /* This is a sideband packet which contains other packets */
787
- error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
830
+ error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt, &data_pkt_buf);
788
831
  break;
789
832
  case GIT_PKT_ERR:
790
833
  giterr_set(GITERR_NET, "report-status: Error reported: %s",
@@ -805,12 +848,24 @@ static int parse_report(transport_smart *transport, git_push *push)
805
848
  git_pkt_free(pkt);
806
849
 
807
850
  /* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
808
- if (error == GIT_ITEROVER)
809
- return 0;
851
+ if (error == GIT_ITEROVER) {
852
+ error = 0;
853
+ if (data_pkt_buf.size > 0) {
854
+ /* If there was data remaining in the pack data buffer,
855
+ * then the server sent a partial pkt-line */
856
+ giterr_set(GITERR_NET, "Incomplete pack data pkt-line");
857
+ error = GIT_ERROR;
858
+ }
859
+ goto done;
860
+ }
810
861
 
811
- if (error < 0)
812
- return error;
862
+ if (error < 0) {
863
+ goto done;
864
+ }
813
865
  }
866
+ done:
867
+ git_buf_free(&data_pkt_buf);
868
+ return error;
814
869
  }
815
870
 
816
871
  static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)