# # # patch "database.cc" # from [026b0f32727c3e31be115a47a4b8de251078151a] # to [4a62da575517d7a24bdb94af91640add74741890] # # patch "lua_hooks.cc" # from [d4f06492ebfd19893156cf0021b7afef29009332] # to [18c9ed5ddb20d87c70d74fe97e937ebf445321e3] # # patch "lua_hooks.hh" # from [e4bfa01a091e43739f11ecfc0b6c096e089b127e] # to [198011aaa5084c022666be48a90459018a4d1dc9] # # patch "std_hooks.lua" # from [a8ce32582e19e799eef97ddb45e91418c8b24fcc] # to [b965d8e41cfce34ab52ca077f4ed8d59199bb254] # ============================================================ --- database.cc 026b0f32727c3e31be115a47a4b8de251078151a +++ database.cc 4a62da575517d7a24bdb94af91640add74741890 @@ -208,7 +208,7 @@ public: // for scoped_ptr's sake public: - explicit database_impl(system_path const & f, bool mem, + explicit database_impl(system_path const & f, bool mem, lua_hooks & lua, system_path const & roster_cache_performance_log); ~database_impl(); @@ -217,8 +217,9 @@ private: // // --== Opening the database and schema checking ==-- // - system_path const filename; + system_path filename; bool use_memory_db; + lua_hooks & lua; struct sqlite3 * __sql; void install_functions(); @@ -227,6 +228,7 @@ private: void check_filename(); void check_db_exists(); void check_db_nonexistent(); + bool find_database_file(); void open(); void close(); void check_format(); @@ -458,10 +460,11 @@ sqlite3_hex_fn(sqlite3_context *f, int n } #endif -database_impl::database_impl(system_path const & f, bool mem, +database_impl::database_impl(system_path const & f, bool mem, lua_hooks & lua, system_path const & roster_cache_performance_log) : filename(f), use_memory_db(mem), + lua(lua), __sql(NULL), transaction_level(0), roster_cache(constants::db_roster_cache_sz, @@ -505,7 +508,7 @@ database::database(app_state & app) boost::shared_ptr & i = app.dbcache->dbs[app.opts.dbname]; if (!i) i.reset(new database_impl(app.opts.dbname, app.opts.dbname_is_memory, - app.opts.roster_cache_performance_log)); + lua, app.opts.roster_cache_performance_log)); imp = i; } @@ -4443,7 +4446,8 @@ database_impl::check_db_exists() return; case path::nonexistent: - E(false, origin::user, F("database %s does not exist") % filename); + E(find_database_file(), origin::user, F("database %s does not exist") % filename); + return; case path::directory: if (directory_is_workspace(filename)) @@ -4475,6 +4479,69 @@ database_impl::check_db_nonexistent() } + +bool +database_impl::find_database_file() +{ + // exit early if the file is found + if (file_exists(filename)) + return true; + + // only pick the base name of the non-existing path + path_component basename = filename.basename(); + std::vector candidates; + std::vector search_paths; + + E(lua.hook_get_default_database_locations(search_paths), origin::system, + F("could not query default database locations")); + + for (std::vector::const_iterator i = search_paths.begin(); + i != search_paths.end(); ++i) + { + if (file_exists((*i) / basename)) + { + candidates.push_back((*i) / basename); + continue; + } + + size_t pos = basename().rfind('.'); + if (pos != std::string::npos && basename().substr(pos + 1) != "mtn") + { + path_component basename_with_ext( + basename() + ".mtn", origin::internal + ); + + if (file_exists((*i) / basename_with_ext)) + { + candidates.push_back((*i) / basename_with_ext); + continue; + } + } + } + + MM(candidates); + + if (candidates.size() == 0) + return false; + + if (candidates.size() == 1) + return true; + + if (candidates.size() > 1) + { + string err = + (F("the database '%s' has multiple ambiguous expansions:") % filename).str(); + + for (std::vector::const_iterator i = candidates.begin(); + i != candidates.end(); ++i) + err += ("\n" + (*i).as_internal()); + + E(false, origin::user, i18n_format(err)); + } + + I(false); +} + void database_impl::open() { @@ -4485,6 +4552,7 @@ database_impl::open() to_open = ":memory:"; else to_open = filename.as_external(); + if (sqlite3_open(to_open.c_str(), &__sql) == SQLITE_NOMEM) throw std::bad_alloc(); ============================================================ --- lua_hooks.cc d4f06492ebfd19893156cf0021b7afef29009332 +++ lua_hooks.cc 18c9ed5ddb20d87c70d74fe97e937ebf445321e3 @@ -653,7 +653,22 @@ lua_hooks::hook_get_date_format_spec(dat return exec_ok; } +bool lua_hooks::hook_get_default_database_locations(std::vector & out) +{ + Lua ll(st); + ll.func("get_default_database_locations"); + ll.call(0, 1); + ll.begin(); + while (ll.next()) + { + std::string path; + ll.extract_str(path).pop(); + out.push_back(system_path(path, origin::user)); + } + return ll.ok() && !out.empty(); +} + bool lua_hooks::hook_hook_wrapper(std::string const & func_name, std::vector const & args, std::string & out) ============================================================ --- lua_hooks.hh e4bfa01a091e43739f11ecfc0b6c096e089b127e +++ lua_hooks.hh 198011aaa5084c022666be48a90459018a4d1dc9 @@ -128,6 +128,8 @@ public: bool hook_get_date_format_spec(date_format_spec in, std::string & out); + bool hook_get_default_database_locations(std::vector & out); + // workspace hooks bool hook_use_inodeprints(); ============================================================ --- std_hooks.lua a8ce32582e19e799eef97ddb45e91418c8b24fcc +++ std_hooks.lua b965d8e41cfce34ab52ca077f4ed8d59199bb254 @@ -1256,10 +1256,16 @@ function get_default_command_options(com end function get_default_command_options(command) - local default_args = {} - return default_args + local default_args = {} + return default_args end +function get_default_database_locations() + local paths = {} + table.insert(paths, get_confdir() .. "/databases") + return paths +end + hook_wrapper_dump = {} hook_wrapper_dump.depth = 0 hook_wrapper_dump._string = function(s) return string.format("%q", s) end