emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/magit e52dedf07f 22/28: magit-stash-{pop, apply}: Stop aft


From: Jonas Bernoulli
Subject: [nongnu] elpa/magit e52dedf07f 22/28: magit-stash-{pop, apply}: Stop after successfully installing conflict
Date: Fri, 6 Dec 2024 17:17:05 -0500 (EST)

branch: elpa/magit
commit e52dedf07f7726528cd006db88235c23a481351d
Author: Jonas Bernoulli <jonas@bernoul.li>
Commit: Jonas Bernoulli <jonas@bernoul.li>

    magit-stash-{pop,apply}: Stop after successfully installing conflict
    
    If we cannot successfully install the conflict with "git stash apply
    --index", we also try "git stash apply", and if that fails as well,
    we continue with "git apply --3way".
    
    That assumed that we could tell whether a stash was either applied
    with no conflict or the conflict was successfully installed by, or
    else the conflict could not be installed, by checking status.
    
    Unfortunately it turns out that the exit status is also 1 if the
    conflict was successfully installed.  Instead we have to look at
    the output.
    
    Unfortunately we can only do that for Git v2.38.0 and later, and
    have to fall back to the less convenient behavior provided by Git
    itself.
    
    Closes #5253.
---
 CHANGELOG           |  6 +++++
 docs/magit.org      | 10 +++++++
 docs/magit.texi     | 10 +++++++
 lisp/magit-stash.el | 77 +++++++++++++++++++++++++++++++++++++----------------
 4 files changed, 80 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index ed2544303b..b11e9147f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,12 @@
 
 - Improved ~magit-process-password-prompt-regexps~.  #5257
 
+Bug fixes:
+
+- ~magit-stash-pop~ and ~magit-stash-apply~ sometimes installed conflicts
+  for the user to resolve that are more complicated than they need to
+  be.  #5253
+
 * v4.1.2    2024-11-02
 
 - Add various minor process logging improvements:
diff --git a/docs/magit.org b/docs/magit.org
index 14fdc7f9b5..981fbb76a8 100644
--- a/docs/magit.org
+++ b/docs/magit.org
@@ -6423,6 +6423,11 @@ Also see [[man:git-stash]]
 
   Apply a stash to the working tree.
 
+  When using a Git release before v2.38.0, simply run ~git stash apply~
+  or with a prefix argument ~git stash apply --index~.
+
+  When using Git v2.38.0 or later, behave more intelligently:
+
   First try ~git stash apply --index~, which tries to preserve
   the index stored in the stash, if any.  This may fail because
   applying the stash could result in conflicts and those have to
@@ -6448,6 +6453,11 @@ Also see [[man:git-stash]]
   stash can be applied without any conflicts, and while preserving
   the stash's index) then remove the stash from stash list.
 
+  When using a Git release before v2.38.0, simply run ~git stash pop~
+  or with a prefix argument ~git stash pop --index~.
+
+  When using Git v2.38.0 or later, behave more intelligently:
+
   First try ~git stash pop --index~, which tries to preserve
   the index stored in the stash, if any.  This may fail because
   applying the stash could result in conflicts and those have to
diff --git a/docs/magit.texi b/docs/magit.texi
index f00d9e7fff..b4ee44b312 100644
--- a/docs/magit.texi
+++ b/docs/magit.texi
@@ -7913,6 +7913,11 @@ prefix arguments are equivalent to @code{--all}-.
 @findex magit-stash-apply
 Apply a stash to the working tree.
 
+When using a Git release before v2.38.0, simply run @code{git stash apply}
+or with a prefix argument @code{git stash apply --index}.
+
+When using Git v2.38.0 or later, behave more intelligently:
+
 First try @code{git stash apply --index}, which tries to preserve
 the index stored in the stash, if any.  This may fail because
 applying the stash could result in conflicts and those have to
@@ -7939,6 +7944,11 @@ Apply a stash to the working tree.  On complete success 
(if the
 stash can be applied without any conflicts, and while preserving
 the stash's index) then remove the stash from stash list.
 
+When using a Git release before v2.38.0, simply run @code{git stash pop}
+or with a prefix argument @code{git stash pop --index}.
+
+When using Git v2.38.0 or later, behave more intelligently:
+
 First try @code{git stash pop --index}, which tries to preserve
 the index stored in the stash, if any.  This may fail because
 applying the stash could result in conflicts and those have to
diff --git a/lisp/magit-stash.el b/lisp/magit-stash.el
index 19d0786551..b929332224 100644
--- a/lisp/magit-stash.el
+++ b/lisp/magit-stash.el
@@ -262,6 +262,11 @@ specifying a list of files to be stashed."
 (defun magit-stash-apply (stash)
   "Apply a stash to the working tree.
 
+When using a Git release before v2.38.0, simply run \"git stash
+apply\" or with a prefix argument \"git stash apply --index\".
+
+When using Git v2.38.0 or later, behave more intelligently:
+
 First try \"git stash apply --index\", which tries to preserve
 the index stored in the stash, if any.  This may fail because
 applying the stash could result in conflicts and those have to
@@ -284,6 +289,11 @@ the user whether to use \"--3way\" or \"--reject\"."
 (defun magit-stash-pop (stash)
   "Apply a stash to the working tree, on success remove it from stash list.
 
+When using a Git release before v2.38.0, simply run \"git stash
+pop\" or with a prefix argument \"git stash pop --index\".
+
+When using Git v2.38.0 or later, behave more intelligently:
+
 First try \"git stash pop --index\", which tries to preserve
 the index stored in the stash, if any.  This may fail because
 applying the stash could result in conflicts and those have to
@@ -303,29 +313,50 @@ the user whether to use \"--3way\" or \"--reject\"."
   (magit-stash--apply "pop" stash))
 
 (defun magit-stash--apply (action stash)
-  (or (= (magit-call-git "stash" action "--index" stash) 0)
-      ;; The stash's index could not be applied, so always keep the stash.
-      (= (magit-call-git "stash" "apply" stash) 0)
-      (let* ((range (format "%s^..%s" stash stash))
-             (stashed (magit-git-items "diff" "-z" "--name-only" range "--"))
-             (conflicts (cl-sort (cl-union (magit-unstaged-files t stashed)
-                                           (magit-untracked-files t stashed)
-                                           :test #'equal)
-                                 #'string<))
-             (arg (cond
-                   ((not conflicts) "--3way")
-                   ((magit-confirm-files
-                     'stash-apply-3way conflicts
-                     "Apply stash using `--3way', which requires first staging"
-                     "(else use `--reject')"
-                     t)
-                    (magit-stage-1 nil conflicts)
-                    "--3way")
-                   ("--reject"))))
-        (with-temp-buffer
-          (magit-git-insert "diff" range)
-          (magit-run-git-with-input "apply" arg "-"))))
-  (magit-refresh))
+  (if (magit-git-version< "2.38.0")
+      (magit-run-git "stash" action stash (and current-prefix-arg "--index"))
+    (or (magit--run-git-stash action "--index" stash)
+        ;; The stash's index could not be applied, so always keep the stash.
+        (magit--run-git-stash "apply" stash)
+        (let* ((range (format "%s^..%s" stash stash))
+               (stashed (magit-git-items "diff" "-z" "--name-only" range "--"))
+               (conflicts (cl-sort (cl-union (magit-unstaged-files t stashed)
+                                             (magit-untracked-files t stashed)
+                                             :test #'equal)
+                                   #'string<))
+               (arg (cond
+                     ((not conflicts) "--3way")
+                     ((magit-confirm-files
+                       'stash-apply-3way conflicts
+                       "Apply stash using `--3way', which requires first 
staging"
+                       "(else use `--reject')"
+                       t)
+                      (magit-stage-1 nil conflicts)
+                      "--3way")
+                     ("--reject"))))
+          (with-temp-buffer
+            (magit-git-insert "diff" range)
+            (magit-run-git-with-input "apply" arg "-"))))
+    (magit-refresh)))
+
+(defun magit--run-git-stash (&rest args)
+  (magit--with-temp-process-buffer
+    (let ((exit (save-excursion
+                  (with-environment-variables (("LC_ALL" "en_US.utf8"))
+                    (magit-process-git t "stash" args))))
+          (buffer (current-buffer))
+          (failed (looking-at "\\`error: \
+Your local changes to the following files would be overwritten by merge")))
+      (with-current-buffer (magit-process-buffer t)
+        (magit-process-finish-section
+         (magit-process-insert-section default-directory magit-git-executable
+                                       (magit-process-git-arguments args)
+                                       exit buffer)
+         exit))
+      (pcase (list exit failed)
+        (`(0  ,_) t) ; no conflict
+        (`(1 nil) t) ; successfully installed conflict
+        (_ nil)))))  ; could not install conflict, or genuine error
 
 ;;;###autoload
 (defun magit-stash-drop (stash)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]