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

Checkpointing v1 design

From: Julian Foad <julianfoad_at_apache.org>
Date: Fri, 3 Nov 2017 14:54:54 +0000

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):
   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]
   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"
   X.applied := false

revert X
   # possible syntax "svn revert --changelist X"
   X.applied := false

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

   delete all versions of 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
Received on 2017-11-03 15:55:07 CET

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