monotone

monotone Mtn Source Tree

Root/restrictions.cc

1// Copyright (C) 2005 Derek Scherger <derek@echologic.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include <map>
11#include <string>
12#include <vector>
13
14#include "restrictions.hh"
15#include "revision.hh"
16#include "safe_map.hh"
17#include "transforms.hh"
18
19using std::make_pair;
20using std::map;
21using std::set;
22using std::vector;
23
24// TODO: add check for relevant rosters to be used by log
25//
26// i.e. as log goes back through older and older rosters it may hit one
27// that pre-dates any of the nodes in the restriction. the nodes that the
28// restriction includes or excludes may not have been born in a sufficiently
29// old roster. at this point log should stop because no earlier roster will
30// include these nodes.
31
32static void
33make_path_set(vector<file_path> const & paths, path_set & split_paths)
34{
35 for (vector<file_path>::const_iterator i = paths.begin(); i != paths.end(); ++i)
36 {
37 split_path sp;
38 i->split(sp);
39 split_paths.insert(sp);
40 }
41}
42
43static void
44map_nodes(map<node_id, restricted_path::status> & node_map,
45 roster_t const & roster,
46 path_set const & paths,
47 path_set & known_paths,
48 restricted_path::status const status)
49{
50 for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
51 {
52 if (roster.has_node(*i))
53 {
54 known_paths.insert(*i);
55 node_id nid = roster.get_node(*i)->self;
56
57 map<node_id, restricted_path::status>::iterator n = node_map.find(nid);
58 if (n != node_map.end())
59 N(n->second == status,
60 F("conflicting include/exclude on path '%s'") % *i);
61 else
62 node_map.insert(make_pair(nid, status));
63 }
64 }
65}
66
67static void
68map_paths(map<split_path, restricted_path::status> & path_map,
69 path_set const & paths,
70 restricted_path::status const status)
71{
72 for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
73 {
74 map<split_path, restricted_path::status>::iterator p = path_map.find(*i);
75 if (p != path_map.end())
76 N(p->second == status,
77 F("conflicting include/exclude on path '%s'") % *i);
78 else
79 path_map.insert(make_pair(*i, status));
80 }
81}
82
83static void
84validate_roster_paths(path_set const & included_paths,
85 path_set const & excluded_paths,
86 path_set const & known_paths,
87 app_state & app)
88{
89 int bad = 0;
90
91 for (path_set::const_iterator i = included_paths.begin();
92 i != included_paths.end(); ++i)
93 {
94 // ignored paths are allowed into the restriction but are not
95 // considered invalid if they are found in none of the restriction's
96 // rosters
97 if (known_paths.find(*i) == known_paths.end())
98 {
99 file_path fp(*i);
100 if (!app.lua.hook_ignore_file(fp))
101 {
102 bad++;
103 W(F("restriction includes unknown path '%s'") % *i);
104 }
105 }
106 }
107
108 for (path_set::const_iterator i = excluded_paths.begin();
109 i != excluded_paths.end(); ++i)
110 {
111 if (known_paths.find(*i) == known_paths.end())
112 {
113 bad++;
114 W(F("restriction excludes unknown path '%s'") % *i);
115 }
116 }
117
118 N(bad == 0, FP("%d unknown path", "%d unknown paths", bad) % bad);
119}
120
121void
122validate_workspace_paths(path_set const & included_paths,
123 path_set const & excluded_paths,
124 app_state & app)
125{
126 int bad = 0;
127
128 for (path_set::const_iterator i = included_paths.begin();
129 i != included_paths.end(); ++i)
130 {
131 if (workspace_root(*i))
132 continue;
133
134 // ignored paths are allowed into the restriction but are not
135 // considered invalid if they are found in none of the restriction's
136 // rosters
137 file_path fp(*i);
138 if (!path_exists(fp) && !app.lua.hook_ignore_file(fp))
139 {
140 bad++;
141 W(F("restriction includes unknown path '%s'") % *i);
142 }
143 }
144
145 for (path_set::const_iterator i = excluded_paths.begin();
146 i != excluded_paths.end(); ++i)
147 {
148 if (workspace_root(*i))
149 continue;
150
151 file_path fp(*i);
152 if (!path_exists(fp))
153 {
154 bad++;
155 W(F("restriction excludes unknown path '%s'") % *i);
156 }
157 }
158
159 N(bad == 0, FP("%d unknown path", "%d unknown paths", bad) % bad);
160}
161
162restriction::restriction(std::vector<file_path> const & includes,
163 std::vector<file_path> const & excludes,
164 long depth)
165 : depth(depth)
166{
167 make_path_set(includes, included_paths);
168 make_path_set(excludes, excluded_paths);
169}
170
171node_restriction::node_restriction(std::vector<file_path> const & includes,
172 std::vector<file_path> const & excludes,
173 long depth,
174 roster_t const & roster,
175 app_state & a) :
176 restriction(includes, excludes, depth)
177{
178 map_nodes(node_map, roster, included_paths, known_paths,
179 restricted_path::included);
180 map_nodes(node_map, roster, excluded_paths, known_paths,
181 restricted_path::excluded);
182
183 validate_roster_paths(included_paths, excluded_paths, known_paths, a);
184}
185
186node_restriction::node_restriction(std::vector<file_path> const & includes,
187 std::vector<file_path> const & excludes,
188 long depth,
189 roster_t const & roster1,
190 roster_t const & roster2,
191 app_state & a) :
192 restriction(includes, excludes, depth)
193{
194 map_nodes(node_map, roster1, included_paths, known_paths,
195 restricted_path::included);
196 map_nodes(node_map, roster1, excluded_paths, known_paths,
197 restricted_path::excluded);
198
199 map_nodes(node_map, roster2, included_paths, known_paths,
200 restricted_path::included);
201 map_nodes(node_map, roster2, excluded_paths, known_paths,
202 restricted_path::excluded);
203
204 validate_roster_paths(included_paths, excluded_paths, known_paths, a);
205}
206
207node_restriction::node_restriction(std::vector<file_path> const & includes,
208 std::vector<file_path> const & excludes,
209 long depth,
210 parent_map const & rosters1,
211 roster_t const & roster2,
212 app_state & a) :
213 restriction(includes, excludes, depth)
214{
215 for (parent_map::const_iterator i = rosters1.begin();
216 i != rosters1.end();
217 i++)
218 {
219 map_nodes(node_map, parent_roster(i), included_paths, known_paths,
220 restricted_path::included);
221 map_nodes(node_map, parent_roster(i), excluded_paths, known_paths,
222 restricted_path::excluded);
223 }
224
225 map_nodes(node_map, roster2, included_paths, known_paths,
226 restricted_path::included);
227 map_nodes(node_map, roster2, excluded_paths, known_paths,
228 restricted_path::excluded);
229
230 validate_roster_paths(included_paths, excluded_paths, known_paths, a);
231}
232
233
234path_restriction::path_restriction(std::vector<file_path> const & includes,
235 std::vector<file_path> const & excludes,
236 long depth,
237 app_state & a) :
238 restriction(includes, excludes, depth)
239{
240 map_paths(path_map, included_paths, restricted_path::included);
241 map_paths(path_map, excluded_paths, restricted_path::excluded);
242
243 validate_workspace_paths(included_paths, excluded_paths, a);
244}
245
246bool
247node_restriction::includes(roster_t const & roster, node_id nid) const
248{
249 MM(roster);
250 I(roster.has_node(nid));
251
252 split_path sp;
253 roster.get_name(nid, sp);
254
255 if (empty())
256 {
257 if (depth != -1)
258 {
259 int path_depth = sp.size() - 1; // -1 to not count root path_component
260 if (path_depth <= depth + 1)
261 {
262 L(FL("depth includes nid %d path '%s'") % nid % file_path(sp));
263 return true;
264 }
265 else
266 {
267 L(FL("depth excludes nid %d path '%s'") % nid % file_path(sp));
268 return false;
269 }
270 }
271 else
272 {
273 // don't log this, we end up using rather a bit of cpu time just
274 // in the logging code, for totally unrestricted operations.
275 return true;
276 }
277 }
278
279 node_id current = nid;
280 int path_depth = 0;
281
282 // FIXME: this uses depth+1 because the old semantics of depth=0 were
283 // something like "the current directory and its immediate children". it
284 // seems somewhat more reasonable here to use depth=0 to mean "exactly
285 // this directory" and depth=1 to mean "this directory and its immediate
286 // children"
287
288 while (!null_node(current) && (depth == -1 || path_depth <= depth + 1))
289 {
290 map<node_id, restricted_path::status>::const_iterator
291 r = node_map.find(current);
292
293 if (r != node_map.end())
294 {
295 switch (r->second)
296 {
297 case restricted_path::included:
298 L(FL("explicit include of nid %d path '%s'")
299 % current % file_path(sp));
300 return true;
301
302 case restricted_path::excluded:
303 L(FL("explicit exclude of nid %d path '%s'")
304 % current % file_path(sp));
305 return false;
306 }
307 }
308
309 node_t node = roster.get_node(current);
310 current = node->parent;
311 path_depth++;
312 }
313
314 if (included_paths.empty())
315 {
316 L(FL("default include of nid %d path '%s'")
317 % nid % file_path(sp));
318 return true;
319 }
320 else
321 {
322 if (global_sanity.debug)
323 {
324 // printing this slows down "log <file>".
325 L(FL("(debug) default exclude of nid %d path '%s'")
326 % nid % file_path(sp));
327 }
328 return false;
329 }
330}
331
332bool
333path_restriction::includes(split_path const & sp) const
334{
335 if (empty())
336 {
337 if (depth != -1)
338 {
339 int path_depth = sp.size() - 1; // -1 to not count root path_component
340 if (path_depth <= depth + 1)
341 {
342 L(FL("depth includes path '%s'") % file_path(sp));
343 return true;
344 }
345 else
346 {
347 L(FL("depth excludes path '%s'") % file_path(sp));
348 return false;
349 }
350 }
351 else
352 {
353 L(FL("empty include of path '%s'") % file_path(sp));
354 return true;
355 }
356 }
357
358 split_path current(sp);
359 int path_depth = 0;
360
361 // FIXME: this uses depth+1 because the old semantics of depth=0 were
362 // something like "the current directory and its immediate children". it
363 // seems somewhat more reasonable here to use depth=0 to mean "exactly
364 // this directory" and depth=1 to mean "this directory and its immediate
365 // children"
366
367 while (!current.empty() && (depth == -1 || path_depth <= depth + 1))
368 {
369 map<split_path, restricted_path::status>::const_iterator
370 r = path_map.find(current);
371
372 if (r != path_map.end())
373 {
374 switch (r->second)
375 {
376 case restricted_path::included:
377 L(FL("explicit include of path '%s'")
378 % file_path(sp));
379 return true;
380
381 case restricted_path::excluded:
382 L(FL("explicit exclude of path '%s'")
383 % file_path(sp));
384 return false;
385 }
386 }
387
388 current.pop_back();
389 path_depth++;
390 }
391
392 if (included_paths.empty())
393 {
394 L(FL("default include of path '%s'")
395 % file_path(sp));
396 return true;
397 }
398 else
399 {
400 L(FL("default exclude of path '%s'")
401 % file_path(sp));
402 return false;
403 }
404}
405
406///////////////////////////////////////////////////////////////////////
407// tests
408///////////////////////////////////////////////////////////////////////
409
410#ifdef BUILD_UNIT_TESTS
411#include "app_state.hh"
412#include "unit_tests.hh"
413#include "roster.hh"
414#include "sanity.hh"
415
416using std::string;
417
418// f's and g's are files
419// x's and y's are directories
420// and this is rather painful
421
422split_path sp_root;
423split_path sp_f;
424split_path sp_g;
425
426split_path sp_x;
427split_path sp_xf;
428split_path sp_xg;
429split_path sp_xx;
430split_path sp_xxf;
431split_path sp_xxg;
432split_path sp_xy;
433split_path sp_xyf;
434split_path sp_xyg;
435
436split_path sp_y;
437split_path sp_yf;
438split_path sp_yg;
439split_path sp_yx;
440split_path sp_yxf;
441split_path sp_yxg;
442split_path sp_yy;
443split_path sp_yyf;
444split_path sp_yyg;
445
446node_id nid_root;
447node_id nid_f;
448node_id nid_g;
449
450node_id nid_x;
451node_id nid_xf;
452node_id nid_xg;
453node_id nid_xx;
454node_id nid_xxf;
455node_id nid_xxg;
456node_id nid_xy;
457node_id nid_xyf;
458node_id nid_xyg;
459
460node_id nid_y;
461node_id nid_yf;
462node_id nid_yg;
463node_id nid_yx;
464node_id nid_yxf;
465node_id nid_yxg;
466node_id nid_yy;
467node_id nid_yyf;
468node_id nid_yyg;
469
470file_id fid_f(string("1000000000000000000000000000000000000000"));
471file_id fid_g(string("2000000000000000000000000000000000000000"));
472
473file_id fid_xf(string("3000000000000000000000000000000000000000"));
474file_id fid_xg(string("4000000000000000000000000000000000000000"));
475file_id fid_xxf(string("5000000000000000000000000000000000000000"));
476file_id fid_xxg(string("6000000000000000000000000000000000000000"));
477file_id fid_xyf(string("7000000000000000000000000000000000000000"));
478file_id fid_xyg(string("8000000000000000000000000000000000000000"));
479
480file_id fid_yf(string("9000000000000000000000000000000000000000"));
481file_id fid_yg(string("a000000000000000000000000000000000000000"));
482file_id fid_yxf(string("b000000000000000000000000000000000000000"));
483file_id fid_yxg(string("c000000000000000000000000000000000000000"));
484file_id fid_yyf(string("d000000000000000000000000000000000000000"));
485file_id fid_yyg(string("e000000000000000000000000000000000000000"));
486
487static void setup(roster_t & roster)
488{
489 temp_node_id_source nis;
490
491 file_path_internal("").split(sp_root);
492 file_path_internal("f").split(sp_f);
493 file_path_internal("g").split(sp_g);
494
495 file_path_internal("x").split(sp_x);
496 file_path_internal("x/f").split(sp_xf);
497 file_path_internal("x/g").split(sp_xg);
498 file_path_internal("x/x").split(sp_xx);
499 file_path_internal("x/x/f").split(sp_xxf);
500 file_path_internal("x/x/g").split(sp_xxg);
501 file_path_internal("x/y").split(sp_xy);
502 file_path_internal("x/y/f").split(sp_xyf);
503 file_path_internal("x/y/g").split(sp_xyg);
504
505 file_path_internal("y").split(sp_y);
506 file_path_internal("y/f").split(sp_yf);
507 file_path_internal("y/g").split(sp_yg);
508 file_path_internal("y/x").split(sp_yx);
509 file_path_internal("y/x/f").split(sp_yxf);
510 file_path_internal("y/x/g").split(sp_yxg);
511 file_path_internal("y/y").split(sp_yy);
512 file_path_internal("y/y/f").split(sp_yyf);
513 file_path_internal("y/y/g").split(sp_yyg);
514
515 // these directories must exist for the path_restrictions to be valid. it
516 // is a bit lame to be creating directories arbitrarily like this. perhaps
517 // unit_tests should run in a unit_tests.dir or something.
518
519 mkdir_p(file_path_internal("x/x"));
520 mkdir_p(file_path_internal("x/y"));
521 mkdir_p(file_path_internal("y/x"));
522 mkdir_p(file_path_internal("y/y"));
523
524 nid_root = roster.create_dir_node(nis);
525 nid_f = roster.create_file_node(fid_f, nis);
526 nid_g = roster.create_file_node(fid_g, nis);
527
528 nid_x = roster.create_dir_node(nis);
529 nid_xf = roster.create_file_node(fid_xf, nis);
530 nid_xg = roster.create_file_node(fid_xg, nis);
531 nid_xx = roster.create_dir_node(nis);
532 nid_xxf = roster.create_file_node(fid_xxf, nis);
533 nid_xxg = roster.create_file_node(fid_xxg, nis);
534 nid_xy = roster.create_dir_node(nis);
535 nid_xyf = roster.create_file_node(fid_xxf, nis);
536 nid_xyg = roster.create_file_node(fid_xxg, nis);
537
538 nid_y = roster.create_dir_node(nis);
539 nid_yf = roster.create_file_node(fid_yf, nis);
540 nid_yg = roster.create_file_node(fid_yg, nis);
541 nid_yx = roster.create_dir_node(nis);
542 nid_yxf = roster.create_file_node(fid_yxf, nis);
543 nid_yxg = roster.create_file_node(fid_yxg, nis);
544 nid_yy = roster.create_dir_node(nis);
545 nid_yyf = roster.create_file_node(fid_yxf, nis);
546 nid_yyg = roster.create_file_node(fid_yxg, nis);
547
548 roster.attach_node(nid_root, sp_root);
549 roster.attach_node(nid_f, sp_f);
550 roster.attach_node(nid_g, sp_g);
551
552 roster.attach_node(nid_x, sp_x);
553 roster.attach_node(nid_xf, sp_xf);
554 roster.attach_node(nid_xg, sp_xg);
555 roster.attach_node(nid_xx, sp_xx);
556 roster.attach_node(nid_xxf, sp_xxf);
557 roster.attach_node(nid_xxg, sp_xxg);
558 roster.attach_node(nid_xy, sp_xy);
559 roster.attach_node(nid_xyf, sp_xyf);
560 roster.attach_node(nid_xyg, sp_xyg);
561
562 roster.attach_node(nid_y, sp_y);
563 roster.attach_node(nid_yf, sp_yf);
564 roster.attach_node(nid_yg, sp_yg);
565 roster.attach_node(nid_yx, sp_yx);
566 roster.attach_node(nid_yxf, sp_yxf);
567 roster.attach_node(nid_yxg, sp_yxg);
568 roster.attach_node(nid_yy, sp_yy);
569 roster.attach_node(nid_yyf, sp_yyf);
570 roster.attach_node(nid_yyg, sp_yyg);
571
572}
573
574UNIT_TEST(restrictions, empty_restriction)
575{
576 roster_t roster;
577 setup(roster);
578
579 // check restricted nodes
580
581 node_restriction nmask;
582
583 BOOST_CHECK(nmask.empty());
584
585 BOOST_CHECK(nmask.includes(roster, nid_root));
586 BOOST_CHECK(nmask.includes(roster, nid_f));
587 BOOST_CHECK(nmask.includes(roster, nid_g));
588
589 BOOST_CHECK(nmask.includes(roster, nid_x));
590 BOOST_CHECK(nmask.includes(roster, nid_xf));
591 BOOST_CHECK(nmask.includes(roster, nid_xg));
592 BOOST_CHECK(nmask.includes(roster, nid_xx));
593 BOOST_CHECK(nmask.includes(roster, nid_xxf));
594 BOOST_CHECK(nmask.includes(roster, nid_xxg));
595 BOOST_CHECK(nmask.includes(roster, nid_xy));
596 BOOST_CHECK(nmask.includes(roster, nid_xyf));
597 BOOST_CHECK(nmask.includes(roster, nid_xyg));
598
599 BOOST_CHECK(nmask.includes(roster, nid_y));
600 BOOST_CHECK(nmask.includes(roster, nid_yf));
601 BOOST_CHECK(nmask.includes(roster, nid_yg));
602 BOOST_CHECK(nmask.includes(roster, nid_yx));
603 BOOST_CHECK(nmask.includes(roster, nid_yxf));
604 BOOST_CHECK(nmask.includes(roster, nid_yxg));
605 BOOST_CHECK(nmask.includes(roster, nid_yy));
606 BOOST_CHECK(nmask.includes(roster, nid_yyf));
607 BOOST_CHECK(nmask.includes(roster, nid_yyg));
608
609 // check restricted paths
610
611 path_restriction pmask;
612
613 BOOST_CHECK(pmask.empty());
614
615 BOOST_CHECK(pmask.includes(sp_root));
616 BOOST_CHECK(pmask.includes(sp_f));
617 BOOST_CHECK(pmask.includes(sp_g));
618
619 BOOST_CHECK(pmask.includes(sp_x));
620 BOOST_CHECK(pmask.includes(sp_xf));
621 BOOST_CHECK(pmask.includes(sp_xg));
622 BOOST_CHECK(pmask.includes(sp_xx));
623 BOOST_CHECK(pmask.includes(sp_xxf));
624 BOOST_CHECK(pmask.includes(sp_xxg));
625 BOOST_CHECK(pmask.includes(sp_xy));
626 BOOST_CHECK(pmask.includes(sp_xyf));
627 BOOST_CHECK(pmask.includes(sp_xyg));
628
629 BOOST_CHECK(pmask.includes(sp_y));
630 BOOST_CHECK(pmask.includes(sp_yf));
631 BOOST_CHECK(pmask.includes(sp_yg));
632 BOOST_CHECK(pmask.includes(sp_yx));
633 BOOST_CHECK(pmask.includes(sp_yxf));
634 BOOST_CHECK(pmask.includes(sp_yxg));
635 BOOST_CHECK(pmask.includes(sp_yy));
636 BOOST_CHECK(pmask.includes(sp_yyf));
637 BOOST_CHECK(pmask.includes(sp_yyg));
638}
639
640UNIT_TEST(restrictions, simple_include)
641{
642 roster_t roster;
643 setup(roster);
644
645 vector<file_path> includes, excludes;
646 includes.push_back(file_path_internal("x/x"));
647 includes.push_back(file_path_internal("y/y"));
648
649 app_state app;
650
651 // check restricted nodes
652
653 node_restriction nmask(includes, excludes, -1, roster, app);
654
655 BOOST_CHECK(!nmask.empty());
656
657 BOOST_CHECK(!nmask.includes(roster, nid_root));
658 BOOST_CHECK(!nmask.includes(roster, nid_f));
659 BOOST_CHECK(!nmask.includes(roster, nid_g));
660
661 BOOST_CHECK(!nmask.includes(roster, nid_x));
662 BOOST_CHECK(!nmask.includes(roster, nid_xf));
663 BOOST_CHECK(!nmask.includes(roster, nid_xg));
664 BOOST_CHECK( nmask.includes(roster, nid_xx));
665 BOOST_CHECK( nmask.includes(roster, nid_xxf));
666 BOOST_CHECK( nmask.includes(roster, nid_xxg));
667 BOOST_CHECK(!nmask.includes(roster, nid_xy));
668 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
669 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
670
671 BOOST_CHECK(!nmask.includes(roster, nid_y));
672 BOOST_CHECK(!nmask.includes(roster, nid_yf));
673 BOOST_CHECK(!nmask.includes(roster, nid_yg));
674 BOOST_CHECK(!nmask.includes(roster, nid_yx));
675 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
676 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
677 BOOST_CHECK( nmask.includes(roster, nid_yy));
678 BOOST_CHECK( nmask.includes(roster, nid_yyf));
679 BOOST_CHECK( nmask.includes(roster, nid_yyg));
680
681 // check restricted paths
682
683 path_restriction pmask(includes, excludes, -1, app);
684
685 BOOST_CHECK(!pmask.empty());
686
687 BOOST_CHECK(!pmask.includes(sp_root));
688 BOOST_CHECK(!pmask.includes(sp_f));
689 BOOST_CHECK(!pmask.includes(sp_g));
690
691 BOOST_CHECK(!pmask.includes(sp_x));
692 BOOST_CHECK(!pmask.includes(sp_xf));
693 BOOST_CHECK(!pmask.includes(sp_xg));
694 BOOST_CHECK( pmask.includes(sp_xx));
695 BOOST_CHECK( pmask.includes(sp_xxf));
696 BOOST_CHECK( pmask.includes(sp_xxg));
697 BOOST_CHECK(!pmask.includes(sp_xy));
698 BOOST_CHECK(!pmask.includes(sp_xyf));
699 BOOST_CHECK(!pmask.includes(sp_xyg));
700
701 BOOST_CHECK(!pmask.includes(sp_y));
702 BOOST_CHECK(!pmask.includes(sp_yf));
703 BOOST_CHECK(!pmask.includes(sp_yg));
704 BOOST_CHECK(!pmask.includes(sp_yx));
705 BOOST_CHECK(!pmask.includes(sp_yxf));
706 BOOST_CHECK(!pmask.includes(sp_yxg));
707 BOOST_CHECK( pmask.includes(sp_yy));
708 BOOST_CHECK( pmask.includes(sp_yyf));
709 BOOST_CHECK( pmask.includes(sp_yyg));
710}
711
712UNIT_TEST(restrictions, simple_exclude)
713{
714 roster_t roster;
715 setup(roster);
716
717 vector<file_path> includes, excludes;
718 excludes.push_back(file_path_internal("x/x"));
719 excludes.push_back(file_path_internal("y/y"));
720
721 app_state app;
722
723 // check restricted nodes
724
725 node_restriction nmask(includes, excludes, -1, roster, app);
726
727 BOOST_CHECK(!nmask.empty());
728
729 BOOST_CHECK( nmask.includes(roster, nid_root));
730 BOOST_CHECK( nmask.includes(roster, nid_f));
731 BOOST_CHECK( nmask.includes(roster, nid_g));
732
733 BOOST_CHECK( nmask.includes(roster, nid_x));
734 BOOST_CHECK( nmask.includes(roster, nid_xf));
735 BOOST_CHECK( nmask.includes(roster, nid_xg));
736 BOOST_CHECK(!nmask.includes(roster, nid_xx));
737 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
738 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
739 BOOST_CHECK( nmask.includes(roster, nid_xy));
740 BOOST_CHECK( nmask.includes(roster, nid_xyf));
741 BOOST_CHECK( nmask.includes(roster, nid_xyg));
742
743 BOOST_CHECK( nmask.includes(roster, nid_y));
744 BOOST_CHECK( nmask.includes(roster, nid_yf));
745 BOOST_CHECK( nmask.includes(roster, nid_yg));
746 BOOST_CHECK( nmask.includes(roster, nid_yx));
747 BOOST_CHECK( nmask.includes(roster, nid_yxf));
748 BOOST_CHECK( nmask.includes(roster, nid_yxg));
749 BOOST_CHECK(!nmask.includes(roster, nid_yy));
750 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
751 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
752
753 // check restricted paths
754
755 path_restriction pmask(includes, excludes, -1, app);
756
757 BOOST_CHECK(!pmask.empty());
758
759 BOOST_CHECK( pmask.includes(sp_root));
760 BOOST_CHECK( pmask.includes(sp_f));
761 BOOST_CHECK( pmask.includes(sp_g));
762
763 BOOST_CHECK( pmask.includes(sp_x));
764 BOOST_CHECK( pmask.includes(sp_xf));
765 BOOST_CHECK( pmask.includes(sp_xg));
766 BOOST_CHECK(!pmask.includes(sp_xx));
767 BOOST_CHECK(!pmask.includes(sp_xxf));
768 BOOST_CHECK(!pmask.includes(sp_xxg));
769 BOOST_CHECK( pmask.includes(sp_xy));
770 BOOST_CHECK( pmask.includes(sp_xyf));
771 BOOST_CHECK( pmask.includes(sp_xyg));
772
773 BOOST_CHECK( pmask.includes(sp_y));
774 BOOST_CHECK( pmask.includes(sp_yf));
775 BOOST_CHECK( pmask.includes(sp_yg));
776 BOOST_CHECK( pmask.includes(sp_yx));
777 BOOST_CHECK( pmask.includes(sp_yxf));
778 BOOST_CHECK( pmask.includes(sp_yxg));
779 BOOST_CHECK(!pmask.includes(sp_yy));
780 BOOST_CHECK(!pmask.includes(sp_yyf));
781 BOOST_CHECK(!pmask.includes(sp_yyg));
782}
783
784UNIT_TEST(restrictions, include_exclude)
785{
786 roster_t roster;
787 setup(roster);
788
789 vector<file_path> includes, excludes;
790 includes.push_back(file_path_internal("x"));
791 includes.push_back(file_path_internal("y"));
792 excludes.push_back(file_path_internal("x/x"));
793 excludes.push_back(file_path_internal("y/y"));
794
795 app_state app;
796
797 // check restricted nodes
798
799 node_restriction nmask(includes, excludes, -1, roster, app);
800
801 BOOST_CHECK(!nmask.empty());
802
803 BOOST_CHECK(!nmask.includes(roster, nid_root));
804 BOOST_CHECK(!nmask.includes(roster, nid_f));
805 BOOST_CHECK(!nmask.includes(roster, nid_g));
806
807 BOOST_CHECK( nmask.includes(roster, nid_x));
808 BOOST_CHECK( nmask.includes(roster, nid_xf));
809 BOOST_CHECK( nmask.includes(roster, nid_xg));
810 BOOST_CHECK(!nmask.includes(roster, nid_xx));
811 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
812 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
813 BOOST_CHECK( nmask.includes(roster, nid_xy));
814 BOOST_CHECK( nmask.includes(roster, nid_xyf));
815 BOOST_CHECK( nmask.includes(roster, nid_xyg));
816
817 BOOST_CHECK( nmask.includes(roster, nid_y));
818 BOOST_CHECK( nmask.includes(roster, nid_yf));
819 BOOST_CHECK( nmask.includes(roster, nid_yg));
820 BOOST_CHECK( nmask.includes(roster, nid_yx));
821 BOOST_CHECK( nmask.includes(roster, nid_yxf));
822 BOOST_CHECK( nmask.includes(roster, nid_yxg));
823 BOOST_CHECK(!nmask.includes(roster, nid_yy));
824 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
825 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
826
827 // check restricted paths
828
829 path_restriction pmask(includes, excludes, -1, app);
830
831 BOOST_CHECK(!pmask.empty());
832
833 BOOST_CHECK(!pmask.includes(sp_root));
834 BOOST_CHECK(!pmask.includes(sp_f));
835 BOOST_CHECK(!pmask.includes(sp_g));
836
837 BOOST_CHECK( pmask.includes(sp_x));
838 BOOST_CHECK( pmask.includes(sp_xf));
839 BOOST_CHECK( pmask.includes(sp_xg));
840 BOOST_CHECK(!pmask.includes(sp_xx));
841 BOOST_CHECK(!pmask.includes(sp_xxf));
842 BOOST_CHECK(!pmask.includes(sp_xxg));
843 BOOST_CHECK( pmask.includes(sp_xy));
844 BOOST_CHECK( pmask.includes(sp_xyf));
845 BOOST_CHECK( pmask.includes(sp_xyg));
846
847 BOOST_CHECK( pmask.includes(sp_y));
848 BOOST_CHECK( pmask.includes(sp_yf));
849 BOOST_CHECK( pmask.includes(sp_yg));
850 BOOST_CHECK( pmask.includes(sp_yx));
851 BOOST_CHECK( pmask.includes(sp_yxf));
852 BOOST_CHECK( pmask.includes(sp_yxg));
853 BOOST_CHECK(!pmask.includes(sp_yy));
854 BOOST_CHECK(!pmask.includes(sp_yyf));
855 BOOST_CHECK(!pmask.includes(sp_yyg));
856}
857
858UNIT_TEST(restrictions, exclude_include)
859{
860 roster_t roster;
861 setup(roster);
862
863 vector<file_path> includes, excludes;
864 // note that excludes higher up the tree than the top
865 // include are rather pointless -- nothing above the
866 // top include is included anyway
867 excludes.push_back(file_path_internal("x"));
868 excludes.push_back(file_path_internal("y"));
869 includes.push_back(file_path_internal("x/x"));
870 includes.push_back(file_path_internal("y/y"));
871
872 app_state app;
873
874 // check restricted nodes
875
876 node_restriction nmask(includes, excludes, -1, roster, app);
877
878 BOOST_CHECK(!nmask.empty());
879
880 BOOST_CHECK(!nmask.includes(roster, nid_root));
881 BOOST_CHECK(!nmask.includes(roster, nid_f));
882 BOOST_CHECK(!nmask.includes(roster, nid_g));
883
884 BOOST_CHECK(!nmask.includes(roster, nid_x));
885 BOOST_CHECK(!nmask.includes(roster, nid_xf));
886 BOOST_CHECK(!nmask.includes(roster, nid_xg));
887 BOOST_CHECK( nmask.includes(roster, nid_xx));
888 BOOST_CHECK( nmask.includes(roster, nid_xxf));
889 BOOST_CHECK( nmask.includes(roster, nid_xxg));
890 BOOST_CHECK(!nmask.includes(roster, nid_xy));
891 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
892 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
893
894 BOOST_CHECK(!nmask.includes(roster, nid_y));
895 BOOST_CHECK(!nmask.includes(roster, nid_yf));
896 BOOST_CHECK(!nmask.includes(roster, nid_yg));
897 BOOST_CHECK(!nmask.includes(roster, nid_yx));
898 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
899 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
900 BOOST_CHECK( nmask.includes(roster, nid_yy));
901 BOOST_CHECK( nmask.includes(roster, nid_yyf));
902 BOOST_CHECK( nmask.includes(roster, nid_yyg));
903
904 // check restricted paths
905
906 path_restriction pmask(includes, excludes, -1, app);
907
908 BOOST_CHECK(!pmask.empty());
909
910 BOOST_CHECK(!pmask.includes(sp_root));
911 BOOST_CHECK(!pmask.includes(sp_f));
912 BOOST_CHECK(!pmask.includes(sp_g));
913
914 BOOST_CHECK(!pmask.includes(sp_x));
915 BOOST_CHECK(!pmask.includes(sp_xf));
916 BOOST_CHECK(!pmask.includes(sp_xg));
917 BOOST_CHECK( pmask.includes(sp_xx));
918 BOOST_CHECK( pmask.includes(sp_xxf));
919 BOOST_CHECK( pmask.includes(sp_xxg));
920 BOOST_CHECK(!pmask.includes(sp_xy));
921 BOOST_CHECK(!pmask.includes(sp_xyf));
922 BOOST_CHECK(!pmask.includes(sp_xyg));
923
924 BOOST_CHECK(!pmask.includes(sp_y));
925 BOOST_CHECK(!pmask.includes(sp_yf));
926 BOOST_CHECK(!pmask.includes(sp_yg));
927 BOOST_CHECK(!pmask.includes(sp_yx));
928 BOOST_CHECK(!pmask.includes(sp_yxf));
929 BOOST_CHECK(!pmask.includes(sp_yxg));
930 BOOST_CHECK( pmask.includes(sp_yy));
931 BOOST_CHECK( pmask.includes(sp_yyf));
932 BOOST_CHECK( pmask.includes(sp_yyg));
933}
934
935UNIT_TEST(restrictions, invalid_roster_paths)
936{
937 roster_t roster;
938 setup(roster);
939
940 vector<file_path> includes, excludes;
941 includes.push_back(file_path_internal("foo"));
942 excludes.push_back(file_path_internal("bar"));
943
944 app_state app;
945 BOOST_CHECK_THROW(node_restriction(includes, excludes, -1, roster, app),
946 informative_failure);
947}
948
949UNIT_TEST(restrictions, invalid_workspace_paths)
950{
951 roster_t roster;
952 setup(roster);
953
954 vector<file_path> includes, excludes;
955 includes.push_back(file_path_internal("foo"));
956 excludes.push_back(file_path_internal("bar"));
957
958 app_state app;
959 BOOST_CHECK_THROW(path_restriction(includes, excludes, -1, app),
960 informative_failure);
961}
962
963UNIT_TEST(restrictions, include_depth_0)
964{
965 roster_t roster;
966 setup(roster);
967
968 vector<file_path> includes, excludes;
969 includes.push_back(file_path_internal("x"));
970 includes.push_back(file_path_internal("y"));
971
972 app_state app;
973 // FIXME: depth == 0 currently means directory + immediate children
974 // this should be changed to mean just the named directory but for
975 // compatibility with old restrictions this behaviour has been preserved
976 long depth = 0;
977
978 // check restricted nodes
979
980 node_restriction nmask(includes, excludes, depth, roster, app);
981
982 BOOST_CHECK(!nmask.empty());
983
984 BOOST_CHECK(!nmask.includes(roster, nid_root));
985 BOOST_CHECK(!nmask.includes(roster, nid_f));
986 BOOST_CHECK(!nmask.includes(roster, nid_g));
987
988 BOOST_CHECK( nmask.includes(roster, nid_x));
989 BOOST_CHECK( nmask.includes(roster, nid_xf));
990 BOOST_CHECK( nmask.includes(roster, nid_xg));
991 BOOST_CHECK( nmask.includes(roster, nid_xx));
992 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
993 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
994 BOOST_CHECK( nmask.includes(roster, nid_xy));
995 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
996 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
997
998 BOOST_CHECK( nmask.includes(roster, nid_y));
999 BOOST_CHECK( nmask.includes(roster, nid_yf));
1000 BOOST_CHECK( nmask.includes(roster, nid_yg));
1001 BOOST_CHECK( nmask.includes(roster, nid_yx));
1002 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
1003 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
1004 BOOST_CHECK( nmask.includes(roster, nid_yy));
1005 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
1006 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
1007
1008 // check restricted paths
1009
1010 path_restriction pmask(includes, excludes, depth, app);
1011
1012 BOOST_CHECK(!pmask.empty());
1013
1014 BOOST_CHECK(!pmask.includes(sp_root));
1015 BOOST_CHECK(!pmask.includes(sp_f));
1016 BOOST_CHECK(!pmask.includes(sp_g));
1017
1018 BOOST_CHECK( pmask.includes(sp_x));
1019 BOOST_CHECK( pmask.includes(sp_xf));
1020 BOOST_CHECK( pmask.includes(sp_xg));
1021 BOOST_CHECK( pmask.includes(sp_xx));
1022 BOOST_CHECK(!pmask.includes(sp_xxf));
1023 BOOST_CHECK(!pmask.includes(sp_xxg));
1024 BOOST_CHECK( pmask.includes(sp_xy));
1025 BOOST_CHECK(!pmask.includes(sp_xyf));
1026 BOOST_CHECK(!pmask.includes(sp_xyg));
1027
1028 BOOST_CHECK( pmask.includes(sp_y));
1029 BOOST_CHECK( pmask.includes(sp_yf));
1030 BOOST_CHECK( pmask.includes(sp_yg));
1031 BOOST_CHECK( pmask.includes(sp_yx));
1032 BOOST_CHECK(!pmask.includes(sp_yxf));
1033 BOOST_CHECK(!pmask.includes(sp_yxg));
1034 BOOST_CHECK( pmask.includes(sp_yy));
1035 BOOST_CHECK(!pmask.includes(sp_yyf));
1036 BOOST_CHECK(!pmask.includes(sp_yyg));
1037}
1038
1039UNIT_TEST(restrictions, include_depth_0_empty_restriction)
1040{
1041 roster_t roster;
1042 setup(roster);
1043
1044 vector<file_path> includes, excludes;
1045
1046 app_state app;
1047 // FIXME: depth == 0 currently means directory + immediate children
1048 // this should be changed to mean just the named directory but for
1049 // compatibility with old restrictions this behaviour has been preserved
1050 long depth = 0;
1051
1052 // check restricted nodes
1053
1054 node_restriction nmask(includes, excludes, depth, roster, app);
1055
1056 BOOST_CHECK( nmask.empty());
1057
1058 BOOST_CHECK( nmask.includes(roster, nid_root));
1059 BOOST_CHECK( nmask.includes(roster, nid_f));
1060 BOOST_CHECK( nmask.includes(roster, nid_g));
1061
1062 BOOST_CHECK( nmask.includes(roster, nid_x));
1063 BOOST_CHECK(!nmask.includes(roster, nid_xf));
1064 BOOST_CHECK(!nmask.includes(roster, nid_xg));
1065 BOOST_CHECK(!nmask.includes(roster, nid_xx));
1066 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
1067 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
1068 BOOST_CHECK(!nmask.includes(roster, nid_xy));
1069 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
1070 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
1071
1072 BOOST_CHECK( nmask.includes(roster, nid_y));
1073 BOOST_CHECK(!nmask.includes(roster, nid_yf));
1074 BOOST_CHECK(!nmask.includes(roster, nid_yg));
1075 BOOST_CHECK(!nmask.includes(roster, nid_yx));
1076 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
1077 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
1078 BOOST_CHECK(!nmask.includes(roster, nid_yy));
1079 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
1080 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
1081
1082 // check restricted paths
1083
1084 path_restriction pmask(includes, excludes, depth, app);
1085
1086 BOOST_CHECK( pmask.empty());
1087
1088 BOOST_CHECK( pmask.includes(sp_root));
1089 BOOST_CHECK( pmask.includes(sp_f));
1090 BOOST_CHECK( pmask.includes(sp_g));
1091
1092 BOOST_CHECK( pmask.includes(sp_x));
1093 BOOST_CHECK(!pmask.includes(sp_xf));
1094 BOOST_CHECK(!pmask.includes(sp_xg));
1095 BOOST_CHECK(!pmask.includes(sp_xx));
1096 BOOST_CHECK(!pmask.includes(sp_xxf));
1097 BOOST_CHECK(!pmask.includes(sp_xxg));
1098 BOOST_CHECK(!pmask.includes(sp_xy));
1099 BOOST_CHECK(!pmask.includes(sp_xyf));
1100 BOOST_CHECK(!pmask.includes(sp_xyg));
1101
1102 BOOST_CHECK( pmask.includes(sp_y));
1103 BOOST_CHECK(!pmask.includes(sp_yf));
1104 BOOST_CHECK(!pmask.includes(sp_yg));
1105 BOOST_CHECK(!pmask.includes(sp_yx));
1106 BOOST_CHECK(!pmask.includes(sp_yxf));
1107 BOOST_CHECK(!pmask.includes(sp_yxg));
1108 BOOST_CHECK(!pmask.includes(sp_yy));
1109 BOOST_CHECK(!pmask.includes(sp_yyf));
1110 BOOST_CHECK(!pmask.includes(sp_yyg));
1111}
1112
1113UNIT_TEST(restrictions, include_depth_1)
1114{
1115 roster_t roster;
1116 setup(roster);
1117
1118 vector<file_path> includes, excludes;
1119 includes.push_back(file_path_internal("x"));
1120 includes.push_back(file_path_internal("y"));
1121
1122 app_state app;
1123 // FIXME: depth == 1 currently means directory + children + grand children
1124 // this should be changed to mean directory + immediate children but for
1125 // compatibility with old restrictions this behaviour has been preserved
1126 long depth = 1;
1127
1128 // check restricted nodes
1129
1130 node_restriction nmask(includes, excludes, depth, roster, app);
1131
1132 BOOST_CHECK(!nmask.empty());
1133
1134 BOOST_CHECK(!nmask.includes(roster, nid_root));
1135 BOOST_CHECK(!nmask.includes(roster, nid_f));
1136 BOOST_CHECK(!nmask.includes(roster, nid_g));
1137
1138 BOOST_CHECK( nmask.includes(roster, nid_x));
1139 BOOST_CHECK( nmask.includes(roster, nid_xf));
1140 BOOST_CHECK( nmask.includes(roster, nid_xg));
1141 BOOST_CHECK( nmask.includes(roster, nid_xx));
1142 BOOST_CHECK( nmask.includes(roster, nid_xxf));
1143 BOOST_CHECK( nmask.includes(roster, nid_xxg));
1144 BOOST_CHECK( nmask.includes(roster, nid_xy));
1145 BOOST_CHECK( nmask.includes(roster, nid_xyf));
1146 BOOST_CHECK( nmask.includes(roster, nid_xyg));
1147
1148 BOOST_CHECK( nmask.includes(roster, nid_y));
1149 BOOST_CHECK( nmask.includes(roster, nid_yf));
1150 BOOST_CHECK( nmask.includes(roster, nid_yg));
1151 BOOST_CHECK( nmask.includes(roster, nid_yx));
1152 BOOST_CHECK( nmask.includes(roster, nid_yxf));
1153 BOOST_CHECK( nmask.includes(roster, nid_yxg));
1154 BOOST_CHECK( nmask.includes(roster, nid_yy));
1155 BOOST_CHECK( nmask.includes(roster, nid_yyf));
1156 BOOST_CHECK( nmask.includes(roster, nid_yyg));
1157
1158 // check restricted paths
1159
1160 path_restriction pmask(includes, excludes, depth, app);
1161
1162 BOOST_CHECK(!pmask.empty());
1163
1164 BOOST_CHECK(!pmask.includes(sp_root));
1165 BOOST_CHECK(!pmask.includes(sp_f));
1166 BOOST_CHECK(!pmask.includes(sp_g));
1167
1168 BOOST_CHECK( pmask.includes(sp_x));
1169 BOOST_CHECK( pmask.includes(sp_xf));
1170 BOOST_CHECK( pmask.includes(sp_xg));
1171 BOOST_CHECK( pmask.includes(sp_xx));
1172 BOOST_CHECK( pmask.includes(sp_xxf));
1173 BOOST_CHECK( pmask.includes(sp_xxg));
1174 BOOST_CHECK( pmask.includes(sp_xy));
1175 BOOST_CHECK( pmask.includes(sp_xyf));
1176 BOOST_CHECK( pmask.includes(sp_xyg));
1177
1178 BOOST_CHECK( pmask.includes(sp_y));
1179 BOOST_CHECK( pmask.includes(sp_yf));
1180 BOOST_CHECK( pmask.includes(sp_yg));
1181 BOOST_CHECK( pmask.includes(sp_yx));
1182 BOOST_CHECK( pmask.includes(sp_yxf));
1183 BOOST_CHECK( pmask.includes(sp_yxg));
1184 BOOST_CHECK( pmask.includes(sp_yy));
1185 BOOST_CHECK( pmask.includes(sp_yyf));
1186 BOOST_CHECK( pmask.includes(sp_yyg));
1187}
1188
1189#endif // BUILD_UNIT_TESTS
1190
1191// Local Variables:
1192// mode: C++
1193// fill-column: 76
1194// c-file-style: "gnu"
1195// indent-tabs-mode: nil
1196// End:
1197// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status