@matheusbsbs / matheus-bagliano / commits / 433ee03f97
Fork 0

git.el: Never clear the status buffer, only update the files.

This makes it unnecessary to save/restore the file marks. Signed-off-by: Alexandre Julliard <julliard@winehq.org>

Alexandre Julliard committed Aug 2, 2008 at 20:35 UTC 433ee03f9748a8a5d0e0495bbf4b054ae922103b
1 file changed +85 -84
contrib/emacs/git.el
+85 -84
@@ -356,7 +356,7 @@ the process output as a string, or nil if the git command failed."
356 (save-buffer))
357 (when created
358 (git-call-process nil "update-index" "--add" "--" (file-relative-name ignore-name)))
359 - (git-update-status-files (list (file-relative-name ignore-name)) 'unknown)))
359 + (git-update-status-files (list (file-relative-name ignore-name)))))
360
361 ; propertize definition for XEmacs, stolen from erc-compat
362 (eval-when-compile
@@ -497,14 +497,11 @@ the process output as a string, or nil if the git command failed."
497 old-perm new-perm ;; permission flags
498 rename-state ;; rename or copy state
499 orig-name ;; original name for renames or copies
500 + needs-update ;; whether file needs to be updated
501 needs-refresh) ;; whether file needs to be refreshed
502
503 (defvar git-status nil)
504
504 -(defun git-clear-status (status)
505 - "Remove everything from the status list."
506 - (ewoc-filter status (lambda (info) nil)))
507 -
505 (defun git-set-fileinfo-state (info state)
506 "Set the state of a file info."
507 (unless (eq (git-fileinfo->state info) state)
@@ -512,6 +509,7 @@ the process output as a string, or nil if the git command failed."
509 (git-fileinfo->new-perm info) (git-fileinfo->old-perm info)
510 (git-fileinfo->rename-state info) nil
511 (git-fileinfo->orig-name info) nil
512 + (git-fileinfo->needs-update info) nil
513 (git-fileinfo->needs-refresh info) t)))
514
515 (defun git-status-filenames-map (status func files &rest args)
@@ -521,10 +519,11 @@ the process output as a string, or nil if the git command failed."
519 (let ((file (pop files))
520 (node (ewoc-nth status 0)))
521 (while (and file node)
524 - (let ((info (ewoc-data node)))
525 - (if (string-lessp (git-fileinfo->name info) file)
522 + (let* ((info (ewoc-data node))
523 + (name (git-fileinfo->name info)))
524 + (if (string-lessp name file)
525 (setq node (ewoc-next status node))
527 - (if (string-equal (git-fileinfo->name info) file)
526 + (if (string-equal name file)
527 (apply func info args))
528 (setq file (pop files))))))))
529
@@ -622,37 +621,50 @@ the process output as a string, or nil if the git command failed."
621 (git-file-type-as-string old-perm new-perm)
622 (git-rename-as-string info)))))
623
625 -(defun git-insert-info-list (status infolist)
626 - "Insert a list of file infos in the status buffer, replacing existing ones if any."
627 - (setq infolist (sort infolist
628 - (lambda (info1 info2)
629 - (string-lessp (git-fileinfo->name info1)
630 - (git-fileinfo->name info2)))))
631 - (let ((info (pop infolist))
632 - (node (ewoc-nth status 0)))
624 +(defun git-update-node-fileinfo (node info)
625 + "Update the fileinfo of the specified node. The names are assumed to match already."
626 + (let ((data (ewoc-data node)))
627 + (setf
628 + ;; preserve the marked flag
629 + (git-fileinfo->marked info) (git-fileinfo->marked data)
630 + (git-fileinfo->needs-update data) nil)
631 + (when (not (equal info data))
632 + (setf (git-fileinfo->needs-refresh info) t
633 + (ewoc-data node) info))))
634 +
635 +(defun git-insert-info-list (status infolist files)
636 + "Insert a sorted list of file infos in the status buffer, replacing existing ones if any."
637 + (let* ((info (pop infolist))
638 + (node (ewoc-nth status 0))
639 + (name (and info (git-fileinfo->name info)))
640 + remaining)
641 (while info
634 - (cond ((not node)
635 - (setq node (ewoc-enter-last status info))
636 - (setq info (pop infolist)))
637 - ((string-lessp (git-fileinfo->name (ewoc-data node))
638 - (git-fileinfo->name info))
639 - (setq node (ewoc-next status node)))
640 - ((string-equal (git-fileinfo->name (ewoc-data node))
641 - (git-fileinfo->name info))
642 - ;; preserve the marked flag
643 - (setf (git-fileinfo->marked info) (git-fileinfo->marked (ewoc-data node)))
644 - (setf (git-fileinfo->needs-refresh info) t)
645 - (setf (ewoc-data node) info)
646 - (setq info (pop infolist)))
647 - (t
648 - (setq node (ewoc-enter-before status node info))
649 - (setq info (pop infolist)))))))
642 + (let ((nodename (and node (git-fileinfo->name (ewoc-data node)))))
643 + (while (and files (string-lessp (car files) name))
644 + (push (pop files) remaining))
645 + (when (and files (string-equal (car files) name))
646 + (setq files (cdr files)))
647 + (cond ((not nodename)
648 + (setq node (ewoc-enter-last status info))
649 + (setq info (pop infolist))
650 + (setq name (and info (git-fileinfo->name info))))
651 + ((string-lessp nodename name)
652 + (setq node (ewoc-next status node)))
653 + ((string-equal nodename name)
654 + ;; preserve the marked flag
655 + (git-update-node-fileinfo node info)
656 + (setq info (pop infolist))
657 + (setq name (and info (git-fileinfo->name info))))
658 + (t
659 + (setq node (ewoc-enter-before status node info))
660 + (setq info (pop infolist))
661 + (setq name (and info (git-fileinfo->name info)))))))
662 + (nconc (nreverse remaining) files)))
663
664 (defun git-run-diff-index (status files)
665 "Run git-diff-index on FILES and parse the results into STATUS.
666 Return the list of files that haven't been handled."
654 - (let ((remaining (copy-sequence files))
655 - infolist)
667 + (let (infolist)
668 (with-temp-buffer
669 (apply #'git-call-process t "diff-index" "-z" "-M" "HEAD" "--" files)
670 (goto-char (point-min))
@@ -669,11 +681,12 @@ Return the list of files that haven't been handled."
681 (push (git-create-fileinfo 'added new-name old-perm new-perm 'copy name) infolist)
682 (push (git-create-fileinfo 'deleted name 0 0 'rename new-name) infolist)
683 (push (git-create-fileinfo 'added new-name old-perm new-perm 'rename name) infolist))
672 - (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist))
673 - (setq remaining (delete name remaining))
674 - (when new-name (setq remaining (delete new-name remaining))))))
675 - (git-insert-info-list status infolist)
676 - remaining))
684 + (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist)))))
685 + (setq infolist (sort (nreverse infolist)
686 + (lambda (info1 info2)
687 + (string-lessp (git-fileinfo->name info1)
688 + (git-fileinfo->name info2)))))
689 + (git-insert-info-list status infolist files)))
690
691 (defun git-find-status-file (status file)
692 "Find a given file in the status ewoc and return its node."
@@ -693,16 +706,14 @@ Return the list of files that haven't been handled."
706 (let ((name (match-string 1)))
707 (push (git-create-fileinfo default-state name 0
708 (if (string-equal "/" (match-string 2)) (lsh ?\110 9) 0))
696 - infolist)
697 - (setq files (delete name files)))))
698 - (git-insert-info-list status infolist)
699 - files))
709 + infolist))))
710 + (setq infolist (nreverse infolist)) ;; assume it is sorted already
711 + (git-insert-info-list status infolist files)))
712
713 (defun git-run-ls-files-cached (status files default-state)
714 "Run git-ls-files -c on FILES and parse the results into STATUS.
715 Return the list of files that haven't been handled."
704 - (let ((remaining (copy-sequence files))
705 - infolist)
716 + (let (infolist)
717 (with-temp-buffer
718 (apply #'git-call-process t "ls-files" "-z" "-s" "-c" "--" files)
719 (goto-char (point-min))
@@ -710,10 +721,9 @@ Return the list of files that haven't been handled."
721 (let* ((new-perm (string-to-number (match-string 1) 8))
722 (old-perm (if (eq default-state 'added) 0 new-perm))
723 (name (match-string 2)))
713 - (push (git-create-fileinfo default-state name old-perm new-perm) infolist)
714 - (setq remaining (delete name remaining)))))
715 - (git-insert-info-list status infolist)
716 - remaining))
724 + (push (git-create-fileinfo default-state name old-perm new-perm) infolist))))
725 + (setq infolist (nreverse infolist)) ;; assume it is sorted already
726 + (git-insert-info-list status infolist files)))
727
728 (defun git-run-ls-unmerged (status files)
729 "Run git-ls-files -u on FILES and parse the results into STATUS."
@@ -742,11 +752,17 @@ Return the list of files that haven't been handled."
752 (concat "--exclude-per-directory=" git-per-dir-ignore-file)
753 (append options (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files)))))
754
745 -(defun git-update-status-files (files &optional default-state)
755 +(defun git-update-status-files (&optional files)
756 "Update the status of FILES from the index."
757 (unless git-status (error "Not in git-status buffer."))
748 - (when (or git-show-uptodate files)
749 - (git-run-ls-files-cached git-status files 'uptodate))
758 + ;; set the needs-update flag on existing files
759 + (if (setq files (sort files #'string-lessp))
760 + (git-status-filenames-map
761 + git-status (lambda (info) (setf (git-fileinfo->needs-update info) t)) files)
762 + (ewoc-map (lambda (info) (setf (git-fileinfo->needs-update info) t) nil) git-status)
763 + (git-call-process nil "update-index" "--refresh")
764 + (when git-show-uptodate
765 + (git-run-ls-files-cached git-status nil 'uptodate)))
766 (let* ((remaining-files
767 (if (git-empty-db-p) ; we need some special handling for an empty db
768 (git-run-ls-files-cached git-status files 'added)
@@ -756,7 +772,11 @@ Return the list of files that haven't been handled."
772 (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'unknown "-o")))
773 (when (or remaining-files (and git-show-ignored (not files)))
774 (setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'ignored "-o" "-i")))
759 - (git-set-filenames-state git-status remaining-files default-state)
775 + (unless files
776 + (setq remaining-files (git-get-filenames (ewoc-collect git-status #'git-fileinfo->needs-update))))
777 + (when remaining-files
778 + (setq remaining-files (git-run-ls-files-cached git-status remaining-files 'uptodate)))
779 + (git-set-filenames-state git-status remaining-files nil)
780 (git-refresh-files)
781 (git-refresh-ewoc-hf git-status)))
782
@@ -891,11 +911,9 @@ Return the list of files that haven't been handled."
911 (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
912 (condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
913 (with-current-buffer buffer (erase-buffer))
894 - (git-update-status-files (git-get-filenames files) 'uptodate)
914 + (git-update-status-files (git-get-filenames files))
915 (git-call-process nil "rerere")
916 (git-call-process nil "gc" "--auto")
897 - (git-refresh-files)
898 - (git-refresh-ewoc-hf git-status)
917 (message "Committed %s." commit)
918 (git-run-hook "post-commit" nil)))
919 (message "Commit aborted."))))
@@ -1009,7 +1027,7 @@ Return the list of files that haven't been handled."
1027 (unless files
1028 (push (file-relative-name (read-file-name "File to add: " nil nil t)) files))
1029 (when (apply 'git-call-process-display-error "update-index" "--add" "--" files)
1012 - (git-update-status-files files 'uptodate)
1030 + (git-update-status-files files)
1031 (git-success-message "Added" files))))
1032
1033 (defun git-ignore-file ()
@@ -1019,7 +1037,7 @@ Return the list of files that haven't been handled."
1037 (unless files
1038 (push (file-relative-name (read-file-name "File to ignore: " nil nil t)) files))
1039 (dolist (f files) (git-append-to-ignore f))
1022 - (git-update-status-files files 'ignored)
1040 + (git-update-status-files files)
1041 (git-success-message "Ignored" files)))
1042
1043 (defun git-remove-file ()
@@ -1037,7 +1055,7 @@ Return the list of files that haven't been handled."
1055 (delete-directory name)
1056 (delete-file name))))
1057 (when (apply 'git-call-process-display-error "update-index" "--remove" "--" files)
1040 - (git-update-status-files files nil)
1058 + (git-update-status-files files)
1059 (git-success-message "Removed" files)))
1060 (message "Aborting"))))
1061
@@ -1065,7 +1083,7 @@ Return the list of files that haven't been handled."
1083 (apply 'git-call-process-display-error "update-index" "--force-remove" "--" added))
1084 (or (not modified)
1085 (apply 'git-call-process-display-error "checkout" "HEAD" modified)))))
1068 - (git-update-status-files (append added modified) 'uptodate)
1086 + (git-update-status-files (append added modified))
1087 (when ok
1088 (dolist (file modified)
1089 (let ((buffer (get-file-buffer file)))
@@ -1078,7 +1096,7 @@ Return the list of files that haven't been handled."
1096 (let ((files (git-get-filenames (git-marked-files-state 'unmerged))))
1097 (when files
1098 (when (apply 'git-call-process-display-error "update-index" "--" files)
1081 - (git-update-status-files files 'uptodate)
1099 + (git-update-status-files files)
1100 (git-success-message "Resolved" files)))))
1101
1102 (defun git-remove-handled ()
@@ -1348,7 +1366,7 @@ amended version of it."
1366 (git-call-process-display-error "reset" "--soft" "HEAD^")
1367 (and (git-update-ref "ORIG_HEAD" commit)
1368 (git-update-ref "HEAD" nil commit)))
1351 - (git-update-status-files (copy-sequence files) 'uptodate)
1369 + (git-update-status-files (copy-sequence files))
1370 (git-mark-files git-status files)
1371 (git-refresh-files)
1372 (git-setup-commit-buffer commit)
@@ -1391,27 +1409,10 @@ amended version of it."
1409 (defun git-refresh-status ()
1410 "Refresh the git status buffer."
1411 (interactive)
1394 - (let* ((status git-status)
1395 - (pos (ewoc-locate status))
1396 - (marked-files (git-get-filenames (ewoc-collect status (lambda (info) (git-fileinfo->marked info)))))
1397 - (cur-name (and pos (git-fileinfo->name (ewoc-data pos)))))
1398 - (unless status (error "Not in git-status buffer."))
1399 - (message "Refreshing git status...")
1400 - (git-call-process nil "update-index" "--refresh")
1401 - (git-clear-status status)
1402 - (git-update-status-files nil)
1403 - ; restore file marks
1404 - (when marked-files
1405 - (git-status-filenames-map status
1406 - (lambda (info)
1407 - (setf (git-fileinfo->marked info) t)
1408 - (setf (git-fileinfo->needs-refresh info) t))
1409 - marked-files)
1410 - (git-refresh-files))
1411 - ; move point to the current file name if any
1412 - (message "Refreshing git status...done")
1413 - (let ((node (and cur-name (git-find-status-file status cur-name))))
1414 - (when node (ewoc-goto-node status node)))))
1412 + (unless git-status (error "Not in git-status buffer."))
1413 + (message "Refreshing git status...")
1414 + (git-update-status-files)
1415 + (message "Refreshing git status...done"))
1416
1417 (defun git-status-quit ()
1418 "Quit git-status mode."
@@ -1591,7 +1592,7 @@ Meant to be used in `after-save-hook'."
1592 ; skip files located inside the .git directory
1593 (unless (string-match "^\\.git/" filename)
1594 (git-call-process nil "add" "--refresh" "--" filename)
1594 - (git-update-status-files (list filename) 'uptodate)))))))
1595 + (git-update-status-files (list filename))))))))
1596
1597 (defun git-help ()
1598 "Display help for Git mode."