2008-08-31 18:11:32 +02:00
|
|
|
;;; Magit -- control Git from Emacs.
|
2008-07-31 22:11:46 +02:00
|
|
|
|
2009-01-21 23:45:41 +01:00
|
|
|
;; Copyright (C) 2008, 2009 Marius Vollmer
|
2008-08-19 22:43:34 +02:00
|
|
|
;; Copyright (C) 2008 Linh Dang
|
2008-11-13 19:48:55 +01:00
|
|
|
;; Copyright (C) 2008 Alex Ott
|
|
|
|
;; Copyright (C) 2008 Marcin Bachry
|
2009-01-21 23:45:41 +01:00
|
|
|
;; Copyright (C) 2009 Alexey Voinov
|
2009-01-28 21:23:46 +01:00
|
|
|
;; Copyright (C) 2009 John Wiegley
|
2008-07-31 22:11:46 +02:00
|
|
|
;;
|
2008-08-06 01:41:05 +02:00
|
|
|
;; Magit is free software; you can redistribute it and/or modify it
|
2008-08-05 18:09:47 +02:00
|
|
|
;; under the terms of the GNU General Public License as published by
|
|
|
|
;; the Free Software Foundation; either version 3, or (at your option)
|
|
|
|
;; any later version.
|
2008-07-31 22:11:46 +02:00
|
|
|
;;
|
2008-08-06 01:41:05 +02:00
|
|
|
;; Magit is distributed in the hope that it will be useful, but WITHOUT
|
2008-08-05 18:09:47 +02:00
|
|
|
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
|
|
;; License for more details.
|
2008-07-31 22:11:46 +02:00
|
|
|
;;
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
2008-10-16 21:24:35 +02:00
|
|
|
;; along with Magit. If not, see <http://www.gnu.org/licenses/>.
|
2008-07-31 22:11:46 +02:00
|
|
|
|
2008-08-13 04:28:16 +02:00
|
|
|
;;; Commentary
|
2008-07-31 22:11:46 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
;; Invoking the magit-status function will show a buffer with the
|
2008-09-13 17:31:33 +02:00
|
|
|
;; status of the current git repository and its working tree. That
|
|
|
|
;; buffer offers key bindings for manipulating the status in simple
|
|
|
|
;; ways.
|
2008-07-31 22:11:46 +02:00
|
|
|
;;
|
|
|
|
;; The status buffer mainly shows the difference between the working
|
|
|
|
;; tree and the index, and the difference between the index and the
|
2008-08-04 01:05:02 +02:00
|
|
|
;; current HEAD. You can add individual hunks from the working tree
|
|
|
|
;; to the index, and you can commit the index.
|
2008-08-12 03:31:07 +02:00
|
|
|
;;
|
2008-08-12 03:41:14 +02:00
|
|
|
;; See the Magit User Manual for more information.
|
2008-08-01 13:37:54 +02:00
|
|
|
|
2008-08-03 20:41:24 +02:00
|
|
|
;;; TODO
|
|
|
|
|
2009-09-06 17:04:50 +02:00
|
|
|
;; For 0.8:
|
|
|
|
;;
|
|
|
|
;; - Fix display of unmerged files.
|
|
|
|
;; - Fix performance problems with large status buffers.
|
|
|
|
;; - Handle the case where remote and local branches have different names.
|
|
|
|
;;
|
|
|
|
;; Later:
|
|
|
|
;;
|
2009-03-08 13:41:52 +01:00
|
|
|
;; - Queuing of asynchronous commands.
|
2009-02-28 16:05:02 +01:00
|
|
|
;; - Good email integration.
|
2009-02-28 18:25:20 +01:00
|
|
|
;; - Showing tags.
|
2008-09-13 17:31:33 +02:00
|
|
|
;; - Visiting from staged hunks doesn't always work since the line
|
|
|
|
;; numbers don't refer to the working tree. Fix that somehow.
|
2009-06-07 20:42:20 +02:00
|
|
|
;; - Figure out how to discard staged changes for files that also have
|
|
|
|
;; unstaged changes.
|
2008-10-02 00:24:44 +02:00
|
|
|
;; - Get current defun from removed lines in a diff
|
2009-02-28 16:05:02 +01:00
|
|
|
;; - Amending commits other than HEAD.
|
2008-08-12 16:39:44 +02:00
|
|
|
;; - 'Subsetting', only looking at a subset of all files.
|
2008-08-03 20:41:24 +02:00
|
|
|
|
2008-08-13 05:14:53 +02:00
|
|
|
(require 'cl)
|
|
|
|
(require 'parse-time)
|
2008-09-01 00:10:07 +02:00
|
|
|
(require 'log-edit)
|
2008-09-28 01:17:31 +02:00
|
|
|
(require 'easymenu)
|
2008-10-12 02:06:40 +02:00
|
|
|
(require 'diff-mode)
|
2008-08-13 05:14:53 +02:00
|
|
|
|
2008-08-19 22:43:34 +02:00
|
|
|
(defgroup magit nil
|
|
|
|
"Controlling Git from Emacs."
|
|
|
|
:prefix "magit-"
|
|
|
|
:group 'tools)
|
|
|
|
|
2009-02-08 22:06:49 +01:00
|
|
|
(defcustom magit-git-executable "git"
|
|
|
|
"The name of the Git executable."
|
|
|
|
:group 'magit
|
|
|
|
:type 'string)
|
|
|
|
|
2009-03-01 20:35:44 +01:00
|
|
|
(defcustom magit-git-standard-options '("--no-pager")
|
|
|
|
"Standard options when running Git."
|
|
|
|
:group 'magit
|
|
|
|
:type '(repeat string))
|
|
|
|
|
2009-07-28 01:25:44 +02:00
|
|
|
(defcustom magit-repo-dirs nil
|
|
|
|
"Directories containing Git repositories.
|
|
|
|
Magit will look into these directories for Git repositories and offers them as choices for magit-status."
|
|
|
|
:group 'magit
|
|
|
|
:type '(repeat string))
|
|
|
|
|
|
|
|
(defcustom magit-repo-dirs-depth 3
|
|
|
|
"When looking for Git repositors below the directories in magit-repo-dirs, Magit will only descend this many levels deep."
|
|
|
|
:group 'magit
|
|
|
|
:type 'integer)
|
|
|
|
|
2009-01-18 23:56:12 +01:00
|
|
|
(defcustom magit-save-some-buffers t
|
|
|
|
"Non-nil means that \\[magit-status] will save modified buffers before running.
|
|
|
|
Setting this to t will ask which buffers to save, setting it to 'dontask will
|
|
|
|
save all modified buffers without asking."
|
|
|
|
:group 'magit
|
|
|
|
:type '(choice (const :tag "Never" nil)
|
|
|
|
(const :tag "Ask" t)
|
|
|
|
(const :tag "Save without asking" dontask)))
|
|
|
|
|
2009-02-20 00:17:37 +01:00
|
|
|
(defcustom magit-commit-all-when-nothing-staged 'ask
|
2009-02-28 18:16:31 +01:00
|
|
|
"Determines what \\[magit-log-edit] does when nothing is staged.
|
|
|
|
Setting this to nil will make it do nothing, setting it to t will arrange things so that the actual commit command will use the \"--all\" option, setting it to 'ask will first ask for confirmation whether to do this, and setting it to 'ask-stage will cause all changes to be staged, after a confirmation."
|
2009-02-20 00:17:37 +01:00
|
|
|
:group 'magit
|
|
|
|
:type '(choice (const :tag "No" nil)
|
|
|
|
(const :tag "Always" t)
|
2009-02-28 18:16:31 +01:00
|
|
|
(const :tag "Ask" ask)
|
|
|
|
(const :tag "Ask to stage everything" ask-stage)))
|
2009-02-20 00:17:37 +01:00
|
|
|
|
2008-12-17 11:23:20 +01:00
|
|
|
(defcustom magit-commit-signoff nil
|
|
|
|
"When performing git commit adds --signoff"
|
|
|
|
:group 'magit
|
|
|
|
:type 'boolean)
|
|
|
|
|
2009-02-04 01:47:47 +01:00
|
|
|
(defcustom magit-log-cutoff-length 100
|
|
|
|
"The maximum number of commits to show in the log and whazzup buffers"
|
|
|
|
:group 'magit
|
|
|
|
:type 'integer)
|
|
|
|
|
2009-02-14 23:58:46 +01:00
|
|
|
(defcustom magit-process-popup-time -1
|
|
|
|
"Popup the process buffer if a command takes longer than this many seconds."
|
|
|
|
:group 'magit
|
|
|
|
:type '(choice (const :tag "Never" -1)
|
|
|
|
(const :tag "Immediately" 0)
|
|
|
|
(integer :tag "After this many seconds")))
|
|
|
|
|
2009-02-22 03:54:13 +01:00
|
|
|
(defcustom magit-log-edit-confirm-cancellation nil
|
|
|
|
"Require acknowledgement before cancelling the log edit buffer."
|
|
|
|
:group 'magit
|
|
|
|
:type 'boolean)
|
2009-02-25 14:55:52 +01:00
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-header
|
2008-08-19 22:43:34 +02:00
|
|
|
'((t))
|
|
|
|
"Face for generic header lines.
|
|
|
|
|
|
|
|
Many Magit faces inherit from this one by default."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-section-title
|
|
|
|
'((t :weight bold :inherit magit-header))
|
2008-08-19 22:43:34 +02:00
|
|
|
"Face for section titles."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-branch
|
|
|
|
'((t :weight bold :inherit magit-header))
|
2008-08-19 22:43:34 +02:00
|
|
|
"Face for the current branch."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-diff-file-header
|
|
|
|
'((t :inherit magit-header))
|
2008-08-19 22:43:34 +02:00
|
|
|
"Face for diff file header lines."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-diff-hunk-header
|
|
|
|
'((t :slant italic :inherit magit-header))
|
2008-08-19 22:43:34 +02:00
|
|
|
"Face for diff hunk header lines."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-diff-add
|
2008-08-19 22:43:34 +02:00
|
|
|
'((((class color) (background light))
|
|
|
|
:foreground "blue1")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:foreground "white"))
|
|
|
|
"Face for lines in a diff that have been added."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-diff-none
|
2008-08-19 22:43:34 +02:00
|
|
|
'((t))
|
|
|
|
"Face for lines in a diff that are unchanged."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:55:42 +02:00
|
|
|
(defface magit-diff-del
|
2008-08-19 22:43:34 +02:00
|
|
|
'((((class color) (background light))
|
|
|
|
:foreground "red")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:foreground "OrangeRed"))
|
|
|
|
"Face for lines in a diff that have been deleted."
|
|
|
|
:group 'magit)
|
|
|
|
|
2009-11-02 11:24:21 +01:00
|
|
|
(defface magit-log-graph
|
|
|
|
'((((class color) (background light))
|
|
|
|
:foreground "grey11")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:foreground "grey30"))
|
|
|
|
"Face for the graph element of the log output."
|
|
|
|
:group 'magit)
|
|
|
|
|
|
|
|
(defface magit-log-sha1
|
|
|
|
'((((class color) (background light))
|
|
|
|
:foreground "firebrick")
|
|
|
|
(((class color) (background dark))
|
2009-11-08 16:53:58 +01:00
|
|
|
:foreground "tomato"))
|
2009-11-02 11:24:21 +01:00
|
|
|
"Face for the sha1 element of the log output."
|
|
|
|
:group 'magit)
|
|
|
|
|
|
|
|
(defface magit-log-message
|
|
|
|
'((t))
|
|
|
|
"Face for the message element of the log output."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-08-19 23:58:34 +02:00
|
|
|
(defface magit-item-highlight
|
2008-08-24 04:37:13 +02:00
|
|
|
'((((class color) (background light))
|
|
|
|
:background "gray95")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:background "dim gray"))
|
2008-08-19 23:58:34 +02:00
|
|
|
"Face for highlighting the current item."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-12-13 08:44:56 +01:00
|
|
|
(defface magit-item-mark
|
|
|
|
'((((class color) (background light))
|
|
|
|
:foreground "red")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:foreground "orange"))
|
|
|
|
"Face for highlighting marked item."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-10-26 18:59:56 +01:00
|
|
|
(defface magit-log-tag-label
|
2008-11-12 23:07:34 +01:00
|
|
|
'((((class color) (background light))
|
|
|
|
:background "LightGoldenRod")
|
|
|
|
(((class color) (background dark))
|
|
|
|
:background "DarkGoldenRod"))
|
2008-10-26 18:59:56 +01:00
|
|
|
"Face for git tag labels shown in log buffer."
|
|
|
|
:group 'magit)
|
|
|
|
|
2009-11-08 15:54:53 +01:00
|
|
|
(defface magit-log-head-label-remote
|
2008-11-12 23:07:34 +01:00
|
|
|
'((((class color) (background light))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 16:23:16 +01:00
|
|
|
:background "Grey85"
|
2009-11-08 15:54:53 +01:00
|
|
|
:foreground "OliveDrab4")
|
2008-11-12 23:07:34 +01:00
|
|
|
(((class color) (background dark))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 15:54:53 +01:00
|
|
|
:background "Grey11"
|
|
|
|
:foreground "DarkSeaGreen2"))
|
|
|
|
"Face for remote branch head labels shown in log buffer."
|
2008-10-26 18:59:56 +01:00
|
|
|
:group 'magit)
|
|
|
|
|
2009-11-08 15:54:53 +01:00
|
|
|
(defface magit-log-head-label-tags
|
|
|
|
'((((class color) (background light))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 16:23:16 +01:00
|
|
|
:background "Grey85"
|
|
|
|
:foreground "VioletRed1")
|
2009-11-08 15:54:53 +01:00
|
|
|
(((class color) (background dark))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 15:54:53 +01:00
|
|
|
:background "Grey13"
|
|
|
|
:foreground "khaki1"))
|
|
|
|
"Face for tag labels shown in log buffer."
|
2008-10-26 18:59:56 +01:00
|
|
|
:group 'magit)
|
|
|
|
|
2009-10-28 21:19:02 +01:00
|
|
|
(defvar magit-completing-read 'completing-read
|
|
|
|
"Function to be called when requesting input from the user.")
|
|
|
|
|
2010-03-10 22:38:04 +01:00
|
|
|
(defvar magit-omit-untracked-dir-contents nil
|
|
|
|
"When non-nil magit will only list an untracked directory, not
|
|
|
|
its contents.")
|
|
|
|
|
2009-11-08 15:54:53 +01:00
|
|
|
(defface magit-log-head-label-local
|
|
|
|
'((((class color) (background light))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 16:23:16 +01:00
|
|
|
:background "Grey85"
|
2009-11-08 15:54:53 +01:00
|
|
|
:foreground "LightSkyBlue4")
|
|
|
|
(((class color) (background dark))
|
2009-11-08 16:53:58 +01:00
|
|
|
:box t
|
2009-11-08 15:54:53 +01:00
|
|
|
:background "Grey13"
|
|
|
|
:foreground "LightSkyBlue1"))
|
|
|
|
"Face for local branch head labels shown in log buffer."
|
|
|
|
:group 'magit)
|
|
|
|
|
2008-10-26 22:58:08 +01:00
|
|
|
;;; Macros
|
|
|
|
|
|
|
|
(defmacro magit-with-refresh (&rest body)
|
|
|
|
(declare (indent 0))
|
|
|
|
`(magit-refresh-wrapper (lambda () ,@body)))
|
|
|
|
|
2008-08-01 13:37:54 +02:00
|
|
|
;;; Utilities
|
|
|
|
|
2008-10-12 02:06:40 +02:00
|
|
|
(defun magit-use-region-p ()
|
|
|
|
(if (fboundp 'use-region-p)
|
|
|
|
(use-region-p)
|
|
|
|
(and transient-mark-mode mark-active)))
|
|
|
|
|
2008-08-13 16:25:32 +02:00
|
|
|
(defun magit-goto-line (line)
|
2008-09-14 22:15:52 +02:00
|
|
|
;; Like goto-line but doesn't set the mark.
|
2008-08-13 16:25:32 +02:00
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(goto-char 1)
|
|
|
|
(forward-line (1- line))))
|
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defun magit-trim-line (str)
|
|
|
|
(if (string= str "")
|
|
|
|
nil
|
|
|
|
(if (equal (elt str (- (length str) 1)) ?\n)
|
|
|
|
(substring str 0 (- (length str) 1))
|
|
|
|
str)))
|
|
|
|
|
|
|
|
(defun magit-split-lines (str)
|
|
|
|
(if (string= str "")
|
|
|
|
nil
|
|
|
|
(let ((lines (nreverse (split-string str "\n"))))
|
|
|
|
(if (string= (car lines) "")
|
|
|
|
(setq lines (cdr lines)))
|
|
|
|
(nreverse lines))))
|
|
|
|
|
2009-09-12 21:36:10 +02:00
|
|
|
(defun magit-git-insert (args)
|
|
|
|
(apply #'process-file
|
|
|
|
magit-git-executable
|
|
|
|
nil (list t nil) nil
|
|
|
|
(append magit-git-standard-options args)))
|
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defun magit-git-output (args)
|
2009-02-22 08:10:32 +01:00
|
|
|
(with-output-to-string
|
|
|
|
(with-current-buffer
|
|
|
|
standard-output
|
2009-09-12 21:36:10 +02:00
|
|
|
(magit-git-insert args))))
|
2009-02-15 22:58:10 +01:00
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defun magit-git-string (&rest args)
|
|
|
|
(magit-trim-line (magit-git-output args)))
|
2009-02-15 22:58:10 +01:00
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defun magit-git-lines (&rest args)
|
|
|
|
(magit-split-lines (magit-git-output args)))
|
2009-02-15 22:58:10 +01:00
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defun magit-git-exit-code (&rest args)
|
2009-09-12 21:36:10 +02:00
|
|
|
(apply #'process-file magit-git-executable nil nil nil
|
|
|
|
(append magit-git-standard-options args)))
|
2008-08-30 23:28:58 +02:00
|
|
|
|
2008-08-06 03:13:40 +02:00
|
|
|
(defun magit-file-lines (file)
|
2009-03-01 19:57:24 +01:00
|
|
|
(when (file-exists-p file)
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents file)
|
|
|
|
(let ((rev (nreverse (split-string (buffer-string) "\n"))))
|
|
|
|
(nreverse (if (equal (car rev) "")
|
|
|
|
(cdr rev)
|
|
|
|
rev))))))
|
2008-08-06 01:21:29 +02:00
|
|
|
|
2009-03-08 13:41:52 +01:00
|
|
|
(defun magit-write-file-lines (file lines)
|
|
|
|
(with-temp-buffer
|
|
|
|
(dolist (l lines)
|
|
|
|
(insert l "\n"))
|
|
|
|
(write-file file)))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-concat-with-delim (delim seqs)
|
2008-08-03 20:33:25 +02:00
|
|
|
(cond ((null seqs)
|
|
|
|
nil)
|
|
|
|
((null (cdr seqs))
|
|
|
|
(car seqs))
|
|
|
|
(t
|
2008-08-06 01:41:05 +02:00
|
|
|
(concat (car seqs) delim (magit-concat-with-delim delim (cdr seqs))))))
|
2008-08-03 20:33:25 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-get (&rest keys)
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "config" (magit-concat-with-delim "." keys)))
|
2008-08-03 20:33:25 +02:00
|
|
|
|
2010-03-07 14:04:48 +01:00
|
|
|
(defun magit-get-all (&rest keys)
|
|
|
|
(magit-git-lines "config" "--get-all" (magit-concat-with-delim "." keys)))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-set (val &rest keys)
|
2008-08-04 01:05:02 +02:00
|
|
|
(if val
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "config" (magit-concat-with-delim "." keys) val)
|
|
|
|
(magit-git-string "config" "--unset" (magit-concat-with-delim "." keys))))
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2009-07-28 01:25:44 +02:00
|
|
|
(defun magit-remove-conflicts (alist)
|
|
|
|
(let ((dict (make-hash-table :test 'equal))
|
|
|
|
(result nil))
|
|
|
|
(dolist (a alist)
|
|
|
|
(puthash (car a) (cons (cdr a) (gethash (car a) dict))
|
|
|
|
dict))
|
|
|
|
(maphash (lambda (key value)
|
|
|
|
(if (= (length value) 1)
|
|
|
|
(push (cons key (car value)) result)
|
|
|
|
(let ((sub (magit-remove-conflicts
|
|
|
|
(mapcar (lambda (entry)
|
|
|
|
(let ((dir (directory-file-name
|
|
|
|
(subseq entry 0 (- (length key))))))
|
|
|
|
(cons (concat (file-name-nondirectory dir) "/" key)
|
|
|
|
entry)))
|
|
|
|
value))))
|
|
|
|
(setq result (append result sub)))))
|
|
|
|
dict)
|
|
|
|
result))
|
|
|
|
|
|
|
|
(defun magit-git-repo-p (dir)
|
|
|
|
(file-exists-p (expand-file-name ".git" dir)))
|
|
|
|
|
|
|
|
(defun magit-list-repos* (dir level)
|
|
|
|
(if (magit-git-repo-p dir)
|
|
|
|
(list dir)
|
|
|
|
(apply #'append
|
|
|
|
(mapcar (lambda (entry)
|
|
|
|
(unless (or (string= (substring entry -3) "/..")
|
|
|
|
(string= (substring entry -2) "/."))
|
|
|
|
(magit-list-repos* entry (+ level 1))))
|
|
|
|
(and (file-directory-p dir)
|
|
|
|
(< level magit-repo-dirs-depth)
|
|
|
|
(directory-files dir t nil t))))))
|
|
|
|
|
|
|
|
(defun magit-list-repos (dirs)
|
|
|
|
(magit-remove-conflicts
|
|
|
|
(apply #'append
|
|
|
|
(mapcar (lambda (dir)
|
|
|
|
(mapcar #'(lambda (repo)
|
|
|
|
(cons (file-name-nondirectory repo)
|
|
|
|
repo))
|
|
|
|
(magit-list-repos* dir 0)))
|
|
|
|
dirs))))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-get-top-dir (cwd)
|
2008-12-04 15:05:04 +01:00
|
|
|
(let ((cwd (expand-file-name cwd)))
|
|
|
|
(and (file-directory-p cwd)
|
2009-02-19 12:44:41 +01:00
|
|
|
(let* ((default-directory cwd)
|
2009-02-18 16:53:54 +01:00
|
|
|
(magit-dir
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "rev-parse" "--git-dir")))
|
2008-12-04 15:05:04 +01:00
|
|
|
(and magit-dir
|
|
|
|
(file-name-as-directory
|
|
|
|
(or (file-name-directory magit-dir) cwd)))))))
|
2008-08-01 13:37:54 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-get-ref (ref)
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "symbolic-ref" "-q" ref))
|
2008-08-03 20:33:25 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-get-current-branch ()
|
|
|
|
(let* ((head (magit-get-ref "HEAD"))
|
2008-08-03 20:33:25 +02:00
|
|
|
(pos (and head (string-match "^refs/heads/" head))))
|
|
|
|
(if pos
|
|
|
|
(substring head 11)
|
|
|
|
nil)))
|
|
|
|
|
2009-06-06 13:54:30 +02:00
|
|
|
(defun magit-ref-exists-p (ref)
|
2009-07-15 01:08:52 +02:00
|
|
|
(= (magit-git-exit-code "show-ref" "--verify" ref) 0))
|
2009-06-06 13:54:30 +02:00
|
|
|
|
2009-07-28 01:25:44 +02:00
|
|
|
(defun magit-read-top-dir (rawp)
|
|
|
|
(if (and (not rawp) magit-repo-dirs)
|
|
|
|
(let* ((repos (magit-list-repos magit-repo-dirs))
|
2009-10-28 21:19:02 +01:00
|
|
|
(reply (funcall magit-completing-read "Git repository: "
|
2009-07-28 01:25:44 +02:00
|
|
|
(magit-list-repos magit-repo-dirs))))
|
|
|
|
(file-name-as-directory
|
|
|
|
(cdr (assoc reply repos))))
|
|
|
|
(file-name-as-directory
|
|
|
|
(read-directory-name "Git repository: "
|
|
|
|
(or (magit-get-top-dir default-directory)
|
|
|
|
default-directory)))))
|
2008-08-01 13:37:54 +02:00
|
|
|
|
2008-08-06 03:18:41 +02:00
|
|
|
(defun magit-name-rev (rev)
|
2008-09-15 01:41:20 +02:00
|
|
|
(and rev
|
2009-07-15 01:08:52 +02:00
|
|
|
(let ((name (magit-git-string "name-rev" "--name-only" rev)))
|
2008-09-26 15:10:17 +02:00
|
|
|
(if (or (not name) (string= name "undefined"))
|
|
|
|
rev
|
|
|
|
name))))
|
2008-08-06 03:18:41 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-put-line-property (prop val)
|
2008-08-19 23:58:34 +02:00
|
|
|
(put-text-property (line-beginning-position) (line-beginning-position 2)
|
2008-08-04 01:05:02 +02:00
|
|
|
prop val))
|
|
|
|
|
2008-08-31 16:53:14 +02:00
|
|
|
(defun magit-format-commit (commit format)
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "log" "--max-count=1"
|
|
|
|
(concat "--pretty=format:" format)
|
|
|
|
commit))
|
2008-08-31 16:53:14 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-current-line ()
|
|
|
|
(buffer-substring-no-properties (line-beginning-position)
|
|
|
|
(line-end-position)))
|
|
|
|
|
2008-10-12 01:50:49 +02:00
|
|
|
(defun magit-insert-region (beg end buf)
|
|
|
|
(let ((text (buffer-substring-no-properties beg end)))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(insert text))))
|
|
|
|
|
|
|
|
(defun magit-insert-current-line (buf)
|
|
|
|
(let ((text (buffer-substring-no-properties
|
|
|
|
(line-beginning-position) (line-beginning-position 2))))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(insert text))))
|
|
|
|
|
2008-09-15 00:17:12 +02:00
|
|
|
(defun magit-file-uptodate-p (file)
|
2009-07-15 01:08:52 +02:00
|
|
|
(eq (magit-git-exit-code "diff" "--quiet" "--" file) 0))
|
2008-09-15 00:17:12 +02:00
|
|
|
|
|
|
|
(defun magit-anything-staged-p ()
|
2009-07-15 01:08:52 +02:00
|
|
|
(not (eq (magit-git-exit-code "diff" "--quiet" "--cached") 0)))
|
2008-09-15 00:17:12 +02:00
|
|
|
|
|
|
|
(defun magit-everything-clean-p ()
|
|
|
|
(and (not (magit-anything-staged-p))
|
2009-07-15 01:08:52 +02:00
|
|
|
(eq (magit-git-exit-code "diff" "--quiet") 0)))
|
2008-09-15 00:17:12 +02:00
|
|
|
|
|
|
|
(defun magit-commit-parents (commit)
|
2009-07-15 01:08:52 +02:00
|
|
|
(cdr (split-string (magit-git-string "rev-list" "-1" "--parents" commit))))
|
2008-09-15 00:17:12 +02:00
|
|
|
|
|
|
|
;; XXX - let the user choose the parent
|
|
|
|
|
|
|
|
(defun magit-choose-parent-id (commit op)
|
|
|
|
(let* ((parents (magit-commit-parents commit)))
|
|
|
|
(if (> (length parents) 1)
|
|
|
|
(error "Can't %s merge commits." op)
|
|
|
|
nil)))
|
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
;;; Revisions and ranges
|
|
|
|
|
2009-06-06 12:40:29 +02:00
|
|
|
(defun magit-list-interesting-refs ()
|
2009-06-06 13:26:18 +02:00
|
|
|
(let ((refs ()))
|
|
|
|
(dolist (line (magit-git-lines "show-ref"))
|
|
|
|
(if (string-match "[^ ]+ +\\(.*\\)" line)
|
|
|
|
(let ((ref (match-string 1 line)))
|
|
|
|
(cond ((string-match "refs/heads/\\(.*\\)" ref)
|
2009-06-06 13:52:05 +02:00
|
|
|
(let ((branch (match-string 1 ref)))
|
|
|
|
(push (cons branch branch) refs)))
|
2009-06-06 13:26:18 +02:00
|
|
|
((string-match "refs/tags/\\(.*\\)" ref)
|
|
|
|
(push (cons (format "%s (tag)" (match-string 1 ref)) ref)
|
|
|
|
refs))
|
2009-06-07 20:41:09 +02:00
|
|
|
((string-match "refs/remotes/\\([^/]+\\)/\\(.+\\)" ref)
|
2009-06-06 13:26:18 +02:00
|
|
|
(push (cons (format "%s (%s)"
|
|
|
|
(match-string 2 ref)
|
|
|
|
(match-string 1 ref))
|
|
|
|
ref)
|
|
|
|
refs))))))
|
|
|
|
refs))
|
2008-08-16 23:37:50 +02:00
|
|
|
|
|
|
|
(defun magit-read-rev (prompt &optional def)
|
2008-08-17 00:40:04 +02:00
|
|
|
(let* ((prompt (if def
|
2008-08-17 01:32:07 +02:00
|
|
|
(format "%s (default %s): " prompt def)
|
2008-08-17 00:40:04 +02:00
|
|
|
(format "%s: " prompt)))
|
2009-06-06 13:26:18 +02:00
|
|
|
(interesting-refs (magit-list-interesting-refs))
|
2009-10-28 21:19:02 +01:00
|
|
|
(reply (funcall magit-completing-read prompt interesting-refs
|
2009-06-06 13:26:18 +02:00
|
|
|
nil nil nil nil def))
|
|
|
|
(rev (or (cdr (assoc reply interesting-refs)) reply)))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if (string= rev "")
|
|
|
|
nil
|
|
|
|
rev)))
|
|
|
|
|
|
|
|
(defun magit-read-rev-range (op &optional def-beg def-end)
|
2009-02-05 21:23:57 +01:00
|
|
|
(let ((beg (magit-read-rev (format "%s start" op)
|
|
|
|
def-beg)))
|
|
|
|
(if (not beg)
|
|
|
|
nil
|
|
|
|
(let ((end (magit-read-rev (format "%s end" op) def-end)))
|
|
|
|
(cons beg end)))))
|
2008-08-16 23:37:50 +02:00
|
|
|
|
|
|
|
(defun magit-rev-to-git (rev)
|
|
|
|
(or rev
|
|
|
|
(error "No revision specified"))
|
|
|
|
(if (string= rev ".")
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-marked-commit)
|
2008-08-16 23:37:50 +02:00
|
|
|
rev))
|
|
|
|
|
|
|
|
(defun magit-rev-range-to-git (range)
|
|
|
|
(or range
|
|
|
|
(error "No revision range specified"))
|
|
|
|
(if (stringp range)
|
|
|
|
range
|
|
|
|
(if (cdr range)
|
|
|
|
(format "%s..%s"
|
|
|
|
(magit-rev-to-git (car range))
|
|
|
|
(magit-rev-to-git (cdr range)))
|
|
|
|
(format "%s" (magit-rev-to-git (car range))))))
|
|
|
|
|
|
|
|
(defun magit-rev-describe (rev)
|
|
|
|
(or rev
|
|
|
|
(error "No revision specified"))
|
|
|
|
(if (string= rev ".")
|
|
|
|
"mark"
|
|
|
|
(magit-name-rev rev)))
|
|
|
|
|
|
|
|
(defun magit-rev-range-describe (range things)
|
|
|
|
(or range
|
|
|
|
(error "No revision range specified"))
|
|
|
|
(if (stringp range)
|
|
|
|
(format "%s in %s" things range)
|
|
|
|
(if (cdr range)
|
2009-02-25 14:55:52 +01:00
|
|
|
(format "%s from %s to %s" things
|
2008-08-16 23:37:50 +02:00
|
|
|
(magit-rev-describe (car range))
|
|
|
|
(magit-rev-describe (cdr range)))
|
|
|
|
(format "%s at %s" things (magit-rev-describe (car range))))))
|
|
|
|
|
2008-08-17 00:37:48 +02:00
|
|
|
(defun magit-default-rev ()
|
2008-09-15 01:41:20 +02:00
|
|
|
(magit-name-rev (magit-commit-at-point t)))
|
2008-08-17 00:37:48 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
;;; Sections
|
2008-08-30 22:18:27 +02:00
|
|
|
|
2008-09-14 01:42:01 +02:00
|
|
|
;; A buffer in magit-mode is organized into hierarchical sections.
|
2008-09-07 01:00:26 +02:00
|
|
|
;; These sections are used for navigation and for hiding parts of the
|
|
|
|
;; buffer.
|
|
|
|
;;
|
|
|
|
;; Most sections also represent the objects that Magit works with,
|
|
|
|
;; such as files, diffs, hunks, commits, etc. The 'type' of a section
|
|
|
|
;; identifies what kind of object it represents (if any), and the
|
|
|
|
;; parent and grand-parent, etc provide the context.
|
|
|
|
|
|
|
|
(defstruct magit-section
|
2009-06-06 22:49:02 +02:00
|
|
|
parent title beginning end children hidden type info
|
|
|
|
needs-refresh-on-show)
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defvar magit-top-section nil)
|
|
|
|
(make-variable-buffer-local 'magit-top-section)
|
2008-09-07 02:15:37 +02:00
|
|
|
(put 'magit-top-section 'permanent-local t)
|
2008-09-07 01:15:45 +02:00
|
|
|
|
|
|
|
(defvar magit-old-top-section nil)
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2009-01-24 23:39:03 +01:00
|
|
|
(defvar magit-section-hidden-default nil)
|
|
|
|
|
|
|
|
(defun magit-new-section (title type)
|
|
|
|
(let* ((s (make-magit-section :parent magit-top-section
|
|
|
|
:title title
|
|
|
|
:type type
|
|
|
|
:hidden magit-section-hidden-default))
|
2008-09-07 02:15:37 +02:00
|
|
|
(old (and magit-old-top-section
|
|
|
|
(magit-find-section (magit-section-path s)
|
|
|
|
magit-old-top-section))))
|
2008-09-07 01:00:26 +02:00
|
|
|
(if magit-top-section
|
|
|
|
(setf (magit-section-children magit-top-section)
|
2008-09-30 22:47:16 +02:00
|
|
|
(cons s (magit-section-children magit-top-section)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(setq magit-top-section s))
|
2008-09-07 01:15:45 +02:00
|
|
|
(if old
|
|
|
|
(setf (magit-section-hidden s) (magit-section-hidden old)))
|
2008-09-07 01:00:26 +02:00
|
|
|
s))
|
|
|
|
|
|
|
|
(defun magit-cancel-section (section)
|
|
|
|
(delete-region (magit-section-beginning section)
|
|
|
|
(magit-section-end section))
|
|
|
|
(let ((parent (magit-section-parent section)))
|
|
|
|
(if parent
|
|
|
|
(setf (magit-section-children parent)
|
|
|
|
(delq section (magit-section-children parent)))
|
|
|
|
(setq magit-top-section nil))))
|
|
|
|
|
2009-01-24 23:39:03 +01:00
|
|
|
(defmacro magit-with-section (title type &rest body)
|
2008-09-07 01:00:26 +02:00
|
|
|
(declare (indent 2))
|
|
|
|
(let ((s (gensym)))
|
2009-01-24 23:39:03 +01:00
|
|
|
`(let* ((,s (magit-new-section ,title ,type))
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-top-section ,s))
|
|
|
|
(setf (magit-section-beginning ,s) (point))
|
|
|
|
,@body
|
|
|
|
(setf (magit-section-end ,s) (point))
|
2008-09-30 22:47:16 +02:00
|
|
|
(setf (magit-section-children ,s)
|
|
|
|
(nreverse (magit-section-children ,s)))
|
2008-09-07 01:00:26 +02:00
|
|
|
,s)))
|
|
|
|
|
|
|
|
(defun magit-set-section-info (info &optional section)
|
|
|
|
(setf (magit-section-info (or section magit-top-section)) info))
|
|
|
|
|
2009-06-06 22:49:02 +02:00
|
|
|
(defun magit-set-section-needs-refresh-on-show (flag &optional section)
|
|
|
|
(setf (magit-section-needs-refresh-on-show
|
|
|
|
(or section magit-top-section))
|
|
|
|
flag))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defmacro magit-create-buffer-sections (&rest body)
|
|
|
|
(declare (indent 0))
|
|
|
|
`(let ((inhibit-read-only t))
|
|
|
|
(erase-buffer)
|
2008-09-07 01:15:45 +02:00
|
|
|
(let ((magit-old-top-section magit-top-section))
|
|
|
|
(setq magit-top-section nil)
|
|
|
|
,@body
|
2008-09-07 22:42:11 +02:00
|
|
|
(when (null magit-top-section)
|
|
|
|
(magit-with-section 'top nil
|
|
|
|
(insert "(empty)\n")))
|
2008-09-07 01:15:45 +02:00
|
|
|
(magit-propertize-section magit-top-section)
|
|
|
|
(magit-section-set-hidden magit-top-section
|
|
|
|
(magit-section-hidden magit-top-section)))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defun magit-propertize-section (section)
|
|
|
|
(put-text-property (magit-section-beginning section)
|
|
|
|
(magit-section-end section)
|
|
|
|
'magit-section section)
|
|
|
|
(dolist (s (magit-section-children section))
|
|
|
|
(magit-propertize-section s)))
|
|
|
|
|
|
|
|
(defun magit-find-section (path top)
|
|
|
|
(if (null path)
|
|
|
|
top
|
|
|
|
(let ((sec (find-if (lambda (s) (equal (car path)
|
|
|
|
(magit-section-title s)))
|
|
|
|
(magit-section-children top))))
|
|
|
|
(if sec
|
|
|
|
(magit-find-section (cdr path) sec)
|
|
|
|
nil))))
|
|
|
|
|
|
|
|
(defun magit-section-path (section)
|
|
|
|
(if (not (magit-section-parent section))
|
|
|
|
'()
|
|
|
|
(append (magit-section-path (magit-section-parent section))
|
|
|
|
(list (magit-section-title section)))))
|
|
|
|
|
|
|
|
(defun magit-find-section-at (pos secs)
|
|
|
|
(while (and secs
|
|
|
|
(not (and (<= (magit-section-beginning (car secs)) pos)
|
|
|
|
(< pos (magit-section-end (car secs))))))
|
|
|
|
(setq secs (cdr secs)))
|
|
|
|
(if secs
|
|
|
|
(or (magit-find-section-at pos (magit-section-children (car secs)))
|
|
|
|
(car secs))
|
|
|
|
nil))
|
2008-08-21 01:19:58 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-find-section-after (pos secs)
|
|
|
|
(while (and secs
|
|
|
|
(not (> (magit-section-beginning (car secs)) pos)))
|
|
|
|
(setq secs (cdr secs)))
|
|
|
|
(car secs))
|
|
|
|
|
|
|
|
(defun magit-find-section-before (pos secs)
|
|
|
|
(let ((prev nil))
|
|
|
|
(while (and secs
|
|
|
|
(not (> (magit-section-beginning (car secs)) pos)))
|
|
|
|
(setq prev (car secs))
|
|
|
|
(setq secs (cdr secs)))
|
|
|
|
prev))
|
|
|
|
|
|
|
|
(defun magit-current-section ()
|
2008-09-07 02:24:14 +02:00
|
|
|
(or (get-text-property (point) 'magit-section)
|
|
|
|
magit-top-section))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2009-01-25 00:01:10 +01:00
|
|
|
(defun magit-insert-section (section-title-and-type
|
|
|
|
buffer-title washer cmd &rest args)
|
2008-09-07 01:00:26 +02:00
|
|
|
(let* ((body-beg nil)
|
2009-01-25 00:01:10 +01:00
|
|
|
(section-title (if (consp section-title-and-type)
|
|
|
|
(car section-title-and-type)
|
|
|
|
section-title-and-type))
|
|
|
|
(section-type (if (consp section-title-and-type)
|
|
|
|
(cdr section-title-and-type)
|
|
|
|
nil))
|
2008-09-07 01:00:26 +02:00
|
|
|
(section
|
2009-01-25 00:01:10 +01:00
|
|
|
(magit-with-section section-title section-type
|
|
|
|
(if buffer-title
|
|
|
|
(insert (propertize buffer-title 'face 'magit-section-title)
|
|
|
|
"\n"))
|
2008-09-07 01:00:26 +02:00
|
|
|
(setq body-beg (point))
|
2009-09-12 21:36:10 +02:00
|
|
|
(apply 'process-file cmd nil t nil (append magit-git-standard-options args))
|
2009-02-12 00:40:00 +01:00
|
|
|
(if (not (eq (char-before) ?\n))
|
2009-02-07 20:20:41 +01:00
|
|
|
(insert "\n"))
|
2008-09-07 01:00:26 +02:00
|
|
|
(if washer
|
|
|
|
(save-restriction
|
|
|
|
(narrow-to-region body-beg (point))
|
|
|
|
(goto-char (point-min))
|
|
|
|
(funcall washer)
|
|
|
|
(goto-char (point-max)))))))
|
|
|
|
(if (= body-beg (point))
|
|
|
|
(magit-cancel-section section)
|
2009-01-24 19:57:53 +01:00
|
|
|
(insert "\n"))
|
|
|
|
section))
|
|
|
|
|
2009-02-15 22:58:10 +01:00
|
|
|
(defun magit-git-section (section-title-and-type
|
|
|
|
buffer-title washer &rest args)
|
|
|
|
(apply #'magit-insert-section
|
|
|
|
section-title-and-type
|
|
|
|
buffer-title
|
|
|
|
washer
|
|
|
|
magit-git-executable
|
|
|
|
(append magit-git-standard-options args)))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-next-section (section)
|
|
|
|
(let ((parent (magit-section-parent section)))
|
|
|
|
(if parent
|
|
|
|
(let ((next (cadr (memq section
|
|
|
|
(magit-section-children parent)))))
|
|
|
|
(or next
|
|
|
|
(magit-next-section parent))))))
|
|
|
|
|
|
|
|
(defun magit-goto-next-section ()
|
|
|
|
(interactive)
|
|
|
|
(let* ((section (magit-current-section))
|
2008-09-08 22:19:12 +02:00
|
|
|
(next (or (and (not (magit-section-hidden section))
|
|
|
|
(magit-section-children section)
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-find-section-after (point)
|
|
|
|
(magit-section-children
|
|
|
|
section)))
|
|
|
|
(magit-next-section section))))
|
2009-02-25 14:55:52 +01:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(if next
|
2008-10-02 22:22:41 +02:00
|
|
|
(progn
|
|
|
|
(goto-char (magit-section-beginning next))
|
|
|
|
(if (memq magit-submode '(log reflog))
|
2009-02-19 04:17:40 +01:00
|
|
|
(magit-show-commit next))
|
2009-03-01 02:02:19 +01:00
|
|
|
(if (not (magit-section-hidden next))
|
|
|
|
(let ((offset (- (line-number-at-pos
|
|
|
|
(magit-section-beginning next))
|
|
|
|
(line-number-at-pos
|
|
|
|
(magit-section-end next)))))
|
|
|
|
(if (< offset (window-height))
|
|
|
|
(recenter offset)))))
|
2008-09-07 01:00:26 +02:00
|
|
|
(message "No next section"))))
|
|
|
|
|
|
|
|
(defun magit-prev-section (section)
|
|
|
|
(let ((parent (magit-section-parent section)))
|
|
|
|
(if parent
|
|
|
|
(let ((prev (cadr (memq section
|
|
|
|
(reverse (magit-section-children parent))))))
|
|
|
|
(cond (prev
|
2008-09-08 22:19:12 +02:00
|
|
|
(while (and (not (magit-section-hidden prev))
|
|
|
|
(magit-section-children prev))
|
2008-09-07 01:00:26 +02:00
|
|
|
(setq prev (car (reverse (magit-section-children prev)))))
|
|
|
|
prev)
|
|
|
|
(t
|
|
|
|
parent))))))
|
|
|
|
|
|
|
|
(defun magit-goto-previous-section ()
|
|
|
|
(interactive)
|
|
|
|
(let ((section (magit-current-section)))
|
|
|
|
(cond ((= (point) (magit-section-beginning section))
|
|
|
|
(let ((prev (magit-prev-section (magit-current-section))))
|
|
|
|
(if prev
|
2008-10-02 22:22:41 +02:00
|
|
|
(progn
|
|
|
|
(if (memq magit-submode '(log reflog))
|
|
|
|
(magit-show-commit (or prev section)))
|
|
|
|
(goto-char (magit-section-beginning prev)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(message "No previous section"))))
|
|
|
|
(t
|
|
|
|
(let ((prev (magit-find-section-before (point)
|
|
|
|
(magit-section-children
|
|
|
|
section))))
|
2008-10-02 22:22:41 +02:00
|
|
|
(if (memq magit-submode '(log reflog))
|
|
|
|
(magit-show-commit (or prev section)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(goto-char (magit-section-beginning (or prev section))))))))
|
|
|
|
|
|
|
|
(defun magit-goto-section (path)
|
|
|
|
(let ((sec (magit-find-section path magit-top-section)))
|
|
|
|
(if sec
|
|
|
|
(goto-char (magit-section-beginning sec))
|
|
|
|
(message "No such section"))))
|
|
|
|
|
|
|
|
(defun magit-for-all-sections (func &optional top)
|
|
|
|
(let ((section (or top magit-top-section)))
|
|
|
|
(when section
|
|
|
|
(funcall func section)
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(magit-for-all-sections func c)))))
|
|
|
|
|
|
|
|
(defun magit-section-set-hidden (section hidden)
|
|
|
|
(setf (magit-section-hidden section) hidden)
|
2009-06-06 22:49:02 +02:00
|
|
|
(if (and (not hidden)
|
|
|
|
(magit-section-needs-refresh-on-show section))
|
|
|
|
(magit-refresh)
|
|
|
|
(let ((inhibit-read-only t)
|
|
|
|
(beg (save-excursion
|
|
|
|
(goto-char (magit-section-beginning section))
|
|
|
|
(forward-line)
|
|
|
|
(point)))
|
|
|
|
(end (magit-section-end section)))
|
|
|
|
(put-text-property beg end 'invisible hidden))
|
|
|
|
(if (not hidden)
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(magit-section-set-hidden c (magit-section-hidden c))))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-10-12 01:15:01 +02:00
|
|
|
(defun magit-section-any-hidden (section)
|
|
|
|
(or (magit-section-hidden section)
|
|
|
|
(some #'magit-section-any-hidden (magit-section-children section))))
|
|
|
|
|
2008-09-07 02:19:52 +02:00
|
|
|
(defun magit-section-collapse (section)
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(setf (magit-section-hidden c) t))
|
|
|
|
(magit-section-set-hidden section nil))
|
|
|
|
|
|
|
|
(defun magit-section-expand (section)
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(setf (magit-section-hidden c) nil))
|
|
|
|
(magit-section-set-hidden section nil))
|
|
|
|
|
2008-10-12 01:15:01 +02:00
|
|
|
(defun magit-section-expand-all-aux (section)
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(setf (magit-section-hidden c) nil)
|
|
|
|
(magit-section-expand-all-aux c)))
|
|
|
|
|
|
|
|
(defun magit-section-expand-all (section)
|
|
|
|
(magit-section-expand-all-aux section)
|
|
|
|
(magit-section-set-hidden section nil))
|
|
|
|
|
2008-09-07 02:19:52 +02:00
|
|
|
(defun magit-section-hideshow (flag-or-func)
|
2008-09-07 01:00:26 +02:00
|
|
|
(let ((section (magit-current-section)))
|
|
|
|
(cond ((magit-section-parent section)
|
|
|
|
(goto-char (magit-section-beginning section))
|
2008-09-07 02:19:52 +02:00
|
|
|
(if (functionp flag-or-func)
|
|
|
|
(funcall flag-or-func section)
|
|
|
|
(magit-section-set-hidden section flag-or-func))))))
|
|
|
|
|
|
|
|
(defun magit-show-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow nil))
|
|
|
|
|
|
|
|
(defun magit-hide-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow t))
|
|
|
|
|
|
|
|
(defun magit-collapse-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow #'magit-section-collapse))
|
|
|
|
|
|
|
|
(defun magit-expand-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow #'magit-section-expand))
|
|
|
|
|
|
|
|
(defun magit-toggle-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow
|
|
|
|
(lambda (s)
|
2008-09-13 22:03:01 +02:00
|
|
|
(magit-section-set-hidden s (not (magit-section-hidden s))))))
|
2008-09-07 02:19:52 +02:00
|
|
|
|
2008-10-12 01:15:01 +02:00
|
|
|
(defun magit-expand-collapse-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow
|
|
|
|
(lambda (s)
|
|
|
|
(cond ((magit-section-any-hidden s)
|
|
|
|
(magit-section-expand-all s))
|
|
|
|
(t
|
|
|
|
(magit-section-collapse s))))))
|
2009-01-24 23:41:03 +01:00
|
|
|
|
2008-09-07 02:19:52 +02:00
|
|
|
(defun magit-cycle-section ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-hideshow
|
|
|
|
(lambda (s)
|
|
|
|
(cond ((magit-section-hidden s)
|
|
|
|
(magit-section-collapse s))
|
|
|
|
((notany #'magit-section-hidden (magit-section-children s))
|
|
|
|
(magit-section-set-hidden s t))
|
|
|
|
(t
|
|
|
|
(magit-section-expand s))))))
|
2008-08-21 01:19:58 +02:00
|
|
|
|
2009-02-08 00:35:56 +01:00
|
|
|
(defun magit-section-lineage (s)
|
|
|
|
(and s (cons s (magit-section-lineage (magit-section-parent s)))))
|
|
|
|
|
|
|
|
(defun magit-section-show-level (section level threshold path)
|
|
|
|
(magit-section-set-hidden section (>= level threshold))
|
|
|
|
(when (< level threshold)
|
|
|
|
(if path
|
|
|
|
(magit-section-show-level (car path) (1+ level) threshold (cdr path))
|
|
|
|
(dolist (c (magit-section-children section))
|
|
|
|
(magit-section-show-level c (1+ level) threshold nil)))))
|
|
|
|
|
|
|
|
(defun magit-show-level (level all)
|
2009-06-06 22:49:02 +02:00
|
|
|
(magit-with-refresh
|
|
|
|
(if all
|
|
|
|
(magit-section-show-level magit-top-section 0 level nil)
|
|
|
|
(let ((path (reverse (magit-section-lineage (magit-current-section)))))
|
|
|
|
(magit-section-show-level (car path) 0 level (cdr path))))))
|
2009-02-08 00:35:56 +01:00
|
|
|
|
2009-02-16 02:38:44 +01:00
|
|
|
(defun magit-show-only-files ()
|
|
|
|
(interactive)
|
|
|
|
(if (eq magit-submode 'status)
|
|
|
|
(call-interactively 'magit-show-level-2)
|
|
|
|
(call-interactively 'magit-show-level-1)))
|
|
|
|
|
|
|
|
(defun magit-show-only-files-all ()
|
|
|
|
(interactive)
|
|
|
|
(if (eq magit-submode 'status)
|
|
|
|
(call-interactively 'magit-show-level-2-all)
|
|
|
|
(call-interactively 'magit-show-level-1-all)))
|
|
|
|
|
2009-02-08 00:35:56 +01:00
|
|
|
(defmacro magit-define-level-shower-1 (level all)
|
|
|
|
(let ((fun (intern (format "magit-show-level-%s%s"
|
|
|
|
level (if all "-all" ""))))
|
|
|
|
(doc (format "Show sections on level %s." level)))
|
|
|
|
`(defun ,fun ()
|
|
|
|
,doc
|
|
|
|
(interactive)
|
|
|
|
(magit-show-level ,level ,all))))
|
|
|
|
|
|
|
|
(defmacro magit-define-level-shower (level)
|
|
|
|
`(progn
|
|
|
|
(magit-define-level-shower-1 ,level nil)
|
|
|
|
(magit-define-level-shower-1 ,level t)))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defmacro magit-define-section-jumper (sym title)
|
|
|
|
(let ((fun (intern (format "magit-jump-to-%s" sym)))
|
|
|
|
(doc (format "Jump to section `%s'." title)))
|
|
|
|
`(defun ,fun ()
|
2009-02-08 00:35:56 +01:00
|
|
|
,doc
|
2008-09-07 01:00:26 +02:00
|
|
|
(interactive)
|
|
|
|
(magit-goto-section '(,sym)))))
|
2008-08-21 01:19:58 +02:00
|
|
|
|
|
|
|
(defvar magit-highlight-overlay nil)
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defvar magit-highlighted-section nil)
|
2008-08-21 01:19:58 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-highlight-section ()
|
|
|
|
(let ((section (magit-current-section)))
|
|
|
|
(when (not (eq section magit-highlighted-section))
|
|
|
|
(setq magit-highlighted-section section)
|
2008-08-21 01:19:58 +02:00
|
|
|
(if (not magit-highlight-overlay)
|
|
|
|
(let ((ov (make-overlay 1 1)))
|
|
|
|
(overlay-put ov 'face 'magit-item-highlight)
|
|
|
|
(setq magit-highlight-overlay ov)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(if (and section (magit-section-type section))
|
2008-08-21 01:19:58 +02:00
|
|
|
(move-overlay magit-highlight-overlay
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-section-beginning section)
|
|
|
|
(magit-section-end section)
|
2008-08-21 01:19:58 +02:00
|
|
|
(current-buffer))
|
|
|
|
(delete-overlay magit-highlight-overlay)))))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-section-context-type (section)
|
|
|
|
(if (null section)
|
|
|
|
'()
|
|
|
|
(let ((c (or (magit-section-type section)
|
|
|
|
(if (symbolp (magit-section-title section))
|
|
|
|
(magit-section-title section)))))
|
|
|
|
(if c
|
|
|
|
(cons c (magit-section-context-type
|
|
|
|
(magit-section-parent section)))
|
|
|
|
'()))))
|
|
|
|
|
|
|
|
(defun magit-prefix-p (prefix list)
|
|
|
|
;;; Very schemish...
|
|
|
|
(or (null prefix)
|
|
|
|
(if (eq (car prefix) '*)
|
|
|
|
(or (magit-prefix-p (cdr prefix) list)
|
2008-09-07 19:23:52 +02:00
|
|
|
(and (not (null list))
|
|
|
|
(magit-prefix-p prefix (cdr list))))
|
2008-09-07 01:00:26 +02:00
|
|
|
(and (not (null list))
|
2009-02-15 23:29:45 +01:00
|
|
|
(equal (car prefix) (car list))
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-prefix-p (cdr prefix) (cdr list))))))
|
|
|
|
|
|
|
|
(defmacro magit-section-case (head &rest clauses)
|
2008-08-24 01:31:49 +02:00
|
|
|
(declare (indent 1))
|
2008-09-07 01:00:26 +02:00
|
|
|
(let ((section (car head))
|
2008-08-24 01:31:49 +02:00
|
|
|
(info (cadr head))
|
2008-09-07 01:00:26 +02:00
|
|
|
(type (gensym))
|
|
|
|
(context (gensym))
|
2008-08-24 01:31:49 +02:00
|
|
|
(opname (caddr head)))
|
2008-09-07 01:00:26 +02:00
|
|
|
`(let* ((,section (magit-current-section))
|
|
|
|
(,info (magit-section-info ,section))
|
|
|
|
(,type (magit-section-type ,section))
|
|
|
|
(,context (magit-section-context-type ,section)))
|
|
|
|
(cond ,@(mapcar (lambda (clause)
|
2009-02-11 09:07:44 +01:00
|
|
|
(if (eq (car clause) t)
|
|
|
|
clause
|
|
|
|
(let ((prefix (reverse (car clause)))
|
|
|
|
(body (cdr clause)))
|
|
|
|
`((magit-prefix-p ',prefix ,context)
|
|
|
|
,@body))))
|
2008-09-07 01:00:26 +02:00
|
|
|
clauses)
|
|
|
|
,@(if opname
|
|
|
|
`(((not ,type)
|
|
|
|
(error "Nothing to %s here." ,opname))
|
|
|
|
(t
|
|
|
|
(error "Can't %s a %s."
|
|
|
|
,opname
|
|
|
|
(or (get ,type 'magit-description)
|
|
|
|
,type)))))))))
|
2008-08-18 22:51:26 +02:00
|
|
|
|
2008-09-21 15:09:11 +02:00
|
|
|
(defmacro magit-section-action (head &rest clauses)
|
|
|
|
(declare (indent 1))
|
|
|
|
`(magit-with-refresh
|
|
|
|
(magit-section-case ,head ,@clauses)))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-wash-sequence (func)
|
|
|
|
(while (and (not (eobp))
|
|
|
|
(funcall func))))
|
2008-08-18 23:42:44 +02:00
|
|
|
|
2008-09-14 17:30:52 +02:00
|
|
|
;;; Running commands
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-08-13 16:27:31 +02:00
|
|
|
(defun magit-set-mode-line-process (str)
|
2008-09-13 21:51:54 +02:00
|
|
|
(let ((pr (if str (concat " " str) "")))
|
|
|
|
(save-excursion
|
|
|
|
(magit-for-all-buffers (lambda ()
|
|
|
|
(setq mode-line-process pr))))))
|
2008-08-13 16:27:31 +02:00
|
|
|
|
2009-02-15 23:29:45 +01:00
|
|
|
(defun magit-process-indicator-from-command (comps)
|
|
|
|
(if (magit-prefix-p (cons magit-git-executable magit-git-standard-options)
|
|
|
|
comps)
|
|
|
|
(setq comps (nthcdr (+ (length magit-git-standard-options) 1) comps)))
|
|
|
|
(cond ((or (null (cdr comps))
|
|
|
|
(not (member (car comps) '("remote"))))
|
|
|
|
(car comps))
|
2008-08-30 23:41:22 +02:00
|
|
|
(t
|
2009-02-15 23:29:45 +01:00
|
|
|
(concat (car comps) " " (cadr comps)))))
|
2008-08-30 23:41:22 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defvar magit-process nil)
|
2008-09-13 23:13:53 +02:00
|
|
|
(defvar magit-process-client-buffer nil)
|
2008-09-10 22:58:15 +02:00
|
|
|
|
2008-09-14 17:30:52 +02:00
|
|
|
(defun magit-run* (cmd-and-args
|
2008-10-12 01:50:49 +02:00
|
|
|
&optional logline noerase noerror nowait input)
|
2009-06-06 18:50:16 +02:00
|
|
|
(if (and magit-process
|
|
|
|
(get-buffer "*magit-process*"))
|
|
|
|
(error "Git is already running."))
|
2008-09-13 23:05:16 +02:00
|
|
|
(let ((cmd (car cmd-and-args))
|
|
|
|
(args (cdr cmd-and-args))
|
|
|
|
(dir default-directory)
|
2008-09-14 17:30:52 +02:00
|
|
|
(buf (get-buffer-create "*magit-process*"))
|
|
|
|
(successp nil))
|
2008-08-30 23:41:22 +02:00
|
|
|
(magit-set-mode-line-process
|
2009-02-15 23:29:45 +01:00
|
|
|
(magit-process-indicator-from-command cmd-and-args))
|
2008-09-13 23:13:53 +02:00
|
|
|
(setq magit-process-client-buffer (current-buffer))
|
2008-08-01 15:04:52 +02:00
|
|
|
(save-excursion
|
|
|
|
(set-buffer buf)
|
2009-02-07 22:03:28 +01:00
|
|
|
(setq buffer-read-only t)
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
(setq default-directory dir)
|
|
|
|
(if noerase
|
|
|
|
(goto-char (point-max))
|
|
|
|
(erase-buffer))
|
|
|
|
(insert "$ " (or logline
|
|
|
|
(magit-concat-with-delim " " cmd-and-args))
|
|
|
|
"\n")
|
|
|
|
(cond (nowait
|
|
|
|
(setq magit-process
|
2009-12-04 16:40:51 +01:00
|
|
|
(let ((process-connection-type nil))
|
|
|
|
(apply 'start-file-process cmd buf cmd args)))
|
2009-02-07 22:03:28 +01:00
|
|
|
(set-process-sentinel magit-process 'magit-process-sentinel)
|
|
|
|
(set-process-filter magit-process 'magit-process-filter)
|
2009-02-14 23:50:54 +01:00
|
|
|
(when input
|
|
|
|
(with-current-buffer input
|
|
|
|
(process-send-region magit-process
|
|
|
|
(point-min) (point-max)))
|
|
|
|
(process-send-eof magit-process)
|
|
|
|
(sit-for 0.1 t))
|
2009-02-14 23:58:46 +01:00
|
|
|
(cond ((= magit-process-popup-time 0)
|
|
|
|
(pop-to-buffer (process-buffer magit-process)))
|
|
|
|
((> magit-process-popup-time 0)
|
|
|
|
(run-with-timer
|
|
|
|
magit-process-popup-time nil
|
|
|
|
(function
|
|
|
|
(lambda (buf)
|
|
|
|
(with-current-buffer buf
|
2009-02-11 08:38:15 +01:00
|
|
|
(when magit-process
|
2009-02-16 02:08:57 +01:00
|
|
|
(display-buffer (process-buffer magit-process))
|
2009-02-11 08:38:15 +01:00
|
|
|
(goto-char (point-max))))))
|
2009-02-14 23:58:46 +01:00
|
|
|
(current-buffer))))
|
2009-02-07 22:03:28 +01:00
|
|
|
(setq successp t))
|
|
|
|
(input
|
|
|
|
(with-current-buffer input
|
|
|
|
(setq default-directory dir)
|
2010-03-04 06:07:18 +01:00
|
|
|
(setq magit-process
|
|
|
|
(apply 'start-file-process cmd buf cmd args))
|
|
|
|
(set-process-filter magit-process 'magit-process-filter)
|
|
|
|
(process-send-region magit-process
|
|
|
|
(point-min) (point-max))
|
|
|
|
(process-send-eof magit-process)
|
|
|
|
(while (equal (process-status magit-process) 'run)
|
|
|
|
(sit-for 0.1 t))
|
2009-02-07 22:03:28 +01:00
|
|
|
(setq successp
|
2010-03-04 06:07:18 +01:00
|
|
|
(equal (process-exit-status magit-process) 0))
|
|
|
|
(setq magit-process nil))
|
2009-02-07 22:03:28 +01:00
|
|
|
(magit-set-mode-line-process nil)
|
|
|
|
(magit-need-refresh magit-process-client-buffer))
|
|
|
|
(t
|
2008-10-12 01:50:49 +02:00
|
|
|
(setq successp
|
2009-09-12 21:43:19 +02:00
|
|
|
(equal (apply 'process-file cmd nil buf nil args) 0))
|
2009-02-07 22:03:28 +01:00
|
|
|
(magit-set-mode-line-process nil)
|
|
|
|
(magit-need-refresh magit-process-client-buffer))))
|
|
|
|
(or successp
|
|
|
|
noerror
|
|
|
|
(error "Git failed."))
|
|
|
|
successp)))
|
2008-09-14 17:30:52 +02:00
|
|
|
|
2008-09-02 22:18:23 +02:00
|
|
|
(defun magit-process-sentinel (process event)
|
2008-09-13 23:13:53 +02:00
|
|
|
(let ((msg (format "Git %s." (substring event 0 -1)))
|
|
|
|
(successp (string-match "^finished" event)))
|
|
|
|
(with-current-buffer (process-buffer process)
|
2009-02-07 22:03:28 +01:00
|
|
|
(let ((inhibit-read-only t))
|
2009-02-11 09:09:08 +01:00
|
|
|
(goto-char (point-max))
|
2009-02-07 22:03:28 +01:00
|
|
|
(insert msg "\n")
|
|
|
|
(message msg)))
|
2008-09-13 23:13:53 +02:00
|
|
|
(setq magit-process nil)
|
|
|
|
(magit-set-mode-line-process nil)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-refresh-buffer magit-process-client-buffer)))
|
2008-09-02 22:18:23 +02:00
|
|
|
|
2010-02-23 08:00:47 +01:00
|
|
|
(defun magit-password (proc string)
|
|
|
|
"Checks if git/ssh asks for a password and ask the user for it."
|
|
|
|
(when (string-match "^Enter passphrase for key '\\\(.*\\\)': $" string)
|
|
|
|
(process-send-string proc
|
|
|
|
(concat (read-passwd
|
|
|
|
(format "Password for '%s': " (match-string 1 string))
|
|
|
|
nil) "\n"))))
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-09-02 22:18:23 +02:00
|
|
|
(defun magit-process-filter (proc string)
|
2009-02-11 09:11:27 +01:00
|
|
|
(save-current-buffer
|
2008-09-02 22:18:23 +02:00
|
|
|
(set-buffer (process-buffer proc))
|
2009-02-07 22:03:28 +01:00
|
|
|
(let ((inhibit-read-only t))
|
2010-02-23 08:00:47 +01:00
|
|
|
(magit-password proc string)
|
2009-02-07 22:03:28 +01:00
|
|
|
(goto-char (process-mark proc))
|
|
|
|
;; Find last ^M in string. If one was found, ignore everything
|
|
|
|
;; before it and delete the current line.
|
|
|
|
(let ((ret-pos (position ?\r string :from-end t)))
|
|
|
|
(cond (ret-pos
|
|
|
|
(goto-char (line-beginning-position))
|
|
|
|
(delete-region (point) (line-end-position))
|
|
|
|
(insert (substring string (+ ret-pos 1))))
|
|
|
|
(t
|
|
|
|
(insert string))))
|
|
|
|
(set-marker (process-mark proc) (point)))))
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-08-30 21:34:40 +02:00
|
|
|
(defun magit-run (cmd &rest args)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-with-refresh
|
|
|
|
(magit-run* (cons cmd args))))
|
2008-08-30 21:34:40 +02:00
|
|
|
|
2009-02-08 22:06:49 +01:00
|
|
|
(defun magit-run-git (&rest args)
|
|
|
|
(magit-with-refresh
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-run* (append (cons magit-git-executable
|
2009-02-15 22:58:10 +01:00
|
|
|
magit-git-standard-options)
|
|
|
|
args))))
|
2009-02-08 22:06:49 +01:00
|
|
|
|
2008-10-12 01:50:49 +02:00
|
|
|
(defun magit-run-with-input (input cmd &rest args)
|
|
|
|
(magit-with-refresh
|
|
|
|
(magit-run* (cons cmd args) nil nil nil nil input)))
|
|
|
|
|
2009-02-15 22:58:10 +01:00
|
|
|
(defun magit-run-git-with-input (input &rest args)
|
|
|
|
(magit-with-refresh
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-run* (append (cons magit-git-executable
|
2009-07-15 01:08:52 +02:00
|
|
|
magit-git-standard-options)
|
2009-02-15 22:58:10 +01:00
|
|
|
args)
|
|
|
|
nil nil nil nil input)))
|
|
|
|
|
|
|
|
(defun magit-run-git-async (&rest args)
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-run* (append (cons magit-git-executable
|
2009-02-15 22:58:10 +01:00
|
|
|
magit-git-standard-options)
|
|
|
|
args)
|
|
|
|
nil nil nil t))
|
2008-08-06 01:21:29 +02:00
|
|
|
|
2009-02-14 23:50:54 +01:00
|
|
|
(defun magit-run-async-with-input (input cmd &rest args)
|
|
|
|
(magit-run* (cons cmd args) nil nil nil t input))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-display-process ()
|
2008-08-03 21:29:08 +02:00
|
|
|
(interactive)
|
2008-08-11 04:42:07 +02:00
|
|
|
(display-buffer "*magit-process*"))
|
2008-08-03 21:29:08 +02:00
|
|
|
|
2008-08-07 00:49:35 +02:00
|
|
|
;;; Mode
|
|
|
|
|
2008-08-18 23:42:44 +02:00
|
|
|
;; We define individual functions (instead of using lambda etc) so
|
|
|
|
;; that the online help can show something meaningful.
|
|
|
|
|
2008-10-12 01:10:06 +02:00
|
|
|
(magit-define-section-jumper untracked "Untracked files")
|
2008-08-18 23:42:44 +02:00
|
|
|
(magit-define-section-jumper unstaged "Unstaged changes")
|
|
|
|
(magit-define-section-jumper staged "Staged changes")
|
2008-09-07 19:24:41 +02:00
|
|
|
(magit-define-section-jumper unpushed "Unpushed commits")
|
2009-02-20 23:16:40 +01:00
|
|
|
(magit-define-section-jumper svn-unpushed "Unpushed commits (SVN)")
|
2008-08-18 23:42:44 +02:00
|
|
|
|
2009-02-08 00:35:56 +01:00
|
|
|
(magit-define-level-shower 1)
|
|
|
|
(magit-define-level-shower 2)
|
|
|
|
(magit-define-level-shower 3)
|
|
|
|
(magit-define-level-shower 4)
|
|
|
|
|
2008-08-12 23:33:31 +02:00
|
|
|
(defvar magit-mode-map
|
|
|
|
(let ((map (make-keymap)))
|
2008-08-18 22:51:26 +02:00
|
|
|
(suppress-keymap map t)
|
2008-09-07 01:00:26 +02:00
|
|
|
(define-key map (kbd "n") 'magit-goto-next-section)
|
|
|
|
(define-key map (kbd "p") 'magit-goto-previous-section)
|
2008-10-12 01:15:01 +02:00
|
|
|
(define-key map (kbd "TAB") 'magit-toggle-section)
|
|
|
|
(define-key map (kbd "<backtab>") 'magit-expand-collapse-section)
|
2009-02-08 00:35:56 +01:00
|
|
|
(define-key map (kbd "1") 'magit-show-level-1)
|
|
|
|
(define-key map (kbd "2") 'magit-show-level-2)
|
|
|
|
(define-key map (kbd "3") 'magit-show-level-3)
|
|
|
|
(define-key map (kbd "4") 'magit-show-level-4)
|
|
|
|
(define-key map (kbd "M-1") 'magit-show-level-1-all)
|
|
|
|
(define-key map (kbd "M-2") 'magit-show-level-2-all)
|
|
|
|
(define-key map (kbd "M-3") 'magit-show-level-3-all)
|
|
|
|
(define-key map (kbd "M-4") 'magit-show-level-4-all)
|
2009-02-16 02:38:44 +01:00
|
|
|
(define-key map (kbd "M-h") 'magit-show-only-files)
|
|
|
|
(define-key map (kbd "M-H") 'magit-show-only-files-all)
|
2009-02-11 09:15:45 +01:00
|
|
|
(define-key map (kbd "M-s") 'magit-show-level-4)
|
|
|
|
(define-key map (kbd "M-S") 'magit-show-level-4-all)
|
2008-09-13 21:51:54 +02:00
|
|
|
(define-key map (kbd "g") 'magit-refresh)
|
|
|
|
(define-key map (kbd "G") 'magit-refresh-all)
|
2008-08-21 01:19:58 +02:00
|
|
|
(define-key map (kbd "s") 'magit-stage-item)
|
2008-08-12 23:33:31 +02:00
|
|
|
(define-key map (kbd "S") 'magit-stage-all)
|
2008-08-21 01:19:58 +02:00
|
|
|
(define-key map (kbd "u") 'magit-unstage-item)
|
2008-08-20 23:19:15 +02:00
|
|
|
(define-key map (kbd "U") 'magit-unstage-all)
|
2008-08-21 01:19:58 +02:00
|
|
|
(define-key map (kbd "i") 'magit-ignore-item)
|
2008-10-12 01:10:06 +02:00
|
|
|
(define-key map (kbd "I") 'magit-ignore-item-locally)
|
2008-08-21 01:19:58 +02:00
|
|
|
(define-key map (kbd "?") 'magit-describe-item)
|
|
|
|
(define-key map (kbd ".") 'magit-mark-item)
|
2008-08-14 00:50:50 +02:00
|
|
|
(define-key map (kbd "=") 'magit-diff-with-mark)
|
2009-02-12 12:53:18 +01:00
|
|
|
(define-key map (kbd "-") 'magit-diff-smaller-hunks)
|
|
|
|
(define-key map (kbd "+") 'magit-diff-larger-hunks)
|
|
|
|
(define-key map (kbd "0") 'magit-diff-default-hunks)
|
2009-02-04 01:31:55 +01:00
|
|
|
(define-key map (kbd "l") 'magit-log)
|
|
|
|
(define-key map (kbd "L") 'magit-log-long)
|
2008-08-31 17:47:26 +02:00
|
|
|
(define-key map (kbd "h") 'magit-reflog-head)
|
|
|
|
(define-key map (kbd "H") 'magit-reflog)
|
2008-08-17 01:35:05 +02:00
|
|
|
(define-key map (kbd "d") 'magit-diff-working-tree)
|
2008-08-16 23:37:50 +02:00
|
|
|
(define-key map (kbd "D") 'magit-diff)
|
2008-08-24 04:28:38 +02:00
|
|
|
(define-key map (kbd "a") 'magit-apply-item)
|
2008-09-15 00:17:12 +02:00
|
|
|
(define-key map (kbd "A") 'magit-cherry-pick-item)
|
2008-08-24 04:28:38 +02:00
|
|
|
(define-key map (kbd "v") 'magit-revert-item)
|
2008-08-16 23:37:50 +02:00
|
|
|
(define-key map (kbd "x") 'magit-reset-head)
|
|
|
|
(define-key map (kbd "X") 'magit-reset-working-tree)
|
2008-08-21 01:41:43 +02:00
|
|
|
(define-key map (kbd "k") 'magit-discard-item)
|
2009-03-06 02:49:30 +01:00
|
|
|
(define-key map (kbd "!") 'magit-shell-command)
|
2008-08-21 01:19:58 +02:00
|
|
|
(define-key map (kbd "RET") 'magit-visit-item)
|
2008-08-24 02:01:29 +02:00
|
|
|
(define-key map (kbd "SPC") 'magit-show-item-or-scroll-up)
|
|
|
|
(define-key map (kbd "DEL") 'magit-show-item-or-scroll-down)
|
2008-10-26 18:47:23 +01:00
|
|
|
(define-key map (kbd "C-w") 'magit-copy-item-as-kill)
|
2008-08-16 23:37:50 +02:00
|
|
|
(define-key map (kbd "b") 'magit-checkout)
|
2008-08-12 23:33:31 +02:00
|
|
|
(define-key map (kbd "B") 'magit-create-branch)
|
|
|
|
(define-key map (kbd "m") 'magit-manual-merge)
|
|
|
|
(define-key map (kbd "M") 'magit-automatic-merge)
|
2009-02-25 14:55:52 +01:00
|
|
|
(define-key map (kbd "e") 'magit-interactive-resolve-item)
|
2008-11-11 19:09:38 +01:00
|
|
|
(define-key map (kbd "N r") 'magit-svn-rebase)
|
|
|
|
(define-key map (kbd "N c") 'magit-svn-dcommit)
|
2008-08-13 04:28:16 +02:00
|
|
|
(define-key map (kbd "R") 'magit-rebase-step)
|
2008-09-08 23:39:21 +02:00
|
|
|
(define-key map (kbd "r s") 'magit-rewrite-start)
|
|
|
|
(define-key map (kbd "r t") 'magit-rewrite-stop)
|
|
|
|
(define-key map (kbd "r a") 'magit-rewrite-abort)
|
|
|
|
(define-key map (kbd "r f") 'magit-rewrite-finish)
|
2008-09-10 22:57:06 +02:00
|
|
|
(define-key map (kbd "r *") 'magit-rewrite-set-unused)
|
|
|
|
(define-key map (kbd "r .") 'magit-rewrite-set-used)
|
2008-08-12 23:33:31 +02:00
|
|
|
(define-key map (kbd "P") 'magit-push)
|
2008-08-20 23:18:04 +02:00
|
|
|
(define-key map (kbd "f") 'magit-remote-update)
|
|
|
|
(define-key map (kbd "F") 'magit-pull)
|
2008-08-12 23:33:31 +02:00
|
|
|
(define-key map (kbd "c") 'magit-log-edit)
|
|
|
|
(define-key map (kbd "C") 'magit-add-log)
|
2008-11-06 22:46:29 +01:00
|
|
|
(define-key map (kbd "t") 'magit-tag)
|
|
|
|
(define-key map (kbd "T") 'magit-annotated-tag)
|
2008-11-09 23:06:13 +01:00
|
|
|
(define-key map (kbd "z") 'magit-stash)
|
2009-02-11 08:37:08 +01:00
|
|
|
(define-key map (kbd "Z") 'magit-stash-snapshot)
|
2009-01-24 19:57:53 +01:00
|
|
|
(define-key map (kbd "w") 'magit-wazzup)
|
2008-08-19 01:06:08 +02:00
|
|
|
(define-key map (kbd "$") 'magit-display-process)
|
2009-01-27 22:08:12 +01:00
|
|
|
(define-key map (kbd "E") 'magit-interactive-rebase)
|
2009-01-27 22:46:35 +01:00
|
|
|
(define-key map (kbd "V") 'magit-show-branches)
|
2008-08-20 23:29:50 +02:00
|
|
|
(define-key map (kbd "q") 'quit-window)
|
2008-08-12 23:33:31 +02:00
|
|
|
map))
|
2008-08-07 00:49:35 +02:00
|
|
|
|
2008-09-28 01:17:31 +02:00
|
|
|
(easy-menu-define magit-mode-menu magit-mode-map
|
|
|
|
"Magit menu"
|
|
|
|
'("Magit"
|
|
|
|
["Refresh" magit-refresh t]
|
|
|
|
["Refresh all" magit-refresh-all t]
|
|
|
|
"---"
|
|
|
|
["Stage" magit-stage-item t]
|
|
|
|
["Stage all" magit-stage-all t]
|
|
|
|
["Unstage" magit-unstage-item t]
|
|
|
|
["Unstage all" magit-unstage-all t]
|
|
|
|
["Commit" magit-log-edit t]
|
|
|
|
["Add log entry" magit-add-log t]
|
2008-11-06 22:46:29 +01:00
|
|
|
["Tag" magit-tag t]
|
|
|
|
["Annotated tag" magit-annotated-tag t]
|
2008-09-28 01:17:31 +02:00
|
|
|
"---"
|
|
|
|
["Diff working tree" magit-diff-working-tree t]
|
|
|
|
["Diff" magit-diff t]
|
|
|
|
["Log" magit-log t]
|
2009-02-04 01:31:55 +01:00
|
|
|
["Long Log" magit-log-long t]
|
2008-09-28 01:17:31 +02:00
|
|
|
["Reflog head" magit-reflog-head t]
|
|
|
|
["Reflog" magit-reflog t]
|
|
|
|
"---"
|
|
|
|
["Cherry pick" magit-cherry-pick-item t]
|
|
|
|
["Apply" magit-apply-item t]
|
|
|
|
["Revert" magit-revert-item t]
|
|
|
|
"---"
|
|
|
|
["Ignore" magit-ignore-item t]
|
2008-10-12 01:10:06 +02:00
|
|
|
["Ignore locally" magit-ignore-item-locally t]
|
2008-09-28 01:17:31 +02:00
|
|
|
["Discard" magit-discard-item t]
|
|
|
|
["Reset head" magit-reset-head t]
|
|
|
|
["Reset working tree" magit-reset-working-tree t]
|
2008-11-09 23:06:13 +01:00
|
|
|
["Stash" magit-stash t]
|
2009-02-11 08:37:08 +01:00
|
|
|
["Snapshot" magit-stash-snapshot t]
|
2008-09-28 01:17:31 +02:00
|
|
|
"---"
|
|
|
|
["Switch branch" magit-checkout t]
|
|
|
|
["Create branch" magit-create-branch t]
|
|
|
|
["Merge" magit-automatic-merge t]
|
|
|
|
["Merge (no commit)" magit-manual-merge t]
|
2009-02-25 14:55:52 +01:00
|
|
|
["Interactive resolve" magit-interactive-resolve-item t]
|
2008-09-28 01:17:31 +02:00
|
|
|
["Rebase" magit-rebase-step t]
|
2009-01-24 23:41:03 +01:00
|
|
|
("Git SVN"
|
|
|
|
["Rebase" magit-svn-rebase (magit-svn-enabled)]
|
|
|
|
["Commit" magit-svn-dcommit (magit-svn-enabled)]
|
|
|
|
)
|
2008-09-28 01:17:31 +02:00
|
|
|
("Rewrite"
|
|
|
|
["Start" magit-rewrite-start t]
|
|
|
|
["Stop" magit-rewrite-stop t]
|
|
|
|
["Finish" magit-rewrite-finish t]
|
|
|
|
["Abort" magit-rewrite-abort t]
|
|
|
|
["Set used" magit-rewrite-set-used t]
|
|
|
|
["Set unused" magit-rewrite-set-unused t])
|
|
|
|
"---"
|
|
|
|
["Push" magit-push t]
|
|
|
|
["Pull" magit-pull t]
|
|
|
|
["Remote update" magit-remote-update t]
|
|
|
|
"---"
|
|
|
|
["Display Git output" magit-display-process t]
|
|
|
|
["Quit Magit" quit-window t]))
|
|
|
|
|
2008-08-07 02:02:45 +02:00
|
|
|
(defvar magit-mode-hook nil)
|
|
|
|
|
|
|
|
(put 'magit-mode 'mode-class 'special)
|
|
|
|
|
2008-08-17 01:27:00 +02:00
|
|
|
(defvar magit-submode nil)
|
|
|
|
(make-variable-buffer-local 'magit-submode)
|
|
|
|
(put 'magit-submode 'permanent-local t)
|
2008-08-13 05:14:53 +02:00
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defvar magit-refresh-function nil)
|
|
|
|
(make-variable-buffer-local 'magit-refresh-function)
|
|
|
|
(put 'magit-refresh-function 'permanent-local t)
|
|
|
|
|
|
|
|
(defvar magit-refresh-args nil)
|
|
|
|
(make-variable-buffer-local 'magit-refresh-args)
|
|
|
|
(put 'magit-refresh-args 'permanent-local t)
|
|
|
|
|
2009-01-24 19:45:34 +01:00
|
|
|
(defvar last-point)
|
|
|
|
|
|
|
|
(defun magit-remember-point ()
|
|
|
|
(setq last-point (point)))
|
|
|
|
|
|
|
|
(defun magit-invisible-region-end (pos)
|
|
|
|
(while (and (not (= pos (point-max))) (invisible-p pos))
|
|
|
|
(setq pos (next-char-property-change pos)))
|
|
|
|
pos)
|
|
|
|
|
|
|
|
(defun magit-invisible-region-start (pos)
|
|
|
|
(while (and (not (= pos (point-min))) (invisible-p pos))
|
|
|
|
(setq pos (1- (previous-char-property-change pos))))
|
|
|
|
pos)
|
|
|
|
|
2009-01-18 23:24:11 +01:00
|
|
|
(defun magit-correct-point-after-command ()
|
2009-01-24 19:45:34 +01:00
|
|
|
;; Emacs often leaves point in invisible regions, it seems. To fix
|
|
|
|
;; this, we move point ourselves and never let Emacs do its own
|
|
|
|
;; adjustements.
|
|
|
|
;;
|
|
|
|
;; When point has to be moved out of an invisible region, it can be
|
|
|
|
;; moved to its end or its beginning. We usually move it to its
|
|
|
|
;; end, except when that would move point back to where it was
|
|
|
|
;; before the last command.
|
|
|
|
;;
|
|
|
|
(if (invisible-p (point))
|
|
|
|
(let ((end (magit-invisible-region-end (point))))
|
|
|
|
(goto-char (if (= end last-point)
|
|
|
|
(magit-invisible-region-start (point))
|
|
|
|
end))))
|
|
|
|
(setq disable-point-adjustment t))
|
2009-01-18 23:24:11 +01:00
|
|
|
|
|
|
|
(defun magit-post-command-hook ()
|
|
|
|
(magit-correct-point-after-command)
|
|
|
|
(magit-highlight-section))
|
|
|
|
|
2008-08-07 00:49:35 +02:00
|
|
|
(defun magit-mode ()
|
|
|
|
"Review the status of a git repository and act on it.
|
2008-08-18 22:13:16 +02:00
|
|
|
|
|
|
|
Please see the manual for a complete description of Magit.
|
2008-08-07 02:02:45 +02:00
|
|
|
|
|
|
|
\\{magit-mode-map}"
|
2008-08-07 00:49:35 +02:00
|
|
|
(kill-all-local-variables)
|
2009-01-07 23:21:38 +01:00
|
|
|
(buffer-disable-undo)
|
2008-08-07 00:49:35 +02:00
|
|
|
(setq buffer-read-only t)
|
2009-06-06 22:49:56 +02:00
|
|
|
(make-local-variable 'line-move-visual)
|
2008-08-07 00:49:35 +02:00
|
|
|
(setq major-mode 'magit-mode
|
2008-08-13 16:27:31 +02:00
|
|
|
mode-name "Magit"
|
2008-08-16 20:52:33 +02:00
|
|
|
mode-line-process ""
|
2009-01-18 23:24:11 +01:00
|
|
|
truncate-lines t
|
|
|
|
line-move-visual nil)
|
2009-01-24 19:45:34 +01:00
|
|
|
(add-hook 'pre-command-hook #'magit-remember-point nil t)
|
|
|
|
(add-hook 'post-command-hook #'magit-post-command-hook t t)
|
2008-08-07 02:02:45 +02:00
|
|
|
(use-local-map magit-mode-map)
|
|
|
|
(run-mode-hooks 'magit-mode-hook))
|
2008-08-03 21:10:00 +02:00
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-mode-init (dir submode refresh-func &rest refresh-args)
|
2008-08-17 01:27:00 +02:00
|
|
|
(setq default-directory dir
|
2008-09-13 21:51:54 +02:00
|
|
|
magit-submode submode
|
|
|
|
magit-refresh-function refresh-func
|
|
|
|
magit-refresh-args refresh-args)
|
|
|
|
(magit-mode)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-refresh-buffer))
|
2008-08-17 01:27:00 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-find-buffer (submode &optional dir)
|
|
|
|
(let ((topdir (magit-get-top-dir (or dir default-directory))))
|
|
|
|
(dolist (buf (buffer-list))
|
|
|
|
(if (save-excursion
|
|
|
|
(set-buffer buf)
|
2009-02-09 01:51:57 +01:00
|
|
|
(and default-directory
|
|
|
|
(equal (expand-file-name default-directory) topdir)
|
2008-09-07 01:00:26 +02:00
|
|
|
(eq major-mode 'magit-mode)
|
|
|
|
(eq magit-submode submode)))
|
|
|
|
(return buf)))))
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-find-status-buffer (&optional dir)
|
|
|
|
(magit-find-buffer 'status dir))
|
2008-09-02 00:36:06 +02:00
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-for-all-buffers (func &optional dir)
|
2008-09-07 01:00:26 +02:00
|
|
|
(dolist (buf (buffer-list))
|
|
|
|
(save-excursion
|
|
|
|
(set-buffer buf)
|
2008-09-13 21:51:54 +02:00
|
|
|
(if (and (eq major-mode 'magit-mode)
|
|
|
|
(or (null dir)
|
|
|
|
(equal default-directory dir)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(funcall func)))))
|
|
|
|
|
2008-09-21 15:09:11 +02:00
|
|
|
(defun magit-refresh-buffer (&optional buffer)
|
2008-09-13 23:05:16 +02:00
|
|
|
(with-current-buffer (or buffer (current-buffer))
|
2008-09-14 22:15:52 +02:00
|
|
|
(let* ((old-line (line-number-at-pos))
|
|
|
|
(old-section (magit-current-section))
|
|
|
|
(old-path (and old-section
|
|
|
|
(magit-section-path (magit-current-section))))
|
|
|
|
(section-line (and old-section
|
|
|
|
(count-lines
|
|
|
|
(magit-section-beginning old-section)
|
|
|
|
(point)))))
|
|
|
|
(if magit-refresh-function
|
|
|
|
(apply magit-refresh-function
|
|
|
|
magit-refresh-args))
|
|
|
|
(magit-refresh-marked-commits-in-buffer)
|
|
|
|
(let ((s (and old-path (magit-find-section old-path magit-top-section))))
|
|
|
|
(cond (s
|
|
|
|
(goto-char (magit-section-beginning s))
|
|
|
|
(forward-line section-line))
|
|
|
|
(t
|
|
|
|
(magit-goto-line old-line)))
|
|
|
|
(dolist (w (get-buffer-window-list (current-buffer)))
|
|
|
|
(set-window-point w (point)))
|
|
|
|
(magit-highlight-section)))))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2009-07-27 23:21:34 +02:00
|
|
|
(defun magit-string-has-prefix-p (string prefix)
|
|
|
|
(eq (compare-strings string nil (length prefix) prefix nil nil) t))
|
|
|
|
|
|
|
|
(defun magit-revert-buffers (dir)
|
2008-10-02 22:11:44 +02:00
|
|
|
(dolist (buffer (buffer-list))
|
|
|
|
(when (and buffer
|
2009-07-27 23:21:34 +02:00
|
|
|
(buffer-file-name buffer)
|
|
|
|
(magit-string-has-prefix-p (buffer-file-name buffer) dir)
|
2008-10-02 22:11:44 +02:00
|
|
|
(not (verify-visited-file-modtime buffer))
|
|
|
|
(not (buffer-modified-p buffer)))
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(ignore-errors
|
2009-07-27 23:05:07 +02:00
|
|
|
(revert-buffer t t nil))))))
|
2008-09-21 15:09:11 +02:00
|
|
|
|
|
|
|
(defvar magit-refresh-needing-buffers nil)
|
|
|
|
(defvar magit-refresh-pending nil)
|
|
|
|
|
|
|
|
(defun magit-refresh-wrapper (func)
|
|
|
|
(if magit-refresh-pending
|
|
|
|
(funcall func)
|
2009-07-27 23:21:34 +02:00
|
|
|
(let* ((dir default-directory)
|
|
|
|
(status-buffer (magit-find-buffer 'status dir))
|
|
|
|
(magit-refresh-needing-buffers nil)
|
|
|
|
(magit-refresh-pending t))
|
2008-09-21 15:09:11 +02:00
|
|
|
(unwind-protect
|
|
|
|
(funcall func)
|
2008-10-02 00:18:25 +02:00
|
|
|
(when magit-refresh-needing-buffers
|
2009-07-27 23:21:34 +02:00
|
|
|
(magit-revert-buffers dir)
|
2008-10-02 00:18:25 +02:00
|
|
|
(dolist (b (adjoin status-buffer
|
|
|
|
magit-refresh-needing-buffers))
|
|
|
|
(magit-refresh-buffer b)))))))
|
2009-01-24 23:41:03 +01:00
|
|
|
|
2008-09-21 15:09:11 +02:00
|
|
|
(defun magit-need-refresh (&optional buffer)
|
2008-09-29 22:35:39 +02:00
|
|
|
(let ((buffer (or buffer (current-buffer))))
|
|
|
|
(when (not (memq buffer magit-refresh-needing-buffers))
|
|
|
|
(setq magit-refresh-needing-buffers
|
|
|
|
(cons buffer magit-refresh-needing-buffers)))))
|
2008-09-21 15:09:11 +02:00
|
|
|
|
|
|
|
(defun magit-refresh ()
|
|
|
|
(interactive)
|
|
|
|
(magit-with-refresh
|
|
|
|
(magit-need-refresh)))
|
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-refresh-all ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-for-all-buffers #'magit-refresh-buffer default-directory))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2008-10-12 01:10:06 +02:00
|
|
|
;;; Untracked files
|
|
|
|
|
|
|
|
(defun magit-wash-untracked-file ()
|
|
|
|
(if (looking-at "^? \\(.*\\)$")
|
|
|
|
(let ((file (match-string-no-properties 1)))
|
|
|
|
(delete-region (point) (+ (line-end-position) 1))
|
|
|
|
(magit-with-section file 'file
|
|
|
|
(magit-set-section-info file)
|
|
|
|
(insert "\t" file "\n"))
|
|
|
|
t)
|
|
|
|
nil))
|
|
|
|
|
|
|
|
(defun magit-wash-untracked-files ()
|
2009-08-17 19:07:09 +02:00
|
|
|
;; Setting magit-old-top-section to nil speeds up washing: no time
|
|
|
|
;; is wasted looking up the old visibility, which doesn't matter for
|
|
|
|
;; untracked files.
|
|
|
|
;;
|
|
|
|
;; XXX - speed this up in a more general way.
|
|
|
|
;;
|
|
|
|
(let ((magit-old-top-section nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-untracked-file)))
|
2008-10-12 01:10:06 +02:00
|
|
|
|
|
|
|
(defun magit-insert-untracked-files ()
|
2010-03-10 22:38:04 +01:00
|
|
|
(apply 'magit-git-section
|
|
|
|
`(untracked
|
|
|
|
"Untracked files:"
|
|
|
|
magit-wash-untracked-files
|
|
|
|
"ls-files" "-t" "--others" "--exclude-standard"
|
|
|
|
,@(when magit-omit-untracked-dir-contents
|
|
|
|
'("--directory")))))
|
2008-10-12 01:10:06 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
;;; Diffs and Hunks
|
2008-09-02 00:36:06 +02:00
|
|
|
|
2009-02-12 12:53:18 +01:00
|
|
|
(defvar magit-diff-context-lines 3)
|
|
|
|
|
|
|
|
(defun magit-diff-U-arg ()
|
|
|
|
(format "-U%d" magit-diff-context-lines))
|
|
|
|
|
|
|
|
(defun magit-diff-smaller-hunks (&optional count)
|
|
|
|
(interactive "p")
|
|
|
|
(setq magit-diff-context-lines (max 0 (- magit-diff-context-lines count)))
|
|
|
|
(magit-refresh))
|
|
|
|
|
|
|
|
(defun magit-diff-larger-hunks (&optional count)
|
|
|
|
(interactive "p")
|
|
|
|
(setq magit-diff-context-lines (+ magit-diff-context-lines count))
|
|
|
|
(magit-refresh))
|
|
|
|
|
|
|
|
(defun magit-diff-default-hunks ()
|
|
|
|
(interactive "")
|
|
|
|
(setq magit-diff-context-lines 3)
|
|
|
|
(magit-refresh))
|
|
|
|
|
2008-09-02 00:36:06 +02:00
|
|
|
(defun magit-diff-line-file ()
|
2009-02-28 18:22:22 +01:00
|
|
|
(cond ((looking-at "^diff --git ./\\(.*\\) ./\\(.*\\)$")
|
2008-09-07 01:00:26 +02:00
|
|
|
(match-string-no-properties 2))
|
2008-09-02 00:36:06 +02:00
|
|
|
((looking-at "^diff --cc +\\(.*\\)$")
|
2008-09-07 01:00:26 +02:00
|
|
|
(match-string-no-properties 1))
|
|
|
|
(t
|
|
|
|
nil)))
|
|
|
|
|
|
|
|
(defun magit-wash-diffs ()
|
2008-09-07 19:24:41 +02:00
|
|
|
(magit-wash-sequence #'magit-wash-diff-or-other-file))
|
|
|
|
|
|
|
|
(defun magit-wash-diff-or-other-file ()
|
|
|
|
(or (magit-wash-diff)
|
|
|
|
(magit-wash-other-file)))
|
|
|
|
|
|
|
|
(defun magit-wash-other-file ()
|
|
|
|
(if (looking-at "^? \\(.*\\)$")
|
|
|
|
(let ((file (match-string-no-properties 1)))
|
|
|
|
(delete-region (point) (+ (line-end-position) 1))
|
|
|
|
(magit-with-section file 'file
|
|
|
|
(magit-set-section-info file)
|
|
|
|
(insert "\tNew " file "\n"))
|
|
|
|
t)
|
|
|
|
nil))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-09-08 22:31:12 +02:00
|
|
|
(defvar magit-hide-diffs nil)
|
|
|
|
|
2009-07-27 22:02:02 +02:00
|
|
|
(defun magit-insert-diff-title (status file file2)
|
|
|
|
(let ((status-text (case status
|
|
|
|
((unmerged)
|
|
|
|
(format "Unmerged %s" file))
|
|
|
|
((new)
|
|
|
|
(format "New %s" file))
|
|
|
|
((deleted)
|
|
|
|
(format "Deleted %s" file))
|
|
|
|
((renamed)
|
|
|
|
(format "Renamed %s (from %s)"
|
|
|
|
file file2))
|
|
|
|
((modified)
|
|
|
|
(format "Modified %s" file))
|
|
|
|
(t
|
|
|
|
(format "? %s" file)))))
|
|
|
|
(insert "\t" status-text "\n")))
|
|
|
|
|
2009-06-06 22:49:02 +02:00
|
|
|
(defun magit-wash-diff-section ()
|
2009-03-22 00:40:40 +01:00
|
|
|
(cond ((looking-at "^\\* Unmerged path \\(.*\\)")
|
2009-06-21 21:09:35 +02:00
|
|
|
(let ((file (match-string-no-properties 1)))
|
|
|
|
(delete-region (point) (line-end-position))
|
|
|
|
(insert "\tUnmerged " file "\n")
|
|
|
|
(magit-set-section-info (list 'unmerged file nil))
|
|
|
|
t))
|
2009-03-22 00:40:40 +01:00
|
|
|
((looking-at "^diff")
|
2009-06-06 22:49:02 +02:00
|
|
|
(let ((file (magit-diff-line-file))
|
|
|
|
(end (save-excursion
|
|
|
|
(forward-line) ;; skip over "diff" line
|
|
|
|
(if (search-forward-regexp "^diff\\|^@@" nil t)
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
(goto-char (point-max)))
|
|
|
|
(point-marker))))
|
|
|
|
(let* ((status (cond
|
|
|
|
((looking-at "^diff --cc")
|
|
|
|
'unmerged)
|
|
|
|
((save-excursion
|
|
|
|
(search-forward-regexp "^new file" end t))
|
|
|
|
'new)
|
|
|
|
((save-excursion
|
|
|
|
(search-forward-regexp "^deleted" end t))
|
|
|
|
'deleted)
|
|
|
|
((save-excursion
|
|
|
|
(search-forward-regexp "^rename" end t))
|
|
|
|
'renamed)
|
|
|
|
(t
|
|
|
|
'modified)))
|
|
|
|
(file2 (cond
|
|
|
|
((save-excursion
|
|
|
|
(search-forward-regexp "^rename from \\(.*\\)"
|
|
|
|
end t))
|
2009-07-27 22:02:02 +02:00
|
|
|
(match-string-no-properties 1)))))
|
2009-06-06 22:49:02 +02:00
|
|
|
(magit-set-section-info (list status file file2))
|
2009-07-27 22:02:02 +02:00
|
|
|
(magit-insert-diff-title status file file2)
|
2009-06-06 22:49:02 +02:00
|
|
|
(goto-char end)
|
|
|
|
(let ((magit-section-hidden-default nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-hunk))))
|
|
|
|
t)
|
2009-02-15 22:58:10 +01:00
|
|
|
(t
|
|
|
|
nil)))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2009-06-06 22:49:02 +02:00
|
|
|
(defun magit-wash-diff ()
|
2009-06-08 20:37:16 +02:00
|
|
|
(let ((magit-section-hidden-default magit-hide-diffs))
|
|
|
|
(magit-with-section (magit-current-line) 'diff
|
|
|
|
(magit-wash-diff-section))))
|
2009-06-06 22:49:02 +02:00
|
|
|
|
2008-09-07 15:31:51 +02:00
|
|
|
(defun magit-diff-item-kind (diff)
|
|
|
|
(car (magit-section-info diff)))
|
|
|
|
|
|
|
|
(defun magit-diff-item-file (diff)
|
|
|
|
(cadr (magit-section-info diff)))
|
|
|
|
|
|
|
|
(defun magit-diff-item-file2 (diff)
|
|
|
|
(caddr (magit-section-info diff)))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-wash-hunk ()
|
|
|
|
(cond ((looking-at "\\(^@+\\)[^@]*@+")
|
2009-01-09 22:02:27 +01:00
|
|
|
(let ((n-columns (1- (length (match-string 1))))
|
2008-09-07 01:00:26 +02:00
|
|
|
(head (match-string 0)))
|
|
|
|
(magit-with-section head 'hunk
|
2010-03-10 22:43:11 +01:00
|
|
|
(add-text-properties (match-beginning 0) (match-end 0)
|
|
|
|
'(face magit-diff-hunk-header))
|
2008-09-07 01:00:26 +02:00
|
|
|
(forward-line)
|
|
|
|
(while (not (or (eobp)
|
|
|
|
(looking-at "^diff\\|^@@")))
|
|
|
|
(let ((prefix (buffer-substring-no-properties
|
2009-01-09 22:02:27 +01:00
|
|
|
(point) (min (+ (point) n-columns) (point-max)))))
|
2008-09-07 01:00:26 +02:00
|
|
|
(cond ((string-match "\\+" prefix)
|
|
|
|
(magit-put-line-property 'face 'magit-diff-add))
|
|
|
|
((string-match "-" prefix)
|
|
|
|
(magit-put-line-property 'face 'magit-diff-del))
|
|
|
|
(t
|
|
|
|
(magit-put-line-property 'face 'magit-diff-none))))
|
|
|
|
(forward-line))))
|
|
|
|
t)
|
2008-09-02 00:36:06 +02:00
|
|
|
(t
|
|
|
|
nil)))
|
|
|
|
|
2009-07-15 01:08:52 +02:00
|
|
|
(defvar magit-diff-options nil)
|
|
|
|
|
2009-06-06 22:49:02 +02:00
|
|
|
(defun magit-insert-diff (file)
|
|
|
|
(let ((cmd magit-git-executable)
|
2009-09-12 21:36:10 +02:00
|
|
|
(args (append (list "diff")
|
2009-06-21 21:13:21 +02:00
|
|
|
(list (magit-diff-U-arg))
|
2009-06-06 22:49:02 +02:00
|
|
|
magit-diff-options
|
|
|
|
(list "--" file))))
|
|
|
|
(let ((p (point)))
|
2009-09-12 21:36:10 +02:00
|
|
|
(magit-git-insert args)
|
2009-06-06 22:49:02 +02:00
|
|
|
(if (not (eq (char-before) ?\n))
|
|
|
|
(insert "\n"))
|
|
|
|
(save-restriction
|
|
|
|
(narrow-to-region p (point))
|
|
|
|
(goto-char p)
|
|
|
|
(magit-wash-diff-section)
|
|
|
|
(goto-char (point-max))))))
|
|
|
|
|
2009-09-06 19:27:18 +02:00
|
|
|
(defvar magit-last-raw-diff nil)
|
|
|
|
(defvar magit-ignore-unmerged-raw-diffs nil)
|
|
|
|
|
2009-07-27 22:02:02 +02:00
|
|
|
(defun magit-wash-raw-diffs ()
|
2009-09-06 19:27:18 +02:00
|
|
|
(let ((magit-last-raw-diff nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-raw-diff)))
|
2009-07-27 22:02:02 +02:00
|
|
|
|
|
|
|
(defun magit-wash-raw-diff ()
|
|
|
|
(if (looking-at
|
|
|
|
":\\([0-7]+\\) \\([0-7]+\\) [0-9a-f]+ [0-9a-f]+ \\(.\\)[0-9]*\t\\([^\t\n]+\\)$")
|
|
|
|
(let ((old-perm (match-string-no-properties 1))
|
|
|
|
(new-perm (match-string-no-properties 2))
|
|
|
|
(status (case (string-to-char (match-string-no-properties 3))
|
|
|
|
(?A 'new)
|
|
|
|
(?D 'deleted)
|
|
|
|
(?M 'modified)
|
|
|
|
(?U 'unmerged)
|
|
|
|
(?T 'new-type)
|
|
|
|
(t nil)))
|
|
|
|
(file (match-string-no-properties 4)))
|
2009-09-06 19:27:18 +02:00
|
|
|
;; If this is for the same file as the last diff, ignore it.
|
|
|
|
;; Unmerged files seem to get two entries.
|
|
|
|
;; We also ignore unmerged files when told so.
|
|
|
|
(if (or (equal file magit-last-raw-diff)
|
|
|
|
(and magit-ignore-unmerged-raw-diffs (eq status 'unmerged)))
|
2009-07-28 20:58:12 +02:00
|
|
|
(delete-region (point) (+ (line-end-position) 1))
|
2009-09-06 19:27:18 +02:00
|
|
|
(setq magit-last-raw-diff file)
|
|
|
|
;; The 'diff' section that is created here will not work with
|
|
|
|
;; magit-insert-diff-item-patch etc when we leave it empty.
|
|
|
|
;; Luckily, raw diffs are only produced for staged and
|
|
|
|
;; unstaged changes, and we never call
|
|
|
|
;; magit-insert-diff-item-patch on them. This is a bit
|
|
|
|
;; brittle, of course.
|
|
|
|
(let ((magit-section-hidden-default magit-hide-diffs))
|
|
|
|
(magit-with-section file 'diff
|
|
|
|
(delete-region (point) (+ (line-end-position) 1))
|
|
|
|
(if (not (magit-section-hidden magit-top-section))
|
|
|
|
(magit-insert-diff file)
|
|
|
|
(magit-set-section-info (list status file nil))
|
|
|
|
(magit-set-section-needs-refresh-on-show t)
|
|
|
|
(magit-insert-diff-title status file nil)))))
|
2009-06-06 22:49:02 +02:00
|
|
|
t)
|
|
|
|
nil))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-hunk-item-diff (hunk)
|
|
|
|
(let ((diff (magit-section-parent hunk)))
|
|
|
|
(or (eq (magit-section-type diff) 'diff)
|
|
|
|
(error "Huh? Parent of hunk not a diff."))
|
|
|
|
diff))
|
|
|
|
|
2008-10-12 01:50:49 +02:00
|
|
|
(defun magit-diff-item-insert-header (diff buf)
|
2009-02-25 14:55:52 +01:00
|
|
|
(let ((beg (save-excursion
|
2008-09-07 01:00:26 +02:00
|
|
|
(goto-char (magit-section-beginning diff))
|
|
|
|
(forward-line)
|
|
|
|
(point)))
|
|
|
|
(end (if (magit-section-children diff)
|
|
|
|
(magit-section-beginning (car (magit-section-children diff)))
|
|
|
|
(magit-section-end diff))))
|
2008-10-12 01:50:49 +02:00
|
|
|
(magit-insert-region beg end buf)))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-10-12 01:50:49 +02:00
|
|
|
(defun magit-insert-diff-item-patch (diff buf)
|
2009-02-25 14:55:52 +01:00
|
|
|
(let ((beg (save-excursion
|
2008-09-13 22:09:51 +02:00
|
|
|
(goto-char (magit-section-beginning diff))
|
|
|
|
(forward-line)
|
|
|
|
(point)))
|
|
|
|
(end (magit-section-end diff)))
|
2008-10-12 01:50:49 +02:00
|
|
|
(magit-insert-region beg end buf)))
|
2008-09-13 22:09:51 +02:00
|
|
|
|
2008-10-12 01:50:49 +02:00
|
|
|
(defun magit-insert-hunk-item-patch (hunk buf)
|
|
|
|
(magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf)
|
|
|
|
(magit-insert-region (magit-section-beginning hunk) (magit-section-end hunk)
|
|
|
|
buf))
|
2008-10-10 14:57:37 +02:00
|
|
|
|
2009-02-15 01:58:26 +01:00
|
|
|
(defun magit-insert-hunk-item-region-patch (hunk reverse beg end buf)
|
2008-10-12 01:50:49 +02:00
|
|
|
(magit-diff-item-insert-header (magit-hunk-item-diff hunk) buf)
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (magit-section-beginning hunk))
|
|
|
|
(magit-insert-current-line buf)
|
|
|
|
(forward-line)
|
2009-02-15 01:58:26 +01:00
|
|
|
(let ((copy-op (if reverse "+" "-")))
|
|
|
|
(while (< (point) (magit-section-end hunk))
|
|
|
|
(if (and (<= beg (point)) (< (point) end))
|
|
|
|
(magit-insert-current-line buf)
|
|
|
|
(cond ((looking-at " ")
|
|
|
|
(magit-insert-current-line buf))
|
|
|
|
((looking-at copy-op)
|
|
|
|
(let ((text (buffer-substring-no-properties
|
|
|
|
(+ (point) 1) (line-beginning-position 2))))
|
|
|
|
(with-current-buffer buf
|
|
|
|
(insert " " text))))))
|
|
|
|
(forward-line))))
|
2008-10-12 01:50:49 +02:00
|
|
|
(with-current-buffer buf
|
|
|
|
(diff-fixup-modifs (point-min) (point-max))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defun magit-hunk-item-is-conflict-p (hunk)
|
|
|
|
;;; XXX - Using the title is a bit too clever...
|
|
|
|
(string-match "^diff --cc"
|
|
|
|
(magit-section-title (magit-hunk-item-diff hunk))))
|
|
|
|
|
|
|
|
(defun magit-hunk-item-target-line (hunk)
|
2008-09-02 00:36:06 +02:00
|
|
|
(save-excursion
|
|
|
|
(beginning-of-line)
|
|
|
|
(let ((line (line-number-at-pos)))
|
|
|
|
(if (looking-at "-")
|
|
|
|
(error "Can't visit removed lines."))
|
2008-09-07 01:00:26 +02:00
|
|
|
(goto-char (magit-section-beginning hunk))
|
2008-09-02 00:36:06 +02:00
|
|
|
(if (not (looking-at "@@+ .* \\+\\([0-9]+\\),[0-9]+ @@+"))
|
|
|
|
(error "Hunk header not found."))
|
|
|
|
(let ((target (parse-integer (match-string 1))))
|
|
|
|
(forward-line)
|
|
|
|
(while (< (line-number-at-pos) line)
|
|
|
|
;; XXX - deal with combined diffs
|
|
|
|
(if (not (looking-at "-"))
|
|
|
|
(setq target (+ target 1)))
|
|
|
|
(forward-line))
|
|
|
|
target))))
|
|
|
|
|
2008-09-13 22:09:51 +02:00
|
|
|
(defun magit-apply-diff-item (diff &rest args)
|
2009-02-12 12:53:18 +01:00
|
|
|
(when (zerop magit-diff-context-lines)
|
|
|
|
(setq args (cons "--unidiff-zero" args)))
|
2009-07-14 23:42:33 +02:00
|
|
|
(let ((tmp (get-buffer-create "*magit-tmp*")))
|
|
|
|
(with-current-buffer tmp
|
|
|
|
(erase-buffer))
|
|
|
|
(magit-insert-diff-item-patch diff "*magit-tmp*")
|
|
|
|
(apply #'magit-run-git-with-input tmp
|
|
|
|
"apply" (append args (list "-")))))
|
2008-09-13 22:09:51 +02:00
|
|
|
|
2009-02-15 01:58:26 +01:00
|
|
|
(defun magit-apply-hunk-item* (hunk reverse &rest args)
|
2009-02-12 12:53:18 +01:00
|
|
|
(when (zerop magit-diff-context-lines)
|
|
|
|
(setq args (cons "--unidiff-zero" args)))
|
2008-10-12 01:50:49 +02:00
|
|
|
(let ((tmp (get-buffer-create "*magit-tmp*")))
|
|
|
|
(with-current-buffer tmp
|
|
|
|
(erase-buffer))
|
2008-10-12 02:06:40 +02:00
|
|
|
(if (magit-use-region-p)
|
2008-10-12 01:50:49 +02:00
|
|
|
(magit-insert-hunk-item-region-patch
|
2009-02-15 01:58:26 +01:00
|
|
|
hunk reverse (region-beginning) (region-end) tmp)
|
2008-10-12 01:50:49 +02:00
|
|
|
(magit-insert-hunk-item-patch hunk tmp))
|
2009-02-15 22:58:10 +01:00
|
|
|
(apply #'magit-run-git-with-input tmp
|
|
|
|
"apply" (append args (list "-")))))
|
2008-09-13 22:09:51 +02:00
|
|
|
|
2009-02-15 01:58:26 +01:00
|
|
|
(defun magit-apply-hunk-item (hunk &rest args)
|
|
|
|
(apply #'magit-apply-hunk-item* hunk nil args))
|
|
|
|
|
|
|
|
(defun magit-apply-hunk-item-reverse (hunk &rest args)
|
|
|
|
(apply #'magit-apply-hunk-item* hunk t (cons "--reverse" args)))
|
|
|
|
|
2008-09-07 02:53:25 +02:00
|
|
|
(defun magit-insert-unstaged-changes (title)
|
2008-09-08 22:31:12 +02:00
|
|
|
(let ((magit-hide-diffs t))
|
2009-06-06 22:49:02 +02:00
|
|
|
(let ((magit-diff-options '()))
|
2009-07-27 22:02:02 +02:00
|
|
|
(magit-git-section 'unstaged title 'magit-wash-raw-diffs
|
|
|
|
"diff-files"))))
|
2008-09-07 02:53:25 +02:00
|
|
|
|
2009-02-15 19:07:13 +01:00
|
|
|
(defun magit-insert-staged-changes (no-commit)
|
2009-06-06 22:49:02 +02:00
|
|
|
(let ((magit-hide-diffs t)
|
|
|
|
(base (if no-commit
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-git-string "mktree")
|
2009-06-06 22:49:02 +02:00
|
|
|
"HEAD")))
|
2009-09-06 19:27:18 +02:00
|
|
|
(let ((magit-diff-options '("--cached"))
|
|
|
|
(magit-ignore-unmerged-raw-diffs t))
|
2009-07-27 22:02:02 +02:00
|
|
|
(magit-git-section 'staged "Staged changes:" 'magit-wash-raw-diffs
|
|
|
|
"diff-index" "--cached"
|
2009-06-06 22:49:02 +02:00
|
|
|
base))))
|
2008-09-07 02:53:25 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
;;; Logs and Commits
|
|
|
|
|
2009-11-02 11:24:21 +01:00
|
|
|
(defvar magit-log-oneline-re
|
|
|
|
(concat
|
|
|
|
"^\\([_\\*|/ ]+\\)" ; graph (1)
|
|
|
|
"\\(?:"
|
|
|
|
"\\([0-9a-fA-F]\\{40\\}\\) " ; sha1 (2)
|
|
|
|
"\\(?:\\((.+)\\) \\)?" ; refs (3)
|
|
|
|
"\\(.*\\)" ; msg (4)
|
|
|
|
"\\)?$")
|
|
|
|
"Regexp used to extract elements of git log output with
|
|
|
|
--pretty=oneline.")
|
|
|
|
|
|
|
|
(defvar magit-present-log-line-function 'magit-present-log-line
|
|
|
|
"The function to use when generating a log line. It takes four
|
|
|
|
args: CHART, SHA1, REFS and MESSAGE. The function must return a
|
|
|
|
string which will represent the log line.")
|
|
|
|
|
2009-11-02 11:33:57 +01:00
|
|
|
(defun magit-present-log-line (graph sha1 refs message)
|
2009-11-02 11:24:21 +01:00
|
|
|
"The default log line generator."
|
2009-11-08 15:54:53 +01:00
|
|
|
(let* ((ref-re "\\(?:tag: \\)?refs/\\(tags\\|remotes\\|heads\\)/\\(.+\\)")
|
2009-11-02 11:24:21 +01:00
|
|
|
(string-refs
|
|
|
|
(when refs
|
|
|
|
(concat (mapconcat
|
|
|
|
(lambda (r)
|
|
|
|
(propertize
|
|
|
|
(if (string-match ref-re r)
|
2009-11-08 15:54:53 +01:00
|
|
|
(match-string 2 r)
|
2009-11-02 11:24:21 +01:00
|
|
|
r)
|
2009-11-08 15:54:53 +01:00
|
|
|
'face (cond
|
|
|
|
((string= (match-string 1 r) "remotes")
|
|
|
|
'magit-log-head-label-remote)
|
|
|
|
((string= (match-string 1 r) "tags")
|
|
|
|
'magit-log-head-label-tags)
|
|
|
|
((string= (match-string 1 r) "heads")
|
|
|
|
'magit-log-head-label-local))))
|
|
|
|
refs
|
|
|
|
" ")
|
|
|
|
" "))))
|
|
|
|
(concat
|
|
|
|
(if sha1
|
|
|
|
(propertize (substring sha1 0 8) 'face 'magit-log-sha1)
|
|
|
|
(insert-char ? 8))
|
|
|
|
" "
|
|
|
|
(propertize graph 'face 'magit-log-graph)
|
|
|
|
string-refs
|
|
|
|
(when message
|
|
|
|
(propertize message 'face 'magit-log-message)))))
|
2008-10-26 18:59:56 +01:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-wash-log-line ()
|
2009-11-02 11:24:21 +01:00
|
|
|
(beginning-of-line)
|
|
|
|
(let ((line-re magit-log-oneline-re))
|
|
|
|
(cond
|
|
|
|
((looking-at magit-log-oneline-re)
|
|
|
|
(let ((chart (match-string 1))
|
|
|
|
(sha1 (match-string 2))
|
|
|
|
(msg (match-string 4))
|
|
|
|
(refs (when (match-string 3)
|
2009-11-08 15:54:53 +01:00
|
|
|
(remove-if (lambda (s)
|
|
|
|
(string= s "tag:"))
|
|
|
|
(split-string (match-string 3) "[(), ]" t)))))
|
2009-11-02 11:24:21 +01:00
|
|
|
(delete-region (point-at-bol) (point-at-eol))
|
2009-12-16 11:47:58 +01:00
|
|
|
(insert (funcall magit-present-log-line-function chart sha1 refs msg))
|
2009-11-02 11:24:21 +01:00
|
|
|
(goto-char (point-at-bol))
|
|
|
|
(if sha1
|
|
|
|
(magit-with-section sha1 'commit
|
|
|
|
(magit-set-section-info sha1)
|
|
|
|
(forward-line))
|
|
|
|
(forward-line))))
|
|
|
|
(t
|
|
|
|
(forward-line)))
|
|
|
|
t))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defun magit-wash-log ()
|
2008-09-10 22:23:47 +02:00
|
|
|
(let ((magit-old-top-section nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-log-line)))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defvar magit-currently-shown-commit nil)
|
|
|
|
|
|
|
|
(defun magit-wash-commit ()
|
|
|
|
(cond ((search-forward-regexp "^diff" nil t)
|
|
|
|
(goto-char (match-beginning 0))
|
2008-09-08 22:32:02 +02:00
|
|
|
(magit-wash-diffs))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-refresh-commit-buffer (commit)
|
|
|
|
(magit-create-buffer-sections
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section nil nil
|
|
|
|
'magit-wash-commit
|
|
|
|
"log" "--max-count=1"
|
|
|
|
"--pretty=medium"
|
|
|
|
"--cc" "-p" commit)))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-show-commit (commit &optional scroll)
|
2008-10-26 13:22:51 +01:00
|
|
|
(when (magit-section-p commit)
|
|
|
|
(setq commit (magit-section-info commit)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(let ((dir default-directory)
|
|
|
|
(buf (get-buffer-create "*magit-commit*")))
|
2010-03-10 22:21:33 +01:00
|
|
|
(cond ((and (equal magit-currently-shown-commit commit)
|
|
|
|
;; if it's empty then the buffer was killed
|
|
|
|
(with-current-buffer buf
|
|
|
|
(> (length (buffer-string)) 1)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(let ((win (get-buffer-window buf)))
|
|
|
|
(cond ((not win)
|
|
|
|
(display-buffer buf))
|
|
|
|
(scroll
|
|
|
|
(with-selected-window win
|
|
|
|
(funcall scroll))))))
|
|
|
|
(t
|
|
|
|
(setq magit-currently-shown-commit commit)
|
|
|
|
(display-buffer buf)
|
2008-10-02 22:22:41 +02:00
|
|
|
(with-current-buffer buf
|
2008-09-07 01:00:26 +02:00
|
|
|
(set-buffer buf)
|
2008-10-02 22:22:41 +02:00
|
|
|
(goto-char (point-min))
|
2008-09-13 21:51:54 +02:00
|
|
|
(magit-mode-init dir 'commit
|
|
|
|
#'magit-refresh-commit-buffer commit))))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defvar magit-marked-commit nil)
|
|
|
|
|
2008-12-13 08:44:56 +01:00
|
|
|
(defvar magit-mark-overlay nil)
|
|
|
|
(make-variable-buffer-local 'magit-mark-overlay)
|
|
|
|
(put 'magit-mark-overlay 'permanent-local t)
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
(defun magit-refresh-marked-commits ()
|
|
|
|
(magit-for-all-buffers #'magit-refresh-marked-commits-in-buffer))
|
|
|
|
|
|
|
|
(defun magit-refresh-marked-commits-in-buffer ()
|
2008-12-13 08:44:56 +01:00
|
|
|
(if (not magit-mark-overlay)
|
|
|
|
(let ((ov (make-overlay 1 1)))
|
2009-01-24 23:41:03 +01:00
|
|
|
(overlay-put ov 'face 'magit-item-mark)
|
|
|
|
(setq magit-mark-overlay ov)))
|
2008-12-13 08:44:56 +01:00
|
|
|
(delete-overlay magit-mark-overlay)
|
|
|
|
(magit-for-all-sections
|
|
|
|
(lambda (section)
|
|
|
|
(when (and (eq (magit-section-type section) 'commit)
|
2009-01-24 23:41:03 +01:00
|
|
|
(equal (magit-section-info section)
|
|
|
|
magit-marked-commit))
|
2008-12-13 08:44:56 +01:00
|
|
|
(move-overlay magit-mark-overlay
|
2009-01-24 23:41:03 +01:00
|
|
|
(magit-section-beginning section)
|
|
|
|
(magit-section-end section)
|
|
|
|
(current-buffer))))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
|
|
|
(defun magit-set-marked-commit (commit)
|
|
|
|
(setq magit-marked-commit commit)
|
|
|
|
(magit-refresh-marked-commits))
|
|
|
|
|
|
|
|
(defun magit-marked-commit ()
|
|
|
|
(or magit-marked-commit
|
2008-11-30 21:31:22 +01:00
|
|
|
(error "No commit marked")))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-09-07 15:50:30 +02:00
|
|
|
(defun magit-insert-unpulled-commits (remote branch)
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'unpulled
|
|
|
|
"Unpulled commits:" 'magit-wash-log
|
|
|
|
"log" "--pretty=format:* %H %s"
|
|
|
|
(format "HEAD..%s/%s" remote branch)))
|
2008-09-07 15:48:44 +02:00
|
|
|
|
2008-09-07 02:53:25 +02:00
|
|
|
(defun magit-insert-unpushed-commits (remote branch)
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'unpushed
|
|
|
|
"Unpushed commits:" 'magit-wash-log
|
|
|
|
"log" "--pretty=format:* %H %s"
|
|
|
|
(format "%s/%s..HEAD" remote branch)))
|
2008-09-07 02:53:25 +02:00
|
|
|
|
2009-10-28 21:37:35 +01:00
|
|
|
(defun magit-insert-unpulled-svn-commits (&optional use-cache)
|
2009-02-20 23:16:40 +01:00
|
|
|
(magit-git-section 'svn-unpulled
|
|
|
|
"Unpulled commits (SVN):" 'magit-wash-log
|
|
|
|
"log" "--pretty=format:* %H %s"
|
2009-10-28 21:37:35 +01:00
|
|
|
(format "HEAD..%s" (magit-get-svn-ref use-cache))))
|
2009-02-20 23:16:40 +01:00
|
|
|
|
2009-10-28 21:37:35 +01:00
|
|
|
(defun magit-insert-unpushed-svn-commits (&optional use-cache)
|
2009-02-20 23:16:40 +01:00
|
|
|
(magit-git-section 'svn-unpushed
|
|
|
|
"Unpushed commits (SVN):" 'magit-wash-log
|
|
|
|
"log" "--pretty=format:* %H %s"
|
2009-10-28 21:37:35 +01:00
|
|
|
(format "%s..HEAD" (magit-get-svn-ref use-cache))))
|
2009-02-20 23:16:40 +01:00
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
;;; Status
|
|
|
|
|
2009-10-28 21:41:43 +01:00
|
|
|
(defun magit-remote-string (remote svn-info)
|
|
|
|
(if remote
|
|
|
|
(concat remote " " (magit-get "remote" remote "url"))
|
|
|
|
(when svn-info
|
|
|
|
(concat (cdr (assoc 'url svn-info))
|
|
|
|
" @ "
|
|
|
|
(cdr (assoc 'revision svn-info))))))
|
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-refresh-status ()
|
2008-09-14 22:15:52 +02:00
|
|
|
(magit-create-buffer-sections
|
|
|
|
(magit-with-section 'status nil
|
|
|
|
(let* ((branch (magit-get-current-branch))
|
2009-02-04 15:54:30 +01:00
|
|
|
(remote (and branch (magit-get "branch" branch "remote")))
|
2009-10-28 21:41:43 +01:00
|
|
|
(svn-info (magit-get-svn-ref-info))
|
|
|
|
(remote-string (magit-remote-string remote svn-info))
|
2009-02-15 22:58:10 +01:00
|
|
|
(head (magit-git-string
|
2009-07-15 01:08:52 +02:00
|
|
|
"log" "--max-count=1" "--abbrev-commit" "--pretty=oneline"))
|
|
|
|
(no-commit (not head)))
|
2009-10-28 21:41:43 +01:00
|
|
|
(when remote-string
|
|
|
|
(insert "Remote: " remote-string "\n"))
|
2008-09-14 22:15:52 +02:00
|
|
|
(insert (format "Local: %s %s\n"
|
|
|
|
(propertize (or branch "(detached)")
|
|
|
|
'face 'magit-branch)
|
|
|
|
(abbreviate-file-name default-directory)))
|
2009-10-28 21:41:43 +01:00
|
|
|
(insert (format "Head: %s\n"
|
2009-10-28 21:37:35 +01:00
|
|
|
(if no-commit "nothing commited (yet)" head)))
|
2008-09-14 22:15:52 +02:00
|
|
|
(let ((merge-heads (magit-file-lines ".git/MERGE_HEAD")))
|
|
|
|
(if merge-heads
|
|
|
|
(insert (format "Merging: %s\n"
|
|
|
|
(magit-concat-with-delim
|
|
|
|
", "
|
|
|
|
(mapcar 'magit-name-rev merge-heads))))))
|
|
|
|
(let ((rebase (magit-rebase-info)))
|
|
|
|
(if rebase
|
|
|
|
(insert (apply 'format "Rebasing: %s (%s of %s)\n" rebase))))
|
|
|
|
(insert "\n")
|
2009-10-28 21:37:35 +01:00
|
|
|
(magit-git-exit-code "update-index" "--refresh")
|
2008-10-12 01:10:06 +02:00
|
|
|
(magit-insert-untracked-files)
|
2008-11-09 23:06:13 +01:00
|
|
|
(magit-insert-stashes)
|
2009-03-06 03:55:13 +01:00
|
|
|
(magit-insert-topics)
|
2008-09-14 22:15:52 +02:00
|
|
|
(magit-insert-pending-changes)
|
|
|
|
(magit-insert-pending-commits)
|
|
|
|
(when remote
|
|
|
|
(magit-insert-unpulled-commits remote branch))
|
2009-10-28 21:41:43 +01:00
|
|
|
(when svn-info
|
2009-10-28 21:37:35 +01:00
|
|
|
(magit-insert-unpulled-svn-commits t))
|
2009-02-04 15:54:30 +01:00
|
|
|
(let ((staged (or no-commit (magit-anything-staged-p))))
|
2008-09-14 22:15:52 +02:00
|
|
|
(magit-insert-unstaged-changes
|
|
|
|
(if staged "Unstaged changes:" "Changes:"))
|
|
|
|
(if staged
|
2009-02-15 19:07:13 +01:00
|
|
|
(magit-insert-staged-changes no-commit)))
|
2008-09-14 22:15:52 +02:00
|
|
|
(when remote
|
2009-02-20 23:16:40 +01:00
|
|
|
(magit-insert-unpushed-commits remote branch))
|
2009-10-28 21:41:43 +01:00
|
|
|
(when svn-info
|
2009-10-28 21:37:35 +01:00
|
|
|
(magit-insert-unpushed-svn-commits t))))))
|
2008-08-17 01:27:00 +02:00
|
|
|
|
2009-02-04 15:49:10 +01:00
|
|
|
(defun magit-init (dir)
|
|
|
|
"Initialize git repository in specified directory"
|
2009-02-15 01:26:21 +01:00
|
|
|
(interactive (list (read-directory-name "Directory for Git repository: ")))
|
2009-02-04 15:49:10 +01:00
|
|
|
(let ((topdir (magit-get-top-dir dir)))
|
|
|
|
(when (or (not topdir)
|
2009-02-15 01:26:21 +01:00
|
|
|
(yes-or-no-p
|
2009-02-04 15:49:10 +01:00
|
|
|
(format
|
|
|
|
(if (string-equal topdir (expand-file-name dir))
|
2009-02-15 01:26:21 +01:00
|
|
|
"There is already a Git repository in %s. Reinitialize? "
|
|
|
|
"There is a Git repository in %s. Create another in %s? ")
|
2009-02-04 15:49:10 +01:00
|
|
|
topdir dir)))
|
|
|
|
(unless (file-directory-p dir)
|
2009-02-15 01:26:21 +01:00
|
|
|
(and (y-or-n-p (format "Directory %s does not exists. Create it? " dir))
|
2009-02-04 15:49:10 +01:00
|
|
|
(make-directory dir)))
|
|
|
|
(let ((default-directory dir))
|
|
|
|
(magit-run* (list "git" "init"))))))
|
|
|
|
|
2009-03-09 20:59:38 +01:00
|
|
|
;;;###autoload
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-status (dir)
|
2009-02-07 21:50:51 +01:00
|
|
|
(interactive (list (or (and (not current-prefix-arg)
|
|
|
|
(magit-get-top-dir default-directory))
|
2009-07-28 01:32:19 +02:00
|
|
|
(magit-read-top-dir (and (consp current-prefix-arg)
|
2009-07-28 01:25:44 +02:00
|
|
|
(> (car current-prefix-arg) 4))))))
|
2009-01-18 23:56:12 +01:00
|
|
|
(if magit-save-some-buffers
|
|
|
|
(save-some-buffers (eq magit-save-some-buffers 'dontask)))
|
2009-02-04 15:49:10 +01:00
|
|
|
(let ((topdir (magit-get-top-dir dir)))
|
|
|
|
(unless topdir
|
2009-02-15 01:26:21 +01:00
|
|
|
(when (y-or-n-p (format "There is no Git repository in %S. Create one? "
|
|
|
|
dir))
|
2009-02-04 15:49:10 +01:00
|
|
|
(magit-init dir)
|
|
|
|
(setq topdir (magit-get-top-dir dir))))
|
|
|
|
(when topdir
|
|
|
|
(let ((buf (or (magit-find-buffer 'status topdir)
|
|
|
|
(switch-to-buffer
|
|
|
|
(get-buffer-create
|
|
|
|
(concat "*magit: "
|
|
|
|
(file-name-nondirectory
|
|
|
|
(directory-file-name topdir)) "*"))))))
|
|
|
|
(switch-to-buffer buf)
|
|
|
|
(magit-mode-init topdir 'status #'magit-refresh-status)))))
|
|
|
|
|
2008-09-07 01:00:26 +02:00
|
|
|
;;; Staging and Unstaging
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-08-21 01:19:58 +02:00
|
|
|
(defun magit-stage-item ()
|
|
|
|
"Add the item at point to the staging area."
|
2008-08-01 15:04:52 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "stage")
|
2008-10-12 01:10:06 +02:00
|
|
|
((untracked file)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "add" info))
|
2009-07-27 22:12:44 +02:00
|
|
|
((untracked)
|
|
|
|
(apply #'magit-run-git "add" "--"
|
|
|
|
(magit-git-lines "ls-files" "--other" "--exclude-standard")))
|
2008-09-07 01:00:26 +02:00
|
|
|
((unstaged diff hunk)
|
2008-08-24 01:31:49 +02:00
|
|
|
(if (magit-hunk-item-is-conflict-p item)
|
2008-09-07 01:00:26 +02:00
|
|
|
(error (concat "Can't stage individual resolution hunks. "
|
|
|
|
"Please stage the whole file.")))
|
2008-08-30 19:54:51 +02:00
|
|
|
(magit-apply-hunk-item item "--cached"))
|
2008-09-07 01:00:26 +02:00
|
|
|
((unstaged diff)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "add" "-u" (magit-diff-item-file item)))
|
2008-09-07 01:00:26 +02:00
|
|
|
((staged *)
|
|
|
|
(error "Already staged"))
|
|
|
|
((hunk)
|
|
|
|
(error "Can't stage this hunk"))
|
2008-08-24 01:31:49 +02:00
|
|
|
((diff)
|
2008-09-07 01:00:26 +02:00
|
|
|
(error "Can't stage this diff"))))
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-08-21 01:19:58 +02:00
|
|
|
(defun magit-unstage-item ()
|
|
|
|
"Remove the item at point from the staging area."
|
2008-08-04 03:13:23 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "unstage")
|
2008-09-07 01:00:26 +02:00
|
|
|
((staged diff hunk)
|
2009-02-15 01:58:26 +01:00
|
|
|
(magit-apply-hunk-item-reverse item "--cached"))
|
2008-09-07 01:00:26 +02:00
|
|
|
((staged diff)
|
2009-03-22 00:40:40 +01:00
|
|
|
(if (eq (car info) 'unmerged)
|
|
|
|
(error "Can't unstage a unmerged file. Resolve it first."))
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "reset" "-q" "HEAD" "--" (magit-diff-item-file item)))
|
2008-09-07 01:00:26 +02:00
|
|
|
((unstaged *)
|
|
|
|
(error "Already unstaged"))
|
|
|
|
((hunk)
|
|
|
|
(error "Can't unstage this hunk"))
|
2008-08-24 01:31:49 +02:00
|
|
|
((diff)
|
2008-09-07 01:00:26 +02:00
|
|
|
(error "Can't unstage this diff"))))
|
2008-08-04 03:13:23 +02:00
|
|
|
|
2009-07-27 22:39:36 +02:00
|
|
|
(defun magit-stage-all (&optional also-untracked-p)
|
|
|
|
(interactive "P")
|
|
|
|
(if also-untracked-p
|
|
|
|
(magit-run-git "add" ".")
|
|
|
|
(magit-run-git "add" "-u" ".")))
|
2008-08-04 02:26:34 +02:00
|
|
|
|
2008-08-20 23:19:15 +02:00
|
|
|
(defun magit-unstage-all ()
|
|
|
|
(interactive)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "reset" "HEAD"))
|
2008-08-20 23:19:15 +02:00
|
|
|
|
2008-08-06 00:08:07 +02:00
|
|
|
;;; Branches
|
|
|
|
|
2009-06-07 20:41:09 +02:00
|
|
|
(defun magit-maybe-create-local-tracking-branch (rev)
|
|
|
|
(if (string-match "^refs/remotes/\\([^/]+\\)/\\(.+\\)" rev)
|
2009-06-06 13:54:30 +02:00
|
|
|
(let ((remote (match-string 1 rev))
|
|
|
|
(branch (match-string 2 rev)))
|
|
|
|
(when (and (not (magit-ref-exists-p (concat "refs/heads/" branch)))
|
|
|
|
(yes-or-no-p
|
|
|
|
(format "Create local tracking branch for %s? " branch)))
|
|
|
|
(magit-run-git "checkout" "-b" branch rev)
|
|
|
|
t))
|
|
|
|
nil))
|
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-checkout (rev)
|
2008-08-17 00:40:04 +02:00
|
|
|
(interactive (list (magit-read-rev "Switch to" (magit-default-rev))))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if rev
|
2009-06-07 20:41:09 +02:00
|
|
|
(if (not (magit-maybe-create-local-tracking-branch rev))
|
2009-06-06 13:54:30 +02:00
|
|
|
(magit-run-git "checkout" (magit-rev-to-git rev)))))
|
2008-08-21 01:19:58 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-read-create-branch-args ()
|
2008-08-16 23:37:50 +02:00
|
|
|
(let* ((cur-branch (magit-get-current-branch))
|
2008-08-06 00:08:07 +02:00
|
|
|
(branch (read-string "Create branch: "))
|
2008-08-17 00:40:04 +02:00
|
|
|
(parent (magit-read-rev "Parent" cur-branch)))
|
2008-08-06 00:08:07 +02:00
|
|
|
(list branch parent)))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-create-branch (branch parent)
|
|
|
|
(interactive (magit-read-create-branch-args))
|
2008-08-06 01:32:27 +02:00
|
|
|
(if (and branch (not (string= branch ""))
|
2008-08-16 23:37:50 +02:00
|
|
|
parent)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "checkout" "-b"
|
2009-02-15 22:58:10 +01:00
|
|
|
branch
|
|
|
|
(magit-rev-to-git parent))))
|
2008-08-06 00:08:07 +02:00
|
|
|
|
2008-08-06 00:17:34 +02:00
|
|
|
;;; Merging
|
|
|
|
|
2009-02-09 02:58:47 +01:00
|
|
|
(defun magit-guess-branch ()
|
|
|
|
(let ((sec (magit-current-section)))
|
|
|
|
(if (and sec (eq (magit-section-type sec) 'wazzup))
|
|
|
|
(magit-section-info sec))))
|
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-manual-merge (rev)
|
2009-10-28 21:13:28 +01:00
|
|
|
"Merge (without commiting) REV. Given a prefix-arg then the
|
|
|
|
merge will be squashed."
|
|
|
|
(interactive
|
|
|
|
(list (magit-read-rev (concat "Manually merge"
|
|
|
|
(when current-prefix-arg
|
|
|
|
" (squashed)"))
|
|
|
|
(magit-guess-branch))))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if rev
|
2009-10-28 21:13:28 +01:00
|
|
|
(magit-run-git "merge" "--no-commit"
|
|
|
|
(if current-prefix-arg
|
|
|
|
"--squash"
|
|
|
|
"--no-ff")
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-rev-to-git rev))))
|
2008-08-06 00:17:34 +02:00
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-automatic-merge (rev)
|
2009-02-09 02:58:47 +01:00
|
|
|
(interactive (list (magit-read-rev "Merge" (magit-guess-branch))))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if rev
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "merge" (magit-rev-to-git rev))))
|
2008-08-06 00:17:34 +02:00
|
|
|
|
2008-08-13 04:28:16 +02:00
|
|
|
;;; Rebasing
|
|
|
|
|
|
|
|
(defun magit-rebase-info ()
|
2009-03-21 23:55:19 +01:00
|
|
|
(cond ((file-exists-p ".git/rebase-apply")
|
|
|
|
(list (magit-name-rev
|
|
|
|
(car (magit-file-lines ".git/rebase-apply/onto")))
|
|
|
|
(car (magit-file-lines ".git/rebase-apply/next"))
|
|
|
|
(car (magit-file-lines ".git/rebase-apply/last"))))
|
|
|
|
((file-exists-p ".dotest")
|
2008-08-13 04:28:16 +02:00
|
|
|
(list (magit-name-rev (car (magit-file-lines ".dotest/onto")))
|
|
|
|
(car (magit-file-lines ".dotest/next"))
|
|
|
|
(car (magit-file-lines ".dotest/last"))))
|
|
|
|
((file-exists-p ".git/.dotest-merge")
|
|
|
|
(list (car (magit-file-lines ".git/.dotest-merge/onto_name"))
|
|
|
|
(car (magit-file-lines ".git/.dotest-merge/msgnum"))
|
|
|
|
(car (magit-file-lines ".git/.dotest-merge/end"))))
|
|
|
|
(t
|
|
|
|
nil)))
|
|
|
|
|
|
|
|
(defun magit-rebase-step ()
|
|
|
|
(interactive)
|
|
|
|
(let ((info (magit-rebase-info)))
|
|
|
|
(if (not info)
|
2008-08-17 00:40:04 +02:00
|
|
|
(let ((rev (magit-read-rev "Rebase to")))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if rev
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "rebase" (magit-rev-to-git rev))))
|
2008-08-13 04:28:16 +02:00
|
|
|
(let ((cursor-in-echo-area t)
|
|
|
|
(message-log-max nil))
|
|
|
|
(message "Rebase in progress. Abort, Skip, or Continue? ")
|
|
|
|
(let ((reply (read-event)))
|
|
|
|
(case reply
|
|
|
|
((?A ?a)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "rebase" "--abort"))
|
2008-08-13 04:28:16 +02:00
|
|
|
((?S ?s)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "rebase" "--skip"))
|
2008-08-13 04:28:16 +02:00
|
|
|
((?C ?c)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "rebase" "--continue"))))))))
|
2008-08-13 04:28:16 +02:00
|
|
|
|
2008-11-11 11:25:30 +01:00
|
|
|
;; git svn commands
|
|
|
|
|
|
|
|
(defun magit-svn-rebase ()
|
2009-01-24 23:41:03 +01:00
|
|
|
(interactive)
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-run-git-async "svn" "rebase"))
|
2008-11-11 11:25:30 +01:00
|
|
|
|
|
|
|
(defun magit-svn-dcommit ()
|
2009-01-24 23:41:03 +01:00
|
|
|
(interactive)
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-run-git-async "svn" "dcommit"))
|
2008-11-11 11:25:30 +01:00
|
|
|
|
|
|
|
(defun magit-svn-enabled ()
|
2009-10-28 21:37:35 +01:00
|
|
|
(not (null (magit-get-svn-ref-info))))
|
2009-10-28 21:33:35 +01:00
|
|
|
|
2010-03-11 11:32:28 +01:00
|
|
|
(defun magit-get-svn-local-ref (url)
|
|
|
|
(let ((branches (cons (magit-get "svn-remote" "svn" "fetch")
|
|
|
|
(magit-get-all "svn-remote" "svn" "branches")))
|
|
|
|
(base-url (magit-get "svn-remote" "svn" "url"))
|
|
|
|
(result nil))
|
|
|
|
(while branches
|
|
|
|
(let* ((pats (split-string (pop branches) ":"))
|
|
|
|
(src (replace-regexp-in-string "\\*" "\\\\(.*\\\\)" (car pats)))
|
|
|
|
(dst (replace-regexp-in-string "\\*" "\\\\1" (cadr pats)))
|
|
|
|
(base-url (replace-regexp-in-string "\\+" "\\\\+" base-url))
|
|
|
|
(pat1 (concat "^" src "$"))
|
|
|
|
(pat2 (cond ((equal src "") (concat "^" base-url "$"))
|
|
|
|
(t (concat "^" base-url "/" src "$")))))
|
|
|
|
(cond ((string-match pat1 url)
|
|
|
|
(setq result (replace-match dst nil nil url))
|
|
|
|
(setq branches nil))
|
|
|
|
((string-match pat2 url)
|
|
|
|
(setq result (replace-match dst nil nil url))
|
|
|
|
(setq branches nil)))))
|
|
|
|
result))
|
|
|
|
|
2009-10-28 21:37:35 +01:00
|
|
|
(defvar magit-get-svn-ref-info-cache nil
|
|
|
|
"As `magit-get-svn-ref-info' might be considered a quite
|
|
|
|
expensive operation a cache is taken so that `magit-status'
|
|
|
|
doesn't repeatedly call it.")
|
|
|
|
|
|
|
|
(defun magit-get-svn-ref-info (&optional use-cache)
|
2009-10-28 21:33:35 +01:00
|
|
|
"Gather details about the current git-svn repository (nil if
|
|
|
|
there isn't one). Keys of the alist are ref-path, trunk-ref-name
|
2009-10-28 21:37:35 +01:00
|
|
|
and local-ref-name. If USE-CACHE is non-nil then return the value
|
|
|
|
of `magit-get-svn-ref-info-cache'."
|
|
|
|
(if use-cache
|
|
|
|
magit-get-svn-ref-info-cache
|
|
|
|
(let* ((fetch (magit-get "svn-remote" "svn" "fetch"))
|
|
|
|
(url)
|
|
|
|
(revision))
|
|
|
|
(when fetch
|
2010-03-11 11:32:28 +01:00
|
|
|
(let* ((ref (cadr (split-string fetch ":")))
|
|
|
|
(ref-path (file-name-directory ref))
|
|
|
|
(trunk-ref-name (file-name-nondirectory ref)))
|
|
|
|
(setq magit-get-svn-ref-info-cache
|
|
|
|
(list
|
|
|
|
(cons 'ref-path ref-path)
|
|
|
|
(cons 'trunk-ref-name trunk-ref-name)
|
|
|
|
;; get the local ref from the log. This is actually
|
|
|
|
;; the way that git-svn does it.
|
|
|
|
(cons 'local-ref
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert (or (magit-git-string "log" "--first-parent")
|
|
|
|
""))
|
|
|
|
(goto-char (point-min))
|
|
|
|
(cond ((re-search-forward "git-svn-id: \\(.+/.+?\\)@\\([0-9]+\\)" nil t)
|
|
|
|
(setq url (match-string 1)
|
|
|
|
revision (match-string 2))
|
|
|
|
(magit-get-svn-local-ref url))
|
|
|
|
(t
|
|
|
|
(setq url (magit-get "svn-remote" "svn" "url"))
|
|
|
|
nil))))
|
|
|
|
(cons 'revision revision)
|
|
|
|
(cons 'url url))))))))
|
2009-10-28 21:37:35 +01:00
|
|
|
|
|
|
|
(defun magit-get-svn-ref (&optional use-cache)
|
2009-10-28 20:54:11 +01:00
|
|
|
"Get the best guess remote ref for the current git-svn based
|
|
|
|
branch."
|
2009-10-28 21:37:35 +01:00
|
|
|
(let ((info (magit-get-svn-ref-info use-cache)))
|
2010-03-11 11:32:28 +01:00
|
|
|
(cdr (assoc 'local-ref info))))
|
2008-11-11 11:25:30 +01:00
|
|
|
|
2008-08-06 13:41:48 +02:00
|
|
|
;;; Resetting
|
|
|
|
|
2009-03-01 14:06:02 +01:00
|
|
|
(defun magit-reset-head (rev &optional hard)
|
|
|
|
(interactive (list (magit-read-rev (format "%s head to"
|
|
|
|
(if current-prefix-arg
|
|
|
|
"Hard reset"
|
|
|
|
"Reset"))
|
2008-08-20 22:57:51 +02:00
|
|
|
(or (magit-default-rev)
|
2009-03-01 14:06:02 +01:00
|
|
|
"HEAD^"))
|
|
|
|
current-prefix-arg))
|
2008-08-16 23:37:50 +02:00
|
|
|
(if rev
|
2009-03-01 14:06:02 +01:00
|
|
|
(magit-run-git "reset" (if hard "--hard" "--soft")
|
2009-02-21 05:03:15 +01:00
|
|
|
(magit-rev-to-git rev))))
|
2008-08-06 13:48:03 +02:00
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-reset-working-tree ()
|
2008-08-16 23:43:49 +02:00
|
|
|
(interactive)
|
2008-08-16 23:37:50 +02:00
|
|
|
(if (yes-or-no-p "Discard all uncommitted changes? ")
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "reset" "--hard")))
|
2008-08-06 13:41:48 +02:00
|
|
|
|
2008-09-07 21:32:08 +02:00
|
|
|
;;; Rewriting
|
|
|
|
|
|
|
|
(defun magit-read-rewrite-info ()
|
|
|
|
(when (file-exists-p ".git/magit-rewrite-info")
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents ".git/magit-rewrite-info")
|
|
|
|
(goto-char (point-min))
|
|
|
|
(read (current-buffer)))))
|
|
|
|
|
|
|
|
(defun magit-write-rewrite-info (info)
|
|
|
|
(with-temp-file ".git/magit-rewrite-info"
|
|
|
|
(prin1 info (current-buffer))
|
|
|
|
(princ "\n" (current-buffer))))
|
|
|
|
|
|
|
|
(defun magit-insert-pending-commits ()
|
|
|
|
(let* ((info (magit-read-rewrite-info))
|
|
|
|
(pending (cdr (assq 'pending info))))
|
|
|
|
(when pending
|
|
|
|
(magit-with-section 'pending nil
|
|
|
|
(insert (propertize "Pending commits:\n"
|
|
|
|
'face 'magit-section-title))
|
|
|
|
(dolist (p pending)
|
2008-09-08 23:46:42 +02:00
|
|
|
(let* ((commit (car p))
|
|
|
|
(properties (cdr p))
|
|
|
|
(used (plist-get properties 'used)))
|
2009-01-24 23:41:03 +01:00
|
|
|
(magit-with-section commit 'commit
|
|
|
|
(magit-set-section-info commit)
|
2009-02-15 22:58:10 +01:00
|
|
|
(insert (magit-git-string
|
2009-07-15 01:08:52 +02:00
|
|
|
"log" "--max-count=1"
|
|
|
|
(if used
|
|
|
|
"--pretty=format:. %s"
|
|
|
|
"--pretty=format:* %s")
|
|
|
|
commit "--")
|
2009-01-24 23:41:03 +01:00
|
|
|
"\n")))))
|
2008-09-07 21:32:08 +02:00
|
|
|
(insert "\n"))))
|
|
|
|
|
2008-09-08 23:46:42 +02:00
|
|
|
(defun magit-rewrite-set-commit-property (commit prop value)
|
|
|
|
(let* ((info (magit-read-rewrite-info))
|
|
|
|
(pending (cdr (assq 'pending info)))
|
|
|
|
(p (assoc commit pending)))
|
|
|
|
(when p
|
|
|
|
(setf (cdr p) (plist-put (cdr p) prop value))
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-write-rewrite-info info)
|
|
|
|
(magit-need-refresh))))
|
2008-09-08 23:46:42 +02:00
|
|
|
|
2008-09-10 22:57:06 +02:00
|
|
|
(defun magit-rewrite-set-used ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info)
|
2008-09-10 22:57:06 +02:00
|
|
|
((pending commit)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-rewrite-set-commit-property info 'used t))))
|
2008-09-10 22:57:06 +02:00
|
|
|
|
|
|
|
(defun magit-rewrite-set-unused ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info)
|
2008-09-10 22:57:06 +02:00
|
|
|
((pending commit)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-rewrite-set-commit-property info 'used nil))))
|
2008-09-10 22:57:06 +02:00
|
|
|
|
2008-09-08 22:39:55 +02:00
|
|
|
(defun magit-insert-pending-changes ()
|
2008-09-07 22:29:44 +02:00
|
|
|
(let* ((info (magit-read-rewrite-info))
|
|
|
|
(orig (cadr (assq 'orig info))))
|
|
|
|
(when orig
|
2008-09-08 22:31:12 +02:00
|
|
|
(let ((magit-hide-diffs t))
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'pending-changes
|
|
|
|
"Pending changes"
|
|
|
|
'magit-wash-diffs
|
|
|
|
"diff" (magit-diff-U-arg) "-R" orig)))))
|
2008-09-07 22:29:44 +02:00
|
|
|
|
2008-09-07 21:58:37 +02:00
|
|
|
(defun magit-rewrite-start (from &optional onto)
|
|
|
|
(interactive (list (magit-read-rev "Rewrite from" (magit-default-rev))))
|
|
|
|
(or (magit-everything-clean-p)
|
|
|
|
(error "You have uncommitted changes."))
|
|
|
|
(or (not (magit-read-rewrite-info))
|
|
|
|
(error "Rewrite in progress."))
|
2009-07-15 01:08:52 +02:00
|
|
|
(let* ((orig (magit-git-string "rev-parse" "HEAD"))
|
2009-05-17 19:34:09 +02:00
|
|
|
(base (or (car (magit-commit-parents from))
|
|
|
|
(error "Can't rewrite a commit without a parent, sorry.")))
|
2009-07-15 01:08:52 +02:00
|
|
|
(pending (magit-git-lines "rev-list" (concat base ".."))))
|
2008-09-07 21:58:37 +02:00
|
|
|
(magit-write-rewrite-info `((orig ,orig)
|
2008-09-08 23:46:42 +02:00
|
|
|
(pending ,@(mapcar #'list pending))))
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "reset" "--hard" base)))
|
2008-09-07 21:58:37 +02:00
|
|
|
|
2008-09-13 23:48:09 +02:00
|
|
|
(defun magit-rewrite-stop (&optional noconfirm)
|
2008-09-07 22:05:54 +02:00
|
|
|
(interactive)
|
|
|
|
(let* ((info (magit-read-rewrite-info)))
|
|
|
|
(or info
|
|
|
|
(error "No rewrite in progress."))
|
2008-09-13 23:48:09 +02:00
|
|
|
(when (or noconfirm
|
|
|
|
(yes-or-no-p "Stop rewrite? "))
|
2008-09-07 22:05:54 +02:00
|
|
|
(magit-write-rewrite-info nil)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-need-refresh))))
|
2008-09-07 22:05:54 +02:00
|
|
|
|
|
|
|
(defun magit-rewrite-abort ()
|
|
|
|
(interactive)
|
|
|
|
(let* ((info (magit-read-rewrite-info))
|
|
|
|
(orig (cadr (assq 'orig info))))
|
|
|
|
(or info
|
|
|
|
(error "No rewrite in progress."))
|
|
|
|
(or (magit-everything-clean-p)
|
|
|
|
(error "You have uncommitted changes."))
|
|
|
|
(when (yes-or-no-p "Abort rewrite? ")
|
|
|
|
(magit-write-rewrite-info nil)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "reset" "--hard" orig))))
|
2008-09-07 22:05:54 +02:00
|
|
|
|
2008-09-10 23:02:56 +02:00
|
|
|
(defun magit-rewrite-finish ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-with-refresh
|
|
|
|
(magit-rewrite-finish-step t)))
|
2008-09-10 23:02:56 +02:00
|
|
|
|
|
|
|
(defun magit-rewrite-finish-step (first-p)
|
|
|
|
(let ((info (magit-read-rewrite-info)))
|
|
|
|
(or info
|
|
|
|
(error "No rewrite in progress."))
|
|
|
|
(let* ((pending (cdr (assq 'pending info)))
|
|
|
|
(first-unused (find-if (lambda (p)
|
|
|
|
(not (plist-get (cdr p) 'used)))
|
|
|
|
pending
|
2008-09-14 01:11:34 +02:00
|
|
|
:from-end t))
|
|
|
|
(commit (car first-unused)))
|
2008-09-14 00:14:39 +02:00
|
|
|
(cond ((not first-unused)
|
|
|
|
(magit-rewrite-stop t))
|
2009-02-15 22:49:01 +01:00
|
|
|
((magit-apply-commit commit t (not first-p))
|
2008-09-14 01:11:34 +02:00
|
|
|
(magit-rewrite-set-commit-property commit 'used t)
|
2008-09-15 00:55:46 +02:00
|
|
|
(magit-rewrite-finish-step nil))))))
|
2008-09-10 23:02:56 +02:00
|
|
|
|
2008-08-20 23:18:04 +02:00
|
|
|
;;; Updating, pull, and push
|
|
|
|
|
|
|
|
(defun magit-remote-update ()
|
|
|
|
(interactive)
|
2009-02-11 08:26:22 +01:00
|
|
|
(if (magit-svn-enabled)
|
2009-02-28 15:49:23 +01:00
|
|
|
(magit-run-git-async "svn" "fetch")
|
|
|
|
(magit-run-git-async "remote" "update")))
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-pull ()
|
2008-08-05 01:30:32 +02:00
|
|
|
(interactive)
|
2009-03-22 00:21:02 +01:00
|
|
|
(let* ((branch (magit-get-current-branch))
|
|
|
|
(config-branch (and branch (magit-get "branch" branch "merge")))
|
|
|
|
(merge-branch (or config-branch
|
|
|
|
(magit-read-rev (format "Pull from")))))
|
|
|
|
(if (and branch (not config-branch))
|
|
|
|
(magit-set merge-branch "branch" branch "merge"))
|
|
|
|
(magit-run-git-async "pull" "-v")))
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2009-03-06 02:49:30 +01:00
|
|
|
(defun magit-shell-command (command)
|
|
|
|
(interactive "sCommand: ")
|
|
|
|
(require 'pcomplete)
|
|
|
|
(let ((args (car (with-temp-buffer
|
|
|
|
(insert command)
|
|
|
|
(pcomplete-parse-buffer-arguments))))
|
|
|
|
(magit-process-popup-time 0))
|
|
|
|
(magit-run* args nil nil nil t)))
|
|
|
|
|
2008-11-06 23:20:13 +01:00
|
|
|
(defun magit-read-remote (prompt def)
|
2009-10-28 21:19:02 +01:00
|
|
|
(funcall magit-completing-read (if def
|
2008-11-06 23:20:13 +01:00
|
|
|
(format "%s (default %s): " prompt def)
|
|
|
|
(format "%s: " prompt))
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-lines "remote")
|
2008-11-06 23:20:13 +01:00
|
|
|
nil nil nil nil def))
|
2008-11-06 23:00:37 +01:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-push ()
|
2008-08-05 01:30:32 +02:00
|
|
|
(interactive)
|
2008-11-06 23:00:37 +01:00
|
|
|
(let* ((branch (or (magit-get-current-branch)
|
|
|
|
(error "Don't push a detached head. That's gross.")))
|
2008-11-06 23:20:13 +01:00
|
|
|
(branch-remote (magit-get "branch" branch "remote"))
|
|
|
|
(push-remote (if (or current-prefix-arg
|
|
|
|
(not branch-remote))
|
|
|
|
(magit-read-remote (format "Push %s to" branch)
|
|
|
|
branch-remote)
|
|
|
|
branch-remote)))
|
|
|
|
(if (and (not branch-remote)
|
|
|
|
(not current-prefix-arg))
|
|
|
|
(magit-set push-remote "branch" branch "remote"))
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-run-git-async "push" "-v" push-remote branch)))
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2008-10-02 00:12:32 +02:00
|
|
|
;;; Log edit mode
|
2008-08-01 15:04:52 +02:00
|
|
|
|
2008-08-31 16:53:14 +02:00
|
|
|
(defvar magit-log-edit-map
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
(define-key map (kbd "C-c C-c") 'magit-log-edit-commit)
|
|
|
|
(define-key map (kbd "C-c C-a") 'magit-log-edit-toggle-amending)
|
2009-06-06 14:18:15 +02:00
|
|
|
(define-key map (kbd "C-c C-s") 'magit-log-edit-toggle-signoff)
|
2008-09-01 00:10:07 +02:00
|
|
|
(define-key map (kbd "M-p") 'log-edit-previous-comment)
|
|
|
|
(define-key map (kbd "M-n") 'log-edit-next-comment)
|
2009-02-22 03:54:13 +01:00
|
|
|
(define-key map (kbd "C-c C-k") 'magit-log-edit-cancel-log-message)
|
2008-08-31 16:53:14 +02:00
|
|
|
map))
|
2008-08-04 14:35:25 +02:00
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defvar magit-pre-log-edit-window-configuration nil)
|
2008-08-04 14:35:25 +02:00
|
|
|
|
2008-10-02 00:12:32 +02:00
|
|
|
(defun magit-log-fill-paragraph (&optional justify)
|
|
|
|
"Fill the paragraph, but preserve open parentheses at beginning of lines.
|
|
|
|
Prefix arg means justify as well."
|
|
|
|
(interactive "P")
|
|
|
|
;; Add lines starting with a left paren or an asterisk.
|
|
|
|
(let ((paragraph-start (concat paragraph-start "\\|*\\|(")))
|
|
|
|
(let ((end (progn (forward-paragraph) (point)))
|
|
|
|
(beg (progn (backward-paragraph) (point)))
|
|
|
|
(adaptive-fill-mode nil))
|
|
|
|
(fill-region beg end justify)
|
|
|
|
t)))
|
|
|
|
|
|
|
|
(define-derived-mode magit-log-edit-mode text-mode "Magit Log Edit"
|
|
|
|
(set (make-local-variable 'fill-paragraph-function)
|
|
|
|
'magit-log-fill-paragraph)
|
|
|
|
(use-local-map magit-log-edit-map))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-log-edit-cleanup ()
|
2008-08-05 21:30:10 +02:00
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-min))
|
|
|
|
(flush-lines "^#")
|
|
|
|
(goto-char (point-min))
|
2008-08-13 05:14:53 +02:00
|
|
|
(if (re-search-forward "[ \t\n]*\\'" nil t)
|
|
|
|
(replace-match "\n" nil nil))))
|
2008-08-05 21:30:10 +02:00
|
|
|
|
2008-08-31 16:53:14 +02:00
|
|
|
(defun magit-log-edit-append (str)
|
|
|
|
(save-excursion
|
|
|
|
(set-buffer (get-buffer-create "*magit-log-edit*"))
|
|
|
|
(goto-char (point-max))
|
|
|
|
(insert str "\n")))
|
|
|
|
|
2008-11-09 22:13:17 +01:00
|
|
|
(defconst magit-log-header-end "-- End of Magit header --\n")
|
|
|
|
|
2008-08-31 16:53:14 +02:00
|
|
|
(defun magit-log-edit-get-fields ()
|
|
|
|
(let ((buf (get-buffer "*magit-log-edit*"))
|
|
|
|
(result nil))
|
|
|
|
(if buf
|
|
|
|
(save-excursion
|
|
|
|
(set-buffer buf)
|
|
|
|
(goto-char (point-min))
|
2009-02-20 00:15:26 +01:00
|
|
|
(while (looking-at "^\\([A-Za-z0-9-_]+\\): *\\(.*\\)$")
|
2008-08-31 16:53:14 +02:00
|
|
|
(setq result (acons (intern (downcase (match-string 1)))
|
|
|
|
(match-string 2)
|
|
|
|
result))
|
2008-11-09 22:13:17 +01:00
|
|
|
(forward-line))
|
|
|
|
(if (not (looking-at (regexp-quote magit-log-header-end)))
|
|
|
|
(setq result nil))))
|
2008-08-31 16:53:14 +02:00
|
|
|
(nreverse result)))
|
|
|
|
|
|
|
|
(defun magit-log-edit-set-fields (fields)
|
|
|
|
(let ((buf (get-buffer-create "*magit-log-edit*")))
|
|
|
|
(save-excursion
|
|
|
|
(set-buffer buf)
|
|
|
|
(goto-char (point-min))
|
2009-02-20 00:15:26 +01:00
|
|
|
(if (search-forward-regexp (format "^\\([A-Za-z0-9-_]+:.*\n\\)+%s"
|
2008-11-09 22:13:17 +01:00
|
|
|
(regexp-quote magit-log-header-end))
|
|
|
|
nil t)
|
2008-08-31 16:53:14 +02:00
|
|
|
(delete-region (match-beginning 0) (match-end 0)))
|
|
|
|
(goto-char (point-min))
|
|
|
|
(when fields
|
|
|
|
(while fields
|
|
|
|
(insert (capitalize (symbol-name (caar fields))) ": "
|
|
|
|
(cdar fields) "\n")
|
|
|
|
(setq fields (cdr fields)))
|
2008-11-09 22:13:17 +01:00
|
|
|
(insert magit-log-header-end)))))
|
2008-08-31 16:53:14 +02:00
|
|
|
|
|
|
|
(defun magit-log-edit-set-field (name value)
|
|
|
|
(let* ((fields (magit-log-edit-get-fields))
|
|
|
|
(cell (assq name fields)))
|
|
|
|
(cond (cell
|
|
|
|
(if value
|
|
|
|
(rplacd cell value)
|
|
|
|
(setq fields (delq cell fields))))
|
|
|
|
(t
|
|
|
|
(if value
|
2008-08-31 18:16:58 +02:00
|
|
|
(setq fields (append fields (list (cons name value)))))))
|
2008-08-31 16:53:14 +02:00
|
|
|
(magit-log-edit-set-fields fields)))
|
|
|
|
|
2009-02-20 00:17:37 +01:00
|
|
|
(defun magit-log-edit-get-field (name)
|
|
|
|
(cdr (assq name (magit-log-edit-get-fields))))
|
|
|
|
|
2008-08-31 18:34:18 +02:00
|
|
|
(defun magit-log-edit-setup-author-env (author)
|
|
|
|
(cond (author
|
|
|
|
;; XXX - this is a bit strict, probably.
|
|
|
|
(or (string-match "\\(.*\\) <\\(.*\\)>, \\(.*\\)" author)
|
|
|
|
(error "Can't parse author string."))
|
2008-09-03 22:40:42 +02:00
|
|
|
;; Shucks, setenv destroys the match data.
|
|
|
|
(let ((name (match-string 1 author))
|
|
|
|
(email (match-string 2 author))
|
|
|
|
(date (match-string 3 author)))
|
|
|
|
(setenv "GIT_AUTHOR_NAME" name)
|
|
|
|
(setenv "GIT_AUTHOR_EMAIL" email)
|
|
|
|
(setenv "GIT_AUTHOR_DATE" date)))
|
2008-08-31 18:34:18 +02:00
|
|
|
(t
|
|
|
|
(setenv "GIT_AUTHOR_NAME")
|
|
|
|
(setenv "GIT_AUTHOR_EMAIL")
|
|
|
|
(setenv "GIT_AUTHOR_DATE"))))
|
|
|
|
|
2008-09-01 00:10:07 +02:00
|
|
|
(defun magit-log-edit-push-to-comment-ring (comment)
|
|
|
|
(when (or (ring-empty-p log-edit-comment-ring)
|
|
|
|
(not (equal comment (ring-ref log-edit-comment-ring 0))))
|
|
|
|
(ring-insert log-edit-comment-ring comment)))
|
|
|
|
|
2008-08-06 01:41:05 +02:00
|
|
|
(defun magit-log-edit-commit ()
|
2008-08-04 14:35:25 +02:00
|
|
|
(interactive)
|
2008-08-31 17:18:46 +02:00
|
|
|
(let* ((fields (magit-log-edit-get-fields))
|
|
|
|
(amend (equal (cdr (assq 'amend fields)) "yes"))
|
2009-02-20 00:17:37 +01:00
|
|
|
(commit-all (equal (cdr (assq 'commit-all fields)) "yes"))
|
2009-06-06 14:18:15 +02:00
|
|
|
(sign-off-field (assq 'sign-off fields))
|
|
|
|
(sign-off (if sign-off-field
|
|
|
|
(equal (cdr sign-off-field) "yes")
|
|
|
|
magit-commit-signoff))
|
2008-11-06 22:46:29 +01:00
|
|
|
(tag (cdr (assq 'tag fields)))
|
2008-08-31 17:18:46 +02:00
|
|
|
(author (cdr (assq 'author fields))))
|
2008-09-01 00:10:07 +02:00
|
|
|
(magit-log-edit-push-to-comment-ring (buffer-string))
|
2008-08-31 18:34:18 +02:00
|
|
|
(magit-log-edit-setup-author-env author)
|
2008-08-31 17:18:46 +02:00
|
|
|
(magit-log-edit-set-fields nil)
|
|
|
|
(magit-log-edit-cleanup)
|
2008-10-12 02:33:34 +02:00
|
|
|
(if (= (buffer-size) 0)
|
|
|
|
(insert "(Empty description)\n"))
|
|
|
|
(let ((commit-buf (current-buffer)))
|
|
|
|
(with-current-buffer (magit-find-buffer 'status default-directory)
|
2008-11-06 22:46:29 +01:00
|
|
|
(cond (tag
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-run-git-with-input commit-buf "tag" tag "-a" "-F" "-"))
|
2008-11-06 22:46:29 +01:00
|
|
|
(t
|
2009-02-14 23:50:54 +01:00
|
|
|
(apply #'magit-run-async-with-input commit-buf
|
2009-02-15 22:58:10 +01:00
|
|
|
magit-git-executable
|
|
|
|
(append magit-git-standard-options
|
|
|
|
(list "commit" "-F" "-")
|
2009-02-20 00:17:37 +01:00
|
|
|
(if commit-all '("--all") '())
|
2008-12-17 11:23:20 +01:00
|
|
|
(if amend '("--amend") '())
|
2009-06-06 14:18:15 +02:00
|
|
|
(if sign-off '("--signoff") '())))))))
|
2008-09-14 17:27:03 +02:00
|
|
|
(erase-buffer)
|
2008-08-31 17:18:46 +02:00
|
|
|
(bury-buffer)
|
2009-03-06 07:48:39 +01:00
|
|
|
(when (file-exists-p ".git/MERGE_MSG")
|
|
|
|
(delete-file ".git/MERGE_MSG"))
|
2008-08-31 17:18:46 +02:00
|
|
|
(when magit-pre-log-edit-window-configuration
|
|
|
|
(set-window-configuration magit-pre-log-edit-window-configuration)
|
|
|
|
(setq magit-pre-log-edit-window-configuration nil))))
|
2008-08-31 17:30:37 +02:00
|
|
|
|
2009-02-22 03:54:13 +01:00
|
|
|
(defun magit-log-edit-cancel-log-message ()
|
|
|
|
(interactive)
|
|
|
|
(when (or (not magit-log-edit-confirm-cancellation)
|
2009-02-25 14:55:52 +01:00
|
|
|
(yes-or-no-p
|
2009-02-22 03:54:13 +01:00
|
|
|
"Really cancel editing the log (any changes will be lost)?"))
|
|
|
|
(erase-buffer)
|
|
|
|
(bury-buffer)
|
|
|
|
(when magit-pre-log-edit-window-configuration
|
|
|
|
(set-window-configuration magit-pre-log-edit-window-configuration)
|
|
|
|
(setq magit-pre-log-edit-window-configuration nil))))
|
|
|
|
|
2008-08-31 16:53:14 +02:00
|
|
|
(defun magit-log-edit-toggle-amending ()
|
|
|
|
(interactive)
|
|
|
|
(let* ((fields (magit-log-edit-get-fields))
|
|
|
|
(cell (assq 'amend fields)))
|
|
|
|
(if cell
|
2008-08-31 17:18:46 +02:00
|
|
|
(rplacd cell (if (equal (cdr cell) "yes") "no" "yes"))
|
2008-08-31 16:53:14 +02:00
|
|
|
(setq fields (acons 'amend "yes" fields))
|
|
|
|
(magit-log-edit-append
|
|
|
|
(magit-format-commit "HEAD" "%s%n%n%b")))
|
|
|
|
(magit-log-edit-set-fields fields)))
|
|
|
|
|
2009-06-06 14:18:15 +02:00
|
|
|
(defun magit-log-edit-toggle-signoff ()
|
|
|
|
(interactive)
|
|
|
|
(let* ((fields (magit-log-edit-get-fields))
|
|
|
|
(cell (assq 'sign-off fields)))
|
|
|
|
(if cell
|
|
|
|
(rplacd cell (if (equal (cdr cell) "yes") "no" "yes"))
|
|
|
|
(setq fields (acons 'sign-off (if magit-commit-signoff "no" "yes")
|
|
|
|
fields)))
|
|
|
|
(magit-log-edit-set-fields fields)))
|
|
|
|
|
2008-11-06 22:46:29 +01:00
|
|
|
(defun magit-pop-to-log-edit (operation)
|
2008-08-04 14:35:25 +02:00
|
|
|
(let ((dir default-directory)
|
2008-08-29 00:39:01 +02:00
|
|
|
(buf (get-buffer-create "*magit-log-edit*")))
|
2008-08-06 03:18:41 +02:00
|
|
|
(setq magit-pre-log-edit-window-configuration
|
|
|
|
(current-window-configuration))
|
2008-08-04 14:35:25 +02:00
|
|
|
(pop-to-buffer buf)
|
2009-03-06 07:48:39 +01:00
|
|
|
(when (file-exists-p ".git/MERGE_MSG")
|
|
|
|
(insert-file-contents ".git/MERGE_MSG"))
|
2008-08-04 14:35:25 +02:00
|
|
|
(setq default-directory dir)
|
2008-10-02 00:12:32 +02:00
|
|
|
(magit-log-edit-mode)
|
2009-02-22 03:54:13 +01:00
|
|
|
(message "Type C-c C-c to %s (C-c C-k to cancel)." operation)))
|
2008-11-06 22:46:29 +01:00
|
|
|
|
|
|
|
(defun magit-log-edit ()
|
|
|
|
(interactive)
|
2009-03-21 23:55:19 +01:00
|
|
|
(cond ((magit-rebase-info)
|
|
|
|
(if (y-or-n-p "Rebase in progress. Continue it? ")
|
|
|
|
(magit-run-git "rebase" "--continue")))
|
|
|
|
(t
|
|
|
|
(magit-log-edit-set-field 'tag nil)
|
|
|
|
(when (and magit-commit-all-when-nothing-staged
|
|
|
|
(not (magit-anything-staged-p)))
|
|
|
|
(cond ((eq magit-commit-all-when-nothing-staged 'ask-stage)
|
|
|
|
(if (and (not (magit-everything-clean-p))
|
|
|
|
(y-or-n-p "Nothing staged. Stage everything now? "))
|
|
|
|
(magit-stage-all)))
|
|
|
|
((not (magit-log-edit-get-field 'commit-all))
|
|
|
|
(magit-log-edit-set-field
|
|
|
|
'commit-all
|
|
|
|
(if (or (eq magit-commit-all-when-nothing-staged t)
|
|
|
|
(y-or-n-p
|
|
|
|
"Nothing staged. Commit all unstaged changes? "))
|
|
|
|
"yes" "no")))))
|
|
|
|
(magit-pop-to-log-edit "commit"))))
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2008-08-11 02:23:54 +02:00
|
|
|
(defun magit-add-log ()
|
|
|
|
(interactive)
|
2009-03-21 23:55:19 +01:00
|
|
|
(cond ((magit-rebase-info)
|
|
|
|
(if (y-or-n-p "Rebase in progress. Continue it? ")
|
|
|
|
(magit-run-git "rebase" "--continue")))
|
|
|
|
(t
|
|
|
|
(let ((section (magit-current-section)))
|
|
|
|
(let ((fun (if (eq (magit-section-type section) 'hunk)
|
|
|
|
(save-window-excursion
|
|
|
|
(save-excursion
|
|
|
|
(magit-visit-item)
|
|
|
|
(add-log-current-defun)))
|
|
|
|
nil))
|
|
|
|
(file (magit-diff-item-file
|
|
|
|
(cond ((eq (magit-section-type section) 'hunk)
|
|
|
|
(magit-hunk-item-diff section))
|
|
|
|
((eq (magit-section-type section) 'diff)
|
|
|
|
section)
|
|
|
|
(t
|
|
|
|
(error "No change at point"))))))
|
|
|
|
(magit-log-edit)
|
|
|
|
(goto-char (point-min))
|
|
|
|
(cond ((not (search-forward-regexp
|
|
|
|
(format "^\\* %s" (regexp-quote file)) nil t))
|
|
|
|
;; No entry for file, create it.
|
|
|
|
(goto-char (point-max))
|
|
|
|
(insert (format "\n* %s" file))
|
|
|
|
(if fun
|
|
|
|
(insert (format " (%s)" fun)))
|
|
|
|
(insert ": "))
|
|
|
|
(fun
|
|
|
|
;; found entry for file, look for fun
|
|
|
|
(let ((limit (or (save-excursion
|
|
|
|
(and (search-forward-regexp "^\\* "
|
|
|
|
nil t)
|
|
|
|
(match-beginning 0)))
|
|
|
|
(point-max))))
|
|
|
|
(cond ((search-forward-regexp (format "(.*\\<%s\\>.*):"
|
|
|
|
(regexp-quote fun))
|
|
|
|
limit t)
|
|
|
|
;; found it, goto end of current entry
|
|
|
|
(if (search-forward-regexp "^(" limit t)
|
|
|
|
(backward-char 2)
|
|
|
|
(goto-char limit)))
|
|
|
|
(t
|
|
|
|
;; not found, insert new entry
|
|
|
|
(goto-char limit)
|
|
|
|
(if (bolp)
|
|
|
|
(open-line 1)
|
|
|
|
(newline))
|
|
|
|
(insert (format "(%s): " fun))))))))))))
|
2008-08-11 02:23:54 +02:00
|
|
|
|
2008-11-06 22:46:29 +01:00
|
|
|
;;; Tags
|
|
|
|
|
|
|
|
(defun magit-tag (name)
|
|
|
|
(interactive "sNew tag name: ")
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "tag" name))
|
2008-11-06 22:46:29 +01:00
|
|
|
|
|
|
|
(defun magit-annotated-tag (name)
|
|
|
|
(interactive "sNew tag name: ")
|
|
|
|
(magit-log-edit-set-field 'tag name)
|
|
|
|
(magit-pop-to-log-edit "tag"))
|
|
|
|
|
2008-11-09 23:06:13 +01:00
|
|
|
;;; Stashing
|
|
|
|
|
|
|
|
(defun magit-wash-stash ()
|
|
|
|
(if (search-forward-regexp "stash@{\\(.*\\)}" (line-end-position) t)
|
|
|
|
(let ((stash (match-string-no-properties 0))
|
|
|
|
(name (match-string-no-properties 1)))
|
|
|
|
(delete-region (match-beginning 0) (match-end 0))
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
(fixup-whitespace)
|
|
|
|
(goto-char (line-beginning-position))
|
|
|
|
(insert name)
|
|
|
|
(goto-char (line-beginning-position))
|
|
|
|
(magit-with-section stash 'stash
|
|
|
|
(magit-set-section-info stash)
|
|
|
|
(forward-line)))
|
|
|
|
(forward-line))
|
|
|
|
t)
|
|
|
|
|
|
|
|
(defun magit-wash-stashes ()
|
|
|
|
(let ((magit-old-top-section nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-stash)))
|
|
|
|
|
|
|
|
(defun magit-insert-stashes ()
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'stashes
|
|
|
|
"Stashes:" 'magit-wash-stashes
|
|
|
|
"stash" "list"))
|
2008-11-09 23:06:13 +01:00
|
|
|
|
|
|
|
(defun magit-stash (description)
|
|
|
|
(interactive "sStash description: ")
|
2010-03-10 22:19:46 +01:00
|
|
|
(apply 'magit-run-git `("stash"
|
|
|
|
"save"
|
|
|
|
,@(when current-prefix-arg '("--keep-index"))
|
|
|
|
,description)))
|
2008-11-09 23:06:13 +01:00
|
|
|
|
2009-02-11 08:37:08 +01:00
|
|
|
(defun magit-stash-snapshot ()
|
|
|
|
(interactive)
|
2009-02-15 19:00:35 +01:00
|
|
|
(magit-with-refresh
|
|
|
|
(magit-run-git "stash" "save"
|
|
|
|
(format-time-string "Snapshot taken at %Y-%m-%d %H:%M:%S"
|
|
|
|
(current-time)))
|
|
|
|
(magit-run-git "stash" "apply" "stash@{0}")))
|
2009-02-11 08:37:08 +01:00
|
|
|
|
2009-02-05 21:42:15 +01:00
|
|
|
(defvar magit-currently-shown-stash nil)
|
|
|
|
|
|
|
|
(defun magit-show-stash (stash &optional scroll)
|
|
|
|
(when (magit-section-p stash)
|
|
|
|
(setq stash (magit-section-info stash)))
|
|
|
|
(let ((dir default-directory)
|
2009-02-15 02:23:45 +01:00
|
|
|
(buf (get-buffer-create "*magit-stash*")))
|
2009-02-05 21:42:15 +01:00
|
|
|
(cond ((equal magit-currently-shown-stash stash)
|
|
|
|
(let ((win (get-buffer-window buf)))
|
|
|
|
(cond ((not win)
|
|
|
|
(display-buffer buf))
|
|
|
|
(scroll
|
|
|
|
(with-selected-window win
|
|
|
|
(funcall scroll))))))
|
|
|
|
(t
|
|
|
|
(setq magit-currently-shown-stash stash)
|
|
|
|
(display-buffer buf)
|
|
|
|
(with-current-buffer buf
|
|
|
|
(set-buffer buf)
|
|
|
|
(goto-char (point-min))
|
2009-02-15 19:07:13 +01:00
|
|
|
(let* ((range (cons (concat stash "^2^") stash))
|
2009-02-05 21:42:15 +01:00
|
|
|
(args (magit-rev-range-to-git range)))
|
|
|
|
(magit-mode-init dir 'diff #'magit-refresh-diff-buffer
|
|
|
|
range args)))))))
|
|
|
|
|
2009-03-06 03:55:13 +01:00
|
|
|
;;; Topic branches (using topgit)
|
|
|
|
|
|
|
|
(defun magit-wash-topic ()
|
|
|
|
(if (search-forward-regexp "^..\\(t/\\S-+\\)\\s-+\\(\\S-+\\)\\s-+\\(\\S-+\\)"
|
|
|
|
(line-end-position) t)
|
|
|
|
(let ((topic (match-string 1)))
|
|
|
|
(delete-region (match-beginning 2) (match-end 2))
|
|
|
|
(goto-char (line-beginning-position))
|
|
|
|
(delete-char 4)
|
|
|
|
(insert "\t")
|
|
|
|
(goto-char (line-beginning-position))
|
|
|
|
(magit-with-section topic 'topic
|
|
|
|
(magit-set-section-info topic)
|
|
|
|
(forward-line)))
|
|
|
|
(delete-region (line-beginning-position) (1+ (line-end-position))))
|
|
|
|
t)
|
|
|
|
|
|
|
|
(defun magit-wash-topics ()
|
|
|
|
(let ((magit-old-top-section nil))
|
|
|
|
(magit-wash-sequence #'magit-wash-topic)))
|
|
|
|
|
|
|
|
(defun magit-insert-topics ()
|
|
|
|
(magit-git-section 'topics
|
|
|
|
"Topics:" 'magit-wash-topics
|
|
|
|
"branch" "-v"))
|
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
;;; Commits
|
2008-08-11 04:10:10 +02:00
|
|
|
|
2008-08-17 00:37:48 +02:00
|
|
|
(defun magit-commit-at-point (&optional nil-ok-p)
|
2008-09-07 01:00:26 +02:00
|
|
|
(let* ((section (magit-current-section))
|
|
|
|
(commit (and (eq (magit-section-type section) 'commit)
|
|
|
|
(magit-section-info section))))
|
2008-08-17 00:37:48 +02:00
|
|
|
(if nil-ok-p
|
|
|
|
commit
|
|
|
|
(or commit
|
|
|
|
(error "No commit at point.")))))
|
2008-08-11 04:10:10 +02:00
|
|
|
|
2009-02-15 22:49:01 +01:00
|
|
|
(defun magit-apply-commit (commit &optional docommit noerase revert)
|
|
|
|
(let* ((parent-id (magit-choose-parent-id commit "cherry-pick"))
|
|
|
|
(success (magit-run* `(,magit-git-executable
|
|
|
|
,@magit-git-standard-options
|
|
|
|
,(if revert "revert" "cherry-pick")
|
|
|
|
,@(if parent-id
|
|
|
|
(list "-m" (number-to-string parent-id)))
|
|
|
|
,@(if (not docommit) (list "--no-commit"))
|
|
|
|
,commit)
|
|
|
|
nil noerase)))
|
|
|
|
(when (or (not docommit) success)
|
|
|
|
(cond (revert
|
|
|
|
(magit-log-edit-append
|
|
|
|
(magit-format-commit commit "Reverting \"%s\"")))
|
|
|
|
(t
|
|
|
|
(magit-log-edit-append
|
|
|
|
(magit-format-commit commit "%s%n%n%b"))
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-log-edit-set-field
|
2009-02-15 22:49:01 +01:00
|
|
|
'author
|
|
|
|
(magit-format-commit commit "%an <%ae>, %ai")))))
|
|
|
|
success))
|
2008-09-08 23:41:36 +02:00
|
|
|
|
2008-08-24 04:28:38 +02:00
|
|
|
(defun magit-apply-item ()
|
2008-08-11 04:10:10 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "apply")
|
2008-09-08 23:41:36 +02:00
|
|
|
((pending commit)
|
2008-09-14 20:42:01 +02:00
|
|
|
(magit-apply-commit info)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-rewrite-set-commit-property info 'used t))
|
2008-08-24 04:28:38 +02:00
|
|
|
((commit)
|
2008-09-13 22:18:12 +02:00
|
|
|
(magit-apply-commit info))
|
|
|
|
((unstaged *)
|
|
|
|
(error "Change is already in your working tree"))
|
|
|
|
((staged *)
|
|
|
|
(error "Change is already in your working tree"))
|
|
|
|
((hunk)
|
|
|
|
(magit-apply-hunk-item item))
|
|
|
|
((diff)
|
2008-11-09 23:06:13 +01:00
|
|
|
(magit-apply-diff-item item))
|
|
|
|
((stash)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "stash" "apply" info))))
|
2008-08-11 04:10:10 +02:00
|
|
|
|
2008-09-15 00:17:12 +02:00
|
|
|
(defun magit-cherry-pick-item ()
|
2008-08-30 20:37:01 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "cherry-pick")
|
2008-09-08 23:41:36 +02:00
|
|
|
((pending commit)
|
2009-02-15 22:49:01 +01:00
|
|
|
(magit-apply-commit info t)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-rewrite-set-commit-property info 'used t))
|
2008-08-30 20:37:01 +02:00
|
|
|
((commit)
|
2009-02-15 22:49:01 +01:00
|
|
|
(magit-apply-commit info t))
|
2008-11-09 23:06:13 +01:00
|
|
|
((stash)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "stash" "pop" info))))
|
2008-09-08 23:41:36 +02:00
|
|
|
|
2008-08-24 04:28:38 +02:00
|
|
|
(defun magit-revert-item ()
|
2008-08-11 17:32:07 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "revert")
|
2008-09-08 23:41:36 +02:00
|
|
|
((pending commit)
|
2009-02-15 22:49:01 +01:00
|
|
|
(magit-apply-commit info nil nil t)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-rewrite-set-commit-property info 'used nil))
|
2008-08-24 04:28:38 +02:00
|
|
|
((commit)
|
2009-02-15 22:49:01 +01:00
|
|
|
(magit-apply-commit info nil nil t))
|
2008-09-13 22:18:12 +02:00
|
|
|
((hunk)
|
2009-02-15 01:58:26 +01:00
|
|
|
(magit-apply-hunk-item-reverse item))
|
2008-09-13 22:18:12 +02:00
|
|
|
((diff)
|
|
|
|
(magit-apply-diff-item item "--reverse"))))
|
2008-08-11 17:32:07 +02:00
|
|
|
|
2008-10-29 18:02:20 +01:00
|
|
|
(defvar magit-have-graph 'unset)
|
2008-10-26 18:59:56 +01:00
|
|
|
(defvar magit-have-decorate 'unset)
|
2009-03-08 02:42:33 +01:00
|
|
|
(make-variable-buffer-local 'magit-have-graph)
|
|
|
|
(put 'magit-have-graph 'permanent-local t)
|
|
|
|
(make-variable-buffer-local 'magit-have-decorate)
|
|
|
|
(put 'magit-have-decorate 'permanent-local t)
|
2008-10-29 18:02:20 +01:00
|
|
|
|
|
|
|
(defun magit-configure-have-graph ()
|
|
|
|
(if (eq magit-have-graph 'unset)
|
2009-07-15 01:08:52 +02:00
|
|
|
(let ((res (magit-git-exit-code "log" "--graph" "--max-count=0")))
|
2008-10-29 18:02:20 +01:00
|
|
|
(setq magit-have-graph (eq res 0)))))
|
|
|
|
|
2008-10-26 18:59:56 +01:00
|
|
|
(defun magit-configure-have-decorate ()
|
|
|
|
(if (eq magit-have-decorate 'unset)
|
2009-11-07 19:37:43 +01:00
|
|
|
(let ((res (magit-git-exit-code "log" "--decorate=full" "--max-count=0")))
|
2008-10-26 18:59:56 +01:00
|
|
|
(setq magit-have-decorate (eq res 0)))))
|
|
|
|
|
2009-02-04 01:31:55 +01:00
|
|
|
(defun magit-refresh-log-buffer (range style args)
|
2008-10-29 18:02:20 +01:00
|
|
|
(magit-configure-have-graph)
|
2008-10-26 18:59:56 +01:00
|
|
|
(magit-configure-have-decorate)
|
2008-09-13 21:51:54 +02:00
|
|
|
(magit-create-buffer-sections
|
2009-02-15 22:58:10 +01:00
|
|
|
(apply #'magit-git-section nil
|
2008-10-29 18:02:20 +01:00
|
|
|
(magit-rev-range-describe range "Commits")
|
2009-01-18 23:55:26 +01:00
|
|
|
'magit-wash-log
|
2009-02-15 22:58:10 +01:00
|
|
|
`("log"
|
|
|
|
,(format "--max-count=%s" magit-log-cutoff-length)
|
|
|
|
,style
|
2009-11-07 19:37:43 +01:00
|
|
|
,@(if magit-have-decorate (list "--decorate=full"))
|
2008-10-29 18:02:20 +01:00
|
|
|
,@(if magit-have-graph (list "--graph"))
|
2008-12-04 15:22:18 +01:00
|
|
|
,args "--"))))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2009-02-04 01:31:55 +01:00
|
|
|
(defun magit-log (&optional arg)
|
|
|
|
(interactive "P")
|
|
|
|
(let* ((range (if arg
|
2009-02-05 21:23:57 +01:00
|
|
|
(magit-read-rev-range "Log" "HEAD")
|
2009-02-04 01:31:55 +01:00
|
|
|
"HEAD"))
|
|
|
|
(topdir (magit-get-top-dir default-directory))
|
|
|
|
(args (magit-rev-range-to-git range)))
|
|
|
|
(switch-to-buffer "*magit-log*")
|
|
|
|
(magit-mode-init topdir 'log #'magit-refresh-log-buffer range
|
|
|
|
"--pretty=oneline" args)))
|
|
|
|
|
|
|
|
(defun magit-log-long (&optional arg)
|
|
|
|
(interactive "P")
|
|
|
|
(let* ((range (if arg
|
2009-02-05 21:23:57 +01:00
|
|
|
(magit-read-rev-range "Long log" "HEAD")
|
2009-02-04 01:31:55 +01:00
|
|
|
"HEAD"))
|
|
|
|
(topdir (magit-get-top-dir default-directory))
|
|
|
|
(args (magit-rev-range-to-git range)))
|
|
|
|
(switch-to-buffer "*magit-log*")
|
|
|
|
(magit-mode-init topdir 'log #'magit-refresh-log-buffer range
|
|
|
|
"--stat" args)))
|
2008-08-12 01:42:13 +02:00
|
|
|
|
2008-08-31 17:47:26 +02:00
|
|
|
;;; Reflog
|
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-refresh-reflog-buffer (head args)
|
|
|
|
(magit-create-buffer-sections
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'reflog
|
|
|
|
(format "Local history of head %s" head)
|
|
|
|
'magit-wash-log
|
|
|
|
"log" "--walk-reflogs"
|
|
|
|
(format "--max-count=%s" magit-log-cutoff-length)
|
|
|
|
"--pretty=oneline"
|
|
|
|
args)))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2008-08-31 17:47:26 +02:00
|
|
|
(defun magit-reflog (head)
|
|
|
|
(interactive (list (magit-read-rev "Reflog of" "HEAD")))
|
|
|
|
(if head
|
|
|
|
(let* ((topdir (magit-get-top-dir default-directory))
|
|
|
|
(args (magit-rev-to-git head)))
|
|
|
|
(switch-to-buffer "*magit-reflog*")
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-mode-init topdir 'reflog
|
2008-09-13 21:51:54 +02:00
|
|
|
#'magit-refresh-reflog-buffer head args))))
|
2008-08-31 17:47:26 +02:00
|
|
|
|
|
|
|
(defun magit-reflog-head ()
|
|
|
|
(interactive)
|
|
|
|
(magit-reflog "HEAD"))
|
|
|
|
|
2008-08-12 01:42:13 +02:00
|
|
|
;;; Diffing
|
|
|
|
|
2008-09-13 21:51:54 +02:00
|
|
|
(defun magit-refresh-diff-buffer (range args)
|
|
|
|
(magit-create-buffer-sections
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-git-section 'diffbuf
|
|
|
|
(magit-rev-range-describe range "Changes")
|
|
|
|
'magit-wash-diffs
|
|
|
|
"diff" (magit-diff-U-arg) args)))
|
2008-09-13 21:51:54 +02:00
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-diff (range)
|
|
|
|
(interactive (list (magit-read-rev-range "Diff")))
|
|
|
|
(if range
|
|
|
|
(let* ((dir default-directory)
|
|
|
|
(args (magit-rev-range-to-git range))
|
|
|
|
(buf (get-buffer-create "*magit-diff*")))
|
|
|
|
(display-buffer buf)
|
|
|
|
(save-excursion
|
|
|
|
(set-buffer buf)
|
2008-09-13 21:51:54 +02:00
|
|
|
(magit-mode-init dir 'diff #'magit-refresh-diff-buffer range args)))))
|
2008-08-16 23:37:50 +02:00
|
|
|
|
2008-08-17 01:35:05 +02:00
|
|
|
(defun magit-diff-working-tree (rev)
|
2008-10-25 21:36:19 +02:00
|
|
|
(interactive (list (magit-read-rev "Diff with (default HEAD)")))
|
|
|
|
(magit-diff (or rev "HEAD")))
|
2008-08-12 02:14:54 +02:00
|
|
|
|
2008-08-16 23:37:50 +02:00
|
|
|
(defun magit-diff-with-mark ()
|
|
|
|
(interactive)
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-diff (cons (magit-marked-commit)
|
2008-08-16 23:37:50 +02:00
|
|
|
(magit-commit-at-point))))
|
2008-08-12 01:42:13 +02:00
|
|
|
|
2009-01-24 19:57:53 +01:00
|
|
|
;;; Wazzup
|
|
|
|
|
2009-03-08 13:41:52 +01:00
|
|
|
(defun magit-wazzup-toggle-ignore (branch edit)
|
2009-03-01 20:26:41 +01:00
|
|
|
(let ((ignore-file ".git/info/wazzup-exclude"))
|
|
|
|
(if edit
|
|
|
|
(setq branch (read-string "Branch to ignore for wazzup: " branch)))
|
2009-03-08 13:41:52 +01:00
|
|
|
(let ((ignored (magit-file-lines ignore-file)))
|
|
|
|
(cond ((member branch ignored)
|
|
|
|
(when (or (not edit)
|
|
|
|
(y-or-n-p "Branch %s is already ignored. Unignore?"))
|
|
|
|
(setq ignored (delete branch ignored))))
|
|
|
|
(t
|
|
|
|
(setq ignored (append ignored (list branch)))))
|
|
|
|
(magit-write-file-lines ignore-file ignored)
|
|
|
|
(magit-need-refresh))))
|
2009-03-01 20:26:41 +01:00
|
|
|
|
|
|
|
(defun magit-refresh-wazzup-buffer (head all)
|
2009-01-24 19:57:53 +01:00
|
|
|
(magit-create-buffer-sections
|
|
|
|
(magit-with-section 'wazzupbuf nil
|
|
|
|
(insert (format "Wazzup, %s\n\n" head))
|
2009-03-01 20:26:41 +01:00
|
|
|
(let* ((excluded (magit-file-lines ".git/info/wazzup-exclude"))
|
2009-06-06 13:26:18 +02:00
|
|
|
(all-branches (magit-list-interesting-refs))
|
2009-03-01 20:26:41 +01:00
|
|
|
(branches (if all all-branches
|
2009-06-06 13:26:18 +02:00
|
|
|
(remove-if (lambda (b) (member (cdr b) excluded))
|
2009-03-01 20:26:41 +01:00
|
|
|
all-branches)))
|
|
|
|
(reported (make-hash-table :test #'equal)))
|
2009-06-06 13:26:18 +02:00
|
|
|
(dolist (branch branches)
|
|
|
|
(let* ((name (car branch))
|
|
|
|
(ref (cdr branch))
|
2009-07-15 01:08:52 +02:00
|
|
|
(hash (magit-git-string "rev-parse" ref))
|
2009-02-18 06:28:57 +01:00
|
|
|
(reported-branch (gethash hash reported)))
|
|
|
|
(unless (or (and reported-branch
|
2009-06-06 13:26:18 +02:00
|
|
|
(string= (file-name-nondirectory ref)
|
2009-02-18 06:28:57 +01:00
|
|
|
reported-branch))
|
2009-07-15 01:08:52 +02:00
|
|
|
(not (magit-git-string "merge-base" head ref)))
|
2009-06-06 13:26:18 +02:00
|
|
|
(puthash hash (file-name-nondirectory ref) reported)
|
2009-07-15 01:08:52 +02:00
|
|
|
(let* ((n (length (magit-git-lines "log" "--pretty=oneline"
|
|
|
|
(concat head ".." ref))))
|
2009-02-18 06:28:57 +01:00
|
|
|
(section
|
|
|
|
(let ((magit-section-hidden-default t))
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-git-section
|
2009-06-06 13:26:18 +02:00
|
|
|
(cons ref 'wazzup)
|
2009-03-01 20:26:41 +01:00
|
|
|
(format "%s unmerged commits in %s%s"
|
2009-06-06 13:26:18 +02:00
|
|
|
n name
|
|
|
|
(if (member ref excluded)
|
2009-03-01 20:26:41 +01:00
|
|
|
" (normally ignored)"
|
|
|
|
""))
|
2009-02-18 06:28:57 +01:00
|
|
|
'magit-wash-log
|
|
|
|
"log"
|
|
|
|
(format "--max-count=%s" magit-log-cutoff-length)
|
|
|
|
"--pretty=oneline"
|
2009-06-06 13:26:18 +02:00
|
|
|
(format "%s..%s" head ref)
|
2009-02-18 06:28:57 +01:00
|
|
|
"--"))))
|
2009-06-06 13:26:18 +02:00
|
|
|
(magit-set-section-info ref section)))))))))
|
2009-01-24 19:57:53 +01:00
|
|
|
|
2009-03-01 20:26:41 +01:00
|
|
|
(defun magit-wazzup (&optional all)
|
|
|
|
(interactive "P")
|
2009-01-24 19:57:53 +01:00
|
|
|
(let* ((topdir (magit-get-top-dir default-directory)))
|
|
|
|
(switch-to-buffer "*magit-wazzup*")
|
2009-02-25 14:55:52 +01:00
|
|
|
(magit-mode-init topdir 'wazzup
|
2009-02-05 21:50:19 +01:00
|
|
|
#'magit-refresh-wazzup-buffer
|
2009-03-01 20:26:41 +01:00
|
|
|
(magit-get-current-branch) all)))
|
2009-01-24 19:57:53 +01:00
|
|
|
|
2008-08-06 02:22:22 +02:00
|
|
|
;;; Miscellaneous
|
2008-08-04 01:05:02 +02:00
|
|
|
|
2008-10-12 01:10:06 +02:00
|
|
|
(defun magit-ignore-file (file edit local)
|
|
|
|
(let ((ignore-file (if local ".git/info/exclude" ".gitignore")))
|
|
|
|
(if edit
|
|
|
|
(setq file (read-string "File to ignore: " file)))
|
2010-03-12 16:06:13 +01:00
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents ignore-file)
|
|
|
|
(goto-char (point-max))
|
2010-03-12 16:43:08 +01:00
|
|
|
(unless (bolp)
|
|
|
|
(insert "\n"))
|
2010-03-12 16:06:13 +01:00
|
|
|
(insert "/" file "\n")
|
|
|
|
(write-region nil nil ignore-file))
|
2008-10-12 01:10:06 +02:00
|
|
|
(magit-need-refresh)))
|
|
|
|
|
2008-08-21 01:19:58 +02:00
|
|
|
(defun magit-ignore-item ()
|
2008-08-04 01:05:02 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "ignore")
|
2008-10-12 01:10:06 +02:00
|
|
|
((untracked file)
|
2009-01-25 00:04:51 +01:00
|
|
|
(magit-ignore-file info current-prefix-arg nil))
|
|
|
|
((wazzup)
|
2009-03-08 13:41:52 +01:00
|
|
|
(magit-wazzup-toggle-ignore info current-prefix-arg))))
|
2008-10-12 01:10:06 +02:00
|
|
|
|
|
|
|
(defun magit-ignore-item-locally ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-action (item info "ignore")
|
|
|
|
((untracked file)
|
|
|
|
(magit-ignore-file info current-prefix-arg t))))
|
2008-08-06 02:22:22 +02:00
|
|
|
|
2009-06-06 18:42:02 +02:00
|
|
|
(defun magit-discard-diff (diff stagedp)
|
2008-10-12 02:06:40 +02:00
|
|
|
(let ((kind (magit-diff-item-kind diff))
|
|
|
|
(file (magit-diff-item-file diff)))
|
2008-10-12 01:50:49 +02:00
|
|
|
(cond ((eq kind 'deleted)
|
|
|
|
(when (yes-or-no-p (format "Resurrect %s? " file))
|
2009-02-15 22:58:10 +01:00
|
|
|
(magit-run-git "reset" "-q" "--" file)
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "checkout" "--" file)))
|
2008-10-12 01:50:49 +02:00
|
|
|
((eq kind 'new)
|
|
|
|
(if (yes-or-no-p (format "Delete %s? " file))
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "rm" "-f" "--" file)))
|
2008-10-12 01:50:49 +02:00
|
|
|
(t
|
|
|
|
(if (yes-or-no-p (format "Discard changes to %s? " file))
|
2009-06-06 18:42:02 +02:00
|
|
|
(if stagedp
|
|
|
|
(magit-run-git "checkout" "HEAD" "--" file)
|
|
|
|
(magit-run-git "checkout" "--" file)))))))
|
2008-10-12 01:50:49 +02:00
|
|
|
|
2008-08-21 01:41:43 +02:00
|
|
|
(defun magit-discard-item ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "discard")
|
2008-10-12 01:10:06 +02:00
|
|
|
((untracked file)
|
2008-08-30 23:28:58 +02:00
|
|
|
(if (yes-or-no-p (format "Delete %s? " info))
|
2008-09-14 17:30:52 +02:00
|
|
|
(magit-run "rm" info)))
|
2009-02-15 01:06:06 +01:00
|
|
|
((untracked)
|
|
|
|
(if (yes-or-no-p "Delete all untracked files and directories? ")
|
|
|
|
(magit-run "git" "clean" "-df")))
|
2008-09-07 01:00:26 +02:00
|
|
|
((unstaged diff hunk)
|
2009-02-15 19:15:46 +01:00
|
|
|
(when (yes-or-no-p (if (magit-use-region-p)
|
|
|
|
"Discard changes in region? "
|
|
|
|
"Discard hunk? "))
|
2009-02-15 01:58:26 +01:00
|
|
|
(magit-apply-hunk-item-reverse item)))
|
2008-09-07 01:00:26 +02:00
|
|
|
((staged diff hunk)
|
2008-09-07 15:31:51 +02:00
|
|
|
(if (magit-file-uptodate-p (magit-diff-item-file
|
|
|
|
(magit-hunk-item-diff item)))
|
2009-02-15 19:15:46 +01:00
|
|
|
(when (yes-or-no-p (if (magit-use-region-p)
|
|
|
|
"Discard changes in region? "
|
|
|
|
"Discard hunk? "))
|
2009-02-15 01:58:26 +01:00
|
|
|
(magit-apply-hunk-item-reverse item "--index"))
|
2008-09-07 01:00:26 +02:00
|
|
|
(error "Can't discard this hunk. Please unstage it first.")))
|
2008-10-12 01:50:49 +02:00
|
|
|
((unstaged diff)
|
2009-06-06 18:42:02 +02:00
|
|
|
(magit-discard-diff item nil))
|
2008-10-12 01:50:49 +02:00
|
|
|
((staged diff)
|
2009-06-07 20:42:20 +02:00
|
|
|
(if (magit-file-uptodate-p (magit-diff-item-file item))
|
|
|
|
(magit-discard-diff item t)
|
|
|
|
(error "Can't discard staged changes to this file. Please unstage it first.")))
|
2008-10-12 01:50:49 +02:00
|
|
|
((hunk)
|
|
|
|
(error "Can't discard this hunk"))
|
2008-08-30 19:54:51 +02:00
|
|
|
((diff)
|
2008-11-09 23:06:13 +01:00
|
|
|
(error "Can't discard this diff"))
|
|
|
|
((stash)
|
|
|
|
(when (yes-or-no-p "Discard stash? ")
|
2009-02-08 22:06:49 +01:00
|
|
|
(magit-run-git "stash" "drop" info)))))
|
2009-01-24 23:41:03 +01:00
|
|
|
|
2008-08-21 01:19:58 +02:00
|
|
|
(defun magit-visit-item ()
|
2008-08-06 02:22:22 +02:00
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info "visit")
|
2008-10-12 01:10:06 +02:00
|
|
|
((untracked file)
|
2008-09-07 01:00:26 +02:00
|
|
|
(find-file info))
|
|
|
|
((diff)
|
2008-09-07 19:24:41 +02:00
|
|
|
(find-file (magit-diff-item-file item)))
|
2008-09-07 01:00:26 +02:00
|
|
|
((hunk)
|
2008-09-07 15:44:18 +02:00
|
|
|
(let ((file (magit-diff-item-file (magit-hunk-item-diff item)))
|
2008-09-07 01:00:26 +02:00
|
|
|
(line (magit-hunk-item-target-line item)))
|
2008-08-24 01:31:49 +02:00
|
|
|
(find-file file)
|
2008-09-07 01:00:26 +02:00
|
|
|
(goto-line line)))
|
2008-08-24 01:31:49 +02:00
|
|
|
((commit)
|
2008-08-24 02:33:24 +02:00
|
|
|
(magit-show-commit info)
|
2009-02-03 21:33:43 +01:00
|
|
|
(pop-to-buffer "*magit-commit*"))
|
|
|
|
((stash)
|
2009-02-05 21:42:15 +01:00
|
|
|
(magit-show-stash info)
|
2009-03-06 03:55:13 +01:00
|
|
|
(pop-to-buffer "*magit-diff*"))
|
|
|
|
((topic)
|
|
|
|
(magit-checkout info))))
|
2008-08-24 02:01:29 +02:00
|
|
|
|
|
|
|
(defun magit-show-item-or-scroll-up ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info)
|
2008-08-24 02:01:29 +02:00
|
|
|
((commit)
|
2009-02-05 21:42:15 +01:00
|
|
|
(magit-show-commit info #'scroll-up))
|
|
|
|
((stash)
|
2009-02-11 09:07:44 +01:00
|
|
|
(magit-show-stash info #'scroll-up))
|
|
|
|
(t
|
|
|
|
(scroll-up))))
|
2008-08-24 02:01:29 +02:00
|
|
|
|
|
|
|
(defun magit-show-item-or-scroll-down ()
|
|
|
|
(interactive)
|
2008-09-21 15:09:11 +02:00
|
|
|
(magit-section-action (item info)
|
2008-08-24 02:01:29 +02:00
|
|
|
((commit)
|
2009-02-05 21:42:15 +01:00
|
|
|
(magit-show-commit info #'scroll-down))
|
|
|
|
((stash)
|
2009-02-11 09:07:44 +01:00
|
|
|
(magit-show-stash info #'scroll-down))
|
|
|
|
(t
|
|
|
|
(scroll-down))))
|
2008-08-06 02:22:22 +02:00
|
|
|
|
2009-01-21 23:45:41 +01:00
|
|
|
(defun magit-mark-item (&optional unmark)
|
|
|
|
(interactive "P")
|
|
|
|
(if unmark
|
|
|
|
(magit-set-marked-commit nil)
|
|
|
|
(magit-section-action (item info "mark")
|
|
|
|
((commit)
|
|
|
|
(magit-set-marked-commit (if (eq magit-marked-commit info)
|
|
|
|
nil
|
|
|
|
info))))))
|
2008-09-07 01:00:26 +02:00
|
|
|
|
2008-08-21 01:19:58 +02:00
|
|
|
(defun magit-describe-item ()
|
2008-08-06 14:48:55 +02:00
|
|
|
(interactive)
|
2008-09-07 01:00:26 +02:00
|
|
|
(let ((section (magit-current-section)))
|
2009-02-15 01:06:53 +01:00
|
|
|
(message "Section: %s %s-%s %S %S %S"
|
2008-09-07 01:00:26 +02:00
|
|
|
(magit-section-type section)
|
|
|
|
(magit-section-beginning section)
|
|
|
|
(magit-section-end section)
|
|
|
|
(magit-section-title section)
|
2009-02-15 01:06:53 +01:00
|
|
|
(magit-section-info section)
|
|
|
|
(magit-section-context-type section))))
|
2008-08-21 01:41:43 +02:00
|
|
|
|
2008-10-26 18:47:23 +01:00
|
|
|
(defun magit-copy-item-as-kill ()
|
|
|
|
"Copy sha1 of commit at point into kill ring."
|
|
|
|
(interactive)
|
|
|
|
(magit-section-action (item info "copy")
|
|
|
|
((commit)
|
|
|
|
(kill-new info)
|
|
|
|
(message "%s" info))))
|
|
|
|
|
2009-01-27 22:08:12 +01:00
|
|
|
(defun magit-interactive-rebase ()
|
|
|
|
"Start a git rebase -i session, old school-style."
|
|
|
|
(interactive)
|
|
|
|
(server-start)
|
|
|
|
(let* ((section (get-text-property (point) 'magit-section))
|
|
|
|
(commit (and (member 'commit (magit-section-context-type section))
|
2009-02-04 01:31:55 +01:00
|
|
|
(magit-section-info section)))
|
2009-01-27 22:08:12 +01:00
|
|
|
(old-editor (getenv "GIT_EDITOR")))
|
|
|
|
(setenv "GIT_EDITOR" (expand-file-name "emacsclient" exec-directory))
|
|
|
|
(unwind-protect
|
2009-07-15 01:08:52 +02:00
|
|
|
(magit-run-git-async "rebase" "-i"
|
|
|
|
(or (and commit (concat commit "^"))
|
|
|
|
(read-string "Interactively rebase to: ")))
|
2009-01-27 22:08:12 +01:00
|
|
|
(if old-editor
|
|
|
|
(setenv "GIT_EDITOR" old-editor)))))
|
|
|
|
|
2009-01-27 22:46:35 +01:00
|
|
|
(defun magit-show-branches ()
|
|
|
|
"Show all of the current branches in other-window."
|
|
|
|
(interactive)
|
|
|
|
(save-selected-window
|
|
|
|
(switch-to-buffer-other-window "*magit-branches*")
|
|
|
|
(erase-buffer)
|
2009-07-15 01:08:52 +02:00
|
|
|
(insert (magit-git-string "branch" "-va"))
|
|
|
|
(insert "\n")))
|
2009-01-27 22:46:35 +01:00
|
|
|
|
2009-02-25 14:55:52 +01:00
|
|
|
(defvar magit-ediff-file)
|
|
|
|
(defvar magit-ediff-windows)
|
|
|
|
|
|
|
|
(defun magit-interactive-resolve (file)
|
2009-07-15 01:08:52 +02:00
|
|
|
(let ((merge-status (magit-git-string "ls-files" "-u" "--" file))
|
2009-02-25 14:55:52 +01:00
|
|
|
(base-buffer (generate-new-buffer (concat file ".base")))
|
2009-03-02 10:43:56 +01:00
|
|
|
(our-buffer (generate-new-buffer (concat file ".current")))
|
|
|
|
(their-buffer (generate-new-buffer (concat file ".merged")))
|
2009-02-25 14:55:52 +01:00
|
|
|
(windows (current-window-configuration)))
|
|
|
|
(if (null merge-status)
|
2009-07-14 23:48:26 +02:00
|
|
|
(error "Cannot resolve %s" file))
|
2009-02-25 14:55:52 +01:00
|
|
|
(with-current-buffer base-buffer
|
|
|
|
(if (string-match "^[0-9]+ [0-9a-f]+ 1" merge-status)
|
2009-07-15 01:08:52 +02:00
|
|
|
(insert (magit-git-string "cat-file" "blob"
|
|
|
|
(concat ":1:" file)))))
|
2009-02-25 14:55:52 +01:00
|
|
|
(with-current-buffer our-buffer
|
|
|
|
(if (string-match "^[0-9]+ [0-9a-f]+ 2" merge-status)
|
2009-07-15 01:08:52 +02:00
|
|
|
(insert (magit-git-string "cat-file" "blob"
|
|
|
|
(concat ":2:" file)))))
|
2009-02-25 14:55:52 +01:00
|
|
|
(with-current-buffer their-buffer
|
|
|
|
(if (string-match "^[0-9]+ [0-9a-f]+ 3" merge-status)
|
2009-07-15 01:08:52 +02:00
|
|
|
(insert (magit-git-string "cat-file" "blob"
|
|
|
|
(concat ":3:" file)))))
|
2009-02-25 14:55:52 +01:00
|
|
|
;; We have now created the 3 buffer with ours, theirs and the ancestor files
|
|
|
|
(with-current-buffer (ediff-merge-buffers-with-ancestor our-buffer their-buffer base-buffer)
|
|
|
|
(make-local-variable 'magit-ediff-file)
|
|
|
|
(setq magit-ediff-file file)
|
|
|
|
(make-local-variable 'magit-ediff-windows)
|
|
|
|
(setq magit-ediff-windows windows)
|
|
|
|
(make-local-variable 'ediff-quit-hook)
|
|
|
|
(add-hook 'ediff-quit-hook
|
|
|
|
(lambda ()
|
|
|
|
(let ((buffer-A ediff-buffer-A)
|
|
|
|
(buffer-B ediff-buffer-B)
|
|
|
|
(buffer-C ediff-buffer-C)
|
|
|
|
(buffer-Ancestor ediff-ancestor-buffer)
|
|
|
|
(file magit-ediff-file)
|
|
|
|
(windows magit-ediff-windows))
|
|
|
|
(ediff-cleanup-mess)
|
|
|
|
(find-file file)
|
|
|
|
(erase-buffer)
|
|
|
|
(insert-buffer-substring buffer-C)
|
|
|
|
(kill-buffer buffer-A)
|
|
|
|
(kill-buffer buffer-B)
|
|
|
|
(kill-buffer buffer-C)
|
|
|
|
(when (bufferp buffer-Ancestor) (kill-buffer buffer-Ancestor))
|
|
|
|
(set-window-configuration windows)
|
|
|
|
(message "Conflict resolution finished; you may save the buffer")))))))
|
|
|
|
|
|
|
|
|
|
|
|
(defun magit-interactive-resolve-item ()
|
|
|
|
(interactive)
|
|
|
|
(magit-section-action (item info "resolv")
|
|
|
|
((diff)
|
|
|
|
(magit-interactive-resolve (cadr info)))))
|
|
|
|
|
2010-03-14 15:42:50 +01:00
|
|
|
(provide 'magit)
|