# # # rename "tests/resolve_content_conflict" # to "tests/resolve_conflicts_content" # # rename "tests/resolve_duplicate_name_conflict" # to "tests/resolve_conflicts_duplicate_name" # # add_dir "tests/resolve_conflicts_none" # # add_dir "tests/resolve_conflicts_propagate" # # add_file "tests/resolve_conflicts_none/__driver__.lua" # content [2562feb882bb09193c928f52630e105475ac5759] # # add_file "tests/resolve_conflicts_none/conflicts-1" # content [d7b31554e1b38d0e14bf4368b71a54fe834b48dc] # # add_file "tests/resolve_conflicts_none/merge-1" # content [e318ce7db05cb468438a03b2612966e370a014fd] # # add_file "tests/resolve_conflicts_none/update-1" # content [af464efb1d785cb2cf673b32721e1de3c5db91e4] # # add_file "tests/resolve_conflicts_propagate/__driver__.lua" # content [9e81d38b28dd374e664fb360501d60f93eb0f5d3] # # add_file "tests/resolve_conflicts_propagate/conflicts-1" # content [699148173160c1d22938da045b8bbe737f7b518f] # # add_file "tests/resolve_conflicts_propagate/conflicts-2" # content [ab6517a02de54ac509bf4919c85c276f04e4853f] # # add_file "tests/resolve_conflicts_propagate/conflicts-resolved" # content [7aa7c26f75e2ae5baa8b83079d2a46150b036b4a] # # add_file "tests/resolve_conflicts_propagate/propagate-1" # content [b99435dfefbfda234d6fa35b2762eaf767cd1081] # # add_file "tests/resolve_conflicts_propagate/propagate-2" # content [834d66cde71ddbf1df55ac19f19ab2e19c8de118] # # patch "cmd_merging.cc" # from [eef129bfd886938703386e2ea241c7bbc6265993] # to [5dabc088cccbe6078efdd4abb65847fdb6871bf3] # # patch "merge.cc" # from [068d8567d6562b4be8cbe18635b62b77f02c6ae6] # to [0cf37494ece43ac20a57803cce9ae1ade26643db] # # patch "monotone.texi" # from [d4d8166717d7a91bcca0f54ffb7225d35a2caaa4] # to [922b39c25148535ddce1387c5708ad48bf386937] # # patch "roster_merge.cc" # from [44ca37421d7646bb49582f6efc88dcd8da8ffef4] # to [59b94631c0931f3ddc7566259e7734ec71bc71d9] # # patch "roster_merge.hh" # from [70962158e3ca990c80c46074a88cf84edd70a14c] # to [4fa9261ad66726a6d755d50ff54e6751c14a39dc] # # patch "tests/resolve_conflicts_errors/__driver__.lua" # from [41bff950ca73088c3ca483457851be730ae78e60] # to [7b8eb3a9c7b7f5d2305558eaa9c745da0438d49c] # ============================================================ --- tests/resolve_conflicts_none/__driver__.lua 2562feb882bb09193c928f52630e105475ac5759 +++ tests/resolve_conflicts_none/__driver__.lua 2562feb882bb09193c928f52630e105475ac5759 @@ -0,0 +1,37 @@ +-- Demonstrate handling conflict resolutions file with no conflicts + +mtn_setup() + +addfile("foo", "foo") +addfile("bar", "bar\none\ntwo\nthree") +addfile("baz", "baz\naaa\nbbb\nccc") +commit("testbranch", "base") +base = base_revision() + +writefile("foo", "foo\nfirst\nrevision") +writefile("bar", "bar\nzero\none\ntwo\nthree") +writefile("baz", "baz\nAAA\nbbb\nccc") +commit("testbranch", "first") +first = base_revision() + +revert_to(base) + +addfile("foobar", "foobar\nfirst\nrevision") +commit("testbranch", "second") +second = base_revision() + +check(mtn("conflicts", "store"), 0, nil, nil) +check(samefilestd("conflicts-1", "_MTN/conflicts")) + +check(mtn("conflicts", "show_first"), 0, nil, true) +canonicalize("stderr") +check(readfile("stderr") == "mtn: all conflicts resolved\n") + +check(mtn("merge", "--resolve-conflicts"), 0, nil, true) +canonicalize("stderr") +check(samefilestd("merge-1", "stderr")) + +check(mtn("update"), 0, nil, true) +canonicalize("stderr") +check(samefilestd("update-1", "stderr")) +-- end of file ============================================================ --- tests/resolve_conflicts_none/conflicts-1 d7b31554e1b38d0e14bf4368b71a54fe834b48dc +++ tests/resolve_conflicts_none/conflicts-1 d7b31554e1b38d0e14bf4368b71a54fe834b48dc @@ -0,0 +1,2 @@ + left [bcd098b31f9ed42acfb5ab550c973e7d8f7203fd] +right [c28c3c0f5a7f9cde848be91f79d86a6dd63e88ca] ============================================================ --- tests/resolve_conflicts_none/merge-1 e318ce7db05cb468438a03b2612966e370a014fd +++ tests/resolve_conflicts_none/merge-1 e318ce7db05cb468438a03b2612966e370a014fd @@ -0,0 +1,7 @@ +mtn: 2 heads on branch 'testbranch' +mtn: merge 1 / 1: +mtn: calculating best pair of heads to merge next +mtn: [left] bcd098b31f9ed42acfb5ab550c973e7d8f7203fd +mtn: [right] c28c3c0f5a7f9cde848be91f79d86a6dd63e88ca +mtn: [merged] 7f38dd536c4f995a4a7ccd788d2b5be2755805cf +mtn: note: your workspaces have not been updated ============================================================ --- tests/resolve_conflicts_none/update-1 af464efb1d785cb2cf673b32721e1de3c5db91e4 +++ tests/resolve_conflicts_none/update-1 af464efb1d785cb2cf673b32721e1de3c5db91e4 @@ -0,0 +1,8 @@ +mtn: updating along branch 'testbranch' +mtn: selected update target 7f38dd536c4f995a4a7ccd788d2b5be2755805cf +mtn: [left] 9c1b716d160fd291ed7c68f5b6387cfbf8afb6fb +mtn: [right] 7f38dd536c4f995a4a7ccd788d2b5be2755805cf +mtn: modifying bar +mtn: modifying baz +mtn: modifying foo +mtn: updated to base revision 7f38dd536c4f995a4a7ccd788d2b5be2755805cf ============================================================ --- tests/resolve_conflicts_propagate/__driver__.lua 9e81d38b28dd374e664fb360501d60f93eb0f5d3 +++ tests/resolve_conflicts_propagate/__driver__.lua 9e81d38b28dd374e664fb360501d60f93eb0f5d3 @@ -0,0 +1,67 @@ +-- Test/demonstrate handling of a duplicate name conflict when +-- propagating branches. +-- +-- For checkout.sh, the user intent is that there be +-- one file with that name; the contents should be merged. +-- +-- For thermostat.c, there should be two files; +-- thermostat-westinghouse.c and thermostat-honeywell.c + +mtn_setup() + +-- Get a non-empty base revision +addfile("randomfile", "blah blah blah") +commit("testbranch") +base = base_revision() + +-- Abe adds conflict files and branches +addfile("checkout.sh", "checkout.sh abe 1") +addfile("thermostat.c", "thermostat westinghouse") +commit("abe_branch", "abe_1") +abe_1 = base_revision() + +revert_to(base) + +-- Beth adds files and branches +addfile("checkout.sh", "checkout.sh beth 1") +addfile("thermostat.c", "thermostat honeywell") +commit("beth_branch", "beth_1") +beth_1 = base_revision() + +-- Propagate abe_branch to beth_branch + +check(mtn("conflicts", "store", abe_1, beth_1), 0, true, nil) +check(samefilestd("conflicts-1", "_MTN/conflicts")) + +check(mtn("conflicts", "resolve_first_left", "drop"), 0, nil, nil) + +check(mtn("conflicts", "show_first"), 0, nil, true) +check(mtn("conflicts", "resolve_first_right", "user", "checkout.sh"), 0, nil, nil) + +check(mtn("conflicts", "resolve_first_left", "rename", "thermostat-westinghouse.c"), 0, nil, nil) +check(mtn("conflicts", "resolve_first_right", "rename", "thermostat-honeywell.c"), 0, nil, nil) + +check(samefilestd("conflicts-resolved", "_MTN/conflicts")) + +check(mtn("propagate", "--resolve-conflicts", "abe_branch", "beth_branch"), 0, nil, true) +canonicalize("stderr") +check(samefilestd("propagate-1", "stderr")) + +check(mtn("conflicts", "clean"), 0, nil, true) + +-- Propagate beth_branch to abe_branch + +revert_to(abe_1) + +check(mtn("automate", "show_conflicts", beth_1, abe_1), 0, true, nil) +canonicalize("stdout") +check(samefilestd("conflicts-2", "stdout")) + +check(mtn("conflicts", "store", beth_1, abe_1), 0, nil, nil) +check(samefilestd("conflicts-2", "_MTN/conflicts")) + +check(mtn("propagate", "beth_branch", "abe_branch"), 0, nil, true) +canonicalize("stderr") +check(samefilestd("propagate-2", "stderr")) + +-- end of file ============================================================ --- tests/resolve_conflicts_propagate/conflicts-1 699148173160c1d22938da045b8bbe737f7b518f +++ tests/resolve_conflicts_propagate/conflicts-1 699148173160c1d22938da045b8bbe737f7b518f @@ -0,0 +1,19 @@ + left [1337cb1059c4bc3e376b14381b43e9383c654da1] + right [d5f1dd136c86b5bbd5e71b0c3365667e328af492] +ancestor [b3ac8a77cee78263b66800c635441ecb1f259a42] + + conflict duplicate_name + left_type "added file" + left_name "checkout.sh" + left_file_id [61b8d4fb0e5d78be111f691b955d523c782fa92e] + right_type "added file" + right_name "checkout.sh" +right_file_id [dd6805ae36432d6edcbdff6ea578ea981ffa2144] + + conflict duplicate_name + left_type "added file" + left_name "thermostat.c" + left_file_id [4cdcec6fa2f9d5c075d5b80d03c708c8e4801196] + right_type "added file" + right_name "thermostat.c" +right_file_id [7e9f2712c5d3570815f1546772d9119474d32afc] ============================================================ --- tests/resolve_conflicts_propagate/conflicts-2 ab6517a02de54ac509bf4919c85c276f04e4853f +++ tests/resolve_conflicts_propagate/conflicts-2 ab6517a02de54ac509bf4919c85c276f04e4853f @@ -0,0 +1,19 @@ + left [d5f1dd136c86b5bbd5e71b0c3365667e328af492] + right [1337cb1059c4bc3e376b14381b43e9383c654da1] +ancestor [b3ac8a77cee78263b66800c635441ecb1f259a42] + + conflict duplicate_name + left_type "added file" + left_name "checkout.sh" + left_file_id [dd6805ae36432d6edcbdff6ea578ea981ffa2144] + right_type "added file" + right_name "checkout.sh" +right_file_id [61b8d4fb0e5d78be111f691b955d523c782fa92e] + + conflict duplicate_name + left_type "added file" + left_name "thermostat.c" + left_file_id [7e9f2712c5d3570815f1546772d9119474d32afc] + right_type "added file" + right_name "thermostat.c" +right_file_id [4cdcec6fa2f9d5c075d5b80d03c708c8e4801196] ============================================================ --- tests/resolve_conflicts_propagate/conflicts-resolved 7aa7c26f75e2ae5baa8b83079d2a46150b036b4a +++ tests/resolve_conflicts_propagate/conflicts-resolved 7aa7c26f75e2ae5baa8b83079d2a46150b036b4a @@ -0,0 +1,23 @@ + left [1337cb1059c4bc3e376b14381b43e9383c654da1] + right [d5f1dd136c86b5bbd5e71b0c3365667e328af492] +ancestor [b3ac8a77cee78263b66800c635441ecb1f259a42] + + conflict duplicate_name + left_type "added file" + left_name "checkout.sh" + left_file_id [61b8d4fb0e5d78be111f691b955d523c782fa92e] + right_type "added file" + right_name "checkout.sh" + right_file_id [dd6805ae36432d6edcbdff6ea578ea981ffa2144] + resolved_drop_left +resolved_user_right "checkout.sh" + + conflict duplicate_name + left_type "added file" + left_name "thermostat.c" + left_file_id [4cdcec6fa2f9d5c075d5b80d03c708c8e4801196] + right_type "added file" + right_name "thermostat.c" + right_file_id [7e9f2712c5d3570815f1546772d9119474d32afc] + resolved_rename_left "thermostat-westinghouse.c" +resolved_rename_right "thermostat-honeywell.c" ============================================================ --- tests/resolve_conflicts_propagate/propagate-1 b99435dfefbfda234d6fa35b2762eaf767cd1081 +++ tests/resolve_conflicts_propagate/propagate-1 b99435dfefbfda234d6fa35b2762eaf767cd1081 @@ -0,0 +1,8 @@ +mtn: propagating abe_branch -> beth_branch +mtn: [left] 1337cb1059c4bc3e376b14381b43e9383c654da1 +mtn: [right] d5f1dd136c86b5bbd5e71b0c3365667e328af492 +mtn: dropping checkout.sh +mtn: replacing content of checkout.sh with checkout.sh +mtn: renaming thermostat.c to thermostat-westinghouse.c +mtn: renaming thermostat.c to thermostat-honeywell.c +mtn: [merged] a74c964afba9c299c81ec404e5233ad6faffadc1 ============================================================ --- tests/resolve_conflicts_propagate/propagate-2 834d66cde71ddbf1df55ac19f19ab2e19c8de118 +++ tests/resolve_conflicts_propagate/propagate-2 834d66cde71ddbf1df55ac19f19ab2e19c8de118 @@ -0,0 +1,4 @@ +mtn: propagating beth_branch -> abe_branch +mtn: [left] a74c964afba9c299c81ec404e5233ad6faffadc1 +mtn: [right] 1337cb1059c4bc3e376b14381b43e9383c654da1 +mtn: no merge necessary; putting a74c964afba9c299c81ec404e5233ad6faffadc1 in branch 'abe_branch' ============================================================ --- cmd_merging.cc eef129bfd886938703386e2ea241c7bbc6265993 +++ cmd_merging.cc 5dabc088cccbe6078efdd4abb65847fdb6871bf3 @@ -647,7 +647,8 @@ CMD(merge_into_dir, "merge_into_dir", "" bool resolutions_given; - parse_resolve_conflicts_opts (app.opts, left_roster, right_roster, result, resolutions_given); + parse_resolve_conflicts_opts + (app.opts, left_rid, left_roster, right_rid, right_roster, result, resolutions_given); resolve_merge_conflicts(app.lua, left_roster, right_roster, result, dba, resolutions_given); @@ -853,24 +854,6 @@ show_conflicts_core (database & db, bool warn_unsupported, 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); - 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); - 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, - result); - // Note that left and right are in the order specified on the command line. // They are not in lexical order as they are with other merge commands so // they may appear swapped here. The user may have done that deliberately, @@ -889,6 +872,48 @@ show_conflicts_core (database & db, P(F("[right] %s") % r_id); } + if (is_ancestor(db, l_id, r_id)) + { + if (basic_io) + { + basic_io::printer pr; + pr.print_stanza(st); + output.write(pr.buf.data(), pr.buf.size()); + } + else + P(F("%s is an ancestor of %s; no merge is needed.") + % l_id % r_id); + + return; + } + + if (is_ancestor(db, r_id, l_id)) + { + if (basic_io) + { + basic_io::printer pr; + pr.print_stanza(st); + output.write(pr.buf.data(), pr.buf.size()); + } + else + P(F("%s is an ancestor of %s; no merge is needed.") + % r_id % l_id); + + return; + } + + 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); + 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, + result); + if (result.is_clean()) { if (basic_io) ============================================================ --- merge.cc 068d8567d6562b4be8cbe18635b62b77f02c6ae6 +++ merge.cc 0cf37494ece43ac20a57803cce9ae1ade26643db @@ -213,7 +213,7 @@ interactive_merge_and_store(lua_hooks & content_merge_database_adaptor dba(db, left_rid, right_rid, left_marking_map, right_marking_map); - parse_resolve_conflicts_opts (opts, left_roster, right_roster, result, resolutions_given); + parse_resolve_conflicts_opts (opts, left_rid, left_roster, right_rid, right_roster, result, resolutions_given); resolve_merge_conflicts(lua, left_roster, right_roster, result, dba, resolutions_given); ============================================================ --- monotone.texi d4d8166717d7a91bcca0f54ffb7225d35a2caaa4 +++ monotone.texi 922b39c25148535ddce1387c5708ad48bf386937 @@ -8830,6 +8830,9 @@ @section Automation ancestor [ead03530f5fefe50c9010157c42c0ebe18086559] @end verbatim +If there are no conflicts, the ancestor revision is not output, and no +conflict stanzas are output. + Attribute changed in both branches, or dropped in one: @verbatim conflict attribute ============================================================ --- roster_merge.cc 44ca37421d7646bb49582f6efc88dcd8da8ffef4 +++ roster_merge.cc 59b94631c0931f3ddc7566259e7734ec71bc71d9 @@ -2107,7 +2107,7 @@ read_file_content_conflict(basic_io::par pars.esym (syms::ancestor_name); pars.str(); pars.esym (syms::ancestor_file_id); pars.hex(tmp); conflict.ancestor = file_id(decode_hexenc(tmp)); - + pars.esym (syms::left_name); pars.str(left_name); pars.esym(syms::left_file_id); pars.hex(tmp); conflict.left = file_id(decode_hexenc(tmp)); @@ -2268,17 +2268,22 @@ roster_merge_result::read_conflict_file( pars.esym(syms::right); pars.hex(temp); right_rid = revision_id(decode_hexenc(temp)); - pars.esym(syms::ancestor); - pars.hex(temp); - ancestor_rid = revision_id(decode_hexenc(temp)); - // we don't fetch the ancestor roster here, because not every function - // needs it. - db.get_roster(left_rid, left_roster, left_marking); - db.get_roster(right_rid, right_roster, right_marking); + if (pars.symp(syms::ancestor)) + { + pars.sym(); + pars.hex(temp); + ancestor_rid = revision_id(decode_hexenc(temp)); - read_conflict_file_core(pars, left_roster, right_roster, *this, false); + // we don't fetch the ancestor roster here, because not every function + // needs it. + db.get_roster(left_rid, left_roster, left_marking); + db.get_roster(right_rid, right_roster, right_marking); + read_conflict_file_core(pars, left_roster, right_roster, *this, false); + } + // else no conflicts + } // roster_merge_result::read_conflict_file void @@ -2327,7 +2332,9 @@ parse_resolve_conflicts_opts (options co void parse_resolve_conflicts_opts (options const & opts, + revision_id const & left_rid, roster_t const & left_roster, + revision_id const & right_rid, roster_t const & right_roster, roster_merge_result & result, bool & resolutions_given) @@ -2343,16 +2350,23 @@ if (opts.resolve_conflicts_given || opts basic_io::input_source src(dat(), opts.resolve_conflicts_file.as_external()); basic_io::tokenizer tok(src); basic_io::parser pars(tok); + std::string temp; - // Skip left, right, ancestor. FIXME_SUTURE: should check these! But don't - // see how to access them right now. - for (int i = 1; i <= 3; i++) + pars.esym(syms::left); + pars.hex(temp); + N(left_rid == revision_id(decode_hexenc(temp)), F("left revision id does not match conflict file")); + + pars.esym(syms::right); + pars.hex(temp); + N(right_rid == revision_id(decode_hexenc(temp)), F("right revision id does not match conflict file")); + + if (pars.symp(syms::ancestor)) { pars.sym(); - pars.hex(); - } + pars.hex(temp); - read_conflict_file_core (pars, left_roster, right_roster, result, true); + read_conflict_file_core (pars, left_roster, right_roster, result, true); + } } else resolutions_given = false; ============================================================ --- roster_merge.hh 70962158e3ca990c80c46074a88cf84edd70a14c +++ roster_merge.hh 4fa9261ad66726a6d755d50ff54e6751c14a39dc @@ -283,7 +283,9 @@ parse_resolve_conflicts_opts (options co void parse_resolve_conflicts_opts (options const & opts, + revision_id const & left_rid, roster_t const & left_roster, + revision_id const & right_rid, roster_t const & right_roster, roster_merge_result & result, bool & resolutions_given); ============================================================ --- tests/resolve_conflicts_errors/__driver__.lua 41bff950ca73088c3ca483457851be730ae78e60 +++ tests/resolve_conflicts_errors/__driver__.lua 7b8eb3a9c7b7f5d2305558eaa9c745da0438d49c @@ -34,4 +34,6 @@ check(samefilestd("conflicts-attr-store- canonicalize("stderr") check(samefilestd("conflicts-attr-store-2", "stderr")) +-- FIXME: use old conflicts file for new merge + -- end of file