Download raw body.
add ssh -J support to commands which use network
Add a -J option to got clone, fetch, send, as well as cvg clone,
update, commit. This allows ad-hoc use of SSH jumphosts without
having to create entries in ~/.ssh/config.
For example, I found this useful when I wanted to fetch from a
IPv6-only system while borrowing an IPv4-only wifi connection.
ok?
M cvg/cvg.1 | 21+ 0-
M cvg/cvg.c | 16+ 7-
M got/got.1 | 21+ 0-
M got/got.c | 18+ 6-
M include/got_fetch.h | 2+ 1-
M include/got_send.h | 2+ 1-
M include/got_worktree_cvg.h | 2+ 2-
M lib/dial.c | 7+ 2-
M lib/fetch.c | 3+ 2-
M lib/got_lib_dial.h | 1+ 1-
M lib/send.c | 3+ 2-
M lib/worktree_cvg.c | 5+ 5-
12 files changed, 101 insertions(+), 29 deletions(-)
commit - 75bd1d8cea00a4cbdbdf6bcea2eb272df2fef76e
commit + acf380be9009698bb1246951ede400f9a6d2c937
blob - 265da0a0dd5a94a5dc92044cdc974254621de8fd
blob + 5e361ba7f6fa77f9358deaad245b6589b7c35e15
--- cvg/cvg.1
+++ cvg/cvg.1
@@ -135,6 +135,7 @@ working directory.
.Cm clone
.Op Fl almqv
.Op Fl b Ar branch
+.Op Fl J Ar jumphost
.Op Fl R Ar reference
.Ar repository-URL
.Op Ar directory
@@ -240,6 +241,12 @@ repository's HEAD reference will be fetched.
Cannot be used together with the
.Fl a
option.
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl l
List branches and tags available for fetching from the remote repository
and exit immediately.
@@ -401,6 +408,7 @@ Silence progress output.
.Op Fl q
.Op Fl b Ar branch
.Op Fl c Ar commit
+.Op Fl J Ar jumphost
.Op Ar path ...
.Xc
.Dl Pq alias: Cm up
@@ -497,6 +505,12 @@ An abbreviated hash argument will be expanded to a com
automatically, provided the abbreviation is unique.
If this option is not specified, the most recent commit on the work tree's
branch will be used.
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl q
Silence progress output.
.El
@@ -1287,6 +1301,7 @@ is a directory.
.Op Fl CNnS
.Op Fl A Ar author
.Op Fl F Ar path
+.Op Fl J Ar jumphost
.Op Fl m Ar message
.Op Ar path ...
.Xc
@@ -1396,6 +1411,12 @@ Use the specified log message when creating the new co
Cannot be used together with the
.Fl F
option.
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl N
This option prevents
.Cm got commit
blob - 14f6f69962facd1f76c094458fd23bec1fabb9f1
blob + 9f093ace3cfdb472bce06ad93efc12cb9138a9e4
--- cvg/cvg.c
+++ cvg/cvg.c
@@ -1534,13 +1534,14 @@ cmd_clone(int argc, char *argv[])
int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
int bflag = 0, list_refs_only = 0;
int *pack_fds = NULL;
+ const char *jumphost = NULL;
TAILQ_INIT(&refs);
TAILQ_INIT(&symrefs);
TAILQ_INIT(&wanted_branches);
TAILQ_INIT(&wanted_refs);
- while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
+ while ((ch = getopt(argc, argv, "ab:J:lmqR:v")) != -1) {
switch (ch) {
case 'a':
fetch_all_branches = 1;
@@ -1552,6 +1553,9 @@ cmd_clone(int argc, char *argv[])
return error;
bflag = 1;
break;
+ case 'J':
+ jumphost = optarg;
+ break;
case 'l':
list_refs_only = 1;
break;
@@ -1670,7 +1674,7 @@ cmd_clone(int argc, char *argv[])
printf("Connecting to %s\n", git_url);
error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (error)
goto done;
@@ -2662,6 +2666,7 @@ cmd_update(int argc, char *argv[])
char *commit_id_str = NULL;
const char *refname;
struct got_reference *head_ref = NULL;
+ const char *jumphost = NULL;
TAILQ_INIT(&paths);
TAILQ_INIT(&refs);
@@ -2670,13 +2675,16 @@ cmd_update(int argc, char *argv[])
TAILQ_INIT(&wanted_branches);
TAILQ_INIT(&wanted_refs);
- while ((ch = getopt(argc, argv, "c:qr:vX")) != -1) {
+ while ((ch = getopt(argc, argv, "c:J:qr:vX")) != -1) {
switch (ch) {
case 'c':
commit_id_str = strdup(optarg);
if (commit_id_str == NULL)
return got_error_from_errno("strdup");
break;
+ case 'J':
+ jumphost = optarg;
+ break;
case 't':
replace_tags = 1;
break;
@@ -2828,7 +2836,7 @@ cmd_update(int argc, char *argv[])
}
error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (error)
goto done;
@@ -7802,7 +7810,7 @@ cmd_commit(int argc, char *argv[])
int nremotes;
char *proto = NULL, *host = NULL, *port = NULL;
char *repo_name = NULL, *server_path = NULL;
- const char *remote_name;
+ const char *remote_name, *jumphost = NULL;
int verbosity = 0;
int i;
@@ -7816,7 +7824,7 @@ cmd_commit(int argc, char *argv[])
err(1, "pledge");
#endif
- while ((ch = getopt(argc, argv, "A:CF:m:NnS")) != -1) {
+ while ((ch = getopt(argc, argv, "A:CF:J:m:NnS")) != -1) {
switch (ch) {
case 'A':
author = optarg;
@@ -8024,7 +8032,8 @@ cmd_commit(int argc, char *argv[])
error = got_worktree_cvg_commit(&id, worktree, &paths, author,
committer, allow_bad_symlinks, show_diff, commit_conflicts,
collect_commit_logmsg, &cl_arg, print_status, NULL, proto, host,
- port, server_path, verbosity, remote, check_cancelled, repo);
+ port, server_path, jumphost, verbosity, remote,
+ check_cancelled, repo);
if (error) {
if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
cl_arg.logmsg_path != NULL)
blob - 4983f2ac232429e5c39c59d67d5fc268d186efd1
blob + 8fb89aed8c779a9d24c3c7b907fbedcfae7c7b29
--- got/got.1
+++ got/got.1
@@ -204,6 +204,7 @@ working directory.
.Cm clone
.Op Fl almqv
.Op Fl b Ar branch
+.Op Fl J Ar jumphost
.Op Fl R Ar reference
.Ar repository-URL
.Op Ar directory
@@ -338,6 +339,12 @@ repository's HEAD reference will be fetched.
Cannot be used together with the
.Fl a
option.
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl l
List branches and tags available for fetching from the remote repository
and exit immediately.
@@ -425,6 +432,7 @@ The maximum is 3.
.Cm fetch
.Op Fl adlqtvX
.Op Fl b Ar branch
+.Op Fl J Ar jumphost
.Op Fl R Ar reference
.Op Fl r Ar repository-path
.Op Ar remote-repository
@@ -531,6 +539,12 @@ Any commit, tree, tag, and blob objects belonging to d
tags remain in the repository and may be removed separately with
Git's garbage collector or
.Cm gotadmin cleanup .
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl l
List branches and tags available for fetching from the remote repository
and exit immediately.
@@ -2331,6 +2345,7 @@ in the repository.
.Op Fl afqTv
.Op Fl b Ar branch
.Op Fl d Ar branch
+.Op Fl J Ar jumphost
.Op Fl r Ar repository-path
.Op Fl t Ar tag
.Op Ar remote-repository
@@ -2465,6 +2480,12 @@ copy of a branch or tag is known to be out-of-date and
disposable.
The risks of creating inconsistencies between different repositories
should also be taken into account.
+.It Fl J Ar jumphost
+Specify a
+.Ar jumphost
+to use with SSH connections.
+The same option will be passed to
+.Xr ssh 1 .
.It Fl q
Suppress progress reporting output.
The same option will be passed to
blob - ed5defc312e6a540e5c6a78407f1fa1d9dce3812
blob + ff35c0c72ff6e7058ac0339162720511890984cc
--- got/got.c
+++ got/got.c
@@ -1627,6 +1627,7 @@ cmd_clone(int argc, char *argv[])
pid_t fetchpid = -1;
struct got_fetch_progress_arg fpa;
char *git_url = NULL;
+ const char *jumphost = NULL;
int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
int bflag = 0, list_refs_only = 0;
int *pack_fds = NULL;
@@ -1636,7 +1637,7 @@ cmd_clone(int argc, char *argv[])
TAILQ_INIT(&wanted_branches);
TAILQ_INIT(&wanted_refs);
- while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
+ while ((ch = getopt(argc, argv, "ab:J:lmqR:v")) != -1) {
switch (ch) {
case 'a':
fetch_all_branches = 1;
@@ -1648,6 +1649,9 @@ cmd_clone(int argc, char *argv[])
return error;
bflag = 1;
break;
+ case 'J':
+ jumphost = optarg;
+ break;
case 'l':
list_refs_only = 1;
break;
@@ -1766,7 +1770,7 @@ cmd_clone(int argc, char *argv[])
printf("Connecting to %s\n", git_url);
error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (error)
goto done;
@@ -2384,6 +2388,7 @@ cmd_fetch(int argc, char *argv[])
int delete_refs = 0, replace_tags = 0, delete_remote = 0;
int *pack_fds = NULL, have_bflag = 0;
const char *remote_head = NULL, *worktree_branch = NULL;
+ const char *jumphost = NULL;
TAILQ_INIT(&refs);
TAILQ_INIT(&symrefs);
@@ -2391,7 +2396,7 @@ cmd_fetch(int argc, char *argv[])
TAILQ_INIT(&wanted_branches);
TAILQ_INIT(&wanted_refs);
- while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
+ while ((ch = getopt(argc, argv, "ab:dJ:lqR:r:tvX")) != -1) {
switch (ch) {
case 'a':
fetch_all_branches = 1;
@@ -2406,6 +2411,9 @@ cmd_fetch(int argc, char *argv[])
case 'd':
delete_refs = 1;
break;
+ case 'J':
+ jumphost = optarg;
+ break;
case 'l':
list_refs_only = 1;
break;
@@ -2643,7 +2651,7 @@ cmd_fetch(int argc, char *argv[])
}
error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (error)
goto done;
#ifndef PROFILE
@@ -9920,6 +9928,7 @@ cmd_send(int argc, char *argv[])
int send_all_branches = 0, send_all_tags = 0;
struct got_reference *ref = NULL;
int *pack_fds = NULL;
+ const char *jumphost = NULL;
TAILQ_INIT(&branches);
TAILQ_INIT(&tags);
@@ -9928,7 +9937,7 @@ cmd_send(int argc, char *argv[])
TAILQ_INIT(&delete_args);
TAILQ_INIT(&delete_branches);
- while ((ch = getopt(argc, argv, "ab:d:fqr:Tt:v")) != -1) {
+ while ((ch = getopt(argc, argv, "ab:d:fJ:qr:Tt:v")) != -1) {
switch (ch) {
case 'a':
send_all_branches = 1;
@@ -9947,6 +9956,9 @@ cmd_send(int argc, char *argv[])
case 'f':
overwrite_refs = 1;
break;
+ case 'J':
+ jumphost = optarg;
+ break;
case 'q':
verbosity = -1;
break;
@@ -10214,7 +10226,7 @@ cmd_send(int argc, char *argv[])
}
error = got_send_connect(&sendpid, &sendfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (error)
goto done;
blob - d14b5f1032910d954b7d663f20e1d8e0b04b216c
blob + abf138991ddab8ea1eae485f37d910d443f8fe76
--- include/got_fetch.h
+++ include/got_fetch.h
@@ -19,6 +19,7 @@
/*
* Attempt to open a connection to a server using the provided protocol
* scheme, hostname port number (as a string) and server-side path.
+ * A jumphost can be specified which will be passed to ssh(1) via -J.
* A verbosity level can be specified; it currently controls the amount
* of -v options passed to ssh(1). If the level is -1 ssh(1) will be run
* with the -q option.
@@ -31,7 +32,7 @@
* the process to exit with waitpid(2). Otherwise, return PID -1.
*/
const struct got_error *got_fetch_connect(pid_t *, int *, const char *,
- const char *, const char *, const char *, int);
+ const char *, const char *, const char *, const char *, int);
/* A callback function which gets invoked with progress information to print. */
typedef const struct got_error *(*got_fetch_progress_cb)(void *,
blob - 038b51f30308b8ca6879fdbddcfd64c6c83b7594
blob + 9f8c6498d5a65aa365c53f33830bcb336c8c2ee3
--- include/got_send.h
+++ include/got_send.h
@@ -26,13 +26,14 @@
*
* If successful return an open file descriptor for the connection which can
* be passed to other functions below, and must be disposed of with close(2).
+ * A jumphost can be specified which will be passed to ssh(1) via -J.
*
* If an ssh(1) process was started return its PID as well, in which case
* the caller should eventually send SIGTERM to the procress and wait for
* the process to exit with waitpid(2). Otherwise, return PID -1.
*/
const struct got_error *got_send_connect(pid_t *, int *, const char *,
- const char *, const char *, const char *, int);
+ const char *, const char *, const char *, const char *, int);
/* A callback function which gets invoked with progress information to print. */
typedef const struct got_error *(*got_send_progress_cb)(void *,
blob - 5607eff4903ac486cf8766910d0e6ea7a47f928a
blob + 72cd9b87962075687ca6d1b929f6f55cb33236ef
--- include/got_worktree_cvg.h
+++ include/got_worktree_cvg.h
@@ -31,8 +31,8 @@ const struct got_error *got_worktree_cvg_commit(struct
struct got_worktree *, struct got_pathlist_head *, const char *,
const char *, int, int, int, got_worktree_commit_msg_cb, void *,
got_worktree_status_cb, void *, const char *, const char *, const char *,
- const char *, int, const struct got_remote_repo *, got_cancel_cb,
- struct got_repository *);
+ const char *, const char *, int, const struct got_remote_repo *,
+ got_cancel_cb, struct got_repository *);
/*
* Get the reference name for a temporary commit to be trivially rebased
blob - 88b600b1f00ec7c68d10041e64ae7ef76b9baac2
blob + 6f47d70612b97fe473d6aba91f3907153a33dd56
--- lib/dial.c
+++ lib/dial.c
@@ -261,13 +261,14 @@ escape_path(char *buf, size_t bufsize, const char *pat
const struct got_error *
got_dial_ssh(pid_t *newpid, int *newfd, const char *host,
- const char *port, const char *path, const char *command, int verbosity)
+ const char *port, const char *path, const char *jumphost,
+ const char *command, int verbosity)
{
const struct got_error *error = NULL;
int pid, pfd[2];
char cmd[64];
char escaped_path[PATH_MAX];
- const char *argv[11];
+ const char *argv[13];
int i = 0, j;
*newpid = -1;
@@ -289,6 +290,10 @@ got_dial_ssh(pid_t *newpid, int *newfd, const char *ho
for (j = 0; j < MIN(3, verbosity); j++)
argv[i++] = "-v";
}
+ if (jumphost) {
+ argv[i++] = "-J";
+ argv[i++] = jumphost;
+ }
argv[i++] = "--";
argv[i++] = (char *)host;
argv[i++] = (char *)cmd;
blob - 7c67b8bd27d8f0b14c6c6ab064426ba9ca064259
blob + b64070e012cce8f1a3fb519298edb01b361b48eb
--- lib/fetch.c
+++ lib/fetch.c
@@ -79,7 +79,8 @@
const struct got_error *
got_fetch_connect(pid_t *fetchpid, int *fetchfd, const char *proto,
- const char *host, const char *port, const char *server_path, int verbosity)
+ const char *host, const char *port, const char *server_path,
+ const char *jumphost, int verbosity)
{
const struct got_error *err = NULL;
@@ -88,7 +89,7 @@ got_fetch_connect(pid_t *fetchpid, int *fetchfd, const
if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
err = got_dial_ssh(fetchpid, fetchfd, host, port,
- server_path, GOT_DIAL_CMD_FETCH, verbosity);
+ server_path, jumphost, GOT_DIAL_CMD_FETCH, verbosity);
else if (strcmp(proto, "git") == 0)
err = got_dial_git(fetchfd, host, port, server_path,
GOT_DIAL_CMD_FETCH);
blob - 63de6cd1cf810d258095343358365fa993a0aa82
blob + 2e53b80d6121b5d2e79d4ffedc74c0fb6529a6de
--- lib/got_lib_dial.h
+++ lib/got_lib_dial.h
@@ -23,7 +23,7 @@ const struct got_error *got_dial_git(int *newfd, const
const struct got_error *got_dial_ssh(pid_t *newpid, int *newfd,
const char *host, const char *port, const char *path,
- const char *command, int verbosity);
+ const char *jumphost, const char *command, int verbosity);
const struct got_error *got_dial_http(pid_t *newpid, int *newfd,
const char *host, const char *port, const char *path, int, int);
blob - f8e87fabb17857a5abf28d64d34330a17b6aefc7
blob + 348d1dbb26e60918ccd5c3ea7b3106ec92916e40
--- lib/send.c
+++ lib/send.c
@@ -86,7 +86,8 @@
const struct got_error *
got_send_connect(pid_t *sendpid, int *sendfd, const char *proto,
- const char *host, const char *port, const char *server_path, int verbosity)
+ const char *host, const char *port, const char *server_path,
+ const char *jumphost, int verbosity)
{
const struct got_error *err = NULL;
@@ -95,7 +96,7 @@ got_send_connect(pid_t *sendpid, int *sendfd, const ch
if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
err = got_dial_ssh(sendpid, sendfd, host, port, server_path,
- GOT_DIAL_CMD_SEND, verbosity);
+ jumphost, GOT_DIAL_CMD_SEND, verbosity);
else if (strcmp(proto, "git") == 0)
err = got_dial_git(sendfd, host, port, server_path,
GOT_DIAL_CMD_SEND);
blob - e385e250cc75d449167dd82181f0654e2dcdf4e5
blob + b9abd5bf360259fba46644942a97cd1cc76f4b9f
--- lib/worktree_cvg.c
+++ lib/worktree_cvg.c
@@ -2764,7 +2764,7 @@ done:
static const struct got_error *
fetch_updated_remote(const char *proto, const char *host, const char *port,
- const char *server_path, int verbosity,
+ const char *server_path, const char *jumphost, int verbosity,
const struct got_remote_repo *remote, struct got_repository *repo,
struct got_reference *head_ref, const char *head_refname)
{
@@ -2790,7 +2790,7 @@ fetch_updated_remote(const char *proto, const char *ho
goto done;
err = got_fetch_connect(&fetchpid, &fetchfd, proto, host,
- port, server_path, verbosity);
+ port, server_path, jumphost, verbosity);
if (err)
goto done;
@@ -2909,7 +2909,7 @@ got_worktree_cvg_commit(struct got_object_id **new_com
got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
got_worktree_status_cb status_cb, void *status_arg,
const char *proto, const char *host, const char *port,
- const char *server_path, int verbosity,
+ const char *server_path, const char *jumphost, int verbosity,
const struct got_remote_repo *remote,
got_cancel_cb check_cancelled,
struct got_repository *repo)
@@ -3089,7 +3089,7 @@ got_worktree_cvg_commit(struct got_object_id **new_com
/* Attempt send to remote branch. */
err = got_send_connect(&sendpid, &sendfd, proto, host, port,
- server_path, verbosity);
+ server_path, jumphost, verbosity);
if (err)
goto done;
@@ -3110,7 +3110,7 @@ got_worktree_cvg_commit(struct got_object_id **new_com
* No trivial-rebase yet; require update to be run manually.
*/
err = fetch_updated_remote(proto, host, port, server_path,
- verbosity, remote, repo, head_ref, head_refname);
+ jumphost, verbosity, remote, repo, head_ref, head_refname);
if (err == NULL)
goto done;
err = got_error(GOT_ERR_COMMIT_OUT_OF_DATE);
add ssh -J support to commands which use network