#
#
# patch "ChangeLog"
# from [c3ec3850928b5d2399a88867eb9502f7ab8922dc]
# to [f6958fd919e56d111b69bab1f6e983d66917249b]
#
# patch "restrictions.cc"
# from [77252f64fc5d5cbd4380de33ee362336379b45ec]
# to [da1dd31e81f09105bdf2016f5f66931237d129f0]
#
# patch "restrictions.hh"
# from [8d68ee9d4981f22f01ecf499602fcbc7b6d4b6fe]
# to [8d966a7dba0e522f4c51391290dc58f1f414edfe]
#
============================================================
--- ChangeLog c3ec3850928b5d2399a88867eb9502f7ab8922dc
+++ ChangeLog f6958fd919e56d111b69bab1f6e983d66917249b
@@ -1,3 +1,8 @@
+2006-02-22 Derek Scherger
+
+ * restrictions.{cc,hh}: allow for foo/... style recursive wildcard
+ paths in restrictions rather than --depth option
+
2006-02-20 Derek Scherger
* restrictions.{cc,hh}: attempt to simplify and remove duplication
============================================================
--- restrictions.cc 77252f64fc5d5cbd4380de33ee362336379b45ec
+++ restrictions.cc da1dd31e81f09105bdf2016f5f66931237d129f0
@@ -15,10 +15,6 @@
using std::make_pair;
using std::set;
-// TODO: add support for --depth (replace recursive boolean with depth value)
-// depth really only makes sense when one directory is specified however. it would
-// be much better to support foo/... style recursive paths
-
// TODO: add check for relevant rosters to be used by log
//
// i.e. as log goes back through older and older rosters it may hit one that
@@ -26,60 +22,107 @@
// includes or excludes may not have been born in a sufficiently old roster. at
// this point log should stop because no earlier roster will include these nodes.
+// TODO: for wildcard/... paths
+// - "file/..." should probably not be legal
+// - possibly support exact directory matching without including *any* children
+// currently dir includes itsself plus immediate children (i.e. --depth=1)
+// and dir/... includes everything below dir (no support for --depth=0)
+//
+
+path_component wildcard("...");
+
+struct wildcard_path
+{
+ split_path path;
+ bool recursive;
+
+ wildcard_path(split_path const &sp)
+ {
+ path = sp;
+ recursive = false;
+
+ if (path.back() == wildcard)
+ {
+ L(F("wildcard path '%s'") % sp);
+ recursive = true;
+ path.pop_back();
+ }
+ }
+
+ bool operator<(struct wildcard_path const & other) const
+ {
+ return path < other.path;
+ }
+};
+
+struct wildcard_node
+{
+ node_id nid;
+ bool recursive;
+
+ wildcard_node(node_id const n, bool const r = false):
+ nid(n), recursive(r) {}
+
+ bool operator<(struct wildcard_node const & other) const
+ {
+ return nid < other.nid;
+ }
+};
+
static void
-make_path_set(vector const & args, path_set & paths)
+make_path_set(vector const & args, set & paths)
{
for (vector::const_iterator i = args.begin(); i != args.end(); ++i)
{
split_path sp;
file_path_external(*i).split(sp);
- paths.insert(sp);
+ paths.insert(wildcard_path(sp));
}
}
// FIXME: should we really be doing implicit includes of parents?
static void
-get_parent_paths(path_set const & paths, path_set & parents)
+get_parent_paths(set const & paths, set & parents)
{
- for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
+ for (set::const_iterator i = paths.begin(); i != paths.end(); ++i)
{
- split_path sp(*i);
+ split_path sp(i->path);
sp.pop_back();
while (!sp.empty() && parents.find(sp) == parents.end())
{
- parents.insert(sp);
+ parents.insert(wildcard_path(sp));
sp.pop_back();
}
}
}
static void
-get_nodes(path_set const & paths, roster_t const & roster,
- set & nodes,
+get_nodes(set const & paths, roster_t const & roster,
+ set & nodes,
path_set & known_paths)
{
- for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
+ for (set::const_iterator i = paths.begin(); i != paths.end(); ++i)
{
- if (roster.has_node(*i))
+ if (roster.has_node(i->path))
{
- known_paths.insert(*i);
- node_id nid = roster.get_node(*i)->self;
- nodes.insert(nid);
+ known_paths.insert(i->path);
+ node_id nid = roster.get_node(i->path)->self;
+ nodes.insert(wildcard_node(nid, i->recursive));
}
}
}
// FIXME: should we really be doing implicit includes of parents?
static void
-get_parent_nodes(set const & nodes, roster_t const & roster, set & parents)
+get_parent_nodes(set const & nodes, roster_t const & roster, set & parents)
{
- for (set::const_iterator i = nodes.begin(); i != nodes.end(); ++i)
+ for (set::const_iterator i = nodes.begin(); i != nodes.end(); ++i)
{
- I(roster.has_node(*i));
- node_id nid = roster.get_node(*i)->parent;
+ I(roster.has_node(i->nid));
+ node_id nid = roster.get_node(i->nid)->parent;
while (!null_node(nid))
{
- parents.insert(nid);
+ parents.insert(wildcard_node(nid));
nid = roster.get_node(nid)->parent;
}
}
@@ -123,56 +166,58 @@
}
static void
-add_paths(map & path_map, path_set const & paths, path_state const state)
+add_paths(map & path_map, set const & paths,
+ path_state const state)
{
- for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
+ for (set::const_iterator i = paths.begin(); i != paths.end(); ++i)
{
- map::iterator p = path_map.find(*i);
+ map::iterator p = path_map.find(i->path);
if (p != path_map.end())
{
path_state merged;
- merge_states(p->second, state, merged, *i);
- p->second = merged;
+ merge_states(p->second.state, state, merged, i->path);
+ p->second.state = merged;
+ p->second.recursive |= i->recursive;
}
else
{
- path_map.insert(make_pair(*i, state));
+ path_map.insert(make_pair(i->path, path_entry(state, i->recursive)));
}
}
}
static void
-add_nodes(map & node_map,
+add_nodes(map & node_map,
roster_t const & roster,
- set const & nodes,
+ set const & nodes,
path_state const state)
{
- for (set::const_iterator i = nodes.begin(); i != nodes.end(); ++i)
+ for (set::const_iterator i = nodes.begin(); i != nodes.end(); ++i)
{
- I(roster.has_node(*i));
+ I(roster.has_node(i->nid));
- map::iterator n = node_map.find(*i);
+ map::iterator n = node_map.find(i->nid);
if (n != node_map.end())
{
path_state merged;
split_path sp;
- roster.get_name(*i, sp);
- merge_states(n->second, state, merged, sp);
- n->second = merged;
+ roster.get_name(i->nid, sp);
+ merge_states(n->second.state, state, merged, sp);
+ n->second.state = merged;
}
else
{
- node_map.insert(make_pair(*i, state));
+ node_map.insert(make_pair(i->nid, path_entry(state, i->recursive)));
}
}
}
static void
-add_paths(map & path_map,
- path_set const & includes,
- path_set const & excludes)
+add_paths(map & path_map,
+ set const & includes,
+ set const & excludes)
{
- path_set parents;
+ set parents;
get_parent_paths(includes, parents);
add_paths(path_map, includes, explicit_include);
@@ -181,13 +226,13 @@
}
static void
-add_nodes(map & node_map,
+add_nodes(map & node_map,
roster_t const & roster,
- path_set const & includes,
- path_set const & excludes,
+ set const & includes,
+ set const & excludes,
path_set & known_paths)
{
- set included_nodes, excluded_nodes, parent_nodes;
+ set included_nodes, excluded_nodes, parent_nodes;
get_nodes(includes, roster, included_nodes, known_paths);
get_nodes(excludes, roster, excluded_nodes, known_paths);
get_parent_nodes(included_nodes, roster, parent_nodes);
@@ -198,25 +243,29 @@
}
static void
-check_paths(path_set const & includes, path_set const & excludes, path_set const & known_paths)
+check_paths(set const & includes,
+ set const & excludes,
+ path_set const & known_paths)
{
int bad = 0;
- for (path_set::const_iterator i = includes.begin(); i != includes.end(); ++i)
+ for (set::const_iterator i = includes.begin();
+ i != includes.end(); ++i)
{
- if (known_paths.find(*i) == known_paths.end())
+ if (known_paths.find(i->path) == known_paths.end())
{
bad++;
- W(F("unknown path included %s") % *i);
+ W(F("unknown path included %s") % i->path);
}
}
- for (path_set::const_iterator i = excludes.begin(); i != excludes.end(); ++i)
+ for (set::const_iterator i = excludes.begin();
+ i != excludes.end(); ++i)
{
- if (known_paths.find(*i) == known_paths.end())
+ if (known_paths.find(i->path) == known_paths.end())
{
bad++;
- W(F("unknown path excluded %s") % *i);
+ W(F("unknown path excluded %s") % i->path);
}
}
@@ -231,7 +280,8 @@
vector const & exclude_args,
roster_t const & roster)
{
- path_set includes, excludes, known_paths;
+ set includes, excludes;
+ path_set known_paths;
make_path_set(include_args, includes);
make_path_set(exclude_args, excludes);
@@ -248,7 +298,8 @@
roster_t const & roster1,
roster_t const & roster2)
{
- path_set includes, excludes, known_paths;
+ set includes, excludes;
+ path_set known_paths;
make_path_set(include_args, includes);
make_path_set(exclude_args, excludes);
@@ -266,7 +317,7 @@
////////////////////////////////////////////////////////////////////////////////
bool
-restriction::includes(roster_t const & roster, node_id nid) const
+restriction::includes(roster_t const & roster, node_id const nid) const
{
MM(roster);
I(roster.has_node(nid));
@@ -282,26 +333,31 @@
}
node_id current = nid;
+ int depth = 0;
while (!null_node(current))
{
- map::const_iterator r = node_map.find(current);
+ map::const_iterator r = node_map.find(current);
if (r != node_map.end())
{
- switch (r->second)
+ switch (r->second.state)
{
case explicit_include:
- L(F("explicit include of nid %d path '%s'") % current % file_path(sp));
- return true;
-
+ if (depth <= 1 || r->second.recursive)
+ {
+ L(F("explicit include of nid %d path '%s'") % current % file_path(sp));
+ return true;
+ }
case explicit_exclude:
- L(F("explicit exclude of nid %d path '%s'") % current % file_path(sp));
- return false;
-
+ if (depth <= 1 || r->second.recursive)
+ {
+ L(F("explicit exclude of nid %d path '%s'") % current % file_path(sp));
+ return false;
+ }
case implicit_include:
// this is non-recursive and requires an exact match
- if (current == nid)
+ if (depth == 0)
{
L(F("implicit include of nid %d path '%s'") % current % file_path(sp));
return true;
@@ -311,6 +367,7 @@
node_t node = roster.get_node(current);
current = node->parent;
+ depth++;
}
if (default_result)
@@ -335,26 +392,31 @@
}
split_path current(sp);
+ int depth = 0;
while (!current.empty())
{
- map::const_iterator r = path_map.find(current);
+ map::const_iterator r = path_map.find(current);
if (r != path_map.end())
{
- switch (r->second)
+ switch (r->second.state)
{
case explicit_include:
- L(F("explicit include of path '%s'") % file_path(sp));
- return true;
-
+ if (depth <= 1 || r->second.recursive)
+ {
+ L(F("explicit include of path '%s'") % file_path(sp));
+ return true;
+ }
case explicit_exclude:
- L(F("explicit exclude of path '%s'") % file_path(sp));
- return false;
-
+ if (depth <= 1 || r->second.recursive)
+ {
+ L(F("explicit exclude of path '%s'") % file_path(sp));
+ return false;
+ }
case implicit_include:
// this is non-recursive and requires an exact match
- if (current == sp)
+ if (depth == 0)
{
L(F("implicit include of path '%s'") % file_path(sp));
return true;
@@ -363,6 +425,7 @@
}
current.pop_back();
+ depth++;
}
if (default_result)
@@ -602,8 +665,8 @@
setup(roster);
vector includes, excludes;
- includes.push_back(utf8(string("x/x")));
- includes.push_back(utf8(string("y/y")));
+ includes.push_back(utf8(string("x/x/...")));
+ includes.push_back(utf8(string("y/y/...")));
restriction mask(includes, excludes, roster);
@@ -667,8 +730,8 @@
setup(roster);
vector includes, excludes;
- excludes.push_back(utf8(string("x/x")));
- excludes.push_back(utf8(string("y/y")));
+ excludes.push_back(utf8(string("x/x/...")));
+ excludes.push_back(utf8(string("y/y/...")));
restriction mask(includes, excludes, roster);
@@ -732,10 +795,10 @@
setup(roster);
vector includes, excludes;
- includes.push_back(utf8(string("x")));
- includes.push_back(utf8(string("y")));
- excludes.push_back(utf8(string("x/x")));
- excludes.push_back(utf8(string("y/y")));
+ includes.push_back(utf8(string("x/...")));
+ includes.push_back(utf8(string("y/...")));
+ excludes.push_back(utf8(string("x/x/...")));
+ excludes.push_back(utf8(string("y/y/...")));
restriction mask(includes, excludes, roster);
@@ -799,10 +862,10 @@
setup(roster);
vector includes, excludes;
- excludes.push_back(utf8(string("x")));
- excludes.push_back(utf8(string("y")));
- includes.push_back(utf8(string("x/x")));
- includes.push_back(utf8(string("y/y")));
+ excludes.push_back(utf8(string("x/...")));
+ excludes.push_back(utf8(string("y/...")));
+ includes.push_back(utf8(string("x/x/...")));
+ includes.push_back(utf8(string("y/y/...")));
restriction mask(includes, excludes, roster);
@@ -875,14 +938,14 @@
static void
test_get_parent_paths()
{
- path_set paths, parents;
+ set paths, parents;
split_path a, ab, abc;
file_path_internal("a").split(a);
file_path_internal("a/b").split(ab);
file_path_internal("a/b/c").split(abc);
- paths.insert(abc);
+ paths.insert(wildcard_path(abc));
get_parent_paths(paths, parents);
BOOST_CHECK(parents.find(a) != parents.end());
============================================================
--- restrictions.hh 8d68ee9d4981f22f01ecf499602fcbc7b6d4b6fe
+++ restrictions.hh 8d966a7dba0e522f4c51391290dc58f1f414edfe
@@ -56,7 +56,14 @@
// TODO: move these into the class below?!?
enum path_state { explicit_include, explicit_exclude, implicit_include };
-
+
+struct path_entry
+{
+ path_state state;
+ bool recursive;
+ path_entry(path_state const s, bool const r = false) : state(s), recursive(r) {}
+};
+
class restriction
{
public:
@@ -84,8 +91,8 @@
// we maintain maps by node_id and also by split_path, which is not
// particularly nice, but paths are required for checking unknown and ignored
// files
- map node_map;
- map path_map;
+ map node_map;
+ map path_map;
};