X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=contrib%2Femacs%2Fvc-git.el;h=b8f6be5c0af64dfbe7e136f984404f22aea68130;hb=5c9afcff1aa048abf95296231d51fa481304a735;hp=3f6ed699f0848cab6709e736e245b968e963978c;hpb=49b2788539016e7fd20559bea11b306ade0183b7;p=git.git diff --git a/contrib/emacs/vc-git.el b/contrib/emacs/vc-git.el index 3f6ed699f..b8f6be5c0 100644 --- a/contrib/emacs/vc-git.el +++ b/contrib/emacs/vc-git.el @@ -23,13 +23,18 @@ ;; system. ;; ;; To install: put this file on the load-path and add GIT to the list -;; of supported backends in `vc-handled-backends'. +;; of supported backends in `vc-handled-backends'; the following line, +;; placed in your ~/.emacs, will accomplish this: +;; +;; (add-to-list 'vc-handled-backends 'GIT) ;; ;; TODO ;; - changelog generation ;; - working with revisions other than HEAD ;; +(eval-when-compile (require 'cl)) + (defvar git-commits-coding-system 'utf-8 "Default coding system for git commits.") @@ -53,8 +58,9 @@ (with-temp-buffer (let* ((dir (file-name-directory file)) (name (file-relative-name file dir))) - (when dir (cd dir)) - (and (eq 0 (call-process "git" nil '(t nil) nil "ls-files" "-c" "-z" "--" name)) + (and (ignore-errors + (when dir (cd dir)) + (eq 0 (call-process "git" nil '(t nil) nil "ls-files" "-c" "-z" "--" name))) (let ((str (buffer-string))) (and (> (length str) (length name)) (string= (substring str 0 (1+ (length name))) (concat name "\0")))))))) @@ -75,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 @@ -114,15 +185,24 @@ (vc-git--run-command file "commit" "-m" comment "--only" "--"))) (defun vc-git-checkout (file &optional editable rev destfile) - (vc-git--run-command file "checkout" (or rev "HEAD"))) + (if destfile + (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) ; FIXME: rev is ignored (let ((name (file-relative-name file))) - (call-process "git" nil buf nil "annotate" name))) + (call-process "git" nil buf nil "blame" name))) (defun vc-git-annotate-time () - (and (re-search-forward "[0-9a-f]+\t(.*\t\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\) \\([-+0-9]+\\)\t[0-9]+)" nil t) + (and (re-search-forward "[0-9a-f]+ (.* \\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\) \\([-+0-9]+\\) +[0-9]+)" nil t) (vc-annotate-convert-time (apply #'encode-time (mapcar (lambda (match) (string-to-number (match-string match))) '(6 5 4 3 2 1 7))))))