[PATCH v4] contrib/emacs/git.el: Add user functions for push, pull, fetch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jari Aalto <jari.aalto@xxxxxxxxx>

Signed-off-by: Jari Aalto <jari.aalto@xxxxxxxxx>
---
 contrib/emacs/git.el |  110 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 1 deletions(-)

  [v2]
  ** This fixes the pull message. The only change is last line:
  ** (message "Pulled from remote: %s" remote)))

  [v3] Fixes commented by <julliard@xxxxxxxxxx>
  ** Extra C-a keymap binding removed
  ** Check success status before displaying message
  ** no need to refresh the status files on push or fetch

  [v4]
  ** Parse remotes from .git/config and offer them as completions (push/pull)

diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 65c95d9..97d2484 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1,6 +1,7 @@
 ;;; git.el --- A user interface for git
 
 ;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Alexandre Julliard <julliard@xxxxxxxxxx>
+;; Copyright (C) 2010 Jari Aalto <jari.aalto@xxxxxxxxx>
 
 ;; Version: 1.0
 
@@ -33,11 +34,14 @@
 ;;
 ;; To start: `M-x git-status'
 ;;
+;; RUDIMENTARY
+;; - fetch/pull. Be sure to start gpg-agent, ssh-agent prior emacs
+;;   to access ssh Git remotes.
+;;
 ;; TODO
 ;;  - diff against other branch
 ;;  - renaming files from the status buffer
 ;;  - creating tags
-;;  - fetch/pull
 ;;  - revlist browser
 ;;  - git-show-branch browser
 ;;
@@ -384,6 +388,25 @@ the process output as a string, or nil if the git command failed."
   (git-get-string-sha1
    (git-call-process-string "rev-parse" rev)))
 
+(defun git-root ()
+  "Return root of git directory. Start from current dir way up."
+  (let* ((dir (file-name-as-directory default-directory))
+	 (try (format "%s%s" dir ".git")))
+    (while (and dir
+		(not (file-directory-p try)))
+      (if (string-match "^\\(.*/\\).+$" dir)
+	  (setq dir (match-string 1 dir)
+		try (format "%s%s" dir ".git"))
+	(setq dir nil
+	      try nil)))
+    try))
+
+(defsubst git-config-file ()
+  "Return 'config' file location."
+  (let ((dir (git-root)))
+    (if dir
+	(format "%s/config" dir))))
+
 (defun git-config (key)
   "Retrieve the value associated to KEY in the git repository config file."
   (let ((str (git-call-process-string "config" key)))
@@ -1527,6 +1550,7 @@ amended version of it."
 
 (unless git-status-mode-map
   (let ((map (make-keymap))
+        (remote-map (make-sparse-keymap))
         (commit-map (make-sparse-keymap))
         (diff-map (make-sparse-keymap))
         (toggle-map (make-sparse-keymap)))
@@ -1554,6 +1578,7 @@ amended version of it."
     (define-key map "P"   'git-prev-unmerged-file)
     (define-key map "q"   'git-status-quit)
     (define-key map "r"   'git-remove-file)
+    (define-key map "R"   remote-map)
     (define-key map "t"    toggle-map)
     (define-key map "T"   'git-toggle-all-marks)
     (define-key map "u"   'git-unmark-file)
@@ -1562,6 +1587,11 @@ 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)
+    ; remotes
+    (define-key remote-map "R" 'git-pull)  ; retrieve "RR"
+    (define-key remote-map "r" 'git-pull)  ; retrieve "Rr" (synonym)
+    (define-key remote-map "p" 'git-push)
+    (define-key remote-map "f" 'git-fetch)
     ; the commit submap
     (define-key commit-map "\C-a" 'git-amend-commit)
     (define-key commit-map "\C-b" 'git-branch)
@@ -1614,6 +1644,10 @@ amended version of it."
       ["Interactive Diff File" git-diff-file-idiff t]
       ["Log" git-log-file t]
       "--------"
+      ["Push" git-push t]
+      ["Pull" git-pull t]
+      ["Fetch" git-fetch t]
+      "--------"
       ["Mark" git-mark-file t]
       ["Mark All" git-mark-all t]
       ["Unmark" git-unmark-file t]
@@ -1696,6 +1730,80 @@ Meant to be used in `after-save-hook'."
             (git-call-process nil "add" "--refresh" "--" filename)
             (git-update-status-files (list filename))))))))
 
+(defun git-remote-parse ()
+  "Parse remotes from current point forward. Return list."
+  (let (list)
+    ;; [remote "origin"]
+    (while (re-search-forward "^\\[remote[[:space:]]+\"\\([^\"]+\\)" nil t)
+      (push (match-string-no-properties 1) list))
+    list))
+
+(defun git-remote-list ()
+  "Return list of remotes from Git configuration."
+  (with-temp-buffer
+    (insert-file-contents-literally (git-config-file))
+    (goto-char (point-min))
+    (git-remote-parse)))
+
+(defun git-ask-remote (prompt)
+  "Read remote with PROMPT."
+  (let ((list (git-remote-list))
+	(default "origin")
+	ret)
+    (unless (member default list)
+      (setq default (car list)))
+    (setq ret
+	  (completing-read prompt
+			   list
+			   (not 'predicate)
+			   'require-match
+			   (not 'default)
+			   (not 'history)
+			   default))
+    (if (string-match "^[ \t\r\n]*$" ret)
+	(setq ret default))
+    ret))
+
+(defun git-push (&optional remote)
+  "Pull to REMOTE. Use \\[current-prefix-arg] to interactively set REMOTE."
+  (interactive
+   (list (or (and current-prefix-arg
+		  (git-ask-remote "Push to remote: "))
+	     "origin")))
+  ;; FIXME: could collect some status data for display
+  (when (git-call-process-display-error "push" remote)
+    (message "Pushed to remote: %s" remote)))
+
+(defun git-fetch (&optional remote)
+  "Fetch from REMOTE. Use \\[current-prefix-arg] to interactively set REMOTE."
+  (interactive
+   (list (or (and current-prefix-arg
+		  (git-ask-remote "Fetch from remote: "))
+	     "origin")))
+  ;; FIXME: could collect some status data for display
+  (when (git-call-process-display-error "fetch" remote)
+    (message "Fetched from remote: %s" remote)))
+
+(defun git-pull (&optional remote)
+  "Pull from REMOTE. Use \\[current-prefix-arg] to interactively set REMOTE."
+  (interactive
+   (list (or (and current-prefix-arg
+		  (git-ask-remote "Pull from remote: "))
+	     "origin")))
+  (let ((not-clean
+	 (ewoc-collect git-status (lambda (info &optional state)
+				    (setq state (git-fileinfo->state info))
+				    (or (memq state '(added
+						      deleted
+						      modified
+						      unmerged)))))))
+    (if not-clean
+	(error "Error: Can't pull while in unclean state (commit all first)."))
+    (unless git-status (error "Not in git-status buffer."))
+    ;; FIXME: could collect some status data for display
+    (when (git-call-process-display-error "pull" remote)
+      (message "Pulled from remote: %s" remote))))
+
 (defun git-help ()
   "Display help for Git mode."
   (interactive)
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]