Function: vc-diff-internal

vc-diff-internal is an autoloaded and byte-compiled function defined in vc.el.gz.

Signature

(vc-diff-internal ASYNC VC-FILESET REV1 REV2 &optional VERBOSE BUFFER)

Documentation

Report diffs between two revisions of a fileset.

Output goes to the buffer BUFFER, which defaults to *vc-diff*. BUFFER, if non-nil, should be a buffer or a buffer name. Return t if the buffer had changes, nil otherwise.

Source Code

;; Defined in /usr/src/emacs/lisp/vc/vc.el.gz
(defun vc-diff-internal (async vc-fileset rev1 rev2 &optional verbose buffer)
  "Report diffs between two revisions of a fileset.
Output goes to the buffer BUFFER, which defaults to *vc-diff*.
BUFFER, if non-nil, should be a buffer or a buffer name.
Return t if the buffer had changes, nil otherwise."
  (unless buffer
    (setq buffer "*vc-diff*"))
  (let* ((files (cadr vc-fileset))
	 (messages (cons (format "Finding changes in %s..."
                                 (vc-delistify files))
                         (format "No changes between %s and %s"
                                 (or rev1 "working revision")
                                 (or rev2 "workfile"))))
	 ;; Set coding system based on the first file.  It's a kluge,
	 ;; but the only way to set it for each file included would
	 ;; be to call the back end separately for each file.
	 (coding-system-for-read
	  (if files (vc-coding-system-for-diff (car files)) 'undecided)))
    ;; On MS-Windows and MS-DOS, Diff is likely to produce DOS-style
    ;; EOLs, which will look ugly if (car files) happens to have Unix
    ;; EOLs.
    (if (memq system-type '(windows-nt ms-dos))
	(setq coding-system-for-read
	      (coding-system-change-eol-conversion coding-system-for-read
						   'dos)))
    (vc-setup-buffer buffer)
    (message "%s" (car messages))
    ;; Many backends don't handle well the case of a file that has been
    ;; added but not yet committed to the repo (notably CVS and Subversion).
    ;; Do that work here so the backends don't have to futz with it.  --ESR
    ;;
    ;; Actually most backends (including CVS) have options to control the
    ;; behavior since which one is better depends on the user and on the
    ;; situation).  Worse yet: this code does not handle the case where
    ;; `file' is a directory which contains added files.
    ;; I made it conditional on vc-diff-added-files but it should probably
    ;; just be removed (or copied/moved to specific backends).  --Stef.
    (when vc-diff-added-files
      (let ((filtered '())
	    process-file-side-effects)
        (dolist (file files)
          (if (or (file-directory-p file)
                  (not (string= (vc-working-revision file) "0")))
              (push file filtered)
            ;; This file is added but not yet committed;
            ;; there is no repository version to diff against.
            (if (or rev1 rev2)
                (error "No revisions of %s exist" file)
              ;; We regard this as "changed".
              ;; Diff it against /dev/null.
              (apply #'vc-do-command buffer
                     (if async 'async 1) "diff" file
                     (append (vc-switches nil 'diff) `(,(null-device)))))))
        (setq files (nreverse filtered))))
    (vc-call-backend (car vc-fileset) 'diff files rev1 rev2 buffer async)
    (set-buffer buffer)
    (diff-mode)
    (setq-local diff-vc-backend (car vc-fileset))
    (setq-local diff-vc-revisions (list rev1 rev2))
    (setq-local revert-buffer-function
                (lambda (_ignore-auto _noconfirm)
                  (vc-diff-internal async vc-fileset rev1 rev2 verbose)))
    ;; Make the *vc-diff* buffer read only, the diff-mode key
    ;; bindings are nicer for read only buffers. pcl-cvs does the
    ;; same thing.
    (setq buffer-read-only t)
    (if (and (zerop (buffer-size))
             (not (get-buffer-process (current-buffer))))
        ;; Treat this case specially so as not to pop the buffer.
        (progn
          (message "%s" (cdr messages))
          nil)
      ;; Display the buffer, but at the end because it can change point.
      (pop-to-buffer (current-buffer))
      ;; The diff process may finish early, so call `vc-diff-finish'
      ;; after `pop-to-buffer'; the former assumes the diff buffer is
      ;; shown in some window.
      (let ((buf (current-buffer)))
        (vc-run-delayed (vc-diff-finish buf (when verbose messages))))
      ;; In the async case, we return t even if there are no differences
      ;; because we don't know that yet.
      t)))