32 |
|
|
33 |
;;; Bugs: |
;;; Bugs: |
34 |
|
|
35 |
;; - VC-dired is either not working or (really) dog slow. |
;; - VC-dired is (really) slow. |
|
;; - vc-print-log does not always jump to the proper log entry because |
|
|
;; it tries to jump to version 1234 even if there's only an entry |
|
|
;; for 1232 (because the file hasn't changed since). |
|
36 |
|
|
37 |
;;; Code: |
;;; Code: |
38 |
|
|
195 |
|
|
196 |
(defun vc-svn-dired-state-info (file) |
(defun vc-svn-dired-state-info (file) |
197 |
"SVN-specific version of `vc-dired-state-info'." |
"SVN-specific version of `vc-dired-state-info'." |
198 |
(let* ((svn-state (vc-state file)) |
(let ((svn-state (vc-state file))) |
199 |
(state (cond ((eq svn-state 'edited) "modified") |
(cond ((eq svn-state 'edited) |
200 |
((eq svn-state 'needs-patch) "patch") |
(if (equal (vc-workfile-version file) "0") |
201 |
((eq svn-state 'needs-merge) "merge") |
"(added)" "(modified)")) |
202 |
;; FIXME: those two states cannot occur right now |
((eq svn-state 'needs-patch) "(patch)") |
203 |
((eq svn-state 'unlocked-changes) "conflict") |
((eq svn-state 'needs-merge) "(merge)")))) |
|
((eq svn-state 'locally-added) "added") |
|
|
))) |
|
|
(if state (concat "(" state ")")))) |
|
204 |
|
|
205 |
|
|
206 |
;;; |
;;; |
213 |
|
|
214 |
`vc-register-switches' and `vc-svn-register-switches' are passed to |
`vc-register-switches' and `vc-svn-register-switches' are passed to |
215 |
the SVN command (in that order)." |
the SVN command (in that order)." |
216 |
(let ((switches (append |
(apply 'vc-svn-command nil 0 file |
217 |
(if (stringp vc-register-switches) |
"add" |
218 |
(list vc-register-switches) |
;; (and comment (string-match "[^\t\n ]" comment) |
219 |
vc-register-switches) |
;; (concat "-m" comment)) |
220 |
(if (stringp vc-svn-register-switches) |
(vc-switches 'SVN 'register))) |
|
(list vc-svn-register-switches) |
|
|
vc-svn-register-switches)))) |
|
|
|
|
|
(apply 'vc-svn-command nil 0 file |
|
|
"add" |
|
|
;; (and comment (string-match "[^\t\n ]" comment) |
|
|
;; (concat "-m" comment)) |
|
|
switches))) |
|
221 |
|
|
222 |
(defun vc-svn-responsible-p (file) |
(defun vc-svn-responsible-p (file) |
223 |
"Return non-nil if SVN thinks it is responsible for FILE." |
"Return non-nil if SVN thinks it is responsible for FILE." |
232 |
|
|
233 |
(defun vc-svn-checkin (file rev comment) |
(defun vc-svn-checkin (file rev comment) |
234 |
"SVN-specific version of `vc-backend-checkin'." |
"SVN-specific version of `vc-backend-checkin'." |
235 |
(let ((switches (if (stringp vc-checkin-switches) |
(let ((status (apply 'vc-svn-command nil 1 file |
236 |
(list vc-checkin-switches) |
"ci" (list* "-m" comment (vc-switches 'SVN 'checkin))))) |
|
vc-checkin-switches)) |
|
|
status) |
|
|
(setq status (apply 'vc-svn-command nil 1 file |
|
|
"ci" (list* "-m" comment switches))) |
|
237 |
(set-buffer "*vc*") |
(set-buffer "*vc*") |
238 |
(goto-char (point-min)) |
(goto-char (point-min)) |
239 |
(unless (equal status 0) |
(unless (equal status 0) |
240 |
;; Check checkin problem. |
;; Check checkin problem. |
241 |
(cond |
(cond |
242 |
((re-search-forward "Up-to-date check failed" nil t) |
((search-forward "Transaction is out of date" nil t) |
243 |
(vc-file-setprop file 'vc-state 'needs-merge) |
(vc-file-setprop file 'vc-state 'needs-merge) |
244 |
(error (substitute-command-keys |
(error (substitute-command-keys |
245 |
(concat "Up-to-date check failed: " |
(concat "Up-to-date check failed: " |
261 |
"cat" |
"cat" |
262 |
(and rev (not (string= rev "")) |
(and rev (not (string= rev "")) |
263 |
(concat "-r" rev)) |
(concat "-r" rev)) |
264 |
(if (stringp vc-checkout-switches) |
(vc-switches 'SVN 'checkout))) |
|
(list vc-checkout-switches) |
|
|
vc-checkout-switches))) |
|
265 |
|
|
266 |
(defun vc-svn-checkout (file &optional editable rev) |
(defun vc-svn-checkout (file &optional editable rev) |
267 |
(message "Checking out %s..." file) |
(message "Checking out %s..." file) |
268 |
(with-current-buffer (or (get-file-buffer file) (current-buffer)) |
(with-current-buffer (or (get-file-buffer file) (current-buffer)) |
269 |
(let ((switches (if (stringp vc-checkout-switches) |
(vc-call update file editable rev (vc-switches 'SVN 'checkout))) |
|
(list vc-checkout-switches) |
|
|
vc-checkout-switches))) |
|
|
(vc-call update file editable rev switches))) |
|
270 |
(vc-mode-line file) |
(vc-mode-line file) |
271 |
(message "Checking out %s...done" file)) |
(message "Checking out %s...done" file)) |
272 |
|
|
380 |
|
|
381 |
(defun vc-svn-diff (file &optional oldvers newvers) |
(defun vc-svn-diff (file &optional oldvers newvers) |
382 |
"Get a difference report using SVN between two versions of FILE." |
"Get a difference report using SVN between two versions of FILE." |
383 |
(let (status (diff-switches-list (vc-diff-switches-list 'SVN))) |
(if (string= (vc-workfile-version file) "0") |
384 |
(if (string= (vc-workfile-version file) "0") |
;; This file is added but not yet committed; there is no master file. |
385 |
;; This file is added but not yet committed; there is no master file. |
(if (or oldvers newvers) |
386 |
(if (or oldvers newvers) |
(error "No revisions of %s exist" file) |
387 |
(error "No revisions of %s exist" file) |
;; We regard this as "changed". |
388 |
;; We regard this as "changed". |
;; Diff it against /dev/null. |
389 |
;; Diff it against /dev/null. |
;; Note: this is NOT a "svn diff". |
390 |
;; Note: this is NOT a "svn diff". |
(apply 'vc-do-command "*vc-diff*" |
391 |
(apply 'vc-do-command "*vc-diff*" |
1 "diff" file |
392 |
1 "diff" file |
(append (vc-switches nil 'diff) '("/dev/null"))) |
393 |
(append diff-switches-list '("/dev/null")))) |
;; Even if it's empty, it's locally modified. |
394 |
(setq status |
1) |
395 |
(apply 'vc-svn-command "*vc-diff*" |
(let* ((switches (vc-switches 'SVN 'diff)) |
396 |
(if (and (vc-svn-stay-local-p file) |
(async (and (vc-svn-stay-local-p file) |
397 |
(or oldvers newvers) ; Svn diffs those locally. |
(or oldvers newvers) ; Svn diffs those locally. |
398 |
(fboundp 'start-process)) |
(fboundp 'start-process))) |
399 |
'async |
(status |
400 |
1) |
(apply 'vc-svn-command "*vc-diff*" |
401 |
file "diff" |
(if async 'async 1) |
402 |
|
file "diff" |
403 |
(append |
(append |
404 |
|
(when switches |
405 |
|
(list "-x" (mapconcat 'identity switches " "))) |
406 |
(when oldvers |
(when oldvers |
407 |
(list "-r" |
(list "-r" (if newvers (concat oldvers ":" newvers) |
408 |
(if newvers (concat oldvers ":" newvers) oldvers))) |
oldvers))))))) |
409 |
(when diff-switches-list |
(if async 1 ; async diff => pessimistic assumption |
410 |
(list "-x" (mapconcat 'identity diff-switches-list " ")))))) |
;; For some reason `svn diff' does not return a useful |
411 |
(if (vc-svn-stay-local-p file) |
;; status w.r.t whether the diff was empty or not. |
412 |
1 ;; async diff, pessimistic assumption |
(buffer-size (get-buffer "*vc-diff*")))))) |
|
status)))) |
|
413 |
|
|
414 |
(defun vc-svn-diff-tree (dir &optional rev1 rev2) |
(defun vc-svn-diff-tree (dir &optional rev1 rev2) |
415 |
"Diff all files at and below DIR." |
"Diff all files at and below DIR." |
429 |
(vc-diff-internal ',f ',rev1 ',rev2)))))) |
(vc-diff-internal ',f ',rev1 ',rev2)))))) |
430 |
;; svn diff: use a single call for the entire tree |
;; svn diff: use a single call for the entire tree |
431 |
(let ((coding-system-for-read (or coding-system-for-read 'undecided)) |
(let ((coding-system-for-read (or coding-system-for-read 'undecided)) |
432 |
(diff-switches-list (vc-diff-switches-list 'SVN))) |
(switches (vc-switches 'SVN 'diff))) |
433 |
(apply 'vc-svn-command "*vc-diff*" 1 nil "diff" |
(apply 'vc-svn-command "*vc-diff*" 1 nil "diff" |
434 |
(append |
(append |
435 |
(when rev1 |
(when rev1 |
436 |
(list "-r" |
(list "-r" (if rev2 (concat rev1 ":" rev2) rev1))) |
437 |
(if rev2 (concat rev1 ":" rev2) rev1))) |
(when switches |
438 |
(when diff-switches-list |
(list "-x" (mapconcat 'identity switches " "))))))))) |
|
(list "-x" (mapconcat 'identity diff-switches-list " "))))))))) |
|
439 |
|
|
440 |
;;; |
;;; |
441 |
;;; Snapshot system |
;;; Snapshot system |
564 |
(setq stay-local (not stay-local))) |
(setq stay-local (not stay-local))) |
565 |
(if stay-local |
(if stay-local |
566 |
'yes |
'yes |
567 |
'no)))))))))))))) |
'no)))))))) |
568 |
|
;; vc-svn-stay-local is neither nil nor list nor string. |
569 |
|
(t 'yes))))))) |
570 |
(if (eq prop 'yes) t nil)))) |
(if (eq prop 'yes) t nil)))) |
571 |
|
|
572 |
(defun vc-svn-parse-status (localp) |
(defun vc-svn-parse-status (localp) |
576 |
(let (file status) |
(let (file status) |
577 |
(goto-char (point-min)) |
(goto-char (point-min)) |
578 |
(while (re-search-forward |
(while (re-search-forward |
579 |
"^[ ADMCI?!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\) +" nil t) |
"^[ ADMCI?!~][ MC][ L][ +][ S]..\\([ *]\\) +\\([-0-9]+\\) +\\([0-9?]+\\) +\\([^ ]+\\) +" nil t) |
580 |
(setq file (expand-file-name |
(setq file (expand-file-name |
581 |
(buffer-substring (point) (line-end-position)))) |
(buffer-substring (point) (line-end-position)))) |
582 |
(setq status (char-after (line-beginning-position))) |
(setq status (char-after (line-beginning-position))) |
583 |
(unless (eq status ??) |
(unless (eq status ??) |
584 |
(vc-file-setprop file 'vc-backend 'SVN) |
(vc-file-setprop file 'vc-backend 'SVN) |
585 |
(vc-file-setprop file 'vc-workfile-version (match-string 2)) |
;; Use the last-modified revision, so that searching in vc-print-log |
586 |
|
;; output works. |
587 |
|
(vc-file-setprop file 'vc-workfile-version (match-string 3)) |
588 |
(vc-file-setprop |
(vc-file-setprop |
589 |
file 'vc-state |
file 'vc-state |
590 |
(cond |
(cond |
595 |
(nth 5 (file-attributes file))) |
(nth 5 (file-attributes file))) |
596 |
'up-to-date)) |
'up-to-date)) |
597 |
((eq status ?A) |
((eq status ?A) |
598 |
|
;; If the file was actually copied, (match-string 2) is "-". |
599 |
|
(vc-file-setprop file 'vc-workfile-version "0") |
600 |
(vc-file-setprop file 'vc-checkout-time 0) |
(vc-file-setprop file 'vc-checkout-time 0) |
601 |
'edited) |
'edited) |
602 |
((memq status '(?M ?C)) |
((memq status '(?M ?C)) |