# # # patch "cmd_merging.cc" # from [47e0b9aed399b96cb0c35f9cd2617d67f95f3e21] # to [58ea84cd757ce9a82b5735d19d77ba44181353fa] # # patch "database_check.cc" # from [2efed1029f06762db5ac5d30e304bd21e4351e0b] # to [6ebc87aa46e879baaa8512fe546f172a94425431] # # patch "merge.cc" # from [261329782b6722da16fcafd9ad02a411e38c57f4] # to [777d0da01664da6d54c58a8149d1daa1f3e38dd5] # # patch "revision.cc" # from [eb4d735c9967f026d1242ca4d38b2de2a483d06e] # to [48753dbeeed4890a89dbd768ac21a9ee1095d47a] # # patch "roster.cc" # from [29314247d94e318e37023a900f3d1b0da1117e49] # to [c10f9bb1dc89dab4e29eb4326497f3ad68185aa6] # # patch "roster_merge.cc" # from [7029afe0cbca494809037d3981cdf052b99d0d65] # to [bf1b4668fad36cfdc8778f3a49cf45e551a929de] # # patch "roster_merge.hh" # from [742f61535acecd23a75df6133af2eda7f5d766e5] # to [f90b99f3bc483d29795a5449968d560f53f0a9c8] # ============================================================ --- cmd_merging.cc 47e0b9aed399b96cb0c35f9cd2617d67f95f3e21 +++ cmd_merging.cc 58ea84cd757ce9a82b5735d19d77ba44181353fa @@ -903,7 +903,7 @@ show_conflicts_core (database & db, revi result.report_directory_loop_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); result.report_orphaned_node_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); - result.report_node_existance_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + result.report_node_existence_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); result.report_multiple_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); result.report_duplicate_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); ============================================================ --- database_check.cc 2efed1029f06762db5ac5d30e304bd21e4351e0b +++ database_check.cc 6ebc87aa46e879baaa8512fe546f172a94425431 @@ -268,6 +268,14 @@ check_rosters_marking(database & db, if (!checked_revisions[mark.birth_revision].found) checked_rosters[ros_id].missing_mark_revs++; + for (set::const_iterator r = mark.existence.begin(); + r != mark.existence.end(); r++) + { + checked_revisions[*r].marking_refs++; + if (!checked_revisions[*r].found) + checked_rosters[ros_id].missing_mark_revs++; + } + for (set::const_iterator r = mark.parent_name.begin(); r != mark.parent_name.end(); r++) { ============================================================ --- merge.cc 261329782b6722da16fcafd9ad02a411e38c57f4 +++ merge.cc 777d0da01664da6d54c58a8149d1daa1f3e38dd5 @@ -148,7 +148,7 @@ resolve_merge_conflicts(lua_hooks & lua, result.report_directory_loop_conflicts(left_roster, right_roster, adaptor, false, std::cout); result.report_orphaned_node_conflicts(left_roster, right_roster, adaptor, false, std::cout); - result.report_node_existance_conflicts(left_roster, right_roster, adaptor, false, std::cout); + result.report_node_existence_conflicts(left_roster, right_roster, adaptor, false, std::cout); result.report_multiple_name_conflicts(left_roster, right_roster, adaptor, false, std::cout); result.report_duplicate_name_conflicts(left_roster, right_roster, adaptor, false, std::cout); ============================================================ --- revision.cc eb4d735c9967f026d1242ca4d38b2de2a483d06e +++ revision.cc 48753dbeeed4890a89dbd768ac21a9ee1095d47a @@ -1144,6 +1144,7 @@ not_dead_yet(node_id nid, u64 birth_rev, parent_roster_map const & parent_rosters, multimap const & child_to_parents) { +#warning Need to fix this for resurrection! // Any given node, at each point in the revision graph, is in one of the // states "alive", "unborn", "dead". The invariant we must maintain in // constructing our revision graph is that if a node is dead in any parent, @@ -1288,6 +1289,7 @@ anc_graph::fixup_node_identities(parent_ // // - If any of the parents thinks that P has died, we do not search for // it in the child; we leave it as "dropped". +#warning Check this - will it work with resurrection? // // - We fetch the name N of the parent node P, and apply the rename map // to N, getting "remapped name" M. If we find a child node C with ============================================================ --- roster.cc 29314247d94e318e37023a900f3d1b0da1117e49 +++ roster.cc c10f9bb1dc89dab4e29eb4326497f3ad68185aa6 @@ -1690,6 +1690,7 @@ mark_merge_roster(roster_t const & left_ node_t const & right_node = rni->second; marking_t const & right_marking = safe_get(right_markings, n->self); // must be unborn on the left (as opposed to dead) +#warning need to check this for resurrection I(right_uncommon_ancestors.find(right_marking.birth_revision) != right_uncommon_ancestors.end()); mark_unmerged_node(right_marking, right_node, @@ -1700,6 +1701,7 @@ mark_merge_roster(roster_t const & left_ node_t const & left_node = lni->second; marking_t const & left_marking = safe_get(left_markings, n->self); // must be unborn on the right (as opposed to dead) +#warning need to check this for resurrection I(left_uncommon_ancestors.find(left_marking.birth_revision) != left_uncommon_ancestors.end()); mark_unmerged_node(left_marking, left_node, @@ -3576,6 +3578,7 @@ namespace roster.attach_node(root_nid, file_path_internal("")); marking_t marking; marking.birth_revision = old_rid; + marking.existence.insert(old_rid); marking.parent_name.insert(old_rid); safe_insert(markings, make_pair(root_nid, marking)); } @@ -3614,6 +3617,7 @@ namespace roster.create_file_node(fid, nid); marking_t marking; marking.birth_revision = scalar_origin_rid; + marking.existence.insert(scalar_origin_rid); marking.parent_name = marking.file_content = singleton(scalar_origin_rid); safe_insert(markings, make_pair(nid, marking)); } @@ -3627,6 +3631,7 @@ namespace roster.create_dir_node(nid); marking_t marking; marking.birth_revision = scalar_origin_rid; + marking.existence.insert(scalar_origin_rid); marking.parent_name = singleton(scalar_origin_rid); safe_insert(markings, make_pair(nid, marking)); } @@ -3722,6 +3727,7 @@ namespace roster.attach_node(c_nid, file_path_internal("dir_c")); marking_t marking; marking.birth_revision = old_rid; + marking.existence.insert(old_rid); marking.parent_name.insert(old_rid); safe_insert(markings, make_pair(a_nid, marking)); safe_insert(markings, make_pair(b_nid, marking)); @@ -4399,6 +4405,7 @@ UNIT_TEST(roster, die_die_die_merge) left_roster.attach_node(left_roster.create_dir_node(nis), file_path()); marking_t an_old_marking; an_old_marking.birth_revision = old_rid; + an_old_marking.existence.insert(old_rid); an_old_marking.parent_name = singleton(old_rid); safe_insert(left_markings, make_pair(left_roster.root()->self, an_old_marking)); @@ -4456,6 +4463,7 @@ UNIT_TEST(roster, same_nid_diff_type) dir_roster.attach_node(dir_roster.create_dir_node(nis), file_path()); marking_t marking; marking.birth_revision = old_rid; + marking.existence.insert(old_rid); marking.parent_name = singleton(old_rid); safe_insert(dir_markings, make_pair(dir_roster.root()->self, marking)); @@ -4608,48 +4616,55 @@ UNIT_TEST(roster, write_roster) roster_data expected(string("format_version \"1\"\n" "\n" - " dir \"\"\n" - " ident \"1\"\n" - " birth [4444444444444444444444444444444444444444]\n" - "path_mark [4444444444444444444444444444444444444444]\n" + " dir \"\"\n" + " ident \"1\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" "\n" - " dir \"fo\"\n" - " ident \"4\"\n" - " birth [4444444444444444444444444444444444444444]\n" - "path_mark [4444444444444444444444444444444444444444]\n" + " dir \"fo\"\n" + " ident \"4\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" "\n" - " dir \"foo\"\n" - " ident \"2\"\n" - " birth [4444444444444444444444444444444444444444]\n" - "path_mark [4444444444444444444444444444444444444444]\n" + " dir \"foo\"\n" + " ident \"2\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" "\n" - " dir \"foo/ang\"\n" - " ident \"6\"\n" - " birth [4444444444444444444444444444444444444444]\n" - "path_mark [4444444444444444444444444444444444444444]\n" + " dir \"foo/ang\"\n" + " ident \"6\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" "\n" - " file \"foo/bar\"\n" - " content [1111111111111111111111111111111111111111]\n" - " ident \"5\"\n" - " attr \"fascist\" \"tidiness\"\n" - " birth [4444444444444444444444444444444444444444]\n" - " path_mark [4444444444444444444444444444444444444444]\n" - "content_mark [4444444444444444444444444444444444444444]\n" - " attr_mark \"fascist\" [4444444444444444444444444444444444444444]\n" + " file \"foo/bar\"\n" + " content [1111111111111111111111111111111111111111]\n" + " ident \"5\"\n" + " attr \"fascist\" \"tidiness\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" + " content_mark [4444444444444444444444444444444444444444]\n" + " attr_mark \"fascist\" [4444444444444444444444444444444444444444]\n" "\n" - " dir \"foo/zoo\"\n" - " ident \"7\"\n" - "dormant_attr \"regime\"\n" - " birth [4444444444444444444444444444444444444444]\n" - " path_mark [4444444444444444444444444444444444444444]\n" - " attr_mark \"regime\" [4444444444444444444444444444444444444444]\n" + " dir \"foo/zoo\"\n" + " ident \"7\"\n" + " dormant_attr \"regime\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" + " attr_mark \"regime\" [4444444444444444444444444444444444444444]\n" "\n" - " dir \"xx\"\n" - " ident \"3\"\n" - " attr \"say\" \"hello\"\n" - " birth [4444444444444444444444444444444444444444]\n" - "path_mark [4444444444444444444444444444444444444444]\n" - "attr_mark \"say\" [4444444444444444444444444444444444444444]\n" + " dir \"xx\"\n" + " ident \"3\"\n" + " attr \"say\" \"hello\"\n" + " birth [4444444444444444444444444444444444444444]\n" + " path_mark [4444444444444444444444444444444444444444]\n" + "existence_mark [4444444444444444444444444444444444444444]\n" + " attr_mark \"say\" [4444444444444444444444444444444444444444]\n" )); MM(expected); @@ -4754,6 +4769,25 @@ UNIT_TEST(roster, check_sane_against) } { + L(FL("TEST: check_sane_against_test, missing existence mark")); + roster_t r; MM(r); + marking_map mm; MM(mm); + + nid = nis.next(); + r.create_dir_node(nid); + r.attach_node(nid, root); + mark_new_node(rid, r.get_node(nid), mm[nid]); + + nid = nis.next(); + r.create_dir_node(nid); + r.attach_node(nid, foo); + mark_new_node(rid, r.get_node(nid), mm[nid]); + mm[nid].existence.clear(); + + UNIT_TEST_CHECK_THROW(r.check_sane_against(mm), logic_error); + } + + { L(FL("TEST: check_sane_against_test, missing content mark")); roster_t r; MM(r); marking_map mm; MM(mm); @@ -4975,6 +5009,7 @@ UNIT_TEST(roster, unify_rosters_end_to_e file_path()); marking_t root_marking; root_marking.birth_revision = old_rid; + root_marking.existence.insert(old_rid); root_marking.parent_name = singleton(old_rid); safe_insert(has_not_markings, make_pair(has_not_roster.root()->self, root_marking)); @@ -4988,6 +5023,7 @@ UNIT_TEST(roster, unify_rosters_end_to_e has_roster.attach_node(new_id, file_path_internal("foo")); marking_t file_marking; file_marking.birth_revision = has_rid; + file_marking.existence.insert(has_rid); file_marking.parent_name = file_marking.file_content = singleton(has_rid); safe_insert(has_markings, make_pair(new_id, file_marking)); } @@ -5058,6 +5094,7 @@ UNIT_TEST(roster, unify_rosters_end_to_e first_roster.attach_node(first_roster.create_dir_node(nis), file_path()); marking_t marking; marking.birth_revision = old_rid; + marking.existence.insert(old_rid); marking.parent_name = singleton(old_rid); safe_insert(first_markings, make_pair(first_roster.root()->self, marking)); @@ -5077,6 +5114,7 @@ UNIT_TEST(roster, unify_rosters_end_to_e make_pair(attr_key("testbar"), make_pair(false, attr_value()))); marking_t marking; marking.birth_revision = second_rid; + marking.existence.insert(second_rid); marking.parent_name = marking.file_content = singleton(second_rid); safe_insert(marking.attrs, make_pair(attr_key("testbar"), singleton(second_rid))); ============================================================ --- roster_merge.cc 7029afe0cbca494809037d3981cdf052b99d0d65 +++ roster_merge.cc bf1b4668fad36cfdc8778f3a49cf45e551a929de @@ -59,10 +59,10 @@ template <> void } template <> void -dump(node_existance_conflict const & conflict, string & out) +dump(node_existence_conflict const & conflict, string & out) { ostringstream oss; - oss << "node_existance_conflict on node: " << conflict.nid << "\n"; + oss << "node_existence_conflict on node: " << conflict.nid << "\n"; out = oss.str(); } @@ -130,6 +130,7 @@ roster_merge_result::has_non_content_con || !invalid_name_conflicts.empty() || !directory_loop_conflicts.empty() || !orphaned_node_conflicts.empty() + || !node_existence_conflicts.empty() || !multiple_name_conflicts.empty() || !duplicate_name_conflicts.empty() || !attribute_conflicts.empty(); @@ -144,6 +145,7 @@ dump_conflicts(roster_merge_result const dump(result.directory_loop_conflicts, out); dump(result.orphaned_node_conflicts, out); + dump(result.node_existence_conflicts, out); dump(result.multiple_name_conflicts, out); dump(result.duplicate_name_conflicts, out); @@ -925,7 +927,7 @@ void } void -roster_merge_result::report_node_existance_conflicts(roster_t const & left_roster, +roster_merge_result::report_node_existence_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -936,9 +938,9 @@ roster_merge_result::report_node_existan #warning FIXME!!! This function needs to be cleaned up! - for (size_t i = 0; i < node_existance_conflicts.size(); ++i) + for (size_t i = 0; i < node_existence_conflicts.size(); ++i) { - node_existance_conflict const & conflict = node_existance_conflicts[i]; + node_existence_conflict const & conflict = node_existence_conflicts[i]; MM(conflict); shared_ptr lca_roster, parent_lca_roster; @@ -955,16 +957,16 @@ roster_merge_result::report_node_existan if (type == file_type) if (basic_io) - st.push_str_pair(syms::conflict, "existance conflict"); + st.push_str_pair(syms::conflict, "existence conflict"); else - P(F("conflict: existance conflict on file '%s' from revision %s") + P(F("conflict: existence conflict on file '%s' from revision %s") % lca_name % lca_rid); else { if (basic_io) - st.push_str_pair(syms::conflict, "existance conflict"); + st.push_str_pair(syms::conflict, "existence conflict"); else - P(F("conflict: existance conflict on directory '%s' from revision %s") + P(F("conflict: existence conflict on directory '%s' from revision %s") % lca_name % lca_rid); } @@ -1394,6 +1396,7 @@ roster_merge_result::clear() directory_loop_conflicts.clear(); orphaned_node_conflicts.clear(); + node_existence_conflicts.clear(); multiple_name_conflicts.clear(); duplicate_name_conflicts.clear(); @@ -1480,32 +1483,150 @@ namespace I(false); } + // We simulate mark merge for existence because we don't have marks + // for the existence on the side where the node has been dropped. + + // If node exists in both, then it exists in the child. + // (and similarly for existing in neither parent and being dead in the child.) + // In either of these cases we won't reach this function + // If node exists in only one parent (so we reach this function), then + // If it was born in an uncommon ancestor then it exists in the child, otherwise + // If the live side doesn't have a mark in that side's uncommon ancestor set, then the node is dead in the child, otherwise + // If the node is dead in all uncommon ancestors on the dead side, then the node is alive in the child, otherwise + // There is a node existence conflict. + + // Justification of why this is mark-merge. + // If the two sides are equal then things are easy - they are the same in the child. + // When the sides differ, only marks in the uncommon ancestors are relevant. On the + // dead side, there will be a mark in the uncommon ancestor set on that side iff the + // node was deleted on that side. i.e. it existed one rev and not the next. + // On the live side we have real marks. + // There are four cases: + // - Neither side has a mark in the uncommon ancestors. In this case the sides + // should be the same, and we should be in the top case. + // - The live side has a mark, and the dead side doesn't. Live side wins. + // - The dead side has a mark, and the live side doesn't. Dead side wins. + // - Both sides have a mark. Conflict + // We speed this up by noticing that finding the marks on the dead side is + // expensive, so we check the live side for information first where possible. + // If the node was born in the uncommon ancestors on the live side then it + // cannot have any marks on the dead side. + // If the live side doesn't have a mark, then either both sides are the same, or + // the dead side has a mark and in either case the child is dead. + + // Note that in all cases where the live side wins outright, we can just use + // the live side's marks for the child. + // Also note that in case of a conflict, the merge node will be marked so in + // that case we don't need to remember marks from either side. The upshot of + // this is that we don't need to reconstruct exact marks for the dead side. + + // This is reasonably efficient: + // The only case we actually need to check for a dead side mark is when there is + // a live side mark and the file wasn't born on the live side. i.e. the file + // was resurrected in the uncommon ancestors on the live side. + // In this last case the dead side mark is need to see if the resurrection wins, + // or if we have a conflict. + inline void - insert_if_unborn(node_t const & n, - marking_map const & markings, - set const & uncommon_ancestors, - roster_t const & parent_roster, - roster_t & new_roster) + mark_merge_existence(node_t const & n, + marking_map const & live_markings, + set const & live_uncommon_ancestors, + roster_t const & live_parent_roster, + set const & dead_uncommon_ancestors, + roster_t const & dead_parent_roster, + roster_merge_result & result) { - revision_id const & birth = safe_get(markings, n->self).birth_revision; - if (uncommon_ancestors.find(birth) != uncommon_ancestors.end()) - create_node_for(n, new_roster); - else + revision_id const & birth = safe_get(live_markings, n->self).birth_revision; + + // if born in a live_uncommon_ancestor then the node exists in the child + if (live_uncommon_ancestors.find(birth) != live_uncommon_ancestors.end()) { + create_node_for(n, result.roster); + return; + } + + // If the live side doesn't have a mark in that side's uncommon ancestor set, then the node is dead in the child. + bool have_mark_in_live_uncommon_ancestor_set = false; + std::set const & marks = safe_get(live_markings, n->self).existence; + for (set::const_iterator it = marks.begin(); it != marks.end(); it++) + { + if (live_uncommon_ancestors.find(*it) != live_uncommon_ancestors.end()) + { + have_mark_in_live_uncommon_ancestor_set = true; + break; + } + } + + if (have_mark_in_live_uncommon_ancestor_set) + { + bool have_mark_in_dead_uncommon_ancestor_set = false; +#warning Need to get DB access in here +/* + // check for marks on the dead side... likely to be a little slow. + for (set::const_iterator it = dead_uncommon_ancestors.begin(); it != dead_uncommon_ancestors.end(); it++) + { + // Is finding out if a file was deleted in a revision really this hard? + // note: only want deletions that would be marked - i.e. not merge nodes. + + set parents; + db.get_revision_parents(*it, parents); + if (parents.size() != 1) // ignore merge nodes as they don't contain marks... + continue; + + roster_t parent_roster; + marking_map parent_markings; + db.get_roster(*(parents.begin()), parent_roster, parent_markings); + + if (!parent_roster.has_node(n)) + continue; + + roster_t rev_roster; + marking_map rev_markings; + db.get_roster(*it, rev_roster, rev_markings); + + if (!rev_roster.has_node(n)) + { + have_mark_in_dead_uncommon_ancestor_set = true; + break; + } + } +*/ + if (have_mark_in_dead_uncommon_ancestor_set) + { + // marks on each side of the merge... conflict! + // at the moment I'm going to create this node. + node_existence_conflict c; + c.nid = n->self; + result.node_existence_conflicts.push_back(c); + create_node_for(n, result.roster); + return; + } + else + { + // no mark on dead side, and mark on live side == live in child + create_node_for(n, result.roster); + return; + } + } + + // If we've reached this point then we've decided not to create the node in the child + + if (true) + { // In this branch we are NOT inserting the node into the new roster as it // has been deleted from the other side of the merge. // In this case, output a warning if there are changes to the file on the // side of the merge where it still exists. - set const & content_marks = safe_get(markings, n->self).file_content; + set const & content_marks = safe_get(live_markings, n->self).file_content; bool found_one_ignored_content = false; for (set::const_iterator it = content_marks.begin(); it != content_marks.end(); it++) { - if (uncommon_ancestors.find(*it) != uncommon_ancestors.end()) + if (live_uncommon_ancestors.find(*it) != live_uncommon_ancestors.end()) { if (!found_one_ignored_content) { file_path fp; - parent_roster.get_name(n->self, fp); + live_parent_roster.get_name(n->self, fp); W(F("Content changes to the file '%s'\n" "will be ignored during this merge as the file has been\n" "removed on one side of the merge. Affected revisions include:") % fp); @@ -1670,9 +1791,10 @@ roster_merge(roster_t const & left_paren MM(right_markings); MM(result); - // First handle lifecycles, by die-die-die merge -- our result will contain - // everything that is alive in both parents, or alive in one and unborn in - // the other, exactly. + // First handle lifecycles. + // We are going to simulate mark-merge. + // See above the mark_merge_existence function for justification. + { parallel::iter i(left_parent.all_nodes(), right_parent.all_nodes()); while (i.next()) @@ -1683,15 +1805,17 @@ roster_merge(roster_t const & left_paren I(false); case parallel::in_left: - insert_if_unborn(i.left_data(), + mark_merge_existence(i.left_data(), left_markings, left_uncommon_ancestors, left_parent, - result.roster); + right_uncommon_ancestors, right_parent, + result); break; case parallel::in_right: - insert_if_unborn(i.right_data(), + mark_merge_existence(i.right_data(), right_markings, right_uncommon_ancestors, right_parent, - result.roster); + left_uncommon_ancestors, left_parent, + result); break; case parallel::in_both: @@ -2082,6 +2206,7 @@ struct base_scalar r.attach_node(nid, file_path_internal(name)); marking_t marking; marking.birth_revision = root_rid; + marking.existence.insert(root_rid); marking.parent_name.insert(root_rid); safe_insert(markings, make_pair(nid, marking)); } @@ -2093,6 +2218,7 @@ struct base_scalar r.attach_node(nid, file_path_internal(name)); marking_t marking; marking.birth_revision = root_rid; + marking.existence.insert(root_rid); marking.parent_name.insert(root_rid); marking.file_content.insert(root_rid); safe_insert(markings, make_pair(nid, marking)); @@ -2497,6 +2623,7 @@ make_dir(roster_t & r, marking_map & mar r.attach_node(nid, file_path_internal(name)); marking_t marking; marking.birth_revision = birth_rid; + marking.existence.insert(birth_rid); marking.parent_name.insert(parent_name_rid); safe_insert(markings, make_pair(nid, marking)); } @@ -2512,6 +2639,7 @@ make_file(roster_t & r, marking_map & ma r.attach_node(nid, file_path_internal(name)); marking_t marking; marking.birth_revision = birth_rid; + marking.existence.insert(birth_rid); marking.parent_name.insert(parent_name_rid); marking.file_content.insert(file_content_rid); safe_insert(markings, make_pair(nid, marking)); ============================================================ --- roster_merge.hh 742f61535acecd23a75df6133af2eda7f5d766e5 +++ roster_merge.hh f90b99f3bc483d29795a5449968d560f53f0a9c8 @@ -52,7 +52,7 @@ struct orphaned_node_conflict }; // A node has been dropped on one side of a merge, and resurrected on the other. -struct node_existance_conflict +struct node_existence_conflict { node_id nid; }; @@ -122,7 +122,7 @@ template <> void dump(orphaned_node_conf template <> void dump(directory_loop_conflict const & conflict, std::string & out); template <> void dump(orphaned_node_conflict const & conflict, std::string & out); -template <> void dump(node_existance_conflict const & conflict, std::string & out); +template <> void dump(node_existence_conflict const & conflict, std::string & out); template <> void dump(multiple_name_conflict const & conflict, std::string & out); template <> void dump(duplicate_name_conflict const & conflict, std::string & out); @@ -147,7 +147,7 @@ struct roster_merge_result std::vector directory_loop_conflicts; std::vector orphaned_node_conflicts; - std::vector node_existance_conflicts; + std::vector node_existence_conflicts; std::vector multiple_name_conflicts; std::vector duplicate_name_conflicts; @@ -183,7 +183,7 @@ struct roster_merge_result content_merge_adaptor & adaptor, bool const basic_io, std::ostream & output) const; - void report_node_existance_conflicts(roster_t const & left, + void report_node_existence_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, bool const basic_io,