#
# add_file "tests/t_automate_keys.at"
#
# patch "ChangeLog"
# from [c4f4a80a415023bcf3db13121d7b8e8d877408c1]
# to [86d863c44b004e81501265ab4e5e6a9b344ebd1a]
#
# patch "automate.cc"
# from [5b96e0ff436ae87bdb8bd25121cd53a522af80d6]
# to [a8bd4b7f0dcff557067dc0c1697e3d47e9f7c890]
#
# patch "basic_io.cc"
# from [3c575f5fd41d00730c3a0a9eafe84105fa51f28a]
# to [f548b2a09749dd603757d8ac491e020a67207eff]
#
# patch "basic_io.hh"
# from [74d226adb3879eeb068b39172c59377a733148ab]
# to [c46a35a67fa990a9bd759f09b1cdd2223e7783de]
#
# patch "commands.cc"
# from [e44277638e21b8a20fa0c6f68f067b3799827d0c]
# to [0ea3bfbf93bf5ab0a18e4b11a894d7c8f31dc646]
#
# patch "monotone.texi"
# from [f03a883ec62cd2aa2b9e7d972d045630391f9e99]
# to [c88edde8d3ac6fcf1f89465a528381a2b0307a6d]
#
# patch "tests/t_automate_keys.at"
# from []
# to [e97dbcb4dc72815d32bfa1f202b9404acbd6ba42]
#
# patch "testsuite.at"
# from [388fd624698f3b9219a28ad8f89df2637d608ca1]
# to [c42fcb759b296535e9105e987d6cad39ed3370f6]
#
========================================================================
--- ChangeLog c4f4a80a415023bcf3db13121d7b8e8d877408c1
+++ ChangeLog 86d863c44b004e81501265ab4e5e6a9b344ebd1a
@@ -1,3 +1,16 @@
+2005-10-07 Timothy Brownawell
+
+ * automate.cc: add "automate keys". like "ls keys", except it
+ uses basic_io (since "ls keys" is now slightly irregular and not
+ very well suited to machine interpretation).
+ * monotone.texi: document it
+ * tests/t_automate_keys.at: test for it
+ * testsuite.at: add test
+ * basic_io.{cc,hh} (stanza): add push_str_multi, for entries
+ that can take a variable number of string arguments.
+ * commands.cc: add "automate keys" to automate help
+ misc minor whitespace cleanup
+
2005-10-06 Timothy Brownawell
* commands.cc (ls_keys): don't insist on having a db
========================================================================
--- automate.cc 5b96e0ff436ae87bdb8bd25121cd53a522af80d6
+++ automate.cc a8bd4b7f0dcff557067dc0c1697e3d47e9f7c890
@@ -14,6 +14,7 @@
#include
#include
+#include
#include "app_state.hh"
#include "basic_io.hh"
@@ -23,8 +24,9 @@
#include "revision.hh"
#include "transforms.hh"
#include "vocab.hh"
+#include "keys.hh"
-static std::string const interface_version = "1.0";
+static std::string const interface_version = "1.1";
// Name: interface_version
// Arguments: none
@@ -1263,6 +1265,105 @@
}
}
+// Name: keys
+// Arguments: none
+// Added in: 1.1
+// Purpose: Prints all keys in the keystore, and if a database is given
+// also all keys in the database, in basic_io format.
+// Output format: For each key, a basic_io stanza is printed. The items in
+// the stanza are:
+// name - the key identifier
+// public_hash - the hash of the public half of the key
+// private_hash - the hash of the private half of the key
+// public_location - where the public half of the key is stored
+// private_location - where the private half of the key is stored
+// The *_location items may have multiple values, as shown below
+// for public_location.
+// If the private key does not exist, then the private_hash and
+// private_location items will be absent.
+//
+// Sample output:
+// name "address@hidden"
+// public_hash [475055ec71ad48f5dfaf875b0fea597b5cbbee64]
+// private_hash [7f76dae3f91bb48f80f1871856d9d519770b7f8a]
+// public_location "database" "keystore"
+// private_location "keystore"
+//
+// name "address@hidden"
+// public_hash [de84b575d5e47254393eba49dce9dc4db98ed42d]
+// public_location "database"
+//
+// name "address@hidden"
+// public_hash [7b6ce0bd83240438e7a8c7c207d8654881b763f6]
+// private_hash [bfc3263e3257087f531168850801ccefc668312d]
+// public_location "keystore"
+// private_location "keystore"
+//
+// Error conditions: None.
+static void
+automate_keys(std::vector args, std::string const & help_name,
+ app_state & app, std::ostream & output)
+{
+ if (args.size() != 0)
+ throw usage(help_name);
+ std::vector dbkeys;
+ std::vector kskeys;
+ // public_hash, private_hash, public_location, private_location
+ std::map, hexenc,
+ std::vector,
+ std::vector > > items;
+ if (app.db.database_specified())
+ {
+ transaction_guard guard(app.db);
+ app.db.get_key_ids("", dbkeys);
+ guard.commit();
+ }
+ app.keys.get_key_ids("", kskeys);
+
+ for (std::vector::iterator i = dbkeys.begin();
+ i != dbkeys.end(); i++)
+ {
+ base64 pub_encoded;
+ hexenc hash_code;
+
+ app.db.get_key(*i, pub_encoded);
+ key_hash_code(*i, pub_encoded, hash_code);
+ items[(*i)()].get<0>() = hash_code;
+ items[(*i)()].get<2>().push_back("database");
+ }
+
+ for (std::vector::iterator i = kskeys.begin();
+ i != kskeys.end(); i++)
+ {
+ keypair kp;
+ hexenc privhash, pubhash;
+ app.keys.get_key_pair(*i, kp);
+ key_hash_code(*i, kp.pub, pubhash);
+ key_hash_code(*i, kp.priv, privhash);
+ items[(*i)()].get<0>() = pubhash;
+ items[(*i)()].get<1>() = privhash;
+ items[(*i)()].get<2>().push_back("keystore");
+ items[(*i)()].get<3>().push_back("keystore");
+ }
+ basic_io::printer prt(output);
+ for (std::map, hexenc,
+ std::vector,
+ std::vector > >::iterator
+ i = items.begin(); i != items.end(); ++i)
+ {
+ basic_io::stanza stz;
+ stz.push_str_pair("name", i->first);
+ stz.push_hex_pair("public_hash", i->second.get<0>()());
+ if (!i->second.get<1>()().empty())
+ stz.push_hex_pair("private_hash", i->second.get<1>()());
+ stz.push_str_multi("public_location", i->second.get<2>());
+ if (!i->second.get<3>().empty())
+ stz.push_str_multi("private_location", i->second.get<3>());
+ prt.print_stanza(stz);
+ }
+}
+
+
void
automate_command(utf8 cmd, std::vector args,
std::string const & root_cmd_name,
@@ -1307,6 +1408,8 @@
automate_get_manifest(args, root_cmd_name, app, output);
else if (cmd() == "get_file")
automate_get_file(args, root_cmd_name, app, output);
+ else if (cmd() == "keys")
+ automate_keys(args, root_cmd_name, app, output);
else
throw usage(root_cmd_name);
}
========================================================================
--- basic_io.cc 3c575f5fd41d00730c3a0a9eafe84105fa51f28a
+++ basic_io.cc f548b2a09749dd603757d8ac491e020a67207eff
@@ -89,6 +89,27 @@
push_str_pair(k, v.as_internal());
}
+void basic_io::stanza::push_str_multi(std::string const & k,
+ std::vector const & v)
+{
+ for (std::string::const_iterator i = k.begin(); i != k.end(); ++i)
+ I(std::isalnum(*i) || *i == '_');
+
+ std::string val;
+ bool first = true;
+ for (std::vector::const_iterator i = v.begin();
+ i != v.end(); ++i)
+ {
+ if (!first)
+ val += " ";
+ val += escape(*i);
+ first = false;
+ }
+ entries.push_back(std::make_pair(k, val));
+ if (k.size() > indent)
+ indent = k.size();
+}
+
basic_io::printer::printer(std::ostream & ost)
: empty_output(true), out(ost)
{}
========================================================================
--- basic_io.hh 74d226adb3879eeb068b39172c59377a733148ab
+++ basic_io.hh c46a35a67fa990a9bd759f09b1cdd2223e7783de
@@ -154,6 +154,8 @@
void push_hex_pair(std::string const & k, std::string const & v);
void push_str_pair(std::string const & k, std::string const & v);
void push_file_pair(std::string const & k, file_path const & v);
+ void push_str_multi(std::string const & k,
+ std::vector const & v);
};
struct
========================================================================
--- commands.cc e44277638e21b8a20fa0c6f68f067b3799827d0c
+++ commands.cc 0ea3bfbf93bf5ab0a18e4b11a894d7c8f31dc646
@@ -599,11 +599,9 @@
guard.commit();
}
-static void
+static void
ls_keys(string const & name, app_state & app, vector const & args)
{
-
-
vector pubs;
vector privkeys;
std::string pattern;
@@ -884,7 +882,7 @@
if (app.keys.key_pair_exists(ident))
{
- P(F("dropping key pair '%s' from key store\n\n") % ident);
+ P(F("dropping key pair '%s' from key store\n") % ident);
app.keys.delete_key(ident);
key_deleted = true;
}
@@ -3733,7 +3731,8 @@
"select SELECTOR\n"
"get_file ID\n"
"get_manifest [ID]\n"
- "get_revision [ID]\n"),
+ "get_revision [ID]\n"
+ "keys\n"),
N_("automation interface"),
OPT_NONE)
{
========================================================================
--- monotone.texi f03a883ec62cd2aa2b9e7d972d045630391f9e99
+++ monotone.texi c88edde8d3ac6fcf1f89465a528381a2b0307a6d
@@ -5515,6 +5515,56 @@
@end table
+
address@hidden monotone automate keys
+
address@hidden @strong
address@hidden Arguments:
+
+None.
+
address@hidden Added in:
+
+1.1
+
address@hidden Purpose:
+
+Print all keys in basic_io format.
+
address@hidden Sample output:
+
address@hidden
+ name "address@hidden"
+ public_hash [475055ec71ad48f5dfaf875b0fea597b5cbbee64]
+ private_hash [7f76dae3f91bb48f80f1871856d9d519770b7f8a]
+ public_location "database" "keystore"
+private_location "keystore"
+
+ name "address@hidden"
+ public_hash [3ac4afcd86af28413b0a23b7d22b9401e15027fc]
+public_location "database"
+
+ name "address@hidden"
+ public_hash [115fdc73d87a5e9901d018462b21a1f53eca33a1]
+ private_hash [b520d2cfe7d30e4ea1725fc4f34646fc5469b13d]
+ public_location "keystore"
+private_location "keystore"
+
address@hidden verbatim
+
address@hidden Output format:
+
+For each key, a basic_io stanza is printed. The public_location and
+private_location items may have multiple values as shown above for public_location, one value for each place that the key is stored. If the
+private key does not exist, then the private_hash and private_location
+items will be absent. The keys are ordered alphabetically by name.
+
address@hidden Error conditions:
+
+None.
+
address@hidden table
+
@end ftable
@page
========================================================================
--- tests/t_automate_keys.at
+++ tests/t_automate_keys.at e97dbcb4dc72815d32bfa1f202b9404acbd6ba42
@@ -0,0 +1,32 @@
+AT_SETUP([automate keys])
+MONOTONE_SETUP
+
+ADD_FILE(testfile, [foo bar
+])
+AT_CHECK(MONOTONE ci -m foobar, [], [ignore], [ignore])
+AT_CHECK((echo address@hidden; echo address@hidden) | MONOTONE genkey address@hidden, [], [ignore], [ignore])
+AT_CHECK((echo address@hidden; echo address@hidden) | MONOTONE genkey address@hidden, [], [ignore], [ignore])
+AT_CHECK(MONOTONE pubkey address@hidden > baz)
+AT_CHECK(MONOTONE dropkey address@hidden, [], [ignore], [ignore])
+AT_CHECK(MONOTONE read < baz, [], [ignore], [ignore])
+
+# we now have address@hidden in the keystore, address@hidden in both keystore
+# and database, and address@hidden in only the database
+AT_CHECK(MONOTONE automate keys, [], [stdout], [ignore])
+AT_CHECK(cp stdout output)
+
+AT_CHECK(sed 's/^$/\n\n/g' < output > processed)
+AT_CHECK(grep -A4 'address@hidden' processed > foobar)
+AT_CHECK(grep -A4 'address@hidden' processed > foobaz)
+AT_CHECK(grep -A4 'address@hidden' processed > tester)
+
+AT_CHECK(QGREP database foobar, [1])
+AT_CHECK(QGREP private foobaz, [1])
+AT_CHECK(grep keystore tester | QGREP database)
+AT_CHECK(grep keystore tester | QGREP -v database)
+AT_CHECK(QGREP private tester)
+AT_CHECK(QGREP public foobar)
+AT_CHECK(QGREP public foobaz)
+AT_CHECK(QGREP public tester)
+
+AT_CLEANUP
========================================================================
--- testsuite.at 388fd624698f3b9219a28ad8f89df2637d608ca1
+++ testsuite.at c42fcb759b296535e9105e987d6cad39ed3370f6
@@ -709,3 +709,4 @@
m4_include(tests/t_unreadable_db.at)
m4_include(tests/t_restriction_with_exclude.at)
m4_include(tests/t_key_management_without_db.at)
+m4_include(tests/t_automate_keys.at)