mirror of
https://github.com/boostorg/filesystem.git
synced 2025-05-12 13:41:47 +00:00
Reworked absolute() to fix appending root directory.
Because of the changed semantics of appending operations in v4, path composition in absolute() would produce incorrect results because at some point it would append root directory and therefore discard root name that was potentially added before. The updated implementation fixes that, and also fixes the case when the input path is already absolute and starts with a root directory, and the base path has a root name. Previously, the returned path would contain the root name from the base path, while the correct thing to do is to return the input path as is.
This commit is contained in:
parent
0d413a5e4f
commit
cc763cb48e
@ -45,6 +45,7 @@
|
||||
<li><b>v4:</b> <code>path</code> append operations now consider root name and root directory in the appended path. If the appended path is absolute, or root name is present and differs from the source path, the resulting path is equivalent to the appended path. If root directory is present, the result is the root directory and
|
||||
relative path rebased on top of the root name of the source path. Otherwise, the behavior is similar to v3.(<a href="https://github.com/boostorg/filesystem/issues/214">#214</a>)</li>
|
||||
<li>Optimized overloads of <code>path::assign</code>, <code>path::append</code>, <code>path::concat</code> and the corresponding operators to avoid unnecessary path copying and reduce the amount of code redundancy.</li>
|
||||
<li>On POSIX systems, fixed <code>absolute(p, base)</code> returning a path with root name <code>base.root_name()</code> if <code>p</code> starts with a root directory. In such a case <code>p</code> is already an absolute path and should be returned as is.</li>
|
||||
<li><code>create_directories</code> no longer reports an error if the input path consists entirely of dot (".") and dot-dot ("..") elements. The implementation is no longer using recursion internally and therefore is better protected from stack overflow on extremely long paths.</li>
|
||||
</ul>
|
||||
|
||||
|
@ -1344,24 +1344,12 @@ BOOST_FILESYSTEM_DECL bool possible_large_file_size_support()
|
||||
BOOST_FILESYSTEM_DECL
|
||||
path absolute(path const& p, path const& base, system::error_code* ec)
|
||||
{
|
||||
// if ( p.empty() || p.is_absolute() )
|
||||
// return p;
|
||||
// // recursively calling absolute is sub-optimal, but is simple
|
||||
// path abs_base(base.is_absolute() ? base : absolute(base));
|
||||
//# ifdef BOOST_WINDOWS_API
|
||||
// if (p.has_root_directory())
|
||||
// return abs_base.root_name() / p;
|
||||
// // !p.has_root_directory
|
||||
// if (p.has_root_name())
|
||||
// return p.root_name()
|
||||
// / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
|
||||
// // !p.has_root_name()
|
||||
//# endif
|
||||
// return abs_base / p;
|
||||
|
||||
if (ec)
|
||||
ec->clear();
|
||||
|
||||
if (p.is_absolute())
|
||||
return p;
|
||||
|
||||
// recursively calling absolute is sub-optimal, but is sure and simple
|
||||
path abs_base = base;
|
||||
if (!base.is_absolute())
|
||||
@ -1378,35 +1366,30 @@ path absolute(path const& p, path const& base, system::error_code* ec)
|
||||
}
|
||||
}
|
||||
|
||||
// store expensive to compute values that are needed multiple times
|
||||
path p_root_name(p.root_name());
|
||||
path base_root_name(abs_base.root_name());
|
||||
path p_root_directory(p.root_directory());
|
||||
|
||||
if (p.empty())
|
||||
return abs_base;
|
||||
|
||||
if (!p_root_name.empty()) // p.has_root_name()
|
||||
path res;
|
||||
if (p.has_root_name())
|
||||
res = p.root_name();
|
||||
else
|
||||
res = abs_base.root_name();
|
||||
|
||||
if (p.has_root_directory())
|
||||
{
|
||||
if (p_root_directory.empty()) // !p.has_root_directory()
|
||||
return p_root_name / abs_base.root_directory() / abs_base.relative_path() / p.relative_path();
|
||||
// p is absolute, so fall through to return p at end of block
|
||||
}
|
||||
else if (!p_root_directory.empty()) // p.has_root_directory()
|
||||
{
|
||||
#ifdef BOOST_POSIX_API
|
||||
// POSIX can have root name it it is a network path
|
||||
if (base_root_name.empty()) // !abs_base.has_root_name()
|
||||
return p;
|
||||
#endif
|
||||
return base_root_name / p;
|
||||
res.concat(p.root_directory());
|
||||
}
|
||||
else
|
||||
{
|
||||
return abs_base / p;
|
||||
res.concat(abs_base.root_directory());
|
||||
res /= abs_base.relative_path();
|
||||
}
|
||||
|
||||
return p; // p.is_absolute() is true
|
||||
path p_relative_path(p.relative_path());
|
||||
if (!p_relative_path.empty())
|
||||
res /= p_relative_path;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_FILESYSTEM_DECL
|
||||
|
@ -1475,10 +1475,17 @@ void absolute_tests()
|
||||
}
|
||||
// !p.has_root_name()
|
||||
// p.has_root_directory()
|
||||
#ifdef BOOST_WINDOWS_API
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/"), fs::path("//xyz/"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/abc"), fs::path("//xyz/"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/"), fs::path("//xyz/foo"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/abc"), fs::path("//xyz/foo"));
|
||||
#else
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/"), fs::path("/"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/"), "//xyz/abc"), fs::path("/"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/"), fs::path("/foo"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("/foo"), "//xyz/abc"), fs::path("/foo"));
|
||||
#endif
|
||||
// !p.has_root_directory()
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("foo"), "//xyz/abc"), fs::path("//xyz/abc/foo"));
|
||||
BOOST_TEST_EQ(fs::absolute(fs::path("foo/bar"), "//xyz/abc"), fs::path("//xyz/abc/foo/bar"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user