rugged 0.21.0 → 0.21.1b0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/ext/rugged/extconf.rb +8 -8
  4. data/ext/rugged/rugged.h +1 -1
  5. data/ext/rugged/rugged_cred.c +23 -0
  6. data/ext/rugged/rugged_index.c +5 -1
  7. data/ext/rugged/rugged_remote.c +68 -0
  8. data/ext/rugged/rugged_repo.c +287 -5
  9. data/ext/rugged/rugged_tag_collection.c +70 -2
  10. data/ext/rugged/rugged_tree.c +29 -10
  11. data/lib/rugged.rb +1 -0
  12. data/lib/rugged/attributes.rb +41 -0
  13. data/lib/rugged/diff.rb +0 -1
  14. data/lib/rugged/diff/line.rb +1 -3
  15. data/lib/rugged/patch.rb +12 -2
  16. data/lib/rugged/version.rb +1 -1
  17. data/vendor/libgit2/CMakeLists.txt +11 -0
  18. data/vendor/libgit2/cmake/Modules/FindGSSAPI.cmake +324 -0
  19. data/vendor/libgit2/deps/http-parser/http_parser.h +2 -0
  20. data/vendor/libgit2/deps/zlib/adler32.c +39 -29
  21. data/vendor/libgit2/deps/zlib/crc32.c +33 -50
  22. data/vendor/libgit2/deps/zlib/crc32.h +1 -1
  23. data/vendor/libgit2/deps/zlib/deflate.c +198 -65
  24. data/vendor/libgit2/deps/zlib/deflate.h +8 -4
  25. data/vendor/libgit2/deps/zlib/infback.c +640 -0
  26. data/vendor/libgit2/deps/zlib/inffast.c +3 -3
  27. data/vendor/libgit2/deps/zlib/inffixed.h +3 -3
  28. data/vendor/libgit2/deps/zlib/inflate.c +84 -52
  29. data/vendor/libgit2/deps/zlib/inftrees.c +15 -39
  30. data/vendor/libgit2/deps/zlib/trees.c +18 -36
  31. data/vendor/libgit2/deps/zlib/zconf.h +4 -0
  32. data/vendor/libgit2/deps/zlib/zlib.h +250 -95
  33. data/vendor/libgit2/deps/zlib/zutil.c +13 -10
  34. data/vendor/libgit2/deps/zlib/zutil.h +41 -62
  35. data/vendor/libgit2/include/git2/attr.h +16 -13
  36. data/vendor/libgit2/include/git2/buffer.h +16 -0
  37. data/vendor/libgit2/include/git2/checkout.h +12 -12
  38. data/vendor/libgit2/include/git2/cherrypick.h +15 -15
  39. data/vendor/libgit2/include/git2/clone.h +77 -69
  40. data/vendor/libgit2/include/git2/diff.h +7 -0
  41. data/vendor/libgit2/include/git2/errors.h +1 -0
  42. data/vendor/libgit2/include/git2/merge.h +16 -0
  43. data/vendor/libgit2/include/git2/oid.h +8 -4
  44. data/vendor/libgit2/include/git2/oidarray.h +40 -0
  45. data/vendor/libgit2/include/git2/remote.h +5 -24
  46. data/vendor/libgit2/include/git2/repository.h +4 -1
  47. data/vendor/libgit2/include/git2/reset.h +4 -0
  48. data/vendor/libgit2/include/git2/status.h +17 -14
  49. data/vendor/libgit2/include/git2/submodule.h +18 -0
  50. data/vendor/libgit2/include/git2/sys/transport.h +354 -0
  51. data/vendor/libgit2/include/git2/transport.h +34 -327
  52. data/vendor/libgit2/include/git2/types.h +16 -6
  53. data/vendor/libgit2/src/array.h +1 -1
  54. data/vendor/libgit2/src/attr_file.c +14 -1
  55. data/vendor/libgit2/src/blame.c +0 -1
  56. data/vendor/libgit2/src/buffer.c +67 -10
  57. data/vendor/libgit2/src/buffer.h +4 -2
  58. data/vendor/libgit2/src/cache.c +9 -9
  59. data/vendor/libgit2/src/cache.h +1 -1
  60. data/vendor/libgit2/src/checkout.c +118 -23
  61. data/vendor/libgit2/src/cherrypick.c +41 -44
  62. data/vendor/libgit2/src/clone.c +94 -56
  63. data/vendor/libgit2/src/config_file.c +4 -4
  64. data/vendor/libgit2/src/diff.c +21 -0
  65. data/vendor/libgit2/src/diff_file.c +1 -0
  66. data/vendor/libgit2/src/diff_print.c +11 -9
  67. data/vendor/libgit2/src/diff_tform.c +3 -1
  68. data/vendor/libgit2/src/errors.c +9 -7
  69. data/vendor/libgit2/src/fileops.c +5 -3
  70. data/vendor/libgit2/src/global.c +9 -1
  71. data/vendor/libgit2/src/global.h +1 -0
  72. data/vendor/libgit2/src/graph.c +2 -2
  73. data/vendor/libgit2/src/indexer.c +6 -1
  74. data/vendor/libgit2/src/merge.c +98 -144
  75. data/vendor/libgit2/src/merge.h +1 -1
  76. data/vendor/libgit2/src/netops.c +4 -0
  77. data/vendor/libgit2/src/oid.c +8 -0
  78. data/vendor/libgit2/src/oid.h +11 -0
  79. data/vendor/libgit2/src/oidarray.c +21 -0
  80. data/vendor/libgit2/src/oidarray.h +18 -0
  81. data/vendor/libgit2/src/pack.c +1 -4
  82. data/vendor/libgit2/src/path.c +93 -33
  83. data/vendor/libgit2/src/path.h +21 -0
  84. data/vendor/libgit2/src/pool.c +1 -1
  85. data/vendor/libgit2/src/posix.h +46 -28
  86. data/vendor/libgit2/src/refs.h +2 -2
  87. data/vendor/libgit2/src/refspec.c +54 -18
  88. data/vendor/libgit2/src/remote.c +31 -8
  89. data/vendor/libgit2/src/remote.h +3 -0
  90. data/vendor/libgit2/src/repository.c +27 -11
  91. data/vendor/libgit2/src/revert.c +4 -6
  92. data/vendor/libgit2/src/revparse.c +15 -18
  93. data/vendor/libgit2/src/revwalk.c +0 -3
  94. data/vendor/libgit2/src/signature.c +2 -2
  95. data/vendor/libgit2/src/stash.c +2 -1
  96. data/vendor/libgit2/src/status.c +11 -2
  97. data/vendor/libgit2/src/strnlen.h +2 -1
  98. data/vendor/libgit2/src/submodule.c +73 -33
  99. data/vendor/libgit2/src/thread-utils.h +0 -7
  100. data/vendor/libgit2/src/trace.h +9 -1
  101. data/vendor/libgit2/src/transport.c +93 -90
  102. data/vendor/libgit2/src/transports/auth.c +71 -0
  103. data/vendor/libgit2/src/transports/auth.h +63 -0
  104. data/vendor/libgit2/src/transports/auth_negotiate.c +275 -0
  105. data/vendor/libgit2/src/transports/auth_negotiate.h +27 -0
  106. data/vendor/libgit2/src/transports/cred.c +58 -0
  107. data/vendor/libgit2/src/transports/cred.h +14 -0
  108. data/vendor/libgit2/src/transports/cred_helpers.c +3 -0
  109. data/vendor/libgit2/src/transports/git.c +1 -0
  110. data/vendor/libgit2/src/transports/http.c +168 -76
  111. data/vendor/libgit2/src/transports/smart.h +1 -0
  112. data/vendor/libgit2/src/transports/smart_protocol.c +4 -2
  113. data/vendor/libgit2/src/transports/ssh.c +214 -38
  114. data/vendor/libgit2/src/transports/winhttp.c +26 -6
  115. data/vendor/libgit2/src/unix/posix.h +23 -9
  116. data/vendor/libgit2/src/unix/realpath.c +8 -7
  117. data/vendor/libgit2/src/util.c +2 -1
  118. data/vendor/libgit2/src/util.h +3 -3
  119. data/vendor/libgit2/src/win32/mingw-compat.h +5 -12
  120. data/vendor/libgit2/src/win32/msvc-compat.h +3 -32
  121. data/vendor/libgit2/src/win32/posix.h +20 -31
  122. data/vendor/libgit2/src/win32/posix_w32.c +33 -4
  123. metadata +81 -69
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Copyright (C) the libgit2 contributors. All rights reserved.
3
+ *
4
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
5
+ * a Linking Exception. For full terms see the included COPYING file.
6
+ */
7
+ #ifndef INCLUDE_git_cred_h__
8
+ #define INCLUDE_git_cred_h__
9
+
10
+ #include "git2/transport.h"
11
+
12
+ const char *git_cred__username(git_cred *cred);
13
+
14
+ #endif
@@ -41,6 +41,9 @@ int git_cred_userpass(
41
41
  else
42
42
  return -1;
43
43
 
44
+ if (GIT_CREDTYPE_USERNAME & allowed_types)
45
+ return git_cred_username_new(cred, effective_username);
46
+
44
47
  if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 ||
45
48
  git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
46
49
  return -1;
@@ -8,6 +8,7 @@
8
8
  #include "git2.h"
9
9
  #include "buffer.h"
10
10
  #include "netops.h"
11
+ #include "git2/sys/transport.h"
11
12
 
12
13
  #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
13
14
 
@@ -11,6 +11,13 @@
11
11
  #include "buffer.h"
12
12
  #include "netops.h"
13
13
  #include "smart.h"
14
+ #include "auth.h"
15
+ #include "auth_negotiate.h"
16
+
17
+ git_http_auth_scheme auth_schemes[] = {
18
+ { GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
19
+ { GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
20
+ };
14
21
 
15
22
  static const char *upload_pack_service = "upload-pack";
16
23
  static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
@@ -20,7 +27,6 @@ static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive
20
27
  static const char *receive_pack_service_url = "/git-receive-pack";
21
28
  static const char *get_verb = "GET";
22
29
  static const char *post_verb = "POST";
23
- static const char *basic_authtype = "Basic";
24
30
 
25
31
  #define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
26
32
 
@@ -35,10 +41,6 @@ enum last_cb {
35
41
  VALUE
36
42
  };
37
43
 
38
- typedef enum {
39
- GIT_HTTP_AUTH_BASIC = 1,
40
- } http_authmechanism_t;
41
-
42
44
  typedef struct {
43
45
  git_smart_subtransport_stream parent;
44
46
  const char *service;
@@ -58,9 +60,6 @@ typedef struct {
58
60
  transport_smart *owner;
59
61
  gitno_socket socket;
60
62
  gitno_connection_data connection_data;
61
- git_cred *cred;
62
- git_cred *url_cred;
63
- http_authmechanism_t auth_mechanism;
64
63
  bool connected;
65
64
 
66
65
  /* Parser structures */
@@ -76,6 +75,11 @@ typedef struct {
76
75
  enum last_cb last_cb;
77
76
  int parse_error;
78
77
  unsigned parse_finished : 1;
78
+
79
+ /* Authentication */
80
+ git_cred *cred;
81
+ git_cred *url_cred;
82
+ git_vector auth_contexts;
79
83
  } http_subtransport;
80
84
 
81
85
  typedef struct {
@@ -88,28 +92,91 @@ typedef struct {
88
92
  size_t *bytes_read;
89
93
  } parser_context;
90
94
 
91
- static int apply_basic_credential(git_buf *buf, git_cred *cred)
95
+ static bool credtype_match(git_http_auth_scheme *scheme, void *data)
92
96
  {
93
- git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
94
- git_buf raw = GIT_BUF_INIT;
95
- int error = -1;
97
+ unsigned int credtype = *(unsigned int *)data;
96
98
 
97
- git_buf_printf(&raw, "%s:%s", c->username, c->password);
99
+ return !!(scheme->credtypes & credtype);
100
+ }
98
101
 
99
- if (git_buf_oom(&raw) ||
100
- git_buf_puts(buf, "Authorization: Basic ") < 0 ||
101
- git_buf_put_base64(buf, git_buf_cstr(&raw), raw.size) < 0 ||
102
- git_buf_puts(buf, "\r\n") < 0)
103
- goto on_error;
102
+ static bool challenge_match(git_http_auth_scheme *scheme, void *data)
103
+ {
104
+ const char *scheme_name = scheme->name;
105
+ const char *challenge = (const char *)data;
106
+ size_t scheme_len;
104
107
 
105
- error = 0;
108
+ scheme_len = strlen(scheme_name);
109
+ return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
110
+ (challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
111
+ }
106
112
 
107
- on_error:
108
- if (raw.size)
109
- memset(raw.ptr, 0x0, raw.size);
113
+ static int auth_context_match(
114
+ git_http_auth_context **out,
115
+ http_subtransport *t,
116
+ bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
117
+ void *data)
118
+ {
119
+ git_http_auth_scheme *scheme = NULL;
120
+ git_http_auth_context *context = NULL, *c;
121
+ size_t i;
122
+
123
+ *out = NULL;
124
+
125
+ for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
126
+ if (scheme_match(&auth_schemes[i], data)) {
127
+ scheme = &auth_schemes[i];
128
+ break;
129
+ }
130
+ }
131
+
132
+ if (!scheme)
133
+ return 0;
134
+
135
+ /* See if authentication has already started for this scheme */
136
+ git_vector_foreach(&t->auth_contexts, i, c) {
137
+ if (c->type == scheme->type) {
138
+ context = c;
139
+ break;
140
+ }
141
+ }
142
+
143
+ if (!context) {
144
+ if (scheme->init_context(&context, &t->connection_data) < 0)
145
+ return -1;
146
+ else if (!context)
147
+ return 0;
148
+ else if (git_vector_insert(&t->auth_contexts, context) < 0)
149
+ return -1;
150
+ }
151
+
152
+ *out = context;
153
+
154
+ return 0;
155
+ }
156
+
157
+ static int apply_credentials(git_buf *buf, http_subtransport *t)
158
+ {
159
+ git_cred *cred = t->cred;
160
+ git_http_auth_context *context;
161
+
162
+ /* Apply the credentials given to us in the URL */
163
+ if (!cred && t->connection_data.user && t->connection_data.pass) {
164
+ if (!t->url_cred &&
165
+ git_cred_userpass_plaintext_new(&t->url_cred,
166
+ t->connection_data.user, t->connection_data.pass) < 0)
167
+ return -1;
168
+
169
+ cred = t->url_cred;
170
+ }
171
+
172
+ if (!cred)
173
+ return 0;
110
174
 
111
- git_buf_free(&raw);
112
- return error;
175
+ /* Get or create a context for the best scheme for this cred type */
176
+ if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
177
+ return -1;
178
+
179
+ return context->next_token(buf, context, cred);
113
180
  }
114
181
 
115
182
  static int gen_request(
@@ -137,19 +204,9 @@ static int gen_request(
137
204
  git_buf_puts(buf, "Accept: */*\r\n");
138
205
 
139
206
  /* Apply credentials to the request */
140
- if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
141
- t->auth_mechanism == GIT_HTTP_AUTH_BASIC &&
142
- apply_basic_credential(buf, t->cred) < 0)
207
+ if (apply_credentials(buf, t) < 0)
143
208
  return -1;
144
209
 
145
- /* Use url-parsed basic auth if username and password are both provided */
146
- if (!t->cred && t->connection_data.user && t->connection_data.pass) {
147
- if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred,
148
- t->connection_data.user, t->connection_data.pass) < 0)
149
- return -1;
150
- if (apply_basic_credential(buf, t->url_cred) < 0) return -1;
151
- }
152
-
153
210
  git_buf_puts(buf, "\r\n");
154
211
 
155
212
  if (git_buf_oom(buf))
@@ -158,20 +215,26 @@ static int gen_request(
158
215
  return 0;
159
216
  }
160
217
 
161
- static int parse_unauthorized_response(
218
+ static int parse_authenticate_response(
162
219
  git_vector *www_authenticate,
163
- int *allowed_types,
164
- http_authmechanism_t *auth_mechanism)
220
+ http_subtransport *t,
221
+ int *allowed_types)
165
222
  {
166
- unsigned i;
167
- char *entry;
168
-
169
- git_vector_foreach(www_authenticate, i, entry) {
170
- if (!strncmp(entry, basic_authtype, 5) &&
171
- (entry[5] == '\0' || entry[5] == ' ')) {
172
- *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT;
173
- *auth_mechanism = GIT_HTTP_AUTH_BASIC;
174
- }
223
+ git_http_auth_context *context;
224
+ char *challenge;
225
+ size_t i;
226
+
227
+ git_vector_foreach(www_authenticate, i, challenge) {
228
+ if (auth_context_match(&context, t, challenge_match, challenge) < 0)
229
+ return -1;
230
+ else if (!context)
231
+ continue;
232
+
233
+ if (context->set_challenge &&
234
+ context->set_challenge(context, challenge) < 0)
235
+ return -1;
236
+
237
+ *allowed_types |= context->credtypes;
175
238
  }
176
239
 
177
240
  return 0;
@@ -248,7 +311,7 @@ static int on_headers_complete(http_parser *parser)
248
311
  http_subtransport *t = ctx->t;
249
312
  http_stream *s = ctx->s;
250
313
  git_buf buf = GIT_BUF_INIT;
251
- int error = 0, no_callback = 0;
314
+ int error = 0, no_callback = 0, allowed_auth_types = 0;
252
315
 
253
316
  /* Both parse_header_name and parse_header_value are populated
254
317
  * and ready for consumption. */
@@ -256,26 +319,26 @@ static int on_headers_complete(http_parser *parser)
256
319
  if (on_header_ready(t) < 0)
257
320
  return t->parse_error = PARSE_ERROR_GENERIC;
258
321
 
259
- /* Check for an authentication failure. */
322
+ /* Capture authentication headers which may be a 401 (authentication
323
+ * is not complete) or a 200 (simply informing us that auth *is*
324
+ * complete.)
325
+ */
326
+ if (parse_authenticate_response(&t->www_authenticate, t,
327
+ &allowed_auth_types) < 0)
328
+ return t->parse_error = PARSE_ERROR_GENERIC;
260
329
 
261
- if (parser->status_code == 401 &&
262
- get_verb == s->verb) {
330
+ /* Check for an authentication failure. */
331
+ if (parser->status_code == 401 && get_verb == s->verb) {
263
332
  if (!t->owner->cred_acquire_cb) {
264
333
  no_callback = 1;
265
334
  } else {
266
- int allowed_types = 0;
267
-
268
- if (parse_unauthorized_response(&t->www_authenticate,
269
- &allowed_types, &t->auth_mechanism) < 0)
270
- return t->parse_error = PARSE_ERROR_GENERIC;
271
-
272
- if (allowed_types &&
273
- (!t->cred || 0 == (t->cred->credtype & allowed_types))) {
335
+ if (allowed_auth_types &&
336
+ (!t->cred || 0 == (t->cred->credtype & allowed_auth_types))) {
274
337
 
275
338
  error = t->owner->cred_acquire_cb(&t->cred,
276
339
  t->owner->url,
277
340
  t->connection_data.user,
278
- allowed_types,
341
+ allowed_auth_types,
279
342
  t->owner->cred_acquire_payload);
280
343
 
281
344
  if (error == GIT_PASSTHROUGH) {
@@ -286,7 +349,8 @@ static int on_headers_complete(http_parser *parser)
286
349
  assert(t->cred);
287
350
 
288
351
  /* Successfully acquired a credential. */
289
- return t->parse_error = PARSE_ERROR_REPLAY;
352
+ t->parse_error = PARSE_ERROR_REPLAY;
353
+ return 0;
290
354
  }
291
355
  }
292
356
  }
@@ -324,7 +388,8 @@ static int on_headers_complete(http_parser *parser)
324
388
  t->connected = 0;
325
389
  s->redirect_count++;
326
390
 
327
- return t->parse_error = PARSE_ERROR_REPLAY;
391
+ t->parse_error = PARSE_ERROR_REPLAY;
392
+ return 0;
328
393
  }
329
394
 
330
395
  /* Check for a 200 HTTP status code. */
@@ -382,6 +447,13 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
382
447
  parser_context *ctx = (parser_context *) parser->data;
383
448
  http_subtransport *t = ctx->t;
384
449
 
450
+ /* If our goal is to replay the request (either an auth failure or
451
+ * a redirect) then don't bother buffering since we're ignoring the
452
+ * content anyway.
453
+ */
454
+ if (t->parse_error == PARSE_ERROR_REPLAY)
455
+ return 0;
456
+
385
457
  if (ctx->buf_size < len) {
386
458
  giterr_set(GITERR_NET, "Can't fit data in the buffer");
387
459
  return t->parse_error = PARSE_ERROR_GENERIC;
@@ -456,7 +528,7 @@ static int http_connect(http_subtransport *t)
456
528
 
457
529
  if (t->connected &&
458
530
  http_should_keep_alive(&t->parser) &&
459
- http_body_is_final(&t->parser))
531
+ t->parse_finished)
460
532
  return 0;
461
533
 
462
534
  if (t->socket.socket)
@@ -502,10 +574,8 @@ replay:
502
574
 
503
575
  clear_parser_state(t);
504
576
 
505
- if (gen_request(&request, s, 0) < 0) {
506
- giterr_set(GITERR_NET, "Failed to generate request");
577
+ if (gen_request(&request, s, 0) < 0)
507
578
  return -1;
508
- }
509
579
 
510
580
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
511
581
  git_buf_free(&request);
@@ -537,7 +607,23 @@ replay:
537
607
  }
538
608
 
539
609
  while (!*bytes_read && !t->parse_finished) {
540
- t->parse_buffer.offset = 0;
610
+ size_t data_offset;
611
+
612
+ /*
613
+ * Make the parse_buffer think it's as full of data as
614
+ * the buffer, so it won't try to recv more data than
615
+ * we can put into it.
616
+ *
617
+ * data_offset is the actual data offset from which we
618
+ * should tell the parser to start reading.
619
+ */
620
+ if (buf_size >= t->parse_buffer.len) {
621
+ t->parse_buffer.offset = 0;
622
+ } else {
623
+ t->parse_buffer.offset = t->parse_buffer.len - buf_size;
624
+ }
625
+
626
+ data_offset = t->parse_buffer.offset;
541
627
 
542
628
  if (gitno_recv(&t->parse_buffer) < 0)
543
629
  return -1;
@@ -558,8 +644,8 @@ replay:
558
644
 
559
645
  bytes_parsed = http_parser_execute(&t->parser,
560
646
  &t->settings,
561
- t->parse_buffer.data,
562
- t->parse_buffer.offset);
647
+ t->parse_buffer.data + data_offset,
648
+ t->parse_buffer.offset - data_offset);
563
649
 
564
650
  t->parser.data = NULL;
565
651
 
@@ -577,7 +663,7 @@ replay:
577
663
  if (t->parse_error < 0)
578
664
  return -1;
579
665
 
580
- if (bytes_parsed != t->parse_buffer.offset) {
666
+ if (bytes_parsed != t->parse_buffer.offset - data_offset) {
581
667
  giterr_set(GITERR_NET,
582
668
  "HTTP parser error: %s",
583
669
  http_errno_description((enum http_errno)t->parser.http_errno));
@@ -604,10 +690,8 @@ static int http_stream_write_chunked(
604
690
 
605
691
  clear_parser_state(t);
606
692
 
607
- if (gen_request(&request, s, 0) < 0) {
608
- giterr_set(GITERR_NET, "Failed to generate request");
693
+ if (gen_request(&request, s, 0) < 0)
609
694
  return -1;
610
- }
611
695
 
612
696
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
613
697
  git_buf_free(&request);
@@ -679,10 +763,8 @@ static int http_stream_write_single(
679
763
 
680
764
  clear_parser_state(t);
681
765
 
682
- if (gen_request(&request, s, len) < 0) {
683
- giterr_set(GITERR_NET, "Failed to generate request");
766
+ if (gen_request(&request, s, len) < 0)
684
767
  return -1;
685
- }
686
768
 
687
769
  if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0)
688
770
  goto on_error;
@@ -849,6 +931,8 @@ static int http_action(
849
931
  static int http_close(git_smart_subtransport *subtransport)
850
932
  {
851
933
  http_subtransport *t = (http_subtransport *) subtransport;
934
+ git_http_auth_context *context;
935
+ size_t i;
852
936
 
853
937
  clear_parser_state(t);
854
938
 
@@ -867,6 +951,13 @@ static int http_close(git_smart_subtransport *subtransport)
867
951
  t->url_cred = NULL;
868
952
  }
869
953
 
954
+ git_vector_foreach(&t->auth_contexts, i, context) {
955
+ if (context->free)
956
+ context->free(context);
957
+ }
958
+
959
+ git_vector_clear(&t->auth_contexts);
960
+
870
961
  gitno_connection_data_free_ptrs(&t->connection_data);
871
962
 
872
963
  return 0;
@@ -878,6 +969,7 @@ static void http_free(git_smart_subtransport *subtransport)
878
969
 
879
970
  http_close(subtransport);
880
971
 
972
+ git_vector_free(&t->auth_contexts);
881
973
  git__free(t);
882
974
  }
883
975