aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2004-03-23 21:34:06 +0000
committerStefan Monnier2004-03-23 21:34:06 +0000
commitdf617e7ff8962604218644b7c0f96aa488384c98 (patch)
tree487c2173ebb75b6cb3ffce95c86997ea3c1ef010
parent81c63b50e29e5afd38d48af09860a730be5a84bd (diff)
downloademacs-df617e7ff8962604218644b7c0f96aa488384c98.tar.gz
emacs-df617e7ff8962604218644b7c0f96aa488384c98.zip
(vc-arch-diff): Handle the special case where `newvers' is equivalent to nil.
(vc-arch-diff3-rej-p): Be a bit more flexible in what we accept. (vc-arch-mode-line-string): Accept `added' state. (vc-arch-state): Use inode-sigs if available. (vc-arch-add-tagline): Rename from vc-arch-add-tag. Copy&delete existing id file if any. Fallback if uuidgen is absent. (vc-arch-tagline-re): New var. (vc-arch-file-source-p, vc-arch-file-id, vc-arch-tagging-method): New funs. (vc-arch-find-file-not-found-hook, vc-arch-register): New backend ops. (vc-arch-registered): Try our best guess using vc-arch-file-source-p.
-rw-r--r--lisp/vc-arch.el190
1 files changed, 169 insertions, 21 deletions
diff --git a/lisp/vc-arch.el b/lisp/vc-arch.el
index 52dc623e9c4..042b4bbbdca 100644
--- a/lisp/vc-arch.el
+++ b/lisp/vc-arch.el
@@ -25,22 +25,21 @@
25;;; Commentary: 25;;; Commentary:
26 26
27;; The home page of the Arch version control system is at 27;; The home page of the Arch version control system is at
28;; 28;;
29;; http://www.gnuarch.org/ 29;; http://www.gnuarch.org/
30;; 30;;
31;; This is derived from vc-mcvs.el as follows: 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 32;; - cp vc-mcvs.el vc-arch.el and then M-% mcvs RET arch RET
33;; 33;;
34;; Then of course started the hacking. 34;; Then of course started the hacking.
35;; 35;;
36;; What has been partly tested: 36;; What has been partly tested:
37;; - Open a file 37;; - Open a file.
38;; - C-x v = without any prefix arg 38;; - C-x v = without any prefix arg.
39;; - C-x v v to commit a change to a single file 39;; - C-x v v to commit a change to a single file.
40 40
41;; Bugs: 41;; Bugs:
42 42
43;; - Opening a new file prompts "blabla was lost; check out? (yes or no)".
44;; - *VC-log*'s initial content lacks the `Summary:' lines. 43;; - *VC-log*'s initial content lacks the `Summary:' lines.
45;; - All files under the tree are considered as "under Arch's control" 44;; - All files under the tree are considered as "under Arch's control"
46;; without regards to =tagging-method and such. 45;; without regards to =tagging-method and such.
@@ -86,17 +85,103 @@
86;;;###autoload (load "vc-arch") 85;;;###autoload (load "vc-arch")
87;;;###autoload (vc-arch-registered file))))) 86;;;###autoload (vc-arch-registered file)))))
88 87
89(defun vc-arch-add-tag () 88(defun vc-arch-add-tagline ()
90 "Add an `arch-tag' to the end of the current file." 89 "Add an `arch-tag' to the end of the current file."
91 (interactive) 90 (interactive)
91 (comment-normalize-vars)
92 (goto-char (point-max)) 92 (goto-char (point-max))
93 (forward-comment -1) 93 (forward-comment -1)
94 (unless (bolp) (insert "\n")) 94 (unless (bolp) (insert "\n"))
95 (let ((beg (point))) 95 (let ((beg (point))
96 (idfile (and buffer-file-name
97 (expand-file-name
98 (concat ".arch-ids/"
99 (file-name-nondirectory buffer-file-name)
100 ".id")
101 (file-name-directory buffer-file-name)))))
96 (insert "arch-tag: ") 102 (insert "arch-tag: ")
97 (call-process "uuidgen" nil t) ;Also inserts a terminal newline. 103 (if (and idfile (file-exists-p idfile))
104 ;; If the file is unreadable, we do want to get an error here.
105 (progn
106 (insert-file-contents idfile)
107 (forward-line 1)
108 (delete-file idfile))
109 (condition-case nil
110 (call-process "uuidgen" nil t)
111 (file-error (insert (format "%s <%s> %s"
112 (current-time-string)
113 user-mail-address
114 (+ (nth 2 (current-time))
115 (buffer-size)))))))
98 (comment-region beg (point)))) 116 (comment-region beg (point))))
99 117
118(defconst vc-arch-tagline-re "^\\W*arch-tag:[ \t]*\\(.*[^ \t\n]\\)")
119
120(defun vc-arch-file-source-p (file)
121 "Can return nil, `maybe' or a non-nil value.
122Only the value `maybe' can be trusted :-(."
123 ;; FIXME: Check the tag and name of parent dirs.
124 (unless (string-match "\\`[,+]" (file-name-nondirectory file))
125 (or (string-match "\\`{arch}/"
126 (file-relative-name file (vc-arch-root file)))
127 (file-exists-p
128 ;; Check the presence of an ID file.
129 (expand-file-name
130 (concat ".arch-ids/" (file-name-nondirectory file) ".id")
131 (file-name-directory file)))
132 ;; Check the presence of a tagline.
133 (with-current-buffer (find-file-noselect file)
134 (save-excursion
135 (goto-char (point-max))
136 (or (re-search-backward vc-arch-tagline-re (- (point) 1000) t)
137 (progn
138 (goto-char (point-min))
139 (re-search-forward vc-arch-tagline-re (+ (point) 1000) t)))))
140 ;; FIXME: check =tagging-method to see whether untagged files might
141 ;; be source or not.
142 (with-current-buffer
143 (find-file-noselect (expand-file-name "{arch}/=tagging-method"
144 (vc-arch-root file)))
145 (let ((untagged-source t)) ;Default is `names'.
146 (save-excursion
147 (goto-char (point-min))
148 (if (re-search-forward "^[ \t]*\\(\\(tagline\\|implicit\\|names\\)\\|explicit\\)" nil t)
149 (setq untagged-source (match-end 2)))
150 (if (re-search-forward "^[ \t]*untagged-source[ \t]+\\(\\(source\\)\\|precious\\|backup\\|junk\\|unrecognized\\)" nil t)
151 (setq untagged-source (match-end 2))))
152 (if untagged-source 'maybe))))))
153
154(defun vc-arch-file-id (file)
155 ;; Don't include the kind of ID this is because it seems to be too messy.
156 (let ((idfile (expand-file-name
157 (concat ".arch-ids/" (file-name-nondirectory file) ".id")
158 (file-name-directory file))))
159 (if (file-exists-p idfile)
160 (with-temp-buffer
161 (insert-file-contents idfile)
162 (looking-at ".*[^ \n\t]")
163 (match-string 0)))
164 (with-current-buffer (find-file-noselect file)
165 (save-excursion
166 (goto-char (point-max))
167 (if (or (re-search-backward vc-arch-tagline-re (- (point) 1000) t)
168 (progn
169 (goto-char (point-min))
170 (re-search-forward vc-arch-tagline-re (+ (point) 1000) t)))
171 (match-string 1)
172 (concat "./" (file-relative-name file (vc-arch-root file))))))))
173
174(defun vc-arch-tagging-method (file)
175 (with-current-buffer
176 (find-file-noselect
177 (expand-file-name "{arch}/=tagging-method" (vc-arch-root file)))
178 (save-excursion
179 (goto-char (point-min))
180 (if (re-search-forward
181 "^[ \t]*\\(tagline\\|implicit\\|names\\|explicit\\)" nil t)
182 (intern (match-string 1))
183 'names))))
184
100(defun vc-arch-root (file) 185(defun vc-arch-root (file)
101 "Return the root directory of a Arch project, if any." 186 "Return the root directory of a Arch project, if any."
102 (or (vc-file-getprop file 'arch-root) 187 (or (vc-file-getprop file 'arch-root)
@@ -111,11 +196,20 @@
111 (setq file (directory-file-name file)))) 196 (setq file (directory-file-name file))))
112 root)))) 197 root))))
113 198
199(defun vc-arch-register (file &optional rev comment)
200 (if rev (error "Explicit initial revision not supported for Arch."))
201 (let ((tagmet (vc-arch-tagging-method file)))
202 (if (and (memq tagmet '(tagline implicit)) comment-start)
203 (with-current-buffer (find-file-noselect file)
204 (vc-arch-add-tagline))
205 (vc-arch-command nil 0 file "add"))))
206
114(defun vc-arch-registered (file) 207(defun vc-arch-registered (file)
115 ;; Don't check whether it's source or not. Checking would require 208 ;; Don't seriously check whether it's source or not. Checking would
116 ;; running TLA, so it's better to not do it, so it also works if TLA is 209 ;; require running TLA, so it's better to not do it, so it also works if
117 ;; not installed. 210 ;; TLA is not installed.
118 (vc-arch-root file)) 211 (and (vc-arch-root file)
212 (vc-arch-file-source-p file)))
119 213
120(defun vc-arch-default-version (file) 214(defun vc-arch-default-version (file)
121 (or (vc-file-getprop (vc-arch-root file) 'arch-default-version) 215 (or (vc-file-getprop (vc-arch-root file) 'arch-default-version)
@@ -138,8 +232,47 @@ Return non-nil if FILE is unchanged."
138 ;; There's no checkout operation and merging is not done from VC 232 ;; There's no checkout operation and merging is not done from VC
139 ;; so the only operation that's state dependent that VC supports is commit 233 ;; so the only operation that's state dependent that VC supports is commit
140 ;; which is only activated if the file is `edited'. 234 ;; which is only activated if the file is `edited'.
141 'edited) 235 (let* ((root (vc-arch-root file))
142 236 (ver (vc-arch-default-version file))
237 (pat (concat "\\`" (subst-char-in-string ?/ ?% ver)))
238 (dir (expand-file-name ",,inode-sigs/"
239 (expand-file-name "{arch}" root)))
240 (sigfile nil))
241 (dolist (f (if (file-directory-p dir) (directory-files dir t pat)))
242 (if (or (not sigfile) (file-newer-than-file-p f sigfile))
243 (setq sigfile f)))
244 (if (not sigfile)
245 'edited ;We know nothing.
246 (let ((id (vc-arch-file-id file)))
247 (setq id (replace-regexp-in-string "[ \t]" "_" id))
248 (with-current-buffer (find-file-noselect sigfile)
249 (goto-char (point-min))
250 (while (and (search-forward id nil 'move)
251 (progn (goto-char (- (match-beginning 0) 2))
252 ;; Ignore E_ entries used for foo.id files.
253 (or (not (bolp)) (looking-at "E_")))))
254 (if (eobp)
255 ;; ID not found.
256 (if (equal (file-name-nondirectory sigfile)
257 (subst-char-in-string
258 ?/ ?% (vc-arch-workfile-version file)))
259 'added
260 ;; Might be `added' or `up-to-date' as well.
261 ;; FIXME: Check in the patch logs to find out.
262 'edited)
263 ;; Found the ID, let's check the inode.
264 (if (not (re-search-forward
265 "\t.*mtime=\\([0-9]+\\):size=\\([0-9]+\\)"
266 (line-end-position) t))
267 ;; Buh? Unexpected format.
268 'edited
269 (let ((ats (file-attributes file)))
270 (if (and (= (nth 7 ats) (string-to-number (match-string 2)))
271 (equal (format-time-string "%s" (nth 5 ats))
272 (match-string 1)))
273 'up-to-date
274 'edited)))))))))
275
143(defun vc-arch-workfile-version (file) 276(defun vc-arch-workfile-version (file)
144 (let* ((root (expand-file-name "{arch}" (vc-arch-root file))) 277 (let* ((root (expand-file-name "{arch}" (vc-arch-root file)))
145 (defbranch (vc-arch-default-version file))) 278 (defbranch (vc-arch-default-version file)))
@@ -180,15 +313,19 @@ Return non-nil if FILE is unchanged."
180 (if (string-match (car rule) rev) 313 (if (string-match (car rule) rev)
181 (setq rev (replace-match (cdr rule) t nil rev)))) 314 (setq rev (replace-match (cdr rule) t nil rev))))
182 (format "Arch%c%s" 315 (format "Arch%c%s"
183 (if (memq (vc-state file) '(up-to-date needs-patch)) ?- ?:) 316 (case (vc-state file)
317 ((up-to-date needs-patch) ?-)
318 (added ?@)
319 (t ?:))
184 rev))) 320 rev)))
185 321
186(defun vc-arch-diff3-rej-p (rej) 322(defun vc-arch-diff3-rej-p (rej)
187 (and (eq (nth 7 (file-attributes rej)) 56) 323 (let ((attrs (file-attributes rej)))
188 (with-temp-buffer 324 (and attrs (< (nth 7 attrs) 60)
189 (insert-file-contents rej) 325 (with-temp-buffer
190 (goto-char (point-min)) 326 (insert-file-contents rej)
191 (looking-at "Conflicts occured, diff3 conflict markers left in file\\.$")))) 327 (goto-char (point-min))
328 (looking-at "Conflicts occured, diff3 conflict markers left in file\\.")))))
192 329
193(defun vc-arch-delete-rej-if-obsolete () 330(defun vc-arch-delete-rej-if-obsolete ()
194 "For use in `write-file-functions'." 331 "For use in `write-file-functions'."
@@ -216,6 +353,11 @@ Return non-nil if FILE is unchanged."
216 (message "There are unresolved conflicts in %s" 353 (message "There are unresolved conflicts in %s"
217 (file-name-nondirectory rej)))))) 354 (file-name-nondirectory rej))))))
218 355
356(defun vc-arch-find-file-not-found-hook ()
357 ;; Do nothing. We are not sure whether the file is `source' or not,
358 ;; so we shouldn't ask the user whether she wants to check it out.
359 )
360
219(defun vc-arch-checkout-model (file) 'implicit) 361(defun vc-arch-checkout-model (file) 'implicit)
220 362
221(defun vc-arch-checkin (file rev comment) 363(defun vc-arch-checkin (file rev comment)
@@ -231,6 +373,12 @@ Return non-nil if FILE is unchanged."
231 373
232(defun vc-arch-diff (file &optional oldvers newvers) 374(defun vc-arch-diff (file &optional oldvers newvers)
233 "Get a difference report using Arch between two versions of FILE." 375 "Get a difference report using Arch between two versions of FILE."
376 (if (and newvers
377 (vc-up-to-date-p file)
378 (equal newvers (vc-workfile-version file)))
379 ;; Newvers is the base revision and the current file is unchanged,
380 ;; so we can diff with the current file.
381 (setq newvers nil))
234 (if newvers 382 (if newvers
235 (error "Diffing specific revisions not implemented.") 383 (error "Diffing specific revisions not implemented.")
236 (let* ((async (fboundp 'start-process)) 384 (let* ((async (fboundp 'start-process))