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)))))))