# # add_file "tests/t_add_inside_MT.at" # # patch "ChangeLog" # from [6c66bdb12e94b277dd3896b4fd4f2ae08ab167b3] # to [6e3a06b93b6818cc50d4f1893f59e3789682947b] # # patch "paths.cc" # from [b77289a76e8d3c43a1dc2467c7b679c1aa6f9ca9] # to [05627e3f8f213cac8d136c09e3cd18259945624c] # # patch "tests/t_add_inside_MT.at" # from [] # to [d0760c6e2f24d3f968d4d66501ab0a17fdbd5e41] # # patch "testsuite.at" # from [6645f9e24d4beff510bf4dc9c2c154d553b62415] # to [2a36cd1b6327f01ac36251cdeff5cf968a816c45] # ======================================================================== --- ChangeLog 6c66bdb12e94b277dd3896b4fd4f2ae08ab167b3 +++ ChangeLog 6e3a06b93b6818cc50d4f1893f59e3789682947b @@ -1,3 +1,10 @@ +2005-10-08 Nathaniel Smith + + * paths.cc: Make initial_rel_path an fs::path. Adjust code + correspondingly. Add tests that calling monotone from inside MT + should work. + * tests/t_add_inside_MT.at, testsuite.at: New test. + 2005-10-04 Nathaniel Smith * monotone.texi (Automation): Document the mysterious columns of ======================================================================== --- paths.cc b77289a76e8d3c43a1dc2467c7b679c1aa6f9ca9 +++ paths.cc 05627e3f8f213cac8d136c09e3cd18259945624c @@ -21,6 +21,8 @@ // filenames. the idea is to make sure // -- we don't depend on the existence of something before it has been set // -- we don't re-set something that has already been used +// -- sometimes, we use the _non_-existence of something, so we shouldn't +// set anything whose un-setted-ness has already been used template struct access_tracker { @@ -65,7 +67,10 @@ // initial_abs_path is for interpreting relative system_path's static access_tracker initial_abs_path; // initial_rel_path is for interpreting external file_path's -static access_tracker initial_rel_path; +// for now we just make it an fs::path for convenience; we used to make it a +// file_path, but then you can't run monotone from inside the MT/ dir (even +// when referring to files outside the MT/ dir). +static access_tracker initial_rel_path; // working_root is for converting file_path's and bookkeeping_path's to // system_path's. static access_tracker working_root; @@ -173,22 +178,22 @@ break; case external: if (!initial_rel_path.initialized) - { - // we are not in a working directory; treat this as an internal - // path, and set the access_tracker() into a very uninitialised - // state so that we will hit an exception if we do eventually - // enter a working directory - initial_rel_path.may_not_initialize(); - data = path; - N(is_valid_internal(path), - F("path '%s' is invalid") % path); - break; - } + { + // we are not in a working directory; treat this as an internal + // path, and set the access_tracker() into a very uninitialised + // state so that we will hit an exception if we do eventually + // enter a working directory + initial_rel_path.may_not_initialize(); + data = path; + N(is_valid_internal(path) && !in_bookkeeping_dir(path), + F("path '%s' is invalid") % path); + break; + } N(!path.empty(), F("empty path '%s' is invalid") % path); fs::path out, base, relative; try { - base = fs::path(initial_rel_path.get().as_internal()); + base = initial_rel_path.get(); // the fs::native is needed to get it to accept paths like ".foo". relative = fs::path(path, fs::native); out = (base / relative).normalize(); @@ -496,10 +501,10 @@ } working_root.set(current.native_file_string(), true); - initial_rel_path.set(file_path_internal(removed.string()), true); + initial_rel_path.set(removed, true); L(F("working root is '%s'") % working_root.get_but_unused()); - L(F("initial relative path is '%s'") % initial_rel_path.get_but_unused()); + L(F("initial relative path is '%s'") % initial_rel_path.get_but_unused().string()); change_current_working_dir(working_root.get_but_unused()); @@ -510,7 +515,7 @@ go_to_working_copy(system_path const & new_working_copy) { working_root.set(new_working_copy, true); - initial_rel_path.set(file_path(), true); + initial_rel_path.set(fs::path(), true); change_current_working_dir(new_working_copy); } @@ -543,13 +548,13 @@ "c:/foo", 0 }; initial_rel_path.unset(); - initial_rel_path.set(file_path(), true); + initial_rel_path.set(fs::path(), true); for (char const ** c = baddies; *c; ++c) { BOOST_CHECK_THROW(file_path_internal(*c), std::logic_error); } initial_rel_path.unset(); - initial_rel_path.set(file_path_internal("blah/blah/blah"), true); + initial_rel_path.set(fs::path("blah/blah/blah", fs::native), true); for (char const ** c = baddies; *c; ++c) { BOOST_CHECK_THROW(file_path_internal(*c), std::logic_error); @@ -575,8 +580,8 @@ for (int i = 0; i < 2; ++i) { initial_rel_path.unset(); - initial_rel_path.set(i ? file_path() - : file_path_internal("blah/blah/blah"), + initial_rel_path.set(i ? fs::path() + : fs::path("blah/blah/blah", fs::native), true); for (char const ** c = goodies; *c; ++c) { @@ -627,10 +632,10 @@ BOOST_CHECK(!null_name(*i)); } -static void test_file_path_external_no_prefix() +static void test_file_path_external_null_prefix() { initial_rel_path.unset(); - initial_rel_path.set(file_path(), true); + initial_rel_path.set(fs::path(), true); char const * baddies[] = {"/foo", "../bar", @@ -646,7 +651,7 @@ 0 }; for (char const ** c = baddies; *c; ++c) { - L(F("test_file_path_external_no_prefix: trying baddie: %s") % *c); + L(F("test_file_path_external_null_prefix: trying baddie: %s") % *c); BOOST_CHECK_THROW(file_path_external(utf8(*c)), informative_failure); } @@ -678,14 +683,28 @@ initial_rel_path.unset(); } +static void test_file_path_external_prefix_MT() +{ + initial_rel_path.unset(); + initial_rel_path.set(fs::path("MT"), true); + + BOOST_CHECK_THROW(file_path_external(utf8("foo")), informative_failure); + BOOST_CHECK_THROW(file_path_external(utf8(".")), informative_failure); + BOOST_CHECK_THROW(file_path_external(utf8("./blah")), informative_failure); + check_fp_normalizes_to("..", ""); + check_fp_normalizes_to("../foo", "foo"); +} + static void test_file_path_external_prefix_a_b() { initial_rel_path.unset(); - initial_rel_path.set(file_path_internal("a/b"), true); + initial_rel_path.set(fs::path("a/b"), true); char const * baddies[] = {"/foo", "../../../bar", "../../..", + "../../MT", + "../../MT/foo", "//blah", "\\foo", "c:\\foo", @@ -906,7 +925,7 @@ working_root.unset(); working_root.set(system_path("/working/root"), true); initial_rel_path.unset(); - initial_rel_path.set(file_path_internal("rel/initial"), true); + initial_rel_path.set(fs::path("rel/initial"), true); BOOST_CHECK(system_path(system_path("foo/bar")).as_internal() == "/a/b/foo/bar"); BOOST_CHECK(!working_root.used); @@ -956,7 +975,8 @@ I(suite); suite->add(BOOST_TEST_CASE(&test_null_name)); suite->add(BOOST_TEST_CASE(&test_file_path_internal)); - suite->add(BOOST_TEST_CASE(&test_file_path_external_no_prefix)); + suite->add(BOOST_TEST_CASE(&test_file_path_external_null_prefix)); + suite->add(BOOST_TEST_CASE(&test_file_path_external_prefix_MT)); suite->add(BOOST_TEST_CASE(&test_file_path_external_prefix_a_b)); suite->add(BOOST_TEST_CASE(&test_split_join)); suite->add(BOOST_TEST_CASE(&test_bookkeeping_path)); ======================================================================== --- tests/t_add_inside_MT.at +++ tests/t_add_inside_MT.at d0760c6e2f24d3f968d4d66501ab0a17fdbd5e41 @@ -0,0 +1,12 @@ +AT_SETUP([add inside MT/]) +MONOTONE_SETUP + +AT_DATA(testfile1, [blah blah +]) +AT_DATA(MT/testfile2, [blah blah +]) + +AT_CHECK(cd MT && MONOTONE add testfile2, [1], [ignore], [ignore]) +AT_CHECK(cd MT && MONOTONE add ../testfile1, [], [ignore], [ignore]) + +AT_CLEANUP ======================================================================== --- testsuite.at 6645f9e24d4beff510bf4dc9c2c154d553b62415 +++ testsuite.at 2a36cd1b6327f01ac36251cdeff5cf968a816c45 @@ -709,3 +709,4 @@ m4_include(tests/t_rename_diff_names.at) m4_include(tests/t_diff_outside_working_dir.at) m4_include(tests/t_log_outside_working_dir.at) +m4_include(tests/t_add_inside_MT.at)