http://bugs.grommit.com/show_bug.cgi?id=347

           Summary: recommit can strip local changes in such a way as to
                    corrupt the manifest
           Product: SCM Migration
           Version: unspecified
          Platform: All
        OS/Version: Solaris 11/Nevada
            Status: NEW
          Severity: blocker
          Priority: P1
         Component: cdm
        AssignedTo: scm-migration-dev at opensolaris.org
        ReportedBy: richlowe at richlowe.net


Bart had a completely linear workspace, with a change he intended to putback.

Someone else made a change in the gate he had to merge with, leaving
him like this.

Before    Merge    After

                     *             
                     |\                       
    *                | *            
  * |                * |                    
  | |       ->       | |            
  |/                 |/             
  *                  *              
  |                  |              


Then he recommitted with the old Hg, which failed (because Hg was old)
and left his workspace at the new rev from the gate.  

At this point his change was linear, merge-turd free, and totally the
right thing.  Except Bart didn't know that...

He thought his change had vanished (it hadn't), and restored it.

Which left him like this:

                          *  <- Bart's change from the first recommit
                          |
                          *  <- change from gate
Bart's change again ->  * |
                        | |
                        |/          
                        *
                        |   

Which left him with two heads again, so he merged again:

 Before     Merge    After

                       *
                       |\
    *                  | *
    |                  | |
    *       ->         | *
  * |                  * | 
  | |                  | |
  |/                   |/ 
  *                    *  
  |                    |                           

So, at this point we have Bart's change, twice, a random change, and a
merge (+ (Bart's change) (+ (Bart's change) (random change)))

Recommit does this:

  Takes those outgoing changes, commits them above the parent tip (the
  newest common node, in this case the change from the gate).

113 -> *  *    <- 112
       |  |\              
        \ | *  <- 110
          \ |
          | *  <- 109
          * |  <- 111
          | |
          |/ 
          *    <- 108
          |   

  where 113 is the reci, 108 the base, 109 the parent tip, 110 is the
  result of the first reci (the one Bart thought failed), and 111 the
  restored changes he thought were gone forever.

  reci then strips the now superfluous changes (the complete subgraphs
  rooted at 110 and 111)

  Removing 110 and 111 leave us (maintaining revnos, despite them
  changing, we really mean nodes here):

             110          Strip        111         

               * <- 113                  * <- 113
               |                         |  
               * <- 109    ->            * <- 109    
      111 -> * |                         |
             | |                         |
             |/                          |
      108 -> *                    108 -> *        
             |                           |        

  Which looks great, exactly what we wanted to happen, right?

  Except the manifest entry for 113 above has a linkrev that now doesn't exist 
  (it refers to the a revno one higher than exists), which doesn't exist, and 
  the workspace is corrupt.

  After the strip of 110 the manifests look thusly:

   109     82752      76     51     109 c70da36d808c 047eabe09854 000000000000
   110     82828     237     51     111 ce97ffb9392c c70da36d808c 000000000000
   111     83065     153     51     111 c5c6709cd76c 047eabe09854 000000000000

  Where the mapping to our simplified numbering is:
   109 -> random change from the gate (109)
   110 -> recommitted change   (113)
   111 -> Bart's change  (111)

  So we have two changes with the same linkrev.  This is already
  bogus, as best as I can tell.  What really nails it, however, is
  when we remove 111, so the link rev referred to in the recommitted
  change no longer exists.  Kablam.

  The first strip did something pretty bad, the second strip made it fatal.

  Now, experimentally, if these are done in reverse order (111 removed
  before 110), everything is fine.  However, when I was testing the logic
  for removing multiple child-local branches, I had workspaces where the
reverse
  was true.  There's something subtly order dependent about stripping these
and, 
  currently, I don't know what it is.

  Investigation continues...


-- 
Configure bugmail: http://bugs.grommit.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

Reply via email to