add magit-diff-master-mergebase command
[emacs-init.git] / setup / magit.el
1 (add-to-list 'load-path (concat (file-name-directory
2                                  (directory-file-name
3                                   (file-name-directory
4                                    (or load-file-name
5                                        (when (boundp 'bytecomp-filename) bytecomp-filename)
6                                        buffer-file-name))))
7                                 "magit/lisp"))
8
9 (add-to-list 'load-path (concat (file-name-directory
10                                  (directory-file-name
11                                   (file-name-directory
12                                    (or load-file-name
13                                        (when (boundp 'bytecomp-filename) bytecomp-filename)
14                                        buffer-file-name))))
15                                 "with-editor"))
16
17 (add-to-list 'load-path (concat (file-name-directory
18                                  (directory-file-name
19                                   (file-name-directory
20                                    (or load-file-name
21                                        (when (boundp 'bytecomp-filename) bytecomp-filename)
22                                        buffer-file-name))))
23                                 "auto-install"))
24
25 (require 'cl)
26
27 (if (not (functionp 'run-hook-wrapped))
28     (defun run-hook-wrapped (hook wrap-function &rest args)
29       (loop for fn in hook
30             thereis (apply 'wrap-function fn args))))
31
32 (if (not (functionp 'process-live-p))
33     (defun process-live-p (process)
34       (memq (process-status process)
35             '(run open listen connect stop))))
36
37 (require 'magit)
38
39 (setq magit-refs-local-branch-format "%C %-48n %U%m\n")
40 (setq magit-refs-remote-branch-format "%C %-48n %m\n")
41
42 (when (eq system-type 'windows-nt)
43
44   (require 'advice)
45
46   (setf (symbol-function 'builtin-process-file) (symbol-function 'process-file))
47
48   (defvar my-magit-shell "c:\\Program Files (x86)\\Git\\bin\\sh")
49
50   (defun my-magit-process-file (program &optional infile buffer display &rest args)
51     (builtin-process-file my-magit-shell infile buffer display
52                           "-c" (mapconcat 'shell-quote-argument (cons "/bin/git" args) " ")))
53
54   (defadvice magit-cmd-output (around my-magit-process-file activate)
55     (letf (((symbol-function 'process-file) (symbol-function 'my-magit-process-file)))
56       ad-do-it))
57
58   (defadvice magit-git-exit-code (around my-magit-process-file activate)
59     (letf (((symbol-function 'process-file) (symbol-function 'my-magit-process-file)))
60       ad-do-it))
61
62   (defadvice magit-run (around activate)
63     (letf (((symbol-function 'process-file) (symbol-function 'my-magit-process-file)))
64       ad-do-it))
65
66 ); End Windows-NT
67
68 (defadvice magit-mode-quit-window (around my-magit-mode-quit-window activate)
69   (letf (((symbol-function 'selected-window) (lambda ())))
70     ad-do-it))
71
72 (global-set-key "\C-cGS" 'magit-status)
73
74 (defun my-shell-command-to-string (cmd)
75   (shell-command cmd " *my-shell-command-to-string*")
76   (save-current-buffer
77     (set-buffer " *my-shell-command-to-string*")
78     (prog1
79         (buffer-string)
80       (kill-buffer " *my-shell-command-to-string*"))))
81
82 (defun git-repo-files ()
83   (let ((default-directory (magit-toplevel default-directory)))
84     (split-string (my-shell-command-to-string "git ls-files") "\n")))
85
86 (defun find-file-in-git-repo ()
87   (interactive)
88   (let ((repo (magit-toplevel default-directory))
89         (files (git-repo-files)))
90     (find-file
91      (concat repo
92              (ido-completing-read
93               "Find file in git repo: "
94               (remove-if (lambda (x) (string= "" x))
95               files))))))
96
97 (defun grep-in-git-repo (regexp &optional words-only)
98   (interactive "sGrep files in Git repo regexp: \nP")
99   (let ((default-directory (magit-toplevel default-directory)))
100     (if (not default-directory)
101         (error "not a Git directory"))
102     (grep (format "git ls-files -z | xargs -r0 grep -d skip -nH -E%s -- %s"
103                   (if words-only " -w" "") (shell-quote-argument regexp)))))
104
105 (setenv "GIT_PAGER" "cat")
106 (setenv "GIT_MAN_VIEWER" "woman")
107 (setenv "GIT_EDITOR" "emacsclient")
108
109 (defun find-file-maybe-git (&optional nogit)
110   (interactive "P")
111   (if (and (not nogit) (magit-toplevel default-directory))
112       (call-interactively 'find-file-in-git-repo)
113     (call-interactively 'ido-find-file)))
114
115 (global-set-key "\C-x\C-f" 'find-file-maybe-git)
116 (global-set-key "\C-cGG" 'grep-in-git-repo)
117
118 (defun git-files-find-symbol (symbol)
119   (interactive (list (read-string "Symbol: " (current-word))))
120   (let ((dir (magit-toplevel default-directory)))
121     (if (not dir) (error "No git repository"))
122     (let ((default-directory dir))
123       (grep (format "git ls-files -z | xargs -r0 grep -d skip -nwHF %s" symbol)))))
124
125 (defun git-files-find-class-decl (symbol)
126   (interactive (list (read-string "Symbol: " (current-word))))
127   (let ((dir (magit-toplevel default-directory)))
128     (if (not dir) (error "No git repository"))
129     (let ((default-directory dir))
130       (grep (format (concat "git ls-files -z"
131                             " | xargs -r0 grep -d skip -nwHF %s"
132                             " | grep -Ew '(class|struct|typedef|using)'"
133                             " | grep -vEw 'friend'")
134                     symbol)))))
135
136 (global-set-key "\C-cGF" 'git-files-find-symbol)
137 (global-set-key "\C-cGC" 'git-files-find-class-decl)
138
139 (defun dired-git-files ()
140   (interactive)
141   (let ((default-directory (magit-toplevel default-directory))\
142         (ls-lisp-use-insert-directory-program t)
143         files)
144     (setq files (delete-if '(lambda (file) (string= file ""))
145                            (split-string (shell-command-to-string "git ls-files") "\n")))
146     (dired (cons default-directory files))))
147
148 (global-set-key "\C-cGD" 'dired-git-files)
149
150 (defun dired-grep-git-files (regexp &optional words-only)
151   (interactive "sRegexp: \nP")
152   (let ((default-directory (magit-toplevel default-directory))
153         (cmd (format "git ls-files -z | xargs -r0 grep -d skip -l -E%s -- %s"
154                      (if words-only " -w" "") (shell-quote-argument regexp))))
155     (if (not default-directory)
156         (error "not in Git repository"))
157     (setq files (delete-if '(lambda (file) (string= file ""))
158                            (split-string (shell-command-to-string cmd)  "\n")))
159     (dired (cons default-directory files))))
160
161 (global-set-key "\C-cGH" 'dired-grep-git-files)
162
163 (defun magit-svn-fetch ()
164   (interactive)
165   (magit-run-git-async "svn" "fetch"))
166
167 (define-key magit-mode-map "Nf" 'magit-svn-fetch)
168
169 (defun magit-quit-window (&optional kill-buffer)
170   (interactive "P")
171   (quit-window kill-buffer))
172
173 (defun magit-diff-master-mergebase (&optional args files)
174   (interactive (magit-diff-arguments))
175   (magit-diff-working-tree
176    (magit-git-string "merge-base" "master" "HEAD") args files))
177
178 (magit-define-popup-action 'magit-diff-popup
179   ?m "Diff merge-base master" 'magit-diff-master-mergebase)
180
181 ; ignore whitespace
182 ; (setq magit-diff-options '("-w"))