[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master eb43e28 1/2: Add a function to modify the dir
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master eb43e28 1/2: Add a function to modify the directory part of a filepath |
Date: |
Mon, 27 May 2019 13:05:47 -0400 (EDT) |
branch: master
commit eb43e288395101f66627a2889824288d934de979
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>
Add a function to modify the directory part of a filepath
---
path_utility.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++
path_utility.hpp | 5 +++++
path_utility_test.cpp | 31 +++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+)
diff --git a/path_utility.cpp b/path_utility.cpp
index c3a5479..d741c0a 100644
--- a/path_utility.cpp
+++ b/path_utility.cpp
@@ -93,6 +93,52 @@ void initialize_filesystem()
fs::initial_path();
}
+/// Change '/path/to/file' to '/some/other/place/file'.
+///
+/// Motivation: It is anomalous that boost permits this:
+/// path file("/bin/sh";
+/// path dir ("/usr/bin");
+/// dir / path; // returns "/usr/bin/bin/sh"
+/// where true == file.is_complete().
+///
+/// Arguably the arguments should be given in the opposite order:
+/// modify_directory("sh", "/usr/bin") // present order
+/// modify_directory("/usr/bin", "sh") // opposite order
+/// because the path precedes the leaf in canonical form. However,
+/// fs::change_extension() uses the present argument order:
+/// function(original, new_part)
+/// and in a nondegenerate case such as:
+/// modify_directory("/bin/sh", "/usr/bin") // present order
+/// simply means "change the directory of /bin/sh to /usr/bin", while
+/// modify_directory("/usr/bin", "/bin/sh") // opposite order
+/// seems less natural.
+///
+/// "change_directory" might be a more natural name, except that it
+/// evokes chdir(2) and cd(1).
+///
+/// Asserted precondition:
+/// - 'original_filepath' is not empty (i.e., true == has_leaf())
+/// It is notably not required that 'supplied_directory' name an
+/// actual existing directory.
+///
+/// Boost provides no way to test whether a path has the form of a
+/// directory. Its fs::is_directory() asks the operating system:
+/// is_directory("/usr/lib")
+/// returns 'true' iff the OS reports that such a directory exists;
+/// but the same function call would return 'false' after
+/// rm -rf /usr/lib ; touch /usr/lib
+/// Notably, path("/bin/sh/") succeeds, silently discarding the
+/// trailing '/'.
+
+fs::path LMI_SO modify_directory
+ (fs::path const& original_filepath
+ ,fs::path const& supplied_directory
+ )
+{
+ LMI_ASSERT(original_filepath.has_leaf());
+ return supplied_directory / fs::path(original_filepath.leaf());
+}
+
/// Return a filename appropriate for posix as well as msw.
///
/// Precondition: argument is not empty.
diff --git a/path_utility.hpp b/path_utility.hpp
index f38ba67..227ed57 100644
--- a/path_utility.hpp
+++ b/path_utility.hpp
@@ -33,6 +33,11 @@
void LMI_SO initialize_filesystem(); // Listed first because of its importance.
+fs::path LMI_SO modify_directory
+ (fs::path const& original_filepath
+ ,fs::path const& supplied_directory
+ );
+
std::string LMI_SO orthodox_filename
(std::string const& original_filename
);
diff --git a/path_utility_test.cpp b/path_utility_test.cpp
index 5c6d13f..ca876f5 100644
--- a/path_utility_test.cpp
+++ b/path_utility_test.cpp
@@ -57,6 +57,36 @@ namespace
}
}
+void test_modify_directory()
+{
+ // Motivating case:
+ BOOST_TEST_EQUAL("/usr/bin/sh" , modify_directory("/bin/sh",
"/usr/bin").string());
+
+ fs::path const file("sh");
+ fs::path const dir0("/bin");
+ fs::path const dir1("/usr/bin/");
+
+ BOOST_TEST_EQUAL("/bin/sh" , modify_directory(file , dir0
).string());
+ BOOST_TEST_EQUAL("/bin/sh" , modify_directory("sh" , "/bin/"
).string());
+ BOOST_TEST_EQUAL("/usr/bin/wish", modify_directory("wish" , dir1
).string());
+ BOOST_TEST_EQUAL("/usr/bin/wish", modify_directory("wish" ,
"/usr/bin").string());
+
+ // An empty directory may be supplied.
+ BOOST_TEST_EQUAL("sh" , modify_directory("sh" , ""
).string());
+ BOOST_TEST_EQUAL("sh" , modify_directory("/bin/sh", ""
).string());
+
+ // Arguably this should be forbidden:
+ // $ls /bin/sh/
+ // ls: cannot access '/bin/sh/': Not a directory
+ BOOST_TEST_EQUAL("/bin/sh" , modify_directory("sh/" , "/bin/"
).string());
+
+ BOOST_TEST_THROW
+ (modify_directory("", "/bin")
+ ,std::runtime_error
+ ,"Assertion 'original_filepath.has_leaf()' failed."
+ );
+}
+
void test_orthodox_filename()
{
BOOST_TEST_THROW
@@ -311,6 +341,7 @@ void test_path_validation()
int test_main(int, char*[])
{
+ test_modify_directory();
test_orthodox_filename();
test_serial_file_path();
test_unique_filepath_with_normal_filenames();