#
# patch "ChangeLog"
# from [1218b5bd0ee80fb7f90b1aa1e64a29d7ae6f3c77]
# to [1486b1d2adf0958d9f9b7f79e1a6083d49d852da]
#
# patch "change_set.cc"
# from [acf229c928d5a98c12d51fae465303b2ab9a1454]
# to [dca63f6f968128d67da90a44a1c2bb09e0d9c0ed]
#
# patch "change_set.hh"
# from [d530354cb57477ef5e3b9e961346861c61508cba]
# to [f8e06d50c8b82b973b2de70137f70171dac6120d]
#
# patch "commands.cc"
# from [e3432b9b21954ad6f3628a6afbff3e6328e3cea1]
# to [5c0ba1f50fee0b05d49e0f705875b563d03efcfd]
#
# patch "pcdv.cc"
# from [98142af12f61b816c38685f185fe3eaae0447dca]
# to [7bb131b0c0268cae51eadc9d22a11d7ec6d7ad11]
#
# patch "pcdv.hh"
# from [f650089a46f20388d4d5976d906389af52c23934]
# to [42ce2c9da4c7a1e77b1200885b6d3fc579592c69]
#
========================================================================
--- ChangeLog 1218b5bd0ee80fb7f90b1aa1e64a29d7ae6f3c77
+++ ChangeLog 1486b1d2adf0958d9f9b7f79e1a6083d49d852da
@@ -1,3 +1,12 @@
+2005-08-16 Timothy Brownawell
+
+ * change_set.{cc,hh}: Replace tree merger with the one in pcdv.{cc,hh}.
+ DOES NOT pass ./testsuite (13 failures, 1 unexpected pass)
+ REMOVE disjoint_merge_test() (no longer applicable in
+ this form, and the same functionality is checked in tests/ .)
+ * commands.cc: New merger takes different arguments; update calls.
+ * pcdv.{cc,hh}: Handle sutures better.
+
2005-08-10 Timothy Brownawell
* pcdv.{cc,hh} (tree merger): Teach it about file suturing.
========================================================================
--- change_set.cc acf229c928d5a98c12d51fae465303b2ab9a1454
+++ change_set.cc dca63f6f968128d67da90a44a1c2bb09e0d9c0ed
@@ -30,6 +30,10 @@
#include "smap.hh"
#include "path_component.hh"
+#include "pcdv.hh"
+#include "database.hh"
+#include "revision.hh"
+
// our analyses in this file happen on one of two families of
// related structures: a path_analysis or a directory_map.
//
@@ -1633,7 +1637,7 @@
// begin stuff related to merging
-
+/*
static void
extend_renumbering_via_added_files(path_analysis const & a,
path_analysis const & b,
@@ -1676,7 +1680,7 @@
}
}
}
-
+*/
static bool
find_item(tid t, path_state const & ps,
path_item & item)
@@ -1687,7 +1691,7 @@
item = path_state_item(i);
return true;
}
-
+/*
static bool
find_items(tid t, path_analysis const & pa,
path_item & first, path_item & second)
@@ -2034,12 +2038,24 @@
}
}
+*/
+struct itempaths
+{
+ file_path anc;
+ file_path left;
+ file_path right;
+ file_path merged;
+ itempaths(file_path const & a, file_path const & l,
+ file_path const & r, file_path const & m):
+ anc(a), left(l), right(r), merged(m)
+ {}
+ itempaths()
+ {}
+};
+
static void
-merge_deltas(file_path const & anc_path,
- file_path const & left_path,
- file_path const & right_path,
- file_path const & path_in_merged,
+merge_deltas(itempaths const & paths,
std::map & merge_finalists,
file_id const & anc,
file_id const & left,
@@ -2047,56 +2063,55 @@
file_id & finalist,
merge_provider & merger)
{
- std::map::const_iterator i = merge_finalists.find(path_in_merged);
+ std::map::const_iterator
+ i = merge_finalists.find(paths.merged);
if (i != merge_finalists.end())
{
L(F("reusing merge resolution '%s' : '%s' -> '%s'\n")
- % path_in_merged % anc % i->second);
+ % paths.merged % anc % i->second);
finalist = i->second;
}
else
{
if (null_id(anc))
{
- N(merger.try_to_merge_files(left_path, right_path, path_in_merged, left, right, finalist),
+ N(merger.try_to_merge_files(paths.left, paths.right, paths.merged,
+ left, right, finalist),
F("merge of '%s' : '%s' vs. '%s' (no common ancestor) failed")
- % path_in_merged % left % right);
+ % paths.merged % left % right);
}
else
{
- N(merger.try_to_merge_files(anc_path, left_path, right_path, path_in_merged,
+ N(merger.try_to_merge_files(paths.anc, paths.left,
+ paths.right, paths.merged,
anc, left, right, finalist),
F("merge of '%s' : '%s' -> '%s' vs '%s' failed")
- % path_in_merged % anc % left % right);
+ % paths.merged % anc % left % right);
}
L(F("merge of '%s' : '%s' -> '%s' vs '%s' resolved to '%s'\n")
- % path_in_merged % anc % left % right % finalist);
+ % paths.merged % anc % left % right % finalist);
- merge_finalists.insert(std::make_pair(path_in_merged, finalist));
+ merge_finalists.insert(std::make_pair(paths.merged, finalist));
}
}
static void
project_missing_deltas(change_set const & a,
change_set const & b,
- path_analysis const & a_analysis,
- path_analysis const & b_analysis,
- path_analysis const & a_merged_analysis,
+ std::vector const & pathset,
change_set & b_merged,
merge_provider & merger,
std::map & merge_finalists)
{
- directory_map a_second_map, b_first_map, a_merged_first_map;
- build_directory_map(a_analysis.second, a_second_map);
- build_directory_map(b_analysis.first, b_first_map);
- build_directory_map(a_merged_analysis.first, a_merged_first_map);
+ std::map pathsmap;
+ for (std::vector::const_iterator i = pathset.begin();
+ i != pathset.end(); ++i)
+ pathsmap.insert(make_pair((*i).left, *i));
- for (change_set::delta_map::const_iterator i = a.deltas.begin();
+ for (change_set::delta_map::const_iterator i = a.deltas.begin();
i != a.deltas.end(); ++i)
{
- file_path path_in_merged, path_in_anc, path_in_b_second;
-
// we have a fork like this:
//
//
@@ -2105,31 +2120,18 @@
// +--> [b2]
//
// and we have a delta applied to a file in a2. we want to
- // figure out what to call this delta's path in b2. this means
- // reconstructing it in a1==b1, then reconstructing it *again*
- // in b2.
+ // figure out what to call this delta's path in b2.
- // first work out what the path in a.first == b.first is
- reconstruct_path(delta_entry_path(i), a_second_map,
- a_analysis.first, path_in_anc);
+ itempaths const & paths = pathsmap[delta_entry_path(i)];
- // first work out what the path in b.second is
- reconstruct_path(path_in_anc, b_first_map,
- b_analysis.second, path_in_b_second);
-
- // then work out what the path in merged is
- reconstruct_path(delta_entry_path(i), a_merged_first_map,
- a_merged_analysis.second, path_in_merged);
-
// now check to see if there was a delta on the b.second name in b
- change_set::delta_map::const_iterator j = b.deltas.find(path_in_b_second);
+ change_set::delta_map::const_iterator j = b.deltas.find(paths.right);
// if the file was deleted in b, we don't want to copy this delta.
- if (b.rearrangement.has_deleted_file(path_in_anc)
- && !(a.rearrangement.has_added_file(path_in_merged)))
+ if (paths.right == file_path() && paths.merged == file_path())
{
L(F("skipping delta '%s'->'%s' on deleted file '%s'\n")
- % delta_entry_src(i) % delta_entry_dst(i) % path_in_anc);
+ % delta_entry_src(i) % delta_entry_dst(i) % paths.anc);
continue;
}
@@ -2137,9 +2139,11 @@
{
// if no deltas in b, copy ours over using the merged name
L(F("merge is copying delta '%s' : '%s' -> '%s'\n")
- % path_in_merged % delta_entry_src(i) % delta_entry_dst(i));
- I(b.deltas.find(path_in_merged) == b.deltas.end());
- b_merged.apply_delta(path_in_merged, delta_entry_src(i), delta_entry_dst(i));
+ % paths.merged % delta_entry_src(i) % delta_entry_dst(i));
+ I(b.deltas.find(paths.merged) == b.deltas.end());
+ b_merged.apply_delta(paths.merged,
+ delta_entry_src(i),
+ delta_entry_dst(i));
}
else
{
@@ -2161,10 +2165,12 @@
// 'a' change_set included a delta []->[...], ie file added. We want to
// follow this fork so it gets added to the b_merged changeset
L(F("propagating new file addition delta on '%s' : '%s' -> '%s'\n")
- % path_in_merged
+ % paths.merged
% delta_entry_src(j)
% delta_entry_dst(i));
- b_merged.apply_delta(path_in_merged, delta_entry_src(i), delta_entry_dst(i));
+ b_merged.apply_delta(paths.merged,
+ delta_entry_src(i),
+ delta_entry_dst(i));
}
else if (null_id(delta_entry_src(j)))
{
@@ -2173,7 +2179,7 @@
// to add it to the b_merged changeset, since any delta in 'a' will be
// ignored (as 'b' includes deletions).
L(F("skipping new file addition delta on '%s' : '' -> '%s'\n")
- % path_in_merged
+ % paths.merged
% delta_entry_dst(j));
}
}
@@ -2181,122 +2187,323 @@
{
// ... absorb identical deltas
L(F("skipping common delta '%s' : '%s' -> '%s'\n")
- % path_in_merged % delta_entry_src(i) % delta_entry_dst(i));
+ % paths.merged % delta_entry_src(i) % delta_entry_dst(i));
}
else if (delta_entry_src(i) == delta_entry_dst(i))
{
L(F("skipping neutral delta on '%s' : %s -> %s\n")
- % delta_entry_path(i)
- % delta_entry_src(i)
- % delta_entry_dst(i));
+ % paths.left
+ % delta_entry_src(i)
+ % delta_entry_dst(i));
}
else if (delta_entry_src(j) == delta_entry_dst(j))
{
L(F("propagating unperturbed delta on '%s' : '%s' -> '%s'\n")
- % delta_entry_path(i)
- % delta_entry_src(i)
- % delta_entry_dst(i));
- b_merged.apply_delta(path_in_merged, delta_entry_dst(j), delta_entry_dst(i));
+ % paths.left
+ % delta_entry_src(i)
+ % delta_entry_dst(i));
+ b_merged.apply_delta(paths.merged,
+ delta_entry_dst(j),
+ delta_entry_dst(i));
}
else
{
// ... or resolve conflict
L(F("merging delta '%s' : '%s' -> '%s' vs. '%s'\n")
- % path_in_merged % delta_entry_src(i) % delta_entry_dst(i) % delta_entry_dst(j));
+ % paths.merged % delta_entry_src(i)
+ % delta_entry_dst(i) % delta_entry_dst(j));
file_id finalist;
- merge_deltas(path_in_anc,
- delta_entry_path(i), // left_path
- delta_entry_path(j), // right_path
- path_in_merged,
+ merge_deltas(paths,
merge_finalists,
delta_entry_src(i), // anc
delta_entry_dst(i), // left
delta_entry_dst(j), // right
finalist, merger);
L(F("resolved merge to '%s' : '%s' -> '%s'\n")
- % path_in_merged % delta_entry_src(i) % finalist);
+ % paths.merged % delta_entry_src(i) % finalist);
// if the conflict resolved to something other than the
// existing post-state of b, add a new entry to the deltas of
// b finishing the job.
if (! (finalist == delta_entry_dst(j)))
- b_merged.apply_delta(path_in_merged, delta_entry_dst(j), finalist);
+ b_merged.apply_delta(paths.merged,
+ delta_entry_dst(j),
+ finalist);
}
}
}
}
+void
+process_filetree_history(revision_id const & anc,
+ revision_id const & left,
+ revision_id const & right,
+ change_set::path_rearrangement
+ const & right_extra_changes,
+ std::vector & paths,
+ change_set::path_rearrangement & lm_re,
+ change_set::path_rearrangement & rm_re,
+ app_state & app)
+{
+ typedef std::multimap::iterator gi;
+ typedef std::map > >::iterator ai;
+ std::multimap graph, rgraph;
+ app.db.get_revision_ancestry(graph);
+ for (gi i = graph.begin(); i != graph.end(); ++i)
+ rgraph.insert(std::make_pair(i->second, i->first));
+ // rev -> {# of parents remaining, children}
+ std::map > > about;
+ std::deque todo, roots;
+ todo.push_back(left);
+ todo.push_back(right);
+ todo.push_back(anc);
+ about.insert(make_pair(left, make_pair(0, std::set())));
+ about.insert(make_pair(right, make_pair(0, std::set())));
+ about.insert(make_pair(anc, make_pair(0, std::set())));
+ while(todo.size())
+ {
+ revision_id c(todo.back());
+ todo.pop_back();
+ gi pb = rgraph.lower_bound(c);
+ gi pe = rgraph.upper_bound(c);
+ int n = 0;
+ for (gi i = pb; i != pe; ++i)
+ {
+ if (null_id(i->second))
+ continue;
+ std::set s;
+ s.insert(c);
+ std::pair r;
+ r = about.insert(make_pair(i->second, make_pair(0, s)));
+ if (r.second)
+ todo.push_back(i->second);
+ else
+ r.first->second.second.insert(c);
+ ++n;
+ }
+ ai me = about.find(c);
+ I(me != about.end());
+ me->second.first = n;
+ if (n == 0)
+ roots.push_back(c);
+ }
+ std::map trees;
+ tree_state emptytree(tree_state::new_tree());
+ while(roots.size())
+ {
+ revision_set rs;
+ app.db.get_revision(roots.front(), rs);
+ std::vector treevec;
+ std::vector revec;
+ for (edge_map::const_iterator i = rs.edges.begin();
+ i != rs.edges.end(); ++i)
+ {
+ tree_state from(emptytree);
+ if (edge_old_revision(i) == revision_id())
+ from = emptytree;
+ else
+ {
+ std::map::iterator
+ j = trees.find(edge_old_revision(i));
+ I(j != trees.end());
+ from = j->second;
+ }
+ treevec.push_back(from);
+ revec.push_back(edge_changes(i).rearrangement);
+ }
+ tree_state newtree(tree_state::merge_with_rearrangement(treevec, revec,
+ roots.front().inner()()));
+ trees.insert(make_pair(roots.front(), newtree));
+
+ ai i = about.find(roots.front());
+ I(i != about.end());
+ std::set const & cs(i->second.second);
+ for (std::set::const_iterator j = cs.begin();
+ j != cs.end(); j++)
+ {
+ ai k = about.find(*j);
+ I(k != about.end());
+ if (--(k->second.first) == 0)
+ roots.push_back(*j);
+ }
+ roots.pop_front();
+ }
+
+ std::map::const_iterator
+ i = trees.find(anc),
+ j = trees.find(left),
+ k = trees.find(right);
+ I(i != trees.end());
+ I(j != trees.end());
+ I(k != trees.end());
+ tree_state a = i->second;
+ tree_state l = j->second;
+ std::vector rp;
+ rp.push_back(k->second);
+ std::vector rr;
+ rr.push_back(right_extra_changes);
+ tree_state r = tree_state::merge_with_rearrangement(rp, rr, "xyzzy");
+ std::vector conf(l.conflict(r));
+ std::set res;
+ E(conf.size() == 0, F("Cannot handle merge conflicts over filenames yet."));
+ std::vector rl;
+ rl.push_back(l);
+ rl.push_back(r);
+ tree_state m = tree_state::merge_with_resolution(rl, res, "abccb");
+
+ std::map ip;
+ std::vector > ps;
+ ps = a.current();
+ for (std::vector >::const_iterator
+ i = ps.begin(); i != ps.end(); ++i)
+ {
+ std::pair::iterator, bool> r;
+ r = ip.insert(std::make_pair(i->first, itempaths()));
+ r.first->second.anc = i->second;
+ }
+ ps = l.current();
+ for (std::vector >::const_iterator
+ i = ps.begin(); i != ps.end(); ++i)
+ {
+ std::pair::iterator, bool> r;
+ r = ip.insert(std::make_pair(i->first, itempaths()));
+ r.first->second.left = (*i).second;
+ }
+ ps = r.current();
+ for (std::vector >::const_iterator
+ i = ps.begin(); i != ps.end(); ++i)
+ {
+ std::pair::iterator, bool> r;
+ r = ip.insert(std::make_pair(i->first, itempaths()));
+ r.first->second.right = (*i).second;
+ }
+ ps = m.current();
+ for (std::vector >::const_iterator
+ i = ps.begin(); i != ps.end(); ++i)
+ {
+ std::pair::iterator, bool> r;
+ r = ip.insert(std::make_pair(i->first, itempaths()));
+ r.first->second.merged = (*i).second;
+ }
+ paths.clear();
+ paths.reserve(ip.size());
+ for (std::map::const_iterator i = ip.begin();
+ i != ip.end(); ++i)
+ paths.push_back(i->second);
+
+ l.get_changes_for_merge(m, lm_re);
+ r.get_changes_for_merge(m, rm_re);
+}
+
void
-merge_change_sets(change_set const & a,
- change_set const & b,
- change_set & a_merged,
- change_set & b_merged,
- merge_provider & merger,
- app_state & app)
+merge_revisions(revision_id const & anc,
+ revision_id const & a,
+ revision_id const & b,
+ change_set const & b_extra_changes,
+ change_set & a_merged,
+ change_set & b_merged,
+ merge_provider & merger,
+ app_state & app)
{
- MM(a);
- MM(b);
MM(a_merged);
MM(b_merged);
- a.check_sane();
- b.check_sane();
- L(F("merging change sets\n"));
+ L(F("merging revisions\n"));
- tid_source ts;
- path_analysis
- a_analysis, b_analysis,
- a_renumbered, b_renumbered,
- a_merged_analysis, b_merged_analysis;
- MM(a_analysis);
- MM(b_analysis);
- MM(a_renumbered);
- MM(b_renumbered);
- MM(a_merged_analysis);
- MM(b_merged_analysis);
+ std::vector paths;
- analyze_rearrangement(a.rearrangement, a_analysis, ts);
- analyze_rearrangement(b.rearrangement, b_analysis, ts);
+ std::map merge_finalists;
- merge_disjoint_analyses(a_analysis, b_analysis,
- a_renumbered, b_renumbered,
- a_merged_analysis, b_merged_analysis,
- ts, app);
+ change_set anc_a, anc_b, anc_bwithchanges;
+ MM(anc_a);
+ MM(anc_b);
+ MM(b_extra_changes);
+ MM(anc_bwithchanges);
+ if (null_id(anc))
+ {
+ manifest_map a_man, b_man;
+ revision_set a_rev, b_rev;
+ MM(a_man);
+ MM(b_man);
+ app.db.get_revision(a, a_rev);
+ app.db.get_revision(b, b_rev);
+ app.db.get_manifest(a_rev.new_manifest, a_man);
+ app.db.get_manifest(b_rev.new_manifest, b_man);
+ build_pure_addition_change_set(a_man, anc_a);
+ build_pure_addition_change_set(b_man, anc_b);
- compose_rearrangement(a_merged_analysis,
- a_merged.rearrangement);
+ for (std::set::const_iterator
+ i = anc_a.rearrangement.added_files.begin();
+ i != anc_a.rearrangement.added_files.end(); ++i)
+ if (!anc_b.rearrangement.has_added_file(*i))
+ {
+ b_merged.add_file(*i);
+ paths.push_back(itempaths(file_path(), *i, file_path(), *i));
+ }
+ else
+ paths.push_back(itempaths(file_path(), *i, *i, *i));
- compose_rearrangement(b_merged_analysis,
- b_merged.rearrangement);
+ for (std::set::const_iterator
+ i = anc_b.rearrangement.added_files.begin();
+ i != anc_b.rearrangement.added_files.end(); ++i)
+ if (!anc_a.rearrangement.has_added_file(*i))
+ {
+ a_merged.add_file(*i);
+ paths.push_back(itempaths(file_path(), file_path(), *i, *i));
+ }
+ }
+ else
+ {
+ process_filetree_history(anc, a, b, b_extra_changes.rearrangement,
+ paths,
+ a_merged.rearrangement,
+ b_merged.rearrangement,
+ app);
+ if (!(anc == a))
+ calculate_arbitrary_change_set(anc, a, app, anc_a);
+ if (!(anc == b))
+ calculate_arbitrary_change_set(anc, b, app, anc_b);
+ }
+ concatenate_change_sets(anc_b, b_extra_changes, anc_bwithchanges);
- std::map merge_finalists;
-
- project_missing_deltas(a, b,
- a_renumbered, b_renumbered,
- a_merged_analysis,
+ project_missing_deltas(anc_a, anc_bwithchanges,
+ paths,
b_merged,
merger, merge_finalists);
- project_missing_deltas(b, a,
- b_renumbered, a_renumbered,
- b_merged_analysis,
+ b_merged.check_sane();
+
+ for (std::vector::iterator i = paths.begin();
+ i != paths.end(); ++i)
+ {
+ file_path t = (*i).left;
+ (*i).left = (*i).right;
+ (*i).right = t;
+ }
+
+ project_missing_deltas(anc_bwithchanges, anc_a,
+ paths,
a_merged,
merger, merge_finalists);
+ a_merged.check_sane();
+
{
// confirmation step
change_set a_check, b_check;
+ MM(a_check);
+ MM(b_check);
// dump_change_set("a", a);
// dump_change_set("a_merged", a_merged);
// dump_change_set("b", b);
// dump_change_set("b_merged", b_merged);
- concatenate_change_sets(a, a_merged, a_check);
- concatenate_change_sets(b, b_merged, b_check);
+ concatenate_change_sets(anc_a, a_merged, a_check);
+ concatenate_change_sets(anc_bwithchanges, b_merged, b_check);
// dump_change_set("a_check", a_check);
// dump_change_set("b_check", b_check);
I(a_check == b_check);
@@ -3005,77 +3212,6 @@
}
}
-static void
-disjoint_merge_test(std::string const & ab_str,
- std::string const & ac_str)
-{
- change_set ab, ac, bm, cm;
-
- app_state app;
-
- L(F("beginning disjoint_merge_test\n"));
-
- read_change_set(data(ab_str), ab);
- read_change_set(data(ac_str), ac);
-
- manifest_map dummy;
-
- merge_provider merger(app, dummy, dummy, dummy);
- merge_change_sets(ab, ac, bm, cm, merger, app);
-
- dump_change_set("ab", ab);
- dump_change_set("ac", ac);
- dump_change_set("bm", bm);
- dump_change_set("cm", cm);
-
- BOOST_CHECK(bm.rearrangement == ac.rearrangement);
- BOOST_CHECK(cm.rearrangement == ab.rearrangement);
-
- L(F("finished disjoint_merge_test\n"));
-}
-
-static void
-disjoint_merge_tests()
-{
- disjoint_merge_test
- ("rename_file \"foo\"\n"
- " to \"bar\"\n",
-
- "rename_file \"apple\"\n"
- " to \"orange\"\n");
-
- disjoint_merge_test
- ("rename_file \"foo/a.txt\"\n"
- " to \"bar/b.txt\"\n",
-
- "rename_file \"bar/c.txt\"\n"
- " to \"baz/d.txt\"\n");
-
- disjoint_merge_test
- ("patch \"foo/file.txt\"\n"
- " from [c6a4a6196bb4a744207e1a6e90273369b8c2e925]\n"
- " to [fe18ec0c55cbc72e4e51c58dc13af515a2f3a892]\n",
-
- "rename_file \"foo/file.txt\"\n"
- " to \"foo/apple.txt\"\n");
-
- disjoint_merge_test
- (
- "rename_file \"apple.txt\"\n"
- " to \"pear.txt\"\n"
- "\n"
- "patch \"foo.txt\"\n"
- " from [c6a4a6196bb4a744207e1a6e90273369b8c2e925]\n"
- " to [fe18ec0c55cbc72e4e51c58dc13af515a2f3a892]\n",
-
- "rename_file \"foo.txt\"\n"
- " to \"bar.txt\"\n"
- "\n"
- "patch \"apple.txt\"\n"
- " from [fe18ec0c55cbc72e4e51c58dc13af515a2f3a892]\n"
- " to [435e816c30263c9184f94e7c4d5aec78ea7c028a]\n");
-}
-
static void
basic_change_set_test()
{
@@ -3645,7 +3781,6 @@
suite->add(BOOST_TEST_CASE(&basic_change_set_test));
suite->add(BOOST_TEST_CASE(&neutralize_change_test));
suite->add(BOOST_TEST_CASE(&non_interfering_change_test));
- suite->add(BOOST_TEST_CASE(&disjoint_merge_tests));
suite->add(BOOST_TEST_CASE(&bad_concatenate_change_tests));
suite->add(BOOST_TEST_CASE(&invert_change_test));
}
========================================================================
--- change_set.hh d530354cb57477ef5e3b9e961346861c61508cba
+++ change_set.hh f8e06d50c8b82b973b2de70137f70171dac6120d
@@ -138,6 +138,7 @@
struct merge_provider;
+/*
void
merge_change_sets(change_set const & a,
change_set const & b,
@@ -145,6 +146,16 @@
change_set & b_merged,
merge_provider & merger,
app_state & app);
+*/
+void
+merge_revisions(revision_id const & anc,
+ revision_id const & a,
+ revision_id const & b,
+ change_set const & b_extra_changes,
+ change_set & a_merged,
+ change_set & b_merged,
+ merge_provider & merger,
+ app_state & app);
// value-oriented access to printers and parsers
========================================================================
--- commands.cc e3432b9b21954ad6f3628a6afbff3e6328e3cea1
+++ commands.cc 5c0ba1f50fee0b05d49e0f705875b563d03efcfd
@@ -3043,11 +3043,11 @@
// we apply the working to merged changeset to the working copy
// and keep the rearrangement from chosen to merged changeset in MT/work
- merge_change_sets(old_to_chosen,
- old_to_working,
- chosen_to_merged,
- working_to_merged,
- merger, app);
+ merge_revisions(r_old_id, r_chosen_id, r_old_id,
+ old_to_working,
+ chosen_to_merged,
+ working_to_merged,
+ merger, app);
// dump_change_set("chosen to merged", chosen_to_merged);
// dump_change_set("working to merged", working_to_merged);
@@ -3151,16 +3151,16 @@
}
else
{
- P(F("no common ancestor found, synthesizing edges\n"));
+ P(F("no common ancestor found, synthesizing edges\n"));
build_pure_addition_change_set(left_man, *anc_to_left);
build_pure_addition_change_set(right_man, *anc_to_right);
}
merge_provider merger(app, anc_man, left_man, right_man);
- merge_change_sets(*anc_to_left, *anc_to_right,
- *left_to_merged, *right_to_merged,
- merger, app);
+ merge_revisions(anc_id, left_id, right_id, change_set(),
+ *left_to_merged, *right_to_merged,
+ merger, app);
{
// we have to record *some* route to this manifest. we pick the
========================================================================
--- pcdv.cc 98142af12f61b816c38685f185fe3eaae0447dca
+++ pcdv.cc 7bb131b0c0268cae51eadc9d22a11d7ec6d7ad11
@@ -974,24 +974,58 @@
}
-
-tree_state::tree_state(boost::shared_ptr > > _items,
- boost::shared_ptr > _itx):
- items(_items),
- states(new std::map()),
- itx(_itx)
-{}
-
tree_state::tree_state():
items(new vector >()),
states(new std::map()),
- itx(new interner())
+ itx(new interner()),
+ sutures(new std::map())
{}
+tree_state
+tree_state::new_skel() const
+{
+ tree_state out;
+ out.items = items;
+ out.itx = itx;
+ out.sutures = sutures;
+ return out;
+}
+
tree_state::~tree_state()
{}
+void
+tree_state::add_suture(item_id l, item_id r)
+{
+ std::map::const_iterator i = sutures->find(r);
+ if (i != sutures->end())
+ add_suture(l, i->second);
+}
+
+void
+tree_state::apply_sutures()
+{
+ for (std::map::const_iterator i = sutures->begin();
+ i != sutures->end(); ++i)
+ {
+ std::map::iterator j = states->find(i->first);
+ std::map::iterator k = states->find(i->second);
+ if (j != states->end())
+ {
+ if (k == states->end())
+ {
+ states->insert(make_pair(i->second, j->second));
+ states->erase(j);
+ }
+ else
+ {
+ k->second = k->second.suture(j->second);
+ states->erase(j);
+ }
+ }
+ }
+}
+
const int deleted_dir(1);
const int deleted_file(2);
const int renamed_dir(3);
@@ -1156,13 +1190,7 @@
if (r.first->second != j->first)
{
W(F("Colliding over %1%") % j->second());
- std::map::iterator a, b;
- a = out.states->find(r.first->second);
- b = out.states->find(j->first);
- I(a != out.states->end());
- I(b != out.states->end());
- a->second = a->second.suture(b->second);
- out.states->erase(b);
+ out.add_suture(r.first->second, j->first);
}
}
}
@@ -1266,15 +1294,10 @@
if (r.first->second != current_id)
{
W(F("Colliding over %1%") % to);
- std::map::iterator a, b;
- a = out.states->find(r.first->second);
- b = out.states->find(j->first);
- I(a != out.states->end());
- I(b != out.states->end());
- a->second = a->second.suture(b->second);
- out.states->erase(b);
+ out.add_suture(r.first->second, j->first);
}
}
+ out.apply_sutures();
return out;
}
@@ -1296,7 +1319,7 @@
tree_state::mash(tree_state const & other) const
{
I(items == other.items);
- tree_state newstate(items, itx);
+ tree_state newstate = new_skel();
map::const_iterator l, r;
l = states->begin();
r = other.states->begin();
@@ -1324,6 +1347,7 @@
tree_state::conflict(tree_state const & other) const
{
tree_state merged(mash(other));
+ merged.apply_sutures();
std::vector out;
std::map > m;
@@ -1510,6 +1534,7 @@
std::string const & revision)
{
tree_state merged(mash(revs));
+ merged.apply_sutures();
std::set resolved;
typedef std::vector splitpath;
========================================================================
--- pcdv.hh f650089a46f20388d4d5976d906389af52c23934
+++ pcdv.hh 42ce2c9da4c7a1e77b1200885b6d3fc579592c69
@@ -227,7 +227,7 @@
};
-// This is a const object type; there are no modifiers.
+// This is a const object type; there are no modifiers. ??
// Usage:
// for a->b
// a.rearrange(, 'b')
@@ -247,11 +247,14 @@
boost::shared_ptr > > items;
boost::shared_ptr > states;
boost::shared_ptr > itx;
+ boost::shared_ptr > sutures;
- tree_state(boost::shared_ptr > > _items,
- boost::shared_ptr > _itx);
tree_state();
+
+ tree_state new_skel() const;
+
+ void add_suture(item_id l, item_id r);
+ void apply_sutures();
public:
~tree_state();