Merge branch 'master' into more-buffer-info
This commit is contained in:
commit
f1fdbd7b83
7 changed files with 674 additions and 319 deletions
|
@ -1,17 +1,18 @@
|
|||
lispdir = $(datadir)/emacs/site-lisp
|
||||
sitestartdir = @SITESTART@
|
||||
|
||||
lisp_DATA = magit.el magit.elc
|
||||
lisp_DATA = magit.el magit.elc magit-svn.el magit-svn.elc magit-topgit.el magit-topgit.elc
|
||||
sitestart_DATA = 50magit.el
|
||||
|
||||
info_TEXINFOS = magit.texi
|
||||
|
||||
CLEANFILES = magit.elc
|
||||
EXTRA_DIST = magit.el 50magit.el magit.spec
|
||||
CLEANFILES = magit-*.elc
|
||||
EXTRA_DIST = magit.el 50magit.el magit.spec magit-svn.el magit-topgit.el
|
||||
|
||||
%.elc: %.el
|
||||
@if [ $(builddir) != $(srcdir) ]; then ln $(srcdir)/$*.el .; fi
|
||||
emacs --batch --eval '(byte-compile-file "$*.el")'
|
||||
emacs --batch --eval "(add-to-list 'load-path \"$(srcdir)\")" \
|
||||
--eval '(byte-compile-file "$*.el")'
|
||||
@if [ $(builddir) != $(srcdir) ]; then rm -f $*.el; fi
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
|
||||
set -e
|
||||
|
||||
function configure_ac_ver_ok {
|
||||
cat configure.ac | grep "${1}" || return 1
|
||||
}
|
||||
|
||||
function magit_el_ver_ok {
|
||||
grep -e ";; Version: *$1" magit.el || return 1
|
||||
}
|
||||
|
||||
USAGE="usage: ${0##*/} <tag>"
|
||||
|
||||
tag="${1}"
|
||||
|
@ -20,6 +28,20 @@ fi
|
|||
# grab that tag
|
||||
git co "${tag}"
|
||||
|
||||
# correct version in magit?
|
||||
if ! magit_el_ver_ok "$tag"; then
|
||||
echo "Please set version in magit.el to $tag"
|
||||
git co master
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# correct version in configure.ac?
|
||||
if ! configure_ac_ver_ok "$tag"; then
|
||||
echo "Please set AC_INIT to $tag in configure.ac"
|
||||
git co master
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# clean up if we need to
|
||||
[ -f Makefile ] && make distclean
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT(magit, 0.8.1)
|
||||
AC_INIT(magit, 0.8.2)
|
||||
AC_CONFIG_SRCDIR([magit.el])
|
||||
AM_INIT_AUTOMAKE([1.10])
|
||||
|
||||
|
|
185
magit-svn.el
Normal file
185
magit-svn.el
Normal file
|
@ -0,0 +1,185 @@
|
|||
;;; magit-svn.el --- git-svn plug-in for Magit
|
||||
|
||||
;; Copyright (C) 2008, 2009 Marius Vollmer
|
||||
;; Copyright (C) 2008 Linh Dang
|
||||
;; Copyright (C) 2008 Alex Ott
|
||||
;; Copyright (C) 2008 Marcin Bachry
|
||||
;; Copyright (C) 2009 Alexey Voinov
|
||||
;; Copyright (C) 2009 John Wiegley
|
||||
;; Copyright (C) 2010 Yann Hodique
|
||||
;;
|
||||
;; Magit is free software; you can redistribute it and/or modify it
|
||||
;; 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.
|
||||
;;
|
||||
;; Magit is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
;; License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with Magit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This plug-in provides git-svn functionality as a separate component of Magit
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'magit)
|
||||
|
||||
;; git svn commands
|
||||
|
||||
(defun magit-svn-find-rev (rev &optional branch)
|
||||
(interactive
|
||||
(list (read-string "SVN revision: ")
|
||||
(if current-prefix-arg
|
||||
(read-string "In branch: "))))
|
||||
(let* ((sha (apply 'magit-git-string
|
||||
`("svn"
|
||||
"find-rev"
|
||||
,(concat "r" rev)
|
||||
,@(when branch (list branch))))))
|
||||
(if sha
|
||||
(magit-show-commit
|
||||
(magit-with-section sha 'commit
|
||||
(magit-set-section-info sha)
|
||||
sha))
|
||||
(error "Revision %s could not be mapped to a commit" rev))))
|
||||
|
||||
(defun magit-svn-rebase ()
|
||||
(interactive)
|
||||
(magit-run-git-async "svn" "rebase"))
|
||||
|
||||
(defun magit-svn-dcommit ()
|
||||
(interactive)
|
||||
(magit-run-git-async "svn" "dcommit"))
|
||||
|
||||
(defun magit-svn-enabled ()
|
||||
(not (null (magit-svn-get-ref-info))))
|
||||
|
||||
(defun magit-svn-get-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))
|
||||
|
||||
(defvar magit-svn-get-ref-info-cache nil
|
||||
"A cache for svn-ref-info.
|
||||
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-svn-get-ref-info (&optional use-cache)
|
||||
"Gather details about the current git-svn repository.
|
||||
Return nil if there isn't one. Keys of the alist are ref-path,
|
||||
trunk-ref-name 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-svn-get-ref-info-cache
|
||||
(let* ((fetch (magit-get "svn-remote" "svn" "fetch"))
|
||||
(url)
|
||||
(revision))
|
||||
(when fetch
|
||||
(let* ((ref (cadr (split-string fetch ":")))
|
||||
(ref-path (file-name-directory ref))
|
||||
(trunk-ref-name (file-name-nondirectory ref)))
|
||||
(setq magit-svn-get-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-svn-get-local-ref url))
|
||||
(t
|
||||
(setq url (magit-get "svn-remote" "svn" "url"))
|
||||
nil))))
|
||||
(cons 'revision revision)
|
||||
(cons 'url url))))))))
|
||||
|
||||
(defun magit-svn-get-ref (&optional use-cache)
|
||||
"Get the best guess remote ref for the current git-svn based branch.
|
||||
If USE-CACHE is non nil, use the cached information."
|
||||
(let ((info (magit-svn-get-ref-info use-cache)))
|
||||
(cdr (assoc 'local-ref info))))
|
||||
|
||||
(magit-define-inserter svn-unpulled (&optional use-cache)
|
||||
(when (magit-svn-get-ref-info)
|
||||
(magit-git-section 'svn-unpulled
|
||||
"Unpulled commits (SVN):" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "HEAD..%s" (magit-svn-get-ref use-cache)))))
|
||||
|
||||
(magit-define-inserter svn-unpushed (&optional use-cache)
|
||||
(when (magit-svn-get-ref-info)
|
||||
(magit-git-section 'svn-unpushed
|
||||
"Unpushed commits (SVN):" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "%s..HEAD" (magit-svn-get-ref use-cache)))))
|
||||
|
||||
(magit-define-section-jumper svn-unpushed "Unpushed commits (SVN)")
|
||||
|
||||
(defun magit-svn-remote-string ()
|
||||
(let ((svn-info (magit-svn-get-ref-info)))
|
||||
(when svn-info
|
||||
(concat (cdr (assoc 'url svn-info))
|
||||
" @ "
|
||||
(cdr (assoc 'revision svn-info))))))
|
||||
|
||||
(defun magit-svn-remote-update ()
|
||||
(interactive)
|
||||
(when (magit-svn-enabled)
|
||||
(magit-run-git-async "svn" "fetch")))
|
||||
|
||||
(defvar magit-svn-extension-keys
|
||||
`((,(kbd "N r") . magit-svn-rebase)
|
||||
(,(kbd "N c") . magit-svn-dcommit)
|
||||
(,(kbd "N f") . magit-svn-remote-update)
|
||||
(,(kbd "N s") . magit-svn-find-rev)))
|
||||
|
||||
(easy-menu-define magit-svn-extension-menu
|
||||
nil
|
||||
"Git SVN extension menu"
|
||||
'("Git SVN"
|
||||
["Rebase" magit-svn-rebase (magit-svn-enabled)]
|
||||
["Fetch" magit-svn-remote-update (magit-svn-enabled)]
|
||||
["Commit" magit-svn-dcommit (magit-svn-enabled)]))
|
||||
|
||||
(defvar magit-svn-extension-inserters
|
||||
'((:after unpulled-commits (lambda () (magit-insert-svn-unpulled t)))
|
||||
(:after unpushed-commits (lambda () (magit-insert-svn-unpushed t)))))
|
||||
|
||||
(defvar magit-svn-extension
|
||||
(make-magit-extension :keys magit-svn-extension-keys
|
||||
:menu magit-svn-extension-menu
|
||||
:insert magit-svn-extension-inserters
|
||||
:remote-string 'magit-svn-remote-string))
|
||||
|
||||
(magit-install-extension magit-svn-extension)
|
||||
|
||||
(provide 'magit-svn)
|
||||
;;; magit-svn.el ends here
|
99
magit-topgit.el
Normal file
99
magit-topgit.el
Normal file
|
@ -0,0 +1,99 @@
|
|||
;;; magit-topgit.el --- topgit plug-in for Magit
|
||||
|
||||
;; Copyright (C) 2008, 2009 Marius Vollmer
|
||||
;; Copyright (C) 2008 Linh Dang
|
||||
;; Copyright (C) 2008 Alex Ott
|
||||
;; Copyright (C) 2008 Marcin Bachry
|
||||
;; Copyright (C) 2009 Alexey Voinov
|
||||
;; Copyright (C) 2009 John Wiegley
|
||||
;; Copyright (C) 2010 Yann Hodique
|
||||
;;
|
||||
;; Magit is free software; you can redistribute it and/or modify it
|
||||
;; 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.
|
||||
;;
|
||||
;; Magit is distributed in the hope that it will be useful, but WITHOUT
|
||||
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
;; License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with Magit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This plug-in provides topgit functionality as a separate component of Magit
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'magit)
|
||||
|
||||
(defcustom magit-topgit-executable "tg"
|
||||
"The name of the TopGit executable."
|
||||
:group 'magit
|
||||
:type 'string)
|
||||
|
||||
;;; Topic branches (using topgit)
|
||||
|
||||
(defun magit-topgit-create-branch (branch parent)
|
||||
(when (zerop (or (string-match "t/" branch) -1))
|
||||
(magit-run* (list magit-topgit-executable "create"
|
||||
branch (magit-rev-to-git parent))
|
||||
nil nil nil t)
|
||||
t))
|
||||
|
||||
(defun magit-topgit-pull ()
|
||||
(when (file-exists-p ".topdeps")
|
||||
(magit-run* (list magit-topgit-executable "update")
|
||||
nil nil nil t)
|
||||
t))
|
||||
|
||||
(defun magit-topgit-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-topgit-wash-topics ()
|
||||
(let ((magit-old-top-section nil))
|
||||
(magit-wash-sequence #'magit-topgit-wash-topic)))
|
||||
|
||||
(magit-define-inserter topics ()
|
||||
(magit-git-section 'topics
|
||||
"Topics:" 'magit-topgit-wash-topics
|
||||
"branch" "-v"))
|
||||
|
||||
(defvar magit-topgit-extension-inserters
|
||||
'((:after stashes magit-insert-topics)))
|
||||
|
||||
(defvar magit-topgit-extension-actions
|
||||
'(("discard" ((topic)
|
||||
(when (yes-or-no-p "Discard topic? ")
|
||||
(magit-run* (list magit-topgit-executable "delete" "-f" info)
|
||||
nil nil nil t))))
|
||||
("visit" ((topic)
|
||||
(magit-checkout info)))))
|
||||
|
||||
(defvar magit-topgit-extension-commands
|
||||
'((create-branch . magit-topgit-create-branch)
|
||||
(pull . magit-topgit-pull)))
|
||||
|
||||
(defvar magit-topgit-extension
|
||||
(make-magit-extension :actions magit-topgit-extension-actions
|
||||
:insert magit-topgit-extension-inserters
|
||||
:commands magit-topgit-extension-commands))
|
||||
|
||||
(magit-install-extension magit-topgit-extension)
|
||||
|
||||
(provide 'magit-topgit)
|
||||
;;; magit-topgit.el ends here
|
489
magit.el
489
magit.el
|
@ -25,10 +25,11 @@
|
|||
;; Copyright (C) 2009 Steve Purcell.
|
||||
;; Copyright (C) 2010 Ævar Arnfjörð Bjarmason.
|
||||
;; Copyright (C) 2010 Óscar Fuentes.
|
||||
;; Copyright (C) 2010 Yann Hodique
|
||||
|
||||
;; Author: Marius Vollmer <marius.vollmer@nokia.com>
|
||||
;; Maintainer: Phil Jackson <phil@shellarchive.co.uk>
|
||||
;; Version: 0.8.1
|
||||
;; Version: 0.8.2
|
||||
;; Keywords: tools
|
||||
|
||||
;;
|
||||
|
@ -150,6 +151,22 @@ after a confirmation."
|
|||
:group 'magit
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom magit-remote-ref-format 'branch-then-remote
|
||||
"What format to use for autocompleting refs, in pariticular for remotes.
|
||||
|
||||
Autocompletion is used by functions like `magit-checkout',
|
||||
`magit-interactive-rebase' and others which offer branch name
|
||||
completion.
|
||||
|
||||
The value 'name-then-remote means remotes will be of the
|
||||
form \"name (remote)\", while the value 'remote-slash-name
|
||||
means that they'll be of the form \"remote/name\". I.e. something that's
|
||||
listed as \"remotes/upstream/next\" by \"git branch -l -a\"
|
||||
will be \"upstream/next\"."
|
||||
:group 'magit
|
||||
:type '(choice (const :tag "name (remote)" branch-then-remote)
|
||||
(const :tag "remote/name" remote-slash-branch)))
|
||||
|
||||
(defcustom magit-process-connection-type (not (eq system-type 'cygwin))
|
||||
"Connection type used for the git process.
|
||||
|
||||
|
@ -342,6 +359,10 @@ Many Magit faces inherit from this one by default."
|
|||
(make-variable-buffer-local 'magit-submode)
|
||||
(put 'magit-submode 'permanent-local t)
|
||||
|
||||
(eval-when-compile
|
||||
(defun magit-dynamic-clauses-helper (clauses context)
|
||||
`(((magit-dynamic-clauses ,clauses ,context) t))))
|
||||
|
||||
(defun magit-use-region-p ()
|
||||
(if (fboundp 'use-region-p)
|
||||
(use-region-p)
|
||||
|
@ -511,12 +532,42 @@ return nil."
|
|||
(or (magit-get-top-dir default-directory)
|
||||
default-directory)))))
|
||||
|
||||
(defun magit-rev-parse (ref)
|
||||
"Return the SHA hash for REF."
|
||||
(magit-git-string "rev-parse" ref))
|
||||
|
||||
(defun magit-ref-ambiguous-p (ref)
|
||||
"Return whether or not REF is ambiguous."
|
||||
;; If REF is ambiguous, rev-parse just prints errors,
|
||||
;; so magit-git-string returns nil.
|
||||
(not (magit-git-string "rev-parse" "--abbrev-ref" ref)))
|
||||
|
||||
(defun magit-name-rev (rev)
|
||||
(and rev
|
||||
(let ((name (magit-git-string "name-rev" "--name-only" rev)))
|
||||
(if (or (not name) (string= name "undefined"))
|
||||
rev
|
||||
name))))
|
||||
"Return a human-readable name for REV.
|
||||
Unlike git name-rev, this will remove tags/ and remotes/ prefixes
|
||||
if that can be done unambiguously. In addition, it will filter
|
||||
out revs involving HEAD."
|
||||
(when rev
|
||||
(let ((name (magit-git-string "name-rev" "--no-undefined" "--name-only" rev)))
|
||||
;; There doesn't seem to be a way of filtering HEAD out from name-rev,
|
||||
;; so we have to do it manually.
|
||||
;; HEAD-based names are too transient to allow.
|
||||
(when (string-match "^\\(.*\\<HEAD\\)\\([~^].*\\|$\\)" name)
|
||||
(let ((head-ref (match-string 1 name))
|
||||
(modifier (match-string 2 name)))
|
||||
;; Sometimes when name-rev gives a HEAD-based name,
|
||||
;; rev-parse will give an actual branch or remote name.
|
||||
(setq name (concat (magit-git-string "rev-parse" "--abbrev-ref" head-ref)
|
||||
modifier))
|
||||
;; If rev-parse doesn't give us what we want, just use the SHA.
|
||||
(when (or (null name) (string-match-p "\\<HEAD\\>" name))
|
||||
(setq name (magit-rev-parse rev)))))
|
||||
(setq rev (or name rev))
|
||||
(when (string-match "^\\(?:tags\\|remotes\\)/\\(.*\\)" rev)
|
||||
(let ((plain-name (match-string 1 rev)))
|
||||
(unless (magit-ref-ambiguous-p plain-name)
|
||||
(setq rev plain-name))))
|
||||
rev)))
|
||||
|
||||
(defun magit-put-line-property (prop val)
|
||||
(put-text-property (line-beginning-position) (line-beginning-position 2)
|
||||
|
@ -584,12 +635,20 @@ pair (START . END), then the range is START..END.")
|
|||
(let ((branch (match-string 1 ref)))
|
||||
(push (cons branch branch) refs)))
|
||||
((string-match "refs/tags/\\(.*\\)" ref)
|
||||
(push (cons (format "%s (tag)" (match-string 1 ref)) ref)
|
||||
(push (cons (format
|
||||
(if (eq magit-remote-ref-format 'branch-then-remote)
|
||||
"%s (tag)" "%s")
|
||||
(match-string 1 ref))
|
||||
ref)
|
||||
refs))
|
||||
((string-match "refs/remotes/\\([^/]+\\)/\\(.+\\)" ref)
|
||||
(push (cons (format "%s (%s)"
|
||||
(push (cons (if (eq magit-remote-ref-format 'branch-then-remote)
|
||||
(format "%s (%s)"
|
||||
(match-string 2 ref)
|
||||
(match-string 1 ref))
|
||||
(format "%s/%s"
|
||||
(match-string 1 ref)
|
||||
(match-string 2 ref)))
|
||||
ref)
|
||||
refs))))))
|
||||
refs))
|
||||
|
@ -1167,6 +1226,18 @@ TITLE is the displayed title of the section."
|
|||
(interactive)
|
||||
(magit-goto-section '(,sym)))))
|
||||
|
||||
(defmacro magit-define-inserter (sym arglist &rest body)
|
||||
(declare (indent defun))
|
||||
(let ((fun (intern (format "magit-insert-%s" sym)))
|
||||
(before (intern (format "magit-insert-%s:before-hook" sym)))
|
||||
(after (intern (format "magit-insert-%s:after-hook" sym)))
|
||||
(doc (format "Insert items for `%s'." sym)))
|
||||
`(defun ,fun ,arglist
|
||||
,doc
|
||||
(run-hooks ',before)
|
||||
,@body
|
||||
(run-hooks ',after))))
|
||||
|
||||
(defvar magit-highlight-overlay nil)
|
||||
|
||||
(defvar magit-highlighted-section nil)
|
||||
|
@ -1209,6 +1280,23 @@ TITLE is the displayed title of the section."
|
|||
(equal (car prefix) (car list))
|
||||
(magit-prefix-p (cdr prefix) (cdr list))))))
|
||||
|
||||
(defun magit-inline-clause (clause context)
|
||||
(if (eq (car clause) t)
|
||||
clause
|
||||
(let ((prefix (reverse (car clause)))
|
||||
(body (cdr clause)))
|
||||
`((magit-prefix-p ',prefix ,context)
|
||||
,@body))))
|
||||
|
||||
(defun magit-dynamic-clauses (clauses context)
|
||||
(let* ((c (car clauses))
|
||||
(prefix (reverse (car c)))
|
||||
(body (cadr c)))
|
||||
(cond ((magit-prefix-p prefix context)
|
||||
(eval body))
|
||||
(t
|
||||
(magit-dynamic-clauses (cdr clauses) context)))))
|
||||
|
||||
(defmacro magit-section-case (head &rest clauses)
|
||||
"Make different action depending of current section.
|
||||
|
||||
|
@ -1224,11 +1312,13 @@ where SECTION-TYPE describe section where BODY will be run."
|
|||
(info (cadr head))
|
||||
(type (make-symbol "*type*"))
|
||||
(context (make-symbol "*context*"))
|
||||
(extra (make-symbol "*extra*"))
|
||||
(opname (caddr head)))
|
||||
`(let* ((,section (magit-current-section))
|
||||
(,info (magit-section-info ,section))
|
||||
(,type (magit-section-type ,section))
|
||||
(,context (magit-section-context-type ,section)))
|
||||
(,context (magit-section-context-type ,section))
|
||||
(,extra (magit-get-extensions-actions ,opname)))
|
||||
(cond ,@(mapcar (lambda (clause)
|
||||
(if (eq (car clause) t)
|
||||
clause
|
||||
|
@ -1237,6 +1327,7 @@ where SECTION-TYPE describe section where BODY will be run."
|
|||
`((magit-prefix-p ',prefix ,context)
|
||||
,@body))))
|
||||
clauses)
|
||||
,@(magit-dynamic-clauses-helper extra context)
|
||||
,@(if opname
|
||||
`(((not ,type)
|
||||
(error "Nothing to %s here" ,opname))
|
||||
|
@ -1258,6 +1349,27 @@ FUNC should leave point at the end of the modified region"
|
|||
(while (and (not (eobp))
|
||||
(funcall func))))
|
||||
|
||||
(defmacro magit-define-command (sym arglist &rest body)
|
||||
(declare (indent defun))
|
||||
(let ((fun (intern (format "magit-%s" sym)))
|
||||
(hook (intern (format "magit-%s:functions" sym)))
|
||||
(doc (format "Command for `%s'." sym))
|
||||
(inter nil)
|
||||
(instr body))
|
||||
(when (stringp (car body))
|
||||
(setq doc (car body)
|
||||
instr (cdr body)))
|
||||
(let ((form (car instr)))
|
||||
(when (eq (car form) 'interactive)
|
||||
(setq inter form
|
||||
instr (cdr instr))))
|
||||
`(defun ,fun ,arglist
|
||||
,doc
|
||||
,inter
|
||||
(or (run-hook-with-args-until-success
|
||||
',hook ,@(remq '&optional (remq '&rest arglist)))
|
||||
,@instr))))
|
||||
|
||||
;;; Running commands
|
||||
|
||||
(defun magit-set-mode-line-process (str)
|
||||
|
@ -1448,7 +1560,6 @@ FUNC should leave point at the end of the modified region"
|
|||
(magit-define-section-jumper unstaged "Unstaged changes")
|
||||
(magit-define-section-jumper staged "Staged changes")
|
||||
(magit-define-section-jumper unpushed "Unpushed commits")
|
||||
(magit-define-section-jumper svn-unpushed "Unpushed commits (SVN)")
|
||||
|
||||
(magit-define-level-shower 1)
|
||||
(magit-define-level-shower 2)
|
||||
|
@ -1484,9 +1595,6 @@ FUNC should leave point at the end of the modified region"
|
|||
(define-key map (kbd "SPC") 'magit-show-item-or-scroll-up)
|
||||
(define-key map (kbd "DEL") 'magit-show-item-or-scroll-down)
|
||||
(define-key map (kbd "C-w") 'magit-copy-item-as-kill)
|
||||
(define-key map (kbd "N r") 'magit-svn-rebase)
|
||||
(define-key map (kbd "N c") 'magit-svn-dcommit)
|
||||
(define-key map (kbd "N f") 'magit-svn-find-rev)
|
||||
(define-key map (kbd "R") 'magit-rebase-step)
|
||||
(define-key map (kbd "r s") 'magit-rewrite-start)
|
||||
(define-key map (kbd "r t") 'magit-rewrite-stop)
|
||||
|
@ -1660,10 +1768,6 @@ FUNC should leave point at the end of the modified region"
|
|||
["Merge (no commit)" magit-manual-merge t]
|
||||
["Interactive resolve" magit-interactive-resolve-item t]
|
||||
["Rebase" magit-rebase-step t]
|
||||
("Git SVN"
|
||||
["Rebase" magit-svn-rebase (magit-svn-enabled)]
|
||||
["Commit" magit-svn-dcommit (magit-svn-enabled)]
|
||||
)
|
||||
("Rewrite"
|
||||
["Start" magit-rewrite-start t]
|
||||
["Stop" magit-rewrite-stop t]
|
||||
|
@ -1676,6 +1780,8 @@ FUNC should leave point at the end of the modified region"
|
|||
["Pull" magit-pull t]
|
||||
["Remote update" magit-remote-update t]
|
||||
"---"
|
||||
("Extensions")
|
||||
"---"
|
||||
["Display Git output" magit-display-process t]
|
||||
["Quit Magit" quit-window t]))
|
||||
|
||||
|
@ -1815,6 +1921,16 @@ Please see the manual for a complete description of Magit.
|
|||
(ignore-errors
|
||||
(revert-buffer t t nil))))))
|
||||
|
||||
(defun magit-update-vc-modeline (dir)
|
||||
"Update the modeline for buffers representable by magit."
|
||||
(dolist (buffer (buffer-list))
|
||||
(when (and buffer
|
||||
(buffer-file-name buffer)
|
||||
(magit-string-has-prefix-p (buffer-file-name buffer) dir))
|
||||
(with-current-buffer buffer
|
||||
(ignore-errors
|
||||
(vc-find-file-hook))))))
|
||||
|
||||
(defvar magit-refresh-needing-buffers nil)
|
||||
(defvar magit-refresh-pending nil)
|
||||
|
||||
|
@ -2204,13 +2320,14 @@ in the corresponding directories."
|
|||
(defun magit-apply-hunk-item-reverse (hunk &rest args)
|
||||
(apply #'magit-apply-hunk-item* hunk t (cons "--reverse" args)))
|
||||
|
||||
(defun magit-insert-unstaged-changes (title)
|
||||
(magit-define-inserter unstaged-changes (title)
|
||||
(let ((magit-hide-diffs t))
|
||||
(let ((magit-diff-options '()))
|
||||
(magit-git-section 'unstaged title 'magit-wash-raw-diffs
|
||||
"diff-files"))))
|
||||
|
||||
(defun magit-insert-staged-changes (no-commit)
|
||||
(magit-define-inserter staged-changes (staged no-commit)
|
||||
(when staged
|
||||
(let ((magit-hide-diffs t)
|
||||
(base (if no-commit
|
||||
(magit-git-string "mktree")
|
||||
|
@ -2219,7 +2336,7 @@ in the corresponding directories."
|
|||
(magit-ignore-unmerged-raw-diffs t))
|
||||
(magit-git-section 'staged "Staged changes:" 'magit-wash-raw-diffs
|
||||
"diff-index" "--cached"
|
||||
base))))
|
||||
base)))))
|
||||
|
||||
;;; Logs and Commits
|
||||
|
||||
|
@ -2411,29 +2528,27 @@ insert a line to tell how to insert more of them"
|
|||
(or magit-marked-commit
|
||||
(error "No commit marked")))
|
||||
|
||||
(defun magit-insert-unpulled-commits (remote branch)
|
||||
(defun magit-remote-branch-name (remote branch)
|
||||
"Get the name of the branch BRANCH on remote REMOTE"
|
||||
(if (string= remote ".")
|
||||
branch
|
||||
(concat remote "/" branch)))
|
||||
|
||||
(magit-define-inserter unpulled-commits (remote branch)
|
||||
(when remote
|
||||
(magit-git-section 'unpulled
|
||||
"Unpulled commits:" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "HEAD..%s/%s" remote branch)))
|
||||
(format "HEAD..%s"
|
||||
(magit-remote-branch-name remote branch)))))
|
||||
|
||||
(defun magit-insert-unpushed-commits (remote branch)
|
||||
(magit-define-inserter unpushed-commits (remote branch)
|
||||
(when remote
|
||||
(magit-git-section 'unpushed
|
||||
"Unpushed commits:" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "%s/%s..HEAD" remote branch)))
|
||||
|
||||
(defun magit-insert-unpulled-svn-commits (&optional use-cache)
|
||||
(magit-git-section 'svn-unpulled
|
||||
"Unpulled commits (SVN):" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "HEAD..%s" (magit-get-svn-ref use-cache))))
|
||||
|
||||
(defun magit-insert-unpushed-svn-commits (&optional use-cache)
|
||||
(magit-git-section 'svn-unpushed
|
||||
"Unpushed commits (SVN):" 'magit-wash-log
|
||||
"log" "--pretty=format:* %H %s"
|
||||
(format "%s..HEAD" (magit-get-svn-ref use-cache))))
|
||||
(format "%s..HEAD"
|
||||
(magit-remote-branch-name remote branch)))))
|
||||
|
||||
(defun magit-remote-branch-for (local-branch)
|
||||
"Guess the remote branch name that LOCAL-BRANCH is tracking."
|
||||
|
@ -2444,13 +2559,23 @@ insert a line to tell how to insert more of them"
|
|||
|
||||
;;; Status
|
||||
|
||||
(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))
|
||||
(defvar magit-remote-string-hook nil)
|
||||
|
||||
(defun magit-remote-string (remote remote-branch)
|
||||
(cond
|
||||
((string= "." remote)
|
||||
(format "branch %s"
|
||||
(propertize remote-branch 'face 'magit-branch)))
|
||||
(remote
|
||||
(concat
|
||||
(propertize remote-branch 'face 'magit-branch)
|
||||
" @ "
|
||||
(cdr (assoc 'revision svn-info))))))
|
||||
remote
|
||||
" ("
|
||||
(magit-get "remote" remote "url")
|
||||
")"))
|
||||
(t
|
||||
(run-hook-with-args-until-success 'magit-remote-string-hook))))
|
||||
|
||||
(defun magit-refresh-status ()
|
||||
(magit-create-buffer-sections
|
||||
|
@ -2458,8 +2583,7 @@ insert a line to tell how to insert more of them"
|
|||
(let* ((branch (magit-get-current-branch))
|
||||
(remote (and branch (magit-get "branch" branch "remote")))
|
||||
(remote-branch (or (and branch (magit-remote-branch-for branch)) branch))
|
||||
(svn-info (magit-get-svn-ref-info))
|
||||
(remote-string (magit-remote-string remote svn-info))
|
||||
(remote-string (magit-remote-string remote remote-branch))
|
||||
(head (magit-git-string
|
||||
"log" "--max-count=1" "--abbrev-commit" "--pretty=oneline"))
|
||||
(no-commit (not head)))
|
||||
|
@ -2484,22 +2608,15 @@ insert a line to tell how to insert more of them"
|
|||
(magit-git-exit-code "update-index" "--refresh")
|
||||
(magit-insert-untracked-files)
|
||||
(magit-insert-stashes)
|
||||
(magit-insert-topics)
|
||||
(magit-insert-pending-changes)
|
||||
(magit-insert-pending-commits)
|
||||
(when remote
|
||||
(magit-insert-unpulled-commits remote remote-branch))
|
||||
(when svn-info
|
||||
(magit-insert-unpulled-svn-commits t))
|
||||
(magit-insert-unpulled-commits remote remote-branch)
|
||||
(let ((staged (or no-commit (magit-anything-staged-p))))
|
||||
(magit-insert-unstaged-changes
|
||||
(if staged "Unstaged changes:" "Changes:"))
|
||||
(if staged
|
||||
(magit-insert-staged-changes no-commit)))
|
||||
(when remote
|
||||
(magit-insert-unpushed-commits remote remote-branch))
|
||||
(when svn-info
|
||||
(magit-insert-unpushed-svn-commits t))))))
|
||||
(magit-insert-staged-changes staged no-commit))
|
||||
(magit-insert-unpushed-commits remote remote-branch)
|
||||
(run-hooks 'magit-refresh-status-hook)))))
|
||||
|
||||
(defun magit-init (dir)
|
||||
"Initialize git repository in the DIR directory."
|
||||
|
@ -2613,7 +2730,9 @@ With prefix argument, add remaining untracked files as well.
|
|||
tracking brach name suggesting a sensible default."
|
||||
(when (yes-or-no-p
|
||||
(format "Create local tracking branch for %s? " branch))
|
||||
(let* ((default-name (concat remote "-" branch))
|
||||
(let* ((default-name (concat remote
|
||||
"-"
|
||||
(replace-regexp-in-string "[/]" "-" branch)))
|
||||
(chosen-name (read-string (format "Call local branch (%s): " default-name)
|
||||
nil
|
||||
nil
|
||||
|
@ -2634,7 +2753,7 @@ rev... maybe."
|
|||
t))
|
||||
nil))
|
||||
|
||||
(defun magit-checkout (revision)
|
||||
(magit-define-command checkout (revision)
|
||||
"Switch 'HEAD' to REVISION and update working tree.
|
||||
Fails if working tree or staging area contain uncommitted changes.
|
||||
If REVISION is a remote branch, offer to create a local tracking branch.
|
||||
|
@ -2650,7 +2769,7 @@ If REVISION is a remote branch, offer to create a local tracking branch.
|
|||
(parent (magit-read-rev "Parent" cur-branch)))
|
||||
(list branch parent)))
|
||||
|
||||
(defun magit-create-branch (branch parent)
|
||||
(magit-define-command create-branch (branch parent)
|
||||
"Switch 'HEAD' to new BRANCH at revision PARENT and update working tree.
|
||||
Fails if working tree or staging area contain uncommitted changes.
|
||||
\('git checkout -b BRANCH REVISION')."
|
||||
|
@ -2685,7 +2804,7 @@ With a prefix-arg, the merge will be squashed.
|
|||
"--no-ff")
|
||||
(magit-rev-to-git revision))))
|
||||
|
||||
(defun magit-automatic-merge (revision)
|
||||
(magit-define-command automatic-merge (revision)
|
||||
"Merge REVISION into the current 'HEAD'; commit unless merge fails.
|
||||
\('git merge REVISION')."
|
||||
(interactive (list (magit-read-rev "Merge" (magit-guess-branch))))
|
||||
|
@ -2730,107 +2849,9 @@ With a prefix-arg, the merge will be squashed.
|
|||
((?C ?c)
|
||||
(magit-run-git "rebase" "--continue"))))))))
|
||||
|
||||
;; git svn commands
|
||||
|
||||
(defun magit-svn-find-rev (rev &optional branch)
|
||||
(interactive
|
||||
(list (read-string "SVN revision: ")
|
||||
(if current-prefix-arg
|
||||
(read-string "In branch: "))))
|
||||
(let* ((sha (apply 'magit-git-string
|
||||
`("svn"
|
||||
"find-rev"
|
||||
,(concat "r" rev)
|
||||
,@(when branch (list branch))))))
|
||||
(if sha
|
||||
(magit-show-commit
|
||||
(magit-with-section sha 'commit
|
||||
(magit-set-section-info sha)
|
||||
sha))
|
||||
(error "Revision %s could not be mapped to a commit" rev))))
|
||||
|
||||
(defun magit-svn-rebase ()
|
||||
(interactive)
|
||||
(magit-run-git-async "svn" "rebase"))
|
||||
|
||||
(defun magit-svn-dcommit ()
|
||||
(interactive)
|
||||
(magit-run-git-async "svn" "dcommit"))
|
||||
|
||||
(defun magit-svn-enabled ()
|
||||
(not (null (magit-get-svn-ref-info))))
|
||||
|
||||
(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))
|
||||
|
||||
(defvar magit-get-svn-ref-info-cache nil
|
||||
"A cache for svn-ref-info.
|
||||
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)
|
||||
"Gather details about the current git-svn repository.
|
||||
Return nil if there isn't one. Keys of the alist are ref-path,
|
||||
trunk-ref-name 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
|
||||
(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))))))))
|
||||
|
||||
(defun magit-get-svn-ref (&optional use-cache)
|
||||
"Get the best guess remote ref for the current git-svn based branch.
|
||||
If USE-CACHE is non nil, use the cached information."
|
||||
(let ((info (magit-get-svn-ref-info use-cache)))
|
||||
(cdr (assoc 'local-ref info))))
|
||||
|
||||
;;; Resetting
|
||||
|
||||
(defun magit-reset-head (revision &optional hard)
|
||||
(magit-define-command reset-head (revision &optional hard)
|
||||
"Switch 'HEAD' to REVISION, keeping prior working tree and staging area.
|
||||
Any differences from REVISION become new changes to be committed.
|
||||
With prefix argument, all uncommitted changes in working tree
|
||||
|
@ -2843,11 +2864,12 @@ and staging area are lost.
|
|||
(or (magit-default-rev)
|
||||
"HEAD^"))
|
||||
current-prefix-arg))
|
||||
(if revision
|
||||
(when revision
|
||||
(magit-run-git "reset" (if hard "--hard" "--soft")
|
||||
(magit-rev-to-git revision))))
|
||||
(magit-rev-to-git revision))
|
||||
(magit-update-vc-modeline default-directory)))
|
||||
|
||||
(defun magit-reset-head-hard (revision)
|
||||
(magit-define-command reset-head-hard (revision)
|
||||
"Switch 'HEAD' to REVISION, losing all changes.
|
||||
Uncomitted changes in both working tree and staging area are lost.
|
||||
\('git reset --hard REVISION')."
|
||||
|
@ -2856,7 +2878,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
"HEAD"))))
|
||||
(magit-reset-head revision t))
|
||||
|
||||
(defun magit-reset-working-tree ()
|
||||
(magit-define-command reset-working-tree ()
|
||||
"Revert working tree and clear changes from staging area.
|
||||
\('git reset --hard HEAD')."
|
||||
(interactive)
|
||||
|
@ -2877,7 +2899,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
(prin1 info (current-buffer))
|
||||
(princ "\n" (current-buffer))))
|
||||
|
||||
(defun magit-insert-pending-commits ()
|
||||
(magit-define-inserter pending-commits ()
|
||||
(let* ((info (magit-read-rewrite-info))
|
||||
(pending (cdr (assq 'pending info))))
|
||||
(when pending
|
||||
|
@ -2920,7 +2942,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
((pending commit)
|
||||
(magit-rewrite-set-commit-property info 'used nil))))
|
||||
|
||||
(defun magit-insert-pending-changes ()
|
||||
(magit-define-inserter pending-changes ()
|
||||
(let* ((info (magit-read-rewrite-info))
|
||||
(orig (cadr (assq 'orig info))))
|
||||
(when orig
|
||||
|
@ -2936,7 +2958,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
(error "You have uncommitted changes"))
|
||||
(or (not (magit-read-rewrite-info))
|
||||
(error "Rewrite in progress"))
|
||||
(let* ((orig (magit-git-string "rev-parse" "HEAD"))
|
||||
(let* ((orig (magit-rev-parse "HEAD"))
|
||||
(base (or (car (magit-commit-parents from))
|
||||
(error "Can't rewrite a commit without a parent, sorry")))
|
||||
(pending (magit-git-lines "rev-list" (concat base ".."))))
|
||||
|
@ -2952,7 +2974,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
(when (or noconfirm
|
||||
(yes-or-no-p "Stop rewrite? "))
|
||||
(magit-write-rewrite-info nil)
|
||||
(magit-need-refresh))))
|
||||
(magit-refresh))))
|
||||
|
||||
(defun magit-rewrite-abort ()
|
||||
(interactive)
|
||||
|
@ -2990,7 +3012,7 @@ Uncomitted changes in both working tree and staging area are lost.
|
|||
|
||||
;;; Updating, pull, and push
|
||||
|
||||
(defun magit-remote-update (&optional remote)
|
||||
(magit-define-command remote-update (&optional remote)
|
||||
"Update REMOTE. If nil, update all remotes.
|
||||
|
||||
When called interactively, update the current remote unless a
|
||||
|
@ -2998,11 +3020,10 @@ prefix arg is given. With prefix arg, prompt for a remote and
|
|||
update it."
|
||||
(interactive (list (when current-prefix-arg (magit-read-remote))))
|
||||
(cond
|
||||
((magit-svn-enabled) (magit-run-git-async "svn" "fetch"))
|
||||
(remote (magit-run-git-async "fetch" remote))
|
||||
(t (magit-run-git-async "remote" "update"))))
|
||||
|
||||
(defun magit-pull ()
|
||||
(magit-define-command pull ()
|
||||
(interactive)
|
||||
(let* ((branch (magit-get-current-branch))
|
||||
(config-branch (and branch (magit-get "branch" branch "merge")))
|
||||
|
@ -3041,7 +3062,7 @@ typing and automatically refreshes the status buffer."
|
|||
args)
|
||||
nil nil nil t))))
|
||||
|
||||
(defun magit-push ()
|
||||
(magit-define-command push ()
|
||||
(interactive)
|
||||
(let* ((branch (or (magit-get-current-branch)
|
||||
(error "Don't push a detached head. That's gross")))
|
||||
|
@ -3055,7 +3076,15 @@ typing and automatically refreshes the status buffer."
|
|||
(if (and (not branch-remote)
|
||||
(not current-prefix-arg))
|
||||
(magit-set push-remote "branch" branch "remote"))
|
||||
(magit-run-git-async "push" "-v" push-remote (format "%s:%s" branch ref-branch))))
|
||||
(magit-run-git-async "push" "-v" push-remote
|
||||
(if ref-branch
|
||||
(format "%s:%s" branch ref-branch)
|
||||
branch))
|
||||
;; Although git will automatically set up the remote,
|
||||
;; it doesn't set up the branch to merge (at least as of Git 1.6.6.1),
|
||||
;; so we have to do that manually.
|
||||
(unless ref-branch
|
||||
(magit-set (concat "refs/heads/" branch) "branch" branch "merge"))))
|
||||
|
||||
;;; Log edit mode
|
||||
|
||||
|
@ -3091,8 +3120,7 @@ Prefix arg means justify as well."
|
|||
|
||||
(define-derived-mode magit-log-edit-mode text-mode "Magit Log Edit"
|
||||
(set (make-local-variable 'fill-paragraph-function)
|
||||
'magit-log-fill-paragraph)
|
||||
(run-mode-hooks 'magit-log-edit-mode-hook))
|
||||
'magit-log-fill-paragraph))
|
||||
|
||||
(defun magit-log-edit-cleanup ()
|
||||
(save-excursion
|
||||
|
@ -3212,7 +3240,7 @@ Prefix arg means justify as well."
|
|||
(bury-buffer)
|
||||
(when (file-exists-p ".git/MERGE_MSG")
|
||||
(delete-file ".git/MERGE_MSG"))
|
||||
(magit-revert-buffers default-directory t)
|
||||
(magit-update-vc-modeline default-directory)
|
||||
(when magit-pre-log-edit-window-configuration
|
||||
(set-window-configuration magit-pre-log-edit-window-configuration)
|
||||
(setq magit-pre-log-edit-window-configuration nil))))
|
||||
|
@ -3342,7 +3370,7 @@ Prefix arg means justify as well."
|
|||
|
||||
;;; Tags
|
||||
|
||||
(defun magit-tag (name rev)
|
||||
(magit-define-command tag (name rev)
|
||||
"Create a new lightweight tag with the given NAME at REV.
|
||||
\('git tag NAME')."
|
||||
(interactive
|
||||
|
@ -3351,7 +3379,7 @@ Prefix arg means justify as well."
|
|||
(magit-read-rev "Place tag on: " (or (magit-default-rev) "HEAD"))))
|
||||
(magit-run-git "tag" name rev))
|
||||
|
||||
(defun magit-annotated-tag (name)
|
||||
(magit-define-command annotated-tag (name)
|
||||
"Start composing an annotated tag with the given NAME.
|
||||
Tag will point to the current 'HEAD'."
|
||||
(interactive "sNew annotated tag name: ")
|
||||
|
@ -3380,12 +3408,12 @@ Tag will point to the current 'HEAD'."
|
|||
(let ((magit-old-top-section nil))
|
||||
(magit-wash-sequence #'magit-wash-stash)))
|
||||
|
||||
(defun magit-insert-stashes ()
|
||||
(magit-define-inserter stashes ()
|
||||
(magit-git-section 'stashes
|
||||
"Stashes:" 'magit-wash-stashes
|
||||
"stash" "list"))
|
||||
|
||||
(defun magit-stash (description)
|
||||
(magit-define-command stash (description)
|
||||
"Create new stash of working tree and staging area named DESCRIPTION.
|
||||
Working tree and staging area revert to the current 'HEAD'.
|
||||
With prefix argument, changes in staging area are kept.
|
||||
|
@ -3394,9 +3422,10 @@ With prefix argument, changes in staging area are kept.
|
|||
(apply 'magit-run-git `("stash"
|
||||
"save"
|
||||
,@(when current-prefix-arg '("--keep-index"))
|
||||
"--"
|
||||
,description)))
|
||||
|
||||
(defun magit-stash-snapshot ()
|
||||
(magit-define-command stash-snapshot ()
|
||||
"Create new stash of working tree and staging area; keep changes in place.
|
||||
\('git stash save \"Snapshot...\"; git stash apply stash@{0}')"
|
||||
(interactive)
|
||||
|
@ -3445,32 +3474,6 @@ With prefix argument, changes in staging area are kept.
|
|||
range args)
|
||||
(magit-stash-mode t)))))))
|
||||
|
||||
;;; 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"))
|
||||
|
||||
;;; Commits
|
||||
|
||||
(defun magit-commit-at-point (&optional nil-ok-p)
|
||||
|
@ -3612,7 +3615,7 @@ With a non numeric prefix ARG, show all entries"
|
|||
(defvar magit-log-grep-buffer-name "*magit-grep-log*"
|
||||
"Buffer name for display of log grep results.")
|
||||
|
||||
(defun magit-display-log (ask-for-range &rest extra-args)
|
||||
(magit-define-command display-log (ask-for-range &rest extra-args)
|
||||
(let* ((log-range (if ask-for-range
|
||||
(magit-read-rev-range "Log" "HEAD")
|
||||
"HEAD"))
|
||||
|
@ -3651,7 +3654,7 @@ level commits."
|
|||
(format "--grep=%s" (shell-quote-argument str))))
|
||||
(magit-log-mode t)))
|
||||
|
||||
(defun magit-log-long (&optional arg)
|
||||
(magit-define-command log-long (&optional arg)
|
||||
(interactive "P")
|
||||
(let* ((range (if arg
|
||||
(magit-read-rev-range "Long log" "HEAD")
|
||||
|
@ -3688,7 +3691,7 @@ This is only non-nil in reflog buffers.")
|
|||
:lighter ()
|
||||
:keymap magit-reflog-mode-map)
|
||||
|
||||
(defun magit-reflog (head)
|
||||
(magit-define-command reflog (head)
|
||||
(interactive (list (magit-read-rev "Reflog of" (or (magit-guess-branch) "HEAD"))))
|
||||
(if head
|
||||
(let* ((topdir (magit-get-top-dir default-directory))
|
||||
|
@ -3698,7 +3701,7 @@ This is only non-nil in reflog buffers.")
|
|||
#'magit-refresh-reflog-buffer head args)
|
||||
(magit-reflog-mode t))))
|
||||
|
||||
(defun magit-reflog-head ()
|
||||
(magit-define-command reflog-head ()
|
||||
(interactive)
|
||||
(magit-reflog "HEAD"))
|
||||
|
||||
|
@ -3719,7 +3722,7 @@ This is only non-nil in reflog buffers.")
|
|||
:lighter ()
|
||||
:keymap magit-diff-mode-map)
|
||||
|
||||
(defun magit-diff (range)
|
||||
(magit-define-command diff (range)
|
||||
(interactive (list (magit-read-rev-range "Diff")))
|
||||
(if range
|
||||
(let* ((dir default-directory)
|
||||
|
@ -3730,7 +3733,7 @@ This is only non-nil in reflog buffers.")
|
|||
(magit-mode-init dir 'diff #'magit-refresh-diff-buffer range args)
|
||||
(magit-diff-mode t)))))
|
||||
|
||||
(defun magit-diff-working-tree (rev)
|
||||
(magit-define-command diff-working-tree (rev)
|
||||
(interactive (list (magit-read-rev "Diff with" (magit-default-rev))))
|
||||
(magit-diff (or rev "HEAD")))
|
||||
|
||||
|
@ -3786,7 +3789,7 @@ This is only meaningful in wazzup buffers.")
|
|||
(dolist (branch branches)
|
||||
(let* ((name (car branch))
|
||||
(ref (cdr branch))
|
||||
(hash (magit-git-string "rev-parse" ref))
|
||||
(hash (magit-rev-parse ref))
|
||||
(reported-branch (gethash hash reported)))
|
||||
(unless (or (and reported-branch
|
||||
(string= (file-name-nondirectory ref)
|
||||
|
@ -3930,8 +3933,6 @@ This is only meaningful in wazzup buffers.")
|
|||
((stash)
|
||||
(magit-show-stash info)
|
||||
(pop-to-buffer magit-stash-buffer-name))
|
||||
((topic)
|
||||
(magit-checkout info))
|
||||
((longer)
|
||||
(magit-log-show-more-entries ()))))
|
||||
|
||||
|
@ -4032,6 +4033,7 @@ Return values:
|
|||
|
||||
(defvar magit-show-branches-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "RET") 'magit-branches-window-checkout)
|
||||
(define-key map (kbd "b") 'magit-branches-window-checkout)
|
||||
(define-key map (kbd "k") 'magit-remove-branch)
|
||||
(define-key map (kbd "m") 'magit-branches-window-manual-merge)
|
||||
|
@ -4055,12 +4057,7 @@ Return values:
|
|||
|
||||
(defun magit--branch-name-from-line (line)
|
||||
"Extract the branch name from line LINE of 'git branch' output."
|
||||
(let ((branch (get-text-property 0 'branch-name line)))
|
||||
(if (and branch
|
||||
(get-text-property 0 'remote line)
|
||||
(string-match-p "^remotes/" branch))
|
||||
(substring branch 8)
|
||||
branch)))
|
||||
(get-text-property 0 'branch-name line))
|
||||
|
||||
(defun magit--branch-name-at-point ()
|
||||
"Get the branch name in the line at point."
|
||||
|
@ -4074,6 +4071,12 @@ Return values:
|
|||
(save-excursion
|
||||
(magit-show-branches)))
|
||||
|
||||
(defun magit-remove-remote (ref)
|
||||
"Return REF with any remote part removed."
|
||||
(if (string-match "^remotes/" ref)
|
||||
(substring ref 8)
|
||||
ref))
|
||||
|
||||
(defun magit-remove-branch (&optional force)
|
||||
"Remove the branch in the line at point.
|
||||
With prefix force the removal even it it hasn't been merged."
|
||||
|
@ -4081,7 +4084,9 @@ With prefix force the removal even it it hasn't been merged."
|
|||
(let ((args (list "branch"
|
||||
(if force "-D" "-d")
|
||||
(when (magit--is-branch-at-point-remote) "-r")
|
||||
(magit--branch-name-at-point))))
|
||||
;; remove the remotes part
|
||||
(magit-remove-remote
|
||||
(magit--branch-name-at-point)))))
|
||||
(save-excursion
|
||||
(apply 'magit-run-git (remq nil args))
|
||||
(magit-show-branches))))
|
||||
|
@ -4111,7 +4116,7 @@ With prefix force the removal even it it hasn't been merged."
|
|||
"\\(.+?\\) +" ; branch name
|
||||
|
||||
"\\(?:"
|
||||
"\\([0-9a-fA-F]\\{7\\}\\) " ; sha1
|
||||
"\\([0-9a-fA-F]\\{7,8\\}\\) " ; sha1
|
||||
"\\|\\(-> \\)" ; or the pointer to a ref
|
||||
"\\)"
|
||||
|
||||
|
@ -4249,6 +4254,46 @@ With prefix force the removal even it it hasn't been merged."
|
|||
(magit-list-buffers))
|
||||
'string=)))
|
||||
|
||||
;; Extensions
|
||||
|
||||
(defvar magit-active-extensions '())
|
||||
|
||||
(defstruct magit-extension
|
||||
keys menu actions insert remote-string commands)
|
||||
|
||||
(defun magit-install-extension (ext)
|
||||
(add-to-list 'magit-active-extensions ext)
|
||||
(let ((keys (magit-extension-keys ext))
|
||||
(menu (magit-extension-menu ext))
|
||||
(actions (magit-extension-actions ext))
|
||||
(insert (magit-extension-insert ext))
|
||||
(remote-string (magit-extension-remote-string ext))
|
||||
(commands (magit-extension-commands ext)))
|
||||
(when keys
|
||||
(mapc (lambda (x) (define-key magit-mode-map (car x) (cdr x)))
|
||||
keys))
|
||||
(when menu
|
||||
(easy-menu-add-item 'magit-mode-menu '("Extensions") menu))
|
||||
(when insert
|
||||
(mapc (lambda (x)
|
||||
(destructuring-bind (position reference hook) x
|
||||
(add-hook (intern (format "magit-insert-%s%s-hook"
|
||||
reference position))
|
||||
hook)))
|
||||
insert))
|
||||
(when remote-string
|
||||
(add-hook 'magit-remote-string-hook remote-string))
|
||||
(when commands
|
||||
(mapc (lambda (x)
|
||||
(add-hook (intern (format "magit-%s:functions" (car x)))
|
||||
(cdr x)))
|
||||
commands))))
|
||||
|
||||
(defun magit-get-extensions-actions (action)
|
||||
(mapcar (lambda (ext)
|
||||
(cadr (assoc action (magit-extension-actions ext))))
|
||||
magit-active-extensions))
|
||||
|
||||
(provide 'magit)
|
||||
|
||||
;;; magit.el ends here
|
||||
|
|
19
magit.texi
19
magit.texi
|
@ -500,7 +500,8 @@ local branch. Deleting works for both local and remote branches.
|
|||
You can merge the branch in the current line by typing @kbd{m} for a
|
||||
manual merge and @kbd{M} for an automatic merge.
|
||||
|
||||
With @kbd{b} you can check out the branch in the current line.
|
||||
With @kbd{RET} or @kbd{b} you can check out the branch in the current
|
||||
line.
|
||||
|
||||
Typing @kbd{$} shows the @code{*magit-process*} buffer which contains
|
||||
the transcript of the most recent command.
|
||||
|
@ -649,10 +650,12 @@ it, like from any other diff.
|
|||
|
||||
Magit will run @code{git push} when you type @kbd{P}. If you give a
|
||||
prefix argument to @kbd{P}, you will be prompted for the repository to
|
||||
push to. When no default remote repositor has been configured yet for
|
||||
push to. When no default remote repository has been configured yet for
|
||||
the current branch, you will be prompted as well. Typing @kbd{P} will
|
||||
only push the current branch to the remote. In other words, it will
|
||||
run @code{git push <remote> <branch>}.
|
||||
only push the current branch to the remote. In other words, it will run
|
||||
@code{git push <remote> <branch>}. The branch will be created in the
|
||||
remote if it doesn't exist already. The local branch will be configured
|
||||
so that it pulls from the new remote branch.
|
||||
|
||||
Typing @kbd{f} will run @code{git remote update}. With a prefix arg, it
|
||||
will prompt for the name of the remote to update. Typing @kbd{F} will
|
||||
|
@ -676,13 +679,13 @@ Magit shows them in a section called @emph{Unpulled changes}. Typing
|
|||
@node Interfacing with Subversion
|
||||
@chapter Interfacing with Subversion
|
||||
|
||||
Typing @kbd{N r} runs @code{git svn rebase} and typing @kbd{N c} runs
|
||||
@code{git svn dcommit}.
|
||||
Typing @kbd{N r} runs @code{git svn rebase}, typing @kbd{N c} runs
|
||||
@code{git svn dcommit} and typing @kbd{N f} runs @code{git svn fetch}.
|
||||
|
||||
@kbd{N f} will prompt you for a (numeric, Subversion) revision and
|
||||
@kbd{N s} will prompt you for a (numeric, Subversion) revision and
|
||||
then search for a corresponding Git sha1 for the commit. This is
|
||||
limited to the path of the remote Subversion repository. With a prefix
|
||||
(@kbd{C-u N f} the user will also be prompted for a branch to search
|
||||
(@kbd{C-u N s} the user will also be prompted for a branch to search
|
||||
in.
|
||||
|
||||
@node Using Git Directly
|
||||
|
|
Loading…
Reference in a new issue