root->add_child("SuccessfulDCPEncodes")->add_child_text(raw_convert<string>(_successful_dcp_encodes));
try {
- doc.write_to_file_formatted(path("analytics.xml").string());
+ doc.write_to_file_formatted(write_path("analytics.xml").string());
} catch (xmlpp::exception& e) {
string s = e.what ();
trim (s);
- throw FileError (s, path("analytics.xml"));
+ throw FileError (s, write_path("analytics.xml"));
}
}
try
{
cxml::Document f ("Analytics");
- f.read_file (path("analytics.xml"));
+ f.read_file (read_path("analytics.xml"));
_successful_dcp_encodes = f.number_child<int>("SuccessfulDCPEncodes");
} catch (...) {
/* Never mind */
#ifdef DCPOMATIC_WINDOWS
_win32_console = false;
#endif
- _cinemas_file = path ("cinemas.xml");
- _dkdm_recipients_file = path ("dkdm_recipients.xml");
+ _cinemas_file = read_path ("cinemas.xml");
+ _dkdm_recipients_file = read_path ("dkdm_recipients.xml");
_show_hints_before_make_dcp = true;
_confirm_kdm_email = true;
_kdm_container_name_format = dcp::NameFormat ("KDM %f %c");
/* Make a copy of the configuration */
try {
int n = 1;
- while (n < 100 && boost::filesystem::exists(path(String::compose("config.xml.%1", n)))) {
+ while (n < 100 && boost::filesystem::exists(write_path(String::compose("config.xml.%1", n)))) {
++n;
}
- boost::filesystem::copy_file(path("config.xml", false), path(String::compose("config.xml.%1", n), false));
- boost::filesystem::copy_file(path("cinemas.xml", false), path(String::compose("cinemas.xml.%1", n), false));
- boost::filesystem::copy_file(path("dkdm_recipients.xml", false), path(String::compose("dkdm_recipients.xml.%1", n), false));
+ boost::filesystem::copy_file(read_path("config.xml"), write_path(String::compose("config.xml.%1", n)));
+ boost::filesystem::copy_file(read_path("cinemas.xml"), write_path(String::compose("cinemas.xml.%1", n)));
+ boost::filesystem::copy_file(read_path("dkdm_recipients.xml"), write_path(String::compose("dkdm_recipients.xml.%1", n)));
} catch (...) {}
}
try
{
cxml::Document f ("Config");
- f.read_file (config_file ());
+ f.read_file (config_read_file());
auto version = f.optional_number_child<int> ("Version");
if (version && *version < _current_version) {
_dkdms->add (DKDMBase::read (i));
}
}
- _cinemas_file = f.optional_string_child("CinemasFile").get_value_or (path ("cinemas.xml").string ());
- _dkdm_recipients_file = f.optional_string_child("DKDMRecipientsFile").get_value_or (path("dkdm_recipients.xml").string());
+ _cinemas_file = f.optional_string_child("CinemasFile").get_value_or(read_path("cinemas.xml").string());
+ _dkdm_recipients_file = f.optional_string_child("DKDMRecipientsFile").get_value_or(read_path("dkdm_recipients.xml").string());
_show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
_confirm_kdm_email = f.optional_bool_child("ConfirmKDMEmail").get_value_or (true);
_kdm_container_name_format = dcp::NameFormat (f.optional_string_child("KDMContainerNameFormat").get_value_or ("KDM %f %c"));
root->add_child("AddFilesPath")->add_child_text(_add_files_path->string());
}
+ auto target = config_write_file();
+
try {
auto const s = doc.write_to_string_formatted ();
- boost::filesystem::path tmp (string(config_file().string()).append(".tmp"));
+ boost::filesystem::path tmp (string(target.string()).append(".tmp"));
auto f = fopen_boost (tmp, "w");
if (!f) {
throw FileError (_("Could not open file for writing"), tmp);
}
checked_fwrite (s.c_str(), s.bytes(), f, tmp);
fclose (f);
- boost::filesystem::remove (config_file());
- boost::filesystem::rename (tmp, config_file());
+ boost::filesystem::remove (target);
+ boost::filesystem::rename (tmp, target);
} catch (xmlpp::exception& e) {
string s = e.what ();
trim (s);
- throw FileError (s, config_file());
+ throw FileError (s, target);
}
}
}
}
+
bool
Config::have_existing (string file)
{
- return boost::filesystem::exists (path (file, false));
+ return boost::filesystem::exists (read_path(file));
}
+
void
Config::read_cinemas (cxml::Document const & f)
{
void
Config::save_template (shared_ptr<const Film> film, string name) const
{
- film->write_template (template_path (name));
+ film->write_template (template_write_path(name));
}
+
list<string>
Config::templates () const
{
- if (!boost::filesystem::exists (path ("templates"))) {
+ if (!boost::filesystem::exists(read_path("templates"))) {
return {};
}
list<string> n;
- for (auto const& i: boost::filesystem::directory_iterator(path("templates"))) {
+ for (auto const& i: boost::filesystem::directory_iterator(read_path("templates"))) {
n.push_back (i.path().filename().string());
}
return n;
bool
Config::existing_template (string name) const
{
- return boost::filesystem::exists (template_path (name));
+ return boost::filesystem::exists (template_read_path(name));
}
+
boost::filesystem::path
-Config::template_path (string name) const
+Config::template_read_path (string name) const
{
- return path("templates") / tidy_for_filename (name);
+ return read_path("templates") / tidy_for_filename (name);
}
+
+boost::filesystem::path
+Config::template_write_path (string name) const
+{
+ return write_path("templates") / tidy_for_filename (name);
+}
+
+
void
Config::rename_template (string old_name, string new_name) const
{
- boost::filesystem::rename (template_path (old_name), template_path (new_name));
+ boost::filesystem::rename (template_read_path(old_name), template_write_path(new_name));
}
void
Config::delete_template (string name) const
{
- boost::filesystem::remove (template_path (name));
+ boost::filesystem::remove (template_write_path(name));
}
/** @return Path to the config.xml containing the actual settings, following a link if required */
boost::filesystem::path
-Config::config_file ()
+config_file (boost::filesystem::path main)
{
cxml::Document f ("Config");
- auto main = path("config.xml", false);
if (!boost::filesystem::exists (main)) {
/* It doesn't exist, so there can't be any links; just return it */
return main;
return main;
}
+
+boost::filesystem::path
+Config::config_read_file ()
+{
+ return config_file (read_path("config.xml"));
+}
+
+
+boost::filesystem::path
+Config::config_write_file ()
+{
+ return config_file (write_path("config.xml"));
+}
+
+
void
Config::reset_cover_sheet ()
{
xmlpp::Document doc;
doc.create_root_node("Config")->add_child("Link")->add_child_text(new_file.string());
try {
- doc.write_to_file_formatted(path("config.xml", true).string());
+ doc.write_to_file_formatted(write_path("config.xml").string());
} catch (xmlpp::exception& e) {
string s = e.what ();
trim (s);
- throw FileError (s, path("config.xml"));
+ throw FileError (s, write_path("config.xml"));
}
}
Config::copy_and_link (boost::filesystem::path new_file) const
{
write ();
- boost::filesystem::copy_file (config_file(), new_file, boost::filesystem::copy_option::overwrite_if_exists);
+ boost::filesystem::copy_file (config_read_file(), new_file, boost::filesystem::copy_option::overwrite_if_exists);
link (new_file);
}
bool
Config::have_write_permission () const
{
- auto f = fopen_boost (config_file(), "r+");
+ auto f = fopen_boost (config_write_file(), "r+");
if (!f) {
return false;
}
void save_template (std::shared_ptr<const Film> film, std::string name) const;
bool existing_template (std::string name) const;
std::list<std::string> templates () const;
- boost::filesystem::path template_path (std::string name) const;
+ boost::filesystem::path template_read_path (std::string name) const;
+ boost::filesystem::path template_write_path (std::string name) const;
void rename_template (std::string old_name, std::string new_name) const;
void delete_template (std::string name) const;
static void drop ();
static void restore_defaults ();
static bool have_existing (std::string);
- static boost::filesystem::path config_file ();
+ static boost::filesystem::path config_read_file ();
+ static boost::filesystem::path config_write_file ();
private:
Config ();
extern boost::filesystem::path home_directory ();
extern bool running_32_on_64 ();
extern void unprivileged ();
-extern boost::filesystem::path config_path ();
+extern boost::filesystem::path config_path (boost::optional<std::string> version);
extern boost::filesystem::path directory_containing_executable ();
extern boost::filesystem::path fix_long_path (boost::filesystem::path path);
extern bool show_in_file_manager (boost::filesystem::path dir, boost::filesystem::path select);
boost::filesystem::path
-config_path ()
+config_path (optional<string> version)
{
boost::filesystem::path p;
p /= g_get_user_config_dir ();
p /= "dcpomatic2";
+ if (version) {
+ p /= *version;
+ }
return p;
}
boost::filesystem::path
-config_path ()
+config_path (optional<string> version)
{
boost::filesystem::path p;
p /= g_get_home_dir ();
p /= "Preferences";
p /= "com.dcpomatic";
p /= "2";
+ if (version) {
+ p /= *version;
+ }
return p;
}
boost::filesystem::path
-config_path ()
+config_path (optional<string> version)
{
boost::filesystem::path p;
p /= g_get_user_config_dir ();
p /= "dcpomatic2";
+ if (version) {
+ p /= *version;
+ }
return p;
}
Film::use_template (string name)
{
_template_film.reset (new Film (optional<boost::filesystem::path>()));
- _template_film->read_metadata (Config::instance()->template_path (name));
+ _template_film->read_metadata (Config::instance()->template_read_path(name));
_use_isdcf_name = _template_film->_use_isdcf_name;
_dcp_content_type = _template_film->_dcp_content_type;
_container = _template_film->_container;
*/
-#include "state.h"
#include "cross.h"
+#include "state.h"
+#include "util.h"
#include <glib.h>
using std::string;
+using boost::optional;
boost::optional<boost::filesystem::path> State::override_path;
+/* List of config versions to look for in descending order of preference;
+ * i.e. look at the first one, and if that doesn't exist, try the second, etc.
+ */
+static std::vector<std::string> config_versions = { "2.16" };
+
+
+static
+boost::filesystem::path
+config_path_or_override (optional<string> version)
+{
+ if (State::override_path) {
+ auto p = *State::override_path;
+ if (version) {
+ p /= *version;
+ }
+ return p;
+ }
+
+ return config_path (version);
+}
+
+
/** @param file State filename
- * @return Full path to write @file to.
+ * @return Full path to read @file from.
*/
boost::filesystem::path
-State::path (string file, bool create_directories)
+State::read_path (string file)
{
- boost::filesystem::path p;
- if (override_path) {
- p = *override_path;
- } else {
- p = config_path ();
+ using namespace boost::filesystem;
+
+ for (auto i: config_versions) {
+ auto full = config_path_or_override(i) / file;
+ if (exists(full)) {
+ return full;
+ }
}
+
+ return config_path_or_override({}) / file;
+}
+
+
+/** @param file State filename
+ * @return Full path to write @file to.
+ */
+boost::filesystem::path
+State::write_path (string file)
+{
+ boost::filesystem::path p = config_path_or_override(config_versions.front());
boost::system::error_code ec;
- if (create_directories) {
- boost::filesystem::create_directories (p, ec);
- }
+ boost::filesystem::create_directories (p, ec);
p /= file;
return p;
}
+
/** If set, this overrides the standard path (in home, Library, AppData or wherever) for config.xml, cinemas.xml etc. */
static boost::optional<boost::filesystem::path> override_path;
- static boost::filesystem::path path (std::string file, bool create_directories = true);
+ static boost::filesystem::path read_path (std::string file);
+ static boost::filesystem::path write_path (std::string file);
};
_("You are making a DKDM which is encrypted by a private key held in"
"\n\n<tt>%s</tt>\n\nIt is <span weight=\"bold\" size=\"larger\">VITALLY IMPORTANT</span> "
"that you <span weight=\"bold\" size=\"larger\">BACK UP THIS FILE</span> since if it is lost "
- "your DKDMs (and the DCPs they protect) will become useless."), std_to_wx(Config::config_file().string()).data()
+ "your DKDMs (and the DCPs they protect) will become useless."), std_to_wx(Config::config_read_file().string()).data()
)
);
/* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
* a better place to put them.
*/
- dcpomatic_log.reset(new FileLog(config_path() / "disk.log"));
+ dcpomatic_log = make_shared<FileLog>(State::write_path("disk.log"));
dcpomatic_log->set_types (dcpomatic_log->types() | LogEntry::TYPE_DISK);
LOG_DISK("dcpomatic_disk %1 started", dcpomatic_git_commit);
#include "lib/exceptions.h"
#include "lib/ext.h"
#include "lib/file_log.h"
+#include "lib/state.h"
#include "lib/nanomsg.h"
+#include "lib/util.h"
#include "lib/version.h"
#include "lib/warnings.h"
/* XXX: this is a hack, but I expect we'll need logs and I'm not sure if there's
* a better place to put them.
*/
- dcpomatic_log.reset(new FileLog(config_path() / "disk_writer.log", LogEntry::TYPE_DISK));
+ dcpomatic_log.reset(new FileLog(State::write_path("disk_writer.log"), LogEntry::TYPE_DISK));
LOG_DISK_NC("dcpomatic_disk_writer started");
#endif
checked_set (_analyse_ebur128, config->analyse_ebur128 ());
#endif
checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
- checked_set (_config_file, config->config_file());
+ checked_set (_config_file, config->config_read_file());
checked_set (_cinemas_file, config->cinemas_file());
GeneralPage::config_changed ();
{
auto config = Config::instance();
boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
- if (new_file == config->config_file()) {
+ if (new_file == config->config_read_file()) {
return;
}
bool copy_and_link = true;
if (copy_and_link) {
config->write ();
- if (new_file != config->config_file()) {
+ if (new_file != config->config_read_file()) {
config->copy_and_link (new_file);
}
} else {
rewrite_bad_config ()
{
boost::system::error_code ec;
- boost::filesystem::remove ("build/test/bad_config/config.xml", ec);
+ boost::filesystem::remove ("build/test/bad_config/2.16/config.xml", ec);
Config::override_path = "build/test/bad_config";
- boost::filesystem::create_directories ("build/test/bad_config");
- ofstream f ("build/test/bad_config/config.xml");
+ boost::filesystem::create_directories ("build/test/bad_config/2.16");
+ ofstream f ("build/test/bad_config/2.16/config.xml");
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<Config>\n"
<< "<Foo></Foo>\n"
Config::instance();
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
Config::drop();
rewrite_bad_config();
Config::instance();
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
Config::drop();
rewrite_bad_config();
Config::instance();
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
- BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
- BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+ BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+ BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
Config::drop();
rewrite_bad_config();
Config::instance();
- BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
- BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
- BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
- BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+ BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+ BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+ BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+ BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
/* This test has called Config::set_defaults(), so take us back
to the config that we want for our tests.
setup_test_config ();
}
+
+BOOST_AUTO_TEST_CASE (config_upgrade_test)
+{
+ boost::filesystem::path dir = "build/test/config_upgrade_test";
+ Config::override_path = dir;
+ Config::drop ();
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+
+ boost::filesystem::copy_file ("test/data/2.14.config.xml", dir / "config.xml");
+ boost::filesystem::copy_file ("test/data/2.14.cinemas.xml", dir / "cinemas.xml");
+ Config::instance();
+ Config::instance()->write();
+
+ check_xml (dir / "config.xml", "test/data/2.14.config.xml", {});
+ check_xml (dir / "cinemas.xml", "test/data/2.14.cinemas.xml", {});
+ check_xml (dir / "2.16" / "config.xml", "test/data/2.16.config.xml", {});
+ /* cinemas.xml is not copied into 2.16 as its format has not changed */
+ BOOST_REQUIRE (!boost::filesystem::exists(dir / "2.16" / "cinemas.xml"));
+}
+
-Subproject commit d8d9a1eedc24b5f67f377b6e87e649cdee6fc3b7
+Subproject commit 56b37afdf96ecc83752ce70af061ee6c7ed4f78b