From 093d031ec45b74bb5c880c3ce3ca7f181c600e9f Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 17 May 2018 14:26:09 +0300 Subject: Pass ignore_dangling flag to dir_iterator() ctor --- build2/algorithm.cxx | 5 +- build2/cc/link-rule.cxx | 5 +- build2/file.cxx | 154 +++++++++++++++++++++-------------------- build2/target.txx | 28 +++++--- build2/test/script/builtin.cxx | 3 +- build2/test/script/runner.cxx | 8 ++- 6 files changed, 113 insertions(+), 90 deletions(-) diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index ba9f5bc..bc810df 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -1055,7 +1055,7 @@ namespace build2 if (!(d ? dir_exists (p) : file_exists (p))) return; - for (;; ) // Retry/fallback loop. + for (;;) // Retry/fallback loop. try { switch (m) @@ -1078,7 +1078,8 @@ namespace build2 try_mkdir (to); - for (const auto& de: dir_iterator (fr)) + for (const auto& de: dir_iterator (fr, + false /* ignore_dangling */)) { path f (fr / de.path ()); path t (to / de.path ()); diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx index 358a835..c413d0a 100644 --- a/build2/cc/link-rule.cxx +++ b/build2/cc/link-rule.cxx @@ -1975,7 +1975,10 @@ namespace build2 return true; }; - path_search (p, rm, dir_path (), false); // Don't follow symlinks. + path_search (p, + rm, + dir_path () /* start */, + false /* follow_symlinks */); } catch (const system_error&) {} // Ignore errors. } diff --git a/build2/file.cxx b/build2/file.cxx index cadcc29..38d4a49 100644 --- a/build2/file.cxx +++ b/build2/file.cxx @@ -179,31 +179,41 @@ namespace build2 // our needs are pretty basic and performance is quite important, so let's // handle this ourselves. // - for (const dir_entry& de: dir_iterator (d)) + try { - // If this is a link, then type() will try to stat() it. And if the link - // is dangling or points to something inaccessible, it will fail. So - // let's first check that the name matches and only then check the type. - // - const path& n (de.path ()); + for (const dir_entry& de: dir_iterator (d, false /* ignore_dangling */)) + { + // If this is a link, then type() will try to stat() it. And if the + // link is dangling or points to something inaccessible, it will fail. + // So let's first check that the name matches and only then check the + // type. + // + const path& n (de.path ()); - if (n.string ().compare (0, pre ? 4 : 5, pre ? "pre-" : "post-") != 0 || - n.extension () != "build") - continue; + if (n.string ().compare (0, + pre ? 4 : 5, + pre ? "pre-" : "post-") != 0 || + n.extension () != "build") + continue; - path f (d / n); + path f (d / n); - try - { - if (de.type () != entry_type::regular) - continue; - } - catch (const system_error& e) - { - fail << "unable to read buildfile " << f << ": " << e; - } + try + { + if (de.type () != entry_type::regular) + continue; + } + catch (const system_error& e) + { + fail << "unable to read buildfile " << f << ": " << e; + } - source_once (root, root, f); + source_once (root, root, f); + } + } + catch (const system_error& e) + { + fail << "unable to iterate over " << d << ": " << e; } } @@ -536,75 +546,71 @@ namespace build2 { tracer trace ("find_subprojects"); - for (const dir_entry& de: dir_iterator (d)) + try { - // If this is a link, then type() will try to stat() it. And if - // the link is dangling or points to something inaccessible, it - // will fail. - // - try + for (const dir_entry& de: dir_iterator (d, true /* ignore_dangling */)) { if (de.type () != entry_type::directory) continue; - } - catch (const system_error&) - { - continue; - } - dir_path sd (d / path_cast (de.path ())); + dir_path sd (d / path_cast (de.path ())); - bool src (false); - if (!((out && is_out_root (sd)) || (src = is_src_root (sd)))) - { - // We used to scan for subproject recursively but this is probably too - // loose (think of some tests laying around). In the future we should - // probably allow specifying something like extra/* or extra/** in - // subprojects. - // - //find_subprojects (sps, sd, root, out); - // - continue; - } + bool src (false); + if (!((out && is_out_root (sd)) || (src = is_src_root (sd)))) + { + // We used to scan for subproject recursively but this is probably + // too loose (think of some tests laying around). In the future we + // should probably allow specifying something like extra/* or + // extra/** in subprojects. + // + //find_subprojects (sps, sd, root, out); + // + continue; + } - // Calculate relative subdirectory for this subproject. - // - dir_path dir (sd.leaf (root)); - l5 ([&]{trace << "subproject " << sd << " as " << dir;}); + // Calculate relative subdirectory for this subproject. + // + dir_path dir (sd.leaf (root)); + l5 ([&]{trace << "subproject " << sd << " as " << dir;}); - // Load its name. Note that here we don't use fallback src_root - // since this function is used to scan both out_root and src_root. - // - string name (find_project_name (sd, dir_path (), &src)); + // Load its name. Note that here we don't use fallback src_root + // since this function is used to scan both out_root and src_root. + // + string name (find_project_name (sd, dir_path (), &src)); - // If the name is empty, then is is an unnamed project. While the - // 'project' variable stays empty, here we come up with a surrogate - // name for a key. The idea is that such a key should never conflict - // with a real project name. We ensure this by using the project's - // sub-directory and appending a trailing directory separator to it. - // - if (name.empty ()) - name = dir.posix_string () + path::traits::directory_separator; + // If the name is empty, then is is an unnamed project. While the + // 'project' variable stays empty, here we come up with a surrogate + // name for a key. The idea is that such a key should never conflict + // with a real project name. We ensure this by using the project's + // sub-directory and appending a trailing directory separator to it. + // + if (name.empty ()) + name = dir.posix_string () + path::traits::directory_separator; - // @@ Can't use move() because we may need the values in diagnostics - // below. Looks like C++17 try_emplace() is what we need. - // - auto rp (sps.emplace (name, dir)); + // @@ Can't use move() because we may need the values in diagnostics + // below. Looks like C++17 try_emplace() is what we need. + // + auto rp (sps.emplace (name, dir)); - // Handle duplicates. - // - if (!rp.second) - { - const dir_path& dir1 (rp.first->second); + // Handle duplicates. + // + if (!rp.second) + { + const dir_path& dir1 (rp.first->second); - if (dir != dir1) - fail << "inconsistent subproject directories for " << name << - info << "first alternative: " << dir1 << - info << "second alternative: " << dir; + if (dir != dir1) + fail << "inconsistent subproject directories for " << name << + info << "first alternative: " << dir1 << + info << "second alternative: " << dir; - l6 ([&]{trace << "skipping duplicate";}); + l6 ([&]{trace << "skipping duplicate";}); + } } } + catch (const system_error& e) + { + fail << "unable to iterate over " << d << ": " << e; + } } bool diff --git a/build2/target.txx b/build2/target.txx index a5d6728..d93d300 100644 --- a/build2/target.txx +++ b/build2/target.txx @@ -158,17 +158,25 @@ namespace build2 // prerequisites_type ps; - for (const dir_entry& e: dir_iterator (base.src_path ())) + try { - if (e.type () == entry_type::directory) - ps.push_back ( - prerequisite (nullopt, - dir::static_type, - dir_path (e.path ().representation ()), - dir_path (), // In the out tree. - string (), - nullopt, - base)); + for (const dir_entry& e: dir_iterator (base.src_path (), + true /* ignore_dangling */)) + { + if (e.type () == entry_type::directory) + ps.push_back ( + prerequisite (nullopt, + dir::static_type, + dir_path (e.path ().representation ()), + dir_path (), // In the out tree. + string (), + nullopt, + base)); + } + } + catch (const system_error& e) + { + fail << "unable to iterate over " << base.src_path () << ": " << e; } if (ps.empty ()) diff --git a/build2/test/script/builtin.cxx b/build2/test/script/builtin.cxx index 91d5bf2..0a238bb 100644 --- a/build2/test/script/builtin.cxx +++ b/build2/test/script/builtin.cxx @@ -306,7 +306,8 @@ namespace build2 if (cleanup) sp.clean ({cleanup_type::always, to}, true); - for (const auto& de: dir_iterator (from)) // Can throw. + for (const auto& de: dir_iterator (from, + false /* ignore_dangling */)) { path f (from / de.path ()); path t (to / de.path ()); diff --git a/build2/test/script/runner.cxx b/build2/test/script/runner.cxx index 889b27c..6496b0f 100644 --- a/build2/test/script/runner.cxx +++ b/build2/test/script/runner.cxx @@ -132,7 +132,8 @@ namespace build2 try { size_t n (0); - for (const dir_entry& de: dir_iterator (p)) + for (const dir_entry& de: dir_iterator (p, + false /* ignore_dangling */)) { if (n++ < 10) d << '\n' << (de.ltype () == entry_type::directory @@ -822,7 +823,10 @@ namespace build2 // try { - path_search (p, rm); + path_search (p, + rm, + dir_path () /* start */, + false /* follow_symlinks */); } catch (const system_error& e) { -- cgit v1.1