# # # patch "restrictions.cc" # from [0ab22cab0d432eb6e2cff34db3db6bac7a1ff6ab] # to [56fc39ab78a21dfadc8c48582e3b6bac297401da] # # patch "restrictions.hh" # from [cbbc558507e794f658622f153ebda63b1b5ea039] # to [d349fca527a084d74bf2660ba809c22a8604adc3] # # patch "unit-tests/restrictions.cc" # from [c7f6ce107a7c5599ed0dac7ecfff2b9f0268f0b3] # to [f5985b0a8c3837537356ba72da60dc9598c9e933] # ============================================================ --- restrictions.cc 0ab22cab0d432eb6e2cff34db3db6bac7a1ff6ab +++ restrictions.cc 56fc39ab78a21dfadc8c48582e3b6bac297401da @@ -37,6 +37,52 @@ static void typedef set::const_iterator path_iterator; static void +add_parents(map & node_map, + roster_t const & roster) +{ + set parents; + + // accumulate the set of parents of all included nodes + for (node_status_iterator i = node_map.begin(); i != node_map.end(); ++i) + { + if (i->second == restricted_path::included && roster.has_node(i->first)) + { + node_id parent = roster.get_node(i->first)->parent; + while (!null_node(parent) && parents.find(parent) == parents.end()) + { + parents.insert(parent); + parent = roster.get_node(parent)->parent; + } + } + } + + // add implicit includes for all required parents + for (set::const_iterator i = parents.begin(); + i != parents.end(); ++i) + { + node_status_iterator n = node_map.find(*i); + if (n == node_map.end()) + { + file_path fp; + roster.get_name(*i, fp); + W(F("including missing parent '%s'") % fp); + node_map[*i] = restricted_path::required; + } + else if (n->second == restricted_path::included) + { + node_map[*i] = restricted_path::included_required; + } + else if (n->second == restricted_path::excluded) + { + file_path fp; + roster.get_name(*i, fp); + W(F("including required parent '%s'") % fp); + node_map[*i] = restricted_path::excluded_required; + } + } +} + +static void map_nodes(map & node_map, roster_t const & roster, set const & paths, @@ -55,7 +101,8 @@ map_nodes(mapsecond == status, origin::user, F("conflicting include/exclude on path '%s'") % *i); else - node_map.insert(make_pair(nid, status)); + node_map[nid] = status; + } } } @@ -74,6 +121,49 @@ static void } static void +add_parents(map & path_map) +{ + set parents; + + // accumulate the set of parents of all included paths + for (path_status_iterator i = path_map.begin(); i != path_map.end(); ++i) + { + if (i->second == restricted_path::included) + { + file_path parent = i->first.dirname(); + while (!parent.empty() && parents.find(parent) == parents.end()) + { + parents.insert(parent); + parent = parent.dirname(); + } + parents.insert(parent); + } + } + + // add implicit includes for all required parents + for (set::const_iterator i = parents.begin(); + i != parents.end(); ++i) + { + path_status_iterator p = path_map.find(*i); + if (p == path_map.end()) + { + W(F("including missing parent '%s'") % *i); + path_map[*i] = restricted_path::required; + } + else if (p->second == restricted_path::included) + { + path_map[*i] = restricted_path::included_required; + } + else if (p->second == restricted_path::excluded) + { + W(F("including required parent '%s'") % *i); + path_map[*i] = restricted_path::excluded_required; + } + } + +} + +static void map_paths(map & path_map, set const & paths, restricted_path::status const status) @@ -85,7 +175,7 @@ map_paths(mapsecond == status, origin::user, F("conflicting include/exclude on path '%s'") % *i); else - path_map.insert(make_pair(*i, status)); + path_map[*i] = status; } } @@ -164,6 +254,7 @@ node_restriction::node_restriction(vecto : restriction(includes, excludes, depth) { map_nodes(node_map, roster, included_paths, excluded_paths, known_paths); + add_parents(node_map, roster); validate_paths(included_paths, excluded_paths, unknown_unignored_node(known_paths, ignore)); } @@ -178,7 +269,8 @@ node_restriction::node_restriction(vecto { map_nodes(node_map, roster1, included_paths, excluded_paths, known_paths); map_nodes(node_map, roster2, included_paths, excluded_paths, known_paths); - + add_parents(node_map, roster1); + add_parents(node_map, roster2); validate_paths(included_paths, excluded_paths, unknown_unignored_node(known_paths, ignore)); } @@ -196,6 +288,12 @@ node_restriction::node_restriction(vecto map_nodes(node_map, parent_roster(i), included_paths, excluded_paths, known_paths); map_nodes(node_map, roster2, included_paths, excluded_paths, known_paths); + + for (parent_map::const_iterator i = rosters1.begin(); + i != rosters1.end(); i++) + add_parents(node_map, parent_roster(i)); + add_parents(node_map, roster2); + validate_paths(included_paths, excluded_paths, unknown_unignored_node(known_paths, ignore)); } @@ -208,7 +306,7 @@ path_restriction::path_restriction(vecto { map_paths(path_map, included_paths, restricted_path::included); map_paths(path_map, excluded_paths, restricted_path::excluded); - + add_parents(path_map); validate_paths(included_paths, excluded_paths, unknown_unignored_path(ignore)); } @@ -221,6 +319,7 @@ path_restriction::path_restriction(vecto { map_paths(path_map, included_paths, restricted_path::included); map_paths(path_map, excluded_paths, restricted_path::excluded); + add_parents(path_map); } bool @@ -268,14 +367,26 @@ node_restriction::includes(roster_t cons switch (r->second) { case restricted_path::included: - L(FL("explicit include of nid %d path '%s'") - % current % fp); + case restricted_path::included_required: + L(FL("explicit include of nid %d path '%s'") % current % fp); return true; case restricted_path::excluded: - L(FL("explicit exclude of nid %d path '%s'") - % current % fp); + L(FL("explicit exclude of nid %d path '%s'") % current % fp); return false; + + case restricted_path::required: + case restricted_path::excluded_required: + if (path_depth == 0) + { + L(FL("implicit include of nid %d path '%s'") % current % fp); + return true; + } + else + { + return false; + } + return true; } } @@ -335,12 +446,25 @@ path_restriction::includes(file_path con switch (r->second) { case restricted_path::included: + case restricted_path::included_required: L(FL("explicit include of path '%s'") % pth); return true; case restricted_path::excluded: L(FL("explicit exclude of path '%s'") % pth); return false; + + case restricted_path::required: + case restricted_path::excluded_required: + if (path_depth == 0) + { + L(FL("implicit include of path '%s'") % pth); + return true; + } + else + { + return false; + } } } @@ -362,11 +486,6 @@ path_restriction::includes(file_path con } } -/////////////////////////////////////////////////////////////////////// -// tests -/////////////////////////////////////////////////////////////////////// - - // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- restrictions.hh cbbc558507e794f658622f153ebda63b1b5ea039 +++ restrictions.hh d349fca527a084d74bf2660ba809c22a8604adc3 @@ -56,7 +56,14 @@ namespace restricted_path namespace restricted_path { - enum status { included, excluded }; + enum status + { + included, + excluded, + required, + included_required, + excluded_required + }; } class restriction ============================================================ --- unit-tests/restrictions.cc c7f6ce107a7c5599ed0dac7ecfff2b9f0268f0b3 +++ unit-tests/restrictions.cc f5985b0a8c3837537356ba72da60dc9598c9e933 @@ -230,11 +230,13 @@ UNIT_TEST(simple_include) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // the root is included implicitly as the parent of x/x and y/y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_x)); + // x is included implicitly as the parent of x/x + UNIT_TEST_CHECK( nmask.includes(roster, nid_x)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xg)); UNIT_TEST_CHECK( nmask.includes(roster, nid_xx)); @@ -244,7 +246,8 @@ UNIT_TEST(simple_include) UNIT_TEST_CHECK(!nmask.includes(roster, nid_xyf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xyg)); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_y)); + // y is included implicitly as the parent of y/y + UNIT_TEST_CHECK( nmask.includes(roster, nid_y)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yg)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yx)); @@ -260,11 +263,13 @@ UNIT_TEST(simple_include) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // the root is included implicitly as the parent of x/x and y/y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g)); - UNIT_TEST_CHECK(!pmask.includes(fp_x)); + // x is included implicitly as the parent of x/x + UNIT_TEST_CHECK( pmask.includes(fp_x)); UNIT_TEST_CHECK(!pmask.includes(fp_xf)); UNIT_TEST_CHECK(!pmask.includes(fp_xg)); UNIT_TEST_CHECK( pmask.includes(fp_xx)); @@ -274,7 +279,8 @@ UNIT_TEST(simple_include) UNIT_TEST_CHECK(!pmask.includes(fp_xyf)); UNIT_TEST_CHECK(!pmask.includes(fp_xyg)); - UNIT_TEST_CHECK(!pmask.includes(fp_y)); + // y is included implicitly as the parent of y/y + UNIT_TEST_CHECK( pmask.includes(fp_y)); UNIT_TEST_CHECK(!pmask.includes(fp_yf)); UNIT_TEST_CHECK(!pmask.includes(fp_yg)); UNIT_TEST_CHECK(!pmask.includes(fp_yx)); @@ -372,7 +378,8 @@ UNIT_TEST(include_exclude) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // the root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); @@ -402,7 +409,8 @@ UNIT_TEST(include_exclude) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // the root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g)); @@ -447,11 +455,16 @@ UNIT_TEST(exclude_include) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // the root is included implicitly as the parent of x/x and y/y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_x)); + // x is included implicitly as the parent of x/x + // even though x is also explcitly excluded + // the implicit include applies only to x but not + // its children + UNIT_TEST_CHECK( nmask.includes(roster, nid_x)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xg)); UNIT_TEST_CHECK( nmask.includes(roster, nid_xx)); @@ -461,7 +474,11 @@ UNIT_TEST(exclude_include) UNIT_TEST_CHECK(!nmask.includes(roster, nid_xyf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_xyg)); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_y)); + // y is included implicitly as the parent of y/y + // even though y is also explcitly excluded + // the implicit include applies only to y but not + // its children + UNIT_TEST_CHECK( nmask.includes(roster, nid_y)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yf)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yg)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_yx)); @@ -477,11 +494,16 @@ UNIT_TEST(exclude_include) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // the root is included implicitly as the parent of x/x and y/y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g)); - UNIT_TEST_CHECK(!pmask.includes(fp_x)); + // x is included implicitly as the parent of x/x + // even though x is also explcitly excluded + // the implicit include applies only to x but not + // its children + UNIT_TEST_CHECK( pmask.includes(fp_x)); UNIT_TEST_CHECK(!pmask.includes(fp_xf)); UNIT_TEST_CHECK(!pmask.includes(fp_xg)); UNIT_TEST_CHECK( pmask.includes(fp_xx)); @@ -491,7 +513,11 @@ UNIT_TEST(exclude_include) UNIT_TEST_CHECK(!pmask.includes(fp_xyf)); UNIT_TEST_CHECK(!pmask.includes(fp_xyg)); - UNIT_TEST_CHECK(!pmask.includes(fp_y)); + // y is included implicitly as the parent of y/y + // even though y is also explcitly excluded + // the implicit include applies only to y but not + // its children + UNIT_TEST_CHECK( pmask.includes(fp_y)); UNIT_TEST_CHECK(!pmask.includes(fp_yf)); UNIT_TEST_CHECK(!pmask.includes(fp_yg)); UNIT_TEST_CHECK(!pmask.includes(fp_yx)); @@ -561,7 +587,8 @@ UNIT_TEST(include_depth_0) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); @@ -591,7 +618,8 @@ UNIT_TEST(include_depth_0) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g)); @@ -633,7 +661,8 @@ UNIT_TEST(include_depth_1) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); @@ -663,7 +692,8 @@ UNIT_TEST(include_depth_1) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g)); @@ -775,7 +805,8 @@ UNIT_TEST(include_depth_2) UNIT_TEST_CHECK(!nmask.empty()); - UNIT_TEST_CHECK(!nmask.includes(roster, nid_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( nmask.includes(roster, nid_root)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_f)); UNIT_TEST_CHECK(!nmask.includes(roster, nid_g)); @@ -805,7 +836,8 @@ UNIT_TEST(include_depth_2) UNIT_TEST_CHECK(!pmask.empty()); - UNIT_TEST_CHECK(!pmask.includes(fp_root)); + // root is included implicitly as the parent of x and y + UNIT_TEST_CHECK( pmask.includes(fp_root)); UNIT_TEST_CHECK(!pmask.includes(fp_f)); UNIT_TEST_CHECK(!pmask.includes(fp_g));