unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* make vc-annotate work through copies and renames
@ 2009-10-14 15:58 Dan Nicolaescu
  2009-10-15  3:10 ` Stefan Monnier
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Nicolaescu @ 2009-10-14 15:58 UTC (permalink / raw)
  To: emacs-devel


The annotate command on modern VC systems can work through file copies
and renames.
In case of a copy/rename the file name appears in the annotate output.
Here's an example from git (using the nicely named command line option -C -C),
annotating the f.csh file, which was copied from the t.csh file at some
point (file contents omitted here):

e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700  1) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700  2) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700  3) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700  4) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700  5) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700  6) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700  7) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700  8) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700  9) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 10) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 11) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 12) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 13) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 14) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 15) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 16) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 17) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 18) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 19) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 20) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 21) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 22) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 23) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 24) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 25) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 26) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 27) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 28) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 29) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 30) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 31) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 32) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 33) 
14d0ca93 t.csh (dann 2008-03-28 09:23:28 -0700 34) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700 35) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700 36) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700 37) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700 38) 
e19523a7 f.csh (dann 2009-07-31 23:53:36 -0700 39) 

vc-annotate.el assumes that the file name is always the same.  This is
not true when showing copies/renames.

One way to deal with this is to make
vc-annotate-extract-revision-at-line return a cons (REVISION . FILENAME)
instead of just REVISION.  Then work through all the commands and change
them to use the FILENAME that is passed.

Here's a patch that implements this, and it makes the "f" command work,
when run on lines 7...34 in the example above, it shows version
"14d0ca93" of t.csh.

Any suggestions?


--- vc-annotate.el.~1.9.~	2009-09-12 11:23:15.000000000 -0700
+++ vc-annotate.el	2009-10-14 05:18:09.000000000 -0700
@@ -432,7 +432,11 @@ revisions after."
 (defun vc-annotate-extract-revision-at-line ()
   "Extract the revision number of the current line."
   ;; 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 +446,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,7 +458,7 @@ 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."
Index: vc-git.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/vc-git.el,v
retrieving revision 1.94
diff -u -3 -p -u -p -r1.94 vc-git.el
--- vc-git.el	20 Sep 2009 19:51:38 -0000	1.94
+++ vc-git.el	14 Oct 2009 13:47:54 -0000
@@ -613,7 +632,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))
 
@@ -627,8 +646,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 (match-string-no-properties 3))
+	  revision)))))
 
 ;;; TAG SYSTEM
 





^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: make vc-annotate work through copies and renames
  2009-10-14 15:58 make vc-annotate work through copies and renames Dan Nicolaescu
@ 2009-10-15  3:10 ` Stefan Monnier
  2009-10-17  6:18   ` Dan Nicolaescu
  0 siblings, 1 reply; 4+ messages in thread
From: Stefan Monnier @ 2009-10-15  3:10 UTC (permalink / raw)
  To: Dan Nicolaescu; +Cc: emacs-devel

> vc-annotate.el assumes that the file name is always the same.  This is
> not true when showing copies/renames.

This varies a lot between backends.  E.g. IIRC in Svn and Arch, the
file-name is basically ignored (replaced by some notion of file identity
that is preserved by renaming), so in your example the f.csh file is the
only name that would appear and revision "14d0ca93" of that file simply
had the name "t.csh" at that time, but you don't need to know about it
to get the `annotate' output, or the `diff' output or ...

So providing support for it in the generic part of the code may turn out
to be trickier than your patch suggests.


        Stefan




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: make vc-annotate work through copies and renames
  2009-10-15  3:10 ` Stefan Monnier
@ 2009-10-17  6:18   ` Dan Nicolaescu
  2009-10-17 12:52     ` Stefan Monnier
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Nicolaescu @ 2009-10-17  6:18 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

  > > vc-annotate.el assumes that the file name is always the same.  This is
  > > not true when showing copies/renames.
  > 
  > This varies a lot between backends.  E.g. IIRC in Svn and Arch, the
  > file-name is basically ignored (replaced by some notion of file identity
  > that is preserved by renaming), so in your example the f.csh file is the
  > only name that would appear and revision "14d0ca93" of that file simply
  > had the name "t.csh" at that time, but you don't need to know about it
  > to get the `annotate' output, or the `diff' output or ...

Arch does not support vc-annotate, so ... 
For Svn nothing should change, it does not display the file names in the
annotate output, and it does not need them, the vc-annotate
functionality does not change in that case.

Here's a complete patch.  It works with copying/renaming for Hg and Git.  
And it continues to work as before for all the other backends.

OK to check in?


Index: vc-annotate.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/vc-annotate.el,v
retrieving revision 1.9
diff -u -3 -p -r1.9 vc-annotate.el
--- vc-annotate.el	11 Sep 2009 10:58:58 -0000	1.9
+++ vc-annotate.el	17 Oct 2009 05:51:41 -0000
@@ -432,7 +432,11 @@ revisions after."
 (defun vc-annotate-extract-revision-at-line ()
   "Extract the revision number of the current line."
   ;; 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 +446,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 +458,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 +485,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 +526,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 +545,7 @@ describes a revision number, so warp to 
 	(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 +554,7 @@ describes a revision number, so warp to 
 	(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 +562,7 @@ describes a revision number, so warp to 
        ((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
Index: vc-git.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/vc-git.el,v
retrieving revision 1.95
diff -u -3 -p -r1.95 vc-git.el
--- vc-git.el	14 Oct 2009 06:28:03 -0000	1.95
+++ vc-git.el	17 Oct 2009 05:51:41 -0000
@@ -610,7 +620,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 +634,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
 
Index: vc-hg.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/vc-hg.el,v
retrieving revision 1.103
diff -u -3 -p -r1.103 vc-hg.el
--- vc-hg.el	5 Oct 2009 15:12:32 -0000	1.103
+++ vc-hg.el	17 Oct 2009 05:51:41 -0000
@@ -313,12 +317,15 @@ If nil, use the value of `vc-diff-switch
 (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"
+  (vc-hg-command buffer 0 file "annotate" "-d" "-n" "--follow"
                  (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))))
+    ;; This stuff does not seem to do anything.
+    ;; (goto-char (point-min))
+    ;; (re-search-forward "^[ \t]*[0-9]")
+    ;; (delete-region (point-min) (match-beginning 0))
+    )
+  )
 
 (declare-function vc-annotate-convert-time "vc-annotate" (time))
 
@@ -329,7 +337,7 @@ Optional arg REVISION is a revision to a
 ;;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 +348,11 @@ Optional arg REVISION is a revision to a
 (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))))
Index: vc.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/vc.el,v
retrieving revision 1.734
diff -u -3 -p -r1.734 vc.el
--- vc.el	14 Oct 2009 06:08:53 -0000	1.734
+++ vc.el	17 Oct 2009 05:51:42 -0000
@@ -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
 ;;




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: make vc-annotate work through copies and renames
  2009-10-17  6:18   ` Dan Nicolaescu
@ 2009-10-17 12:52     ` Stefan Monnier
  0 siblings, 0 replies; 4+ messages in thread
From: Stefan Monnier @ 2009-10-17 12:52 UTC (permalink / raw)
  To: Dan Nicolaescu; +Cc: emacs-devel

> Here's a complete patch.  It works with copying/renaming for Hg and Git.  
> And it continues to work as before for all the other backends.

I guess it's OK, then,


        Stefan




^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-10-17 12:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-14 15:58 make vc-annotate work through copies and renames Dan Nicolaescu
2009-10-15  3:10 ` Stefan Monnier
2009-10-17  6:18   ` Dan Nicolaescu
2009-10-17 12:52     ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).