rugged 0.21.1b0 → 0.21.1b1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 71c12ca95964095a5400cc76eeb9b98c1c116a69
4
- data.tar.gz: 752fefe7898903eeeef4139198eb6a719b044059
3
+ metadata.gz: 9ed02879508a982b7b663a4f5231c57547e41fae
4
+ data.tar.gz: d37846bf7d551e08dfea3e9d85df6c7728e6b9c5
5
5
  SHA512:
6
- metadata.gz: 4b16dedcf38b935c0d7a17c3b4c34c11f3280dafc6247f6b8ce88fa81e1f66696b3e2ae695405f75e3f8cc9c45eeff8017375156b6328fc3c8f285d31f3d1043
7
- data.tar.gz: 3b0f3d1bc1f12cf4f8f65cafc7ea4028239787225e0b04aa5e9476e85171dcf5ed0e1621b03eb070fa2273d3c7a5307932a82602b5cc2e76972b5fd54af676cd
6
+ metadata.gz: 69c90b7d81884a885b6ce51a3343b6220b16e3161b67da4b90c651a8f7cf0a220c9dd4ff9a39b4de976a359479abae266e0f23b80cac35382fd4f7ad9c00134f
7
+ data.tar.gz: 42ecdf50faf6fac65888223902d763753df78095af2eeb6d010297541f6d03d1d9ffdf55ec8f786232321fdff4221c25df0c26a7d8f8d5b654a550b04a14d131
@@ -756,7 +756,7 @@ static VALUE rb_git_index_readtree(VALUE self, VALUE rb_tree)
756
756
  * :recurse_untracked_dirs ::
757
757
  * Even if +:include_untracked+ is true, untracked directories will only be
758
758
  * marked with a single entry in the diff. If this flag is set to true,
759
- * all files under ignored directories will be included in the di ff, too.
759
+ * all files under ignored directories will be included in the diff, too.
760
760
  *
761
761
  * :disable_pathspec_match ::
762
762
  * If true, the given +:paths+ will be applied as exact matches, instead of
@@ -29,7 +29,7 @@ extern VALUE rb_cRuggedRepo;
29
29
  extern VALUE rb_eRuggedError;
30
30
  VALUE rb_cRuggedRemote;
31
31
 
32
- #define RUGGED_REMOTE_CALLBACKS_INIT {1, progress_cb, NULL, credentials_cb, transfer_progress_cb, update_tips_cb, NULL}
32
+ #define RUGGED_REMOTE_CALLBACKS_INIT {1, progress_cb, NULL, credentials_cb, NULL, transfer_progress_cb, update_tips_cb, NULL}
33
33
 
34
34
  static int progress_cb(const char *str, int len, void *data)
35
35
  {
@@ -1,3 +1,3 @@
1
1
  module Rugged
2
- Version = VERSION = '0.21.1b0'
2
+ Version = VERSION = '0.21.1b1'
3
3
  end
@@ -42,6 +42,7 @@ typedef enum {
42
42
  GIT_ELOCKED = -14, /**< Lock file prevented operation */
43
43
  GIT_EMODIFIED = -15, /**< Reference value does not match expected */
44
44
  GIT_EAUTH = -16, /**< Authentication error */
45
+ GIT_ECERTIFICATE = -17, /**< Server certificate is invalid */
45
46
 
46
47
  GIT_PASSTHROUGH = -30, /**< Internal only */
47
48
  GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
@@ -407,14 +407,6 @@ GIT_EXTERN(int) git_remote_supported_url(const char* url);
407
407
  */
408
408
  GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo);
409
409
 
410
- /**
411
- * Choose whether to check the server's certificate (applies to HTTPS only)
412
- *
413
- * @param remote the remote to configure
414
- * @param check whether to check the server's certificate (defaults to yes)
415
- */
416
- GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check);
417
-
418
410
  /**
419
411
  * Argument to the completion callback which tells it which operation
420
412
  * finished.
@@ -455,6 +447,14 @@ struct git_remote_callbacks {
455
447
  */
456
448
  git_cred_acquire_cb credentials;
457
449
 
450
+ /**
451
+ * If cert verification fails, this will be called to let the
452
+ * user make the final decision of whether to allow the
453
+ * connection to proceed. Returns 1 to allow the connection, 0
454
+ * to disallow it or a negative value to indicate an error.
455
+ */
456
+ git_transport_certificate_check_cb certificate_check;
457
+
458
458
  /**
459
459
  * During the download of new data, this will be regularly
460
460
  * called with the current count of progress done by the
@@ -119,6 +119,19 @@ GIT_EXTERN(void) git_repository_set_refdb(git_repository *repo, git_refdb *refdb
119
119
  */
120
120
  GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index);
121
121
 
122
+ /**
123
+ * Set a repository to be bare.
124
+ *
125
+ * Clear the working directory and set core.bare to true. You may also
126
+ * want to call `git_repository_set_index(repo, NULL)` since a bare repo
127
+ * typically does not have an index, but this function will not do that
128
+ * for you.
129
+ *
130
+ * @param repo Repo to make bare
131
+ * @return 0 on success, <0 on failure
132
+ */
133
+ GIT_EXTERN(int) git_repository_set_bare(git_repository *repo);
134
+
122
135
  /** @} */
123
136
  GIT_END_DECL
124
137
  #endif
@@ -23,9 +23,6 @@ GIT_BEGIN_DECL
23
23
 
24
24
  typedef enum {
25
25
  GIT_TRANSPORTFLAGS_NONE = 0,
26
- /* If the connection is secured with SSL/TLS, the authenticity
27
- * of the server certificate should not be verified. */
28
- GIT_TRANSPORTFLAGS_NO_CHECK_CERT = 1
29
26
  } git_transport_flags_t;
30
27
 
31
28
  typedef struct git_transport git_transport;
@@ -37,6 +34,7 @@ struct git_transport {
37
34
  git_transport *transport,
38
35
  git_transport_message_cb progress_cb,
39
36
  git_transport_message_cb error_cb,
37
+ git_transport_certificate_check_cb certificate_check_cb,
40
38
  void *payload);
41
39
 
42
40
  /* Connect the transport to the remote repository, using the given
@@ -20,6 +20,67 @@
20
20
  */
21
21
  GIT_BEGIN_DECL
22
22
 
23
+ /**
24
+ * Type of SSH host fingerprint
25
+ */
26
+ typedef enum {
27
+ /** MD5 is available */
28
+ GIT_CERT_SSH_MD5 = (1 << 0),
29
+ /** SHA-1 is available */
30
+ GIT_CERT_SSH_SHA1 = (1 << 1),
31
+ } git_cert_ssh_t;
32
+
33
+ /**
34
+ * Hostkey information taken from libssh2
35
+ */
36
+ typedef struct {
37
+ /**
38
+ * Type of certificate. Here to share the header with
39
+ * `git_cert`.
40
+ */
41
+ git_cert_t cert_type;
42
+ /**
43
+ * A hostkey type from libssh2, either
44
+ * `GIT_CERT_SSH_MD5` or `GIT_CERT_SSH_SHA1`
45
+ */
46
+ git_cert_ssh_t type;
47
+
48
+ /**
49
+ * Hostkey hash. If type has `GIT_CERT_SSH_MD5` set, this will
50
+ * have the MD5 hash of the hostkey.
51
+ */
52
+ unsigned char hash_md5[16];
53
+
54
+ /**
55
+ * Hostkey hash. If type has `GIT_CERT_SSH_SHA1` set, this will
56
+ * have the SHA-1 hash of the hostkey.
57
+ */
58
+ unsigned char hash_sha1[20];
59
+ } git_cert_hostkey;
60
+
61
+ /**
62
+ * X.509 certificate information
63
+ */
64
+ typedef struct {
65
+ /**
66
+ * Type of certificate. Here to share the header with
67
+ * `git_cert`.
68
+ */
69
+ git_cert_t cert_type;
70
+ /**
71
+ * Pointer to the X.509 certificate data
72
+ */
73
+ void *data;
74
+ /**
75
+ * Length of the memory block pointed to by `data`.
76
+ */
77
+ size_t len;
78
+ } git_cert_x509;
79
+
80
+ /*
81
+ *** Begin interface for credentials acquisition ***
82
+ */
83
+
23
84
  /** Authentication type requested */
24
85
  typedef enum {
25
86
  /* git_cred_userpass_plaintext */
@@ -253,6 +253,44 @@ typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void
253
253
  */
254
254
  typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
255
255
 
256
+ /**
257
+ * Type of host certificate structure that is passed to the check callback
258
+ */
259
+ typedef enum git_cert_t {
260
+ /**
261
+ * The `data` argument to the callback will be a pointer to
262
+ * the DER-encoded data.
263
+ */
264
+ GIT_CERT_X509,
265
+ /**
266
+ * The `data` argument to the callback will be a pointer to a
267
+ * `git_cert_hostkey` structure.
268
+ */
269
+ GIT_CERT_HOSTKEY_LIBSSH2,
270
+ } git_cert_t;
271
+
272
+ /**
273
+ * Parent type for `git_cert_hostkey` and `git_cert_x509`.
274
+ */
275
+ typedef struct {
276
+ /**
277
+ * Type of certificate. A `GIT_CERT_` value.
278
+ */
279
+ git_cert_t cert_type;
280
+ } git_cert;
281
+
282
+ /**
283
+ * Callback for the user's custom certificate checks.
284
+ *
285
+ * @param type The type of certificate or host info, SSH or X.509
286
+ * @param data The data for the certificate or host info
287
+ * @param len The size of the certificate or host info
288
+ * @param valid Whether the libgit2 checks (OpenSSL or WinHTTP) think
289
+ * this certificate is valid
290
+ * @param payload Payload provided by the caller
291
+ */
292
+ typedef int (*git_transport_certificate_check_cb)(git_cert *cert, int valid, void *payload);
293
+
256
294
  /**
257
295
  * Opaque structure representing a submodule.
258
296
  */
@@ -377,7 +377,7 @@ static int push_attr_file(
377
377
  return error;
378
378
  }
379
379
 
380
- static int push_one_attr(void *ref, git_buf *path)
380
+ static int push_one_attr(void *ref, const char *path)
381
381
  {
382
382
  int error = 0, n_src, i;
383
383
  attr_walk_up_info *info = (attr_walk_up_info *)ref;
@@ -388,7 +388,7 @@ static int push_one_attr(void *ref, git_buf *path)
388
388
 
389
389
  for (i = 0; !error && i < n_src; ++i)
390
390
  error = push_attr_file(
391
- info->repo, info->files, src[i], path->ptr, GIT_ATTR_FILE);
391
+ info->repo, info->files, src[i], path, GIT_ATTR_FILE);
392
392
 
393
393
  return error;
394
394
  }
@@ -411,7 +411,7 @@ static int collect_attr_files(
411
411
  const char *path,
412
412
  git_vector *files)
413
413
  {
414
- int error;
414
+ int error = 0;
415
415
  git_buf dir = GIT_BUF_INIT;
416
416
  const char *workdir = git_repository_workdir(repo);
417
417
  attr_walk_up_info info = { NULL };
@@ -447,7 +447,11 @@ static int collect_attr_files(
447
447
  giterr_clear(); /* no error even if there is no index */
448
448
  info.files = files;
449
449
 
450
- error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
450
+ if (!strcmp(dir.ptr, "."))
451
+ error = push_one_attr(&info, "");
452
+ else
453
+ error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
454
+
451
455
  if (error < 0)
452
456
  goto cleanup;
453
457
 
@@ -505,15 +505,15 @@ static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
505
505
  return error;
506
506
  }
507
507
 
508
- static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
508
+ static int futils__rmdir_empty_parent(void *opaque, const char *path)
509
509
  {
510
510
  futils__rmdir_data *data = opaque;
511
511
  int error = 0;
512
512
 
513
- if (git_buf_len(path) <= data->baselen)
513
+ if (strlen(path) <= data->baselen)
514
514
  error = GIT_ITEROVER;
515
515
 
516
- else if (p_rmdir(git_buf_cstr(path)) < 0) {
516
+ else if (p_rmdir(path) < 0) {
517
517
  int en = errno;
518
518
 
519
519
  if (en == ENOENT || en == ENOTDIR) {
@@ -521,7 +521,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path)
521
521
  } else if (en == ENOTEMPTY || en == EEXIST || en == EBUSY) {
522
522
  error = GIT_ITEROVER;
523
523
  } else {
524
- error = git_path_set_error(errno, git_buf_cstr(path), "rmdir");
524
+ error = git_path_set_error(errno, path, "rmdir");
525
525
  }
526
526
  }
527
527
 
@@ -91,11 +91,11 @@ static int push_ignore_file(
91
91
  return error;
92
92
  }
93
93
 
94
- static int push_one_ignore(void *payload, git_buf *path)
94
+ static int push_one_ignore(void *payload, const char *path)
95
95
  {
96
96
  git_ignores *ign = payload;
97
97
  ign->depth++;
98
- return push_ignore_file(ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
98
+ return push_ignore_file(ign, &ign->ign_path, path, GIT_IGNORE_FILE);
99
99
  }
100
100
 
101
101
  static int get_internal_ignores(git_attr_file **out, git_repository *repo)
@@ -2338,7 +2338,6 @@ done:
2338
2338
 
2339
2339
  static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths)
2340
2340
  {
2341
- git_index *index_repo = NULL;
2342
2341
  git_diff *wd_diff_list = NULL;
2343
2342
  git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
2344
2343
  int error = 0;
@@ -2347,6 +2346,16 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
2347
2346
 
2348
2347
  *conflicts = 0;
2349
2348
 
2349
+ /* We need to have merged at least 1 file for the possibility to exist to
2350
+ * have conflicts with the workdir. Passing 0 as the pathspec count paramter
2351
+ * will consider all files in the working directory, that is, we may detect
2352
+ * a conflict if there were untracked files in the workdir prior to starting
2353
+ * the merge. This typically happens when cherry-picking a commmit whose
2354
+ * changes have already been applied.
2355
+ */
2356
+ if (merged_paths->length == 0)
2357
+ return 0;
2358
+
2350
2359
  opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
2351
2360
 
2352
2361
  /* Workdir changes may exist iff they do not conflict with changes that
@@ -2356,13 +2365,12 @@ static int merge_check_workdir(size_t *conflicts, git_repository *repo, git_inde
2356
2365
  opts.pathspec.count = merged_paths->length;
2357
2366
  opts.pathspec.strings = (char **)merged_paths->contents;
2358
2367
 
2359
- if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, index_repo, &opts)) < 0)
2368
+ if ((error = git_diff_index_to_workdir(&wd_diff_list, repo, NULL, &opts)) < 0)
2360
2369
  goto done;
2361
2370
 
2362
2371
  *conflicts = wd_diff_list->deltas.length;
2363
2372
 
2364
2373
  done:
2365
- git_index_free(index_repo);
2366
2374
  git_diff_free(wd_diff_list);
2367
2375
 
2368
2376
  return error;
@@ -384,10 +384,10 @@ on_error:
384
384
  cert_fail_name:
385
385
  OPENSSL_free(peer_cn);
386
386
  giterr_set(GITERR_SSL, "hostname does not match certificate");
387
- return -1;
387
+ return GIT_ECERTIFICATE;
388
388
  }
389
389
 
390
- static int ssl_setup(gitno_socket *socket, const char *host, int flags)
390
+ static int ssl_setup(gitno_socket *socket, const char *host)
391
391
  {
392
392
  int ret;
393
393
 
@@ -406,9 +406,6 @@ static int ssl_setup(gitno_socket *socket, const char *host, int flags)
406
406
  if ((ret = SSL_connect(socket->ssl.ssl)) <= 0)
407
407
  return ssl_set_error(&socket->ssl, ret);
408
408
 
409
- if (GITNO_CONNECT_SSL_NO_CHECK_CERT & flags)
410
- return 0;
411
-
412
409
  return verify_server_cert(&socket->ssl, host);
413
410
  }
414
411
  #endif
@@ -494,8 +491,9 @@ int gitno_connect(gitno_socket *s_out, const char *host, const char *port, int f
494
491
  p_freeaddrinfo(info);
495
492
 
496
493
  #ifdef GIT_SSL
497
- if ((flags & GITNO_CONNECT_SSL) && ssl_setup(s_out, host, flags) < 0)
498
- return -1;
494
+ if ((flags & GITNO_CONNECT_SSL) &&
495
+ (ret = ssl_setup(s_out, host)) < 0)
496
+ return ret;
499
497
  #else
500
498
  /* SSL is not supported */
501
499
  if (flags & GITNO_CONNECT_SSL) {
@@ -47,10 +47,6 @@ typedef struct gitno_buffer gitno_buffer;
47
47
  enum {
48
48
  /* Attempt to create an SSL connection. */
49
49
  GITNO_CONNECT_SSL = 1,
50
-
51
- /* Valid only when GITNO_CONNECT_SSL is also specified.
52
- * Indicates that the server certificate should not be validated. */
53
- GITNO_CONNECT_SSL_NO_CHECK_CERT = 2,
54
50
  };
55
51
 
56
52
  /**
@@ -417,7 +417,7 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
417
417
  int git_path_walk_up(
418
418
  git_buf *path,
419
419
  const char *ceiling,
420
- int (*cb)(void *data, git_buf *),
420
+ int (*cb)(void *data, const char *),
421
421
  void *data)
422
422
  {
423
423
  int error = 0;
@@ -435,12 +435,20 @@ int git_path_walk_up(
435
435
  }
436
436
  scan = git_buf_len(path);
437
437
 
438
+ /* empty path: yield only once */
439
+ if (!scan) {
440
+ error = cb(data, "");
441
+ if (error)
442
+ giterr_set_after_callback(error);
443
+ return error;
444
+ }
445
+
438
446
  iter.ptr = path->ptr;
439
447
  iter.size = git_buf_len(path);
440
448
  iter.asize = path->asize;
441
449
 
442
450
  while (scan >= stop) {
443
- error = cb(data, &iter);
451
+ error = cb(data, iter.ptr);
444
452
  iter.ptr[scan] = oldc;
445
453
 
446
454
  if (error) {
@@ -460,6 +468,13 @@ int git_path_walk_up(
460
468
  if (scan >= 0)
461
469
  iter.ptr[scan] = oldc;
462
470
 
471
+ /* relative path: yield for the last component */
472
+ if (!error && stop == 0 && iter.ptr[0] != '/') {
473
+ error = cb(data, "");
474
+ if (error)
475
+ giterr_set_after_callback(error);
476
+ }
477
+
463
478
  return error;
464
479
  }
465
480
 
@@ -965,7 +980,7 @@ int git_path_direach(
965
980
  path_dirent_data de_data;
966
981
  struct dirent *de, *de_buf = (struct dirent *)&de_data;
967
982
 
968
- (void)flags;
983
+ GIT_UNUSED(flags);
969
984
 
970
985
  #ifdef GIT_USE_ICONV
971
986
  git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -1036,7 +1051,7 @@ int git_path_dirload(
1036
1051
  path_dirent_data de_data;
1037
1052
  struct dirent *de, *de_buf = (struct dirent *)&de_data;
1038
1053
 
1039
- (void)flags;
1054
+ GIT_UNUSED(flags);
1040
1055
 
1041
1056
  #ifdef GIT_USE_ICONV
1042
1057
  git_path_iconv_t ic = GIT_PATH_ICONV_INIT;
@@ -1088,8 +1103,10 @@ int git_path_dirload(
1088
1103
  entry_path[path_len] = '/';
1089
1104
  memcpy(&entry_path[path_len + need_slash], de_path, de_len);
1090
1105
 
1091
- if ((error = git_vector_insert(contents, entry_path)) < 0)
1106
+ if ((error = git_vector_insert(contents, entry_path)) < 0) {
1107
+ git__free(entry_path);
1092
1108
  break;
1109
+ }
1093
1110
  }
1094
1111
 
1095
1112
  closedir(dir);
@@ -323,7 +323,7 @@ extern int git_path_cmp(
323
323
  extern int git_path_walk_up(
324
324
  git_buf *pathbuf,
325
325
  const char *ceiling,
326
- int (*callback)(void *payload, git_buf *path),
326
+ int (*callback)(void *payload, const char *path),
327
327
  void *payload);
328
328
 
329
329
  /**
@@ -80,6 +80,8 @@ static int ensure_remote_name_is_valid(const char *name)
80
80
  return error;
81
81
  }
82
82
 
83
+ #if 0
84
+ /* We could export this as a helper */
83
85
  static int get_check_cert(int *out, git_repository *repo)
84
86
  {
85
87
  git_config *cfg;
@@ -105,6 +107,7 @@ static int get_check_cert(int *out, git_repository *repo)
105
107
  *out = git_config__get_bool_force(cfg, "http.sslverify", 1);
106
108
  return 0;
107
109
  }
110
+ #endif
108
111
 
109
112
  static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
110
113
  {
@@ -121,9 +124,6 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
121
124
  remote->repo = repo;
122
125
  remote->update_fetchhead = 1;
123
126
 
124
- if (get_check_cert(&remote->check_cert, repo) < 0)
125
- goto on_error;
126
-
127
127
  if (git_vector_init(&remote->refs, 32, NULL) < 0)
128
128
  goto on_error;
129
129
 
@@ -274,7 +274,6 @@ int git_remote_dup(git_remote **dest, git_remote *source)
274
274
  remote->transport_cb_payload = source->transport_cb_payload;
275
275
  remote->repo = source->repo;
276
276
  remote->download_tags = source->download_tags;
277
- remote->check_cert = source->check_cert;
278
277
  remote->update_fetchhead = source->update_fetchhead;
279
278
 
280
279
  if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
@@ -369,9 +368,6 @@ int git_remote_load(git_remote **out, git_repository *repo, const char *name)
369
368
  remote->name = git__strdup(name);
370
369
  GITERR_CHECK_ALLOC(remote->name);
371
370
 
372
- if ((error = get_check_cert(&remote->check_cert, repo)) < 0)
373
- goto cleanup;
374
-
375
371
  if (git_vector_init(&remote->refs, 32, NULL) < 0 ||
376
372
  git_vector_init(&remote->refspecs, 2, NULL) < 0 ||
377
373
  git_vector_init(&remote->active_refspecs, 2, NULL) < 0) {
@@ -673,12 +669,9 @@ int git_remote_connect(git_remote *remote, git_direction direction)
673
669
  return error;
674
670
 
675
671
  if (t->set_callbacks &&
676
- (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.payload)) < 0)
672
+ (error = t->set_callbacks(t, remote->callbacks.sideband_progress, NULL, remote->callbacks.certificate_check, remote->callbacks.payload)) < 0)
677
673
  goto on_error;
678
674
 
679
- if (!remote->check_cert)
680
- flags |= GIT_TRANSPORTFLAGS_NO_CHECK_CERT;
681
-
682
675
  if ((error = t->connect(t, url, remote->callbacks.credentials, remote->callbacks.payload, direction, flags)) != 0)
683
676
  goto on_error;
684
677
 
@@ -1065,16 +1058,20 @@ static int update_tips_for_spec(
1065
1058
  if (autotag && !git_odb_exists(odb, &head->oid))
1066
1059
  continue;
1067
1060
 
1068
- if (git_vector_insert(&update_heads, head) < 0)
1061
+ if (!autotag && git_vector_insert(&update_heads, head) < 0)
1069
1062
  goto on_error;
1070
1063
 
1071
1064
  error = git_reference_name_to_id(&old, remote->repo, refname.ptr);
1072
1065
  if (error < 0 && error != GIT_ENOTFOUND)
1073
1066
  goto on_error;
1074
1067
 
1075
- if (error == GIT_ENOTFOUND)
1068
+ if (error == GIT_ENOTFOUND) {
1076
1069
  memset(&old, 0, GIT_OID_RAWSZ);
1077
1070
 
1071
+ if (autotag && git_vector_insert(&update_heads, head) < 0)
1072
+ goto on_error;
1073
+ }
1074
+
1078
1075
  if (!git_oid__cmp(&old, &head->oid))
1079
1076
  continue;
1080
1077
 
@@ -1244,13 +1241,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
1244
1241
  return 0;
1245
1242
  }
1246
1243
 
1247
- void git_remote_check_cert(git_remote *remote, int check)
1248
- {
1249
- assert(remote);
1250
-
1251
- remote->check_cert = check;
1252
- }
1253
-
1254
1244
  int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks)
1255
1245
  {
1256
1246
  assert(remote && callbacks);
@@ -1263,6 +1253,7 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal
1263
1253
  return remote->transport->set_callbacks(remote->transport,
1264
1254
  remote->callbacks.sideband_progress,
1265
1255
  NULL,
1256
+ remote->callbacks.certificate_check,
1266
1257
  remote->callbacks.payload);
1267
1258
 
1268
1259
  return 0;
@@ -31,7 +31,6 @@ struct git_remote {
31
31
  git_transfer_progress stats;
32
32
  unsigned int need_pack;
33
33
  git_remote_autotag_option_t download_tags;
34
- int check_cert;
35
34
  int update_fetchhead;
36
35
  };
37
36
 
@@ -1681,6 +1681,32 @@ int git_repository_is_bare(git_repository *repo)
1681
1681
  return repo->is_bare;
1682
1682
  }
1683
1683
 
1684
+ int git_repository_set_bare(git_repository *repo)
1685
+ {
1686
+ int error;
1687
+ git_config *config;
1688
+
1689
+ assert(repo);
1690
+
1691
+ if (repo->is_bare)
1692
+ return 0;
1693
+
1694
+ if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1695
+ return error;
1696
+
1697
+ if ((error = git_config_set_bool(config, "core.bare", false)) < 0)
1698
+ return error;
1699
+
1700
+ if ((error = git_config__update_entry(config, "core.worktree", NULL, true, true)) < 0)
1701
+ return error;
1702
+
1703
+ git__free(repo->workdir);
1704
+ repo->workdir = NULL;
1705
+ repo->is_bare = 1;
1706
+
1707
+ return 0;
1708
+ }
1709
+
1684
1710
  int git_repository_head_tree(git_tree **tree, git_repository *repo)
1685
1711
  {
1686
1712
  git_reference *head;
@@ -19,6 +19,10 @@ git_http_auth_scheme auth_schemes[] = {
19
19
  { GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
20
20
  };
21
21
 
22
+ #ifdef GIT_SSL
23
+ # include <openssl/x509v3.h>
24
+ #endif
25
+
22
26
  static const char *upload_pack_service = "upload-pack";
23
27
  static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
24
28
  static const char *upload_pack_service_url = "/git-upload-pack";
@@ -524,7 +528,7 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
524
528
 
525
529
  static int http_connect(http_subtransport *t)
526
530
  {
527
- int flags = 0;
531
+ int flags = 0, error;
528
532
 
529
533
  if (t->connected &&
530
534
  http_should_keep_alive(&t->parser) &&
@@ -541,13 +545,55 @@ static int http_connect(http_subtransport *t)
541
545
  return -1;
542
546
 
543
547
  flags |= GITNO_CONNECT_SSL;
544
-
545
- if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & tflags)
546
- flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT;
547
548
  }
548
549
 
549
- if (gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags) < 0)
550
- return -1;
550
+ error = gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags);
551
+
552
+ #ifdef GIT_SSL
553
+ if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) {
554
+ X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl);
555
+ git_cert_x509 cert_info;
556
+ int len, is_valid;
557
+ unsigned char *guard, *encoded_cert;
558
+
559
+ /* Retrieve the length of the certificate first */
560
+ len = i2d_X509(cert, NULL);
561
+ if (len < 0) {
562
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
563
+ return -1;
564
+ }
565
+
566
+
567
+ encoded_cert = git__malloc(len);
568
+ GITERR_CHECK_ALLOC(encoded_cert);
569
+ /* i2d_X509 makes 'copy' point to just after the data */
570
+ guard = encoded_cert;
571
+
572
+ len = i2d_X509(cert, &guard);
573
+ if (len < 0) {
574
+ git__free(encoded_cert);
575
+ giterr_set(GITERR_NET, "failed to retrieve certificate information");
576
+ return -1;
577
+ }
578
+
579
+ giterr_clear();
580
+ is_valid = error != GIT_ECERTIFICATE;
581
+ cert_info.cert_type = GIT_CERT_X509;
582
+ cert_info.data = encoded_cert;
583
+ cert_info.len = len;
584
+ error = t->owner->certificate_check_cb((git_cert *) &cert_info, is_valid, t->owner->message_cb_payload);
585
+ git__free(encoded_cert);
586
+
587
+ if (error < 0) {
588
+ if (!giterr_last())
589
+ giterr_set(GITERR_NET, "user cancelled certificate check");
590
+
591
+ return error;
592
+ }
593
+ }
594
+ #endif
595
+ if (error < 0)
596
+ return error;
551
597
 
552
598
  t->connected = 1;
553
599
  return 0;
@@ -608,6 +654,7 @@ replay:
608
654
 
609
655
  while (!*bytes_read && !t->parse_finished) {
610
656
  size_t data_offset;
657
+ int error;
611
658
 
612
659
  /*
613
660
  * Make the parse_buffer think it's as full of data as
@@ -654,8 +701,8 @@ replay:
654
701
  if (PARSE_ERROR_REPLAY == t->parse_error) {
655
702
  s->sent_request = 0;
656
703
 
657
- if (http_connect(t) < 0)
658
- return -1;
704
+ if ((error = http_connect(t)) < 0)
705
+ return error;
659
706
 
660
707
  goto replay;
661
708
  }
@@ -907,8 +954,8 @@ static int http_action(
907
954
  (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0)
908
955
  return ret;
909
956
 
910
- if (http_connect(t) < 0)
911
- return -1;
957
+ if ((ret = http_connect(t)) < 0)
958
+ return ret;
912
959
 
913
960
  switch (action) {
914
961
  case GIT_SERVICE_UPLOADPACK_LS:
@@ -53,12 +53,14 @@ static int git_smart__set_callbacks(
53
53
  git_transport *transport,
54
54
  git_transport_message_cb progress_cb,
55
55
  git_transport_message_cb error_cb,
56
+ git_transport_certificate_check_cb certificate_check_cb,
56
57
  void *message_cb_payload)
57
58
  {
58
59
  transport_smart *t = (transport_smart *)transport;
59
60
 
60
61
  t->progress_cb = progress_cb;
61
62
  t->error_cb = error_cb;
63
+ t->certificate_check_cb = certificate_check_cb;
62
64
  t->message_cb_payload = message_cb_payload;
63
65
 
64
66
  return 0;
@@ -137,6 +137,7 @@ typedef struct {
137
137
  int flags;
138
138
  git_transport_message_cb progress_cb;
139
139
  git_transport_message_cb error_cb;
140
+ git_transport_certificate_check_cb certificate_check_cb;
140
141
  void *message_cb_payload;
141
142
  git_smart_subtransport *wrapped;
142
143
  git_smart_subtransport_stream *current_stream;
@@ -473,6 +473,46 @@ static int _git_ssh_setup_conn(
473
473
  GITERR_CHECK_ALLOC(port);
474
474
  }
475
475
 
476
+ if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
477
+ goto on_error;
478
+
479
+ if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
480
+ goto on_error;
481
+
482
+ if (t->owner->certificate_check_cb != NULL) {
483
+ git_cert_hostkey cert = { 0 };
484
+ const char *key;
485
+
486
+ cert.cert_type = GIT_CERT_HOSTKEY_LIBSSH2;
487
+
488
+ key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
489
+ if (key != NULL) {
490
+ cert.type |= GIT_CERT_SSH_SHA1;
491
+ memcpy(&cert.hash_sha1, key, 20);
492
+ }
493
+
494
+ key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
495
+ if (key != NULL) {
496
+ cert.type |= GIT_CERT_SSH_MD5;
497
+ memcpy(&cert.hash_md5, key, 16);
498
+ }
499
+
500
+ if (cert.type == 0) {
501
+ giterr_set(GITERR_SSH, "unable to get the host key");
502
+ return -1;
503
+ }
504
+
505
+ /* We don't currently trust any hostkeys */
506
+ giterr_clear();
507
+ error = t->owner->certificate_check_cb((git_cert *) &cert, 0, t->owner->message_cb_payload);
508
+ if (error < 0) {
509
+ if (!giterr_last())
510
+ giterr_set(GITERR_NET, "user cancelled hostkey check");
511
+
512
+ goto on_error;
513
+ }
514
+ }
515
+
476
516
  /* we need the username to ask for auth methods */
477
517
  if (!user) {
478
518
  if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
@@ -488,12 +528,6 @@ static int _git_ssh_setup_conn(
488
528
  goto on_error;
489
529
  }
490
530
 
491
- if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
492
- goto on_error;
493
-
494
- if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
495
- goto on_error;
496
-
497
531
  if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
498
532
  goto on_error;
499
533
 
@@ -602,10 +636,8 @@ static int ssh_receivepack_ls(
602
636
  {
603
637
  const char *cmd = t->cmd_receivepack ? t->cmd_receivepack : cmd_receivepack;
604
638
 
605
- if (_git_ssh_setup_conn(t, url, cmd, stream) < 0)
606
- return -1;
607
639
 
608
- return 0;
640
+ return _git_ssh_setup_conn(t, url, cmd, stream);
609
641
  }
610
642
 
611
643
  static int ssh_receivepack(
@@ -16,6 +16,8 @@
16
16
  #include "remote.h"
17
17
  #include "repository.h"
18
18
 
19
+ #include <wincrypt.h>
20
+ #pragma comment(lib, "crypt32")
19
21
  #include <winhttp.h>
20
22
  #pragma comment(lib, "winhttp")
21
23
 
@@ -203,6 +205,39 @@ static int fallback_cred_acquire_cb(
203
205
  return error;
204
206
  }
205
207
 
208
+ static int certificate_check(winhttp_stream *s, int valid)
209
+ {
210
+ int error;
211
+ winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
212
+ PCERT_CONTEXT cert_ctx;
213
+ DWORD cert_ctx_size = sizeof(cert_ctx);
214
+ git_cert_x509 cert;
215
+
216
+ /* If there is no override, we should fail if WinHTTP doesn't think it's fine */
217
+ if (t->owner->certificate_check_cb == NULL && !valid)
218
+ return GIT_ECERTIFICATE;
219
+
220
+ if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl)
221
+ return 0;
222
+
223
+ if (!WinHttpQueryOption(s->request, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert_ctx, &cert_ctx_size)) {
224
+ giterr_set(GITERR_OS, "failed to get server certificate");
225
+ return -1;
226
+ }
227
+
228
+ giterr_clear();
229
+ cert.cert_type = GIT_CERT_X509;
230
+ cert.data = cert_ctx->pbCertEncoded;
231
+ cert.len = cert_ctx->cbCertEncoded;
232
+ error = t->owner->certificate_check_cb((git_cert *) &cert, valid, t->owner->cred_acquire_payload);
233
+ CertFreeCertificateContext(cert_ctx);
234
+
235
+ if (error < 0 && !giterr_last())
236
+ giterr_set(GITERR_NET, "user cancelled certificate check");
237
+
238
+ return error;
239
+ }
240
+
206
241
  static int winhttp_stream_connect(winhttp_stream *s)
207
242
  {
208
243
  winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
@@ -353,13 +388,6 @@ static int winhttp_stream_connect(winhttp_stream *s)
353
388
 
354
389
  if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
355
390
  goto on_error;
356
-
357
- if ((GIT_TRANSPORTFLAGS_NO_CHECK_CERT & flags) &&
358
- !WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS,
359
- (LPVOID)&no_check_cert_flags, sizeof(no_check_cert_flags))) {
360
- giterr_set(GITERR_OS, "Failed to set options to ignore cert errors");
361
- goto on_error;
362
- }
363
391
  }
364
392
 
365
393
  /* If we have a credential on the subtransport, apply it to the request */
@@ -527,6 +555,74 @@ on_error:
527
555
  return error;
528
556
  }
529
557
 
558
+ static int do_send_request(winhttp_stream *s, size_t len, int ignore_length)
559
+ {
560
+ int request_failed = 0, cert_valid = 1, error = 0;
561
+
562
+ if (ignore_length) {
563
+ if (!WinHttpSendRequest(s->request,
564
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
565
+ WINHTTP_NO_REQUEST_DATA, 0,
566
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
567
+ return -1;
568
+ }
569
+ } else {
570
+ if (!WinHttpSendRequest(s->request,
571
+ WINHTTP_NO_ADDITIONAL_HEADERS, 0,
572
+ WINHTTP_NO_REQUEST_DATA, 0,
573
+ len, 0)) {
574
+ return -1;
575
+ }
576
+ }
577
+
578
+ return 0;
579
+ }
580
+
581
+ static int send_request(winhttp_stream *s, size_t len, int ignore_length)
582
+ {
583
+ int request_failed = 0, cert_valid = 1, error = 0;
584
+ DWORD ignore_flags;
585
+
586
+ if ((error = do_send_request(s, len, ignore_length)) < 0)
587
+ request_failed = 1;
588
+
589
+ if (request_failed) {
590
+ if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
591
+ giterr_set(GITERR_OS, "failed to send request");
592
+ return -1;
593
+ } else {
594
+ cert_valid = 0;
595
+ }
596
+ }
597
+
598
+ giterr_clear();
599
+ if ((error = certificate_check(s, cert_valid)) < 0) {
600
+ if (!giterr_last())
601
+ giterr_set(GITERR_OS, "user cancelled certificate check");
602
+
603
+ return error;
604
+ }
605
+
606
+ /* if neither the request nor the certificate check returned errors, we're done */
607
+ if (!request_failed)
608
+ return 0;
609
+
610
+ ignore_flags =
611
+ SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
612
+ SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
613
+ SECURITY_FLAG_IGNORE_UNKNOWN_CA;
614
+
615
+ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
616
+ giterr_set(GITERR_OS, "failed to set security options");
617
+ return -1;
618
+ }
619
+
620
+ if ((error = do_send_request(s, len, ignore_length)) < 0)
621
+ giterr_set(GITERR_OS, "failed to send request");
622
+
623
+ return error;
624
+ }
625
+
530
626
  static int winhttp_stream_read(
531
627
  git_smart_subtransport_stream *stream,
532
628
  char *buffer,
@@ -537,6 +633,7 @@ static int winhttp_stream_read(
537
633
  winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
538
634
  DWORD dw_bytes_read;
539
635
  char replay_count = 0;
636
+ int error;
540
637
 
541
638
  replay:
542
639
  /* Enforce a reasonable cap on the number of replays */
@@ -553,15 +650,12 @@ replay:
553
650
  DWORD status_code, status_code_length, content_type_length, bytes_written;
554
651
  char expected_content_type_8[MAX_CONTENT_TYPE_LEN];
555
652
  wchar_t expected_content_type[MAX_CONTENT_TYPE_LEN], content_type[MAX_CONTENT_TYPE_LEN];
653
+ int request_failed = 0, cert_valid = 1;
556
654
 
557
655
  if (!s->sent_request) {
558
- if (!WinHttpSendRequest(s->request,
559
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
560
- WINHTTP_NO_REQUEST_DATA, 0,
561
- s->post_body_len, 0)) {
562
- giterr_set(GITERR_OS, "Failed to send request");
563
- return -1;
564
- }
656
+
657
+ if ((error = send_request(s, s->post_body_len, 0)) < 0)
658
+ return error;
565
659
 
566
660
  s->sent_request = 1;
567
661
  }
@@ -815,6 +909,7 @@ static int winhttp_stream_write_single(
815
909
  winhttp_stream *s = (winhttp_stream *)stream;
816
910
  winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
817
911
  DWORD bytes_written;
912
+ int error;
818
913
 
819
914
  if (!s->request && winhttp_stream_connect(s) < 0)
820
915
  return -1;
@@ -825,13 +920,8 @@ static int winhttp_stream_write_single(
825
920
  return -1;
826
921
  }
827
922
 
828
- if (!WinHttpSendRequest(s->request,
829
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
830
- WINHTTP_NO_REQUEST_DATA, 0,
831
- (DWORD)len, 0)) {
832
- giterr_set(GITERR_OS, "Failed to send request");
833
- return -1;
834
- }
923
+ if ((error = send_request(s, len, 0)) < 0)
924
+ return error;
835
925
 
836
926
  s->sent_request = 1;
837
927
 
@@ -954,6 +1044,7 @@ static int winhttp_stream_write_chunked(
954
1044
  {
955
1045
  winhttp_stream *s = (winhttp_stream *)stream;
956
1046
  winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
1047
+ int error;
957
1048
 
958
1049
  if (!s->request && winhttp_stream_connect(s) < 0)
959
1050
  return -1;
@@ -967,13 +1058,8 @@ static int winhttp_stream_write_chunked(
967
1058
  return -1;
968
1059
  }
969
1060
 
970
- if (!WinHttpSendRequest(s->request,
971
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
972
- WINHTTP_NO_REQUEST_DATA, 0,
973
- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
974
- giterr_set(GITERR_OS, "Failed to send request");
975
- return -1;
976
- }
1061
+ if ((error = send_request(s, 0, 1)) < 0)
1062
+ return error;
977
1063
 
978
1064
  s->sent_request = 1;
979
1065
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rugged
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.1b0
4
+ version: 0.21.1b1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Chacon
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-09-11 00:00:00.000000000 Z
12
+ date: 2014-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler