From d9780da69a5c51093dab13d9503754254ed78ca7 Mon Sep 17 00:00:00 2001 From: Mauro Aranda Date: Mon, 17 Mar 2025 06:55:07 -0300 Subject: [PATCH] Make marking conflicted files as resolved upon saving opt-out This fixes Bug#3860. * lisp/vc/vc.el (vc-resolve-conflicts): New user option. * lisp/vc/vc-bzr.el (vc-bzr-resolve-conflicts): New user option. (vc-bzr-find-file-hook): Use it. * lisp/vc/vc-hg.el (vc-hg-resolve-conflicts): New user option. (vc-hg-find-file-hook): Use it. * lisp/vc/vc-svn.el (vc-svn-resolve-conflicts): New user option. (vc-svn-find-file-hook): Use it. * lisp/vc/vc-git.el (vc-git-resolve-conflicts): Support 'default' as an option. Adjust docstring and version. (vc-git-find-file-hook): Respect vc-resolve-conflicts. * etc/NEWS: Announce the new options. (cherry picked from commit acb96a5ca8ac3bef80ca2ff1496cacb3ab57c87a) --- lisp/vc/vc-bzr.el | 15 ++++++++++++++- lisp/vc/vc-git.el | 21 +++++++++++++++------ lisp/vc/vc-hg.el | 15 ++++++++++++++- lisp/vc/vc-svn.el | 15 ++++++++++++++- lisp/vc/vc.el | 15 +++++++++++++++ 5 files changed, 72 insertions(+), 9 deletions(-) diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el index 97f9b4adc47..513052b37b0 100644 --- a/lisp/vc/vc-bzr.el +++ b/lisp/vc/vc-bzr.el @@ -110,6 +110,16 @@ The option \"--no-classify\" should be present if your bzr supports it." (repeat :tag "Argument List" :value ("") string)) :version "24.1") +(defcustom vc-bzr-resolve-conflicts 'default + "Whether to mark conflicted file as resolved upon saving. +If this is t and there are no more conflict markers in the file, +VC will mark the conflicts in the saved file as resolved. +A value of `default' means to use the value of `vc-resolve-conflicts'." + :type '(choice (const :tag "Don't resolve" nil) + (const :tag "Resolve" t) + (const :tag "Use vc-resolve-conflicts" default)) + :version "31.1") + ;; since v0.9, bzr supports removing the progress indicators ;; by setting environment variable BZR_PROGRESS_BAR to "none". (defun vc-bzr-command (bzr-command buffer okstatus file-or-list &rest args) @@ -531,7 +541,10 @@ in the branch repository (or whose status not be determined)." ;; but the one in `bzr pull' isn't, so it would be good to provide an ;; elisp function to remerge from the .BASE/OTHER/THIS files. (smerge-start-session) - (add-hook 'after-save-hook #'vc-bzr-resolve-when-done nil t) + (when (or (eq vc-bzr-resolve-conflicts t) + (and (eq vc-bzr-resolve-conflicts 'default) + vc-resolve-conflicts)) + (add-hook 'after-save-hook #'vc-bzr-resolve-when-done nil t)) (vc-message-unresolved-conflicts buffer-file-name))) (defun vc-bzr-clone (remote directory rev) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index baf66d05d43..6672c25e4f8 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -166,17 +166,24 @@ uses a full scan)." (repeat :tag "Argument List" :value ("") string)) :version "30.1") -(defcustom vc-git-resolve-conflicts t - "When non-nil, mark conflicted file as resolved upon saving. +(defcustom vc-git-resolve-conflicts 'default + "Whether to mark conflicted file as resolved upon saving. That is performed after all conflict markers in it have been removed. + +If this is t and there are no more conflict markers in the file, +VC will mark the conflicts in the saved file as resolved. + If the value is `unstage-maybe', and no merge, rebase or similar operation is in progress, then after the last conflict is resolved, also -clear the staging area." +clear the staging area. + +A value of `default' means to use the value of `vc-resolve-conflicts'." :type '(choice (const :tag "Don't resolve" nil) (const :tag "Resolve" t) (const :tag "Resolve and maybe unstage all files" - unstage-maybe)) - :version "25.1") + unstage-maybe) + (const :tag "Use vc-resolve-conflicts" default)) + :version "31.1") (defcustom vc-git-program "git" "Name of the Git executable (excluding any arguments)." @@ -1445,7 +1452,9 @@ This prompts for a branch to merge from." (goto-char (point-min)) (re-search-forward "^<<<<<<< " nil 'noerror))) (smerge-start-session) - (when vc-git-resolve-conflicts + (unless (or (null vc-git-resolve-conflicts) + (and (eq vc-git-resolve-conflicts 'default) + (not vc-resolve-conflicts))) (add-hook 'after-save-hook #'vc-git-resolve-when-done nil 'local)) (vc-message-unresolved-conflicts buffer-file-name))) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index b4d7844013a..b7200da0914 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -183,6 +183,16 @@ If `ask', you will be prompted for a branch type." (const :tag "Ask" ask)) :version "28.1") +(defcustom vc-hg-resolve-conflicts 'default + "Whether to mark conflicted file as resolved upon saving. +If this is t and there are no more conflict markers in the file, +VC will mark the conflicts in the saved file as resolved. +A value of `default' means to use the value of `vc-resolve-conflicts'." + :type '(choice (const :tag "Don't resolve" nil) + (const :tag "Resolve" t) + (const :tag "Use vc-resolve-conflicts" default)) + :version "31.1") + ;; Clear up the cache to force vc-call to check again and discover ;; new functions when we reload this file. @@ -1263,7 +1273,10 @@ REV is the revision to check out into WORKFILE." ;; Hg may not recognize "conflict" as a state, but we can do better. (vc-file-setprop buffer-file-name 'vc-state 'conflict) (smerge-start-session) - (add-hook 'after-save-hook #'vc-hg-resolve-when-done nil t) + (when (or (eq vc-hg-resolve-conflicts t) + (and (eq vc-hg-resolve-conflicts 'default) + vc-resolve-conflicts)) + (add-hook 'after-save-hook #'vc-hg-resolve-when-done nil t)) (vc-message-unresolved-conflicts buffer-file-name))) (defun vc-hg-clone (remote directory rev) diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el index 422ef48f8c0..e81636552b5 100644 --- a/lisp/vc/vc-svn.el +++ b/lisp/vc/vc-svn.el @@ -106,6 +106,16 @@ switches." :version "24.1" ; no longer consult the obsolete vc-header-alist :type '(repeat string)) +(defcustom vc-svn-resolve-conflicts 'default + "Whether to mark conflicted file as resolved upon saving. +If this is t and there are no more conflict markers in the file, +VC will mark the conflicts in the saved file as resolved. +A value of `default' means to use the value of `vc-resolve-conflicts'." + :type '(choice (const :tag "Don't resolve" nil) + (const :tag "Resolve" t) + (const :tag "Use vc-resolve-conflicts" default)) + :version "31.1") + ;; We want to autoload it for use by the autoloaded version of ;; vc-svn-registered, but we want the value to be compiled at startup, not ;; at dump time. @@ -688,7 +698,10 @@ and that it passes `vc-svn-global-switches' to it before FLAGS." ;; There are conflict markers. (progn (smerge-start-session) - (add-hook 'after-save-hook #'vc-svn-resolve-when-done nil t)) + (when (or (eq vc-svn-resolve-conflicts t) + (and (eq vc-svn-resolve-conflicts 'default) + vc-resolve-conflicts)) + (add-hook 'after-save-hook #'vc-svn-resolve-when-done nil t))) ;; There are no conflict markers. This is problematic: maybe it means ;; the conflict has been resolved and we should immediately call "svn ;; resolved", or it means that the file's type does not allow Svn to diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index dba487aa0a7..883590b941e 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -999,6 +999,21 @@ the URL-REGEXP of the association." :value-type ,vc-cloneable-backends-custom-type) :version "31.1") +(defcustom vc-resolve-conflicts t + "Whether to mark conflicted file as resolved upon saving. + +If this is non-nil and there are no more conflict markers in the file, +VC will mark the conflicts in the saved file as resolved. This is +only meaningful for VCS that handle conflicts by inserting conflict +markers in a conflicted file. + +When saving a conflicted file, VC first tries to use the value +of `vc-BACKEND-resolve-conflicts', for handling backend-specific +settings. It defaults to this option if that option has the special +value `default'." + :type 'boolean + :version "31.1") + ;; File property caching -- 2.39.5