* lisp/xgit-gnus.el (xgit-gnus-apply-patch): Don't throw error if no
  apply-patch mapping directory found.  Make sure working directory has
  trailing slash.  If no .git directory exists in working directory, do a
  "git apply" and then prepare an initial commit message for the patch.
  (xgit-gnus-stage-patch-for-commit): New function that extracts subject
  and body from a patch buffer, runs dvc-diff, and makes an initial
  commit message.
  (xgit-gnus-view-status-for-apply-patch): Make sure working directory
  has trailing slash.

* lisp/xgit.el (xgit-apply-patch): New function that runs "git apply".
  (xgit-apply-mbox): Improve documentation.
---
Committed revision 2b4b57b89ce2878101f8b67c9a3a2a9e157d0f0d
to <git://git.hcoop.net/git/mwolson/emacs/dvc.git>.

 lisp/xgit-gnus.el |   55 +++++++++++++++++++++++++++++++++++++++++++++-------
 lisp/xgit.el      |   19 +++++++++++++++++-
 2 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/lisp/xgit-gnus.el b/lisp/xgit-gnus.el
index 0cb78b6..e5f19b2 100644
--- a/lisp/xgit-gnus.el
+++ b/lisp/xgit-gnus.el
@@ -78,6 +78,7 @@ patches from the entire message."
                                  ".patch"))
         (window-conf (current-window-configuration))
         (err-occurred nil)
+        (trigger-commit nil)
         working-dir patch-buffer)
     (gnus-summary-show-article 'raw)
     (gnus-summary-select-article-buffer)
@@ -91,9 +92,7 @@ patches from the entire message."
         (dolist (m xgit-apply-patch-mapping)
           (when (looking-at (car m))
             (setq working-dir (dvc-uniquify-file-name (cadr m)))
-            (throw 'found t)))
-        (error (concat "Unable to find an matching entry in"
-                       " `xgit-apply-patch-mapping'"))))
+            (throw 'found t)))))
     (gnus-summary-show-article)
     (delete-other-windows)
     (dvc-buffer-push-previous-window-config)
@@ -101,20 +100,58 @@ patches from the entire message."
     (setq patch-buffer (current-buffer))
     (setq working-dir (dvc-read-directory-name "Apply git patch to: "
                                                nil nil t working-dir))
+    (when working-dir
+      (setq working-dir (file-name-as-directory working-dir)))
     (unwind-protect
         (progn
           (when working-dir
             (let ((default-directory working-dir))
-              (xgit-apply-mbox patch-file-name force)))
+              (if (or (xgit-lookup-external-git-dir)
+                      (file-exists-p ".git/"))
+                  ;; apply the patch and commit if it applies cleanly
+                  (xgit-apply-mbox patch-file-name force)
+                ;; just apply the patch, since we might not be in a
+                ;; git repo
+                (xgit-apply-patch patch-file-name)
+                (setq trigger-commit t))))
           (set-window-configuration window-conf)
-          (when (and working-dir
-                     (y-or-n-p "Run git log in working directory? "))
-            (xgit-log working-dir nil)
-            (delete-other-windows)))
+          (when working-dir
+            (if trigger-commit
+                (xgit-gnus-stage-patch-for-commit working-dir patch-buffer)
+              (when (y-or-n-p "Run git log in working directory? ")
+                (xgit-log working-dir nil)
+                (delete-other-windows)))))
       ;; clean up temporary file
       (delete-file patch-file-name)
       (kill-buffer patch-buffer))))
 
+(defun xgit-gnus-stage-patch-for-commit (working-dir patch-buffer)
+  "Switch to directory WORKING-DIR and set up a commit based on the patch
+contained in PATCH-BUFFER."
+  (let ((default-directory working-dir))
+    (destructuring-bind (subject body)
+        (with-current-buffer patch-buffer
+          (let (subject body)
+            (goto-char (point-min))
+            (when (re-search-forward "^Subject: *\\(.+\\)$" nil t)
+              (setq subject (match-string 1)))
+            (goto-char (point-min))
+            (when (re-search-forward "^$" nil t)
+              (forward-line 1)
+              (let ((beg (point)))
+                (when (re-search-forward "^---$" nil t)
+                  (setq body (buffer-substring beg (match-beginning 0))))))
+            (list subject body)))
+      ;; strip "[COMMIT]" prefix
+      (when (and subject
+                 (string-match "\\`\\[[^]]+\\] *" subject))
+        (setq subject (substring subject (match-end 0))))
+      (message "Staging patch for commit ...")
+      (dvc-diff)
+      (dvc-log-edit)
+      (erase-buffer)
+      (insert subject "\n\n" body))))
+
 (defvar xgit-gnus-status-window-configuration nil)
 (defun xgit-gnus-article-view-status-for-apply-patch (n)
   "View the status for the repository, where MIME part N would be applied
@@ -143,6 +180,8 @@ guess the repository path via `xgit-apply-patch-mapping'."
       (setq working-dir (dvc-read-directory-name
                          "View git repository status for: "
                          nil nil t working-dir)))
+    (when working-dir
+      (setq working-dir (file-name-as-directory working-dir)))
     (let ((default-directory working-dir))
       (xgit-dvc-status)
       (delete-other-windows)
diff --git a/lisp/xgit.el b/lisp/xgit.el
index da6a35d..bbc8c40 100644
--- a/lisp/xgit.el
+++ b/lisp/xgit.el
@@ -686,8 +686,25 @@ When ALL is given, show all branches, using \"git branch 
-a\"."
                       :finished 'dvc-output-buffer-split-handler)))
 
 ;;;###autoload
+(defun xgit-apply-patch (file)
+  "Run \"git apply\" to apply the contents of FILE as a patch."
+  (interactive (list (dvc-confirm-read-file-name
+                      "Apply file containing patch: " t)))
+  (dvc-run-dvc-sync 'xgit
+                    (list "apply" (expand-file-name file))
+                    :finished
+                    (lambda (output error status arguments)
+                      (message "Imported git patch from %s" file))
+                    :error
+                    (lambda (output error status arguments)
+                      (dvc-show-error-buffer error)
+                      (error "Error occurred while applying patch(es)"))))
+
+;;;###autoload
 (defun xgit-apply-mbox (mbox &optional force)
-  "Run git am to apply the contents of MBOX as one or more patches."
+  "Run \"git am\" to apply the contents of MBOX as one or more patches.
+If this command succeeds, it will result in a new commit being added to
+the current git repository."
   (interactive (list (dvc-confirm-read-file-name
                       "Apply mbox containing patch(es): " t)))
   (dvc-run-dvc-sync 'xgit
-- 
1.5.4.3


-- 
|       Michael Olson  |  FSF Associate Member #652     |
| http://mwolson.org/  |  Hobbies: Lisp, HCoop          |
| Projects: Emacs, Muse, ERC, EMMS, ErBot, DVC, Planner |
`-------------------------------------------------------'

_______________________________________________
Dvc-dev mailing list
[email protected]
https://mail.gna.org/listinfo/dvc-dev

Reply via email to