From d1e4c4037e88f3256db19813805d03f8ad0291fa Mon Sep 17 00:00:00 2001 From: Dan Nicolaescu Date: Mon, 19 Oct 2009 05:04:22 +0000 Subject: [PATCH] Make vc-annotate work through copies and renames. * vc-annotate.el (vc-annotate-extract-revision-at-line): Return the file name too. (vc-annotate-revision-at-line) (vc-annotate-find-revision-at-line) (vc-annotate-revision-previous-to-line) (vc-annotate-show-log-revision-at-line): Update to get the file name from vc-annotate-extract-revision-at-line. (vc-annotate-show-diff-revision-at-line-internal): Change the argument to mean whether to show a file diff or not. Get the file name from vc-annotate-extract-revision-at-line. (vc-annotate-show-diff-revision-at-line): Update vc-annotate-show-diff-revision-at-line call. (vc-annotate-warp-revision): Add an optional file argument. * vc-git.el (vc-git-annotate-command): Pass -C -C to the blame command. (vc-git-annotate-extract-revision-at-line): Also return the file name if found. * vc-hg.el (vc-hg-annotate-command): Pass --follow to the annotate command. Remove unused code. (vc-hg-annotate-re): Update to match --follow output. (vc-hg-annotate-extract-revision-at-line): Also return the file name if found. * vc.el: Update annotate-extract-revision-at-line documentation. --- etc/NEWS | 5 ++++ lisp/ChangeLog | 29 +++++++++++++++++++++++ lisp/vc-annotate.el | 58 ++++++++++++++++++++++++++++----------------- lisp/vc-git.el | 9 ++++--- lisp/vc-hg.el | 16 ++++++------- lisp/vc.el | 3 +++ 6 files changed, 87 insertions(+), 33 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 197751c6e5..4d8778b10b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -193,6 +193,11 @@ file. *** FIXME: add info about the new VC functions: vc-root-diff and vc-root-print-log once they stabilize. +*** vc-annotate supports annotations through file copies and renames, +it displays the old names for the files and it can show logs/diffs for +the corresponding lines. Currently only Git and Mercurial take +advantage of this feature. + *** When a file is not found, VC will not try to check it out of RCS anymore. *** vc-git changes diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0d7a1044a9..46c27390b5 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,32 @@ +2009-10-19 Dan Nicolaescu + + Make vc-annotate work through copies and renames. + * vc-annotate.el (vc-annotate-extract-revision-at-line): Return + the file name too. + (vc-annotate-revision-at-line) + (vc-annotate-find-revision-at-line) + (vc-annotate-revision-previous-to-line) + (vc-annotate-show-log-revision-at-line): Update to get the file + name from vc-annotate-extract-revision-at-line. + (vc-annotate-show-diff-revision-at-line-internal): Change the + argument to mean whether to show a file diff or not. Get the file + name from vc-annotate-extract-revision-at-line. + (vc-annotate-show-diff-revision-at-line): Update + vc-annotate-show-diff-revision-at-line call. + (vc-annotate-warp-revision): Add an optional file argument. + + * vc-git.el (vc-git-annotate-command): Pass -C -C to the blame command. + (vc-git-annotate-extract-revision-at-line): Also return the file + name if found. + + * vc-hg.el (vc-hg-annotate-command): Pass --follow to the annotate + command. Remove unused code. + (vc-hg-annotate-re): Update to match --follow output. + (vc-hg-annotate-extract-revision-at-line): Also return the file + name if found. + + * vc.el: Update annotate-extract-revision-at-line documentation. + 2009-10-18 Kevin Ryde * ibuffer.el (ibuffer-confirm-operation-on): Correction to error diff --git a/lisp/vc-annotate.el b/lisp/vc-annotate.el index 6c7ae5a876..f939d58e5d 100644 --- a/lisp/vc-annotate.el +++ b/lisp/vc-annotate.el @@ -430,9 +430,14 @@ revisions after." (vc-annotate-warp-revision warp-rev))))) (defun vc-annotate-extract-revision-at-line () - "Extract the revision number of the current line." + "Extract the revision number of the current line. +Return a cons (REV . FILENAME)." ;; This function must be invoked from a buffer in vc-annotate-mode - (vc-call-backend vc-annotate-backend 'annotate-extract-revision-at-line)) + (let ((rev (vc-call-backend vc-annotate-backend + 'annotate-extract-revision-at-line))) + (if (or (null rev) (consp rev)) + rev + (cons rev vc-annotate-parent-file)))) (defun vc-annotate-revision-at-line () "Visit the annotation of the revision identified in the current line." @@ -442,9 +447,9 @@ revisions after." (let ((rev-at-line (vc-annotate-extract-revision-at-line))) (if (not rev-at-line) (message "Cannot extract revision number from the current line") - (if (equal rev-at-line vc-annotate-parent-rev) + (if (equal (car rev-at-line) vc-annotate-parent-rev) (message "Already at revision %s" rev-at-line) - (vc-annotate-warp-revision rev-at-line)))))) + (vc-annotate-warp-revision (car rev-at-line) (cdr rev-at-line))))))) (defun vc-annotate-find-revision-at-line () "Visit the revision identified in the current line." @@ -454,21 +459,24 @@ revisions after." (let ((rev-at-line (vc-annotate-extract-revision-at-line))) (if (not rev-at-line) (message "Cannot extract revision number from the current line") - (vc-revision-other-window rev-at-line))))) + (switch-to-buffer-other-window + (vc-find-revision (cdr rev-at-line) (car rev-at-line))))))) (defun vc-annotate-revision-previous-to-line () "Visit the annotation of the revision before the revision at line." (interactive) (if (not (equal major-mode 'vc-annotate-mode)) (message "Cannot be invoked outside of a vc annotate buffer") - (let ((rev-at-line (vc-annotate-extract-revision-at-line)) - (prev-rev nil)) + (let* ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil) + (rev (car rev-at-line)) + (fname (cdr rev-at-line))) (if (not rev-at-line) (message "Cannot extract revision number from the current line") (setq prev-rev (vc-call-backend vc-annotate-backend 'previous-revision - vc-annotate-parent-file rev-at-line)) - (vc-annotate-warp-revision prev-rev))))) + fname rev)) + (vc-annotate-warp-revision rev fname))))) (defun vc-annotate-show-log-revision-at-line () "Visit the log of the revision at line." @@ -478,33 +486,39 @@ revisions after." (let ((rev-at-line (vc-annotate-extract-revision-at-line))) (if (not rev-at-line) (message "Cannot extract revision number from the current line") - (vc-print-log rev-at-line))))) + (vc-print-log-internal + vc-annotate-backend (list (cdr rev-at-line)) (car rev-at-line)))))) -(defun vc-annotate-show-diff-revision-at-line-internal (fileset) +(defun vc-annotate-show-diff-revision-at-line-internal (filediff) (if (not (equal major-mode 'vc-annotate-mode)) (message "Cannot be invoked outside of a vc annotate buffer") - (let ((rev-at-line (vc-annotate-extract-revision-at-line)) - (prev-rev nil)) + (let* ((rev-at-line (vc-annotate-extract-revision-at-line)) + (prev-rev nil) + (rev (car rev-at-line)) + (fname (cdr rev-at-line))) (if (not rev-at-line) (message "Cannot extract revision number from the current line") (setq prev-rev (vc-call-backend vc-annotate-backend 'previous-revision - vc-annotate-parent-file rev-at-line)) + fname rev)) (if (not prev-rev) - (message "Cannot diff from any revision prior to %s" rev-at-line) + (message "Cannot diff from any revision prior to %s" rev) (save-window-excursion (vc-diff-internal nil ;; The value passed here should follow what ;; `vc-deduce-fileset' returns. - (cons vc-annotate-backend (cons fileset nil)) - prev-rev rev-at-line)) + (list vc-annotate-backend + (if filediff + (list fname) + nil)) + prev-rev rev)) (switch-to-buffer "*vc-diff*")))))) (defun vc-annotate-show-diff-revision-at-line () "Visit the diff of the revision at line from its previous revision." (interactive) - (vc-annotate-show-diff-revision-at-line-internal (list vc-annotate-parent-file))) + (vc-annotate-show-diff-revision-at-line-internal t)) (defun vc-annotate-show-changeset-diff-revision-at-line () "Visit the diff of the revision at line from its previous revision for all files in the changeset." @@ -513,7 +527,7 @@ revisions after." (error "The %s backend does not support changeset diffs" vc-annotate-backend)) (vc-annotate-show-diff-revision-at-line-internal nil)) -(defun vc-annotate-warp-revision (revspec) +(defun vc-annotate-warp-revision (revspec &optional file) "Annotate the revision described by REVSPEC. If REVSPEC is a positive integer, warp that many revisions forward, @@ -532,7 +546,7 @@ describes a revision number, so warp to that revision." (setq newrev vc-annotate-parent-rev) (while (and (> revspec 0) newrev) (setq newrev (vc-call-backend vc-annotate-backend 'next-revision - vc-annotate-parent-file newrev)) + (or file vc-annotate-parent-file) newrev)) (setq revspec (1- revspec))) (unless newrev (message "Cannot increment %d revisions from revision %s" @@ -541,7 +555,7 @@ describes a revision number, so warp to that revision." (setq newrev vc-annotate-parent-rev) (while (and (< revspec 0) newrev) (setq newrev (vc-call-backend vc-annotate-backend 'previous-revision - vc-annotate-parent-file newrev)) + (or file vc-annotate-parent-file) newrev)) (setq revspec (1+ revspec))) (unless newrev (message "Cannot decrement %d revisions from revision %s" @@ -549,7 +563,7 @@ describes a revision number, so warp to that revision." ((stringp revspec) (setq newrev revspec)) (t (error "Invalid argument to vc-annotate-warp-revision"))) (when newrev - (vc-annotate vc-annotate-parent-file newrev + (vc-annotate (or file vc-annotate-parent-file) newrev vc-annotate-parent-display-mode buf ;; Pass the current line so that vc-annotate will diff --git a/lisp/vc-git.el b/lisp/vc-git.el index 6a757e32da..cee3abe0bb 100644 --- a/lisp/vc-git.el +++ b/lisp/vc-git.el @@ -610,7 +610,7 @@ or BRANCH^ (where \"^\" can be repeated)." (defun vc-git-annotate-command (file buf &optional rev) (let ((name (file-relative-name file))) - (vc-git-command buf 'async name "blame" "--date=iso" rev "--"))) + (vc-git-command buf 'async name "blame" "--date=iso" "-C" "-C" rev))) (declare-function vc-annotate-convert-time "vc-annotate" (time)) @@ -624,8 +624,11 @@ or BRANCH^ (where \"^\" can be repeated)." (defun vc-git-annotate-extract-revision-at-line () (save-excursion (move-beginning-of-line 1) - (and (looking-at "[0-9a-f^][0-9a-f]+") - (buffer-substring-no-properties (match-beginning 0) (match-end 0))))) + (when (looking-at "\\([0-9a-f^][0-9a-f]+\\) \\(\\([^(]+\\) \\)?") + (let ((revision (match-string-no-properties 1))) + (if (match-beginning 2) + (cons revision (expand-file-name (match-string-no-properties 3))) + revision))))) ;;; TAG SYSTEM diff --git a/lisp/vc-hg.el b/lisp/vc-hg.el index 1dedff159e..8443257efa 100644 --- a/lisp/vc-hg.el +++ b/lisp/vc-hg.el @@ -313,12 +313,8 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches." (defun vc-hg-annotate-command (file buffer &optional revision) "Execute \"hg annotate\" on FILE, inserting the contents in BUFFER. Optional arg REVISION is a revision to annotate from." - (vc-hg-command buffer 0 file "annotate" "-d" "-n" - (when revision (concat "-r" revision))) - (with-current-buffer buffer - (goto-char (point-min)) - (re-search-forward "^[ \t]*[0-9]") - (delete-region (point-min) (match-beginning 0)))) + (vc-hg-command buffer 0 file "annotate" "-d" "-n" "--follow" + (when revision (concat "-r" revision)))) (declare-function vc-annotate-convert-time "vc-annotate" (time)) @@ -329,7 +325,7 @@ Optional arg REVISION is a revision to annotate from." ;;215 Wed Jun 20 21:22:58 2007 -0700 foo.c: CONTENTS ;; i.e. VERSION_NUMBER DATE FILENAME: CONTENTS (defconst vc-hg-annotate-re - "^[ \t]*\\([0-9]+\\) \\(.\\{30\\}\\)[^:\n]*\\(:[^ \n][^:\n]*\\)*: ") + "^[ \t]*\\([0-9]+\\) \\(.\\{30\\}\\)\\(?:\\(: \\)\\|\\(?: +\\(.+\\): \\)\\)") (defun vc-hg-annotate-time () (when (looking-at vc-hg-annotate-re) @@ -340,7 +336,11 @@ Optional arg REVISION is a revision to annotate from." (defun vc-hg-annotate-extract-revision-at-line () (save-excursion (beginning-of-line) - (when (looking-at vc-hg-annotate-re) (match-string-no-properties 1)))) + (when (looking-at vc-hg-annotate-re) + (if (match-beginning 3) + (match-string-no-properties 1) + (cons (match-string-no-properties 1) + (expand-file-name (match-string-no-properties 4))))))) (defun vc-hg-previous-revision (file rev) (let ((newrev (1- (string-to-number rev)))) diff --git a/lisp/vc.el b/lisp/vc.el index 87cade8485..2d5e325de2 100644 --- a/lisp/vc.el +++ b/lisp/vc.el @@ -418,6 +418,9 @@ ;; Invoked from a buffer in vc-annotate-mode, return the revision ;; corresponding to the current line, or nil if there is no revision ;; corresponding to the current line. +;; If the backend supports annotating through copies and renames, +;; and displays a file name and a revision, then return a cons +;; (REVISION . FILENAME). ;; ;; TAG SYSTEM ;; -- 2.20.1