----------------------------------------------------------------------
Revision: bce9def35807144b73ce06c7ade6ae610463b5c9
Parent:   8cb2147f6c474c56b6bea37f7fed2ae37ea7e155
Author:   yan12125@gmail.com
Date:     西元2019年06月13日 21時16分57秒
Branch:   net.venge.monotone

Changelog: 

Fix building with botan 2.9+

In https://github.com/randombit/botan/commit/b909778857b3e0b7eb86ac26c818e5f25baaddbd,
botan uses E to denote the exception class in the template function do_throw_error().
This conflicts with the error macro E() in monotone.

Changes against parent 8cb2147f6c474c56b6bea37f7fed2ae37ea7e155

  patched  src/asciik.cc
  patched  src/automate.cc
  patched  src/automate_reader.cc
  patched  src/basic_io.cc
  patched  src/botan_glue.cc
  patched  src/charset.cc
  patched  src/cmd.cc
  patched  src/cmd.hh
  patched  src/cmd_automate.cc
  patched  src/cmd_conflicts.cc
  patched  src/cmd_db.cc
  patched  src/cmd_diff_log.cc
  patched  src/cmd_files.cc
  patched  src/cmd_key_cert.cc
  patched  src/cmd_list.cc
  patched  src/cmd_merging.cc
  patched  src/cmd_netsync.cc
  patched  src/cmd_othervcs.cc
  patched  src/cmd_packet.cc
  patched  src/cmd_ws_commit.cc
  patched  src/commands.cc
  patched  src/database.cc
  patched  src/database_check.cc
  patched  src/dates.cc
  patched  src/file_io.cc
  patched  src/file_io.hh
  patched  src/git_export.cc
  patched  src/globish.cc
  patched  src/key_packet.cc
  patched  src/key_store.cc
  patched  src/keys.cc
  patched  src/lua.cc
  patched  src/lua_hooks.cc
  patched  src/luaext_parse_basic_io.cc
  patched  src/merge_conflict.cc
  patched  src/merge_content.cc
  patched  src/merge_roster.cc
  patched  src/migrate_ancestry.cc
  patched  src/migrate_schema.cc
  patched  src/migrate_work.cc
  patched  src/monotone.cc
  patched  src/netsync.cc
  patched  src/network/automate_session.cc
  patched  src/network/connection_info.cc
  patched  src/network/netsync_session.cc
  patched  src/network/session.cc
  patched  src/netxx_pipe.cc
  patched  src/option.cc
  patched  src/options_list.hh
  patched  src/packet.cc
  patched  src/paths.cc
  patched  src/paths.hh
  patched  src/pcrewrap.cc
  patched  src/platform.hh
  patched  src/project.cc
  patched  src/rcs_import.cc
  patched  src/refiner.cc
  patched  src/restrictions.cc
  patched  src/revision.cc
  patched  src/roster.cc
  patched  src/sanity.hh
  patched  src/selectors.cc
  patched  src/ssh_agent.cc
  patched  src/transforms.cc
  patched  src/ui.cc
  patched  src/unix/fs.cc
  patched  src/unix/parse_date.cc
  patched  src/unix/process.cc
  patched  src/unix/ssh_agent_platform.cc
  patched  src/uri.cc
  patched  src/vocab.cc
  patched  src/win32/fs.cc
  patched  src/win32/parse_date.cc
  patched  src/win32/ssh_agent_platform.cc
  patched  src/work.cc
  patched  src/work.hh
  patched  test/src/tester.cc
  patched  test/src/unix/tester-plaf.cc
  patched  test/src/win32/tester-plaf.cc
  patched  test/unit/tests/netxx_pipe.cc

============================================================
--- src/asciik.cc	40f500c5ec534ca70eb273021b893d931efc6761
+++ src/asciik.cc	d69fc65c7cdb3e60ab6a262bce26765eeee18afd
@@ -384,7 +384,7 @@ CMD(asciik, "asciik", "", CMD_REF(debug)
     "",
     options::opts::pager)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   set<revision_id> revs;
============================================================
--- src/automate.cc	46ced211db0c7930b02a1eec7d667e6ee5c43509
+++ src/automate.cc	de866add5dab0306a46eba02c07feb6047d513c2
@@ -80,7 +80,7 @@ CMD_AUTOMATE(heads, N_("[BRANCH]"),
              "",
              options::opts::none)
 {
-  E(args.size() < 2, origin::user,
+  MONOTONE_ERROR(args.size() < 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -117,7 +117,7 @@ CMD_AUTOMATE(ancestors, N_("REV1 [REV2 [
              "",
              options::opts::none)
 {
-  E(args.size() > 0, origin::user,
+  MONOTONE_ERROR(args.size() > 0, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -127,7 +127,7 @@ CMD_AUTOMATE(ancestors, N_("REV1 [REV2 [
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       frontier.push_back(rid);
     }
@@ -169,7 +169,7 @@ CMD_AUTOMATE(descendents, N_("REV1 [REV2
              "",
              options::opts::none)
 {
-  E(args.size() > 0, origin::user,
+  MONOTONE_ERROR(args.size() > 0, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -179,7 +179,7 @@ CMD_AUTOMATE(descendents, N_("REV1 [REV2
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       frontier.push_back(rid);
     }
@@ -228,7 +228,7 @@ CMD_AUTOMATE(erase_ancestors, N_("[REV1 
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       revs.insert(rid);
     }
@@ -261,7 +261,7 @@ CMD_AUTOMATE(erase_descendants, N_("[REV
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       revs.insert(rid);
     }
@@ -291,7 +291,7 @@ CMD_AUTOMATE(toposort, N_("[REV1 [REV2 [
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       revs.insert(rid);
     }
@@ -324,7 +324,7 @@ CMD_AUTOMATE(ancestry_difference, N_("NE
              "",
              options::opts::none)
 {
-  E(args.size() > 0, origin::user,
+  MONOTONE_ERROR(args.size() > 0, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -333,12 +333,12 @@ CMD_AUTOMATE(ancestry_difference, N_("NE
   set<revision_id> bs;
   args_vector::const_iterator i = args.begin();
   a = decode_hexenc_as<revision_id>((*i)(), origin::user);
-  E(db.revision_exists(a), origin::user,
+  MONOTONE_ERROR(db.revision_exists(a), origin::user,
     F("no revision %s found in database") % a);
   for (++i; i != args.end(); ++i)
     {
       revision_id b(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(b), origin::user,
+      MONOTONE_ERROR(db.revision_exists(b), origin::user,
         F("no revision %s found in database") % b);
       bs.insert(b);
     }
@@ -368,7 +368,7 @@ CMD_AUTOMATE(leaves, "",
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -393,7 +393,7 @@ CMD_AUTOMATE(roots, "",
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -422,13 +422,13 @@ CMD_AUTOMATE(parents, N_("REV"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
 
   revision_id rid(decode_hexenc_as<revision_id>(idx(args, 0)(), origin::user));
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
   set<revision_id> parents = db.get_revision_parents(rid);
   for (set<revision_id>::const_iterator i = parents.begin();
@@ -452,13 +452,13 @@ CMD_AUTOMATE(children, N_("REV"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
 
   revision_id rid(decode_hexenc_as<revision_id>(idx(args, 0)(), origin::user));
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
   set<revision_id> children = db.get_revision_children(rid);
   for (set<revision_id>::const_iterator i = children.begin();
@@ -492,7 +492,7 @@ CMD_AUTOMATE(graph, "",
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -537,7 +537,7 @@ CMD_AUTOMATE(select, N_("SELECTOR"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1058,7 +1058,7 @@ CMD_AUTOMATE(inventory,  N_("[PATH]...")
   // for now, until we've figured out what the format could look like
   // and what conceptional model we can implement
   // see: http://wiki.monotone.ca/MultiParentWorkspaceFallout/
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   roster_t old_roster = parent_roster(parents.begin()),
@@ -1283,14 +1283,14 @@ CMD_AUTOMATE(get_revision, N_("REVID"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
 
   revision_id rid(decode_hexenc_as<revision_id>(idx(args, 0)(),
                                                 origin::user));
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
   revision_data dat = db.get_revision_data(rid);
 
@@ -1345,13 +1345,13 @@ CMD_AUTOMATE(get_base_revision_id, "",
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   workspace work(app);
 
   revision_t rev = work.get_work_rev();
-  E(rev.edges.size() == 1, origin::user,
+  MONOTONE_ERROR(rev.edges.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   output << rev.edges.begin()->first << '\n';
@@ -1371,7 +1371,7 @@ CMD_AUTOMATE(get_current_revision_id, ""
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   workspace work(app);
@@ -1433,7 +1433,7 @@ CMD_AUTOMATE(get_manifest_of, N_("[REVID
 {
   database db(app);
 
-  E(args.size() < 2, origin::user,
+  MONOTONE_ERROR(args.size() < 2, origin::user,
     F("wrong argument count"));
 
   roster_t new_roster;
@@ -1448,7 +1448,7 @@ CMD_AUTOMATE(get_manifest_of, N_("[REVID
     {
       revision_id rid = decode_hexenc_as<revision_id>(idx(args, 0)(),
                                                       origin::user);
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       new_roster = db.get_roster(rid);
     }
@@ -1565,7 +1565,7 @@ CMD_AUTOMATE(get_extended_manifest_of, "
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1574,7 +1574,7 @@ CMD_AUTOMATE(get_extended_manifest_of, "
 
   revision_id rid = decode_hexenc_as<revision_id>(idx(args, 0)(),
                                                   origin::user);
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
   db.get_roster_and_markings(rid, roster, mm);
 
@@ -1600,7 +1600,7 @@ CMD_AUTOMATE(packet_for_rdata, N_("REVID
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1609,7 +1609,7 @@ CMD_AUTOMATE(packet_for_rdata, N_("REVID
 
   revision_id r_id(decode_hexenc_as<revision_id>(idx(args, 0)(),
                                                  origin::user));
-  E(db.revision_exists(r_id), origin::user,
+  MONOTONE_ERROR(db.revision_exists(r_id), origin::user,
     F("no revision %s found in database") % r_id);
   pw.consume_revision_data(r_id, db.get_revision_data(r_id));
 }
@@ -1630,7 +1630,7 @@ CMD_AUTOMATE(packets_for_certs, N_("REVI
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1640,7 +1640,7 @@ CMD_AUTOMATE(packets_for_certs, N_("REVI
   revision_id r_id(decode_hexenc_as<revision_id>(idx(args, 0)(), origin::user));
   vector<cert> certs;
 
-  E(db.revision_exists(r_id), origin::user,
+  MONOTONE_ERROR(db.revision_exists(r_id), origin::user,
     F("no revision %s found in database") % r_id);
   project.get_revision_certs(r_id, certs);
 
@@ -1664,7 +1664,7 @@ CMD_AUTOMATE(packet_for_fdata, N_("FILEI
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1672,7 +1672,7 @@ CMD_AUTOMATE(packet_for_fdata, N_("FILEI
   packet_writer pw(output);
 
   file_id f_id(decode_hexenc_as<file_id>(idx(args, 0)(), origin::user));
-  E(db.file_version_exists(f_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists(f_id), origin::user,
     F("no such file '%s'") % f_id);
   pw.consume_file_data(f_id, db.get_file_version(f_id));
 }
@@ -1693,7 +1693,7 @@ CMD_AUTOMATE(packet_for_fdelta, N_("OLD_
              "",
              options::opts::none)
 {
-  E(args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() == 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1703,9 +1703,9 @@ CMD_AUTOMATE(packet_for_fdelta, N_("OLD_
   file_id f_old_id(decode_hexenc_as<file_id>(idx(args, 0)(), origin::user));
   file_id f_new_id(decode_hexenc_as<file_id>(idx(args, 1)(), origin::user));
 
-  E(db.file_version_exists(f_old_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists(f_old_id), origin::user,
     F("no revision %s found in database") % f_old_id);
-  E(db.file_version_exists(f_new_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists(f_new_id), origin::user,
     F("no revision %s found in database") % f_new_id);
   delta del;
   diff(db.get_file_version(f_old_id).inner(),
@@ -1732,7 +1732,7 @@ CMD_AUTOMATE(common_ancestors, N_("REV1 
              "",
              options::opts::none)
 {
-  E(args.size() > 0, origin::user,
+  MONOTONE_ERROR(args.size() > 0, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1741,7 +1741,7 @@ CMD_AUTOMATE(common_ancestors, N_("REV1 
   for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
     {
       revision_id rid(decode_hexenc_as<revision_id>((*i)(), origin::user));
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("no revision %s found in database") % rid);
       revs.insert(rid);
     }
@@ -1770,7 +1770,7 @@ CMD_AUTOMATE(branches, "",
              "",
              options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -1822,7 +1822,7 @@ CMD_AUTOMATE(tags, N_("[BRANCH_PATTERN]"
              "",
              options::opts::none)
 {
-  E(args.size() < 2, origin::user,
+  MONOTONE_ERROR(args.size() < 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1905,7 +1905,7 @@ CMD_AUTOMATE(get_option, N_("OPTION"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   workspace work(app);
@@ -1938,7 +1938,7 @@ CMD_AUTOMATE(get_content_changed, N_("RE
              "",
              options::opts::none)
 {
-  E(args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() == 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1948,12 +1948,12 @@ CMD_AUTOMATE(get_content_changed, N_("RE
   marking_map mm;
 
   ident = decode_hexenc_as<revision_id>(idx(args, 0)(), origin::user);
-  E(db.revision_exists(ident), origin::user,
+  MONOTONE_ERROR(db.revision_exists(ident), origin::user,
     F("no revision %s found in database") % ident);
   db.get_roster_and_markings(ident, new_roster, mm);
 
   file_path path = file_path_external(idx(args,1));
-  E(new_roster.has_node(path), origin::user,
+  MONOTONE_ERROR(new_roster.has_node(path), origin::user,
     F("file '%s' is unknown for revision %s")
     % path % ident);
 
@@ -2001,7 +2001,7 @@ CMD_AUTOMATE(get_corresponding_path, N_(
              "",
              options::opts::none)
 {
-  E(args.size() == 3, origin::user,
+  MONOTONE_ERROR(args.size() == 3, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2009,17 +2009,17 @@ CMD_AUTOMATE(get_corresponding_path, N_(
   revision_id ident, old_ident;
 
   ident = decode_hexenc_as<revision_id>(idx(args, 0)(), origin::user);
-  E(db.revision_exists(ident), origin::user,
+  MONOTONE_ERROR(db.revision_exists(ident), origin::user,
     F("no revision %s found in database") % ident);
   roster_t new_roster = db.get_roster(ident);
 
   old_ident = decode_hexenc_as<revision_id>(idx(args, 2)(), origin::user);
-  E(db.revision_exists(old_ident), origin::user,
+  MONOTONE_ERROR(db.revision_exists(old_ident), origin::user,
     F("no revision %s found in database") % old_ident);
   roster_t old_roster = db.get_roster(old_ident);
 
   file_path path = file_path_external(idx(args,1));
-  E(new_roster.has_node(path), origin::user,
+  MONOTONE_ERROR(new_roster.has_node(path), origin::user,
     F("file '%s' is unknown for revision %s") % path % ident);
 
   const_node_t node = new_roster.get_node(path);
@@ -2052,7 +2052,7 @@ CMD_AUTOMATE(put_file, N_("[FILEID] CONT
              "",
              options::opts::none)
 {
-  E(args.size() == 1 || args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() == 1 || args.size() == 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2070,7 +2070,7 @@ CMD_AUTOMATE(put_file, N_("[FILEID] CONT
       file_data dat = typecast_vocab<file_data>(idx(args, 1));
       sha1sum = calculate_ident(dat);
       file_id base_id(decode_hexenc_as<file_id>(idx(args, 0)(), origin::user));
-      E(db.file_version_exists(base_id), origin::user,
+      MONOTONE_ERROR(db.file_version_exists(base_id), origin::user,
         F("no file version %s found in database") % base_id);
 
       // put_file_version won't do anything if the target ID already exists,
@@ -2103,7 +2103,7 @@ CMD_AUTOMATE(put_revision, N_("REVISION-
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2133,7 +2133,7 @@ CMD_AUTOMATE(put_revision, N_("REVISION-
 
   // If the database refuses the revision, make sure this is because it's
   // already there.
-  E(db.put_revision(id, move(rev)) || db.revision_exists(id),
+  MONOTONE_ERROR(db.put_revision(id, move(rev)) || db.revision_exists(id),
     origin::user,
     F("missing prerequisite for revision %s") % id);
 
@@ -2157,7 +2157,7 @@ CMD_AUTOMATE(cert, N_("REVISION-ID NAME 
              "",
              options::opts::none)
 {
-  E(args.size() == 3, origin::user,
+  MONOTONE_ERROR(args.size() == 3, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2166,7 +2166,7 @@ CMD_AUTOMATE(cert, N_("REVISION-ID NAME 
 
   hexenc<id> hrid(idx(args, 0)(), origin::user);
   revision_id rid(decode_hexenc_as<revision_id>(hrid(), origin::user));
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % hrid);
 
   cache_user_key(app.opts, project, keys, app.lua);
@@ -2193,7 +2193,7 @@ CMD_AUTOMATE(get_db_variables, N_("[DOMA
              "",
              options::opts::none)
 {
-  E(args.size() < 2, origin::user,
+  MONOTONE_ERROR(args.size() < 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2235,7 +2235,7 @@ CMD_AUTOMATE(get_db_variables, N_("[DOMA
       st.push_str_triple(syms::entry, i->first.second(), i->second());
     }
 
-  E(found_something, origin::user,
+  MONOTONE_ERROR(found_something, origin::user,
     F("no variables found or invalid domain specified"));
 
   // print the last stanza
@@ -2262,7 +2262,7 @@ CMD_AUTOMATE(set_db_variable, N_("DOMAIN
              "",
              options::opts::none)
 {
-  E(args.size() == 3, origin::user,
+  MONOTONE_ERROR(args.size() == 3, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2292,7 +2292,7 @@ CMD_AUTOMATE(drop_db_variables, N_("DOMA
              "",
              options::opts::none)
 {
-  E(args.size() == 1 || args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() == 1 || args.size() == 2, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -2303,7 +2303,7 @@ CMD_AUTOMATE(drop_db_variables, N_("DOMA
     {
       var_name name = typecast_vocab<var_name>(idx(args, 1));
       var_key  key(domain, name);
-      E(db.var_exists(key), origin::user,
+      MONOTONE_ERROR(db.var_exists(key), origin::user,
         F("no var with name '%s' in domain '%s'") % name % domain);
       db.clear_var(key);
     }
@@ -2322,7 +2322,7 @@ CMD_AUTOMATE(drop_db_variables, N_("DOMA
             }
         }
 
-      E(found_something, origin::user,
+      MONOTONE_ERROR(found_something, origin::user,
         F("no variables found in domain '%s'") % domain);
     }
 }
@@ -2367,12 +2367,12 @@ CMD_AUTOMATE(lua, "LUA_FUNCTION [ARG1 [A
              "",
              options::opts::none)
 {
-  E(args.size() >= 1, origin::user,
+  MONOTONE_ERROR(args.size() >= 1, origin::user,
     F("wrong argument count"));
 
   std::string func = idx(args, 0)();
 
-  E(app.lua.hook_exists(func), origin::user,
+  MONOTONE_ERROR(app.lua.hook_exists(func), origin::user,
     F("lua function '%s' does not exist") % func);
 
   std::vector<std::string> func_args;
@@ -2385,7 +2385,7 @@ CMD_AUTOMATE(lua, "LUA_FUNCTION [ARG1 [A
     }
 
   std::string out;
-  E(app.lua.hook_hook_wrapper(func, func_args, out), origin::user,
+  MONOTONE_ERROR(app.lua.hook_hook_wrapper(func, func_args, out), origin::user,
     F("lua call '%s' failed") % func);
 
   // the output already contains a trailing newline, so we don't add
@@ -2420,12 +2420,12 @@ automate_stdio_shared_setup(app_state & 
 
   if (matches.empty())
     {
-      E(false, origin::network,
+      MONOTONE_ERROR(false, origin::network,
         F("no completions for this command"));
     }
   else if (matches.size() > 1)
     {
-      E(false, origin::network,
+      MONOTONE_ERROR(false, origin::network,
         F("multiple completions possible for this command"));
     }
 
@@ -2437,7 +2437,7 @@ automate_stdio_shared_setup(app_state & 
   acmd = dynamic_cast< automate const * >(cmd);
   I(acmd != NULL);
 
-  E(acmd->can_run_from_stdio(), origin::network,
+  MONOTONE_ERROR(acmd->can_run_from_stdio(), origin::network,
     F("sorry, that can't be run remotely or over stdio"));
 
 
============================================================
--- src/automate_reader.cc	ac60e48d6902a3cef96bc86a93640936c125beee
+++ src/automate_reader.cc	cd342871c1107e3c87fe4225706cf62e98db14ca
@@ -42,7 +42,7 @@ bool automate_reader::get_string(string 
       size = (size*10)+(c-'0');
       read(&c, 1);
     }
-  E(c == ':', origin::user,
+  MONOTONE_ERROR(c == ':', origin::user,
     F("bad input to automate stdio: expected ':' after string size"));
   char *str = new char[size];
   size_t got = 0;
@@ -62,7 +62,7 @@ streamsize automate_reader::read(char *b
 
   rv = in.rdbuf()->sgetn(buf, nbytes);
 
-  E(eof_ok || rv > 0, origin::user,
+  MONOTONE_ERROR(eof_ok || rv > 0, origin::user,
     F("bad input to automate stdio: unexpected EOF"));
   return rv;
 }
@@ -90,7 +90,7 @@ void automate_reader::go_to_next_item()
     case 'o': loc = opt; break;
     case 'l': loc = cmd; break;
     default:
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("bad input to automate stdio: unknown start token '%c'") % c);
     }
 }
@@ -112,14 +112,14 @@ bool automate_reader::get_command(vector
         params.push_back(make_pair(key, val));
       go_to_next_item();
     }
-  E(loc == cmd, origin::user,
+  MONOTONE_ERROR(loc == cmd, origin::user,
     F("bad input to automate stdio: expected '%c' token") % cmd);
   string item;
   while (get_string(item))
     {
       cmdline.push_back(item);
     }
-  E(cmdline.size() > 0, origin::user,
+  MONOTONE_ERROR(cmdline.size() > 0, origin::user,
     F("bad input to automate stdio: command name is missing"));
   return true;
 }
============================================================
--- src/basic_io.cc	95ae5bc17a2c7140bfe13691036591b8975bcf41
+++ src/basic_io.cc	69a3a3da5c05094f0088e5ebf241cfbf8da4a806
@@ -26,7 +26,7 @@ void basic_io::input_source::err(string 
 
 void basic_io::input_source::err(string const & s)
 {
-  E(false, made_from,
+  MONOTONE_ERROR(false, made_from,
     F("parsing a %s at %d:%d:E: %s") % name % line % col % s);
 }
 
============================================================
--- src/botan_glue.cc	fe2162c2c50bd9ea6632d5a37667378984b548f9
+++ src/botan_glue.cc	76076e4d8a9aa50586ad574267c73734987618bc
@@ -120,7 +120,7 @@ load_pkcs8_key(string const & name, stri
       if (strstr(e.what(), "Passphrase required") != NULL)
         throw Passphrase_Required("Passphrase required");
 #endif
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("malformed key_packet: invalid private key data for '%s': %s")
           % name % e.what());
     }
============================================================
--- src/charset.cc	c507ab057cf8e8c1300ea322ab1618b1353f7e97
+++ src/charset.cc	710b80ed17d73faf3ce42c1c2b074553733ba0c1
@@ -68,7 +68,7 @@ charset_convert(string const & src_chars
             converted = src.c_str();
         }
 
-      E(converted != NULL, whence,
+      MONOTONE_ERROR(converted != NULL, whence,
         F("failed to convert string from %s to %s: '%s'")
          % src_charset % dst_charset % src);
       dst = string(converted);
@@ -333,7 +333,7 @@ ace_to_utf8(string const & a, utf8 & utf
   char *out = NULL;
   L(FL("converting %d bytes from IDNA ACE to UTF-8") % a.size());
   int res = idna_to_unicode_8z8z(a.c_str(), &out, IDNA_USE_STD3_ASCII_RULES);
-  E(res == IDNA_SUCCESS || res == IDNA_NO_ACE_PREFIX, whence,
+  MONOTONE_ERROR(res == IDNA_SUCCESS || res == IDNA_NO_ACE_PREFIX, whence,
     F("error converting %d UTF-8 bytes to IDNA ACE: %s")
     % a.size()
     % decode_idna_error(res));
@@ -347,7 +347,7 @@ utf8_to_ace(utf8 const & utf, string & a
   char *out = NULL;
   L(FL("converting %d bytes from UTF-8 to IDNA ACE") % utf().size());
   int res = idna_to_ascii_8z(utf().c_str(), &out, IDNA_USE_STD3_ASCII_RULES);
-  E(res == IDNA_SUCCESS, utf.made_from,
+  MONOTONE_ERROR(res == IDNA_SUCCESS, utf.made_from,
     F("error converting %d UTF-8 bytes to IDNA ACE: %s")
     % utf().size()
     % decode_idna_error(res));
============================================================
--- src/cmd.cc	3a76154b01802f7abcbb1000e0de54fa19113fba
+++ src/cmd.cc	58bdb664240567553f7851e7ac08b995962ecb61
@@ -197,7 +197,7 @@ namespace commands {
                                                  ident.end()))();
 
     I(cmd->is_leaf() || cmd->is_group());
-    E(!(cmd->is_group() && cmd->parent() == CMD_REF(__root__)),
+    MONOTONE_ERROR(!(cmd->is_group() && cmd->parent() == CMD_REF(__root__)),
       origin::user,
       F("command '%s' is invalid; it is a group") % join_words(ident));
 
@@ -206,10 +206,10 @@ namespace commands {
         // args used in the command name have not been stripped yet
         remove_command_name_from_args(ident, app.opts.args);
 
-        E(!args.empty(), origin::user,
+        MONOTONE_ERROR(!args.empty(), origin::user,
           F("no subcommand specified for '%s'") % visibleid);
 
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F("could not match '%s' to a subcommand of '%s'") %
           join_words(args) % visibleid);
       }
@@ -460,7 +460,7 @@ namespace commands {
 
       app.mtn_automate_allowed = false;
 
-      E(ll.ok(), origin::user,
+      MONOTONE_ERROR(ll.ok(), origin::user,
         F("call to user command '%s' (lua command: '%s') failed.")
         % primary_name() % f_name);
     }
@@ -471,7 +471,7 @@ LUAEXT(alias_command, )
 {
   const char *old_cmd = luaL_checkstring(LS, -2);
   const char *new_cmd = luaL_checkstring(LS, -1);
-  E(old_cmd && new_cmd, origin::user,
+  MONOTONE_ERROR(old_cmd && new_cmd, origin::user,
     F("'%s' called with an invalid parameter") % "alias_command");
 
   args_vector args;
@@ -494,7 +494,7 @@ LUAEXT(register_command, )
   const char *cmd_desc = luaL_checkstring(LS, -2);
   const char *cmd_func = luaL_checkstring(LS, -1);
 
-  E(cmd_name && cmd_params && cmd_abstract && cmd_desc && cmd_func,
+  MONOTONE_ERROR(cmd_name && cmd_params && cmd_abstract && cmd_desc && cmd_func,
     origin::user,
     F("'%s' called with an invalid parameter") % "register_command");
 
@@ -531,7 +531,7 @@ CMD_NO_WORKSPACE(version, "version", "",
     "",
     options::opts::full)
 {
-  E(args.empty(), origin::user,
+  MONOTONE_ERROR(args.empty(), origin::user,
     F("no arguments allowed"));
 
   if (app.opts.full)
@@ -549,7 +549,7 @@ CMD_HIDDEN(check_glob, "check_glob", "",
   globish g = typecast_vocab<globish>(idx(args,0));
   string s(idx(args,1)());
 
-  E(g.matches(s), origin::user,
+  MONOTONE_ERROR(g.matches(s), origin::user,
     F("Glob '%s' does not match string '%s'") % g % s);
 }
 
@@ -563,9 +563,9 @@ CMD_HIDDEN(crash, "crash", "", CMD_REF(d
     throw usage(execid);
   bool spoon_exists(false);
   if (idx(args,0)() == "N")
-    E(spoon_exists, origin::user, i18n_format("There is no spoon."));
+    MONOTONE_ERROR(spoon_exists, origin::user, i18n_format("There is no spoon."));
   else if (idx(args,0)() == "E")
-    E(spoon_exists, origin::system, i18n_format("There is no spoon."));
+    MONOTONE_ERROR(spoon_exists, origin::system, i18n_format("There is no spoon."));
   else if (idx(args,0)() == "I")
     {
       I(spoon_exists);
@@ -971,11 +971,11 @@ CMD_NO_WORKSPACE(manpage, "manpage", "",
     }
 
   string cmd;
-  E(app.lua.hook_get_man_page_formatter_command(cmd) && !cmd.empty(),
+  MONOTONE_ERROR(app.lua.hook_get_man_page_formatter_command(cmd) && !cmd.empty(),
     origin::user, F("no man page formatter command configured"));
 
   FILE * fp = popen(cmd.c_str(), "w");
-  E(fp != NULL, origin::system,
+  MONOTONE_ERROR(fp != NULL, origin::system,
     F("could not execute man page formatter command '%s': %s")
       % cmd % strerror(errno));
 
@@ -992,7 +992,7 @@ process_commit_message_args(options cons
                             utf8 const & message_prefix)
 {
   // can't have both a --message and a --message-file ...
-  E(!opts.message_given || !opts.msgfile_given, origin::user,
+  MONOTONE_ERROR(!opts.message_given || !opts.msgfile_given, origin::user,
     F("'--message' and '--message-file' are mutually exclusive"));
 
   if (opts.message_given)
============================================================
--- src/cmd.hh	a0edea1362380df6742b0b342b23f1e776157485
+++ src/cmd.hh	e20b22664c6d3ecfd19b14019c413ffe3c269b6f
@@ -167,7 +167,7 @@ args_to_paths(args_vector const & args)
   // behavior for empty path sets -- in particular, it is the same as having
   // no restriction at all.  "mtn revert _MTN" turning into "mtn revert"
   // would be bad.  (Or substitute diff, etc.)
-  E(!(!args.empty() && paths.empty()), origin::user,
+  MONOTONE_ERROR(!(!args.empty() && paths.empty()), origin::user,
     F("all arguments given were bookkeeping paths; aborting"));
   return paths;
 }
============================================================
--- src/cmd_automate.cc	dc0f4afbfbe80e3b14277d6818fdf8ed3ebb06ac
+++ src/cmd_automate.cc	e30a44faaf10122806c639d841730dcb810c5c8f
@@ -110,7 +110,7 @@ CMD_AUTOMATE(interface_version, "",
              "",
              options::opts::none)
 {
-  E(args.empty(), origin::user,
+  MONOTONE_ERROR(args.empty(), origin::user,
     F("no arguments needed"));
 
   output << interface_version << '\n';
@@ -135,7 +135,7 @@ CMD_AUTOMATE_HIDDEN(bandtest, "{ info | 
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   std::string type = args.at(0)();
@@ -145,7 +145,7 @@ CMD_AUTOMATE_HIDDEN(bandtest, "{ info | 
   else if (type.compare("warning") == 0)
     W(F("this is a warning"));
   else if (type.compare("error") == 0)
-    E(false, origin::user, F("this is an error message"));
+    MONOTONE_ERROR(false, origin::user, F("this is an error message"));
   else if (type.compare("ticker") == 0)
     {
       ticker first("fake ticker (not fixed)", "f1", 3);
@@ -232,7 +232,7 @@ CMD_AUTOMATE_NO_STDIO(stdio, "",
                       "",
                       options::opts::automate_stdio_size)
 {
-  E(args.empty(), origin::user,
+  MONOTONE_ERROR(args.empty(), origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -321,7 +321,7 @@ LUAEXT(mtn_automate, )
       app_state* app_p = get_app_state(LS);
       I(app_p != NULL);
       I(app_p->lua.check_lua_state(LS));
-      E(app_p->mtn_automate_allowed, origin::user,
+      MONOTONE_ERROR(app_p->mtn_automate_allowed, origin::user,
           F("it is illegal to call the mtn_automate() lua extension,\n"
             "unless from a command function defined by register_command()."));
 
@@ -330,7 +330,7 @@ LUAEXT(mtn_automate, )
 
       int n = lua_gettop(LS);
 
-      E(n > 0, origin::user,
+      MONOTONE_ERROR(n > 0, origin::user,
         F("bad input to mtn_automate() lua extension: command name is missing"));
 
       L(FL("Starting call to mtn_automate lua hook"));
============================================================
--- src/cmd_conflicts.cc	149a8fefb86542c92f6665a5074c18aae5038771
+++ src/cmd_conflicts.cc	3e6ba155ae300340fa70ce0b020a2cd16819fefe
@@ -392,13 +392,13 @@ set_resolution(resolve_conflicts::file_r
 {
   if ("drop" == idx(args, 0)())
     {
-      E(args.size() == 1, origin::user, F("too many arguments"));
+      MONOTONE_ERROR(args.size() == 1, origin::user, F("too many arguments"));
       resolution.resolution = resolve_conflicts::drop;
     }
   else if ("keep" == idx(args, 0)())
     {
-      E(args.size() == 1, origin::user, F("too many arguments"));
-      E(other_resolution.resolution == resolve_conflicts::none ||
+      MONOTONE_ERROR(args.size() == 1, origin::user, F("too many arguments"));
+      MONOTONE_ERROR(other_resolution.resolution == resolve_conflicts::none ||
         other_resolution.resolution == resolve_conflicts::drop ||
         other_resolution.resolution == resolve_conflicts::rename ||
         other_resolution.resolution == resolve_conflicts::content_user_rename,
@@ -409,14 +409,14 @@ set_resolution(resolve_conflicts::file_r
     }
   else if ("rename" == idx(args, 0)())
     {
-      E(args.size() == 2, origin::user, F("wrong number of arguments"));
+      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
       resolution.resolution  = resolve_conflicts::rename;
       resolution.rename = file_path_external(idx(args,1));
     }
   else if ("user" == idx(args, 0)())
     {
-      E(args.size() == 2, origin::user, F("wrong number of arguments"));
-      E(other_resolution.resolution == resolve_conflicts::none ||
+      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
+      MONOTONE_ERROR(other_resolution.resolution == resolve_conflicts::none ||
         other_resolution.resolution == resolve_conflicts::drop ||
         other_resolution.resolution == resolve_conflicts::rename ||
         other_resolution.resolution == resolve_conflicts::content_user_rename,
@@ -429,14 +429,14 @@ set_resolution(resolve_conflicts::file_r
     }
   else if ("user_rename" == idx(args,0)())
     {
-      E(args.size() == 3, origin::user, F("wrong number of arguments"));
+      MONOTONE_ERROR(args.size() == 3, origin::user, F("wrong number of arguments"));
 
       resolution.resolution  = resolve_conflicts::content_user_rename;
       resolution.content = new_optimal_path(idx(args,1)(), false);
       resolution.rename = file_path_external(idx(args,2));
     }
   else
-    E(false, origin::user,
+    MONOTONE_ERROR(false, origin::user,
       F(conflict_resolution_not_supported_msg) % idx(args,0) % "duplicate_name");
 
 } // set_resolution
@@ -448,7 +448,7 @@ set_first_conflict(database & db,
                    args_vector const & args,
                    side_t side)
 {
-  E(args.size() > 0, origin::user, F("wrong number of arguments"));
+  MONOTONE_ERROR(args.size() > 0, origin::user, F("wrong number of arguments"));
 
   if (side != neither)
     {
@@ -465,11 +465,11 @@ set_first_conflict(database & db,
             case left:
               if (conflict.left_resolution.resolution == resolve_conflicts::none)
                 {
-                  E(conflict.left_nid != the_null_node, origin::user,
+                  MONOTONE_ERROR(conflict.left_nid != the_null_node, origin::user,
                     F("must specify resolve_first (not _left or _right)"));
 
                   if ("keep" == idx(args,0)())
-                    E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                    MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                   set_resolution(conflict.left_resolution, conflict.right_resolution, args);
                   return;
@@ -478,11 +478,11 @@ set_first_conflict(database & db,
             case right:
               if (conflict.right_resolution.resolution == resolve_conflicts::none)
                 {
-                  E(conflict.right_nid != the_null_node, origin::user,
+                  MONOTONE_ERROR(conflict.right_nid != the_null_node, origin::user,
                     F("must specify resolve_first (not _left or _right)"));
 
                   if ("keep" == idx(args,0)())
-                    E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                    MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                   set_resolution(conflict.right_resolution, conflict.left_resolution, args);
                   return;
@@ -536,20 +536,20 @@ set_first_conflict(database & db,
             {
               if ("drop" == idx(args,0)())
                 {
-                  E(args.size() == 1, origin::user, F("wrong number of arguments"));
+                  MONOTONE_ERROR(args.size() == 1, origin::user, F("wrong number of arguments"));
 
                   conflict.resolution.resolution  = resolve_conflicts::drop;
                 }
               else if ("rename" == idx(args,0)())
                 {
-                  E(args.size() == 2, origin::user, F("wrong number of arguments"));
+                  MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
 
                   conflict.resolution.resolution  = resolve_conflicts::rename;
                   conflict.resolution.rename = file_path_external(idx(args,1));
                 }
               else
                 {
-                  E(false, origin::user,
+                  MONOTONE_ERROR(false, origin::user,
                     F(conflict_resolution_not_supported_msg) % idx(args,0) % "orphaned_node");
                 }
               return;
@@ -567,7 +567,7 @@ set_first_conflict(database & db,
           switch (conflict.dropped_side)
             {
             case resolve_conflicts::left_side:
-              E(conflict.left_nid == the_null_node, origin::user,
+              MONOTONE_ERROR(conflict.left_nid == the_null_node, origin::user,
                 F("must specify 'resolve_first_left' or 'resolve_first_right' (not just 'resolve_first')"));
 
               // the left side stays dropped; we either drop, keep or replace the right side
@@ -575,35 +575,35 @@ set_first_conflict(database & db,
                 {
                   if ("drop" == idx(args,0)())
                     {
-                      E(args.size() == 1, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 1, origin::user, F("wrong number of arguments"));
 
                       conflict.right_resolution.resolution = resolve_conflicts::drop;
                     }
                   else if ("keep" == idx(args,0)())
                     {
-                      E(args.size() == 1, origin::user, F("wrong number of arguments"));
-                      E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                      MONOTONE_ERROR(args.size() == 1, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                       conflict.right_resolution.resolution = resolve_conflicts::keep;
                     }
                   else if ("user" == idx(args,0)())
                     {
-                      E(args.size() == 2, origin::user, F("wrong number of arguments"));
-                      E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                       conflict.right_resolution.resolution  = resolve_conflicts::content_user;
                       conflict.right_resolution.content = new_optimal_path(idx(args,1)(), false);
                     }
                   else if ("rename" == idx(args,0)())
                     {
-                      E(args.size() == 2, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
 
                       conflict.right_resolution.resolution  = resolve_conflicts::rename;
                       conflict.right_resolution.rename = file_path_external(idx(args,1));
                     }
                   else if ("user_rename" == idx(args,0)())
                     {
-                      E(args.size() == 3, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 3, origin::user, F("wrong number of arguments"));
 
                       conflict.right_resolution.resolution  = resolve_conflicts::content_user_rename;
                       conflict.right_resolution.content = new_optimal_path(idx(args,1)(), false);
@@ -611,7 +611,7 @@ set_first_conflict(database & db,
                     }
                   else
                     {
-                      E(false, origin::user,
+                      MONOTONE_ERROR(false, origin::user,
                         F(conflict_resolution_not_supported_msg) % idx(args,0) % "dropped_modified");
                     }
                   return;
@@ -619,7 +619,7 @@ set_first_conflict(database & db,
               break;
 
             case resolve_conflicts::right_side:
-              E(conflict.right_nid == the_null_node, origin::user,
+              MONOTONE_ERROR(conflict.right_nid == the_null_node, origin::user,
                 F("must specify 'resolve_first_left' or 'resolve_first_right' (not just 'resolve_first')"));
 
               // the right side stays dropped; we either drop, keep or replace the left side
@@ -627,35 +627,35 @@ set_first_conflict(database & db,
                 {
                   if ("drop" == idx(args,0)())
                     {
-                      E(args.size() == 1, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 1, origin::user, F("wrong number of arguments"));
 
                       conflict.left_resolution.resolution = resolve_conflicts::drop;
                     }
                   else if ("keep" == idx(args,0)())
                     {
-                      E(args.size() == 1, origin::user, F("wrong number of arguments"));
-                      E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                      MONOTONE_ERROR(args.size() == 1, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                       conflict.left_resolution.resolution  = resolve_conflicts::keep;
                     }
                   else if ("user" == idx(args,0)())
                     {
-                      E(args.size() == 2, origin::user, F("wrong number of arguments"));
-                      E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+                      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
                       conflict.left_resolution.resolution  = resolve_conflicts::content_user;
                       conflict.left_resolution.content = new_optimal_path(idx(args,1)(), false);
                     }
                   else if ("rename" == idx(args,0)())
                     {
-                      E(args.size() == 2, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
 
                       conflict.left_resolution.resolution  = resolve_conflicts::rename;
                       conflict.left_resolution.rename = file_path_external(idx(args,1));
                     }
                   else if ("user_rename" == idx(args,0)())
                     {
-                      E(args.size() == 3, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(args.size() == 3, origin::user, F("wrong number of arguments"));
 
                       conflict.left_resolution.resolution  = resolve_conflicts::content_user_rename;
                       conflict.left_resolution.content = new_optimal_path(idx(args,1)(), false);
@@ -663,7 +663,7 @@ set_first_conflict(database & db,
                     }
                   else
                     {
-                      E(false, origin::user,
+                      MONOTONE_ERROR(false, origin::user,
                         F(conflict_resolution_not_supported_msg) % idx(args,0) % "dropped_modified");
                     }
                   return;
@@ -707,7 +707,7 @@ set_first_conflict(database & db,
                       break;
 
                     default:
-                      E(false, origin::user, F("wrong number of arguments"));
+                      MONOTONE_ERROR(false, origin::user, F("wrong number of arguments"));
                     }
 
                   if (do_interactive_merge(db, lua, conflicts, conflict.nid,
@@ -726,7 +726,7 @@ set_first_conflict(database & db,
                 }
               else if ("user" == idx(args,0)())
                 {
-                  E(args.size() == 2, origin::user, F("wrong number of arguments"));
+                  MONOTONE_ERROR(args.size() == 2, origin::user, F("wrong number of arguments"));
 
                   conflict.resolution.resolution  = resolve_conflicts::content_user;
                   conflict.resolution.content = new_optimal_path(idx(args,1)(), false);
@@ -735,7 +735,7 @@ set_first_conflict(database & db,
                 {
                   // We don't allow the user to specify 'resolved_internal'; that
                   // is only done by automate show_conflicts.
-                  E(false, origin::user,
+                  MONOTONE_ERROR(false, origin::user,
                     F(conflict_resolution_not_supported_msg) % idx(args,0) % "file_content");
                 }
               return;
@@ -746,15 +746,15 @@ set_first_conflict(database & db,
   switch (side)
     {
     case left:
-      E(false, origin::user, F("no resolvable yet unresolved left side conflicts"));
+      MONOTONE_ERROR(false, origin::user, F("no resolvable yet unresolved left side conflicts"));
       break;
 
     case right:
-      E(false, origin::user, F("no resolvable yet unresolved right side conflicts"));
+      MONOTONE_ERROR(false, origin::user, F("no resolvable yet unresolved right side conflicts"));
       break;
 
     case neither:
-      E(false, origin::user, F("no resolvable yet unresolved single-file conflicts"));
+      MONOTONE_ERROR(false, origin::user, F("no resolvable yet unresolved single-file conflicts"));
       break;
     }
 
@@ -779,7 +779,7 @@ CMD(show_first, "show_first", "", CMD_RE
   database db(app);
   conflicts_t conflicts (db, app.opts.conflicts_file);
 
-  E(args.size() == 0, origin::user, F("wrong number of arguments"));
+  MONOTONE_ERROR(args.size() == 0, origin::user, F("wrong number of arguments"));
   show_conflicts(db, conflicts, first);
 }
 
@@ -796,7 +796,7 @@ CMD(show_remaining, "show_remaining", ""
   database db(app);
   conflicts_t conflicts (db, app.opts.conflicts_file);
 
-  E(args.size() == 0, origin::user, F("wrong number of arguments"));
+  MONOTONE_ERROR(args.size() == 0, origin::user, F("wrong number of arguments"));
   show_conflicts(db, conflicts, remaining);
 }
 
============================================================
--- src/cmd_db.cc	4dd6dff6224977cc4f66ccac035c04c60b4ff6c5
+++ src/cmd_db.cc	5938cc68b338d336b7fbbdbf45a295281e403822
@@ -46,7 +46,7 @@ CMD(db_init, "init", "", CMD_REF(db), ""
     N_("Creates a new database file and initializes it."),
     options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -62,7 +62,7 @@ CMD(db_info, "info", "", CMD_REF(db), ""
     "",
     options::opts::full | options::opts::pager)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -74,7 +74,7 @@ CMD(db_version, "version", "", CMD_REF(d
     "",
     options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -91,7 +91,7 @@ CMD(db_fix_certs, "fix_certs", "", CMD_R
        "such certs with 'mtn read'."),
     options::opts::drop_bad_certs)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -109,7 +109,7 @@ CMD(db_dump, "dump", "", CMD_REF(db), ""
        "restore the database from a text file that serves as a backup."),
     options::opts::pager)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -123,7 +123,7 @@ CMD(db_load, "load", "", CMD_REF(db), ""
        "output generated by the 'dump' command."),
     options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -139,7 +139,7 @@ CMD(db_migrate, "migrate", "", CMD_REF(d
 {
   key_store keys(app);
 
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   migration_status mstat;
@@ -197,7 +197,7 @@ CMD(db_kill_rev_locally, "kill_revision"
 
   // Check that the revision does not have any children
   std::set<revision_id> children = db.get_revision_children(revid);
-  E(!children.size(), origin::user,
+  MONOTONE_ERROR(!children.size(), origin::user,
     F("revision %s already has children. We cannot kill it.")
     % revid);
 
@@ -223,7 +223,7 @@ CMD(db_kill_rev_locally, "kill_revision"
           if (edge_old_revision(i) != revid)
             continue;
 
-          E(!work.has_changes(db), origin::user,
+          MONOTONE_ERROR(!work.has_changes(db), origin::user,
             F("cannot kill revision %s,\n"
               "because it would leave the current workspace in an invalid\n"
               "state, from which monotone cannot recover automatically since\n"
@@ -325,7 +325,7 @@ CMD(db_check, "check", "", CMD_REF(db), 
        "checks."),
     options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -341,7 +341,7 @@ CMD(db_changesetify, "changesetify", "",
   key_store keys(app);
   project_t project(db);
 
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   db.ensure_open_for_format_changes();
@@ -362,7 +362,7 @@ CMD(db_rosterify, "rosterify", "", CMD_R
   key_store keys(app);
   project_t project(db);
 
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   db.ensure_open_for_format_changes();
@@ -380,7 +380,7 @@ CMD(db_regenerate_caches, "regenerate_ca
     "",
     options::opts::none)
 {
-  E(args.size() == 0, origin::user,
+  MONOTONE_ERROR(args.size() == 0, origin::user,
     F("no arguments needed"));
 
   database db(app);
@@ -407,7 +407,7 @@ CMD(db_set_epoch, "set_epoch", "", CMD_R
   if (args.size() != 2)
     throw usage(execid);
 
-  E(idx(args, 1)().size() == constants::epochlen, origin::user,
+  MONOTONE_ERROR(idx(args, 1)().size() == constants::epochlen, origin::user,
     F("The epoch must be %d characters") % constants::epochlen);
 
   epoch_data ed(decode_hexenc_as<epoch_data>(idx(args, 1)(), origin::user));
@@ -450,7 +450,7 @@ CMD(unset, "unset", "", CMD_REF(variable
   var_key k(d, n);
 
   database db(app);
-  E(db.var_exists(k), origin::user,
+  MONOTONE_ERROR(db.var_exists(k), origin::user,
     F("no var with name '%s' in domain '%s'") % n % d);
   db.clear_var(k);
 }
@@ -464,7 +464,7 @@ CMD(register_workspace, "register_worksp
   if (args.size() > 1)
     throw usage(execid);
 
-  E(args.size() == 1 || workspace::found, origin::user,
+  MONOTONE_ERROR(args.size() == 1 || workspace::found, origin::user,
     F("no workspace given"));
 
   system_path workspace;
@@ -486,7 +486,7 @@ CMD(unregister_workspace, "unregister_wo
   if (args.size() > 1)
     throw usage(execid);
 
-  E(args.size() == 1 || workspace::found, origin::user,
+  MONOTONE_ERROR(args.size() == 1 || workspace::found, origin::user,
     F("no workspace given"));
 
   system_path workspace;
@@ -554,7 +554,7 @@ CMD(complete, "complete", "", CMD_REF(in
   database db(app);
   project_t project(db);
 
-  E(idx(args, 1)().find_first_not_of("abcdef0123456789") == string::npos,
+  MONOTONE_ERROR(idx(args, 1)().find_first_not_of("abcdef0123456789") == string::npos,
     origin::user,
     F("non-hex digits in partial id"));
 
@@ -617,7 +617,7 @@ CMD_HIDDEN(rev_height, "rev_height", "",
   revision_id rid(decode_hexenc_as<revision_id>(idx(args, 0)(),
                                                 origin::user));
   database db(app);
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
   P(F("cached height: %s") % db.get_rev_height(rid));
 }
============================================================
--- src/cmd_diff_log.cc	6849a40ebcf3550a1c1b29cdb2f844ad72a6982d
+++ src/cmd_diff_log.cc	4232dbda923df2ff65f9d5eae301ddf74bf36665
@@ -257,10 +257,10 @@ prepare_diff(app_state & app,
   // initialize before transaction so we have a database to work with.
   project_t project(db);
 
-  E(app.opts.revision.size() <= 2, origin::user,
+  MONOTONE_ERROR(app.opts.revision.size() <= 2, origin::user,
     F("more than two revisions given"));
 
-  E(!app.opts.reverse || app.opts.revision.size() == 1, origin::user,
+  MONOTONE_ERROR(!app.opts.reverse || app.opts.revision.size() == 1, origin::user,
     F("'--reverse' only allowed with exactly one revision"));
 
   if (app.opts.revision.empty())
@@ -272,7 +272,7 @@ prepare_diff(app_state & app,
       parent_map parents = work.get_parent_rosters(db);
 
       // With no arguments, which parent should we diff against?
-      E(parents.size() == 1, origin::user,
+      MONOTONE_ERROR(parents.size() == 1, origin::user,
         F("this workspace has more than one parent\n"
           "(specify a revision to diff against with '--revision')"));
 
@@ -451,7 +451,7 @@ CMD(diff, "diff", "di", CMD_REF(informat
   (void)execid;
 
   if (app.opts.external_diff_args_given)
-    E(app.opts.diff_format == external_diff, origin::user,
+    MONOTONE_ERROR(app.opts.diff_format == external_diff, origin::user,
       F("'--diff-args' requires '--external'; try adding '--external' or remove '--diff-args'"));
 
   roster_t old_roster, new_roster;
@@ -674,7 +674,7 @@ log_common (app_state & app,
 
   log_direction direction = log_reverse;
 
-  E(last == -1 || next == -1, origin::user,
+  MONOTONE_ERROR(last == -1 || next == -1, origin::user,
     F("only one of '--last'/'--next' allowed"));
 
   if (next >= 0)
@@ -703,7 +703,7 @@ log_common (app_state & app,
           if ((FL("%s") % rid).str().empty()) {
             W(F("workspace has no parent revision, probably an empty branch"));
           } else {
-            E(db.revision_exists(rid), origin::user,
+            MONOTONE_ERROR(db.revision_exists(rid), origin::user,
               F("workspace parent revision %s not found - "
                 "did you specify a wrong database?") % rid);
             starting_revs.insert(rid);
============================================================
--- src/cmd_files.cc	2abfd5dfeb0b8ef04c0cb715064fc62b339b911a
+++ src/cmd_files.cc	8e5a876c9f9fdd711f033b61af8f90ea298a5a52
@@ -66,13 +66,13 @@ CMD(fmerge, "fmerge", "", CMD_REF(debug)
     right_id(decode_hexenc_as<file_id>(idx(args, 2)(), origin::user));
 
   database db(app);
-  E(db.file_version_exists (anc_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists (anc_id), origin::user,
     F("ancestor file id does not exist"));
 
-  E(db.file_version_exists (left_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists (left_id), origin::user,
     F("left file id does not exist"));
 
-  E(db.file_version_exists (right_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists (right_id), origin::user,
     F("right file id does not exist"));
 
   file_data
@@ -85,7 +85,7 @@ CMD(fmerge, "fmerge", "", CMD_REF(debug)
   split_into_lines(anc.inner()(), anc_lines);
   split_into_lines(left.inner()(), left_lines);
   split_into_lines(right.inner()(), right_lines);
-  E(merge3(anc_lines, left_lines, right_lines, merged_lines),
+  MONOTONE_ERROR(merge3(anc_lines, left_lines, right_lines, merged_lines),
     origin::user, F("merge failed"));
   copy(merged_lines.begin(), merged_lines.end(), ostream_iterator<string>(cout, "\n"));
 
@@ -113,10 +113,10 @@ CMD(fdiff, "fdiff", "", CMD_REF(debug), 
     dst_id(decode_hexenc_as<file_id>(idx(args, 3)(), origin::user));
 
   database db(app);
-  E(db.file_version_exists (src_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists (src_id), origin::user,
     F("source file id does not exist"));
 
-  E(db.file_version_exists (dst_id), origin::user,
+  MONOTONE_ERROR(db.file_version_exists (dst_id), origin::user,
     F("destination file id does not exist"));
 
   file_data
@@ -173,7 +173,7 @@ CMD(annotate, "annotate", "", CMD_REF(in
       // wants.  See tests/two_parent_workspace_annotate.
       workspace work(app);
       revision_t rev = work.get_work_rev();
-      E(rev.edges.size() == 1, origin::user,
+      MONOTONE_ERROR(rev.edges.size() == 1, origin::user,
         F("with no revision selected, this command can only be used in "
           "a single-parent workspace"));
 
@@ -191,11 +191,11 @@ CMD(annotate, "annotate", "", CMD_REF(in
     }
 
   // find the version of the file requested
-  E(roster.has_node(file), origin::user,
+  MONOTONE_ERROR(roster.has_node(file), origin::user,
     F("no such file '%s' in revision %s")
       % file % rid);
   const_node_t node = roster.get_node(file);
-  E(is_file_t(node), origin::user,
+  MONOTONE_ERROR(is_file_t(node), origin::user,
     F("'%s' in revision %s is not a file")
       % file % rid);
 
@@ -234,12 +234,12 @@ CMD_AUTOMATE(identify, N_("PATH"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   utf8 path = idx(args, 0);
 
-  E(path() != "-", origin::user,
+  MONOTONE_ERROR(path() != "-", origin::user,
     F("cannot read from stdin"));
 
   data dat = read_data_for_command_line(path);
@@ -249,7 +249,7 @@ dump_file(database & db, std::ostream & 
 static void
 dump_file(database & db, std::ostream & output, file_id const & ident)
 {
-  E(db.file_version_exists(ident), origin::user,
+  MONOTONE_ERROR(db.file_version_exists(ident), origin::user,
     F("no file version %s found in database") % ident);
 
   L(FL("dumping file %s") % ident);
@@ -260,7 +260,7 @@ dump_file(database & db, std::ostream & 
 static void
 dump_file(database & db, std::ostream & output, revision_id rid, utf8 filename)
 {
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % rid);
 
   // Paths are interpreted as standard external ones when we're in a
@@ -270,11 +270,11 @@ dump_file(database & db, std::ostream & 
   roster_t roster;
   marking_map marks;
   db.get_roster_and_markings(rid, roster, marks);
-  E(roster.has_node(fp), origin::user,
+  MONOTONE_ERROR(roster.has_node(fp), origin::user,
     F("no file '%s' found in revision %s") % fp % rid);
 
   const_node_t node = roster.get_node(fp);
-  E((!null_node(node->self) && is_file_t(node)), origin::user,
+  MONOTONE_ERROR((!null_node(node->self) && is_file_t(node)), origin::user,
     F("no file '%s' found in revision %s") % fp % rid);
 
   const_file_t file_node = downcast_to_file_t(node);
@@ -301,7 +301,7 @@ CMD(cat, "cat", "", CMD_REF(informative)
     {
       workspace work(app);
       parent_map parents = work.get_parent_rosters(db);
-      E(parents.size() == 1, origin::user,
+      MONOTONE_ERROR(parents.size() == 1, origin::user,
         F("this command can only be used in a single-parent workspace"));
       rid = parent_id(parents.begin());
     }
@@ -329,7 +329,7 @@ CMD_AUTOMATE(get_file, N_("FILEID"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -353,14 +353,14 @@ CMD_AUTOMATE(get_file_size, N_("FILEID")
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
   hexenc<id> hident(idx(args, 0)(), origin::user);
   file_id ident(decode_hexenc_as<file_id>(hident(), hident.made_from));
 
-  E(db.file_version_exists(ident), origin::user,
+  MONOTONE_ERROR(db.file_version_exists(ident), origin::user,
     F("no file version %s found in database") % ident);
 
   output << lexical_cast<string>(db.get_file_size(ident)) << "\n";
@@ -385,7 +385,7 @@ CMD_AUTOMATE(get_file_of, N_("FILENAME")
              "",
              options::opts::revision)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -396,7 +396,7 @@ CMD_AUTOMATE(get_file_of, N_("FILENAME")
       workspace work(app);
 
       parent_map parents = work.get_parent_rosters(db);
-      E(parents.size() == 1, origin::user,
+      MONOTONE_ERROR(parents.size() == 1, origin::user,
         F("this command can only be used in a single-parent workspace"));
       rid = parent_id(parents.begin());
     }
============================================================
--- src/cmd_key_cert.cc	d0f1ad7a8e4afd9844beca248db38a6a9dcd5553
+++ src/cmd_key_cert.cc	91058d5907d250639b3488745e8e9ace712beacb
@@ -58,11 +58,11 @@ CMD(genkey, "genkey", "", CMD_REF(key_an
 
   if (!app.opts.force_duplicate_key)
     {
-      E(!keys.key_pair_exists(name), origin::user,
+      MONOTONE_ERROR(!keys.key_pair_exists(name), origin::user,
         F("you already have a key named '%s'") % name);
       if (db.database_specified())
         {
-          E(!db.public_key_exists(name), origin::user,
+          MONOTONE_ERROR(!db.public_key_exists(name), origin::user,
             F("there is another key named '%s'") % name);
         }
     }
@@ -80,7 +80,7 @@ CMD_AUTOMATE(generate_key, N_("KEY_NAME 
   // not unified with CMD(genkey), because the call to create_key_pair is
   // significantly different.
 
-  E(args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() == 2, origin::user,
     F("wrong argument count"));
 
   database db(app, database::maybe_unspecified);
@@ -90,11 +90,11 @@ CMD_AUTOMATE(generate_key, N_("KEY_NAME 
 
   if (!app.opts.force_duplicate_key)
     {
-      E(!keys.key_pair_exists(name), origin::user,
+      MONOTONE_ERROR(!keys.key_pair_exists(name), origin::user,
         F("you already have a key named '%s'") % name);
       if (db.database_specified())
         {
-          E(!db.public_key_exists(name), origin::user,
+          MONOTONE_ERROR(!db.public_key_exists(name), origin::user,
             F("there is another key named '%s'") % name);
         }
     }
@@ -165,7 +165,7 @@ dropkey_common(app_state & app,
   else
     fmt = F("public or private key '%s' does not exist "
             "in keystore, and no database was specified");
-  E(key_deleted, origin::user, fmt % idx(args, 0)());
+  MONOTONE_ERROR(key_deleted, origin::user, fmt % idx(args, 0)());
 }
 
 CMD(dropkey, "dropkey", "", CMD_REF(key_and_cert), N_("KEY_NAME_OR_HASH"),
@@ -188,7 +188,7 @@ CMD_AUTOMATE(drop_public_key, N_("KEY_NA
   (void)execid;
   (void)output;
 
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   dropkey_common(app, args,
@@ -413,7 +413,7 @@ CMD(approve, "approve", "", CMD_REF(revi
   revision_id rev_id;
   complete(app.opts, app.lua, project, idx(args, 0)(), rev_id);
   app.opts.branch = project.guess_branch(app.opts, rev_id);
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("need '--branch' argument for approval"));
 
   cache_user_key(app.opts, project, keys, app.lua);
@@ -439,7 +439,7 @@ CMD(suspend, "suspend", "", CMD_REF(revi
   revision_id rev_id;
   complete(app.opts, app.lua, project, idx(args, 0)(), rev_id);
   app.opts.branch = project.guess_branch(app.opts, rev_id);
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("need '--branch' argument to suspend"));
 
   cache_user_key(app.opts, project, keys, app.lua);
@@ -466,13 +466,13 @@ CMD(comment, "comment", "", CMD_REF(revi
   else
     {
       external comment_external;
-      E(app.lua.hook_edit_comment(external(""), comment_external),
+      MONOTONE_ERROR(app.lua.hook_edit_comment(external(""), comment_external),
         origin::user,
         F("edit comment failed"));
       system_to_utf8(comment_external, comment);
     }
 
-  E(comment().find_first_not_of("\n\r\t ") != string::npos,
+  MONOTONE_ERROR(comment().find_first_not_of("\n\r\t ") != string::npos,
     origin::user,
     F("empty comment"));
 
============================================================
--- src/cmd_list.cc	21e848a20b9242b79c8de070eaf22e4acaa9c362
+++ src/cmd_list.cc	67eb3b105ef2adf57ccd8f0ee670b1cb669ac059
@@ -227,7 +227,7 @@ CMD(duplicates, "duplicates", "", CMD_RE
   database db(app);
   project_t project(db);
 
-  E(app.opts.revision.size() <= 1, origin::user,
+  MONOTONE_ERROR(app.opts.revision.size() <= 1, origin::user,
     F("more than one revision given"));
 
   if (app.opts.revision.empty())
@@ -239,7 +239,7 @@ CMD(duplicates, "duplicates", "", CMD_RE
     {
       complete(app.opts, app.lua, project,
                idx(app.opts.revision, 0)(), rev_id);
-      E(db.revision_exists(rev_id), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rev_id), origin::user,
         F("no revision %s found in database") % rev_id);
       roster = db.get_roster(rev_id);
     }
@@ -542,7 +542,7 @@ CMD(epochs, "epochs", "", CMD_REF(list),
         {
           map<branch_name, epoch_data>::const_iterator j =
             epochs.find(typecast_vocab<branch_name>((*i)));
-          E(j != epochs.end(), origin::user, F("no epoch for branch '%s'") % *i);
+          MONOTONE_ERROR(j != epochs.end(), origin::user, F("no epoch for branch '%s'") % *i);
           cout << encode_hexenc(j->second.inner()(),
                                 j->second.inner().made_from)
                << ' ' << j->first << '\n';
@@ -711,11 +711,11 @@ CMD(databases, "databases", "dbs", CMD_R
 {
   vector<system_path> search_paths, files, specials, dirs;
 
-  E(app.lua.hook_get_default_database_locations(search_paths), origin::user,
+  MONOTONE_ERROR(app.lua.hook_get_default_database_locations(search_paths), origin::user,
     F("no default database location configured"));
 
   globish file_matcher;
-  E(app.lua.hook_get_default_database_glob(file_matcher), origin::user,
+  MONOTONE_ERROR(app.lua.hook_get_default_database_glob(file_matcher), origin::user,
     F("could not query default database glob"));
 
   for (system_path const search_path : search_paths)
@@ -997,7 +997,7 @@ CMD_AUTOMATE(keys, "",
              "",
              options::opts::none)
 {
-  E(args.empty(), origin::user,
+  MONOTONE_ERROR(args.empty(), origin::user,
     F("no arguments needed"));
 
   database db(app, database::maybe_unspecified);
@@ -1056,7 +1056,7 @@ CMD_AUTOMATE(certs, N_("REV"),
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -1069,7 +1069,7 @@ CMD_AUTOMATE(certs, N_("REV"),
   hexenc<id> hrid(idx(args, 0)(), origin::user);
   revision_id rid(decode_hexenc_as<revision_id>(hrid(), origin::user));
 
-  E(db.revision_exists(rid), origin::user,
+  MONOTONE_ERROR(db.revision_exists(rid), origin::user,
     F("no revision %s found in database") % hrid);
 
   vector<cert> ts;
============================================================
--- src/cmd_merging.cc	dd574477bc1cec5ef6ad110e518b863967111953
+++ src/cmd_merging.cc	9491220dfef660a11266a62b2f04f8a6dd1bdbce
@@ -172,7 +172,7 @@ pick_branch_for_update(options & opts, d
           for (set<branch_name>::const_iterator i = branches.begin();
                i != branches.end(); i++)
             branch_list += "\n  " + (*i)();
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("target revision is in multiple branches:%s\n\n"
               "Try again with explicit '--branch'") % branch_list);
         }
@@ -203,15 +203,15 @@ update(app_state & app,
 
   // Figure out where we are
   parent_map parents = work.get_parent_rosters(db);
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   revision_id old_rid = parent_id(parents.begin());
-  E(!null_id(old_rid), origin::user,
+  MONOTONE_ERROR(!null_id(old_rid), origin::user,
     F("this workspace is a new project; cannot update"));
 
   // Figure out where we're going
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("cannot determine branch for update"));
 
   revision_id chosen_rid;
@@ -222,7 +222,7 @@ update(app_state & app,
       pick_update_candidates(app.lua, project, candidates, old_rid,
                              app.opts.branch,
                              app.opts.ignore_suspend_certs);
-      E(!candidates.empty(), origin::user,
+      MONOTONE_ERROR(!candidates.empty(), origin::user,
         F("your request matches no descendents of the current revision.\n"
           "In fact, it doesn't even match the current revision.\n"
           "Maybe you want something like '--revision=h:%s'")
@@ -235,7 +235,7 @@ update(app_state & app,
             P(i18n_format("  %s")
               % describe_revision(app.opts, app.lua, project, *i));
           P(F("choose one with '%s update -r<id>'") % prog_name);
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("multiple update candidates remain after selection"));
         }
       chosen_rid = *(candidates.begin());
@@ -374,10 +374,10 @@ CMD_AUTOMATE(update, "",
              options::opts::branch | options::opts::revision |
              options::opts::move_conflicting_paths)
 {
-  E(args.empty(), origin::user,
+  MONOTONE_ERROR(args.empty(), origin::user,
     F("wrong argument count"));
 
-  E(app.opts.revision.size() <= 1, origin::user,
+  MONOTONE_ERROR(app.opts.revision.size() <= 1, origin::user,
     F("at most one revision selector may be specified"));
 
   update(app, args);
@@ -518,14 +518,14 @@ CMD(merge, "merge", "", CMD_REF(tree), "
   if (!args.empty())
     throw usage(execid);
 
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("please specify a branch, with '--branch=BRANCH'"));
 
   set<revision_id> heads;
   project.get_branch_heads(app.opts.branch, heads,
                            app.opts.ignore_suspend_certs);
 
-  E(!heads.empty(), origin::user,
+  MONOTONE_ERROR(!heads.empty(), origin::user,
     F("branch '%s' is empty") % app.opts.branch);
   if (heads.size() == 1)
     {
@@ -626,14 +626,14 @@ void perform_merge_into_dir(app_state & 
   project.get_branch_heads(typecast_vocab<branch_name>(idx(args, 1)), dst_heads,
                            app.opts.ignore_suspend_certs);
 
-  E(src_heads.size() != 0, origin::user,
+  MONOTONE_ERROR(src_heads.size() != 0, origin::user,
     F("branch '%s' is empty") % idx(args, 0)());
-  E(src_heads.size() == 1, origin::user,
+  MONOTONE_ERROR(src_heads.size() == 1, origin::user,
     F("branch '%s' is not merged") % idx(args, 0)());
 
-  E(dst_heads.size() != 0, origin::user,
+  MONOTONE_ERROR(dst_heads.size() != 0, origin::user,
     F("branch '%s' is empty") % idx(args, 1)());
-  E(dst_heads.size() == 1, origin::user,
+  MONOTONE_ERROR(dst_heads.size() == 1, origin::user,
     F("branch '%s' is not merged") % idx(args, 1)());
 
   set<revision_id>::const_iterator src_i = src_heads.begin();
@@ -693,7 +693,7 @@ void perform_merge_into_dir(app_state & 
             MM(dir);
             pth.dirname_basename(dir, base);
 
-            E(right_roster.has_node(dir), origin::user,
+            MONOTONE_ERROR(right_roster.has_node(dir), origin::user,
               F("Path '%s' not found in destination tree.") % pth);
             const_node_t parent = right_roster.get_node(dir);
             moved_root->parent = parent->self;
@@ -815,13 +815,13 @@ CMD(merge_into_workspace, "merge_into_wo
 
   {
     parent_map parents = work.get_parent_rosters(db);
-    E(parents.size() == 1, origin::user,
+    MONOTONE_ERROR(parents.size() == 1, origin::user,
       F("this command can only be used in a single-parent workspace"));
 
     *working_roster = work.get_current_roster_shape(db);
     work.update_current_roster_from_filesystem(*working_roster);
 
-    E(parent_roster(parents.begin()) == *working_roster, origin::user,
+    MONOTONE_ERROR(parent_roster(parents.begin()) == *working_roster, origin::user,
       F("'%s' can only be used in a workspace with no pending changes") %
         join_words(execid)());
 
@@ -834,12 +834,12 @@ CMD(merge_into_workspace, "merge_into_wo
 
   complete(app.opts, app.lua, project, idx(args, 0)(), right_id);
   cached_roster right = db.get_cached_roster(right_id);
-  E(!(left_id == right_id), origin::user,
+  MONOTONE_ERROR(!(left_id == right_id), origin::user,
     F("workspace is already at revision %s") % left_id);
 
-  E(!is_ancestor(db, right_id, left_id), origin::user,
+  MONOTONE_ERROR(!is_ancestor(db, right_id, left_id), origin::user,
     F("revision %s is already an ancestor of your workspace") % right_id);
-  E(!is_ancestor(db, left_id, right_id), origin::user,
+  MONOTONE_ERROR(!is_ancestor(db, left_id, right_id), origin::user,
     F("revision %s is a descendant of the workspace parent,\n"
       "did you mean 'mtn update -r %s'?") % right_id % right_id);
 
@@ -923,13 +923,13 @@ CMD(explicit_merge, "explicit_merge", ""
   complete(app.opts, app.lua, project, idx(args, 1)(), right);
   branch = typecast_vocab<branch_name>(idx(args, 2));
 
-  E(!(left == right), origin::user,
+  MONOTONE_ERROR(!(left == right), origin::user,
     F("%s and %s are the same revision, aborting")
     % left % right);
-  E(!is_ancestor(db, left, right), origin::user,
+  MONOTONE_ERROR(!is_ancestor(db, left, right), origin::user,
     F("%s is already an ancestor of %s")
     % left % right);
-  E(!is_ancestor(db, right, left), origin::user,
+  MONOTONE_ERROR(!is_ancestor(db, right, left), origin::user,
     F("%s is already an ancestor of %s")
     % right % left);
 
@@ -1120,14 +1120,14 @@ static void get_conflicts_rids(args_vect
   if (args.empty())
     {
       // get ids from heads
-      E(!app.opts.branch().empty(), origin::user,
+      MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
         F("please specify a branch, with '--branch=BRANCH'"));
 
       set<revision_id> heads;
       project.get_branch_heads(app.opts.branch, heads,
                                app.opts.ignore_suspend_certs);
 
-      E(heads.size() >= 2, origin::user,
+      MONOTONE_ERROR(heads.size() >= 2, origin::user,
         F("branch '%s' has only 1 head; must be at least 2 for conflicts") % app.opts.branch);
 
       revpair p = find_heads_to_merge (db, heads);
@@ -1141,7 +1141,7 @@ static void get_conflicts_rids(args_vect
       complete(app.opts, app.lua, project, idx(args,1)(), right_rid);
     }
   else
-    E(false, origin::user, F("wrong argument count"));
+    MONOTONE_ERROR(false, origin::user, F("wrong argument count"));
 }
 
 // Name: show_conflicts
@@ -1218,7 +1218,7 @@ CMD_AUTOMATE(file_merge, N_("LEFT_REVID 
   // way to specify the ancestor id for a merge adaptor; why should we trust
   // the user?
 
-  E(args.size() == 4, origin::user,
+  MONOTONE_ERROR(args.size() == 4, origin::user,
     F("wrong argument count"));
 
   database  db(app);
@@ -1258,7 +1258,7 @@ CMD_AUTOMATE(file_merge, N_("LEFT_REVID 
                     adaptor);
   file_data ancestor_data, left_data, right_data, merge_data;
 
-  E(cm.attempt_auto_merge(ancestor_path, left_path, right_path,
+  MONOTONE_ERROR(cm.attempt_auto_merge(ancestor_path, left_path, right_path,
                           ancestor_fid, left_n->content, right_n->content,
                           left_data, right_data, merge_data),
     origin::user,
@@ -1292,7 +1292,7 @@ CMD(pluck, "pluck", "", CMD_REF(workspac
       complete(app.opts, app.lua, project,
                idx(app.opts.revision, 0)(), to_rid);
       set<revision_id> parents = db.get_revision_parents(to_rid);
-      E(parents.size() == 1, origin::user,
+      MONOTONE_ERROR(parents.size() == 1, origin::user,
         F("revision %s is a merge.\n"
           "To apply the changes relative to one of its parents, use:\n"
           "  %s pluck -r PARENT -r %s")
@@ -1311,7 +1311,7 @@ CMD(pluck, "pluck", "", CMD_REF(workspac
   else
     throw usage(execid);
 
-  E(!(from_rid == to_rid), origin::user, F("no changes to apply"));
+  MONOTONE_ERROR(!(from_rid == to_rid), origin::user, F("no changes to apply"));
 
   // notionally, we have the situation
   //
@@ -1372,7 +1372,7 @@ CMD(pluck, "pluck", "", CMD_REF(workspac
     from_to_to = cset(*from_roster, restricted_roster);
     from_to_to_excluded = cset(restricted_roster, to_true_roster);
   }
-  E(!from_to_to.empty(), origin::user, F("no changes to be applied"));
+  MONOTONE_ERROR(!from_to_to.empty(), origin::user, F("no changes to be applied"));
   // ...and use it to create the TO roster
   shared_ptr<roster_t> to_roster = make_shared<roster_t>();
   MM(*to_roster);
@@ -1417,7 +1417,7 @@ CMD(pluck, "pluck", "", CMD_REF(workspac
   // we apply the working to merged cset to the workspace
   cset update(*working_roster, merged_roster);
   MM(update);
-  E(!update.empty(), origin::no_fault, F("no changes were applied"));
+  MONOTONE_ERROR(!update.empty(), origin::no_fault, F("no changes were applied"));
   work.perform_content_update(*working_roster, merged_roster, update, wca,
                               true, app.opts.move_conflicting_paths);
 
@@ -1462,7 +1462,7 @@ CMD(heads, "heads", "", CMD_REF(tree), "
   if (!args.empty())
     throw usage(execid);
 
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("please specify a branch, with '--branch=BRANCH'"));
 
   database db(app);
============================================================
--- src/cmd_netsync.cc	42d5e8687b9dc65499efe1f16089ae790c535674
+++ src/cmd_netsync.cc	cf7deebb9a874f580c31428d9c07714e20d26987
@@ -64,7 +64,7 @@ extract_client_connection_info(options &
     {
       if (args.size() == 1)
         {
-          E(!opts.exclude_given, origin::user,
+          MONOTONE_ERROR(!opts.exclude_given, origin::user,
             F("cannot use '--exclude' in URI mode"));
 
           netsync_connection_info::setup_from_uri(opts, project.db, lua, type,
@@ -217,7 +217,7 @@ CMD_AUTOMATE_NO_STDIO(remote,
                       options::opts::min_netsync_version |
                       options::opts::set_default)
 {
-  E(args.size() >= 1, origin::user,
+  MONOTONE_ERROR(args.size() >= 1, origin::user,
     F("wrong argument count"));
 
   if (!app.opts.dbname_given)
@@ -276,7 +276,7 @@ CMD_AUTOMATE_NO_STDIO(remote,
                        client_voice, source_and_sink_role, info,
                        connection_counts::create());
 
-  E(os.get_error() == 0, origin::network,
+  MONOTONE_ERROR(os.get_error() == 0, origin::network,
     F("received remote error code %d") % os.get_error());
 }
 
@@ -740,7 +740,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
   if (!(no_ambigious_revision && (url_arg || host_branch_arg)))
     throw usage(execid);
 
-  E(url_arg || (host_branch_arg && !app.opts.branch_given), origin::user,
+  MONOTONE_ERROR(url_arg || (host_branch_arg && !app.opts.branch_given), origin::user,
     F("the '--branch' option is only valid with an URI to clone"));
 
   // we create the database before anything else, but we
@@ -764,7 +764,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
 
    if (url_arg)
     {
-      E(!app.opts.exclude_given, origin::user,
+      MONOTONE_ERROR(!app.opts.exclude_given, origin::user,
         F("cannot use '--exclude' in URI mode"));
 
       netsync_connection_info::setup_from_uri(app.opts, project.db, app.lua,
@@ -789,7 +789,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
   if (app.opts.branch().empty())
     {
       globish include_pattern = info->client.get_include_pattern();
-      E(!include_pattern().empty() && !include_pattern.contains_meta_chars(),
+      MONOTONE_ERROR(!include_pattern().empty() && !include_pattern.contains_meta_chars(),
         origin::user, F("you must specify an unambiguous branch to clone"));
       app.opts.branch = branch_name(include_pattern.unescaped(), origin::user);
     }
@@ -862,7 +862,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
       set<revision_id> heads;
       project.get_branch_heads(app.opts.branch, heads,
                                app.opts.ignore_suspend_certs);
-      E(!heads.empty(), origin::user,
+      MONOTONE_ERROR(!heads.empty(), origin::user,
         F("branch '%s' is empty") % app.opts.branch);
       if (heads.size() > 1)
         {
@@ -871,7 +871,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
             P(i18n_format("  %s")
               % describe_revision(app.opts, app.lua, project, *i));
           P(F("choose one with '%s clone -r<id> URI'") % prog_name);
-          E(false, origin::user, F("branch '%s' has multiple heads") % app.opts.branch);
+          MONOTONE_ERROR(false, origin::user, F("branch '%s' has multiple heads") % app.opts.branch);
         }
       ident = *(heads.begin());
     }
@@ -880,7 +880,7 @@ CMD_NO_WORKSPACE(clone, "clone", "", CMD
       // use specified revision
       complete(app.opts, app.lua, project, idx(app.opts.revision, 0)(), ident);
 
-      E(project.revision_is_in_branch(ident, app.opts.branch),
+      MONOTONE_ERROR(project.revision_is_in_branch(ident, app.opts.branch),
         origin::user,
         F("revision %s is not a member of branch '%s'")
           % ident % app.opts.branch);
@@ -913,7 +913,7 @@ struct pid_file
       return;
     require_path_is_nonexistent(path, F("pid file '%s' already exists") % path);
     file.open(path.as_external().c_str());
-    E(file.is_open(), origin::system, F("failed to create pid file '%s'") % path);
+    MONOTONE_ERROR(file.is_open(), origin::system, F("failed to create pid file '%s'") % path);
     file << get_process_id() << '\n';
     file.flush();
   }
============================================================
--- src/cmd_othervcs.cc	01389bf7bccdab20dcbbd54ee73840392002622a
+++ src/cmd_othervcs.cc	175d8549c2c111442d309fc7b60d419258d5a59c
@@ -52,7 +52,7 @@ CMD(cvs_import, "cvs_import", "", CMD_RE
   if (args.size() != 1)
     throw usage(execid);
 
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("need base '--branch' argument for importing"));
 
   system_path cvsroot(idx(args, 0)(), origin::user);
============================================================
--- src/cmd_packet.cc	adf591bbe10d5184ec04fb4e0484d0eddb1a1ff8
+++ src/cmd_packet.cc	54dd035e5230f6e7e60605362d7a43ef4a5b8a16
@@ -70,7 +70,7 @@ CMD_AUTOMATE(put_public_key, N_("KEY-PAC
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -108,7 +108,7 @@ pubkey_common(app_state & app,
       key = kp.pub;
       exists = true;
     }
-  E(exists, origin::user,
+  MONOTONE_ERROR(exists, origin::user,
     F("public key '%s' does not exist") % idx(args, 0)());
 
   packet_writer pw(output);
@@ -135,7 +135,7 @@ CMD_AUTOMATE(get_public_key, N_("KEY_NAM
     "",
     options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   pubkey_common(app, args, output);
@@ -259,7 +259,7 @@ CMD_AUTOMATE(read_packets, N_("PACKET-DA
              "",
              options::opts::none)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   database db(app);
@@ -282,7 +282,7 @@ CMD(read, "read", "", CMD_REF(packet_io)
   if (args.empty())
     {
       count += read_packets(cin, dbw);
-      E(count != 0, origin::user, F("no packets found on stdin"));
+      MONOTONE_ERROR(count != 0, origin::user, F("no packets found on stdin"));
     }
   else
     {
@@ -293,7 +293,7 @@ CMD(read, "read", "", CMD_REF(packet_io)
           istringstream ss(dat());
           count += read_packets(ss, dbw);
         }
-      E(count != 0, origin::user,
+      MONOTONE_ERROR(count != 0, origin::user,
         FP("no packets found in given file",
            "no packets found in given files",
            args.size()));
============================================================
--- src/cmd_ws_commit.cc	8642e2de09758ea82c50c4a26065178a317b9f77
+++ src/cmd_ws_commit.cc	bdde4720b89aa07ebfdf9d6d5c2a37048e8ff9c6
@@ -188,7 +188,7 @@ get_log_message_interactively(lua_hooks 
                               string const & date_fmt, utf8 & log_message)
 {
   utf8 backup = work.load_commit_text();
-  E(backup().empty(), origin::user,
+  MONOTONE_ERROR(backup().empty(), origin::user,
     F("a backup from a previously failed commit exists in '_MTN/commit'.\n"
       "This file must be removed before commit will proceed.\n"
       "You may recover the previous message from this file if necessary."));
@@ -281,7 +281,7 @@ get_log_message_interactively(lua_hooks 
 
   utf8_to_system_best_effort(full_message, input_message);
 
-  E(lua.hook_edit_comment(input_message, output_message),
+  MONOTONE_ERROR(lua.hook_edit_comment(input_message, output_message),
     origin::user,
     F("edit of log message failed"));
 
@@ -297,7 +297,7 @@ get_log_message_interactively(lua_hooks 
       if (changelog_end != string::npos)
         work.write_user_log(utf8(trim_right(full_message().substr(0, changelog_end)) + '\n', origin::user));
 
-      E(false, origin::user, F("commit cancelled."));
+      MONOTONE_ERROR(false, origin::user, F("commit cancelled."));
     }
 
   // save the message in _MTN/commit so it's not lost if something fails
@@ -314,39 +314,39 @@ get_log_message_interactively(lua_hooks 
   // this can't fail, since we start reading where we found it above.
   message.read(cancel());
 
-  E(message.read(instructions()), origin::user,
+  MONOTONE_ERROR(message.read(instructions()), origin::user,
     F("commit failed. Instructions not found."));
 
   // Branch:
 
-  E(message.read(trim_right(BRANCH())), origin::user,
+  MONOTONE_ERROR(message.read(trim_right(BRANCH())), origin::user,
     F("commit failed. Branch header not found."));
 
   string b = message.readline();
 
-  E(!b.empty(), origin::user,
+  MONOTONE_ERROR(!b.empty(), origin::user,
     F("commit failed. Branch value empty."));
 
   branch = branch_name(b, origin::user);
 
   // Author:
 
-  E(message.read(trim_right(AUTHOR())), origin::user,
+  MONOTONE_ERROR(message.read(trim_right(AUTHOR())), origin::user,
     F("commit failed. Author header not found."));
 
   author = message.readline();
 
-  E(!author.empty(), origin::user,
+  MONOTONE_ERROR(!author.empty(), origin::user,
     F("commit failed. Author value empty."));
 
   // Date:
 
-  E(message.read(trim_right(DATE())), origin::user,
+  MONOTONE_ERROR(message.read(trim_right(DATE())), origin::user,
     F("commit failed. Date header not found."));
 
   string d = message.readline();
 
-  E(!d.empty(), origin::user,
+  MONOTONE_ERROR(!d.empty(), origin::user,
     F("commit failed. Date value empty."));
 
   if (!is_date_fmt_valid || date_fmt.empty())
@@ -367,7 +367,7 @@ revert(app_state & app,
 {
   roster_t old_roster, new_roster;
 
-  E(app.opts.missing || !args.empty() || !app.opts.exclude.empty(),
+  MONOTONE_ERROR(app.opts.missing || !args.empty() || !app.opts.exclude.empty(),
     origin::user,
     F("you must pass at least one path to 'revert' (perhaps '.')"));
 
@@ -375,7 +375,7 @@ revert(app_state & app,
   workspace work(app);
 
   parent_map parents = work.get_parent_rosters(db);
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
   old_roster = parent_roster(parents.begin());
 
@@ -483,7 +483,7 @@ revert(app_state & app,
               P(F("reverting %s") % path);
               L(FL("reverting %s to [%s]") % path % f->content);
 
-              E(db.file_version_exists(f->content), origin::user,
+              MONOTONE_ERROR(db.file_version_exists(f->content), origin::user,
                 F("no file version %s found in database for '%s'")
                 % f->content % path);
 
@@ -570,16 +570,16 @@ walk_revisions(database & db, const revi
 
   do
     {
-      E(!null_id(r), origin::user,
+      MONOTONE_ERROR(!null_id(r), origin::user,
         F("revision %s it not a child of %s, cannot invert")
         % from_rev % to_rev);
 
       revision_t rev = db.get_revision(r);
-      E(rev.edges.size() < 2, origin::user,
+      MONOTONE_ERROR(rev.edges.size() < 2, origin::user,
         F("revision %s has %d parents, cannot invert")
         % r % rev.edges.size());
 
-      E(rev.edges.size() > 0, origin::user,
+      MONOTONE_ERROR(rev.edges.size() > 0, origin::user,
         F("revision %s it not a child of %s, cannot invert")
         % from_rev % to_rev);
       r = edge_old_revision (rev.edges.begin());
@@ -614,12 +614,12 @@ CMD(disapprove, "disapprove", "", CMD_RE
       complete(app.opts, app.lua, project, idx(args, 0)(), child_rev);
       rev = db.get_revision(child_rev);
 
-      E(rev.edges.size() == 1, origin::user,
+      MONOTONE_ERROR(rev.edges.size() == 1, origin::user,
         F("revision %s has %d parents, cannot invert")
         % child_rev % rev.edges.size());
 
       app.opts.branch = project.guess_branch(app.opts, child_rev);
-      E(!app.opts.branch().empty(), origin::user,
+      MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
         F("need '--branch' argument for disapproval"));
 
       process_commit_message_args(app.opts, log_message_given, log_message,
@@ -642,10 +642,10 @@ CMD(disapprove, "disapprove", "", CMD_RE
         {
           set<revision_id> ancestors;
           db.get_common_ancestors (rev_set, ancestors);
-          E(ancestors.size() > 0, origin::user,
+          MONOTONE_ERROR(ancestors.size() > 0, origin::user,
             F("revisions %s and %s do not share common history, cannot invert")
             % parent_rev % child_rev);
-          E(ancestors.size() < 1, origin::user,
+          MONOTONE_ERROR(ancestors.size() < 1, origin::user,
             F("revisions share common history"
               ", but %s is not an ancestor of %s, cannot invert")
             % parent_rev % child_rev);
@@ -654,12 +654,12 @@ CMD(disapprove, "disapprove", "", CMD_RE
       walk_revisions(db, child_rev, parent_rev);
       rev = db.get_revision(parent_rev);
 
-      E(rev.edges.size() == 1, origin::user,
+      MONOTONE_ERROR(rev.edges.size() == 1, origin::user,
         F("revision %s has %d parents, cannot invert")
         % child_rev % rev.edges.size());
 
       app.opts.branch = project.guess_branch(app.opts, child_rev);
-      E(!app.opts.branch().empty(), origin::user,
+      MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
         F("need '--branch' argument for disapproval"));
 
       process_commit_message_args(app.opts, log_message_given, log_message,
@@ -678,7 +678,7 @@ CMD(disapprove, "disapprove", "", CMD_RE
   unsigned int old_head_size = heads.size();
 
   edge_entry const & old_edge = *rev.edges.begin();
-  E(!null_id(edge_old_revision(old_edge)), origin::user,
+  MONOTONE_ERROR(!null_id(edge_old_revision(old_edge)), origin::user,
     F("cannot disapprove root revision"));
   rev_inverse.new_manifest
     = db.get_revision_manifest(edge_old_revision(old_edge));
@@ -740,7 +740,7 @@ CMD(mkdir, "mkdir", "", CMD_REF(workspac
       // we'll treat this as a user (fatal) error.  it really wouldn't make
       // sense to add a dir to .mtn-ignore and then try to add it to the
       // project with a mkdir statement, but one never can tell...
-      E(app.opts.no_ignore || !work.ignore_file(fp),
+      MONOTONE_ERROR(app.opts.no_ignore || !work.ignore_file(fp),
         origin::user,
         F("ignoring directory '%s' (see '.mtn-ignore')") % fp);
 
@@ -777,7 +777,7 @@ void perform_add(app_state & app,
         {
           for (file_path const & path : items.special)
             P(F("special file: %s") % path);
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("cannot handle special files"));
         }
 
@@ -894,7 +894,7 @@ CMD(rename, "rename", "mv", CMD_REF(work
   //cases for more than one source item.
   if (src_paths.size() == 1 && dstr()[dstr().size() -1] == '/')
     if (get_path_status(*src_paths.begin()) != path::directory)
-      E(get_path_status(dst_path) == path::directory, origin::user,
+      MONOTONE_ERROR(get_path_status(dst_path) == path::directory, origin::user,
         F(_("the specified target directory '%s/' doesn't exist.")) % dst_path);
 
   work.perform_rename(db, src_paths, dst_path, app.opts.bookkeep_only);
@@ -1411,13 +1411,13 @@ checkout_common(app_state & app,
   if (app.opts.revision.empty())
     {
       // use branch head revision
-      E(!app.opts.branch().empty(), origin::user,
+      MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
         F("use '--revision' or '--branch' to specify what to checkout"));
 
       set<revision_id> heads;
       project.get_branch_heads(app.opts.branch, heads,
                                app.opts.ignore_suspend_certs);
-      E(!heads.empty(), origin::user,
+      MONOTONE_ERROR(!heads.empty(), origin::user,
         F("branch '%s' is empty") % app.opts.branch);
       if (heads.size() > 1)
         {
@@ -1426,7 +1426,7 @@ checkout_common(app_state & app,
             P(i18n_format("  %s")
               % describe_revision(app.opts, app.lua, project, rid));
           P(F("choose one with '%s checkout -r<id>'") % prog_name);
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("branch '%s' has multiple heads") % app.opts.branch);
         }
       rev_id = *(heads.begin());
@@ -1440,7 +1440,7 @@ checkout_common(app_state & app,
       app.opts.branch = project.guess_branch(app.opts, rev_id);
       I(!app.opts.branch().empty());
 
-      E(project.revision_is_in_branch(rev_id, app.opts.branch),
+      MONOTONE_ERROR(project.revision_is_in_branch(rev_id, app.opts.branch),
         origin::user,
         F("revision %s is not a member of branch %s")
         % rev_id % app.opts.branch);
@@ -1458,7 +1458,7 @@ checkout_common(app_state & app,
     if (args.empty())
       {
         // No checkout dir specified, use branch name for dir.
-        E(!app.opts.branch().empty(), origin::user,
+        MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
           F("you must specify a destination directory"));
         dir = system_path(app.opts.branch(), origin::user);
       }
@@ -1518,10 +1518,10 @@ CMD_AUTOMATE(checkout, N_("[DIRECTORY]")
     options::opts::branch | options::opts::revision |
     options::opts::move_conflicting_paths)
 {
-  E(args.size() < 2, origin::user,
+  MONOTONE_ERROR(args.size() < 2, origin::user,
     F("wrong argument count"));
 
-  E(app.opts.revision.size() < 2, origin::user,
+  MONOTONE_ERROR(app.opts.revision.size() < 2, origin::user,
     F("wrong revision count"));
 
   checkout_common(app, args);
@@ -1543,7 +1543,7 @@ drop_attr(app_state & app, args_vector c
   roster_t old_roster = work.get_current_roster_shape(db);
   file_path path = file_path_external(idx(args, 0));
 
-  E(old_roster.has_node(path), origin::user,
+  MONOTONE_ERROR(old_roster.has_node(path), origin::user,
     F("unknown path '%s'") % path);
 
   roster_t new_roster = old_roster;
@@ -1560,7 +1560,7 @@ drop_attr(app_state & app, args_vector c
     {
       I(args.size() == 2);
       attr_key a_key = typecast_vocab<attr_key>(idx(args, 1));
-      E(node->attrs.find(a_key) != node->attrs.end(), origin::user,
+      MONOTONE_ERROR(node->attrs.find(a_key) != node->attrs.end(), origin::user,
         F("path '%s' does not have attribute '%s'")
         % path % a_key);
       node->attrs[a_key] = make_pair(false, attr_value(""));
@@ -1610,7 +1610,7 @@ CMD(attr_get, "get", "", CMD_REF(attr), 
 
   file_path path = file_path_external(idx(args, 0));
 
-  E(new_roster.has_node(path), origin::user, F("unknown path '%s'") % path);
+  MONOTONE_ERROR(new_roster.has_node(path), origin::user, F("unknown path '%s'") % path);
   const_node_t node = new_roster.get_node(path);
 
   if (args.size() == 1)
@@ -1655,7 +1655,7 @@ set_attr(app_state & app, args_vector co
   roster_t old_roster = work.get_current_roster_shape(db);
   file_path path = file_path_external(idx(args, 0));
 
-  E(old_roster.has_node(path), origin::user,
+  MONOTONE_ERROR(old_roster.has_node(path), origin::user,
     F("unknown path '%s'") % path);
 
   roster_t new_roster = old_roster;
@@ -1713,7 +1713,7 @@ CMD_AUTOMATE(get_attributes, N_("PATH"),
                 "at this specific revision are returned."),
              options::opts::revision)
 {
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("wrong argument count"));
 
   file_path path = file_path_external(idx(args,0));
@@ -1730,11 +1730,11 @@ CMD_AUTOMATE(get_attributes, N_("PATH"),
       // get the base and the current roster of this workspace
       current = work.get_current_roster_shape(db);
       parent_map parents = work.get_parent_rosters(db);
-      E(parents.size() == 1, origin::user,
+      MONOTONE_ERROR(parents.size() == 1, origin::user,
         F("this command can only be used in a single-parent workspace"));
       base = parent_roster(parents.begin());
 
-      E(current.has_node(path), origin::user,
+      MONOTONE_ERROR(current.has_node(path), origin::user,
         F("unknown path '%s'") % path);
     }
   else if (app.opts.revision.size() == 1)
@@ -1746,11 +1746,11 @@ CMD_AUTOMATE(get_attributes, N_("PATH"),
       complete(app.opts, app.lua, project, idx(app.opts.revision, 0)(), rid);
       current = db.get_roster(rid);
 
-      E(current.has_node(path), origin::user,
+      MONOTONE_ERROR(current.has_node(path), origin::user,
         F("unknown path '%s' in %s") % path % rid);
     }
   else
-    E(false, origin::user, F("none or only one revision must be given"));
+    MONOTONE_ERROR(false, origin::user, F("none or only one revision must be given"));
 
   basic_io::printer pr;
 
@@ -1852,7 +1852,7 @@ CMD_AUTOMATE(set_attribute, N_("PATH KEY
              "",
              options::opts::none)
 {
-  E(args.size() == 3, origin::user,
+  MONOTONE_ERROR(args.size() == 3, origin::user,
     F("wrong argument count"));
 
   set_attr(app, args);
@@ -1874,7 +1874,7 @@ CMD_AUTOMATE(drop_attribute, N_("PATH [K
              "",
              options::opts::none)
 {
-  E(args.size() ==1 || args.size() == 2, origin::user,
+  MONOTONE_ERROR(args.size() ==1 || args.size() == 2, origin::user,
     F("wrong argument count"));
 
   drop_attr(app, args);
@@ -1908,7 +1908,7 @@ void perform_commit(app_state & app,
     = make_restricted_revision(old_rosters, new_roster, mask,
                                excluded, join_words(execid));
   restricted_rev.check_sane();
-  E(restricted_rev.is_nontrivial(), origin::user, F("no changes to commit"));
+  MONOTONE_ERROR(restricted_rev.is_nontrivial(), origin::user, F("no changes to commit"));
 
   set<branch_name> old_branches = get_old_branch_names(db, old_rosters);
   revision_id restricted_rev_id = calculate_ident(restricted_rev);
@@ -1923,7 +1923,7 @@ void perform_commit(app_state & app,
           // this will prefer --branch if it was set
           bn_candidate =
             project.guess_branch(app.opts, edge_old_revision(edge));
-          E(branchname() == "" || branchname == bn_candidate, origin::user,
+          MONOTONE_ERROR(branchname() == "" || branchname == bn_candidate, origin::user,
             F("parent revisions of this commit are in different branches:\n"
               "'%s' and '%s'.\n"
               "Please specify a branch name for the commit, with '--branch'.")
@@ -1944,7 +1944,7 @@ void perform_commit(app_state & app,
   app.lua.hook_validate_changes(rev_data, app.opts.branch,
                                 changes_validated, reason);
 
-  E(changes_validated, origin::user,
+  MONOTONE_ERROR(changes_validated, origin::user,
     F("changes rejected by hook: %s") % reason);
 
   if (global_sanity.debug_p())
@@ -1957,7 +1957,7 @@ void perform_commit(app_state & app,
 
   process_commit_message_args(app.opts, log_message_given, log_message);
 
-  E(!(log_message_given && work.has_contents_user_log() &&
+  MONOTONE_ERROR(!(log_message_given && work.has_contents_user_log() &&
       app.opts.msgfile() != "_MTN/log"), origin::user,
     F("'_MTN/log' is non-empty and log message "
       "was specified on command line.\n"
@@ -2002,7 +2002,7 @@ void perform_commit(app_state & app,
       // type --message="", then there wasn't any reason to stop them.
       // FIXME: perhaps there should be no changelog cert in this case.
 
-      E(log_message().find_first_not_of("\n\r\t ") != string::npos,
+      MONOTONE_ERROR(log_message().find_first_not_of("\n\r\t ") != string::npos,
         origin::user,
         F("empty log message; commit canceled"));
 
@@ -2023,7 +2023,7 @@ void perform_commit(app_state & app,
 
   app.lua.hook_validate_commit_message(log_message, rev_data, app.opts.branch,
                                        message_validated, reason);
-  E(message_validated, origin::user,
+  MONOTONE_ERROR(message_validated, origin::user,
     F("log message rejected by hook: %s") % reason);
 
   cache_user_key(app.opts, project, keys, app.lua);
@@ -2078,7 +2078,7 @@ void perform_commit(app_state & app,
                     data new_data = read_data(path);
                     // sanity check
                     file_id tid = calculate_ident(file_data(new_data));
-                    E(tid == new_content, origin::user,
+                    MONOTONE_ERROR(tid == new_content, origin::user,
                       F("file '%s' modified during commit, aborting")
                       % path);
                     delta del;
@@ -2088,7 +2088,7 @@ void perform_commit(app_state & app,
                   }
                 else
                   // If we don't err out here, the database will later.
-                  E(false, origin::no_fault,
+                  MONOTONE_ERROR(false, origin::no_fault,
                     F("your database is missing version %s of file '%s'")
                     % old_content % path);
               }
@@ -2105,7 +2105,7 @@ void perform_commit(app_state & app,
                 data new_data = read_data(path);
                 // sanity check
                 file_id tid = calculate_ident(file_data(new_data));
-                E(tid == new_content, origin::user,
+                MONOTONE_ERROR(tid == new_content, origin::user,
                   F("file '%s' modified during commit, aborting")
                   % path);
                 db.put_file(new_content, file_data(new_data));
@@ -2207,7 +2207,7 @@ CMD_NO_WORKSPACE(setup, "setup", "", CMD
   if (args.size() > 1)
     throw usage(execid);
 
-  E(!app.opts.branch().empty(), origin::user,
+  MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
     F("need '--branch' argument for setup"));
 
   string dir;
@@ -2258,7 +2258,7 @@ CMD_NO_WORKSPACE(import, "import", "", C
   database db(app);
   project_t project(db);
 
-  E(args.size() == 1, origin::user,
+  MONOTONE_ERROR(args.size() == 1, origin::user,
     F("you must specify a directory to import"));
 
   if (app.opts.revision.size() == 1)
@@ -2269,7 +2269,7 @@ CMD_NO_WORKSPACE(import, "import", "", C
       app.opts.branch = project.guess_branch(app.opts, ident);
       I(!app.opts.branch().empty());
 
-      E(project.revision_is_in_branch(ident, app.opts.branch),
+      MONOTONE_ERROR(project.revision_is_in_branch(ident, app.opts.branch),
         origin::user,
         F("revision %s is not a member of branch '%s'")
         % ident % app.opts.branch);
@@ -2277,7 +2277,7 @@ CMD_NO_WORKSPACE(import, "import", "", C
   else
     {
       // use branch head revision
-      E(!app.opts.branch().empty(), origin::user,
+      MONOTONE_ERROR(!app.opts.branch().empty(), origin::user,
         F("use '--revision' or '--branch' to specify the parent revision for the import"));
 
       set<revision_id> heads;
@@ -2290,7 +2290,7 @@ CMD_NO_WORKSPACE(import, "import", "", C
             P(i18n_format("  %s")
               % describe_revision(app.opts, app.lua, project, *i));
           P(F("choose one with '%s import -r<id>'") % prog_name);
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("branch '%s' has multiple heads") % app.opts.branch);
         }
       if (!heads.empty())
@@ -2413,10 +2413,10 @@ CMD(reset, "reset", "", CMD_REF(bisect),
 
   vector<bisect::entry> info = work.get_bisect_info();
 
-  E(!info.empty(), origin::user, F("no bisection in progress"));
+  MONOTONE_ERROR(!info.empty(), origin::user, F("no bisection in progress"));
 
   parent_map parents = work.get_parent_rosters(db);
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   revision_id current_id = parent_id(*parents.begin());
@@ -2424,7 +2424,7 @@ CMD(reset, "reset", "", CMD_REF(bisect),
   roster_t current_roster = work.get_current_roster_shape(db);
   work.update_current_roster_from_filesystem(current_roster);
 
-  E(parent_roster(parents.begin()) == current_roster, origin::user,
+  MONOTONE_ERROR(parent_roster(parents.begin()) == current_roster, origin::user,
     F("this command can only be used in a workspace with no pending changes"));
 
   bisect::entry start = *info.begin();
@@ -2458,7 +2458,7 @@ bisect_select(options const & opts, lua_
   graph_loader loader(project.db);
   set<revision_id> good, bad, skipped;
 
-  E(!info.empty(), origin::user,
+  MONOTONE_ERROR(!info.empty(), origin::user,
     F("no bisection in progress"));
 
   for (vector<bisect::entry>::const_iterator i = info.begin();
@@ -2634,14 +2634,14 @@ bisect_update(app_state & app, bisect::t
   project_t project(db);
 
   parent_map parents = work.get_parent_rosters(db);
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   revision_id current_id = parent_id(*parents.begin());
   roster_t current_roster = work.get_current_roster_shape(db);
   work.update_current_roster_from_filesystem(current_roster);
 
-  E(parent_roster(parents.begin()) == current_roster, origin::user,
+  MONOTONE_ERROR(parent_roster(parents.begin()) == current_roster, origin::user,
     F("this command can only be used in a workspace with no pending changes"));
 
   set<revision_id> marked_ids;
@@ -2686,7 +2686,7 @@ bisect_update(app_state & app, bisect::t
                   marked_ids.erase(i->second);
                 }
               else
-                E(false, origin::user, F("conflicting bisect %s/%s on revision %s")
+                MONOTONE_ERROR(false, origin::user, F("conflicting bisect %s/%s on revision %s")
                   % type % i->first % i->second);
             }
         }
@@ -2737,7 +2737,7 @@ CMD(bisect_status, "status", "", CMD_REF
   project_t project(db);
 
   parent_map parents = work.get_parent_rosters(db);
-  E(parents.size() == 1, origin::user,
+  MONOTONE_ERROR(parents.size() == 1, origin::user,
     F("this command can only be used in a single-parent workspace"));
 
   revision_id current_id = parent_id(*parents.begin());
============================================================
--- src/commands.cc	fea3779443f114ed1f043c5a1665065978830437
+++ src/commands.cc	21d1607613ca9786a5782304c7d0f8a3fe975ae5
@@ -493,7 +493,7 @@ namespace commands
 
     if (matches.empty())
       {
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F("unknown command '%s'") % join_words(id));
       }
     else if (matches.size() == 1)
@@ -509,7 +509,7 @@ namespace commands
         for (set< command_id >::const_iterator iter = matches.begin();
              iter != matches.end(); iter++)
           err += '\n' + join_words(*iter)();
-        E(false, origin::user, i18n_format(err));
+        MONOTONE_ERROR(false, origin::user, i18n_format(err));
       }
 
     I(!id.empty());
============================================================
--- src/database.cc	87c79458cd5a84c73189a899081d886ac7b0d9eb
+++ src/database.cc	d9a4a3cf7ca90e2df61a34364502e5c90803c157
@@ -592,7 +592,7 @@ database::check_is_not_rosterified()
 void
 database::check_is_not_rosterified()
 {
-  E(!imp->table_has_data("rosters"), origin::user,
+  MONOTONE_ERROR(!imp->table_has_data("rosters"), origin::user,
     F("this database already contains rosters"));
 }
 
@@ -614,7 +614,7 @@ database_impl::check_format()
 
       // they need to either changesetify or rosterify.  which?
       if (table_has_data("revisions"))
-        E(false, origin::no_fault,
+        MONOTONE_ERROR(false, origin::no_fault,
           F("database '%s' contains old-style revisions.\n"
             "If you are a project leader or doing local testing:\n"
             "  see the file UPGRADE for instructions on upgrading.\n"
@@ -624,7 +624,7 @@ database_impl::check_format()
             "Sorry about the inconvenience.")
           % filename);
       else
-        E(false, origin::no_fault,
+        MONOTONE_ERROR(false, origin::no_fault,
           F("database '%s' contains manifests but no revisions.\n"
             "This is a very old database; it needs to be upgraded.\n"
             "Please see 'http://wiki.monotone.ca/upgradefromchangesets/'\n"
@@ -647,7 +647,7 @@ database_impl::check_caches()
       caches_are_filled = caches_are_filled && table_has_data("file_sizes");
     }
 
-  E(caches_are_filled, origin::no_fault,
+  MONOTONE_ERROR(caches_are_filled, origin::no_fault,
     F("database '%s' lacks some cached data.\n"
       "Run '%s db regenerate_caches' to restore use of this database")
     % filename % prog_name);
@@ -1444,13 +1444,13 @@ database_impl::fetch(results & res,
       L(FL("prepared statement %s") % query.sql_cmd);
 
       // no support for multiple statements here
-      E(*tail == 0, origin::internal,
+      MONOTONE_ERROR(*tail == 0, origin::internal,
         F("multiple statements in query: %s") % query.sql_cmd);
     }
 
   ncol = sqlite3_column_count(i->second.stmt());
 
-  E(want_cols == any_cols || want_cols == ncol, origin::database,
+  MONOTONE_ERROR(want_cols == any_cols || want_cols == ncol, origin::database,
     F("wanted %d columns got %d in query: %s") % want_cols % ncol % query.sql_cmd);
 
   // bind parameters for this execution
@@ -1529,7 +1529,7 @@ database_impl::fetch(results & res,
         {
           // We never store NULLs, so we should never see one.
           int const datatype = sqlite3_column_type(i->second.stmt(), col);
-          E(datatype != SQLITE_NULL, origin::database,
+          MONOTONE_ERROR(datatype != SQLITE_NULL, origin::database,
             F("null result in query: %s") % query.sql_cmd);
           const char * value = (const char*)sqlite3_column_blob(i->second.stmt(), col);
           int bytes = sqlite3_column_bytes(i->second.stmt(), col);
@@ -1554,7 +1554,7 @@ database_impl::fetch(results & res,
 
   i->second.count++;
 
-  E(want_rows == any_rows || want_rows == nrow,
+  MONOTONE_ERROR(want_rows == any_rows || want_rows == nrow,
     origin::database,
     F("wanted %d rows got %d in query: %s") % want_rows % nrow % query.sql_cmd);
 }
@@ -1895,7 +1895,7 @@ database_impl::get_roster_base(revision_
 
   id checksum(res[0][0], origin::database);
   id calculated = calculate_ident(data(res[0][1], origin::database));
-  E(calculated == checksum, origin::database,
+  MONOTONE_ERROR(calculated == checksum, origin::database,
     F("roster does not match hash"));
 
   gzip<data> dat_packed(res[0][1], origin::database);
@@ -1914,7 +1914,7 @@ database_impl::get_roster_delta(id const
 
   id checksum(res[0][0], origin::database);
   id calculated = calculate_ident(data(res[0][1], origin::database));
-  E(calculated == checksum, origin::database,
+  MONOTONE_ERROR(calculated == checksum, origin::database,
     F("roster_delta does not match hash"));
 
   gzip<delta> del_packed(res[0][1], origin::database);
@@ -2092,7 +2092,7 @@ database_impl::get_version(id const & id
   appl->finish(tmp);
   dat = data(tmp, origin::database);
 
-  E(calculate_ident(dat) == ident, origin::database,
+  MONOTONE_ERROR(calculate_ident(dat) == ident, origin::database,
     F("delta-reconstructed '%s' item does not match hash")
     % data_table);
 
@@ -2818,7 +2818,7 @@ database::get_revision_data(revision_id 
   decode_gzip(gzdata,rdat);
 
   // verify that we got a revision with the right id
-  E(id == calculate_ident(revision_data(rdat)), origin::database,
+  MONOTONE_ERROR(id == calculate_ident(revision_data(rdat)), origin::database,
     F("revision does not match hash"));
 
   return revision_data(rdat);
@@ -3095,7 +3095,7 @@ database::put_roster_for_revision(revisi
   shared_ptr<marking_map> mm_writeable = make_shared<marking_map>();
   MM(*mm_writeable);
   make_roster_for_revision(*this, rev, new_id, *ros_writeable, *mm_writeable);
-  E(rev.new_manifest == calculate_ident(*ros_writeable, false),
+  MONOTONE_ERROR(rev.new_manifest == calculate_ident(*ros_writeable, false),
     rev.made_from,
     F("revision contains incorrect manifest_id"));
   // const'ify the objects, suitable for caching etc.
@@ -3434,7 +3434,7 @@ database::check_signature(key_id const &
       shared_ptr<RSA_PublicKey> pub_key
         = std::dynamic_pointer_cast<RSA_PublicKey>(x509_key);
 
-      E(pub_key, id.inner().made_from,
+      MONOTONE_ERROR(pub_key, id.inner().made_from,
         F("failed to get RSA verifying key for %s") % id);
 
 #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,10,0)
@@ -3574,7 +3574,7 @@ database_impl::oldstyle_results_to_certs
         else if (key_res.size() == 1)
           k_id = key_id(key_res[0][0], origin::database);
         else
-          E(false, origin::database,
+          MONOTONE_ERROR(false, origin::database,
             F("your database contains multiple keys named '%s'") % k_name);
       }
 
@@ -4170,7 +4170,7 @@ database_impl::add_prefix_matching_const
     {
       for (string::const_iterator i = prefix.begin(); i != prefix.end(); ++i)
        {
-         E(is_xdigit(*i), origin::user,
+         MONOTONE_ERROR(is_xdigit(*i), origin::user,
            F("bad character '%c' in id name '%s'") % *i % prefix);
        }
 
@@ -4744,7 +4744,7 @@ database_impl::check_filename()
 void
 database_impl::check_filename()
 {
-  E(!filename.empty(), origin::user, F("no database specified"));
+  MONOTONE_ERROR(!filename.empty(), origin::user, F("no database specified"));
 }
 
 
@@ -4757,21 +4757,21 @@ database_impl::check_db_exists()
       return;
 
     case path::nonexistent:
-      E(false, origin::user, F("database '%s' does not exist") % filename);
+      MONOTONE_ERROR(false, origin::user, F("database '%s' does not exist") % filename);
 
     case path::directory:
       if (directory_is_workspace(filename))
         {
           options opts = workspace::get_options(filename);
-          E(opts.dbname.as_internal().empty(), origin::user,
+          MONOTONE_ERROR(opts.dbname.as_internal().empty(), origin::user,
             F("'%s' is a workspace, not a database\n"
               "(did you mean '%s'?)") % filename % opts.dbname);
         }
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("'%s' is a directory, not a database") % filename);
 
     case path::special:
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("cannot handle special file '%s'") % filename);
     }
 }
@@ -4888,7 +4888,7 @@ database_path_helper::get_database_path(
           L(FL("no database option given or options empty"));
           return;
         }
-      E(false, origin::user, F("no database specified"));
+      MONOTONE_ERROR(false, origin::user, F("no database specified"));
     }
 
   if (opts.dbname_type == unmanaged_db)
@@ -4910,7 +4910,7 @@ database_path_helper::get_database_path(
   vector<system_path> candidates;
   vector<system_path> search_paths;
 
-  E(lua.hook_get_default_database_locations(search_paths) && search_paths.size() > 0,
+  MONOTONE_ERROR(lua.hook_get_default_database_locations(search_paths) && search_paths.size() > 0,
     origin::user, F("no default database location configured"));
 
   for (vector<system_path>::const_iterator i = search_paths.begin();
@@ -4953,7 +4953,7 @@ database_path_helper::get_database_path(
            i != candidates.end(); ++i)
         err += ("\n  " + (*i).as_internal());
 
-      E(false, origin::user, i18n_format(err));
+      MONOTONE_ERROR(false, origin::user, i18n_format(err));
     }
 }
 
@@ -4968,7 +4968,7 @@ database_path_helper::maybe_set_default_
     }
 
   string alias;
-  E(lua.hook_get_default_database_alias(alias) && !alias.empty(),
+  MONOTONE_ERROR(lua.hook_get_default_database_alias(alias) && !alias.empty(),
     origin::user, F("could not query default database alias"));
 
   P(F("using default database '%s'") % alias);
@@ -4980,15 +4980,15 @@ database_path_helper::validate_and_clean
 void
 database_path_helper::validate_and_clean_alias(string const & alias, path_component & pc)
 {
-  E(alias.find(':') == 0, origin::system,
+  MONOTONE_ERROR(alias.find(':') == 0, origin::system,
     F("invalid database alias '%s': does not start with a colon") % alias);
 
   string pure_alias = alias.substr(1);
-  E(pure_alias.size() > 0, origin::system,
+  MONOTONE_ERROR(pure_alias.size() > 0, origin::system,
     F("invalid database alias '%s': must not be empty") % alias);
 
   globish matcher;
-  E(lua.hook_get_default_database_glob(matcher),
+  MONOTONE_ERROR(lua.hook_get_default_database_glob(matcher),
     origin::user, F("could not query default database glob"));
 
   if (!matcher.matches(pure_alias))
@@ -5000,7 +5000,7 @@ database_path_helper::validate_and_clean
     }
   catch (...)
     {
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("invalid database alias '%s': does contain invalid characters") % alias);
     }
 }
============================================================
--- src/database_check.cc	9d48083f29ab0431111e7368276625f73138bd50
+++ src/database_check.cc	fb53f6f40f416b4c51335d7a540c5e53d80e4dfd
@@ -150,7 +150,7 @@ check_db_integrity_check(database & db)
 check_db_integrity_check(database & db)
 {
     L(FL("asking sqlite to check db integrity"));
-    E(db.check_integrity(), origin::database,
+    MONOTONE_ERROR(db.check_integrity(), origin::database,
       F("file structure is corrupted; cannot check further"));
 }
 
@@ -212,7 +212,7 @@ check_rosters_manifest(database & db,
           db.get_roster_and_markings(*i, ros, mm);
         }
       // When attempting to fetch a roster with no corresponding revision,
-      // we fail with E(), not I() (when it tries to look up the manifest_id
+      // we fail with MONOTONE_ERROR(), not I() (when it tries to look up the manifest_id
       // to check).  std::exception catches both informative_failure's and
       // logic_error's.
       catch (std::exception & e)
@@ -1183,7 +1183,7 @@ check_db(database & db)
     {
       // should be origin::database, but that gives the "almost certainly a bug"
       // message, which we don't want.
-      E(false, origin::no_fault, F("serious problems detected"));
+      MONOTONE_ERROR(false, origin::no_fault, F("serious problems detected"));
     }
   else if (total)
     P(F("minor problems detected"));
============================================================
--- src/dates.cc	9641439095909a8fbe8ee1a9456427929a1ebeca
+++ src/dates.cc	828dc1c7498f8dea8d9458e4e6cef00fedaa1906
@@ -345,7 +345,7 @@ date_t::now()
 {
   time_t t = std::time(0);
   s64 tu = MILLISEC(t) + get_epoch_offset();
-  E(valid_ms_count(tu), origin::system,
+  MONOTONE_ERROR(valid_ms_count(tu), origin::system,
     F("current date '%s' is outside usable range\n"
       "(your system clock may not be set correctly)")
     % std::ctime(&t));
@@ -390,11 +390,11 @@ date_t::as_formatted_localtime(string co
 
   L(FL("%s seconds UTC since unix epoch") % seconds);
 
-  E(seconds >= numeric_limits<time_t>::min(), origin::user,
+  MONOTONE_ERROR(seconds >= numeric_limits<time_t>::min(), origin::user,
     F("date '%s' is out of range and cannot be formatted")
     % as_iso_8601_extended());
 
-  E(seconds <= numeric_limits<time_t>::max(), origin::user,
+  MONOTONE_ERROR(seconds <= numeric_limits<time_t>::max(), origin::user,
     F("date '%s' is out of range and cannot be formatted")
     % as_iso_8601_extended());
 
@@ -402,7 +402,7 @@ date_t::as_formatted_localtime(string co
   // boundary. To simplify things, we generally enforce a lower limit of
   // year 1902 if the system can only handle 32-bit dates.
   if (sizeof(time_t) <= 4 || STD_MKTIME_64BIT_WORKS == 0)
-    E(seconds >= -2145916800, origin::user,
+    MONOTONE_ERROR(seconds >= -2145916800, origin::user,
       F("date '%s' is out of range and cannot be formatted")
       % as_iso_8601_extended());
 
@@ -445,7 +445,7 @@ date_t::as_formatted_localtime(string co
       return string();
     }
 
-  E(false, origin::user,
+  MONOTONE_ERROR(false, origin::user,
     F("date '%s' is too long when formatted using '%s'"
       " (the result must fit in %d characters)")
     % (sizeof buf - 1));
@@ -482,7 +482,7 @@ date_t::from_formatted_localtime(string 
   // We generally enforce a lower limit of year 1902 if the system can only
   // handle 32-bit dates.
   if (sizeof(time_t) <= 4 || STD_MKTIME_64BIT_WORKS == 0)
-    E(tb.tm_year > 1, origin::user,
+    MONOTONE_ERROR(tb.tm_year > 1, origin::user,
       F("date '%s' is out of range and cannot be parsed")
       % s);
 
@@ -504,7 +504,7 @@ date_t::from_formatted_localtime(string 
 
   tm check(*localtime(&t)); // back to local timezone values
 
-  E(tb.tm_sec   == check.tm_sec &&
+  MONOTONE_ERROR(tb.tm_sec   == check.tm_sec &&
     tb.tm_min   == check.tm_min &&
     tb.tm_hour  == check.tm_hour &&
     tb.tm_mday  == check.tm_mday &&
@@ -563,7 +563,7 @@ date_t::date_t(string const & s)
           if (mid == string::npos)
             {
               mid = s.rfind(' ');
-              E(mid != string::npos, origin::user, parse_err_msg);
+              MONOTONE_ERROR(mid != string::npos, origin::user, parse_err_msg);
             }
 
           // Discount matches before the space or 'T' separator.
@@ -578,18 +578,18 @@ date_t::date_t(string const & s)
       else
         {
           if (s.at(tz_start) == 'Z')
-            E(tz_start == s.size() - 1, origin::user, parse_err_msg);
+            MONOTONE_ERROR(tz_start == s.size() - 1, origin::user, parse_err_msg);
           else
             {
               i = s.size() - 1;
 
-              E(s.at(i) >= '0' && s.at(i) <= '9'
+              MONOTONE_ERROR(s.at(i) >= '0' && s.at(i) <= '9'
                 && s.at(i-1) >= '0' && s.at(i-1) <= '9', origin::user,
                 parse_err_msg);
 
               u8 last_part = (s.at(i-1) - '0') * 10 + (s.at(i) - '0');
               i -= 2;
-              E(i >= tz_start, origin::user, parse_err_msg);
+              MONOTONE_ERROR(i >= tz_start, origin::user, parse_err_msg);
               if (i == tz_start)
                 // Only an hour offset was given. Multiply accordingly.
                 timezone_offset = last_part * HOUR;
@@ -600,7 +600,7 @@ date_t::date_t(string const & s)
                     i--;
 
                   // Minutes parsed, now read hours of time zone offset.
-                  E(s.at(i) >= '0' && s.at(i) <= '9'
+                  MONOTONE_ERROR(s.at(i) >= '0' && s.at(i) <= '9'
                     && s.at(i-1) >= '0' && s.at(i-1) <= '9', origin::user,
                     parse_err_msg);
                   u8 tz_hours = (s.at(i-1) - '0') * 10 + (s.at(i) - '0');
@@ -611,7 +611,7 @@ date_t::date_t(string const & s)
               if (s.at(i) == '-')
                 timezone_offset = -timezone_offset;
               else
-                E(s.at(i) == '+', origin::user, parse_err_msg);
+                MONOTONE_ERROR(s.at(i) == '+', origin::user, parse_err_msg);
             }
         }
 
@@ -631,12 +631,12 @@ date_t::date_t(string const & s)
 
       // seconds
       u8 sec;
-      E(s.at(i) >= '0' && s.at(i) <= '9'
+      MONOTONE_ERROR(s.at(i) >= '0' && s.at(i) <= '9'
         && s.at(i-1) >= '0' && s.at(i-1) <= '5',
         origin::user, parse_err_msg);
       sec = (s.at(i-1) - '0')*10 + (s.at(i) - '0');
       i -= 2;
-      E(sec <= 60, origin::user,
+      MONOTONE_ERROR(sec <= 60, origin::user,
         F("seconds out of range"));
 
       // optional colon
@@ -645,12 +645,12 @@ date_t::date_t(string const & s)
 
       // minutes
       u8 min;
-      E(s.at(i) >= '0' && s.at(i) <= '9'
+      MONOTONE_ERROR(s.at(i) >= '0' && s.at(i) <= '9'
         && s.at(i-1) >= '0' && s.at(i-1) <= '5',
         origin::user, parse_err_msg);
       min = (s.at(i-1) - '0')*10 + (s.at(i) - '0');
       i -= 2;
-      E(min < 60, origin::user,
+      MONOTONE_ERROR(min < 60, origin::user,
         F("minutes out of range"));
 
       // optional colon
@@ -659,22 +659,22 @@ date_t::date_t(string const & s)
 
       // hours
       u8 hour;
-      E((s.at(i-1) >= '0' && s.at(i-1) <= '1'
+      MONOTONE_ERROR((s.at(i-1) >= '0' && s.at(i-1) <= '1'
          && s.at(i) >= '0' && s.at(i) <= '9')
         || (s.at(i-1) == '2' && s.at(i) >= '0' && s.at(i) <= '3'),
         origin::user, parse_err_msg);
       hour = (s.at(i-1) - '0')*10 + (s.at(i) - '0');
       i -= 2;
-      E(hour < 24, origin::user,
+      MONOTONE_ERROR(hour < 24, origin::user,
         F("hour out of range"));
 
       // We accept 'T' as well as spaces between the date and the time
-      E(s.at(i) == 'T' || s.at(i) == ' ', origin::user, parse_err_msg);
+      MONOTONE_ERROR(s.at(i) == 'T' || s.at(i) == ' ', origin::user, parse_err_msg);
       i--;
 
       // day
       u8 day;
-      E(s.at(i-1) >= '0' && s.at(i-1) <= '3'
+      MONOTONE_ERROR(s.at(i-1) >= '0' && s.at(i-1) <= '3'
         && s.at(i) >= '0' && s.at(i) <= '9', origin::user, parse_err_msg);
       day = (s.at(i-1) - '0')*10 + (s.at(i) - '0');
       i -= 2;
@@ -685,10 +685,10 @@ date_t::date_t(string const & s)
 
       // month
       u8 month;
-      E(s.at(i-1) >= '0' && s.at(i-1) <= '1'
+      MONOTONE_ERROR(s.at(i-1) >= '0' && s.at(i-1) <= '1'
         && s.at(i) >= '0' && s.at(i) <= '9', origin::user, parse_err_msg);
       month = (s.at(i-1) - '0')*10 + (s.at(i) - '0');
-      E(month >= 1 && month <= 12, origin::user,
+      MONOTONE_ERROR(month >= 1 && month <= 12, origin::user,
         F("month out of range in '%s'") % s);
       i -= 2;
 
@@ -697,7 +697,7 @@ date_t::date_t(string const & s)
         i--;
 
       // year
-      E(i >= 3, origin::user, parse_err_msg);
+      MONOTONE_ERROR(i >= 3, origin::user, parse_err_msg);
 
       // this counts down through zero and stops when it wraps around
       // (size_t being unsigned)
@@ -705,15 +705,15 @@ date_t::date_t(string const & s)
       u32 digit = 1;
       while (i < s.size())
         {
-          E(s.at(i) >= '0' && s.at(i) <= '9', origin::user, parse_err_msg);
+          MONOTONE_ERROR(s.at(i) >= '0' && s.at(i) <= '9', origin::user, parse_err_msg);
           year += (s.at(i) - '0')*digit;
           i--;
           digit *= 10;
         }
 
-      E(year >= 1, origin::user,
+      MONOTONE_ERROR(year >= 1, origin::user,
         F("date too early (monotone only goes back to 0001-01-01T00:00:00)"));
-      E(year <= 292278994, origin::user,
+      MONOTONE_ERROR(year <= 292278994, origin::user,
         F("date too late (monotone only goes forward to year 292,278,993)"));
 
       u8 mdays;
@@ -722,7 +722,7 @@ date_t::date_t(string const & s)
       else
         mdays = DAYS_PER_MONTH[month-1];
 
-      E(day >= 1 && day <= mdays, origin::user,
+      MONOTONE_ERROR(day >= 1 && day <= mdays, origin::user,
         F("day out of range for its month in '%s'") % s);
 
       broken_down_time t;
@@ -739,7 +739,7 @@ date_t::date_t(string const & s)
     }
   catch (std::out_of_range)
     {
-      E(false, origin::user, parse_err_msg);
+      MONOTONE_ERROR(false, origin::user, parse_err_msg);
     }
 }
 
============================================================
--- src/file_io.cc	957aebe4616af705852f92ac18fbc419ae7334e4
+++ src/file_io.cc	df8ad78a5ee3ea172f70502798bd0c5dc6ca409b
@@ -57,7 +57,7 @@ require_path_is_nonexistent(any_path con
 require_path_is_nonexistent(any_path const & path,
                             i18n_format const & message)
 {
-  E(!path_exists(path), origin::user, message);
+  MONOTONE_ERROR(!path_exists(path), origin::user, message);
 }
 
 void
@@ -69,13 +69,13 @@ require_path_is_file(any_path const & pa
   switch (get_path_status(path))
     {
     case path::nonexistent:
-      E(false, origin::user, message_if_nonexistent);
+      MONOTONE_ERROR(false, origin::user, message_if_nonexistent);
     case path::file:
       return;
     case path::directory:
-      E(false, origin::user, message_if_directory);
+      MONOTONE_ERROR(false, origin::user, message_if_directory);
     case path::special:
-      E(false, origin::user, message_if_special);
+      MONOTONE_ERROR(false, origin::user, message_if_special);
     }
 }
 
@@ -88,11 +88,11 @@ require_path_is_directory(any_path const
   switch (get_path_status(path))
     {
     case path::nonexistent:
-      E(false, origin::user, message_if_nonexistent);
+      MONOTONE_ERROR(false, origin::user, message_if_nonexistent);
     case path::file:
-      E(false, origin::user, message_if_file);
+      MONOTONE_ERROR(false, origin::user, message_if_file);
     case path::special:
-      E(false, origin::user, message_if_special);
+      MONOTONE_ERROR(false, origin::user, message_if_special);
     case path::directory:
       return;
     }
@@ -183,10 +183,10 @@ mkdir_p(any_path const & p)
     case path::directory:
       return;
     case path::file:
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("could not create directory '%s': it is a file") % p);
     case path::special:
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("could not create directory '%s': it is a special file") % p);
     case path::nonexistent:
       std::string const current = p.as_external();
@@ -228,7 +228,7 @@ delete_file_or_dir_shallow(any_path cons
 void
 delete_file_or_dir_shallow(any_path const & p)
 {
-  E(path_exists(p), origin::user,
+  MONOTONE_ERROR(path_exists(p), origin::user,
     F("object to delete, '%s', does not exist") % p);
   do_remove(p.as_external());
 }
@@ -277,7 +277,7 @@ move_path(any_path const & old_path,
 move_path(any_path const & old_path,
           any_path const & new_path)
 {
-  E(path_exists(old_path), origin::user,
+  MONOTONE_ERROR(path_exists(old_path), origin::user,
     F("rename source path '%s' does not exist") % old_path);
   require_path_is_nonexistent(new_path,
                               F("rename target '%s' already exists")
@@ -296,7 +296,7 @@ read_data(any_path const & p)
 
   ifstream file(p.as_external().c_str(),
                 ios_base::in | ios_base::binary);
-  E(file, origin::user, F("cannot open file '%s' for reading") % p);
+  MONOTONE_ERROR(file, origin::user, F("cannot open file '%s' for reading") % p);
   unfiltered_pipe->start_msg();
   file >> *unfiltered_pipe;
   unfiltered_pipe->end_msg();
@@ -312,7 +312,7 @@ read_data_stdin()
 read_data_stdin()
 {
   static bool have_consumed_stdin = false;
-  E(!have_consumed_stdin, origin::user,
+  MONOTONE_ERROR(!have_consumed_stdin, origin::user,
     F("cannot read standard input multiple times"));
   have_consumed_stdin = true;
   unfiltered_pipe->start_msg();
@@ -343,7 +343,7 @@ write_data_impl(any_path const & p,
                 any_path const & tmp,
                 bool user_private)
 {
-  E(!directory_exists(p), origin::user,
+  MONOTONE_ERROR(!directory_exists(p), origin::user,
     F("file '%s' cannot be overwritten as data; it is a directory") % p);
 
   make_dir_for(p);
@@ -438,7 +438,7 @@ walk_tree(file_path const & path, tree_w
   switch (get_path_status(path))
     {
     case path::nonexistent:
-      E(false, origin::user, F("no such file or directory: '%s'") % path);
+      MONOTONE_ERROR(false, origin::user, F("no such file or directory: '%s'") % path);
       break;
     case path::file:
       walker.visit_file(path);
============================================================
--- src/file_io.hh	7eb18c4cc3c1256bc48b85ee183770432ff25bab
+++ src/file_io.hh	168e0fc92d840714cb3ed8dbf1ce9207d64838dc
@@ -28,7 +28,7 @@ void assert_path_is_directory(any_path c
 void assert_path_is_file(any_path const & path);
 void assert_path_is_directory(any_path const & path);
 
-// use E()
+// use MONOTONE_ERROR()
 void require_path_is_nonexistent(any_path const & path,
                                  i18n_format const & message);
 void require_path_is_file(any_path const & path,
============================================================
--- src/git_export.cc	ffae5a4230a3582454eb46057dbeb0a44e08cf17
+++ src/git_export.cc	c7e484e62c69b927ab0dc9ba9a36b91af9297a52
@@ -86,7 +86,7 @@ validate_author_mappings(lua_hooks & lua
   for (map<string, string>::const_iterator i = authors.begin(); 
        i != authors.end(); ++i)
     {
-      E(lua.hook_validate_git_author(i->second), origin::user,
+      MONOTONE_ERROR(lua.hook_validate_git_author(i->second), origin::user,
         F("invalid git author '%s' mapped from monotone author '%s'")
         % i->second % i->first);
     }
@@ -106,17 +106,17 @@ import_marks(system_path const & marks_f
       string tmp;
 
       marks.get(c);
-      E(c == ':', origin::user, F("missing leading ':' in marks file"));
+      MONOTONE_ERROR(c == ':', origin::user, F("missing leading ':' in marks file"));
       marks >> mark;
 
       marks.get(c);
-      E(c == ' ', origin::user, F("missing space after mark"));
+      MONOTONE_ERROR(c == ' ', origin::user, F("missing space after mark"));
       marks >> tmp;
-      E(tmp.size() == 40, origin::user, F("bad revision id in marks file"));
+      MONOTONE_ERROR(tmp.size() == 40, origin::user, F("bad revision id in marks file"));
       revision_id revid(decode_hexenc(tmp, origin::user), origin::user);
 
       marks.get(c);
-      E(c == '\n', origin::user, F("incomplete line in marks file"));
+      MONOTONE_ERROR(c == '\n', origin::user, F("incomplete line in marks file"));
 
       marked_revs[revid] = mark;
       if (mark > mark_id) mark_id = mark+1;
@@ -301,7 +301,7 @@ export_changes(database & db, lua_hooks 
         {
           string unmapped_key;
           lua.hook_unmapped_git_author(author_key, unmapped_key);
-          E(lua.hook_validate_git_author(unmapped_key), origin::user,
+          MONOTONE_ERROR(lua.hook_validate_git_author(unmapped_key), origin::user,
             F("invalid git author '%s' from monotone author key '%s'")
             % unmapped_key % author_key);
           valid_authors.insert(make_pair(author_key, unmapped_key));
@@ -318,7 +318,7 @@ export_changes(database & db, lua_hooks 
         {
           string unmapped_name;
           lua.hook_unmapped_git_author(author_name, unmapped_name);
-          E(lua.hook_validate_git_author(unmapped_name), origin::user,
+          MONOTONE_ERROR(lua.hook_validate_git_author(unmapped_name), origin::user,
             F("invalid git author '%s' from monotone author value '%s'")
             % unmapped_name % author_name);
           valid_authors.insert(make_pair(author_name, unmapped_name));
============================================================
--- src/globish.cc	05742d8536befa06b6edfb9a85308e45005375c4
+++ src/globish.cc	aa5c98dceaefa16fae174d106d2e82402efcc996
@@ -51,14 +51,14 @@ compile_charclass(string const & pat, st
   char bra = (char)META_CC_BRA;
 
   p++;
-  E(p != pat.end(), made_from,
+  MONOTONE_ERROR(p != pat.end(), made_from,
     F("invalid pattern '%s': unmatched '['") % pat);
 
   if (*p == '!' || *p == '^')
     {
       bra = (char)META_CC_INV_BRA;
       p++;
-      E(p != pat.end(), made_from,
+      MONOTONE_ERROR(p != pat.end(), made_from,
         F("invalid pattern '%s': unmatched '['") % pat);
     }
 
@@ -84,21 +84,21 @@ compile_charclass(string const & pat, st
 
           // the cast is needed because boost::format will not obey the %x
           // if given a 'char'.
-          E((widen<unsigned int, char>(*p)) >= ' ', made_from,
+          MONOTONE_ERROR((widen<unsigned int, char>(*p)) >= ' ', made_from,
             F("invalid pattern '%s': control character 0x%02x is not allowed")
             % pat % (widen<unsigned int, char>(*p)));
 
           unsigned int start = widen<unsigned int, char>(in_class.end()[-1]);
           unsigned int stop = widen<unsigned int, char>(*p);
 
-          E(start != stop, made_from,
+          MONOTONE_ERROR(start != stop, made_from,
             F("invalid pattern '%s': "
               "one-element character ranges are not allowed") % pat);
-          E(start < stop, made_from,
+          MONOTONE_ERROR(start < stop, made_from,
             F("invalid pattern '%s': "
               "endpoints of a character range must be in "
               "ascending numeric order") % pat);
-          E(start < 0x80 && stop < 0x80, made_from,
+          MONOTONE_ERROR(start < 0x80 && stop < 0x80, made_from,
             F("invalid pattern '%s': cannot use non-ASCII characters "
               "in classes") % pat);
 
@@ -109,15 +109,15 @@ compile_charclass(string const & pat, st
             in_class.push_back((char)r);
         }
       else
-        E(*p != '[', made_from,
+        MONOTONE_ERROR(*p != '[', made_from,
           F("syntax error in '%s': "
             "character classes may not be nested") % pat);
 
-      E((widen<unsigned int, char>(*p)) >= ' ', made_from,
+      MONOTONE_ERROR((widen<unsigned int, char>(*p)) >= ' ', made_from,
         F("invalid pattern '%s': control character 0x%02x is not allowed")
         % pat % (widen<unsigned int, char>(*p)));
 
-      E((widen<unsigned int, char>(*p)) < 0x80, made_from,
+      MONOTONE_ERROR((widen<unsigned int, char>(*p)) < 0x80, made_from,
         F("invalid pattern '%s': cannot use non-ASCII characters in classes")
         % pat);
 
@@ -125,10 +125,10 @@ compile_charclass(string const & pat, st
       p++;
     }
 
-  E(p != pat.end(), made_from,
+  MONOTONE_ERROR(p != pat.end(), made_from,
     F("invalid pattern '%s': unmatched '['") % pat);
 
-  E(!in_class.empty(), made_from,
+  MONOTONE_ERROR(!in_class.empty(), made_from,
     F("invalid pattern '%s': empty character class") % pat);
 
   // minor optimization: one-element non-inverted character class becomes
@@ -157,7 +157,7 @@ compile_frag(string const & pat, back_in
     switch (*p)
       {
       default:
-        E((widen<unsigned int, char>(*p)) >= ' ', made_from,
+        MONOTONE_ERROR((widen<unsigned int, char>(*p)) >= ' ', made_from,
           F("invalid pattern '%s': control character 0x%02x is not allowed")
           % pat % (widen<unsigned int, char>(*p)));
 
@@ -188,10 +188,10 @@ compile_frag(string const & pat, back_in
 
       case '\\':
         p++;
-        E(p != pat.end(), made_from,
+        MONOTONE_ERROR(p != pat.end(), made_from,
           F("invalid pattern '%s': un-escaped \\ at end") % pat);
 
-        E((widen<unsigned int, char>(*p)) >= ' ', made_from,
+        MONOTONE_ERROR((widen<unsigned int, char>(*p)) >= ' ', made_from,
           F("invalid pattern '%s': control character 0x%02x is not allowed")
           % pat % (widen<unsigned int, char>(*p)));
 
@@ -203,7 +203,7 @@ compile_frag(string const & pat, back_in
         break;
 
       case ']':
-        E(false, made_from, F("invalid pattern '%s': unmatched ']'") % pat);
+        MONOTONE_ERROR(false, made_from, F("invalid pattern '%s': unmatched ']'") % pat);
 
       case '{':
         // There's quite a bit of optimization we could be doing on
@@ -211,7 +211,7 @@ compile_frag(string const & pat, back_in
         // nested alternatives; so we're not doing any of it now.
         // (Look at emacs's regexp-opt.el for inspiration.)
         brace_depth++;
-        E(brace_depth < 6, made_from,
+        MONOTONE_ERROR(brace_depth < 6, made_from,
           F("invalid pattern '%s': braces nested too deeply") % pat);
         *to++ = META_ALT_BRA;
         break;
@@ -224,14 +224,14 @@ compile_frag(string const & pat, back_in
         break;
 
       case '}':
-        E(brace_depth > 0, made_from,
+        MONOTONE_ERROR(brace_depth > 0, made_from,
           F("invalid pattern '%s': unmatched '}'") % pat);
         brace_depth--;
         *to++ = META_ALT_KET;
         break;
       }
 
-  E(brace_depth == 0, made_from,
+  MONOTONE_ERROR(brace_depth == 0, made_from,
     F("invalid pattern '%s': unmatched '{'") % pat);
 }
 
============================================================
--- src/key_packet.cc	ee1d82af2b1cc782b422d0b19d5809c2f6b2d2ef
+++ src/key_packet.cc	e9db9c5b6de4aa7a90510c88ff94c0821e83c557
@@ -90,20 +90,20 @@ namespace
     {}
     void validate_base64(string const & s) const
     {
-      E(!s.empty()
+      MONOTONE_ERROR(!s.empty()
         && s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
         made_from,
         F("malformed key_packet: invalid base64 block"));
     }
     void validate_arg_base64(string const & s) const
     {
-      E(s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
+      MONOTONE_ERROR(s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
         made_from,
         F("malformed key_packet: invalid base64 block"));
     }
     void validate_key(string const & k) const
     {
-      E(!k.empty()
+      MONOTONE_ERROR(!k.empty()
         && k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
         made_from,
         F("malformed key_packet: invalid key name"));
@@ -123,7 +123,7 @@ namespace
         }
       catch (Botan::Decoding_Error const & e)
         {
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("malformed key_packet: invalid public key data for '%s': %s")
               % name % e.what());
         }
@@ -143,7 +143,7 @@ namespace
     {
       string next;
       iss >> next;
-      E(next.empty(), made_from,
+      MONOTONE_ERROR(next.empty(), made_from,
         F("malformed key_packet: too many arguments in header"));
     }
 
============================================================
--- src/key_store.cc	e4a85bbc2cb19021f0817aa0969968f9b4509239
+++ src/key_store.cc	0d6680d1ede9e073cd790065cd92e77889ac7928
@@ -84,7 +84,7 @@ struct key_store_state
       non_interactive(app.opts.non_interactive),
       have_read(false), lua(app.lua)
   {
-    E(app.opts.key_dir_given
+    MONOTONE_ERROR(app.opts.key_dir_given
       || app.opts.key_dir != system_path(get_default_keydir(), origin::user)
       || app.opts.conf_dir_given
       || !app.opts.no_default_confdir,
@@ -133,22 +133,22 @@ namespace
     keyreader(key_store_state & kss): kss(kss) {}
     virtual void consume_file_data(file_id const & /* ident */,
                                    file_data const & /* dat */)
-    {E(false, origin::system, F("extraneous data in key store"));}
+    {MONOTONE_ERROR(false, origin::system, F("extraneous data in key store"));}
     virtual void consume_file_delta(file_id const & /* id_old */,
                                     file_id const & /* id_new */,
                                     file_delta const & /* del */)
-    {E(false, origin::system, F("extraneous data in key store"));}
+    {MONOTONE_ERROR(false, origin::system, F("extraneous data in key store"));}
 
     virtual void consume_revision_data(revision_id const & /* ident */,
                                        revision_data const & /* dat */)
-    {E(false, origin::system, F("extraneous data in key store"));}
+    {MONOTONE_ERROR(false, origin::system, F("extraneous data in key store"));}
     virtual void consume_revision_cert(cert const & /* t */)
-    {E(false, origin::system, F("extraneous data in key store"));}
+    {MONOTONE_ERROR(false, origin::system, F("extraneous data in key store"));}
 
 
     virtual void consume_public_key(key_name const & /* ident */,
                                     rsa_pub_key const & /* k */)
-    {E(false, origin::system, F("extraneous data in key store"));}
+    {MONOTONE_ERROR(false, origin::system, F("extraneous data in key store"));}
 
     virtual void consume_key_pair(key_name const & name,
                                   keypair const & kp)
@@ -156,7 +156,7 @@ namespace
       L(FL("reading key pair '%s' from key store") % name);
 
       key_id ident = key_hash_code(name, kp.pub);
-      E(kss.put_key_pair_memory(full_key_info(ident, key_info(name, kp))),
+      MONOTONE_ERROR(kss.put_key_pair_memory(full_key_info(ident, key_info(name, kp))),
         origin::system,
         F("key store has multiple copies of the key with id %s") % ident);
 
@@ -417,25 +417,25 @@ struct key_delete_validator : public pac
   virtual ~key_delete_validator() {}
   virtual void consume_file_data(file_id const & /* ident */,
                                  file_data const & /* dat */)
-  { E(false, origin::system, F("invalid data in key file")); }
+  { MONOTONE_ERROR(false, origin::system, F("invalid data in key file")); }
   virtual void consume_file_delta(file_id const & /* id_old */,
                                   file_id const & /* id_new */,
                                   file_delta const & /* del */)
-  { E(false, origin::system, F("invalid data in key file")); }
+  { MONOTONE_ERROR(false, origin::system, F("invalid data in key file")); }
   virtual void consume_revision_data(revision_id const & /* ident */,
                                      revision_data const & /* dat */)
-  { E(false, origin::system, F("invalid data in key file")); }
+  { MONOTONE_ERROR(false, origin::system, F("invalid data in key file")); }
   virtual void consume_revision_cert(cert const & /* t */)
-  { E(false, origin::system, F("invalid data in key file")); }
+  { MONOTONE_ERROR(false, origin::system, F("invalid data in key file")); }
   virtual void consume_public_key(key_name const & /* ident */,
                                   rsa_pub_key const & /* k */)
-  { E(false, origin::system, F("invalid data in key file")); }
+  { MONOTONE_ERROR(false, origin::system, F("invalid data in key file")); }
   virtual void consume_key_pair(key_name const & name,
                                 keypair const & kp)
   {
      L(FL("reading key pair '%s' from key store for validation") % name);
      key_id ident = key_hash_code(name, kp.pub);
-     E(ident == expected_ident, origin::user,
+     MONOTONE_ERROR(ident == expected_ident, origin::user,
        F("expected key with id %s in key file '%s', got key with id %s")
          % expected_ident % file % ident);
   }
@@ -527,7 +527,7 @@ get_passphrase(utf8 & phrase,
           if (strcmp(pass1, pass2) == 0)
             break;
 
-          E(i++ < 2, origin::user, F("too many failed passphrases"));
+          MONOTONE_ERROR(i++ < 2, origin::user, F("too many failed passphrases"));
           P(F("passphrases do not match, try again"));
         }
 
@@ -556,7 +556,7 @@ key_store_state::decrypt_private_key(key
 
   keypair kp;
   key_name name;
-  E(maybe_get_key_pair(id, name, kp), origin::user,
+  MONOTONE_ERROR(maybe_get_key_pair(id, name, kp), origin::user,
     F("no key pair %s found in key store '%s'") % id % key_dir);
 
   L(FL("%d-byte private key") % kp.priv().size());
@@ -605,7 +605,7 @@ key_store_state::decrypt_private_key(key
             cycles++;
             L(FL("decrypt_private_key: failure %d to load encrypted key: %s")
               % cycles % e.what());
-            E(cycles < 3 && !non_interactive, origin::no_fault,
+            MONOTONE_ERROR(cycles < 3 && !non_interactive, origin::no_fault,
               F("failed to decrypt old private RSA key, probably incorrect "
                 "passphrase or missing 'get_passphrase' lua hook"));
 
@@ -618,7 +618,7 @@ key_store_state::decrypt_private_key(key
 
   shared_ptr<RSA_PrivateKey> priv_key;
   priv_key = dynamic_pointer_cast<RSA_PrivateKey>(pkcs8_key);
-  E(priv_key, origin::no_fault,
+  MONOTONE_ERROR(priv_key, origin::no_fault,
     F("failed to extract RSA private key from PKCS#8 keypair"));
 
   // Cache the decrypted key if we're allowed.
@@ -659,7 +659,7 @@ key_store::create_key_pair(database & db
       if (i->second.first == ident)
         exists = true;
     }
-  E(!exists, origin::user, F("key '%s' already exists") % ident);
+  MONOTONE_ERROR(!exists, origin::user, F("key '%s' already exists") % ident);
 
   utf8 prompted_passphrase;
   if (!maybe_passphrase)
@@ -771,7 +771,7 @@ key_store::change_key_passphrase(key_id 
   {
     s->maybe_read_key_dir();
     key_map::const_iterator i = s->keys.find(id);
-    E(i != s->keys.end(), origin::user,
+    MONOTONE_ERROR(i != s->keys.end(), origin::user,
       F("no key pair '%s' found in key store '%s'") % id % s->key_dir);
     name = i->second.first;
     kp = i->second.second;
@@ -853,7 +853,7 @@ key_store::decrypt_rsa(key_id const & id
   catch (Botan::Exception & e)
 #endif
     {
-      E(false, ciphertext.made_from,
+      MONOTONE_ERROR(false, ciphertext.made_from,
         F("Botan error decrypting data: '%s'") % e.what());
     }
 }
@@ -876,7 +876,7 @@ key_store::make_signature(database & db,
   ssh_agent & agent = s->get_agent();
 
   //sign with ssh-agent (if connected)
-  E(agent.connected() || s->ssh_sign_mode != "only", origin::user,
+  MONOTONE_ERROR(agent.connected() || s->ssh_sign_mode != "only", origin::user,
     F("you have chosen to sign only with ssh-agent but ssh-agent"
       " does not seem to be running"));
   if (s->ssh_sign_mode == "yes"
@@ -911,7 +911,7 @@ key_store::make_signature(database & db,
 
   string ssh_sig = sig_string;
 
-  E(ssh_sig.length() > 0 || s->ssh_sign_mode != "only", origin::user,
+  MONOTONE_ERROR(ssh_sig.length() > 0 || s->ssh_sign_mode != "only", origin::user,
     F("you don't seem to have your monotone key imported "));
 
   if (ssh_sig.length() <= 0
@@ -979,7 +979,7 @@ key_store::make_signature(database & db,
 
   if (s->ssh_sign_mode == "check" && ssh_sig.length() > 0)
     {
-      E(ssh_sig == sig_string, origin::system,
+      MONOTONE_ERROR(ssh_sig == sig_string, origin::system,
         F("make_signature: ssh signature (%i) != monotone signature (%i)\n"
           "ssh signature     : %s\n"
           "monotone signature: %s")
@@ -996,7 +996,7 @@ key_store::make_signature(database & db,
 
   cert_status s = db.check_signature(id, tosign, signature);
   I(s != cert_unknown);
-  E(s == cert_ok, origin::system, F("make_signature: signature is not valid"));
+  MONOTONE_ERROR(s == cert_ok, origin::system, F("make_signature: signature is not valid"));
 }
 
 //
@@ -1007,7 +1007,7 @@ key_store::add_key_to_agent(key_id const
 key_store::add_key_to_agent(key_id const & id)
 {
   ssh_agent & agent = s->get_agent();
-  E(agent.connected(), origin::user,
+  MONOTONE_ERROR(agent.connected(), origin::user,
     F("no ssh-agent is available, cannot add key %s") % id);
 
   shared_ptr<RSA_PrivateKey> priv = s->decrypt_private_key(id);
@@ -1120,7 +1120,7 @@ key_store_state::migrate_old_key_pair
         L(FL("migrate_old_key_pair: failure %d to load old private key: %s")
           % cycles % e.what());
 
-        E(cycles <= 3, origin::no_fault,
+        MONOTONE_ERROR(cycles <= 3, origin::no_fault,
           F("failed to decrypt old private RSA key, "
             "probably incorrect passphrase"));
 
============================================================
--- src/keys.cc	1af4995cc9311c4d609b6c087b9296675ce3d82d
+++ src/keys.cc	a3268f589832c29c92a3ffdb81bbe288ce5f7d60
@@ -39,7 +39,7 @@ load_key_pair(key_store & keys, key_id c
 void
 load_key_pair(key_store & keys, key_id const & id)
 {
-  E(keys.key_pair_exists(id), origin::user,
+  MONOTONE_ERROR(keys.key_pair_exists(id), origin::user,
     F("no key pair %s found in key store '%s'")
     % id % keys.get_key_dir());
 }
@@ -83,7 +83,7 @@ namespace {
           {
             rsa_pub_key pub_key;
             db.get_key(chosen_key, pub_key);
-            E(keys_match(name, pub_key, name, priv_key.pub),
+            MONOTONE_ERROR(keys_match(name, pub_key, name, priv_key.pub),
               origin::no_fault,
               F("the key %s stored in your database does\n"
                 "not match the version in your local key store!")
@@ -98,10 +98,10 @@ namespace {
   {
     vector<key_id> all_privkeys;
     keys.get_key_ids(all_privkeys);
-    E(key_requiredness == key_optional || !all_privkeys.empty(), origin::user,
+    MONOTONE_ERROR(key_requiredness == key_optional || !all_privkeys.empty(), origin::user,
       F("you have no private key to make signatures with.\n"
         "Perhaps you need to 'genkey <your email>'"));
-    E(key_requiredness == key_optional || all_privkeys.size() < 2, origin::user,
+    MONOTONE_ERROR(key_requiredness == key_optional || all_privkeys.size() < 2, origin::user,
       F("you have multiple private keys.\n"
         "Pick one to use for signatures by adding "
         "'-k<keyname>' to your command"));
@@ -140,7 +140,7 @@ get_user_key(options const & opts, lua_h
         }
       else
         {
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("a key is required for this operation, but the '--key' option "
               "was given with an empty argument"));
         }
============================================================
--- src/lua.cc	3d0789badf13ac3d28e5672906d689b5f00355b6
+++ src/lua.cc	e8f72fd1fcb624ab07530201231676e9b8190ad6
@@ -507,7 +507,7 @@ LUAEXT(include, )
 LUAEXT(include, )
 {
   const char *path = luaL_checkstring(LS, -1);
-  E(path, origin::user,
+  MONOTONE_ERROR(path, origin::user,
     F("%s called with an invalid parameter") % "Include");
 
   bool res = run_file(LS, path);
@@ -519,7 +519,7 @@ LUAEXT(includedir, )
 LUAEXT(includedir, )
 {
   const char *pathstr = luaL_checkstring(LS, -1);
-  E(pathstr, origin::user,
+  MONOTONE_ERROR(pathstr, origin::user,
     F("%s called with an invalid parameter") % "IncludeDir");
 
   run_directory(LS, pathstr, "*");
@@ -531,7 +531,7 @@ LUAEXT(includedirpattern, )
 {
   const char *pathstr = luaL_checkstring(LS, -2);
   const char *pattern = luaL_checkstring(LS, -1);
-  E(pathstr && pattern, origin::user,
+  MONOTONE_ERROR(pathstr && pattern, origin::user,
     F("%s called with an invalid parameter") % "IncludeDirPattern");
 
   run_directory(LS, pathstr, pattern);
@@ -615,10 +615,10 @@ run_directory(lua_State * st, char const
   switch (get_path_status(path))
     {
     case path::nonexistent:
-      E(false, origin::user, F("directory '%s' does not exist") % pathstr);
+      MONOTONE_ERROR(false, origin::user, F("directory '%s' does not exist") % pathstr);
     case path::file:
     case path::special:
-      E(false, origin::user, F("'%s' is not a directory") % pathstr);
+      MONOTONE_ERROR(false, origin::user, F("'%s' is not a directory") % pathstr);
     case path::directory:
       break;
     }
@@ -640,7 +640,7 @@ run_directory(lua_State * st, char const
         .loadfile(i->c_str())
         .call(0,1)
         .ok();
-      E(res, origin::user, F("lua error while loading rcfile '%s'") % *i);
+      MONOTONE_ERROR(res, origin::user, F("lua error while loading rcfile '%s'") % *i);
       L(FL("'%s' is ok") % *i);
     }
 }
============================================================
--- src/lua_hooks.cc	b37cb78102f923e8a71cc9c7240d148365c6c8a3
+++ src/lua_hooks.cc	113137cd5df903dd3b761e54f5c85e8106aa4e51
@@ -211,7 +211,7 @@ lua_hooks::load_rcfile(utf8 const & rc)
     {
       L(FL("opening rcfile '%s'") % rc);
       data dat = read_data_for_command_line(rc);
-      E(run_string(st, dat().c_str(), rc().c_str()), origin::user,
+      MONOTONE_ERROR(run_string(st, dat().c_str(), rc().c_str()), origin::user,
         F("lua error while loading rcfile '%s'") % rc);
       L(FL("'%s' is ok") % rc);
     }
@@ -240,13 +240,13 @@ lua_hooks::load_rcfile(any_path const & 
   if (exists)
     {
       L(FL("opening rcfile '%s'") % rc);
-      E(run_file(st, rc.as_external().c_str()), origin::user,
+      MONOTONE_ERROR(run_file(st, rc.as_external().c_str()), origin::user,
         F("lua error while loading '%s'") % rc);
       L(FL("'%s' is ok") % rc);
     }
   else
     {
-      E(!required, origin::user, F("rcfile '%s' does not exist") % rc);
+      MONOTONE_ERROR(!required, origin::user, F("rcfile '%s' does not exist") % rc);
       L(FL("skipping nonexistent rcfile '%s'") % rc);
     }
 }
============================================================
--- src/luaext_parse_basic_io.cc	f7a89950b6355b57d24ccf12331c7e2beae686bd
+++ src/luaext_parse_basic_io.cc	9b52b20d8bc3b47c1a12c97aa13406d131d9b6ef
@@ -45,7 +45,7 @@ LUAEXT(parse_basic_io, )
               break;
             case basic_io::TOK_STRING:
             case basic_io::TOK_HEX:
-              E(!res.empty(), origin::user, F("bad input to parse_basic_io"));
+              MONOTONE_ERROR(!res.empty(), origin::user, F("bad input to parse_basic_io"));
               res.back().second.push_back(got);
               break;
             default:
============================================================
--- src/merge_conflict.cc	1223ab20cb8b2718dc9fe2ec1203d162e1f52c68
+++ src/merge_conflict.cc	6b44d626d3afeba6f1d70639ed438efc82340b65
@@ -1888,7 +1888,7 @@ read_orphaned_node_conflict(basic_io::pa
           pars.str();
         }
       else
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F(conflict_resolution_not_supported_msg) % pars.token % "orphaned_node");
     }
 
@@ -1934,9 +1934,9 @@ validate_orphaned_node_conflicts(basic_i
           read_orphaned_node_conflict(pars, file_conflict, left_roster, right_roster);
         }
       else
-        E(false, origin::user, F("expected orphaned_directory or orphaned_file, found %s") % pars.token);
+        MONOTONE_ERROR(false, origin::user, F("expected orphaned_directory or orphaned_file, found %s") % pars.token);
 
-      E(merge_conflict.nid == file_conflict.nid, origin::user,
+      MONOTONE_ERROR(merge_conflict.nid == file_conflict.nid, origin::user,
         F(conflicts_mismatch_msg));
 
       merge_conflict.resolution = file_conflict.resolution;
@@ -1946,7 +1946,7 @@ validate_orphaned_node_conflicts(basic_i
       else
         {
           std::vector<orphaned_node_conflict>::iterator tmp = i;
-          E(++tmp == conflicts.end(), origin::user,
+          MONOTONE_ERROR(++tmp == conflicts.end(), origin::user,
             F("conflicts file does not match current conflicts"));
         }
     }
@@ -2096,14 +2096,14 @@ read_dropped_modified_conflict(basic_io:
         }
       else if (pars.symp (syms::resolved_keep_left))
         {
-          E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+          MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
           conflict.left_resolution.resolution = resolve_conflicts::keep;
           pars.sym();
         }
       else if (pars.symp (syms::resolved_keep_right))
         {
-          E(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
+          MONOTONE_ERROR(!conflict.orphaned, origin::user, F("orphaned files must be renamed"));
 
           conflict.right_resolution.resolution = resolve_conflicts::keep;
           pars.sym();
@@ -2149,7 +2149,7 @@ read_dropped_modified_conflict(basic_io:
           pars.str();
         }
       else
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F(conflict_resolution_not_supported_msg) % pars.token % "dropped_modified");
     }
 } // read_dropped_modified_conflict
@@ -2197,7 +2197,7 @@ validate_dropped_modified_conflicts(basi
       read_dropped_modified_conflict(pars, file_conflict, left_rid, left_roster, right_rid, right_roster);
 
       // Note that we do not confirm the file ids.
-      E(merge_conflict.dropped_side == file_conflict.dropped_side &&
+      MONOTONE_ERROR(merge_conflict.dropped_side == file_conflict.dropped_side &&
         merge_conflict.left_nid == file_conflict.left_nid &&
         merge_conflict.right_nid == file_conflict.right_nid,
         origin::user,
@@ -2213,7 +2213,7 @@ validate_dropped_modified_conflicts(basi
       else
         {
           std::vector<dropped_modified_conflict>::iterator tmp = i;
-          E(++tmp == conflicts.end(), origin::user,
+          MONOTONE_ERROR(++tmp == conflicts.end(), origin::user,
              F(conflicts_mismatch_msg));
         }
     }
@@ -2280,7 +2280,7 @@ read_duplicate_name_conflict(basic_io::p
           pars.str();
         }
       else
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F(conflict_resolution_not_supported_msg) % pars.token % "duplicate_name");
     }
 
@@ -2324,7 +2324,7 @@ validate_duplicate_name_conflicts(basic_
       read_duplicate_name_conflict(pars, file_conflict, left_roster, right_roster);
 
       // Note that we do not confirm the file ids.
-      E(merge_conflict.left_nid == file_conflict.left_nid &&
+      MONOTONE_ERROR(merge_conflict.left_nid == file_conflict.left_nid &&
         merge_conflict.right_nid == file_conflict.right_nid,
         origin::user,
         F(conflicts_mismatch_msg));
@@ -2337,7 +2337,7 @@ validate_duplicate_name_conflicts(basic_
       else
         {
           std::vector<duplicate_name_conflict>::iterator tmp = i;
-          E(++tmp == conflicts.end(), origin::user,
+          MONOTONE_ERROR(++tmp == conflicts.end(), origin::user,
              F(conflicts_mismatch_msg));
         }
     }
@@ -2490,7 +2490,7 @@ read_file_content_conflict(basic_io::par
           pars.str();
         }
       else
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F(conflict_resolution_not_supported_msg) % pars.token % "file_content");
     }
 
@@ -2534,7 +2534,7 @@ validate_file_content_conflicts(basic_io
 
       read_file_content_conflict(pars, file_conflict, left_roster, right_roster);
 
-      E(merge_conflict.nid == file_conflict.nid, origin::user,
+      MONOTONE_ERROR(merge_conflict.nid == file_conflict.nid, origin::user,
         F(conflicts_mismatch_msg));
 
       merge_conflict.resolution = file_conflict.resolution;
@@ -2544,7 +2544,7 @@ validate_file_content_conflicts(basic_io
       else
         {
           std::vector<file_content_conflict>::iterator tmp = i;
-          E(++tmp == conflicts.end(), origin::user,
+          MONOTONE_ERROR(++tmp == conflicts.end(), origin::user,
             F("conflicts file does not match current conflicts"));
         }
     }
@@ -2602,7 +2602,7 @@ read_conflict_file_core(basic_io::parser
       read_file_content_conflicts(pars, result.file_content_conflicts, left_roster, right_roster);
     }
 
-  E(pars.tok.in.lookahead == EOF, pars.tok.in.made_from,
+  MONOTONE_ERROR(pars.tok.in.lookahead == EOF, pars.tok.in.made_from,
     F("extra data in file"));
 } // read_conflict_file_core
 
@@ -2730,13 +2730,13 @@ parse_resolve_conflicts_opts (options co
 
       pars.esym(syms::left);
       pars.hex(temp);
-      E(left_rid == decode_hexenc_as<revision_id>(temp, src.made_from),
+      MONOTONE_ERROR(left_rid == decode_hexenc_as<revision_id>(temp, src.made_from),
         origin::user,
         F("left revision id does not match conflict file"));
 
       pars.esym(syms::right);
       pars.hex(temp);
-      E(right_rid == decode_hexenc_as<revision_id>(temp, src.made_from),
+      MONOTONE_ERROR(right_rid == decode_hexenc_as<revision_id>(temp, src.made_from),
         origin::user,
         F("right revision id does not match conflict file"));
 
@@ -2768,9 +2768,9 @@ attach_node (lua_hooks & lua,
 
   I(!target_path.empty());
 
-  E(!new_roster.has_node(target_path), origin::user,
+  MONOTONE_ERROR(!new_roster.has_node(target_path), origin::user,
     F("'%s' already exists") % target_path.as_external());
-  E(new_roster.has_node(target_path.dirname()), origin::user,
+  MONOTONE_ERROR(new_roster.has_node(target_path.dirname()), origin::user,
     F("directory '%s' does not exist or is unknown") % target_path.dirname());
 
   new_roster.attach_node (nid, target_path);
@@ -2819,7 +2819,7 @@ roster_merge_result::resolve_orphaned_no
         case resolve_conflicts::drop:
           if (is_dir_t(roster.get_node(conflict.nid)))
             {
-              E(downcast_to_dir_t(roster.get_node(conflict.nid))->children.empty(), origin::user,
+              MONOTONE_ERROR(downcast_to_dir_t(roster.get_node(conflict.nid))->children.empty(), origin::user,
                 F("can't drop directory '%s'; it is not empty") % name);
             }
 
@@ -2833,12 +2833,12 @@ roster_merge_result::resolve_orphaned_no
           break;
 
         case resolve_conflicts::none:
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("no resolution provided for orphaned_node '%s'") % name);
           break;
 
         default:
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("invalid resolution for orphaned_node '%s'") % name);
         }
     } // end for
@@ -2927,13 +2927,13 @@ resolve_dropped_modified_one(lua_hooks &
 {
   if (nid == the_null_node)
     {
-      E(resolution.resolution == resolve_conflicts::none, origin::user,
+      MONOTONE_ERROR(resolution.resolution == resolve_conflicts::none, origin::user,
         F("extra %s_resolution provided for dropped_modified '%s'") % side_image % name);
       return;
     }
   else
     {
-      E(resolution.resolution != resolve_conflicts::none, origin::user,
+      MONOTONE_ERROR(resolution.resolution != resolve_conflicts::none, origin::user,
         (other_resolution.resolution == resolve_conflicts::none) ?
         F("no resolution provided for dropped_modified '%s'") % name :
         F("no %s_resolution provided for dropped_modified '%s'") % side_image % name);
@@ -3169,7 +3169,7 @@ resolve_duplicate_name_one_side(lua_hook
     {
     case resolve_conflicts::content_user:
       {
-        E(other_resolution.resolution == resolve_conflicts::drop ||
+        MONOTONE_ERROR(other_resolution.resolution == resolve_conflicts::drop ||
           other_resolution.resolution == resolve_conflicts::rename,
           origin::user,
           F("inconsistent left/right resolutions for '%s'") % name);
@@ -3199,13 +3199,13 @@ resolve_duplicate_name_one_side(lua_hook
       if (is_dir_t(result_roster.get_node(nid)))
         {
           const_dir_t n = downcast_to_dir_t(result_roster.get_node(nid));
-          E(n->children.empty(), origin::user, F("can't drop '%s'; not empty") % name);
+          MONOTONE_ERROR(n->children.empty(), origin::user, F("can't drop '%s'; not empty") % name);
         }
       result_roster.drop_detached_node(nid);
       break;
 
     case resolve_conflicts::keep:
-      E(other_resolution.resolution == resolve_conflicts::drop ||
+      MONOTONE_ERROR(other_resolution.resolution == resolve_conflicts::drop ||
         other_resolution.resolution == resolve_conflicts::rename,
         origin::user,
         F("inconsistent left/right resolutions for '%s'") % name);
@@ -3220,7 +3220,7 @@ resolve_duplicate_name_one_side(lua_hook
       break;
 
     case resolve_conflicts::none:
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("no resolution provided for duplicate_name '%s'") % name);
       break;
 
@@ -3318,7 +3318,7 @@ roster_merge_result::resolve_file_conten
             {
               file_id merged_id;
 
-              E(resolve_conflicts::do_auto_merge(lua, conflict, adaptor, left_roster,
+              MONOTONE_ERROR(resolve_conflicts::do_auto_merge(lua, conflict, adaptor, left_roster,
                                                  right_roster, this->roster, merged_id),
                 origin::user,
                 F("merge of '%s', '%s' failed") % left_name % right_name);
============================================================
--- src/merge_content.cc	25f88a74962c2736d488e55fae3c81cf95e0d440
+++ src/merge_content.cc	8b58285f952c2f8deb8e35ed4a10811fb75e9a0f
@@ -336,7 +336,7 @@ content_merge_workspace_adaptor::get_ver
         F("'%s' in workspace is not a regular file") % i->second);
       tmp = read_data(i->second);
       fid = calculate_ident(file_data(tmp));
-      E(fid == ident, origin::system,
+      MONOTONE_ERROR(fid == ident, origin::system,
         F("file '%s' in workspace has id %s, wanted %s")
         % i->second
         % fid
@@ -731,15 +731,15 @@ resolve_merge_conflicts(lua_hooks & lua,
           // resolutions, give a nice error message.
           char const * const msg = "conflict resolution for %s not yet supported";
 
-          E(!result.missing_root_conflict, origin::user,
+          MONOTONE_ERROR(!result.missing_root_conflict, origin::user,
             F(msg) % "missing_root_dir");
-          E(result.invalid_name_conflicts.size() == 0, origin::user,
+          MONOTONE_ERROR(result.invalid_name_conflicts.size() == 0, origin::user,
             F(msg) % "invalid_name_conflicts");
-          E(result.directory_loop_conflicts.size() == 0, origin::user,
+          MONOTONE_ERROR(result.directory_loop_conflicts.size() == 0, origin::user,
             F(msg) % "directory_loop_conflicts");
-          E(result.multiple_name_conflicts.size() == 0, origin::user,
+          MONOTONE_ERROR(result.multiple_name_conflicts.size() == 0, origin::user,
             F(msg) % "multiple_name_conflicts");
-          E(result.attribute_conflicts.size() == 0, origin::user,
+          MONOTONE_ERROR(result.attribute_conflicts.size() == 0, origin::user,
             F(msg) % "attribute_conflicts");
 
           // Resolve the ones we can, if they have resolutions specified. Each
@@ -795,7 +795,7 @@ resolve_merge_conflicts(lua_hooks & lua,
           // felt this whole design is already too complicated; we are
           // working to find a better solution. See thread at
           // http://lists.gnu.org/archive/html/monotone-devel/2010-04/msg00000.html
-          E(!opts.non_interactive, origin::user,
+          MONOTONE_ERROR(!opts.non_interactive, origin::user,
             F("can't spawn external merger when non-interactive"));
 
           result.report_file_content_conflicts(lua, left_roster, right_roster, adaptor, false, std::cout);
@@ -805,7 +805,7 @@ resolve_merge_conflicts(lua_hooks & lua,
         }
     }
 
-  E(result.is_clean(), origin::user,
+  MONOTONE_ERROR(result.is_clean(), origin::user,
     F("merge failed due to unresolved conflicts"));
 }
 
============================================================
--- src/merge_roster.cc	7146fe6241e5b38357bea093ce92457ad00bdce3
+++ src/merge_roster.cc	c322af5eb9091e9315176900529d50db3e8d753f
@@ -415,7 +415,7 @@ namespace
                       }
                     else
                       {
-                        E(false, origin::user,
+                        MONOTONE_ERROR(false, origin::user,
                           F("unsupported '%s' conflict resolution in mtn:resolve_conflict attribute") %
                           i->second.first);
                       }
============================================================
--- src/migrate_ancestry.cc	b5d5566eb6fc92bf2a9be080b3dc8e2f7ed978ba
+++ src/migrate_ancestry.cc	992b75e2621aad668518e4feeec9078c22a1643b
@@ -483,7 +483,7 @@ insert_parents_into_roster(roster_t & ch
 {
   if (child_roster.has_node(pth))
     {
-      E(is_dir_t(child_roster.get_node(pth)), origin::internal,
+      MONOTONE_ERROR(is_dir_t(child_roster.get_node(pth)), origin::internal,
         F("directory '%s' for path '%s' cannot be added, "
           "as there is a file in the way") % pth % full);
       return;
@@ -504,10 +504,10 @@ insert_into_roster(roster_t & child_rost
   if (child_roster.has_node(pth))
     {
       const_node_t n = child_roster.get_node(pth);
-      E(is_file_t(n), origin::internal,
+      MONOTONE_ERROR(is_file_t(n), origin::internal,
         F("path '%s' cannot be added, as there is a directory in the way") % pth);
       const_file_t f = downcast_to_file_t(n);
-      E(f->content == fid, origin::internal,
+      MONOTONE_ERROR(f->content == fid, origin::internal,
         F("path '%s' added twice with differing content") % pth);
       return;
     }
@@ -794,7 +794,7 @@ anc_graph::construct_revisions_from_ance
                                                     attr_value(k->second,
                                                                origin::internal));
                             else
-                              E(false, origin::no_fault,
+                              MONOTONE_ERROR(false, origin::no_fault,
                                 F("unknown attribute '%s' on path '%s'.\n"
                                   "Please contact %s so we can work out the right way to migrate this\n"
                                   "(if you just want it to go away, see the switch '--drop-attr', but\n"
============================================================
--- src/migrate_schema.cc	ca20562fa4ba8079a4ed29ad5fa760579fec6ae8
+++ src/migrate_schema.cc	52165143ec681ab10abef6096b97c110e3a43d35
@@ -61,7 +61,7 @@ assert_sqlite3_ok(sqlite3 * db)
   // thrown from within an SQL extension function, caught, and turned
   // into a call to sqlite3_result_error.  (Extension functions have to
   // do this to avoid corrupting sqlite's internal state.)  If it is,
-  // rethrow it rather than feeding it to E(), lest we get "error:
+  // rethrow it rather than feeding it to MONOTONE_ERROR(), lest we get "error:
   // sqlite error: error: " ugliness.
   char const *pfx = _("error: ");
   if (!std::strncmp(errmsg, pfx, strlen(pfx)))
@@ -102,7 +102,7 @@ assert_sqlite3_ok(sqlite3 * db)
     }
 
   // if the auxiliary message is empty, the \n will be stripped off too
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("sqlite error: %s\n%s") % errmsg % auxiliary_message);
 }
 
@@ -1155,16 +1155,16 @@ diagnose_unrecognized_schema(schema_mism
 diagnose_unrecognized_schema(schema_mismatch_case cat,
                              system_path const & filename)
 {
-  E(cat != SCHEMA_EMPTY, origin::user,
+  MONOTONE_ERROR(cat != SCHEMA_EMPTY, origin::user,
     F("cannot use the empty sqlite database '%s'\n"
       "(monotone databases must be created with '%s db init')")
     % filename % prog_name);
 
-  E(cat != SCHEMA_NOT_MONOTONE, origin::user,
+  MONOTONE_ERROR(cat != SCHEMA_NOT_MONOTONE, origin::user,
     F("'%s' does not appear to be a monotone database\n")
     % filename);
 
-  E(cat != SCHEMA_TOO_NEW, origin::user,
+  MONOTONE_ERROR(cat != SCHEMA_TOO_NEW, origin::user,
     F("'%s' appears to be a monotone database, but this version of\n"
       "monotone does not recognize its schema.\n"
       "You probably need a newer version of monotone.")
@@ -1183,7 +1183,7 @@ check_sql_schema(sqlite3 * db, system_pa
 
   diagnose_unrecognized_schema(cat, filename);
 
-  E(cat != SCHEMA_MIGRATION_NEEDED, origin::user,
+  MONOTONE_ERROR(cat != SCHEMA_MIGRATION_NEEDED, origin::user,
     F("database '%s' is laid out according to an old schema.\n"
       "Try '%s db migrate' to upgrade\n"
       "(this is irreversible; you may want to make a backup copy first)")
@@ -1331,10 +1331,10 @@ test_migration_step(sqlite3 * db, key_st
     if (schema == m->id)
       break;
 
-  E(m >= migration_events, origin::user,
+  MONOTONE_ERROR(m >= migration_events, origin::user,
     F("cannot test migration from unknown schema %s") % schema);
 
-  E(m->migrator_sql || m->migrator_func, origin::user,
+  MONOTONE_ERROR(m->migrator_sql || m->migrator_func, origin::user,
     F("schema %s is up to date") % schema);
 
   L(FL("testing migration from %s to %s\n in database '%s'")
============================================================
--- src/migrate_work.cc	c74f33296d4cef14d8e318cf3a2f668528db75ed
+++ src/migrate_work.cc	1a36415c27899ad410fe340732a38d9f3fc2ad5c
@@ -64,7 +64,7 @@ get_workspace_format()
       else if (directory_exists(file_path() / old_bookkeeping_root_component))
         format = 0;
       else
-        E(false, origin::user, F("workspace required but not found"));
+        MONOTONE_ERROR(false, origin::user, F("workspace required but not found"));
     }
   else
     {
@@ -75,7 +75,7 @@ get_workspace_format()
         }
       catch (exception & e)
         {
-          E(false, origin::system,
+          MONOTONE_ERROR(false, origin::system,
             F("workspace is corrupt: '%s' is invalid")
             % f_path);
         }
@@ -121,7 +121,7 @@ workspace::check_format()
   unsigned int format = get_workspace_format();
 
   // Don't give user false expectations about format 0.
-  E(format > 0, origin::system,
+  MONOTONE_ERROR(format > 0, origin::system,
     F("this workspace's metadata is in format 0. To use this workspace\n"
       "with this version of monotone, you must delete it and check it\n"
       "out again (migration from format 0 is not possible).\n"
@@ -130,7 +130,7 @@ workspace::check_format()
       "We apologize for the inconvenience.")
     % first_version_supporting_current_format);
 
-  E(format >= current_workspace_format, origin::system,
+  MONOTONE_ERROR(format >= current_workspace_format, origin::system,
     F("to use this workspace with this version of monotone, its metadata\n"
       "must be migrated from format %d to format %d, using the command\n"
       "'%s migrate_workspace'.\n"
@@ -140,7 +140,7 @@ workspace::check_format()
     % first_version_supporting_current_format);
 
   // keep this message in sync with the copy in migrate_format
-  E(format <= current_workspace_format, origin::system,
+  MONOTONE_ERROR(format <= current_workspace_format, origin::system,
     F("this version of monotone only understands workspace metadata\n"
       "in formats 0 through %d.  Your workspace is in format %d.\n"
       "You need a newer version of monotone to use this workspace.")
@@ -169,7 +169,7 @@ migrate_0_to_1()
   // number corresponding to what was cached.  Thus, even if we did convert
   // the workspace, it would still be unusable.
 
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("it is not possible to migrate from workspace format 0 to any\n"
       "later format.  You must delete this workspace and check it out\n"
       "again.  We apologize for the inconvenience."));
@@ -194,7 +194,7 @@ migrate_1_to_2()
     }
   catch (exception & e)
     {
-      E(false, origin::system, F("workspace is corrupt: reading '%s': %s")
+      MONOTONE_ERROR(false, origin::system, F("workspace is corrupt: reading '%s': %s")
         % rev_path % e.what());
     }
   revision_id base_rid(decode_hexenc_as<revision_id>(remove_ws(base_rev_data()),
@@ -216,7 +216,7 @@ migrate_1_to_2()
           }
         catch (exception & e)
           {
-            E(false, origin::system,
+            MONOTONE_ERROR(false, origin::system,
               F("workspace is corrupt: reading '%s': %s")
               % workcs_path % e.what());
           }
@@ -272,7 +272,7 @@ workspace::migrate_format()
     default:
       I(format > current_workspace_format);
       // keep this message in sync with the copy in check_format
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("this version of monotone only understands workspace metadata\n"
           "in formats 0 through %d.  Your workspace is in format %d.\n"
           "You need a newer version of monotone to use this workspace.")
============================================================
--- src/monotone.cc	f55dc9871b59e3ab3a313c32417b1059c1a95d5b
+++ src/monotone.cc	dc6c3f95d09f74e613dbf74af8eb4e6b05a7dfb5
@@ -138,10 +138,10 @@ cpp_main(int argc, char ** argv)
         }
 
 #ifdef SUPPORT_SQLITE_BEFORE_3003014
-      E(sqlite3_libversion_number() >= 3003008, origin::system,
+      MONOTONE_ERROR(sqlite3_libversion_number() >= 3003008, origin::system,
         F("this monotone binary requires at least SQLite 3.3.8 to run"));
 #else
-      E(sqlite3_libversion_number() >= 3003014, origin::system,
+      MONOTONE_ERROR(sqlite3_libversion_number() >= 3003014, origin::system,
         F("this monotone binary requires at least SQLite 3.3.14 to run"));
 #endif
 
@@ -153,29 +153,29 @@ cpp_main(int argc, char ** argv)
       // In Botan 1.9.9, the DataSink_Stream cannot be instantiated per
       // se. As 1.10.1 is already out, let's simply disable support for
       // that specific (testing) version of botan.
-      E(linked_botan_version != BOTAN_VERSION_CODE_FOR(1,9,9), origin::system,
+      MONOTONE_ERROR(linked_botan_version != BOTAN_VERSION_CODE_FOR(1,9,9), origin::system,
         F("monotone does not support Botan 1.9.9"));
 
 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
 #error Botan versions older than 1.8.0 are no longer supported.
 #elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,4)
       // motonote binary compiled against botan 1.8.0 - 1.9.3
-      E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,8,0), origin::system,
+      MONOTONE_ERROR(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,8,0), origin::system,
         F("this monotone binary requires Botan 1.8.0 or newer"));
-      E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
+      MONOTONE_ERROR(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
         F("this monotone binary does not work with Botan 1.9.4 or newer"));
 
 #elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,11)
       // motonote binary compiled against botan 1.9.4 - 1.9.10
 #pragma message ( "The resulting monotone binary won't be able to run with any stable release of botan." )
-      E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
+      MONOTONE_ERROR(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
         F("this monotone binary requires Botan 1.9.4 or newer"));
-      E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
+      MONOTONE_ERROR(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
         F("this monotone binary does not work with Botan 1.9.11 or newer"));
 
 #else
       // motonote binary compiled against botan 1.9.11 and newer
-      E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
+      MONOTONE_ERROR(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
         F("this monotone binary requires Botan 1.9.11 or newer"));
 #endif
 
============================================================
--- src/netsync.cc	542d5a097ca3a34a61fb5e586a02961c4788842c
+++ src/netsync.cc	adfef24f5cf567cf237248fb9510c03544c56c03
@@ -162,8 +162,8 @@ call_server(app_state & app,
           // We failed during processing. This should only happen in
           // client voice when we have a decode exception, or received an
           // error from our server (which is translated to a decode
-          // exception). We call these cases E() errors.
-          E(false, origin::network,
+          // exception). We call these cases MONOTONE_ERROR() errors.
+          MONOTONE_ERROR(false, origin::network,
             F("processing failure while talking to peer '%s', disconnecting")
             % sess->get_peer());
           return;
@@ -171,7 +171,7 @@ call_server(app_state & app,
 
       bool io_ok = react.do_io();
 
-      E(io_ok, origin::network,
+      MONOTONE_ERROR(io_ok, origin::network,
         F("timed out waiting for I/O with peer '%s', disconnecting")
         % sess->get_peer());
 
@@ -200,7 +200,7 @@ call_server(app_state & app,
               return;
             }
           else
-            E(false, origin::network,
+            MONOTONE_ERROR(false, origin::network,
               (F("I/O failure while talking to peer '%s', disconnecting")
                % sess->get_peer()));
         }
============================================================
--- src/network/automate_session.cc	e8eff583a0556256cbee3b1bca56555b9dd138e9
+++ src/network/automate_session.cc	0ebbf32dd478c29d1c2ca53b51b5b6705d5a60d9
@@ -125,7 +125,7 @@ public:
     : app(app), remote_identity(ri), cmdline(c), params(p)
   { }
   void operator()() {
-    E(app.lua.hook_get_remote_automate_permitted(remote_identity,
+    MONOTONE_ERROR(app.lua.hook_get_remote_automate_permitted(remote_identity,
                                                  cmdline, params),
       origin::user,
       F("sorry, you aren't allowed to do that."));
@@ -216,7 +216,7 @@ bool automate_session::do_work(transacti
         return true;
       }
     default:
-      E(false, origin::network,
+      MONOTONE_ERROR(false, origin::network,
         F("unexpected netcmd '%d' received on automate connection")
         % cmd_in->get_cmd_code());
     }
============================================================
--- src/network/connection_info.cc	3cc57537bf3f460495cd4c071dbf513bd536b94f
+++ src/network/connection_info.cc	b88ce86a971d7a6ddab14ea072dd29f41bbee3cf
@@ -279,7 +279,7 @@ netsync_connection_info::Client::set_raw
   if (uri.scheme.empty())
     uri.scheme = "mtn";
 
-  E(uri.scheme != "mtn" || !uri.host.empty(), origin::user,
+  MONOTONE_ERROR(uri.scheme != "mtn" || !uri.host.empty(), origin::user,
     F("a non-empty hostname is expected for the 'mtn' uri scheme"));
 
   var_key server_include(var_domain("server-include"),
@@ -339,10 +339,10 @@ netsync_connection_info::Client::ensure_
 void
 netsync_connection_info::Client::ensure_completeness() const
 {
-  E(!uri.host.empty() || !uri.path.empty(), origin::user,
+  MONOTONE_ERROR(!uri.host.empty() || !uri.path.empty(), origin::user,
     F("connection host / path is empty and no default value could be loaded"));
 
-  E(conn_type != netsync_connection || !include_pattern().empty(), origin::user,
+  MONOTONE_ERROR(conn_type != netsync_connection || !include_pattern().empty(), origin::user,
     F("branch pattern is empty and no default value could be loaded"));
 }
 
@@ -421,7 +421,7 @@ netsync_connection_info::setup_from_sync
                                !request.exclude.empty();
   bool query_exists = !info->client.uri.query.empty();
 
-  E(!(include_exclude_given && query_exists), origin::user,
+  MONOTONE_ERROR(!(include_exclude_given && query_exists), origin::user,
     F("include / exclude pattern was given both as part of the URI "
       "and as a separate argument"));
 
@@ -501,7 +501,7 @@ netsync_connection_info::setup_from_serv
   info->client.conn_type = type;
 
   info->client.set_raw_uri(host());
-  E(info->client.uri.query.empty(), origin::user,
+  MONOTONE_ERROR(info->client.uri.query.empty(), origin::user,
     F("you can specify either a query string or separate include/exclude parameters, but not both"));
   info->client.set_include_exclude_pattern(includes, excludes);
 
@@ -522,7 +522,7 @@ netsync_connection_info::setup_for_serve
 
   if (!opts.no_transport_auth)
     {
-      E(lua.hook_persist_phrase_ok(), origin::user,
+      MONOTONE_ERROR(lua.hook_persist_phrase_ok(), origin::user,
         F("need permission to store persistent passphrase "
           "(see hook persist_phrase_ok())"));
     }
============================================================
--- src/network/netsync_session.cc	6145f264aaf265eba81f23d16dfff64e535b8a23
+++ src/network/netsync_session.cc	d2cc87e37fa2f598a43fcb05f32b48b3de123711
@@ -491,7 +491,7 @@ decrement_if_nonzero(netcmd_item_type ty
     {
       string typestr;
       netcmd_item_type_to_string(ty, typestr);
-      E(false, origin::network,
+      MONOTONE_ERROR(false, origin::network,
         F("underflow on count of %s items to receive") % typestr);
     }
   --n;
============================================================
--- src/network/session.cc	605603a68faa778d8875c27bd68cc4c0b95f5618
+++ src/network/session.cc	ad9ace623d063b6a9b7cce51923c73fb41f8e1f8
@@ -283,7 +283,7 @@ bool session::do_work(transaction_guard 
                               % printable_key_hash
                               % expected_key_hash
                               % prog_name % their_key_key.first % their_key_key.second);
-                            E(false, origin::network, F("server key changed"));
+                            MONOTONE_ERROR(false, origin::network, F("server key changed"));
                           }
                       }
                     else
============================================================
--- src/netxx_pipe.cc	43d43c0bae7402e2c196006261c8540ac4acc318
+++ src/netxx_pipe.cc	3fbb1b6c64789a16e6cb28813daa948ec40698b5
@@ -49,7 +49,7 @@ Netxx::PipeStream::PipeStream(int _readf
 #endif
 {
 #if defined(_WIN32) || defined(_WIN64)
-  E(0, origin::system, F("this transport not supported on native Win32; use Cygwin"));
+  MONOTONE_ERROR(0, origin::system, F("this transport not supported on native Win32; use Cygwin"));
 
   // keeping code in case someone wants to try fixing it
 
@@ -61,7 +61,7 @@ Netxx::PipeStream::PipeStream(int _readf
 
   named_pipe = (HANDLE)_get_osfhandle(_readfd);
 
-  E(named_pipe != INVALID_HANDLE_VALUE, origin::system,
+  MONOTONE_ERROR(named_pipe != INVALID_HANDLE_VALUE, origin::system,
     F("pipe handle is invalid"));
 
   // Create infrastructure for overlapping I/O
@@ -188,7 +188,7 @@ Netxx::PipeStream::PipeStream (const str
 
 #if defined(_WIN32) || defined(_WIN64)
 
-  E(0, origin::system, F("this transport not supported on native Win32; use Cygwin"));
+  MONOTONE_ERROR(0, origin::system, F("this transport not supported on native Win32; use Cygwin"));
 
   // keeping code in case someone wants to try fixing it
 
@@ -211,7 +211,7 @@ Netxx::PipeStream::PipeStream (const str
                                1000,
                                0);
 
-  E(named_pipe != INVALID_HANDLE_VALUE, origin::system,
+  MONOTONE_ERROR(named_pipe != INVALID_HANDLE_VALUE, origin::system,
     F("CreateNamedPipe(%s,...) call failed: %s")
     % pipename % err_msg());
 
@@ -228,7 +228,7 @@ Netxx::PipeStream::PipeStream (const str
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,0);
 
-  E(hpipe != INVALID_HANDLE_VALUE, origin::system,
+  MONOTONE_ERROR(hpipe != INVALID_HANDLE_VALUE, origin::system,
     F("CreateFile(%s,...) call failed: %s")
     % pipename % err_msg());
 
@@ -259,7 +259,7 @@ Netxx::PipeStream::PipeStream (const str
                                NULL, // Current directory
                                &siStartInfo,
                                &piProcInfo);
-  E(started, origin::system,
+  MONOTONE_ERROR(started, origin::system,
     F("CreateProcess(%s,...) call failed: %s")
     % cmdline % err_msg());
 
@@ -276,7 +276,7 @@ Netxx::PipeStream::PipeStream (const str
 
   int fd1[2], fd2[2];
   child = pipe_and_fork(fd1, fd2);
-  E(child >= 0, origin::system, F("pipe/fork failed: %s") % strerror(errno));
+  MONOTONE_ERROR(child >= 0, origin::system, F("pipe/fork failed: %s") % strerror(errno));
   if (!child)
     {
       execvp(newargv[0], const_cast<char * const *>(newargv));
@@ -322,7 +322,7 @@ Netxx::PipeStream::write(const void *buf
 #if defined(_WIN32) || defined(_WIN64)
   DWORD written = 0;
   BOOL ok = WriteFile(named_pipe, buffer, length, &written, NULL);
-  E(ok, origin::system, F("WriteFile call failed: %s") % err_msg());
+  MONOTONE_ERROR(ok, origin::system, F("WriteFile call failed: %s") % err_msg());
 #else
   size_t written = ::write(writefd, buffer, length);
 #endif
@@ -413,7 +413,7 @@ Netxx::PipeCompatibleProbe::ready(const 
           // Issue an async request to fill our buffer.
           BOOL ok = ReadFile(pipe->named_pipe, pipe->readbuf,
                              sizeof(pipe->readbuf), NULL, &pipe->overlap);
-          E(ok || GetLastError() == ERROR_IO_PENDING, origin::system,
+          MONOTONE_ERROR(ok || GetLastError() == ERROR_IO_PENDING, origin::system,
             F("ReadFile call failed: %s") % err_msg());
           pipe->read_in_progress = true;
         }
@@ -448,7 +448,7 @@ Netxx::PipeCompatibleProbe::ready(const 
                                                FALSE,
                                                milliseconds);
 
-              E(wstatus != WAIT_FAILED, origin::system,
+              MONOTONE_ERROR(wstatus != WAIT_FAILED, origin::system,
                 F("WaitForMultipleObjects call failed: %s") % err_msg());
 
               if (wstatus == WAIT_OBJECT_0 + 1)
@@ -458,7 +458,7 @@ Netxx::PipeCompatibleProbe::ready(const 
             {
               wstatus = WaitForSingleObject(pipe->overlap.hEvent,
                                             milliseconds);
-              E(wstatus != WAIT_FAILED, origin::system,
+              MONOTONE_ERROR(wstatus != WAIT_FAILED, origin::system,
                 F("WaitForSingleObject call failed: %s") % err_msg());
             }
 
@@ -478,7 +478,7 @@ Netxx::PipeCompatibleProbe::ready(const 
           else
             {
               // We did not complete our read.
-              E(GetLastError() == ERROR_IO_INCOMPLETE, origin::system,
+              MONOTONE_ERROR(GetLastError() == ERROR_IO_INCOMPLETE, origin::system,
                 F("GetOverlappedResult call failed: %s")
                 % err_msg());
             }
============================================================
--- src/option.cc	bc0641cad61c4d5aa09920fe5d5b9426c85eb2d1
+++ src/option.cc	51c076d154a10e1c76c52943914ced1f99614e6e
@@ -235,7 +235,7 @@ tokenize_for_command_line(string const &
         {
           if (type != one)
             ++i;
-          E(i != from.end(), origin::user, F("invalid escape in '--xargs' file"));
+          MONOTONE_ERROR(i != from.end(), origin::user, F("invalid escape in '--xargs' file"));
           cur += *i;
           have_tok = true;
         }
@@ -349,7 +349,7 @@ getopt(map<string, concrete_option> cons
           err += "\n'--" + *j + "' (" + i->second.description + ")";
     }
 
-  E(false, origin::user, i18n_format(err));
+  MONOTONE_ERROR(false, origin::user, i18n_format(err));
 }
 
 // helper for get_by_name
============================================================
--- src/options_list.hh	bb707efe26c892a78f5853f2fd577b01e7294d84
+++ src/options_list.hh	f5d01e3eeb88171e0822a27765e86b478a4651d6
@@ -617,7 +617,7 @@ OPTION(resolve_conflicts_opts, resolve_c
 {
   // we can't call  bookkeeping_path::external_string_is_bookkeeping_path
   // here, because we haven't found the workspace yet.
-  E(bookkeeping_path::internal_string_is_bookkeeping_path(utf8(arg, origin::user)),
+  MONOTONE_ERROR(bookkeeping_path::internal_string_is_bookkeeping_path(utf8(arg, origin::user)),
     origin::user,
     F("conflicts file must be under '_MTN'"));
   resolve_conflicts_file = bookkeeping_path(arg, origin::user);
@@ -638,7 +638,7 @@ OPTION(conflicts_opts, conflicts_file, t
 {
   // we can't call bookkeeping_path::external_string_is_bookkeeping_path
   // here, because we haven't found the workspace yet.
-  E(bookkeeping_path::internal_string_is_bookkeeping_path(utf8(arg, origin::user)),
+  MONOTONE_ERROR(bookkeeping_path::internal_string_is_bookkeeping_path(utf8(arg, origin::user)),
     origin::user,
     F("conflicts file must be under '_MTN'"));
   conflicts_file = bookkeeping_path(arg, origin::user);
============================================================
--- src/packet.cc	5f21e6e2db23ee7496c84cbfa1d49fb1bf2edc13
+++ src/packet.cc	cbf01ed0c0c822fe587f2a3401a59d9641fd823a
@@ -133,27 +133,27 @@ namespace
     {}
     void validate_id(string const & id) const
     {
-      E(id.size() == constants::idlen
+      MONOTONE_ERROR(id.size() == constants::idlen
         && id.find_first_not_of(constants::legal_id_bytes) == string::npos,
         made_from,
         F("malformed packet: invalid identifier"));
     }
     void validate_base64(string const & s) const
     {
-      E(!s.empty()
+      MONOTONE_ERROR(!s.empty()
         && s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
         made_from,
         F("malformed packet: invalid base64 block"));
     }
     void validate_arg_base64(string const & s) const
     {
-      E(s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
+      MONOTONE_ERROR(s.find_first_not_of(constants::legal_base64_bytes) == string::npos,
         made_from,
         F("malformed packet: invalid base64 block"));
     }
     void validate_key(string const & k) const
     {
-      E(!k.empty()
+      MONOTONE_ERROR(!k.empty()
         && k.find_first_not_of(constants::legal_key_name_bytes) == string::npos,
         made_from,
         F("malformed packet: invalid key name"));
@@ -173,7 +173,7 @@ namespace
         }
       catch (Botan::Decoding_Error const & e)
         {
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("malformed packet: invalid public key data for '%s': %s")
               % name % e.what());
         }
@@ -191,7 +191,7 @@ namespace
 
     void validate_certname(string const & cn) const
     {
-      E(!cn.empty()
+      MONOTONE_ERROR(!cn.empty()
         && cn.find_first_not_of(constants::legal_cert_name_bytes) == string::npos,
         made_from,
         F("malformed packet: invalid cert name"));
@@ -200,7 +200,7 @@ namespace
     {
       string next;
       iss >> next;
-      E(next.empty(), made_from,
+      MONOTONE_ERROR(next.empty(), made_from,
         F("malformed packet: too many arguments in header"));
     }
 
============================================================
--- src/paths.cc	934f378acd6077d5493b7cd9624565212424c37f
+++ src/paths.cc	2af1ebb2fd63dd95207ccf8e2ac5806e210cb29c
@@ -357,12 +357,12 @@ normalize_external_path(string const & p
       // enter a workspace
       initial_rel_path.may_not_initialize();
       normalized = path;
-      E(is_valid_internal(path), origin::user,
+      MONOTONE_ERROR(is_valid_internal(path), origin::user,
         F("path '%s' is invalid") % path);
     }
   else
     {
-      E(!is_absolute_here(path), origin::user,
+      MONOTONE_ERROR(!is_absolute_here(path), origin::user,
         F("absolute path '%s' is invalid") % path);
       string base;
       try
@@ -379,11 +379,11 @@ normalize_external_path(string const & p
         }
       catch (exception &)
         {
-          E(false, origin::user, F("path '%s' is invalid") % path);
+          MONOTONE_ERROR(false, origin::user, F("path '%s' is invalid") % path);
         }
       if (normalized == ".")
         normalized = string("");
-      E(fully_normalized_path(normalized), origin::user,
+      MONOTONE_ERROR(fully_normalized_path(normalized), origin::user,
         F("path '%s' is invalid") % normalized);
     }
 }
@@ -443,7 +443,7 @@ file_path::file_path(file_path::source_t
     {
       string normalized;
       normalize_external_path(path, normalized, to_workspace_root);
-      E(!in_bookkeeping_dir(normalized), origin::user,
+      MONOTONE_ERROR(!in_bookkeeping_dir(normalized), origin::user,
         F("path '%s' is in bookkeeping dir") % normalized);
       data = normalized;
     }
@@ -458,12 +458,12 @@ file_path::file_path(file_path::source_t
   : any_path(path.made_from)
 {
   MM(path);
-  E(utf8_validate(path), made_from, F("invalid utf8"));
+  MONOTONE_ERROR(utf8_validate(path), made_from, F("invalid utf8"));
   if (type == external)
     {
       string normalized;
       normalize_external_path(path(), normalized, to_workspace_root);
-      E(!in_bookkeeping_dir(normalized), origin::user,
+      MONOTONE_ERROR(!in_bookkeeping_dir(normalized), origin::user,
         F("path '%s' is in bookkeeping dir") % normalized);
       data = normalized;
     }
@@ -482,8 +482,8 @@ bookkeeping_path::bookkeeping_path(strin
 
 bookkeeping_path::bookkeeping_path(string const & path, origin::type made_from)
 {
-  E(fully_normalized_path(path), made_from, F("path is not normalized"));
-  E(in_bookkeeping_dir(path), made_from,
+  MONOTONE_ERROR(fully_normalized_path(path), made_from, F("path is not normalized"));
+  MONOTONE_ERROR(in_bookkeeping_dir(path), made_from,
     F("bookkeeping path is not in bookkeeping directory"));
   data = path;
 }
@@ -825,7 +825,7 @@ static inline string const_system_path(u
 
 static inline string const_system_path(utf8 const & path)
 {
-  E(!path().empty(), path.made_from, F("invalid path ''"));
+  MONOTONE_ERROR(!path().empty(), path.made_from, F("invalid path ''"));
   string expanded = tilde_expand(path());
   if (is_absolute_here(expanded))
     return normalize_path(expanded);
============================================================
--- src/paths.hh	6c5767a2f033d996b507050cb949af9ae1ea6855
+++ src/paths.hh	31989682fdf18232ddc653c9581097b03d32707a
@@ -50,7 +50,7 @@
 //          to the project root.
 //        file_path_external: use this for strings that come from the user.
 //          these strings are normalized before being checked, and if there
-//          is a problem trigger E() invariants rather than I() invariants.
+//          is a problem trigger MONOTONE_ERROR() invariants rather than I() invariants.
 //          if in a workspace, such strings are interpreted as being
 //          _relative to the user's original directory_. if not in a
 //          workspace, strings are treated as relative to the tree root. The
============================================================
--- src/pcrewrap.cc	b1a7a2bf946a3d65df9ec8ec019b883965e22b56
+++ src/pcrewrap.cc	d25bccfd7ebc16d1818cdba6cc799bd49e3e5bcd
@@ -277,7 +277,7 @@ pcre_compile_error(int errcode, char con
       // character offset 0 in the pattern, so in practice we give the
       // position-ful variant for all errors, but I'm leaving the == -1 check
       // here in case PCRE gets fixed.
-      E(false, caused_by, (erroff == -1
+      MONOTONE_ERROR(false, caused_by, (erroff == -1
                            ? (F("error in regex '%s': %s")
                               % pattern % err)
                            : (F("error near char %d of regex '%s': %s")
@@ -312,16 +312,16 @@ pcre_exec_error(int errcode,
       throw std::bad_alloc();
 
     case PCRE_ERROR_MATCHLIMIT:
-      E(false, subject_from,
+      MONOTONE_ERROR(false, subject_from,
         F("backtrack limit exceeded in regular expression matching"));
 
     case PCRE_ERROR_RECURSIONLIMIT:
-      E(false, subject_from,
+      MONOTONE_ERROR(false, subject_from,
         F("recursion limit exceeded in regular expression matching"));
 
     case PCRE_ERROR_BADUTF8:
     case PCRE_ERROR_BADUTF8_OFFSET:
-      E(false, subject_from,
+      MONOTONE_ERROR(false, subject_from,
         F("invalid UTF-8 sequence found during regular expression matching"));
 
     default:
============================================================
--- src/platform.hh	4b3bad0070d3a4a75611b9f750f7486049e5c040
+++ src/platform.hh	9276d8a314fbca9e78e8f3963b77331e094b1b30
@@ -116,7 +116,7 @@ std::string get_current_working_dir();
 // filesystem stuff
 // FIXME: BUG: this returns a string in the filesystem charset/encoding
 std::string get_current_working_dir();
-// calls E() if fails
+// calls MONOTONE_ERROR() if fails
 void change_current_working_dir(std::string const & to);
 std::string tilde_expand(std::string const & path);
 std::string get_default_confdir();
============================================================
--- src/project.cc	274448eb7d071c838995184ea3df762ec0f69e84
+++ src/project.cc	703ee6aff5aceb0c2b7d6a4553ddc80f4d37fbfc
@@ -472,7 +472,7 @@ project_t::put_revision_testresult(key_s
            results == "0")
     passed = false;
   else
-    E(false, origin::user,
+    MONOTONE_ERROR(false, origin::user,
       F("could not interpret test result string '%s'; "
         "valid strings are: 1, 0, yes, no, true, false, pass, fail")
       % results);
@@ -536,7 +536,7 @@ project_t::lookup_key_by_name(key_store 
         }
     }
 
-  E(ks_match_by_local_name.size() < 2, origin::user,
+  MONOTONE_ERROR(ks_match_by_local_name.size() < 2, origin::user,
     F("you have %d keys named '%s'") %
     ks_match_by_local_name.size() % name);
   if (ks_match_by_local_name.size() == 1)
@@ -544,7 +544,7 @@ project_t::lookup_key_by_name(key_store 
       id = *ks_match_by_local_name.begin();
       return;
     }
-  E(db_match_by_local_name.size() < 2, origin::user,
+  MONOTONE_ERROR(db_match_by_local_name.size() < 2, origin::user,
     F("there are %d keys named '%s'") %
     db_match_by_local_name.size() % name);
   if (db_match_by_local_name.size() == 1)
@@ -552,7 +552,7 @@ project_t::lookup_key_by_name(key_store 
       id = *db_match_by_local_name.begin();
       return;
     }
-  E(ks_match_by_given_name.size() < 2, origin::user,
+  MONOTONE_ERROR(ks_match_by_given_name.size() < 2, origin::user,
     F("you have %d keys named '%s'") %
     ks_match_by_local_name.size() % name);
   if (ks_match_by_given_name.size() == 1)
@@ -560,7 +560,7 @@ project_t::lookup_key_by_name(key_store 
       id = *ks_match_by_given_name.begin();
       return;
     }
-  E(false, origin::user,
+  MONOTONE_ERROR(false, origin::user,
     F("there is no key named '%s'") % name);
 }
 
@@ -581,7 +581,7 @@ project_t::get_given_name_of_key(key_sto
     }
   else
     {
-      E(false, id.inner().made_from,
+      MONOTONE_ERROR(false, id.inner().made_from,
         F("key %s does not exist") % id);
     }
 }
@@ -725,18 +725,18 @@ project_t::guess_branch(options const & 
     return opts.branch;
   else
     {
-      E(!ident.inner()().empty(), origin::user,
+      MONOTONE_ERROR(!ident.inner()().empty(), origin::user,
         F("no branch found for empty revision, "
           "please provide a branch name"));
 
       set<branch_name> branches;
       get_revision_branches(ident, branches);
 
-      E(!branches.empty(), origin::user,
+      MONOTONE_ERROR(!branches.empty(), origin::user,
         F("no branch certs found for revision %s, "
           "please provide a branch name") % ident);
 
-      E(branches.size() == 1, origin::user,
+      MONOTONE_ERROR(branches.size() == 1, origin::user,
         F("multiple branch certs found for revision %s, "
           "please provide a branch name") % ident);
 
============================================================
--- src/rcs_import.cc	77ec301af13aa8de3d0f81c6964e4b018f4427e1
+++ src/rcs_import.cc	475b9427d8c85d560d79a6b086ba6c567cfa344e
@@ -1210,7 +1210,7 @@ import_cvs_repo(project_t & project,
                 branch_name const & branchname)
 
 {
-  E(!directory_exists(cvsroot / "CVSROOT"), origin::user,
+  MONOTONE_ERROR(!directory_exists(cvsroot / "CVSROOT"), origin::user,
     F("'%s' appears to be a CVS repository root directory\n"
       "try importing a module instead, with 'cvs_import %s/<module_name>'")
     % cvsroot % cvsroot);
============================================================
--- src/refiner.cc	31f39c58b006dc38d655bbdb3f85bc8d3cec0672
+++ src/refiner.cc	dc09d9e9d79066ef1bfe971ba5df1cbdba599306
@@ -399,7 +399,7 @@ refiner::process_refinement_command(refi
 
   if (ty == refinement_response)
     {
-      E((queries_in_flight > 0), origin::network,
+      MONOTONE_ERROR((queries_in_flight > 0), origin::network,
         F("underflow on query-in-flight counter"));
       --queries_in_flight;
 
============================================================
--- src/restrictions.cc	b00fbd236b8c556bf3178358301f83e786b67493
+++ src/restrictions.cc	0f3c92f45c7f6d75a0099d947f5d4ff7f26bded1
@@ -98,7 +98,7 @@ map_nodes(map<node_id, restricted_path::
 
           node_status_iterator n = node_map.find(nid);
           if (n != node_map.end())
-            E(n->second == status, origin::user,
+            MONOTONE_ERROR(n->second == status, origin::user,
               F("conflicting include/exclude on path '%s'") % *i);
           else
             node_map[nid] = status;
@@ -172,7 +172,7 @@ map_paths(map<file_path, restricted_path
     {
       path_status_iterator p = path_map.find(*i);
       if (p != path_map.end())
-        E(p->second == status, origin::user,
+        MONOTONE_ERROR(p->second == status, origin::user,
           F("conflicting include/exclude on path '%s'") % *i);
       else
         path_map[*i] = status;
@@ -234,7 +234,7 @@ validate_paths(set<file_path> const & in
         W(F("restriction excludes unknown path '%s'") % *i);
       }
 
-  E(bad == 0, origin::user,
+  MONOTONE_ERROR(bad == 0, origin::user,
     FP("%d unknown path", "%d unknown paths", bad) % bad);
 }
 
============================================================
--- src/revision.cc	5a10cfbecee66dfb7e9d5ebaa798f5436198a09e
+++ src/revision.cc	9709d8f93b2619c8f459c13b4e9c4216b798181d
@@ -30,7 +30,7 @@ void revision_t::check_sane() const
 
 void revision_t::check_sane() const
 {
-  E(!null_id(new_manifest), made_from, F("revision has no manifest id"));
+  MONOTONE_ERROR(!null_id(new_manifest), made_from, F("revision has no manifest id"));
 
   if (edges.size() == 1)
     {
@@ -40,12 +40,12 @@ void revision_t::check_sane() const
     {
       // merge nodes cannot have null revisions
       for (edge_map::const_iterator i = edges.begin(); i != edges.end(); ++i)
-        E(!null_id(edge_old_revision(i)), made_from,
+        MONOTONE_ERROR(!null_id(edge_old_revision(i)), made_from,
           F("merge revision has a null parent"));
     }
   else
     // revisions must always have either 1 or 2 edges
-    E(false, made_from, F("revision has %d edges, not 1 or 2") % edges.size());
+    MONOTONE_ERROR(false, made_from, F("revision has %d edges, not 1 or 2") % edges.size());
 
   // we used to also check that if there were multiple edges that had patches
   // for the same file, then the new hashes on each edge matched each other.
@@ -218,7 +218,7 @@ make_restricted_revision(parent_map cons
         no_excludes = false;
     }
 
-  E(old_rosters.size() == 1 || no_excludes, origin::user,
+  MONOTONE_ERROR(old_rosters.size() == 1 || no_excludes, origin::user,
     F("the command '%s %s' cannot be restricted in a two-parent workspace")
     % prog_name % cmd_name);
 
@@ -355,7 +355,7 @@ parse_revision(basic_io::parser & parser
   string tmp;
   parser.esym(syms::format_version);
   parser.str(tmp);
-  E(tmp == "1", parser.tok.in.made_from,
+  MONOTONE_ERROR(tmp == "1", parser.tok.in.made_from,
     F("encountered a revision with unknown format, version %s.\n"
       "I only know how to understand the version 1 format.\n"
       "A newer version of monotone is required to complete this operation")
@@ -380,7 +380,7 @@ read_revision(revision_data const & dat)
   basic_io::tokenizer tok(src);
   basic_io::parser pars(tok);
   rev = parse_revision(pars);
-  E(src.lookahead == EOF, rev.made_from,
+  MONOTONE_ERROR(src.lookahead == EOF, rev.made_from,
     F("failed to parse revision"));
   return rev;
 }
============================================================
--- src/roster.cc	73bab18b296d94f3f7046cca24b5ab5afc26f20a
+++ src/roster.cc	6821919c0ff86c7a3befce9d0c08d456a00f5062
@@ -2549,7 +2549,7 @@ make_restricted_roster(roster_t const & 
      problems++;
    }
 
-  E(problems == 0, origin::user, F("invalid restriction"));
+  MONOTONE_ERROR(problems == 0, origin::user, F("invalid restriction"));
 
   if (!restricted.all_nodes().empty())
     restricted.check_sane(true);
============================================================
--- src/sanity.hh	cecb19decb0393a9bdef456b6751cdfdcb2dd7d9
+++ src/sanity.hh	8162e955c46178f24ae2d826732a32c383d2781d
@@ -374,11 +374,11 @@ struct bad_decode {
 
 // E is for errors; they are normal (i.e., not a bug), but not necessarily
 // attributable to user naughtiness
-#define E(e, whence, explain)                                          \
+#define MONOTONE_ERROR(e, whence, explain)                             \
   do {                                                                 \
     if (UNLIKELY(!(e)))                                                \
       {                                                                \
-        global_sanity.generic_failure("E("#e")", (whence),             \
+        global_sanity.generic_failure("MONOTONE_ERROR("#e")", (whence),             \
                                       (explain),                       \
                                       __FILE__, __LINE__);             \
       }                                                                \
============================================================
--- src/selectors.cc	cc809a10de1a05a72ab8c0e26497c1bd5bcc54fe
+++ src/selectors.cc	8601c5fc2a5893f9a0a2ea20aa78fdd3f3c01967
@@ -57,7 +57,7 @@ diagnose_ambiguous_expansion(options con
        i != completions.end(); ++i)
     err += ("\n" + describe_revision(opts, lua, project, *i));
 
-  E(false, origin::user, i18n_format(err));
+  MONOTONE_ERROR(false, origin::user, i18n_format(err));
 }
 
 class selector
@@ -92,7 +92,7 @@ public:
 public:
   key_selector(string const & arg, lua_hooks & lua, project_t & project)
   {
-    E(!arg.empty(), origin::user,
+    MONOTONE_ERROR(!arg.empty(), origin::user,
       F("the key selector k: must not be empty"));
 
     project.get_key_identity(lua,
@@ -127,7 +127,7 @@ public:
 public:
   cert_selector(string const & arg) : value(arg)
   {
-    E(!value.empty(), origin::user,
+    MONOTONE_ERROR(!value.empty(), origin::user,
       F("the cert selector c: may not be empty"));
   }
   virtual set<revision_id> complete(project_t & project)
@@ -145,7 +145,7 @@ string preprocess_date_for_selector(stri
   string tmp;
   if (lua.hook_exists("expand_date"))
     {
-      E(lua.hook_expand_date(sel, tmp), origin::user,
+      MONOTONE_ERROR(lua.hook_expand_date(sel, tmp), origin::user,
         F("selector '%s' is not a valid date") % sel);
     }
   else
@@ -161,7 +161,7 @@ string preprocess_date_for_selector(stri
     tmp += "-01T00:00:00";
   else if (tmp.size()<11 && !equals)
     tmp += "T00:00:00";
-  E(tmp.size()==19 || equals, origin::user,
+  MONOTONE_ERROR(tmp.size()==19 || equals, origin::user,
     F("selector '%s' is not a valid date (internally completed to '%s')") % sel % tmp);
 
   if (sel != tmp)
@@ -329,7 +329,7 @@ public:
 public:
   update_selector(string const & arg, lua_hooks & lua)
   {
-    E(arg.empty(), origin::user,
+    MONOTONE_ERROR(arg.empty(), origin::user,
       F("no value is allowed with the update selector u:"));
 
     workspace work(lua, F("the update selector u: refers to the "
@@ -350,7 +350,7 @@ public:
   working_base_selector(string const & arg, project_t & project,
                         lua_hooks & lua)
   {
-    E(arg.empty(), origin::user,
+    MONOTONE_ERROR(arg.empty(), origin::user,
       F("no value is allowed with the base revision selector w:"));
 
     workspace work(lua, F("the selector w: returns the "
@@ -468,7 +468,7 @@ diagnose_wrong_arg_count(string const & 
 static void
 diagnose_wrong_arg_count(string const & func, int expected, int actual)
 {
-  E(expected == actual, origin::user,
+  MONOTONE_ERROR(expected == actual, origin::user,
     FP("the '%s' function takes %d argument, not %d",
        "the '%s' function takes %d arguments, not %d",
        expected)
@@ -606,7 +606,7 @@ public:
       }
     else
       {
-        E(false, origin::user,
+        MONOTONE_ERROR(false, origin::user,
           F("unknown selection function '%s'") % name);
       }
   }
@@ -683,7 +683,7 @@ selector::create_simple_selector(options
       return shared_ptr<selector>(make_shared<working_base_selector>
                                   (sel, project, lua));
     default:
-      E(false, origin::user, F("unknown selector type: %c") % sel_type);
+      MONOTONE_ERROR(false, origin::user, F("unknown selector type: %c") % sel_type);
     }
 }
 
@@ -717,12 +717,12 @@ shared_ptr<selector> selector::create(op
             splitted.push_back(string());
 
           ++iter;
-          E(iter != tokenizer.end(), origin::user,
+          MONOTONE_ERROR(iter != tokenizer.end(), origin::user,
             F("selector '%s' is invalid, it ends with the escape character '\\'")
             % orig);
           string const & val2 = *iter;
           I(!val2.empty());
-          E(special_chars.find(val2) != string::npos, origin::user,
+          MONOTONE_ERROR(special_chars.find(val2) != string::npos, origin::user,
             F("selector '%s' is invalid, it contains an unknown escape sequence '%s%s'")
             % val % '\\' % val2.substr(0,1));
           splitted.back().append(val2);
@@ -761,7 +761,7 @@ shared_ptr<selector> selector::create(op
           {
             ++lparen_pos;
           }
-        E(lparen_pos < items.size(), origin::user,
+        MONOTONE_ERROR(lparen_pos < items.size(), origin::user,
           F("selector '%s' is invalid, unmatched ')'") % orig);
         I(idx(items, items.size() - lparen_pos).str == "(");
         unsigned int name_idx = items.size() - lparen_pos - 1;
@@ -779,7 +779,7 @@ shared_ptr<selector> selector::create(op
               {
                 L(FL("        found argument at stack position %d") % i);
                 shared_ptr<selector> arg = idx(items,i).sel;
-                E(i == items.size() - 1 || idx(items,i+1).str == ";", origin::user,
+                MONOTONE_ERROR(i == items.size() - 1 || idx(items,i+1).str == ";", origin::user,
                   F("selector '%s' is invalid, function argument doesn't look like an arg-list"));
                 to_add->add(arg);
               }
@@ -790,7 +790,7 @@ shared_ptr<selector> selector::create(op
         else
           {
             // just parentheses for grouping, closing paren is not on the item stack
-            E(lparen_pos == 2 && idx(items, items.size() - 1).sel, origin::user,
+            MONOTONE_ERROR(lparen_pos == 2 && idx(items, items.size() - 1).sel, origin::user,
               F("selector '%s' is invalid, grouping parentheses contain something that "
                 "doesn't look like an expr") % orig);
             shared_ptr<selector> to_add =
@@ -802,11 +802,11 @@ shared_ptr<selector> selector::create(op
       } else if (*tok == ";") {
         items.push_back(parse_item(*tok));
       } else if (*tok == "/") {
-        E(!items.empty(), origin::user,
+        MONOTONE_ERROR(!items.empty(), origin::user,
           F("selector '%s' is invalid, because it starts with a '/'") % orig);
         items.push_back(parse_item(*tok));
       } else if (*tok == "|") {
-        E(!items.empty(), origin::user,
+        MONOTONE_ERROR(!items.empty(), origin::user,
           F("selector '%s' is invalid, because it starts with a '|'") % orig);
         items.push_back(parse_item(*tok));
       } else {
@@ -831,17 +831,17 @@ shared_ptr<selector> selector::create(op
             {
               shared_ptr<selector> lhs = idx(items, items.size() - 3).sel;
               shared_ptr<selector> rhs = idx(items, items.size() - 1).sel;
-              E(lhs, origin::user,
+              MONOTONE_ERROR(lhs, origin::user,
                 F("selector '%s' is invalid, because there is a '%s' someplace it shouldn't be")
                 % orig % op);
               shared_ptr<or_selector> lhs_as_or
                 = std::dynamic_pointer_cast<or_selector>(lhs);
               shared_ptr<and_selector> lhs_as_and
                 = std::dynamic_pointer_cast<and_selector>(lhs);
-              E(op == "/" || !lhs_as_and, origin::user,
+              MONOTONE_ERROR(op == "/" || !lhs_as_and, origin::user,
                 F("selector '%s' is invalid, don't mix '/' and '|' operators without parentheses")
                 % orig);
-              E(op == "|" || !lhs_as_or, origin::user,
+              MONOTONE_ERROR(op == "|" || !lhs_as_or, origin::user,
                 F("selector '%s' is invalid, don't mix '/' and '|' operators without parentheses")
                 % orig);
               shared_ptr<selector> new_item;
@@ -880,7 +880,7 @@ shared_ptr<selector> selector::create(op
             }
         }
     }
-  E(items.size() == 1 && items[0].sel, origin::user,
+  MONOTONE_ERROR(items.size() == 1 && items[0].sel, origin::user,
     F("selector '%s' is invalid, it doesn't look like an expr") % orig);
   return items[0].sel;
 }
@@ -899,7 +899,7 @@ complete(options const & opts, lua_hooks
   if (isel && isel->is_full_length())
     {
       completions.insert(isel->get_assuming_full_length());
-      E(project.db.revision_exists(*completions.begin()), origin::user,
+      MONOTONE_ERROR(project.db.revision_exists(*completions.begin()), origin::user,
         F("no revision %s found in database") % *completions.begin());
       return;
     }
@@ -907,7 +907,7 @@ complete(options const & opts, lua_hooks
   P(F("expanding selection '%s'") % str);
   completions = sel->complete(project);
 
-  E(!completions.empty(), origin::user,
+  MONOTONE_ERROR(!completions.empty(), origin::user,
     F("no match for selection '%s'") % str);
 
   for (set<revision_id>::const_iterator i = completions.begin();
@@ -917,7 +917,7 @@ complete(options const & opts, lua_hooks
 
       // This may be impossible, but let's make sure.
       // All the callers used to do it.
-      E(project.db.revision_exists(*i), origin::user,
+      MONOTONE_ERROR(project.db.revision_exists(*i), origin::user,
         F("no revision %s found in database") % *i);
     }
 }
============================================================
--- src/ssh_agent.cc	6b9a6795f0277380767199906ed94d9c9fd4aac5
+++ src/ssh_agent.cc	3ce0bebe5098ef21e06507842f48af793af93390
@@ -140,7 +140,7 @@ get_long_from_buf(string const & buf, u3
 static u32
 get_long_from_buf(string const & buf, u32 & loc)
 {
-  E(buf.length() >= loc + 4, origin::system,
+  MONOTONE_ERROR(buf.length() >= loc + 4, origin::system,
     F("string not long enough to get a long"));
   u32 ret = get_long(buf.data() + loc);
   loc += 4;
@@ -158,7 +158,7 @@ get_string_from_buf(string const & buf,
     % loc);
   len = get_long_from_buf(buf, loc);
   L(FL("ssh_agent: get_string_from_buf: len: %u" ) % len);
-  E(loc + len <= buf.length(), origin::system,
+  MONOTONE_ERROR(loc + len <= buf.length(), origin::system,
     F("ssh_agent: length (%i) of buf less than loc (%u) + len (%u)")
     % buf.length()
     % loc
@@ -270,7 +270,7 @@ ssh_agent_state::read_packet(string & pa
   read_data(4, len_buf);
   u32 l = 0;
   len = get_long_from_buf(len_buf, l);
-  E(len > 0, origin::system,
+  MONOTONE_ERROR(len > 0, origin::system,
     F("ssh_agent: fetch_packet: zero-length packet from ssh-agent"));
 
   L(FL("ssh_agent: fetch_packet: response len %u") % len);
@@ -321,7 +321,7 @@ ssh_agent::get_keys()
 
   //first byte is packet type
   u32 packet_loc = 0;
-  E(packet.at(0) == 12, origin::system,
+  MONOTONE_ERROR(packet.at(0) == 12, origin::system,
     F("ssh_agent: packet type (%u) != 12")
     % (u32)packet.at(0));
   packet_loc += 1;
@@ -359,7 +359,7 @@ ssh_agent::get_keys()
                                     BigInt::Binary);
           L(FL("ssh_agent: n: %s, len %u") % n % slen);
 
-          E(key.length() == key_loc, origin::system,
+          MONOTONE_ERROR(key.length() == key_loc, origin::system,
             F("ssh_agent: get_keys: not all or too many key bytes consumed,"
               " location (%u), length (%i)")
             % key_loc
@@ -383,7 +383,7 @@ ssh_agent::get_keys()
       get_string_from_buf(packet, packet_loc, comment_len, comment);
       L(FL("ssh_agent: comment_len: %u, comment: %s") % comment_len % comment);
     }
-  E(packet.length() == packet_loc, origin::system,
+  MONOTONE_ERROR(packet.length() == packet_loc, origin::system,
     F("ssh_agent: get_keys: not all or too many packet bytes consumed,"
       " location (%u), length (%i)")
     % packet_loc
@@ -432,7 +432,7 @@ ssh_agent::sign_data(RSA_PublicKey const
                      string const & data,
                      string & out)
 {
-  E(connected(), origin::system,
+  MONOTONE_ERROR(connected(), origin::system,
     F("ssh_agent: get_keys: attempted to sign data when not connected"));
 
   L(FL("ssh_agent: sign_data: key e: %s, n: %s, data len: %i")
@@ -478,13 +478,13 @@ ssh_agent::sign_data(RSA_PublicKey const
   L(FL("ssh_agent: sign_data: type (%u), '%s'") % type_len % type);
   get_string_from_buf(full_sig, full_sig_loc, out_len, out);
   L(FL("ssh_agent: sign_data: output length %u") % out_len);
-  E(full_sig.length() == full_sig_loc, origin::system,
+  MONOTONE_ERROR(full_sig.length() == full_sig_loc, origin::system,
     (F("ssh_agent: sign_data: not all or too many signature bytes consumed,"
        " location (%u), length (%i)")
      % full_sig_loc
      % full_sig.length()));
 
-  E(packet_in.length() == packet_in_loc, origin::system,
+  MONOTONE_ERROR(packet_in.length() == packet_in_loc, origin::system,
     (F("ssh_agent: sign_data: not all or too many packet bytes consumed,"
        " location (%u), length (%i)")
      % packet_in_loc
@@ -494,7 +494,7 @@ ssh_agent::add_identity(RSA_PrivateKey c
 void
 ssh_agent::add_identity(RSA_PrivateKey const & key, string const & comment)
 {
-  E(s->connected(), origin::system,
+  MONOTONE_ERROR(s->connected(), origin::system,
     F("ssh_agent: add_identity: attempted to add a key when not connected"));
 
   L(FL("ssh_agent: add_identity: key e: %s, n: %s, comment len: %i")
@@ -510,10 +510,10 @@ ssh_agent::add_identity(RSA_PrivateKey c
 
   string packet_in;
   s->read_packet(packet_in);
-  E(packet_in.length() == 1, origin::system,
+  MONOTONE_ERROR(packet_in.length() == 1, origin::system,
     F("ssh_agent: add_identity: response packet of unexpected size (%u)")
     % packet_in.length());
-  E(packet_in.at(0) == 6, origin::system,
+  MONOTONE_ERROR(packet_in.at(0) == 6, origin::system,
     F("ssh_agent: packet type (%u) != 6")
     % (u32)packet_in.at(0));
 }
============================================================
--- src/transforms.cc	a2af76783de4a02b528685459e99349ba9b118da
+++ src/transforms.cc	472775c49c875a91eeb891e23b73d86e17e4dc99
@@ -82,7 +82,7 @@ error_in_transform(std::exception & e, o
             *p = ' ';
         }
 
-      E(false, caused_by,
+      MONOTONE_ERROR(false, caused_by,
         F("%s\n"
           "This may be due to a memory glitch, data corruption during\n"
           "a network transfer, corruption of your database or workspace,\n"
============================================================
--- src/ui.cc	8bdaebf0da3e90cbe0026d140c2000e92998693f
+++ src/ui.cc	537a6bd9c479e6aae463237c6ade682af4ddbde9
@@ -839,7 +839,7 @@ user_interface::redirect_log_to(system_p
   if (filestr.is_open())
     filestr.close();
   filestr.open(filename.as_external().c_str(), ofstream::out | ofstream::app);
-  E(filestr.is_open(), origin::system,
+  MONOTONE_ERROR(filestr.is_open(), origin::system,
     F("failed to open log file '%s'") % filename);
   clog.rdbuf(filestr.rdbuf());
 }
============================================================
--- src/unix/fs.cc	5b3be0d56e4ba2ae8526a4913a731e1134117900
+++ src/unix/fs.cc	71e6b909346d0875ccaba0a1b1fcce2135865138
@@ -62,7 +62,7 @@ get_current_working_dir()
   while (errno == ERANGE);
 
   const int err = errno;
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("cannot get working directory: %s") % os_strerror(err));
 }
 
@@ -72,7 +72,7 @@ change_current_working_dir(string const 
   if (chdir(to.c_str()))
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("cannot change to directory '%s': %s") % to % os_strerror(err));
     }
 }
@@ -94,7 +94,7 @@ get_homedir()
     return string(home);
 
   struct passwd * pw = getpwuid(getuid());
-  E(pw != NULL, origin::user,
+  MONOTONE_ERROR(pw != NULL, origin::user,
     F("could not find home directory for uid %d") % getuid());
   return string(pw->pw_dir);
 }
@@ -127,7 +127,7 @@ tilde_expand(string const & in)
   // treating system-provided data as utf8, but it's probably in the
   // filesystem charset)
   pw = getpwnam(user.c_str());
-  E(pw != NULL, origin::user,
+  MONOTONE_ERROR(pw != NULL, origin::user,
     F("could not find home directory for user '%s'") % user);
 
   return string(pw->pw_dir) + after;
@@ -145,7 +145,7 @@ get_path_status(string const & path)
       if (err == ENOENT)
         return path::nonexistent;
       else
-        E(false, origin::system,
+        MONOTONE_ERROR(false, origin::system,
           F("error accessing file '%s': %s") % path % os_strerror(err));
     }
   if (S_ISREG(buf.st_mode))
@@ -168,7 +168,7 @@ namespace
       if (!d)
         {
           const int err = errno;
-          E(false, origin::system,
+          MONOTONE_ERROR(false, origin::system,
             F("could not open directory '%s': %s") % path % os_strerror(err));
         }
     }
@@ -260,7 +260,7 @@ read_directory(string const & path,
 
       int err = errno;
 
-      E(st_result == 0, origin::system,
+      MONOTONE_ERROR(st_result == 0, origin::system,
         F("error accessing '%s/%s': %s") % p % d->d_name % os_strerror(err));
 
       if (S_ISREG(st.st_mode))
@@ -282,7 +282,7 @@ make_accessible(string const & name)
   if (stat(name.c_str(), &st) != 0)
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("stat(%s) failed: %s") % name % os_strerror(err));
     }
 
@@ -294,7 +294,7 @@ make_accessible(string const & name)
   if (chmod(name.c_str(), new_mode) != 0)
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("chmod(%s) failed: %s") % name % os_strerror(err));
     }
 }
@@ -337,7 +337,7 @@ rename_clobberingly(string const & from,
 
               err = errno;
 
-              E(read_count >= 0, origin::system,
+              MONOTONE_ERROR(read_count >= 0, origin::system,
                 F ("error reading file '%s': %s") % from % os_strerror(err));
 
               remaining -= read_count;
@@ -352,7 +352,7 @@ rename_clobberingly(string const & from,
             {
               ssize_t write_count = write(to_fd, ptr, remaining);
               err = errno;
-              E(write_count >= 0, origin::system,
+              MONOTONE_ERROR(write_count >= 0, origin::system,
                 F("error writing file '%s': %s") % to % os_strerror(err));
 
               remaining -= write_count;
@@ -367,7 +367,7 @@ rename_clobberingly(string const & from,
         }
       else
         {
-          E(false, origin::system,
+          MONOTONE_ERROR(false, origin::system,
             F("renaming '%s' to '%s' failed: %s") % from % to % os_strerror(err));
         }
     }
@@ -381,7 +381,7 @@ do_remove(string const & path)
   if (remove(path.c_str()))
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("could not remove '%s': %s") % path % os_strerror(err));
     }
 }
@@ -436,7 +436,7 @@ do_remove_recursive(string const & path)
   if (err == ENOENT)
     return; // nothing to delete
 
-  E((err == ENOTEMPTY) || (err == EEXIST), origin::system,
+  MONOTONE_ERROR((err == ENOTEMPTY) || (err == EEXIST), origin::system,
     F("could not remove '%s': %s") % path % os_strerror(err));
 
   // If we get here, it's a non-empty directory to be recursed through.
@@ -463,14 +463,14 @@ do_mkdir(string const & path)
   if (mkdir(path.c_str(), 0777))
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("could not create directory '%s': %s") % path % os_strerror(err));
     }
 }
 
 // Create a temporary file in directory DIR, writing its name to NAME and
 // returning a read-write file descriptor for it.  If unable to create
-// the file, throws an E().
+// the file, throws an MONOTONE_ERROR().
 //
 
 // N.B. None of the standard temporary-file creation routines in libc do
@@ -527,9 +527,9 @@ make_temp_file(string const & dir, strin
       // plain error.  (ENOTDIR is a bug, and so are some ELOOP and EACCES
       // conditions - caller's responsibility to make sure that 'dir' is in
       // fact a directory to which we can write - but we get better
-      // diagnostics from this E() than we would from an I().)
+      // diagnostics from this MONOTONE_ERROR() than we would from an I().)
 
-      E(err == EEXIST, origin::system,
+      MONOTONE_ERROR(err == EEXIST, origin::system,
         F("cannot create temp file '%s': %s") % tmp % os_strerror(err));
 
       // This increment is relatively prime to 'limit', therefore 'value'
@@ -539,7 +539,7 @@ make_temp_file(string const & dir, strin
     }
 
   // we really should never get here.
-  E(false, origin::no_fault,
+  MONOTONE_ERROR(false, origin::no_fault,
     F("all %d possible temporary file names are in use") % limit);
 }
 
@@ -580,12 +580,12 @@ write_data_worker(string const & fname,
       {
         ssize_t written = write(fd, ptr, remaining);
         const int err = errno;
-        E(written >= 0, origin::system,
+        MONOTONE_ERROR(written >= 0, origin::system,
           F("error writing to temp file '%s': %s") % tmp % os_strerror(err));
         if (written == 0)
           {
             deadcycles++;
-            E(deadcycles < 4, origin::system,
+            MONOTONE_ERROR(deadcycles < 4, origin::system,
               FP("giving up after four zero-length writes to '%s' "
                  "(%d byte written, %d left)",
                  "giving up after four zero-length writes to '%s' "
============================================================
--- src/unix/parse_date.cc	0eca6adcb3e796a84fbc3c08c974694c916bb58e
+++ src/unix/parse_date.cc	a82dd38c5b1f404ad5191201ec754d7e99fb1a0b
@@ -17,10 +17,10 @@ void parse_date(const std::string s, con
 {
   char *p = strptime(s.c_str(), fmt.c_str(), tp);
 
-  E(p, origin::user,// failed to match all of the fromat string
+  MONOTONE_ERROR(p, origin::user,// failed to match all of the fromat string
     F("unable to parse date '%s' with format '%s'") % s % fmt);
 
-  E(*p == 0, origin::user, // extraneous characters in input string
+  MONOTONE_ERROR(*p == 0, origin::user, // extraneous characters in input string
     F("invalid date '%s' not matched by format '%s'") % s % fmt);
 }
 
============================================================
--- src/unix/process.cc	00cf53c7ea3c15dd04d7957fa7c8ad89efd802c5
+++ src/unix/process.cc	40caaf41e3e4e8616e48688e3f4c37317e6f5a8b
@@ -62,7 +62,7 @@ bool is_executable(const char *path)
   if (rc == -1)
     {
       const int err = errno;
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("error getting status of file '%s': %s") % path % os_strerror(err));
     }
 
@@ -86,7 +86,7 @@ int change_xbits(const char *path, const
   if (fd == -1)
     {
       const int err = errno;
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("error opening file '%s': %s") % path % os_strerror(err));
     }
   if (fstat(fd, &s))
@@ -118,7 +118,7 @@ int change_xbits(const char *path, const
   if (close(fd) != 0)
     {
       const int err = errno;
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("error closing file '%s': %s") % path % os_strerror(err));
     }
 
============================================================
--- src/unix/ssh_agent_platform.cc	d7c26b7328fc34212efe48fbdb7aeabb1babfb4d
+++ src/unix/ssh_agent_platform.cc	fb8801753b39082833d27dbc0e445ac0d33df500
@@ -96,17 +96,17 @@ ssh_agent_platform::write_data(string co
     {
       ssize_t sent = ::send(sock, buf, put, MSG_NOSIGNAL);
 
-      E(sent >= 0, origin::system,
+      MONOTONE_ERROR(sent >= 0, origin::system,
         F("ssh_agent: error during send: %s") % strerror(errno));
       if (sent == 0)
-        E(++deadcycles < 8, origin::system,
+        MONOTONE_ERROR(++deadcycles < 8, origin::system,
           F("ssh_agent: giving up after %d ineffective sends to agent")
           % deadcycles);
 
       buf += sent;
       put -= sent;
     }
-  E(put == 0, origin::system,
+  MONOTONE_ERROR(put == 0, origin::system,
     F("ssh_agent: sent %u extra bytes to agent") % -put);
 }
 
@@ -126,16 +126,16 @@ ssh_agent_platform::read_data(string::si
     {
       ssize_t recvd = ::recv(sock, buf, min(get, bufsize), MSG_WAITALL);
 
-      E(recvd >= 0, origin::system,
+      MONOTONE_ERROR(recvd >= 0, origin::system,
         F("ssh_agent: error during receive: %s") % strerror(errno));
       if (recvd == 0)
-        E(++deadcycles < 8, origin::system,
+        MONOTONE_ERROR(++deadcycles < 8, origin::system,
           F("ssh_agent: giving up after %d ineffective receives from agent"));
 
       out.append(buf, recvd);
       get -= recvd;
     }
-  E(get == 0, origin::system,
+  MONOTONE_ERROR(get == 0, origin::system,
     F("ssh_agent: received %u extra bytes from agent") % -get);
 }
 
============================================================
--- src/uri.cc	f50e7599f6294a9872c055a8b230ea4933bdcc82
+++ src/uri.cc	7cf4f862ab7b454597db5084c50c8320617a2869
@@ -36,7 +36,7 @@ parse_uri(string const & in, uri_t & uri
   pcre::regex matcher("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?",
                       origin::internal);
   vector<string> matches;
-  E(matcher.match(modified, made_from, matches), made_from,
+  MONOTONE_ERROR(matcher.match(modified, made_from, matches), made_from,
     F("unable to parse URI '%s'") % in);
 
   I(matches.size() == 10);
@@ -64,7 +64,7 @@ parse_uri(string const & in, uri_t & uri
                            origin::internal);
       vector<string> hostlike_matches;
 
-      E(hostlike.match(matches[4], made_from, hostlike_matches), made_from,
+      MONOTONE_ERROR(hostlike.match(matches[4], made_from, hostlike_matches), made_from,
         F("unable to parse host of URI '%s'") % in);
 
       if (!hostlike_matches[2].empty())
@@ -147,10 +147,10 @@ urldecode(string const & in, origin::typ
         {
           char d1, d2;
           ++i;
-          E(i != in.end(), made_from, F("bad URLencoded string '%s'") % in);
+          MONOTONE_ERROR(i != in.end(), made_from, F("bad URLencoded string '%s'") % in);
           d1 = *i;
           ++i;
-          E(i != in.end(), made_from, F("bad URLencoded string '%s'") % in);
+          MONOTONE_ERROR(i != in.end(), made_from, F("bad URLencoded string '%s'") % in);
           d2 = *i;
 
           char c = 0;
@@ -172,7 +172,7 @@ urldecode(string const & in, origin::typ
             case 'd': case 'D': c += 13; break;
             case 'e': case 'E': c += 14; break;
             case 'f': case 'F': c += 15; break;
-            default: E(false, made_from, F("bad URLencoded string '%s'") % in);
+            default: MONOTONE_ERROR(false, made_from, F("bad URLencoded string '%s'") % in);
             }
           c *= 16;
           switch(d2)
@@ -193,7 +193,7 @@ urldecode(string const & in, origin::typ
             case 'd': case 'D': c += 13; break;
             case 'e': case 'E': c += 14; break;
             case 'f': case 'F': c += 15; break;
-            default: E(false, made_from, F("bad URLencoded string '%s'") % in);
+            default: MONOTONE_ERROR(false, made_from, F("bad URLencoded string '%s'") % in);
             }
           out += c;
         }
============================================================
--- src/vocab.cc	1bbd1368822b5ab65aed2d1f16d165da0c096e54
+++ src/vocab.cc	921456660e6e409ab5d7373199b346f8474cbbdf
@@ -37,7 +37,7 @@ verify(hexenc<INNER> const & val)
 {
   for (string::const_iterator i = val().begin(); i != val().end(); ++i)
     {
-      E(is_xdigit(*i), val.made_from,
+      MONOTONE_ERROR(is_xdigit(*i), val.made_from,
         F("bad character '%c' in '%s'") % *i % val);
     }
 }
@@ -49,11 +49,11 @@ verify(hexenc<id> const & val)
   if (val().empty())
     return;
 
-  E(val().size() == constants::idlen, val.made_from,
+  MONOTONE_ERROR(val().size() == constants::idlen, val.made_from,
     F("hex encoded ID '%s' size != %d") % val % constants::idlen);
   for (string::const_iterator i = val().begin(); i != val().end(); ++i)
     {
-      E(is_xdigit(*i), val.made_from,
+      MONOTONE_ERROR(is_xdigit(*i), val.made_from,
         F("bad character '%c' in id name '%s'") % *i % val);
     }
 }
@@ -65,7 +65,7 @@ verify(id & val)
   if (val().empty())
     return;
 
-  E(val().size() == constants::idlen_bytes, val.made_from,
+  MONOTONE_ERROR(val().size() == constants::idlen_bytes, val.made_from,
     F("invalid ID '%s'") % val);
 }
 
@@ -74,7 +74,7 @@ verify(symbol const & val)
 {
   for (string::const_iterator i = val().begin(); i != val().end(); ++i)
     {
-      E(is_alnum(*i) || *i == '_', val.made_from,
+      MONOTONE_ERROR(is_alnum(*i) || *i == '_', val.made_from,
         F("bad character '%c' in symbol '%s'") % *i % val);
     }
 }
@@ -83,7 +83,7 @@ verify(cert_name const & val)
 verify(cert_name const & val)
 {
   string::size_type pos = val().find_first_not_of(constants::legal_cert_name_bytes);
-  E(pos == string::npos, val.made_from,
+  MONOTONE_ERROR(pos == string::npos, val.made_from,
     F("bad character '%c' in cert name '%s'") % val().at(pos) % val);
 }
 
@@ -91,7 +91,7 @@ verify(key_name const & val)
 verify(key_name const & val)
 {
   string::size_type pos = val().find_first_not_of(constants::legal_key_name_bytes);
-  E(pos == string::npos, val.made_from,
+  MONOTONE_ERROR(pos == string::npos, val.made_from,
     F("bad character '%c' in key name '%s'") % val().at(pos) % val);
 }
 
@@ -108,7 +108,7 @@ verify(netsync_session_key & val)
       return;
     }
 
-  E(val().size() == constants::netsync_session_key_length_in_bytes,
+  MONOTONE_ERROR(val().size() == constants::netsync_session_key_length_in_bytes,
     val.made_from,
     F("invalid key length of %d bytes") % val().length());
 }
@@ -122,7 +122,7 @@ verify(netsync_hmac_value & val)
       return;
     }
 
-  E(val().size() == constants::netsync_hmac_value_length_in_bytes,
+  MONOTONE_ERROR(val().size() == constants::netsync_hmac_value_length_in_bytes,
     val.made_from,
     F("invalid hmac length of %d bytes") % val().length());
 }
============================================================
--- src/win32/fs.cc	0f64aceb6403806181436efb1d255fd8cce902b3
+++ src/win32/fs.cc	970294ab94b3b068b4ae042135fd402c898b6806
@@ -24,7 +24,7 @@ get_current_working_dir()
 get_current_working_dir()
 {
   char buffer[4096];
-  E(getcwd(buffer, 4096), origin::system,
+  MONOTONE_ERROR(getcwd(buffer, 4096), origin::system,
     F("cannot get working directory: %s") % strerror(errno));
   std::string str(buffer);
 
@@ -40,7 +40,7 @@ change_current_working_dir(std::string c
 void
 change_current_working_dir(std::string const & to)
 {
-  E(!chdir(to.c_str()), origin::system,
+  MONOTONE_ERROR(!chdir(to.c_str()), origin::system,
     F("cannot change to directory '%s': %s") % to % strerror(errno));
 }
 
@@ -58,7 +58,7 @@ get_default_confdir()
       if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath)))
         base = szPath;
     }
-  E(!base.empty(), origin::system, F("could not determine configuration path"));
+  MONOTONE_ERROR(!base.empty(), origin::system, F("could not determine configuration path"));
   return base + "\\monotone";
 }
 
@@ -143,7 +143,7 @@ get_path_status(std::string const & path
          || err == ERROR_BAD_NETPATH)
         return path::nonexistent;
 
-          E(false, origin::system, F("'%s': GetFileAttributes error: %s") % path % os_strerror(err));
+          MONOTONE_ERROR(false, origin::system, F("'%s': GetFileAttributes error: %s") % path % os_strerror(err));
     }
   else if (attrs & FILE_ATTRIBUTE_DIRECTORY)
     return path::directory;
@@ -171,7 +171,7 @@ namespace
           if (GetLastError() == ERROR_FILE_NOT_FOUND) // zero files in dir
             last = true;
           else
-            E(false, origin::system, F("could not open directory '%s': %s")
+            MONOTONE_ERROR(false, origin::system, F("could not open directory '%s': %s")
               % path % os_strerror(GetLastError()));
         }
     }
@@ -192,7 +192,7 @@ namespace
         }
       if (FindNextFile(h, data))
         return true;
-          E(GetLastError() == ERROR_NO_MORE_FILES, origin::system,
+          MONOTONE_ERROR(GetLastError() == ERROR_NO_MORE_FILES, origin::system,
         F("error while reading directory: %s") % os_strerror(errno));
       last = true;
       return false;
@@ -246,7 +246,7 @@ do_remove(std::string const & path)
       // the path doesn't exist.
       break;
     }
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("could not remove '%s': %s") % path % os_strerror(GetLastError()));
 }
 
@@ -296,10 +296,10 @@ do_remove_recursive(std::string const & 
   op.lpszProgressTitle = NULL;
 
   int rc = SHFileOperationA(&op);
-  E(rc == 0, origin::system,
+  MONOTONE_ERROR(rc == 0, origin::system,
     F("could not remove '%s' and contents: SHFileOperation error code 0x%x")
     % path % rc);
-  E(!op.fAnyOperationsAborted, origin::system,
+  MONOTONE_ERROR(!op.fAnyOperationsAborted, origin::system,
     F("could not remove '%s' and contents: SHFileOperation partially aborted")
     % path);
 
@@ -308,7 +308,7 @@ do_mkdir(std::string const & path)
 void
 do_mkdir(std::string const & path)
 {
-  E(CreateDirectoryA(path.c_str(), 0) != 0, origin::system,
+  MONOTONE_ERROR(CreateDirectoryA(path.c_str(), 0) != 0, origin::system,
     F("could not create directory '%s': %s")
     % path % os_strerror(GetLastError()));
 }
@@ -364,11 +364,11 @@ void make_accessible(std::string const &
 void make_accessible(std::string const & name)
 {
   DWORD attrs = GetFileAttributes(name.c_str());
-  E(attrs != INVALID_FILE_ATTRIBUTES, origin::system,
+  MONOTONE_ERROR(attrs != INVALID_FILE_ATTRIBUTES, origin::system,
     F("GetFileAttributes(%s) failed: %s")
     % name % os_strerror(GetLastError()));
 
-  E(SetFileAttributes(name.c_str(), attrs & ~FILE_ATTRIBUTE_READONLY),
+  MONOTONE_ERROR(SetFileAttributes(name.c_str(), attrs & ~FILE_ATTRIBUTE_READONLY),
     origin::system,
     F("SetFileAttributes(%s) failed: %s")
     % name % os_strerror(GetLastError()));
@@ -395,14 +395,14 @@ rename_clobberingly(std::string const & 
     if (sleepTime < 250)
       sleepTime *= 2;
   }
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("renaming '%s' to '%s' failed: %s (%d)") % from % to
       % os_strerror(lastError) % lastError);
 }
 
 // Create a temporary file in directory DIR, writing its name to NAME and
 // returning a read-write file descriptor for it.  If unable to create
-// the file, throws an E().
+// the file, throws an MONOTONE_ERROR().
 //
 // N.B. We could use GetTempFileName but it wouldn't help significantly, as
 // we want to do the CreateFile ourselves (eventually we will want to
@@ -456,7 +456,7 @@ make_temp_file(std::string const & dir, 
       // ERROR_ALREADY_EXISTS means we should go 'round again.  Any other
       // GetLastError() value is a plain error.  (Presumably, just as for
       // Unix, there are values that would represent bugs.)
-      E(GetLastError() == ERROR_ALREADY_EXISTS, origin::system,
+      MONOTONE_ERROR(GetLastError() == ERROR_ALREADY_EXISTS, origin::system,
         F("cannot create temp file '%s': %s")
         % tmp % os_strerror(GetLastError()));
 
@@ -464,7 +464,7 @@ make_temp_file(std::string const & dir, 
       // 'value' will visit every number in its range.
       value += 7777;
     }
-  E(false, origin::system,
+  MONOTONE_ERROR(false, origin::system,
     F("cannot find a temporary file (tried %d possibilities)") % limit);
 }
 
@@ -516,7 +516,7 @@ write_data_worker(std::string const & fn
     do
       {
         DWORD written;
-        E(WriteFile(h, (LPCVOID)ptr, remaining, &written, (LPOVERLAPPED)0),
+        MONOTONE_ERROR(WriteFile(h, (LPCVOID)ptr, remaining, &written, (LPOVERLAPPED)0),
           origin::system,
           F("error writing to temp file '%s': %s")
           % tmp % os_strerror(GetLastError()));
@@ -524,7 +524,7 @@ write_data_worker(std::string const & fn
         if (written == 0)
           {
             deadcycles++;
-            E(deadcycles < 4, origin::system,
+            MONOTONE_ERROR(deadcycles < 4, origin::system,
               FP("giving up after four zero-length writes to '%s' "
                  "(%d byte written, %d left)",
                  "giving up after four zero-length writes to '%s' "
============================================================
--- src/win32/parse_date.cc	e327b76670852e07142535c5db0521fbbbc6a2d4
+++ src/win32/parse_date.cc	f82660922cb5e201514f35863ef7d38248bd602b
@@ -20,7 +20,7 @@ void parse_date(const std::string /* s *
   // So far, parse_date is only used in the changelog processing to
   // allow the user to change the date cert. So we just disable that
   // on Win32; see cmd_ws_commit.cc get_log_message_interactively.
-  E(false, origin::system, F("date parsing not available on win32"));
+  MONOTONE_ERROR(false, origin::system, F("date parsing not available on win32"));
 }
 
 // Local Variables:
============================================================
--- src/win32/ssh_agent_platform.cc	3db66d3900b7b7a0d43642e5ff6e0a1778faf919
+++ src/win32/ssh_agent_platform.cc	9ba1a22e6ef591b5272fff1dc02facbcef6fb108
@@ -79,7 +79,7 @@ ssh_agent_platform::write_data(string co
   L(FL("ssh_agent_platform::write_data: writing %u bytes to %s")
     % data.length() % mapname);
 
-  E(data.length() < AGENT_MAX_MSGLEN, origin::system,
+  MONOTONE_ERROR(data.length() < AGENT_MAX_MSGLEN, origin::system,
     F("asked to write more than %u to pageant") %  AGENT_MAX_MSGLEN);
 
   memcpy(filemap_view, data.c_str(), data.length());
@@ -89,7 +89,7 @@ ssh_agent_platform::write_data(string co
 
   id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds);
 
-  E(id > 0, origin::system, F("error sending message to pageant (%d)") % id);
+  MONOTONE_ERROR(id > 0, origin::system, F("error sending message to pageant (%d)") % id);
 
   //Start our read counter again
   read_len = 0;
@@ -102,7 +102,7 @@ ssh_agent_platform::read_data(u32 const 
 
   L(FL("ssh_agent: read_data: asked to read %u bytes") % len);
 
-  E((read_len + len) < AGENT_MAX_MSGLEN, origin::system,
+  MONOTONE_ERROR((read_len + len) < AGENT_MAX_MSGLEN, origin::system,
     F("asked to read more than %u from pageant") % AGENT_MAX_MSGLEN);
 
   out.append(filemap_view + read_len, len);
============================================================
--- src/work.cc	2faefc419f1f3f90874a25cf60a5b0e6b35395a6
+++ src/work.cc	73fef1f51c92a675f74f9367e14f2cd052a4270b
@@ -138,7 +138,7 @@ workspace::require_workspace()
 void
 workspace::require_workspace()
 {
-  E(workspace::found, origin::user,
+  MONOTONE_ERROR(workspace::found, origin::user,
     F("workspace required but not found"));
   workspace::used = true;
 }
@@ -146,7 +146,7 @@ workspace::require_workspace(i18n_format
 void
 workspace::require_workspace(i18n_format const & explanation)
 {
-  E(workspace::found, origin::user,
+  MONOTONE_ERROR(workspace::found, origin::user,
     F("workspace required but not found\n%s") % explanation.str());
   workspace::used = true;
 }
@@ -156,7 +156,7 @@ workspace::create_workspace(options cons
                             lua_hooks & lua,
                             system_path const & new_dir)
 {
-  E(!new_dir.empty(), origin::user, F("invalid directory ''"));
+  MONOTONE_ERROR(!new_dir.empty(), origin::user, F("invalid directory ''"));
 
   L(FL("creating workspace in %s") % new_dir);
 
@@ -164,7 +164,7 @@ workspace::create_workspace(options cons
   go_to_workspace(new_dir);
   mark_std_paths_used();
 
-  E(!directory_exists(bookkeeping_root), origin::user,
+  MONOTONE_ERROR(!directory_exists(bookkeeping_root), origin::user,
     F("monotone bookkeeping directory '%s' already exists in '%s'")
     % bookkeeping_root % new_dir);
 
@@ -230,7 +230,7 @@ workspace::get_work_rev()
     }
   catch(exception & e)
     {
-      E(false, origin::system,
+      MONOTONE_ERROR(false, origin::system,
         F("workspace is corrupt: reading '%s': %s")
         % rev_path % e.what());
     }
@@ -257,13 +257,13 @@ workspace::get_update_id()
 {
   revision_id update_id;
   bookkeeping_path update_path = get_update_path();
-  E(file_exists(update_path), origin::user,
+  MONOTONE_ERROR(file_exists(update_path), origin::user,
     F("no update has occurred in this workspace"));
 
   data update_data = read_data(update_path);
   update_id = revision_id(decode_hexenc(update_data(), origin::internal),
                           origin::internal);
-  E(!null_id(update_id), origin::internal,
+  MONOTONE_ERROR(!null_id(update_id), origin::internal,
     F("no update revision available"));
   return update_id;
 }
@@ -295,7 +295,7 @@ get_roster_for_rid(database & db,
     }
   else
     {
-      E(db.revision_exists(rid), origin::user,
+      MONOTONE_ERROR(db.revision_exists(rid), origin::user,
         F("base revision %s does not exist in database") % rid);
       cr = db.get_cached_roster(rid);
     }
@@ -311,7 +311,7 @@ workspace::require_parents_in_db(databas
        i != rev.edges.end(); i++)
     {
       revision_id const & parent(edge_old_revision(i));
-      E(null_id(parent) || db.revision_exists(parent), origin::user,
+      MONOTONE_ERROR(null_id(parent) || db.revision_exists(parent), origin::user,
         F("parent revision %s does not exist, did you specify the wrong database?")
         % parent);
     }
@@ -489,7 +489,7 @@ read_options_file(any_path const & optsp
 
       if (opt == "database")
         {
-          E(val != memory_db_identifier, origin::user,
+          MONOTONE_ERROR(val != memory_db_identifier, origin::user,
             F("a memory database '%s' cannot be used in a workspace")
                 % memory_db_identifier);
 
@@ -525,7 +525,7 @@ read_options_file(any_path const & optsp
         W(F("unrecognized key '%s' in options file '%s' - ignored")
           % opt % optspath);
     }
-  E(src.lookahead == EOF, src.made_from,
+  MONOTONE_ERROR(src.lookahead == EOF, src.made_from,
     F("Could not parse entire options file '%s'") % optspath);
 }
 
@@ -535,7 +535,7 @@ write_options_file(bookkeeping_path cons
 {
   basic_io::stanza st;
 
-  E(opts.dbname_type != memory_db, origin::user,
+  MONOTONE_ERROR(opts.dbname_type != memory_db, origin::user,
     F("a memory database '%s' cannot be used in a workspace")
       % memory_db_identifier);
 
@@ -636,7 +636,7 @@ workspace::set_options(options const & o
 workspace::set_options(options const & opts, lua_hooks & lua,
                        bool branch_is_sticky)
 {
-  E(workspace::found, origin::user, F("workspace required but not found"));
+  MONOTONE_ERROR(workspace::found, origin::user, F("workspace required but not found"));
 
   bookkeeping_path o_path;
   get_options_path(o_path);
@@ -719,7 +719,7 @@ workspace::print_option(utf8 const & opt
 void
 workspace::print_option(utf8 const & opt, std::ostream & output)
 {
-  E(workspace::found, origin::user, F("workspace required but not found"));
+  MONOTONE_ERROR(workspace::found, origin::user, F("workspace required but not found"));
 
   bookkeeping_path o_path;
   get_options_path(o_path);
@@ -736,7 +736,7 @@ workspace::print_option(utf8 const & opt
   else if (opt() == "keydir")
     output << opts.key_dir << '\n';
   else
-    E(false, origin::user, F("'%s' is not a recognized workspace option") % opt);
+    MONOTONE_ERROR(false, origin::user, F("'%s' is not a recognized workspace option") % opt);
 }
 
 // _MTN/bisect handling.
@@ -858,7 +858,7 @@ workspace::get_local_dump_path()
 bookkeeping_path
 workspace::get_local_dump_path()
 {
-  E(workspace::found, origin::user, F("workspace required but not found"));
+  MONOTONE_ERROR(workspace::found, origin::user, F("workspace required but not found"));
 
   bookkeeping_path d_path = bookkeeping_root / local_dump_file_name;
   L(FL("local dump path is %s") % d_path);
@@ -1132,7 +1132,7 @@ addition_builder::add_nodes_for(file_pat
   // that the roster has a root node, which will be a directory.
   if (ros.has_node(path))
     {
-      E(is_dir_t(ros.get_node(path)), origin::user,
+      MONOTONE_ERROR(is_dir_t(ros.get_node(path)), origin::user,
         F("cannot add '%s', because '%s' is recorded as a file "
           "in the workspace manifest") % goal % path);
       return;
@@ -1157,7 +1157,7 @@ addition_builder::add_nodes_for(file_pat
       nid = er.create_dir_node();
       break;
     case path::special:
-      E(false, origin::user,
+      MONOTONE_ERROR(false, origin::user,
         F("cannot handle special file '%s'") % path);
     }
 
@@ -1213,7 +1213,7 @@ addition_builder::visit_special(file_pat
       return;
     }
 
-  E(false, origin::user,
+  MONOTONE_ERROR(false, origin::user,
     F("cannot add '%s'; it is not a regular file") % path);
 }
 
@@ -1442,7 +1442,7 @@ editable_working_tree::apply_delta(file_
                        F("file '%s' does not exist") % pth,
                        F("file '%s' is a directory") % pth,
                        F("file '%s' is not a regular file") % pth);
-  E(calculate_ident(pth) == old_id, origin::system,
+  MONOTONE_ERROR(calculate_ident(pth) == old_id, origin::system,
     F("content of file '%s' has changed, not overwriting") % pth);
   P(F("updating '%s'") % pth);
 
@@ -1804,7 +1804,7 @@ workspace::update_current_roster_from_fi
 
   // Emit an error, if the caller doesn't want to cope with missing or
   // mismatched files and directories in the workspace.
-  E(missing_items == 0 || wres.get() != NULL, origin::user,
+  MONOTONE_ERROR(missing_items == 0 || wres.get() != NULL, origin::user,
     F("%d missing items; use '%s ls missing' to view.\n"
       "To restore consistency, on each missing item run either\n"
       " '%s drop ITEM' to remove it permanently, or\n"
@@ -1899,7 +1899,7 @@ workspace::perform_additions(database & 
           switch (get_path_status(path))
             {
             case path::nonexistent:
-              E(false, origin::user,
+              MONOTONE_ERROR(false, origin::user,
                 F("no such file or directory: '%s'") % path);
               break;
             case path::file:
@@ -1909,7 +1909,7 @@ workspace::perform_additions(database & 
               build.visit_dir(path);
               break;
             case path::special:
-              E(false, origin::user,
+              MONOTONE_ERROR(false, origin::user,
                 F("cannot handle special file '%s'") % path);
             }
         }
@@ -1962,7 +1962,7 @@ workspace::perform_deletions(database & 
     {
       file_path const & name(todo.front());
 
-      E(!name.empty(), origin::user,
+      MONOTONE_ERROR(!name.empty(), origin::user,
         F("unable to drop the root directory"));
 
       if (!new_roster.has_node(name))
@@ -1975,7 +1975,7 @@ workspace::perform_deletions(database & 
               const_dir_t d = downcast_to_dir_t(n);
               if (!d->children.empty())
                 {
-                  E(recursive, origin::user,
+                  MONOTONE_ERROR(recursive, origin::user,
                     F("cannot remove '%s/', it is not empty") % name);
                   for (dir_map::const_iterator j = d->children.begin();
                        j != d->children.end(); ++j)
@@ -2042,10 +2042,10 @@ workspace::perform_rename(database & db,
       file_path const & src = *srcs.begin();
       file_path dpath = dst;
 
-      E(!src.empty(), origin::user,
+      MONOTONE_ERROR(!src.empty(), origin::user,
         F("cannot rename the workspace root (try '%s pivot_root' instead)")
         % prog_name);
-      E(new_roster.has_node(src), origin::user,
+      MONOTONE_ERROR(new_roster.has_node(src), origin::user,
         F("source file '%s' is not versioned") % src);
 
       if (src == dst || dst.is_beneath_of(src))
@@ -2069,7 +2069,7 @@ workspace::perform_rename(database & db,
           // touch foo
           // mtn mv foo bar/foo where bar doesn't exist
           file_path parent = dst.dirname();
-          E(directory_exists(parent), origin::user,
+          MONOTONE_ERROR(directory_exists(parent), origin::user,
             F("destination path's parent directory '%s/' doesn't exist")
             % parent);
 
@@ -2087,16 +2087,16 @@ workspace::perform_rename(database & db,
       // 2) mv foo bar
       //    mtn mv --bookkeep-only foo bar
 
-      E(directory_exists(dst), origin::user,
+      MONOTONE_ERROR(directory_exists(dst), origin::user,
         F("destination '%s/' is not a directory") % dst);
 
       for (set<file_path>::const_iterator i = srcs.begin();
            i != srcs.end(); i++)
         {
-          E(!i->empty(), origin::user,
+          MONOTONE_ERROR(!i->empty(), origin::user,
             F("cannot rename the workspace root (try '%s pivot_root' instead)")
             % prog_name);
-          E(new_roster.has_node(*i), origin::user,
+          MONOTONE_ERROR(new_roster.has_node(*i), origin::user,
             F("source file '%s' is not versioned") % *i);
 
           file_path d = dst / i->basename();
@@ -2113,7 +2113,7 @@ workspace::perform_rename(database & db,
               // case 1)
               d = dst / i->basename();
 
-              E(!new_roster.has_node(d), origin::user,
+              MONOTONE_ERROR(!new_roster.has_node(d), origin::user,
                 F("destination '%s' already exists in the workspace manifest") % d);
             }
 
@@ -2188,13 +2188,13 @@ workspace::perform_pivot_root(database &
   MM(new_roster);
 
   I(old_roster.has_root());
-  E(old_roster.has_node(new_root), origin::user,
+  MONOTONE_ERROR(old_roster.has_node(new_root), origin::user,
     F("proposed new root directory '%s' is not versioned or does not exist")
     % new_root);
-  E(is_dir_t(old_roster.get_node(new_root)), origin::user,
+  MONOTONE_ERROR(is_dir_t(old_roster.get_node(new_root)), origin::user,
     F("proposed new root directory '%s' is not a directory") % new_root);
   {
-    E(!old_roster.has_node(new_root / bookkeeping_root_component), origin::user,
+    MONOTONE_ERROR(!old_roster.has_node(new_root / bookkeeping_root_component), origin::user,
       F("proposed new root directory '%s' contains illegal path '%s'")
       % new_root % bookkeeping_root);
   }
@@ -2204,14 +2204,14 @@ workspace::perform_pivot_root(database &
     file_path current_path_to_put_old_parent
       = current_path_to_put_old.dirname();
 
-    E(old_roster.has_node(current_path_to_put_old_parent), origin::user,
+    MONOTONE_ERROR(old_roster.has_node(current_path_to_put_old_parent), origin::user,
       F("directory '%s' is not versioned or does not exist")
       % current_path_to_put_old_parent);
-    E(is_dir_t(old_roster.get_node(current_path_to_put_old_parent)),
+    MONOTONE_ERROR(is_dir_t(old_roster.get_node(current_path_to_put_old_parent)),
       origin::user,
       F("'%s' is not a directory")
       % current_path_to_put_old_parent);
-    E(!old_roster.has_node(current_path_to_put_old),
+    MONOTONE_ERROR(!old_roster.has_node(current_path_to_put_old),
       origin::user,
       F("'%s' is in the way") % current_path_to_put_old);
   }
@@ -2251,7 +2251,7 @@ workspace::perform_content_update(roster
   bookkeeping_path detached = path_for_detached_nids();
   bool moved_conflicting = false;
 
-  E(!directory_exists(detached), origin::user,
+  MONOTONE_ERROR(!directory_exists(detached), origin::user,
     F("workspace is locked\n"
       "you must clean up and remove the %s directory")
     % detached);
@@ -2270,7 +2270,7 @@ workspace::perform_content_update(roster
   // wants them back
   if (swt.has_conflicting_paths())
     {
-      E(move_conflicting_paths, origin::user,
+      MONOTONE_ERROR(move_conflicting_paths, origin::user,
         F("re-run this command with '--move-conflicting-paths' to move "
           "conflicting paths out of the way"));
       move_conflicting_paths_into_bookkeeping(swt.get_conflicting_paths());
============================================================
--- src/work.hh	0a914719f5adbd4961a962b8e07a7467af8b064c
+++ src/work.hh	2f80920a3a1867e89933785929d386eee3b68c7f
@@ -37,7 +37,7 @@ class app_state;
 // as well as many instance methods.  class methods can be used when you're
 // not sure yet whether or not there is a workspace.  instance methods can
 // only be used if there definitely is a workspace; the workspace object
-// constructor will throw an E() if there isn't one.  (this can also be
+// constructor will throw an MONOTONE_ERROR() if there isn't one.  (this can also be
 // triggered by the class method require_workspace, for the sake of a few
 // places that need to do that but not create the workspace object yet.)
 //
============================================================
--- test/src/tester.cc	ff0fdf93f175dfc1d8dee61bb01bdc902860c653
+++ test/src/tester.cc	7687a74b445ec7f3b528bc4a6b8f9a72c8bf9639
@@ -170,7 +170,7 @@ void do_copy_recursive(string const & fr
 {
   path::status fromstat = get_path_status(from);
 
-  E(fromstat != path::nonexistent, origin::user,
+  MONOTONE_ERROR(fromstat != path::nonexistent, origin::user,
     F("Source '%s' for copy does not exist") % from);
 
   switch (get_path_status(to))
@@ -201,7 +201,7 @@ void do_copy_recursive(string const & fr
       struct file_copier copy_files(from, to);
 
       read_directory(from, copy_files, get_subdirs, get_specials);
-      E(specials.empty(), origin::user,
+      MONOTONE_ERROR(specials.empty(), origin::user,
         F("cannot copy special files in '%s'") % from);
       for (vector<string>::const_iterator i = subdirs.begin();
            i != subdirs.end(); i++)
@@ -221,14 +221,14 @@ LUAEXT(posix_umask, )
 LUAEXT(posix_umask, )
 {
   unsigned int decmask = (unsigned int)luaL_checknumber(LS, -1);
-  E(decmask <= 777, origin::user,
+  MONOTONE_ERROR(decmask <= 777, origin::user,
     F("invalid argument %d to umask") % decmask);
 
   unsigned int a = decmask / 100  % 10;
   unsigned int b = decmask / 10   % 10;
   unsigned int c = decmask / 1    % 10;
 
-  E(a <= 7 && b <= 7 && c <= 7, origin::user,
+  MONOTONE_ERROR(a <= 7 && b <= 7 && c <= 7, origin::user,
     F("invalid octal number %d in umask") % decmask);
 
   int oldmask = do_umask((a*8 + b)*8 + c);
@@ -361,7 +361,7 @@ LUAEXT(normalize_path, )
 LUAEXT(normalize_path, )
 {
   const char *pathstr = luaL_checkstring(LS, -1);
-  E(pathstr, origin::user,
+  MONOTONE_ERROR(pathstr, origin::user,
     F("%s called with an invalid parameter") % "normalize_path");
 
   lua_pushstring(LS, system_path(pathstr).as_external().c_str());
@@ -426,7 +426,7 @@ LUAEXT(require_not_root, )
 
 LUAEXT(require_not_root, )
 {
-  // E() doesn't work here, I just get "warning: " in the
+  // MONOTONE_ERROR() doesn't work here, I just get "warning: " in the
   // output.  Why?
   if (running_as_root())
     {
@@ -498,7 +498,7 @@ int test_invoker::operator()(std::string
     }
   catch (std::exception & e)
     {
-      E(false, origin::no_fault, F("test %s: %s") % testname % e.what());
+      MONOTONE_ERROR(false, origin::no_fault, F("test %s: %s") % testname % e.what());
       retcode = 124;
     }
   return retcode;
@@ -868,7 +868,7 @@ parse_command_line(int argc, char const 
   if (jxx != 0)
     jobs = jxx;
 
-  E(!run_one || (!want_help && !debugging && !list_only
+  MONOTONE_ERROR(!run_one || (!want_help && !debugging && !list_only
                  && tests_to_run.size() == 3 && jobs == 0),
     origin::user,
     F("incorrect self-invocation; -r <abs path to testsuite.lua> <abs path to work_dir> <test>"));
@@ -955,7 +955,7 @@ int main(int argc, char **argv)
           lua_lib st(tests_to_run[1], tests_to_run[0]);
           return test_invoker(st())(tests_to_run[2]);
 #else
-          E(false, origin::user,
+          MONOTONE_ERROR(false, origin::user,
             F("self-invocation should not be used on Unix\n"));
 #endif
         }
============================================================
--- test/src/unix/tester-plaf.cc	e89307c5460db6fe1a76214c34ad914f178a9988
+++ test/src/unix/tester-plaf.cc	4e1d615e4ebe4e4da34ddca7d401635e9d4372d4
@@ -38,7 +38,7 @@ time_t get_last_write_time(char const * 
   if (stat(name, &st) != 0)
     {
       const int err = errno;
-      E(false, origin::system, F("stat(%s) failed: %s") % name % os_strerror(err));
+      MONOTONE_ERROR(false, origin::system, F("stat(%s) failed: %s") % name % os_strerror(err));
     }
 
   return st.st_mtime;
@@ -50,7 +50,7 @@ void do_copy_file(string const & from, s
   int ifd, ofd;
   ifd = open(from.c_str(), O_RDONLY);
   const int err = errno;
-  E(ifd >= 0, origin::system, F("open %s: %s") % from % os_strerror(err));
+  MONOTONE_ERROR(ifd >= 0, origin::system, F("open %s: %s") % from % os_strerror(err));
   struct stat st;
   st.st_mode = 0666;  // sane default if fstat fails
   fstat(ifd, &st);
@@ -59,7 +59,7 @@ void do_copy_file(string const & from, s
     {
       const int err = errno;
       close(ifd);
-      E(false, origin::system, F("open %s: %s") % to % os_strerror(err));
+      MONOTONE_ERROR(false, origin::system, F("open %s: %s") % to % os_strerror(err));
     }
 
   ssize_t nread, nwrite;
@@ -96,21 +96,21 @@ void do_copy_file(string const & from, s
     int err = errno;
     close(ifd);
     close(ofd);
-    E(false, origin::system, F("read error copying %s to %s: %s")
+    MONOTONE_ERROR(false, origin::system, F("read error copying %s to %s: %s")
       % from % to % os_strerror(err));
   }
  write_error:  {
     int err = errno;
     close(ifd);
     close(ofd);
-    E(false, origin::system, F("write error copying %s to %s: %s")
+    MONOTONE_ERROR(false, origin::system, F("write error copying %s to %s: %s")
       % from % to % os_strerror(err));
   }
  spinning:
   {
     close(ifd);
     close(ofd);
-    E(false, origin::system,
+    MONOTONE_ERROR(false, origin::system,
       F("abandoning copy of %s to %s after four zero-length writes")
       % from % to);
   }
@@ -196,7 +196,7 @@ char * make_temp_dir()
     {
       strcpy(tmpdir, templ);
       result = mktemp(tmpdir);
-      E(result, origin::system,
+      MONOTONE_ERROR(result, origin::system,
         F("mktemp(%s) failed: %s") % tmpdir % os_strerror(errno));
       I(result == tmpdir);
 
@@ -207,11 +207,11 @@ char * make_temp_dir()
           return templ;
         }
 
-      E(errno == EEXIST, origin::system,
+      MONOTONE_ERROR(errno == EEXIST, origin::system,
         F("mkdir(%s) failed: %s") % tmpdir % os_strerror(errno));
 
       cycles++;
-      E(cycles < limit, origin::system,
+      MONOTONE_ERROR(cycles < limit, origin::system,
         F("%d temporary names are all in use") % limit);
     }
 
@@ -377,7 +377,7 @@ void prepare_for_parallel_testcases(int 
   if (jread == -1 && jwrite == -1)
     {
       int jp[2];
-      E(pipe(jp) == 0, origin::system,
+      MONOTONE_ERROR(pipe(jp) == 0, origin::system,
         F("creating jobs pipe: %s") % os_strerror(errno));
       jread = jp[0];
       jwrite = jp[1];
@@ -456,7 +456,7 @@ namespace {
               break;
             if (errno == EINTR)
               continue;
-            E(false, origin::system,
+            MONOTONE_ERROR(false, origin::system,
               F("waitpid failed: %s") % os_strerror(errno));
           }
 
@@ -500,7 +500,7 @@ void run_tests_in_children(test_enumerat
   sa.sa_handler = sigchld;
   sa.sa_flags = SA_NOCLDSTOP; // deliberate non-use of SA_RESTART
 
-  E(sigaction(SIGCHLD, &sa, &osa) == 0, origin::system,
+  MONOTONE_ERROR(sigaction(SIGCHLD, &sa, &osa) == 0, origin::system,
     F("setting SIGCHLD handler: %s") % os_strerror(errno));
 
   while (next_test(t))
============================================================
--- test/src/win32/tester-plaf.cc	645562da8321cb84ee9f1956d085528ac0892375
+++ test/src/win32/tester-plaf.cc	5ee26097eae48366f0ae3f2875eaae6b4295b3de
@@ -22,11 +22,11 @@ time_t get_last_write_time(char const * 
 {
   HANDLE h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
                         OPEN_EXISTING, 0, NULL);
-  E(h != INVALID_HANDLE_VALUE, origin::system,
+  MONOTONE_ERROR(h != INVALID_HANDLE_VALUE, origin::system,
     F("CreateFile(%s) failed: %s") % name % os_strerror(GetLastError()));
 
   FILETIME ft;
-  E(GetFileTime(h, NULL, NULL, &ft), origin::system,
+  MONOTONE_ERROR(GetFileTime(h, NULL, NULL, &ft), origin::system,
     F("GetFileTime(%s) failed: %s") % name % os_strerror(GetLastError()));
 
   CloseHandle(h);
@@ -43,7 +43,7 @@ void do_copy_file(std::string const & fr
 void do_copy_file(std::string const & from, std::string const & to)
 {
   // For once something is easier with Windows.
-  E(CopyFile(from.c_str(), to.c_str(), true), origin::system,
+  MONOTONE_ERROR(CopyFile(from.c_str(), to.c_str(), true), origin::system,
     F("copy %s to %s: %s") % from % to % os_strerror(GetLastError()));
 }
 
@@ -98,7 +98,7 @@ char * make_temp_dir()
   // GetTempFileName wants 14 characters at the end of the path.
   {
     DWORD ret = GetTempPath(DIR_MAX_SIZE - 14, dir);
-    E(ret > 0 && ret <= DIR_MAX_SIZE - 14, origin::system,
+    MONOTONE_ERROR(ret > 0 && ret <= DIR_MAX_SIZE - 14, origin::system,
       F("GetTempPath failed: %s") % os_strerror(GetLastError()));
   }
 
@@ -111,16 +111,16 @@ char * make_temp_dir()
       if (base + i == 0)
         continue;
 
-      E(GetTempFileName(dir, "MTN", base + i, name) != 0, origin::system,
+      MONOTONE_ERROR(GetTempFileName(dir, "MTN", base + i, name) != 0, origin::system,
         F("GetTempFileName failed: %s") % os_strerror(GetLastError()));
 
       if (CreateDirectory(name, NULL))
         return name;
 
-      E(GetLastError() == ERROR_ALREADY_EXISTS, origin::system,
+      MONOTONE_ERROR(GetLastError() == ERROR_ALREADY_EXISTS, origin::system,
         F("CreateDirectory(%s) failed: %s") % name % GetLastError());
     }
-  E(false, origin::system, F("All temporary directory names are already in use."));
+  MONOTONE_ERROR(false, origin::system, F("All temporary directory names are already in use."));
 }
 
 bool running_as_root()
============================================================
--- test/unit/tests/netxx_pipe.cc	2141174212668037af24060f742c06430c59e3a7
+++ test/unit/tests/netxx_pipe.cc	98c22586e6363e1d34bdaa1f0bcbcaf32d192fd7
@@ -56,7 +56,7 @@ UNIT_TEST(simple_pipe)
           probe.clear();
           probe.add(pipe, Netxx::Probe::ready_read);
           res = probe.ready(timeout);
-          E(res.second & Netxx::Probe::ready_read, origin::system,
+          MONOTONE_ERROR(res.second & Netxx::Probe::ready_read, origin::system,
             F("timeout reading data %d") % c);
 #if defined(_WIN32) || defined(_WIN64)
           I(res.first == pipe.get_socketfd());
