[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [#61071] New features: VC timemachine and BackupOnSave to RCS

From: John Yates
Subject: Re: [#61071] New features: VC timemachine and BackupOnSave to RCS
Date: Sat, 28 Jan 2023 09:35:09 -0500


Here are the commit messages from the three patches.  Each provides
independently useful functionality.

Following the commit messages I provide a discussion of some known
open issues.

If these descriptions are insufficient to understand the new features,
please suggest, relative to what I am already describing in these
messages, how the descriptions could be improved.



[PATCH 1/3] Refactor and document vc-find-revision caching

Previously there existed two helper functions for vc--revision-other-window:

* vc--revision-other-window-save
* vc--revision-other-window-no-save

The expectation seems to have been that when materializing a revision is
deemed costly (slow backend? remote? ...) it should be saved.  I believe
that, even though the word 'cache' is never used, this was intended to
be a caching mechanism.  That said, the logic provided only a single
save/no-save global toggle.  Aspects of this mechanism were discussed
in this email thread:


I have tried to address some of the concerns raised therein and to
provide some clearer abstractions:

* When a revision gets saved it is deemed a cache.  Thus it is imperative
  that the cached revision be protected and adequately validated before
  being reused.

* A cached revision may be saved as a sibling of the file that triggered its
  materialization or it may be saved in a mirror directory tree rooted at
  `vc-cache-root'.  The latter choice avoids cluttering work trees with
  historic revisions and enables caching across work trees.  `vc-cache-root'
  will also provide a location for the forthcoming vc-bos's backups.

* I have defined the concept of a revision buffer.  This is the form
  of buffer returned by vc's find-revision operation.  It is bound to
  a specific revision, it is read-only and it has a nil buffer-file-name.
  Thus it visits no saved nor cached file.  The rationale is twofold:

  - A revision is a materialization of immutable history

  - The only potential value for a revision buffer's buffer-file-name is a
    cache file which should likewise be regarded as immutable.  Further, if
    materializing revisions is not deemed costly, even that file may not
    exist.  So, in the interest of consistency, revision buffers do not
    visit files.


[PATCH 2/3] Introduce VC timemachine capability

Introducing timemachine functionality into vc was discussed in this thread:


Where the previous commit introduced the concept of a revision buffer bound
to a unique revision, this commit introduces the concept of a timemachine
buffer, bound to the linear sequence of revisions on the branch from which
a work file was checked out.

`vc-tm-revision-head creates' a timemachine buffer, which then behaves as
a cursor over the linear sequence of revisions on a branch.  The buffer can
be repositioned along that branch via:

- `vc-tm-revision-next'
  "Show work file's next revision on checked-out branch."

- `vc-tm-revision-previous'
  "Show work file's previous revision on checked-out branch."

- `vc-tm-revision-nth'
  "Show work file's N'th most recent revision on checked-out branch
  (1 being HEAD)."

- `vc-tm-revision-complete-subject'
  "Show work file's revision via subject completion on checked-out branch."

A timemachine buffer is read-only and has a nil buffer-file-name (meaning
that it is not visiting any file).  The rationale is exactly the same as
for a revision buffer: a timemachine buffer displays immutable history.

To support timemachine functionality a backend needs to support the new
tm-revisions vc operation.  Optionally, it may support the tm-map-line
operation.  In this commit vc-rcs supports only tm-revisions while vc-git
supports both operations.

My implementation borrows design ideas and code from Peter Stiernström's
original git-timemachine.el.  In reality, my effort was little more than an
extended refactoring effort to fit git-timemachine into the vc framework.


Subject: [PATCH 3/3] Introduce vc-bos: backup on save (to an RCS file)

The dream of this vc-bos capability was what first got me working on
vc-timemachine.  From vc-bos.el's front-matter:

    ;; Modern version control systems, such as git, are wonderful.  But they
    ;; have drawbacks when dealing with lightweight save operations:
    ;; * Too invasive: new revisions are created only by explicitly action;
    ;;   this includes supplying a commit message (even if empty)
    ;; * Too coarse: a revision captures an entire "project"
    ;; * Too smart: even files listed in .gitignore (or equivalent) remain
    ;;   eligible for editing and hence deserve to get backed-up
    ;; * Requires setup: what about files that have no project?
    ;; Enter vc-bos...
    ;; vc-bos provides easy access to past revisions of edited files by
    ;; integrating with VC's timemachine functionality.  To do this it
    ;; requires that VC's vc-cache-root be set and that it have '/RCS' as
    ;; one of its directory components (typically the last).
    ;; Given such a configuration, vc-bos maintains a mirror tree of RCS
    ;; control files below vc-cache-root.  A control file appears at the
    ;; same position and has exactly the same name as the file that it
    ;; tracks (meaning no ',v' suffix).  This works because RCS treats
    ;; *any* file *anywhere* beneath an RCS directory as a control file.
    ;; On FIRST change and EVERY subsequent save cx-bos:
    ;; * Qualifies the buffer's path
    ;; * Ensures existence of a mirror directory beneath vc-cache-root
    ;; * Records the newly saved file as the latest RCS revision with
    ;;   an empty commit message
    ;; vc-bos's tracking is independent of whether a file is tracked by
    ;; any other VCS.

Thus, vc-bos is both a minimally invasive way to capture save history for
arbitrary files and a convenient way of accessing that history.



When I started this work I already had BOSTR (my backup on save to
RCS) functionality working.  Creating those backups worked exactly as
I desired.  That included creating the backups in a shadow tree

The problem was recovering a backup.  Doing that required using VC or
RCS via the command-line on a history with no commit messages, only
time stamps.  That was not a happy user experience.  I was familiar
with git-timemachine and desired an equivalently light-weight means of
exploring my backups.

Thus my effort proceeded in three stages (to whit, the above three

* Integrate BOSTR's mirror directory tree with VC's notion of saving
  backups when retrieving a revision

* Refactor git-timemachine into a shared vc-timemachine component and
  a per backend pair of abstractions; implement those abstractions for
  git and RCS

* Move the remainder of BOSTR as vc-bos; in vc-prefix-map, bind ","
  to vc-tm-revision-head to open a timemachine on backed-up revisions
  of the current file

Open items:

* Eli has already pointed out that, to comply with Emacs conventions,
  vc-tm-revision-next and vc-tm-revision-previous need to accept a
  numeric argument.  This will be trivial to address.

* The greatest weakness is in the cache area.  Often revisions are
  opened using a symbolic name.  If caching is enabled (it is off by
  default) then the revision gets cached under that symbolic name, not
  using its canonical ID.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]