History of the problem:
=======================
Subversion's implementation of renames is problematic. We implement
'svn rename foo bar' as 'svn copy foo bar; svn delete foo'. This is
speaking loosely; we don't actually turn one client operation into
two, of course. But the effect is the same. In the repository, a
rename looks like two events that happen as part of one commit: a copy
of SRC to DST, and a removal of SRC.
The reason we do things this way is, well, stupid. Basically, we let
a detail of working copy implementation impose itself on core
Subversion. The motivating scenario was this:
$ svn mv foo bar
$ svn ci -m "Committing only one side of a rename." bar
(Could just as easily be 'foo' instead of 'bar' in the commit.)
We thought, "Well, if we just treat rename as copy+delete, then the
above scenario works consistently, no matter whether the user
specifies both SRC and DST or just one." Of course, this solution
makes it difficult to distinguish between renames and copies/deletes
in the repository, and it loses object identity (!). Somehow we
thought that was okay at the time. I don't know what we were smoking.
I was one of the advocates of this line of thinking, perhaps the
principal advocate, and I hereby recant. I was wrong. I was so
wrong. Honey, can you ever forgive me for what I did? Can't we make
this work, somehow?
A Multi-Staged Solution:
========================
Fixing rename should happen in stages, because it involves several
entirely separable tasks. The stages I have in mind are:
1. Implement true renames in the repository. That is, implement
svn_fs_rename() and whatever associated machinery goes along
with it, and make 'svn rename URL1 URL2' use it.
Complications:
Search in issue #898 for the word "subtle", and you will see a
big diagram from me and Mike Pilato that shows why implementing
svn_fs_rename() is not quite as trivial as one might think.
Notes:
Commits from a working copy would not use this functionality
yet. That comes in stage 2. Also, updates would not try to do
any fancy copying to be efficient; they'd continue to receive a
'delete' directive and an 'add with history' directive, and get
the whole new file from the RA layer, just as they do now.
Making updates more efficient is stage 3.
2. Support true renames from working copy commits. This means that
when you do 'svn rename foo bar' in a working copy, foo's entry
knows this it is a rename source and knows the dest, and bar's
entry knows it is a rename dest and knows the source.
If you try to commit just one side of a rename, the client
library will error articulately, telling you that you must
commit either all or none of a rename, and pointing you to the
other side. I think this is appropriate, because by running
'svn rename' (or the GUI equivalent), the user has expressed
their intention that this is all one operation. The client
library should protect the user from contradicting themselves
later.
This stage would also have to ensure support for the
rename+modification scenario described in issue #898. As the
issue says, there really aren't any major complications there,
it really should just work "out of the box". However, stage 2
is the first moment where this becomes an issue, so we should
not
3. (optional) Support efficient use of working-copy-side data when
update receives a rename. This is merely a matter of
performance, not correctness. The idea is that if the RA layer
transmits a rename from server to client, and the client already
has the source, then the server can just tell the client to mv
the source to the dest, and maybe apply a diff if there are
modifications too.
What To Do Right Now:
=====================
I think we should aim to do stage 1 for Subversion 1.3.
That means finding a solution for the repository node-revision ID
problem described in issue #898.
I'm not going to resummarize here the problem described in the issue,
or the solutions outlined there. Anyone who cares about this enough
to enter the discussion, please just look at #898. Note that the
diagram is in the extra-formal style preferred by me and (apparently)
no one else: the path components do not label the directories they
appear in, but rather represent directory *entries* and name the thing
they're pointing to in the next level down. Thus, all rectangular
objects are directories, and the lone file just appears as "(file)".
So, seeing the problem there, does anyone have any thoughts for an
elegant solution?
-Karl
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri May 20 19:57:17 2005