# # # patch "paths.cc" # from [b0902623bc22d2c70bf7f9a17f6352dba3b165eb] # to [c17f38dc8d335bba640982d366d6d464a20cb042] # # patch "paths.hh" # from [80790ad2366edac43b0ac04114fddfe526b97c8a] # to [80931173a8567a2f0dffd3d0551d929540bd33a9] # # patch "restrictions.cc" # from [1cfe70b83bb6fc1cc0c3291dee38ba94e0d03de0] # to [36f318743e3c6d54e1cc23362709fed8048e4699] # ============================================================ --- paths.cc b0902623bc22d2c70bf7f9a17f6352dba3b165eb +++ paths.cc c17f38dc8d335bba640982d366d6d464a20cb042 @@ -508,6 +508,22 @@ file_path::dirname() const return file_path(s, 0, sep); } + +// count the number of /-separated components of the path. +unsigned int +file_path::depth() const +{ + if (data().empty()) + return 0; + + unsigned int components = 1; + for (string::const_iterator p = data().begin(); p != data().end(); p++) + if (*p == '/') + components++; + + return components; +} + /////////////////////////////////////////////////////////////////////////// // localizing file names (externalizing them) // this code must be superfast when there is no conversion needed @@ -1345,7 +1361,6 @@ UNIT_TEST(paths, basename) initial_abs_path.unset(); } - UNIT_TEST(paths, dirname) { struct t @@ -1372,6 +1387,18 @@ UNIT_TEST(paths, dirname) } } +UNIT_TEST(paths, depth) +{ + char const * const cases[] = {"", "foo", "foo/bar", "foo/bar/baz", 0}; + for (unsigned int i = 0; cases[i]; i++) + { + file_path fp = file_path_internal(cases[i]); + unsigned int d = fp.depth(); + UNIT_TEST_CHECK_MSG(d == i, + FL("depth('%s') = %d (expect %d)") % fp % d % i); + } +} + static void check_bk_normalizes_to(char * before, char * after) { bookkeeping_path bp(bookkeeping_root / before); ============================================================ --- paths.hh 80790ad2366edac43b0ac04114fddfe526b97c8a +++ paths.hh 80931173a8567a2f0dffd3d0551d929540bd33a9 @@ -195,8 +195,18 @@ public: file_path operator /(file_path const & to_append) const; void split(split_path & sp) const; + + // these functions could be defined on any_path but are only needed + // for file_path, and not defining them for system_path gets us out + // of nailing down the semantics near the absolute root. + + // returns a path with the last component removed. file_path dirname() const; + // returns the number of /-separated components of the path. + // The empty path has depth zero. + unsigned int depth() const; + // ordering... bool operator ==(const file_path & other) const { return data == other.data; } ============================================================ --- restrictions.cc 1cfe70b83bb6fc1cc0c3291dee38ba94e0d03de0 +++ restrictions.cc 36f318743e3c6d54e1cc23362709fed8048e4699 @@ -237,15 +237,13 @@ node_restriction::includes(roster_t cons I(roster.has_node(nid)); file_path fp; - split_path sp; roster.get_name(nid, fp); - fp.split(sp); if (empty()) { if (depth != -1) { - int path_depth = sp.size() - 1; // -1 to not count root path_component + int path_depth = fp.depth(); if (path_depth <= depth + 1) { L(FL("depth includes nid %d path '%s'") % nid % fp); @@ -321,27 +319,25 @@ path_restriction::includes(file_path con bool path_restriction::includes(file_path const & pth) const { - split_path sp; - pth.split(sp); if (empty()) { if (depth != -1) { - int path_depth = sp.size() - 1; // -1 to not count root path_component + int path_depth = pth.depth(); if (path_depth <= depth + 1) { - L(FL("depth includes path '%s'") % file_path(sp)); + L(FL("depth includes path '%s'") % pth); return true; } else { - L(FL("depth excludes path '%s'") % file_path(sp)); + L(FL("depth excludes path '%s'") % pth); return false; } } else { - L(FL("empty include of path '%s'") % file_path(sp)); + L(FL("empty include of path '%s'") % pth); return true; } } @@ -353,10 +349,11 @@ path_restriction::includes(file_path con // children" int path_depth = 0; - while (!sp.empty() && (depth == -1 || path_depth <= depth + 1)) + file_path fp = pth; + while (depth == -1 || path_depth <= depth + 1) { map::const_iterator - r = path_map.find(file_path(sp)); + r = path_map.find(fp); if (r != path_map.end()) { @@ -372,7 +369,9 @@ path_restriction::includes(file_path con } } - sp.pop_back(); + if (fp.empty()) + break; + fp = fp.dirname(); path_depth++; }