From ee01adf1f39fd60b5f93a9109578ef1a89f8d7ab Mon Sep 17 00:00:00 2001 From: Phil Jackson Date: Wed, 28 Oct 2009 19:54:11 +0000 Subject: [PATCH 1/4] `magit-get-svn-ref' now emulates the git-svn way of remote fetching. * magit.el (magit-get-svn-ref): Parse log output for the remote svn url. --- magit.el | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/magit.el b/magit.el index a911950d..4b133bcf 100644 --- a/magit.el +++ b/magit.el @@ -2193,12 +2193,20 @@ in log buffer." (not (null (magit-get-svn-ref)))) (defun magit-get-svn-ref () - (cond ((magit-ref-exists-p "refs/remotes/git-svn") - "refs/remotes/git-svn") - ((magit-ref-exists-p "refs/remotes/trunk") - "refs/remotes/trunk") - (t - nil))) + "Get the best guess remote ref for the current git-svn based +branch." + (let* ((info (magit-get "svn-remote" "svn" "fetch")) + (refs)) + (when info + (concat + (file-name-directory (cadr (split-string info ":"))) + (with-temp-buffer + ;; grab the git-svn-id information, this is how git-svn.perl + ;; does it :/ + (insert (magit-git-string "log" "--first-parent")) + (goto-char (point-min)) + (when (re-search-forward "git-svn-id: .+/\\(.+?\\)@" nil t) + (match-string 1))))))) ;;; Resetting From 3bfe2300518ce49a20de75ff540b0336a24ebc4b Mon Sep 17 00:00:00 2001 From: Phil Jackson Date: Wed, 28 Oct 2009 20:33:35 +0000 Subject: [PATCH 2/4] More detailed and structured information from git-svn. * magit.el (magit-svn-enabled): alist of git-svn information returned. --- magit.el | 45 ++++++++++++++++++++++++++++++++------------- magit.etest | 16 ++++++++++++++++ 2 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 magit.etest diff --git a/magit.el b/magit.el index 4b133bcf..975fb13f 100644 --- a/magit.el +++ b/magit.el @@ -2190,23 +2190,42 @@ in log buffer." (magit-run-git-async "svn" "dcommit")) (defun magit-svn-enabled () - (not (null (magit-get-svn-ref)))) + (not (null (magit-get "svn-remote" "svn" "fetch")))) + +(defun magit-get-svn-ref-info () + "Gather details about the current git-svn repository (nil if +there isn't one). Keys of the alist are ref-path, trunk-ref-name +and local-ref-name." + (let* ((fetch (magit-get "svn-remote" "svn" "fetch")) + (branches (magit-get "svn-remote" "svn" "fetch"))) + (when fetch + (list + (cons 'ref-path (file-name-directory + (cadr (split-string fetch ":")))) + (cons 'trunk-ref-name (file-name-nondirectory + (cadr (split-string fetch ":")))) + ;; get the local ref from the log. This is actually + ;; the way that git-svn does it. + (cons 'local-ref-name + (with-temp-buffer + (insert (magit-git-string "log" "--first-parent")) + (goto-char (point-min)) + (when (re-search-forward "git-svn-id: .+/\\(.+?\\)@" nil t) + (match-string 1)))))))) + +(defun magit-get-svn-trunk-ref () + "Get the best guess remote trunk ref for the current git-svn +based branch." + (let ((info (magit-get-svn-ref-info))) + (concat (cdr (assoc 'ref-path info)) + (cdr (assoc 'trunk-ref-name info))))) (defun magit-get-svn-ref () "Get the best guess remote ref for the current git-svn based branch." - (let* ((info (magit-get "svn-remote" "svn" "fetch")) - (refs)) - (when info - (concat - (file-name-directory (cadr (split-string info ":"))) - (with-temp-buffer - ;; grab the git-svn-id information, this is how git-svn.perl - ;; does it :/ - (insert (magit-git-string "log" "--first-parent")) - (goto-char (point-min)) - (when (re-search-forward "git-svn-id: .+/\\(.+?\\)@" nil t) - (match-string 1))))))) + (let ((info (magit-get-svn-ref-info))) + (concat (cdr (assoc 'ref-path info)) + (cdr (assoc 'local-ref-name info))))) ;;; Resetting diff --git a/magit.etest b/magit.etest new file mode 100644 index 00000000..66afcea8 --- /dev/null +++ b/magit.etest @@ -0,0 +1,16 @@ +(require 'el-mock) + +(etest + ("svn" + (equal (assoc 'trunk-ref-name + (with-mock + (stub magit-get => "someproject/trunk:refs/remotes/hello/trunk") + (magit-get-svn-ref-info))) + '(trunk-ref-name . "trunk") + "correct refpath from `magit-get-svn-ref-info'") + (equal (assoc 'refpath + (with-mock + (stub magit-get => "someproject/trunk:refs/remotes/hello/trunk") + (magit-get-svn-ref-info))) + '(refpath . "refs/remotes/hello/") + "correct refpath from `magit-get-svn-ref-info'"))) From 8ea39540d951a5d5dd3a7afd4bb3af6fc4692135 Mon Sep 17 00:00:00 2001 From: Phil Jackson Date: Wed, 28 Oct 2009 20:37:35 +0000 Subject: [PATCH 3/4] A simple caching mechanism to ease the `magit-get-svn-ref-info' pain. * magit.el: Every call to `magit-get-svn-ref-info', post the first, retrieves a cached list. --- magit.el | 90 +++++++++++++++++++++++++++++------------------------ magit.etest | 6 ++-- 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/magit.el b/magit.el index 975fb13f..87881d8f 100644 --- a/magit.el +++ b/magit.el @@ -1935,17 +1935,17 @@ in log buffer." "log" "--pretty=format:* %H %s" (format "%s/%s..HEAD" remote branch))) -(defun magit-insert-unpulled-svn-commits () +(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)))) + (format "HEAD..%s" (magit-get-svn-ref use-cache)))) -(defun magit-insert-unpushed-svn-commits () +(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)))) + (format "%s..HEAD" (magit-get-svn-ref use-cache)))) ;;; Status @@ -1954,19 +1954,19 @@ in log buffer." (magit-with-section 'status nil (let* ((branch (magit-get-current-branch)) (remote (and branch (magit-get "branch" branch "remote"))) - (svn-enabled (magit-svn-enabled)) + (svn-enabled (magit-svn-enabled)) (head (magit-git-string "log" "--max-count=1" "--abbrev-commit" "--pretty=oneline")) (no-commit (not head))) (if remote (insert (format "Remote: %s %s\n" remote (magit-get "remote" remote "url")))) - (insert (format "Local: %s %s\n" + (insert (format "Local: %s %s\n" (propertize (or branch "(detached)") 'face 'magit-branch) (abbreviate-file-name default-directory))) - (insert (format "Head: %s\n" - (if no-commit "nothing commited (yet)" head))) + (insert (format "Head: %s\n" + (if no-commit "nothing commited (yet)" head))) (let ((merge-heads (magit-file-lines ".git/MERGE_HEAD"))) (if merge-heads (insert (format "Merging: %s\n" @@ -1977,7 +1977,7 @@ in log buffer." (if rebase (insert (apply 'format "Rebasing: %s (%s of %s)\n" rebase)))) (insert "\n") - (magit-git-exit-code "update-index" "--refresh") + (magit-git-exit-code "update-index" "--refresh") (magit-insert-untracked-files) (magit-insert-stashes) (magit-insert-topics) @@ -1985,8 +1985,8 @@ in log buffer." (magit-insert-pending-commits) (when remote (magit-insert-unpulled-commits remote branch)) - (when svn-enabled - (magit-insert-unpulled-svn-commits)) + (when svn-enabled + (magit-insert-unpulled-svn-commits t)) (let ((staged (or no-commit (magit-anything-staged-p)))) (magit-insert-unstaged-changes (if staged "Unstaged changes:" "Changes:")) @@ -1994,8 +1994,8 @@ in log buffer." (magit-insert-staged-changes no-commit))) (when remote (magit-insert-unpushed-commits remote branch)) - (when svn-enabled - (magit-insert-unpushed-svn-commits)))))) + (when svn-enabled + (magit-insert-unpushed-svn-commits t)))))) (defun magit-init (dir) "Initialize git repository in specified directory" @@ -2190,40 +2190,48 @@ in log buffer." (magit-run-git-async "svn" "dcommit")) (defun magit-svn-enabled () - (not (null (magit-get "svn-remote" "svn" "fetch")))) + (not (null (magit-get-svn-ref-info)))) -(defun magit-get-svn-ref-info () +(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) "Gather details about the current git-svn repository (nil if there isn't one). Keys of the alist are ref-path, trunk-ref-name -and local-ref-name." - (let* ((fetch (magit-get "svn-remote" "svn" "fetch")) - (branches (magit-get "svn-remote" "svn" "fetch"))) - (when fetch - (list - (cons 'ref-path (file-name-directory - (cadr (split-string fetch ":")))) - (cons 'trunk-ref-name (file-name-nondirectory - (cadr (split-string fetch ":")))) - ;; get the local ref from the log. This is actually - ;; the way that git-svn does it. - (cons 'local-ref-name - (with-temp-buffer - (insert (magit-git-string "log" "--first-parent")) - (goto-char (point-min)) - (when (re-search-forward "git-svn-id: .+/\\(.+?\\)@" nil t) - (match-string 1)))))))) +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")) + (branches (magit-get "svn-remote" "svn" "fetch")) + (url) + (revision)) + (when fetch + (setq magit-get-svn-ref-info-cache + (list + (cons 'ref-path (file-name-directory + (cadr (split-string fetch ":")))) + (cons 'trunk-ref-name (file-name-nondirectory + (cadr (split-string fetch ":")))) + ;; get the local ref from the log. This is actually + ;; the way that git-svn does it. + (cons 'local-ref-name + (with-temp-buffer + (insert (magit-git-string "log" "--first-parent")) + (goto-char (point-min)) + (when (re-search-forward "git-svn-id: \\(.+/\\(.+?\\)\\)@\\([0-9]+\\)" nil t) + (setq url (match-string 1) + revision (match-string 3)) + (match-string 2)))) + (cons 'revision revision) + (cons 'url url))))))) -(defun magit-get-svn-trunk-ref () - "Get the best guess remote trunk ref for the current git-svn -based branch." - (let ((info (magit-get-svn-ref-info))) - (concat (cdr (assoc 'ref-path info)) - (cdr (assoc 'trunk-ref-name info))))) - -(defun magit-get-svn-ref () +(defun magit-get-svn-ref (&optional use-cache) "Get the best guess remote ref for the current git-svn based branch." - (let ((info (magit-get-svn-ref-info))) + (let ((info (magit-get-svn-ref-info use-cache))) (concat (cdr (assoc 'ref-path info)) (cdr (assoc 'local-ref-name info))))) diff --git a/magit.etest b/magit.etest index 66afcea8..56724fc1 100644 --- a/magit.etest +++ b/magit.etest @@ -7,10 +7,10 @@ (stub magit-get => "someproject/trunk:refs/remotes/hello/trunk") (magit-get-svn-ref-info))) '(trunk-ref-name . "trunk") - "correct refpath from `magit-get-svn-ref-info'") - (equal (assoc 'refpath + "correct trunk-ref-name from `magit-get-svn-ref-info'") + (equal (assoc 'ref-path (with-mock (stub magit-get => "someproject/trunk:refs/remotes/hello/trunk") (magit-get-svn-ref-info))) '(refpath . "refs/remotes/hello/") - "correct refpath from `magit-get-svn-ref-info'"))) + "correct refpath from `magit-get-svn-ref-info'"))) \ No newline at end of file From e3a37dbc39eba45377c5205ea7f60deb91b384b9 Mon Sep 17 00:00:00 2001 From: Phil Jackson Date: Wed, 28 Oct 2009 20:41:43 +0000 Subject: [PATCH 4/4] Set the remote string to the svn url and revision when in a git-svn repo. --- magit.el | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/magit.el b/magit.el index 87881d8f..f49b85f2 100644 --- a/magit.el +++ b/magit.el @@ -1949,23 +1949,31 @@ in log buffer." ;;; 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)) + " @ " + (cdr (assoc 'revision svn-info)))))) + (defun magit-refresh-status () (magit-create-buffer-sections (magit-with-section 'status nil (let* ((branch (magit-get-current-branch)) (remote (and branch (magit-get "branch" branch "remote"))) - (svn-enabled (magit-svn-enabled)) + (svn-info (magit-get-svn-ref-info)) + (remote-string (magit-remote-string remote svn-info)) (head (magit-git-string "log" "--max-count=1" "--abbrev-commit" "--pretty=oneline")) (no-commit (not head))) - (if remote - (insert (format "Remote: %s %s\n" - remote (magit-get "remote" remote "url")))) - (insert (format "Local: %s %s\n" + (when remote-string + (insert "Remote: " remote-string "\n")) + (insert (format "Local: %s %s\n" (propertize (or branch "(detached)") 'face 'magit-branch) (abbreviate-file-name default-directory))) - (insert (format "Head: %s\n" + (insert (format "Head: %s\n" (if no-commit "nothing commited (yet)" head))) (let ((merge-heads (magit-file-lines ".git/MERGE_HEAD"))) (if merge-heads @@ -1985,7 +1993,7 @@ in log buffer." (magit-insert-pending-commits) (when remote (magit-insert-unpulled-commits remote branch)) - (when svn-enabled + (when svn-info (magit-insert-unpulled-svn-commits t)) (let ((staged (or no-commit (magit-anything-staged-p)))) (magit-insert-unstaged-changes @@ -1994,7 +2002,7 @@ in log buffer." (magit-insert-staged-changes no-commit))) (when remote (magit-insert-unpushed-commits remote branch)) - (when svn-enabled + (when svn-info (magit-insert-unpushed-svn-commits t)))))) (defun magit-init (dir)