aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorGöktuğ Kayaalp2016-10-18 03:01:58 +0300
committerDmitry Gutov2016-10-18 03:03:17 +0300
commite535ca4522222e68c9405a51c2abba83f9f2cd69 (patch)
treeb37ca8035868e49897d086db9b0c40cc3e7c046d /lisp
parent12da149670a40c6d6c1bc107e8c29d7fcdcf7824 (diff)
downloademacs-e535ca4522222e68c9405a51c2abba83f9f2cd69.tar.gz
emacs-e535ca4522222e68c9405a51c2abba83f9f2cd69.zip
Fix display of vc-dir CVS file statuses in subdirectories
* lisp/vc/vc-cvs.el (vc-cvs-dir-status-files): Use 'cvs update' instead of 'cvs status'. It's faster, easier to parse, and relieves us of the need to use vc-expand-dirs. (Bug#24082) (vc-cvs-after-dir-status): Parse its output.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/vc/vc-cvs.el137
1 files changed, 31 insertions, 106 deletions
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index a2499a2294b..3cfe8ee56a2 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -938,103 +938,32 @@ state."
938 (t 'edited)))))))) 938 (t 'edited))))))))
939 939
940(defun vc-cvs-after-dir-status (update-function) 940(defun vc-cvs-after-dir-status (update-function)
941 ;; Heavily inspired by vc-cvs-parse-status. AKA a quick hack. 941 (let ((result nil)
942 ;; This needs a lot of testing. 942 (translation '((?? . unregistered)
943 (let ((status nil) 943 (?A . added)
944 (status-str nil) 944 (?C . conflict)
945 (file nil) 945 (?M . edited)
946 (result nil) 946 (?P . needs-merge)
947 (missing nil) 947 (?R . removed)
948 (ignore-next nil) 948 (?U . needs-update))))
949 (subdir default-directory))
950 (goto-char (point-min)) 949 (goto-char (point-min))
951 (while 950 (while (not (eobp))
952 ;; Look for either a file entry, an unregistered file, or a 951 (if (looking-at "^[ACMPRU?] \\(.*\\)$")
953 ;; directory change. 952 (push (list (match-string 1)
954 (re-search-forward 953 (cdr (assoc (char-after) translation)))
955 "\\(^=+\n\\([^=c?\n].*\n\\|\n\\)+\\)\\|\\(\\(^?? .*\n\\)+\\)\\|\\(^cvs status: \\(Examining\\|nothing\\) .*\n\\)" 954 result)
956 nil t) 955 (cond
957 ;; FIXME: get rid of narrowing here. 956 ((looking-at "cvs update: warning: \\(.*\\) was lost")
958 (narrow-to-region (match-beginning 0) (match-end 0)) 957 ;; Format is:
959 (goto-char (point-min)) 958 ;; cvs update: warning: FILENAME was lost
960 ;; The subdir 959 ;; U FILENAME
961 (when (looking-at "cvs status: Examining \\(.+\\)") 960 (push (list (match-string 1) 'missing) result)
962 (setq subdir (expand-file-name (match-string 1)))) 961 ;; Skip the "U" line
963 ;; Unregistered files 962 (forward-line 1))
964 (while (looking-at "? \\(.*\\)") 963 ((looking-at "cvs update: New directory `\\(.*\\)' -- ignored")
965 (setq file (file-relative-name 964 (push (list (match-string 1) 'unregistered) result))))
966 (expand-file-name (match-string 1) subdir))) 965 (forward-line 1))
967 (push (list file 'unregistered) result) 966 (funcall update-function result)))
968 (forward-line 1))
969 (when (looking-at "cvs status: nothing known about")
970 ;; We asked about a non existent file. The output looks like this:
971
972 ;; cvs status: nothing known about `lisp/v.diff'
973 ;; ===================================================================
974 ;; File: no file v.diff Status: Unknown
975 ;;
976 ;; Working revision: No entry for v.diff
977 ;; Repository revision: No revision control file
978 ;;
979
980 ;; Due to narrowing in this iteration we only see the "cvs
981 ;; status:" line, so just set a flag so that we can ignore the
982 ;; file in the next iteration.
983 (setq ignore-next t))
984 ;; A file entry.
985 (when (re-search-forward "^File: \\(no file \\)?\\(.*[^ \t]\\)[ \t]+Status: \\(.*\\)" nil t)
986 (setq missing (match-string 1))
987 (setq file (file-relative-name
988 (expand-file-name (match-string 2) subdir)))
989 (setq status-str (match-string 3))
990 (setq status
991 (cond
992 ((string-match "Up-to-date" status-str) 'up-to-date)
993 ((string-match "Locally Modified" status-str) 'edited)
994 ((string-match "Needs Merge" status-str) 'needs-merge)
995 ((string-match "Needs \\(Checkout\\|Patch\\)" status-str)
996 (if missing 'missing 'needs-update))
997 ((string-match "Locally Added" status-str) 'added)
998 ((string-match "Locally Removed" status-str) 'removed)
999 ((string-match "File had conflicts " status-str) 'conflict)
1000 ((string-match "Unknown" status-str) 'unregistered)
1001 (t 'edited)))
1002 (if ignore-next
1003 (setq ignore-next nil)
1004 (unless (eq status 'up-to-date)
1005 (push (list file status) result))))
1006 (goto-char (point-max))
1007 (widen))
1008 (funcall update-function result))
1009 ;; Alternative implementation: use the "update" command instead of
1010 ;; the "status" command.
1011 ;; (let ((result nil)
1012 ;; (translation '((?? . unregistered)
1013 ;; (?A . added)
1014 ;; (?C . conflict)
1015 ;; (?M . edited)
1016 ;; (?P . needs-merge)
1017 ;; (?R . removed)
1018 ;; (?U . needs-update))))
1019 ;; (goto-char (point-min))
1020 ;; (while (not (eobp))
1021 ;; (if (looking-at "^[ACMPRU?] \\(.*\\)$")
1022 ;; (push (list (match-string 1)
1023 ;; (cdr (assoc (char-after) translation)))
1024 ;; result)
1025 ;; (cond
1026 ;; ((looking-at "cvs update: warning: \\(.*\\) was lost")
1027 ;; ;; Format is:
1028 ;; ;; cvs update: warning: FILENAME was lost
1029 ;; ;; U FILENAME
1030 ;; (push (list (match-string 1) 'missing) result)
1031 ;; ;; Skip the "U" line
1032 ;; (forward-line 1))
1033 ;; ((looking-at "cvs update: New directory `\\(.*\\)' -- ignored")
1034 ;; (push (list (match-string 1) 'unregistered) result))))
1035 ;; (forward-line 1))
1036 ;; (funcall update-function result)))
1037 )
1038 967
1039;; Based on vc-cvs-dir-state-heuristic from Emacs 22. 968;; Based on vc-cvs-dir-state-heuristic from Emacs 22.
1040;; FIXME does not mention unregistered files. 969;; FIXME does not mention unregistered files.
@@ -1071,16 +1000,12 @@ state."
1071Query all files in DIR if files is nil." 1000Query all files in DIR if files is nil."
1072 (let ((local (vc-cvs-stay-local-p dir))) 1001 (let ((local (vc-cvs-stay-local-p dir)))
1073 (if (and (not files) local (not (eq local 'only-file))) 1002 (if (and (not files) local (not (eq local 'only-file)))
1074 (vc-cvs-dir-status-heuristic dir update-function) 1003 (vc-cvs-dir-status-heuristic dir update-function))
1075 (if (not files) (setq files (vc-expand-dirs (list dir) 'CVS))) 1004 (vc-cvs-command (current-buffer) 'async
1076 (vc-cvs-command (current-buffer) 'async files "-f" "status") 1005 files
1077 ;; Alternative implementation: use the "update" command instead of 1006 "-f" "-n" "-q" "update")
1078 ;; the "status" command. 1007 (vc-run-delayed
1079 ;; (vc-cvs-command (current-buffer) 'async 1008 (vc-cvs-after-dir-status update-function))))
1080 ;; (file-relative-name dir)
1081 ;; "-f" "-n" "update" "-d" "-P")
1082 (vc-run-delayed
1083 (vc-cvs-after-dir-status update-function)))))
1084 1009
1085(defun vc-cvs-file-to-string (file) 1010(defun vc-cvs-file-to-string (file)
1086 "Read the content of FILE and return it as a string." 1011 "Read the content of FILE and return it as a string."