blob: 85b0995f956866c987bf5f013213b03dbf977dbc (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
;;; gitsum.el --- basic darcsum feelalike for Git
;; Copyright (C) 2008 Christian Neukirchen <purl.org/net/chneukirchen>
;; Licensed under the same terms as Emacs.
;; Repository: http://github.com/chneukirchen/gitsum
;; git://github.com/chneukirchen/gitsum.git
;; Patches to: chneukirchen@gmail.com
;; Version: 0.2
;; 04feb2008 +chris+
(eval-when-compile (require 'cl))
(easy-mmode-defmap gitsum-diff-mode-shared-map
'(("c" . gitsum-commit)
("g" . gitsum-refresh)
("s" . gitsum-switch-to-git-status)
("q" . gitsum-kill-buffer)
("u" . gitsum-undo))
"Basic keymap for `gitsum-diff-mode', bound to various prefix keys.")
(define-derived-mode gitsum-diff-mode diff-mode "gitsum"
"Git summary mode is for preparing patches to a Git repository.
This mode is meant to be activated by `M-x gitsum' or pressing `s' in git-status.
\\{gitsum-diff-mode-map}"
;; magic...
(lexical-let ((ro-bind (cons 'buffer-read-only gitsum-diff-mode-shared-map)))
(add-to-list 'minor-mode-overriding-map-alist ro-bind))
(setq buffer-read-only t))
(define-key gitsum-diff-mode-map (kbd "C-c C-c") 'gitsum-commit)
(define-key gitsum-diff-mode-map (kbd "C-/") 'gitsum-undo)
(define-key gitsum-diff-mode-map (kbd "C-_") 'gitsum-undo)
;; When git.el is loaded, hack into keymap.
(when (boundp 'git-status-mode-map)
(define-key git-status-mode-map "s" 'gitsum))
;; Undo doesn't work in read-only buffers else.
(defun gitsum-undo ()
"Undo some previous changes.
Repeat this command to undo more changes.
A numeric argument serves as a repeat count."
(interactive)
(let ((inhibit-read-only t))
(undo)))
(defun gitsum-refresh ()
"Regenerate the patch based on the current state of the index."
(interactive)
(let ((inhibit-read-only t))
(erase-buffer)
(insert "# Directory: " default-directory "\n")
(insert "# Use n and p to navigate and k to kill a hunk. u is undo, g will refresh.\n")
(insert "# Edit the patch as you please and press 'c' to commit.\n\n")
(let ((diff (shell-command-to-string "git diff")))
(if (zerop (length diff))
(insert "## No changes. ##")
(insert diff)
(goto-char (point-min))
(delete-matching-lines "^index \\|^diff --git ")))
(set-buffer-modified-p nil)))
(defun gitsum-commit ()
"Commit the patch as-is, asking for a commit message."
(interactive)
(shell-command-on-region (point-min) (point-max) "git apply --check --cached")
(let ((buffer (get-buffer-create "*gitsum-commit*")))
(shell-command-on-region (point-min) (point-max) "(cat; git diff --cached) | git apply --stat" buffer)
(with-current-buffer buffer
(goto-char (point-min))
(insert "\n")
(while (re-search-forward "^" nil t)
(replace-match "# " nil nil))
(forward-line 0)
(forward-char -1)
(delete-region (point) (point-max))
(goto-char (point-min)))
(log-edit 'gitsum-do-commit nil nil buffer)))
(defun gitsum-do-commit ()
"Perform the actual commit using the current buffer as log message."
(interactive)
(with-current-buffer log-edit-parent-buffer
(shell-command-on-region (point-min) (point-max)
"git apply --cached"))
(shell-command-on-region (point-min) (point-max)
"git commit -F- --cleanup=strip")
(with-current-buffer log-edit-parent-buffer
(gitsum-refresh)))
(defun gitsum-kill-buffer ()
"Kill the current buffer if it has no manual changes."
(interactive)
(unless (buffer-modified-p)
(kill-buffer nil)))
(defun gitsum-switch-to-git-status ()
"Switch to git-status."
(interactive)
(git-status default-directory))
(defun gitsum ()
"Entry point into gitsum-diff-mode."
(interactive)
(switch-to-buffer (generate-new-buffer "*gitsum*"))
(gitsum-diff-mode)
(gitsum-refresh))
|