[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

How should update-over-replace behave? (issue #3282)

From: Karl Fogel <kfogel_at_red-bean.com>
Date: Wed, 10 Sep 2008 17:30:38 -0400

I know this post is long, but I couldn't think of any way to explain
the situation other than to transcribe it. Once you've read it, a
summary would make sense, but not before :-).

This is about a semi-corruption bug: the working copy and repository
can get out-of-sync with each other and not know it. (See issue #3282.)

The question at hand is, how should Subversion behave when it receives
an update to a file that is already schedule-replace? (I realize as I
ask this that it's sort of a tree-conflict issue.)

The right answer, I think, is that:

   a) First of all, a schedule-replace file should have .svn-revert
      base files instead of .svn-base (obviously), and

   b) After being updated, the file should still be schedule-replace,
      with its revert-bases still in place, but those bases should
      have the new text and new props. In other words, it should be
      just as though the user "replaced" the new file.

Does this sound sane?

Now let's look at what actually happens. The following sequence of
commands sets up the scenario:

   svn co $repos_url wc1
   svn co $repos_url wc2
   
   cd wc1
   echo "original foo" > foo
   svn add foo
   svn propset p v foo
   svn ci -m "Create foo, with both text and properties."
   cd ..
   
   cd wc2
   svn up
   echo "change to foo, made in the other wc" > foo
   svn ci -m "Change foo from wc2."
   cd ..
   
   cd wc1
   svn rm foo
   echo "replace foo, in original wc" > foo
   svn add foo
   # Now update, receiving changes (to old foo) on top of the
   # schedule-replace (new) foo:
   svn up
   cd ..

Here's what happens currently:

Right after the replacement, but *before* that final 'svn up' in wc1,
this is the situation in wc1:
 
   $ cat .svn/entries | imagine-fancy-grep-command-for-entry-foo
   foo
   file
   1
   
   
   replace
   2008-09-10T20:24:31.000000Z

   2008-09-10T20:24:31.292007Z
   1
   kfogel
   [... many blank lines omitted ...]
   13 # (that's the number of bytes, if you didn't remember)
   $ ls .svn/text-base/
   foo.svn-base
   $ ls .svn/prop-base/
   foo.svn-base
   $ ls .svn/props/
   $ cat .svn/text-base/foo.svn-base
   original foo
   $ cat .svn/prop-base/foo.svn-base
   K 1
   p
   V 1
   v
   END
   $

Before we run the 'svn up', note some things:

   1. Despite the the fact that foo is schedule-replace, its text-base
      and prop-base files are still in their original locations (i.e.,
      'foo.svn-base', not 'foo.svn-revert'). I think this is wrong,
      as per issue #3282, and am trying to fix it.

   2. Note that the 'foo' entry lists no checksum (it would be where
      the blank line is between the two dates). This is expected:
      when a file become schedule-replace, the entry loses its
      checksum.

Okay, now we run 'svn up' and receive the changes from wc2 on top of
the schedule-replace 'foo' (in wc1):

   $ svn up
   Conflict discovered in 'foo'.
   Select: (p) postpone, (df) diff-full, (e) edit,
           (mc) mine-conflict, (tc) theirs-conflict,
           (s) show all options: p
   C foo
   Updated to revision 2.
   $ cat .svn/entries | imagine-fancy-grep-command-for-entry-foo
   foo
   file
   
   
   
   replace
   
   
   2008-09-10T20:24:33.224621Z
   2
   kfogel
   
   has-prop-mods
   
   
   
   foo.r1
   foo.r2
   foo.mine
   $ ls .svn/text-base/
   foo.svn-base
   $ ls .svn/prop-base/
   foo.svn-base
   $ ls .svn/props/
   foo.svn-work
   $ cat .svn/text-base/foo.svn-base
   change foo in the other wc
   $ cat .svn/prop-base/foo.svn-base
   K 1
   p
   V 1
   v
   END
   $ cat .svn/props/foo.svn-work
   $ ls -l .svn/props/foo.svn-work
   -r--r--r-- 1 kfogel kfogel 0 2008-09-10 16:37 .svn/props/foo.svn-work
   $ svn st -vu
   CM 2 2 kfogel foo
   ? foo.r1
   ? foo.r2
   ? foo.mine
                   2 2 kfogel .
   Status against revision: 2
   $

So, most signs that this file was ever scheduled for replacement are
gone. It now has a working props file, and the entry says it
'has-props' (meaning there are mods w.r.t. the prop-base). But
although the .svn/props/foo.svn-work file exists, it is empty.

My patch (in progress) for issue #3282 solves the "replacment doesn't
move old base files aside" problem: the old foo.svn-base files will
now become foo.svn-revert files as soon as we add the replacement foo.
But when we update, the new changes come in and affect the revert
files, which would be fine if the file stayed schedule-replace, but it
doesn't. Well here, maybe it's better if I show you what happens with
my patch:

Again, this is right after the replacement but before the update:

   $ cat .svn/entries | imagine-fancy-grep-command-for-entry-foo
   foo
   file
   1
   
   
   replace
   2008-09-10T20:54:49.000000Z
   
   2008-09-10T20:54:49.310135Z
   1
   kfogel
   [...]
   13
   $ ls .svn/text-base/
   foo.svn-revert
   $ ls .svn/prop-base/
   foo.svn-revert
   $ ls .svn/props/
   $ cat .svn/text-base/foo.svn-revert
   original foo
   $ cat .svn/prop-base/foo.svn-revert
   K 1
   p
   V 1
   v
   END
   $

Good! I think that's exactly how things should look, for a
schedule-replace file (i.e. the replacement has not been committed).

Now let's run 'svn up' and see what happens:

   $ svn up
   Conflict discovered in 'foo'.
   Select: (p) postpone, (df) diff-full, (e) edit,
           (mc) mine-conflict, (tc) theirs-conflict,
           (s) show all options: p
   CU foo
   Updated to revision 2.
   $ cat .svn/entries | imagine-fancy-grep-command-for-entry-foo
   foo
   file
   
   
   
   
   
   
   2008-09-10T20:54:51.241517Z
   2
   kfogel
   has-props
   
   
   
   
   foo.r1
   foo.r2
   foo.mine
   $ ls .svn/text-base/
   foo.svn-revert
   $ ls .svn/prop-base/
   foo.svn-base foo.svn-revert
   $ ls .svn/props/
   $ cat .svn/text-base/foo.svn-revert
   change foo in the other wc
   $ cat .svn/prop-base/foo.svn-base
   K 1
   p
   V 1
   v
   END
   $ cat .svn/prop-base/foo.svn-revert
   K 1
   p
   V 1
   v
   END
   $ svn st -vu
   C 2 2 kfogel foo
   ? foo.r1
   ? foo.r2
   ? foo.mine
                   2 2 kfogel .
   Status against revision: 2
   $

There is so much wrongness here I don't know where to start :-).
(Some of it might be due to my patch, and it would be interesting to
run the 'svn up' part using a pristine Subversion, but I don't want to
make this mail more complicated than it already is.)

Some things to note:

   1. Again, the file no longer thinks it's schedule-replace after the
      update. That seems bad.

   2. We have revert-base files for both text and props, but we *also*
      have a regular base file for props now (and it contains the same
      text as the revert-base). WTF?

   3. This time, the update printed 'CU' instead of just 'C'. It
      thinks it received a prop update. I don't know why.

   4. But 'svn st' thinks the file has only a textual conflict now,
      with no property modification. That's good, I guess.

Anyway, now we're back to my original question: what should happen?

My answer is that the file should still be schedule-replace, still
have revert-bases (and no regular bases), the revert-bases should have
the new content. The working file should *not* be in conflict, but
should simply have the same replacement text it had before the update.

Does anyone think that's the wrong goal?

-Karl

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-09-10 23:30:52 CEST

This is an archived mail posted to the Subversion Dev mailing list.