Mercurial > emacs
comparison lisp/vc-bzr.el @ 82491:962fb740e73f
Merge from emacs--rel--22
Patches applied:
* emacs--rel--22 (patch 93-96)
- Update from CVS
- Merge from gnus--rel--5.10
* gnus--rel--5.10 (patch 245)
- Update from CVS
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-856
author | Miles Bader <miles@gnu.org> |
---|---|
date | Tue, 21 Aug 2007 04:51:30 +0000 |
parents | e5a68f18fcb9 8f9613d80af0 |
children | 13fc3289f099 aaccdab0ee26 |
comparison
equal
deleted
inserted
replaced
82490:458dcdfc3e27 | 82491:962fb740e73f |
---|---|
57 ;; new functions when we reload this file. | 57 ;; new functions when we reload this file. |
58 (put 'Bzr 'vc-functions nil) | 58 (put 'Bzr 'vc-functions nil) |
59 | 59 |
60 (defgroup vc-bzr nil | 60 (defgroup vc-bzr nil |
61 "VC bzr backend." | 61 "VC bzr backend." |
62 ;; :version "22" | 62 :version "22.2" |
63 :group 'vc) | 63 :group 'vc) |
64 | 64 |
65 (defcustom vc-bzr-program "bzr" | 65 (defcustom vc-bzr-program "bzr" |
66 "Name of the bzr command (excluding any arguments)." | 66 "Name of the bzr command (excluding any arguments)." |
67 :group 'vc-bzr | 67 :group 'vc-bzr |
129 only parsed if it contains the string `#bazaar dirstate flat | 129 only parsed if it contains the string `#bazaar dirstate flat |
130 format 3' in the first line. | 130 format 3' in the first line. |
131 | 131 |
132 If the `checkout/dirstate' file cannot be parsed, fall back to | 132 If the `checkout/dirstate' file cannot be parsed, fall back to |
133 running `vc-bzr-state'." | 133 running `vc-bzr-state'." |
134 (condition-case nil | 134 (lexical-let ((root (vc-bzr-root file))) |
135 (lexical-let ((root (vc-bzr-root file))) | 135 (when root ; Short cut. |
136 (and root ; Short cut. | 136 ;; This looks at internal files. May break if they change |
137 ;; This looks at internal files. May break if they change | 137 ;; their format. |
138 ;; their format. | 138 (lexical-let ((dirstate (expand-file-name vc-bzr-admin-dirstate root))) |
139 (lexical-let | 139 (if (not (file-readable-p dirstate)) |
140 ((dirstate-file (expand-file-name vc-bzr-admin-dirstate root))) | 140 (vc-bzr-state file) ; Expensive. |
141 (if (file-exists-p dirstate-file) | 141 (with-temp-buffer |
142 (with-temp-buffer | 142 (insert-file-contents dirstate) |
143 (insert-file-contents dirstate-file) | 143 (goto-char (point-min)) |
144 (goto-char (point-min)) | 144 (if (not (looking-at "#bazaar dirstate flat format 3")) |
145 (when (looking-at "#bazaar dirstate flat format 3") | 145 (vc-bzr-state file) ; Some other unknown format? |
146 (let* ((relfile (file-relative-name file root)) | 146 (let* ((relfile (file-relative-name file root)) |
147 (reldir (file-name-directory relfile))) | 147 (reldir (file-name-directory relfile))) |
148 (re-search-forward | 148 (re-search-forward |
149 (concat "^\0" | 149 (concat "^\0" |
150 (if reldir (regexp-quote (directory-file-name reldir))) | 150 (if reldir (regexp-quote (directory-file-name reldir))) |
151 "\0" | 151 "\0" |
152 (regexp-quote (file-name-nondirectory relfile)) | 152 (regexp-quote (file-name-nondirectory relfile)) |
153 "\0") | 153 "\0") |
154 nil t)))) | 154 nil t))))))))) |
155 t)) | |
156 (vc-bzr-state file))) ; Expensive. | |
157 (file-error nil))) ; vc-bzr-program not found | |
158 | |
159 (defun vc-bzr-buffer-nonblank-p (&optional buffer) | |
160 "Return non-nil if BUFFER contains any non-blank characters." | |
161 (or (> (buffer-size buffer) 0) | |
162 (save-excursion | |
163 (set-buffer (or buffer (current-buffer))) | |
164 (goto-char (point-min)) | |
165 (re-search-forward "[^ \t\n]" (point-max) t)))) | |
166 | 155 |
167 (defconst vc-bzr-state-words | 156 (defconst vc-bzr-state-words |
168 "added\\|ignored\\|kind changed\\|modified\\|removed\\|renamed\\|unknown" | 157 "added\\|ignored\\|kind changed\\|modified\\|removed\\|renamed\\|unknown" |
169 "Regexp matching file status words as reported in `bzr' output.") | 158 "Regexp matching file status words as reported in `bzr' output.") |
170 | 159 |
179 ;; FIXME: Also get this in a non-registered sub-directory. | 168 ;; FIXME: Also get this in a non-registered sub-directory. |
180 ;; It already works for me. -- Riccardo | 169 ;; It already works for me. -- Riccardo |
181 (defun vc-bzr-status (file) | 170 (defun vc-bzr-status (file) |
182 "Return FILE status according to Bzr. | 171 "Return FILE status according to Bzr. |
183 Return value is a cons (STATUS . WARNING), where WARNING is a | 172 Return value is a cons (STATUS . WARNING), where WARNING is a |
184 string or nil, and STATUS is one of the symbols: 'added, | 173 string or nil, and STATUS is one of the symbols: `added', |
185 'ignored, 'kindchange, 'modified, 'removed, 'renamed, 'unknown, | 174 `ignored', `kindchanged', `modified', `removed', `renamed', `unknown', |
186 which directly correspond to `bzr status' output, or 'unchanged | 175 which directly correspond to `bzr status' output, or 'unchanged |
187 for files whose copy in the working tree is identical to the one | 176 for files whose copy in the working tree is identical to the one |
188 in the branch repository, or nil for files that are not | 177 in the branch repository, or nil for files that are not |
189 registered with Bzr. | 178 registered with Bzr. |
190 | 179 |
191 If any error occurred in running `bzr status', then return nil." | 180 If any error occurred in running `bzr status', then return nil." |
192 (condition-case nil | |
193 (with-temp-buffer | 181 (with-temp-buffer |
194 (let ((ret (vc-bzr-command "status" t 0 file)) | 182 (let ((ret (condition-case nil |
195 (status 'unchanged)) | 183 (vc-bzr-command "status" t 0 file) |
196 ;; the only secure status indication in `bzr status' output | 184 (file-error nil))) ; vc-bzr-program not found. |
197 ;; is a couple of lines following the pattern:: | 185 (status 'unchanged)) |
198 ;; | <status>: | 186 ;; the only secure status indication in `bzr status' output |
199 ;; | <file name> | 187 ;; is a couple of lines following the pattern:: |
200 ;; if the file is up-to-date, we get no status report from `bzr', | 188 ;; | <status>: |
201 ;; so if the regexp search for the above pattern fails, we consider | 189 ;; | <file name> |
202 ;; the file to be up-to-date. | 190 ;; if the file is up-to-date, we get no status report from `bzr', |
203 (goto-char (point-min)) | 191 ;; so if the regexp search for the above pattern fails, we consider |
204 (when | 192 ;; the file to be up-to-date. |
205 (re-search-forward | 193 (goto-char (point-min)) |
206 ;; bzr prints paths relative to the repository root | 194 (when (re-search-forward |
207 (concat "^\\(" vc-bzr-state-words "\\):[ \t\n]+" | 195 ;; bzr prints paths relative to the repository root. |
208 (regexp-quote (vc-bzr-file-name-relative file)) | 196 (concat "^\\(" vc-bzr-state-words "\\):[ \t\n]+" |
209 (if (file-directory-p file) "/?" "") | 197 (regexp-quote (vc-bzr-file-name-relative file)) |
210 "[ \t\n]*$") | 198 (if (file-directory-p file) "/?" "") |
211 (point-max) t) | 199 "[ \t\n]*$") |
212 (let ((start (match-beginning 0)) | 200 nil t) |
213 (end (match-end 0))) | 201 (let ((status (match-string 1))) |
214 (goto-char start) | 202 ;; Erase the status text that matched. |
203 (delete-region (match-beginning 0) (match-end 0)) | |
215 (setq status | 204 (setq status |
216 (cond | 205 (and (equal ret 0) ; Seems redundant. --Stef |
217 ((not (equal ret 0)) nil) | 206 (intern (replace-regexp-in-string " " "" |
218 ((looking-at "added") 'added) | 207 status)))))) |
219 ((looking-at "kind changed") 'kindchange) | 208 (when status |
220 ((looking-at "renamed") 'renamed) | 209 (goto-char (point-min)) |
221 ((looking-at "modified") 'modified) | 210 (skip-chars-forward " \n\t") ;Throw away spaces. |
222 ((looking-at "removed") 'removed) | 211 (cons status |
223 ((looking-at "ignored") 'ignored) | 212 ;; "bzr" will output warnings and informational messages to |
224 ((looking-at "unknown") 'unknown))) | 213 ;; stderr; due to Emacs' `vc-do-command' (and, it seems, |
225 ;; erase the status text that matched | 214 ;; `start-process' itself) limitations, we cannot catch stderr |
226 (delete-region start end))) | 215 ;; and stdout into different buffers. So, if there's anything |
227 (if status | 216 ;; left in the buffer after removing the above status |
228 (cons status | 217 ;; keywords, let us just presume that any other message from |
229 ;; "bzr" will output warnings and informational messages to | 218 ;; "bzr" is a user warning, and display it. |
230 ;; stderr; due to Emacs' `vc-do-command' (and, it seems, | 219 (unless (eobp) (buffer-substring (point) (point-max)))))))) |
231 ;; `start-process' itself) limitations, we cannot catch stderr | |
232 ;; and stdout into different buffers. So, if there's anything | |
233 ;; left in the buffer after removing the above status | |
234 ;; keywords, let us just presume that any other message from | |
235 ;; "bzr" is a user warning, and display it. | |
236 (if (vc-bzr-buffer-nonblank-p) | |
237 (buffer-substring (point-min) (point-max))))))) | |
238 (file-error nil))) ; vc-bzr-program not found | |
239 | 220 |
240 (defun vc-bzr-state (file) | 221 (defun vc-bzr-state (file) |
241 (lexical-let ((result (vc-bzr-status file))) | 222 (lexical-let ((result (vc-bzr-status file))) |
242 (when (consp result) | 223 (when (consp result) |
243 (if (cdr result) | 224 (if (cdr result) |
244 (message "Warnings in `bzr' output: %s" (cdr result))) | 225 (message "Warnings in `bzr' output: %s" (cdr result))) |
245 (cdr (assq (car result) | 226 (cdr (assq (car result) |
246 '((added . edited) | 227 '((added . edited) |
247 (kindchange . edited) | 228 (kindchanged . edited) |
248 (renamed . edited) | 229 (renamed . edited) |
249 (modified . edited) | 230 (modified . edited) |
250 (removed . edited) | 231 (removed . edited) |
251 (ignored . nil) | 232 (ignored . nil) |
252 (unknown . nil) | 233 (unknown . nil) |
263 (lastrev-file (concat rootdir "/" "branch/last-revision"))) | 244 (lastrev-file (concat rootdir "/" "branch/last-revision"))) |
264 ;; Count lines in .bzr/branch/revision-history to avoid forking a | 245 ;; Count lines in .bzr/branch/revision-history to avoid forking a |
265 ;; bzr process. This looks at internal files. May break if they | 246 ;; bzr process. This looks at internal files. May break if they |
266 ;; change their format. | 247 ;; change their format. |
267 (if (file-exists-p branch-format-file) | 248 (if (file-exists-p branch-format-file) |
268 (with-temp-buffer | 249 (with-temp-buffer |
269 (insert-file-contents branch-format-file) | 250 (insert-file-contents branch-format-file) |
270 (goto-char (point-min)) | 251 (goto-char (point-min)) |
271 (cond | 252 (cond |
272 ((or | 253 ((or |
273 (looking-at "Bazaar-NG branch, format 0.0.4") | 254 (looking-at "Bazaar-NG branch, format 0.0.4") |
274 (looking-at "Bazaar-NG branch format 5")) | 255 (looking-at "Bazaar-NG branch format 5")) |
275 ;; count lines in .bzr/branch/revision-history | 256 ;; count lines in .bzr/branch/revision-history |
276 (insert-file-contents revhistory-file) | 257 (insert-file-contents revhistory-file) |
277 (number-to-string (count-lines (line-end-position) (point-max)))) | 258 (number-to-string (count-lines (line-end-position) (point-max)))) |
278 ((looking-at "Bazaar Branch Format 6 (bzr 0.15)") | 259 ((looking-at "Bazaar Branch Format 6 (bzr 0.15)") |
279 ;; revno is the first number in .bzr/branch/last-revision | 260 ;; revno is the first number in .bzr/branch/last-revision |
280 (insert-file-contents lastrev-file) | 261 (insert-file-contents lastrev-file) |
281 (goto-char (line-end-position)) | 262 (goto-char (line-end-position)) |
339 EDITABLE is ignored." | 320 EDITABLE is ignored." |
340 (unless destfile | 321 (unless destfile |
341 (setq destfile (vc-version-backup-file-name file rev))) | 322 (setq destfile (vc-version-backup-file-name file rev))) |
342 (let ((coding-system-for-read 'binary) | 323 (let ((coding-system-for-read 'binary) |
343 (coding-system-for-write 'binary)) | 324 (coding-system-for-write 'binary)) |
344 (with-temp-file destfile | 325 (with-temp-file destfile |
345 (if rev | 326 (if rev |
346 (vc-bzr-command "cat" t 0 file "-r" rev) | 327 (vc-bzr-command "cat" t 0 file "-r" rev) |
347 (vc-bzr-command "cat" t 0 file))))) | 328 (vc-bzr-command "cat" t 0 file))))) |
348 | 329 |
349 (defun vc-bzr-revert (file &optional contents-done) | 330 (defun vc-bzr-revert (file &optional contents-done) |
350 (unless contents-done | 331 (unless contents-done |
351 (with-temp-buffer (vc-bzr-command "revert" t 0 file)))) | 332 (with-temp-buffer (vc-bzr-command "revert" t 0 file)))) |
352 | 333 |
375 | 356 |
376 (defun vc-bzr-print-log (files &optional buffer) ; get buffer arg in Emacs 22 | 357 (defun vc-bzr-print-log (files &optional buffer) ; get buffer arg in Emacs 22 |
377 "Get bzr change log for FILES into specified BUFFER." | 358 "Get bzr change log for FILES into specified BUFFER." |
378 ;; Fixme: This might need the locale fixing up if things like `revno' | 359 ;; Fixme: This might need the locale fixing up if things like `revno' |
379 ;; got localized, but certainly it shouldn't use LC_ALL=C. | 360 ;; got localized, but certainly it shouldn't use LC_ALL=C. |
380 ;; NB. Can't be async -- see `vc-bzr-post-command-function'. | |
381 (vc-bzr-command "log" buffer 0 files) | 361 (vc-bzr-command "log" buffer 0 files) |
382 ;; FIXME: Until Emacs-23, VC was missing a hook to sort out the mode for | 362 ;; FIXME: Until Emacs-23, VC was missing a hook to sort out the mode for |
383 ;; the buffer, or at least set the regexps right. | 363 ;; the buffer, or at least set the regexps right. |
384 (unless (fboundp 'vc-default-log-view-mode) | 364 (unless (fboundp 'vc-default-log-view-mode) |
385 (add-hook 'log-view-mode-hook 'vc-bzr-log-view-mode))) | 365 (add-hook 'log-view-mode-hook 'vc-bzr-log-view-mode))) |
399 (let ((working (vc-workfile-version (if (consp files) (car files) files)))) | 379 (let ((working (vc-workfile-version (if (consp files) (car files) files)))) |
400 (if (and (equal rev1 working) (not rev2)) | 380 (if (and (equal rev1 working) (not rev2)) |
401 (setq rev1 nil)) | 381 (setq rev1 nil)) |
402 (if (and (not rev1) rev2) | 382 (if (and (not rev1) rev2) |
403 (setq rev1 working)) | 383 (setq rev1 working)) |
404 ;; NB. Can't be async -- see `vc-bzr-post-command-function'. | |
405 ;; bzr diff produces condition code 1 for some reason. | 384 ;; bzr diff produces condition code 1 for some reason. |
406 (apply #'vc-bzr-command "diff" (or buffer "*vc-diff*") 1 files | 385 (apply #'vc-bzr-command "diff" (or buffer "*vc-diff*") 1 files |
407 "--diff-options" (mapconcat 'identity (vc-diff-switches-list bzr) | 386 "--diff-options" (mapconcat 'identity (vc-diff-switches-list bzr) |
408 " ") | 387 " ") |
409 (when rev1 | 388 (when rev1 |
461 (replace-match "") | 440 (replace-match "") |
462 (insert tag " |"))))) | 441 (insert tag " |"))))) |
463 | 442 |
464 ;; Definition from Emacs 22 | 443 ;; Definition from Emacs 22 |
465 (unless (fboundp 'vc-annotate-convert-time) | 444 (unless (fboundp 'vc-annotate-convert-time) |
466 (defun vc-annotate-convert-time (time) | 445 (defun vc-annotate-convert-time (time) |
467 "Convert a time value to a floating-point number of days. | 446 "Convert a time value to a floating-point number of days. |
468 The argument TIME is a list as returned by `current-time' or | 447 The argument TIME is a list as returned by `current-time' or |
469 `encode-time', only the first two elements of that list are considered." | 448 `encode-time', only the first two elements of that list are considered." |
470 (/ (+ (* (float (car time)) (lsh 1 16)) (cadr time)) 24 3600))) | 449 (/ (+ (* (float (car time)) (lsh 1 16)) (cadr time)) 24 3600))) |
471 | 450 |
472 (defun vc-bzr-annotate-time () | 451 (defun vc-bzr-annotate-time () |
473 (when (re-search-forward "^ *[0-9]+ |" nil t) | 452 (when (re-search-forward "^ *[0-9]+ |" nil t) |
474 (let ((prop (get-text-property (line-beginning-position) 'help-echo))) | 453 (let ((prop (get-text-property (line-beginning-position) 'help-echo))) |
475 (string-match "[0-9]+\\'" prop) | 454 (string-match "[0-9]+\\'" prop) |
547 ((looking-at "^added") | 526 ((looking-at "^added") |
548 (setq current-vc-state 'edited) | 527 (setq current-vc-state 'edited) |
549 (setq current-bzr-state 'added)) | 528 (setq current-bzr-state 'added)) |
550 ((looking-at "^kind changed") | 529 ((looking-at "^kind changed") |
551 (setq current-vc-state 'edited) | 530 (setq current-vc-state 'edited) |
552 (setq current-bzr-state 'kindchange)) | 531 (setq current-bzr-state 'kindchanged)) |
553 ((looking-at "^modified") | 532 ((looking-at "^modified") |
554 (setq current-vc-state 'edited) | 533 (setq current-vc-state 'edited) |
555 (setq current-bzr-state 'modified)) | 534 (setq current-bzr-state 'modified)) |
556 ((looking-at "^renamed") | 535 ((looking-at "^renamed") |
557 (setq current-vc-state 'edited) | 536 (setq current-vc-state 'edited) |
589 (if bzr-state | 568 (if bzr-state |
590 (concat "(" (symbol-name bzr-state) ")") | 569 (concat "(" (symbol-name bzr-state) ")") |
591 ;; else fall back to default vc representation | 570 ;; else fall back to default vc representation |
592 (vc-default-dired-state-info 'Bzr file))))) | 571 (vc-default-dired-state-info 'Bzr file))))) |
593 | 572 |
594 ;; In case of just `(load "vc-bzr")', but that's probably the wrong | |
595 ;; way to do it. | |
596 (add-to-list 'vc-handled-backends 'Bzr) | |
597 | |
598 (eval-after-load "vc" | 573 (eval-after-load "vc" |
599 '(add-to-list 'vc-directory-exclusion-list vc-bzr-admin-dirname t)) | 574 '(add-to-list 'vc-directory-exclusion-list vc-bzr-admin-dirname t)) |
600 | 575 |
601 (defconst vc-bzr-unload-hook | |
602 (lambda () | |
603 (setq vc-handled-backends (delq 'Bzr vc-handled-backends)) | |
604 (remove-hook 'vc-post-command-functions 'vc-bzr-post-command-function))) | |
605 | 576 |
606 (provide 'vc-bzr) | 577 (provide 'vc-bzr) |
607 ;; arch-tag: 8101bad8-4e92-4e7d-85ae-d8e08b4e7c06 | 578 ;; arch-tag: 8101bad8-4e92-4e7d-85ae-d8e08b4e7c06 |
608 ;;; vc-bzr.el ends here | 579 ;;; vc-bzr.el ends here |