threads / patch / 12181

v3, 3 partsswitching, branch creating branch and merging within Emacs

Subject: [PATCH v3 00/03] switching, branch creating branch and merging within Emacs

## tl;dr

4 messages between Feb 18, 2008 and Feb 18, 2008. Diffs are folded; open one to read it.

replies: 3people: 1as markdown or json

Rémi Vanicat· Feb 18, 2008, 16:24 UTC · lore

So, I resend my patch series, with better keys binding, reworked refs reading (using git-for-each-ref), and a common framework for building menu for merge/checkout/rebase/branching (even if it is for now only use for checkout and merge).

-- 
Rémi Vanicat
Remi Vanicat· Feb 18, 2008, 16:32 UTC · re: Rémi Vanicat · lore

[PATCH v3 01/03] Add helpers functions for refs and commitish to git.el

git-list-refs list refs
git-refs-build-menu is a function to build menu for refs
git-read-commitish ask the user a commitish, with completion for
branch, local and remote, and tags.
---
 contrib/emacs/git.el |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 71 insertions(+), 0 deletions(-)
Show changes to contrib/emacs/git.el +71 −0
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index a8bf0ef..5166fca 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1138,6 +1138,77 @@ Return the list of files that haven't been handled."
   (when (eq (window-buffer) (current-buffer))
     (shrink-window-if-larger-than-buffer)))
 
+(defun git-list-refs (&optional spec)
+  "return a list of refs using git-for-each-refs
+
+if type is nil or :all return all refs
+if it is :branches return local branches
+if it is :remotes return remote branches
+if it is :tags return tags"
+  (let ((ref-spec (cond
+		    ((or (eq spec :all) (eq spec ()))
+		     "*/*/*")
+		    ((eq spec :branches)
+		     "refs/heads")
+		    ((eq spec :remotes)
+		     "refs/remotes")
+		    ((eq spec :tags)
+		     "refs/tags")
+		    (t (error "don't know what to do with %s" spec))))
+	refs)
+    (with-temp-buffer
+      (git-call-process-env t nil "for-each-ref" ref-spec "--format=%(refname)")
+      (goto-char (point-min))
+      (while (re-search-forward "^[^/]+/[^/]+/\\([^\n]*\\)$" () t)
+	(push (cons (match-string 1)
+		    (match-string 0))
+	      refs)))
+    (nreverse refs)))
+
+(defun git-refs-build-menu-helper (refs fcts)
+  (let ((menu ()))
+    (dolist (branch (git-list-refs refs))
+      (push (funcall fcts (car branch) (cdr branch))
+	    menu))
+     (nreverse menu)))
+
+(defun git-refs-build-menu (&rest rest)
+  (let (before branch tag remote after)
+    (while (and rest
+		(cdr rest)
+		(keywordp (car rest)))
+      (cond
+	((eq :before (car rest))
+	 (setq before (cadr rest)))
+	((eq :branch (car rest))
+	 (setq branch (cadr rest)))
+	((eq :tag (car rest))
+	 (setq tag (cadr rest)))
+	((eq :remote (car rest))
+	 (setq remote (cadr rest)))
+	((eq :after (car rest))
+	 (setq after (cadr rest)))
+	((error "git-refs-build-menu: I don't know this keyword")))
+      (setq rest (cddr rest)))
+    (unless (and (not rest)
+		 remote tag branch)
+      (error "bad argument list"))
+    `(,@before
+      ,@(git-refs-build-menu-helper :branches branch)
+      "------"
+      ("Remotes" ,@(git-refs-build-menu-helper :remotes remote))
+      ("Tags" ,@(git-refs-build-menu-helper :tags remote))
+      "------"
+      ,@after)))
+
+(defun git-read-commitish (prompt &optional default)
+  "ask user a commitish, with commpletion for local branch, remote branch and tag"
+  (completing-read prompt (list* "HEAD"
+				 "ORIG_HEAD"
+				 "FETCH_HEAD"
+				 (git-list-refs :all))
+		   () () () () default))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
-- 
1.5.4.1.123.gcb68-dirty
Rémi Vanicat· Feb 18, 2008, 16:34 UTC · re: Rémi Vanicat · lore

[PATCH v3 02/03] Adding checkout function for commitish in git.el

M-x git-checkout ask for a commitish, and checkout it as in
  git checkout commitish --
  key binding: "C-cC-o"
M-x git-branch ask for the name of a new branch, create it and
checkout it as in
  git checkout -b name
  key binding: "C-cC-b"
M-x git-create-branch ask for a new branchname, a startpoint (a
commitish) and create a new branch as in
  git branch branchname startpoint
  key binding "B C"
A menu is also available for just switching branch
---
 contrib/emacs/git.el |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 52 insertions(+), 0 deletions(-)
Show changes to contrib/emacs/git.el +52 −0
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 5166fca..d35f837 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1209,6 +1209,51 @@ if it is :tags return tags"
 				 (git-list-refs :all))
 		   () () () () default))
 
+(defun git-checkout (branch &optional merge)
+  "checkout a branch, tag, or any commitish
+
+use a prefix arg if git should merge while checking out"
+  (interactive
+   (list (git-read-commitish "Branch: ")
+	 current-prefix-arg))
+  (let ((args (list branch "--")))
+    (if merge (push "-m" args))
+    (if (apply #'git-call-process-display-error "checkout" args)
+	(git-refresh-status))))
+
+(defun git-branch (branch)
+  "branch from current commit and checkout the new branch"
+  (interactive "MBranch: ")
+  (if (git-call-process-display-error "checkout" "-b" branch)
+      (git-refresh-status)))
+
+(defun git-create-branch (branch start-point)
+  "create a new branch named [branch] from the [start-point]"
+  (interactive
+   (list (read-string "New branch: ")
+	 (git-read-commitish "Start point(HEAD): " "HEAD")))
+  (git-call-process-display-error "branch" branch start-point))
+
+(defun git-checkout-menu-filter (rest)
+  "define the change branch menu"
+  (let ((head (git-symbolic-ref "HEAD")))
+    (git-refs-build-menu
+     :before `(["detached head" ignore
+				:visible ,(not head)
+				:selected ,(not head)
+				:style radio
+				:key-sequence nil])
+     :branch (lambda (short-name ref-name)
+	       `[,short-name (git-checkout ,short-name)
+			      :style radio
+			      :selected ,(string= head ref-name)])
+     :remote (lambda (short-name ref-name)
+	       `[,short-name (git-checkout ,ref-name)])
+     :tag (lambda (short-name ref-name)
+	    `[,short-name (git-checkout ,ref-name)])
+     :after `(["checkout any commitish" git-checkout t]
+	      ["change to new" git-branch t]))))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1491,6 +1536,7 @@ amended version of it."
 (unless git-status-mode-map
   (let ((map (make-keymap))
         (commit-map (make-sparse-keymap))
+        (branch-map (make-sparse-keymap))
         (diff-map (make-sparse-keymap))
         (toggle-map (make-sparse-keymap)))
     (suppress-keymap map)
@@ -1498,6 +1544,7 @@ amended version of it."
     (define-key map "h"   'git-help)
     (define-key map " "   'git-next-file)
     (define-key map "a"   'git-add-file)
+    (define-key map "B"    branch-map)
     (define-key map "c"   'git-commit-file)
     (define-key map "\C-c" commit-map)
     (define-key map "d"    diff-map)
@@ -1525,8 +1572,12 @@ amended version of it."
     (define-key map "x"   'git-remove-handled)
     (define-key map "\C-?" 'git-unmark-file-up)
     (define-key map "\M-\C-?" 'git-unmark-all)
+    ; the branch map
+    (define-key branch-map "C" 'git-create-branch)
     ; the commit submap
     (define-key commit-map "\C-a" 'git-amend-commit)
+    (define-key commit-map "\C-o" 'git-checkout)
+    (define-key commit-map "\C-b" 'git-branch)
     ; the diff submap
     (define-key diff-map "b" 'git-diff-file-base)
     (define-key diff-map "c" 'git-diff-file-combined)
@@ -1547,6 +1598,7 @@ amended version of it."
     `("Git"
       ["Refresh" git-refresh-status t]
       ["Commit" git-commit-file t]
+      ("Checkout Branch" :filter git-checkout-menu-filter)
       ("Merge"
 	["Next Unmerged File" git-next-unmerged-file t]
 	["Prev Unmerged File" git-prev-unmerged-file t]
-- 
1.5.4.1.123.gcb68-dirty
Rémi Vanicat· Feb 18, 2008, 16:35 UTC · re: Rémi Vanicat · lore

[PATCH v3 03/03] Adding command for merging in git.el

M-x git-merge will ask for an commitish, and merge with it.
    key binding "C-cC-m"
A new submenu is also available for merging with local and remote
branch.
---
 contrib/emacs/git.el |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)
Show changes to contrib/emacs/git.el +23 −1
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index d35f837..5c3fc01 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1254,6 +1254,26 @@ use a prefix arg if git should merge while checking out"
      :after `(["checkout any commitish" git-checkout t]
 	      ["change to new" git-branch t]))))
 
+(defun git-merge (commitish)
+  "merge with commitish
+
+Note that in case of conflict, after resolving everty conflict,
+one have to select every concerned file before commiting"
+  (interactive (list (git-read-commitish "Merge with: ")))
+  (git-call-process-display-error "merge" commitish)
+  (git-refresh-status))
+
+(defun git-merge-menu-filter (rest)
+  "define the change branch menu"
+  (git-refs-build-menu
+   :branch (lambda (short-name ref-name)
+	     `[,short-name (git-merge ,short-name)])
+   :remote (lambda (short-name ref-name)
+	     `[,short-name (git-merge ,short-name)])
+   :tag (lambda (short-name ref-name)
+	  `[,short-name (git-merge ,short-name)])
+   :after `(["merge with any commitish" git-merge t])))
+
 (defun git-diff-file ()
   "Diff the marked file(s) against HEAD."
   (interactive)
@@ -1578,6 +1598,7 @@ amended version of it."
     (define-key commit-map "\C-a" 'git-amend-commit)
     (define-key commit-map "\C-o" 'git-checkout)
     (define-key commit-map "\C-b" 'git-branch)
+    (define-key commit-map "\C-m" 'git-merge)
     ; the diff submap
     (define-key diff-map "b" 'git-diff-file-base)
     (define-key diff-map "c" 'git-diff-file-combined)
@@ -1599,7 +1620,8 @@ amended version of it."
       ["Refresh" git-refresh-status t]
       ["Commit" git-commit-file t]
       ("Checkout Branch" :filter git-checkout-menu-filter)
-      ("Merge"
+      ("Merge" :filter git-merge-menu-filter)
+      ("Resolve Merge"
 	["Next Unmerged File" git-next-unmerged-file t]
 	["Prev Unmerged File" git-prev-unmerged-file t]
 	["Mark as Resolved" git-resolve-file t]
-- 
1.5.4.1.123.gcb68-dirty

← back to recent threads