# # add_file "tests/t_restriction_with_exclude.at" # # patch "ChangeLog" # from [16768c3e61cd01848429d635a3cd40271fd353c3] # to [746912cbb100ebc57364b0e9c8d3785cb3cc5f7d] # # patch "app_state.cc" # from [913741f52364afa34c20540f2008ef88fc911f30] # to [4c8ba6a5cdc3fa945a945e19ea63e1fc857d3ca1] # # patch "app_state.hh" # from [6f4dfe92668723e2ca2eb8bb005ebab6c0d050c5] # to [869c3e0393d765e37fc17ae117ccbbe69776b177] # # patch "commands.cc" # from [59ff7fa5fa25b87fd469695fa7efa6cc197a23b0] # to [61185ae5cc7cd776c25ca1655199a314bdd40378] # # patch "monotone.cc" # from [21176c710f4d646215c27d82b55f182830d13268] # to [21be582ccd322a35a5d1864ee1251e5773054619] # # patch "tests/t_restriction_with_exclude.at" # from [] # to [bf85428b2d62062acb23d375b0b18a3706adc5dd] # # patch "testsuite.at" # from [f37b217c9d261739b96a0f8ccdc61269f1c0ee67] # to [9843a5c53ec471614fc6d5ef5dfcf16fc6995608] # ======================================================================== --- ChangeLog 16768c3e61cd01848429d635a3cd40271fd353c3 +++ ChangeLog 746912cbb100ebc57364b0e9c8d3785cb3cc5f7d @@ -1,3 +1,11 @@ +2005-09-15 Timothy Brownawell + + * app_state.{cc,hh}: restrictions now understand --exclude + * commands.cc: commit and revert now take OPT_EXCLUDE + * monotone.cc: update description of --exclude + * tests/t_restriction_with_exclude.at: new test + * testsuite.at: add it + 2005-09-14 Timothy Brownawell * contrib/ciabot_monotone_hookversion.py: CIA bot client script ======================================================================== --- app_state.cc 913741f52364afa34c20540f2008ef88fc911f30 +++ app_state.cc 4c8ba6a5cdc3fa945a945e19ea63e1fc857d3ca1 @@ -123,6 +123,7 @@ { static file_path root = file_path_internal(""); restrictions.clear(); + excludes.clear(); for (vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { file_path p = file_path_external(*i); @@ -140,6 +141,24 @@ restrictions.insert(p); } + for (std::set::const_iterator i = exclude_patterns.begin(); + i != exclude_patterns.end(); ++i) + { + file_path p = file_path_external(*i); + + if (respect_ignore && lua.hook_ignore_file(p)) + { + L(F("'%s' ignored by excluded path set\n") % p); + continue; + } + + N(p == root || valid_paths.find(p) != valid_paths.end(), + F("unknown path '%s'\n") % p); + + L(F("'%s' added to excluded path set\n") % p); + excludes.insert(p); + } + // if user supplied a depth but provided no paths // assume current directory if ((depth != -1) && restrictions.empty()) @@ -152,23 +171,37 @@ app_state::restriction_includes(file_path const & path) { static file_path root = file_path_internal(""); - if (restrictions.empty()) + + if (restrictions.empty()) { - return true; - } + if (!excludes.empty()) + { + if (excludes.find(root) != excludes.end()) + return false; + fs::path test = fs::path(path.as_external(), fs::native); - bool user_supplied_depth = (depth != -1); + while (!test.empty()) + { + L(F("checking excluded path set for '%s'\n") % test.string()); - // a path that normalizes to "." means that the restriction has been - // essentially cleared (all files are included). rather than be - // careful about what goes in to the restricted path set we just - // check for this special case here. + file_path p = file_path_internal(test.string()); + path_set::const_iterator i = excludes.find(p); - if ((!user_supplied_depth) && restrictions.find(root) != restrictions.end()) - { + if (i != excludes.end()) + { + L(F("path '%s' found in excluded path set; '%s' excluded\n") + % test.string() % path); + return false; + } + + test = test.branch_path(); + } + } return true; } + bool user_supplied_depth = (depth != -1); + fs::path test = fs::path(path.as_external(), fs::native); long branch_depth = 0; long max_depth = depth + 1; @@ -179,6 +212,7 @@ file_path p = file_path_internal(test.string()); path_set::const_iterator i = restrictions.find(p); + path_set::const_iterator j = excludes.find(p); if (i != restrictions.end()) { @@ -186,10 +220,11 @@ % test.string() % path); return true; } - else + else if (j != excludes.end()) { - L(F("path '%s' not found in restricted path set; '%s' excluded\n") + L(F("path '%s' found in excluded path set; '%s' excluded\n") % test.string() % path); + return false; } if (user_supplied_depth && (max_depth == branch_depth)) return false; @@ -197,9 +232,13 @@ ++branch_depth; } - if (user_supplied_depth && (restrictions.find(root) != restrictions.end())) + // a path that normalizes to "." means that the restriction has been + // essentially cleared (all files are included). rather than be + // careful about what goes in to the restricted path set we just + // check for this special case here. + if (restrictions.find(root) != restrictions.end()) { - return (branch_depth <= max_depth); + return (!user_supplied_depth) || (branch_depth <= max_depth); } return false; ======================================================================== --- app_state.hh 6f4dfe92668723e2ca2eb8bb005ebab6c0d050c5 +++ app_state.hh 869c3e0393d765e37fc17ae117ccbbe69776b177 @@ -50,6 +50,7 @@ std::set exclude_patterns; std::vector extra_rcfiles; path_set restrictions; + path_set excludes; bool found_working_copy; long depth; long last; ======================================================================== --- commands.cc 59ff7fa5fa25b87fd469695fa7efa6cc197a23b0 +++ commands.cc 61185ae5cc7cd776c25ca1655199a314bdd40378 @@ -2214,7 +2214,7 @@ CMD(commit, N_("working copy"), N_("[PATH]..."), N_("commit working copy to database"), - OPT_BRANCH_NAME % OPT_MESSAGE % OPT_MSGFILE % OPT_DATE % OPT_AUTHOR % OPT_DEPTH) + OPT_BRANCH_NAME % OPT_MESSAGE % OPT_MSGFILE % OPT_DATE % OPT_AUTHOR % OPT_DEPTH % OPT_EXCLUDE) { string log_message(""); revision_set rs; @@ -3304,7 +3304,7 @@ CMD(revert, N_("working copy"), N_("[PATH]..."), - N_("revert file(s), dir(s) or entire working copy"), OPT_DEPTH) + N_("revert file(s), dir(s) or entire working copy"), OPT_DEPTH % OPT_EXCLUDE) { manifest_map m_old; revision_id old_revision_id; ======================================================================== --- monotone.cc 21176c710f4d646215c27d82b55f182830d13268 +++ monotone.cc 21be582ccd322a35a5d1864ee1251e5773054619 @@ -61,7 +61,7 @@ {"diffs", 0, POPT_ARG_NONE, NULL, OPT_DIFFS, gettext_noop("print diffs along with logs"), NULL}, {"no-merges", 0, POPT_ARG_NONE, NULL, OPT_NO_MERGES, gettext_noop("skip merges when printing logs"), NULL}, {"set-default", 0, POPT_ARG_NONE, NULL, OPT_SET_DEFAULT, gettext_noop("use the current arguments as the future default"), NULL}, - {"exclude", 0, POPT_ARG_STRING, &argstr, OPT_EXCLUDE, gettext_noop("leave out branches matching a pattern"), NULL}, + {"exclude", 0, POPT_ARG_STRING, &argstr, OPT_EXCLUDE, gettext_noop("leave out anything described by its argument"), NULL}, {"unified", 0, POPT_ARG_NONE, NULL, OPT_UNIFIED_DIFF, gettext_noop("use unified diff format"), NULL}, {"context", 0, POPT_ARG_NONE, NULL, OPT_CONTEXT_DIFF, gettext_noop("use context diff format"), NULL}, {"external", 0, POPT_ARG_NONE, NULL, OPT_EXTERNAL_DIFF, gettext_noop("use external diff hook for generating diffs"), NULL}, ======================================================================== --- tests/t_restriction_with_exclude.at +++ tests/t_restriction_with_exclude.at bf85428b2d62062acb23d375b0b18a3706adc5dd @@ -0,0 +1,40 @@ +AT_SETUP([use restrictions with --exclude]) +MONOTONE_SETUP + +AT_CHECK(mkdir foo) +AT_DATA(file1, [x +]) +AT_DATA(foo/bar, [y +]) + +AT_CHECK(MONOTONE add file1, [], [ignore], [ignore]) +AT_CHECK(MONOTONE add foo/bar, [], [ignore], [ignore]) + +AT_CHECK(MONOTONE ci --exclude . -m 'x', [1], [ignore], [ignore]) + +AT_CHECK(MONOTONE ci --exclude . file1 -m 'x', [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "foo/bar", [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "file1", [1], [ignore], [ignore]) +AT_CHECK(echo a >>file1) + +AT_CHECK(MONOTONE ci --exclude foo -m 'x', [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "foo/bar", [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "file1", [1], [ignore], [ignore]) +AT_CHECK(echo a >>file1) + +AT_CHECK(MONOTONE ci . --exclude file1 -m 'x', [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "foo/bar", [1], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "file1", [], [ignore], [ignore]) +AT_CHECK(echo b >>foo/bar) + +AT_CHECK(MONOTONE ci . --exclude foo foo/bar -m 'x', [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "foo/bar", [1], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "file1", [1], [ignore], [ignore]) +AT_CHECK(echo a >>file1) +AT_CHECK(echo b >>foo/bar) + +AT_CHECK(MONOTONE ci --exclude foo foo/bar -m 'x', [], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "foo/bar", [1], [ignore], [ignore]) +AT_CHECK(MONOTONE status --brief | grep "file1", [], [ignore], [ignore]) + +AT_CLEANUP ======================================================================== --- testsuite.at f37b217c9d261739b96a0f8ccdc61269f1c0ee67 +++ testsuite.at 9843a5c53ec471614fc6d5ef5dfcf16fc6995608 @@ -704,3 +704,4 @@ m4_include(tests/t_automate_get_manifest.at) m4_include(tests/t_automate_get_revision.at) m4_include(tests/t_unreadable_db.at) +m4_include(tests/t_restriction_with_exclude.at)