From b596e96b43d68e76ee1bbcdb682fa840febc1890 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sat, 16 Jan 2010 10:27:31 -0500 Subject: [PATCH] Enhancement - Path, File, Directory integration - Replaced all access calls. - Replaced all stat calls. - Obsoleted util.cpp isAbsoluteDirectory calls. - Obsoleted util.cpp expandPath calls. --- src/Config.cpp | 8 +++---- src/Context.cpp | 54 ++++++++++++++++++++++++-------------------- src/TDB.cpp | 23 +++++++++---------- src/command.cpp | 7 ++++-- src/edit.cpp | 7 +++--- src/report.cpp | 27 ++++++++++------------ src/tests/util.t.cpp | 15 +----------- src/util.cpp | 43 ----------------------------------- src/util.h | 2 -- 9 files changed, 66 insertions(+), 120 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 2255f3255..0648d56d3 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -33,7 +33,7 @@ #include #include #include -#include "Path.h" +#include "Directory.h" #include "File.h" #include "Config.h" #include "text.h" @@ -354,9 +354,9 @@ void Config::createDefaultRC (const std::string& rc, const std::string& data) //////////////////////////////////////////////////////////////////////////////// void Config::createDefaultData (const std::string& data) { - Path p (data); - if (! p.exists ()) - mkdir (data.c_str (), S_IRWXU); + Directory d (data); + if (! d.exists ()) + d.create (); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Context.cpp b/src/Context.cpp index 71028b4db..3d3d83494 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -32,6 +32,8 @@ #include #include #include "Context.h" +#include "Directory.h" +#include "File.h" #include "Timer.h" #include "text.h" #include "util.h" @@ -107,7 +109,7 @@ void Context::initialize () // Load appropriate stringtable as soon after the config file as possible, to // allow all subsequent messages to be localizable. - std::string location = expandPath (config.get ("data.location")); + Directory location (config.get ("data.location")); std::string locale = config.get ("locale"); // If there is a locale variant (en-US.), then strip it. @@ -116,16 +118,16 @@ void Context::initialize () locale = locale.substr (0, period); if (locale != "") - stringtable.load (location + "/strings." + locale); + stringtable.load (location.data + "/strings." + locale); // TODO Handle "--version, -v" right here? // init TDB. tdb.clear (); std::vector all; - split (all, location, ','); + split (all, location.data, ','); foreach (path, all) - tdb.location (expandPath (*path)); + tdb.location (*path); } //////////////////////////////////////////////////////////////////////////////// @@ -244,8 +246,8 @@ int Context::dispatch (std::string &out) void Context::shadow () { // Determine if shadow file is enabled. - std::string shadowFile = expandPath (config.get ("shadow.file")); - if (shadowFile != "") + File shadowFile (config.get ("shadow.file")); + if (shadowFile.data != "") { inShadow = true; // Prevents recursion in case shadow command writes. @@ -281,21 +283,21 @@ void Context::shadow () parse (); std::string result; (void)dispatch (result); - std::ofstream out (shadowFile.c_str ()); + std::ofstream out (shadowFile.data.c_str ()); if (out.good ()) { out << result; out.close (); } else - throw std::string ("Could not write file '") + shadowFile + "'"; + throw std::string ("Could not write file '") + shadowFile.data + "'"; config.set ("curses", oldCurses); config.set ("color", oldColor); // Optionally display a notification that the shadow file was updated. if (config.getBoolean ("shadow.notify")) - footnote (std::string ("[Shadow file '") + shadowFile + "' updated]"); + footnote (std::string ("[Shadow file '") + shadowFile.data + "' updated]"); inShadow = false; } @@ -355,8 +357,10 @@ void Context::loadCorrectConfigFile () "Could not read home directory from the passwd file.")); std::string home = pw->pw_dir; - std::string rc = home + "/.taskrc"; - std::string data = home + "/.task"; +// std::string rc = home + "/.taskrc"; +// std::string data = home + "/.task"; + File rc (home + "/.taskrc"); + Directory data (home + "./task"); // Is there an file_override for rc:? foreach (arg, args) @@ -366,17 +370,17 @@ void Context::loadCorrectConfigFile () else if (arg->substr (0, 3) == "rc:") { file_override = *arg; - rc = arg->substr (3); + rc = File (arg->substr (3)); - home = rc; - std::string::size_type last_slash = rc.rfind ("/"); + home = rc.data; + std::string::size_type last_slash = rc.data.rfind ("/"); if (last_slash != std::string::npos) - home = rc.substr (0, last_slash); + home = rc.data.substr (0, last_slash); else home = "."; args.erase (arg); - header ("Using alternate .taskrc file " + rc); // TODO i18n + header ("Using alternate .taskrc file " + rc.data); // TODO i18n break; } } @@ -384,10 +388,10 @@ void Context::loadCorrectConfigFile () // Load rc file. config.clear (); // Dump current values. config.setDefaults (); // Add in the custom reports. - config.load (rc); // Load new file. + config.load (rc.data); // Load new file. if (config.get ("data.location") != "") - data = config.get ("data.location"); + data = Directory (config.get ("data.location")); // Are there any var_overrides for data.location? foreach (arg, args) @@ -397,35 +401,35 @@ void Context::loadCorrectConfigFile () else if (arg->substr (0, 17) == "rc.data.location:" || arg->substr (0, 17) == "rc.data.location=") { - data = arg->substr (17); - header ("Using alternate data.location " + data); // TODO i18n + data = Directory (arg->substr (17)); + header ("Using alternate data.location " + data.data); // TODO i18n break; } } // Do we need to create a default rc? - if (access (rc.c_str (), F_OK)) + if (! rc.exists ()) { if (confirm ("A configuration file could not be found in " // TODO i18n + home + "\n\n" + "Would you like a sample " - + rc + + rc.data + " created, so task can proceed?")) { - config.createDefaultRC (rc, data); + config.createDefaultRC (rc.data, data.data); } else throw std::string ("Cannot proceed without rc file."); } // Create data location, if necessary. - config.createDefaultData (data); + config.createDefaultData (data.data); // Load rc file. config.clear (); // Dump current values. config.setDefaults (); // Add in the custom reports. - config.load (rc); // Load new file. + config.load (rc.data); // Load new file. // Apply overrides of type: "rc.name:value", or "rc.name=value". std::vector filtered; diff --git a/src/TDB.cpp b/src/TDB.cpp index 5e31bc2ca..c231d86ec 100644 --- a/src/TDB.cpp +++ b/src/TDB.cpp @@ -35,6 +35,7 @@ #include "text.h" #include "util.h" #include "TDB.h" +#include "Directory.h" #include "Table.h" #include "Timer.h" #include "Color.h" @@ -107,12 +108,13 @@ void TDB::clear () //////////////////////////////////////////////////////////////////////////////// void TDB::location (const std::string& path) { - if (access (expandPath (path).c_str (), F_OK)) + Directory d (path); + if (!d.exists ()) throw std::string ("Data location '") + path + "' does not exist, or is not readable and writable."; - mLocations.push_back (Location (path)); + mLocations.push_back (Location (d.data)); } //////////////////////////////////////////////////////////////////////////////// @@ -503,11 +505,11 @@ int TDB::nextId () //////////////////////////////////////////////////////////////////////////////// void TDB::undo () { - std::string location = expandPath (context.config.get ("data.location")); + Directory location (context.config.get ("data.location")); - std::string undoFile = location + "/undo.data"; - std::string pendingFile = location + "/pending.data"; - std::string completedFile = location + "/completed.data"; + std::string undoFile = location.data + "/undo.data"; + std::string pendingFile = location.data + "/pending.data"; + std::string completedFile = location.data + "/completed.data"; // load undo.data std::vector u; @@ -725,9 +727,10 @@ FILE* TDB::openAndLock (const std::string& file) // TODO Need provision here for read-only locations. // Check for access. - bool exists = access (file.c_str (), F_OK) ? false : true; + File f (file); + bool exists = f.exists (); if (exists) - if (access (file.c_str (), R_OK | W_OK)) + if (!f.readable () || !f.writable ()) throw std::string ("Task does not have the correct permissions for '") + file + "'."; @@ -755,8 +758,6 @@ FILE* TDB::openAndLock (const std::string& file) //////////////////////////////////////////////////////////////////////////////// void TDB::writeUndo (const Task& after, FILE* file) { - Timer t ("TDB::writeUndo"); - fprintf (file, "time %u\nnew %s---\n", (unsigned int) time (NULL), @@ -766,8 +767,6 @@ void TDB::writeUndo (const Task& after, FILE* file) //////////////////////////////////////////////////////////////////////////////// void TDB::writeUndo (const Task& before, const Task& after, FILE* file) { - Timer t ("TDB::writeUndo"); - fprintf (file, "time %u\nold %snew %s---\n", (unsigned int) time (NULL), diff --git a/src/command.cpp b/src/command.cpp index 3e9eca531..432fbf734 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -37,6 +37,7 @@ #include #include "Permission.h" +#include "Directory.h" #include "text.h" #include "util.h" #include "main.h" @@ -619,12 +620,14 @@ int handleConfig (std::string &outs) } else { - if (context.config.get ("data.location") == "") + Directory location (context.config.get ("data.location")); + + if (location.data == "") out << "Configuration error: data.location not specified in .taskrc " "file." << std::endl; - if (access (expandPath (context.config.get ("data.location")).c_str (), X_OK)) + if (! location.exists ()) out << "Configuration error: data.location contains a directory name" " that doesn't exist, or is unreadable." << std::endl; diff --git a/src/edit.cpp b/src/edit.cpp index b61e81aa3..59abc0c1b 100644 --- a/src/edit.cpp +++ b/src/edit.cpp @@ -33,6 +33,7 @@ #include #include #include +#include "Directory.h" #include "Date.h" #include "Duration.h" #include "text.h" @@ -521,13 +522,13 @@ static void parseTask (Task& task, const std::string& after) void editFile (Task& task) { // Check for file permissions. - std::string dataLocation = expandPath (context.config.get ("data.location")); - if (access (dataLocation.c_str (), X_OK)) + Directory location (context.config.get ("data.location")); + if (! location.writable ()) throw std::string ("Your data.location directory is not writable."); // Create a temp file name in data.location. std::stringstream file; - file << dataLocation << "/task." << getpid () << "." << task.id << ".task"; + file << location.data << "/task." << getpid () << "." << task.id << ".task"; // Format the contents, T -> text, write to a file. std::string before = formatTask (task); diff --git a/src/report.cpp b/src/report.cpp index 9e0598d4f..ca0198a23 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,8 @@ #include #include "Context.h" +#include "Directory.h" +#include "File.h" #include "Date.h" #include "Table.h" #include "text.h" @@ -1716,24 +1717,20 @@ int handleReportStats (std::string &outs) // Go get the file sizes. size_t dataSize = 0; - struct stat s; - std::string location = expandPath (context.config.get ("data.location")); - std::string file = location + "/pending.data"; - if (!stat (file.c_str (), &s)) - dataSize += s.st_size; + Directory location (context.config.get ("data.location")); + File pending (location.data + "/pending.data"); + dataSize += pending.size (); - file = location + "/completed.data"; - if (!stat (file.c_str (), &s)) - dataSize += s.st_size; + File completed (location.data + "/completed.data"); + dataSize += completed.size (); - file = location + "/undo.data"; - if (!stat (file.c_str (), &s)) - dataSize += s.st_size; + File undo (location.data + "/undo.data"); + dataSize += undo.size (); - std::vector undo; - slurp (file, undo, false); + std::vector undoTxns; + slurp (undo.data, undoTxns, false); int undoCount = 0; - foreach (tx, undo) + foreach (tx, undoTxns) if (tx->substr (0, 3) == "---") ++undoCount; diff --git a/src/tests/util.t.cpp b/src/tests/util.t.cpp index 5003e25e2..ecc6b796c 100644 --- a/src/tests/util.t.cpp +++ b/src/tests/util.t.cpp @@ -34,7 +34,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest t (439); + UnitTest t (430); // TODO bool confirm (const std::string&); // TODO int confirm3 (const std::string&); @@ -514,19 +514,6 @@ int main (int argc, char** argv) // TODO const std::string uuid (); - // std::string expandPath (const std::string&); - t.ok (expandPath ("foo") == "foo", "expandPath nop"); - t.ok (expandPath ("~/") != "~/", "expandPath ~/"); - t.ok (expandPath ("~") != "~", "expandPath ~"); - - // bool isAbsolutePath (const std::string&); - t.notok (isAbsolutePath ("."), "isAbsolutePath ."); - t.notok (isAbsolutePath ("~"), "isAbsolutePath ~"); - t.ok (isAbsolutePath (expandPath ("~")), "isAbsolutePath (expandPath ~)"); - t.ok (isAbsolutePath (expandPath ("~/")), "isAbsolutePath (expandPath ~/)"); - t.ok (isAbsolutePath ("/"), "isAbsolutePath /"); - t.ok (isAbsolutePath ("/tmp"), "isAbsolutePath /tmp"); - // TODO bool slurp (const std::string&, std::vector &, bool trimLines = false); // TODO bool slurp (const std::string&, std::string&, bool trimLines = false); // TODO void spit (const std::string&, const std::string&); diff --git a/src/util.cpp b/src/util.cpp index 28bff6d2b..69df5360b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -341,49 +341,6 @@ const std::string uuid () } #endif -//////////////////////////////////////////////////////////////////////////////// -// no i18n -std::string expandPath (const std::string& in) -{ - std::string copy = in; - std::string::size_type tilde; - - if ((tilde = copy.find ("~/")) != std::string::npos) - { - struct passwd* pw = getpwuid (getuid ()); - copy.replace (tilde, 1, pw->pw_dir); - } - else if ((tilde = copy.find ("~")) != std::string::npos) - { - struct passwd* pw = getpwuid (getuid ()); - std::string home = pw->pw_dir; - home += "/"; - copy.replace (tilde, 1, home); - } - else if ((tilde = copy.find ("~")) != std::string::npos) - { - std::string::size_type slash; - if ((slash = copy.find ("/", tilde)) != std::string::npos) - { - std::string name = copy.substr (tilde + 1, slash - tilde - 1); - struct passwd* pw = getpwnam (name.c_str ()); - if (pw) - copy.replace (tilde, slash - tilde, pw->pw_dir); - } - } - - return copy; -} - -//////////////////////////////////////////////////////////////////////////////// -bool isAbsolutePath (const std::string& in) -{ - if (in.length () && in[0] == '/') - return true; - - return false; -} - //////////////////////////////////////////////////////////////////////////////// // On Solaris no flock function exists. #ifdef SOLARIS diff --git a/src/util.h b/src/util.h index b6ee6576f..3dbd8b2ea 100644 --- a/src/util.h +++ b/src/util.h @@ -60,8 +60,6 @@ std::string formatSecondsCompact (time_t); std::string formatBytes (size_t); int autoComplete (const std::string&, const std::vector&, std::vector&); const std::string uuid (); -std::string expandPath (const std::string&); -bool isAbsolutePath (const std::string&); #ifdef SOLARIS #define LOCK_SH 1