subversion-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Julian Foad <julianf...@apache.org>
Subject Checkpointing v1 design
Date Fri, 03 Nov 2017 14:54:54 GMT
After playing with two pre-prototypes and discussing a wide variety of 
ideas on this list, I have given detailed thought to a v1 checkpointing 
design with the following properties:

   * local (not server)
   * built on shelving v1 (patches)
   * main commands are 'checkpoint' to save a new version and 'rollback' 
to revert to version N
   * not intended for making a series of commits
   * designed to integrate with 'changelists' later

This aims to streamline the manual method, which I use myself, of using 
'svn diff' and 'svn patch' to create and apply patches named 
'feature-v1.patch', 'feature-v2.patch', etc.

I plan to go ahead and implement this, in order to have something 
useful. At the same time I will keep an eye on further developments and 
the wider picture.


== Shelving and Checkpointing Commands ==

unshelve X [N]
   assert(not X.applied)
   if (any patch-get-paths(X) is modified):
     warn?
   patch-apply X [N]
   X.applied := true

shelve X [PATH...]
   # X may or may not be previously 'applied'
   assert(any PATH... is modified)
   patch-save(X, PATH...)
   patch-unapply X
   X.applied := false

checkpoint X [PATH...]
   # X may or may not be previously 'applied'
   assert(any PATH... is modified)
   patch-save(X, PATH...)
   X.applied := true

rollback X [N]
   assert(X.applied)
   revert(union( patch-get-files(X, X.current),
                 patch-get-files(X, N) ))
   patch-apply(X, N)
   patch-set-current(X, N)

drop/remove/delete X
   # current syntax "svn shelve --delete X"
   assert(not X.applied)
   patch-delete-all X


== Interaction with existing commands ==

Existing ways to remove a change from the WC are 'revert' and 'commit'.

commit X
   # possible syntax "svn commit --changelist X"
   assert(X.applied)
   commit(patch-get-files(X))
   X.applied := false

revert X
   # possible syntax "svn revert --changelist X"
   assert(X.applied)
   revert(patch-get-files(X))
   X.applied := false

revert PATH...
   revert(PATH...)
   if PATH... includes patch-get-files(X):
     X.active := false


== Low-level Interface ==

patch-save(X, PATH...)
   save diff(PATH...) as 'X-<latest+1>.patch'

patch-apply(X, N=latest)
   apply 'X-N.patch' to the WC

patch-unapply(X, N=latest)
   reverse-apply 'X-N.patch' to the WC

patch-delete-all(X)
   delete all versions of X

patch-get-current(X)
   return N = the maximum '*' in 'X-*.patch'

path-set-current(X, N)
   mark the current applied version of X as being N
   (options: prune all versions greater than N, or set X.current=N,
   or even perhaps 'symlink' 'X-<latest+1>.patch' to 'X-N.patch')

patch-get-files(X, N=latest)
   return the list of (file) paths in X version N


=== Remembering the Applied/Shelved state ===

For each change-set name X, the WC will remember whether X is considered 
to be currently 'applied' to the WC, and if so, at which version N. This 
is needed so that 'rollback' knows (roughly) what to revert, and to a 
lesser degree so that commands like 'shelve' and 'unshelve' can say 
'hold on, you already have [or do not have] that change-set applied'.

The Shelving v1 implementation by default deleted a patch (or rather 
renamed it to '.bak') when unshelving, and when shelving it objected if 
the given name was already shelved. Now in this design we are going to 
keep all versions of X (and 'shelve' will always add a new version) so 
we will store a separate 'applied' flag instead.

Multiple independent change-sets can be active in the WC at the same 
time, like with 'changelists'. Clashes (overlaps) in the list of paths 
affected must be managed manually. (Potential enhancement: add some 
warnings, e.g. if 'rollback' is going to revert a file that is part of 
both the specified change-set and another one.)


=== Rollback and Revert ===

Perhaps one of the trickiest parts is which files will 'rollback' 
revert. Suggestion is union(files in current applied version, files in 
requested version).

May want to check and warn if those files overlap with any other 
currently applied change-set.

Integration with changelists should clarify this.


=== Path spec [PATH...] ===

* is applicable to 'save' commands (shelve, checkpoint)
* is not applicable to other commands
* default is "." like in most svn commands
* is restrictive (restricts operation to PATH...)
* is not tracked or managed
* clashes (same path in more than one applied patch) are not managed

Future considerations:

* when checkpointing, warn if PATH... excludes any paths that were in 
the previous version?
* consider allowing restricting paths on 'apply' commands.


=== Changelists and Terminology ===

Already in this design we see a need to specify a 'change set' which is 
not necessarily in a 'shelved' state. The existing 'changelist' fits 
this concept quite closely. It makes sense to extend it to do so. I even 
suggest 'svn revert|commit --changelist=X' as a possible syntax although 
that won't quite fit the v1 implementation if we haven't integrated with 
changelists yet.

One implication is we need a consistent name to use for the change-sets 
that we are dealing with. 'change-set' is pretty good; 'changelist' has 
the advantage of already existing although I don't like it so much. 
'Shelved change' and 'patch' no longer work when talking about 
modifications in the WC.

I was already finding terminology very awkward (and I have been 
inconsistent in using it) because of the difference between 'shelf' 
(noun) and 'shelve' (verb) and whether a single change-set contains 'a 
change' or 'some changes'. I am glad to have a reason to change it.


=== Roll Forward ===

As a starting point, rollback be destructive, deleting versions newer 
than the target version. As an enhancement, it could be made to keep the 
newer versions and allow rolling forward to them. It could operate like 
the 'undo stack' model commonly found in editing applications, where 
roll-forward (often named 'redo') is possible up until a different 
change is saved to the stack, at which time the possibility is lost.

Auto checkpoint before rollback would then be possible too.


=== Commit Log Messages ===

Each new version should keep any previously specified log message by 
default, and allow it to be replaced or edited.

In 'rollback': keep the latest version of the log message; maybe do not 
even store older versions of it.

This mental model -- unversioned log message, versioned files -- is 
simple and fits well with existing svn concepts.


- Julian

Mime
View raw message