From ede84eefd781d67370aefe96b57e68f4758b1bfb Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Tue, 29 May 2012 15:53:02 +0000 Subject: [PATCH] Filesystem: Further fixes for #6932. Clarify docs. Add test cases. [SVN r78747] --- doc/reference.html | 25 ++++++++++++-------- doc/src/source.html | 25 ++++++++++++-------- doc/src/tr2_snippets.html | 17 +++++++++++++- src/operations.cpp | 48 +++++++++++++++++++-------------------- test/operations_test.cpp | 12 ++++++---- 5 files changed, 77 insertions(+), 50 deletions(-) diff --git a/doc/reference.html b/doc/reference.html index fbfd7a0..f4cf435 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -2287,18 +2287,24 @@ void copy_symlink(const path& existing_symlink, const path& new_symlink,
bool create_directories(const path& p);
 bool create_directories(const path& p, system::error_code& ec);
-

Requires: p.empty() ||
- forall px: px == p || is_parent(px, p): is_directory(px) || !exists( px )

+

Effects: Establishes the postcondition by calling + create_directory() for any element of p that does not + exist.

Postcondition: is_directory(p)

-

Returns: The value of !exists(p) prior to the - establishment of the postcondition.

+

Returns: true if a new directory was created, otherwise + false.

Throws: As specified in Error reporting.

+

Complexity: O(n+1) where n is the number of elements + of p that do not exist.

bool create_directory(const path& p);
 bool create_directory(const path& p, system::error_code& ec);
-

Effects: Attempts to create the directory p resolves to, - as if by POSIX mkdir() with a second argument of S_IRWXU|S_IRWXG|S_IRWXO.

+

Effects: Establishes the postcondition by attempting to create the + directory p resolves to, as if by POSIX + mkdir() with a second argument of S_IRWXU|S_IRWXG|S_IRWXO. Creation + failure because p resolves to an existing directory shall not be + treated as an error.

Postcondition: is_directory(p)

Returns: true if a new directory was created, otherwise false.

Throws: As specified in Error reporting.

@@ -2383,10 +2389,9 @@ void current_path(const path& p, system::error_code& ec);
bool exists(const path& p);
 bool exists(const path& p, system::error_code& ec) noexcept;
-

Returns: exists(status(p)) or exists(status(p, ec)), - respectively.

-

Throws: filesystem_error; overload with error_code& throws -nothing.

+

Returns: exists(status(p)) or exists(status(p, ec)), + respectively. If ec != 0 and an error

+

Throws: As specified in Error reporting.

bool equivalent(const path& p1, const path& p2);
 bool equivalent(const path& p1, const path& p2, system::error_code& ec);
diff --git a/doc/src/source.html b/doc/src/source.html index c799a86..c32867e 100644 --- a/doc/src/source.html +++ b/doc/src/source.html @@ -2227,18 +2227,24 @@ void copy_symlink(const path& existing_symlink, const path& new_symlink,
bool create_directories(const path& p);
 bool create_directories(const path& p, system::error_code& ec);
-

Requires: p.empty() ||
- forall px: px == p || is_parent(px, p): is_directory(px) || !exists( px )

+

Effects: Establishes the postcondition by calling + create_directory() for any element of p that does not + exist.

Postcondition: is_directory(p)

-

Returns: The value of !exists(p) prior to the - establishment of the postcondition.

+

Returns: true if a new directory was created, otherwise + false.

Throws: As specified in Error reporting.

+

Complexity: O(n+1) where n is the number of elements + of p that do not exist.

bool create_directory(const path& p);
 bool create_directory(const path& p, system::error_code& ec);
-

Effects: Attempts to create the directory p resolves to, - as if by POSIX mkdir() with a second argument of S_IRWXU|S_IRWXG|S_IRWXO.

+

Effects: Establishes the postcondition by attempting to create the + directory p resolves to, as if by POSIX + mkdir() with a second argument of S_IRWXU|S_IRWXG|S_IRWXO. Creation + failure because p resolves to an existing directory shall not be + treated as an error.

Postcondition: is_directory(p)

Returns: true if a new directory was created, otherwise false.

Throws: As specified in Error reporting.

@@ -2323,10 +2329,9 @@ void current_path(const path& p, system::error_code& ec);
bool exists(const path& p);
 bool exists(const path& p, system::error_code& ec) noexcept;
-

Returns: exists(status(p)) or exists(status(p, ec)), - respectively.

-

Throws: filesystem_error; overload with error_code& throws -nothing.

+

Returns: exists(status(p)) or exists(status(p, ec)), + respectively. If ec != 0 and an error

+

Throws: As specified in Error reporting.

bool equivalent(const path& p1, const path& p2);
 bool equivalent(const path& p1, const path& p2, system::error_code& ec);
diff --git a/doc/src/tr2_snippets.html b/doc/src/tr2_snippets.html index c500f2e..51d14d9 100644 --- a/doc/src/tr2_snippets.html +++ b/doc/src/tr2_snippets.html @@ -20,7 +20,7 @@ $id frontmatter= Date: - 2012-04-18 + 2012-04-24 Project: @@ -394,6 +394,21 @@ behavior without reference to how it is achieved. (If someone wants to propose a quoted manipulator, that's a separate proposal for a different TR.)

Action:  Beman to apply to proposed wording.


+

Issue 8: Rename rename       +Status: New

+

Discussion

+

There are minor problems with the name of the rename() function:

+
    +
  • There is already a "rename" function, albeit in namespace std, and it has + different semantics as regards error handling. Thus giving the function a + different name might reduce the chance of user error.
  • +
  • The name "move" would  better reflect the actual semantics, + particularly for moves between directories., and this is the name used by some + API's, console commands, and GUI file managers for that functionality.
  • +
+

Proposed resolution

+

Change the name of the rename() function to move().

+

$endid $id backmatter= diff --git a/src/operations.cpp b/src/operations.cpp index 05d21cf..02a542b 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -913,45 +913,43 @@ namespace detail # endif } - BOOST_FILESYSTEM_DECL + BOOST_FILESYSTEM_DECL bool create_directories(const path& p, system::error_code* ec) { - if (exists(p)) + error_code local_ec; + file_status p_status = status(p, local_ec); + + if (p_status.type() == directory_file) { - if (!is_directory(p)) - { - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error( - "boost::filesystem::create_directories", p, - error_code(system::errc::file_exists, system::generic_category()))); - else - ec->assign(system::errc::file_exists, system::generic_category()); - } - else if (ec) + if (ec != 0) ec->clear(); return false; } - // First create branch, by calling ourself recursively path parent = p.parent_path(); if (!parent.empty()) { - error_code local_ec; - create_directories(parent, local_ec); - if (local_ec) + // determine if the parent exists + file_status parent_status = status(parent, local_ec); + + // if the parent does not exist, create the parent + if (parent_status.type() == file_not_found) { - if (ec == 0) - BOOST_FILESYSTEM_THROW(filesystem_error( - "boost::filesystem::create_directories", p, local_ec)); - else - *ec = local_ec; - return false; + create_directories(parent, local_ec); + if (local_ec) + { + if (ec == 0) + BOOST_FILESYSTEM_THROW(filesystem_error( + "boost::filesystem::create_directories", parent, local_ec)); + else + *ec = local_ec; + return false; + } } } - // Now that parent's path exists, create the directory - create_directory(p, ec); - return ec == 0 || *ec == 0; + // create the directory + return create_directory(p, ec); } BOOST_FILESYSTEM_DECL diff --git a/test/operations_test.cpp b/test/operations_test.cpp index 4853121..c9690a0 100644 --- a/test/operations_test.cpp +++ b/test/operations_test.cpp @@ -1073,7 +1073,9 @@ namespace { cout << "create_directories_tests..." << endl; - fs::path p = dir / "level1" / "level2"; + BOOST_TEST(!fs::create_directories("/")); + + fs::path p = dir / "level1" / "level2" / "level3"; BOOST_TEST(!fs::exists(p)); BOOST_TEST(fs::create_directories(p)); @@ -1083,6 +1085,7 @@ namespace if (fs::exists("/permissions_test")) { error_code ec; + BOOST_TEST(!fs::create_directories("/permissions_test", ec)); BOOST_TEST(!fs::create_directories("/permissions_test/another_directory", ec)); BOOST_TEST(ec); } @@ -1598,7 +1601,7 @@ namespace // Windows only tests if (platform == "Windows") { - cout << "Window specific tests..." << endl; + cout << "Windows specific tests..." << endl; if (!skip_long_windows_tests) { cout << " (may take several seconds)"<< endl; @@ -1939,7 +1942,6 @@ int cpp_main(int argc, char* argv[]) initial_tests(); predicate_and_status_tests(); exception_tests(); - platform_specific_tests(); create_directory_tests(); current_directory_tests(); space_tests(); @@ -1992,8 +1994,10 @@ int cpp_main(int argc, char* argv[]) if (create_symlink_ok) // only if symlinks supported remove_symlink_tests(); write_time_tests(dir); - temp_directory_path_tests(); + + platform_specific_tests(); // do these last since they take a lot of time on Windows, + // and that's a pain during manual testing cout << "testing complete" << endl;