comparison lisp/vc.el @ 40124:9031427edfa3

(vc-diff-internal, vc-coding-system-for-diff, vc-default-diff-tree): New functions. (vc-version-diff): Use them. As a result, coding systems are now set up properly for all sorts of diffs, and tree diffs can now also be done locally. (vc-diff): With a prefix argument, don't require that it's called from a buffer under version control.
author André Spiegel <spiegel@gnu.org>
date Sun, 21 Oct 2001 12:15:22 +0000
parents 900ad37906a7
children 2e0eb9ecea2c
comparison
equal deleted inserted replaced
40123:e528f2adeed4 40124:9031427edfa3
4 4
5 ;; Author: FSF (see below for full credits) 5 ;; Author: FSF (see below for full credits)
6 ;; Maintainer: Andre Spiegel <spiegel@gnu.org> 6 ;; Maintainer: Andre Spiegel <spiegel@gnu.org>
7 ;; Keywords: tools 7 ;; Keywords: tools
8 8
9 ;; $Id: vc.el,v 1.310 2001/09/22 20:04:21 monnier Exp $ 9 ;; $Id: vc.el,v 1.311 2001/09/24 22:29:15 monnier Exp $
10 10
11 ;; This file is part of GNU Emacs. 11 ;; This file is part of GNU Emacs.
12 12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify 13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by 14 ;; it under the terms of the GNU General Public License as published by
286 ;; use the current workfile version (as found in the repository) as the 286 ;; use the current workfile version (as found in the repository) as the
287 ;; older version; if REV2 is nil, use the current workfile contents as 287 ;; older version; if REV2 is nil, use the current workfile contents as
288 ;; the newer version. This function should return a status of either 0 288 ;; the newer version. This function should return a status of either 0
289 ;; (no differences found), or 1 (either non-empty diff or the diff is 289 ;; (no differences found), or 1 (either non-empty diff or the diff is
290 ;; run asynchronously). 290 ;; run asynchronously).
291 ;;
292 ;; - diff-tree (dir &optional rev1 rev2)
293 ;;
294 ;; Insert the diff for all files at and below DIR into the *vc-diff*
295 ;; buffer. The meaning of REV1 and REV2 is the same as for
296 ;; vc-BACKEND-diff. The default implementation does an explicit tree
297 ;; walk, calling vc-BACKEND-diff for each individual file.
291 ;; 298 ;;
292 ;; - annotate-command (file buf rev) 299 ;; - annotate-command (file buf rev)
293 ;; 300 ;;
294 ;; If this function is provided, it should produce an annotated version 301 ;; If this function is provided, it should produce an annotated version
295 ;; of FILE in BUF, relative to version REV. This is currently only 302 ;; of FILE in BUF, relative to version REV. This is currently only
1682 Normally this compares the current file and buffer with the most recent 1689 Normally this compares the current file and buffer with the most recent
1683 checked in version of that file. This uses no arguments. 1690 checked in version of that file. This uses no arguments.
1684 With a prefix argument, it reads the file name to use 1691 With a prefix argument, it reads the file name to use
1685 and two version designators specifying which versions to compare." 1692 and two version designators specifying which versions to compare."
1686 (interactive (list current-prefix-arg t)) 1693 (interactive (list current-prefix-arg t))
1687 (vc-ensure-vc-buffer)
1688 (if historic 1694 (if historic
1689 (call-interactively 'vc-version-diff) 1695 (call-interactively 'vc-version-diff)
1696 (vc-ensure-vc-buffer)
1690 (let ((file buffer-file-name)) 1697 (let ((file buffer-file-name))
1691 (vc-buffer-sync not-urgent) 1698 (vc-buffer-sync not-urgent)
1692 (if (vc-workfile-unchanged-p buffer-file-name) 1699 (if (vc-workfile-unchanged-p buffer-file-name)
1693 (message "No changes to %s since latest version" file) 1700 (message "No changes to %s since latest version" file)
1694 (vc-version-diff file nil nil))))) 1701 (vc-version-diff file nil nil)))))
1739 (insert "Diffs between " 1746 (insert "Diffs between "
1740 (or rel1 "last version checked in") 1747 (or rel1 "last version checked in")
1741 " and " 1748 " and "
1742 (or rel2 "current workfile(s)") 1749 (or rel2 "current workfile(s)")
1743 ":\n\n")) 1750 ":\n\n"))
1744 (setq default-directory (file-name-as-directory file)) 1751 (let ((dir (file-name-as-directory file)))
1745 ;; FIXME: this should do a single exec in CVS. 1752 (vc-call-backend (vc-responsible-backend dir)
1746 (vc-file-tree-walk 1753 'diff-tree dir rel1 rel2))
1747 default-directory
1748 (lambda (f)
1749 (vc-exec-after
1750 `(progn
1751 (message "Looking at %s" ',f)
1752 (vc-call-backend ',(vc-backend file) 'diff ',f ',rel1 ',rel2)))))
1753 (vc-exec-after `(let ((inhibit-read-only t)) 1754 (vc-exec-after `(let ((inhibit-read-only t))
1754 (insert "\nEnd of diffs.\n")))) 1755 (insert "\nEnd of diffs.\n"))))
1755 ;; single file diff 1756 ;; single file diff
1756 (if (or (not rel1) (string-equal rel1 "")) 1757 (vc-diff-internal file rel1 rel2))
1757 (setq rel1 (vc-workfile-version file)))
1758 (if (string-equal rel2 "")
1759 (setq rel2 nil))
1760 (let ((file-rel1 (vc-version-backup-file file rel1))
1761 (file-rel2 (if (not rel2)
1762 file
1763 (vc-version-backup-file file rel2))))
1764 (if (and file-rel1 file-rel2)
1765 (apply 'vc-do-command "*vc-diff*" 1 "diff" nil
1766 (append (if (listp diff-switches)
1767 diff-switches
1768 (list diff-switches))
1769 (if (listp vc-diff-switches)
1770 vc-diff-switches
1771 (list vc-diff-switches))
1772 (list (file-relative-name file-rel1)
1773 (file-relative-name file-rel2))))
1774 (vc-call diff file rel1 rel2))))
1775 (set-buffer "*vc-diff*") 1758 (set-buffer "*vc-diff*")
1776 (if (and (zerop (buffer-size)) 1759 (if (and (zerop (buffer-size))
1777 (not (get-buffer-process (current-buffer)))) 1760 (not (get-buffer-process (current-buffer))))
1778 (progn 1761 (progn
1779 (if rel1 1762 (if rel1
1791 (insert "No differences found.\n")) 1774 (insert "No differences found.\n"))
1792 (goto-char (point-min)) 1775 (goto-char (point-min))
1793 (shrink-window-if-larger-than-buffer))) 1776 (shrink-window-if-larger-than-buffer)))
1794 t)) 1777 t))
1795 1778
1779 (defun vc-diff-internal (file rel1 rel2)
1780 "Run diff to compare FILE's revisions REL1 and REL2.
1781 Output goes to the current buffer, which is assumed properly set up.
1782 The exit status of the diff command is returned.
1783
1784 This function takes care to set up a proper coding system for diff output.
1785 If both revisions are available as local files, then it also does not
1786 actually call the backend, but performs a local diff."
1787 (if (or (not rel1) (string-equal rel1 ""))
1788 (setq rel1 (vc-workfile-version file)))
1789 (if (string-equal rel2 "")
1790 (setq rel2 nil))
1791 (let ((file-rel1 (vc-version-backup-file file rel1))
1792 (file-rel2 (if (not rel2)
1793 file
1794 (vc-version-backup-file file rel2)))
1795 (coding-system-for-read (vc-coding-system-for-diff file)))
1796 (if (and file-rel1 file-rel2)
1797 (apply 'vc-do-command "*vc-diff*" 1 "diff" nil
1798 (append (if (listp diff-switches)
1799 diff-switches
1800 (list diff-switches))
1801 (if (listp vc-diff-switches)
1802 vc-diff-switches
1803 (list vc-diff-switches))
1804 (list (file-relative-name file-rel1)
1805 (file-relative-name file-rel2))))
1806 (vc-call diff file rel1 rel2))))
1807
1796 (defmacro vc-diff-switches-list (backend) 1808 (defmacro vc-diff-switches-list (backend)
1797 "Make a list of `diff-switches', `vc-diff-switches', 1809 "Make a list of `diff-switches', `vc-diff-switches',
1798 and `vc-BACKEND-diff-switches'." 1810 and `vc-BACKEND-diff-switches'."
1799 `(append 1811 `(append
1800 (if (listp diff-switches) diff-switches (list diff-switches)) 1812 (if (listp diff-switches) diff-switches (list diff-switches))
1801 (if (listp vc-diff-switches) vc-diff-switches (list vc-diff-switches)) 1813 (if (listp vc-diff-switches) vc-diff-switches (list vc-diff-switches))
1802 (let ((backend-switches 1814 (let ((backend-switches
1803 (eval (intern (concat "vc-" (symbol-name ',backend) 1815 (eval (intern (concat "vc-" (symbol-name ',backend)
1804 "-diff-switches"))))) 1816 "-diff-switches")))))
1805 (if (listp backend-switches) backend-switches (list backend-switches))))) 1817 (if (listp backend-switches) backend-switches (list backend-switches)))))
1818
1819 (defun vc-default-diff-tree (backend dir rel1 rel2)
1820 "Default implementation for diffing an entire tree at and below DIR.
1821 The meaning of REL1 and REL2 is the same as for `vc-version-diff'."
1822 ;; This implementation does an explicit tree walk, and calls
1823 ;; vc-BACKEND-diff directly for each file. An optimization
1824 ;; would be to use `vc-diff-internal', so that diffs can be local,
1825 ;; and to call it only for files that are actually changed.
1826 ;; However, this is expensive for some backends, and so it is left
1827 ;; to backend-specific implementations.
1828 (setq default-directory dir)
1829 (vc-file-tree-walk
1830 default-directory
1831 (lambda (f)
1832 (vc-exec-after
1833 `(let ((coding-system-for-read (vc-coding-system-for-diff ',f)))
1834 (message "Looking at %s" ',f)
1835 (vc-call-backend ',(vc-backend f)
1836 'diff ',f ',rel1 ',rel2))))))
1837
1838 (defun vc-coding-system-for-diff (file)
1839 "Return the coding system for reading diff output for FILE."
1840 (or coding-system-for-read
1841 ;; if we already have this file open,
1842 ;; use the buffer's coding system
1843 (let ((buf (find-buffer-visiting file)))
1844 (if buf (with-current-buffer buf
1845 buffer-file-coding-system)))
1846 ;; otherwise, try to find one based on the file name
1847 (car (find-operation-coding-system 'insert-file-contents
1848 file))
1849 ;; and a final fallback
1850 'undecided))
1806 1851
1807 ;;;###autoload 1852 ;;;###autoload
1808 (defun vc-version-other-window (rev) 1853 (defun vc-version-other-window (rev)
1809 "Visit version REV of the current buffer in another window. 1854 "Visit version REV of the current buffer in another window.
1810 If the current buffer is named `F', the version is named `F.~REV~'. 1855 If the current buffer is named `F', the version is named `F.~REV~'.