Merge changes from emacs-23 branch
[bpt/emacs.git] / lisp / vc / ediff-merg.el
CommitLineData
475f9031 1;;; ediff-merg.el --- merging utilities
b578f267 2
0d30b337 3;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
114f9c96 4;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
475f9031 5
50a07e18 6;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
bd78fa1d 7;; Package: ediff
475f9031
KH
8
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
475f9031 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
475f9031
KH
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
475f9031 23
3afbc435
PJ
24;;; Commentary:
25
b578f267 26;;; Code:
475f9031 27
ddc90f39 28
ddc90f39
MK
29;; compiler pacifier
30(defvar ediff-window-A)
31(defvar ediff-window-B)
32(defvar ediff-window-C)
33(defvar ediff-merge-window-share)
34(defvar ediff-window-config-saved)
35
36(eval-when-compile
8480ec72 37 (require 'ediff-util))
ddc90f39
MK
38;; end pacifier
39
475f9031
KH
40(require 'ediff-init)
41
1e70790f 42(defcustom ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge
9201cc28 43 "Hooks to run before quitting a merge job.
1e70790f
MK
44The most common use is to save and delete the merge buffer."
45 :type 'hook
46 :group 'ediff-merge)
47
bbe6126c 48
ddc90f39 49(defcustom ediff-default-variant 'combined
9201cc28 50 "The variant to be used as a default for buffer C in merging.
ddc90f39
MK
51Valid values are the symbols `default-A', `default-B', and `combined'."
52 :type '(radio (const default-A) (const default-B) (const combined))
53 :group 'ediff-merge)
475f9031 54
71296446 55(defcustom ediff-combination-pattern
086171bf 56 '("<<<<<<< variant A" A ">>>>>>> variant B" B "####### Ancestor" Ancestor "======= end")
9201cc28 57 "Pattern to be used for combining difference regions in buffers A and B.
71296446 58The value must be a list of the form
4601d7c4 59\(STRING1 bufspec1 STRING2 bufspec2 STRING3 bufspec3 STRING4)
086171bf
MK
60where bufspec is the symbol A, B, or Ancestor. For instance, if the value is
61'(STRING1 A STRING2 Ancestor STRING3 B STRING4) then the
62combined text will look like this:
475f9031
KH
63
64STRING1
65diff region from variant A
66STRING2
086171bf 67diff region from the ancestor
475f9031 68STRING3
086171bf
MK
69diff region from variant B
70STRING4
ddc90f39 71"
086171bf
MK
72 :type '(choice (list string symbol string symbol string)
73 (list string symbol string symbol string symbol string))
ddc90f39 74 :group 'ediff-merge)
475f9031 75
3af0304a 76(defcustom ediff-show-clashes-only nil
9201cc28 77 "If t, show only those diff regions where both buffers disagree with the ancestor.
475f9031 78This means that regions that have status prefer-A or prefer-B will be
4601d7c4 79skipped over. A value of nil means show all regions."
3af0304a
MK
80 :type 'boolean
81 :group 'ediff-merge
82 )
83(make-variable-buffer-local 'ediff-show-clashes-only)
84
85(defcustom ediff-skip-merge-regions-that-differ-from-default nil
9201cc28 86 "If t, show only the regions that have not been changed by the user.
3af0304a
MK
87A region is considered to have been changed if it is different from the current
88default (`default-A', `default-B', `combined') and it hasn't been marked as
89`prefer-A' or `prefer-B'.
71296446 90A region is considered to have been changed also when it is marked as
3af0304a
MK
91as `prefer-A', but is different from the corresponding difference region in
92Buffer A or if it is marked as `prefer-B' and is different from the region in
93Buffer B."
94 :type 'boolean
95 :group 'ediff-merge
96 )
97(make-variable-buffer-local 'ediff-skip-merge-regions-that-differ-from-default)
475f9031 98
e2de3a29 99;; check if there is no clash between the ancestor and one of the variants.
39bcfe5f 100;; if it is not a merge job then return true
68b962d4 101(defun ediff-merge-region-is-non-clash (n)
39bcfe5f
MK
102 (if (ediff-merge-job)
103 (string-match "prefer" (or (ediff-get-state-of-merge n) ""))
104 t))
e2de3a29 105
8e41a31c
MK
106;; If ediff-show-clashes-only, check if there is no clash between the ancestor
107;; and one of the variants.
68b962d4
MK
108(defun ediff-merge-region-is-non-clash-to-skip (n)
109 (and (ediff-merge-job)
110 ediff-show-clashes-only
e2de3a29 111 (ediff-merge-region-is-non-clash n)))
8e41a31c 112
3af0304a
MK
113;; If ediff-skip-changed-regions, check if the merge region differs from
114;; the current default. If a region is different from the default, it means
115;; that the user has made determination as to how to merge for this particular
71296446 116;; region.
68b962d4
MK
117(defun ediff-skip-merge-region-if-changed-from-default-p (n)
118 (and (ediff-merge-job)
119 ediff-skip-merge-regions-that-differ-from-default
3af0304a
MK
120 (ediff-merge-changed-from-default-p n 'prefers-too)))
121
122
086171bf
MK
123(defun ediff-get-combined-region (n)
124 (let ((pattern-list ediff-combination-pattern)
125 (combo-region "")
126 (err-msg
127 "ediff-combination-pattern: Invalid format. Please consult the documentation")
50a07e18 128 region-delim region-spec)
086171bf
MK
129
130 (if (< (length pattern-list) 5)
131 (error err-msg))
132
133 (while (> (length pattern-list) 2)
134 (setq region-delim (nth 0 pattern-list)
135 region-spec (nth 1 pattern-list))
136 (or (and (stringp region-delim) (memq region-spec '(A B Ancestor)))
137 (error err-msg))
138
50a07e18 139 (condition-case nil
086171bf
MK
140 (setq combo-region
141 (concat combo-region
142 region-delim "\n"
71296446 143 (ediff-get-region-contents
086171bf
MK
144 n region-spec ediff-control-buffer)))
145 (error ""))
146 (setq pattern-list (cdr (cdr pattern-list)))
147 )
148
149 (setq region-delim (nth 0 pattern-list))
150 (or (stringp region-delim)
151 (error err-msg))
152 (setq combo-region (concat combo-region region-delim "\n"))
153 ))
154
155;;(defsubst ediff-make-combined-diff (regA regB)
156;; (concat (nth 0 ediff-combination-pattern) "\n"
157;; regA
158;; (nth 1 ediff-combination-pattern) "\n"
159;; regB
160;; (nth 2 ediff-combination-pattern) "\n"))
009650b3 161
475f9031
KH
162(defsubst ediff-set-state-of-all-diffs-in-all-buffers (ctl-buf)
163 (let ((n 0))
164 (while (< n ediff-number-of-differences)
165 (ediff-set-state-of-diff-in-all-buffers n ctl-buf)
166 (setq n (1+ n)))))
71296446 167
475f9031
KH
168(defun ediff-set-state-of-diff-in-all-buffers (n ctl-buf)
169 (let ((regA (ediff-get-region-contents n 'A ctl-buf))
170 (regB (ediff-get-region-contents n 'B ctl-buf))
171 (regC (ediff-get-region-contents n 'C ctl-buf)))
13340e24
KH
172 (cond ((and (string= regA regB) (string= regA regC))
173 (ediff-set-state-of-diff n 'A "=diff(B)")
174 (ediff-set-state-of-diff n 'B "=diff(C)")
175 (ediff-set-state-of-diff n 'C "=diff(A)"))
176 ((string= regA regB)
475f9031
KH
177 (ediff-set-state-of-diff n 'A "=diff(B)")
178 (ediff-set-state-of-diff n 'B "=diff(A)")
179 (ediff-set-state-of-diff n 'C nil))
180 ((string= regA regC)
181 (ediff-set-state-of-diff n 'A "=diff(C)")
182 (ediff-set-state-of-diff n 'C "=diff(A)")
183 (ediff-set-state-of-diff n 'B nil))
184 ((string= regB regC)
185 (ediff-set-state-of-diff n 'C "=diff(B)")
186 (ediff-set-state-of-diff n 'B "=diff(C)")
187 (ediff-set-state-of-diff n 'A nil))
188 ((string= regC (ediff-get-combined-region n))
189 (ediff-set-state-of-diff n 'A nil)
190 (ediff-set-state-of-diff n 'B nil)
191 (ediff-set-state-of-diff n 'C "=diff(A+B)"))
192 (t (ediff-set-state-of-diff n 'A nil)
193 (ediff-set-state-of-diff n 'B nil)
194 (ediff-set-state-of-diff n 'C nil)))
195 ))
71296446 196
13340e24 197(defun ediff-set-merge-mode ()
13340e24
KH
198 (normal-mode t)
199 (remove-hook 'local-write-file-hooks 'ediff-set-merge-mode))
c439fb30 200
71296446 201
475f9031
KH
202;; Go over all diffs starting with DIFF-NUM and copy regions into buffer C
203;; according to the state of the difference.
204;; Since ediff-copy-diff refuses to copy identical diff regions, there is
205;; no need to optimize ediff-do-merge any further.
206;;
207;; If re-merging, change state of merge in all diffs starting with
208;; DIFF-NUM, except those where the state is prefer-* or where it is
13340e24
KH
209;; `default-*' or `combined' but the buf C region appears to be modified
210;; since last set by default.
475f9031
KH
211(defun ediff-do-merge (diff-num &optional remerging)
212 (if (< diff-num 0) (setq diff-num 0))
213 (let ((n diff-num)
bbe6126c 214 ;;(default-state-of-merge (format "%S" ediff-default-variant))
13340e24 215 do-not-copy state-of-merge)
475f9031 216 (while (< n ediff-number-of-differences)
bbe6126c 217 (setq do-not-copy nil) ; reset after each cycle
475f9031
KH
218 (if (= (mod n 10) 0)
219 (message "%s buffers A & B into C ... region %d of %d"
220 (if remerging "Re-merging" "Merging")
221 n
222 ediff-number-of-differences))
71296446 223
475f9031 224 (setq state-of-merge (ediff-get-state-of-merge n))
475f9031
KH
225
226 (if remerging
50a07e18
MK
227 ;;(let ((reg-A (ediff-get-region-contents n 'A ediff-control-buffer))
228 ;; (reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
229 ;; (reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
1e2b6acf 230 (progn
71296446 231
bbe6126c 232 ;; if region was edited since it was first set by default
3af0304a
MK
233 (if (or (ediff-merge-changed-from-default-p n)
234 ;; was preferred
13340e24 235 (string-match "prefer" state-of-merge))
3af0304a 236 ;; then ignore
475f9031 237 (setq do-not-copy t))
71296446 238
475f9031 239 ;; change state of merge for this diff, if necessary
13340e24
KH
240 (if (and (string-match "\\(default\\|combined\\)" state-of-merge)
241 (not do-not-copy))
475f9031
KH
242 (ediff-set-state-of-merge
243 n (format "%S" ediff-default-variant)))
244 ))
71296446 245
475f9031 246 ;; state-of-merge may have changed via ediff-set-state-of-merge, so
13340e24 247 ;; check it once again
475f9031 248 (setq state-of-merge (ediff-get-state-of-merge n))
71296446 249
475f9031
KH
250 (or do-not-copy
251 (if (string= state-of-merge "combined")
252 ;; use n+1 because ediff-combine-diffs works via user numbering
253 ;; of diffs, which is 1+ to what ediff uses internally
254 (ediff-combine-diffs (1+ n) 'batch)
71296446 255 (ediff-copy-diff
13340e24 256 n (if (string-match "-A" state-of-merge) 'A 'B) 'C 'batch)))
475f9031
KH
257 (setq n (1+ n)))
258 (message "Merging buffers A & B into C ... Done")
259 ))
71296446 260
475f9031
KH
261
262(defun ediff-re-merge ()
3af0304a 263 "Remerge unmodified diff regions using a new default. Start with the current region."
475f9031
KH
264 (interactive)
265 (let* ((default-variant-alist
266 (list '("default-A") '("default-B") '("combined")))
267 (actual-alist
268 (delete (list (symbol-name ediff-default-variant))
269 default-variant-alist)))
270 (setq ediff-default-variant
271 (intern
71296446 272 (completing-read
3af0304a 273 (format "Current merge default is `%S'. New default: "
475f9031
KH
274 ediff-default-variant)
275 actual-alist nil 'must-match)))
276 (ediff-do-merge ediff-current-difference 'remerge)
277 (ediff-recenter)
278 ))
71296446 279
475f9031
KH
280(defun ediff-shrink-window-C (arg)
281 "Shrink window C to just one line.
282With a prefix argument, returns window C to its normal size.
283Used only for merging jobs."
284 (interactive "P")
285 (if (not ediff-merge-job)
286 (error "ediff-shrink-window-C can be used only for merging jobs"))
287 (cond ((eq arg '-) (setq arg -1))
288 ((not (numberp arg)) (setq arg nil)))
289 (cond ((null arg)
290 (let ((ediff-merge-window-share
291 (if (< (window-height ediff-window-C) 3)
292 ediff-merge-window-share 0)))
293 (setq ediff-window-config-saved "") ; force redisplay
294 (ediff-recenter 'no-rehighlight)))
295 ((and (< arg 0) (> (window-height ediff-window-C) 2))
296 (setq ediff-merge-window-share (* ediff-merge-window-share 0.9))
297 (setq ediff-window-config-saved "") ; force redisplay
298 (ediff-recenter 'no-rehighlight))
299 ((and (> arg 0) (> (window-height ediff-window-A) 2))
300 (setq ediff-merge-window-share (* ediff-merge-window-share 1.1))
301 (setq ediff-window-config-saved "") ; force redisplay
302 (ediff-recenter 'no-rehighlight))))
303
304
3af0304a 305;; N here is the user's region number. It is 1+ what Ediff uses internally.
475f9031
KH
306(defun ediff-combine-diffs (n &optional batch-invocation)
307 "Combine Nth diff regions of buffers A and B and place the combination in C.
3af0304a 308N is a prefix argument. If nil, combine the current difference regions.
4ae69eac
MK
309Combining is done according to the specifications in variable
310`ediff-combination-pattern'."
475f9031 311 (interactive "P")
4ae69eac 312 (setq n (if (numberp n) (1- n) ediff-current-difference))
71296446 313
50a07e18 314 (let (reg-combined)
086171bf
MK
315 ;;(setq regA (ediff-get-region-contents n 'A ediff-control-buffer)
316 ;; regB (ediff-get-region-contents n 'B ediff-control-buffer))
317 ;;(setq reg-combined (ediff-make-combined-diff regA regB))
318 (setq reg-combined (ediff-get-combined-region n))
71296446 319
475f9031 320 (ediff-copy-diff n nil 'C batch-invocation reg-combined))
4ae69eac 321 (or batch-invocation (ediff-jump-to-difference (1+ n))))
71296446 322
475f9031
KH
323
324;; Checks if the region in buff C looks like a combination of the regions
3af0304a 325;; in buffers A and B. Return a list (reg-a-beg reg-a-end reg-b-beg reg-b-end)
086171bf
MK
326;; These refer to where the delimiters for region A, B, Ancestor start and end
327;; in buffer C
475f9031
KH
328(defun ediff-looks-like-combined-merge (region-num)
329 (if ediff-merge-job
330 (let ((combined (string-match (regexp-quote "(A+B)")
331 (or (ediff-get-state-of-diff region-num 'C)
332 "")))
086171bf
MK
333 (mrgreg-beg (ediff-get-diff-posn 'C 'beg region-num))
334 (mrgreg-end (ediff-get-diff-posn 'C 'end region-num))
335 (pattern-list ediff-combination-pattern)
336 delim reg-beg reg-end delim-regs-list)
71296446 337
475f9031 338 (if combined
e756eb9f 339 (ediff-with-current-buffer ediff-buffer-C
086171bf
MK
340 (while pattern-list
341 (goto-char mrgreg-beg)
342 (setq delim (nth 0 pattern-list))
343 (search-forward delim mrgreg-end 'noerror)
344 (setq reg-beg (match-beginning 0))
345 (setq reg-end (match-end 0))
346 (if (and reg-beg reg-end)
347 (setq delim-regs-list
348 ;; in reverse
349 (cons reg-end (cons reg-beg delim-regs-list))))
350 (if (> (length pattern-list) 1)
351 (setq pattern-list (cdr (cdr pattern-list)))
352 (setq pattern-list nil))
353 )))
354
355 (reverse delim-regs-list)
475f9031 356 )))
3b90e5b8 357
937382fa 358(defvar state-of-merge) ; dynamic var
3af0304a
MK
359
360;; Check if the non-preferred merge has been modified since originally set.
361;; This affects only the regions that are marked as default-A/B or combined.
362;; If PREFERS-TOO is non-nil, then look at the regions marked as prefers-A/B as
363;; well.
364(defun ediff-merge-changed-from-default-p (diff-num &optional prefers-too)
365 (let ((reg-A (ediff-get-region-contents diff-num 'A ediff-control-buffer))
366 (reg-B (ediff-get-region-contents diff-num 'B ediff-control-buffer))
367 (reg-C (ediff-get-region-contents diff-num 'C ediff-control-buffer)))
368
369 (setq state-of-merge (ediff-get-state-of-merge diff-num))
71296446 370
3af0304a
MK
371 ;; if region was edited since it was first set by default
372 (or (and (string= state-of-merge "default-A")
373 (not (string= reg-A reg-C)))
374 (and (string= state-of-merge "default-B")
375 (not (string= reg-B reg-C)))
376 (and (string= state-of-merge "combined")
086171bf
MK
377 ;;(not (string= (ediff-make-combined-diff reg-A reg-B) reg-C)))
378 (not (string= (ediff-get-combined-region diff-num) reg-C)))
3af0304a
MK
379 (and prefers-too
380 (string= state-of-merge "prefer-A")
381 (not (string= reg-A reg-C)))
382 (and prefers-too
383 (string= state-of-merge "prefer-B")
384 (not (string= reg-B reg-C)))
385 )))
71296446 386
475f9031 387
b6178721
MK
388(provide 'ediff-merg)
389
390
fa043571
SM
391;; Local Variables:
392;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
393;; eval: (put 'ediff-with-current-buffer 'lisp-indent-hook 1)
394;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
395;; End:
92c51e07 396
cbee283d 397;; arch-tag: 9b798cf9-02ba-487f-a62e-b63aa823dbfb
3afbc435 398;;; ediff-merg.el ends here