From d55552f6e3b63ab6f33dd61071760bee42b9bc5e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 17 Mar 2007 20:40:12 +0100 Subject: git.el: Add support for commit hooks. Run the pre-commit and post-commit hooks at appropriate places, and display their output if any. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index db87a37..5f22dec 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -1,6 +1,6 @@ ;;; git.el --- A user interface for git -;; Copyright (C) 2005, 2006 Alexandre Julliard +;; Copyright (C) 2005, 2006, 2007 Alexandre Julliard ;; Version: 1.0 @@ -213,6 +213,23 @@ and returns the process output as a string." (error "Failed to run \"git %s\":\n%s" (mapconcat (lambda (x) x) args " ") (buffer-string))) (message "Running git %s...done" (car args))) +(defun git-run-hook (hook env &rest args) + "Run a git hook and display its output if any." + (let ((dir default-directory) + (hook-name (expand-file-name (concat ".git/hooks/" hook)))) + (or (not (file-executable-p hook-name)) + (let (status (buffer (get-buffer-create "*Git Hook Output*"))) + (with-current-buffer buffer + (erase-buffer) + (cd dir) + (setq status + (if env + (apply #'call-process "env" nil (list buffer t) nil + (append (git-get-env-strings env) (list hook-name) args)) + (apply #'call-process hook-name nil (list buffer t) nil args)))) + (display-message-or-buffer buffer) + (eq 0 status))))) + (defun git-get-string-sha1 (string) "Read a SHA1 from the specified string." (and string @@ -590,6 +607,20 @@ and returns the process output as a string." (when modified (apply #'git-run-command nil env "update-index" "--" (git-get-filenames modified))))) +(defun git-run-pre-commit-hook () + "Run the pre-commit hook if any." + (unless git-status (error "Not in git-status buffer.")) + (let ((files (git-marked-files-state 'added 'deleted 'modified))) + (or (not files) + (not (file-executable-p ".git/hooks/pre-commit")) + (let ((index-file (make-temp-file "gitidx"))) + (unwind-protect + (let ((head-tree (unless (git-empty-db-p) (git-rev-parse "HEAD^{tree}")))) + (git-read-tree head-tree index-file) + (git-update-index index-file files) + (git-run-hook "pre-commit" `(("GIT_INDEX_FILE" . ,index-file)))) + (delete-file index-file)))))) + (defun git-do-commit () "Perform the actual commit using the current buffer as log message." (interactive) @@ -622,7 +653,8 @@ and returns the process output as a string." (git-run-command nil nil "rerere")) (git-refresh-files) (git-refresh-ewoc-hf git-status) - (message "Committed %s." commit)) + (message "Committed %s." commit) + (git-run-hook "post-commit" nil)) (message "Commit aborted.")))) (message "No files to commit."))) (delete-file index-file)))))) @@ -944,28 +976,29 @@ and returns the process output as a string." "Commit the marked file(s), asking for a commit message." (interactive) (unless git-status (error "Not in git-status buffer.")) - (let ((buffer (get-buffer-create "*git-commit*")) - (coding-system (git-get-commits-coding-system)) - author-name author-email subject date) - (when (eq 0 (buffer-size buffer)) - (when (file-readable-p ".dotest/info") - (with-temp-buffer - (insert-file-contents ".dotest/info") - (goto-char (point-min)) - (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t) - (setq author-name (match-string 1)) - (setq author-email (match-string 2))) - (goto-char (point-min)) - (when (re-search-forward "^Subject: \\(.*\\)$" nil t) - (setq subject (match-string 1))) - (goto-char (point-min)) - (when (re-search-forward "^Date: \\(.*\\)$" nil t) - (setq date (match-string 1))))) - (git-setup-log-buffer buffer author-name author-email subject date)) - (log-edit #'git-do-commit nil #'git-log-edit-files buffer) - (setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords)) - (setq buffer-file-coding-system coding-system) - (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t))) + (when (git-run-pre-commit-hook) + (let ((buffer (get-buffer-create "*git-commit*")) + (coding-system (git-get-commits-coding-system)) + author-name author-email subject date) + (when (eq 0 (buffer-size buffer)) + (when (file-readable-p ".dotest/info") + (with-temp-buffer + (insert-file-contents ".dotest/info") + (goto-char (point-min)) + (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t) + (setq author-name (match-string 1)) + (setq author-email (match-string 2))) + (goto-char (point-min)) + (when (re-search-forward "^Subject: \\(.*\\)$" nil t) + (setq subject (match-string 1))) + (goto-char (point-min)) + (when (re-search-forward "^Date: \\(.*\\)$" nil t) + (setq date (match-string 1))))) + (git-setup-log-buffer buffer author-name author-email subject date)) + (log-edit #'git-do-commit nil #'git-log-edit-files buffer) + (setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords)) + (setq buffer-file-coding-system coding-system) + (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t)))) (defun git-find-file () "Visit the current file in its own buffer." -- cgit v0.10.2-6-g49f6