Mercurial > hg > xemacs-beta
comparison lisp/ediff/ediff-mult.el @ 12:bcdc7deadc19 r19-15b7
Import from CVS: tag r19-15b7
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:48:16 +0200 |
parents | ac2d302a0011 |
children | 9ee227acff29 |
comparison
equal
deleted
inserted
replaced
11:91ffe8bd52e4 | 12:bcdc7deadc19 |
---|---|
153 (defvar ediff-registry-setup-hook nil | 153 (defvar ediff-registry-setup-hook nil |
154 "*Hooks run just after the registry control panel is set up.") | 154 "*Hooks run just after the registry control panel is set up.") |
155 (defvar ediff-session-group-setup-hook nil | 155 (defvar ediff-session-group-setup-hook nil |
156 "*Hooks run just after a meta-buffer controlling a session group, such as | 156 "*Hooks run just after a meta-buffer controlling a session group, such as |
157 ediff-directories, is run.") | 157 ediff-directories, is run.") |
158 (defvar ediff-quit-session-group-hook nil | |
159 "*Hooks run just before exiting a session group.") | |
158 (defvar ediff-show-registry-hook nil | 160 (defvar ediff-show-registry-hook nil |
159 "*Hooks run just after the registry buffer is shown.") | 161 "*Hooks run just after the registry buffer is shown.") |
160 (defvar ediff-show-session-group-hook nil | 162 (defvar ediff-show-session-group-hook nil |
161 "*Hooks run just after a session group buffer is shown.") | 163 "*Hooks run just after a session group buffer is shown.") |
164 (defvar ediff-meta-buffer-keymap-setup-hook nil | |
165 "*Hooks run just after setting up the ediff-meta-buffer-map. | |
166 This keymap controls key bindings in the meta buffer and is a local variable. | |
167 This means that you can set different bindings for different kinds of meta | |
168 buffers.") | |
162 | 169 |
163 ;; buffer holding the multi-file patch. local to the meta buffer | 170 ;; buffer holding the multi-file patch. local to the meta buffer |
164 (ediff-defvar-local ediff-meta-patchbufer nil "") | 171 (ediff-defvar-local ediff-meta-patchbufer nil "") |
165 | 172 |
166 ;;; API for ediff-meta-list | 173 ;;; API for ediff-meta-list |
167 | 174 |
168 ;; group buffer/regexp | 175 ;; group buffer/regexp |
169 (defun ediff-get-group-buffer (meta-list) | 176 (defun ediff-get-group-buffer (meta-list) |
170 (nth 0 (car meta-list))) | 177 (nth 0 (car meta-list))) |
178 | |
171 (defun ediff-get-group-regexp (meta-list) | 179 (defun ediff-get-group-regexp (meta-list) |
172 (nth 1 (car meta-list))) | 180 (nth 1 (car meta-list))) |
173 ;; group objects | 181 ;; group objects |
174 (defun ediff-get-group-objA (meta-list) | 182 (defun ediff-get-group-objA (meta-list) |
175 (nth 2 (car meta-list))) | 183 (nth 2 (car meta-list))) |
176 (defun ediff-get-group-objB (meta-list) | 184 (defun ediff-get-group-objB (meta-list) |
177 (nth 3 (car meta-list))) | 185 (nth 3 (car meta-list))) |
178 (defun ediff-get-group-objC (meta-list) | 186 (defun ediff-get-group-objC (meta-list) |
179 (nth 4 (car meta-list))) | 187 (nth 4 (car meta-list))) |
188 (defun ediff-get-group-merge-autostore-dir (meta-list) | |
189 (nth 5 (car meta-list))) | |
190 | |
180 ;; session buffer | 191 ;; session buffer |
181 (defun ediff-get-session-buffer (elt) | 192 (defun ediff-get-session-buffer (elt) |
182 (nth 0 elt)) | 193 (nth 0 elt)) |
183 (defun ediff-get-session-status (elt) | 194 (defun ediff-get-session-status (elt) |
184 (nth 1 elt)) | 195 (nth 1 elt)) |
222 (define-key ediff-meta-buffer-map "\C-h" 'ediff-previous-meta-item)) | 233 (define-key ediff-meta-buffer-map "\C-h" 'ediff-previous-meta-item)) |
223 (if ediff-emacs-p | 234 (if ediff-emacs-p |
224 (define-key ediff-meta-buffer-map [mouse-2] ediff-meta-action-function) | 235 (define-key ediff-meta-buffer-map [mouse-2] ediff-meta-action-function) |
225 (define-key ediff-meta-buffer-map [button2] ediff-meta-action-function)) | 236 (define-key ediff-meta-buffer-map [button2] ediff-meta-action-function)) |
226 | 237 |
227 (use-local-map ediff-meta-buffer-map)) | 238 (use-local-map ediff-meta-buffer-map) |
239 ;; modify ediff-meta-buffer-map here | |
240 (run-hooks 'ediff-meta-buffer-keymap-setup-hook)) | |
228 | 241 |
229 (defun ediff-meta-mode () | 242 (defun ediff-meta-mode () |
230 "This mode controls all operations on Ediff session groups. | 243 "This mode controls all operations on Ediff session groups. |
231 It is entered through one of the following commands: | 244 It is entered through one of the following commands: |
232 `ediff-directories' | 245 `ediff-directories' |
311 (skip-chars-backward "a-zA-Z*")) | 324 (skip-chars-backward "a-zA-Z*")) |
312 (if (> (skip-chars-forward "-+?H* \t0-9") 0) | 325 (if (> (skip-chars-forward "-+?H* \t0-9") 0) |
313 (backward-char 1))) | 326 (backward-char 1))) |
314 )) | 327 )) |
315 | 328 |
316 | 329 (defsubst ediff-add-slash-if-directory (dir file) |
317 | 330 (if (file-directory-p (concat dir file)) |
318 ;; DIR1, DIR2, DIR3 are directories. | 331 (file-name-as-directory file) |
319 ;; REGEXP is a regexp used to filter | 332 file)) |
320 ;; files in the directories. | 333 |
334 | |
335 ;; DIR1, DIR2, DIR3 are directories. DIR3 can be nil. | |
336 ;; OUTPUT-DIR is a directory for auto-storing the results of merge jobs. | |
337 ;; Can be nil. | |
338 ;; REGEXP is a regexp used to filter out files in the directories. | |
321 ;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not | 339 ;; If a file is a directory in dir1 but not dir2 (or vice versa), it is not |
322 ;; included in the intersection. However, a regular file that is a dir in dir3 | 340 ;; included in the intersection. However, a regular file that is a dir in dir3 |
323 ;; is included, since dir3 files are supposed to be ancestors for merging. | 341 ;; is included, since dir3 files are supposed to be ancestors for merging. |
324 ;; Returns a list of the form: | 342 ;; Returns a list of the form: |
325 ;; ((dir1 dir2 dir3) (f1 f2 f3) (f1 f2 f3) ...) | 343 ;; ((dir1 dir2 dir3) (f1 f2 f3) (f1 f2 f3) ...) |
326 ;; dir3, f3 can be nil if intersecting only 2 directories. | 344 ;; dir3, f3 can be nil if intersecting only 2 directories. |
327 ;; If COMPARISON-FUNC is given, use it. Otherwise, use string= | 345 ;; If COMPARISON-FUNC is given, use it. Otherwise, use string= |
328 ;; DIFF-VAR is contains the name of the variable in which to return the | 346 ;; DIFF-VAR contains the name of the variable in which to return the |
329 ;; difference list. The diff list is of the form: | 347 ;; difference list (which represents the differences among the contents of |
348 ;; directories). The diff list is of the form: | |
330 ;; ((dir1 dir2 dir3) (file . num) (file . num)...) | 349 ;; ((dir1 dir2 dir3) (file . num) (file . num)...) |
331 ;; where num encodes the set of dirs where the file is found: | 350 ;; where num encodes the set of dirs where the file is found: |
332 ;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc. | 351 ;; 2 - only dir1; 3 - only dir2; 5 - only dir3; 6 - dir1&2; 10 - dir1&3; etc. |
333 (defun ediff-intersect-directories (jobname | 352 (defun ediff-intersect-directories (jobname |
334 diff-var regexp dir1 dir2 | 353 diff-var regexp dir1 dir2 |
335 &optional dir3 comparison-func) | 354 &optional |
355 dir3 merge-autostore-dir comparison-func) | |
336 (setq comparison-func (or comparison-func 'string=)) | 356 (setq comparison-func (or comparison-func 'string=)) |
337 (let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 difflist) | 357 (let (lis1 lis2 lis3 common auxdir1 auxdir2 auxdir3 difflist) |
338 | 358 |
339 (setq auxdir1 (file-name-as-directory dir1) | 359 (setq auxdir1 (file-name-as-directory dir1) |
340 lis1 (directory-files auxdir1 nil regexp) | 360 lis1 (directory-files auxdir1 nil regexp) |
361 lis1 (delete "." lis1) | |
362 lis1 (delete ".." lis1) | |
363 lis1 (mapcar | |
364 (function | |
365 (lambda (elt) | |
366 (ediff-add-slash-if-directory auxdir1 elt))) | |
367 lis1) | |
341 auxdir2 (file-name-as-directory dir2) | 368 auxdir2 (file-name-as-directory dir2) |
342 lis2 (directory-files auxdir2 nil regexp)) | 369 lis2 (mapcar |
370 (function | |
371 (lambda (elt) | |
372 (ediff-add-slash-if-directory auxdir2 elt))) | |
373 (directory-files auxdir2 nil regexp))) | |
343 | 374 |
344 (if (stringp dir3) | 375 (if (stringp dir3) |
345 (setq auxdir3 (file-name-as-directory dir3) | 376 (setq auxdir3 (file-name-as-directory dir3) |
346 lis3 (directory-files auxdir3 nil regexp))) | 377 lis3 (mapcar |
347 | 378 (function |
348 (setq lis1 (delete "." lis1) | 379 (lambda (elt) |
349 lis1 (delete ".." lis1)) | 380 (ediff-add-slash-if-directory auxdir3 elt))) |
350 | 381 (directory-files auxdir3 nil regexp)))) |
382 | |
383 (if (stringp merge-autostore-dir) | |
384 (setq merge-autostore-dir | |
385 (file-name-as-directory merge-autostore-dir))) | |
351 (setq common (ediff-intersection lis1 lis2 comparison-func)) | 386 (setq common (ediff-intersection lis1 lis2 comparison-func)) |
352 ;; get rid of files that are directories in dir1 but not dir2 | 387 |
353 (mapcar (function (lambda (elt) | 388 ;; In merge with ancestor jobs, we don't intersect with lis3. |
354 (if (Xor (file-directory-p (concat auxdir1 elt)) | 389 ;; If there is no ancestor, we'll offer to merge without the ancestor. |
355 (file-directory-p (concat auxdir2 elt))) | 390 ;; So, we intersect with lis3 only when we are doing 3-way file comparison |
356 (setq common (delq elt common))))) | 391 (if (and lis3 (ediff-comparison-metajob3 jobname)) |
357 common) | 392 (setq common (ediff-intersection common lis3 comparison-func))) |
358 ;; intersect with the third dir | |
359 (if lis3 (setq common (ediff-intersection common lis3 comparison-func))) | |
360 (if (ediff-comparison-metajob3 jobname) | |
361 (mapcar (function (lambda (elt) | |
362 (if (Xor (file-directory-p (concat auxdir1 elt)) | |
363 (file-directory-p (concat auxdir3 elt))) | |
364 (setq common (delq elt common))))) | |
365 common)) | |
366 | 393 |
367 ;; copying is needed because sort sorts via side effects | 394 ;; copying is needed because sort sorts via side effects |
368 (setq common (sort (ediff-copy-list common) 'string-lessp)) | 395 (setq common (sort (ediff-copy-list common) 'string-lessp)) |
369 | 396 |
370 ;; compute difference list | 397 ;; compute difference list |
391 (setcdr elt (* (cdr elt) 5))) | 418 (setcdr elt (* (cdr elt) 5))) |
392 )) | 419 )) |
393 difflist) | 420 difflist) |
394 (setq difflist (cons (list regexp auxdir1 auxdir2 auxdir3) difflist)) | 421 (setq difflist (cons (list regexp auxdir1 auxdir2 auxdir3) difflist)) |
395 | 422 |
423 ;; return the difference list back to the calling function | |
396 (set diff-var difflist) | 424 (set diff-var difflist) |
397 | 425 |
398 ;; return result | 426 ;; return result |
399 (cons (list regexp auxdir1 auxdir2 auxdir3) | 427 (cons (list regexp auxdir1 auxdir2 auxdir3 merge-autostore-dir) |
400 (mapcar (function (lambda (elt) | 428 (mapcar |
401 (list (concat auxdir1 elt) | 429 (function |
402 (concat auxdir2 elt) | 430 (lambda (elt) |
403 (if lis3 | 431 (list (concat auxdir1 elt) |
404 (concat auxdir3 elt))))) | 432 (concat auxdir2 elt) |
405 common)) | 433 (if lis3 |
434 (progn | |
435 ;; The following is done because: | |
436 ;; In merging with ancestor, we don't intersect | |
437 ;; with lis3. So, it is possible that elt is a | |
438 ;; file in auxdir1/2 but a directory in auxdir3 | |
439 ;; Or elt may not exist in auxdir3 at all. | |
440 ;; In the first case, we add a slash at the end. | |
441 ;; In the second case, we insert nil. | |
442 (setq elt (ediff-add-slash-if-directory auxdir3 elt)) | |
443 (if (file-exists-p (concat auxdir3 elt)) | |
444 (concat auxdir3 elt))))))) | |
445 common)) | |
406 )) | 446 )) |
407 | 447 |
408 ;; find directory files that are under revision. | 448 ;; find directory files that are under revision. |
409 ;; display subdirectories, too, since we may visit them recursively. | 449 ;; Include subdirectories, since we may visit them recursively. |
410 (defun ediff-get-directory-files-under-revision (jobname regexp dir1) | 450 ;; DIR1 is the directory to inspect. |
451 ;; OUTPUT-DIR is the directory where to auto-store the results of merges. Can | |
452 ;; be nil. | |
453 (defun ediff-get-directory-files-under-revision (jobname | |
454 regexp dir1 | |
455 &optional merge-autostore-dir) | |
411 (let (lis1 elt common auxdir1) | 456 (let (lis1 elt common auxdir1) |
412 (setq auxdir1 (file-name-as-directory dir1) | 457 (setq auxdir1 (file-name-as-directory dir1) |
413 lis1 (directory-files auxdir1 nil regexp)) | 458 lis1 (directory-files auxdir1 nil regexp)) |
459 | |
460 (if (stringp merge-autostore-dir) | |
461 (setq merge-autostore-dir | |
462 (file-name-as-directory merge-autostore-dir))) | |
414 | 463 |
415 (while lis1 | 464 (while lis1 |
416 (setq elt (car lis1) | 465 (setq elt (car lis1) |
417 lis1 (cdr lis1)) | 466 lis1 (cdr lis1)) |
418 ;; take files under revision control | 467 ;; take files under revision control |
424 (setq common (cons elt common))) | 473 (setq common (cons elt common))) |
425 ) ; cond | 474 ) ; cond |
426 ) ; while | 475 ) ; while |
427 | 476 |
428 (setq common (delete "." common) | 477 (setq common (delete "." common) |
429 common (delete ".." common)) | 478 common (delete ".." common) |
479 common (delete "RCS" common)) | |
430 | 480 |
431 ;; copying is needed because sort sorts via side effects | 481 ;; copying is needed because sort sorts via side effects |
432 (setq common (sort (ediff-copy-list common) 'string-lessp)) | 482 (setq common (sort (ediff-copy-list common) 'string-lessp)) |
433 | 483 |
434 ;; return result | 484 ;; return result |
435 (cons (list regexp auxdir1 nil nil) | 485 (cons (list regexp auxdir1 nil nil merge-autostore-dir) |
436 (mapcar (function (lambda (elt) | 486 (mapcar (function (lambda (elt) |
437 (list (concat auxdir1 elt) | 487 (list (concat auxdir1 elt) |
438 nil nil))) | 488 nil nil))) |
439 common)) | 489 common)) |
440 )) | 490 )) |
497 ediff-meta-list meta-list) | 547 ediff-meta-list meta-list) |
498 ;; this func is used only from registry buffer, not from other | 548 ;; this func is used only from registry buffer, not from other |
499 ;; meta-buffs. | 549 ;; meta-buffs. |
500 (define-key | 550 (define-key |
501 ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry)) | 551 ediff-meta-buffer-map "M" 'ediff-show-meta-buff-from-registry)) |
502 ;; initialize the meta list -- don't do this for registry we prepend | 552 ;; Initialize the meta list -- don't do this for registry. |
503 ;; '(nil nil) to all elts of meta-list, except the first. The | 553 ;; |
504 ;; first nil will later be replaced by the session buffer. The second | 554 ;; We prepend '(nil nil) to all elts of meta-list, except the first. |
505 ;; is reserved for session status. | 555 ;; The first nil will later be replaced by the session buffer. The |
556 ;; second is reserved for session status. | |
557 ;; | |
506 ;; (car ediff-meta-list) gets cons'ed with the session group buffer. | 558 ;; (car ediff-meta-list) gets cons'ed with the session group buffer. |
507 ;; Also, session objA/B/C are turned into lists (obj eq-indicator) | 559 ;; Also, session objects A/B/C are turned into lists of the form |
560 ;; (obj eq-indicator). Eq-indicator is either nil or =. Initialized to | |
561 ;; nil. If later it is discovered that this file is = to some other | |
562 ;; file in the same session, eq-indicator is changed to `='. | |
508 ;; For now, the eq-indicator is used only for 2 and 3-file jobs. | 563 ;; For now, the eq-indicator is used only for 2 and 3-file jobs. |
509 (setq ediff-meta-list | 564 (setq ediff-meta-list |
510 (cons (cons meta-buffer (car meta-list)) | 565 (cons (cons meta-buffer (car meta-list)) |
511 (mapcar (function | 566 (mapcar |
512 (lambda (elt) | 567 (function |
513 (cons nil | 568 (lambda (elt) |
514 (cons nil | 569 (cons nil |
515 ;; convert each obj to (obj nil), | 570 (cons nil |
516 ;; where nil may later be replaced | 571 ;; convert each obj to (obj nil), |
517 ;; by =, if this file equals some | 572 ;; where nil is the initial value |
518 ;; other file in the same session | 573 ;; for eq-indicator -- see above |
519 (mapcar (function | 574 (mapcar |
520 (lambda (obj) | 575 (function (lambda (obj) (list obj nil))) |
521 (list obj nil))) | 576 elt))))) |
522 elt))))) | 577 (cdr meta-list))))) |
523 (cdr meta-list))))) | |
524 | 578 |
525 (or (eq meta-buffer ediff-registry-buffer) | 579 (or (eq meta-buffer ediff-registry-buffer) |
526 (setq ediff-session-registry | 580 (setq ediff-session-registry |
527 (cons meta-buffer ediff-session-registry))) | 581 (cons meta-buffer ediff-session-registry))) |
528 | 582 |
532 ;; set read-only/non-modified | 586 ;; set read-only/non-modified |
533 (setq buffer-read-only t) | 587 (setq buffer-read-only t) |
534 (set-buffer-modified-p nil) | 588 (set-buffer-modified-p nil) |
535 | 589 |
536 (run-hooks 'startup-hooks) | 590 (run-hooks 'startup-hooks) |
537 ;; arrange for showing directory contents differences | 591 |
538 ;; must be after run startup-hooks, since ediff-dir-difference-list is | 592 ;; Arrange to show directory contents differences |
593 ;; Must be after run startup-hooks, since ediff-dir-difference-list is | |
539 ;; set inside these hooks | 594 ;; set inside these hooks |
540 (if (eq action-func 'ediff-filegroup-action) | 595 (if (eq action-func 'ediff-filegroup-action) |
541 (progn | 596 (progn |
542 ;; put meta buffer in (car ediff-dir-difference-list) | 597 ;; put meta buffer in (car ediff-dir-difference-list) |
543 (setq ediff-dir-difference-list | 598 (setq ediff-dir-difference-list |
572 ;; extract directories | 627 ;; extract directories |
573 (let ((meta-buf (ediff-get-group-buffer meta-list)) | 628 (let ((meta-buf (ediff-get-group-buffer meta-list)) |
574 (empty t) | 629 (empty t) |
575 (sessionNum 0) | 630 (sessionNum 0) |
576 regexp elt session-buf f1 f2 f3 pt | 631 regexp elt session-buf f1 f2 f3 pt |
632 merge-autostore-dir | |
577 point tmp-list buffer-read-only) | 633 point tmp-list buffer-read-only) |
578 (ediff-eval-in-buffer meta-buf | 634 (ediff-eval-in-buffer meta-buf |
579 (setq point (point)) | 635 (setq point (point)) |
580 (erase-buffer) | 636 (erase-buffer) |
581 (insert (format ediff-meta-buffer-message | 637 (insert (format ediff-meta-buffer-message |
582 (ediff-abbrev-jobname ediff-metajob-name))) | 638 (ediff-abbrev-jobname ediff-metajob-name))) |
583 | 639 |
584 (setq regexp (ediff-get-group-regexp meta-list)) | 640 (setq regexp (ediff-get-group-regexp meta-list) |
641 merge-autostore-dir (ediff-get-group-merge-autostore-dir meta-list)) | |
585 | 642 |
586 (cond ((ediff-collect-diffs-metajob) | 643 (cond ((ediff-collect-diffs-metajob) |
587 (insert | 644 (insert |
588 " `P':\tcollect custom diffs of all marked sessions\n")) | 645 " `P':\tcollect custom diffs of all marked sessions\n")) |
589 ((ediff-patch-metajob) | 646 ((ediff-patch-metajob) |
596 " `D':\tshow differences among directories\n" | 653 " `D':\tshow differences among directories\n" |
597 " `=':\tmark identical files in each session\n\n")) | 654 " `=':\tmark identical files in each session\n\n")) |
598 | 655 |
599 (if (and (stringp regexp) (> (length regexp) 0)) | 656 (if (and (stringp regexp) (> (length regexp) 0)) |
600 (insert (format "Filter-through regular expression: %s\n" regexp))) | 657 (insert (format "Filter-through regular expression: %s\n" regexp))) |
601 | 658 (if (and ediff-autostore-merges (ediff-merge-metajob) |
659 (stringp merge-autostore-dir)) | |
660 (insert (format | |
661 "\nMerges are automatically stored in directory: %s\n" | |
662 merge-autostore-dir))) | |
602 (insert "\n | 663 (insert "\n |
603 Size Last modified Name | 664 Size Last modified Name |
604 ----------------------------------------------------------------------- | 665 ----------------------------------------------------------------------- |
605 | 666 |
606 ") | 667 ") |
619 " ****** ****** This session group has no members\n")) | 680 " ****** ****** This session group has no members\n")) |
620 | 681 |
621 ;; now organize file names like this: | 682 ;; now organize file names like this: |
622 ;; use-mark sizeA dateA sizeB dateB filename | 683 ;; use-mark sizeA dateA sizeB dateB filename |
623 ;; make sure directories are displayed with a trailing slash. | 684 ;; make sure directories are displayed with a trailing slash. |
624 ;; If one is a directory and another isn't, indicate this with a `?' | |
625 (while meta-list | 685 (while meta-list |
626 (setq elt (car meta-list) | 686 (setq elt (car meta-list) |
627 meta-list (cdr meta-list) | 687 meta-list (cdr meta-list) |
628 sessionNum (1+ sessionNum)) | 688 sessionNum (1+ sessionNum)) |
629 (if (eq (ediff-get-session-status elt) ?I) | 689 (if (eq (ediff-get-session-status elt) ?I) |
650 meta-buf))) | 710 meta-buf))) |
651 | 711 |
652 ;; Check if this is a problematic session. | 712 ;; Check if this is a problematic session. |
653 ;; Return nil if not. Otherwise, return symbol representing the problem | 713 ;; Return nil if not. Otherwise, return symbol representing the problem |
654 ;; At present, problematic sessions occur only in -with-ancestor comparisons | 714 ;; At present, problematic sessions occur only in -with-ancestor comparisons |
655 ;; when the ancestor is a directory rather than a file. | 715 ;; when the ancestor is a directory rather than a file, or when there is no |
716 ;; suitable ancestor file in the ancestor directory | |
656 (defun ediff-problematic-session-p (session) | 717 (defun ediff-problematic-session-p (session) |
657 (let ((f1 (ediff-get-session-objA-name session)) | 718 (let ((f1 (ediff-get-session-objA-name session)) |
658 (f2 (ediff-get-session-objB-name session)) | 719 (f2 (ediff-get-session-objB-name session)) |
659 (f3 (ediff-get-session-objC-name session))) | 720 (f3 (ediff-get-session-objC-name session))) |
660 (cond ((and (stringp f1) (not (file-directory-p f1)) | 721 (cond ((and (stringp f1) (not (file-directory-p f1)) |
661 (stringp f2) (not (file-directory-p f2)) | 722 (stringp f2) (not (file-directory-p f2)) |
662 (stringp f3) (file-directory-p f3) | 723 ;; either invalid file name or a directory |
724 (or (not (stringp f3)) (file-directory-p f3)) | |
663 (ediff-ancestor-metajob)) | 725 (ediff-ancestor-metajob)) |
664 ;; more may be added later | 726 ;; more may be added later |
665 'ancestor-is-dir) | 727 'ancestor-is-dir) |
666 (t nil)))) | 728 (t nil)))) |
667 | 729 |
668 (defun ediff-meta-insert-file-info (fileinfo) | 730 (defun ediff-meta-insert-file-info (fileinfo) |
669 (let ((file-size -1) | 731 (let ((fname (car fileinfo)) |
670 (fname (car fileinfo)) | |
671 (feq (ediff-get-file-eqstatus fileinfo)) | 732 (feq (ediff-get-file-eqstatus fileinfo)) |
672 (file-modtime "*file doesn't exist*")) | 733 file-modtime file-size) |
673 | 734 |
674 (if (and (stringp fname) (file-exists-p fname)) | 735 (cond ((not (stringp fname)) (setq file-size -2)) ; file doesn't exist |
675 (setq file-size (ediff-file-size fname) | 736 ((not (ediff-file-remote-p fname)) |
676 file-modtime (ediff-file-modtime fname))) | 737 (if (file-exists-p fname) |
738 ;; set real size and modtime | |
739 (setq file-size (ediff-file-size fname) | |
740 file-modtime (ediff-file-modtime fname)) | |
741 (setq file-size -2))) ; file doesn't exist | |
742 ( t (setq file-size -1))) ; remote file | |
677 (if (stringp fname) | 743 (if (stringp fname) |
678 (insert | 744 (insert |
679 (format | 745 (format |
680 "%s %s %-20s %s\n" | 746 "%s %s %-20s %s\n" |
681 (if feq "=" " ") ; equality indicator | 747 (if feq "=" " ") ; equality indicator |
682 (format "%10s" (if (< file-size 0) | 748 (format "%10s" (cond ((= file-size -1) "--") |
683 "remote" | 749 ((< file-size -1) "--") |
684 file-size)) | 750 (t file-size))) |
685 (if (< file-size 0) | 751 (cond ((= file-size -1) "*remote file*") |
686 "file" | 752 ((< file-size -1) "*file doesn't exist*") |
687 (ediff-format-date (decode-time file-modtime))) | 753 (t (ediff-format-date (decode-time file-modtime)))) |
688 ;; dir names in meta lists have no trailing `/' so insert it | 754 |
689 (cond ((file-directory-p fname) | 755 ;; dir names in meta lists have training slashes, so we just |
690 (file-name-as-directory (ediff-abbreviate-file-name fname))) | 756 ;; abbreviate the file name, if file exists |
691 (t (ediff-abbreviate-file-name fname))))) | 757 (if (and (not (stringp fname)) (< file-size -1)) |
692 ))) | 758 "-------" ; file doesn't exist |
759 (ediff-abbreviate-file-name fname))))))) | |
693 | 760 |
694 (defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr") | 761 (defconst ediff-months '((1 . "Jan") (2 . "Feb") (3 . "Mar") (4 . "Apr") |
695 (5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug") | 762 (5 . "May") (6 . "Jun") (7 . "Jul") (8 . "Aug") |
696 (9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec")) | 763 (9 . "Sep") (10 . "Oct") (11 . "Nov") (12 . "Dec")) |
697 "Months' associative array.") | 764 "Months' associative array.") |
765 | |
766 ;; returns 2char string | |
767 (defsubst ediff-fill-leading-zero (num) | |
768 (if (< num 10) | |
769 (format "0%d" num) | |
770 (number-to-string num))) | |
698 | 771 |
699 ;; TIME is like the output of decode-time | 772 ;; TIME is like the output of decode-time |
700 (defun ediff-format-date (time) | 773 (defun ediff-format-date (time) |
701 (format "%s %2d %4d %s:%s:%s" | 774 (format "%s %2d %4d %s:%s:%s" |
702 (cdr (assoc (nth 4 time) ediff-months)) ; month | 775 (cdr (assoc (nth 4 time) ediff-months)) ; month |
704 (nth 5 time) ; year | 777 (nth 5 time) ; year |
705 (ediff-fill-leading-zero (nth 2 time)) ; hour | 778 (ediff-fill-leading-zero (nth 2 time)) ; hour |
706 (ediff-fill-leading-zero (nth 1 time)) ; min | 779 (ediff-fill-leading-zero (nth 1 time)) ; min |
707 (ediff-fill-leading-zero (nth 0 time)) ; sec | 780 (ediff-fill-leading-zero (nth 0 time)) ; sec |
708 )) | 781 )) |
709 | |
710 ;; returns 2char string | |
711 (defsubst ediff-fill-leading-zero (num) | |
712 (if (< num 10) | |
713 (format "0%d" num) | |
714 (number-to-string num))) | |
715 | 782 |
716 (defun ediff-draw-dir-diffs (diff-list) | 783 (defun ediff-draw-dir-diffs (diff-list) |
717 (if (null diff-list) (error "Lost difference info on these directories")) | 784 (if (null diff-list) (error "Lost difference info on these directories")) |
718 (let* ((buf-name (ediff-unique-buffer-name | 785 (let* ((buf-name (ediff-unique-buffer-name |
719 "*Ediff File Group Differences" "*")) | 786 "*Ediff File Group Differences" "*")) |
948 (interactive "P") | 1015 (interactive "P") |
949 (let* ((pos (ediff-event-point last-command-event)) | 1016 (let* ((pos (ediff-event-point last-command-event)) |
950 (meta-buf (ediff-event-buffer last-command-event)) | 1017 (meta-buf (ediff-event-buffer last-command-event)) |
951 ;; ediff-get-meta-info gives error if meta-buf or pos are invalid | 1018 ;; ediff-get-meta-info gives error if meta-buf or pos are invalid |
952 (info (ediff-get-meta-info meta-buf pos)) | 1019 (info (ediff-get-meta-info meta-buf pos)) |
1020 merge-autostore-dir | |
953 (session-buf (ediff-get-session-buffer info))) | 1021 (session-buf (ediff-get-session-buffer info))) |
954 | 1022 |
955 (if (eq (ediff-get-session-status info) ?H) | 1023 (if (eq (ediff-get-session-status info) ?H) |
956 (setq unmark t)) | 1024 (setq unmark t)) |
957 (if unmark | 1025 (if unmark |
1147 (ediff-set-session-status info nil) | 1215 (ediff-set-session-status info nil) |
1148 (ediff-update-meta-buffer meta-buf)) | 1216 (ediff-update-meta-buffer meta-buf)) |
1149 (error "Aborted")))) | 1217 (error "Aborted")))) |
1150 | 1218 |
1151 (ediff-eval-in-buffer meta-buf | 1219 (ediff-eval-in-buffer meta-buf |
1220 (setq merge-autostore-dir | |
1221 (ediff-get-group-merge-autostore-dir ediff-meta-list)) | |
1152 (goto-char pos) ; if the user clicked on session--move point there | 1222 (goto-char pos) ; if the user clicked on session--move point there |
1153 ;; First handle sessions involving directories (which are themselves | 1223 ;; First handle sessions involving directories (which are themselves |
1154 ;; session groups) | 1224 ;; session groups) |
1155 ;; After that handle individual sessions | 1225 ;; After that handle individual sessions |
1156 (cond ((and (file-directory-p file1) | 1226 (cond ((and (file-directory-p file1) |
1201 (ediff-recenter 'no-rehighlight))) | 1271 (ediff-recenter 'no-rehighlight))) |
1202 | 1272 |
1203 ((ediff-problematic-session-p info) | 1273 ((ediff-problematic-session-p info) |
1204 (beep) | 1274 (beep) |
1205 (if (y-or-n-p | 1275 (if (y-or-n-p |
1206 "This session's ancestor is a directory, merge without the ancestor? ") | 1276 "This session has no ancestor. Merge without the ancestor? ") |
1207 (ediff-merge-files | 1277 (ediff-merge-files |
1208 file1 file2 | 1278 file1 file2 |
1209 ;; provide startup hooks | 1279 ;; provide startup hooks |
1210 (` (list (lambda () | 1280 (` (list (lambda () |
1211 (setq ediff-meta-buffer (, (current-buffer))) | 1281 (setq ediff-meta-buffer (, (current-buffer))) |
1212 ;; see below for the explanation of what this does | 1282 (setq ediff-merge-store-file |
1283 (, (concat | |
1284 merge-autostore-dir | |
1285 "mrg_" | |
1286 (file-name-nondirectory file1)))) | |
1287 ;; make ediff-startup pass | |
1288 ;; ediff-control-buffer back to the meta | |
1289 ;; level; see below | |
1213 (setcar | 1290 (setcar |
1214 (quote (, info)) ediff-control-buffer))))) | 1291 (quote (, info)) ediff-control-buffer))))) |
1215 (error "Aborted"))) | 1292 (error "Aborted"))) |
1216 ((ediff-one-filegroup-metajob) ; needs 1 file arg | 1293 ((ediff-one-filegroup-metajob) ; needs 1 file arg |
1217 (funcall ediff-session-action-function | 1294 (funcall ediff-session-action-function |
1218 file1 | 1295 file1 |
1219 ;; provide startup hooks | 1296 ;; provide startup hooks |
1220 (` (list (lambda () | 1297 (` (list (lambda () |
1221 (setq ediff-meta-buffer (, (current-buffer))) | 1298 (setq ediff-meta-buffer (, (current-buffer))) |
1222 ;; see below for explanation of what this does | 1299 (setq ediff-merge-store-file |
1300 (, (concat | |
1301 merge-autostore-dir | |
1302 "mrg_" | |
1303 (file-name-nondirectory file1)))) | |
1304 ;; make ediff-startup pass | |
1305 ;; ediff-control-buffer back to the meta | |
1306 ;; level; see below | |
1223 (setcar | 1307 (setcar |
1224 (quote (, info)) ediff-control-buffer)))))) | 1308 (quote (, info)) ediff-control-buffer)))))) |
1225 ((not (ediff-metajob3)) ; need 2 file args | 1309 ((not (ediff-metajob3)) ; need 2 file args |
1226 (funcall ediff-session-action-function | 1310 (funcall ediff-session-action-function |
1227 file1 file2 | 1311 file1 file2 |
1228 ;; provide startup hooks | 1312 ;; provide startup hooks |
1229 (` (list (lambda () | 1313 (` (list (lambda () |
1230 (setq ediff-meta-buffer (, (current-buffer))) | 1314 (setq ediff-meta-buffer (, (current-buffer))) |
1231 ;; this makes ediff-startup pass the value of | 1315 (setq ediff-merge-store-file |
1316 (, (concat | |
1317 merge-autostore-dir | |
1318 "mrg_" | |
1319 (file-name-nondirectory file1)))) | |
1320 ;; make ediff-startup pass | |
1232 ;; ediff-control-buffer back to the meta | 1321 ;; ediff-control-buffer back to the meta |
1233 ;; level, to the record in the meta list | 1322 ;; level; see below |
1234 ;; containing the information about the | |
1235 ;; session associated with that | |
1236 ;; ediff-control-buffer | |
1237 (setcar | 1323 (setcar |
1238 (quote (, info)) ediff-control-buffer)))))) | 1324 (quote (, info)) ediff-control-buffer)))))) |
1239 ((ediff-metajob3) ; need 3 file args | 1325 ((ediff-metajob3) ; need 3 file args |
1240 (funcall ediff-session-action-function | 1326 (funcall ediff-session-action-function |
1241 file1 file2 file3 | 1327 file1 file2 file3 |
1242 ;; arrange startup hooks | 1328 ;; arrange startup hooks |
1243 (` (list (lambda () | 1329 (` (list (lambda () |
1330 (setq ediff-merge-store-file | |
1331 (, (concat | |
1332 merge-autostore-dir | |
1333 "mrg_" | |
1334 (file-name-nondirectory file1)))) | |
1244 (setq ediff-meta-buffer (, (current-buffer))) | 1335 (setq ediff-meta-buffer (, (current-buffer))) |
1336 ;; this arranges that ediff-startup will pass | |
1337 ;; the value of ediff-control-buffer back to | |
1338 ;; the meta level, to the record in the meta | |
1339 ;; list containing the information about the | |
1340 ;; session associated with that | |
1341 ;; ediff-control-buffer | |
1245 (setcar | 1342 (setcar |
1246 (quote (, info)) ediff-control-buffer)))))) | 1343 (quote (, info)) ediff-control-buffer)))))) |
1247 ) ; cond | 1344 ) ; cond |
1248 ) ; eval in meta-buf | 1345 ) ; eval in meta-buf |
1249 )) | 1346 )) |
1402 "*Ediff Registry" | 1499 "*Ediff Registry" |
1403 'ediff-redraw-registry-buffer | 1500 'ediff-redraw-registry-buffer |
1404 'ediff-registry)) | 1501 'ediff-registry)) |
1405 )) | 1502 )) |
1406 | 1503 |
1407 ;; if meta-buf exists, it is redrawn along with parent. Otherwise, nothing | 1504 ;; If meta-buf exists, it is redrawn along with parent. |
1408 ;; happens | 1505 ;; Otherwise, nothing happens. |
1409 (defun ediff-cleanup-meta-buffer (meta-buffer) | 1506 (defun ediff-cleanup-meta-buffer (meta-buffer) |
1410 (if (ediff-buffer-live-p meta-buffer) | 1507 (if (ediff-buffer-live-p meta-buffer) |
1411 (ediff-eval-in-buffer meta-buffer | 1508 (ediff-eval-in-buffer meta-buffer |
1412 (ediff-update-meta-buffer meta-buffer) | 1509 (ediff-update-meta-buffer meta-buffer) |
1413 (if (ediff-buffer-live-p ediff-parent-meta-buffer) | 1510 (if (ediff-buffer-live-p ediff-parent-meta-buffer) |
1428 (setq cont nil)) | 1525 (setq cont nil)) |
1429 (setq lis (cdr lis))) | 1526 (setq lis (cdr lis))) |
1430 cont)))) | 1527 cont)))) |
1431 | 1528 |
1432 (defun ediff-quit-meta-buffer () | 1529 (defun ediff-quit-meta-buffer () |
1433 "If no unprocessed sessions in the group, delete the meta buffer. | 1530 "If the group has no active session, delete the meta buffer. |
1434 If no session is in progress, ask to confirm before deleting meta buffer. | 1531 If no session is in progress, ask to confirm before deleting meta buffer. |
1435 Otherwise, bury the meta buffer. | 1532 Otherwise, bury the meta buffer. |
1436 If this is a session registry buffer then just bury it." | 1533 If this is a session registry buffer then just bury it." |
1437 (interactive) | 1534 (interactive) |
1438 (let* ((buf (current-buffer)) | 1535 (let* ((buf (current-buffer)) |
1443 (if dont-show-registry | 1540 (if dont-show-registry |
1444 (bury-buffer) | 1541 (bury-buffer) |
1445 (ediff-cleanup-meta-buffer buf) | 1542 (ediff-cleanup-meta-buffer buf) |
1446 (cond ((and (ediff-safe-to-quit buf) | 1543 (cond ((and (ediff-safe-to-quit buf) |
1447 (y-or-n-p "Quit this session group? ")) | 1544 (y-or-n-p "Quit this session group? ")) |
1545 (run-hooks 'ediff-quit-session-group-hook) | |
1448 (message "") | 1546 (message "") |
1449 (ediff-dispose-of-meta-buffer buf)) | 1547 (ediff-dispose-of-meta-buffer buf)) |
1450 ((ediff-safe-to-quit buf) | 1548 ((ediff-safe-to-quit buf) |
1451 (bury-buffer)) | 1549 (bury-buffer)) |
1452 (t | 1550 (t |
1615 | 1713 |
1616 | 1714 |
1617 ;;; Local Variables: | 1715 ;;; Local Variables: |
1618 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) | 1716 ;;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun) |
1619 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) | 1717 ;;; eval: (put 'ediff-eval-in-buffer 'lisp-indent-hook 1) |
1718 ;;; eval: (put 'ediff-eval-in-buffer 'edebug-form-spec '(form body)) | |
1620 ;;; End: | 1719 ;;; End: |
1621 | 1720 |
1622 (provide 'ediff-mult) | 1721 (provide 'ediff-mult) |
1623 (require 'ediff-util) | 1722 (require 'ediff-util) |
1624 | 1723 |