* vc-p4.el (vc-p4-diff): Support lists of files. Perform only a

single request to the server in the simplest case (diff edited
file to synced version).

* p4-lowlevel.el (p4-lowlevel-command-into-buffer): Don't reorder
info and text lines.
(p4-lowlevel-diff): Support lists of files as well as a single file.

[git-p4: depot-paths = "//guest/Ben_Key/vc-p4/,//guest/jonathan_kamens/vc-p4/,//guest/magnus_henoch/vc-p4/": change = 7484]
This commit is contained in:
Magnus Henoch 2009-11-16 12:56:58 -08:00
parent 5305e9d39e
commit 4667f79c0a
2 changed files with 74 additions and 43 deletions

View file

@ -303,9 +303,7 @@ buffer, then puts output in that buffer. Returns the buffer."
(save-excursion
(set-buffer output-buffer)
(erase-buffer)
(insert (p4-lowlevel-info-lines output-alist))
(if (setq text (p4-lowlevel-text output-alist))
(insert text))
(insert (p4-lowlevel-lines-matching-tag "^\\(text\\|info\\)" output-alist))
output-buffer)))
(defun p4-lowlevel-command-messages ()
@ -417,19 +415,27 @@ value with `-m'; if S-VAL is non-nil, pass that value with `-s'."
; DO need to support diffing a single file.
; Do NOT need to support diffing multiple files.
(defun p4-lowlevel-diff (file &optional rev buffer)
(defun p4-lowlevel-diff (files &optional rev buffer)
"Run `p4 diff' on FILE at revision REV and return a buffer
containing the results. REV is in the syntax described by `p4 help
revisions'. If REV is nil, compare the client's sync'd revision to
the file on disk. Uses `p4-lowlevel-diff-switches' to determine flags
to pass to `p4 diff'. If optional BUFFER is non-nil, put output in
that buffer."
(unless (listp files)
(setq files (list files)))
(setq rev (p4-lowlevel-canonicalize-revision rev))
(when (file-directory-p file)
(setq file (concat (directory-file-name file) "/...")))
(let* ((file-spec (if rev (concat file rev) file))
(setq files
(mapcar (lambda (file)
(if (file-directory-p file)
(concat (directory-file-name file) "/...")
file))
files))
(let* ((file-specs (if rev
(mapcar (lambda (file) (concat file rev)) files)
files))
(diff-args (append (list "diff") p4-lowlevel-diff-switches
(list "-f" "-t" file-spec)))
(list "-f" "-t") file-specs))
(buffer (p4-lowlevel-command-into-buffer diff-args
(or buffer "diff"))))
buffer))

View file

@ -492,43 +492,68 @@ files under the default directory otherwise."
("^date: \\(.+\\)" (1 'change-log-date))
("^summary:[ \t]+\\(.+\\)" (1 'log-view-message))))))
(defun vc-p4-diff (files &optional rev1 rev2 buff)
(defun vc-p4-diff (file-or-files &optional rev1 rev2 buff)
"Do a Perforce diff."
(let* ((buffer (or (bufferp buff) (get-buffer-create "*vc-diff*")))
;; In emacs-23 vc-diff has a list of files as a parameter,
;; before it used to be just a single file. We don't support
;; that interface yet, so just use the first file in the list.
(file (if (listp files) (car files) files))
(workfile-version (vc-file-getprop file 'vc-workfile-version))
(inhibit-read-only t))
(if (not rev1)
(if (not rev2)
(if (string= (vc-file-getprop file 'vc-p4-action)
"add")
; I can't figure out anything better to do here than
; to use diff-switches. It would be so much easier if
; "p4 diff" and "p4 diff2" accepted real diff
; arguments instead of arguments with "-d" in front of
; them.
(progn
(set-buffer buffer)
(erase-buffer)
(apply 'call-process
(append
(list diff-command
nil
buffer
nil)
(if (listp diff-switches)
diff-switches
(list diff-switches))
(list "/dev/null"
file))))
(p4-lowlevel-diff file nil buffer))
(p4-lowlevel-diff2 file file workfile-version rev2 buffer))
(if rev2
(p4-lowlevel-diff2 file file rev1 rev2 buffer)
(p4-lowlevel-diff file rev1 buffer)))))
(files (if (atom file-or-files) (list file-or-files) file-or-files))
(inhibit-read-only t))
(cond
((and (null rev1) (null rev2))
(let (added modified)
(dolist (file files)
(if (string= (vc-file-getprop file 'vc-p4-action) "add")
(push file added)
(push file modified)))
(setq added (nreverse added)
modified (nreverse modified))
;; For added files, Perforce can't give us what we want
;; (diff the new file against /dev/null), so we do it
;; ourselves.
(with-current-buffer buffer
(erase-buffer)
(dolist (file added)
(apply 'call-process
(append
(list diff-command
nil
buffer
nil)
(if (listp diff-switches)
diff-switches
(list diff-switches))
(list "/dev/null"
file))))
;; Now diff all the modified files in a single call to the server.
(when modified
(let (temp-buffer)
(unwind-protect
(progn
(setq temp-buffer (p4-lowlevel-diff modified))
(insert-buffer-substring temp-buffer))
(when (buffer-live-p temp-buffer)
(kill-buffer temp-buffer))))))))
(t
;; At this point things get complicated. Let's just make one
;; request per file and hope the server administrator doesn't
;; mind.
(with-current-buffer buffer
(let (temp-buffer)
(dolist (file files)
(setq temp-buffer
(cond
((and (not rev1) rev2)
(p4-lowlevel-diff2 file file
(vc-file-getprop file 'vc-workfile-version)
rev2))
((and rev1 rev2)
(p4-lowlevel-diff2 file file rev1 rev2))
((and rev1 (not rev2))
(p4-lowlevel-diff file rev1))))
(insert-buffer-substring temp-buffer)
(kill-buffer temp-buffer))))))))
(defun vc-p4-annotate-command (file buffer &optional version)
"Annotate FILE into BUFFER file using `vc-p4-annotate-command'.