Below is the file 'app_state.cc' from this revision. You can also download the file.
#include <iostream> #include <string> #include <vector> #ifdef WIN32 #include <io.h> /* for chdir() */ #endif #include <cstdlib> // for strtoul() #include <boost/filesystem/path.hpp> #include <boost/filesystem/operations.hpp> #include <boost/filesystem/convenience.hpp> #include <boost/filesystem/exception.hpp> #include "app_state.hh" #include "database.hh" #include "file_io.hh" #include "sanity.hh" #include "transforms.hh" #include "work.hh" // copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com> // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details using namespace std; static string const database_option("database"); static string const branch_option("branch"); static string const key_option("key"); app_state::app_state() : branch_name(""), db(""), stdhooks(true), rcfiles(true), diffs(false), search_root("/"), depth(-1), last(-1), verbose(false) { db.set_app(this); } app_state::~app_state() { } void app_state::allow_working_copy() { fs::path root = mkpath(search_root()); fs::path working; fs::path current; found_working_copy = find_working_copy(root, working, current); if (found_working_copy) { L(F("initializing from directory %s\n") % fs::initial_path().string()); L(F("found working copy directory %s\n") % working.string()); N(chdir(working.native_directory_string().c_str()) != -1, F("cannot change to directory to %s\n") % working.native_directory_string()); read_options(); string dbname = absolutify(options[database_option]()); if (dbname != "") db.set_filename(mkpath(dbname)); if (branch_name().empty()) branch_name = options[branch_option]; L(F("branch name is '%s'\n") % branch_name()); internalize_rsa_keypair_id(options[key_option], signing_key); if (!current.empty()) { relative_directory = file_path(current.native_directory_string()); L(F("relative directory is '%s'\n") % relative_directory()); } if (global_sanity.filename == "") { local_path dump_path; get_local_dump_path(dump_path); L(F("setting dump path to %s\n") % dump_path); global_sanity.filename = dump_path(); } } load_rcfiles(); } void app_state::require_working_copy() { N(found_working_copy, F("working copy directory required but not found")); write_options(); } void app_state::create_working_copy(std::string const & dir) { N(dir.size(), F("invalid directory ''")); // cd back to where we started from N(chdir(fs::initial_path().native_directory_string().c_str()) != -1, F("cannot change to initial directory %s\n") % fs::initial_path().native_directory_string()); string target = absolutify(dir); L(F("create working copy in %s\n") % target); { fs::path new_dir = mkpath(target); try { fs::create_directories(new_dir); } catch (fs::filesystem_error & err) { N(false, F("could not create directory: %s: %s\n") % err.path1().native_directory_string() % strerror(err.native_error())); } N(chdir(new_dir.native_directory_string().c_str()) != -1, F("cannot change to new directory %s\n") % new_dir.native_directory_string()); relative_directory = file_path(); } local_path mt(book_keeping_dir); N(!directory_exists(mt), F("monotone book-keeping directory '%s' already exists in '%s'\n") % book_keeping_dir % target); L(F("creating book-keeping directory '%s' for working copy in '%s'\n") % book_keeping_dir % target); mkdir_p(mt); make_branch_sticky(); write_options(); blank_user_log(); if (lua.hook_use_inodeprints()) enable_inodeprints(); load_rcfiles(); } file_path app_state::prefix(utf8 const & path) { fs::path p1 = mkpath(relative_directory()) / mkpath(path()); file_path p2(p1.normalize().string()); L(F("'%s' prefixed to '%s'\n") % path() % p2()); return p2; } void app_state::set_restriction(path_set const & valid_paths, vector<utf8> const & paths, bool respect_ignore) { // this can't be a file-global static, because file_path's initializer // depends on another global static being defined. static file_path dot("."); restrictions.clear(); for (vector<utf8>::const_iterator i = paths.begin(); i != paths.end(); ++i) { file_path p = prefix(*i); if (respect_ignore && lua.hook_ignore_file(p)) { L(F("'%s' ignored by restricted path set\n") % p()); continue; } N(p == dot || valid_paths.find(p) != valid_paths.end(), F("unknown path '%s'\n") % p()); L(F("'%s' added to restricted path set\n") % p()); restrictions.insert(p); } // if user supplied a depth but provided no paths // assume current directory if ((depth != -1) && restrictions.empty()) { restrictions.insert(dot); } } bool app_state::restriction_includes(file_path const & path) { // this can't be a file-global static, because file_path's initializer // depends on another global static being defined. static file_path dot("."); if (restrictions.empty()) { return true; } bool user_supplied_depth = (depth != -1); // a path that normalizes to "." means that the restriction has been // essentially cleared (all files are included). rather than be // careful about what goes in to the restricted path set we just // check for this special case here. if ((!user_supplied_depth) && restrictions.find(dot) != restrictions.end()) { return true; } fs::path test = mkpath(path()); long branch_depth = 0; long max_depth = depth + 1; while (!test.empty()) { L(F("checking restricted path set for '%s'\n") % test.string()); file_path p(test.string()); path_set::const_iterator i = restrictions.find(p); if (i != restrictions.end()) { L(F("path '%s' found in restricted path set; '%s' included\n") % test.string() % path()); return true; } else { L(F("path '%s' not found in restricted path set; '%s' excluded\n") % test.string() % path()); } if (user_supplied_depth && (max_depth == branch_depth)) return false; test = test.branch_path(); ++branch_depth; } if (user_supplied_depth && (restrictions.find(dot) != restrictions.end())) { return (branch_depth <= max_depth); } return false; } void app_state::set_database(utf8 const & filename) { string dbname = absolutify(filename()); if (dbname != "") db.set_filename(mkpath(dbname)); options[database_option] = utf8(dbname); } void app_state::set_branch(utf8 const & branch) { branch_name = branch(); } void app_state::make_branch_sticky() { options[branch_option] = branch_name(); } void app_state::set_signing_key(utf8 const & key) { internalize_rsa_keypair_id(key, signing_key); options[key_option] = key; } void app_state::set_root(utf8 const & path) { search_root = absolutify(path()); fs::path root = mkpath(search_root()); N(fs::exists(root), F("search root '%s' does not exist\n") % search_root); N(fs::is_directory(root), F("search root '%s' is not a directory\n") % search_root); L(F("set search root to %s\n") % search_root); } void app_state::set_message(utf8 const & m) { message = m; } void app_state::set_message_file(utf8 const & m) { message_file = m; } void app_state::set_date(utf8 const & d) { date = d; } void app_state::set_author(utf8 const & a) { author = a; } void app_state::set_depth(long d) { N(d >= 0, F("negative depth not allowed\n")); depth = d; } void app_state::set_last(long l) { N(l > 0, F("negative or zero last not allowed\n")); last = l; } void app_state::set_pidfile(utf8 const & p) { pidfile = mkpath(p()); } void app_state::add_revision(utf8 const & selector) { revision_selectors.push_back(selector); } void app_state::set_stdhooks(bool b) { stdhooks = b; } void app_state::set_rcfiles(bool b) { rcfiles = b; } void app_state::set_verbose(bool b) { verbose = b; } void app_state::add_rcfile(utf8 const & filename) { extra_rcfiles.push_back(filename); } // rc files are loaded after we've changed to the working copy directory so // that MT/monotonerc can be loaded between ~/.monotone/monotonerc and other // rcfiles void app_state::load_rcfiles() { // built-in rc settings are defaults if (stdhooks) lua.add_std_hooks(); // ~/.monotone/monotonerc overrides that, and // MT/monotonerc overrides *that* if (rcfiles) { fs::path default_rcfile; fs::path working_copy_rcfile; lua.default_rcfilename(default_rcfile); lua.working_copy_rcfilename(working_copy_rcfile); lua.load_rcfile(default_rcfile, false); lua.load_rcfile(working_copy_rcfile, false); } // command-line rcfiles override even that for (vector<utf8>::const_iterator i = extra_rcfiles.begin(); i != extra_rcfiles.end(); ++i) { lua.load_rcfile(*i); } } void app_state::read_options() { local_path o_path; get_options_path(o_path); try { if (file_exists(o_path)) { data dat; read_data(o_path, dat); read_options_map(dat, options); } } catch(std::exception & e) { W(F("Failed to read options file %s") % o_path); } } void app_state::write_options() { local_path o_path; get_options_path(o_path); try { data dat; write_options_map(dat, options); write_data(o_path, dat); } catch(std::exception & e) { W(F("Failed to write options file %s") % o_path); } }