# # patch "paths.cc" # from [b1624115da5bc2aaef4bb8677a9fe40c091038fa] # to [d3290e08f71dd807af63d32ffbefbe84c8e61757] # # patch "roster.cc" # from [f93fa0acd8d00425ab90242c1fa9ab4496d0ac97] # to [853c03fd06ccedbfd81897a9350e5b0341ec825c] # # patch "roster_merge.cc" # from [053900b693576f72fa3b6f08697a4fcdae13399b] # to [9598a6096285adba63177bcb09b5a27ae6def84d] # # patch "roster_merge.hh" # from [27a2989edd99424357d037fc0b50dec372bfdd06] # to [b90caa1f69004ea37e1732462d3284d0bcf15af4] # ======================================================================== --- paths.cc b1624115da5bc2aaef4bb8677a9fe40c091038fa +++ paths.cc d3290e08f71dd807af63d32ffbefbe84c8e61757 @@ -791,12 +791,12 @@ BOOST_CHECK(split1[3] == split2[2]); file_path fp3 = file_path_internal(""); - pcv split3; + split_path split3; fp3.split(split3); BOOST_CHECK(split3.size() == 1 && null_name(split3[0])); // empty split_path is invalid - pcv split4; + split_path split4; // this comparison tricks the compiler into not completely eliminating this // code as dead... BOOST_CHECK_THROW(file_path(split4) == file_path(), std::logic_error); @@ -821,7 +821,7 @@ // Make sure that we can't use joining to create a path into the bookkeeping // dir - pcv split_mt1, split_mt2; + split_path split_mt1, split_mt2; file_path_internal("foo/MT").split(split_mt1); BOOST_CHECK(split_mt1.size() == 3); split_mt2.push_back(the_null_component); ======================================================================== --- roster.cc f93fa0acd8d00425ab90242c1fa9ab4496d0ac97 +++ roster.cc 853c03fd06ccedbfd81897a9350e5b0341ec825c @@ -2385,10 +2385,22 @@ make_cset(b, a, b_to_a); roster_t a2(b); MM(a2); roster_t b2(a); MM(b2); - editable_roster_base eb(a2, nis); - b_to_a.apply_to(eb); - editable_roster_base ea(b2, nis); - a_to_b.apply_to(ea); + // we can't use a cset to entirely empty out a roster, so don't bother doing + // the apply_to tests towards an empty roster + if (!a.all_nodes().empty()) + { + editable_roster_base eb(a2, nis); + b_to_a.apply_to(eb); + } + else + a2 = a; + if (!b.all_nodes().empty()) + { + editable_roster_base ea(b2, nis); + a_to_b.apply_to(ea); + } + else + b2 = b; // We'd like to assert that a2 == a and b2 == b, but we can't, because they // will have new ids assigned. // But they _will_ have the same manifests, assuming things are working @@ -2608,9 +2620,22 @@ attr_key k = pick_attr(n->attrs); if (safe_get(n->attrs, k).first) { - // L(F("clearing attr on '%s'\n") % file_path(pth)); - safe_insert(c.attrs_cleared, make_pair(pth, k)); + if (flip()) + { + // L(F("clearing attr on '%s'\n") % file_path(pth)); + safe_insert(c.attrs_cleared, make_pair(pth, k)); + } + else + { + // L(F("changing attr on '%s'\n) % file_path(pth)); + safe_insert(c.attrs_set, make_pair(make_pair(pth, k), new_word())); + } } + else + { + // L(F("setting previously set attr on '%s'\n") % file_path(pth)); + safe_insert(c.attrs_set, make_pair(make_pair(pth, k), new_word())); + } } else { ======================================================================== --- roster_merge.cc 053900b693576f72fa3b6f08697a4fcdae13399b +++ roster_merge.cc 9598a6096285adba63177bcb09b5a27ae6def84d @@ -15,7 +15,9 @@ { return node_name_conflicts.empty() && file_content_conflicts.empty() - && node_attr_conflicts.empty(); + && node_attr_conflicts.empty() + && orphaned_node_conflicts.empty() + && rename_target_conflicts.empty(); } void @@ -24,6 +26,8 @@ node_attr_conflicts.clear(); file_content_conflicts.clear(); node_attr_conflicts.clear(); + orphaned_node_conflicts.clear(); + rename_target_conflicts.clear(); roster = roster_t(); } ======================================================================== --- roster_merge.hh 27a2989edd99424357d037fc0b50dec372bfdd06 +++ roster_merge.hh b90caa1f69004ea37e1732462d3284d0bcf15af4 @@ -65,22 +65,22 @@ // orphaned nodes always merged their name cleanly, so we simply put that name // here. the node in the resulting roster is detached. -// struct orphaned_node_conflict -// { -// node_id nid; -// node_id dead_parent; -// path_component name; -// }; +struct orphaned_node_conflict +{ + node_id nid; + node_id dead_parent; + path_component name; +}; // this is when two (or more, but in fact only two is possible, since we only // merge two rosters at a time) distinct nodes want to have the same name. // these nodes always each merged their names cleanly. // the nodes in the resulting roster are both detached. -// struct rename_target_conflict -// { -// node_id nid1, nid2; -// std::pair name; -// }; +struct rename_target_conflict +{ + node_id nid_left, nid_right; + std::pair name; +}; // FIXME: @@ -94,6 +94,8 @@ std::vector node_name_conflicts; std::vector file_content_conflicts; std::vector node_attr_conflicts; + std::vector orphaned_node_conflicts; + std::vector rename_target_conflicts; // this roster is sane if is_clean() returns true roster_t roster; bool is_clean();