Function: vc-dir-update

vc-dir-update is a byte-compiled function defined in vc-dir.el.gz.

Signature

(vc-dir-update ENTRIES BUFFER &optional NOINSERT)

Documentation

Update BUFFER's ewoc from the list of ENTRIES.

If NOINSERT, ignore elements on ENTRIES which are not in the ewoc.

Source Code

;; Defined in /usr/src/emacs/lisp/vc/vc-dir.el.gz
(defun vc-dir-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."
  ;; Add ENTRIES to the vc-dir buffer BUFFER.
  (with-current-buffer buffer
    ;; Insert the entries sorted by name into the ewoc.
    ;; We assume the ewoc is sorted too, which should be the
    ;; case if we always add entries with vc-dir-update.
    (setq entries
          (let ((entry-dirs
                 (mapcar (lambda (entry)
                           (cons (file-name-directory
                                  (directory-file-name (expand-file-name (car entry))))
                                 entry))
                         entries)))
	  ;; Sort: first files and then subdirectories.
            (mapcar #'cdr
                    (sort entry-dirs
                          (lambda (pair1 pair2)
                            (let ((dir1 (car pair1))
                                  (dir2 (car pair2)))
                              (cond
                               ((string< dir1 dir2) t)
                               ((not (string= dir1 dir2)) nil)
                               ((string< (cadr pair1) (cadr pair2))))))))))
    ;; Insert directory entries in the right places.
    (let ((entry (car entries))
	  (node (ewoc-nth vc-ewoc 0))
	  (to-remove nil)
	  (dotname (file-relative-name default-directory)))
      ;; Insert . if it is not present.
      (unless node
	(ewoc-enter-last
	 vc-ewoc (vc-dir-create-fileinfo
		  dotname nil nil nil default-directory))
	(setq node (ewoc-nth vc-ewoc 0)))

      (while (and entry node)
	(let* ((entryfile (car entry))
	       (entrydir (file-name-directory (directory-file-name
					       (expand-file-name entryfile))))
	       (nodedir (vc-dir-node-directory node)))
	  (cond
	   ;; First try to find the directory.
	   ((string-lessp nodedir entrydir)
	    (setq node (ewoc-next vc-ewoc node)))
	   ((string-equal nodedir entrydir)
	    ;; Found the directory, find the place for the file name.
	    (let ((nodefile (vc-dir-fileinfo->name (ewoc-data node))))
	      (cond
	       ((string= nodefile dotname)
		(setq node (ewoc-next vc-ewoc node)))
	       ((string-lessp nodefile entryfile)
		(setq node (ewoc-next vc-ewoc node)))
	       ((string-equal nodefile entryfile)
		(if (nth 1 entry)
		    (progn
		      (setf (vc-dir-fileinfo->state (ewoc-data node)) (nth 1 entry))
		      (setf (vc-dir-fileinfo->extra (ewoc-data node)) (nth 2 entry))
		      (setf (vc-dir-fileinfo->needs-update (ewoc-data node)) nil)
		      (ewoc-invalidate vc-ewoc node))
		  ;; If the state is nil, the file does not exist
		  ;; anymore, so remember the entry so we can remove
		  ;; it after we are done inserting all ENTRIES.
		  (push node to-remove))
		(setq entries (cdr entries))
		(setq entry (car entries))
		(setq node (ewoc-next vc-ewoc node)))
	       (t
		(unless noinsert
		  (ewoc-enter-before vc-ewoc node
				     (apply #'vc-dir-create-fileinfo entry)))
		(setq entries (cdr entries))
		(setq entry (car entries))))))
	   (t
	    (unless noinsert
	      ;; We might need to insert a directory node if the
	      ;; previous node was in a different directory.
	      (let* ((rd (file-relative-name entrydir))
		     (prev-node (ewoc-prev vc-ewoc node))
		     (prev-dir (if prev-node
				   (vc-dir-node-directory prev-node))))
		(unless (string-equal entrydir prev-dir)
		  (ewoc-enter-before
		   vc-ewoc node (vc-dir-create-fileinfo rd nil nil nil entrydir))))
	      ;; Now insert the node itself.
	      (ewoc-enter-before vc-ewoc node
				 (apply #'vc-dir-create-fileinfo entry)))
	    (setq entries (cdr entries) entry (car entries))))))
      ;; We're past the last node, all remaining entries go to the end.
      (unless (or node noinsert)
	(let ((lastdir (vc-dir-node-directory (ewoc-nth vc-ewoc -1))))
	  (dolist (entry entries)
	    (let ((entrydir (file-name-directory
			     (directory-file-name (expand-file-name (car entry))))))
	      ;; Insert a directory node if needed.
	      (unless (string-equal lastdir entrydir)
		(setq lastdir entrydir)
		(let ((rd (file-relative-name entrydir)))
		  (ewoc-enter-last
		   vc-ewoc (vc-dir-create-fileinfo rd nil nil nil entrydir))))
	      ;; Now insert the node itself.
	      (ewoc-enter-last vc-ewoc
			       (apply #'vc-dir-create-fileinfo entry))))))
      (when to-remove
	(let ((inhibit-read-only t))
	  (apply #'ewoc-delete vc-ewoc (nreverse to-remove)))))))