comparison lisp/vc.el @ 12872:857663042672

(vc-revert-buffer1): Split part of the function into vc-buffer-context and vc-restore-buffer-context, so we can use it also in other circumstances. (vc-buffer-context, vc-restore-buffer-context): New functions. (vc-clear-headers): New function, uses the above. (vc-cancel-version): When `norevert', locks the most recent remaining version. Also, refuse to work on anything but the latest version of a branch. Removed the check whether the version is the user's, because that is difficult to decide, now that multiple branches are possible. (vc-latest-on-branch-p): New function. (vc-head-version): New access function to the already existing property. (vc-trunk-p, vc-branch-part): Functions moved before first use.
author André Spiegel <spiegel@gnu.org>
date Thu, 17 Aug 1995 12:40:03 +0000
parents e6713915dd94
children 03d3b7d60f67
comparison
equal deleted inserted replaced
12871:d998327b9011 12872:857663042672
191 )) 191 ))
192 192
193 (if (not (boundp 'file-regular-p)) 193 (if (not (boundp 'file-regular-p))
194 (fset 'file-regular-p 'file-regular-p-18)) 194 (fset 'file-regular-p 'file-regular-p-18))
195 195
196 ;;; functions that operate on RCS revision numbers
197
198 (defun vc-trunk-p (rev)
199 ;; return t if REV is a revision on the trunk
200 (not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev))))
201
202 (defun vc-branch-part (rev)
203 ;; return the branch part of a revision number REV
204 (substring rev 0 (string-match "\\.[0-9]+\\'" rev)))
205
196 ;; File property caching 206 ;; File property caching
197 207
198 (defun vc-clear-context () 208 (defun vc-clear-context ()
199 "Clear all cached file properties and the comment ring." 209 "Clear all cached file properties and the comment ring."
200 (interactive) 210 (interactive)
217 (vc-file-setprop file 'vc-top-version nil) 227 (vc-file-setprop file 'vc-top-version nil)
218 (vc-file-setprop file 'vc-master-locks nil)) 228 (vc-file-setprop file 'vc-master-locks nil))
219 (progn 229 (progn
220 (vc-file-setprop file 'vc-cvs-status nil)))) 230 (vc-file-setprop file 'vc-cvs-status nil))))
221 231
222 ;;; functions that operate on RCS revision numbers 232 (defun vc-head-version (file)
223 233 ;; Return the RCS head version of FILE
224 (defun vc-trunk-p (rev) 234 (cond ((vc-file-getprop file 'vc-head-version))
225 ;; return t if REV is a revision on the trunk 235 (t (vc-fetch-master-properties file)
226 (not (eq nil (string-match "\\`[0-9]+\\.[0-9]+\\'" rev)))) 236 (vc-file-getprop file 'vc-head-version))))
227
228 (defun vc-branch-part (rev)
229 ;; return the branch part of a revision number REV
230 (substring rev 0 (string-match "\\.[0-9]+\\'" rev)))
231 237
232 ;; Random helper functions 238 ;; Random helper functions
239
240 (defun vc-latest-on-branch-p (file)
241 ;; return t iff the current workfile version of FILE is
242 ;; the latest on its branch.
243 (vc-backend-dispatch file
244 ;; SCCS
245 (string= (vc-workfile-version file) (vc-latest-version file))
246 ;; RCS
247 (let ((workfile-version (vc-workfile-version file)) tip-version)
248 (if (vc-trunk-p workfile-version)
249 (progn
250 ;; Re-fetch the head version number. This is to make
251 ;; sure that no-one has checked in a new version behind
252 ;; our back.
253 (vc-fetch-master-properties file)
254 (string= (vc-file-getprop file 'vc-head-version)
255 workfile-version))
256 ;; If we are not on the trunk, we need to examine the
257 ;; whole current branch. (vc-top-version is not what we need.)
258 (save-excursion
259 (set-buffer (get-buffer-create "*vc-info*"))
260 (vc-insert-file (vc-name file) "^desc")
261 (setq tip-version (car (vc-parse-buffer (list (list
262 (concat "^\\(" (regexp-quote (vc-branch-part workfile-version))
263 "\\.[0-9]+\\)\ndate[ \t]+\\([0-9.]+\\);") 1 2)))))
264 (if (get-buffer "*vc-info*")
265 (kill-buffer (get-buffer "*vc-info*")))
266 (string= tip-version workfile-version))))
267 ;; CVS
268 (error "vc-latest-on-branch-p is not defined for CVS files")))
233 269
234 (defun vc-registration-error (file) 270 (defun vc-registration-error (file)
235 (if file 271 (if file
236 (error "File %s is not under version control" file) 272 (error "File %s is not under version control" file)
237 (error "Buffer %s is not associated with a file" (buffer-name)))) 273 (error "Buffer %s is not associated with a file" (buffer-name))))
320 ) 356 )
321 357
322 ;;; Save a bit of the text around POSN in the current buffer, to help 358 ;;; Save a bit of the text around POSN in the current buffer, to help
323 ;;; us find the corresponding position again later. This works even 359 ;;; us find the corresponding position again later. This works even
324 ;;; if all markers are destroyed or corrupted. 360 ;;; if all markers are destroyed or corrupted.
361 ;;; A lot of this was shamelessly lifted from Sebastian Kremer's rcs.el mode.
325 (defun vc-position-context (posn) 362 (defun vc-position-context (posn)
326 (list posn 363 (list posn
327 (buffer-size) 364 (buffer-size)
328 (buffer-substring posn 365 (buffer-substring posn
329 (min (point-max) (+ posn 100))))) 366 (min (point-max) (+ posn 100)))))
346 ;; beginning of buffer like backward-char would 383 ;; beginning of buffer like backward-char would
347 (search-forward context-string nil t))) 384 (search-forward context-string nil t)))
348 ;; to beginning of OSTRING 385 ;; to beginning of OSTRING
349 (- (point) (length context-string)))))))) 386 (- (point) (length context-string))))))))
350 387
351 (defun vc-revert-buffer1 (&optional arg no-confirm) 388 (defun vc-buffer-context ()
352 ;; Most of this was shamelessly lifted from Sebastian Kremer's rcs.el mode. 389 ;; Return a list '(point-context mark-context reparse); from which
353 ;; Revert buffer, try to keep point and mark where user expects them in spite 390 ;; vc-restore-buffer-context can later restore the context.
354 ;; of changes because of expanded version-control key words.
355 ;; This is quite important since otherwise typeahead won't work as expected.
356 (interactive "P")
357 (widen)
358 (let ((point-context (vc-position-context (point))) 391 (let ((point-context (vc-position-context (point)))
359 ;; Use mark-marker to avoid confusion in transient-mark-mode. 392 ;; Use mark-marker to avoid confusion in transient-mark-mode.
360 (mark-context (if (eq (marker-buffer (mark-marker)) (current-buffer)) 393 (mark-context (if (eq (marker-buffer (mark-marker)) (current-buffer))
361 (vc-position-context (mark-marker)))) 394 (vc-position-context (mark-marker))))
362 ;; Make the right thing happen in transient-mark-mode. 395 ;; Make the right thing happen in transient-mark-mode.
383 (cdr (car errors)))) 416 (cdr (car errors))))
384 (setq buffer-error-marked-p t)) 417 (setq buffer-error-marked-p t))
385 (setq errors (cdr errors))) 418 (setq errors (cdr errors)))
386 (if buffer-error-marked-p buffer)))) 419 (if buffer-error-marked-p buffer))))
387 (buffer-list))))))) 420 (buffer-list)))))))
388 421 (list point-context mark-context reparse)))
389 (revert-buffer arg no-confirm) 422
390 423 (defun vc-restore-buffer-context (context)
424 ;; Restore point/mark, and reparse any affected compilation buffers.
425 ;; CONTEXT is that which vc-buffer-context returns.
426 (let ((point-context (nth 0 context))
427 (mark-context (nth 1 context))
428 (reparse (nth 2 context)))
391 ;; Reparse affected compilation buffers. 429 ;; Reparse affected compilation buffers.
392 (while reparse 430 (while reparse
393 (if (car reparse) 431 (if (car reparse)
394 (save-excursion 432 (save-excursion
395 (set-buffer (car reparse)) 433 (set-buffer (car reparse))
411 (let ((new-point (vc-find-position-by-context point-context))) 449 (let ((new-point (vc-find-position-by-context point-context)))
412 (if new-point (goto-char new-point))) 450 (if new-point (goto-char new-point)))
413 (if mark-context 451 (if mark-context
414 (let ((new-mark (vc-find-position-by-context mark-context))) 452 (let ((new-mark (vc-find-position-by-context mark-context)))
415 (if new-mark (set-mark new-mark)))))) 453 (if new-mark (set-mark new-mark))))))
454
455 (defun vc-revert-buffer1 (&optional arg no-confirm)
456 ;; Revert buffer, try to keep point and mark where user expects them in spite
457 ;; of changes because of expanded version-control key words.
458 ;; This is quite important since otherwise typeahead won't work as expected.
459 (interactive "P")
460 (widen)
461 (let ((context (vc-buffer-context)))
462 (revert-buffer arg no-confirm)
463 (vc-restore-buffer-context context)))
416 464
417 465
418 (defun vc-buffer-sync (&optional not-urgent) 466 (defun vc-buffer-sync (&optional not-urgent)
419 ;; Make sure the current buffer and its working file are in sync 467 ;; Make sure the current buffer and its working file are in sync
420 ;; NOT-URGENT means it is ok to continue if the user says not to save. 468 ;; NOT-URGENT means it is ok to continue if the user says not to save.
1086 (if (string-match (car f) buffer-file-name) 1134 (if (string-match (car f) buffer-file-name)
1087 (insert (format (cdr f) (car hdstrings)))))) 1135 (insert (format (cdr f) (car hdstrings))))))
1088 vc-static-header-alist)) 1136 vc-static-header-alist))
1089 ) 1137 )
1090 ))))) 1138 )))))
1139
1140 (defun vc-clear-headers ()
1141 ;; Clear all version headers in the current buffer, i.e. reset them
1142 ;; to the nonexpanded form. Only implemented for RCS, yet.
1143 ;; Don't lose point and mark during this.
1144 (let ((context (vc-buffer-context)))
1145 (goto-char (point-min))
1146 (while (re-search-forward "\\$\\([A-Za-z]+\\): [^\\$]+\\$" nil t)
1147 (replace-match "$\\1$"))
1148 (vc-restore-buffer-context context)))
1091 1149
1092 ;; The VC directory submode. Coopt Dired for this. 1150 ;; The VC directory submode. Coopt Dired for this.
1093 ;; All VC commands get mapped into logical equivalents. 1151 ;; All VC commands get mapped into logical equivalents.
1094 1152
1095 (defvar vc-dired-prefix-map (make-sparse-keymap)) 1153 (defvar vc-dired-prefix-map (make-sparse-keymap))
1395 (interactive "P") 1453 (interactive "P")
1396 (if vc-dired-mode 1454 (if vc-dired-mode
1397 (find-file-other-window (dired-get-filename))) 1455 (find-file-other-window (dired-get-filename)))
1398 (while vc-parent-buffer 1456 (while vc-parent-buffer
1399 (pop-to-buffer vc-parent-buffer)) 1457 (pop-to-buffer vc-parent-buffer))
1400 (if (eq (vc-backend (buffer-file-name)) 'CVS) 1458 (cond
1401 (error "Unchecking files under CVS is dangerous and not supported in VC")) 1459 ((eq (vc-backend (buffer-file-name)) 'CVS)
1402 (let* ((target (concat (vc-latest-version (buffer-file-name)))) 1460 (error "Unchecking files under CVS is dangerous and not supported in VC"))
1403 (yours (concat (vc-your-latest-version (buffer-file-name)))) 1461 ((vc-locking-user (buffer-file-name))
1404 (prompt (if (string-equal yours target) 1462 (error "This version is locked. Use vc-revert-buffer to discard changes."))
1405 "Remove your version %s from master? " 1463 ((not (vc-latest-on-branch-p (buffer-file-name)))
1406 "Version %s was not your change. Remove it anyway? "))) 1464 (error "This is not the latest version. VC cannot cancel it.")))
1407 (if (null (yes-or-no-p (format prompt target))) 1465 (let ((target (vc-workfile-version (buffer-file-name))))
1466 (if (null (yes-or-no-p "Remove this version from master? "))
1408 nil 1467 nil
1468 (setq norevert (or norevert (not
1469 (yes-or-no-p "Revert buffer to most recent remaining version? "))))
1409 (vc-backend-uncheck (buffer-file-name) target) 1470 (vc-backend-uncheck (buffer-file-name) target)
1410 (if (or norevert 1471 (if (not norevert)
1411 (not (yes-or-no-p "Revert buffer to most recent remaining version? "))) 1472 (vc-checkout (buffer-file-name) nil)
1412 (vc-mode-line (buffer-file-name)) 1473 ;; If norevert, lock the most recent remaining version,
1413 (vc-checkout (buffer-file-name) nil))) 1474 ;; and mark the buffer modified.
1414 )) 1475 (if (eq (vc-backend (buffer-file-name)) 'RCS)
1476 (progn (setq buffer-read-only nil)
1477 (vc-clear-headers)))
1478 (vc-backend-checkout (buffer-file-name) t (vc-branch-part target))
1479 (set-visited-file-name (buffer-file-name))
1480 (vc-mode-line (buffer-file-name)))
1481 (message "Version %s has been removed from the master." target)
1482 )))
1415 1483
1416 ;;;###autoload 1484 ;;;###autoload
1417 (defun vc-rename-file (old new) 1485 (defun vc-rename-file (old new)
1418 "Rename file OLD to NEW, and rename its master file likewise." 1486 "Rename file OLD to NEW, and rename its master file likewise."
1419 (interactive "fVC rename file: \nFRename to: ") 1487 (interactive "fVC rename file: \nFRename to: ")
1839 (vc-file-setprop file 'vc-locking-user (user-login-name)) 1907 (vc-file-setprop file 'vc-locking-user (user-login-name))
1840 (message "Stealing lock on %s...done" file) 1908 (message "Stealing lock on %s...done" file)
1841 ) 1909 )
1842 1910
1843 (defun vc-backend-uncheck (file target) 1911 (defun vc-backend-uncheck (file target)
1844 ;; Undo the latest checkin. Note: this code will have to get a lot 1912 ;; Undo the latest checkin.
1845 ;; smarter when we support multiple branches.
1846 (message "Removing last change from %s..." file) 1913 (message "Removing last change from %s..." file)
1847 (vc-backend-dispatch file 1914 (vc-backend-dispatch file
1848 (vc-do-command nil 0 "rmdel" file 'MASTER (concat "-r" target)) 1915 (vc-do-command nil 0 "rmdel" file 'MASTER (concat "-r" target))
1849 (vc-do-command nil 0 "rcs" file 'MASTER (concat "-o" target)) 1916 (vc-do-command nil 0 "rcs" file 'MASTER (concat "-o" target))
1850 nil ;; this is never reached under CVS 1917 nil ;; this is never reached under CVS