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