From 96f48ebd97c19384f487c8a9c4cf474705ce1e37 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Tue, 24 Apr 2012 23:19:57 +0200 Subject: emacs.d/lisp/magit: version bump --- emacs.d/lisp/magit/magit-svn.el | 240 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 emacs.d/lisp/magit/magit-svn.el (limited to 'emacs.d/lisp/magit/magit-svn.el') diff --git a/emacs.d/lisp/magit/magit-svn.el b/emacs.d/lisp/magit/magit-svn.el new file mode 100644 index 0000000..d08c048 --- /dev/null +++ b/emacs.d/lisp/magit/magit-svn.el @@ -0,0 +1,240 @@ +;;; magit-svn.el --- git-svn plug-in for Magit + +;; Copyright (C) 2008 Alex Ott +;; Copyright (C) 2009 Alexey Voinov +;; Copyright (C) 2009 John Wiegley +;; Copyright (C) 2008 Linh Dang +;; Copyright (C) 2008 Marcin Bachry +;; Copyright (C) 2008, 2009 Marius Vollmer +;; 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 . + +;;; Commentary: + +;; This plug-in provides git-svn functionality as a separate component of Magit + +;;; Code: + +(require 'magit) +(eval-when-compile + (require 'cl)) + +;; 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-create-branch (name) + (interactive "sBranch name: ") + (magit-run-git "svn" "branch" name)) + +(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 t)))) + +(defun magit-svn-expand-braces-in-branches (branch) + (if (not (string-match "\\(.+\\){\\(.+,.+\\)}\\(.*\\):\\(.*\\)\\\*" branch)) + (list branch) + (let ((prefix (match-string 1 branch)) + (suffix (match-string 3 branch)) + (rhs (match-string 4 branch)) + (pieces (split-string (match-string 2 branch) ","))) + (mapcar (lambda (p) (concat prefix p suffix ":" rhs p)) pieces)))) + +(defun magit-svn-get-local-ref (url) + (let* ((branches (cons (magit-get "svn-remote" "svn" "fetch") + (magit-get-all "svn-remote" "svn" "branches"))) + (branches (apply 'nconc + (mapcar 'magit-svn-expand-braces-in-branches + 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)) + (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 (and use-cache magit-svn-get-ref-info-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))) + (set (make-local-variable + '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" + "--grep" "git-svn" "-1") + "")) + (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-enabled) + (apply #'magit-git-section + 'svn-unpulled "Unpulled commits (SVN):" 'magit-wash-log "log" + (append magit-git-log-options + (list + (format "HEAD..%s" (magit-svn-get-ref use-cache))))))) + +(magit-define-inserter svn-unpushed (&optional use-cache) + (when (magit-svn-enabled) + (apply #'magit-git-section + 'svn-unpushed "Unpushed commits (SVN):" 'magit-wash-log "log" + (append magit-git-log-options + (list + (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"))) + +(easy-menu-define magit-svn-extension-menu + nil + "Git SVN extension menu" + '("Git SVN" + :visible magit-svn-mode + ["Create branch" magit-svn-create-branch (magit-svn-enabled)] + ["Rebase" magit-svn-rebase (magit-svn-enabled)] + ["Fetch" magit-svn-remote-update (magit-svn-enabled)] + ["Commit" magit-svn-dcommit (magit-svn-enabled)])) + +(easy-menu-add-item 'magit-mode-menu + '("Extensions") + magit-svn-extension-menu) + +;; add the group and its keys +(progn + ;; (re-)create the group + (magit-key-mode-add-group 'svn) + + (magit-key-mode-insert-action 'svn "r" "Rebase" 'magit-svn-rebase) + (magit-key-mode-insert-action 'svn "c" "DCommit" 'magit-svn-dcommit) + (magit-key-mode-insert-action 'svn "f" "Fetch" 'magit-svn-remote-update) + (magit-key-mode-insert-action 'svn "s" "Find rev" 'magit-svn-find-rev) + (magit-key-mode-insert-action 'svn "B" "Create branch" 'magit-svn-create-branch) + + ;; generate and bind the menu popup function + (magit-key-mode-generate 'svn)) + +(defvar magit-svn-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "N") 'magit-key-mode-popup-svn) + map)) + +;;;###autoload +(define-minor-mode magit-svn-mode "SVN support for Magit" + :lighter " SVN" :require 'magit-svn :keymap 'magit-svn-mode-map + (or (derived-mode-p 'magit-mode) + (error "This mode only makes sense with magit")) + (let ((unpulled-hook (lambda () (magit-insert-svn-unpulled t))) + (unpushed-hook (lambda () (magit-insert-svn-unpushed t))) + (remote-hook 'magit-svn-remote-string)) + (if magit-svn-mode + (progn + (add-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook nil t) + (add-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook nil t) + (add-hook 'magit-remote-string-hook remote-hook nil t)) + (progn + (remove-hook 'magit-after-insert-unpulled-commits-hook unpulled-hook t) + (remove-hook 'magit-after-insert-unpushed-commits-hook unpushed-hook t) + (remove-hook 'magit-remote-string-hook remote-hook t))) + (when (called-interactively-p 'any) + (magit-refresh)))) + +;;;###autoload +(defun turn-on-magit-svn () + "Unconditionally turn on `magit-svn-mode'." + (magit-svn-mode 1)) + +(provide 'magit-svn) +;;; magit-svn.el ends here -- cgit v1.2.3