rugged 0.22.0b4 → 0.22.0b5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rugged/rugged.c +8 -7
  3. data/ext/rugged/rugged_note.c +1 -1
  4. data/ext/rugged/rugged_remote.c +0 -5
  5. data/ext/rugged/rugged_tree.c +23 -25
  6. data/lib/rugged/version.rb +1 -1
  7. data/vendor/libgit2/include/git2/blame.h +0 -1
  8. data/vendor/libgit2/include/git2/branch.h +1 -1
  9. data/vendor/libgit2/include/git2/buffer.h +1 -1
  10. data/vendor/libgit2/include/git2/cherrypick.h +5 -2
  11. data/vendor/libgit2/include/git2/clone.h +0 -1
  12. data/vendor/libgit2/include/git2/common.h +6 -1
  13. data/vendor/libgit2/include/git2/config.h +13 -4
  14. data/vendor/libgit2/include/git2/filter.h +3 -0
  15. data/vendor/libgit2/include/git2/global.h +10 -4
  16. data/vendor/libgit2/include/git2/index.h +3 -0
  17. data/vendor/libgit2/include/git2/merge.h +20 -5
  18. data/vendor/libgit2/include/git2/net.h +3 -2
  19. data/vendor/libgit2/include/git2/notes.h +5 -7
  20. data/vendor/libgit2/include/git2/push.h +7 -14
  21. data/vendor/libgit2/include/git2/rebase.h +14 -1
  22. data/vendor/libgit2/include/git2/refs.h +7 -1
  23. data/vendor/libgit2/include/git2/remote.h +6 -1
  24. data/vendor/libgit2/include/git2/repository.h +6 -0
  25. data/vendor/libgit2/include/git2/revert.h +5 -2
  26. data/vendor/libgit2/include/git2/stash.h +15 -6
  27. data/vendor/libgit2/include/git2/submodule.h +1 -1
  28. data/vendor/libgit2/include/git2/sys/diff.h +5 -2
  29. data/vendor/libgit2/include/git2/sys/hashsig.h +3 -0
  30. data/vendor/libgit2/include/git2/sys/mempack.h +1 -1
  31. data/vendor/libgit2/include/git2/sys/stream.h +40 -0
  32. data/vendor/libgit2/include/git2/sys/transport.h +17 -4
  33. data/vendor/libgit2/include/git2/tree.h +3 -3
  34. data/vendor/libgit2/src/checkout.c +27 -1
  35. data/vendor/libgit2/src/commit_list.c +1 -1
  36. data/vendor/libgit2/src/common.h +1 -1
  37. data/vendor/libgit2/src/config_cache.c +2 -0
  38. data/vendor/libgit2/src/config_file.c +1 -1
  39. data/vendor/libgit2/src/describe.c +2 -2
  40. data/vendor/libgit2/src/global.c +31 -14
  41. data/vendor/libgit2/src/ignore.c +86 -3
  42. data/vendor/libgit2/src/index.c +48 -25
  43. data/vendor/libgit2/src/indexer.c +1 -0
  44. data/vendor/libgit2/src/netops.c +18 -474
  45. data/vendor/libgit2/src/netops.h +3 -8
  46. data/vendor/libgit2/src/notes.c +3 -3
  47. data/vendor/libgit2/src/odb.c +1 -0
  48. data/vendor/libgit2/src/odb_loose.c +1 -1
  49. data/vendor/libgit2/src/openssl_stream.c +375 -0
  50. data/vendor/libgit2/src/openssl_stream.h +14 -0
  51. data/vendor/libgit2/src/path.c +256 -0
  52. data/vendor/libgit2/src/path.h +44 -1
  53. data/vendor/libgit2/src/pool.c +1 -1
  54. data/vendor/libgit2/src/push.c +5 -5
  55. data/vendor/libgit2/src/rebase.c +2 -2
  56. data/vendor/libgit2/src/refdb_fs.c +11 -1
  57. data/vendor/libgit2/src/remote.c +2 -7
  58. data/vendor/libgit2/src/repository.c +25 -0
  59. data/vendor/libgit2/src/repository.h +26 -2
  60. data/vendor/libgit2/src/socket_stream.c +212 -0
  61. data/vendor/libgit2/src/socket_stream.h +21 -0
  62. data/vendor/libgit2/src/stream.h +48 -0
  63. data/vendor/libgit2/src/tag.c +1 -1
  64. data/vendor/libgit2/src/transports/git.c +71 -57
  65. data/vendor/libgit2/src/transports/http.c +40 -62
  66. data/vendor/libgit2/src/transports/local.c +6 -11
  67. data/vendor/libgit2/src/transports/smart.c +3 -3
  68. data/vendor/libgit2/src/transports/ssh.c +12 -8
  69. data/vendor/libgit2/src/transports/winhttp.c +68 -47
  70. data/vendor/libgit2/src/tree.c +16 -14
  71. data/vendor/libgit2/src/tree.h +1 -0
  72. data/vendor/libgit2/src/util.c +91 -0
  73. data/vendor/libgit2/src/util.h +12 -0
  74. data/vendor/libgit2/src/win32/findfile.c +1 -0
  75. data/vendor/libgit2/src/win32/path_w32.c +305 -0
  76. data/vendor/libgit2/src/win32/path_w32.h +80 -0
  77. data/vendor/libgit2/src/win32/posix.h +1 -0
  78. data/vendor/libgit2/src/win32/posix_w32.c +25 -42
  79. data/vendor/libgit2/src/win32/utf-conv.c +36 -6
  80. data/vendor/libgit2/src/win32/utf-conv.h +0 -39
  81. data/vendor/libgit2/src/win32/w32_util.h +1 -0
  82. data/vendor/libgit2/src/xdiff/xdiffi.c +1 -1
  83. data/vendor/libgit2/src/xdiff/xhistogram.c +1 -1
  84. metadata +10 -2
@@ -131,6 +131,7 @@ int git_openssl_set_locking(void)
131
131
  giterr_set(GITERR_THREAD, "libgit2 as not built with threads");
132
132
  return -1;
133
133
  # endif
134
+ #else
134
135
  giterr_set(GITERR_SSL, "libgit2 was not built with OpenSSL support");
135
136
  return -1;
136
137
  #endif
@@ -194,19 +195,21 @@ static int synchronized_threads_init(void)
194
195
 
195
196
  int git_libgit2_init(void)
196
197
  {
197
- int error = 0;
198
+ int ret;
198
199
 
199
200
  /* Enter the lock */
200
201
  while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
201
202
 
202
203
  /* Only do work on a 0 -> 1 transition of the refcount */
203
- if (1 == git_atomic_inc(&git__n_inits))
204
- error = synchronized_threads_init();
204
+ if ((ret = git_atomic_inc(&git__n_inits)) == 1) {
205
+ if (synchronized_threads_init() < 0)
206
+ ret = -1;
207
+ }
205
208
 
206
209
  /* Exit the lock */
207
210
  InterlockedExchange(&_mutex, 0);
208
211
 
209
- return error;
212
+ return ret;
210
213
  }
211
214
 
212
215
  static void synchronized_threads_shutdown(void)
@@ -217,17 +220,21 @@ static void synchronized_threads_shutdown(void)
217
220
  git_mutex_free(&git__mwindow_mutex);
218
221
  }
219
222
 
220
- void git_libgit2_shutdown(void)
223
+ int git_libgit2_shutdown(void)
221
224
  {
225
+ int ret;
226
+
222
227
  /* Enter the lock */
223
228
  while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); }
224
229
 
225
230
  /* Only do work on a 1 -> 0 transition of the refcount */
226
- if (0 == git_atomic_dec(&git__n_inits))
231
+ if ((ret = git_atomic_dec(&git__n_inits)) == 0)
227
232
  synchronized_threads_shutdown();
228
233
 
229
234
  /* Exit the lock */
230
235
  InterlockedExchange(&_mutex, 0);
236
+
237
+ return ret;
231
238
  }
232
239
 
233
240
  git_global_st *git__global_state(void)
@@ -281,17 +288,22 @@ static void init_once(void)
281
288
 
282
289
  int git_libgit2_init(void)
283
290
  {
291
+ int ret;
292
+
284
293
  pthread_once(&_once_init, init_once);
285
- git_atomic_inc(&git__n_inits);
286
- return init_error;
294
+ ret = git_atomic_inc(&git__n_inits);
295
+
296
+ return init_error ? init_error : ret;
287
297
  }
288
298
 
289
- void git_libgit2_shutdown(void)
299
+ int git_libgit2_shutdown(void)
290
300
  {
291
301
  void *ptr = NULL;
292
302
  pthread_once_t new_once = PTHREAD_ONCE_INIT;
303
+ int ret;
293
304
 
294
- if (git_atomic_dec(&git__n_inits) > 0) return;
305
+ if ((ret = git_atomic_dec(&git__n_inits)) > 0)
306
+ return ret;
295
307
 
296
308
  /* Shut down any subsystems that have global state */
297
309
  git__shutdown();
@@ -303,6 +315,8 @@ void git_libgit2_shutdown(void)
303
315
  pthread_key_delete(_tls_key);
304
316
  git_mutex_free(&git__mwindow_mutex);
305
317
  _once_init = new_once;
318
+
319
+ return ret;
306
320
  }
307
321
 
308
322
  git_global_st *git__global_state(void)
@@ -336,15 +350,18 @@ int git_libgit2_init(void)
336
350
  ssl_inited = 1;
337
351
  }
338
352
 
339
- git_atomic_inc(&git__n_inits);
340
- return 0;
353
+ return git_atomic_inc(&git__n_inits);
341
354
  }
342
355
 
343
- void git_libgit2_shutdown(void)
356
+ int git_libgit2_shutdown(void)
344
357
  {
358
+ int ret;
359
+
345
360
  /* Shut down any subsystems that have global state */
346
- if (0 == git_atomic_dec(&git__n_inits))
361
+ if (ret = git_atomic_dec(&git__n_inits))
347
362
  git__shutdown();
363
+
364
+ return ret;
348
365
  }
349
366
 
350
367
  git_global_st *git__global_state(void)
@@ -4,11 +4,87 @@
4
4
  #include "attrcache.h"
5
5
  #include "path.h"
6
6
  #include "config.h"
7
+ #include "fnmatch.h"
7
8
 
8
9
  #define GIT_IGNORE_INTERNAL "[internal]exclude"
9
10
 
10
11
  #define GIT_IGNORE_DEFAULT_RULES ".\n..\n.git\n"
11
12
 
13
+ /**
14
+ * A negative ignore can only unignore a file which is given explicitly before, thus
15
+ *
16
+ * foo
17
+ * !foo/bar
18
+ *
19
+ * does not unignore 'foo/bar' as it's not in the list. However
20
+ *
21
+ * foo/<star>
22
+ * !foo/bar
23
+ *
24
+ * does unignore 'foo/bar', as it is contained within the 'foo/<star>' rule.
25
+ */
26
+ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match)
27
+ {
28
+ int error = 0;
29
+ size_t i;
30
+ git_attr_fnmatch *rule;
31
+ char *path;
32
+ git_buf buf = GIT_BUF_INIT;
33
+
34
+ /* path of the file relative to the workdir, so we match the rules in subdirs */
35
+ if (match->containing_dir) {
36
+ git_buf_puts(&buf, match->containing_dir);
37
+ }
38
+ if (git_buf_puts(&buf, match->pattern) < 0)
39
+ return -1;
40
+
41
+ path = git_buf_detach(&buf);
42
+
43
+ git_vector_foreach(rules, i, rule) {
44
+ /* no chance of matching w/o a wilcard */
45
+ if (!(rule->flags & GIT_ATTR_FNMATCH_HASWILD))
46
+ continue;
47
+
48
+ /*
49
+ * If we're dealing with a directory (which we know via the
50
+ * strchr() check) we want to use 'dirname/<star>' as the
51
+ * pattern so p_fnmatch() honours FNM_PATHNAME
52
+ */
53
+ git_buf_clear(&buf);
54
+ if (rule->containing_dir) {
55
+ git_buf_puts(&buf, rule->containing_dir);
56
+ }
57
+ if (!strchr(rule->pattern, '*'))
58
+ error = git_buf_printf(&buf, "%s/*", rule->pattern);
59
+ else
60
+ error = git_buf_puts(&buf, rule->pattern);
61
+
62
+ if (error < 0)
63
+ goto out;
64
+
65
+
66
+ if ((error = p_fnmatch(git_buf_cstr(&buf), path, FNM_PATHNAME)) < 0) {
67
+ giterr_set(GITERR_INVALID, "error matching pattern");
68
+ goto out;
69
+ }
70
+
71
+ /* if we found a match, we want to keep this rule */
72
+ if (error != FNM_NOMATCH) {
73
+ *out = 1;
74
+ error = 0;
75
+ goto out;
76
+ }
77
+ }
78
+
79
+ *out = 0;
80
+ error = 0;
81
+
82
+ out:
83
+ git__free(path);
84
+ git_buf_free(&buf);
85
+ return error;
86
+ }
87
+
12
88
  static int parse_ignore_file(
13
89
  git_repository *repo, git_attr_file *attrs, const char *data)
14
90
  {
@@ -32,6 +108,8 @@ static int parse_ignore_file(
32
108
  }
33
109
 
34
110
  while (!error && *scan) {
111
+ int valid_rule = 1;
112
+
35
113
  if (!match && !(match = git__calloc(1, sizeof(*match)))) {
36
114
  error = -1;
37
115
  break;
@@ -48,11 +126,16 @@ static int parse_ignore_file(
48
126
  match->flags |= GIT_ATTR_FNMATCH_ICASE;
49
127
 
50
128
  scan = git__next_line(scan);
51
- error = git_vector_insert(&attrs->rules, match);
129
+
130
+ /* if a negative match doesn't actually do anything, throw it away */
131
+ if (match->flags & GIT_ATTR_FNMATCH_NEGATIVE)
132
+ error = does_negate_rule(&valid_rule, &attrs->rules, match);
133
+
134
+ if (!error && valid_rule)
135
+ error = git_vector_insert(&attrs->rules, match);
52
136
  }
53
137
 
54
- if (error != 0) {
55
- git__free(match->pattern);
138
+ if (error != 0 || !valid_rule) {
56
139
  match->pattern = NULL;
57
140
 
58
141
  if (error == GIT_ENOTFOUND)
@@ -762,23 +762,35 @@ void git_index_entry__init_from_stat(
762
762
  entry->file_size = st->st_size;
763
763
  }
764
764
 
765
- static git_index_entry *index_entry_alloc(const char *path)
765
+ static int index_entry_create(
766
+ git_index_entry **out,
767
+ git_repository *repo,
768
+ const char *path)
766
769
  {
767
770
  size_t pathlen = strlen(path);
768
- struct entry_internal *entry =
769
- git__calloc(sizeof(struct entry_internal) + pathlen + 1, 1);
770
- if (!entry)
771
- return NULL;
771
+ struct entry_internal *entry;
772
+
773
+ if (!git_path_isvalid(repo, path,
774
+ GIT_PATH_REJECT_DEFAULTS | GIT_PATH_REJECT_DOT_GIT)) {
775
+ giterr_set(GITERR_INDEX, "Invalid path: '%s'", path);
776
+ return -1;
777
+ }
778
+
779
+ entry = git__calloc(sizeof(struct entry_internal) + pathlen + 1, 1);
780
+ GITERR_CHECK_ALLOC(entry);
772
781
 
773
782
  entry->pathlen = pathlen;
774
783
  memcpy(entry->path, path, pathlen);
775
784
  entry->entry.path = entry->path;
776
785
 
777
- return (git_index_entry *)entry;
786
+ *out = (git_index_entry *)entry;
787
+ return 0;
778
788
  }
779
789
 
780
790
  static int index_entry_init(
781
- git_index_entry **entry_out, git_index *index, const char *rel_path)
791
+ git_index_entry **entry_out,
792
+ git_index *index,
793
+ const char *rel_path)
782
794
  {
783
795
  int error = 0;
784
796
  git_index_entry *entry = NULL;
@@ -790,14 +802,17 @@ static int index_entry_init(
790
802
  "Could not initialize index entry. "
791
803
  "Index is not backed up by an existing repository.");
792
804
 
805
+ if (index_entry_create(&entry, INDEX_OWNER(index), rel_path) < 0)
806
+ return -1;
807
+
793
808
  /* write the blob to disk and get the oid and stat info */
794
809
  error = git_blob__create_from_paths(
795
810
  &oid, &st, INDEX_OWNER(index), NULL, rel_path, 0, true);
796
- if (error < 0)
797
- return error;
798
811
 
799
- entry = index_entry_alloc(rel_path);
800
- GITERR_CHECK_ALLOC(entry);
812
+ if (error < 0) {
813
+ index_entry_free(entry);
814
+ return error;
815
+ }
801
816
 
802
817
  entry->id = oid;
803
818
  git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
@@ -853,7 +868,10 @@ static void index_entry_cpy(git_index_entry *tgt, const git_index_entry *src)
853
868
  tgt->path = tgt_path; /* reset to existing path data */
854
869
  }
855
870
 
856
- static int index_entry_dup(git_index_entry **out, const git_index_entry *src)
871
+ static int index_entry_dup(
872
+ git_index_entry **out,
873
+ git_repository *repo,
874
+ const git_index_entry *src)
857
875
  {
858
876
  git_index_entry *entry;
859
877
 
@@ -862,11 +880,11 @@ static int index_entry_dup(git_index_entry **out, const git_index_entry *src)
862
880
  return 0;
863
881
  }
864
882
 
865
- *out = entry = index_entry_alloc(src->path);
866
- GITERR_CHECK_ALLOC(entry);
883
+ if (index_entry_create(&entry, repo, src->path) < 0)
884
+ return -1;
867
885
 
868
886
  index_entry_cpy(entry, src);
869
-
887
+ *out = entry;
870
888
  return 0;
871
889
  }
872
890
 
@@ -1131,7 +1149,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
1131
1149
  return -1;
1132
1150
  }
1133
1151
 
1134
- if ((ret = index_entry_dup(&entry, source_entry)) < 0 ||
1152
+ if ((ret = index_entry_dup(&entry, INDEX_OWNER(index), source_entry)) < 0 ||
1135
1153
  (ret = index_insert(index, &entry, 1)) < 0)
1136
1154
  return ret;
1137
1155
 
@@ -1251,9 +1269,9 @@ int git_index_conflict_add(git_index *index,
1251
1269
 
1252
1270
  assert (index);
1253
1271
 
1254
- if ((ret = index_entry_dup(&entries[0], ancestor_entry)) < 0 ||
1255
- (ret = index_entry_dup(&entries[1], our_entry)) < 0 ||
1256
- (ret = index_entry_dup(&entries[2], their_entry)) < 0)
1272
+ if ((ret = index_entry_dup(&entries[0], INDEX_OWNER(index), ancestor_entry)) < 0 ||
1273
+ (ret = index_entry_dup(&entries[1], INDEX_OWNER(index), our_entry)) < 0 ||
1274
+ (ret = index_entry_dup(&entries[2], INDEX_OWNER(index), their_entry)) < 0)
1257
1275
  goto on_error;
1258
1276
 
1259
1277
  for (i = 0; i < 3; i++) {
@@ -1770,7 +1788,10 @@ static int read_conflict_names(git_index *index, const char *buffer, size_t size
1770
1788
  }
1771
1789
 
1772
1790
  static size_t read_entry(
1773
- git_index_entry **out, const void *buffer, size_t buffer_size)
1791
+ git_index_entry **out,
1792
+ git_index *index,
1793
+ const void *buffer,
1794
+ size_t buffer_size)
1774
1795
  {
1775
1796
  size_t path_length, entry_size;
1776
1797
  const char *path_ptr;
@@ -1834,7 +1855,7 @@ static size_t read_entry(
1834
1855
 
1835
1856
  entry.path = (char *)path_ptr;
1836
1857
 
1837
- if (index_entry_dup(out, &entry) < 0)
1858
+ if (index_entry_dup(out, INDEX_OWNER(index), &entry) < 0)
1838
1859
  return 0;
1839
1860
 
1840
1861
  return entry_size;
@@ -1935,7 +1956,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
1935
1956
  /* Parse all the entries */
1936
1957
  for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
1937
1958
  git_index_entry *entry;
1938
- size_t entry_size = read_entry(&entry, buffer, buffer_size);
1959
+ size_t entry_size = read_entry(&entry, index, buffer, buffer_size);
1939
1960
 
1940
1961
  /* 0 bytes read means an object corruption */
1941
1962
  if (entry_size == 0) {
@@ -2296,6 +2317,7 @@ int git_index_entry_stage(const git_index_entry *entry)
2296
2317
  }
2297
2318
 
2298
2319
  typedef struct read_tree_data {
2320
+ git_index *index;
2299
2321
  git_vector *old_entries;
2300
2322
  git_vector *new_entries;
2301
2323
  git_vector_cmp entry_cmp;
@@ -2316,8 +2338,8 @@ static int read_tree_cb(
2316
2338
  if (git_buf_joinpath(&path, root, tentry->filename) < 0)
2317
2339
  return -1;
2318
2340
 
2319
- entry = index_entry_alloc(path.ptr);
2320
- GITERR_CHECK_ALLOC(entry);
2341
+ if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr) < 0)
2342
+ return -1;
2321
2343
 
2322
2344
  entry->mode = tentry->attr;
2323
2345
  entry->id = tentry->oid;
@@ -2357,6 +2379,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree)
2357
2379
 
2358
2380
  git_vector_set_cmp(&entries, index->entries._cmp); /* match sort */
2359
2381
 
2382
+ data.index = index;
2360
2383
  data.old_entries = &index->entries;
2361
2384
  data.new_entries = &entries;
2362
2385
  data.entry_cmp = index->entries_search;
@@ -2476,7 +2499,7 @@ int git_index_add_all(
2476
2499
  break;
2477
2500
 
2478
2501
  /* make the new entry to insert */
2479
- if ((error = index_entry_dup(&entry, wd)) < 0)
2502
+ if ((error = index_entry_dup(&entry, INDEX_OWNER(index), wd)) < 0)
2480
2503
  break;
2481
2504
 
2482
2505
  entry->id = blobid;
@@ -1028,6 +1028,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
1028
1028
  p_rename(idx->pack->pack_name, git_buf_cstr(&filename));
1029
1029
 
1030
1030
  git_buf_free(&filename);
1031
+ git_hash_ctx_cleanup(&ctx);
1031
1032
  return 0;
1032
1033
 
1033
1034
  on_error:
@@ -4,27 +4,6 @@
4
4
  * This file is part of libgit2, distributed under the GNU GPL v2 with
5
5
  * a Linking Exception. For full terms see the included COPYING file.
6
6
  */
7
- #ifndef _WIN32
8
- # include <sys/types.h>
9
- # include <sys/socket.h>
10
- # include <sys/select.h>
11
- # include <sys/time.h>
12
- # include <netdb.h>
13
- # include <netinet/in.h>
14
- # include <arpa/inet.h>
15
- #else
16
- # include <winsock2.h>
17
- # include <ws2tcpip.h>
18
- # ifdef _MSC_VER
19
- # pragma comment(lib, "ws2_32")
20
- # endif
21
- #endif
22
-
23
- #ifdef GIT_SSL
24
- # include <openssl/ssl.h>
25
- # include <openssl/err.h>
26
- # include <openssl/x509v3.h>
27
- #endif
28
7
 
29
8
  #include <ctype.h>
30
9
  #include "git2/errors.h"
@@ -36,136 +15,46 @@
36
15
  #include "http_parser.h"
37
16
  #include "global.h"
38
17
 
39
- #ifdef GIT_WIN32
40
- static void net_set_error(const char *str)
41
- {
42
- int error = WSAGetLastError();
43
- char * win32_error = git_win32_get_error_message(error);
44
-
45
- if (win32_error) {
46
- giterr_set(GITERR_NET, "%s: %s", str, win32_error);
47
- git__free(win32_error);
48
- } else {
49
- giterr_set(GITERR_NET, str);
50
- }
51
- }
52
- #else
53
- static void net_set_error(const char *str)
54
- {
55
- giterr_set(GITERR_NET, "%s: %s", str, strerror(errno));
56
- }
57
- #endif
58
-
59
- #ifdef GIT_SSL
60
- static int ssl_set_error(gitno_ssl *ssl, int error)
61
- {
62
- int err;
63
- unsigned long e;
64
-
65
- err = SSL_get_error(ssl->ssl, error);
66
-
67
- assert(err != SSL_ERROR_WANT_READ);
68
- assert(err != SSL_ERROR_WANT_WRITE);
69
-
70
- switch (err) {
71
- case SSL_ERROR_WANT_CONNECT:
72
- case SSL_ERROR_WANT_ACCEPT:
73
- giterr_set(GITERR_NET, "SSL error: connection failure\n");
74
- break;
75
- case SSL_ERROR_WANT_X509_LOOKUP:
76
- giterr_set(GITERR_NET, "SSL error: x509 error\n");
77
- break;
78
- case SSL_ERROR_SYSCALL:
79
- e = ERR_get_error();
80
- if (e > 0) {
81
- giterr_set(GITERR_NET, "SSL error: %s",
82
- ERR_error_string(e, NULL));
83
- break;
84
- } else if (error < 0) {
85
- giterr_set(GITERR_OS, "SSL error: syscall failure");
86
- break;
87
- }
88
- giterr_set(GITERR_NET, "SSL error: received early EOF");
89
- break;
90
- case SSL_ERROR_SSL:
91
- e = ERR_get_error();
92
- giterr_set(GITERR_NET, "SSL error: %s",
93
- ERR_error_string(e, NULL));
94
- break;
95
- case SSL_ERROR_NONE:
96
- case SSL_ERROR_ZERO_RETURN:
97
- default:
98
- giterr_set(GITERR_NET, "SSL error: unknown error");
99
- break;
100
- }
101
- return -1;
102
- }
103
- #endif
104
-
105
18
  int gitno_recv(gitno_buffer *buf)
106
19
  {
107
20
  return buf->recv(buf);
108
21
  }
109
22
 
110
- #ifdef GIT_SSL
111
- static int gitno__recv_ssl(gitno_buffer *buf)
23
+ void gitno_buffer_setup_callback(
24
+ gitno_buffer *buf,
25
+ char *data,
26
+ size_t len,
27
+ int (*recv)(gitno_buffer *buf), void *cb_data)
112
28
  {
113
- int ret;
114
-
115
- do {
116
- ret = SSL_read(buf->socket->ssl.ssl, buf->data + buf->offset, buf->len - buf->offset);
117
- } while (SSL_get_error(buf->socket->ssl.ssl, ret) == SSL_ERROR_WANT_READ);
118
-
119
- if (ret < 0) {
120
- net_set_error("Error receiving socket data");
121
- return -1;
122
- }
123
-
124
- buf->offset += ret;
125
- return ret;
29
+ memset(data, 0x0, len);
30
+ buf->data = data;
31
+ buf->len = len;
32
+ buf->offset = 0;
33
+ buf->recv = recv;
34
+ buf->cb_data = cb_data;
126
35
  }
127
- #endif
128
36
 
129
- static int gitno__recv(gitno_buffer *buf)
37
+ static int recv_stream(gitno_buffer *buf)
130
38
  {
39
+ git_stream *io = (git_stream *) buf->cb_data;
131
40
  int ret;
132
41
 
133
- ret = p_recv(buf->socket->socket, buf->data + buf->offset, buf->len - buf->offset, 0);
134
- if (ret < 0) {
135
- net_set_error("Error receiving socket data");
42
+ ret = git_stream_read(io, buf->data + buf->offset, buf->len - buf->offset);
43
+ if (ret < 0)
136
44
  return -1;
137
- }
138
45
 
139
46
  buf->offset += ret;
140
47
  return ret;
141
48
  }
142
49
 
143
- void gitno_buffer_setup_callback(
144
- gitno_socket *socket,
145
- gitno_buffer *buf,
146
- char *data,
147
- size_t len,
148
- int (*recv)(gitno_buffer *buf), void *cb_data)
50
+ void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len)
149
51
  {
150
52
  memset(data, 0x0, len);
151
53
  buf->data = data;
152
54
  buf->len = len;
153
55
  buf->offset = 0;
154
- buf->socket = socket;
155
- buf->recv = recv;
156
- buf->cb_data = cb_data;
157
- }
158
-
159
- void gitno_buffer_setup(gitno_socket *socket, gitno_buffer *buf, char *data, size_t len)
160
- {
161
- #ifdef GIT_SSL
162
- if (socket->ssl.ssl) {
163
- gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv_ssl, NULL);
164
- return;
165
- }
166
- #endif
167
-
168
- gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv, NULL);
56
+ buf->recv = recv_stream;
57
+ buf->cb_data = st;
169
58
  }
170
59
 
171
60
  /* Consume up to ptr and move the rest of the buffer to the beginning */
@@ -191,24 +80,6 @@ void gitno_consume_n(gitno_buffer *buf, size_t cons)
191
80
  buf->offset -= cons;
192
81
  }
193
82
 
194
- #ifdef GIT_SSL
195
-
196
- static int gitno_ssl_teardown(gitno_ssl *ssl)
197
- {
198
- int ret;
199
-
200
- ret = SSL_shutdown(ssl->ssl);
201
- if (ret < 0)
202
- ret = ssl_set_error(ssl, ret);
203
- else
204
- ret = 0;
205
-
206
- SSL_free(ssl->ssl);
207
- return ret;
208
- }
209
-
210
- #endif
211
-
212
83
  /* Match host names according to RFC 2818 rules */
213
84
  int gitno__match_host(const char *pattern, const char *host)
214
85
  {
@@ -248,333 +119,6 @@ int gitno__match_host(const char *pattern, const char *host)
248
119
  return -1;
249
120
  }
250
121
 
251
- static int check_host_name(const char *name, const char *host)
252
- {
253
- if (!strcasecmp(name, host))
254
- return 0;
255
-
256
- if (gitno__match_host(name, host) < 0)
257
- return -1;
258
-
259
- return 0;
260
- }
261
-
262
- #ifdef GIT_SSL
263
-
264
- static int verify_server_cert(gitno_ssl *ssl, const char *host)
265
- {
266
- X509 *cert;
267
- X509_NAME *peer_name;
268
- ASN1_STRING *str;
269
- unsigned char *peer_cn = NULL;
270
- int matched = -1, type = GEN_DNS;
271
- GENERAL_NAMES *alts;
272
- struct in6_addr addr6;
273
- struct in_addr addr4;
274
- void *addr;
275
- int i = -1,j;
276
-
277
- if (SSL_get_verify_result(ssl->ssl) != X509_V_OK) {
278
- giterr_set(GITERR_SSL, "The SSL certificate is invalid");
279
- return GIT_ECERTIFICATE;
280
- }
281
-
282
- /* Try to parse the host as an IP address to see if it is */
283
- if (p_inet_pton(AF_INET, host, &addr4)) {
284
- type = GEN_IPADD;
285
- addr = &addr4;
286
- } else {
287
- if(p_inet_pton(AF_INET6, host, &addr6)) {
288
- type = GEN_IPADD;
289
- addr = &addr6;
290
- }
291
- }
292
-
293
-
294
- cert = SSL_get_peer_certificate(ssl->ssl);
295
- if (!cert) {
296
- giterr_set(GITERR_SSL, "the server did not provide a certificate");
297
- return -1;
298
- }
299
-
300
- /* Check the alternative names */
301
- alts = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
302
- if (alts) {
303
- int num;
304
-
305
- num = sk_GENERAL_NAME_num(alts);
306
- for (i = 0; i < num && matched != 1; i++) {
307
- const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i);
308
- const char *name = (char *) ASN1_STRING_data(gn->d.ia5);
309
- size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5);
310
-
311
- /* Skip any names of a type we're not looking for */
312
- if (gn->type != type)
313
- continue;
314
-
315
- if (type == GEN_DNS) {
316
- /* If it contains embedded NULs, don't even try */
317
- if (memchr(name, '\0', namelen))
318
- continue;
319
-
320
- if (check_host_name(name, host) < 0)
321
- matched = 0;
322
- else
323
- matched = 1;
324
- } else if (type == GEN_IPADD) {
325
- /* Here name isn't so much a name but a binary representation of the IP */
326
- matched = !!memcmp(name, addr, namelen);
327
- }
328
- }
329
- }
330
- GENERAL_NAMES_free(alts);
331
-
332
- if (matched == 0)
333
- goto cert_fail_name;
334
-
335
- if (matched == 1)
336
- return 0;
337
-
338
- /* If no alternative names are available, check the common name */
339
- peer_name = X509_get_subject_name(cert);
340
- if (peer_name == NULL)
341
- goto on_error;
342
-
343
- if (peer_name) {
344
- /* Get the index of the last CN entry */
345
- while ((j = X509_NAME_get_index_by_NID(peer_name, NID_commonName, i)) >= 0)
346
- i = j;
347
- }
348
-
349
- if (i < 0)
350
- goto on_error;
351
-
352
- str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(peer_name, i));
353
- if (str == NULL)
354
- goto on_error;
355
-
356
- /* Work around a bug in OpenSSL whereby ASN1_STRING_to_UTF8 fails if it's already in utf-8 */
357
- if (ASN1_STRING_type(str) == V_ASN1_UTF8STRING) {
358
- int size = ASN1_STRING_length(str);
359
-
360
- if (size > 0) {
361
- peer_cn = OPENSSL_malloc(size + 1);
362
- GITERR_CHECK_ALLOC(peer_cn);
363
- memcpy(peer_cn, ASN1_STRING_data(str), size);
364
- peer_cn[size] = '\0';
365
- }
366
- } else {
367
- int size = ASN1_STRING_to_UTF8(&peer_cn, str);
368
- GITERR_CHECK_ALLOC(peer_cn);
369
- if (memchr(peer_cn, '\0', size))
370
- goto cert_fail_name;
371
- }
372
-
373
- if (check_host_name((char *)peer_cn, host) < 0)
374
- goto cert_fail_name;
375
-
376
- OPENSSL_free(peer_cn);
377
-
378
- return 0;
379
-
380
- on_error:
381
- OPENSSL_free(peer_cn);
382
- return ssl_set_error(ssl, 0);
383
-
384
- cert_fail_name:
385
- OPENSSL_free(peer_cn);
386
- giterr_set(GITERR_SSL, "hostname does not match certificate");
387
- return GIT_ECERTIFICATE;
388
- }
389
-
390
- static int ssl_setup(gitno_socket *socket, const char *host)
391
- {
392
- int ret;
393
-
394
- if (git__ssl_ctx == NULL) {
395
- giterr_set(GITERR_NET, "OpenSSL initialization failed");
396
- return -1;
397
- }
398
-
399
- socket->ssl.ssl = SSL_new(git__ssl_ctx);
400
- if (socket->ssl.ssl == NULL)
401
- return ssl_set_error(&socket->ssl, 0);
402
-
403
- if((ret = SSL_set_fd(socket->ssl.ssl, socket->socket)) == 0)
404
- return ssl_set_error(&socket->ssl, ret);
405
-
406
- if ((ret = SSL_connect(socket->ssl.ssl)) <= 0)
407
- return ssl_set_error(&socket->ssl, ret);
408
-
409
- return verify_server_cert(&socket->ssl, host);
410
- }
411
- #endif
412
-
413
- static int gitno__close(GIT_SOCKET s)
414
- {
415
- #ifdef GIT_WIN32
416
- if (SOCKET_ERROR == closesocket(s))
417
- return -1;
418
-
419
- if (0 != WSACleanup()) {
420
- giterr_set(GITERR_OS, "Winsock cleanup failed");
421
- return -1;
422
- }
423
-
424
- return 0;
425
- #else
426
- return close(s);
427
- #endif
428
- }
429
-
430
- int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int flags)
431
- {
432
- struct addrinfo *info = NULL, *p;
433
- struct addrinfo hints;
434
- GIT_SOCKET s = INVALID_SOCKET;
435
- int ret;
436
-
437
- #ifdef GIT_WIN32
438
- /* on win32, the WSA context needs to be initialized
439
- * before any socket calls can be performed */
440
- WSADATA wsd;
441
-
442
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
443
- giterr_set(GITERR_OS, "Winsock init failed");
444
- return -1;
445
- }
446
-
447
- if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) {
448
- WSACleanup();
449
- giterr_set(GITERR_OS, "Winsock init failed");
450
- return -1;
451
- }
452
- #endif
453
-
454
- /* Zero the socket structure provided */
455
- memset(s_out, 0x0, sizeof(gitno_socket));
456
-
457
- memset(&hints, 0x0, sizeof(struct addrinfo));
458
- hints.ai_socktype = SOCK_STREAM;
459
- hints.ai_family = AF_UNSPEC;
460
-
461
- if ((ret = p_getaddrinfo(host, port, &hints, &info)) != 0) {
462
- giterr_set(GITERR_NET,
463
- "Failed to resolve address for %s: %s", host, p_gai_strerror(ret));
464
- return -1;
465
- }
466
-
467
- for (p = info; p != NULL; p = p->ai_next) {
468
- s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
469
-
470
- if (s == INVALID_SOCKET) {
471
- net_set_error("error creating socket");
472
- break;
473
- }
474
-
475
- if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0)
476
- break;
477
-
478
- /* If we can't connect, try the next one */
479
- gitno__close(s);
480
- s = INVALID_SOCKET;
481
- }
482
-
483
- /* Oops, we couldn't connect to any address */
484
- if (s == INVALID_SOCKET && p == NULL) {
485
- giterr_set(GITERR_OS, "Failed to connect to %s", host);
486
- p_freeaddrinfo(info);
487
- return -1;
488
- }
489
-
490
- s_out->socket = s;
491
- p_freeaddrinfo(info);
492
-
493
- #ifdef GIT_SSL
494
- if ((flags & GITNO_CONNECT_SSL) &&
495
- (ret = ssl_setup(s_out, host)) < 0)
496
- return ret;
497
- #else
498
- /* SSL is not supported */
499
- if (flags & GITNO_CONNECT_SSL) {
500
- giterr_set(GITERR_OS, "SSL is not supported by this copy of libgit2.");
501
- return -1;
502
- }
503
- #endif
504
-
505
- return 0;
506
- }
507
-
508
- #ifdef GIT_SSL
509
- static int gitno_send_ssl(gitno_ssl *ssl, const char *msg, size_t len, int flags)
510
- {
511
- int ret;
512
- size_t off = 0;
513
-
514
- GIT_UNUSED(flags);
515
-
516
- while (off < len) {
517
- ret = SSL_write(ssl->ssl, msg + off, len - off);
518
- if (ret <= 0 && ret != SSL_ERROR_WANT_WRITE)
519
- return ssl_set_error(ssl, ret);
520
-
521
- off += ret;
522
- }
523
-
524
- return off;
525
- }
526
- #endif
527
-
528
- int gitno_send(gitno_socket *socket, const char *msg, size_t len, int flags)
529
- {
530
- int ret;
531
- size_t off = 0;
532
-
533
- #ifdef GIT_SSL
534
- if (socket->ssl.ssl)
535
- return gitno_send_ssl(&socket->ssl, msg, len, flags);
536
- #endif
537
-
538
- while (off < len) {
539
- errno = 0;
540
- ret = p_send(socket->socket, msg + off, len - off, flags);
541
- if (ret < 0) {
542
- net_set_error("Error sending data");
543
- return -1;
544
- }
545
-
546
- off += ret;
547
- }
548
-
549
- return (int)off;
550
- }
551
-
552
- int gitno_close(gitno_socket *s)
553
- {
554
- #ifdef GIT_SSL
555
- if (s->ssl.ssl &&
556
- gitno_ssl_teardown(&s->ssl) < 0)
557
- return -1;
558
- #endif
559
-
560
- return gitno__close(s->socket);
561
- }
562
-
563
- int gitno_select_in(gitno_buffer *buf, long int sec, long int usec)
564
- {
565
- fd_set fds;
566
- struct timeval tv;
567
-
568
- tv.tv_sec = sec;
569
- tv.tv_usec = usec;
570
-
571
- FD_ZERO(&fds);
572
- FD_SET(buf->socket->socket, &fds);
573
-
574
- /* The select(2) interface is silly */
575
- return select((int)buf->socket->socket + 1, &fds, NULL, NULL, &tv);
576
- }
577
-
578
122
  static const char *prefix_http = "http://";
579
123
  static const char *prefix_https = "https://";
580
124