summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Batischev <eual.jp@gmail.com>2017-09-20 21:34:02 +0300
committerGitHub <noreply@github.com>2017-09-20 21:34:02 +0300
commitbd8bc9c015338717d35331f0dafec4374b659619 (patch)
tree7ab3a45338457d5e646635d7436c9858d2886dfc
parente171c84de8a67a978a29889067f597a0f0432a1d (diff)
parent360f3a611eddd115399d65a0e1b6e465d952b58e (diff)
Merge pull request #2 from newsboat/feature/1-migrate-from-newsbeuter
Migrate Newsbeuter configuration on the first run
-rw-r--r--include/controller.h8
-rw-r--r--src/controller.cpp216
2 files changed, 203 insertions, 21 deletions
diff --git a/include/controller.h b/include/controller.h
index e2fec2ee..0feb5a28 100644
--- a/include/controller.h
+++ b/include/controller.h
@@ -104,8 +104,11 @@ class controller {
unsigned int get_feed_count_per_tag(const std::string& tag);
private:
void usage(char * argv0);
- bool setup_dirs_xdg(const char *env_home, bool silent);
- void setup_dirs(bool silent);
+ bool setup_dirs_xdg(const char *env_home);
+ void setup_dirs();
+ void migrate_data_from_newsbeuter(bool silent);
+ bool migrate_data_from_newsbeuter_xdg(const char* env_home, bool silent);
+ bool migrate_data_from_newsbeuter_simple(const char* env_home, bool silent);
void version_information(const char * argv0, unsigned int level);
void import_opml(const std::string& filename);
void export_opml();
@@ -128,6 +131,7 @@ class controller {
cache * rsscache;
std::vector<std::shared_ptr<rss_feed>> feeds;
std::string config_dir;
+ std::string data_dir;
std::string url_file;
std::string cache_file;
std::string config_file;
diff --git a/src/controller.cpp b/src/controller.cpp
index 8965ea63..ef084bdb 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -94,7 +94,7 @@ controller::controller() : v(0), urlcfg(0), rsscache(0), url_file("urls"), cache
*
* returns false, if that fails
*/
-bool controller::setup_dirs_xdg(const char *env_home, bool silent) {
+bool controller::setup_dirs_xdg(const char *env_home) {
const char *env_xdg_config;
const char *env_xdg_data;
std::string xdg_config_dir;
@@ -129,16 +129,6 @@ bool controller::setup_dirs_xdg(const char *env_home, bool silent) {
bool config_dir_exists = 0 == access(xdg_config_dir.c_str(), R_OK | X_OK);
if (!config_dir_exists) {
- if (!silent) {
- std::cerr
- << strprintf::fmt(
- _("XDG: configuration directory '%s' not accessible, "
- "using '%s' instead."),
- xdg_config_dir,
- config_dir)
- << std::endl;
- }
-
return false;
}
@@ -149,9 +139,6 @@ bool controller::setup_dirs_xdg(const char *env_home, bool silent) {
config_dir = xdg_config_dir;
- // create data directory if it doesn't exist
- utils::mkdir_parents(xdg_data_dir, 0700);
-
/* in config */
url_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + url_file;
config_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + config_file;
@@ -166,7 +153,7 @@ bool controller::setup_dirs_xdg(const char *env_home, bool silent) {
return true;
}
-void controller::setup_dirs(bool silent) {
+void controller::setup_dirs() {
const char * env_home;
if (!(env_home = ::getenv("HOME"))) {
struct passwd * spw = ::getpwuid(::getuid());
@@ -183,11 +170,9 @@ void controller::setup_dirs(bool silent) {
config_dir.append(NEWSBEUTER_PATH_SEP);
config_dir.append(NEWSBOAT_CONFIG_SUBDIR);
- if (setup_dirs_xdg(env_home, silent))
+ if (setup_dirs_xdg(env_home))
return;
- mkdir(config_dir.c_str(),0700); // create configuration directory if it doesn't exist
-
url_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + url_file;
cache_file = config_dir + std::string(NEWSBEUTER_PATH_SEP) + cache_file;
lock_file = cache_file + LOCK_SUFFIX;
@@ -198,6 +183,187 @@ void controller::setup_dirs(bool silent) {
cmdlinefile = strprintf::fmt("%s%shistory.cmdline", config_dir, NEWSBEUTER_PATH_SEP);
}
+void copy_file(
+ const std::string& input_filepath,
+ const std::string& output_filepath)
+{
+ std::cerr << input_filepath << " -> " << output_filepath << '\n';
+
+ std::ifstream src(input_filepath, std::ios_base::binary);
+ std::ofstream dst(output_filepath, std::ios_base::binary);
+ dst << src.rdbuf();
+}
+
+bool controller::migrate_data_from_newsbeuter_xdg(const char* env_home, bool silent) {
+ const char* env_xdg_config = ::getenv("XDG_CONFIG_HOME");
+ std::string xdg_config_dir;
+ if (env_xdg_config) {
+ xdg_config_dir = env_xdg_config;
+ } else {
+ xdg_config_dir = env_home;
+ xdg_config_dir.append(NEWSBEUTER_PATH_SEP);
+ xdg_config_dir.append(".config");
+ }
+
+ const char* env_xdg_data = ::getenv("XDG_DATA_HOME");
+ std::string xdg_data_dir;
+ if (env_xdg_data) {
+ xdg_data_dir = env_xdg_data;
+ } else {
+ xdg_data_dir = env_home;
+ xdg_data_dir.append(NEWSBEUTER_PATH_SEP);
+ xdg_data_dir.append(".local");
+ xdg_data_dir.append(NEWSBEUTER_PATH_SEP);
+ xdg_data_dir.append("share");
+ }
+
+ const auto newsbeuter_config_dir
+ = xdg_config_dir + NEWSBEUTER_PATH_SEP + NEWSBEUTER_SUBDIR_XDG + NEWSBEUTER_PATH_SEP;
+ const auto newsbeuter_data_dir
+ = xdg_data_dir + NEWSBEUTER_PATH_SEP + NEWSBEUTER_SUBDIR_XDG + NEWSBEUTER_PATH_SEP;
+
+ const auto newsboat_config_dir
+ = xdg_config_dir + NEWSBEUTER_PATH_SEP + NEWSBOAT_SUBDIR_XDG + NEWSBEUTER_PATH_SEP;
+ const auto newsboat_data_dir
+ = xdg_data_dir + NEWSBEUTER_PATH_SEP + NEWSBOAT_SUBDIR_XDG + NEWSBEUTER_PATH_SEP;
+
+ bool newsbeuter_config_dir_exists = 0 == access(newsbeuter_config_dir.c_str(), R_OK | X_OK);
+
+ if (! newsbeuter_config_dir_exists) {
+ return false;
+ }
+
+ auto exists = [silent](const std::string& dir) -> bool {
+ bool dir_exists = 0 == access(dir.c_str(), F_OK);
+ if (dir_exists) {
+ LOG(level::DEBUG, "%s already exists, aborting XDG migration.", dir);
+ }
+ return dir_exists;
+ };
+ if (exists(newsboat_config_dir)) {
+ return false;
+ }
+ if (exists(newsboat_data_dir)) {
+ return false;
+ }
+
+ if (! silent) {
+ std::cerr
+ << "Migrating configs and data from Newsbeuter's XDG dirs..."
+ << std::endl;
+ }
+
+ auto try_mkdir = [silent](const std::string& dir) -> bool{
+ bool result = 0 == utils::mkdir_parents(dir, 0700);
+ if (! result) {
+ LOG(level::DEBUG,
+ "Aborting XDG migration because mkdir on %s failed: %s",
+ dir, strerror(errno));
+ }
+ return result;
+ };
+ if (! try_mkdir(newsboat_config_dir)) {
+ return false;
+ }
+ if (! try_mkdir(newsboat_data_dir)) {
+ return false;
+ }
+
+ /* in config */
+ copy_file(newsbeuter_config_dir + "urls", newsboat_config_dir + "urls");
+ copy_file(newsbeuter_config_dir + "config", newsboat_config_dir + "config");
+
+ /* in data */
+ copy_file(newsbeuter_data_dir + "cache.db", newsboat_data_dir + "cache.db");
+ copy_file(newsbeuter_data_dir + "queue", newsboat_data_dir + "queue");
+ copy_file(newsbeuter_data_dir + "history.search", newsboat_data_dir + "history.search");
+ copy_file(newsbeuter_data_dir + "history.cmdline", newsboat_data_dir + "history.cmdline");
+
+ return true;
+}
+
+bool controller::migrate_data_from_newsbeuter_simple(const char* env_home, bool silent) {
+ std::string newsbeuter_dir = env_home;
+ newsbeuter_dir += NEWSBEUTER_PATH_SEP;
+ newsbeuter_dir += NEWSBEUTER_CONFIG_SUBDIR;
+ newsbeuter_dir += NEWSBEUTER_PATH_SEP;
+
+ bool newsbeuter_dir_exists = 0 == access(newsbeuter_dir.c_str(), R_OK | X_OK);
+ if (! newsbeuter_dir_exists) {
+ return false;
+ }
+
+ std::string newsboat_dir = env_home;
+ newsboat_dir += NEWSBEUTER_PATH_SEP;
+ newsboat_dir += NEWSBOAT_CONFIG_SUBDIR;
+ newsboat_dir += NEWSBEUTER_PATH_SEP;
+
+ bool newsboat_dir_exists = 0 == access(newsboat_dir.c_str(), F_OK);
+ if (newsboat_dir_exists) {
+ LOG(level::DEBUG, "%s already exists, aborting migration.", newsboat_dir);
+ return false;
+ }
+
+ if (! silent) {
+ std::cerr
+ << "Migrating configs and data from Newsbeuter's dotdir..."
+ << std::endl;
+ }
+
+ if (0 != ::mkdir(newsboat_dir.c_str(), 0700)) {
+ if (! silent) {
+ std::cerr
+ << "Aborting migration because mkdir on "
+ << newsboat_dir
+ << " failed: "
+ << strerror(errno)
+ << std::endl;
+ }
+ return false;
+ }
+
+ copy_file(newsbeuter_dir + "urls", newsboat_dir + "urls");
+ copy_file(newsbeuter_dir + "cache.db", newsboat_dir + "cache.db");
+ copy_file(newsbeuter_dir + "config", newsboat_dir + "config");
+ copy_file(newsbeuter_dir + "queue", newsboat_dir + "queue");
+ copy_file(newsbeuter_dir + "history.search", newsboat_dir + "history.search");
+ copy_file(newsbeuter_dir + "history.cmdline", newsboat_dir + "history.cmdline");
+
+ return true;
+}
+
+void controller::migrate_data_from_newsbeuter(bool silent) {
+ const char * env_home;
+ if (!(env_home = ::getenv("HOME"))) {
+ struct passwd * spw = ::getpwuid(::getuid());
+ if (spw) {
+ env_home = spw->pw_dir;
+ } else {
+ std::cerr << _("Fatal error: couldn't determine home directory!") << std::endl;
+ std::cerr << strprintf::fmt(_("Please set the HOME environment variable or add a valid user for UID %u!"), ::getuid()) << std::endl;
+ ::exit(EXIT_FAILURE);
+ }
+ }
+
+ bool migrated = migrate_data_from_newsbeuter_xdg(env_home, silent);
+
+ if (migrated) {
+ // Re-running to pick up XDG dirs
+ url_file = "urls";
+ cache_file = "cache.db";
+ config_file = "config";
+ queue_file = "queue";
+ setup_dirs();
+ } else {
+ migrated = migrate_data_from_newsbeuter_simple(env_home, silent);
+ }
+
+ if (migrated) {
+ std::cerr << "\nATTENTION! Only default files were migrated. Please check the result "
+ "before deleting the originals.\n\n";
+ }
+}
+
controller::~controller() {
delete rsscache;
delete urlcfg;
@@ -261,7 +427,9 @@ void controller::run(int argc, char * argv[]) {
}
}
- setup_dirs(silent);
+ setup_dirs();
+
+ bool using_nonstandard_configs = false;
/* Now that silencing's set up, let's rewind to the beginning of argv and
* process the options */
@@ -292,14 +460,17 @@ void controller::run(int argc, char * argv[]) {
break;
case 'u':
url_file = optarg;
+ using_nonstandard_configs = true;
break;
case 'c':
cache_file = optarg;
lock_file = std::string(cache_file) + LOCK_SUFFIX;
cachefile_given_on_cmdline = true;
+ using_nonstandard_configs = true;
break;
case 'C':
config_file = optarg;
+ using_nonstandard_configs = true;
break;
case 'X':
do_vacuum = true;
@@ -361,6 +532,13 @@ void controller::run(int argc, char * argv[]) {
LOG(level::INFO, "nl_langinfo(CODESET): %s", nl_langinfo(CODESET));
+ if ((! using_nonstandard_configs) && (0 != access(url_file.c_str(), F_OK))) {
+ migrate_data_from_newsbeuter(silent);
+ }
+
+ utils::mkdir_parents(config_dir.c_str(), 0700);
+ utils::mkdir_parents(data_dir.c_str(), 0700);
+
if (!do_export) {
if (!silent)