rugged 0.24.0 → 0.24.5

Sign up to get free protection for your applications and to get access to all the features.
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)