# # # add_file "origin_type.hh" # content [83986c9ae7a38a915c2ccd791f5409713e4c7587] # # patch "Makefile.am" # from [cc098fcd7d979e7002ab949e577ce5d6ba022dfa] # to [1e44eed9b9128fb339f2402a393f2d3601715f0c] # # patch "basic_io.hh" # from [0920e36ed9009d17aac702409276d91de13b6162] # to [c1f0e7760a1316c80a511016d8449e9903924b38] # # patch "cmd_conflicts.cc" # from [29e1876b543138cc183212139efb332db9c95983] # to [3640edcbbeef0f67e8d78a356e6e04af92a34e0c] # # patch "cmd_files.cc" # from [b8db84b8984cf84110a0ecb7b5138866d8c618c8] # to [b3e3d6f26ce057141bb46a5ac40afc6d0846e478] # # patch "cmd_netsync.cc" # from [55e8b9ceb5f555fc86b421bef7ecb57835ddd903] # to [a8a7568be78fa844600d3c7ac0a8a0d9ed781063] # # patch "cmd_othervcs.cc" # from [7efd05e12a524fdbbfa4438eb833f7c8cea190d6] # to [ca6b6d84259d7758b81cd9209d996979a757f4c5] # # patch "cmd_ws_commit.cc" # from [83bf8a9b89ee4a465ab7f6767e8eb841f59ad52d] # to [dc652103959227fea14da68af9184089dcc179cf] # # patch "database.cc" # from [5c86b91315bf645035ae0f3ecff182bb6b53a634] # to [e78cfcc12075d231f04fb0e9fd00422be5616b7d] # # patch "option.hh" # from [0f9cf0b04b3c675f23dbdbf0a0b3d1a59565edc5] # to [2d2b4949004f5ad7040601b41f78fb7c8af6beb1] # # patch "options_list.hh" # from [5b581fedf957ed2688f4d2938041dc71a5728945] # to [fc2922bfd28c0305846cbbf685cffca5e5556ffc] # # patch "paths.cc" # from [a53b0c0a5948913606695990415f5138fd363b36] # to [3dbef065748bfed896a414be6c370a9e154f3d77] # # patch "paths.hh" # from [edb57b0c1b475e6c1fa9605b04cc78bf09b92f29] # to [dc8439eff099b017dacdb4220da15142a8dbdf30] # # patch "revision.cc" # from [00e3d526df53116e91516b34cf842e3f5855191b] # to [dfe64e39257b207622000d2d46869c3761cd5b30] # # patch "sanity.cc" # from [e0e720eee44daac55658d052e1228cacf40db178] # to [f3a45e23411c78323154066a9d0deaa398d14e45] # # patch "sanity.hh" # from [54140473a7a17d68c30ed9a5755ddff2451fed7a] # to [0f1f754d269c4ee6ed16e5e1d1865b492f0a5c71] # # patch "transforms.cc" # from [ef82ffcfd001598c224e1fffc4ad2fe4bb7fe8e7] # to [9c171dc101906f2eafda1d1bcb8ba5c46ac1bc80] # # patch "transforms.hh" # from [49fbc9dd50c870a1bc0c379117622382665033b8] # to [f6a91fd1ca667f76e8a84da4358e323988d7bdaa] # # patch "work.cc" # from [c5b0e24f7df69d1a0f32da5d1da3d91a5c462a5a] # to [6ef327477ba19f52cb2b11baa48b1c2dd3c37e7f] # ============================================================ --- origin_type.hh 83986c9ae7a38a915c2ccd791f5409713e4c7587 +++ origin_type.hh 83986c9ae7a38a915c2ccd791f5409713e4c7587 @@ -0,0 +1,24 @@ +#ifndef __ORIGIN_TYPE_HH__ +#define __ORIGIN_TYPE_HH__ + +// sanity.cc:type_to_string(type t) will need to match this +namespace origin { + enum type { + internal, + network, + database, + workspace, + system, + user, + no_fault + }; +} + +// Local Variables: +// mode: C++ +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: + +#endif ============================================================ --- Makefile.am cc098fcd7d979e7002ab949e577ce5d6ba022dfa +++ Makefile.am 1e44eed9b9128fb339f2402a393f2d3601715f0c @@ -10,7 +10,7 @@ SANITY_CORE_SOURCES = \ sanity.cc sanity.hh quick_alloc.hh vector.hh base.hh \ simplestring_xform.cc simplestring_xform.hh \ constants.cc constants.hh numeric_vocab.hh \ - platform.hh numeric_vocab.cc + platform.hh numeric_vocab.cc origin_type.hh LUAEXT_SOURCES = \ vocab.hh vocab.cc vocab_terms.hh vocab_macros.hh vocab_cast.hh \ ============================================================ --- basic_io.hh 0920e36ed9009d17aac702409276d91de13b6162 +++ basic_io.hh c1f0e7760a1316c80a511016d8449e9903924b38 @@ -66,6 +66,10 @@ namespace basic_io : line(1), col(1), in(in), curr(in.begin()), name(nm), lookahead(0), c('\0') {} + input_source(std::string const & in, std::string const & nm, origin::type w) + : origin_aware(w), line(1), col(1), in(in), curr(in.begin()), + name(nm), lookahead(0), c('\0') + {} inline void peek() { ============================================================ --- cmd_conflicts.cc 29e1876b543138cc183212139efb332db9c95983 +++ cmd_conflicts.cc 3640edcbbeef0f67e8d78a356e6e04af92a34e0c @@ -296,7 +296,7 @@ set_first_conflict(database & db, E(bookkeeping_path::external_string_is_bookkeeping_path(utf8(idx(args,1)())), origin::user, F("result path must be under _MTN")); - bookkeeping_path const result_path(idx(args,1)()); + bookkeeping_path const result_path(idx(args,1)(), origin::user); if (do_interactive_merge(db, lua, conflicts, conflict.nid, conflict.ancestor, conflict.left, conflict.right, result_path)) ============================================================ --- cmd_files.cc b8db84b8984cf84110a0ecb7b5138866d8c618c8 +++ cmd_files.cc b3e3d6f26ce057141bb46a5ac40afc6d0846e478 @@ -330,7 +330,7 @@ CMD_AUTOMATE(get_file, N_("FILEID"), F("wrong argument count")); database db(app); - hexenc hident(idx(args, 0)()); + hexenc hident(idx(args, 0)(), origin::user); file_id ident(decode_hexenc_as(hident(), hident.made_from)); dump_file(db, output, ident); } ============================================================ --- cmd_netsync.cc 55e8b9ceb5f555fc86b421bef7ecb57835ddd903 +++ cmd_netsync.cc a8a7568be78fa844600d3c7ac0a8a0d9ed781063 @@ -336,7 +336,7 @@ CMD(clone, "clone", "", CMD_REF(network) if (args.size() == 2) { // No checkout dir specified, use branch name for dir. - workspace_dir = system_path(branchname()); + workspace_dir = system_path(branchname(), origin::user); } else { @@ -349,7 +349,7 @@ CMD(clone, "clone", "", CMD_REF(network) // remember the initial working dir so that relative file:// // db URIs will work - system_path start_dir(get_current_working_dir()); + system_path start_dir(get_current_working_dir(), origin::system); bool internal_db = !app.opts.dbname_given || app.opts.dbname.empty(); ============================================================ --- cmd_othervcs.cc 7efd05e12a524fdbbfa4438eb833f7c8cea190d6 +++ cmd_othervcs.cc ca6b6d84259d7758b81cd9209d996979a757f4c5 @@ -29,7 +29,7 @@ CMD(rcs_import, "rcs_import", "", CMD_RE for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i) - test_parse_rcs_file(system_path((*i)())); + test_parse_rcs_file(system_path((*i)(), origin::user)); } @@ -48,7 +48,7 @@ CMD(cvs_import, "cvs_import", "", CMD_RE E(app.opts.branchname() != "", origin::user, F("need base --branch argument for importing")); - system_path cvsroot(idx(args, 0)()); + system_path cvsroot(idx(args, 0)(), origin::user); require_path_is_directory(cvsroot, F("path %s does not exist") % cvsroot, F("'%s' is not a directory") % cvsroot); ============================================================ --- cmd_ws_commit.cc 83bf8a9b89ee4a465ab7f6767e8eb841f59ad52d +++ cmd_ws_commit.cc dc652103959227fea14da68af9184089dcc179cf @@ -669,7 +669,7 @@ CMD(checkout, "checkout", "co", CMD_REF( // No checkout dir specified, use branch name for dir. E(!app.opts.branchname().empty(), origin::user, F("you must specify a destination directory")); - dir = system_path(app.opts.branchname()); + dir = system_path(app.opts.branchname(), origin::user); } else { @@ -1362,7 +1362,7 @@ CMD_NO_WORKSPACE(setup, "setup", "", CMD else dir = "."; - workspace::create_workspace(app.opts, app.lua, dir); + workspace::create_workspace(app.opts, app.lua, system_path(dir, origin::user)); workspace work(app); revision_t rev; ============================================================ --- database.cc 5c86b91315bf645035ae0f3ecff182bb6b53a634 +++ database.cc e78cfcc12075d231f04fb0e9fd00422be5616b7d @@ -3735,7 +3735,7 @@ database_impl::check_db_nonexistent() F("database %s already exists") % filename); - system_path journal(filename.as_internal() + "-journal"); + system_path journal(filename.as_internal() + "-journal", origin::internal); require_path_is_nonexistent(journal, F("existing (possibly stale) journal file '%s' " "has same stem as new database '%s'\n" ============================================================ --- option.hh 0f9cf0b04b3c675f23dbdbf0a0b3d1a59565edc5 +++ option.hh 2d2b4949004f5ad7040601b41f78fb7c8af6beb1 @@ -29,6 +29,7 @@ public: public: explicit arg_type(void) : utf8() {} explicit arg_type(std::string const & s) : utf8(s) {} + arg_type(std::string const & s, origin::type f) : utf8(s, f) {} explicit arg_type(utf8 const & u) : utf8(u) {} }; template <> ============================================================ --- options_list.hh 5b581fedf957ed2688f4d2938041dc71a5728945 +++ options_list.hh fc2922bfd28c0305846cbbf685cffca5e5556ffc @@ -54,20 +54,24 @@ OPTVAR(globals, type, name, default_) \ OPTION(globals, name, has_arg(), string, description) +// because 'default_' is constructor arguments, and may need to be a list +// This doesn't work if fed through the OPT / GOPT shorthand versions +#define COMMA , + OPTSET(globals) OPTVAR(globals, args_vector, args, ) OPTION(globals, positionals, true, "--", "") #ifdef option_bodies { - args.push_back(arg_type(arg)); + args.push_back(arg_type(arg, origin::user)); } #endif OPT(author, "author", utf8, , gettext_noop("override author for commit")) #ifdef option_bodies { - author = utf8(arg); + author = utf8(arg, origin::user); } #endif @@ -90,7 +94,7 @@ OPTION(bind_opts, bind, true, "bind", gettext_noop("address:port to listen on (default :4691)")) #ifdef option_bodies { - bind_uris.push_back(utf8(arg)); + bind_uris.push_back(utf8(arg, origin::user)); bind_stdio = false; } #endif @@ -114,7 +118,7 @@ OPTION(branch, branch, true, "branch,b", gettext_noop("select branch cert for operation")) #ifdef option_bodies { - branchname = branch_name(arg); + branchname = branch_name(arg, origin::user); } #endif @@ -134,11 +138,14 @@ OPT(revs_only, "revs-only", bool, false, } #endif -GOPT(conf_dir, "confdir", system_path, get_default_confdir(), - gettext_noop("set location of configuration directory")) +//GOPT(conf_dir, "confdir", system_path, get_default_confdir() COMMA origin::user, +// gettext_noop("set location of configuration directory")) +OPTVAR(globals, system_path, conf_dir, get_default_confdir() COMMA origin::user) +OPTION(globals, conf_dir, true, "confdir", + gettext_noop("set location of configuration directory")) #ifdef option_bodies { - conf_dir = system_path(arg); + conf_dir = system_path(arg, origin::user); if (!key_dir_given) key_dir = (conf_dir / "keys"); } @@ -170,7 +177,7 @@ GOPT(dbname, "db,d", system_path, , gett GOPT(dbname, "db,d", system_path, , gettext_noop("set name of database")) #ifdef option_bodies { - dbname = system_path(arg); + dbname = system_path(arg, origin::user); } #endif @@ -282,7 +289,7 @@ OPTION(globals, dump, true, "dump", gettext_noop("file to dump debugging log to, on failure")) #ifdef option_bodies { - global_sanity.set_dump_path(system_path(arg).as_external()); + global_sanity.set_dump_path(system_path(arg, origin::user).as_external()); } #endif @@ -291,7 +298,7 @@ OPTION(exclude, exclude, true, "exclude" gettext_noop("leave out anything described by its argument")) #ifdef option_bodies { - exclude_patterns.push_back(arg_type(arg)); + exclude_patterns.push_back(arg_type(arg, origin::user)); } #endif @@ -345,7 +352,7 @@ OPTION(include, include, true, "include" gettext_noop("include anything described by its argument")) #ifdef option_bodies { - include_patterns.push_back(arg_type(arg)); + include_patterns.push_back(arg_type(arg, origin::user)); } #endif @@ -362,15 +369,17 @@ OPTION(globals, key, true, "key,k", gett OPTION(globals, key, true, "key,k", gettext_noop("set key for signatures")) #ifdef option_bodies { - internalize_rsa_keypair_id(utf8(arg), signing_key); + internalize_rsa_keypair_id(utf8(arg, origin::user), signing_key); } #endif -GOPT(key_dir, "keydir", system_path, get_default_keydir(), - gettext_noop("set location of key store")) +//GOPT(key_dir, "keydir", system_path, get_default_keydir() COMMA origin::user, +// gettext_noop("set location of key store")) +OPTVAR(globals, system_path, key_dir, get_default_keydir() COMMA origin::user) +OPTION(globals, key_dir, true, "keydir", gettext_noop("set location of key store")) #ifdef option_bodies { - key_dir = system_path(arg); + key_dir = system_path(arg, origin::user); } #endif @@ -380,7 +389,7 @@ OPTION(key_to_push, key_to_push, true, " #ifdef option_bodies { rsa_keypair_id keyid; - internalize_rsa_keypair_id(utf8(arg), keyid); + internalize_rsa_keypair_id(utf8(arg, origin::user), keyid); keys_to_push.push_back(keyid); } #endif @@ -398,7 +407,7 @@ OPTION(globals, log, true, "log", gettex OPTION(globals, log, true, "log", gettext_noop("file to write the log to")) #ifdef option_bodies { - ui.redirect_log_to(system_path(arg)); + ui.redirect_log_to(system_path(arg, origin::user)); } #endif @@ -417,7 +426,7 @@ OPTION(messages, msgfile, true, "message gettext_noop("set filename containing commit changelog message")) #ifdef option_bodies { - msgfile = utf8(arg); + msgfile = utf8(arg, origin::user); } #endif OPTION(messages, no_prefix, false, "no-prefix", @@ -498,7 +507,7 @@ OPT(pidfile, "pid-file", system_path, , gettext_noop("record process id of server")) #ifdef option_bodies { - pidfile = system_path(arg); + pidfile = system_path(arg, origin::user); } #endif @@ -516,7 +525,7 @@ GOPT(extra_rcfiles, "rcfile", args_vecto gettext_noop("load extra rc file")) #ifdef option_bodies { - extra_rcfiles.push_back(arg_type(arg)); + extra_rcfiles.push_back(arg_type(arg, origin::user)); } #endif @@ -543,7 +552,7 @@ OPTION(revision, revision, true, "revisi gettext_noop("select revision id for operation")) #ifdef option_bodies { - revision_selectors.push_back(arg_type(arg)); + revision_selectors.push_back(arg_type(arg, origin::user)); } #endif @@ -590,14 +599,14 @@ OPT(from, "from", args_vector, , gettext OPT(from, "from", args_vector, , gettext_noop("revision(s) to start logging at")) #ifdef option_bodies { - from.push_back(arg_type(arg)); + from.push_back(arg_type(arg, origin::user)); } #endif OPT(to, "to", args_vector, , gettext_noop("revision(s) to stop logging at")) #ifdef option_bodies { - to.push_back(arg_type(arg)); + to.push_back(arg_type(arg, origin::user)); } #endif @@ -681,10 +690,10 @@ 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)), + E(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); + resolve_conflicts_file = bookkeeping_path(arg, origin::user); } #endif @@ -707,10 +716,10 @@ 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)), + E(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); + conflicts_file = bookkeeping_path(arg, origin::user); } #endif ============================================================ --- paths.cc a53b0c0a5948913606695990415f5138fd363b36 +++ paths.cc 3dbef065748bfed896a414be6c370a9e154f3d77 @@ -84,7 +84,8 @@ save_initial_path() save_initial_path() { // FIXME: BUG: this only works if the current working dir is in utf8 - initial_abs_path.set(system_path(get_current_working_dir()), false); + initial_abs_path.set(system_path(get_current_working_dir(), + origin::system), false); L(FL("initial abs path is: %s") % initial_abs_path.get_but_unused()); } @@ -287,7 +288,7 @@ normalize_path(string const & in) #ifdef WIN32 else { - I(inT[1] == ':'); + I(inT.size() > 1 && inT[1] == ':'); if (inT.size() > 2 && inT[2] == '/') { leader = inT.substr(0, 3); @@ -477,13 +478,21 @@ file_path::file_path(file_path::source_t I(is_valid_internal(data)); } -bookkeeping_path::bookkeeping_path(string const & path) +bookkeeping_path::bookkeeping_path(char const * const path) { I(fully_normalized_path(path)); I(in_bookkeeping_dir(path)); data = path; } +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, + F("Bookkeeping path is not in bookkeeping dir")); + data = path; +} + bool bookkeeping_path::external_string_is_bookkeeping_path(utf8 const & path) { @@ -759,7 +768,7 @@ bookkeeping_path::operator /(char const I(!is_absolute_somewhere(to_append)); I(!empty()); return bookkeeping_path(((*(data.end() - 1) == '/') ? data : data + "/") - + to_append); + + to_append, origin::internal); } system_path @@ -768,7 +777,7 @@ system_path::operator /(char const * to_ I(!empty()); I(!is_absolute_here(to_append)); return system_path(((*(data.end() - 1) == '/') ? data : data + "/") - + to_append); + + to_append, origin::internal); } /////////////////////////////////////////////////////////////////////////// @@ -803,16 +812,23 @@ static inline string const_system_path(u + "/" + path()); } -system_path::system_path(string const & path) +system_path::system_path(string const & path, origin::type from) { - data = const_system_path(utf8(path)); + data = const_system_path(utf8(path, from)); } +system_path::system_path(char const * const path) +{ + data = const_system_path(utf8(path, origin::internal)); +} + system_path::system_path(utf8 const & path) { data = const_system_path(utf8(path)); } +// If this wasn't a user-supplied path, we should know +// which kind it is. boost::shared_ptr new_optimal_path(std::string path, bool to_workspace_root) { @@ -825,11 +841,11 @@ new_optimal_path(std::string path, bool catch (recoverable_failure &) { // not in workspace - return boost::shared_ptr(new system_path(path)); + return boost::shared_ptr(new system_path(path, origin::user)); } if (in_bookkeeping_dir(normalized)) - return boost::shared_ptr(new bookkeeping_path(normalized)); + return boost::shared_ptr(new bookkeeping_path(normalized, origin::user)); else return boost::shared_ptr(new file_path(file_path_internal(normalized))); }; @@ -947,12 +963,12 @@ find_and_go_to_workspace(string const & } else I(false); #else - root = system_path("/"); + root = system_path("/", origin::internal); #endif } else { - root = system_path(search_root); + root = system_path(search_root, origin::user); L(FL("limiting search for workspace to %s") % root); require_path_is_directory(root, @@ -1521,7 +1537,8 @@ static void check_bk_normalizes_to(char bookkeeping_path bp(bookkeeping_root / before); L(FL("normalizing %s to %s (got %s)") % before % after % bp); UNIT_TEST_CHECK(bp.as_external() == after); - UNIT_TEST_CHECK(bookkeeping_path(bp.as_internal()).as_internal() == bp.as_internal()); + UNIT_TEST_CHECK(bookkeeping_path(bp.as_internal(), + origin::internal).as_internal() == bp.as_internal()); } UNIT_TEST(paths, bookkeeping) @@ -1548,9 +1565,10 @@ UNIT_TEST(paths, bookkeeping) for (char const * const * c = baddies; *c; ++c) { L(FL("test_bookkeeping_path baddie: trying '%s'") % *c); - UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign(*c)), - logic_error); - UNIT_TEST_CHECK_THROW(bookkeeping_root / *c, logic_error); + UNIT_TEST_CHECK_THROW(bookkeeping_path(tmp_path_string.assign(*c), + origin::internal), + logic_error); + UNIT_TEST_CHECK_THROW(bookkeeping_root / *c, logic_error); } // these are legitimate as things to append to bookkeeping_root, but @@ -1571,7 +1589,8 @@ static void check_system_normalizes_to(c system_path sp(before); L(FL("normalizing '%s' to '%s' (got '%s')") % before % after % sp); UNIT_TEST_CHECK(sp.as_external() == after); - UNIT_TEST_CHECK(system_path(sp.as_internal()).as_internal() == sp.as_internal()); + UNIT_TEST_CHECK(system_path(sp.as_internal(), + origin::internal).as_internal() == sp.as_internal()); } UNIT_TEST(paths, system) @@ -1626,7 +1645,7 @@ UNIT_TEST(paths, system) == "/a/b/~this_user_does_not_exist_anywhere"); #else UNIT_TEST_CHECK_THROW(system_path("~this_user_does_not_exist_anywhere"), - unrecoverable_failure); + recoverable_failure); #endif // finally, make sure that the copy-from-any_path constructor works right ============================================================ --- paths.hh edb57b0c1b475e6c1fa9605b04cc78bf09b92f29 +++ paths.hh dc8439eff099b017dacdb4220da15142a8dbdf30 @@ -102,6 +102,7 @@ // it were a string #include +#include "origin_type.hh" class any_path; class file_path; @@ -312,7 +313,8 @@ public: // path _should_ contain the leading _MTN/ // and _should_ look like an internal path // usually you should just use the / operator as a constructor! - bookkeeping_path(std::string const &); + explicit bookkeeping_path(char const * const path); + bookkeeping_path(std::string const &, origin::type made_from); bookkeeping_path operator /(char const *) const; bookkeeping_path operator /(path_component const &) const; @@ -366,8 +368,9 @@ public: // this path can contain anything, and it will be absolutified and // tilde-expanded. it will considered to be relative to the directory // monotone started in. it should be in utf8. - system_path(std::string const & path); - system_path(utf8 const & path); + explicit system_path(char const * const path); + system_path(std::string const & path, origin::type from); + explicit system_path(utf8 const & path); bool operator==(const system_path & other) const { return data== other.data; } ============================================================ --- revision.cc 00e3d526df53116e91516b34cf842e3f5855191b +++ revision.cc dfe64e39257b207622000d2d46869c3761cd5b30 @@ -75,7 +75,7 @@ void revision_t::check_sane() const { for (edge_map::const_iterator i = edges.begin(); i != edges.end(); ++i) - I(null_id(edge_old_revision(i))); + E(null_id(edge_old_revision(i)), made_from, F("Revision has no manifest id")); } if (edges.size() == 1) @@ -86,11 +86,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) - I(!null_id(edge_old_revision(i))); + E(!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 - I(false); + E(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. @@ -2001,7 +2002,7 @@ UNIT_TEST(revision, from_network) UNIT_TEST_CHECK_THROW(read_revision(data(bad_revisions[i], origin::network), rev), - bad_decode); + recoverable_failure); } } ============================================================ --- sanity.cc e0e720eee44daac55658d052e1228cacf40db178 +++ sanity.cc f3a45e23411c78323154066a9d0deaa398d14e45 @@ -52,6 +52,8 @@ origin::type_to_string(origin::type t) return string("system"); case user: return string("user"); + case workspace: + return string("workspace"); case no_fault: return string("general"); default: @@ -365,8 +367,10 @@ sanity::generic_failure(char const * exp { prefix = _("error: "); } + string detection_msg((F("detected at %s:%d") % file % line).str()); string message; - prefix_lines_with(prefix, do_format(explain, file, line), message); + prefix_lines_with(prefix, detection_msg + string("\n") + + do_format(explain, file, line), message); switch (caused_by) { case origin::database: ============================================================ --- sanity.hh 54140473a7a17d68c30ed9a5755ddff2451fed7a +++ sanity.hh 0f1f754d269c4ee6ed16e5e1d1865b492f0a5c71 @@ -17,6 +17,7 @@ #include "i18n.h" #include "numeric_vocab.hh" +#include "origin_type.hh" // our assertion / sanity / error logging system *was* based on GNU Nana, // but we're only using a small section of it, and have anyways rewritten @@ -27,14 +28,6 @@ namespace origin { // internal failure but a suggestion that they do something differently. namespace origin { - enum type { - internal, - network, - database, - system, - user, - no_fault - }; std::string type_to_string(type t); } ============================================================ --- transforms.cc ef82ffcfd001598c224e1fffc4ad2fe4bb7fe8e7 +++ transforms.cc 9c171dc101906f2eafda1d1bcb8ba5c46ac1bc80 @@ -197,6 +197,13 @@ SPECIALIZE_XFORM(Gzip_Decompression,); SPECIALIZE_XFORM(Gzip_Compression,); SPECIALIZE_XFORM(Gzip_Decompression,); +template <> +std::string decode_base64_as(std::string const & in, + origin::type made_from) +{ + return xform(in, made_from); +} + template void pack(T const & in, base64< gzip > & out) { ============================================================ --- transforms.hh 49fbc9dd50c870a1bc0c379117622382665033b8 +++ transforms.hh f6a91fd1ca667f76e8a84da4358e323988d7bdaa @@ -71,6 +71,11 @@ T decode_base64_as(std::string const & i { return T(xform(in, made_from), made_from); } + +template <> +std::string decode_base64_as(std::string const & in, + origin::type made_from); + // hex encoding template ============================================================ --- work.cc c5b0e24f7df69d1a0f32da5d1da3d91a5c462a5a +++ work.cc 6ef327477ba19f52cb2b11baa48b1c2dd3c37e7f @@ -379,7 +379,7 @@ read_options_file(any_path const & optsp return; } - basic_io::input_source src(dat(), optspath.as_external()); + basic_io::input_source src(dat(), optspath.as_external(), origin::workspace); basic_io::tokenizer tok(src); basic_io::parser parser(tok); @@ -390,13 +390,13 @@ read_options_file(any_path const & optsp parser.str(val); if (opt == "database") - database_option = system_path(val); + database_option = system_path(val, origin::workspace); else if (opt == "branch") - branch_option = branch_name(val); + branch_option = branch_name(val, origin::workspace); else if (opt == "key") - internalize_rsa_keypair_id(utf8(val), key_option); + internalize_rsa_keypair_id(utf8(val, origin::workspace), key_option); else if (opt == "keydir") - keydir_option = system_path(val); + keydir_option = system_path(val, origin::workspace); else W(F("unrecognized key '%s' in options file %s - ignored") % opt % optspath);