Various modifications to vc-p4 that I have been using for years.

Unfortunately I did not document the changes as I made them. I have been able to determine the purpose of most of the changes by code inspection but there are a few changes for which I have not been able to determine a purpose.

* Modifications to support XEmacs.

* Added the p4-lowlevel-locate-p4 function. This function is used to locate the p4 executable on the exec-path. It is used by the vc-p4-registered function to avoid an error on systems on which the Perforce client is not installed. This is useful if the same .emacs file is used on multiple systems, some of which do not have the Perforce client installed.

* Modified the p4-lowlevel-successful-alist-p function so that a command that returns the message "file(s) up-to-date" does not trigger an error. As part of this change I added the p4-lowlevel-ignore-error-list defcustom and the p4-lowlevel-should-ignore-error function.

* Modified the vc-p4-registered function so that it uses the p4-lowlevel-locate-p4 function to verify that the Perforce client is installed.

[git-p4: depot-paths = "//guest/Ben_Key/vc-p4/,//guest/jonathan_kamens/vc-p4/,//guest/magnus_henoch/vc-p4/": change = 12013]
This commit is contained in:
Ben_Key 2015-03-10 14:43:47 -08:00
parent ff996708d6
commit 3cb296d970
2 changed files with 67 additions and 25 deletions

View file

@ -58,6 +58,21 @@ If vc-command-messages is bound and non-nil, it does the same thing."
:type 'boolean :type 'boolean
:group 'p4-lowlevel) :group 'p4-lowlevel)
(defcustom p4-lowlevel-ignore-error-list '("file(s) up-to-date")
"*A list of Perforce errors to ignore. Note that each item in the list can be
a portion of the error string you wish to ignore."
:type '(repeat (string :tag "Error to Ignore"))
:group 'p4-lowlevel)
(defun p4-lowlevel-locate-p4 ()
"Attempts to locate the p4 command. Used by `vc-p4-registered' to
avoid an error on systems on which the Perforce client is not installed."
(if (and (boundp 'exec-suffixes) (fboundp 'file-executable-p))
(locate-file p4-lowlevel-p4-program exec-path exec-suffixes 'file-executable-p) ; GNU Emacs
(locate-file p4-lowlevel-p4-program exec-path '("" ".btm" ".bat" ".cmd" ".exe" ".com") 'executable) ; XEmacs
)
)
(defun p4-lowlevel-command-to-buffer (args &optional input output) (defun p4-lowlevel-command-to-buffer (args &optional input output)
"Call `p4-lowlevel-p4-command' with specified list of ARGS. "Call `p4-lowlevel-p4-command' with specified list of ARGS.
ARGS can be a list or a single string argument. Do not specify the ARGS can be a list or a single string argument. Do not specify the
@ -189,6 +204,25 @@ the return value of `p4-lowlevel-command-to-buffer' on failure."
(setq matching-alist (cons element matching-alist)))) (setq matching-alist (cons element matching-alist))))
(nreverse matching-alist))) (nreverse matching-alist)))
(defun p4-lowlevel-should-ignore-error (error-string)
"Determines whether the error specified by ERROR-STRING should be ignored."
(if (stringp error-string)
(let (should-ignore)
(dolist (item p4-lowlevel-ignore-error-list should-ignore)
(if (string-match item error-string)
(progn
(setq should-ignore t)
(if p4-lowlevel-command-messages
(message "Ignoring error: %s" error-string)
)
)
)
)
)
nil
)
)
(defun p4-lowlevel-successful-alist-p (output) (defun p4-lowlevel-successful-alist-p (output)
"Determines if OUTPUT, a buffer or alist, is from a successful p4 command. "Determines if OUTPUT, a buffer or alist, is from a successful p4 command.
Does this by confirming that OUTPUT is a buffer or alist, that there Does this by confirming that OUTPUT is a buffer or alist, that there
@ -202,8 +236,11 @@ value of 0."
(if (not (or (not element) (equal (cdr element) "0"))) (if (not (or (not element) (equal (cdr element) "0")))
nil nil
(if (p4-lowlevel-re-assoc "^error" output) (if (p4-lowlevel-re-assoc "^error" output)
nil (let ((err (assoc "error" output)))
t))))) (if (and (not (null err)) (p4-lowlevel-should-ignore-error (cdr err)))
t
nil))
t)))))
(defun p4-lowlevel-items-matching-tag (tag output) (defun p4-lowlevel-items-matching-tag (tag output)
"Returns a list of the items maching TAG in p4 OUTPUT, or nil if none. "Returns a list of the items maching TAG in p4 OUTPUT, or nil if none.
@ -320,13 +357,15 @@ commands."
; revision number (#rev) or a change number (@change). We assume ; revision number (#rev) or a change number (@change). We assume
; that a bare number is a revision number. ; that a bare number is a revision number.
(if rev (if rev
(if (string= rev "") (if (eq rev t)
nil nil
(if (string-match "\\`[0-9]+\\'" rev) (if (string= rev "")
(concat "#" rev) nil
(if (not (string-match "^[#@]" rev)) (if (string-match "\\`[0-9]+\\'" rev)
(concat "@" rev) (concat "#" rev)
rev))))) (if (not (string-match "^[#@]" rev))
(concat "@" rev)
rev))))))
; Here's what we need to support from the "p4 add" command, at least ; Here's what we need to support from the "p4 add" command, at least
; for the time being: ; for the time being:

View file

@ -59,7 +59,9 @@
;;; Code: ;;; Code:
(eval-when-compile (eval-and-compile
(if (not (string-match "XEmacs" emacs-version))
(require 'vc-annotate))
(require 'vc-hooks) (require 'vc-hooks)
(require 'vc) (require 'vc)
(require 'ediff)) (require 'ediff))
@ -103,19 +105,20 @@ specify a starting date when you run C-u C-x v g."
(defun vc-p4-registered (file) (defun vc-p4-registered (file)
"Return non-nil is FILE is handled by Perforce." "Return non-nil is FILE is handled by Perforce."
(if (and vc-p4-require-p4config (if (p4-lowlevel-locate-p4)
(getenv "P4CONFIG") (if (and vc-p4-require-p4config
(not (vc-p4-find-p4config (file-name-directory file)))) (getenv "P4CONFIG")
nil (not (vc-p4-find-p4config (file-name-directory file))))
(let* ((fstat (p4-lowlevel-fstat file nil t)) nil
(action (cdr (or (assoc "action" fstat) (let* ((fstat (p4-lowlevel-fstat file nil t))
(assoc "headAction" fstat))))) (action (cdr (or (assoc "action" fstat)
(if (or (not fstat) (assoc "headAction" fstat)))))
(string= action "delete")) (if (or (not fstat)
nil (string= action "delete"))
; This sets a bunch of VC properties nil
(vc-p4-state file fstat) ; This sets a bunch of VC properties
t)))) (vc-p4-state file fstat)
t)))))
(defun vc-p4-state (file &optional fstat-list force dont-compare-nonopened) (defun vc-p4-state (file &optional fstat-list force dont-compare-nonopened)
"Returns the current version control state of FILE in Perforce. "Returns the current version control state of FILE in Perforce.
@ -344,7 +347,7 @@ comment COMMENT."
((null action) ((null action)
;; If Perforce doesn't believe that we edited the file, we have ;; If Perforce doesn't believe that we edited the file, we have
;; to use sync instead of revert. ;; to use sync instead of revert.
(p4-lowlevel-sync file (vc-working-revision file) t)) (p4-lowlevel-sync file (vc-workfile-version file) t))
(t (t
(p4-lowlevel-revert file))) (p4-lowlevel-revert file)))
(if (string= action "add") (if (string= action "add")
@ -854,7 +857,7 @@ Optional arg VERSION is a version to annotate from."
"Returns the time of the next Perforce annotation at or after point, "Returns the time of the next Perforce annotation at or after point,
as a floating point fractional number of days. as a floating point fractional number of days.
Moves the point to the end of the annotation." Moves the point to the end of the annotation."
(when (looking-at vc-p4-annotate-re) (when (and (looking-at vc-p4-annotate-re) (fboundp 'vc-annotate-convert-time))
(goto-char (match-end 0)) (goto-char (match-end 0))
(let ((timestr (match-string-no-properties 1))) (let ((timestr (match-string-no-properties 1)))
(string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" timestr) (string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" timestr)