lmi-commits
[Top][All Lists]
Advanced

[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();



reply via email to

[Prev in Thread] Current Thread [Next in Thread]