# # # add_file "tests/automate_show_conflicts/expected-directory-loop.stdout" # content [126d670d2ed346aae2cb4be5e41e65e3f1305c3a] # # add_file "tests/automate_show_conflicts/expected-invalid-add.stdout" # content [1c422d6075982cf93aae8ba0fdffcb40c511be97] # # add_file "tests/automate_show_conflicts/expected-invalid-rename.stdout" # content [4c93b3d355de2514c2cd5933df3fde827929c7af] # # add_file "tests/automate_show_conflicts/expected-orphaned-add.stdout" # content [c4ec6b5ddcb02798e9908aa3ec0a5e309cbb0cff] # # add_file "tests/automate_show_conflicts/expected-orphaned-rename.stdout" # content [1d41ad105622b0f1d306717762e99631267e7b49] # # patch "cmd_merging.cc" # from [6a81e714d8098bf221652f4f634dee0da6055035] # to [12f8cc6f507023f1ad3d8e38c75a8eea7d1c9405] # # patch "diff_patch.cc" # from [daeb9be7d8c10d33781b54debd541027618dbfce] # to [5f941aad3eadddd6aa80a428ec8db7734f460dcd] # # patch "diff_patch.hh" # from [2f4ccb77db4094b7de55931464331e22537cf560] # to [8386bfd9dc62a30e7173fca60d27adab6d02167b] # # patch "merge.cc" # from [a2c3037bc94027b942ffbcbded5a3fdfc588f363] # to [3085e923fba02976219da4889f0a71892a91ca74] # # patch "merge.hh" # from [f2aebbc268773f136c78e287ce22207d5fd0bc64] # to [f3613e195ad378f7666d003b959b322abbce97d0] # # patch "roster_merge.cc" # from [66aa7c730cb7780c93615df48d0ec9d617d75e6d] # to [b4908780906e5d6cedcf8a9a45bbf152debf6912] # # patch "roster_merge.hh" # from [34abb44e0b7f62ef5fff648ced4d43984511ccd6] # to [48d9aa743811732826e3f855a5759c1d61416984] # # patch "tests/automate_show_conflicts/expected-missing-root.stdout" # from [d975884f1defedb384b194f9ab1f4e4e0f5f492f] # to [58849682f3a571f8c4b2d16798254f8bdf58ca18] # # patch "tests/conflict_messages/__driver__.lua" # from [4294e488db07d33260abd6ab276fc85d9c2dd508] # to [a681cb85649f5e5ce53bad9b8ef8f2300c22d9d8] # ============================================================ --- tests/automate_show_conflicts/expected-directory-loop.stdout 126d670d2ed346aae2cb4be5e41e65e3f1305c3a +++ tests/automate_show_conflicts/expected-directory-loop.stdout 126d670d2ed346aae2cb4be5e41e65e3f1305c3a @@ -0,0 +1,11 @@ + left [be04cb44902df12f3b36bf0efabba784547ccd34] + right [7cd48d9599eee2a67e8c510112659c0d313fb1df] +ancestor [08ccbb14523a09d342568ce27a1b9f631d42aa9c] + + conflict "directory loop created" + left_type "renamed directory" +ancestor_name "foo" + left_name "bar/foo" + right_type "renamed directory" +ancestor_name "bar" + right_name "foo/bar" ============================================================ --- tests/automate_show_conflicts/expected-invalid-add.stdout 1c422d6075982cf93aae8ba0fdffcb40c511be97 +++ tests/automate_show_conflicts/expected-invalid-add.stdout 1c422d6075982cf93aae8ba0fdffcb40c511be97 @@ -0,0 +1,9 @@ + left [507f1209e78415722129e65633a8d6a9dd6003f1] + right [cdf9a4171d1d386f9ecb83218a11df6c5fa75c6c] +ancestor [36e6935d3fddf349ef829125e8b6d41ea85d1db8] + + conflict "invalid name" + left_type "pivoted root" +ancestor_name "foo" + right_type "added directory" + right_name "foo/_MTN" ============================================================ --- tests/automate_show_conflicts/expected-invalid-rename.stdout 4c93b3d355de2514c2cd5933df3fde827929c7af +++ tests/automate_show_conflicts/expected-invalid-rename.stdout 4c93b3d355de2514c2cd5933df3fde827929c7af @@ -0,0 +1,11 @@ + left [2bf9335ed387a7f1f082b0bc5ecdffa303d8393f] + right [459c32f4c7b4676d47e23aff2bd67c1e2eae5f09] +ancestor [e7f711a68627ccae4aded5907fc80516ea1215fd] + + conflict "invalid name" + left_type "pivoted root" +ancestor_name "foo" + right_type "renamed file" +ancestor_name "bad/_MTN" + right_name "foo/_MTN" +right_file_id [629d9e5d254241abf4b46f108fb53189e314e41d] ============================================================ --- tests/automate_show_conflicts/expected-orphaned-add.stdout c4ec6b5ddcb02798e9908aa3ec0a5e309cbb0cff +++ tests/automate_show_conflicts/expected-orphaned-add.stdout c4ec6b5ddcb02798e9908aa3ec0a5e309cbb0cff @@ -0,0 +1,10 @@ + left [140a1d712e5e7368dc88766144e0975746f27b9a] + right [872259407b5e1445c6b463768243ddaf531bd73a] +ancestor [cce148761e33b0abbaa1c072ee913dcc23d7bfc3] + + conflict "orphaned file" + right_type "deleted directory" +ancestor_name "foo" + left_type "added file" + left_name "foo/baz" + left_file_id [f5122a7f896cb2dd7ecaa84be89c94ab09c15101] ============================================================ --- tests/automate_show_conflicts/expected-orphaned-rename.stdout 1d41ad105622b0f1d306717762e99631267e7b49 +++ tests/automate_show_conflicts/expected-orphaned-rename.stdout 1d41ad105622b0f1d306717762e99631267e7b49 @@ -0,0 +1,11 @@ + left [4ceae2a74d9d0d7341d2cd01a71c9e84eb1fefa7] + right [16a19ace8ec26cd2ed13c7e727a3021e82a2204f] +ancestor [b5f52dbc0dc530adffbdd140a7de5b129cf74f29] + + conflict "orphaned file" + right_type "deleted directory" +ancestor_name "foo" + left_type "renamed file" +ancestor_name "bar" + left_name "foo/baz" + left_file_id [ac4c6d06436632e017bb7d3ea241734e8899f8ce] ============================================================ --- cmd_merging.cc 6a81e714d8098bf221652f4f634dee0da6055035 +++ cmd_merging.cc 12f8cc6f507023f1ad3d8e38c75a8eea7d1c9405 @@ -281,7 +281,7 @@ CMD(update, "update", "", CMD_REF(worksp content_merge_workspace_adaptor wca(db, old_rid, old_roster, left_markings, right_markings, paths); wca.cache_roster(working_rid, working_roster); - resolve_merge_conflicts(app.lua, db, *working_roster, chosen_roster, + resolve_merge_conflicts(app.lua, *working_roster, chosen_roster, result, wca); // Make sure it worked... @@ -630,7 +630,7 @@ CMD(merge_into_dir, "merge_into_dir", "" content_merge_database_adaptor dba(db, left_rid, right_rid, left_marking_map, right_marking_map); - resolve_merge_conflicts(app.lua, db, left_roster, right_roster, + resolve_merge_conflicts(app.lua, left_roster, right_roster, result, dba); { @@ -742,7 +742,7 @@ CMD(merge_into_workspace, "merge_into_wo content_merge_workspace_adaptor wca(db, lca_id, lca.first, *left.second, *right.second, paths); wca.cache_roster(working_rid, working_roster); - resolve_merge_conflicts(app.lua, db, *left.first, *right.first, merge_result, wca); + resolve_merge_conflicts(app.lua, *left.first, *right.first, merge_result, wca); // Make sure it worked... I(merge_result.is_clean()); @@ -810,27 +810,29 @@ namespace { namespace syms { + symbol const ancestor("ancestor"); symbol const left("left"); symbol const right("right"); } } -void +static void show_conflicts_core (database & db, revision_id const & l_id, revision_id const & r_id, bool const basic_io, std::ostream & output) { N(!is_ancestor(db, l_id, r_id), F("%s is an ancestor of %s; no merge is needed.") % l_id % r_id); N(!is_ancestor(db, r_id, l_id), F("%s is an ancestor of %s; no merge is needed.") % r_id % l_id); - roster_t l_roster, r_roster; + shared_ptr l_roster = shared_ptr(new roster_t()); + shared_ptr r_roster = shared_ptr(new roster_t()); marking_map l_marking, r_marking; - db.get_roster(l_id, l_roster, l_marking); - db.get_roster(r_id, r_roster, r_marking); + db.get_roster(l_id, *l_roster, l_marking); + db.get_roster(r_id, *r_roster, r_marking); set l_uncommon_ancestors, r_uncommon_ancestors; db.get_uncommon_ancestors(l_id, r_id, l_uncommon_ancestors, r_uncommon_ancestors); roster_merge_result result; - roster_merge(l_roster, l_marking, l_uncommon_ancestors, - r_roster, r_marking, r_uncommon_ancestors, + roster_merge(*l_roster, l_marking, l_uncommon_ancestors, + *r_roster, r_marking, r_uncommon_ancestors, result); // note that left and right are in the order specified on the command line @@ -838,14 +840,12 @@ show_conflicts_core (database & db, revi // they may appear swapped here. The user may have done that deliberately, // especially via automate, so we don't sort them here. + basic_io::stanza st; + if (basic_io) { - basic_io::stanza st; - basic_io::printer pr; st.push_hex_pair(syms::left, l_id.inner()); st.push_hex_pair(syms::right, r_id.inner()); - pr.print_stanza(st); - output.write(pr.buf.data(), pr.buf.size()); } else { @@ -855,7 +855,13 @@ show_conflicts_core (database & db, revi if (result.is_clean()) { - if (not basic_io) + if (basic_io) + { + basic_io::printer pr; + pr.print_stanza(st); + output.write(pr.buf.data(), pr.buf.size()); + } + else P(F("no conflicts detected")); } else @@ -863,16 +869,28 @@ show_conflicts_core (database & db, revi content_merge_database_adaptor adaptor(db, l_id, r_id, l_marking, r_marking); - result.report_missing_root_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); - result.report_invalid_name_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); - result.report_directory_loop_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); + { + basic_io::printer pr; + st.push_hex_pair(syms::ancestor, adaptor.lca.inner()); + pr.print_stanza(st); + output.write(pr.buf.data(), pr.buf.size()); + } - result.report_orphaned_node_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); - result.report_multiple_name_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); - result.report_duplicate_name_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); + // The basic_io routines in roster_merge.cc access these rosters via + // the adaptor. + adaptor.cache_roster (l_id, l_roster); + adaptor.cache_roster (r_id, r_roster); - result.report_attribute_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); - result.report_file_content_conflicts(db, l_roster, r_roster, adaptor, basic_io, output); + result.report_missing_root_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + result.report_invalid_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + 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_multiple_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + result.report_duplicate_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + + result.report_attribute_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); + result.report_file_content_conflicts(*l_roster, *r_roster, adaptor, basic_io, output); } } @@ -1088,7 +1106,7 @@ CMD(pluck, "pluck", "", CMD_REF(workspac // to_roster is not fetched from the db which does not have temporary nids wca.cache_roster(to_rid, to_roster); - resolve_merge_conflicts(app.lua, db, *working_roster, *to_roster, + resolve_merge_conflicts(app.lua, *working_roster, *to_roster, result, wca); I(result.is_clean()); ============================================================ --- diff_patch.cc daeb9be7d8c10d33781b54debd541027618dbfce +++ diff_patch.cc 5f941aad3eadddd6aa80a428ec8db7734f460dcd @@ -494,7 +494,7 @@ content_merge_database_adaptor::content_ revision_id const & right, marking_map const & left_mm, marking_map const & right_mm) - : db(db), left_mm(left_mm), right_mm(right_mm) + : db(db), left_rid (left), right_rid (right), left_mm(left_mm), right_mm(right_mm) { // FIXME: possibly refactor to run this lazily, as we don't // need to find common ancestors if we're never actually @@ -530,6 +530,13 @@ content_merge_database_adaptor::record_m guard.commit(); } +void +content_merge_database_adaptor::cache_roster(revision_id const & rid, + boost::shared_ptr roster) +{ + safe_insert(rosters, make_pair(rid, roster)); +}; + static void load_and_cache_roster(database & db, revision_id const & rid, map > & rmap, ============================================================ --- diff_patch.hh 2f4ccb77db4094b7de55931464331e22537cf560 +++ diff_patch.hh 8386bfd9dc62a30e7173fca60d27adab6d02167b @@ -64,6 +64,8 @@ content_merge_database_adaptor { database & db; revision_id lca; + revision_id left_rid; + revision_id right_rid; marking_map const & left_mm; marking_map const & right_mm; std::map > rosters; @@ -79,6 +81,9 @@ content_merge_database_adaptor file_data const & right_data, file_data const & merged_data); + void cache_roster(revision_id const & rid, + boost::shared_ptr roster); + void get_ancestral_roster(node_id nid, revision_id & rid, boost::shared_ptr & anc); ============================================================ --- merge.cc a2c3037bc94027b942ffbcbded5a3fdfc588f363 +++ merge.cc 3085e923fba02976219da4889f0a71892a91ca74 @@ -126,7 +126,7 @@ void } void -resolve_merge_conflicts(lua_hooks & lua, database & db, +resolve_merge_conflicts(lua_hooks & lua, roster_t const & left_roster, roster_t const & right_roster, roster_merge_result & result, @@ -143,16 +143,16 @@ resolve_merge_conflicts(lua_hooks & lua, if (result.has_non_content_conflicts()) { - result.report_missing_root_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); - result.report_invalid_name_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); - result.report_directory_loop_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); + result.report_missing_root_conflicts(left_roster, right_roster, adaptor, false, std::cout); + result.report_invalid_name_conflicts(left_roster, right_roster, adaptor, false, std::cout); + result.report_directory_loop_conflicts(left_roster, right_roster, adaptor, false, std::cout); - result.report_orphaned_node_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); - result.report_multiple_name_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); - result.report_duplicate_name_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); + result.report_orphaned_node_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); - result.report_attribute_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); - result.report_file_content_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); + result.report_attribute_conflicts(left_roster, right_roster, adaptor, false, std::cout); + result.report_file_content_conflicts(left_roster, right_roster, adaptor, false, std::cout); } else if (result.has_content_conflicts()) { @@ -168,7 +168,7 @@ resolve_merge_conflicts(lua_hooks & lua, if (remaining > 0) { P(F("%d content conflicts require user intervention") % remaining); - result.report_file_content_conflicts(db, left_roster, right_roster, adaptor, false, std::cout); + result.report_file_content_conflicts(left_roster, right_roster, adaptor, false, std::cout); try_to_merge_files(lua, left_roster, right_roster, result, adaptor, user_merge); @@ -202,7 +202,7 @@ interactive_merge_and_store(lua_hooks & content_merge_database_adaptor dba(db, left_rid, right_rid, left_marking_map, right_marking_map); - resolve_merge_conflicts(lua, db, left_roster, right_roster, + resolve_merge_conflicts(lua, left_roster, right_roster, result, dba); // write new files into the db ============================================================ --- merge.hh f2aebbc268773f136c78e287ce22207d5fd0bc64 +++ merge.hh f3613e195ad378f7666d003b959b322abbce97d0 @@ -25,7 +25,7 @@ void struct content_merge_adaptor; void -resolve_merge_conflicts(lua_hooks & lua, database & db, +resolve_merge_conflicts(lua_hooks & lua, roster_t const & left_roster, roster_t const & right_roster, roster_merge_result & result, ============================================================ --- roster_merge.cc 66aa7c730cb7780c93615df48d0ec9d617d75e6d +++ roster_merge.cc b4908780906e5d6cedcf8a9a45bbf152debf6912 @@ -183,24 +183,156 @@ namespace { namespace syms { + symbol const ancestor_name("ancestor_name"); symbol const conflict("conflict"); - symbol const left_id("left_id"); + symbol const left_file_id("left_file_id"); symbol const left_name("left_name"); symbol const left_type("left_type"); - symbol const name("name"); - symbol const right_id("right_id"); + symbol const right_file_id("right_file_id"); symbol const right_name("right_name"); - symbol const right_rev_id("right_rev_id"); symbol const right_type("right_type"); } } +static void +put_added_conflict_left (basic_io::stanza & st, + content_merge_adaptor & adaptor, + node_id const nid) +{ + // We access the roster via the adaptor, to be sure we use the left + // roster; avoids typos in long parameter lists. + + // If we get a workspace adaptor here someday, we should add the required + // access functions to content_merge_adaptor. + + content_merge_database_adaptor & db_adaptor (dynamic_cast(adaptor)); + boost::shared_ptr roster(db_adaptor.rosters[db_adaptor.left_rid]); + file_path name; + + roster->get_name (nid, name); + + if (file_type == get_type (*roster, nid)) + { + file_id fid; + db_adaptor.db.get_file_content (db_adaptor.left_rid, nid, fid); + st.push_str_pair(syms::left_type, "added file"); + st.push_str_pair(syms::left_name, name.as_external()); + st.push_hex_pair(syms::left_file_id, fid.inner()); + } + else + { + st.push_str_pair(syms::left_type, "added directory"); + st.push_str_pair(syms::left_name, name.as_external()); + } +} + +static void +put_added_conflict_right (basic_io::stanza & st, + content_merge_adaptor & adaptor, + node_id const nid) +{ + content_merge_database_adaptor & db_adaptor (dynamic_cast(adaptor)); + boost::shared_ptr roster(db_adaptor.rosters[db_adaptor.right_rid]); + I(0 != roster); + + file_path name; + + roster->get_name (nid, name); + + if (file_type == get_type (*roster, nid)) + { + file_id fid; + db_adaptor.db.get_file_content (db_adaptor.right_rid, nid, fid); + + st.push_str_pair(syms::right_type, "added file"); + st.push_str_pair(syms::right_name, name.as_external()); + st.push_hex_pair(syms::right_file_id, fid.inner()); + } + else + { + st.push_str_pair(syms::right_type, "added directory"); + st.push_str_pair(syms::right_name, name.as_external()); + } +} + +static void +put_rename_conflict_left (basic_io::stanza & st, + content_merge_adaptor & adaptor, + node_id const nid, + file_path const & ancestor_name) +{ + content_merge_database_adaptor & db_adaptor (dynamic_cast(adaptor)); + boost::shared_ptr roster(db_adaptor.rosters[db_adaptor.left_rid]); + file_path name; + + roster->get_name (nid, name); + + if (file_type == get_type (*roster, nid)) + { + file_id fid; + db_adaptor.db.get_file_content (db_adaptor.left_rid, nid, fid); + st.push_str_pair(syms::left_type, "renamed file"); + st.push_str_pair(syms::ancestor_name, ancestor_name.as_external()); + st.push_str_pair(syms::left_name, name.as_external()); + st.push_hex_pair(syms::left_file_id, fid.inner()); + } + else + { + st.push_str_pair(syms::left_type, "renamed directory"); + st.push_str_pair(syms::ancestor_name, ancestor_name.as_external()); + st.push_str_pair(syms::left_name, name.as_external()); + } +} + +static void +put_rename_conflict_right (basic_io::stanza & st, + content_merge_adaptor & adaptor, + node_id const nid, + file_path const & ancestor_name) +{ + content_merge_database_adaptor & db_adaptor (dynamic_cast(adaptor)); + boost::shared_ptr roster(db_adaptor.rosters[db_adaptor.right_rid]); + I(0 != roster); + + file_path name; + + roster->get_name (nid, name); + + if (file_type == get_type (*roster, nid)) + { + file_id fid; + db_adaptor.db.get_file_content (db_adaptor.right_rid, nid, fid); + st.push_str_pair(syms::right_type, "renamed file"); + st.push_str_pair(syms::ancestor_name, ancestor_name.as_external()); + st.push_str_pair(syms::right_name, name.as_external()); + st.push_hex_pair(syms::right_file_id, fid.inner()); + } + else + { + st.push_str_pair(syms::right_type, "renamed directory"); + st.push_str_pair(syms::ancestor_name, ancestor_name.as_external()); + st.push_str_pair(syms::right_name, name.as_external()); + } +} + +static void +put_stanza (basic_io::stanza & st, + std::ostream & output) +{ + // We have to declare the printer here, rather than more globally, + // because adaptor.get_ancestral_roster uses a basic_io::printer + // internally, and there can only be one active at a time. + basic_io::printer pr; + output << "\n"; + pr.print_stanza(st); + output.write(pr.buf.data(), pr.buf.size()); +} + void -roster_merge_result::report_missing_root_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_missing_root_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const { MM(left_roster); @@ -233,25 +365,26 @@ roster_merge_result::report_missing_root basic_io::stanza st; if (basic_io) - { - st.push_str_pair(syms::conflict, "missing root"); - st.push_str_pair(syms::name, left_lca_name.as_external()); - } + st.push_str_pair(syms::conflict, "missing root"); else - { - P(F("conflict: missing root directory")); - } + P(F("conflict: missing root directory")); if (left_root != left_lca_root && right_root == right_lca_root) { if (basic_io) - st.push_str_pair(syms::left_type, "pivoted root"); + { + st.push_str_pair(syms::left_type, "pivoted root"); + st.push_str_pair(syms::ancestor_name, left_lca_name.as_external()); + } else P(F("directory '%s' pivoted to root on the left") % left_lca_name); if (!right_roster.has_node(left_root)) if (basic_io) - st.push_str_pair(syms::right_type, "deleted directory"); + { + st.push_str_pair(syms::right_type, "deleted directory"); + st.push_str_pair(syms::ancestor_name, left_lca_name.as_external()); + } else P(F("directory '%s' deleted on the right") % left_lca_name); } @@ -277,18 +410,12 @@ roster_merge_result::report_missing_root // in these cases don't report anything about pivot_root if (basic_io) - { - basic_io::printer pr; - output << "\n"; - pr.print_stanza(st); - output.write(pr.buf.data(), pr.buf.size()); - } + put_stanza (st, output); } } void -roster_merge_result::report_invalid_name_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_invalid_name_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -307,6 +434,7 @@ roster_merge_result::report_invalid_name shared_ptr lca_roster, parent_lca_roster; revision_id lca_rid, parent_lca_rid; file_path lca_name, lca_parent_name; + basic_io::stanza st; adaptor.get_ancestral_roster(conflict.nid, lca_rid, lca_roster); lca_roster->get_name(conflict.nid, lca_name); @@ -315,24 +443,39 @@ roster_merge_result::report_invalid_name adaptor.get_ancestral_roster(conflict.parent_name.first, parent_lca_rid, parent_lca_roster); - P(F("conflict: invalid name _MTN in root directory")); + if (basic_io) + st.push_str_pair(syms::conflict, "invalid name"); + else + P(F("conflict: invalid name _MTN in root directory")); if (left_roster.root()->self == conflict.parent_name.first) { - P(F("'%s' pivoted to root on the left") - % lca_parent_name); + if (basic_io) + { + st.push_str_pair(syms::left_type, "pivoted root"); + st.push_str_pair(syms::ancestor_name, lca_parent_name.as_external()); + } + else + P(F("'%s' pivoted to root on the left") + % lca_parent_name); file_path right_name; right_roster.get_name(conflict.nid, right_name); if (parent_lca_roster->has_node(conflict.nid)) { - P(F("'%s' renamed to '%s' on the right") - % lca_name % right_name); + if (basic_io) + put_rename_conflict_right (st, adaptor, conflict.nid, lca_name); + else + P(F("'%s' renamed to '%s' on the right") + % lca_name % right_name); } else { - P(F("'%s' added in revision %s on the right") - % right_name % lca_rid); + if (basic_io) + put_added_conflict_right (st, adaptor, conflict.nid); + else + P(F("'%s' added in revision %s on the right") + % right_name % lca_rid); } } else if (right_roster.root()->self == conflict.parent_name.first) @@ -355,12 +498,14 @@ roster_merge_result::report_invalid_name } else I(false); + + if (basic_io) + put_stanza(st, output); } } void -roster_merge_result::report_directory_loop_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_directory_loop_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -387,34 +532,52 @@ roster_merge_result::report_directory_lo shared_ptr lca_roster; revision_id lca_rid; file_path lca_name, lca_parent_name; + basic_io::stanza st; adaptor.get_ancestral_roster(conflict.nid, lca_rid, lca_roster); lca_roster->get_name(conflict.nid, lca_name); lca_roster->get_name(conflict.parent_name.first, lca_parent_name); - P(F("conflict: directory loop created")); + if (basic_io) + st.push_str_pair(syms::conflict, "directory loop created"); + else + P(F("conflict: directory loop created")); if (left_name != lca_name) - P(F("'%s' renamed to '%s' on the left") - % lca_name % left_name); + if (basic_io) + put_rename_conflict_left (st, adaptor, conflict.nid, lca_name); + else + P(F("'%s' renamed to '%s' on the left") + % lca_name % left_name); if (right_name != lca_name) - P(F("'%s' renamed to '%s' on the right") - % lca_name % right_name); + if (basic_io) + put_rename_conflict_right (st, adaptor, conflict.nid, lca_name); + else + P(F("'%s' renamed to '%s' on the right") + % lca_name % right_name); if (left_parent_name != lca_parent_name) - P(F("'%s' renamed to '%s' on the left") - % lca_parent_name % left_parent_name); + if (basic_io) + put_rename_conflict_left (st, adaptor, conflict.parent_name.first, lca_parent_name); + else + P(F("'%s' renamed to '%s' on the left") + % lca_parent_name % left_parent_name); if (right_parent_name != lca_parent_name) - P(F("'%s' renamed to '%s' on the right") - % lca_parent_name % right_parent_name); + if (basic_io) + put_rename_conflict_right (st, adaptor, conflict.parent_name.first, lca_parent_name); + else + P(F("'%s' renamed to '%s' on the right") + % lca_parent_name % right_parent_name); + + if (basic_io) + put_stanza(st, output); } } void -roster_merge_result::report_orphaned_node_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_orphaned_node_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -445,21 +608,18 @@ roster_merge_result::report_orphaned_nod basic_io::stanza st; if (type == file_type) - P(F("conflict: orphaned file '%s' from revision %s") - % lca_name % lca_rid); + if (basic_io) + st.push_str_pair(syms::conflict, "orphaned file"); + else + P(F("conflict: orphaned file '%s' from revision %s") + % lca_name % lca_rid); else { if (basic_io) - { - st.push_str_pair(syms::conflict, "orphaned directory"); - st.push_str_pair(syms::name, lca_name.as_external()); - st.push_hex_pair(syms::right_rev_id, lca_rid.inner()); - } + st.push_str_pair(syms::conflict, "orphaned directory"); else - { - P(F("conflict: orphaned directory '%s' from revision %s") - % lca_name % lca_rid); - } + P(F("conflict: orphaned directory '%s' from revision %s") + % lca_name % lca_rid); } if (left_roster.has_node(conflict.parent_name.first) && @@ -470,35 +630,39 @@ roster_merge_result::report_orphaned_nod left_roster.get_name(conflict.parent_name.first, parent_name); if (basic_io) - st.push_str_pair(syms::right_type, "deleted directory"); + { + st.push_str_pair(syms::right_type, "deleted directory"); + st.push_str_pair(syms::ancestor_name, parent_name.as_external()); + } else P(F("parent directory '%s' was deleted on the right") % parent_name); if (parent_lca_roster->has_node(conflict.nid)) { - if (type == file_type) - P(F("file '%s' was renamed from '%s' on the left") - % orphan_name % lca_name); + if (basic_io) + put_rename_conflict_left (st, adaptor, conflict.nid, lca_name); else - if (basic_io) - { - st.push_str_pair(syms::left_type, "renamed directory"); - st.push_str_pair(syms::left_name, orphan_name.as_external()); - } + if (type == file_type) + P(F("file '%s' was renamed from '%s' on the left") + % orphan_name % lca_name); else P(F("directory '%s' was renamed from '%s' on the left") % orphan_name % lca_name); } else { - if (type == file_type) - P(F("file '%s' was added on the left") - % orphan_name); + if (basic_io) + put_added_conflict_left (st, adaptor, conflict.nid); else - P(F("directory '%s' was added on the left") - % orphan_name); - + { + if (type == file_type) + P(F("file '%s' was added on the left") + % orphan_name); + else + P(F("directory '%s' was added on the left") + % orphan_name); + } } } else if (!left_roster.has_node(conflict.parent_name.first) && @@ -534,18 +698,12 @@ roster_merge_result::report_orphaned_nod I(false); if (basic_io) - { - basic_io::printer pr; - output << "\n"; - pr.print_stanza(st); - output.write(pr.buf.data(), pr.buf.size()); - } + put_stanza (st, output); } } void -roster_merge_result::report_multiple_name_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_multiple_name_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -575,21 +733,32 @@ roster_merge_result::report_multiple_nam node_type type = get_type(*lca_roster, conflict.nid); - if (type == file_type) - P(F("conflict: multiple names for file '%s' from revision %s") - % lca_name % lca_rid); + basic_io::stanza st; + + if (basic_io) + { + st.push_str_pair(syms::conflict, "multiple names"); + put_rename_conflict_left (st, adaptor, conflict.nid, lca_name); + put_rename_conflict_right (st, adaptor, conflict.nid, lca_name); + } else - P(F("conflict: multiple names for directory '%s' from revision %s") - % lca_name % lca_rid); + { + if (type == file_type) + P(F("conflict: multiple names for file '%s' from revision %s") + % lca_name % lca_rid); + else + P(F("conflict: multiple names for directory '%s' from revision %s") + % lca_name % lca_rid); - P(F("renamed to '%s' on the left") % left_name); - P(F("renamed to '%s' on the right") % right_name); + P(F("renamed to '%s' on the left") % left_name); + P(F("renamed to '%s' on the right") % right_name); + } + } } void -roster_merge_result::report_duplicate_name_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_duplicate_name_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool const basic_io, @@ -627,51 +796,35 @@ roster_merge_result::report_duplicate_na basic_io::stanza st; if (basic_io) - { - st.push_str_pair(syms::conflict, "duplicate name"); - st.push_str_pair(syms::name, left_name.as_external()); - } + st.push_str_pair(syms::conflict, "duplicate name"); else - { - P(F("conflict: duplicate name '%s'") % left_name); - } + P(F("conflict: duplicate name '%s'") % left_name); + node_type left_type = get_type(left_roster, left_nid); node_type right_type = get_type(right_roster, right_nid); if (!left_lca_roster->has_node(right_nid) && !right_lca_roster->has_node(left_nid)) { - if (left_type == file_type) - if (basic_io) - { - file_id fid; - db.get_file_content (left_lca_rid, left_nid, fid); - st.push_str_pair(syms::left_type, "added file"); - st.push_hex_pair(syms::left_id, fid.inner()); - } - else - P(F("added as a new file on the left")); + if (basic_io) + put_added_conflict_left (st, adaptor, left_nid); else - if (basic_io) - st.push_str_pair(syms::left_type, "added directory"); - else - P(F("added as a new directory on the left")); + { + if (left_type == file_type) + P(F("added as a new file on the left")); + else + P(F("added as a new directory on the left")); + } - if (right_type == file_type) - if (basic_io) - { - file_id fid; - db.get_file_content (right_lca_rid, right_nid, fid); - st.push_str_pair(syms::right_type, "added file"); - st.push_hex_pair(syms::right_id, fid.inner()); - } - else - P(F("added as a new file on the right")); + if (basic_io) + put_added_conflict_right (st, adaptor, right_nid); else - if (basic_io) - st.push_str_pair(syms::right_type, "added directory"); - else - P(F("added as a new directory on the right")); + { + if (right_type == file_type) + P(F("added as a new file on the right")); + else + P(F("added as a new directory on the right")); + } } else if (!left_lca_roster->has_node(right_nid) && right_lca_roster->has_node(left_nid)) @@ -679,33 +832,23 @@ roster_merge_result::report_duplicate_na file_path left_lca_name; left_lca_roster->get_name(left_nid, left_lca_name); - if (left_type == file_type) - if (basic_io) - { - st.push_str_pair(syms::left_type, "renamed file"); - st.push_str_pair(syms::left_name, left_lca_name.as_external()); - } - else - P(F("renamed from file '%s' on the left") % left_lca_name); + if (basic_io) + put_rename_conflict_left (st, adaptor, left_nid, left_lca_name); else - if (basic_io) - { - st.push_str_pair(syms::left_type, "renamed directory"); - st.push_str_pair(syms::left_name, left_lca_name.as_external()); - } + if (left_type == file_type) + P(F("renamed from file '%s' on the left") % left_lca_name); else P(F("renamed from directory '%s' on the left") % left_lca_name); - if (right_type == file_type) - if (basic_io) - st.push_str_pair(syms::right_type, "added file"); - else - P(F("added as a new file on the right")); + if (basic_io) + put_added_conflict_right (st, adaptor, right_nid); else - if (basic_io) - st.push_str_pair(syms::right_type, "added directory"); - else - P(F("added as a new directory on the right")); + { + if (right_type == file_type) + P(F("added as a new file on the right")); + else + P(F("added as a new directory on the right")); + } } else if (left_lca_roster->has_node(right_nid) && !right_lca_roster->has_node(left_nid)) @@ -713,33 +856,25 @@ roster_merge_result::report_duplicate_na file_path right_lca_name; right_lca_roster->get_name(right_nid, right_lca_name); - if (left_type == file_type) - if (basic_io) - st.push_str_pair(syms::left_type, "added file"); - else - P(F("added as a new file on the left")); + if (basic_io) + put_added_conflict_left (st, adaptor, left_nid); else - if (basic_io) - st.push_str_pair(syms::right_type, "added directory"); - else - P(F("added as a new directory on the left")); + { + if (left_type == file_type) + P(F("added as a new file on the left")); + else + P(F("added as a new directory on the left")); + } - if (right_type == file_type) - if (basic_io) - { - st.push_str_pair(syms::right_type, "renamed file"); - st.push_str_pair(syms::right_name, right_lca_name.as_external()); - } - else - P(F("renamed from file '%s' on the right") % right_lca_name); + if (basic_io) + put_rename_conflict_right (st, adaptor, right_nid, right_lca_name); else - if (basic_io) - { - st.push_str_pair(syms::right_type, "renamed directory"); - st.push_str_pair(syms::right_name, right_lca_name.as_external()); - } - else - P(F("renamed from directory '%s' on the right") % right_lca_name); + { + if (right_type == file_type) + P(F("renamed from file '%s' on the right") % right_lca_name); + else + P(F("renamed from directory '%s' on the right") % right_lca_name); + } } else if (left_lca_roster->has_node(right_nid) && right_lca_roster->has_node(left_nid)) @@ -748,59 +883,36 @@ roster_merge_result::report_duplicate_na left_lca_roster->get_name(left_nid, left_lca_name); right_lca_roster->get_name(right_nid, right_lca_name); - if (left_type == file_type) - if (basic_io) - { - st.push_str_pair(syms::left_type, "renamed file"); - st.push_str_pair(syms::left_name, left_lca_name.as_external()); - } - else - P(F("renamed from file '%s' on the left") % left_lca_name); + if (basic_io) + put_rename_conflict_left (st, adaptor, left_nid, left_lca_name); else - if (basic_io) - { - st.push_str_pair(syms::left_type, "renamed directory"); - st.push_str_pair(syms::left_name, left_lca_name.as_external()); - } - else - P(F("renamed from directory '%s' on the left") % left_lca_name); + { + if (left_type == file_type) + P(F("renamed from file '%s' on the left") % left_lca_name); + else + P(F("renamed from directory '%s' on the left") % left_lca_name); + } - if (right_type == file_type) - if (basic_io) - { - st.push_str_pair(syms::right_type, "renamed file"); - st.push_str_pair(syms::right_name, right_lca_name.as_external()); - } - else - P(F("renamed from file '%s' on the right") % right_lca_name); + if (basic_io) + put_rename_conflict_right (st, adaptor, right_nid, right_lca_name); else - if (basic_io) - { - st.push_str_pair(syms::right_type, "renamed directory"); - st.push_str_pair(syms::right_name, right_lca_name.as_external()); - } - else - P(F("renamed from directory '%s' on the right") % right_lca_name); + { + if (right_type == file_type) + P(F("renamed from file '%s' on the right") % right_lca_name); + else + P(F("renamed from directory '%s' on the right") % right_lca_name); + } } else I(false); if (basic_io) - { - // We have to declare the printer here, rather than more globally, - // because adaptor.get_ancestral_roster uses a basic_io::printer - // internally, and there can only be one active at a time. - basic_io::printer pr; - output << "\n"; - pr.print_stanza(st); - output.write(pr.buf.data(), pr.buf.size()); - } + put_stanza(st, output); } } void -roster_merge_result::report_attribute_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_attribute_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, @@ -904,8 +1016,7 @@ void } void -roster_merge_result::report_file_content_conflicts(database & db, - roster_t const & left_roster, +roster_merge_result::report_file_content_conflicts(roster_t const & left_roster, roster_t const & right_roster, content_merge_adaptor & adaptor, bool basic_io, ============================================================ --- roster_merge.hh 34abb44e0b7f62ef5fff648ced4d43984511ccd6 +++ roster_merge.hh 48d9aa743811732826e3f855a5759c1d61416984 @@ -154,55 +154,47 @@ struct roster_merge_result bool has_non_content_conflicts() const; void log_conflicts() const; - void report_missing_root_conflicts(database & db, - roster_t const & left, + void report_missing_root_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_invalid_name_conflicts(database & db, - roster_t const & left, + void report_invalid_name_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_directory_loop_conflicts(database & db, - roster_t const & left, + void report_directory_loop_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_orphaned_node_conflicts(database & db, - roster_t const & left, + void report_orphaned_node_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_multiple_name_conflicts(database & db, - roster_t const & left, + void report_multiple_name_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_duplicate_name_conflicts(database & db, - roster_t const & left, + void report_duplicate_name_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, bool const basic_io, std::ostream & output) const; - void report_attribute_conflicts(database & db, - roster_t const & left, + void report_attribute_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; - void report_file_content_conflicts(database & db, - roster_t const & left, + void report_file_content_conflicts(roster_t const & left, roster_t const & right, content_merge_adaptor & adaptor, - bool basic_io, + bool const basic_io, std::ostream & output) const; void clear(); ============================================================ --- tests/automate_show_conflicts/expected-missing-root.stdout d975884f1defedb384b194f9ab1f4e4e0f5f492f +++ tests/automate_show_conflicts/expected-missing-root.stdout 58849682f3a571f8c4b2d16798254f8bdf58ca18 @@ -1,14 +1,16 @@ - left [532ab5011ea9e64aa212d4ea52363b1b8133d5ba] -right [b94a03a922c2c281a88d8988db64e76a32edb6a1] + left [532ab5011ea9e64aa212d4ea52363b1b8133d5ba] + right [b94a03a922c2c281a88d8988db64e76a32edb6a1] +ancestor [ead03530f5fefe50c9010157c42c0ebe18086559] - conflict "missing root" - name "foo" - left_type "pivoted root" -right_type "deleted directory" + conflict "missing root" + left_type "pivoted root" +ancestor_name "foo" + right_type "deleted directory" +ancestor_name "foo" + conflict "orphaned directory" + right_type "deleted directory" +ancestor_name "" + left_type "renamed directory" +ancestor_name "" + left_name "bar" - conflict "orphaned directory" - name "" -right_rev_id [ead03530f5fefe50c9010157c42c0ebe18086559] - right_type "deleted directory" - left_type "renamed directory" - left_name "bar" ============================================================ --- tests/conflict_messages/__driver__.lua 4294e488db07d33260abd6ab276fc85d9c2dd508 +++ tests/conflict_messages/__driver__.lua a681cb85649f5e5ce53bad9b8ef8f2300c22d9d8 @@ -36,7 +36,7 @@ message = "conflict: missing root direct message = "conflict: missing root directory" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -85,7 +85,7 @@ message = "conflict: invalid name" message = "conflict: invalid name" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -133,7 +133,7 @@ message = "conflict: invalid name" message = "conflict: invalid name" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -182,7 +182,7 @@ message = "conflict: directory loop" check(mtn("mv", "bar", "foo"), 0, false, false) message = "conflict: directory loop" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -234,7 +234,7 @@ message = "conflict: orphaned file" message = "conflict: orphaned file" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -285,7 +285,7 @@ message = "conflict: orphaned file" message = "conflict: orphaned file" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -331,7 +331,7 @@ message = "conflict: multiple names" message = "conflict: multiple names" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -381,7 +381,7 @@ message = "conflict: duplicate name" message = "conflict: duplicate name" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -428,7 +428,7 @@ message = "conflict: duplicate name" message = "conflict: duplicate name" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -474,7 +474,7 @@ message = "conflict: duplicate name" message = "conflict: duplicate name" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -524,7 +524,7 @@ message = "conflict: multiple values for message = "conflict: multiple values for attribute" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -576,7 +576,7 @@ message = "conflict: multiple values for message = "conflict: multiple values for attribute" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -628,7 +628,7 @@ message = "conflict: content conflict on message = "conflict: content conflict on file 'foo'" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) check(not qgrep("conflict: content conflict on file 'bar'", "stderr")) check(not qgrep("conflict: content conflict on file 'baz'", "stderr")) @@ -678,7 +678,7 @@ message = "conflict: content conflict on message = "conflict: content conflict on file" -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message, "stderr")) commit(branch .. "-propagate") @@ -737,7 +737,7 @@ message2 = "conflict: duplicate name" -- this doesn't result in a duplicate name conflict because the multiple name -- conflict prevents foo from being attached in the result roster -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message1, "stderr")) check(not qgrep(message2, "stderr")) @@ -800,7 +800,7 @@ message2 = "conflict: orphaned" -- this doesn't result in a directory loop conflict because the multiple name -- conflict prevents foo from being attached in the result roster -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message1, "stderr")) check(not qgrep(message2, "stderr")) @@ -865,7 +865,7 @@ message2 = "conflict: directory loop" -- this doesn't result in a directory loop conflict because the multiple name -- conflict prevents foo from being attached in the result roster -check(mtn("update", "--debug"), 1, false, true) +check(mtn("update"), 1, false, true) check(qgrep(message1, "stderr")) check(not qgrep(message2, "stderr")) @@ -940,7 +940,7 @@ message3 = "conflict: multiple names" message2 = "conflict: duplicate name" message3 = "conflict: multiple names" -check(indir(dir2, mtn("update", "--debug")), 1, false, true) +check(indir(dir2, mtn("update")), 1, false, true) check(qgrep(message1, "stderr")) check(qgrep(message2, "stderr")) check(qgrep(message3, "stderr")) @@ -1000,7 +1000,7 @@ message2 = "conflict: duplicate name" message1 = "conflict: missing root directory" message2 = "conflict: duplicate name" --- check(mtn("update", "--debug"), 1, false, true) +-- check(mtn("update"), 1, false, true) -- check(qgrep(message1, "stderr")) -- check(qgrep(message2, "stderr"))