#
# patch "ChangeLog"
# from [c21fba304d06e2f3a724a17ed2cf85b49a3e4cd2]
# to [69d8cc3b1214855d6424b4dce05283294eafd230]
#
# patch "NEWS"
# from [4e6e48c7d84b9e778412486592d47032638dff3f]
# to [ef7e6cd276057ab21594eb5f3c7831a011000484]
#
# patch "change_set.cc"
# from [ac5f6d85330f8287a66d747e06d414b9120cb2cd]
# to [e963e597bcc9c332da6ff0d2593ac2c6e6e183ca]
#
# patch "revision.cc"
# from [e3df88382e4fd3be836ca176063ae93244f6f268]
# to [b90b4de954657d808ecfec14c81b182dd103ce83]
#
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,15 @@
+2005-04-29 Nathaniel Smith
+
+ * change_set.cc (dump_change_set): Don't truncate output.
+ (invert_change_test): New unit test.
+ (invert_change_set): Make it pass. This fixes (some?)
+ isect.empty() invariant failures.
+
+ * NEWS: Start updating for 0.19.
+
+ * revision.cc (check_sane_history): Make comment more
+ informative.
+
2005-04-28 Nathaniel Smith
* tests/t_netsync_error.at: New test.
--- NEWS
+++ NEWS
@@ -1,3 +1,72 @@
+????????????????????????????
+
+ 0.19 release. performance improvements, features, ui
+ improvements, and bug fixes.
+
+ - many operations sped up by another factor of 2 or better.
+ - special thanks to Matt Johnston .
+ - new major features:
+ - "annotate" command; still requires optimization.
+ Thanks to Emile Snyder .
+ - "inodeprints" for fast change detection in large
+ working dirs now fully supported; see manual for
+ details.
+ - new minor features:
+ - new selector "c:name=value" for selecting on
+ arbitrary certs. Thanks to Richard Levitte
+ .
+ - new automate command "select", to do selector
+ expansion. Thanks to Richard Levitte
+ .
+ - new automate commands "graph", "parents",
+ "children", "ancestors", to easily inspect history.
+ Special thanks to Sebastian Spaeth
+ .
+ - new command "db kill_rev_locally". Thanks to
+ Sebastian Spaeth .
+ - new arguments to "commit": --author, --date; useful
+ for patch attribution and importing history.
+ - ui improvements:
+ - netsync progress ticker in kilobytes/megabytes.
+ Thanks to Matt Johnston ,
+ - tickers do not cause annoying scrolling when wider
+ than window. Special thanks to Matthew Gregan
+ .
+ - warn users when a commit creates divergence, and
+ when an update ignores it. Thanks to Jeremy Cowgar
+ .
+ - many bug fixes:
+ - many cvs_import bugs fixed. Special thanks to Jon
+ Bright , Emile Snyder
+ , Hansjoerg Lipp
+ , Matthew Gregan
+ .
+ - windows/unix working copy line conversion now works
+ correctly. Thanks to Emile Snyder
+ .
+ - many fixes to locale-specific filename support
+ - "drop" and "rename" now affect file attributes as
+ well. Thanks to Richard Levitte
+ and Joel Reed
+ .
+ - better error reporting in netsync. Thanks to
+ Grahame Bowland .
+ - only set working directory's default branch on some
+ commands (update, commit). Thanks to Florian Weimer
+ .
+ - "db check" now sets exit status correctly, for use
+ in scripts. Thanks to Derek Scherger
+ .
+ - many others...
+ - fantastic emacs integration in contrib/monotone.el. Thanks
+ to Harley Gorrell .
+
+ - upgrading from 0.18: database and working copies are
+ fully compatible. NOTE that the configuration file
+ is now ~/.monotone/monotonerc, rather than old
+ ~/.monotonerc. Simply create ~/.monotone, and
+ rename any existing configuration file.
+
Sun Apr 10 17:49:25 PDT 2005
0.18 release. performance improvements, features, and bug fixes.
--- change_set.cc
+++ change_set.cc
@@ -2273,6 +2273,8 @@
b2a.deltas.clear();
+ std::set moved_deltas;
+
// existing deltas are in "b space"
for (path_state::const_iterator b = b2a_analysis.first.begin();
b != b2a_analysis.first.end(); ++b)
@@ -2310,7 +2312,7 @@
get_full_path(b2a_analysis.first, path_state_tid(b), b_pth);
get_full_path(b2a_analysis.second, path_state_tid(a), a_pth);
change_set::delta_map::const_iterator del = a2b.deltas.find(b_pth);
- if (del == a2b.deltas.end())
+ if (del == a2b.deltas.end())
continue;
file_id src_id(delta_entry_src(del)), dst_id(delta_entry_dst(del));
L(F("converting delta %s -> %s on %s\n")
@@ -2318,6 +2320,7 @@
L(F("inverse is delta %s -> %s on %s\n")
% dst_id % src_id % a_pth);
b2a.deltas.insert(std::make_pair(a_pth, std::make_pair(dst_id, src_id)));
+ moved_deltas.insert(b_pth);
}
}
}
@@ -2331,8 +2334,11 @@
if (null_id(delta_entry_src(del)))
continue;
// check to make sure this isn't one of the already-moved deltas
- if (b2a.deltas.find(delta_entry_path(del)) != b2a.deltas.end())
+ if (moved_deltas.find(delta_entry_path(del)) != moved_deltas.end())
continue;
+ // we shouldn't have created a delta earlier, if this file really is
+ // untouched...
+ I(b2a.deltas.find(delta_entry_path(del)) == b2a.deltas.end());
b2a.deltas.insert(std::make_pair(delta_entry_path(del),
std::make_pair(delta_entry_dst(del),
delta_entry_src(del))));
@@ -2893,6 +2899,7 @@
#ifdef BUILD_UNIT_TESTS
#include "unit_tests.hh"
#include "sanity.hh"
+#include "transforms.hh"
static void dump_change_set(std::string const & ctx,
change_set const & cs)
@@ -2900,7 +2907,11 @@
data tmp;
write_change_set(cs, tmp);
L(F("[begin changeset %s]\n") % ctx);
- L(F("%s") % tmp);
+ std::vector lines;
+ split_into_lines(tmp(), lines);
+ for (std::vector::const_iterator i = lines.begin();
+ i != lines.end(); ++i)
+ L(F("%s") % *i);
L(F("[end changeset %s]\n") % ctx);
}
@@ -3031,6 +3042,46 @@
}
}
+static void
+invert_change_test()
+{
+ L(F("STARTING invert_change_test\n"));
+ change_set cs;
+ manifest_map a;
+
+ a.insert(std::make_pair(file_path("usr/lib/zombie"),
+ file_id(hexenc("92ceb3cd922db36e48d5c30764e0f5488cdfca28"))));
+ cs.delete_file(file_path("usr/lib/zombie"));
+ cs.add_file(file_path("usr/bin/cat"),
+ file_id(hexenc("adc83b19e793491b1c6ea0fd8b46cd9f32e592fc")));
+ cs.add_file(file_path("usr/local/dog"),
+ file_id(hexenc("adc83b19e793491b1c6ea0fd8b46cd9f32e592fc")));
+ a.insert(std::make_pair(file_path("usr/foo"),
+ file_id(hexenc("9a4d3ae90b0cc26758e17e1f80229a13f57cad6e"))));
+ cs.rename_file(file_path("usr/foo"), file_path("usr/bar"));
+ cs.apply_delta(file_path("usr/bar"),
+ file_id(hexenc("9a4d3ae90b0cc26758e17e1f80229a13f57cad6e")),
+ file_id(hexenc("fe18ec0c55cbc72e4e51c58dc13af515a2f3a892")));
+ a.insert(std::make_pair(file_path("usr/quuux"),
+ file_id(hexenc("fe18ec0c55cbc72e4e51c58dc13af515a2f3a892"))));
+ cs.apply_delta(file_path("usr/quuux"),
+ file_id(hexenc("fe18ec0c55cbc72e4e51c58dc13af515a2f3a892")),
+ file_id(hexenc("c6a4a6196bb4a744207e1a6e90273369b8c2e925")));
+
+ manifest_map b;
+ apply_change_set(a, cs, b);
+
+ dump_change_set("invert_change_test, cs", cs);
+ change_set cs2, cs3;
+ invert_change_set(cs, a, cs2);
+ dump_change_set("invert_change_test, cs2", cs2);
+ invert_change_set(cs2, b, cs3);
+ dump_change_set("invert_change_test, cs3", cs3);
+ BOOST_CHECK(cs.rearrangement == cs3.rearrangement);
+ BOOST_CHECK(cs.deltas == cs3.deltas);
+ L(F("ENDING invert_change_test\n"));
+}
+
static void
neutralize_change_test()
{
@@ -3527,6 +3578,7 @@
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));
}
--- revision.cc
+++ revision.cc
@@ -90,6 +90,11 @@
// change sets can be applied to the old manifests to create the new
// manifest.
//
+// We also make a special check for merge nodes, where if the previous
+// paragraph wasn't enough to get us back to a common ancestor, we also search
+// all the way up to a common ancestor and make the same check, because that's
+// the invariant that merge is actually required to preserve.
+//
// NB: While this function has some invariants in it itself, a lot of its
// purpose is just to exercise all the invariants inside change_set.cc. So
// don't remove those invariants. (As if you needed another reason...)