diff options
| author | Göktuğ Kayaalp | 2016-10-18 03:01:58 +0300 |
|---|---|---|
| committer | Dmitry Gutov | 2016-10-18 03:03:17 +0300 |
| commit | e535ca4522222e68c9405a51c2abba83f9f2cd69 (patch) | |
| tree | b37ca8035868e49897d086db9b0c40cc3e7c046d /lisp | |
| parent | 12da149670a40c6d6c1bc107e8c29d7fcdcf7824 (diff) | |
| download | emacs-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.el | 137 |
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." | |||
| 1071 | Query all files in DIR if files is nil." | 1000 | Query 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." |