Mercurial > emacs
comparison lisp/vc.el @ 94003:2ecb2ea8d5b5
Change `dir-status' to not take (and pass) status-buffer.
(vc-status-create-fileinfo): Make `extra' optional.
(vc-status-busy): New fun.
(vc-status-menu-map): Use it.
(vc-status-crt-marked): Remove.
(vc-status-update): Rename from vc-status-add-entries.
Add argument so as to prevent addition of entries. Rewrite.
(vc-update-vc-status-buffer): Remove.
(vc-status-refresh): Don't remove old entries, set them to
up-to-date instead. Also do it after the update is complete.
(vc-status-marked-files): ¦Ç-reduce.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Fri, 11 Apr 2008 15:17:59 +0000 |
parents | bfc762f0b49c |
children | c249cf124bd6 |
comparison
equal
deleted
inserted
replaced
94002:bae1479690d4 | 94003:2ecb2ea8d5b5 |
---|---|
166 ;; rather store the files' states into the corresponding properties. | 166 ;; rather store the files' states into the corresponding properties. |
167 ;; Two properties are required: `vc-backend' and `vc-state'. (Note: | 167 ;; Two properties are required: `vc-backend' and `vc-state'. (Note: |
168 ;; in older versions this method was not required to recurse into | 168 ;; in older versions this method was not required to recurse into |
169 ;; subdirectories.) | 169 ;; subdirectories.) |
170 ;; | 170 ;; |
171 ;; - dir-status (dir update-function status-buffer) | 171 ;; - dir-status (dir update-function) |
172 ;; | 172 ;; |
173 ;; Produce RESULT: a list of lists of the form (FILE VC-STATE EXTRA) | 173 ;; Produce RESULT: a list of lists of the form (FILE VC-STATE EXTRA) |
174 ;; for the files in DIR. | 174 ;; for the files in DIR. |
175 ;; EXTRA can be used for backend specific information about FILE. | 175 ;; EXTRA can be used for backend specific information about FILE. |
176 ;; If a command needs to be run to compute this list, it should be | 176 ;; If a command needs to be run to compute this list, it should be |
177 ;; run asynchronously using (current-buffer) as the buffer for the | 177 ;; run asynchronously using (current-buffer) as the buffer for the |
178 ;; command. When RESULT is computed, it should be passed back by | 178 ;; command. When RESULT is computed, it should be passed back by |
179 ;; doing: (funcall UPDATE-FUNCTION RESULT STATUS-BUFFER nil). | 179 ;; doing: (funcall UPDATE-FUNCTION RESULT nil). |
180 ;; If the backend uses a process filter, hence it produces partial results, | 180 ;; If the backend uses a process filter, hence it produces partial results, |
181 ;; they can be passed back by doing: | 181 ;; they can be passed back by doing: |
182 ;; (funcall UPDATE-FUNCTION RESULT STATUS-BUFFER t) | 182 ;; (funcall UPDATE-FUNCTION RESULT t) |
183 ;; and then do a (funcall UPDATE-FUNCTION RESULT STATUS-BUFFER nil) | 183 ;; and then do a (funcall UPDATE-FUNCTION RESULT nil) |
184 ;; when all the results have been computed. | 184 ;; when all the results have been computed. |
185 ;; To provide more backend specific functionality for `vc-status' | 185 ;; To provide more backend specific functionality for `vc-status' |
186 ;; the following functions might be needed: `status-extra-headers', | 186 ;; the following functions might be needed: `status-extra-headers', |
187 ;; `status-printer', `extra-status-menu' and `status-fileinfo-extra'. | 187 ;; `status-printer', `extra-status-menu' and `status-fileinfo-extra'. |
188 ;; This function is used by `vc-status', a replacement for | 188 ;; This function is used by `vc-status', a replacement for |
580 ;; is specific to a backend and which does not map to any of the VC | 580 ;; is specific to a backend and which does not map to any of the VC |
581 ;; generic concepts. | 581 ;; generic concepts. |
582 | 582 |
583 ;;; Todo: | 583 ;;; Todo: |
584 | 584 |
585 ;; - vc-status-kill-dir-status-process should not be specific to dir-status, | |
586 ;; it should work for other async commands as well (pull/push/...). | |
587 ;; | |
585 ;; - vc-update/vc-merge should deal with VC systems that don't | 588 ;; - vc-update/vc-merge should deal with VC systems that don't |
586 ;; update/merge on a file basis, but on a whole repository basis. | 589 ;; update/merge on a file basis, but on a whole repository basis. |
587 ;; | 590 ;; |
588 ;; - deal with push/pull operations. | 591 ;; - deal with push/pull operations. |
589 ;; | 592 ;; |
1436 (dolist (f (cdr marked)) | 1439 (dolist (f (cdr marked)) |
1437 (unless (eq (vc-backend f) firstbackend) | 1440 (unless (eq (vc-backend f) firstbackend) |
1438 (error "All members of a fileset must be under the same version-control system.")))) | 1441 (error "All members of a fileset must be under the same version-control system.")))) |
1439 marked)) | 1442 marked)) |
1440 ((eq major-mode 'vc-status-mode) | 1443 ((eq major-mode 'vc-status-mode) |
1441 (let ((marked (vc-status-marked-files))) | 1444 (or (vc-status-marked-files) |
1442 (if marked | 1445 (list (vc-status-current-file)))) |
1443 marked | |
1444 (list (vc-status-current-file))))) | |
1445 ((vc-backend buffer-file-name) | 1446 ((vc-backend buffer-file-name) |
1446 (list buffer-file-name)) | 1447 (list buffer-file-name)) |
1447 ((and vc-parent-buffer (or (buffer-file-name vc-parent-buffer) | 1448 ((and vc-parent-buffer (or (buffer-file-name vc-parent-buffer) |
1448 (with-current-buffer vc-parent-buffer | 1449 (with-current-buffer vc-parent-buffer |
1449 (or vc-dired-mode (eq major-mode 'vc-status-mode))))) | 1450 (or vc-dired-mode (eq major-mode 'vc-status-mode))))) |
2703 | 2704 |
2704 ;; Used to store information for the files displayed in the *VC status* buffer. | 2705 ;; Used to store information for the files displayed in the *VC status* buffer. |
2705 ;; Each item displayed corresponds to one of these defstructs. | 2706 ;; Each item displayed corresponds to one of these defstructs. |
2706 (defstruct (vc-status-fileinfo | 2707 (defstruct (vc-status-fileinfo |
2707 (:copier nil) | 2708 (:copier nil) |
2709 (:type list) ;So we can use `member' on lists of FIs. | |
2708 (:constructor | 2710 (:constructor |
2709 vc-status-create-fileinfo (name state extra &optional marked)) | 2711 ;; We could define it as an alias for `list'. |
2712 vc-status-create-fileinfo (name state &optional extra marked)) | |
2710 (:conc-name vc-status-fileinfo->)) | 2713 (:conc-name vc-status-fileinfo->)) |
2711 marked | 2714 name ;Keep it as first, for `member'. |
2712 state | 2715 state |
2713 name | |
2714 ;; For storing backend specific information. | 2716 ;; For storing backend specific information. |
2715 extra) | 2717 extra |
2718 marked) | |
2716 | 2719 |
2717 (defvar vc-status nil) | 2720 (defvar vc-status nil) |
2718 | 2721 |
2719 (defun vc-default-status-extra-headers (backend dir) | 2722 (defun vc-default-status-extra-headers (backend dir) |
2720 ;; Be loud by default to remind people to add coded to display | 2723 ;; Be loud by default to remind people to add coded to display |
2802 (define-key map [quit] | 2805 (define-key map [quit] |
2803 '(menu-item "Quit" bury-buffer | 2806 '(menu-item "Quit" bury-buffer |
2804 :help "Quit")) | 2807 :help "Quit")) |
2805 (define-key map [kill] | 2808 (define-key map [kill] |
2806 '(menu-item "Kill Update Command" vc-status-kill-dir-status-process | 2809 '(menu-item "Kill Update Command" vc-status-kill-dir-status-process |
2807 :enable vc-status-process-buffer | 2810 :enable (vc-status-busy) |
2808 :help "Kill the command that updates VC status buffer")) | 2811 :help "Kill the command that updates VC status buffer")) |
2809 (define-key map [refresh] | 2812 (define-key map [refresh] |
2810 '(menu-item "Refresh" vc-status-refresh | 2813 '(menu-item "Refresh" vc-status-refresh |
2811 :enable (not vc-status-process-buffer) | 2814 :enable (not (vc-status-busy)) |
2812 :help "Refresh the contents of the VC status buffer")) | 2815 :help "Refresh the contents of the VC status buffer")) |
2813 (define-key map [remup] | 2816 (define-key map [remup] |
2814 '(menu-item "Hide up-to-date" vc-status-hide-up-to-date | 2817 '(menu-item "Hide up-to-date" vc-status-hide-up-to-date |
2815 :help "Hide up-to-date items from display")) | 2818 :help "Hide up-to-date items from display")) |
2816 ;; VC commands. | 2819 ;; VC commands. |
2972 map)) | 2975 map)) |
2973 | 2976 |
2974 (defvar vc-status-process-buffer nil | 2977 (defvar vc-status-process-buffer nil |
2975 "The buffer used for the asynchronous call that computes the VC status.") | 2978 "The buffer used for the asynchronous call that computes the VC status.") |
2976 | 2979 |
2977 (defvar vc-status-crt-marked nil | |
2978 "The list of marked files before `vc-status-refresh'.") | |
2979 | |
2980 (defun vc-status-mode () | 2980 (defun vc-status-mode () |
2981 "Major mode for VC status. | 2981 "Major mode for VC status. |
2982 \\{vc-status-mode-map}" | 2982 \\{vc-status-mode-map}" |
2983 (setq mode-name "VC Status") | 2983 (setq mode-name "VC Status") |
2984 (setq major-mode 'vc-status-mode) | 2984 (setq major-mode 'vc-status-mode) |
2985 (setq buffer-read-only t) | 2985 (setq buffer-read-only t) |
2986 (set (make-local-variable 'vc-status-crt-marked) nil) | |
2987 (use-local-map vc-status-mode-map) | 2986 (use-local-map vc-status-mode-map) |
2988 (set (make-local-variable 'tool-bar-map) vc-status-tool-bar-map) | 2987 (set (make-local-variable 'tool-bar-map) vc-status-tool-bar-map) |
2989 (let ((buffer-read-only nil) | 2988 (let ((buffer-read-only nil) |
2990 (backend (vc-responsible-backend default-directory)) | 2989 (backend (vc-responsible-backend default-directory)) |
2991 entries) | 2990 entries) |
2997 (add-hook 'after-save-hook 'vc-status-mark-buffer-changed) | 2996 (add-hook 'after-save-hook 'vc-status-mark-buffer-changed) |
2998 (vc-status-refresh))) | 2997 (vc-status-refresh))) |
2999 | 2998 |
3000 (put 'vc-status-mode 'mode-class 'special) | 2999 (put 'vc-status-mode 'mode-class 'special) |
3001 | 3000 |
3002 (defun vc-status-add-entries (entries buffer) | 3001 (defun vc-status-update (entries buffer &optional noinsert) |
3002 "Update BUFFER's ewoc from the list of ENTRIES. | |
3003 If NOINSERT, ignore elements on ENTRIES which are not in the ewoc." | |
3003 ;; Add ENTRIES to the vc-status buffer BUFFER. | 3004 ;; Add ENTRIES to the vc-status buffer BUFFER. |
3004 (with-current-buffer buffer | 3005 (with-current-buffer buffer |
3005 (when entries | 3006 ;; Insert the entries sorted by name into the ewoc. |
3006 ;; Insert the entries sorted by name into the ewoc. | 3007 ;; We assume the ewoc is sorted too, which should be the |
3007 ;; We assume the ewoc is sorted too, which should be the | 3008 ;; case if we always add entries with vc-status-update. |
3008 ;; case if we always add entries with vc-status-add-entries. | 3009 (setq entries (sort entries |
3009 (setq entries (sort (copy-sequence entries) | 3010 (lambda (entry1 entry2) |
3010 (lambda (entry1 entry2) | 3011 (string-lessp (car entry1) (car entry2))))) |
3011 (string-lessp (car entry1) (car entry2))))) | 3012 (let ((entry (car entries)) |
3012 (let ((entry (pop entries)) | 3013 (node (ewoc-nth vc-status 0))) |
3013 (node (ewoc-nth vc-status 0))) | 3014 (while (and entry node) |
3014 (while entry | 3015 (let ((entryfile (car entry)) |
3015 (while (and vc-status-crt-marked | 3016 (nodefile (vc-status-fileinfo->name (ewoc-data node)))) |
3016 (string-lessp (car vc-status-crt-marked) (car entry))) | 3017 (cond |
3017 (setq vc-status-crt-marked (cdr vc-status-crt-marked))) | 3018 ((string-lessp nodefile entryfile) |
3018 (let* ((file (car entry)) | 3019 (setq node (ewoc-next vc-status node))) |
3019 (state (nth 1 entry)) | 3020 ((string-lessp nodefile entryfile) |
3020 (extra (nth 2 entry)) | 3021 (unless noinsert |
3021 (marked (and vc-status-crt-marked | 3022 (ewoc-enter-before vc-status node |
3022 (string-equal (car vc-status-crt-marked) file)))) | 3023 (apply 'vc-status-create-fileinfo entry))) |
3023 (cond ((not node) | 3024 (setq entries (cdr entries) entry (car entries))) |
3024 (setq node (ewoc-enter-last vc-status | 3025 (t |
3025 (vc-status-create-fileinfo file state extra marked))) | 3026 (setf (vc-status-fileinfo->state (ewoc-data node)) (nth 1 entry)) |
3026 (setq entry (pop entries))) | 3027 (setf (vc-status-fileinfo->extra (ewoc-data node)) (nth 2 entry)) |
3027 ((string-lessp (vc-status-fileinfo->name (ewoc-data node)) file) | 3028 (ewoc-invalidate vc-status node) |
3028 (setq node (ewoc-next vc-status node))) | 3029 (setq entries (cdr entries) entry (car entries)) |
3029 ((string-equal (vc-status-fileinfo->name (ewoc-data node)) file) | 3030 (setq node (ewoc-next vc-status node)))))) |
3030 (setf (vc-status-fileinfo->state (ewoc-data node)) state) | 3031 (unless (or node noinsert) |
3031 (setf (vc-status-fileinfo->extra (ewoc-data node)) extra) | 3032 ;; We're past the last node, all remaining entries go to the end. |
3032 (ewoc-invalidate vc-status node) | 3033 (while entries |
3033 (setq entry (pop entries))) | 3034 (ewoc-enter-last vc-status |
3034 (t | 3035 (apply 'vc-status-create-fileinfo (pop entries)))))))) |
3035 (setq node (ewoc-enter-before vc-status node | 3036 |
3036 (vc-status-create-fileinfo file state extra marked))) | 3037 (defun vc-status-busy () |
3037 (setq entry (pop entries)))))))))) | 3038 (and (buffer-live-p vc-status-process-buffer) |
3038 | 3039 (get-buffer-process vc-status-process-buffer))) |
3039 (defun vc-update-vc-status-buffer (entries buffer &optional more-to-come) | |
3040 ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. | |
3041 ;; BUFFER is the *vc-status* buffer to be updated with ENTRIES | |
3042 ;; If MORE-TO-COME is true, then more updates will come from the | |
3043 ;; asynchronous process. | |
3044 (with-current-buffer buffer | |
3045 (when entries | |
3046 (vc-status-add-entries entries buffer) | |
3047 (ewoc-goto-node vc-status (ewoc-nth vc-status 0))) | |
3048 ;; No more updates are expected from the asynchronous process. | |
3049 (unless more-to-come | |
3050 (setq vc-status-process-buffer nil) | |
3051 ;; We are done, turn off the mode-line "in progress" message. | |
3052 (setq mode-line-process nil)))) | |
3053 | 3040 |
3054 (defun vc-status-refresh () | 3041 (defun vc-status-refresh () |
3055 "Refresh the contents of the VC status buffer. | 3042 "Refresh the contents of the VC status buffer. |
3056 Throw an error if another update process is in progress." | 3043 Throw an error if another update process is in progress." |
3057 (interactive) | 3044 (interactive) |
3058 (if vc-status-process-buffer | 3045 (if (vc-status-busy) |
3059 (error "Another update process is in progress, cannot run two at a time") | 3046 (error "Another update process is in progress, cannot run two at a time") |
3060 ;; We clear the ewoc, but remember the marked files so that we can | |
3061 ;; mark them again after the refresh is done. | |
3062 ;; This is not very efficient; ewoc could use a new function here. | |
3063 (setq vc-status-crt-marked | |
3064 (mapcar | |
3065 (lambda (elem) | |
3066 (vc-status-fileinfo->name elem)) | |
3067 (ewoc-collect | |
3068 vc-status | |
3069 (lambda (crt) (vc-status-fileinfo->marked crt))))) | |
3070 (ewoc-filter vc-status (lambda (node) nil)) | |
3071 | |
3072 (let ((backend (vc-responsible-backend default-directory)) | 3047 (let ((backend (vc-responsible-backend default-directory)) |
3073 (status-buffer (current-buffer)) | 3048 (status-buffer (current-buffer)) |
3074 (def-dir default-directory)) | 3049 (def-dir default-directory)) |
3075 (vc-set-mode-line-busy-indicator) | 3050 (vc-set-mode-line-busy-indicator) |
3076 ;; Call the `dir-status' backend function. | 3051 ;; Call the `dir-status' backend function. |
3082 ;; Create a buffer that can be used by `dir-status' and call | 3057 ;; Create a buffer that can be used by `dir-status' and call |
3083 ;; `dir-status' with this buffer as the current buffer. Use | 3058 ;; `dir-status' with this buffer as the current buffer. Use |
3084 ;; `vc-status-process-buffer' to remember this buffer, so that | 3059 ;; `vc-status-process-buffer' to remember this buffer, so that |
3085 ;; it can be used later to kill the update process in case it | 3060 ;; it can be used later to kill the update process in case it |
3086 ;; takes too long. | 3061 ;; takes too long. |
3087 (setq vc-status-process-buffer | 3062 (unless (buffer-live-p vc-status-process-buffer) |
3088 (get-buffer-create | 3063 (setq vc-status-process-buffer |
3089 (generate-new-buffer-name (format " *VC-%s* tmp status" backend)))) | 3064 (generate-new-buffer (format " *VC-%s* tmp status" backend)))) |
3090 (with-current-buffer vc-status-process-buffer | 3065 (lexical-let ((oldentries (ewoc-collect vc-status (lambda (_) t))) |
3091 (cd def-dir) | 3066 (buffer (current-buffer))) |
3092 (erase-buffer) | 3067 (with-current-buffer vc-status-process-buffer |
3093 (vc-call-backend backend 'dir-status def-dir | 3068 (cd def-dir) |
3094 #'vc-update-vc-status-buffer status-buffer))))) | 3069 (erase-buffer) |
3070 (vc-call-backend | |
3071 backend 'dir-status def-dir | |
3072 (lambda (entries &optional more-to-come) | |
3073 ;; ENTRIES is a list of (FILE VC_STATE EXTRA) items. | |
3074 ;; If MORE-TO-COME is true, then more updates will come from | |
3075 ;; the asynchronous process. | |
3076 (with-current-buffer buffer | |
3077 (dolist (entry entries) | |
3078 (setq oldentries | |
3079 (delq (member (car entry) oldentries) oldentries))) | |
3080 (vc-status-update entries buffer) | |
3081 (ewoc-goto-node vc-status (ewoc-nth vc-status 0)) | |
3082 ;; No more updates are expected from the asynchronous process. | |
3083 (unless more-to-come | |
3084 ;; We are done, turn off the mode-line "in progress" message. | |
3085 (setq mode-line-process nil) | |
3086 ;; Update old entries that were not mentioned, and were | |
3087 ;; hence implicitly given as uptodate. | |
3088 (dolist (entry oldentries) | |
3089 (setf (vc-status-fileinfo->state entry) 'up-to-date)) | |
3090 (vc-status-update oldentries buffer 'noinsert)))))))))) | |
3095 | 3091 |
3096 (defun vc-status-kill-dir-status-process () | 3092 (defun vc-status-kill-dir-status-process () |
3097 "Kill the temporary buffer and associated process." | 3093 "Kill the temporary buffer and associated process." |
3098 (interactive) | 3094 (interactive) |
3099 (when (buffer-live-p vc-status-process-buffer) | 3095 (when (buffer-live-p vc-status-process-buffer) |
3234 (vc-status-mark-unmark 'vc-status-toggle-mark-file)) | 3230 (vc-status-mark-unmark 'vc-status-toggle-mark-file)) |
3235 | 3231 |
3236 (defun vc-status-register () | 3232 (defun vc-status-register () |
3237 "Register the marked files, or the current file if no marks." | 3233 "Register the marked files, or the current file if no marks." |
3238 (interactive) | 3234 (interactive) |
3239 (let ((files (or (vc-status-marked-files) | 3235 ;; FIXME: Just pass the fileset to vc-register. |
3240 (list (vc-status-current-file))))) | 3236 (mapc 'vc-register (or (vc-status-marked-files) |
3241 (dolist (file files) | 3237 (list (vc-status-current-file))))) |
3242 (vc-register file)))) | |
3243 | 3238 |
3244 (defun vc-status-find-file () | 3239 (defun vc-status-find-file () |
3245 "Find the file on the current line." | 3240 "Find the file on the current line." |
3246 (interactive) | 3241 (interactive) |
3247 (find-file (vc-status-current-file))) | 3242 (find-file (vc-status-current-file))) |
3258 (expand-file-name (vc-status-fileinfo->name (ewoc-data node))))) | 3253 (expand-file-name (vc-status-fileinfo->name (ewoc-data node))))) |
3259 | 3254 |
3260 (defun vc-status-marked-files () | 3255 (defun vc-status-marked-files () |
3261 "Return the list of marked files" | 3256 "Return the list of marked files" |
3262 (mapcar | 3257 (mapcar |
3263 (lambda (elem) | 3258 (lambda (elem) (expand-file-name (vc-status-fileinfo->name elem))) |
3264 (expand-file-name (vc-status-fileinfo->name elem))) | 3259 (ewoc-collect vc-status 'vc-status-fileinfo->marked))) |
3265 (ewoc-collect | |
3266 vc-status | |
3267 (lambda (crt) (vc-status-fileinfo->marked crt))))) | |
3268 | 3260 |
3269 (defun vc-status-hide-up-to-date () | 3261 (defun vc-status-hide-up-to-date () |
3270 "Hide up-to-date items from display." | 3262 "Hide up-to-date items from display." |
3271 (interactive) | 3263 (interactive) |
3272 (ewoc-filter | 3264 (ewoc-filter |
3295 (extra | 3287 (extra |
3296 (and backend | 3288 (and backend |
3297 (vc-call-backend backend 'status-fileinfo-extra file))) | 3289 (vc-call-backend backend 'status-fileinfo-extra file))) |
3298 (entry | 3290 (entry |
3299 (list file-short (if state state 'unregistered) extra))) | 3291 (list file-short (if state state 'unregistered) extra))) |
3300 (vc-status-add-entries (list entry) status-buf)))))) | 3292 (vc-status-update (list entry) status-buf)))))) |
3301 ;; We didn't find any vc-status buffers, remove the hook, it is | 3293 ;; We didn't find any vc-status buffers, remove the hook, it is |
3302 ;; not needed. | 3294 ;; not needed. |
3303 (unless found-vc-status-buf (remove-hook 'after-save-hook 'vc-status-mark-buffer-changed))))) | 3295 (unless found-vc-status-buf (remove-hook 'after-save-hook 'vc-status-mark-buffer-changed))))) |
3304 | 3296 |
3305 ;; Named-configuration entry points | 3297 ;; Named-configuration entry points |