monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-devel] Please review: initial Attic patch


From: Tom Tromey
Subject: [Monotone-devel] Please review: initial Attic patch
Date: 11 Dec 2003 18:08:49 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50

Here's the Attic patch.  I haven't had much time to work on it lately
(and probably won't in the near future), and it is at least better
than what we currently do, so I thought I'd post it for comments.

Take a look at the FIXME comments in t_cvsimport2.at to see various
cvs import failure modes I've found.  I think all of these represent
real bugs.

The cvs_history::set_filename part of the patch is basically
independent.  It could go in separately if desired.  It just
canonicalizes file names by removing the "Attic" component.


A quick note on Attic directories: a ,v file is moved into Attic if
and only if the tip of the trunk is dead.  However, the location of
the ,v file is redundant -- cvs also marks the revision as "State:
dead".  The existence of Attic is just a backward compatibility hack
with versions of cvs predating the "dead" state support.


Anyway, what do you think?  I don't want to commit this without
somebody else reading over it.  If the main bits look bad, I'd still
like to check in the test case at the very least.

Tom


# Old manifest: ce5403dbdbe8ba8b6e228d14c791628a1835ab52
# New manifest: ff1d04bbc64faa614d81c251bbe503af09bf27e7
# Summary of changes:
#   add tests/t_cvsimport2.at as 8a6628bf2871292034deaf1f0962857f53fcc4e7
#   patch ChangeLog 7b966c9c3a7b63ba61afd026fe84d469638b6174 -> 
f55501a774d7dd0a81be8c1da6b55aaa1d0b95af
#   patch rcs_import.cc d2535758d21aaaf36c96415e1ebc0f4700361074 -> 
47ec16d0e8c048ef129d7e45b08c3c2f36c25b32
#   patch testsuite.at db82390ede299cfa11af8a1c07f189a2d824bbef -> 
9f0608acd0521168135756bf795c7ec45f1fc3d7
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,18 @@
+2003-12-05  Tom Tromey  <address@hidden>
+
+       * testsuite.at: Include new test.
+       * tests/t_cvsimport2.at: New file.
+       * rcs_import.cc (cvs_history::set_filename): Rewrite name if file
+       is in Attic.
+       (delta_live_p): New function.
+       (note_file_edge): Added prev_living and curr_living arguments.
+       Update deletions list when required.  Don't add file to head
+       manifest if it has been deleted.
+       (struct cvs_state): New field deletions.
+       (build_parent_state): Process deletions.
+       (build_child_state): Process deletions.
+       (struct cvs_history): New field head_deletions.
+
 2003-11-29  Tom Tromey  <address@hidden>
 
        * rcs_import.cc (store_auxiliary_certs): Renamed to fix typo.
--- rcs_import.cc
+++ rcs_import.cc
@@ -121,6 +121,7 @@
 {
   set<cvs_file_edge> in_edges;
   map< cvs_key, shared_ptr<cvs_state> > substates;
+  set<file_path> deletions;
 };
 
 struct cvs_history
@@ -145,6 +146,7 @@
   state_stack stk;
   file_path curr_file;
   manifest_map head_manifest;
+  set<file_path> head_deletions;
   string base_branch;
 
   ticker n_versions;
@@ -155,11 +156,13 @@
   void set_filename(string const & file,
                    file_id const & ident);
   void push_branch(rcs_file const & r, string const & rcs_version_num);
-  void note_file_edge(rcs_file const & r, 
+  void note_file_edge(rcs_file const & r,
                      string const & prev_rcs_version_num,
                      string const & next_rcs_version_num,
                      file_id const & prev_version,
-                     file_id const & next_version);
+                     file_id const & next_version,
+                     bool prev_living,
+                     bool next_living);
   void pop_branch();
 };
 
@@ -373,6 +375,12 @@
   rcs_put_raw_file_edge(next_id, curr_id, del, db);
 }
 
+static bool
+delta_live_p (shared_ptr<rcs_delta> &delta)
+{
+  // cvs sets state to "dead" when a file is removed.
+  return delta->state != string("dead");
+}
 
 static void 
 process_branch(string const & begin_version, 
@@ -397,9 +403,19 @@
       L(F("version %s has %d lines\n") % curr_version % curr_lines->size());
       
       // construct this edge on our own branch
-      string next_version = r.deltas.find(curr_version)->second->next;
+      shared_ptr<rcs_delta> delta = r.deltas.find(curr_version)->second;
+      string next_version = delta->next;
       L(F("following RCS edge %s -> %s\n") % curr_version % next_version);
 
+      bool curr_living = delta_live_p(delta);
+
+      bool next_living = true;
+      if (r.deltas.find(next_version) != r.deltas.end())
+       {
+         shared_ptr<rcs_delta> d2 = r.deltas.find(next_version)->second;
+         next_living = delta_live_p(d2);
+       }
+
       construct_version(*curr_lines, next_version, *next_lines, r);
       L(F("constructed RCS version %s, inserting into database\n") % 
        next_version);
@@ -408,15 +418,18 @@
                     *next_lines, next_data, next_id, db);
 
       cvs.note_file_edge (r, curr_version, next_version, 
-                         file_id(curr_id), file_id(next_id));
+                         file_id(curr_id), file_id(next_id),
+                         curr_living, next_living);
 
       // recursively follow any branches rooted here
-      boost::shared_ptr<rcs_delta> curr_delta = 
r.deltas.find(curr_version)->second;
+      shared_ptr<rcs_delta> curr_delta = r.deltas.find(curr_version)->second;
       for(vector<string>::const_iterator i = curr_delta->branches.begin();
          i != curr_delta->branches.end(); ++i)
        {
          L(F("following RCS branch %s\n") % (*i));
          vector< piece > branch_lines;
+         shared_ptr<rcs_delta> curr_delta = r.deltas.find(*i)->second;
+         bool branch_living = delta_live_p(curr_delta);
          construct_version(*curr_lines, *i, branch_lines, r);
          
          data branch_data;
@@ -426,7 +429,8 @@
          cvs.push_branch (r, curr_version);
 
          cvs.note_file_edge (r, curr_version, *i,
-                             file_id(curr_id), file_id(branch_id));
+                             file_id(curr_id), file_id(branch_id),
+                             curr_living, branch_living);
 
          process_branch(*i, branch_lines, branch_data, branch_id, r, db, cvs);
          cvs.pop_branch();
@@ -641,8 +642,35 @@
   I(file.size() > 2);
   I(file.substr(file.size() - 2) == string(",v"));
   string ss = file;
+
+  // A file in a directory named Attic is really the same as a file
+  // outside the attic.  In the Attic, the head main branch revision
+  // is dead, but this is also noted in the ,v file itself.  FIXME:
+  // should probably notice and give an error if a file appears both
+  // in the Attic and outside it; this shouldn't happen.
+  string::size_type spos = ss.rfind('/');
+  if (spos != string::npos)
+    {
+      if (spos > 5 && ss.substr(spos - 6, 6) == string("/Attic"))
+       {
+         string nf = ss;
+         nf.erase(spos - 6, 6);
+         L(F("rewriting %s to %s\n") % ss % nf);
+         ss = nf;
+       }
+      else if (spos == 5 && ss.substr(0, 5) == string("Attic"))
+       {
+         string nf = ss;
+         // Also remove the trailing "/".
+         nf.erase(0, 6);
+         L(F("rewriting %s to %s\n") % ss % nf);
+         ss = nf;
+       }
+    }
+
   ui.set_tick_trailer(ss);
   ss.resize(ss.size() - 2);
+
   curr_file = file_path(ss);
 }
 
@@ -713,15 +740,18 @@
   stk.push(s);
 }
 
-void cvs_history::note_file_edge(rcs_file const & r, 
+void cvs_history::note_file_edge(rcs_file const & r,
                                 string const & prev_rcs_version_num,
                                 string const & next_rcs_version_num,
                                 file_id const & prev_version,
-                                file_id const & next_version) 
+                                file_id const & next_version,
+                                bool prev_living,
+                                bool next_living)
 {
 
   cvs_key k;
   shared_ptr<cvs_state> s;
+  bool living;
 
   I(stk.size() > 0);
   I(! curr_file().empty());
@@ -734,11 +737,11 @@
       L(F("noting trunk edge %s : %s -> %s\n") % curr_file
        % next_rcs_version_num
        % prev_rcs_version_num);
-      // find_key_and_state (r, next_rcs_version_num, k, s); // just to create 
it if necessary
       find_key_and_state (r, prev_rcs_version_num, k, s);
       s->in_edges.insert(cvs_file_edge(next_version, curr_file, 
                                       prev_version, curr_file, 
                                       *this));
+      living = next_living;
     }
   else
     {
@@ -750,11 +750,42 @@
       s->in_edges.insert(cvs_file_edge(prev_version, curr_file, 
                                       next_version, curr_file, 
                                       *this));
+      living = prev_living;
     }
   
-  // add this file and youngest version to the manifest if we've never seen it 
before
-  if (head_manifest.find(curr_file) ==  head_manifest.end())
-    head_manifest.insert(make_pair(curr_file, prev_version));
+  // the logic here is a bit obscure.  if we've never seen this file
+  // before, we add its youngest version to the manifest.  however, if
+  // we've seen an explicit deletion for this file, then we *don't*
+  // add the file to the head manifest.  in any case, if this is a
+  // deletion, we make a note to delete the file again when walking
+  // the cvs state tree.  we only bother with this on the trunk, as
+  // branches are taken care of when walking them later.
+  if (stk.size () == 1)
+    {
+      if (head_manifest.find(curr_file) == head_manifest.end())
+       {
+         if (! prev_living)
+           {
+             L(F("file %s at revision %s is dead at first sight\n")
+               % curr_file % prev_version);
+             head_deletions.insert(curr_file);
+           }
+         else if (head_deletions.find(curr_file) == head_deletions.end())
+           {
+             // never saw, and live.
+             L(F("adding file %s at revision %s to manifest\n") % curr_file
+               % prev_version);
+             head_manifest.insert(make_pair(curr_file, prev_version));
+           }
+       }
+    }
+
+  if (! living)
+    {
+      L(F("removing file %s at revision %s from manifest\n") % curr_file
+       % prev_version);
+      s->deletions.insert(curr_file);
+    }
   
   ++n_versions;
 }
@@ -908,6 +939,14 @@
       file_path pth(cvs.path_interner.lookup(f->parent_path));
       state_map[pth] = fid;
     }  
+  for (set<file_path>::const_iterator i = state->deletions.begin();
+       i != state->deletions.end(); ++i)
+    {
+      string s = (*i)();
+      L(F("deleting file %s from manifest\n") % s);
+      state_map.erase(*i);
+    }
+
   L(F("logical changeset from child -> parent has %d file deltas\n")
     % state->in_edges.size());
 }
@@ -925,6 +933,14 @@
       file_path pth(cvs.path_interner.lookup(f->child_path));
       state_map[pth] = fid;
     }  
+  for (set<file_path>::const_iterator i = state->deletions.begin();
+       i != state->deletions.end(); ++i)
+    {
+      string s = (*i)();
+      L(F("deleting file %s from manifest\n") % s);
+      state_map.erase(*i);
+    }
+
   L(F("logical changeset from parent -> child has %d file deltas\n") 
     % state->in_edges.size());
 }
--- testsuite.at
+++ testsuite.at
@@ -109,4 +109,5 @@
 m4_include(tests/t_erename.at)
 m4_include(tests/t_smtp.at)
 m4_include(tests/t_cvsimport.at)
+m4_include(tests/t_cvsimport2.at)
 m4_include(tests/t_proxy.at)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]