threads / discuss / 8980

Getting version output for a file.

Subject: Getting version output for a file.

## tl;dr

3 messages between Jul 11, 2007 and Jul 12, 2007.

replies: 2people: 2as markdown or json

David Kastrup· Jul 11, 2007, 11:39 UTC · lore
Hi,

the Emacs support for git is incomplete, making it bomb out, for example, when doing C-u C-x v =

In order to have it work better, I need to fill in the following functions:

(vc-git-previous-version FILE REV) Return the version number immediately preceding REV for FILE, or nil if there is no previous version.

(vc-git-next-version FILE REV) Return the version number immediately following REV for FILE, or nil if there is no previous version.

REV will tend to be a symbolic reference like "master" or possibly "master{2}" (I am fuzzy about the details, but at least repeated invocations of vc-git-previous-version should work with the previous output). The corresponding next and previous versions should be changes that actually changed the file in question.

There is likely going to be some magic shell invocation of git-rev-list, git-symbolic-ref and/or similar things to achieve this task. I don't have enough of a clue to fill in the necessary details, but I'd be able to convert them into Elisp.

Anybody with good suggestions? It would be beneficial if this would not require the newest git version in order to work. If that means that the output needs to be somewhat more massaged, that's ok.

Thanks,
-- 
David Kastrup
Brian Gernhardt· Jul 11, 2007, 19:48 UTC · re: David Kastrup · lore

Re: Getting version output for a file.

I don't know lisp very well, and elisp not at all, but I can help you with what command lines would give you the results you might want.

On Jul 11, 2007, at 7:39 AM, David Kastrup wrote:
> (vc-git-previous-version FILE REV)
> Return the version number immediately preceding REV for FILE,
> or nil if there is no previous version.

If you want the last revision where the file was altered, you could easily use

git rev-list -2 $current_rev -- $file | tail -1

The result would be a SHA-1 of the next commit where the file was altered.

> (vc-git-next-version FILE REV)
> Return the version number immediately following REV for FILE,
> or nil if there is no previous version.

This is a little more problematic as git doesn't have forward links in it's history. If you have a ref to start with (HEAD is a good one to use, if you don't have anything else) you could use a similar command to the above

git rev-list $ref -- $file | grep -C1 -m1 $current_rev | head -1

If you don't have a ref to start from, you could use --all, but that may not be what the user expects.

If you want a human readable name for either you could use name-rev. (Add "| git name-rev --stdin" to the end of the above.) It places a human readable name after the SHA-1 in parentheses. (example: "54dadbdb29668fbd51effefd0a0c65d915f5422b (master~3)")

~~ Brian
David Kastrup· Jul 12, 2007, 14:48 UTC · re: Brian Gernhardt · lore

[PATCH] Add missing functions to contrib/emacs/vc-git.el

This is necessary to make several editing functions work, like C-u C-x v =

Signed-off-by: David Kastrup <dak@gnu.org>
---
 contrib/emacs/vc-git.el |   65 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/contrib/emacs/vc-git.el b/contrib/emacs/vc-git.el
index e456ab9..b8f6be5 100644
--- a/contrib/emacs/vc-git.el
+++ b/contrib/emacs/vc-git.el
@@ -81,6 +81,71 @@
         (match-string 2 str)
       str)))
 
+(defun vc-git-symbolic-commit (commit)
+  "Translate COMMIT string into symbolic form.
+Returns nil if not possible."
+  (and commit
+       (with-temp-buffer
+	 (and
+	  (zerop
+	   (call-process "git" nil '(t nil) nil "name-rev"
+			 "--name-only" "--tags"
+			 commit))
+	  (goto-char (point-min))
+	  (= (forward-line 2) 1)
+	  (bolp)
+	  (buffer-substring-no-properties (point-min) (1- (point-max)))))))
+
+(defun vc-git-previous-version (file rev)
+  "git-specific version of `vc-previous-version'."
+  (let ((default-directory (file-name-directory (expand-file-name file)))
+	(file (file-name-nondirectory file)))
+    (vc-git-symbolic-commit
+     (with-temp-buffer
+       (and
+	(zerop
+	 (call-process "git" nil '(t nil) nil "rev-list"
+		       "-2" rev "--" file))
+	(goto-char (point-max))
+	(bolp)
+	(zerop (forward-line -1))
+	(not (bobp))
+	(buffer-substring-no-properties
+	   (point)
+	   (1- (point-max))))))))
+
+(defun vc-git-next-version (file rev)
+  "git-specific version of `vc-next-version'."
+  (let* ((default-directory (file-name-directory
+			     (expand-file-name file)))
+	(file (file-name-nondirectory file))
+	(current-rev
+	 (with-temp-buffer
+	   (and
+	    (zerop
+	     (call-process "git" nil '(t nil) nil "rev-list"
+			   "-1" rev "--" file))
+	    (goto-char (point-max))
+	    (bolp)
+	    (zerop (forward-line -1))
+	    (bobp)
+	    (buffer-substring-no-properties
+	     (point)
+	     (1- (point-max)))))))
+    (and current-rev
+	 (vc-git-symbolic-commit
+	  (with-temp-buffer
+	    (and
+	     (zerop
+	      (call-process "git" nil '(t nil) nil "rev-list"
+			    "HEAD" "--" file))
+	     (goto-char (point-min))
+	     (search-forward current-rev nil t)
+	     (zerop (forward-line -1))
+	     (buffer-substring-no-properties
+	      (point)
+	      (progn (forward-line 1) (1- (point))))))))))
+
 (defun vc-git-revert (file &optional contents-done)
   "Revert FILE to the version stored in the git repository."
   (if contents-done
-- 
1.5.3.rc0.51.gb0b1f


-- 
David Kastrup

← back to recent threads