Merge branch 'maint'
[gitweb.git] / contrib / emacs / vc-git.el
index 65c455006978932cee3f6f3a4d7d014ff18a6489..b8f6be5c0af64dfbe7e136f984404f22aea68130 100644 (file)
   (let ((name (file-relative-name file)))
     (eq 0 (apply #'call-process "git" nil (get-buffer "*Messages") nil (append args (list name))))))
 
-(defun vc-git--run-command-out (output &rest args)
-  "Run a git command, output to output."
-  (eq 0 (apply #'call-process "git" nil output nil (append args))))
-
 (defun vc-git-registered (file)
   "Check whether FILE is registered with git."
   (with-temp-buffer
         (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
 
 (defun vc-git-checkout (file &optional editable rev destfile)
   (if destfile
-      (let ((mybuff (get-buffer-create "vc-git-checkout-tmp")))
-       (let ((rv
-              (vc-git--run-command-out
-               mybuff "cat-file" "blob"
-               (concat (or rev "HEAD")
-                       ":"
-                       (let ((output (vc-git--run-command-string
-                                      (file-relative-name file)
-                                      "ls-files" "--full-name")))
-                         (string-match "\\(.*\\)" output)
-                         (match-string 1 output))
-                       )))
-             )
-         (if rv
-             (save-current-buffer
-               (set-buffer mybuff)
-               (set-visited-file-name destfile t)
-               (save-buffer)
-               )
-           rv)))
+      (let ((fullname (substring
+                       (vc-git--run-command-string file "ls-files" "-z" "--full-name" "--")
+                       0 -1))
+            (coding-system-for-read 'no-conversion)
+            (coding-system-for-write 'no-conversion))
+        (with-temp-file destfile
+          (eq 0 (call-process "git" nil t nil "cat-file" "blob"
+                              (concat (or rev "HEAD") ":" fullname)))))
     (vc-git--run-command file "checkout" (or rev "HEAD"))))
 
 (defun vc-git-annotate-command (file buf &optional rev)