diff options
| author | Stefan Monnier | 2004-03-15 03:39:09 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2004-03-15 03:39:09 +0000 |
| commit | 0f6c7af8d6fedaa93266e22b2a2f458b5a4d58b5 (patch) | |
| tree | 270e5c00ffe1ba15ba638d2a38682944e5d9cb87 | |
| parent | 0eeca3c1498bba87bdbb2da0615a455501d9488e (diff) | |
| download | emacs-0f6c7af8d6fedaa93266e22b2a2f458b5a4d58b5.tar.gz emacs-0f6c7af8d6fedaa93266e22b2a2f458b5a4d58b5.zip | |
New file.
| -rw-r--r-- | lisp/vc-arch.el | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/lisp/vc-arch.el b/lisp/vc-arch.el new file mode 100644 index 00000000000..555d49b65fb --- /dev/null +++ b/lisp/vc-arch.el | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | ;;; vc-arch.el --- VC backend for the Arch version-control system | ||
| 2 | |||
| 3 | ;; Copyright (C) 1995,98,99,2000,01,02,03,2004 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: FSF (see vc.el for full credits) | ||
| 6 | ;; Maintainer: Stefan Monnier <monnier@gnu.org> | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 22 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;; The home page of the Arch version control system is at | ||
| 28 | ;; | ||
| 29 | ;; http://www.gnuarch.org/ | ||
| 30 | ;; | ||
| 31 | ;; This is derived from vc-mcvs.el as follows: | ||
| 32 | ;; - cp vc-mcvs.el vc-arch.el and then M-% mcvs RET arch RET | ||
| 33 | ;; | ||
| 34 | ;; Then of course started the hacking. | ||
| 35 | ;; | ||
| 36 | ;; What has been partly tested: | ||
| 37 | ;; - Open a file | ||
| 38 | ;; - C-x v = without any prefix arg | ||
| 39 | ;; - C-x v v to commit a change to a single file | ||
| 40 | |||
| 41 | ;; Bugs: | ||
| 42 | |||
| 43 | ;; - All files under the tree are considered as "under Arch's control" | ||
| 44 | ;; without regards to =tagging-method and such. | ||
| 45 | ;; - Files are always considered as `edited'. | ||
| 46 | ;; - C-x v i does not work. | ||
| 47 | ;; - VC-dired does not work. | ||
| 48 | ;; - And more... | ||
| 49 | |||
| 50 | ;;; Code: | ||
| 51 | |||
| 52 | (eval-when-compile (require 'vc)) | ||
| 53 | |||
| 54 | ;;; | ||
| 55 | ;;; Customization options | ||
| 56 | ;;; | ||
| 57 | |||
| 58 | (defvar vc-arch-command | ||
| 59 | (let ((candidates '("tla"))) | ||
| 60 | (while (and candidates (not (executable-find (car candidates)))) | ||
| 61 | (setq candidates (cdr candidates))) | ||
| 62 | (or (car candidates) "tla"))) | ||
| 63 | |||
| 64 | ;; Clear up the cache to force vc-call to check again and discover | ||
| 65 | ;; new functions when we reload this file. | ||
| 66 | (put 'Arch 'vc-functions nil) | ||
| 67 | |||
| 68 | ;;;###autoload (defun vc-arch-registered (file) | ||
| 69 | ;;;###autoload (let ((dir file)) | ||
| 70 | ;;;###autoload (while (and (stringp dir) | ||
| 71 | ;;;###autoload (not (equal | ||
| 72 | ;;;###autoload dir (setq dir (file-name-directory dir)))) | ||
| 73 | ;;;###autoload dir) | ||
| 74 | ;;;###autoload (setq dir (if (file-directory-p | ||
| 75 | ;;;###autoload (expand-file-name "{arch}" dir)) | ||
| 76 | ;;;###autoload t (directory-file-name dir)))) | ||
| 77 | ;;;###autoload (if (eq dir t) | ||
| 78 | ;;;###autoload (progn | ||
| 79 | ;;;###autoload (load "vc-arch") | ||
| 80 | ;;;###autoload (vc-arch-registered file))))) | ||
| 81 | |||
| 82 | (defun vc-arch-add-tag () | ||
| 83 | "Add an `arch-tag' to the end of the current file." | ||
| 84 | (interactive) | ||
| 85 | (goto-char (point-max)) | ||
| 86 | (forward-comment -1) | ||
| 87 | (unless (bolp) (insert "\n")) | ||
| 88 | (let ((beg (point))) | ||
| 89 | (insert "arch-tag: ") | ||
| 90 | (call-process "uuidgen" nil t) ;Also inserts a terminal newline. | ||
| 91 | (comment-region beg (point)))) | ||
| 92 | |||
| 93 | (defun vc-arch-root (file) | ||
| 94 | "Return the root directory of a Arch project, if any." | ||
| 95 | (or (vc-file-getprop file 'arch-root) | ||
| 96 | (vc-file-setprop | ||
| 97 | file 'arch-root | ||
| 98 | (let ((root nil)) | ||
| 99 | (while (not (or root | ||
| 100 | (equal file (setq file (file-name-directory file))) | ||
| 101 | (null file))) | ||
| 102 | (if (file-directory-p (expand-file-name "{arch}" file)) | ||
| 103 | (setq root file) | ||
| 104 | (setq file (directory-file-name file)))) | ||
| 105 | root)))) | ||
| 106 | |||
| 107 | (defun vc-arch-registered (file) | ||
| 108 | ;; Don't check whether it's source or not. Checking would require | ||
| 109 | ;; running TLA, so it's better to not do it, so it also works if TLA is | ||
| 110 | ;; not installed. | ||
| 111 | (vc-arch-root file)) | ||
| 112 | |||
| 113 | (defun vc-arch-default-version (file) | ||
| 114 | (or (vc-file-getprop (vc-arch-root file) 'arch-default-version) | ||
| 115 | (let* ((root (vc-arch-root file)) | ||
| 116 | (f (expand-file-name "{arch}/++default-version" root))) | ||
| 117 | (if (file-readable-p f) | ||
| 118 | (vc-file-setprop | ||
| 119 | root 'arch-default-version | ||
| 120 | (with-temp-buffer | ||
| 121 | (insert-file-contents f) | ||
| 122 | ;; Strip the terminating newline. | ||
| 123 | (buffer-substring (point-min) (1- (point-max))))))))) | ||
| 124 | |||
| 125 | (defun vc-arch-state (file) | ||
| 126 | ;; There's no checkout operation and merging is not done from VC | ||
| 127 | ;; so the only operation that's state dependent that VC supports is commit | ||
| 128 | ;; which is only activated if the file is `edited'. | ||
| 129 | 'edited) | ||
| 130 | |||
| 131 | (defun vc-arch-workfile-version (file) | ||
| 132 | (let* ((root (expand-file-name "{arch}" (vc-arch-root file))) | ||
| 133 | (defbranch (vc-arch-default-version file))) | ||
| 134 | (when (and defbranch (string-match "\\`\\(.+@[^/\n]+\\)/\\(\\(\\(.*\\)--.*\\)--.*\\)\\'" defbranch)) | ||
| 135 | (let* ((archive (match-string 1 defbranch)) | ||
| 136 | (category (match-string 4 defbranch)) | ||
| 137 | (branch (match-string 3 defbranch)) | ||
| 138 | (version (match-string 2 defbranch)) | ||
| 139 | (rev-nb 0) | ||
| 140 | (rev nil) | ||
| 141 | logdir tmp) | ||
| 142 | (setq logdir (expand-file-name category root)) | ||
| 143 | (setq logdir (expand-file-name branch logdir)) | ||
| 144 | (setq logdir (expand-file-name version logdir)) | ||
| 145 | (setq logdir (expand-file-name archive logdir)) | ||
| 146 | (setq logdir (expand-file-name "patch-log" logdir)) | ||
| 147 | (dolist (file (directory-files logdir)) | ||
| 148 | (if (and (string-match "-\\([0-9]+\\)\\'" file) | ||
| 149 | (setq tmp (string-to-number (match-string 1 file))) | ||
| 150 | (>= tmp rev-nb)) | ||
| 151 | (setq rev-nb tmp rev file))) | ||
| 152 | (concat defbranch "--" rev))))) | ||
| 153 | |||
| 154 | |||
| 155 | (defcustom vc-arch-mode-line-rewrite | ||
| 156 | '(("\\`.*--\\(.*--.*\\)--.*-\\([0-9]+\\)\\'" . "\\2[\\1]")) | ||
| 157 | "Rewrite rules to shorten Arch's revision names on the mode-line." | ||
| 158 | :type '(repeat (cons regexp string))) | ||
| 159 | |||
| 160 | (defun vc-arch-mode-line-string (file) | ||
| 161 | "Return string for placement in modeline by `vc-mode-line' for FILE." | ||
| 162 | (let ((rev (vc-workfile-version file))) | ||
| 163 | (dolist (rule vc-arch-mode-line-rewrite) | ||
| 164 | (if (string-match (car rule) rev) | ||
| 165 | (setq rev (replace-match (cdr rule) t nil rev)))) | ||
| 166 | (format "Arch%c%s" | ||
| 167 | (if (memq (vc-state file) '(up-to-date needs-patch)) ?- ?:) | ||
| 168 | rev))) | ||
| 169 | |||
| 170 | (defun vc-arch-diff3-rej-p (rej) | ||
| 171 | (and (eq (nth 7 (file-attributes rej)) 56) | ||
| 172 | (with-temp-buffer | ||
| 173 | (insert-file-contents rej) | ||
| 174 | (goto-char (point-min)) | ||
| 175 | (looking-at "Conflicts occured, diff3 conflict markers left in file\\.$")))) | ||
| 176 | |||
| 177 | (defun vc-arch-delete-rej-if-obsolete () | ||
| 178 | "For use in `write-file-functions'." | ||
| 179 | (let ((rej (concat buffer-file-name ".rej"))) | ||
| 180 | (when (and buffer-file-name (vc-arch-diff3-rej-p rej)) | ||
| 181 | (if (not (re-search-forward "^>>>>>>> " nil t)) | ||
| 182 | ;; The .rej file is obsolete. | ||
| 183 | (condition-case nil (delete-file rej) (error nil))))) | ||
| 184 | ;; This did not save the buffer. | ||
| 185 | nil) | ||
| 186 | |||
| 187 | (defun vc-arch-find-file-hook () | ||
| 188 | (let ((rej (concat buffer-file-name ".rej"))) | ||
| 189 | (when (and buffer-file-name (file-exists-p rej)) | ||
| 190 | (if (vc-arch-diff3-rej-p rej) | ||
| 191 | (save-excursion | ||
| 192 | (goto-char (point-min)) | ||
| 193 | (if (not (re-search-forward "^>>>>>>> " nil t)) | ||
| 194 | ;; The .rej file is obsolete. | ||
| 195 | (condition-case nil (delete-file rej) (error nil)) | ||
| 196 | (smerge-mode 1) | ||
| 197 | (add-hook 'write-file-functions | ||
| 198 | 'vc-arch-delete-rej-if-obsolete nil t) | ||
| 199 | (message "There are unresolved conflicts in this file"))) | ||
| 200 | (message "There are unresolved conflicts in %s" | ||
| 201 | (file-name-nondirectory rej)))))) | ||
| 202 | |||
| 203 | (defun vc-arch-checkout-model (file) 'implicit) | ||
| 204 | |||
| 205 | (defun vc-arch-checkin (file rev comment) | ||
| 206 | (if rev (error "Committing to a specific revision is unsupported.")) | ||
| 207 | (vc-arch-command nil 0 file "commit" "-L" comment "--" | ||
| 208 | (vc-switches 'Arch 'checkin))) | ||
| 209 | |||
| 210 | (defun vc-arch-diff (file &optional oldvers newvers) | ||
| 211 | "Get a difference report using Arch between two versions of FILE." | ||
| 212 | (if newvers | ||
| 213 | (error "Diffing specific revisions not implemented.") | ||
| 214 | (let* ((async (fboundp 'start-process)) | ||
| 215 | ;; Run the command from the root dir. | ||
| 216 | (default-directory (vc-arch-root file)) | ||
| 217 | (status | ||
| 218 | (vc-arch-command | ||
| 219 | "*vc-diff*" | ||
| 220 | (if async 'async 1) | ||
| 221 | nil "file-diffs" | ||
| 222 | ;; Arch does not support the typical flags. | ||
| 223 | ;; (vc-switches 'Arch 'diff) | ||
| 224 | (file-relative-name file) | ||
| 225 | (if (equal oldvers (vc-workfile-version file)) | ||
| 226 | nil | ||
| 227 | oldvers)))) | ||
| 228 | (if async 1 status)))) ; async diff, pessimistic assumption. | ||
| 229 | |||
| 230 | (defun vc-arch-delete-file (file) | ||
| 231 | (vc-arch-command nil 0 file "rm")) | ||
| 232 | |||
| 233 | (defun vc-arch-rename-file (old new) | ||
| 234 | (vc-arch-command nil 0 new "mv" (file-relative-name old))) | ||
| 235 | |||
| 236 | (defun vc-arch-command (buffer okstatus file &rest flags) | ||
| 237 | "A wrapper around `vc-do-command' for use in vc-arch.el." | ||
| 238 | (apply 'vc-do-command buffer okstatus vc-arch-command file flags)) | ||
| 239 | |||
| 240 | (provide 'vc-arch) | ||
| 241 | |||
| 242 | ;;; arch-tag: a35c7c1c-5237-429d-88ef-3d718fd2e704 | ||
| 243 | ;;; vc-arch.el ends here | ||