You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Ben Collins-Sussman <su...@newton.ch.collab.net> on 2001/03/17 14:36:24 UTC

commit logic.

I assume you all saw the bug that Fitz posted and Mike analyzed.

Namely, if your wc is at revision 1, *except* for `iota', which is at
revision 2, and then you try to commit a local mod on iota -- you get
an error.

Mike correctly analyzed the problem:  the fs commit editor is
currently operating under the assumption that the commit is happening
on a single pristine tree.  We haven't taught it how to deal with a
mixed-revision working copy yet.  (We've been planning to. :))

But this is *exactly* the problem that Jim and I talked on the phone
about, and then I argued with Karl about.  I still don't understand
the resolution to this problem.  Jim and I came up with something, I
think, but then Karl pointed out that the problem isn't fixed.

We need to talk about this.

----------------------------

If I'm committing on transaction that is originally based on revision
1, and suddenly the client calls replace_file(baserev=2), what is the
proper behavior?

Ben's first instinct was:  oh, in that case, replace_file should do an
fs_copy of the the immutable node 2:/path/to/iota into our transaction.

Jim's argument was:  but how do we know that 2:/path/to/iota even
exists?  Somebody may have renamed iota's parent dir in rev. 2!

Jim's solution was:  punt on the problem, and instead declare that
replace_file() was called erroneously.  New rule that editor-drivers
must follow:  if you try to commit a target that it at a "unexpected"
rev, (i.e. a rev you wouldn't expect to find in a parent of a
different rev) then the driver must call delete(iota), and then
add_file(iota, copyfrom=2:/path/to/iota).

Karl's objection was: I don't see how this solves the problem.  The
client *still* doesn't know that 2:/path/to/iota exists.  Calling
{delete, add} has the exact same effect on the transaction as if
replace_file() had called {fs_copy}, and the same set of assumptions.

Ben's thought is:  The user ended up with rev.2 of iota in one of two
ways:

    1. he committed iota, creating revision 2 in the fs.

    2. he did an `svn update iota'.

In case 1, we *know* that 2:/path/to/iota exists, so we're ok.

In case 2, we don't know that the path exists.  BUT:  I ask here --
if, when somebody else created revision 2, renamed one of iota's
parent dirs, wouldn't the update command fail in the first place?
Wouldn't the user get an error saying 

   "sorry, I can't update iota for you. because I can't find
    /path/to/iota in the head revision.  One of iota's parents is
    out-of-date; please update at a higher point in your working
    copy."

Once again, we come back to the issue of how to do partial updates.
Ugh.  :)

Re: commit logic.

Posted by Ben Collins-Sussman <su...@newton.ch.collab.net>.
Great.  Just phoned Karl, and he agrees with this analysis.  Mike,
either one of us can fix the bug just as we would expect to.  Go ahead
and assume that replace_*() functions need to call fs_copy when they
get an unexpected base_rev argument.  (And don't forget that our
dir_batons now need to store local revision numbers too!)




cmpilato@collab.net writes:

> Ben Collins-Sussman <su...@newton.ch.collab.net> writes:
> 
> > If I'm committing on transaction that is originally based on revision
> > 1, and suddenly the client calls replace_file(baserev=2), what is the
> > proper behavior?
> > 
> > Ben's first instinct was:  oh, in that case, replace_file should do an
> > fs_copy of the the immutable node 2:/path/to/iota into our transaction.
> 
> This was Mike's first thought after a night of sleep.  And until
> reading your mail, Ben, I had started to believe that I *was*
> qualified to fix this bug! :-)
> 
> > Jim's argument was:  but how do we know that 2:/path/to/iota even
> > exists?  Somebody may have renamed iota's parent dir in rev. 2!
> 
> This is a serious bug that needs to be addressed yesterday, which is
> to say, regardless the proper solution to the unexpected revision
> number issue, it is unacceptable to have an error message as obscure
> as "Delta source ended unexpectedly" come out of this situation.  I
> spent over an hour looking into this from the delta point of view
> before realizing what was really going on.  Right now, we have no
> immediate support for the rename action anyway.
> 
> > In case 2, we don't know that the path exists.  BUT:  I ask here --
> > if, when somebody else created revision 2, renamed one of iota's
> > parent dirs, wouldn't the update command fail in the first place?
> > Wouldn't the user get an error saying 
> > 
> >    "sorry, I can't update iota for you. because I can't find
> >     /path/to/iota in the head revision.  One of iota's parents is
> >     out-of-date; please update at a higher point in your working
> >     copy."
> 
> This is my thinking as well.

Re: commit logic.

Posted by Ben Collins-Sussman <su...@newton.ch.collab.net>.
Jim, you wanted some kind of "proof" that it's okay to call
svn_fs_copy inside of replace_dir() and replace_file().  Let me see if
I can summarize here.

We're crawling a local copy and are in directory D, at revision N.  We
notice an entry E needs to be committed, but E is at revision M.  The
driver calls replace_*(E, baserev=M).

On the editor side, is it valid to call svn_fs_copy(M, /path/to/D/E,
txn, /path/to/D/E)?  How do we know that the path to E in M is the
*same* as the path in E in N?

Proof by contradiction: assume that the path to E is M is *not* the
same as the path to E in N.

How did the user end up with their working copy state?

  1.  The user had revision N of E, changed E, committed, thereby
      creating revision M, and resulting in only E being
      revision-bumped.  But then the paths to E would be the same in
      both revisions.  Contradiction.

  or

  2.  The user selectively updated E, not its parent.  But in updating
      E to M, the filesystem *must* have been been able to find E in
      the same location as in N.  (Else it would have returned
      out-of-date error.)  Thus the paths are the same in N and M.
      Contradiction.

Jim, is this the proof you were looking for?  Are we out of the
theoretical woods?  :)

Re: commit logic.

Posted by cm...@collab.net.
Ben Collins-Sussman <su...@newton.ch.collab.net> writes:

> If I'm committing on transaction that is originally based on revision
> 1, and suddenly the client calls replace_file(baserev=2), what is the
> proper behavior?
> 
> Ben's first instinct was:  oh, in that case, replace_file should do an
> fs_copy of the the immutable node 2:/path/to/iota into our transaction.

This was Mike's first thought after a night of sleep.  And until
reading your mail, Ben, I had started to believe that I *was*
qualified to fix this bug! :-)

> Jim's argument was:  but how do we know that 2:/path/to/iota even
> exists?  Somebody may have renamed iota's parent dir in rev. 2!

This is a serious bug that needs to be addressed yesterday, which is
to say, regardless the proper solution to the unexpected revision
number issue, it is unacceptable to have an error message as obscure
as "Delta source ended unexpectedly" come out of this situation.  I
spent over an hour looking into this from the delta point of view
before realizing what was really going on.  Right now, we have no
immediate support for the rename action anyway.

> In case 2, we don't know that the path exists.  BUT:  I ask here --
> if, when somebody else created revision 2, renamed one of iota's
> parent dirs, wouldn't the update command fail in the first place?
> Wouldn't the user get an error saying 
> 
>    "sorry, I can't update iota for you. because I can't find
>     /path/to/iota in the head revision.  One of iota's parents is
>     out-of-date; please update at a higher point in your working
>     copy."

This is my thinking as well.