rugged 0.21.1b0 → 0.21.1b1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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