The unified diff between revisions [4775b468..] and [5db0a3df..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "ChangeLog"
#  from [032614fe128da6d74ed0791c9ad72d7c21198a71]
#    to [28b285fc7dd7ab59bf95ee10a08a0533f12f9d4c]
#
# patch "commands.cc"
#  from [78f143816a40546e5749613deffcbd9717b26b9b]
#    to [b646237c84abb7968c65dd9d7c1868104626f2da]
#
# patch "cycle_detector.hh"
#  from [ef399391fc668c64ba6b4b54e900b6b629d4e76f]
#    to [1c092e0a2df37f3b38d12fc50598d1f829f565e5]
#
# patch "diff_patch.cc"
#  from [ab12c48d78c000fbfe7f9b35fdbe0f6d8d783ec8]
#    to [ed46b89c63fb502546e64c4b2abc6d3cdb0d48e9]
#
# patch "monotone.spec"
#  from [2816529346d63a7fc3689adbf0532157f305b978]
#    to [a86e1d9969df82ed932bffcefb6ab07a43c873d0]
#
# patch "rcs_import.cc"
#  from [9183ef64322019ff3fcb8503db0a59b2b2ebb45f]
#    to [bc8d80071e9070a84d3298e1771c5a8752eed902]
#
============================================================
--- ChangeLog	032614fe128da6d74ed0791c9ad72d7c21198a71
+++ ChangeLog	28b285fc7dd7ab59bf95ee10a08a0533f12f9d4c
@@ -1,5 +1,11 @@ 2003-09-27  graydon hoare  <graydon@pobo
 2003-09-27  graydon hoare  <graydon@pobox.com>

+	* diff_patch.cc: Rework conflict detection.
+	* rcs_import.cc: Remove some pointless slowness.
+	* monotone.spec: Install info files properly.
+
+2003-09-27  graydon hoare  <graydon@pobox.com>
+
 	* AUTHORS, NEWS, configure.ac: Update for 0.5 release.
 	* monotone.texi: Various updates.
 	* xdelta.cc (compute_delta): Fix handling of empty data.
============================================================
--- commands.cc	78f143816a40546e5749613deffcbd9717b26b9b
+++ commands.cc	b646237c84abb7968c65dd9d7c1868104626f2da
@@ -1482,11 +1482,27 @@ CMD(merge, "tree", "", "merge unmerged h
 }


-// fmerge is a simple command for debugging the line merger.  most of the
-// time, leave it commented out. it can be helpful for certain cases,
-// though.
+// float and fmerge are simple commands for debugging the line merger.
+// most of the time, leave them commented out. they can be helpful for certain
+// cases, though.

 /*
+CMD(fload, "tree", "", "load file contents into db")
+{
+  string s = get_stdin();
+  base64< gzip< data > > gzd;
+
+  pack(data(s), gzd);
+
+  file_id f_id;
+  file_data f_data(gzd);
+
+  calculate_ident (f_data, f_id);
+
+  packet_db_writer dbw(app);
+  dbw.consume_file_data(f_id, f_data);
+}
+
 CMD(fmerge, "tree", "<parent> <left> <right>", "merge 3 files and output result")
 {
   if (args.size() != 3)
============================================================
--- cycle_detector.hh	ef399391fc668c64ba6b4b54e900b6b629d4e76f
+++ cycle_detector.hh	1c092e0a2df37f3b38d12fc50598d1f829f565e5
@@ -45,7 +45,6 @@ struct cycle_detector

   bool edge_makes_cycle(T const & src, T const & dst)
   {
-
     if (src == dst)
       return true;

============================================================
--- diff_patch.cc	ab12c48d78c000fbfe7f9b35fdbe0f6d8d783ec8
+++ diff_patch.cc	ed46b89c63fb502546e64c4b2abc6d3cdb0d48e9
@@ -138,10 +138,13 @@ struct hunk_offset_calculator : public h
 struct hunk_offset_calculator : public hunk_consumer
 {
   vector<size_t> & leftpos;
+  set<size_t> & deletes;
+  set<size_t> & inserts;
   size_t apos;
   size_t lpos;
   size_t final;
-  hunk_offset_calculator(vector<size_t> & lp, size_t fin);
+  hunk_offset_calculator(vector<size_t> & lp, size_t fin,
+			 set<size_t> & dels, set<size_t> & inss);
   virtual void flush_hunk(size_t pos);
   virtual void advance_to(size_t newpos);
   virtual void insert_at(size_t b_pos);
@@ -149,8 +152,9 @@ struct hunk_offset_calculator : public h
   virtual ~hunk_offset_calculator();
 };

-hunk_offset_calculator::hunk_offset_calculator(vector<size_t> & off, size_t fin)
-  : leftpos(off), apos(0), lpos(0), final(fin)
+hunk_offset_calculator::hunk_offset_calculator(vector<size_t> & off, size_t fin,
+					       set<size_t> & dels, set<size_t> & inss)
+  : leftpos(off), deletes(dels), inserts(inss), apos(0), lpos(0), final(fin)
 {}

 hunk_offset_calculator::~hunk_offset_calculator()
@@ -179,6 +183,7 @@ void hunk_offset_calculator::insert_at(s
 {
   //   L("insert at %d: [%d,%d] -> [%d,%d] (sz=%d)\n",
   //     lp, apos, lpos, apos, lpos+1, leftpos.size());
+  inserts.insert(apos);
   I(lpos == lp);
   lpos++;
 }
@@ -187,6 +192,7 @@ void hunk_offset_calculator::delete_at(s
 {
   //   L("delete at %d: [%d,%d] -> [%d,%d] (sz=%d)\n",
   //      ap, apos, lpos, apos+1, lpos, leftpos.size());
+  deletes.insert(apos);
   I(apos == ap);
   apos++;
   leftpos.push_back(lpos);
@@ -194,7 +200,9 @@ void calculate_hunk_offsets(vector<strin

 void calculate_hunk_offsets(vector<string> const & ancestor,
 			    vector<string> const & left,
-			    vector<size_t> & leftpos)
+			    vector<size_t> & leftpos,
+			    set<size_t> & deletes,
+			    set<size_t> & inserts)
 {

   vector<long> anc_interned;
@@ -213,13 +221,14 @@ void calculate_hunk_offsets(vector<strin
        i != left.end(); ++i)
     left_interned.push_back(in.intern(*i));

+  lcs.reserve(std::min(left.size(),ancestor.size()));
   longest_common_subsequence(anc_interned.begin(), anc_interned.end(),
 			     left_interned.begin(), left_interned.end(),
-			     std::max(ancestor.size(), left.size()),
+			     std::min(ancestor.size(), left.size()),
 			     back_inserter(lcs));

   leftpos.clear();
-  hunk_offset_calculator calc(leftpos, ancestor.size());
+  hunk_offset_calculator calc(leftpos, ancestor.size(), deletes, inserts);
   walk_hunk_consumer(lcs, anc_interned, left_interned, calc);
 }

@@ -232,6 +241,8 @@ struct hunk_merger : public hunk_consume
   vector<string> const & ancestor;
   vector<string> const & right;
   vector<size_t> const & ancestor_to_leftpos_map;
+  set<size_t> const & deletes;
+  set<size_t> const & inserts;
   vector<string> & merged;
   size_t apos;
   size_t lpos;
@@ -239,6 +250,8 @@ struct hunk_merger : public hunk_consume
 	      vector<string> const & anc,
 	      vector<string> const & rght,
 	      vector<size_t> const & lpos,
+	      set<size_t> const & dels,
+	      set<size_t> const & inss,
 	      vector<string> & mrgd);
   virtual void flush_hunk(size_t apos);
   virtual void advance_to(size_t apos);
@@ -253,9 +266,12 @@ hunk_merger::hunk_merger(vector<string>
 			 vector<string> const & anc,
 			 vector<string> const & rght,
 			 vector<size_t> const & lpos,
+			 set<size_t> const & dels,
+			 set<size_t> const & inss,
 			 vector<string> & mrgd)
   : left(lft), ancestor(anc), right(rght),
-    ancestor_to_leftpos_map(lpos), merged(mrgd),
+    ancestor_to_leftpos_map(lpos), deletes(dels),
+    inserts(inss), merged(mrgd),
     apos(0), lpos(0)
 {
   merged.clear();
@@ -298,9 +314,9 @@ void hunk_merger::advance_to(size_t ap)
 	lend = ancestor_to_leftpos_map.at(ap);
     }

-  //   L("advance to %d / %d (lpos = %d / %d -> %d / %d)\n",
-  //     ap, ancestor.size(), lpos, left.size(),
-  //     lend, left.size());
+//   L("advance to %d / %d (lpos = %d / %d -> %d / %d)\n",
+//     ap, ancestor.size(), lpos, left.size(),
+//     lend, left.size());

   I(lpos <= lend);
   I(lend <= left.size());
@@ -339,22 +355,14 @@ void hunk_merger::insert_at(size_t rp)

 void hunk_merger::insert_at(size_t rp)
 {
-  //   L("insert at %d (lpos = %d)\n", rp, lpos);
+//   L("insert at %d (lpos = %d) '%8s'...\n", rp, lpos,
+//     right.at(rp).c_str());
   I(ancestor.size() == ancestor_to_leftpos_map.size());
   I(rp < right.size());
   I(apos <= ancestor_to_leftpos_map.size());

-  bool insert_here = false;
-  bool delete_here = false;
-
-  if (apos > 0 && apos < ancestor_to_leftpos_map.size())
-    insert_here =
-      (ancestor_to_leftpos_map.at(apos - 1) + 1 <
-       ancestor_to_leftpos_map.at(apos));
-
-  if (apos + 1 < ancestor_to_leftpos_map.size())
-    delete_here = (ancestor_to_leftpos_map.at(apos + 1) ==
-		   ancestor_to_leftpos_map.at(apos));
+  bool insert_here = inserts.find(apos) != inserts.end();
+  bool delete_here = deletes.find(apos) != deletes.end();

   if (! (insert_here || delete_here))
     merged.push_back(right.at(rp));
@@ -371,6 +379,7 @@ void hunk_merger::insert_at(size_t rp)

   else if (insert_here)
     {
+      // simultaneous, identical insert?
       if (left.at(lpos) == right.at(rp))
 	return;

@@ -415,28 +424,21 @@ void hunk_merger::delete_at(size_t ap)

 void hunk_merger::delete_at(size_t ap)
 {
-  //   L("delete at %d (apos = %d, lpos = %d, translated = %d)\n",
-  //     ap, apos, lpos, ancestor_to_leftpos_map.at(ap));
+//   L("delete at %d (apos = %d, lpos = %d, translated = %d) '%8s'...\n",
+//     ap, apos, lpos, ancestor_to_leftpos_map.at(ap),
+//     ancestor.at(ap).c_str());
   I(ancestor.size() == ancestor_to_leftpos_map.size());
   I(ap < ancestor_to_leftpos_map.size());
   I(ap == apos);
   I(ancestor_to_leftpos_map.at(ap) == lpos);

+  bool insert_here = inserts.find(apos) != inserts.end();
+  bool delete_here = deletes.find(apos) != deletes.end();

-  bool insert_here = false;
-  bool delete_here = false;
-
-  if (ap > 0 && apos < ancestor_to_leftpos_map.size())
-    insert_here =
-      (ancestor_to_leftpos_map.at(apos - 1) + 1 <
-       ancestor_to_leftpos_map.at(apos));
-
-  if (ap + 1 < ancestor_to_leftpos_map.size())
-    delete_here = (ancestor_to_leftpos_map.at(apos + 1) ==
-		   ancestor_to_leftpos_map.at(apos));
-
   if (!(insert_here || delete_here))
-    {apos++; lpos++;}
+    {
+      apos++; lpos++;
+    }

   else if (delete_here)
     {
@@ -475,6 +477,8 @@ void merge_hunks_via_offsets(vector<stri
 			     vector<string> const & ancestor,
 			     vector<string> const & right,
 			     vector<size_t> const & leftpos,
+			     set<size_t> const & deletes,
+			     set<size_t> const & inserts,
 			     vector<string> & merged)
 {
   vector<long> anc_interned;
@@ -499,11 +503,12 @@ void merge_hunks_via_offsets(vector<stri
        i != right.end(); ++i)
     right_interned.push_back(in.intern(*i));

+  lcs.reserve(std::min(right.size(),ancestor.size()));
   longest_common_subsequence(anc_interned.begin(), anc_interned.end(),
 			     right_interned.begin(), right_interned.end(),
-			     std::max(ancestor.size(), right.size()),
+			     std::min(ancestor.size(), right.size()),
 			     back_inserter(lcs));
-  hunk_merger merger(left, ancestor, right, leftpos, merged);
+  hunk_merger merger(left, ancestor, right, leftpos, deletes, inserts, merged);
   walk_hunk_consumer(lcs, anc_interned, right_interned, merger);
 }

@@ -516,9 +521,12 @@ bool merge3(vector<string> const & ances
   try
     {
       vector<size_t> leftpos;
+      set<size_t> deletes;
+      set<size_t> inserts;
+
       L("calculating offsets from ancestor:[%d..%d) to left:[%d..%d)\n",
 	0, ancestor.size(), 0, left.size());
-      calculate_hunk_offsets(ancestor, left, leftpos);
+      calculate_hunk_offsets(ancestor, left, leftpos, deletes, inserts);

       L("sanity-checking offset table (sz=%d, ancestor=%d)\n",
 	leftpos.size(), ancestor.size());
@@ -533,7 +541,8 @@ bool merge3(vector<string> const & ances

       L("merging differences from ancestor:[%d..%d) to right:[%d..%d)\n",
 	0, ancestor.size(), 0, right.size());
-      merge_hunks_via_offsets(left, ancestor, right, leftpos, merged);
+      merge_hunks_via_offsets(left, ancestor, right, leftpos,
+			      deletes, inserts, merged);
     }
   catch(conflict & c)
     {
@@ -1137,9 +1146,10 @@ void unidiff(string const & filename1,
        i != lines2.end(); ++i)
     right_interned.push_back(in.intern(*i));

+  lcs.reserve(std::min(lines1.size(),lines2.size()));
   longest_common_subsequence(left_interned.begin(), left_interned.end(),
 			     right_interned.begin(), right_interned.end(),
-			     std::max(lines1.size(), lines2.size()),
+			     std::min(lines1.size(), lines2.size()),
 			     back_inserter(lcs));

   unidiff_hunk_writer hunks(lines1, lines2, 3, ost);
============================================================
--- monotone.spec	2816529346d63a7fc3689adbf0532157f305b978
+++ monotone.spec	a86e1d9969df82ed932bffcefb6ab07a43c873d0
@@ -33,10 +33,19 @@ rm -rf $RPM_BUILD_ROOT
 rm -rf $RPM_BUILD_ROOT

 %post
-%_install_info monotone
+if [ -x /sbin/install-info ]
+then
+/sbin/install-info --info-dir=%{_infodir} \
+             --entry="* monotone: (monotone).              Monotone version control system" \
+             --section=Programming \
+	     %{_infodir}/monotone.info.gz
+fi

 %preun
-%_remove_install_info monotone
+if [ -x /sbin/install-info ]
+then
+/sbin/install-info --info-dir=%{_infodir} --remove monotone
+fi

 %files
 %defattr(-,root,root,-)
============================================================
--- rcs_import.cc	9183ef64322019ff3fcb8503db0a59b2b2ebb45f
+++ rcs_import.cc	bc8d80071e9070a84d3298e1771c5a8752eed902
@@ -690,9 +690,7 @@ public:
     string file = path();
     if (file.substr(file.size() - 2) == string(",v"))
       {
-	transaction_guard guard(db);
 	import_rcs_file_with_cvs(file, db, cvs);
-	guard.commit();
       }
     else
       L("skipping non-RCS file %s\n", file.c_str());
@@ -893,7 +891,8 @@ void import_substates(ticker & n_edges,
       calculate_manifest_map_ident(child_map, child_id);
       store_branch_manifest_edge(parent_map, child_map, parent_id, child_id, app, cvs);
       store_auxilliary_certs(i->first, child_id, app, cvs);
-      import_substates(n_edges, n_branches, i->second, child_map, cvs, app);
+      if (i->second->substates.size() > 0)
+	import_substates(n_edges, n_branches, i->second, child_map, cvs, app);
       parent_map = child_map;
       parent_id = child_id;
       ++n_edges;
@@ -904,12 +903,16 @@ void import_cvs_repo(fs::path const & cv
 void import_cvs_repo(fs::path const & cvsroot, app_state & app)
 {
   cvs_history cvs;
-  cvs_tree_walker walker(cvs, app.db);
-  I( fs::is_directory(cvsroot));
-  I( fs::exists(cvsroot));
-  app.db.ensure_open();
-  I(chdir(cvsroot.native_directory_string().c_str()) == 0);
-  walk_tree(walker);
+  {
+    transaction_guard guard(app.db);
+    cvs_tree_walker walker(cvs, app.db);
+    I( fs::is_directory(cvsroot));
+    I( fs::exists(cvsroot));
+    app.db.ensure_open();
+    I(chdir(cvsroot.native_directory_string().c_str()) == 0);
+    walk_tree(walker);
+    guard.commit();
+  }

   P("phase 1 (version import) complete\n");
   L("phase 1 complete, all versions imported\n");
@@ -944,7 +947,8 @@ void import_cvs_repo(fs::path const & cv
 	calculate_manifest_map_ident(parent_map, parent_id);
 	store_trunk_manifest_edge(parent_map, child_map, parent_id, child_id, app, cvs);
 	store_auxilliary_certs(i->first, parent_id, app, cvs);
-	import_substates(n_edges, n_branches, i->second, parent_map, cvs, app);
+	if (i->second->substates.size() > 0)
+	  import_substates(n_edges, n_branches, i->second, parent_map, cvs, app);
 	child_map = parent_map;
 	child_id = parent_id;
 	++n_edges;