That file contains the documentation to build support for a different dvc, using the dvc layer: Conventions used in the document: * is used as placeholder for the dvc backend to implement -------------------------------------------------------------------------------- * Base functions that are required for every supported dvc system * That functions should be located in the -dvc.el file -------------------------------------------------------------------------------- When no function is provided, dvc-dvc- is used instead. - -dvc-tree-root (defun -dvc-tree-root (&optional location no-error) "Return the tree root for LOCATION, nil if not in a local tree. If NO-ERROR is non-nil, don't raise an error if LOCATION is not a managed tree (but return nil)." - -dvc-log-edit-done (defun -dvc-log-edit-done () "Finish a commit for ." - -dvc-diff (defun -dvc-diff () "Shows the changes in the current tree." - -dvc-log (defun -dvc-log () "Shows the changelog in the current tree." - -dvc-command-version (defun -dvc-command-version () "Returns and/or shows the version identity string of backend command." - -dvc-file-has-conflict-p (defun -dvc-file-has-conflict-p (filename) "Return non-nil if FILENAME is marked as having conflicts") - -dvc-resolved (defun -dvc-resolved (filename) "Mark FILENAME as not having conflict anymore") To handle the case of a workspace that is controlled by more than one back-end, all dispatching interactive front-end functions dvc-foo should have a corresponding function -foo, that specifies which back-end to use. A simple way to provide -foo is to put dvc-foo in dvc-back-end-wrappers (in dvc-unified.el); then -foo is automatically generated by dvc-register-dvc. This defines -foo as (see dvc-register.el for the actual code): (defun -foo () (interactive) (let ((dvc-temp-current-active-dvc )) (call-interactively 'dvc-foo))) This means that back-ends may _not_ define a function -foo. Note that functions defined by dvc-define-unified-command dispatch to -dvc-foo. Calling -dvc-foo is _not_ the same as calling -foo, since dvc-temp-current-active-dvc is not bound, the interactive argument processing may be different, and -dvc-foo may not even exist (if the default dvc-dvc-foo is sufficient). ----------------------------------------------------------------------------- * Revision API ----------------------------------------------------------------------------- Definition ========== DVC deals with several RCS, with different ways to designate a revision. We define a unified way to designate a revision in lisp, which we call revision identifiers, or rev-id: REVISION-ID :: ( BACK-END-ID) ;; is one of 'tla, 'bzr, 'xhg, ... BACK-END-ID :: (revision BACK-END-REVISION) ;; An already commited revision ;; The way to specify it depends on the back-end. | (local-tree PATH) ;; Uncommited revision in the local tree PATH | (last-revision PATH NUM) ;; Last commited revision in tree PATH if NUM = 1 ;; Last but NUM-1 revision in tree PATH if NUM > 1 | (previous-revision BACK-END-REVISION NUM) ;; Nth Ancestor of BACK-END-ID. (probably we'll need a (head REMOTE-BRANCH) too) PATH :: string ;; must be a tree root directory NUM :: number REV-STRING :: string For Xtla (tla and baz): BACK-END-REVISION :: ("archive" "category" "branch" "version" "revision") ;; archive/category--branch--version--revision For bzr: BACK-END-REVISION :: (local "path" NUM) | (remote "url" NUM) | (tag REV-STRING) For xhg: TODO For xgit: BACK-END-REVISION :: (revision "sha1") | (index) ;; content of the index (aka staging area). Example ======= (bzr (revision (local "/path/to/archive" 3))) (baz (last-revision "/path/to/project" 1)) (baz (revision ("archive" "category" "branch" "version" "revision"))) (xgit (revision "c576304d512df18fa30b91bb3ac15478d5d4dfb1")) Functions ========= Based upon that, we define the functions: dvc-revision-get-file-in-buffer: get the particular revision of a file in a buffer. ----------------------------------------------------------------------------- * Back-end specific features Vs Unification ----------------------------------------------------------------------------- DVC provides the user an interface for multiple revision control system, and does it using as much back-end independant code as possible. This has several benefits : * For the user: - Similar user-interface, keybindings, ... for different back-ends. - Unified interface for most operations : one menu, one set of keybindings, and DVC detects which back-end to use automatically. * For the developers: - much less code to write than individual, independant interfaces. However, some back-end features do not fit well in the DVC common interface. For example, git differs from other common version control systems in several regards (the index, for example, is something probably unique to git, and it leads to a different flow to prepare a commit). In this case, there's nothing wrong providing additional functions, which might not have a dvc-* dispatching command. The user can call them with M-x -command RET explicitly. Additionaly, one can extend some DVC modes with additional keybindings and menus. See `dvc-diff-mode' and `xgit-diff-mode' for an example. ----------------------------------------------------------------------------- * External tools ----------------------------------------------------------------------------- * 'sh' is required for dvc-run-sync and dvc-run-async. In practice, that is not a problem for Unix users, but requires cygwin or mingw for Windows users. 'sh' is used to separate stdout from stderr; the Emacs function 'call-process' merges them. It may be possible to do this with native Windows tools, if someone wants to investigate.