rugged 0.24.6.1 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/ext/rugged/extconf.rb +9 -2
  4. data/ext/rugged/rugged.c +85 -21
  5. data/ext/rugged/rugged.h +7 -21
  6. data/ext/rugged/rugged_backend.c +3 -20
  7. data/ext/rugged/rugged_blame.c +7 -24
  8. data/ext/rugged/rugged_blob.c +136 -59
  9. data/ext/rugged/rugged_branch.c +3 -20
  10. data/ext/rugged/rugged_branch_collection.c +3 -20
  11. data/ext/rugged/rugged_commit.c +251 -101
  12. data/ext/rugged/rugged_config.c +3 -20
  13. data/ext/rugged/rugged_cred.c +3 -20
  14. data/ext/rugged/rugged_diff.c +3 -20
  15. data/ext/rugged/rugged_diff_delta.c +3 -20
  16. data/ext/rugged/rugged_diff_hunk.c +3 -20
  17. data/ext/rugged/rugged_diff_line.c +3 -20
  18. data/ext/rugged/rugged_index.c +46 -229
  19. data/ext/rugged/rugged_note.c +3 -20
  20. data/ext/rugged/rugged_object.c +3 -20
  21. data/ext/rugged/rugged_patch.c +192 -34
  22. data/ext/rugged/rugged_rebase.c +90 -48
  23. data/ext/rugged/rugged_reference.c +4 -21
  24. data/ext/rugged/rugged_reference_collection.c +3 -20
  25. data/ext/rugged/rugged_remote.c +70 -42
  26. data/ext/rugged/rugged_remote_collection.c +3 -20
  27. data/ext/rugged/rugged_repo.c +50 -59
  28. data/ext/rugged/rugged_revwalk.c +4 -21
  29. data/ext/rugged/rugged_settings.c +3 -20
  30. data/ext/rugged/rugged_signature.c +3 -20
  31. data/ext/rugged/rugged_submodule.c +4 -21
  32. data/ext/rugged/rugged_submodule_collection.c +3 -20
  33. data/ext/rugged/rugged_tag.c +3 -20
  34. data/ext/rugged/rugged_tag_collection.c +3 -20
  35. data/ext/rugged/rugged_tree.c +189 -184
  36. data/lib/rugged/attributes.rb +5 -0
  37. data/lib/rugged/blob.rb +5 -0
  38. data/lib/rugged/branch.rb +6 -1
  39. data/lib/rugged/commit.rb +5 -0
  40. data/lib/rugged/console.rb +5 -0
  41. data/lib/rugged/credentials.rb +5 -0
  42. data/lib/rugged/diff/delta.rb +5 -0
  43. data/lib/rugged/diff/hunk.rb +5 -0
  44. data/lib/rugged/diff/line.rb +5 -0
  45. data/lib/rugged/diff.rb +5 -0
  46. data/lib/rugged/index.rb +120 -0
  47. data/lib/rugged/object.rb +5 -0
  48. data/lib/rugged/patch.rb +5 -0
  49. data/lib/rugged/reference.rb +5 -0
  50. data/lib/rugged/remote.rb +5 -0
  51. data/lib/rugged/repository.rb +9 -4
  52. data/lib/rugged/submodule_collection.rb +5 -0
  53. data/lib/rugged/tag.rb +5 -0
  54. data/lib/rugged/tree.rb +156 -1
  55. data/lib/rugged/version.rb +6 -1
  56. data/lib/rugged/walker.rb +5 -0
  57. data/lib/rugged.rb +5 -0
  58. data/vendor/libgit2/CMakeLists.txt +12 -2
  59. data/vendor/libgit2/include/git2/blob.h +39 -28
  60. data/vendor/libgit2/include/git2/commit.h +76 -0
  61. data/vendor/libgit2/include/git2/common.h +21 -1
  62. data/vendor/libgit2/include/git2/describe.h +5 -2
  63. data/vendor/libgit2/include/git2/diff.h +62 -7
  64. data/vendor/libgit2/include/git2/errors.h +2 -1
  65. data/vendor/libgit2/include/git2/index.h +25 -0
  66. data/vendor/libgit2/include/git2/merge.h +10 -1
  67. data/vendor/libgit2/include/git2/odb.h +47 -1
  68. data/vendor/libgit2/include/git2/pack.h +4 -4
  69. data/vendor/libgit2/include/git2/patch.h +1 -1
  70. data/vendor/libgit2/include/git2/proxy.h +92 -0
  71. data/vendor/libgit2/include/git2/refs.h +11 -0
  72. data/vendor/libgit2/include/git2/remote.h +21 -8
  73. data/vendor/libgit2/include/git2/repository.h +20 -1
  74. data/vendor/libgit2/include/git2/revwalk.h +4 -6
  75. data/vendor/libgit2/include/git2/signature.h +13 -0
  76. data/vendor/libgit2/include/git2/submodule.h +11 -3
  77. data/vendor/libgit2/include/git2/sys/merge.h +177 -0
  78. data/vendor/libgit2/include/git2/sys/odb_backend.h +11 -0
  79. data/vendor/libgit2/include/git2/sys/remote.h +16 -0
  80. data/vendor/libgit2/include/git2/sys/stream.h +2 -1
  81. data/vendor/libgit2/include/git2/sys/time.h +31 -0
  82. data/vendor/libgit2/include/git2/sys/transport.h +3 -1
  83. data/vendor/libgit2/include/git2/tag.h +9 -0
  84. data/vendor/libgit2/include/git2/transaction.h +9 -0
  85. data/vendor/libgit2/include/git2/tree.h +55 -0
  86. data/vendor/libgit2/include/git2/version.h +4 -4
  87. data/vendor/libgit2/include/git2.h +1 -0
  88. data/vendor/libgit2/src/annotated_commit.c +99 -80
  89. data/vendor/libgit2/src/annotated_commit.h +5 -2
  90. data/vendor/libgit2/src/apply.c +377 -0
  91. data/vendor/libgit2/src/apply.h +21 -0
  92. data/vendor/libgit2/src/array.h +0 -1
  93. data/vendor/libgit2/src/blob.c +71 -39
  94. data/vendor/libgit2/src/branch.c +7 -5
  95. data/vendor/libgit2/src/buffer.c +252 -20
  96. data/vendor/libgit2/src/buffer.h +8 -0
  97. data/vendor/libgit2/src/checkout.c +69 -42
  98. data/vendor/libgit2/src/clone.c +0 -8
  99. data/vendor/libgit2/src/commit.c +193 -49
  100. data/vendor/libgit2/src/commit_list.c +8 -3
  101. data/vendor/libgit2/src/commit_list.h +1 -0
  102. data/vendor/libgit2/src/common.h +2 -1
  103. data/vendor/libgit2/src/config.c +3 -3
  104. data/vendor/libgit2/src/config_file.c +20 -10
  105. data/vendor/libgit2/src/crlf.c +1 -0
  106. data/vendor/libgit2/src/curl_stream.c +106 -6
  107. data/vendor/libgit2/src/delta.c +238 -62
  108. data/vendor/libgit2/src/delta.h +79 -58
  109. data/vendor/libgit2/src/describe.c +1 -1
  110. data/vendor/libgit2/src/diff.c +32 -1554
  111. data/vendor/libgit2/src/diff.h +14 -122
  112. data/vendor/libgit2/src/diff_driver.c +4 -6
  113. data/vendor/libgit2/src/diff_file.c +3 -0
  114. data/vendor/libgit2/src/diff_generate.c +1613 -0
  115. data/vendor/libgit2/src/diff_generate.h +123 -0
  116. data/vendor/libgit2/src/diff_parse.c +101 -0
  117. data/vendor/libgit2/src/diff_parse.h +18 -0
  118. data/vendor/libgit2/src/diff_print.c +263 -144
  119. data/vendor/libgit2/src/diff_stats.c +21 -12
  120. data/vendor/libgit2/src/diff_tform.c +1 -0
  121. data/vendor/libgit2/src/diff_tform.h +22 -0
  122. data/vendor/libgit2/src/diff_xdiff.c +9 -9
  123. data/vendor/libgit2/src/diff_xdiff.h +5 -5
  124. data/vendor/libgit2/src/fetchhead.c +8 -8
  125. data/vendor/libgit2/src/filebuf.c +6 -1
  126. data/vendor/libgit2/src/filebuf.h +1 -0
  127. data/vendor/libgit2/src/fileops.c +22 -1
  128. data/vendor/libgit2/src/fileops.h +8 -2
  129. data/vendor/libgit2/src/fnmatch.c +18 -5
  130. data/vendor/libgit2/src/global.c +21 -4
  131. data/vendor/libgit2/src/global.h +6 -0
  132. data/vendor/libgit2/src/graph.c +1 -1
  133. data/vendor/libgit2/src/index.c +159 -46
  134. data/vendor/libgit2/src/index.h +2 -0
  135. data/vendor/libgit2/src/iterator.c +1573 -1468
  136. data/vendor/libgit2/src/iterator.h +52 -69
  137. data/vendor/libgit2/src/merge.c +163 -64
  138. data/vendor/libgit2/src/merge.h +61 -2
  139. data/vendor/libgit2/src/merge_driver.c +397 -0
  140. data/vendor/libgit2/src/merge_driver.h +60 -0
  141. data/vendor/libgit2/src/merge_file.c +11 -49
  142. data/vendor/libgit2/src/netops.c +12 -10
  143. data/vendor/libgit2/src/object_api.c +19 -1
  144. data/vendor/libgit2/src/odb.c +228 -52
  145. data/vendor/libgit2/src/odb_loose.c +19 -1
  146. data/vendor/libgit2/src/odb_mempack.c +1 -1
  147. data/vendor/libgit2/src/odb_pack.c +27 -1
  148. data/vendor/libgit2/src/openssl_stream.c +4 -5
  149. data/vendor/libgit2/src/pack-objects.c +105 -76
  150. data/vendor/libgit2/src/pack-objects.h +13 -12
  151. data/vendor/libgit2/src/pack.c +16 -10
  152. data/vendor/libgit2/src/pack.h +2 -0
  153. data/vendor/libgit2/src/patch.c +216 -0
  154. data/vendor/libgit2/src/patch.h +66 -0
  155. data/vendor/libgit2/src/{diff_patch.c → patch_generate.c} +203 -376
  156. data/vendor/libgit2/src/patch_generate.h +68 -0
  157. data/vendor/libgit2/src/patch_parse.c +1159 -0
  158. data/vendor/libgit2/src/patch_parse.h +56 -0
  159. data/vendor/libgit2/src/path.c +38 -2
  160. data/vendor/libgit2/src/path.h +18 -0
  161. data/vendor/libgit2/src/pathspec.c +1 -1
  162. data/vendor/libgit2/src/pool.h +5 -0
  163. data/vendor/libgit2/src/pqueue.c +12 -5
  164. data/vendor/libgit2/src/pqueue.h +1 -0
  165. data/vendor/libgit2/src/proxy.c +32 -0
  166. data/vendor/libgit2/src/proxy.h +14 -0
  167. data/vendor/libgit2/src/push.c +1 -1
  168. data/vendor/libgit2/src/rebase.c +63 -36
  169. data/vendor/libgit2/src/refdb.c +4 -2
  170. data/vendor/libgit2/src/refdb_fs.c +82 -54
  171. data/vendor/libgit2/src/refs.c +13 -1
  172. data/vendor/libgit2/src/remote.c +20 -81
  173. data/vendor/libgit2/src/repository.c +212 -29
  174. data/vendor/libgit2/src/reset.c +1 -1
  175. data/vendor/libgit2/src/revparse.c +1 -1
  176. data/vendor/libgit2/src/revwalk.c +260 -184
  177. data/vendor/libgit2/src/settings.c +11 -3
  178. data/vendor/libgit2/src/signature.c +27 -2
  179. data/vendor/libgit2/src/sortedcache.c +14 -5
  180. data/vendor/libgit2/src/stash.c +1 -0
  181. data/vendor/libgit2/src/status.c +1 -0
  182. data/vendor/libgit2/src/stransport_stream.c +4 -2
  183. data/vendor/libgit2/src/stream.h +2 -2
  184. data/vendor/libgit2/src/submodule.c +16 -4
  185. data/vendor/libgit2/src/sysdir.c +1 -1
  186. data/vendor/libgit2/src/transport.c +3 -5
  187. data/vendor/libgit2/src/transports/http.c +38 -13
  188. data/vendor/libgit2/src/transports/local.c +4 -1
  189. data/vendor/libgit2/src/transports/smart.c +6 -0
  190. data/vendor/libgit2/src/transports/smart.h +1 -0
  191. data/vendor/libgit2/src/transports/smart_pkt.c +5 -13
  192. data/vendor/libgit2/src/transports/smart_protocol.c +22 -7
  193. data/vendor/libgit2/src/transports/winhttp.c +144 -11
  194. data/vendor/libgit2/src/tree.c +267 -2
  195. data/vendor/libgit2/src/unix/posix.h +10 -0
  196. data/vendor/libgit2/src/unix/pthread.h +2 -0
  197. data/vendor/libgit2/src/util.c +25 -2
  198. data/vendor/libgit2/src/util.h +10 -0
  199. data/vendor/libgit2/src/varint.c +44 -0
  200. data/vendor/libgit2/src/varint.h +15 -0
  201. data/vendor/libgit2/src/vector.c +58 -0
  202. data/vendor/libgit2/src/vector.h +8 -0
  203. data/vendor/libgit2/src/win32/posix.h +3 -0
  204. data/vendor/libgit2/src/win32/thread.c +18 -0
  205. data/vendor/libgit2/src/win32/thread.h +2 -0
  206. data/vendor/libgit2/src/win32/w32_util.h +1 -1
  207. data/vendor/libgit2/src/zstream.c +37 -8
  208. data/vendor/libgit2/src/zstream.h +8 -1
  209. metadata +100 -82
  210. data/vendor/libgit2/Makefile.embed +0 -60
  211. data/vendor/libgit2/src/delta-apply.c +0 -166
  212. data/vendor/libgit2/src/delta-apply.h +0 -62
  213. data/vendor/libgit2/src/diff_patch.h +0 -83
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "git2/diff.h"
21
21
  #include "diff.h"
22
+ #include "diff_generate.h"
22
23
 
23
24
  static unsigned int index_delta2status(const git_diff_delta *head2idx)
24
25
  {
@@ -120,11 +120,13 @@ static int stransport_certificate(git_cert **out, git_stream *stream)
120
120
  return 0;
121
121
  }
122
122
 
123
- static int stransport_set_proxy(git_stream *stream, const char *proxy)
123
+ static int stransport_set_proxy(
124
+ git_stream *stream,
125
+ const git_proxy_options *proxy_opts)
124
126
  {
125
127
  stransport_stream *st = (stransport_stream *) stream;
126
128
 
127
- return git_stream_set_proxy(st->io, proxy);
129
+ return git_stream_set_proxy(st->io, proxy_opts);
128
130
  }
129
131
 
130
132
  /*
@@ -35,14 +35,14 @@ GIT_INLINE(int) git_stream_supports_proxy(git_stream *st)
35
35
  return st->proxy_support;
36
36
  }
37
37
 
38
- GIT_INLINE(int) git_stream_set_proxy(git_stream *st, const char *proxy_url)
38
+ GIT_INLINE(int) git_stream_set_proxy(git_stream *st, const git_proxy_options *proxy_opts)
39
39
  {
40
40
  if (!st->proxy_support) {
41
41
  giterr_set(GITERR_INVALID, "proxy not supported on this stream");
42
42
  return -1;
43
43
  }
44
44
 
45
- return st->set_proxy(st, proxy_url);
45
+ return st->set_proxy(st, proxy_opts);
46
46
  }
47
47
 
48
48
  GIT_INLINE(ssize_t) git_stream_read(git_stream *st, void *data, size_t len)
@@ -93,6 +93,7 @@ static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
93
93
  static git_config *gitmodules_snapshot(git_repository *repo);
94
94
  static int get_url_base(git_buf *url, git_repository *repo);
95
95
  static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
96
+ static int lookup_default_remote(git_remote **remote, git_repository *repo);
96
97
  static int submodule_load_each(const git_config_entry *entry, void *payload);
97
98
  static int submodule_read_config(git_submodule *sm, git_config *cfg);
98
99
  static int submodule_load_from_wd_lite(git_submodule *);
@@ -1131,7 +1132,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
1131
1132
  if (error != GIT_ENOTFOUND)
1132
1133
  goto done;
1133
1134
 
1134
- if (error == GIT_ENOTFOUND && !init) {
1135
+ if (!init) {
1135
1136
  giterr_set(GITERR_SUBMODULE, "Submodule is not initialized.");
1136
1137
  error = GIT_ERROR;
1137
1138
  goto done;
@@ -1171,9 +1172,20 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio
1171
1172
  * update the workdir contents of the subrepository, and set the subrepository's
1172
1173
  * head to the new commit.
1173
1174
  */
1174
- if ((error = git_submodule_open(&sub_repo, sm)) < 0 ||
1175
- (error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0 ||
1176
- (error = git_checkout_tree(sub_repo, target_commit, &update_options.checkout_opts)) != 0 ||
1175
+ if ((error = git_submodule_open(&sub_repo, sm)) < 0)
1176
+ goto done;
1177
+
1178
+ /* Look up the target commit in the submodule. */
1179
+ if ((error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0) {
1180
+ /* If it isn't found then fetch and try again. */
1181
+ if (error != GIT_ENOTFOUND || !update_options.allow_fetch ||
1182
+ (error = lookup_default_remote(&remote, sub_repo)) < 0 ||
1183
+ (error = git_remote_fetch(remote, NULL, &update_options.fetch_opts, NULL)) < 0 ||
1184
+ (error = git_object_lookup(&target_commit, sub_repo, git_submodule_index_id(sm), GIT_OBJ_COMMIT)) < 0)
1185
+ goto done;
1186
+ }
1187
+
1188
+ if ((error = git_checkout_tree(sub_repo, target_commit, &update_options.checkout_opts)) != 0 ||
1177
1189
  (error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0)
1178
1190
  goto done;
1179
1191
 
@@ -171,7 +171,7 @@ int git_sysdir_set(git_sysdir_t which, const char *search_path)
171
171
  expand_path = strstr(search_path, PATH_MAGIC);
172
172
 
173
173
  /* reset the default if this path has been cleared */
174
- if (!search_path || expand_path)
174
+ if (!search_path)
175
175
  git_sysdir__dirs[which].guess(&git_sysdir__dirs[which].buf);
176
176
 
177
177
  /* if $PATH is not referenced, then just set the path */
@@ -29,9 +29,7 @@ static transport_definition local_transport_definition = { "file://", git_transp
29
29
  static transport_definition transports[] = {
30
30
  { "git://", git_transport_smart, &git_subtransport_definition },
31
31
  { "http://", git_transport_smart, &http_subtransport_definition },
32
- #if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
33
32
  { "https://", git_transport_smart, &http_subtransport_definition },
34
- #endif
35
33
  { "file://", git_transport_local, NULL },
36
34
  #ifdef GIT_SSH
37
35
  { "ssh://", git_transport_smart, &ssh_subtransport_definition },
@@ -89,10 +87,10 @@ static int transport_find_fn(
89
87
  /* For other systems, perform the SSH check first, to avoid going to the
90
88
  * filesystem if it is not necessary */
91
89
 
92
- /* It could be a SSH remote path. Check to see if there's a :
93
- * SSH is an unsupported transport mechanism in this version of libgit2 */
90
+ /* It could be a SSH remote path. Check to see if there's a : */
94
91
  if (!definition && strrchr(url, ':')) {
95
- // re-search transports again with ssh:// as url so that we can find a third party ssh transport
92
+ /* re-search transports again with ssh:// as url
93
+ * so that we can find a third party ssh transport */
96
94
  definition = transport_find_by_url("ssh://");
97
95
  }
98
96
 
@@ -208,7 +208,7 @@ static int gen_request(
208
208
 
209
209
  git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
210
210
 
211
- git_buf_printf(buf, "User-Agent: git/1.0 (%s)\r\n", user_agent());
211
+ git_buf_printf(buf, "User-Agent: git/2.0 (%s)\r\n", user_agent());
212
212
  git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host);
213
213
 
214
214
  if (s->chunked || content_length > 0) {
@@ -555,10 +555,40 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
555
555
  return 0;
556
556
  }
557
557
 
558
+ static int apply_proxy_config(http_subtransport *t)
559
+ {
560
+ int error;
561
+ git_proxy_t proxy_type;
562
+
563
+ if (!git_stream_supports_proxy(t->io))
564
+ return 0;
565
+
566
+ proxy_type = t->owner->proxy.type;
567
+
568
+ if (proxy_type == GIT_PROXY_NONE)
569
+ return 0;
570
+
571
+ if (proxy_type == GIT_PROXY_AUTO) {
572
+ char *url;
573
+ git_proxy_options opts = GIT_PROXY_OPTIONS_INIT;
574
+
575
+ if ((error = git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &url)) < 0)
576
+ return error;
577
+
578
+ opts.type = GIT_PROXY_SPECIFIED;
579
+ opts.url = url;
580
+ error = git_stream_set_proxy(t->io, &opts);
581
+ git__free(url);
582
+
583
+ return error;
584
+ }
585
+
586
+ return git_stream_set_proxy(t->io, &t->owner->proxy);
587
+ }
588
+
558
589
  static int http_connect(http_subtransport *t)
559
590
  {
560
591
  int error;
561
- char *proxy_url;
562
592
 
563
593
  if (t->connected &&
564
594
  http_should_keep_alive(&t->parser) &&
@@ -587,27 +617,20 @@ static int http_connect(http_subtransport *t)
587
617
 
588
618
  GITERR_CHECK_VERSION(t->io, GIT_STREAM_VERSION, "git_stream");
589
619
 
590
- if (git_stream_supports_proxy(t->io) &&
591
- !git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url)) {
592
- error = git_stream_set_proxy(t->io, proxy_url);
593
- git__free(proxy_url);
594
-
595
- if (error < 0)
596
- return error;
597
- }
620
+ apply_proxy_config(t);
598
621
 
599
622
  error = git_stream_connect(t->io);
600
623
 
601
- #if defined(GIT_OPENSSL) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_CURL)
602
624
  if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
603
625
  git_stream_is_encrypted(t->io)) {
604
626
  git_cert *cert;
605
- int is_valid = (error == GIT_OK);
627
+ int is_valid;
606
628
 
607
629
  if ((error = git_stream_certificate(&cert, t->io)) < 0)
608
630
  return error;
609
631
 
610
632
  giterr_clear();
633
+ is_valid = error != GIT_ECERTIFICATE;
611
634
  error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
612
635
 
613
636
  if (error < 0) {
@@ -617,7 +640,7 @@ static int http_connect(http_subtransport *t)
617
640
  return error;
618
641
  }
619
642
  }
620
- #endif
643
+
621
644
  if (error < 0)
622
645
  return error;
623
646
 
@@ -1013,6 +1036,8 @@ static int http_close(git_smart_subtransport *subtransport)
1013
1036
 
1014
1037
  clear_parser_state(t);
1015
1038
 
1039
+ t->connected = 0;
1040
+
1016
1041
  if (t->io) {
1017
1042
  git_stream_close(t->io);
1018
1043
  git_stream_free(t->io);
@@ -25,6 +25,7 @@
25
25
  #include "odb.h"
26
26
  #include "push.h"
27
27
  #include "remote.h"
28
+ #include "proxy.h"
28
29
 
29
30
  typedef struct {
30
31
  git_transport parent;
@@ -199,6 +200,7 @@ static int local_connect(
199
200
  const char *url,
200
201
  git_cred_acquire_cb cred_acquire_cb,
201
202
  void *cred_acquire_payload,
203
+ const git_proxy_options *proxy,
202
204
  int direction, int flags)
203
205
  {
204
206
  git_repository *repo;
@@ -209,6 +211,7 @@ static int local_connect(
209
211
 
210
212
  GIT_UNUSED(cred_acquire_cb);
211
213
  GIT_UNUSED(cred_acquire_payload);
214
+ GIT_UNUSED(proxy);
212
215
 
213
216
  if (t->connected)
214
217
  return 0;
@@ -439,7 +442,7 @@ static int local_push(
439
442
 
440
443
  if (!url || t->parent.close(&t->parent) < 0 ||
441
444
  t->parent.connect(&t->parent, url,
442
- NULL, NULL, GIT_DIRECTION_PUSH, flags))
445
+ NULL, NULL, NULL, GIT_DIRECTION_PUSH, flags))
443
446
  goto on_error;
444
447
  }
445
448
 
@@ -8,6 +8,7 @@
8
8
  #include "smart.h"
9
9
  #include "refs.h"
10
10
  #include "refspec.h"
11
+ #include "proxy.h"
11
12
 
12
13
  static int git_smart__recv_cb(gitno_buffer *buf)
13
14
  {
@@ -199,6 +200,7 @@ static int git_smart__connect(
199
200
  const char *url,
200
201
  git_cred_acquire_cb cred_acquire_cb,
201
202
  void *cred_acquire_payload,
203
+ const git_proxy_options *proxy,
202
204
  int direction,
203
205
  int flags)
204
206
  {
@@ -216,6 +218,9 @@ static int git_smart__connect(
216
218
  t->url = git__strdup(url);
217
219
  GITERR_CHECK_ALLOC(t->url);
218
220
 
221
+ if (git_proxy_options_dup(&t->proxy, proxy) < 0)
222
+ return -1;
223
+
219
224
  t->direction = direction;
220
225
  t->flags = flags;
221
226
  t->cred_acquire_cb = cred_acquire_cb;
@@ -439,6 +444,7 @@ static void git_smart__free(git_transport *transport)
439
444
  git_pkt_free(p);
440
445
 
441
446
  git_vector_free(refs);
447
+ git__free((char *)t->proxy.url);
442
448
 
443
449
  git_strarray_free(&t->custom_headers);
444
450
 
@@ -133,6 +133,7 @@ typedef struct {
133
133
  char *url;
134
134
  git_cred_acquire_cb cred_acquire_cb;
135
135
  void *cred_acquire_payload;
136
+ git_proxy_options proxy;
136
137
  int direction;
137
138
  int flags;
138
139
  git_transport_message_cb progress_cb;
@@ -427,23 +427,15 @@ int git_pkt_parse_line(
427
427
  if (bufflen > 0 && bufflen < (size_t)len)
428
428
  return GIT_EBUFS;
429
429
 
430
- /*
431
- * The length has to be exactly 0 in case of a flush
432
- * packet or greater than PKT_LEN_SIZE, as the decoded
433
- * length includes its own encoded length of four bytes.
434
- */
435
- if (len != 0 && len < PKT_LEN_SIZE)
436
- return GIT_ERROR;
437
-
438
430
  line += PKT_LEN_SIZE;
439
431
  /*
440
- * The Git protocol does not specify empty lines as part
441
- * of the protocol. Not knowing what to do with an empty
442
- * line, we should return an error upon hitting one.
432
+ * TODO: How do we deal with empty lines? Try again? with the next
433
+ * line?
443
434
  */
444
435
  if (len == PKT_LEN_SIZE) {
445
- giterr_set_str(GITERR_NET, "Invalid empty packet");
446
- return GIT_ERROR;
436
+ *head = NULL;
437
+ *out = line;
438
+ return 0;
447
439
  }
448
440
 
449
441
  if (len == 0) { /* Flush pkt */
@@ -50,7 +50,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
50
50
  if ((recvd = gitno_recv(buf)) < 0)
51
51
  return recvd;
52
52
 
53
- if (recvd == 0 && !flush) {
53
+ if (recvd == 0) {
54
54
  giterr_set(GITERR_NET, "early EOF");
55
55
  return GIT_EEOF;
56
56
  }
@@ -222,8 +222,12 @@ static int recv_pkt(git_pkt **out, gitno_buffer *buf)
222
222
  if (error < 0 && error != GIT_EBUFS)
223
223
  return error;
224
224
 
225
- if ((ret = gitno_recv(buf)) < 0)
225
+ if ((ret = gitno_recv(buf)) < 0) {
226
226
  return ret;
227
+ } else if (ret == 0) {
228
+ giterr_set(GITERR_NET, "early EOF");
229
+ return GIT_EEOF;
230
+ }
227
231
  } while (error);
228
232
 
229
233
  gitno_consume(buf, line_end);
@@ -408,12 +412,12 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
408
412
 
409
413
  if (i % 20 == 0 && t->rpc) {
410
414
  git_pkt_ack *pkt;
411
- unsigned int i;
415
+ unsigned int j;
412
416
 
413
417
  if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
414
418
  goto on_error;
415
419
 
416
- git_vector_foreach(&t->common, i, pkt) {
420
+ git_vector_foreach(&t->common, j, pkt) {
417
421
  if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
418
422
  goto on_error;
419
423
  }
@@ -428,12 +432,12 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
428
432
  /* Tell the other end that we're done negotiating */
429
433
  if (t->rpc && t->common.length > 0) {
430
434
  git_pkt_ack *pkt;
431
- unsigned int i;
435
+ unsigned int j;
432
436
 
433
437
  if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
434
438
  goto on_error;
435
439
 
436
- git_vector_foreach(&t->common, i, pkt) {
440
+ git_vector_foreach(&t->common, j, pkt) {
437
441
  if ((error = git_pkt_buffer_have(&pkt->oid, &data)) < 0)
438
442
  goto on_error;
439
443
  }
@@ -724,7 +728,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
724
728
  static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_buf *data_pkt_buf)
725
729
  {
726
730
  git_pkt *pkt;
727
- const char *line, *line_end;
731
+ const char *line, *line_end = NULL;
728
732
  size_t line_len;
729
733
  int error;
730
734
  int reading_from_buf = data_pkt_buf->size > 0;
@@ -759,6 +763,14 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
759
763
  line_len -= (line_end - line);
760
764
  line = line_end;
761
765
 
766
+ /* When a valid packet with no content has been
767
+ * read, git_pkt_parse_line does not report an
768
+ * error, but the pkt pointer has not been set.
769
+ * Handle this by skipping over empty packets.
770
+ */
771
+ if (pkt == NULL)
772
+ continue;
773
+
762
774
  error = add_push_report_pkt(push, pkt);
763
775
 
764
776
  git_pkt_free(pkt);
@@ -813,6 +825,9 @@ static int parse_report(transport_smart *transport, git_push *push)
813
825
 
814
826
  error = 0;
815
827
 
828
+ if (pkt == NULL)
829
+ continue;
830
+
816
831
  switch (pkt->type) {
817
832
  case GIT_PKT_DATA:
818
833
  /* This is a sideband packet which contains other packets */
@@ -91,13 +91,39 @@ typedef struct {
91
91
  git_smart_subtransport parent;
92
92
  transport_smart *owner;
93
93
  gitno_connection_data connection_data;
94
+ gitno_connection_data proxy_connection_data;
94
95
  git_cred *cred;
95
96
  git_cred *url_cred;
97
+ git_cred *proxy_cred;
96
98
  int auth_mechanism;
97
99
  HINTERNET session;
98
100
  HINTERNET connection;
99
101
  } winhttp_subtransport;
100
102
 
103
+ static int apply_basic_credential_proxy(HINTERNET request, git_cred *cred)
104
+ {
105
+ git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
106
+ wchar_t *user, *pass;
107
+ int error;
108
+
109
+ if ((error = git__utf8_to_16_alloc(&user, c->username)) < 0)
110
+ return error;
111
+
112
+ if ((error = git__utf8_to_16_alloc(&pass, c->password)) < 0)
113
+ return error;
114
+
115
+ if (!WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC,
116
+ user, pass, NULL)) {
117
+ giterr_set(GITERR_OS, "failed to set proxy auth");
118
+ error = -1;
119
+ }
120
+
121
+ git__free(user);
122
+ git__free(pass);
123
+
124
+ return error;
125
+ }
126
+
101
127
  static int apply_basic_credential(HINTERNET request, git_cred *cred)
102
128
  {
103
129
  git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
@@ -271,6 +297,37 @@ static void winhttp_stream_close(winhttp_stream *s)
271
297
  s->sent_request = 0;
272
298
  }
273
299
 
300
+ /**
301
+ * Extract the url and password from a URL. The outputs are pointers
302
+ * into the input.
303
+ */
304
+ static int userpass_from_url(wchar_t **user, int *user_len,
305
+ wchar_t **pass, int *pass_len,
306
+ const wchar_t *url, int url_len)
307
+ {
308
+ URL_COMPONENTS components = { 0 };
309
+
310
+ components.dwStructSize = sizeof(components);
311
+ /* These tell WinHttpCrackUrl that we're interested in the fields */
312
+ components.dwUserNameLength = 1;
313
+ components.dwPasswordLength = 1;
314
+
315
+ if (!WinHttpCrackUrl(url, url_len, 0, &components)) {
316
+ giterr_set(GITERR_OS, "failed to extract user/pass from url");
317
+ return -1;
318
+ }
319
+
320
+ *user = components.lpszUserName;
321
+ *user_len = components.dwUserNameLength;
322
+ *pass = components.lpszPassword;
323
+ *pass_len = components.dwPasswordLength;
324
+
325
+ return 0;
326
+ }
327
+
328
+ #define SCHEME_HTTP "http://"
329
+ #define SCHEME_HTTPS "https://"
330
+
274
331
  static int winhttp_stream_connect(winhttp_stream *s)
275
332
  {
276
333
  winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
@@ -284,6 +341,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
284
341
  int default_timeout = TIMEOUT_INFINITE;
285
342
  int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
286
343
  size_t i;
344
+ const git_proxy_options *proxy_opts;
287
345
 
288
346
  /* Prepare URL */
289
347
  git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url);
@@ -317,26 +375,66 @@ static int winhttp_stream_connect(winhttp_stream *s)
317
375
  goto on_error;
318
376
  }
319
377
 
320
- /* Set proxy if necessary */
321
- if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
322
- goto on_error;
378
+ proxy_opts = &t->owner->proxy;
379
+ if (proxy_opts->type == GIT_PROXY_AUTO) {
380
+ /* Set proxy if necessary */
381
+ if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
382
+ goto on_error;
383
+ }
384
+ else if (proxy_opts->type == GIT_PROXY_SPECIFIED) {
385
+ proxy_url = git__strdup(proxy_opts->url);
386
+ GITERR_CHECK_ALLOC(proxy_url);
387
+ }
323
388
 
324
389
  if (proxy_url) {
390
+ git_buf processed_url = GIT_BUF_INIT;
325
391
  WINHTTP_PROXY_INFO proxy_info;
326
392
  wchar_t *proxy_wide;
327
393
 
328
- /* Convert URL to wide characters */
329
- int proxy_wide_len = git__utf8_to_16_alloc(&proxy_wide, proxy_url);
394
+ if (!git__prefixcmp(proxy_url, SCHEME_HTTP)) {
395
+ t->proxy_connection_data.use_ssl = false;
396
+ } else if (!git__prefixcmp(proxy_url, SCHEME_HTTPS)) {
397
+ t->proxy_connection_data.use_ssl = true;
398
+ } else {
399
+ giterr_set(GITERR_NET, "invalid URL: '%s'", proxy_url);
400
+ return -1;
401
+ }
330
402
 
331
- if (proxy_wide_len < 0) {
332
- giterr_set(GITERR_OS, "Failed to convert string to wide form");
403
+ gitno_connection_data_free_ptrs(&t->proxy_connection_data);
404
+
405
+ if ((error = gitno_extract_url_parts(&t->proxy_connection_data.host, &t->proxy_connection_data.port, NULL,
406
+ &t->proxy_connection_data.user, &t->proxy_connection_data.pass, proxy_url, NULL)) < 0)
333
407
  goto on_error;
408
+
409
+ if (t->proxy_connection_data.user && t->proxy_connection_data.pass) {
410
+ if (t->proxy_cred) {
411
+ t->proxy_cred->free(t->proxy_cred);
412
+ }
413
+
414
+ if ((error = git_cred_userpass_plaintext_new(&t->proxy_cred, t->proxy_connection_data.user, t->proxy_connection_data.pass)) < 0)
415
+ goto on_error;
334
416
  }
335
417
 
336
- /* Strip any trailing forward slash on the proxy URL;
337
- * WinHTTP doesn't like it if one is present */
338
- if (proxy_wide_len > 1 && L'/' == proxy_wide[proxy_wide_len - 2])
339
- proxy_wide[proxy_wide_len - 2] = L'\0';
418
+ if (t->proxy_connection_data.use_ssl)
419
+ git_buf_PUTS(&processed_url, SCHEME_HTTPS);
420
+ else
421
+ git_buf_PUTS(&processed_url, SCHEME_HTTP);
422
+
423
+ git_buf_puts(&processed_url, t->proxy_connection_data.host);
424
+ if (t->proxy_connection_data.port)
425
+ git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port);
426
+
427
+ if (git_buf_oom(&processed_url)) {
428
+ giterr_set_oom();
429
+ error = -1;
430
+ goto on_error;
431
+ }
432
+
433
+ /* Convert URL to wide characters */
434
+ error = git__utf8_to_16_alloc(&proxy_wide, processed_url.ptr);
435
+ git_buf_free(&processed_url);
436
+ if (error < 0)
437
+ goto on_error;
340
438
 
341
439
  proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
342
440
  proxy_info.lpszProxy = proxy_wide;
@@ -352,6 +450,14 @@ static int winhttp_stream_connect(winhttp_stream *s)
352
450
  }
353
451
 
354
452
  git__free(proxy_wide);
453
+
454
+ if (t->proxy_cred) {
455
+ if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) {
456
+ if ((error = apply_basic_credential_proxy(s->request, t->proxy_cred)) < 0)
457
+ goto on_error;
458
+ }
459
+ }
460
+
355
461
  }
356
462
 
357
463
  /* Disable WinHTTP redirects so we can handle them manually. Why, you ask?
@@ -919,6 +1025,26 @@ replay:
919
1025
  goto replay;
920
1026
  }
921
1027
 
1028
+ /* Handle proxy authentication failures */
1029
+ if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) {
1030
+ int allowed_types;
1031
+
1032
+ if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0)
1033
+ return -1;
1034
+
1035
+ /* TODO: extract the username from the url, no payload? */
1036
+ if (t->owner->proxy.credentials) {
1037
+ int cred_error = 1;
1038
+ cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, NULL);
1039
+
1040
+ if (cred_error < 0)
1041
+ return cred_error;
1042
+ }
1043
+
1044
+ winhttp_stream_close(s);
1045
+ goto replay;
1046
+ }
1047
+
922
1048
  /* Handle authentication failures */
923
1049
  if (HTTP_STATUS_DENIED == status_code && get_verb == s->verb) {
924
1050
  int allowed_types;
@@ -1362,12 +1488,19 @@ static int winhttp_close(git_smart_subtransport *subtransport)
1362
1488
 
1363
1489
  gitno_connection_data_free_ptrs(&t->connection_data);
1364
1490
  memset(&t->connection_data, 0x0, sizeof(gitno_connection_data));
1491
+ gitno_connection_data_free_ptrs(&t->proxy_connection_data);
1492
+ memset(&t->proxy_connection_data, 0x0, sizeof(gitno_connection_data));
1365
1493
 
1366
1494
  if (t->cred) {
1367
1495
  t->cred->free(t->cred);
1368
1496
  t->cred = NULL;
1369
1497
  }
1370
1498
 
1499
+ if (t->proxy_cred) {
1500
+ t->proxy_cred->free(t->proxy_cred);
1501
+ t->proxy_cred = NULL;
1502
+ }
1503
+
1371
1504
  if (t->url_cred) {
1372
1505
  t->url_cred->free(t->url_cred);
1373
1506
  t->url_cred = NULL;