changeset 94059:c249cf124bd6

(vc-status-update): Revert an incorrect rewrite. Add some comments. (vc-status-refresh-files): New function. (vc-status-refresh): Use `vc-status-refresh-files' to refresh the state of up-to-date files. (vc-default-dir-status-files): New function.
author Alexandre Julliard <julliard@winehq.org>
date Sun, 13 Apr 2008 18:06:35 +0000
parents 5e1992e5137e
children 6c138603231c
files lisp/vc.el
diffstat 1 files changed, 82 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/vc.el	Sun Apr 13 16:29:55 2008 +0000
+++ b/lisp/vc.el	Sun Apr 13 18:06:35 2008 +0000
@@ -184,12 +184,20 @@
 ;;   when all the results have been computed.
 ;;   To provide more backend specific functionality for `vc-status'
 ;;   the following functions might be needed: `status-extra-headers',
-;;   `status-printer', `extra-status-menu' and `status-fileinfo-extra'.
+;;   `status-printer', `extra-status-menu' and `dir-status-files'.
 ;;   This function is used by `vc-status', a replacement for
 ;;   `vc-dired'.  vc-status is still under development, and is NOT
 ;;   feature complete.  As such, the requirements for this function
 ;;   might change.  This is a replacement for `dir-state'.
 ;;
+;; - dir-status-files (dir files default-state update-function)
+;;
+;;   This function is identical to dir-status except that it should
+;;   only report status for the specified FILES. Also it needs to
+;;   report on all requested files, including up-to-date or ignored
+;;   files. If not provided, the default is to consider that the files
+;;   are in DEFAULT-STATE.
+;;
 ;; - status-extra-headers (dir)
 ;;
 ;;   Return a string that will be added to the *vc-status* buffer header.
@@ -643,11 +651,6 @@
 ;; - vc-status needs a command to insert a file entry in the status
 ;;   display, similar to `cvs-mode-insert'.
 ;;
-;; - the dir-status backend function should take as an argument an
-;;   optional fileset, and should return the results just for that
-;;   fileset.  This can be used to speed up status buffer updates
-;;   after VC operations.
-;;
 ;; - vc-status: refresh should not completely wipe out the current
 ;;   contents of the vc-status buffer.
 ;;
@@ -2715,7 +2718,9 @@
   state
   ;; For storing backend specific information.
   extra
-  marked)
+  marked
+  ;; To keep track of not updated files during a global refresh
+  needs-update)
 
 (defvar vc-status nil)
 
@@ -2998,9 +3003,8 @@
 
 (put 'vc-status-mode 'mode-class 'special)
 
-(defun vc-status-update (entries buffer &optional noinsert)
-  "Update BUFFER's ewoc from the list of ENTRIES.
-If NOINSERT, ignore elements on ENTRIES which are not in the ewoc."
+(defun vc-status-update (entries buffer)
+  "Update BUFFER's ewoc from the list of ENTRIES."
   ;; Add ENTRIES to the vc-status buffer BUFFER.
   (with-current-buffer buffer
     ;; Insert the entries sorted by name into the ewoc.
@@ -3009,35 +3013,64 @@
     (setq entries (sort entries
                         (lambda (entry1 entry2)
                           (string-lessp (car entry1) (car entry2)))))
-    (let ((entry (car entries))
-           (node (ewoc-nth vc-status 0)))
-      (while (and entry node)
-        (let ((entryfile (car entry))
-              (nodefile (vc-status-fileinfo->name (ewoc-data node))))
-          (cond
-           ((string-lessp nodefile entryfile)
-            (setq node (ewoc-next vc-status node)))
-           ((string-lessp nodefile entryfile)
-            (unless noinsert
-              (ewoc-enter-before vc-status node
-                                 (apply 'vc-status-create-fileinfo entry)))
-            (setq entries (cdr entries) entry (car entries)))
-           (t
-            (setf (vc-status-fileinfo->state (ewoc-data node)) (nth 1 entry))
-            (setf (vc-status-fileinfo->extra (ewoc-data node)) (nth 2 entry))
-            (ewoc-invalidate vc-status node)
-            (setq entries (cdr entries) entry (car entries))
-            (setq node (ewoc-next vc-status node))))))
-      (unless (or node noinsert)
-        ;; We're past the last node, all remaining entries go to the end.
-        (while entries
-          (ewoc-enter-last vc-status
-                           (apply 'vc-status-create-fileinfo (pop entries))))))))
+    (let ((entry (pop entries))
+          (node (ewoc-nth vc-status 0)))
+      (while entry
+        (let ((file (car entry)))
+          ;; Note: we always keep node pointing to the last inserted entry
+          ;; in order to catch duplicates in the entries list
+          (cond ((not node)
+                 (setq node (ewoc-enter-last vc-status
+                                             (apply 'vc-status-create-fileinfo entry)))
+                 (setq entry (pop entries)))
+                ((string-lessp (vc-status-fileinfo->name (ewoc-data node)) file)
+                 (setq node (ewoc-next vc-status node)))
+                ((string-equal (vc-status-fileinfo->name (ewoc-data node)) file)
+                 (setf (vc-status-fileinfo->state (ewoc-data node)) (nth 1 entry))
+                 (setf (vc-status-fileinfo->extra (ewoc-data node)) (nth 2 entry))
+                 (setf (vc-status-fileinfo->needs-update (ewoc-data node)) nil)
+                 (ewoc-invalidate vc-status node)
+                 (setq entry (pop entries)))
+                (t
+                 (setq node (ewoc-enter-before vc-status node
+                                               (apply 'vc-status-create-fileinfo entry)))
+                 (setq entry (pop entries)))))))))
 
 (defun vc-status-busy ()
   (and (buffer-live-p vc-status-process-buffer)
        (get-buffer-process vc-status-process-buffer)))
 
+(defun vc-status-refresh-files (files default-state)
+  "Refresh some files in the VC status buffer."
+  (let ((backend (vc-responsible-backend default-directory))
+        (status-buffer (current-buffer))
+        (def-dir default-directory))
+    (vc-set-mode-line-busy-indicator)
+    ;; Call the `dir-status-file' backend function.
+    ;; `dir-status-file' is supposed to be asynchronous.
+    ;; It should compute the results, and then call the function
+    ;; passed as an argument in order to update the vc-status buffer
+    ;; with the results.
+    (unless (buffer-live-p vc-status-process-buffer)
+      (setq vc-status-process-buffer
+            (generate-new-buffer (format " *VC-%s* tmp status" backend))))
+    (lexical-let ((buffer (current-buffer)))
+      (with-current-buffer vc-status-process-buffer
+        (cd def-dir)
+        (erase-buffer)
+        (vc-call-backend
+         backend 'dir-status-files def-dir files default-state
+         (lambda (entries &optional more-to-come)
+           ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items.
+           ;; If MORE-TO-COME is true, then more updates will come from
+           ;; the asynchronous process.
+           (with-current-buffer buffer
+             (vc-status-update entries buffer)
+             (unless more-to-come
+               (setq mode-line-process nil)
+               ;; Remove the ones that haven't been updated at all
+               (ewoc-filter vc-status (lambda (info) (not (vc-status-fileinfo->needs-update info))))))))))))
+
 (defun vc-status-refresh ()
   "Refresh the contents of the VC status buffer.
 Throw an error if another update process is in progress."
@@ -3062,8 +3095,9 @@
       (unless (buffer-live-p vc-status-process-buffer)
         (setq vc-status-process-buffer
               (generate-new-buffer (format " *VC-%s* tmp status" backend))))
-      (lexical-let ((oldentries (ewoc-collect vc-status (lambda (_) t)))
-                    (buffer (current-buffer)))
+      ;; set the needs-update flag on all entries
+      (ewoc-map (lambda (info) (setf (vc-status-fileinfo->needs-update info) t) nil) vc-status)
+      (lexical-let ((buffer (current-buffer)))
         (with-current-buffer vc-status-process-buffer
           (cd def-dir)
           (erase-buffer)
@@ -3074,20 +3108,16 @@
              ;; If MORE-TO-COME is true, then more updates will come from
              ;; the asynchronous process.
              (with-current-buffer buffer
-               (dolist (entry entries)
-                 (setq oldentries
-                       (delq (member (car entry) oldentries) oldentries)))
                (vc-status-update entries buffer)
-               (ewoc-goto-node vc-status (ewoc-nth vc-status 0))
-               ;; No more updates are expected from the asynchronous process.
                (unless more-to-come
-                 ;; We are done, turn off the mode-line "in progress" message.
-                 (setq mode-line-process nil)
-                 ;; Update old entries that were not mentioned, and were
-                 ;; hence implicitly given as uptodate.
-                 (dolist (entry oldentries)
-                   (setf (vc-status-fileinfo->state entry) 'up-to-date))
-                 (vc-status-update oldentries buffer 'noinsert))))))))))
+                 (let ((remaining
+                        (ewoc-collect vc-status
+                                      (lambda (info) (vc-status-fileinfo->needs-update info)))))
+                   (if remaining
+                       (vc-status-refresh-files
+                        (mapcar (lambda (info) (vc-status-fileinfo->name info)) remaining)
+                        'up-to-date)
+                     (setq mode-line-process nil))))))))))))
 
 (defun vc-status-kill-dir-status-process ()
   "Kill the temporary buffer and associated process."
@@ -3993,6 +4023,10 @@
 
 (defalias 'vc-default-revision-completion-table 'ignore)
 
+(defun vc-default-dir-status-files (backend dir files default-state update-function)
+  (funcall update-function
+           (mapcar (lambda (file) (list file default-state)) files)))
+
 (defun vc-check-headers ()
   "Check if the current file has any headers in it."
   (interactive)