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
: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)
"Call `p4-lowlevel-p4-command' with specified list of ARGS.
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))))
(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)
"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
@ -202,8 +236,11 @@ value of 0."
(if (not (or (not element) (equal (cdr element) "0")))
nil
(if (p4-lowlevel-re-assoc "^error" output)
nil
t)))))
(let ((err (assoc "error" output)))
(if (and (not (null err)) (p4-lowlevel-should-ignore-error (cdr err)))
t
nil))
t)))))
(defun p4-lowlevel-items-matching-tag (tag output)
"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
; that a bare number is a revision number.
(if rev
(if (string= rev "")
nil
(if (string-match "\\`[0-9]+\\'" rev)
(concat "#" rev)
(if (not (string-match "^[#@]" rev))
(concat "@" rev)
rev)))))
(if (eq rev t)
nil
(if (string= rev "")
nil
(if (string-match "\\`[0-9]+\\'" rev)
(concat "#" rev)
(if (not (string-match "^[#@]" rev))
(concat "@" rev)
rev))))))
; Here's what we need to support from the "p4 add" command, at least
; for the time being:

View file

@ -59,7 +59,9 @@
;;; Code:
(eval-when-compile
(eval-and-compile
(if (not (string-match "XEmacs" emacs-version))
(require 'vc-annotate))
(require 'vc-hooks)
(require 'vc)
(require 'ediff))
@ -103,19 +105,20 @@ specify a starting date when you run C-u C-x v g."
(defun vc-p4-registered (file)
"Return non-nil is FILE is handled by Perforce."
(if (and vc-p4-require-p4config
(getenv "P4CONFIG")
(not (vc-p4-find-p4config (file-name-directory file))))
nil
(let* ((fstat (p4-lowlevel-fstat file nil t))
(action (cdr (or (assoc "action" fstat)
(assoc "headAction" fstat)))))
(if (or (not fstat)
(string= action "delete"))
nil
; This sets a bunch of VC properties
(vc-p4-state file fstat)
t))))
(if (p4-lowlevel-locate-p4)
(if (and vc-p4-require-p4config
(getenv "P4CONFIG")
(not (vc-p4-find-p4config (file-name-directory file))))
nil
(let* ((fstat (p4-lowlevel-fstat file nil t))
(action (cdr (or (assoc "action" fstat)
(assoc "headAction" fstat)))))
(if (or (not fstat)
(string= action "delete"))
nil
; This sets a bunch of VC properties
(vc-p4-state file fstat)
t)))))
(defun vc-p4-state (file &optional fstat-list force dont-compare-nonopened)
"Returns the current version control state of FILE in Perforce.
@ -344,7 +347,7 @@ comment COMMENT."
((null action)
;; If Perforce doesn't believe that we edited the file, we have
;; 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
(p4-lowlevel-revert file)))
(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,
as a floating point fractional number of days.
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))
(let ((timestr (match-string-no-properties 1)))
(string-match "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]+\\)" timestr)