mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Feature - #352 rc file should support includes
- Added include file support to Config.cpp. - Implemented isAbsolutePath helper. - Added unit tests for isAbsolutePath. - Fixed small bug in bug.bulk.t. - Added TODO items to config.t.cpp.
This commit is contained in:
parent
8d43a35ca4
commit
0780919c2e
8 changed files with 64 additions and 4 deletions
|
@ -17,6 +17,7 @@
|
|||
"description.contains:th".
|
||||
+ The 'version' command now complains about use of deprecated color names and
|
||||
duplicate entries.
|
||||
+ Task now supports nested .taskrc files using the "include /path" directive.
|
||||
+ Fixed bug that showed a calendar for the year 2037 when 'task calendar due'
|
||||
was run, and there are no tasks with due dates.
|
||||
+ Fixed bug #316 which caused the timesheet report to display an oddly sorted
|
||||
|
|
|
@ -58,8 +58,16 @@ Config::Config (const std::string& file)
|
|||
// Read the Configuration file and populate the *this map. The file format is
|
||||
// simply lines with name=value pairs. Whitespace between name, = and value is
|
||||
// not tolerated, but blank lines and comments starting with # are allowed.
|
||||
bool Config::load (const std::string& file)
|
||||
//
|
||||
// Nested files are now supported, with the following construct:
|
||||
// include /absolute/path/to/file
|
||||
//
|
||||
bool Config::load (const std::string& file, int nest /* = 1 */)
|
||||
{
|
||||
if (nest > 10)
|
||||
throw std::string ("Configuration file nested to more than 10 levels deep"
|
||||
" - this has to be a mistake.");
|
||||
|
||||
std::ifstream in;
|
||||
in.open (file.c_str (), std::ifstream::in);
|
||||
if (in.good ())
|
||||
|
@ -82,9 +90,29 @@ bool Config::load (const std::string& file)
|
|||
{
|
||||
std::string key = trim (line.substr (0, equal), " \t"); // no i18n
|
||||
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t"); // no i18n
|
||||
|
||||
(*this)[key] = value;
|
||||
sequence.push_back (key);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string::size_type include = line.find ("include"); // no i18n.
|
||||
if (include != std::string::npos)
|
||||
{
|
||||
std::string included = expandPath ( trim ( line.substr (include + 7, std::string::npos), " \t"));
|
||||
if (isAbsolutePath (included))
|
||||
{
|
||||
if (!access (included.c_str (), F_OK | R_OK))
|
||||
this->load (included, nest + 1);
|
||||
else
|
||||
throw std::string ("Could not read include file '") + included + "'";
|
||||
}
|
||||
else
|
||||
throw std::string ("Can only include files with absolute paths, not '") + included + "'";
|
||||
}
|
||||
else
|
||||
throw std::string ("Malformed entry in ") + file + ": '" + line + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
Config (const Config&);
|
||||
Config& operator= (const Config&);
|
||||
|
||||
bool load (const std::string&);
|
||||
bool load (const std::string&, int nest = 1);
|
||||
void createDefaultRC (const std::string&, const std::string&);
|
||||
void createDefaultData (const std::string&);
|
||||
void setDefaults ();
|
||||
|
|
|
@ -52,7 +52,7 @@ qx{../task rc:bulk.rc add t6 due:saturday};
|
|||
my $output = qx{echo "quit"|../task rc:bulk.rc pro:p1 pri:M 4 5 6};
|
||||
like ($output, qr/Modified 0 tasks/, '"quit" prevents any further modifications');
|
||||
|
||||
my $output = qx{echo "all"|../task rc:bulk.rc pro:p1 pri:M 4 5 6};
|
||||
$output = qx{echo "All"|../task rc:bulk.rc pro:p1 pri:M 4 5 6};
|
||||
unlike ($output, qr/Task 4 "t4"\n - No changes were made/, 'Task 4 modified');
|
||||
unlike ($output, qr/Task 5 "t5"\n - No changes were made/, 'Task 5 modified');
|
||||
unlike ($output, qr/Task 6 "t6"\n - No changes were made/, 'Task 6 modified');
|
||||
|
|
|
@ -105,6 +105,11 @@ int main (int argc, char** argv)
|
|||
// 22 default report setting created in Config::Config.
|
||||
t.ok (all.size () >= 8, "Config::all");
|
||||
|
||||
// TODO Test includes
|
||||
// TODO Test included nesting limit
|
||||
// TODO Test included absolute vs relative
|
||||
// TODO Test included missing file
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ Context context;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (67);
|
||||
UnitTest t (74);
|
||||
|
||||
// TODO bool confirm (const std::string&);
|
||||
// TODO int confirm3 (const std::string&);
|
||||
|
@ -113,6 +113,15 @@ int main (int argc, char** argv)
|
|||
// 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 <std::string>&, bool trimLines = false);
|
||||
// TODO bool slurp (const std::string&, std::string&, bool trimLines = false);
|
||||
|
|
16
src/util.cpp
16
src/util.cpp
|
@ -355,6 +355,13 @@ std::string expandPath (const std::string& in)
|
|||
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)
|
||||
|
@ -369,6 +376,15 @@ std::string expandPath (const std::string& in)
|
|||
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
|
||||
|
|
|
@ -61,6 +61,7 @@ std::string formatBytes (size_t);
|
|||
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||
const std::string uuid ();
|
||||
std::string expandPath (const std::string&);
|
||||
bool isAbsolutePath (const std::string&);
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define LOCK_SH 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue