diff --git a/README.md b/README.md index 74a6bdfc..de4286ce 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ The add commands return a pointer to an internally stored `Option`. If you set t * `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option policy. Shortcuts available: `->take_last()`, `->take_first()`, and `->join()`. This will only affect options expecting 1 argument or bool flags (which always default to take last). * `->check(CLI::ExistingFile)`: Requires that the file exists if given. * `->check(CLI::ExistingDirectory)`: Requires that the directory exists. +* `->check(CLI::ExistingPath)`: Requires that the path (file or directory) exists. * `->check(CLI::NonexistentPath)`: Requires that the path does not exist. * `->check(CLI::Range(min,max))`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0. * `->transform(std::string(std::string))`: Converts the input string into the output string, in-place in the parsed options. diff --git a/include/CLI/Validators.hpp b/include/CLI/Validators.hpp index 7ccf034e..f158f927 100644 --- a/include/CLI/Validators.hpp +++ b/include/CLI/Validators.hpp @@ -50,6 +50,16 @@ inline std::string ExistingDirectory(const std::string &filename) { return std::string(); } +/// Check for an existing path +inline std::string ExistingPath(const std::string &filename) { + struct stat buffer; + bool const exist = stat(filename.c_str(), &buffer) == 0; + if(!exist) { + return "Path does not exist: " + filename; + } + return std::string(); +} + /// Check for a non-existing path inline std::string NonexistentPath(const std::string &filename) { struct stat buffer; diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp index 3f29cc38..b1fb343d 100644 --- a/tests/HelpersTest.cpp +++ b/tests/HelpersTest.cpp @@ -133,6 +133,27 @@ TEST(Validators, DirectoryIsFile) { EXPECT_TRUE(CLI::NonexistentPath(myfile).empty()); } +TEST(Validators, PathExistsDir) { + std::string mydir{"../tests"}; + EXPECT_EQ(CLI::ExistingPath(mydir), ""); +} + +TEST(Validators, PathExistsFile) { + std::string myfile{"TestFileNotUsed.txt"}; + EXPECT_FALSE(CLI::ExistingPath(myfile).empty()); + bool ok = static_cast(std::ofstream(myfile.c_str()).put('a')); // create file + EXPECT_TRUE(ok); + EXPECT_TRUE(CLI::ExistingPath(myfile).empty()); + + std::remove(myfile.c_str()); + EXPECT_FALSE(CLI::ExistingPath(myfile).empty()); +} + +TEST(Validators, PathNotExistsDir) { + std::string mydir{"nonpath"}; + EXPECT_NE(CLI::ExistingPath(mydir), ""); +} + // Yes, this is testing an app_helper :) TEST(AppHelper, TempfileCreated) { std::string name = "TestFileNotUsed.txt";