On Mon, Dec 18, 2000 at 04:27:52PM -0800, Greg Stein wrote:
>...
> In the checkout case, it appears (again) only the revision is needed.
>
> It seems the path is only important on the commit side of things, as a way
> of tracking the ancestry of a change.
>
> It is non-orthogonal (the client doesn't need the path) because the client
> is a snapshot of state. It doesn't care *where* it came from. It is only
> concerned with changes made to it. (the client uses "svn log" to discover
> history information)
>
> [think think think]
>
> We have four "main" editor processes, and in all cases, the revision *must*
> be supplied to the editor:
>
> 1) report revision status [to determine what must be updated]
> - definitely need the revision; don't need the path, though
>
> 2) apply updates to the WC
> - need the revision so the WC knows what rev is now in the WC
>
> 3) commit WC changes to the server
> - need the path/revision pair to describe ancestry from a move/copy
> - need the revision to specify what a diff was built against
> - add file/dir: revision is N/A
>
> 4) checkout fresh source from the server
> - need the revision so the WC knows what rev is now in the WC
>
>
> How about if we upgrade revision to generally "required", and the "start
> from scratch" case allows a NULL/INVALID_REVNUM pair if there is no
> ancestor? And the path element is typically NULL.
[ thought more on the problem while running errands ]
We aren't supplying enough information in the editor callbacks.
Consider the case of "svn copy" (replacing a file) and then a commit. This
will map into a replace_file() call. We need to tell the system three pieces
of information:
1) the revision of the file we're replacing (was it the latest?)
2) the path of the file we copied
3) the revision of the file we copied
If we enumerate the different types of editor processes, and the add/replace
file/dir callbacks:
1) report revision status:
a) add: old_revision=N/A, copyfrom_path=PATH|NULL,
copyfrom_revision=REV|INVALID
b) replace: old_revision=REV, copyfrom_path=PATH|NULL,
copyfrom_revision=REV|INVALID
[ these are the raw calls involved; the report editor will probably
collapse these into "I have a file/dir here, possibly from <path>, with
revision <rev>, possibly with local changes" ]
2) apply update to the WC:
a) add: old_revision=N/A, copyfrom_path=NULL, copyfrom_rev=THIS_REV
b) replace: old_revision=DIFF_BASE_REV, copyfrom_path=NULL,
copyfrom_rev=THIS_REV
path=NULL, rev=REV implies "this isn't copied from anywhere, and it
refers to revision REV." Contrast with (1) which can say, "it was copied
from revision REV of path PATH." In both cases, REV is the stated
revision for the resource.
3) commit WC changes: same as (1)
If the replace() copied from somewhere, then old_revision describes what
revision was replaced. If there is no copy, then old_revision specifies
the base for a "diff".
4) checkout:
a) add: old_revision=N/A, copyfrom_path=NULL, copyfrom_rev=THIS_REV
b) replace: not used
This is the same as (2), but replace_*() is not used.
This gives us the two behaviors that we want to track:
1) specify the base revision that we are replacing
2) specify the ancestry when copying from another resource
Now, for some simpliciation. Note that the "add" case never specifies an
old_revision, so we're back to just the copyfrom_* parameters (although we
use them in two different ways). Here is a description of the semantics for
each combination of parameters:
ADD semantics:
*) 1a, 3a: added a file, which may be a copy of COPYFROM, possibly with
additional changes against that PATH/REV.
(PATH, REV) or (NULL, INVALID)
*) 2a, 4a: here is rev THIS_REV of the file
(THIS_REV)
REPLACE semantics:
*) 1b: replaced revision REV of a file with new content, which may be a
copy of COPYFROM
(OLD_REV, PATH, REV) or (OLD_REV, NULL, INVALID)
*) 2b: here is a diff against DIFF_BASE_REV of this file, it will be
called THIS_REV after the update.
(DIFF_BASE_REV, THIS_REV)
*) 3b: here is a diff against DIFF_BASE_REV of this file
(DIFF_BASE_REV, NULL, INVALID)
*) 3b: revision REV of this file was replaced with COPYFROM, possibly with
additional changes against that PATH/REV.
(OLD_REV, PATH, REV)
[ hmm.... where to go with this... trying to find the "right" semantics ]
Okay. Let's do the ballon treatment and expand completely:
add_* (void)
set_revision (THIS_REV)
replace_* (OLD_REV)
copy_*_from (PATH, REV)
apply_txdelta (void)
[ parameters not relevant to this discussion omitted ]
And then rejigger the process a bit:
1a) add_*(), maybe followed by copy_*_from(), maybe followed by
apply_txdelta (the txdelta is optional cuz there may be no changes to
the copied resource)
1b) replace_*(OLD_REV), maybed followed by copy_*_from()
[ on status reporting, we may not need the copyfrom information; the
server will not issue an update against the copied resource, but it
could issue a conflict if OLD_REV < LATEST_REV ]
2a) add_*(), followed by apply_txdelta(), followed by set_revision(THIS_REV)
2b) replace_*(OLD_REV), followed by apply_txdelta(), followed by
set_revision(THIS_REV)
3a) add_*(), maybe followed by copy_*_from(), maybe followed by
apply_txdelta()
3b) replace_*(OLD_REV), maybe followed by copy_*_from(), maybe followed by
apply_txdelta()
4a) same as (2a): add_*(), followed by apply_txdelta(), followed by
set_revision(THIS_REV)
Okay... enough stream of consciousness for now :-)
Thoughts on the direction? Basically, I think that I'm proposing to rejigger
the editor callbacks' params, and to add set_revision() and copy_*_from().
There could very well be some simplification / collapsing of the interface;
this has all been pretty much on the fly and still needs to settle a bit in
my head.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
Received on Sat Oct 21 14:36:17 2006