diff options
| author | Po Lu | 2023-04-19 09:14:25 +0800 |
|---|---|---|
| committer | Po Lu | 2023-04-19 09:14:25 +0800 |
| commit | 5b314731894f09bb71fd02c76add45263e2d4f77 (patch) | |
| tree | 7f5f225277f7014397bad473622a525b793102b9 | |
| parent | 55388c288a0b05fe51f15b065db5b61c99bab867 (diff) | |
| parent | 9a2c723f1bc592fdd28763c8ec67129c5c5d91f1 (diff) | |
| download | emacs-5b314731894f09bb71fd02c76add45263e2d4f77.tar.gz emacs-5b314731894f09bb71fd02c76add45263e2d4f77.zip | |
Merge remote-tracking branch 'origin/master' into feature/android
| -rw-r--r-- | lisp/gnus/gnus-sum.el | 4 | ||||
| -rw-r--r-- | lisp/progmodes/eglot.el | 19 | ||||
| -rw-r--r-- | lisp/progmodes/flymake.el | 10 | ||||
| -rw-r--r-- | lisp/progmodes/verilog-mode.el | 54 | ||||
| -rw-r--r-- | lisp/vc/vc-cvs.el | 215 | ||||
| -rw-r--r-- | lisp/vc/vc.el | 3 | ||||
| -rw-r--r-- | test/lisp/vc/vc-cvs-tests.el | 107 |
7 files changed, 304 insertions, 108 deletions
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 35e867a3508..4effaa981ec 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el | |||
| @@ -9081,8 +9081,8 @@ is non-numeric or nil fetch the number specified by the | |||
| 9081 | (cl-merge 'list gnus-newsgroup-headers new-headers | 9081 | (cl-merge 'list gnus-newsgroup-headers new-headers |
| 9082 | 'gnus-article-sort-by-number))) | 9082 | 'gnus-article-sort-by-number))) |
| 9083 | (setq gnus-newsgroup-articles | 9083 | (setq gnus-newsgroup-articles |
| 9084 | (gnus-sorted-nunion gnus-newsgroup-articles article-ids)) | 9084 | (gnus-sorted-nunion gnus-newsgroup-articles article-ids))) |
| 9085 | (gnus-summary-limit-include-thread id gnus-refer-thread-limit-to-thread))) | 9085 | (gnus-summary-limit-include-thread id gnus-refer-thread-limit-to-thread)) |
| 9086 | (gnus-summary-show-thread)) | 9086 | (gnus-summary-show-thread)) |
| 9087 | 9087 | ||
| 9088 | (defun gnus-summary-open-group-with-article (message-id) | 9088 | (defun gnus-summary-open-group-with-article (message-id) |
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7ad33fa3786..fe0c986d746 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -1935,10 +1935,9 @@ Use `eglot-managed-p' to determine if current buffer is managed.") | |||
| 1935 | "Return logical Eglot server for current buffer, nil if none." | 1935 | "Return logical Eglot server for current buffer, nil if none." |
| 1936 | (setq eglot--cached-server | 1936 | (setq eglot--cached-server |
| 1937 | (or eglot--cached-server | 1937 | (or eglot--cached-server |
| 1938 | (cl-find major-mode | 1938 | (cl-find-if #'eglot--languageId |
| 1939 | (gethash (eglot--current-project) eglot--servers-by-project) | 1939 | (gethash (eglot--current-project) |
| 1940 | :key #'eglot--major-modes | 1940 | eglot--servers-by-project)) |
| 1941 | :test #'memq) | ||
| 1942 | (and eglot-extend-to-xref | 1941 | (and eglot-extend-to-xref |
| 1943 | buffer-file-name | 1942 | buffer-file-name |
| 1944 | (gethash (expand-file-name buffer-file-name) | 1943 | (gethash (expand-file-name buffer-file-name) |
| @@ -2360,12 +2359,20 @@ THINGS are either registrations or unregisterations (sic)." | |||
| 2360 | (append (eglot--TextDocumentIdentifier) | 2359 | (append (eglot--TextDocumentIdentifier) |
| 2361 | `(:version ,eglot--versioned-identifier))) | 2360 | `(:version ,eglot--versioned-identifier))) |
| 2362 | 2361 | ||
| 2362 | (cl-defun eglot--languageId (&optional (server (eglot--current-server-or-lose))) | ||
| 2363 | "Compute LSP \\='languageId\\=' string for current buffer. | ||
| 2364 | Doubles as an predicate telling if SERVER can manage current | ||
| 2365 | buffer." | ||
| 2366 | (cl-loop for (mode . languageid) in | ||
| 2367 | (eglot--languages server) | ||
| 2368 | when (provided-mode-derived-p major-mode mode) | ||
| 2369 | return languageid)) | ||
| 2370 | |||
| 2363 | (defun eglot--TextDocumentItem () | 2371 | (defun eglot--TextDocumentItem () |
| 2364 | "Compute TextDocumentItem object for current buffer." | 2372 | "Compute TextDocumentItem object for current buffer." |
| 2365 | (append | 2373 | (append |
| 2366 | (eglot--VersionedTextDocumentIdentifier) | 2374 | (eglot--VersionedTextDocumentIdentifier) |
| 2367 | (list :languageId | 2375 | (list :languageId (eglot--languageId) |
| 2368 | (alist-get major-mode (eglot--languages (eglot--current-server-or-lose))) | ||
| 2369 | :text | 2376 | :text |
| 2370 | (eglot--widening | 2377 | (eglot--widening |
| 2371 | (buffer-substring-no-properties (point-min) (point-max)))))) | 2378 | (buffer-substring-no-properties (point-min) (point-max)))))) |
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index b744a717c5c..f03b9ab56a0 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el | |||
| @@ -447,25 +447,25 @@ verify FILTER, a function, and sort them by COMPARE (using KEY)." | |||
| 447 | :package-version '(Flymake . "1.3.4")) | 447 | :package-version '(Flymake . "1.3.4")) |
| 448 | 448 | ||
| 449 | (defface flymake-end-of-line-diagnostics-face | 449 | (defface flymake-end-of-line-diagnostics-face |
| 450 | '((t :height 0.7 :box (:line-width 1))) | 450 | '((t :height 0.85 :box (:line-width -1))) |
| 451 | "Face used for end-of-line diagnostics. | 451 | "Face used for end-of-line diagnostics. |
| 452 | See variable `flymake-show-diagnostics-at-end-of-line'." | 452 | See variable `flymake-show-diagnostics-at-end-of-line'." |
| 453 | :package-version '("Flymake" . "1.3.5")) | 453 | :package-version '(Flymake . "1.3.5")) |
| 454 | 454 | ||
| 455 | (defface flymake-error-echo-at-eol | 455 | (defface flymake-error-echo-at-eol |
| 456 | '((t :inherit (flymake-end-of-line-diagnostics-face compilation-error))) | 456 | '((t :inherit (flymake-end-of-line-diagnostics-face compilation-error))) |
| 457 | "Face like `flymake-error-echo', but for end-of-line overlays." | 457 | "Face like `flymake-error-echo', but for end-of-line overlays." |
| 458 | :package-version '("Flymake" . "1.3.5")) | 458 | :package-version '(Flymake . "1.3.5")) |
| 459 | 459 | ||
| 460 | (defface flymake-warning-echo-at-eol | 460 | (defface flymake-warning-echo-at-eol |
| 461 | '((t :inherit (flymake-end-of-line-diagnostics-face compilation-warning))) | 461 | '((t :inherit (flymake-end-of-line-diagnostics-face compilation-warning))) |
| 462 | "Face like `flymake-warning-echo', but for end-of-line overlays." | 462 | "Face like `flymake-warning-echo', but for end-of-line overlays." |
| 463 | :package-version '("Flymake" . "1.3.5")) | 463 | :package-version '(Flymake . "1.3.5")) |
| 464 | 464 | ||
| 465 | (defface flymake-note-echo-at-eol | 465 | (defface flymake-note-echo-at-eol |
| 466 | '((t :inherit (flymake-end-of-line-diagnostics-face flymake-note))) | 466 | '((t :inherit (flymake-end-of-line-diagnostics-face flymake-note))) |
| 467 | "Face like `flymake-note-echo', but for end-of-line overlays." | 467 | "Face like `flymake-note-echo', but for end-of-line overlays." |
| 468 | :package-version '("Flymake" . "1.3.5")) | 468 | :package-version '(Flymake . "1.3.5")) |
| 469 | 469 | ||
| 470 | (defcustom flymake-show-diagnostics-at-end-of-line nil | 470 | (defcustom flymake-show-diagnostics-at-end-of-line nil |
| 471 | "If non-nil, add diagnostic summary messages at end-of-line." | 471 | "If non-nil, add diagnostic summary messages at end-of-line." |
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el index ac6fd382a46..9199119b602 100644 --- a/lisp/progmodes/verilog-mode.el +++ b/lisp/progmodes/verilog-mode.el | |||
| @@ -356,7 +356,9 @@ wherever possible, since it is slow." | |||
| 356 | (eval-and-compile | 356 | (eval-and-compile |
| 357 | ;; Both xemacs and emacs | 357 | ;; Both xemacs and emacs |
| 358 | (condition-case nil | 358 | (condition-case nil |
| 359 | (require 'diff) ; diff-command and diff-switches | 359 | ;; `diff-command' and `diff-switches', |
| 360 | ;; although XEmacs lacks the former. | ||
| 361 | (require 'diff) | ||
| 360 | (error nil)) | 362 | (error nil)) |
| 361 | (condition-case nil | 363 | (condition-case nil |
| 362 | (require 'compile) ; compilation-error-regexp-alist-alist | 364 | (require 'compile) ; compilation-error-regexp-alist-alist |
| @@ -11883,31 +11885,33 @@ If optional REGEXP, ignore differences matching it." | |||
| 11883 | This requires the external program `diff-command' to be in your `exec-path', | 11885 | This requires the external program `diff-command' to be in your `exec-path', |
| 11884 | and uses `diff-switches' in which you may want to have \"-u\" flag. | 11886 | and uses `diff-switches' in which you may want to have \"-u\" flag. |
| 11885 | Ignores WHITESPACE if t, and writes output to stdout if SHOW." | 11887 | Ignores WHITESPACE if t, and writes output to stdout if SHOW." |
| 11886 | ;; Similar to `diff-buffer-with-file' but works on XEmacs, and doesn't | 11888 | ;; Similar to `diff-buffer-with-file' but works on Emacs 21, and |
| 11887 | ;; call `diff' as `diff' has different calling semantics on different | 11889 | ;; doesn't call `diff' as `diff' has different calling semantics on |
| 11888 | ;; versions of Emacs. | 11890 | ;; different versions of Emacs. |
| 11889 | (if (not (file-exists-p f1)) | 11891 | (if (not (file-exists-p f1)) |
| 11890 | (message "Buffer `%s' has no associated file on disk" (buffer-name b2)) | 11892 | (message "Buffer `%s' has no associated file on disk" b2) |
| 11891 | (with-temp-buffer "*Verilog-Diff*" | 11893 | (let ((outbuf (get-buffer "*Verilog-Diff*")) |
| 11892 | (let ((outbuf (current-buffer)) | 11894 | (f2 (make-temp-file "vm-diff-auto-"))) |
| 11893 | (f2 (make-temp-file "vm-diff-auto-"))) | 11895 | (unwind-protect |
| 11894 | (unwind-protect | 11896 | ;; User may want -u in `diff-switches'. |
| 11895 | (progn | 11897 | (let ((args `(,@(if (listp diff-switches) |
| 11896 | (with-current-buffer b2 | 11898 | diff-switches |
| 11897 | (save-restriction | 11899 | (list diff-switches)) |
| 11898 | (widen) | 11900 | ,@(and whitespace '("-b")) |
| 11899 | (write-region (point-min) (point-max) f2 nil 'nomessage))) | 11901 | ,f1 ,f2))) |
| 11900 | (call-process diff-command nil outbuf t | 11902 | (with-current-buffer b2 |
| 11901 | diff-switches ; User may want -u in diff-switches | 11903 | (save-restriction |
| 11902 | (if whitespace "-b" "") | 11904 | (widen) |
| 11903 | f1 f2) | 11905 | (write-region (point-min) (point-max) f2 nil 'nomessage))) |
| 11904 | ;; Print out results. Alternatively we could have call-processed | 11906 | (apply #'call-process diff-command nil outbuf t args) |
| 11905 | ;; ourself, but this way we can reuse diff switches | 11907 | ;; Print out results. Alternatively we could have call-processed |
| 11906 | (when show | 11908 | ;; ourself, but this way we can reuse diff switches. |
| 11907 | (with-current-buffer outbuf (message "%s" (buffer-string)))))) | 11909 | (when show |
| 11908 | (sit-for 0) | 11910 | (with-current-buffer outbuf (message "%s" (buffer-string))))) |
| 11909 | (when (file-exists-p f2) | 11911 | (sit-for 0) |
| 11910 | (delete-file f2)))))) | 11912 | (condition-case nil |
| 11913 | (delete-file f2) | ||
| 11914 | (error nil)))))) | ||
| 11911 | 11915 | ||
| 11912 | (defun verilog-diff-report (b1 b2 diffpt) | 11916 | (defun verilog-diff-report (b1 b2 diffpt) |
| 11913 | "Report differences detected with `verilog-diff-auto'. | 11917 | "Report differences detected with `verilog-diff-auto'. |
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el index 6e0246ea762..c6056c1e5bd 100644 --- a/lisp/vc/vc-cvs.el +++ b/lisp/vc/vc-cvs.el | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | (require 'vc-rcs) | 27 | (require 'vc-rcs) |
| 28 | (eval-when-compile (require 'vc)) | 28 | (eval-when-compile (require 'vc)) |
| 29 | (eval-when-compile (require 'cl-lib)) | ||
| 29 | (require 'log-view) | 30 | (require 'log-view) |
| 30 | 31 | ||
| 31 | (declare-function vc-checkout "vc" (file &optional rev)) | 32 | (declare-function vc-checkout "vc" (file &optional rev)) |
| @@ -813,7 +814,10 @@ individually should stay local." | |||
| 813 | 'yes 'no)))))))))))) | 814 | 'yes 'no)))))))))))) |
| 814 | 815 | ||
| 815 | (defun vc-cvs-repository-hostname (dirname) | 816 | (defun vc-cvs-repository-hostname (dirname) |
| 816 | "Hostname of the CVS server associated to workarea DIRNAME." | 817 | "Hostname of the CVS server associated to workarea DIRNAME. |
| 818 | |||
| 819 | Returns nil if there is not hostname or the hostname could not be | ||
| 820 | determined because the CVS/Root specification is invalid." | ||
| 817 | (let ((rootname (expand-file-name "CVS/Root" dirname))) | 821 | (let ((rootname (expand-file-name "CVS/Root" dirname))) |
| 818 | (when (file-readable-p rootname) | 822 | (when (file-readable-p rootname) |
| 819 | (with-temp-buffer | 823 | (with-temp-buffer |
| @@ -822,73 +826,143 @@ individually should stay local." | |||
| 822 | default-file-name-coding-system))) | 826 | default-file-name-coding-system))) |
| 823 | (vc-insert-file rootname)) | 827 | (vc-insert-file rootname)) |
| 824 | (goto-char (point-min)) | 828 | (goto-char (point-min)) |
| 825 | (nth 2 (vc-cvs-parse-root | 829 | (let ((hostname |
| 826 | (buffer-substring (point) | 830 | (nth 2 (vc-cvs-parse-root |
| 827 | (line-end-position)))))))) | 831 | (buffer-substring (point) |
| 828 | 832 | (line-end-position)))))) | |
| 829 | (defun vc-cvs-parse-uhp (path) | 833 | (unless (string= hostname "") |
| 830 | "Parse user@host/path into (user@host /path)." | 834 | hostname)))))) |
| 831 | (if (string-match "\\([^/]+\\)\\(/.*\\)" path) | 835 | |
| 832 | (list (match-string 1 path) (match-string 2 path)) | 836 | (cl-defun vc-cvs-parse-root (root) |
| 833 | (list nil path))) | 837 | "Split CVS Root specification string into a list of fields. |
| 834 | 838 | ||
| 835 | (defun vc-cvs-parse-root (root) | 839 | A CVS Root specification of the form |
| 836 | "Split CVS ROOT specification string into a list of fields. | 840 | [:METHOD:][[[USER][:PASSWORD]@]HOSTNAME][:[PORT]]/pathname/to/repository |
| 837 | A CVS root specification of the form | ||
| 838 | [:METHOD:][[USER@]HOSTNAME]:?/path/to/repository | ||
| 839 | is converted to a normalized record with the following structure: | 841 | is converted to a normalized record with the following structure: |
| 840 | \(METHOD USER HOSTNAME CVS-ROOT). | 842 | \(METHOD USER HOSTNAME PATHNAME). |
| 843 | |||
| 841 | The default METHOD for a CVS root of the form | 844 | The default METHOD for a CVS root of the form |
| 842 | /path/to/repository | 845 | /pathname/to/repository |
| 843 | is `local'. | 846 | is \"local\". |
| 844 | The default METHOD for a CVS root of the form | 847 | The default METHOD for a CVS root of the form |
| 845 | [USER@]HOSTNAME:/path/to/repository | 848 | [USER@]HOSTNAME:/pathname/to/repository |
| 846 | is `ext'. | 849 | is \"ext\". |
| 847 | For an empty string, nil is returned (invalid CVS root)." | 850 | |
| 848 | ;; Split CVS root into colon separated fields (0-4). | 851 | If METHOD is explicitly \"local\" or \"fork\", then the pathname |
| 849 | ;; The `x:' makes sure, that leading colons are not lost; | 852 | starts immediately after the method block. This must be used on |
| 850 | ;; `HOST:/PATH' is then different from `:METHOD:/PATH'. | 853 | Windows platforms when pathnames start with a drive letter. |
| 851 | (let* ((root-list (cdr (split-string (concat "x:" root) ":"))) | 854 | |
| 852 | (len (length root-list)) | 855 | Note that, except for METHOD, which is defaulted if not present, |
| 853 | ;; All syntactic varieties will get a proper METHOD. | 856 | other optional fields are returned as nil if not syntactically |
| 854 | (root-list | 857 | present, or as the empty string if delimited but empty. |
| 855 | (cond | 858 | |
| 856 | ((= len 0) | 859 | Returns nil in case of an unparsable CVS root (including the |
| 857 | ;; Invalid CVS root | 860 | empty string) and issues a warning. This function doesn't check |
| 858 | nil) | 861 | that an explicit method is valid, or that some fields are empty |
| 859 | ((= len 1) | 862 | or nil but should not for a given method." |
| 860 | (let ((uhp (vc-cvs-parse-uhp (car root-list)))) | 863 | (let (method user password hostname port pathname |
| 861 | (cons (if (car uhp) "ext" "local") uhp))) | 864 | ;; IDX set by `next-delim' as a side-effect |
| 862 | ((= len 2) | 865 | idx) |
| 863 | ;; [USER@]HOST:PATH => method `ext' | 866 | (cl-labels |
| 864 | (and (not (equal (car root-list) "")) | 867 | ((invalid (reason &rest args) |
| 865 | (cons "ext" root-list))) | 868 | (apply #'lwarn '(vc-cvs) :warning |
| 866 | ((= len 3) | 869 | (concat "vc-cvs-parse-root: Can't parse '%s': " reason) |
| 867 | ;; :METHOD:PATH or :METHOD:USER@HOSTNAME/PATH | 870 | root args) |
| 868 | (cons (cadr root-list) | 871 | (cl-return-from vc-cvs-parse-root)) |
| 869 | (vc-cvs-parse-uhp (nth 2 root-list)))) | 872 | (no-pathname () |
| 870 | (t | 873 | (invalid "No pathname")) |
| 871 | ;; :METHOD:[USER@]HOST:PATH | 874 | (next-delim (start) |
| 872 | (cdr root-list))))) | 875 | ;; Search for a :, @ or /. If none is found, there can be |
| 873 | (if root-list | 876 | ;; no path at the end, which is an error. |
| 874 | (let ((method (car root-list)) | 877 | (setq idx (string-match-p "[:@/]" root start)) |
| 875 | (uhost (or (cadr root-list) "")) | 878 | (if idx (aref root idx) (no-pathname))) |
| 876 | (root (nth 2 root-list)) | 879 | (grab-user (start end) |
| 877 | user host) | 880 | (setq user (substring root start end))) |
| 878 | ;; Split USER@HOST | 881 | (at-hostname-block (start) |
| 879 | (if (string-match "\\(.*\\)@\\(.*\\)" uhost) | 882 | (let ((cand (next-delim start))) |
| 880 | (setq user (match-string 1 uhost) | 883 | (cl-ecase cand |
| 881 | host (match-string 2 uhost)) | 884 | (?: |
| 882 | (setq host uhost)) | 885 | ;; Could be : before PORT and PATHNAME, or before |
| 883 | ;; Remove empty HOST | 886 | ;; PASSWORD. We search for a @ to disambiguate. |
| 884 | (and (equal host "") | 887 | (let ((colon-idx idx) |
| 885 | (setq host nil)) | 888 | (cand (next-delim (1+ idx)))) |
| 886 | ;; Fix windows style CVS root `:local:C:\\project\\cvs\\some\\dir' | 889 | (cl-ecase cand |
| 887 | (and host | 890 | (?: |
| 888 | (equal method "local") | 891 | (invalid |
| 889 | (setq root (concat host ":" root) host nil)) | 892 | (eval-when-compile |
| 890 | ;; Normalize CVS root record | 893 | (concat "Hostname block: Superfluous : at %s " |
| 891 | (list method user host root))))) | 894 | "or missing @ before")) |
| 895 | idx)) | ||
| 896 | (?@ | ||
| 897 | ;; USER:PASSWORD case | ||
| 898 | (grab-user start colon-idx) | ||
| 899 | (delimited-password (1+ colon-idx) idx)) | ||
| 900 | (?/ | ||
| 901 | ;; HOSTNAME[:[PORT]] case | ||
| 902 | (grab-hostname start colon-idx) | ||
| 903 | (delimited-port (1+ colon-idx) idx))))) | ||
| 904 | (?@ | ||
| 905 | (grab-user start idx) | ||
| 906 | (at-hostname (1+ idx))) | ||
| 907 | (?/ | ||
| 908 | (if (/= idx start) | ||
| 909 | (grab-hostname start idx)) | ||
| 910 | (at-pathname idx))))) | ||
| 911 | (delimited-password (start end) | ||
| 912 | (setq password (substring root start end)) | ||
| 913 | (at-hostname (1+ end))) | ||
| 914 | (grab-hostname (start end) | ||
| 915 | (setq hostname (substring root start end))) | ||
| 916 | (at-hostname (start) | ||
| 917 | (let ((cand (next-delim start))) | ||
| 918 | (cl-ecase cand | ||
| 919 | (?: | ||
| 920 | (grab-hostname start idx) | ||
| 921 | (at-port (1+ idx))) | ||
| 922 | (?@ | ||
| 923 | (invalid "Hostname: Unexpected @ after index %s" start)) | ||
| 924 | (?/ | ||
| 925 | (grab-hostname start idx) | ||
| 926 | (at-pathname idx))))) | ||
| 927 | (delimited-port (start end) | ||
| 928 | (setq port (substring root start end)) | ||
| 929 | (at-pathname end)) | ||
| 930 | (at-port (start) | ||
| 931 | (let ((end (string-match-p "/" root start))) | ||
| 932 | (if end (delimited-port start end) (no-pathname)))) | ||
| 933 | (at-pathname (start) | ||
| 934 | (setq pathname (substring root start)))) | ||
| 935 | (when (string= root "") | ||
| 936 | (invalid "Empty string")) | ||
| 937 | ;; Check for a starting ":" | ||
| 938 | (if (= (aref root 0) ?:) | ||
| 939 | ;; 3 possible cases: | ||
| 940 | ;; - :METHOD: at start. METHOD doesn't have any @. | ||
| 941 | ;; - :PASSWORD@ at start. Must be followed by HOSTNAME. | ||
| 942 | ;; - :[PORT] at start. Must be followed immediately by a "/". | ||
| 943 | ;; So, find the next character equal to ":", "@" or "/". | ||
| 944 | (let ((cand (next-delim 1))) | ||
| 945 | (cl-ecase cand | ||
| 946 | (?: | ||
| 947 | ;; :METHOD: case | ||
| 948 | (setq method (substring root 1 idx)) | ||
| 949 | ;; Continue | ||
| 950 | (if (member method '("local" "fork")) | ||
| 951 | (at-pathname (1+ idx)) | ||
| 952 | (at-hostname-block (1+ idx)))) | ||
| 953 | (?@ | ||
| 954 | ;; :PASSWORD@HOSTNAME case | ||
| 955 | (delimited-password 1 idx)) | ||
| 956 | (?/ | ||
| 957 | ;; :[PORT] case. | ||
| 958 | (at-port 1 idx)))) | ||
| 959 | ;; No starting ":", there can't be any METHOD. | ||
| 960 | (at-hostname-block 0))) | ||
| 961 | (unless method | ||
| 962 | ;; Default the method if not specified | ||
| 963 | (setq method | ||
| 964 | (if (or user password hostname port) "ext" "local"))) | ||
| 965 | (list method user hostname pathname))) | ||
| 892 | 966 | ||
| 893 | ;; XXX: This does not work correctly for subdirectories. "cvs status" | 967 | ;; XXX: This does not work correctly for subdirectories. "cvs status" |
| 894 | ;; information is context sensitive, it contains lines like: | 968 | ;; information is context sensitive, it contains lines like: |
| @@ -955,13 +1029,16 @@ state." | |||
| 955 | (cdr (assoc (char-after) translation))) | 1029 | (cdr (assoc (char-after) translation))) |
| 956 | result) | 1030 | result) |
| 957 | (cond | 1031 | (cond |
| 958 | ((looking-at "cvs update: warning: \\(.*\\) was lost") | 1032 | ((looking-at "cvs update: warning: .* was lost") |
| 959 | ;; Format is: | 1033 | ;; Format is: |
| 960 | ;; cvs update: warning: FILENAME was lost | 1034 | ;; cvs update: warning: FILENAME was lost |
| 961 | ;; U FILENAME | 1035 | ;; U FILENAME |
| 962 | (push (list (match-string 1) 'missing) result) | 1036 | ;; with FILENAME in the first line possibly enclosed in |
| 963 | ;; Skip the "U" line | 1037 | ;; quotes (since CVS 1.12.3). To avoid problems, use the U |
| 964 | (forward-line 1)) | 1038 | ;; line where name is never quoted. |
| 1039 | (forward-line 1) | ||
| 1040 | (when (looking-at "^U \\(.*\\)$") | ||
| 1041 | (push (list (match-string 1) 'missing) result))) | ||
| 965 | ((looking-at "cvs update: New directory `\\(.*\\)' -- ignored") | 1042 | ((looking-at "cvs update: New directory `\\(.*\\)' -- ignored") |
| 966 | (push (list (match-string 1) 'unregistered) result)))) | 1043 | (push (list (match-string 1) 'unregistered) result)))) |
| 967 | (forward-line 1)) | 1044 | (forward-line 1)) |
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 32b0d5d7556..91d3f6f70d3 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el | |||
| @@ -3604,7 +3604,8 @@ to provide the `find-revision' operation instead." | |||
| 3604 | (file-buffer (or (get-file-buffer file) (current-buffer)))) | 3604 | (file-buffer (or (get-file-buffer file) (current-buffer)))) |
| 3605 | (message "Checking out %s..." file) | 3605 | (message "Checking out %s..." file) |
| 3606 | (let ((failed t) | 3606 | (let ((failed t) |
| 3607 | (backup-name (car (find-backup-file-name file)))) | 3607 | (backup-name (when (file-exists-p file) |
| 3608 | (car (find-backup-file-name file))))) | ||
| 3608 | (when backup-name | 3609 | (when backup-name |
| 3609 | (copy-file file backup-name 'ok-if-already-exists 'keep-date) | 3610 | (copy-file file backup-name 'ok-if-already-exists 'keep-date) |
| 3610 | (unless (file-writable-p file) | 3611 | (unless (file-writable-p file) |
diff --git a/test/lisp/vc/vc-cvs-tests.el b/test/lisp/vc/vc-cvs-tests.el new file mode 100644 index 00000000000..99ac9c8eb96 --- /dev/null +++ b/test/lisp/vc/vc-cvs-tests.el | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | ;;; vc-cvs-tests.el --- tests for vc/vc-cvs.el -*- lexical-binding:t -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Olivier Certner <olce.emacs@certner.fr> | ||
| 6 | ;; Maintainer: emacs-devel@gnu.org | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 13 | ;; (at your option) any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;;; Code: | ||
| 26 | |||
| 27 | (require 'vc-cvs) | ||
| 28 | |||
| 29 | (ert-deftest vc-cvs-test-parse-root--local-no-method () | ||
| 30 | (vc-cvs-test--check-parse-root | ||
| 31 | "/home/joe/repo" | ||
| 32 | '("local" nil nil "/home/joe/repo"))) | ||
| 33 | |||
| 34 | (ert-deftest vc-cvs-test-parse-root--local-windows-drive-letter () | ||
| 35 | (vc-cvs-test--check-parse-root | ||
| 36 | ":local:c:/users/joe/repo" | ||
| 37 | '("local" nil nil "c:/users/joe/repo"))) | ||
| 38 | |||
| 39 | (ert-deftest vc-cvs-test-parse-root--ext-no-method-host-no-port-colon () | ||
| 40 | (vc-cvs-test--check-parse-root | ||
| 41 | "host/home/serv/repo" | ||
| 42 | '("ext" nil "host" "/home/serv/repo"))) | ||
| 43 | |||
| 44 | (ert-deftest vc-cvs-test-parse-root--pserver-host-no-port-colon () | ||
| 45 | (vc-cvs-test--check-parse-root | ||
| 46 | ":pserver:host/home/serv/repo" | ||
| 47 | '("pserver" nil "host" "/home/serv/repo"))) | ||
| 48 | |||
| 49 | (ert-deftest vc-cvs-test-parse-root--pserver-host-port-colon () | ||
| 50 | (vc-cvs-test--check-parse-root | ||
| 51 | ":pserver:host:/home/serv/repo" | ||
| 52 | '("pserver" nil "host" "/home/serv/repo"))) | ||
| 53 | |||
| 54 | (ert-deftest vc-cvs-test-parse-root--ext-no-method-user-host-no-port-colon () | ||
| 55 | (vc-cvs-test--check-parse-root | ||
| 56 | "usr@host/home/serv/repo" | ||
| 57 | '("ext" "usr" "host" "/home/serv/repo"))) | ||
| 58 | |||
| 59 | (ert-deftest vc-cvs-test-parse-root--ext-no-method-user-host-port-colon () | ||
| 60 | (vc-cvs-test--check-parse-root | ||
| 61 | "usr@host:/home/serv/repo" | ||
| 62 | '("ext" "usr" "host" "/home/serv/repo"))) | ||
| 63 | |||
| 64 | (ert-deftest vc-cvs-test-parse-root--pserver-user-password-host-no-port-colon () | ||
| 65 | (vc-cvs-test--check-parse-root | ||
| 66 | ":pserver:usr:passwd@host/home/serv/repo" | ||
| 67 | '("pserver" "usr" "host" "/home/serv/repo"))) | ||
| 68 | |||
| 69 | (ert-deftest vc-cvs-test-parse-root--pserver-user-password-host-port-colon () | ||
| 70 | (vc-cvs-test--check-parse-root | ||
| 71 | ":pserver:usr:passwd@host:/home/serv/repo" | ||
| 72 | '("pserver" "usr" "host" "/home/serv/repo"))) | ||
| 73 | |||
| 74 | (ert-deftest vc-cvs-test-parse-root--pserver-user-password-host-port () | ||
| 75 | (vc-cvs-test--check-parse-root | ||
| 76 | ":pserver:usr:passwd@host:28/home/serv/repo" | ||
| 77 | '("pserver" "usr" "host" "/home/serv/repo"))) | ||
| 78 | |||
| 79 | ;; Next 3 tests are just to err on the side of caution. It doesn't | ||
| 80 | ;; seem that CVS 1.12 can ever produce such lines. | ||
| 81 | |||
| 82 | (ert-deftest | ||
| 83 | vc-cvs-test-parse-root--ext-no-method-user-password-host-no-port-colon | ||
| 84 | () | ||
| 85 | (vc-cvs-test--check-parse-root | ||
| 86 | "usr:passwd@host/home/serv/repo" | ||
| 87 | '("ext" "usr" "host" "/home/serv/repo"))) | ||
| 88 | |||
| 89 | (ert-deftest | ||
| 90 | vc-cvs-test-parse-root--ext-no-method-user-password-host-port-colon | ||
| 91 | () | ||
| 92 | (vc-cvs-test--check-parse-root | ||
| 93 | "usr:passwd@host:/home/serv/repo" | ||
| 94 | '("ext" "usr" "host" "/home/serv/repo"))) | ||
| 95 | |||
| 96 | (ert-deftest | ||
| 97 | vc-cvs-test-parse-root--ext-no-method-user-password-host-port | ||
| 98 | () | ||
| 99 | (vc-cvs-test--check-parse-root | ||
| 100 | "usr:passwd@host:28/home/serv/repo" | ||
| 101 | '("ext" "usr" "host" "/home/serv/repo"))) | ||
| 102 | |||
| 103 | |||
| 104 | (defun vc-cvs-test--check-parse-root (input expected-output) | ||
| 105 | (should (equal (vc-cvs-parse-root input) expected-output))) | ||
| 106 | |||
| 107 | ;;; vc-cvs-tests.el ends here | ||