349 lines
14 KiB
Plaintext
349 lines
14 KiB
Plaintext
* General
|
|
|
|
xmtn is an Emacs Lisp package that provides a DVC backend for monotone
|
|
(the distributed version control system) as well as general facilities
|
|
for interacting with monotone from Emacs Lisp.
|
|
|
|
For more information about monotone, see http://monotone.ca/ .
|
|
|
|
xmtn's facilities for interacting with monotone are meant to be
|
|
reusable by code that is unrelated to DVC, even though they currently
|
|
depend on the subprocess handling utilities that DVC provides.
|
|
|
|
xmtn should work on GNU Emacs 21 or newer. Work on supporting XEmacs
|
|
has started but is unfinished; patches welcome. On XEmacs, xmtn
|
|
requires MULE.
|
|
|
|
|
|
* Download and installation
|
|
|
|
Follow the download and installation instructions for DVC. xmtn is
|
|
part of DVC.
|
|
|
|
In addition, the variable `xmtn-executable' needs to point to the
|
|
monotone executable. It defaults to "mtn", which will be sufficient
|
|
if mtn is in your PATH. Depending on your configuration, the PATH
|
|
that Emacs sees can differ from the PATH that you see in your shell.
|
|
Try M-x getenv RET PATH RET if in doubt.
|
|
|
|
You may wish to set `dvc-debug' to nil; DVC tends to be a bit chatty.
|
|
|
|
|
|
|
|
* Brief tutorial
|
|
|
|
(DVC's tutorial does not apply to xmtn, it seems to be specific to
|
|
tla.)
|
|
|
|
Start Emacs. Visit a file that is under version control by monotone.
|
|
Modify the file. While in the file's buffer, press C-x V d to see the
|
|
diff for this file.
|
|
|
|
Pressing C-x V = will bring up the tree diff buffer. (What monotone
|
|
calls a "workspace" is called a "tree" in DVC.) This buffer shows the
|
|
list of all modified files in the tree as well as the diffs for those
|
|
files. Use j to jump back and forth between the name of a file in the
|
|
list and the diffs for that file. Use RET with point inside a diff
|
|
hunk to go to the corresponding file at the corresponding position.
|
|
|
|
Like many other DVC buffers, the contents of the tree diff buffer can
|
|
be refreshed using g.
|
|
|
|
In the tree diff buffer, files to commit can be marked and unmarked
|
|
with m and u. Pressing c lets you commit the selected files; it will
|
|
bring up a log edit buffer where you can enter a commit message.
|
|
|
|
In the log edit buffer, the commit can be executed by pressing C-c
|
|
C-c. To abort the commit, simply don't press C-c C-c -- just switch
|
|
away from the buffer or kill it. The log edit buffer edits the file
|
|
_MTN/log.
|
|
|
|
To bring up the log edit buffer without going through the tree diff
|
|
buffer, use C-x V c.
|
|
|
|
To view the revision history, use C-x V l or C-x V L. The former
|
|
shows the full commit message for each revision, while the latter only
|
|
shows the first line. The resulting buffer is a so-called revlist
|
|
buffer. In revlist buffers, use cursor up/down to move between
|
|
revisions, RET to show details on the revision at point, = to show its
|
|
diff from its parent. Revisions can be marked and unmarked with m and
|
|
u.
|
|
|
|
M-x xmtn-view-heads-revlist shows a revlist buffer with just the heads
|
|
of the default branch of your tree. To update your tree to one of the
|
|
revisions in a revlist buffer, move point to it and use M-x
|
|
xmtn-revlist-update. To merge two head revisions, mark them and use
|
|
M-x xmtn-revlist-explicit-merge.
|
|
|
|
M-x xmtn-view-revlist-for-selector prompts for a monotone selector and
|
|
shows a revlist buffer with all matching revisions.
|
|
|
|
C-x V u performs mtn update. C-x V m shows a revlist buffer with the
|
|
revisions that mtn update would apply to your tree.
|
|
|
|
C-x V f a performs mtn add. M-x dvc-ignore-files and M-x
|
|
dvc-ignore-file-extensions can be used to add entries to .mt-ignore.
|
|
These commands can also be used from dired buffers.
|
|
|
|
C-x V s shows the status buffer. This currently shows modified,
|
|
renamed and unknown files. It's supposed to allow operations like
|
|
diff, commit, revert etc. (like pcl-cvs), but that's not implemented
|
|
yet. C-x V = is preferable at the moment, although it doesn't show
|
|
unknown files.
|
|
|
|
C-x V a can be used to add a ChangeLog entry to _MTN/log.
|
|
|
|
There are other useful operations, but these should be enough to get
|
|
started.
|
|
|
|
|
|
|
|
* Known limitations
|
|
|
|
xmtn currently just bails out when it needs to operate on a head of a
|
|
branch and notices that the branch is unmerged. It should prompt the
|
|
user to select a head instead. To update to a head of an unmerged
|
|
revision graph, use M-x xmtn-view-heads-revlist and M-x
|
|
xmtn-revlist-update.
|
|
|
|
`xmtn-dvc-diff' breaks when called in a workspace that has no base
|
|
revision (e.g. a newly created project). mtn diff works in this case.
|
|
|
|
Building a revlist buffer is currently a bit slow (or maybe very slow
|
|
for long histories?), and the revlist display is not very pretty.
|
|
|
|
For `dvc-ignore-files' and `dvc-ignore-file-extensions', xmtn operates
|
|
on the file .mtn-ignore. This may fail to have the intended effect if
|
|
the user has customized monotone's ignore_file hook in a way that
|
|
changes the meaning of this file.
|
|
|
|
The ability to perform operations such as diff and commit from the
|
|
status buffer is missing. For now, use the tree diff buffer for this.
|
|
|
|
xmtn doesn't define any key bindings for monotone-specific commands.
|
|
Only the backend-independent key bindings defined by DVC are available.
|
|
|
|
For now, I don't see the point of checking automate interface_version:
|
|
Many of xmtn's operations rely on non-automate commands, so a
|
|
compatible automate interface_version doesn't guarantee actual
|
|
compatibility; we have to check for a compatible command version
|
|
anyway, and that check subsumes the check of interface_version. And
|
|
declaring incompatibility whenever we see an automate
|
|
interface_version that is too high for us yields false positives too
|
|
easily to be useful.
|
|
|
|
xmtn currently uses mtn automate get_revision in places where it
|
|
should be using mtn automate inventory. This is because I was trying
|
|
to avoid having to implement a parser for mtn automate inventory, and
|
|
get_revision seemed to return almost the same information. However,
|
|
get_revision fails if there are missing files -- I discovered this too
|
|
late. This is part of the reason why many operations first check
|
|
whether files are missing from the tree, and abort if this is the
|
|
case.
|
|
|
|
DVC REVISION-IDs that refer to the "Nth ancestor" such as `(xmtn
|
|
(last-revision ...))' or `(xmtn (previous-revision ...))' are
|
|
ill-defined for non-linear history in monotone. xmtn currently
|
|
throws an error when it encounters a node that has multiple parents
|
|
while trying to resolve such IDs.
|
|
|
|
The support for international character sets/coding systems is partly
|
|
based on guesswork but works for my tests.
|
|
|
|
xmtn does not entirely follow DVC's philosophy: It only implements
|
|
DVC's protocols, but doesn't provide its own UI that parallels DVC's.
|
|
Hence, much of xmtn's functionality is only available through DVC.
|
|
This is because xmtn currently provides only few features beyond what
|
|
DVC requires, and implementing a redundant UI was not a high priority
|
|
for me.
|
|
|
|
Currently, the following parts of the DVC protocol are not implemented
|
|
by xmtn:
|
|
|
|
* xmtn-dvc-send-commit-notification, xmtn-dvc-submit-patch: These
|
|
commands send an e-mail. Probably useful to people who use a
|
|
certain work flow, but not to me right now. These will have to
|
|
wait until someone comes along who actually has a use for them.
|
|
|
|
* xmtn-insinuate-gnus: Need to find out what, precisely, this is
|
|
supposed to do. I don't use Gnus myself.
|
|
|
|
* xmtn-dvc-save-diff: xhg seems to be the only backend that
|
|
implements this. It really seems this could be moved into the
|
|
common part of DVC anyway. Won't bother implementing it right
|
|
now.
|
|
|
|
* xmtn-dvc-pull: Should be easy. But syncing via command line is
|
|
acceptable to me at the moment. The docstring looks like this
|
|
needs to do both mtn pull and mtn update -- but I doubt that this
|
|
is a good idea for monotone.
|
|
|
|
|
|
|
|
* Internals
|
|
|
|
This section describes some of the internals of xmtn and some of the
|
|
design decisions behind it.
|
|
|
|
|
|
|
|
** Conventions
|
|
|
|
monotone.el (from montone's contrib/ directory) already uses the
|
|
prefix mtn-. monotone- is already taken by Wim Oudshoorn's e-monotone
|
|
package. So this package is named xmtn. xhg, xcg, xdarcs seem to be
|
|
in similar situations.
|
|
|
|
The prefix xmtn- is for definitions exported for the user or for DVC,
|
|
the prefix xmtn-- is for internal definitions. Similarly,
|
|
xmtn-automate uses xmtn-automate- and xmtn-automate--, etc.
|
|
|
|
It seems like "monotone" is usually written in small letters. The
|
|
manual capitalizes it at the beginnings of sentences, but e.g. the web
|
|
page or mtn --version never capitalize it at all -- then again, the
|
|
web page doesn't capitalize much at all. In xmtn, we capitalize it
|
|
like a noun. xmtn and mtn (as a command name) are always in lower
|
|
case.
|
|
|
|
Monotone uses the term "workspace", DVC uses the term "tree". In our
|
|
UI, we use "tree" for consistency with DVC. The idea behind this
|
|
decision was that consistency with DVC (and other aspects of Emacs'
|
|
UI) is more important than consistency with other monotone front-ends.
|
|
But I'm not so sure about this any more; the term "workspace" is so
|
|
much more clear... But I guess it makes little sense for version
|
|
control systems that don't distinguish between workspaces and
|
|
branches.
|
|
|
|
|
|
|
|
** Architecture
|
|
|
|
This section is unlikely to stay fully up-to-date as xmtn's
|
|
implementation evolves, but should remain useful as a general
|
|
introduction to xmtn's architecture.
|
|
|
|
xmtn consists of several modules. One way of understanding their
|
|
relationship is to group them into layers.
|
|
|
|
|
|
User-visible functionality: xmtn-dvc.el, xmtn-revlist.el
|
|
|
|
Domain-specific utilities: xmtn-ids.el
|
|
|
|
High-level interface to mtn: xmtn-automate.el, xmtn-basic-io.el
|
|
|
|
Low-level interface to mtn: xmtn-run.el
|
|
|
|
Monotone-related definitions: xmtn-base.el
|
|
|
|
Support libraries: xmtn-compat.el
|
|
|
|
Language extensions: xmtn-match.el
|
|
|
|
|
|
Each module should only depend on modules at layers beneath it. (At
|
|
least, that's the idea; the code might not satisfy this perfectly.)
|
|
|
|
xmtn-dvc.el implements the protocols required by DVC, except for
|
|
functionality related to interactive display and manipulation of
|
|
revision history, which is in xmtn-revlist.el.
|
|
|
|
xmtn-ids.el contains code to resolve symbolic revision ids in a
|
|
certain syntax to explicit hash ids. DVC needs this, but xmtn
|
|
provides some useful extensions. For example, a symbolic id `(xmtn
|
|
(previous-revision (previous-revision (revision
|
|
"75da2575dfc565f6976ed5dd1997bc7afc0ce908"))))' resolves to `(revision
|
|
"721c3ab9b5099d3ed7d8b807e08382f3c95badec")'; i.e. the parent of the
|
|
parent of revision 75da2575dfc565f6976ed5dd1997bc7afc0ce908 is
|
|
revision 721c3ab9b5099d3ed7d8b807e08382f3c95badec.
|
|
|
|
xmtn-automate.el and xmtn-basic-io.el implement an interface to
|
|
monotone's automate functionality and a parser for monotone's basic_io
|
|
output format. These modules aren't specific to DVC and should be
|
|
reusable by other Emacs Lisp code that wants to use monotone.
|
|
|
|
xmtn-run.el provides functions for running individual (non-automate)
|
|
monotone commands and checking the version of the monotone executable.
|
|
The functionality of xmtn-run.el isn't specific to DVC, either, but
|
|
its current implementation depends on DVC's process handling
|
|
functions, so it's fairly heavyweight.
|
|
|
|
xmtn-base.el was supposed to contain definitions related to monotone
|
|
that are common to xmtn-run.el, xmtn-automate.el and/or
|
|
xmtn-basic-io.el, to avoid having to have dependencies on xmtn-run.el
|
|
in xmtn-automate.el or xmtn-basic-io.el. This refactoring is not
|
|
complete (yet?), though.
|
|
|
|
xmtn-compat.el contains compatibility wrappers for some Emacs Lisp
|
|
functions that are not fully portable across Emacs versions.
|
|
|
|
xmtn-match.el provides a pattern-matching facility for Emacs Lisp that
|
|
is very useful for destructuring DVC REVISION-IDs and processing
|
|
basic_io stanzas the way xmtn-basic-io.el parses them. But it is
|
|
rather generic and could also be useful for code entirely unrelated to
|
|
montone and DVC.
|
|
|
|
There are a few automated regression tests in
|
|
lisp/tests/xmtn-tests.el.
|
|
|
|
|
|
|
|
|
|
** Implementation details
|
|
|
|
|
|
|
|
*** Futures
|
|
|
|
For some subprocess interactions, xmtn uses a concept called
|
|
"futures". In this context, a future is a concurrent computation
|
|
represented by a zero-argument anonymous function that, when called,
|
|
blocks until the concurrent computation finishes, and returns its
|
|
result.
|
|
|
|
For example, the function `xmtn--unknown-files-future' returns a
|
|
future for the list of unknown files instead of returning the list of
|
|
unknown files directly. This allows Emacs Lisp code to ask monotone
|
|
for the list of unknown files, but then do something different while
|
|
monotone computes the list. Only when Emacs actually needs the list
|
|
in order to continue, it calls the future and waits for monotone to
|
|
finish (if it hasn't finished already).
|
|
|
|
If a future is called a second time or more often, it will just keep
|
|
returning the same result. (What a future does if the concurrent
|
|
computation terminates unsuccessfully isn't currently very
|
|
well-defined. It should probably signal an error when it is called.)
|
|
|
|
Spawning computations in parallel has yielded tremendous speed-ups for
|
|
certain parts of xmtn (at least in some versions -- I haven't profiled
|
|
it recently). Futures make this type of parallelism simple to deal
|
|
with.
|
|
|
|
|
|
|
|
|
|
*** Notes on variable names and dynamic bindings
|
|
|
|
In higher-order functions (functions that take functions as
|
|
arguments), xmtn attempts to avoid introducing spurious dynamic
|
|
bindings because they might shadow bindings that the caller wants to
|
|
provide to the argument function. xmtn uses `lexical-let' for this
|
|
purpose. Unfortunately, function arguments are always dynamic
|
|
bindings in Emacs Lisp. That's why the argument names of higher-order
|
|
functions in xmtn always have the prefix xmtn-- and are immediately
|
|
re-bound to (pseudo-)lexical variables using `lexical-let'. This
|
|
makes it unlikely that the arguments will collide with the caller's
|
|
variables.
|
|
|
|
The alternative would be to always use `lexical-let' for bindings that
|
|
should be passed through higher-order functions to closures. This is
|
|
the most reliable approach, and xmtn also follows it. But errors
|
|
resulting from accidental violations of this convention can be very
|
|
hard to debug, so the above is still useful for additional safety.
|
|
|
|
|
|
|
|
|
|
LocalWords: DVC minibuffer UI montone xmtn revlist unmerged docstring backend
|
|
LocalWords: backends destructuring mtn
|