The unified diff between revisions [1e32aef4..] and [95c3202d..] is displayed below. It can also be downloaded as a raw diff.
#
#
# patch "cmd_netsync.cc"
# from [814327c3c6fcc1982fc34d000a1410f3d86f3267]
# to [6b39feccad350c30a4d3900619e180c47a01d0fc]
#
# patch "key_store.cc"
# from [510eb02eab491fd9e79c49fcfcf5e6efa145872f]
# to [5c423e17442795e5cd6ca41ddc2c041e5ac5e553]
#
# patch "key_store.hh"
# from [a2cba22c7534941db07838f8f7b9e3abede66cce]
# to [86b0cfb3002761e38f91aa1b2b696d604a6bc674]
#
# patch "monotone.texi"
# from [c3c35da89e98ebf1c7c0386dfb83336c64f95422]
# to [c6f295ff19bdc6a6fc1fe1d4ec1a43d500f782dc]
#
# patch "netsync.cc"
# from [f46b86a575c13f5454ac1df71a28f03d977e282a]
# to [22eda2f383261b7bb48b44fa3f77bee10a4e2f3b]
#
# patch "options_list.hh"
# from [06fc91493585539a0397d9020253aeda717ccb90]
# to [a2b3cbf33d9686a72ab80da09489e9ea3bf5ee33]
#
============================================================
--- cmd_netsync.cc 814327c3c6fcc1982fc34d000a1410f3d86f3267
+++ cmd_netsync.cc 6b39feccad350c30a4d3900619e180c47a01d0fc
@@ -237,6 +237,39 @@ CMD(push, "push", "", CMD_REF(network),
client_voice, source_role, info);
}
+CMD_AUTOMATE(push, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"),
+ N_("Pushes branches to a netsync server"),
+ "",
+ options::opts::set_default | options::opts::exclude |
+ options::opts::key_to_push | options::opts::do_not_enforce_ssh_agent)
+{
+ database db(app);
+ key_store keys(app);
+ project_t project(db);
+
+ netsync_connection_info info;
+ extract_client_connection_info(app.opts, app.lua, db, keys, args, info);
+
+ if (app.opts.signing_key() != "" && !app.opts.do_not_enforce_ssh_agent)
+ {
+ // enforce that any command which needs to encrypt a private key later on
+ // uses the ssh_agent to do the task, because we cannot handle password
+ // prompts over stdio. basically this is the same as giving --ssh-sign=only
+ // as option to stdio, but it is more explicit. however, this also leaves
+ // the opportunity of giving a possible passphrase via the get_passphrase
+ // lua hook, because the ssh agent is _always_ used, but its a reasonable
+ // trade-off
+ keys.enforce_ssh_agent();
+
+ N(keys.agent_knows_key(app.opts.signing_key),
+ F("key '%s' is unknown to the running ssh-agent instance")
+ % app.opts.signing_key);
+ }
+
+ run_netsync_protocol(app.opts, app.lua, project, keys,
+ client_voice, source_role, info);
+}
+
CMD(pull, "pull", "", CMD_REF(network),
N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"),
N_("Pulls branches from a netsync server"),
@@ -262,7 +295,8 @@ CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUM
CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"),
N_("Pulls branches from a netsync server"),
"",
- options::opts::set_default | options::opts::exclude)
+ options::opts::set_default | options::opts::exclude |
+ options::opts::do_not_enforce_ssh_agent)
{
database db(app);
key_store keys(app);
@@ -272,9 +306,22 @@ CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUM
extract_client_connection_info(app.opts, app.lua, db, keys,
args, info, false);
- if (app.opts.signing_key() == "")
- P(F("doing anonymous pull; use -kKEYNAME if you need authentication"));
+ if (app.opts.signing_key() != "" && !app.opts.do_not_enforce_ssh_agent)
+ {
+ // enforce that any command which needs to encrypt a private key later on
+ // uses the ssh_agent to do the task, because we cannot handle password
+ // prompts over stdio. basically this is the same as giving --ssh-sign=only
+ // as option to stdio, but it is more explicit. however, this also leaves
+ // the opportunity of giving a possible passphrase via the get_passphrase
+ // lua hook, because the ssh agent is _always_ used, but its a reasonable
+ // trade-off
+ keys.enforce_ssh_agent();
+ N(keys.agent_knows_key(app.opts.signing_key),
+ F("key '%s' is unknown to the running ssh-agent instance")
+ % app.opts.signing_key);
+ }
+
run_netsync_protocol(app.opts, app.lua, project, keys,
client_voice, sink_role, info);
}
@@ -285,7 +332,7 @@ CMD(sync, "sync", "", CMD_REF(network),
N_("This synchronizes branches that match the pattern given in PATTERN "
"with the netsync server at the address ADDRESS."),
options::opts::set_default | options::opts::exclude |
- options::opts::key_to_push)
+ options::opts::key_to_push | options::opts::do_not_enforce_ssh_agent)
{
database db(app);
key_store keys(app);
@@ -305,6 +352,39 @@ CMD(sync, "sync", "", CMD_REF(network),
client_voice, source_and_sink_role, info);
}
+CMD_AUTOMATE(sync, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"),
+ N_("Synchronizes branches with a netsync server"),
+ "",
+ options::opts::set_default | options::opts::exclude |
+ options::opts::key_to_push)
+{
+ database db(app);
+ key_store keys(app);
+ project_t project(db);
+
+ netsync_connection_info info;
+ extract_client_connection_info(app.opts, app.lua, db, keys, args, info);
+
+ if (app.opts.signing_key() != "" && !app.opts.do_not_enforce_ssh_agent)
+ {
+ // enforce that any command which needs to encrypt a private key later on
+ // uses the ssh_agent to do the task, because we cannot handle password
+ // prompts over stdio. basically this is the same as giving --ssh-sign=only
+ // as option to stdio, but it is more explicit. however, this also leaves
+ // the opportunity of giving a possible passphrase via the get_passphrase
+ // lua hook, because the ssh agent is _always_ used, but its a reasonable
+ // trade-off
+ keys.enforce_ssh_agent();
+
+ N(keys.agent_knows_key(app.opts.signing_key),
+ F("key '%s' is unknown to the running ssh-agent instance")
+ % app.opts.signing_key);
+ }
+
+ run_netsync_protocol(app.opts, app.lua, project, keys,
+ client_voice, source_and_sink_role, info);
+}
+
class dir_cleanup_helper
{
public:
============================================================
--- key_store.cc 510eb02eab491fd9e79c49fcfcf5e6efa145872f
+++ key_store.cc 5c423e17442795e5cd6ca41ddc2c041e5ac5e553
@@ -710,7 +710,31 @@ key_store::export_key_for_agent(rsa_keyp
p.end_msg();
}
+void
+key_store::enforce_ssh_agent()
+{
+ ssh_agent & agent = s->get_agent();
+ N(agent.connected(),
+ F("this command enforces the only usage of ssh_agent, "
+ "but no ssh-agent is available."));
+ if (s->ssh_sign_mode != "only")
+ {
+ W(F("enforcing the only usage of ssh_agent"));
+ const_cast<std::string &>(s->ssh_sign_mode) = "only";
+ }
+}
+bool
+key_store::agent_knows_key(rsa_keypair_id const & ident)
+{
+ keypair keyp;
+ N(maybe_get_key_pair(ident, keyp),
+ F("no keypair for '%s' in keyring") % ident);
+
+ ssh_agent & agent = s->get_agent();
+ return agent.has_key(keyp);
+}
+
//
// Migration from old databases
//
============================================================
--- key_store.hh a2cba22c7534941db07838f8f7b9e3abede66cce
+++ key_store.hh 86b0cfb3002761e38f91aa1b2b696d604a6bc674
@@ -82,6 +82,8 @@ public:
void add_key_to_agent(rsa_keypair_id const & id);
void export_key_for_agent(rsa_keypair_id const & id,
std::ostream & os);
+ void enforce_ssh_agent();
+ bool agent_knows_key(rsa_keypair_id const & ident);
// Migration from old databases
============================================================
--- monotone.texi c3c35da89e98ebf1c7c0386dfb83336c64f95422
+++ monotone.texi c6f295ff19bdc6a6fc1fe1d4ec1a43d500f782dc
@@ -7573,6 +7573,103 @@ @section Automation
@end table
+
+@item mtn automate pull [--set-default] [@var{uri-or-address}] [@var{glob} [...] [--exclude=@var{exclude-glob}]]] [--do-not-enforce-ssh-agent]
+@itemx mtn automate push [--set-default] [@var{uri-or-address}] [@var{glob} [...] [--exclude=@var{exclude-glob}]]] [--do-not-enforce-ssh-agent] [--key-to-push=@var{key-id}]
+@itemx mtn automate sync [--set-default] [@var{uri-or-address}] [@var{glob} [...] [--exclude=@var{exclude-glob}]]] [--do-not-enforce-ssh-agent] [--key-to-push=@var{key-id}]
+
+@table @strong
+@item Arguments:
+
+The automate versions of pull, push and sync have a superset of arguments and
+options compared to the non-automate versions. For an explanation of these
+common parts please check this manual in the appropriate section.
+
+Furthermore, you can define @option{--do-not-enforce-ssh-agent} which make
+these commands not using a running ssh agent instance explicitely. The setting
+of this option is highly discouraged if you run the command from inside stdio,
+because it might break your output in case a password is needed to decrypt a
+user key and no get_passphrase() lua hook has been set up.
+
+@item Added in:
+
+8.0
+
+@item Purpose:
+
+Pushes, pulls or syncs (push & pull) revisions, certificates and keys from
+the given database to / from / with to another (foreign) one. A running
+ssh-agent instance is required and the key which is used for signing /
+authentication has to be loaded into ssh-agent beforehand.
+
+@item Sample output (stdio):
+
+The following output shows an example of a pull which transferred two revisions
+and eight certs.
+
+@emph{Note:} The linebreaks are not part of the actual format.
+
+@verbatim
+0:0:p:62:doing anonymous pull; use -kKEYNAME if you need authentication
+0:0:p:25:connecting to monotone.ca0:0:p:29:finding items to synchronize:
+0:0:t:34:c:certificates;k:keys;r:revisions;
+0:0:t:12:c=0;k=0;r=0;
+0:0:t:13:c#0;k#0;r#64;
+0:0:t:14:c#0;k#0;r#128;
+[...]
+0:0:t:6:c;k;r;
+0:0:t:44:>:bytes in;<:bytes out;c:certs in;r:revs in;
+0:0:t:16:>=0;<=0;c=0;r=0;
+0:0:t:21:>#420;<#1344;c#0;r#0;
+0:0:t:22:>#1165;<#1741;c#0;r#0;
+[...]
+0:0:t:24:>#20839;<#14882;c#0;r#1;
+0:0:t:24:>#20839;<#14882;c#3;r#1;
+0:0:t:24:>#20839;<#14882;c#4;r#2;
+0:0:t:24:>#20839;<#14882;c#6;r#2;
+0:0:t:24:>#20863;<#14930;c#8;r#2;
+0:0:t:8:<;>;c;r;
+0:0:p:36:successful exchange with monotone.ca
+0:0:l:0:
+@end verbatim
+
+@item Output format:
+
+Netsync commands output info and ticker messages just like the normal netsync
+commands do.
+
+If these commands are run over stdio, the stdio ticker format is used
+(for a description of this format, check @command{automate stdio}).
+
+The following ticker types are printed out during the refinement phase:
+
+@itemize
+@item 'c': The amount of certs found for an upcoming synchronization
+@item 'k': The amount of keys found for an upcoming synchronization
+@item 'r': The amount of revisions found for an upcoming synchronization
+@end itemize
+
+After refinement the actual synchronization between the two nodes start. The
+ticker stanzas in this phase are the following:
+
+@itemize
+@item '>': number of incoming bytes
+@item '<': number of outgoing bytes
+@item 'c': number of incoming certs (only pull and sync)
+@item 'C': number of outgoing certs (only push and sync)
+@item 'r': number of incoming revisions (only pull and sync)
+@item 'R': number of outgoing revisions (only push and sync)
+@end itemize
+
+@item Error conditions:
+
+If no ssh-agent instance is running, the signing key hasn't been loaded into
+a running ssh-agent instance or a netsync error occurs, the command outputs
+an error and exits with status 1.
+
+@end table
+
+
@item mtn automate get_current_revision [--exclude @var{excl}] [--depth=@var{depth}] [@var{path} ...]
@table @strong
============================================================
--- netsync.cc f46b86a575c13f5454ac1df71a28f03d977e282a
+++ netsync.cc 22eda2f383261b7bb48b44fa3f77bee10a4e2f3b
@@ -2498,6 +2498,9 @@ call_server(options & opts,
// Commit whatever work we managed to accomplish anyways.
guard.commit();
+ // ensure that the tickers have finished and write any last ticks
+ ui.ensure_clean_line();
+
// We had an I/O error. We must decide if this represents a
// user-reported error or a clean disconnect. See protocol
// state diagram in session::process_bye_cmd.
============================================================
--- options_list.hh 06fc91493585539a0397d9020253aeda717ccb90
+++ options_list.hh a2b3cbf33d9686a72ab80da09489e9ea3bf5ee33
@@ -80,6 +80,17 @@ OPT(automate_stdio_size, "automate-stdio
}
#endif
+OPT(do_not_enforce_ssh_agent, "do-not-enforce-ssh-agent", bool, false,
+ gettext_noop("do not enforce the usage of ssh-agent. enabling this is "
+ "highly discouraged if you run this command over stdio "
+ "as it may prompt for a key password which cannot be "
+ "handled."))
+#ifdef option_bodies
+{
+ do_not_enforce_ssh_agent = true;
+}
+#endif
+
OPTSET(bind_opts)
OPTVAR(bind_opts, std::list<utf8>, bind_uris, )
OPTVAR(bind_opts, bool, bind_stdio, false)