summaryrefslogtreecommitdiffstats
path: root/emacs.d/lisp/magit/magit-topgit.el
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--emacs.d/lisp/magit/magit-topgit.el191
1 files changed, 191 insertions, 0 deletions
diff --git a/emacs.d/lisp/magit/magit-topgit.el b/emacs.d/lisp/magit/magit-topgit.el
new file mode 100644
index 0000000..6f0080c
--- /dev/null
+++ b/emacs.d/lisp/magit/magit-topgit.el
@@ -0,0 +1,191 @@
+;;; magit-topgit.el --- topgit plug-in for Magit
+
+;; Copyright (C) 2010 Nathan Weizenbaum
+;; 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)
+(eval-when-compile
+ (require 'cl))
+
+(defcustom magit-topgit-executable "tg"
+ "The name of the TopGit executable."
+ :group 'magit
+ :type 'string)
+
+(defcustom magit-topgit-branch-prefix "t/"
+ "Convention prefix for topic branch creation."
+ :group 'magit
+ :type 'string)
+
+(defface magit-topgit-current
+ '((t :weight bold :inherit magit-branch))
+ "Face for section titles."
+ :group 'magit-faces)
+
+;;; Topic branches (using topgit)
+
+(defun magit-topgit-in-topic-p ()
+ (and (file-exists-p ".topdeps")
+ (executable-find magit-topgit-executable)))
+
+(defun magit-topgit-create-branch (branch parent)
+ (when (zerop (or (string-match magit-topgit-branch-prefix 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 (magit-topgit-in-topic-p)
+ (magit-run* (list magit-topgit-executable "update")
+ nil nil nil t)
+ t))
+
+(defun magit-topgit-push ()
+ (when (magit-topgit-in-topic-p)
+ (let* ((branch (or (magit-get-current-branch)
+ (error "Don't push a detached head. That's gross")))
+ (remote (magit-get "topgit" "remote"))
+ (push-remote (if (or current-prefix-arg (not remote))
+ (magit-read-remote (format "Push %s to" branch))
+ remote)))
+ (when (and (not remote)
+ (not current-prefix-arg))
+ (magit-set push-remote "topgit" "remote"))
+ (magit-run magit-topgit-executable "push" "-r" push-remote))
+ t))
+
+(defun magit-topgit-remote-update (&optional remote)
+ (when (magit-topgit-in-topic-p)
+ (let* ((remote (magit-get "topgit" "remote"))
+ (remote-update (if (or current-prefix-arg (not remote))
+ (magit-read-remote)
+ remote)))
+ (if (and (not remote)
+ (not current-prefix-arg))
+ (progn
+ (magit-set remote-update "topgit" "remote")
+ (magit-run magit-topgit-executable "remote"
+ "--populate" remote-update)))
+ (magit-run magit-topgit-executable "remote" remote-update))
+ ;; We return nil anyway, as we also want regular "git remote update" to
+ ;; happen
+ nil))
+
+(defun magit-topgit-parse-flags (flags-string)
+ (let ((flags (string-to-list flags-string))
+ (void-flag ?\ ))
+ (list :current (not (eq (nth 0 flags) void-flag))
+ :empty (not (eq (nth 1 flags) void-flag)))))
+
+(defun magit-topgit-wash-topic ()
+ (let ((fmt "^\\(.\\{7\\}\\)\\s-\\(\\S-+\\)\\s-+\\(.*\\)"))
+ (if (search-forward-regexp fmt (line-end-position) t)
+ (let ((flags (magit-topgit-parse-flags (match-string 1)))
+ (topic (match-string 2)))
+ (goto-char (line-beginning-position))
+ (delete-char 8)
+ (insert "\t")
+ (goto-char (line-beginning-position))
+ (magit-with-section topic 'topic
+ (magit-set-section-info topic)
+ (let ((beg (1+ (line-beginning-position)))
+ (end (line-end-position)))
+ (when (plist-get flags :current)
+ (put-text-property beg end 'face 'magit-topgit-current))
+ (when (plist-get flags :empty)
+ (put-text-property beg end 'face `(:strike-through t :inherit ,(get-text-property beg 'face)))))
+ (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)))
+
+(defun magit-topgit-section (section title washer &rest args)
+ (when (executable-find magit-topgit-executable)
+ (let ((magit-git-executable magit-topgit-executable)
+ (magit-git-standard-options nil))
+ (apply 'magit-git-section section title washer args))))
+
+(magit-define-inserter topics ()
+ (magit-topgit-section 'topics
+ "Topics:" 'magit-topgit-wash-topics
+ "summary"))
+
+(magit-add-action (item info "discard")
+ ((topic)
+ (when (yes-or-no-p "Discard topic? ")
+ (magit-run* (list magit-topgit-executable "delete" "-f" info)
+ nil nil nil t))))
+
+(magit-add-action (item info "visit")
+ ((topic)
+ (magit-checkout info)))
+
+(defun magit-topgit-get-top-bases-color (suffix)
+ (list nil nil))
+
+(defun magit-topgit-get-remote-top-bases-color (suffix)
+ (when (string-match "^\\(?:[^/]+\\)/top-bases" suffix)
+ (list nil nil)))
+
+(defconst magit-topgit-ignored-namespace
+ '("top-bases" magit-topgit-get-top-bases-color))
+
+;;;###autoload
+(define-minor-mode magit-topgit-mode "Topgit support for Magit"
+ :lighter " Topgit" :require 'magit-topgit
+ (or (derived-mode-p 'magit-mode)
+ (error "This mode only makes sense with magit"))
+ (if magit-topgit-mode
+ (progn
+ (add-hook 'magit-after-insert-stashes-hook 'magit-insert-topics nil t)
+ (add-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch nil t)
+ (add-hook 'magit-pull-command-hook 'magit-topgit-pull nil t)
+ (add-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update nil t)
+ (add-hook 'magit-push-command-hook 'magit-topgit-push nil t)
+ ;; hide refs for top-bases namespace in any remote
+ (add-hook 'magit-log-remotes-color-hook
+ 'magit-topgit-get-remote-top-bases-color)
+ ;; hide refs in the top-bases namespace, as they're not meant for the user
+ (add-to-list 'magit-refs-namespaces magit-topgit-ignored-namespace))
+ (progn
+ (remove-hook 'magit-after-insert-stashes-hook 'magit-insert-topics t)
+ (remove-hook 'magit-create-branch-command-hook 'magit-topgit-create-branch t)
+ (remove-hook 'magit-pull-command-hook 'magit-topgit-pull t)
+ (remove-hook 'magit-remote-update-command-hook 'magit-topgit-remote-update t)
+ (remove-hook 'magit-push-command-hook 'magit-topgit-push t)
+ (remove-hook 'magit-log-remotes-color-hook
+ 'magit-topgit-get-remote-top-bases-color)
+ (delete magit-topgit-ignored-namespace magit-refs-namespaces)))
+ (when (called-interactively-p 'any)
+ (magit-refresh)))
+
+;;;###autoload
+(defun turn-on-magit-topgit ()
+ "Unconditionally turn on `magit-topgit-mode'."
+ (magit-topgit-mode 1))
+
+(provide 'magit-topgit)
+;;; magit-topgit.el ends here