#
#
# add_dir "tests/automate_show_conflicts"
#
# add_dir "tests/resolve_duplicate_name_conflict"
#
# add_file "cmd_merging.hh"
# content [8fdbae1fdc78bf36f86efb904d8e068684743ce6]
#
# add_file "tests/automate_show_conflicts/__driver__.lua"
# content [1702dae2d13bb2b959fb7c1a9b9b669ae0d70c05]
#
# add_file "tests/automate_show_conflicts/expected-1.stdout"
# content [f1d2d2f924e986ac86fdf7b36c94bcdf32beec15]
#
# add_file "tests/automate_show_conflicts/expected-2.stdout"
# content [e242ed3bffccdf271b7fbaf34ed72d089537b42f]
#
# add_file "tests/resolve_duplicate_name_conflict/__driver__.lua"
# content [d876aec0f26b52b9f8016aa8580d5fcfd4fae293]
#
# patch "automate.cc"
# from [be3c9252738e13b5a931b2cb063c30e7565ef203]
# to [ef2ff038b98144c19686fc37f49222a4c5e9152e]
#
# patch "cmd_automate.cc"
# from [fdad3e113ea4f077db08c1e789c1f2bf39abe2c0]
# to [aa644eac27e978e1f51203db320206272a98f8a1]
#
# patch "cmd_merging.cc"
# from [9a1dacae8931c700a6f7acd0b71c50082f663117]
# to [fb2f2037a464226d7e99feb91ea119b6f90c76b2]
#
# patch "merge.cc"
# from [5110775ef0a938c14246f95abd33a6b97118baba]
# to [3085e923fba02976219da4889f0a71892a91ca74]
#
# patch "monotone.texi"
# from [5fab7072154208ae616663e4579cef644987b6bd]
# to [5179a73b50747a8bf47b842250caf0917bfe341b]
#
# patch "roster_merge.cc"
# from [d565f9299ca85d77bd1d7f2a29196d7161f0ea08]
# to [13c48d6355d0a7521acaeb841383395a3740119a]
#
# patch "roster_merge.hh"
# from [fb803cd207c21b77a69115552a6820664b607ba5]
# to [528467e96d5195c9639b3c3b48799391c3fb2d7f]
#
============================================================
--- cmd_merging.hh 8fdbae1fdc78bf36f86efb904d8e068684743ce6
+++ cmd_merging.hh 8fdbae1fdc78bf36f86efb904d8e068684743ce6
@@ -0,0 +1,21 @@
+#ifndef __CMD_MERGING_HH__
+#define __CMD_MERGING__HH__
+
+// Copyright (C) 2008 Stephen Leake
+//
+// This program is made available under the GNU GPL version 2.0 or
+// greater. See the accompanying file COPYING for details.
+//
+// This program is distributed WITHOUT ANY WARRANTY; without even the
+// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE.
+
+// Functions in cmd_merging.cc that are shared between command-line
+// and automate interfaces
+
+// If basic_io, display results in basic_io stanzas. Otherwise use
+// command-line format.
+void
+show_conflicts_core (database & db, revision_id const & l_id, revision_id const & r_id, bool const basic_io, std::ostream & output);
+
+#endif
============================================================
--- tests/automate_show_conflicts/__driver__.lua 1702dae2d13bb2b959fb7c1a9b9b669ae0d70c05
+++ tests/automate_show_conflicts/__driver__.lua 1702dae2d13bb2b959fb7c1a9b9b669ae0d70c05
@@ -0,0 +1,39 @@
+-- Test 'automate show_conflicts'
+
+mtn_setup()
+
+check(get("expected-1.stdout"))
+check(get("expected-2.stdout"))
+
+-- Get a non-empty base revision, then create conflicts
+addfile("randomfile", "blah blah blah")
+commit()
+base = base_revision()
+
+-- Abe adds conflict files
+addfile("checkout.sh", "checkout.sh abe 1")
+addfile("thermostat.c", "thermostat westinghouse")
+commit()
+abe_1 = base_revision()
+
+revert_to(base)
+
+-- Beth adds conflict files
+addfile("checkout.sh", "checkout.sh beth 1")
+addfile("thermostat.c", "thermostat honeywell")
+commit()
+beth_1 = base_revision()
+
+check(mtn("automate", "show_conflicts"), 0, true, false)
+canonicalize("stdout")
+check(readfile("expected-1.stdout") == readfile("stdout"))
+
+-- Now specify revisions, in an order that reverses left/right from
+-- the previous, to show the arguments are used.
+
+check(mtn("automate", "show_conflicts", abe_1, beth_1), 0, true, false)
+canonicalize("stdout")
+check(readfile("expected-2.stdout") == readfile("stdout"))
+
+
+-- end of file
============================================================
--- tests/automate_show_conflicts/expected-1.stdout f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
+++ tests/automate_show_conflicts/expected-1.stdout f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
@@ -0,0 +1 @@
+foo
============================================================
--- tests/automate_show_conflicts/expected-2.stdout e242ed3bffccdf271b7fbaf34ed72d089537b42f
+++ tests/automate_show_conflicts/expected-2.stdout e242ed3bffccdf271b7fbaf34ed72d089537b42f
@@ -0,0 +1 @@
+bar
============================================================
--- tests/resolve_duplicate_name_conflict/__driver__.lua d876aec0f26b52b9f8016aa8580d5fcfd4fae293
+++ tests/resolve_duplicate_name_conflict/__driver__.lua d876aec0f26b52b9f8016aa8580d5fcfd4fae293
@@ -0,0 +1,52 @@
+-- Test/demonstrate handling of a duplicate name conflict; Abe and
+-- Beth add files with the same names.
+--
+-- 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()
+base = base_revision()
+
+-- Abe adds conflict files
+addfile("checkout.sh", "checkout.sh abe 1")
+addfile("thermostat.c", "thermostat westinghouse")
+commit()
+abe_1 = base_revision()
+
+revert_to(base)
+
+-- Beth adds files, and attempts to merge
+addfile("checkout.sh", "checkout.sh beth 1")
+addfile("thermostat.c", "thermostat honeywell")
+commit()
+beth_1 = base_revision()
+
+-- This fails due to duplicate name conflicts
+check(mtn("merge"), 1, false, false)
+
+-- Beth fixes the conflicts.
+--
+-- For checkout.sh, she retrieves Abe's version to merge with hers,
+-- using 'automate get_file_of'. This requires knowing the revision id
+-- of Abe's commit, which we get from 'automate show_conflicts'.
+--
+-- For thermostat.c, she renames her version, letting Abe rename his.
+
+check (mtn("automate show_conflicts"), 0, false, false)
+
+check (mtn ("drop", "checkout.sh"), 0, false, false)
+check (mtn ("rename", "thermostat.c", "thermostat-honeywell.c"), 0, false, false)
+commit()
+
+-- This succeeds
+check(mtn("merge"), 0, false, false)
+
+-- end of file
+
============================================================
--- automate.cc be3c9252738e13b5a931b2cb063c30e7565ef203
+++ automate.cc ef2ff038b98144c19686fc37f49222a4c5e9152e
@@ -1,5 +1,5 @@
+// Copyright (C) 2007 - 2008 Stephen Leake
// Copyright (C) 2004, 2007 Nathaniel Smith
-// Copyright (C) 2007 - 2008 Stephen Leake
//
// This program is made available under the GNU GPL version 2.0 or
// greater. See the accompanying file COPYING for details.
@@ -25,6 +25,7 @@
#include "basic_io.hh"
#include "cert.hh"
#include "cmd.hh"
+#include "cmd_merging.hh"
#include "commands.hh"
#include "constants.hh"
#include "inodeprint.hh"
@@ -1249,7 +1250,7 @@ CMD_AUTOMATE(get_current_revision, N_("[
excluded, join_words(execid));
rev.check_sane();
N(rev.is_nontrivial(), F("no changes to commit"));
-
+
calculate_ident(rev, ident);
write_revision(rev, dat);
@@ -2251,6 +2252,54 @@ CMD_AUTOMATE(drop_db_variables, N_("DOMA
}
}
+// Name: show_conflicts
+// Arguments:
+// Two revision ids (optional, determined from the workspace if not given; there must be exactly two heads)
+// Added in: 7.1
+// Purpose: Prints the conflicts between two revisions, to aid in merging them.
+//
+// Output format: see monotone.texi
+//
+// Error conditions:
+//
+// If the revision IDs are unknown or invalid prints an error message to
+// stderr and exits with status 1.
+//
+// If revision ids are not given, and the current workspace does not have
+// two heads, prints an error message to stderr and exits with status 1.
+//
+CMD_AUTOMATE(show_conflicts, N_("[REVID, REVID]"),
+ N_("Shows the conflicts between two revisions (default two heads of current workspace)"),
+ "",
+ options::opts::none)
+{
+ database db(app);
+ project_t project(db);
+ revision_id l_id, r_id;
+
+ if (args.size() == 0)
+ {
+ // get ids from heads
+ set heads;
+ project.get_branch_heads(app.opts.branchname, heads,
+ app.opts.ignore_suspend_certs);
+
+ N(heads.size() == 2, F("branch '%s' has %d heads; must be exactly 2 for show_conflicts") % app.opts.branchname % heads.size());
+ l_id = *heads.begin();
+ r_id = *heads.end();
+ }
+ else if (args.size() == 2)
+ {
+ // get ids from args
+ complete(app.opts, app.lua, project, idx(args,0)(), l_id);
+ complete(app.opts, app.lua, project, idx(args,1)(), r_id);
+ }
+ else
+ throw usage(execid);
+
+ show_conflicts_core(db, l_id, r_id, true, output);
+}
+
// Local Variables:
// mode: C++
// fill-column: 76
============================================================
--- cmd_automate.cc fdad3e113ea4f077db08c1e789c1f2bf39abe2c0
+++ cmd_automate.cc aa644eac27e978e1f51203db320206272a98f8a1
@@ -63,7 +63,7 @@ namespace commands {
}
}
-static string const interface_version = "7.0";
+static string const interface_version = "7.1";
// Major or minor number only increments once for each monotone release;
// check the most recent release before incrementing this.
============================================================
--- cmd_merging.cc 9a1dacae8931c700a6f7acd0b71c50082f663117
+++ cmd_merging.cc fb2f2037a464226d7e99feb91ea119b6f90c76b2
@@ -1,3 +1,4 @@
+// Copyright (C) 2008 Stephen Leake
// Copyright (C) 2002 Graydon Hoare
//
// This program is made available under the GNU GPL version 2.0 or
@@ -12,7 +13,9 @@
#include
#include
+#include "basic_io.hh"
#include "cmd.hh"
+#include "cmd_merging.hh"
#include "diff_patch.hh"
#include "merge.hh"
#include "restrictions.hh"
@@ -818,6 +821,22 @@ CMD(show_conflicts, "show_conflicts", ""
revision_id l_id, r_id;
complete(app.opts, app.lua, project, idx(args,0)(), l_id);
complete(app.opts, app.lua, project, idx(args,1)(), r_id);
+
+ show_conflicts_core(db, l_id, r_id, false, std::cout);
+}
+
+namespace
+{
+ namespace syms
+ {
+ symbol const left("left");
+ symbol const right("right");
+ }
+}
+
+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),
@@ -827,41 +846,52 @@ CMD(show_conflicts, "show_conflicts", ""
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);
+ 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. perhaps we should sort left and right
- // before using them?
+ // 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,
+ // especially via automate, so we don't sort them here.
- P(F("[left] %s") % l_id);
- P(F("[right] %s") % r_id);
+ 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
+ {
+ P(F("[left] %s") % l_id);
+ P(F("[right] %s") % r_id);
+ }
if (result.is_clean())
{
- P(F("no conflicts detected"));
+ if (not basic_io)
+ P(F("no conflicts detected"));
}
else
{
content_merge_database_adaptor adaptor(db, l_id, r_id,
l_marking, r_marking);
- result.report_missing_root_conflicts(l_roster, r_roster, adaptor);
- result.report_invalid_name_conflicts(l_roster, r_roster, adaptor);
- result.report_directory_loop_conflicts(l_roster, r_roster, adaptor);
+ 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);
- result.report_multiple_name_conflicts(l_roster, r_roster, adaptor);
- result.report_duplicate_name_conflicts(l_roster, r_roster, adaptor);
+ 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);
- result.report_file_content_conflicts(l_roster, r_roster, adaptor);
+ 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);
}
}
============================================================
--- merge.cc 5110775ef0a938c14246f95abd33a6b97118baba
+++ merge.cc 3085e923fba02976219da4889f0a71892a91ca74
@@ -1,4 +1,5 @@
-// Copyright (C) 2005 Nathaniel Smith
+// Copyright (C) 2008 Stephen Leake
+// Copyright (C) 2008 Nathaniel Smith
//
// This program is made available under the GNU GPL version 2.0 or
// greater. See the accompanying file COPYING for details.
@@ -8,6 +9,7 @@
// PURPOSE.
#include "base.hh"
+#include
#include
#include
@@ -141,16 +143,16 @@ resolve_merge_conflicts(lua_hooks & lua,
if (result.has_non_content_conflicts())
{
- result.report_missing_root_conflicts(left_roster, right_roster, adaptor);
- result.report_invalid_name_conflicts(left_roster, right_roster, adaptor);
- result.report_directory_loop_conflicts(left_roster, right_roster, adaptor);
+ 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(left_roster, right_roster, adaptor);
- result.report_multiple_name_conflicts(left_roster, right_roster, adaptor);
- result.report_duplicate_name_conflicts(left_roster, right_roster, adaptor);
+ 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(left_roster, right_roster, adaptor);
- result.report_file_content_conflicts(left_roster, right_roster, adaptor);
+ 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())
{
@@ -166,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(left_roster, right_roster, adaptor);
+ 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);
============================================================
--- monotone.texi 5fab7072154208ae616663e4579cef644987b6bd
+++ monotone.texi 5179a73b50747a8bf47b842250caf0917bfe341b
@@ -8524,6 +8524,63 @@ @section Automation
@end table
address@hidden mtn automate show_conflicts
+
address@hidden @strong
address@hidden Arguments:
+
+Optional left and right revision ids. They default to the two heads of
+the current workspace.
+
address@hidden Added in:
+
+7.1
+
address@hidden Purpose:
+
+Show all conflicts between two revisions.
+
address@hidden Sample output:
address@hidden
address@hidden
+ left "1337cb1059c4bc3e376b14381b43e9383c654da1"
+ right "d5f1dd136c86b5bbd5e71b0c3365667e328af492"
+
+ conflict "duplicate name"
+ name "checkout.sh"
+ left_id "FIXME:left id"
+ left_type file
+ right_id "FIXME:right id"
+right_type file
+
+FIXME: show all conflicts
+
address@hidden group
address@hidden smallexample
+
address@hidden Output format:
+
+First the revision ids of the left and right revisions are printed in
+one basic_io stanza.
+
+Then each conflict is listed in a basic_io stanza. Stanzas are
+separated by blank lines.
+
+Each conflict stanza starts with a @code{conflict} line, and contains
+up to FIXME: lines. The order of the lines is not important, and may
+change in future revisions, except that the first line will always be
address@hidden
+
address@hidden Error conditions:
+
+If the revision IDs are gvien, but either is unknown or
+invalid, prints an error message to stderr and exits with status 1.
+
+If revision ids are not given, and the current workspace does not have
+two heads, prints an error message to stderr and exits with status 1.
+
address@hidden table
+
@end ftable
@page
============================================================
--- roster_merge.cc d565f9299ca85d77bd1d7f2a29196d7161f0ea08
+++ roster_merge.cc 13c48d6355d0a7521acaeb841383395a3740119a
@@ -1,3 +1,4 @@
+// Copyright (C) 2008 Stephen Leake
// Copyright (C) 2005 Nathaniel Smith
//
// This program is made available under the GNU GPL version 2.0 or
@@ -12,6 +13,7 @@
#include
+#include "basic_io.hh"
#include "vocab.hh"
#include "roster_merge.hh"
#include "parallel_iter.hh"
@@ -177,10 +179,27 @@ namespace
}
}
+namespace
+{
+ namespace syms
+ {
+ symbol const conflict("conflict");
+ symbol const name("name");
+ symbol const left_id("left_id");
+ symbol const right_id("right_id");
+ symbol const left_type("left_type");
+ symbol const right_type("right_type");
+ symbol const left_name("left_name");
+ symbol const right_name("right_name");
+ }
+}
+
void
roster_merge_result::report_missing_root_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -243,7 +262,9 @@ roster_merge_result::report_invalid_name
void
roster_merge_result::report_invalid_name_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -312,7 +333,9 @@ roster_merge_result::report_directory_lo
void
roster_merge_result::report_directory_loop_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -363,7 +386,9 @@ roster_merge_result::report_orphaned_nod
void
roster_merge_result::report_orphaned_node_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -461,7 +486,9 @@ roster_merge_result::report_multiple_nam
void
roster_merge_result::report_multiple_name_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -502,7 +529,9 @@ roster_merge_result::report_duplicate_na
void
roster_merge_result::report_duplicate_name_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -514,6 +543,9 @@ roster_merge_result::report_duplicate_na
node_id left_nid, right_nid;
+ basic_io::stanza st;
+ basic_io::printer pr;
+
left_nid = conflict.left_nid;
right_nid = conflict.right_nid;
@@ -533,8 +565,17 @@ roster_merge_result::report_duplicate_na
adaptor.get_ancestral_roster(left_nid, left_lca_rid, left_lca_roster);
adaptor.get_ancestral_roster(right_nid, right_lca_rid, right_lca_roster);
- P(F("conflict: duplicate name '%s'") % left_name);
-
+ if (basic_io)
+ {
+ st.push_str_pair(syms::conflict, "duplicate_name");
+ st.push_str_pair(syms::name, left_name.as_external());
+ st.push_hex_pair(syms::left_id, left_lca_rid.inner()); // FIXME: get file revision, not ancestor revision?
+ st.push_hex_pair(syms::right_id, right_lca_rid.inner());
+ }
+ else
+ {
+ 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);
@@ -542,14 +583,26 @@ roster_merge_result::report_duplicate_na
!right_lca_roster->has_node(left_nid))
{
if (left_type == file_type)
- P(F("added as a new file on the left"));
+ if (basic_io)
+ st.push_str_pair(syms::left_type, "added file");
+ else
+ P(F("added as a new file on the left"));
else
- P(F("added as a new directory on the left"));
+ if (basic_io)
+ st.push_str_pair(syms::left_type, "added directory");
+ else
+ P(F("added as a new directory on the left"));
if (right_type == file_type)
- P(F("added as a new file on the right"));
+ if (basic_io)
+ st.push_str_pair(syms::right_type, "added file");
+ else
+ P(F("added as a new file on the right"));
else
- P(F("added as a new directory on the right"));
+ if (basic_io)
+ st.push_str_pair(syms::right_type, "added directory");
+ 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))
@@ -558,14 +611,32 @@ roster_merge_result::report_duplicate_na
left_lca_roster->get_name(left_nid, left_lca_name);
if (left_type == file_type)
- P(F("renamed from file '%s' on the left") % left_lca_name);
+ 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);
else
- P(F("renamed from directory '%s' on the left") % left_lca_name);
+ 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 (right_type == file_type)
- P(F("added as a new file on the right"));
+ if (basic_io)
+ st.push_str_pair(syms::right_type, "added file");
+ else
+ P(F("added as a new file on the right"));
else
- P(F("added as a new directory on the right"));
+ if (basic_io)
+ st.push_str_pair(syms::right_type, "added directory");
+ 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))
@@ -574,14 +645,32 @@ roster_merge_result::report_duplicate_na
right_lca_roster->get_name(right_nid, right_lca_name);
if (left_type == file_type)
- P(F("added as a new file on the left"));
+ if (basic_io)
+ st.push_str_pair(syms::left_type, "added file");
+ else
+ P(F("added as a new file on the left"));
else
- P(F("added as a new directory on the left"));
+ if (basic_io)
+ st.push_str_pair(syms::right_type, "added directory");
+ else
+ P(F("added as a new directory on the left"));
if (right_type == file_type)
- P(F("renamed from file '%s' on the right") % right_lca_name);
+ 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);
else
- P(F("renamed from directory '%s' on the right") % right_lca_name);
+ 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);
}
else if (left_lca_roster->has_node(right_nid) &&
right_lca_roster->has_node(left_nid))
@@ -591,24 +680,53 @@ roster_merge_result::report_duplicate_na
right_lca_roster->get_name(right_nid, right_lca_name);
if (left_type == file_type)
- P(F("renamed from file '%s' on the left") % left_lca_name);
+ 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);
else
- P(F("renamed from directory '%s' on the left") % left_lca_name);
+ 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 (right_type == file_type)
- P(F("renamed from file '%s' on the right") % right_lca_name);
+ 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);
else
- P(F("renamed from directory '%s' on the right") % right_lca_name);
+ 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);
}
else
I(false);
+
+ if (basic_io)
+ output.write(pr.buf.data(), pr.buf.size());
}
}
void
roster_merge_result::report_attribute_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
@@ -710,7 +828,9 @@ roster_merge_result::report_file_content
void
roster_merge_result::report_file_content_conflicts(roster_t const & left_roster,
roster_t const & right_roster,
- content_merge_adaptor & adaptor) const
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const
{
MM(left_roster);
MM(right_roster);
============================================================
--- roster_merge.hh fb803cd207c21b77a69115552a6820664b607ba5
+++ roster_merge.hh 528467e96d5195c9639b3c3b48799391c3fb2d7f
@@ -155,30 +155,46 @@ struct roster_merge_result
void report_missing_root_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_invalid_name_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_directory_loop_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_orphaned_node_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_multiple_name_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_duplicate_name_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_attribute_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void report_file_content_conflicts(roster_t const & left,
roster_t const & right,
- content_merge_adaptor & adaptor) const;
+ content_merge_adaptor & adaptor,
+ bool basic_io,
+ std::ostream & output) const;
void clear();
};