aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/vc-bzr.el241
1 files changed, 92 insertions, 149 deletions
diff --git a/lisp/vc-bzr.el b/lisp/vc-bzr.el
index e3076c714cf..1ad7de8a9ee 100644
--- a/lisp/vc-bzr.el
+++ b/lisp/vc-bzr.el
@@ -58,6 +58,7 @@
58;;; Code: 58;;; Code:
59 59
60(eval-when-compile 60(eval-when-compile
61 (require 'cl)
61 (require 'vc)) ; for vc-exec-after 62 (require 'vc)) ; for vc-exec-after
62 63
63(defgroup vc-bzr nil 64(defgroup vc-bzr nil
@@ -66,18 +67,18 @@
66 :group 'vc) 67 :group 'vc)
67 68
68(defcustom vc-bzr-program "bzr" 69(defcustom vc-bzr-program "bzr"
69 "*Name of the bzr command (excluding any arguments)." 70 "Name of the bzr command (excluding any arguments)."
70 :group 'vc-bzr 71 :group 'vc-bzr
71 :type 'string) 72 :type 'string)
72 73
73;; Fixme: there's probably no call for this. 74;; Fixme: there's probably no call for this.
74(defcustom vc-bzr-program-args nil 75(defcustom vc-bzr-program-args nil
75 "*List of global arguments to pass to `vc-bzr-program'." 76 "List of global arguments to pass to `vc-bzr-program'."
76 :group 'vc-bzr 77 :group 'vc-bzr
77 :type '(repeat string)) 78 :type '(repeat string))
78 79
79(defcustom vc-bzr-diff-switches nil 80(defcustom vc-bzr-diff-switches nil
80 "*String/list of strings specifying extra switches for bzr diff under VC." 81 "String/list of strings specifying extra switches for bzr diff under VC."
81 :type '(choice (const :tag "None" nil) 82 :type '(choice (const :tag "None" nil)
82 (string :tag "Argument String") 83 (string :tag "Argument String")
83 (repeat :tag "Argument List" :value ("") string)) 84 (repeat :tag "Argument List" :value ("") string))
@@ -91,93 +92,42 @@
91 "Return a three-numeric element list with components of the bzr version. 92 "Return a three-numeric element list with components of the bzr version.
92This is of the form (X Y Z) for revision X.Y.Z. The elements are zero 93This is of the form (X Y Z) for revision X.Y.Z. The elements are zero
93if running `vc-bzr-program' doesn't produce the expected output." 94if running `vc-bzr-program' doesn't produce the expected output."
94 (if vc-bzr-version 95 (or vc-bzr-version
95 vc-bzr-version 96 (setq vc-bzr-version
96 (let ((s (shell-command-to-string 97 (let ((s (shell-command-to-string
97 (concat (shell-quote-argument vc-bzr-program) " --version")))) 98 (concat (shell-quote-argument vc-bzr-program)
98 (if (string-match "\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)$" s) 99 " --version"))))
99 (setq vc-bzr-version (list (string-to-number (match-string 1 s)) 100 (if (string-match "\\([0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)$" s)
100 (string-to-number (match-string 2 s)) 101 (list (string-to-number (match-string 1 s))
101 (string-to-number (match-string 3 s)))) 102 (string-to-number (match-string 2 s))
102 '(0 0 0))))) 103 (string-to-number (match-string 3 s)))
104 '(0 0 0))))))
103 105
104(defun vc-bzr-at-least-version (vers) 106(defun vc-bzr-at-least-version (vers)
105 "Return t if the bzr command reports being a least version VERS. 107 "Return t if the bzr command reports being a least version VERS.
106First argument VERS is a list of the form (X Y Z), as returned by `vc-bzr-version'." 108First argument VERS is a list of the form (X Y Z), as returned by `vc-bzr-version'."
107 (version-list-<= vers (vc-bzr-version))) 109 (version-list-<= vers (vc-bzr-version)))
108 110
109(eval-when-compile 111;; since v0.9, bzr supports removing the progress indicators
110 (defmacro vc-bzr-with-process-environment (envspec &rest body) 112;; by setting environment variable BZR_PROGRESS_BAR to "none".
111 "Prepend the contents of ENVSPEC to `process-environment', then execute BODY." 113(defun vc-bzr-command (bzr-command buffer okstatus file &rest args)
112 `(let ((process-environment process-environment)) 114 "Wrapper round `vc-do-command' using `vc-bzr-program' as COMMAND.
113 (mapcar (lambda (var) (add-to-list 'process-environment var)) ,envspec)
114 ,@body))
115
116 (defmacro vc-bzr-std-process-invocation (&rest body)
117 `(vc-bzr-with-process-environment
118 '("BZR_PROGRESS_BAR=none" ; suppress progress output (bzr >=0.9)
119 "LC_ALL=C") ; force English output
120 ;; bzr may attempt some kind of user interaction if its stdin/stdout
121 ;; is connected to a PTY; therefore, ask Emacs to use a pipe to
122 ;; communicate with it.
123 (let ((process-connection-type nil))
124 ,@body))))
125
126;; XXX: vc-do-command is tailored for RCS and assumes that command-line
127;; options precede the file name (e.g., "ci -something file"); with bzr,
128;; we need to pass options *after* the subcommand, e.g. "bzr ls --versioned".
129(defun vc-bzr-do-command* (buffer okstatus command &rest args)
130 "Execute bzr COMMAND, notifying user and checking for errors.
131This is a wrapper around `vc-do-command', which see for detailed
132explanation of arguments BUFFER, OKSTATUS and COMMAND.
133
134If the optional list of ARGS is present, its elements are
135appended to the command line, in the order given.
136
137Unlike `vc-do-command', this has no way of telling which elements
138in ARGS are file names and which are command-line options, so be
139sure to pass absolute file names if needed. On the other hand,
140you can mix options and file names in any order."
141 (apply 'vc-do-command buffer okstatus command nil args))
142
143(cond
144 ((vc-bzr-at-least-version '(0 9))
145 ;; since v0.9, bzr supports removing the progress indicators
146 ;; by setting environment variable BZR_PROGRESS_BAR to "none".
147 (defun vc-bzr-command (bzr-command buffer okstatus file &rest args)
148 "Wrapper round `vc-do-command' using `vc-bzr-program' as COMMAND.
149Invoke the bzr command adding `BZR_PROGRESS_BAR=none' to the environment." 115Invoke the bzr command adding `BZR_PROGRESS_BAR=none' to the environment."
150 (vc-bzr-std-process-invocation 116 (let ((process-environment
151 (apply 'vc-do-command buffer okstatus vc-bzr-program 117 (list* "BZR_PROGRESS_BAR=none" ; Suppress progress output (bzr >=0.9)
152 file bzr-command (append vc-bzr-program-args args)))) 118 "LC_ALL=C" ; Force English output
153 119 process-environment))
154 (defun vc-bzr-command* (bzr-command buffer okstatus file &rest args) 120 ;; bzr may attempt some kind of user interaction if its stdin/stdout
155 "Wrapper round `vc-bzr-do-command*' using `vc-bzr-program' as COMMAND. 121 ;; is connected to a PTY; therefore, ask Emacs to use a pipe to
156Invoke the bzr command adding `BZR_PROGRESS_BAR=none' to the environment. 122 ;; communicate with it.
157First argument BZR-COMMAND is passed as the first optional argument to 123 ;; This is redundant because vc-do-command does it already. --Stef
158`vc-bzr-do-command*'." 124 (process-connection-type nil))
159 (vc-bzr-std-process-invocation 125 (apply 'vc-do-command buffer okstatus vc-bzr-program
160 (apply 'vc-bzr-do-command* buffer okstatus vc-bzr-program 126 file bzr-command (append vc-bzr-program-args args))))
161 bzr-command (append vc-bzr-program-args args)))))
162 127
163 (t 128(unless (vc-bzr-at-least-version '(0 9))
164 ;; for older versions, we fall back to washing the log buffer 129 ;; For older versions, we fall back to washing the log buffer
165 ;; when all output has been gathered. 130 ;; when all output has been gathered.
166 (defun vc-bzr-command (command buffer okstatus file &rest args)
167 "Wrapper round `vc-do-command' using `vc-bzr-program' as COMMAND."
168 ;; Note: The ^Ms from the progress-indicator stuff that bzr prints
169 ;; on stderr cause auto-detection of a mac coding system on the
170 ;; stream for async output. bzr ought to be fixed to be able to
171 ;; suppress this. See also `vc-bzr-post-command-function'. (We
172 ;; can't sink the stderr output in `vc-do-command'.)
173 (apply 'vc-do-command buffer okstatus vc-bzr-program
174 file command (append vc-bzr-program-args args)))
175
176 (defun vc-bzr-command* (command buffer okstatus &rest args)
177 "Wrapper round `vc-bzr-do-command*' using `vc-bzr-program' as COMMAND."
178 (apply 'vc-bzr-do-command* buffer okstatus vc-bzr-program
179 command file (append vc-bzr-program-args args)))
180
181 (defun vc-bzr-post-command-function (command file flags) 131 (defun vc-bzr-post-command-function (command file flags)
182 "`vc-post-command-functions' function to remove progress messages." 132 "`vc-post-command-functions' function to remove progress messages."
183 ;; Note that using this requires that the vc command is run 133 ;; Note that using this requires that the vc command is run
@@ -196,29 +146,26 @@ First argument BZR-COMMAND is passed as the first optional argument to
196 (while (looking-at "read knit.*\n") 146 (while (looking-at "read knit.*\n")
197 (replace-match ""))))) 147 (replace-match "")))))
198 148
199 (add-hook 'vc-post-command-functions 'vc-bzr-post-command-function))) 149 (add-hook 'vc-post-command-functions 'vc-bzr-post-command-function))
150
151;;;###autoload
152(defconst vc-bzr-admin-dirname ".bzr") ; FIXME: "_bzr" on w32?
153
154;;;###autoload (defun vc-bzr-registered (file)
155;;;###autoload (if (vc-find-root file vc-bzr-admin-dirname)
156;;;###autoload (progn
157;;;###autoload (load "vc-bzr")
158;;;###autoload (vc-bzr-registered file))))
200 159
201(defun vc-bzr-bzr-dir (file) 160(defun vc-bzr-root-dir (file)
202 "Return the .bzr directory in the hierarchy above FILE. 161 "Return the root directory in the hierarchy above FILE.
203Return nil if there isn't one." 162Return nil if there isn't one."
204 (setq file (expand-file-name file)) 163 (vc-find-root file vc-bzr-admin-dirname))
205 (let ((dir (if (file-directory-p file)
206 file
207 (file-name-directory file)))
208 bzr)
209 (catch 'found
210 (while t
211 (setq bzr (expand-file-name ".bzr" dir)) ; fixme: "_bzr" on Doze??
212 (if (file-directory-p bzr)
213 (throw 'found (file-name-as-directory bzr)))
214 (if (equal "" (file-name-nondirectory (directory-file-name dir)))
215 (throw 'found nil)
216 (setq dir (file-name-directory (directory-file-name dir))))))))
217 164
218(defun vc-bzr-registered (file) 165(defun vc-bzr-registered (file)
219 "Return non-nil if FILE is registered with bzr." 166 "Return non-nil if FILE is registered with bzr."
220 (if (vc-bzr-bzr-dir file) ; short cut 167 (if (vc-bzr-root-dir file) ; Short cut.
221 (vc-bzr-state file))) ; expensive 168 (vc-bzr-state file))) ; Expensive.
222 169
223(defun vc-bzr-buffer-nonblank-p (&optional buffer) 170(defun vc-bzr-buffer-nonblank-p (&optional buffer)
224 "Return non-nil if BUFFER contains any non-blank characters." 171 "Return non-nil if BUFFER contains any non-blank characters."
@@ -298,11 +245,10 @@ COMMENT is ignored."
298 245
299;; Could run `bzr status' in the directory and see if it succeeds, but 246;; Could run `bzr status' in the directory and see if it succeeds, but
300;; that's relatively expensive. 247;; that's relatively expensive.
301(defun vc-bzr-responsible-p (file) 248(defalias 'vc-bzr-responsible-p 'vc-bzr-root-dir
302 "Return non-nil if FILE is (potentially) controlled by bzr. 249 "Return non-nil if FILE is (potentially) controlled by bzr.
303The criterion is that there is a `.bzr' directory in the same 250The criterion is that there is a `.bzr' directory in the same
304or a superior directory." 251or a superior directory.")
305 (vc-bzr-bzr-dir file))
306 252
307(defun vc-bzr-could-register (file) 253(defun vc-bzr-could-register (file)
308 "Return non-nil if FILE could be registered under bzr." 254 "Return non-nil if FILE could be registered under bzr."
@@ -342,43 +288,39 @@ EDITABLE is ignored."
342 (unless contents-done 288 (unless contents-done
343 (with-temp-buffer (vc-bzr-command "revert" t 'async file)))) 289 (with-temp-buffer (vc-bzr-command "revert" t 'async file))))
344 290
345(eval-when-compile 291(defvar log-view-message-re)
346 (defvar log-view-message-re) 292(defvar log-view-file-re)
347 (defvar log-view-file-re) 293(defvar log-view-font-lock-keywords)
348 (defvar log-view-font-lock-keywords) 294(defvar log-view-current-tag-function)
349 (defvar log-view-current-tag-function)) 295
350 296(define-derived-mode vc-bzr-log-view-mode log-view-mode "Bzr-Log-View"
351;; Grim hack to account for lack of an extension mechanism for 297 (remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack.
352;; log-view. Should be fixed in VC...
353(defun vc-bzr-view-log-function ()
354 "To be added to `log-view-mode-hook' to set variables for bzr output.
355Removes itself after running."
356 (remove-hook 'log-view-mode-hook 'vc-bzr-view-log-function)
357 (require 'add-log) 298 (require 'add-log)
358 ;; Don't have file markers, so use impossible regexp. 299 ;; Don't have file markers, so use impossible regexp.
359 (set (make-local-variable 'log-view-file-re) "\\'\\`") 300 (set (make-local-variable 'log-view-file-re) "\\'\\`")
360 (set (make-local-variable 'log-view-message-re) "^ *-+\n *\\(revno: [0-9]+\\|merged: .+\\)") 301 (set (make-local-variable 'log-view-message-re)
302 "^ *-+\n *\\(?:revno: \\([0-9]+\\)\\|merged: .+\\)")
361 (set (make-local-variable 'log-view-font-lock-keywords) 303 (set (make-local-variable 'log-view-font-lock-keywords)
362 `(("^ *committer: \ 304 ;; log-view-font-lock-keywords is careful to use the buffer-local
363\\([^<(]+?\\)[ ]*[(<]\\([A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+\\)[>)]" 305 ;; value of log-view-message-re only since Emacs-23.
364 nil nil 306 (append `((,log-view-message-re . 'log-view-message-face))
365 (1 'change-log-name-face nil t) 307 ;; log-view-font-lock-keywords
366 (2 'change-log-email-face nil t) 308 '(("^ *committer: \
367 (3 'change-log-email-face nil t)) 309\\([^<(]+?\\)[ ]*[(<]\\([[:alnum:]_.-]+@[[:alnum:]_.-]+\\)[>)]"
368 ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face)) 310 (1 'change-log-name)
369 (,log-view-message-re . 'log-view-message-face) 311 (2 'change-log-email))
370;; ("^ \\(.*\\)$" (1 'log-view-message-face)) 312 ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face))))))
371 )))
372 313
373(defun vc-bzr-print-log (file &optional buffer) ; get buffer arg in Emacs 22 314(defun vc-bzr-print-log (file &optional buffer) ; get buffer arg in Emacs 22
374 "Get bzr change log for FILE into specified BUFFER." 315 "Get bzr change log for FILE into specified BUFFER."
375 ;; Fixme: VC needs a hook to sort out the mode for the buffer, or at
376 ;; least set the regexps right.
377 ;; Fixme: This might need the locale fixing up if things like `revno' 316 ;; Fixme: This might need the locale fixing up if things like `revno'
378 ;; got localized, but certainly it shouldn't use LC_ALL=C. 317 ;; got localized, but certainly it shouldn't use LC_ALL=C.
379 ;; NB. Can't be async -- see `vc-bzr-post-command-function'. 318 ;; NB. Can't be async -- see `vc-bzr-post-command-function'.
380 (vc-bzr-command "log" buffer 0 file) 319 (vc-bzr-command "log" buffer 0 file)
381 (add-hook 'log-view-mode-hook 'vc-bzr-view-log-function)) 320 ;; FIXME: Until Emacs-23, VC was missing a hook to sort out the mode for
321 ;; the buffer, or at least set the regexps right.
322 (unless (fboundp 'vc-default-log-view-mode)
323 (add-hook 'log-view-mode-hook 'vc-bzr-log-view-mode)))
382 324
383(defun vc-bzr-show-log-entry (version) 325(defun vc-bzr-show-log-entry (version)
384 "Find entry for patch name VERSION in bzr change log buffer." 326 "Find entry for patch name VERSION in bzr change log buffer."
@@ -511,21 +453,22 @@ Return nil if current line isn't annotated."
511(defun vc-bzr-dir-state (dir &optional localp) 453(defun vc-bzr-dir-state (dir &optional localp)
512 "Find the VC state of all files in DIR. 454 "Find the VC state of all files in DIR.
513Optional argument LOCALP is always ignored." 455Optional argument LOCALP is always ignored."
514 (let (at-start bzr-root-directory current-bzr-state current-vc-state) 456 (let ((bzr-root-directory (vc-bzr-root dir))
515 ;; check that DIR is a bzr repository 457 (at-start t)
516 (set 'bzr-root-directory (vc-bzr-root dir)) 458 current-bzr-state current-vc-state)
517 (unless (string-match "^/" bzr-root-directory) 459 ;; Check that DIR is a bzr repository.
460 (unless (file-name-absolute-p bzr-root-directory)
518 (error "Cannot find bzr repository for directory `%s'" dir)) 461 (error "Cannot find bzr repository for directory `%s'" dir))
519 ;; `bzr ls --versioned' lists all versioned files; 462 ;; `bzr ls --versioned' lists all versioned files;
520 ;; assume they are up-to-date, unless we are given 463 ;; assume they are up-to-date, unless we are given
521 ;; evidence of the contrary. 464 ;; evidence of the contrary.
522 (set 'at-start t) 465 (setq at-start t)
523 (with-temp-buffer 466 (with-temp-buffer
524 (vc-bzr-command* "ls" t 0 "--versioned" "--non-recursive") 467 (vc-bzr-command "ls" t 0 nil "--versioned" "--non-recursive")
525 (goto-char (point-min)) 468 (goto-char (point-min))
526 (while (or at-start 469 (while (or at-start
527 (eq 0 (forward-line))) 470 (eq 0 (forward-line)))
528 (set 'at-start nil) 471 (setq at-start nil)
529 (let ((file (expand-file-name 472 (let ((file (expand-file-name
530 (buffer-substring-no-properties 473 (buffer-substring-no-properties
531 (line-beginning-position) (line-end-position)) 474 (line-beginning-position) (line-end-position))
@@ -535,26 +478,26 @@ Optional argument LOCALP is always ignored."
535 ;; mixes different SCMs in the same dir? 478 ;; mixes different SCMs in the same dir?
536 (vc-file-setprop file 'vc-backend 'BZR)))) 479 (vc-file-setprop file 'vc-backend 'BZR))))
537 ;; `bzr status' reports on added/modified/renamed and unknown/ignored files 480 ;; `bzr status' reports on added/modified/renamed and unknown/ignored files
538 (set 'at-start t) 481 (setq at-start t)
539 (with-temp-buffer 482 (with-temp-buffer
540 (vc-bzr-command "status" t 0 nil) 483 (vc-bzr-command "status" t 0 nil)
541 (goto-char (point-min)) 484 (goto-char (point-min))
542 (while (or at-start 485 (while (or at-start
543 (eq 0 (forward-line))) 486 (eq 0 (forward-line)))
544 (set 'at-start nil) 487 (setq at-start nil)
545 (cond 488 (cond
546 ((looking-at "^added") 489 ((looking-at "^added")
547 (set 'current-vc-state 'edited) 490 (setq current-vc-state 'edited)
548 (set 'current-bzr-state 'added)) 491 (setq current-bzr-state 'added))
549 ((looking-at "^modified") 492 ((looking-at "^modified")
550 (set 'current-vc-state 'edited) 493 (setq current-vc-state 'edited)
551 (set 'current-bzr-state 'modified)) 494 (setq current-bzr-state 'modified))
552 ((looking-at "^renamed") 495 ((looking-at "^renamed")
553 (set 'current-vc-state 'edited) 496 (setq current-vc-state 'edited)
554 (set 'current-bzr-state 'renamed)) 497 (setq current-bzr-state 'renamed))
555 ((looking-at "^\\(unknown\\|ignored\\)") 498 ((looking-at "^\\(unknown\\|ignored\\)")
556 (set 'current-vc-state nil) 499 (setq current-vc-state nil)
557 (set 'current-bzr-state 'not-versioned)) 500 (setq current-bzr-state 'not-versioned))
558 ((looking-at " ") 501 ((looking-at " ")
559 ;; file names are indented by two spaces 502 ;; file names are indented by two spaces
560 (when current-vc-state 503 (when current-vc-state
@@ -575,8 +518,8 @@ Optional argument LOCALP is always ignored."
575 (vc-file-setprop file 'vc-state nil)))) 518 (vc-file-setprop file 'vc-state nil))))
576 (t 519 (t
577 ;; skip this part of `bzr status' output 520 ;; skip this part of `bzr status' output
578 (set 'current-vc-state nil) 521 (setq current-vc-state nil)
579 (set 'current-bzr-state nil))))))) 522 (setq current-bzr-state nil)))))))
580 523
581(defun vc-bzr-dired-state-info (file) 524(defun vc-bzr-dired-state-info (file)
582 "Bzr-specific version of `vc-dired-state-info'." 525 "Bzr-specific version of `vc-dired-state-info'."