rugged 0.18.0.gh.de28323 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -4
- data/Rakefile +1 -1
- data/ext/rugged/extconf.rb +10 -0
- data/ext/rugged/rugged.c +153 -86
- data/ext/rugged/rugged.h +44 -33
- data/ext/rugged/rugged_blob.c +288 -60
- data/ext/rugged/rugged_branch.c +82 -57
- data/ext/rugged/rugged_commit.c +83 -86
- data/ext/rugged/rugged_config.c +68 -68
- data/ext/rugged/rugged_diff.c +509 -0
- data/ext/rugged/rugged_diff_delta.c +94 -0
- data/ext/rugged/rugged_diff_hunk.c +100 -0
- data/ext/rugged/rugged_diff_line.c +79 -0
- data/ext/rugged/rugged_diff_patch.c +169 -0
- data/ext/rugged/rugged_index.c +539 -8
- data/ext/rugged/rugged_note.c +74 -80
- data/ext/rugged/rugged_object.c +63 -8
- data/ext/rugged/rugged_reference.c +231 -145
- data/ext/rugged/rugged_remote.c +509 -53
- data/ext/rugged/rugged_repo.c +572 -236
- data/ext/rugged/rugged_revwalk.c +59 -36
- data/ext/rugged/rugged_settings.c +7 -9
- data/ext/rugged/rugged_signature.c +7 -11
- data/ext/rugged/rugged_tag.c +93 -39
- data/ext/rugged/rugged_tree.c +321 -58
- data/lib/rugged.rb +1 -0
- data/lib/rugged/commit.rb +16 -1
- data/lib/rugged/console.rb +9 -0
- data/lib/rugged/diff.rb +19 -0
- data/lib/rugged/diff/delta.rb +54 -0
- data/lib/rugged/diff/hunk.rb +23 -0
- data/lib/rugged/diff/line.rb +29 -0
- data/lib/rugged/diff/patch.rb +28 -0
- data/lib/rugged/repository.rb +36 -39
- data/lib/rugged/version.rb +1 -1
- data/test/blob_test.rb +308 -1
- data/test/branch_test.rb +7 -0
- data/test/commit_test.rb +7 -10
- data/test/coverage/cover.rb +9 -1
- data/test/diff_test.rb +777 -0
- data/test/fixtures/archive.tar.gz +0 -0
- data/test/fixtures/attr/attr0 +1 -0
- data/test/fixtures/attr/attr1 +29 -0
- data/test/fixtures/attr/attr2 +21 -0
- data/test/fixtures/attr/attr3 +4 -0
- data/test/fixtures/attr/binfile +1 -0
- data/test/fixtures/attr/dir/file +0 -0
- data/test/fixtures/attr/file +1 -0
- data/test/fixtures/attr/gitattributes +29 -0
- data/test/fixtures/attr/gitignore +2 -0
- data/test/fixtures/attr/ign +1 -0
- data/test/fixtures/attr/macro_bad +1 -0
- data/test/fixtures/attr/macro_test +1 -0
- data/test/fixtures/attr/root_test1 +1 -0
- data/test/fixtures/attr/root_test2 +6 -0
- data/test/fixtures/attr/root_test3 +19 -0
- data/test/fixtures/attr/root_test4.txt +14 -0
- data/test/fixtures/attr/sub/abc +37 -0
- data/test/fixtures/attr/sub/dir/file +0 -0
- data/test/fixtures/attr/sub/file +1 -0
- data/test/fixtures/attr/sub/ign/file +1 -0
- data/test/fixtures/attr/sub/ign/sub/file +1 -0
- data/test/fixtures/attr/sub/sub/dir +0 -0
- data/test/fixtures/attr/sub/sub/file +1 -0
- data/test/fixtures/attr/sub/sub/subsub.txt +1 -0
- data/test/fixtures/attr/sub/subdir_test1 +2 -0
- data/test/fixtures/attr/sub/subdir_test2.txt +1 -0
- data/test/fixtures/diff/another.txt +38 -0
- data/test/fixtures/diff/readme.txt +36 -0
- data/test/fixtures/mergedrepo/conflicts-one.txt +5 -0
- data/test/fixtures/mergedrepo/conflicts-two.txt +5 -0
- data/test/fixtures/mergedrepo/one.txt +10 -0
- data/test/fixtures/mergedrepo/two.txt +12 -0
- data/test/fixtures/status/current_file +1 -0
- data/test/fixtures/status/ignored_file +1 -0
- data/test/fixtures/status/modified_file +2 -0
- data/test/fixtures/status/new_file +1 -0
- data/test/fixtures/status/staged_changes +2 -0
- data/test/fixtures/status/staged_changes_modified_file +3 -0
- data/test/fixtures/status/staged_delete_modified_file +1 -0
- data/test/fixtures/status/staged_new_file +1 -0
- data/test/fixtures/status/staged_new_file_modified_file +2 -0
- data/test/fixtures/status/subdir.txt +2 -0
- data/test/fixtures/status/subdir/current_file +1 -0
- data/test/fixtures/status/subdir/modified_file +2 -0
- data/test/fixtures/status/subdir/new_file +1 -0
- data/test/fixtures/status//350/277/231 +1 -0
- data/test/fixtures/testrepo.git/config +5 -0
- data/test/fixtures/testrepo.git/objects/77/71329dfa3002caf8c61a0ceb62a31d09023f37 +0 -0
- data/test/fixtures/text_file.md +464 -0
- data/test/fixtures/unsymlinked.git/HEAD +1 -0
- data/test/fixtures/unsymlinked.git/config +6 -0
- data/test/fixtures/unsymlinked.git/description +1 -0
- data/test/fixtures/unsymlinked.git/info/exclude +2 -0
- data/test/fixtures/unsymlinked.git/objects/08/8b64704e0d6b8bd061dea879418cb5442a3fbf +0 -0
- data/test/fixtures/unsymlinked.git/objects/13/a5e939bca25940c069fd2169d993dba328e30b +0 -0
- data/test/fixtures/unsymlinked.git/objects/19/bf568e59e3a0b363cafb4106226e62d4a4c41c +0 -0
- data/test/fixtures/unsymlinked.git/objects/58/1fadd35b4cf320d102a152f918729011604773 +0 -0
- data/test/fixtures/unsymlinked.git/objects/5c/87b6791e8b13da658a14d1ef7e09b5dc3bac8c +0 -0
- data/test/fixtures/unsymlinked.git/objects/6f/e5f5398af85fb3de8a6aba0339b6d3bfa26a27 +0 -0
- data/test/fixtures/unsymlinked.git/objects/7f/ccd75616ec188b8f1b23d67506a334cc34a49d +0 -0
- data/test/fixtures/unsymlinked.git/objects/80/6999882bf91d24241e4077906b9017605eb1f3 +0 -0
- data/test/fixtures/unsymlinked.git/objects/83/7d176303c5005505ec1e4a30231c40930c0230 +0 -0
- data/test/fixtures/unsymlinked.git/objects/a8/595ccca04f40818ae0155c8f9c77a230e597b6 +2 -0
- data/test/fixtures/unsymlinked.git/objects/cf/8f1cf5cce859c438d6cc067284cb5e161206e7 +0 -0
- data/test/fixtures/unsymlinked.git/objects/d5/278d05c8607ec420bfee4cf219fbc0eeebfd6a +0 -0
- data/test/fixtures/unsymlinked.git/objects/f4/e16fb76536591a41454194058d048d8e4dd2e9 +0 -0
- data/test/fixtures/unsymlinked.git/objects/f9/e65619d93fdf2673882e0a261c5e93b1a84006 +0 -0
- data/test/fixtures/unsymlinked.git/refs/heads/exe-file +1 -0
- data/test/fixtures/unsymlinked.git/refs/heads/master +1 -0
- data/test/fixtures/unsymlinked.git/refs/heads/reg-file +1 -0
- data/test/index_test.rb +120 -0
- data/test/reference_test.rb +38 -3
- data/test/remote_test.rb +224 -3
- data/test/repo_reset_test.rb +2 -0
- data/test/repo_test.rb +147 -10
- data/test/test_helper.rb +5 -2
- data/vendor/libgit2/include/git2/attr.h +3 -3
- data/vendor/libgit2/include/git2/blob.h +11 -17
- data/vendor/libgit2/include/git2/branch.h +3 -2
- data/vendor/libgit2/include/git2/checkout.h +7 -0
- data/vendor/libgit2/include/git2/clone.h +3 -0
- data/vendor/libgit2/include/git2/commit.h +61 -66
- data/vendor/libgit2/include/git2/common.h +73 -42
- data/vendor/libgit2/include/git2/config.h +57 -71
- data/vendor/libgit2/include/git2/cred_helpers.h +2 -2
- data/vendor/libgit2/include/git2/diff.h +179 -30
- data/vendor/libgit2/include/git2/errors.h +3 -3
- data/vendor/libgit2/include/git2/index.h +225 -146
- data/vendor/libgit2/include/git2/indexer.h +2 -22
- data/vendor/libgit2/include/git2/inttypes.h +9 -9
- data/vendor/libgit2/include/git2/merge.h +123 -5
- data/vendor/libgit2/include/git2/odb.h +59 -38
- data/vendor/libgit2/include/git2/odb_backend.h +45 -104
- data/vendor/libgit2/include/git2/oid.h +30 -19
- data/vendor/libgit2/include/git2/pack.h +21 -3
- data/vendor/libgit2/include/git2/refdb.h +0 -35
- data/vendor/libgit2/include/git2/refs.h +93 -31
- data/vendor/libgit2/include/git2/refspec.h +17 -0
- data/vendor/libgit2/include/git2/remote.h +60 -20
- data/vendor/libgit2/include/git2/repository.h +48 -70
- data/vendor/libgit2/include/git2/reset.h +3 -3
- data/vendor/libgit2/include/git2/revparse.h +22 -0
- data/vendor/libgit2/include/git2/stash.h +1 -1
- data/vendor/libgit2/include/git2/status.h +131 -56
- data/vendor/libgit2/include/git2/strarray.h +2 -2
- data/vendor/libgit2/include/git2/submodule.h +16 -16
- data/vendor/libgit2/include/git2/sys/commit.h +46 -0
- data/vendor/libgit2/include/git2/sys/config.h +71 -0
- data/vendor/libgit2/include/git2/sys/index.h +179 -0
- data/vendor/libgit2/include/git2/sys/odb_backend.h +86 -0
- data/vendor/libgit2/include/git2/sys/refdb_backend.h +158 -0
- data/vendor/libgit2/include/git2/sys/refs.h +38 -0
- data/vendor/libgit2/include/git2/sys/repository.h +106 -0
- data/vendor/libgit2/include/git2/tag.h +44 -18
- data/vendor/libgit2/include/git2/trace.h +1 -2
- data/vendor/libgit2/include/git2/transport.h +74 -0
- data/vendor/libgit2/include/git2/tree.h +12 -22
- data/vendor/libgit2/include/git2/types.h +33 -0
- data/vendor/libgit2/include/git2/version.h +2 -2
- data/vendor/libgit2/src/array.h +66 -0
- data/vendor/libgit2/src/attr.c +26 -13
- data/vendor/libgit2/src/attr_file.c +3 -2
- data/vendor/libgit2/src/attr_file.h +3 -3
- data/vendor/libgit2/src/attrcache.h +4 -4
- data/vendor/libgit2/src/blob.c +13 -9
- data/vendor/libgit2/src/blob.h +2 -2
- data/vendor/libgit2/src/branch.c +67 -49
- data/vendor/libgit2/src/cache.c +224 -54
- data/vendor/libgit2/src/cache.h +33 -20
- data/vendor/libgit2/src/checkout.c +145 -85
- data/vendor/libgit2/src/clone.c +62 -50
- data/vendor/libgit2/src/commit.c +74 -40
- data/vendor/libgit2/src/commit.h +2 -3
- data/vendor/libgit2/src/commit_list.c +14 -8
- data/vendor/libgit2/src/config.c +119 -36
- data/vendor/libgit2/src/config.h +3 -0
- data/vendor/libgit2/src/config_cache.c +24 -7
- data/vendor/libgit2/src/config_file.c +9 -6
- data/vendor/libgit2/src/crlf.c +4 -2
- data/vendor/libgit2/src/date.c +3 -3
- data/vendor/libgit2/src/delta.c +1 -1
- data/vendor/libgit2/src/diff.c +681 -303
- data/vendor/libgit2/src/diff.h +34 -2
- data/vendor/libgit2/src/diff_driver.c +405 -0
- data/vendor/libgit2/src/diff_driver.h +49 -0
- data/vendor/libgit2/src/diff_file.c +447 -0
- data/vendor/libgit2/src/diff_file.h +58 -0
- data/vendor/libgit2/src/diff_patch.c +995 -0
- data/vendor/libgit2/src/diff_patch.h +46 -0
- data/vendor/libgit2/src/diff_print.c +430 -0
- data/vendor/libgit2/src/diff_tform.c +464 -203
- data/vendor/libgit2/src/diff_xdiff.c +166 -0
- data/vendor/libgit2/src/diff_xdiff.h +28 -0
- data/vendor/libgit2/src/fetch.c +11 -4
- data/vendor/libgit2/src/fileops.c +85 -61
- data/vendor/libgit2/src/fileops.h +4 -0
- data/vendor/libgit2/src/global.c +10 -2
- data/vendor/libgit2/src/global.h +0 -8
- data/vendor/libgit2/src/hash/hash_generic.h +3 -3
- data/vendor/libgit2/src/hash/hash_win32.h +4 -4
- data/vendor/libgit2/src/hashsig.c +0 -1
- data/vendor/libgit2/src/ignore.c +68 -28
- data/vendor/libgit2/src/ignore.h +10 -1
- data/vendor/libgit2/src/index.c +666 -84
- data/vendor/libgit2/src/index.h +6 -0
- data/vendor/libgit2/src/indexer.c +10 -28
- data/vendor/libgit2/src/iterator.c +427 -283
- data/vendor/libgit2/src/iterator.h +58 -4
- data/vendor/libgit2/src/merge.c +1892 -32
- data/vendor/libgit2/src/merge.h +132 -5
- data/vendor/libgit2/src/merge_file.c +174 -0
- data/vendor/libgit2/src/merge_file.h +71 -0
- data/vendor/libgit2/src/mwindow.c +1 -1
- data/vendor/libgit2/src/notes.c +45 -48
- data/vendor/libgit2/src/object.c +89 -127
- data/vendor/libgit2/src/object.h +0 -1
- data/vendor/libgit2/src/object_api.c +129 -0
- data/vendor/libgit2/src/odb.c +156 -59
- data/vendor/libgit2/src/odb.h +5 -2
- data/vendor/libgit2/src/odb_loose.c +31 -17
- data/vendor/libgit2/src/odb_pack.c +39 -43
- data/vendor/libgit2/src/oid.c +62 -27
- data/vendor/libgit2/src/oid.h +33 -0
- data/vendor/libgit2/src/oidmap.h +4 -6
- data/vendor/libgit2/src/pack-objects.c +54 -22
- data/vendor/libgit2/src/pack.c +98 -56
- data/vendor/libgit2/src/pack.h +3 -1
- data/vendor/libgit2/src/pathspec.c +26 -1
- data/vendor/libgit2/src/pathspec.h +14 -0
- data/vendor/libgit2/src/pool.c +5 -0
- data/vendor/libgit2/src/posix.c +2 -2
- data/vendor/libgit2/src/posix.h +3 -0
- data/vendor/libgit2/src/push.c +13 -10
- data/vendor/libgit2/src/refdb.c +82 -62
- data/vendor/libgit2/src/refdb.h +16 -16
- data/vendor/libgit2/src/refdb_fs.c +386 -133
- data/vendor/libgit2/src/reflog.c +3 -1
- data/vendor/libgit2/src/refs.c +247 -221
- data/vendor/libgit2/src/refs.h +2 -1
- data/vendor/libgit2/src/refspec.c +18 -1
- data/vendor/libgit2/src/refspec.h +3 -1
- data/vendor/libgit2/src/remote.c +434 -253
- data/vendor/libgit2/src/remote.h +5 -3
- data/vendor/libgit2/src/repository.c +197 -111
- data/vendor/libgit2/src/repository.h +26 -5
- data/vendor/libgit2/src/reset.c +1 -1
- data/vendor/libgit2/src/revparse.c +84 -79
- data/vendor/libgit2/src/revwalk.c +1 -1
- data/vendor/libgit2/src/signature.c +22 -10
- data/vendor/libgit2/src/stash.c +5 -2
- data/vendor/libgit2/src/status.c +311 -107
- data/vendor/libgit2/src/status.h +23 -0
- data/vendor/libgit2/src/submodule.c +21 -13
- data/vendor/libgit2/src/tag.c +42 -31
- data/vendor/libgit2/src/tag.h +2 -3
- data/vendor/libgit2/src/thread-utils.h +105 -3
- data/vendor/libgit2/src/trace.c +1 -2
- data/vendor/libgit2/src/trace.h +3 -3
- data/vendor/libgit2/src/transport.c +18 -6
- data/vendor/libgit2/src/transports/cred.c +103 -1
- data/vendor/libgit2/src/transports/local.c +19 -9
- data/vendor/libgit2/src/transports/smart_protocol.c +32 -12
- data/vendor/libgit2/src/transports/ssh.c +519 -0
- data/vendor/libgit2/src/transports/winhttp.c +3 -1
- data/vendor/libgit2/src/tree.c +26 -28
- data/vendor/libgit2/src/tree.h +3 -3
- data/vendor/libgit2/src/unix/posix.h +2 -0
- data/vendor/libgit2/src/util.c +43 -6
- data/vendor/libgit2/src/util.h +40 -12
- data/vendor/libgit2/src/vector.c +3 -5
- data/vendor/libgit2/src/vector.h +9 -0
- data/vendor/libgit2/src/win32/dir.c +1 -1
- data/vendor/libgit2/src/win32/error.c +2 -0
- data/vendor/libgit2/src/win32/findfile.c +3 -6
- data/vendor/libgit2/src/win32/posix_w32.c +85 -59
- data/vendor/libgit2/src/win32/pthread.c +16 -8
- data/vendor/libgit2/src/win32/pthread.h +7 -4
- metadata +407 -306
- data/test/coverage/HEAD.json +0 -1
- data/vendor/libgit2/include/git2/refdb_backend.h +0 -109
- data/vendor/libgit2/src/diff_output.c +0 -1819
- data/vendor/libgit2/src/diff_output.h +0 -93
data/vendor/libgit2/src/trace.h
CHANGED
@@ -25,14 +25,14 @@ GIT_INLINE(void) git_trace__write_fmt(
|
|
25
25
|
git_trace_level_t level,
|
26
26
|
const char *fmt, ...)
|
27
27
|
{
|
28
|
-
git_trace_callback callback = git_trace__data.callback;
|
28
|
+
git_trace_callback callback = git_trace__data.callback;
|
29
29
|
git_buf message = GIT_BUF_INIT;
|
30
30
|
va_list ap;
|
31
|
-
|
31
|
+
|
32
32
|
va_start(ap, fmt);
|
33
33
|
git_buf_vprintf(&message, fmt, ap);
|
34
34
|
va_end(ap);
|
35
|
-
|
35
|
+
|
36
36
|
callback(level, git_buf_cstr(&message));
|
37
37
|
|
38
38
|
git_buf_free(&message);
|
@@ -18,19 +18,27 @@ typedef struct transport_definition {
|
|
18
18
|
void *param;
|
19
19
|
} transport_definition;
|
20
20
|
|
21
|
-
static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
|
22
|
-
static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
|
23
|
-
|
24
21
|
static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1 };
|
25
22
|
static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0 };
|
23
|
+
#ifdef GIT_SSH
|
24
|
+
static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 };
|
25
|
+
#endif
|
26
|
+
|
27
|
+
static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
|
28
|
+
#ifdef GIT_SSH
|
29
|
+
static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
|
30
|
+
#else
|
31
|
+
static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
|
32
|
+
#endif
|
26
33
|
|
27
34
|
static transport_definition transports[] = {
|
28
35
|
{"git://", 1, git_transport_smart, &git_subtransport_definition},
|
29
36
|
{"http://", 1, git_transport_smart, &http_subtransport_definition},
|
30
37
|
{"https://", 1, git_transport_smart, &http_subtransport_definition},
|
31
38
|
{"file://", 1, git_transport_local, NULL},
|
32
|
-
|
33
|
-
{"ssh
|
39
|
+
#ifdef GIT_SSH
|
40
|
+
{"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
|
41
|
+
#endif
|
34
42
|
{NULL, 0, 0}
|
35
43
|
};
|
36
44
|
|
@@ -73,7 +81,11 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
|
|
73
81
|
/* It could be a SSH remote path. Check to see if there's a :
|
74
82
|
* SSH is an unsupported transport mechanism in this version of libgit2 */
|
75
83
|
if (!definition && strrchr(url, ':'))
|
76
|
-
|
84
|
+
#ifdef GIT_SSH
|
85
|
+
definition = &ssh_transport_definition;
|
86
|
+
#else
|
87
|
+
definition = &dummy_transport_definition;
|
88
|
+
#endif
|
77
89
|
|
78
90
|
/* Check to see if the path points to a file on the local file system */
|
79
91
|
if (!definition && git_path_exists(url) && git_path_isdir(url))
|
@@ -17,7 +17,7 @@ static void plaintext_free(struct git_cred *cred)
|
|
17
17
|
git__free(c->username);
|
18
18
|
|
19
19
|
/* Zero the memory which previously held the password */
|
20
|
-
|
20
|
+
git__memzero(c->password, pass_len);
|
21
21
|
git__free(c->password);
|
22
22
|
|
23
23
|
memset(c, 0, sizeof(*c));
|
@@ -58,3 +58,105 @@ int git_cred_userpass_plaintext_new(
|
|
58
58
|
*cred = &c->parent;
|
59
59
|
return 0;
|
60
60
|
}
|
61
|
+
|
62
|
+
#ifdef GIT_SSH
|
63
|
+
static void ssh_keyfile_passphrase_free(struct git_cred *cred)
|
64
|
+
{
|
65
|
+
git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred;
|
66
|
+
size_t pass_len = strlen(c->passphrase);
|
67
|
+
|
68
|
+
if (c->publickey) {
|
69
|
+
git__free(c->publickey);
|
70
|
+
}
|
71
|
+
|
72
|
+
git__free(c->privatekey);
|
73
|
+
|
74
|
+
if (c->passphrase) {
|
75
|
+
/* Zero the memory which previously held the passphrase */
|
76
|
+
git__memzero(c->passphrase, pass_len);
|
77
|
+
git__free(c->passphrase);
|
78
|
+
}
|
79
|
+
|
80
|
+
memset(c, 0, sizeof(*c));
|
81
|
+
|
82
|
+
git__free(c);
|
83
|
+
}
|
84
|
+
|
85
|
+
int git_cred_ssh_keyfile_passphrase_new(
|
86
|
+
git_cred **cred,
|
87
|
+
const char *publickey,
|
88
|
+
const char *privatekey,
|
89
|
+
const char *passphrase)
|
90
|
+
{
|
91
|
+
git_cred_ssh_keyfile_passphrase *c;
|
92
|
+
|
93
|
+
assert(cred && privatekey);
|
94
|
+
|
95
|
+
c = git__calloc(1, sizeof(git_cred_ssh_keyfile_passphrase));
|
96
|
+
GITERR_CHECK_ALLOC(c);
|
97
|
+
|
98
|
+
c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE;
|
99
|
+
c->parent.free = ssh_keyfile_passphrase_free;
|
100
|
+
|
101
|
+
c->privatekey = git__strdup(privatekey);
|
102
|
+
GITERR_CHECK_ALLOC(c->privatekey);
|
103
|
+
|
104
|
+
if (publickey) {
|
105
|
+
c->publickey = git__strdup(publickey);
|
106
|
+
GITERR_CHECK_ALLOC(c->publickey);
|
107
|
+
}
|
108
|
+
|
109
|
+
if (passphrase) {
|
110
|
+
c->passphrase = git__strdup(passphrase);
|
111
|
+
GITERR_CHECK_ALLOC(c->passphrase);
|
112
|
+
}
|
113
|
+
|
114
|
+
*cred = &c->parent;
|
115
|
+
return 0;
|
116
|
+
}
|
117
|
+
|
118
|
+
static void ssh_publickey_free(struct git_cred *cred)
|
119
|
+
{
|
120
|
+
git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
|
121
|
+
|
122
|
+
git__free(c->publickey);
|
123
|
+
|
124
|
+
c->sign_callback = NULL;
|
125
|
+
c->sign_data = NULL;
|
126
|
+
|
127
|
+
memset(c, 0, sizeof(*c));
|
128
|
+
|
129
|
+
git__free(c);
|
130
|
+
}
|
131
|
+
|
132
|
+
int git_cred_ssh_publickey_new(
|
133
|
+
git_cred **cred,
|
134
|
+
const char *publickey,
|
135
|
+
size_t publickey_len,
|
136
|
+
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
|
137
|
+
void *sign_data)
|
138
|
+
{
|
139
|
+
git_cred_ssh_publickey *c;
|
140
|
+
|
141
|
+
if (!cred)
|
142
|
+
return -1;
|
143
|
+
|
144
|
+
c = git__malloc(sizeof(git_cred_ssh_publickey));
|
145
|
+
GITERR_CHECK_ALLOC(c);
|
146
|
+
|
147
|
+
c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY;
|
148
|
+
c->parent.free = ssh_publickey_free;
|
149
|
+
|
150
|
+
c->publickey = git__malloc(publickey_len);
|
151
|
+
GITERR_CHECK_ALLOC(c->publickey);
|
152
|
+
|
153
|
+
memcpy(c->publickey, publickey, publickey_len);
|
154
|
+
|
155
|
+
c->publickey_len = publickey_len;
|
156
|
+
c->sign_callback = sign_callback;
|
157
|
+
c->sign_data = sign_data;
|
158
|
+
|
159
|
+
*cred = &c->parent;
|
160
|
+
return 0;
|
161
|
+
}
|
162
|
+
#endif
|
@@ -119,15 +119,24 @@ on_error:
|
|
119
119
|
|
120
120
|
static int store_refs(transport_local *t)
|
121
121
|
{
|
122
|
-
|
122
|
+
size_t i;
|
123
|
+
git_remote_head *head;
|
123
124
|
git_strarray ref_names = {0};
|
124
125
|
|
125
126
|
assert(t);
|
126
127
|
|
127
|
-
if (git_reference_list(&ref_names, t->repo
|
128
|
-
git_vector_init(&t->refs, ref_names.count, NULL) < 0)
|
128
|
+
if (git_reference_list(&ref_names, t->repo) < 0)
|
129
129
|
goto on_error;
|
130
130
|
|
131
|
+
/* Clear all heads we might have fetched in a previous connect */
|
132
|
+
git_vector_foreach(&t->refs, i, head) {
|
133
|
+
git__free(head->name);
|
134
|
+
git__free(head);
|
135
|
+
}
|
136
|
+
|
137
|
+
/* Clear the vector so we can reuse it */
|
138
|
+
git_vector_clear(&t->refs);
|
139
|
+
|
131
140
|
/* Sort the references first */
|
132
141
|
git__tsort((void **)ref_names.strings, ref_names.count, &git__strcmp_cb);
|
133
142
|
|
@@ -282,7 +291,7 @@ static int local_push_copy_object(
|
|
282
291
|
odb_obj_size) < 0 ||
|
283
292
|
odb_stream->finalize_write(&remote_odb_obj_oid, odb_stream) < 0) {
|
284
293
|
error = -1;
|
285
|
-
} else if (
|
294
|
+
} else if (git_oid__cmp(&obj->id, &remote_odb_obj_oid) != 0) {
|
286
295
|
giterr_set(GITERR_ODB, "Error when writing object to remote odb "
|
287
296
|
"during local push operation. Remote odb object oid does not "
|
288
297
|
"match local oid.");
|
@@ -348,7 +357,7 @@ static int local_push(
|
|
348
357
|
if ((error = git_repository_open(&remote_repo, push->remote->url)) < 0)
|
349
358
|
return error;
|
350
359
|
|
351
|
-
/* We don't currently support pushing locally to non-bare repos. Proper
|
360
|
+
/* We don't currently support pushing locally to non-bare repos. Proper
|
352
361
|
non-bare repo push support would require checking configs to see if
|
353
362
|
we should override the default 'don't let this happen' behavior */
|
354
363
|
if (!remote_repo->is_bare) {
|
@@ -495,7 +504,7 @@ static int local_download_pack(
|
|
495
504
|
/* Tag or some other wanted object. Add it on its own */
|
496
505
|
error = git_packbuilder_insert(pack, &rhead->oid, rhead->name);
|
497
506
|
}
|
498
|
-
|
507
|
+
git_object_free(obj);
|
499
508
|
}
|
500
509
|
|
501
510
|
/* Walk the objects, building a packfile */
|
@@ -593,9 +602,6 @@ static void local_free(git_transport *transport)
|
|
593
602
|
size_t i;
|
594
603
|
git_remote_head *head;
|
595
604
|
|
596
|
-
/* Close the transport, if it's still open. */
|
597
|
-
local_close(transport);
|
598
|
-
|
599
605
|
git_vector_foreach(&t->refs, i, head) {
|
600
606
|
git__free(head->name);
|
601
607
|
git__free(head);
|
@@ -603,6 +609,9 @@ static void local_free(git_transport *transport)
|
|
603
609
|
|
604
610
|
git_vector_free(&t->refs);
|
605
611
|
|
612
|
+
/* Close the transport, if it's still open. */
|
613
|
+
local_close(transport);
|
614
|
+
|
606
615
|
/* Free the transport */
|
607
616
|
git__free(t);
|
608
617
|
}
|
@@ -632,6 +641,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
|
|
632
641
|
t->parent.read_flags = local_read_flags;
|
633
642
|
t->parent.cancel = local_cancel;
|
634
643
|
|
644
|
+
git_vector_init(&t->refs, 0, NULL);
|
635
645
|
t->owner = owner;
|
636
646
|
|
637
647
|
*out = (git_transport *) t;
|
@@ -5,6 +5,7 @@
|
|
5
5
|
* a Linking Exception. For full terms see the included COPYING file.
|
6
6
|
*/
|
7
7
|
#include "git2.h"
|
8
|
+
#include "git2/odb_backend.h"
|
8
9
|
|
9
10
|
#include "smart.h"
|
10
11
|
#include "refs.h"
|
@@ -20,12 +21,18 @@ int git_smart__store_refs(transport_smart *t, int flushes)
|
|
20
21
|
gitno_buffer *buf = &t->buffer;
|
21
22
|
git_vector *refs = &t->refs;
|
22
23
|
int error, flush = 0, recvd;
|
23
|
-
const char *line_end;
|
24
|
-
git_pkt *pkt;
|
24
|
+
const char *line_end = NULL;
|
25
|
+
git_pkt *pkt = NULL;
|
26
|
+
git_pkt_ref *ref;
|
27
|
+
size_t i;
|
25
28
|
|
26
29
|
/* Clear existing refs in case git_remote_connect() is called again
|
27
30
|
* after git_remote_disconnect().
|
28
31
|
*/
|
32
|
+
git_vector_foreach(refs, i, ref) {
|
33
|
+
git__free(ref->head.name);
|
34
|
+
git__free(ref);
|
35
|
+
}
|
29
36
|
git_vector_clear(refs);
|
30
37
|
|
31
38
|
do {
|
@@ -128,7 +135,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps)
|
|
128
135
|
static int recv_pkt(git_pkt **out, gitno_buffer *buf)
|
129
136
|
{
|
130
137
|
const char *ptr = buf->data, *line_end = ptr;
|
131
|
-
git_pkt *pkt;
|
138
|
+
git_pkt *pkt = NULL;
|
132
139
|
int pkt_type, error = 0, ret;
|
133
140
|
|
134
141
|
do {
|
@@ -186,7 +193,7 @@ static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
|
|
186
193
|
unsigned int i;
|
187
194
|
git_reference *ref;
|
188
195
|
|
189
|
-
if (git_reference_list(&refs, repo
|
196
|
+
if (git_reference_list(&refs, repo) < 0)
|
190
197
|
return -1;
|
191
198
|
|
192
199
|
if (git_revwalk_new(&walk, repo) < 0)
|
@@ -569,7 +576,7 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
|
|
569
576
|
|
570
577
|
switch (pkt->type) {
|
571
578
|
case GIT_PKT_OK:
|
572
|
-
status =
|
579
|
+
status = git__calloc(1, sizeof(push_status));
|
573
580
|
GITERR_CHECK_ALLOC(status);
|
574
581
|
status->msg = NULL;
|
575
582
|
status->ref = git__strdup(((git_pkt_ok *)pkt)->ref);
|
@@ -633,8 +640,8 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
|
|
633
640
|
|
634
641
|
static int parse_report(gitno_buffer *buf, git_push *push)
|
635
642
|
{
|
636
|
-
git_pkt *pkt;
|
637
|
-
const char *line_end;
|
643
|
+
git_pkt *pkt = NULL;
|
644
|
+
const char *line_end = NULL;
|
638
645
|
int error, recvd;
|
639
646
|
|
640
647
|
for (;;) {
|
@@ -806,13 +813,13 @@ int git_smart__push(git_transport *transport, git_push *push)
|
|
806
813
|
transport_smart *t = (transport_smart *)transport;
|
807
814
|
git_smart_subtransport_stream *s;
|
808
815
|
git_buf pktline = GIT_BUF_INIT;
|
809
|
-
int error = -1;
|
816
|
+
int error = -1, need_pack = 0;
|
817
|
+
push_spec *spec;
|
818
|
+
unsigned int i;
|
810
819
|
|
811
820
|
#ifdef PUSH_DEBUG
|
812
821
|
{
|
813
822
|
git_remote_head *head;
|
814
|
-
push_spec *spec;
|
815
|
-
unsigned int i;
|
816
823
|
char hex[41]; hex[40] = '\0';
|
817
824
|
|
818
825
|
git_vector_foreach(&push->remote->refs, i, head) {
|
@@ -830,10 +837,23 @@ int git_smart__push(git_transport *transport, git_push *push)
|
|
830
837
|
}
|
831
838
|
#endif
|
832
839
|
|
840
|
+
/*
|
841
|
+
* Figure out if we need to send a packfile; which is in all
|
842
|
+
* cases except when we only send delete commands
|
843
|
+
*/
|
844
|
+
git_vector_foreach(&push->specs, i, spec) {
|
845
|
+
if (spec->lref) {
|
846
|
+
need_pack = 1;
|
847
|
+
break;
|
848
|
+
}
|
849
|
+
}
|
850
|
+
|
833
851
|
if (git_smart__get_push_stream(t, &s) < 0 ||
|
834
852
|
gen_pktline(&pktline, push) < 0 ||
|
835
|
-
s->write(s, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0
|
836
|
-
|
853
|
+
s->write(s, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0)
|
854
|
+
goto on_error;
|
855
|
+
|
856
|
+
if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, s) < 0)
|
837
857
|
goto on_error;
|
838
858
|
|
839
859
|
/* If we sent nothing or the server doesn't support report-status, then
|
@@ -0,0 +1,519 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#ifdef GIT_SSH
|
9
|
+
|
10
|
+
#include "git2.h"
|
11
|
+
#include "buffer.h"
|
12
|
+
#include "netops.h"
|
13
|
+
#include "smart.h"
|
14
|
+
|
15
|
+
#include <libssh2.h>
|
16
|
+
|
17
|
+
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
|
18
|
+
|
19
|
+
static const char prefix_ssh[] = "ssh://";
|
20
|
+
static const char default_user[] = "git";
|
21
|
+
static const char cmd_uploadpack[] = "git-upload-pack";
|
22
|
+
static const char cmd_receivepack[] = "git-receive-pack";
|
23
|
+
|
24
|
+
typedef struct {
|
25
|
+
git_smart_subtransport_stream parent;
|
26
|
+
gitno_socket socket;
|
27
|
+
LIBSSH2_SESSION *session;
|
28
|
+
LIBSSH2_CHANNEL *channel;
|
29
|
+
const char *cmd;
|
30
|
+
char *url;
|
31
|
+
unsigned sent_command : 1;
|
32
|
+
} ssh_stream;
|
33
|
+
|
34
|
+
typedef struct {
|
35
|
+
git_smart_subtransport parent;
|
36
|
+
transport_smart *owner;
|
37
|
+
ssh_stream *current_stream;
|
38
|
+
git_cred *cred;
|
39
|
+
} ssh_subtransport;
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Create a git protocol request.
|
43
|
+
*
|
44
|
+
* For example: git-upload-pack '/libgit2/libgit2'
|
45
|
+
*/
|
46
|
+
static int gen_proto(git_buf *request, const char *cmd, const char *url)
|
47
|
+
{
|
48
|
+
char *repo;
|
49
|
+
|
50
|
+
if (!git__prefixcmp(url, prefix_ssh)) {
|
51
|
+
url = url + strlen(prefix_ssh);
|
52
|
+
repo = strchr(url, '/');
|
53
|
+
} else {
|
54
|
+
repo = strchr(url, ':');
|
55
|
+
}
|
56
|
+
|
57
|
+
if (!repo) {
|
58
|
+
return -1;
|
59
|
+
}
|
60
|
+
|
61
|
+
int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
|
62
|
+
|
63
|
+
git_buf_grow(request, len);
|
64
|
+
git_buf_printf(request, "%s '%s'", cmd, repo);
|
65
|
+
git_buf_putc(request, '\0');
|
66
|
+
|
67
|
+
if (git_buf_oom(request))
|
68
|
+
return -1;
|
69
|
+
|
70
|
+
return 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
static int send_command(ssh_stream *s)
|
74
|
+
{
|
75
|
+
int error;
|
76
|
+
git_buf request = GIT_BUF_INIT;
|
77
|
+
|
78
|
+
error = gen_proto(&request, s->cmd, s->url);
|
79
|
+
if (error < 0)
|
80
|
+
goto cleanup;
|
81
|
+
|
82
|
+
error = libssh2_channel_exec(
|
83
|
+
s->channel,
|
84
|
+
request.ptr
|
85
|
+
);
|
86
|
+
|
87
|
+
if (0 != error)
|
88
|
+
goto cleanup;
|
89
|
+
|
90
|
+
s->sent_command = 1;
|
91
|
+
|
92
|
+
cleanup:
|
93
|
+
git_buf_free(&request);
|
94
|
+
return error;
|
95
|
+
}
|
96
|
+
|
97
|
+
static int ssh_stream_read(
|
98
|
+
git_smart_subtransport_stream *stream,
|
99
|
+
char *buffer,
|
100
|
+
size_t buf_size,
|
101
|
+
size_t *bytes_read)
|
102
|
+
{
|
103
|
+
ssh_stream *s = (ssh_stream *)stream;
|
104
|
+
|
105
|
+
*bytes_read = 0;
|
106
|
+
|
107
|
+
if (!s->sent_command && send_command(s) < 0)
|
108
|
+
return -1;
|
109
|
+
|
110
|
+
int rc = libssh2_channel_read(s->channel, buffer, buf_size);
|
111
|
+
if (rc < 0)
|
112
|
+
return -1;
|
113
|
+
|
114
|
+
*bytes_read = rc;
|
115
|
+
|
116
|
+
return 0;
|
117
|
+
}
|
118
|
+
|
119
|
+
static int ssh_stream_write(
|
120
|
+
git_smart_subtransport_stream *stream,
|
121
|
+
const char *buffer,
|
122
|
+
size_t len)
|
123
|
+
{
|
124
|
+
ssh_stream *s = (ssh_stream *)stream;
|
125
|
+
|
126
|
+
if (!s->sent_command && send_command(s) < 0)
|
127
|
+
return -1;
|
128
|
+
|
129
|
+
int rc = libssh2_channel_write(s->channel, buffer, len);
|
130
|
+
if (rc < 0) {
|
131
|
+
return -1;
|
132
|
+
}
|
133
|
+
|
134
|
+
return rc;
|
135
|
+
}
|
136
|
+
|
137
|
+
static void ssh_stream_free(git_smart_subtransport_stream *stream)
|
138
|
+
{
|
139
|
+
ssh_stream *s = (ssh_stream *)stream;
|
140
|
+
ssh_subtransport *t = OWNING_SUBTRANSPORT(s);
|
141
|
+
int ret;
|
142
|
+
|
143
|
+
GIT_UNUSED(ret);
|
144
|
+
|
145
|
+
t->current_stream = NULL;
|
146
|
+
|
147
|
+
if (s->channel) {
|
148
|
+
libssh2_channel_close(s->channel);
|
149
|
+
libssh2_channel_free(s->channel);
|
150
|
+
s->channel = NULL;
|
151
|
+
}
|
152
|
+
|
153
|
+
if (s->session) {
|
154
|
+
libssh2_session_free(s->session), s->session = NULL;
|
155
|
+
}
|
156
|
+
|
157
|
+
if (s->socket.socket) {
|
158
|
+
ret = gitno_close(&s->socket);
|
159
|
+
assert(!ret);
|
160
|
+
}
|
161
|
+
|
162
|
+
git__free(s->url);
|
163
|
+
git__free(s);
|
164
|
+
}
|
165
|
+
|
166
|
+
static int ssh_stream_alloc(
|
167
|
+
ssh_subtransport *t,
|
168
|
+
const char *url,
|
169
|
+
const char *cmd,
|
170
|
+
git_smart_subtransport_stream **stream)
|
171
|
+
{
|
172
|
+
ssh_stream *s;
|
173
|
+
|
174
|
+
if (!stream)
|
175
|
+
return -1;
|
176
|
+
|
177
|
+
s = git__calloc(sizeof(ssh_stream), 1);
|
178
|
+
GITERR_CHECK_ALLOC(s);
|
179
|
+
|
180
|
+
s->parent.subtransport = &t->parent;
|
181
|
+
s->parent.read = ssh_stream_read;
|
182
|
+
s->parent.write = ssh_stream_write;
|
183
|
+
s->parent.free = ssh_stream_free;
|
184
|
+
|
185
|
+
s->cmd = cmd;
|
186
|
+
s->url = git__strdup(url);
|
187
|
+
|
188
|
+
if (!s->url) {
|
189
|
+
git__free(s);
|
190
|
+
return -1;
|
191
|
+
}
|
192
|
+
|
193
|
+
*stream = &s->parent;
|
194
|
+
return 0;
|
195
|
+
}
|
196
|
+
|
197
|
+
static int git_ssh_extract_url_parts(
|
198
|
+
char **host,
|
199
|
+
char **username,
|
200
|
+
const char *url)
|
201
|
+
{
|
202
|
+
char *colon, *at;
|
203
|
+
const char *start;
|
204
|
+
|
205
|
+
colon = strchr(url, ':');
|
206
|
+
|
207
|
+
if (colon == NULL) {
|
208
|
+
giterr_set(GITERR_NET, "Malformed URL: missing :");
|
209
|
+
return -1;
|
210
|
+
}
|
211
|
+
|
212
|
+
at = strchr(url, '@');
|
213
|
+
if (at) {
|
214
|
+
start = at+1;
|
215
|
+
*username = git__substrdup(url, at - url);
|
216
|
+
} else {
|
217
|
+
start = url;
|
218
|
+
*username = git__strdup(default_user);
|
219
|
+
}
|
220
|
+
|
221
|
+
*host = git__substrdup(start, colon - start);
|
222
|
+
|
223
|
+
return 0;
|
224
|
+
}
|
225
|
+
|
226
|
+
static int _git_ssh_authenticate_session(
|
227
|
+
LIBSSH2_SESSION* session,
|
228
|
+
const char *user,
|
229
|
+
git_cred* cred
|
230
|
+
)
|
231
|
+
{
|
232
|
+
int rc;
|
233
|
+
do {
|
234
|
+
switch (cred->credtype) {
|
235
|
+
case GIT_CREDTYPE_USERPASS_PLAINTEXT: {
|
236
|
+
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
|
237
|
+
rc = libssh2_userauth_password(
|
238
|
+
session,
|
239
|
+
c->username,
|
240
|
+
c->password
|
241
|
+
);
|
242
|
+
break;
|
243
|
+
}
|
244
|
+
case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: {
|
245
|
+
git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred;
|
246
|
+
rc = libssh2_userauth_publickey_fromfile(
|
247
|
+
session,
|
248
|
+
user,
|
249
|
+
c->publickey,
|
250
|
+
c->privatekey,
|
251
|
+
c->passphrase
|
252
|
+
);
|
253
|
+
break;
|
254
|
+
}
|
255
|
+
case GIT_CREDTYPE_SSH_PUBLICKEY: {
|
256
|
+
git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
|
257
|
+
rc = libssh2_userauth_publickey(
|
258
|
+
session,
|
259
|
+
user,
|
260
|
+
(const unsigned char *)c->publickey,
|
261
|
+
c->publickey_len,
|
262
|
+
c->sign_callback,
|
263
|
+
&c->sign_data
|
264
|
+
);
|
265
|
+
break;
|
266
|
+
}
|
267
|
+
default:
|
268
|
+
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
|
269
|
+
}
|
270
|
+
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
271
|
+
|
272
|
+
return rc;
|
273
|
+
}
|
274
|
+
|
275
|
+
static int _git_ssh_session_create
|
276
|
+
(
|
277
|
+
LIBSSH2_SESSION** session,
|
278
|
+
gitno_socket socket
|
279
|
+
)
|
280
|
+
{
|
281
|
+
if (!session) {
|
282
|
+
return -1;
|
283
|
+
}
|
284
|
+
|
285
|
+
LIBSSH2_SESSION* s = libssh2_session_init();
|
286
|
+
if (!s)
|
287
|
+
return -1;
|
288
|
+
|
289
|
+
int rc = 0;
|
290
|
+
do {
|
291
|
+
rc = libssh2_session_startup(s, socket.socket);
|
292
|
+
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
|
293
|
+
|
294
|
+
if (0 != rc) {
|
295
|
+
goto on_error;
|
296
|
+
}
|
297
|
+
|
298
|
+
libssh2_session_set_blocking(s, 1);
|
299
|
+
|
300
|
+
*session = s;
|
301
|
+
|
302
|
+
return 0;
|
303
|
+
|
304
|
+
on_error:
|
305
|
+
if (s) {
|
306
|
+
libssh2_session_free(s), s = NULL;
|
307
|
+
}
|
308
|
+
|
309
|
+
return -1;
|
310
|
+
}
|
311
|
+
|
312
|
+
static int _git_ssh_setup_conn(
|
313
|
+
ssh_subtransport *t,
|
314
|
+
const char *url,
|
315
|
+
const char *cmd,
|
316
|
+
git_smart_subtransport_stream **stream
|
317
|
+
)
|
318
|
+
{
|
319
|
+
char *host, *port=NULL, *user=NULL, *pass=NULL;
|
320
|
+
const char *default_port="22";
|
321
|
+
ssh_stream *s;
|
322
|
+
LIBSSH2_SESSION* session=NULL;
|
323
|
+
LIBSSH2_CHANNEL* channel=NULL;
|
324
|
+
|
325
|
+
*stream = NULL;
|
326
|
+
if (ssh_stream_alloc(t, url, cmd, stream) < 0)
|
327
|
+
return -1;
|
328
|
+
|
329
|
+
s = (ssh_stream *)*stream;
|
330
|
+
|
331
|
+
if (!git__prefixcmp(url, prefix_ssh)) {
|
332
|
+
url = url + strlen(prefix_ssh);
|
333
|
+
if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0)
|
334
|
+
goto on_error;
|
335
|
+
} else {
|
336
|
+
if (git_ssh_extract_url_parts(&host, &user, url) < 0)
|
337
|
+
goto on_error;
|
338
|
+
port = git__strdup(default_port);
|
339
|
+
GITERR_CHECK_ALLOC(port);
|
340
|
+
}
|
341
|
+
|
342
|
+
if (gitno_connect(&s->socket, host, port, 0) < 0)
|
343
|
+
goto on_error;
|
344
|
+
|
345
|
+
if (user && pass) {
|
346
|
+
if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
|
347
|
+
goto on_error;
|
348
|
+
} else {
|
349
|
+
if (t->owner->cred_acquire_cb(&t->cred,
|
350
|
+
t->owner->url,
|
351
|
+
user,
|
352
|
+
GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE,
|
353
|
+
t->owner->cred_acquire_payload) < 0)
|
354
|
+
return -1;
|
355
|
+
}
|
356
|
+
assert(t->cred);
|
357
|
+
|
358
|
+
if (!user) {
|
359
|
+
user = git__strdup(default_user);
|
360
|
+
}
|
361
|
+
|
362
|
+
if (_git_ssh_session_create(&session, s->socket) < 0)
|
363
|
+
goto on_error;
|
364
|
+
|
365
|
+
if (_git_ssh_authenticate_session(session, user, t->cred) < 0)
|
366
|
+
goto on_error;
|
367
|
+
|
368
|
+
channel = libssh2_channel_open_session(session);
|
369
|
+
if (!channel)
|
370
|
+
goto on_error;
|
371
|
+
|
372
|
+
libssh2_channel_set_blocking(channel, 1);
|
373
|
+
|
374
|
+
s->session = session;
|
375
|
+
s->channel = channel;
|
376
|
+
|
377
|
+
t->current_stream = s;
|
378
|
+
git__free(host);
|
379
|
+
git__free(port);
|
380
|
+
git__free(user);
|
381
|
+
git__free(pass);
|
382
|
+
|
383
|
+
return 0;
|
384
|
+
|
385
|
+
on_error:
|
386
|
+
if (*stream)
|
387
|
+
ssh_stream_free(*stream);
|
388
|
+
|
389
|
+
git__free(host);
|
390
|
+
git__free(port);
|
391
|
+
git__free(user);
|
392
|
+
git__free(pass);
|
393
|
+
|
394
|
+
if (session)
|
395
|
+
libssh2_session_free(session), session = NULL;
|
396
|
+
|
397
|
+
return -1;
|
398
|
+
}
|
399
|
+
|
400
|
+
static int ssh_uploadpack_ls(
|
401
|
+
ssh_subtransport *t,
|
402
|
+
const char *url,
|
403
|
+
git_smart_subtransport_stream **stream)
|
404
|
+
{
|
405
|
+
if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0)
|
406
|
+
return -1;
|
407
|
+
|
408
|
+
return 0;
|
409
|
+
}
|
410
|
+
|
411
|
+
static int ssh_uploadpack(
|
412
|
+
ssh_subtransport *t,
|
413
|
+
const char *url,
|
414
|
+
git_smart_subtransport_stream **stream)
|
415
|
+
{
|
416
|
+
GIT_UNUSED(url);
|
417
|
+
|
418
|
+
if (t->current_stream) {
|
419
|
+
*stream = &t->current_stream->parent;
|
420
|
+
return 0;
|
421
|
+
}
|
422
|
+
|
423
|
+
giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK");
|
424
|
+
return -1;
|
425
|
+
}
|
426
|
+
|
427
|
+
static int ssh_receivepack_ls(
|
428
|
+
ssh_subtransport *t,
|
429
|
+
const char *url,
|
430
|
+
git_smart_subtransport_stream **stream)
|
431
|
+
{
|
432
|
+
if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0)
|
433
|
+
return -1;
|
434
|
+
|
435
|
+
return 0;
|
436
|
+
}
|
437
|
+
|
438
|
+
static int ssh_receivepack(
|
439
|
+
ssh_subtransport *t,
|
440
|
+
const char *url,
|
441
|
+
git_smart_subtransport_stream **stream)
|
442
|
+
{
|
443
|
+
GIT_UNUSED(url);
|
444
|
+
|
445
|
+
if (t->current_stream) {
|
446
|
+
*stream = &t->current_stream->parent;
|
447
|
+
return 0;
|
448
|
+
}
|
449
|
+
|
450
|
+
giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK");
|
451
|
+
return -1;
|
452
|
+
}
|
453
|
+
|
454
|
+
static int _ssh_action(
|
455
|
+
git_smart_subtransport_stream **stream,
|
456
|
+
git_smart_subtransport *subtransport,
|
457
|
+
const char *url,
|
458
|
+
git_smart_service_t action)
|
459
|
+
{
|
460
|
+
ssh_subtransport *t = (ssh_subtransport *) subtransport;
|
461
|
+
|
462
|
+
switch (action) {
|
463
|
+
case GIT_SERVICE_UPLOADPACK_LS:
|
464
|
+
return ssh_uploadpack_ls(t, url, stream);
|
465
|
+
|
466
|
+
case GIT_SERVICE_UPLOADPACK:
|
467
|
+
return ssh_uploadpack(t, url, stream);
|
468
|
+
|
469
|
+
case GIT_SERVICE_RECEIVEPACK_LS:
|
470
|
+
return ssh_receivepack_ls(t, url, stream);
|
471
|
+
|
472
|
+
case GIT_SERVICE_RECEIVEPACK:
|
473
|
+
return ssh_receivepack(t, url, stream);
|
474
|
+
}
|
475
|
+
|
476
|
+
*stream = NULL;
|
477
|
+
return -1;
|
478
|
+
}
|
479
|
+
|
480
|
+
static int _ssh_close(git_smart_subtransport *subtransport)
|
481
|
+
{
|
482
|
+
ssh_subtransport *t = (ssh_subtransport *) subtransport;
|
483
|
+
|
484
|
+
assert(!t->current_stream);
|
485
|
+
|
486
|
+
GIT_UNUSED(t);
|
487
|
+
|
488
|
+
return 0;
|
489
|
+
}
|
490
|
+
|
491
|
+
static void _ssh_free(git_smart_subtransport *subtransport)
|
492
|
+
{
|
493
|
+
ssh_subtransport *t = (ssh_subtransport *) subtransport;
|
494
|
+
|
495
|
+
assert(!t->current_stream);
|
496
|
+
|
497
|
+
git__free(t);
|
498
|
+
}
|
499
|
+
|
500
|
+
int git_smart_subtransport_ssh(git_smart_subtransport **out, git_transport *owner)
|
501
|
+
{
|
502
|
+
ssh_subtransport *t;
|
503
|
+
|
504
|
+
if (!out)
|
505
|
+
return -1;
|
506
|
+
|
507
|
+
t = git__calloc(sizeof(ssh_subtransport), 1);
|
508
|
+
GITERR_CHECK_ALLOC(t);
|
509
|
+
|
510
|
+
t->owner = (transport_smart *)owner;
|
511
|
+
t->parent.action = _ssh_action;
|
512
|
+
t->parent.close = _ssh_close;
|
513
|
+
t->parent.free = _ssh_free;
|
514
|
+
|
515
|
+
*out = (git_smart_subtransport *) t;
|
516
|
+
return 0;
|
517
|
+
}
|
518
|
+
|
519
|
+
#endif
|