comparison lisp/vc-bzr.el @ 91327:606f2d163a64

Merge from emacs--devo--0 Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-312
author Miles Bader <miles@gnu.org>
date Wed, 09 Jan 2008 01:21:15 +0000
parents c938ab6810a4 107ccd98fa12
children
comparison
equal deleted inserted replaced
91326:b1a63d7fa09c 91327:606f2d163a64
1 ;;; vc-bzr.el --- VC backend for the bzr revision control system 1 ;;; vc-bzr.el --- VC backend for the bzr revision control system
2 2
3 ;; Copyright (C) 2006, 2007 Free Software Foundation, Inc. 3 ;; Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
4 4
5 ;; Author: Dave Love <fx@gnu.org>, Riccardo Murri <riccardo.murri@gmail.com> 5 ;; Author: Dave Love <fx@gnu.org>, Riccardo Murri <riccardo.murri@gmail.com>
6 ;; Keywords: tools 6 ;; Keywords: tools
7 ;; Created: Sept 2006 7 ;; Created: Sept 2006
8 ;; Version: 2007-09-05 8 ;; Version: 2008-01-04 (Bzr revno 25)
9 ;; URL: http://launchpad.net/vc-bzr 9 ;; URL: http://launchpad.net/vc-bzr
10 10
11 ;; This file is free software; you can redistribute it and/or modify 11 ;; This file is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by 12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option) 13 ;; the Free Software Foundation; either version 3, or (at your option)
24 ;; Boston, MA 02110-1301, USA. 24 ;; Boston, MA 02110-1301, USA.
25 25
26 26
27 ;;; Commentary: 27 ;;; Commentary:
28 28
29 ;; See <URL:http://bazaar-vcs.org/> concerning bzr. 29 ;; See <URL:http://bazaar-vcs.org/> concerning bzr. See
30 30 ;; <URL:http://launchpad.net/vc-bzr> for alternate development
31 ;; Load this library to register bzr support in VC. It covers basic VC 31 ;; branches of `vc-bzr'.
32 ;; functionality, but was only lightly exercised with a few Emacs/bzr 32
33 ;; version combinations, namely those current on the authors' PCs. 33 ;; Load this library to register bzr support in VC.
34 ;; See various Fixmes below.
35
36 34
37 ;; Known bugs 35 ;; Known bugs
38 ;; ========== 36 ;; ==========
39 37
40 ;; When edititing a symlink and *both* the symlink and its target 38 ;; When edititing a symlink and *both* the symlink and its target
64 62
65 (defcustom vc-bzr-program "bzr" 63 (defcustom vc-bzr-program "bzr"
66 "Name of the bzr command (excluding any arguments)." 64 "Name of the bzr command (excluding any arguments)."
67 :group 'vc-bzr 65 :group 'vc-bzr
68 :type 'string) 66 :type 'string)
69
70 ;; Fixme: there's probably no call for this.
71 (defcustom vc-bzr-program-args nil
72 "List of global arguments to pass to `vc-bzr-program'."
73 :group 'vc-bzr
74 :type '(repeat string))
75 67
76 (defcustom vc-bzr-diff-switches nil 68 (defcustom vc-bzr-diff-switches nil
77 "String/list of strings specifying extra switches for bzr diff under VC." 69 "String/list of strings specifying extra switches for bzr diff under VC."
78 :type '(choice (const :tag "None" nil) 70 :type '(choice (const :tag "None" nil)
79 (string :tag "Argument String") 71 (string :tag "Argument String")
80 (repeat :tag "Argument List" :value ("") string)) 72 (repeat :tag "Argument List" :value ("") string))
81 :group 'vc-bzr) 73 :group 'vc-bzr)
82 74
75 (defcustom vc-bzr-log-switches nil
76 "String/list of strings specifying extra switches for `bzr log' under VC."
77 :type '(choice (const :tag "None" nil)
78 (string :tag "Argument String")
79 (repeat :tag "Argument List" :value ("") string))
80 :group 'vc-bzr)
81
83 ;; since v0.9, bzr supports removing the progress indicators 82 ;; since v0.9, bzr supports removing the progress indicators
84 ;; by setting environment variable BZR_PROGRESS_BAR to "none". 83 ;; by setting environment variable BZR_PROGRESS_BAR to "none".
85 (defun vc-bzr-command (bzr-command buffer okstatus file-or-list &rest args) 84 (defun vc-bzr-command (bzr-command buffer okstatus file-or-list &rest args)
86 "Wrapper round `vc-do-command' using `vc-bzr-program' as COMMAND. 85 "Wrapper round `vc-do-command' using `vc-bzr-program' as COMMAND.
87 Invoke the bzr command adding `BZR_PROGRESS_BAR=none' to the environment." 86 Invoke the bzr command adding `BZR_PROGRESS_BAR=none' and
87 `LC_MESSAGES=C' to the environment."
88 (let ((process-environment 88 (let ((process-environment
89 (list* "BZR_PROGRESS_BAR=none" ; Suppress progress output (bzr >=0.9) 89 (list* "BZR_PROGRESS_BAR=none" ; Suppress progress output (bzr >=0.9)
90 "LC_ALL=C" ; Force English output 90 "LC_MESSAGES=C" ; Force English output
91 process-environment))) 91 process-environment)))
92 (apply 'vc-do-command buffer okstatus vc-bzr-program 92 (apply 'vc-do-command buffer okstatus vc-bzr-program
93 file-or-list bzr-command (append vc-bzr-program-args args)))) 93 file-or-list bzr-command args)))
94 94
95 95
96 ;;;###autoload 96 ;;;###autoload
97 (defconst vc-bzr-admin-dirname ".bzr" ; FIXME: "_bzr" on w32? 97 (defconst vc-bzr-admin-dirname ".bzr"
98 "Name of the directory containing Bzr repository status files.") 98 "Name of the directory containing Bzr repository status files.")
99 ;;;###autoload 99 ;;;###autoload
100 (defconst vc-bzr-admin-checkout-format-file 100 (defconst vc-bzr-admin-checkout-format-file
101 (concat vc-bzr-admin-dirname "/checkout/format")) 101 (concat vc-bzr-admin-dirname "/checkout/format"))
102 (defconst vc-bzr-admin-dirstate 102 (defconst vc-bzr-admin-dirstate
116 116
117 (defun vc-bzr-root (file) 117 (defun vc-bzr-root (file)
118 "Return the root directory of the bzr repository containing FILE." 118 "Return the root directory of the bzr repository containing FILE."
119 ;; Cache technique copied from vc-arch.el. 119 ;; Cache technique copied from vc-arch.el.
120 (or (vc-file-getprop file 'bzr-root) 120 (or (vc-file-getprop file 'bzr-root)
121 (vc-file-setprop 121 (let ((root (vc-find-root file vc-bzr-admin-checkout-format-file)))
122 file 'bzr-root 122 (when root (vc-file-setprop file 'bzr-root root)))))
123 (vc-find-root file vc-bzr-admin-checkout-format-file))))
124 123
125 (defun vc-bzr-registered (file) 124 (defun vc-bzr-registered (file)
126 "Return non-nil if FILE is registered with bzr. 125 "Return non-nil if FILE is registered with bzr.
127 126
128 For speed, this function tries first to parse Bzr internal file 127 For speed, this function tries first to parse Bzr internal file
161 160
162 (defun vc-bzr-file-name-relative (filename) 161 (defun vc-bzr-file-name-relative (filename)
163 "Return file name FILENAME stripped of the initial Bzr repository path." 162 "Return file name FILENAME stripped of the initial Bzr repository path."
164 (lexical-let* 163 (lexical-let*
165 ((filename* (expand-file-name filename)) 164 ((filename* (expand-file-name filename))
166 (rootdir (vc-bzr-root (file-name-directory filename*)))) 165 (rootdir (vc-bzr-root filename*)))
167 (when rootdir 166 (when rootdir
168 (file-relative-name filename* rootdir)))) 167 (file-relative-name filename* rootdir))))
169 168
170 ;; FIXME: Also get this in a non-registered sub-directory.
171 ;; It already works for me. -- Riccardo
172 (defun vc-bzr-status (file) 169 (defun vc-bzr-status (file)
173 "Return FILE status according to Bzr. 170 "Return FILE status according to Bzr.
174 Return value is a cons (STATUS . WARNING), where WARNING is a 171 Return value is a cons (STATUS . WARNING), where WARNING is a
175 string or nil, and STATUS is one of the symbols: `added', 172 string or nil, and STATUS is one of the symbols: `added',
176 `ignored', `kindchanged', `modified', `removed', `renamed', `unknown', 173 `ignored', `kindchanged', `modified', `removed', `renamed', `unknown',
195 (goto-char (point-min)) 192 (goto-char (point-min))
196 (when (re-search-forward 193 (when (re-search-forward
197 ;; bzr prints paths relative to the repository root. 194 ;; bzr prints paths relative to the repository root.
198 (concat "^\\(" vc-bzr-state-words "\\):[ \t\n]+" 195 (concat "^\\(" vc-bzr-state-words "\\):[ \t\n]+"
199 (regexp-quote (vc-bzr-file-name-relative file)) 196 (regexp-quote (vc-bzr-file-name-relative file))
200 (if (file-directory-p file) "/?" "") 197 ;; Bzr appends a '/' to directory names and
198 ;; '*' to executable files
199 (if (file-directory-p file) "/?" "\\*?")
201 "[ \t\n]*$") 200 "[ \t\n]*$")
202 nil t) 201 nil t)
203 (lexical-let ((statusword (match-string 1))) 202 (lexical-let ((statusword (match-string 1)))
204 ;; Erase the status text that matched. 203 ;; Erase the status text that matched.
205 (delete-region (match-beginning 0) (match-end 0)) 204 (delete-region (match-beginning 0) (match-end 0))
206 (setq status 205 (setq status
207 (and (equal ret 0) ; Seems redundant. --Stef 206 (intern (replace-regexp-in-string " " "" statusword)))))
208 (intern (replace-regexp-in-string " " ""
209 statusword))))))
210 (when status 207 (when status
211 (goto-char (point-min)) 208 (goto-char (point-min))
212 (skip-chars-forward " \n\t") ;Throw away spaces. 209 (skip-chars-forward " \n\t") ;Throw away spaces.
213 (cons status 210 (cons status
214 ;; "bzr" will output warnings and informational messages to 211 ;; "bzr" will output warnings and informational messages to
278 275
279 (defun vc-bzr-create-repo () 276 (defun vc-bzr-create-repo ()
280 "Create a new Bzr repository." 277 "Create a new Bzr repository."
281 (vc-bzr-command "init" nil 0 nil)) 278 (vc-bzr-command "init" nil 0 nil))
282 279
280 (defun vc-bzr-init-version (&optional file)
281 "Always return nil, as Bzr cannot register explicit versions."
282 nil)
283
283 (defun vc-bzr-register (files &optional rev comment) 284 (defun vc-bzr-register (files &optional rev comment)
284 "Register FILE under bzr. 285 "Register FILE under bzr.
285 Signal an error unless REV is nil. 286 Signal an error unless REV is nil.
286 COMMENT is ignored." 287 COMMENT is ignored."
287 (if rev (error "Can't register explicit revision with bzr")) 288 (if rev (error "Can't register explicit revision with bzr"))
306 (looking-at "added ")) 307 (looking-at "added "))
307 (error)))) 308 (error))))
308 309
309 (defun vc-bzr-unregister (file) 310 (defun vc-bzr-unregister (file)
310 "Unregister FILE from bzr." 311 "Unregister FILE from bzr."
311 (vc-bzr-command "remove" nil 0 file)) 312 (vc-bzr-command "remove" nil 0 file "--keep"))
312 313
313 (defun vc-bzr-checkin (files rev comment) 314 (defun vc-bzr-checkin (files rev comment)
314 "Check FILE in to bzr with log message COMMENT. 315 "Check FILE in to bzr with log message COMMENT.
315 REV non-nil gets an error." 316 REV non-nil gets an error."
316 (if rev (error "Can't check in a specific revision with bzr")) 317 (if rev (error "Can't check in a specific revision with bzr"))
317 (vc-bzr-command "commit" nil 0 files "-m" comment)) 318 (vc-bzr-command "commit" nil 0 files "-m" comment))
319
320 (defun vc-bzr-find-version (file rev buffer)
321 "Fetch version REV of file FILE and put it into BUFFER."
322 (with-current-buffer buffer
323 (if (and rev (stringp rev) (not (string= rev "")))
324 (vc-bzr-command "cat" t 0 file "-r" rev)
325 (vc-bzr-command "cat" t 0 file))))
318 326
319 (defun vc-bzr-checkout (file &optional editable rev destfile) 327 (defun vc-bzr-checkout (file &optional editable rev destfile)
320 "Checkout revision REV of FILE from bzr to DESTFILE. 328 "Checkout revision REV of FILE from bzr to DESTFILE.
321 EDITABLE is ignored." 329 EDITABLE is ignored."
322 (unless destfile 330 (unless destfile
323 (setq destfile (vc-version-backup-file-name file rev))) 331 (setq destfile (vc-version-backup-file-name file rev)))
324 (let ((coding-system-for-read 'binary) 332 (let ((coding-system-for-read 'binary)
325 (coding-system-for-write 'binary)) 333 (coding-system-for-write 'binary))
326 (with-temp-file destfile 334 (with-temp-file destfile
327 (if rev 335 (if (and rev (stringp rev) (not (string= rev "")))
328 (vc-bzr-command "cat" t 0 file "-r" rev) 336 (vc-bzr-command "cat" t 0 file "-r" rev)
329 (vc-bzr-command "cat" t 0 file))))) 337 (vc-bzr-command "cat" t 0 file)))))
330 338
331 (defun vc-bzr-revert (file &optional contents-done) 339 (defun vc-bzr-revert (file &optional contents-done)
332 (unless contents-done 340 (unless contents-done
355 (2 'change-log-email)) 363 (2 'change-log-email))
356 ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face)))))) 364 ("^ *timestamp: \\(.*\\)" (1 'change-log-date-face))))))
357 365
358 (defun vc-bzr-print-log (files &optional buffer) ; get buffer arg in Emacs 22 366 (defun vc-bzr-print-log (files &optional buffer) ; get buffer arg in Emacs 22
359 "Get bzr change log for FILES into specified BUFFER." 367 "Get bzr change log for FILES into specified BUFFER."
360 ;; Fixme: This might need the locale fixing up if things like `revno' 368 ;; FIXME: `vc-bzr-command' runs `bzr log' with `LC_MESSAGES=C', so
361 ;; got localized, but certainly it shouldn't use LC_ALL=C. 369 ;; the log display may not what the user wants - but I see no other
362 (vc-bzr-command "log" buffer 0 files) 370 ;; way of getting the above regexps working.
371 (apply 'vc-bzr-command "log" buffer 0 files
372 (if (stringp vc-bzr-log-switches)
373 (list vc-bzr-log-switches)
374 vc-bzr-log-switches))
363 ;; FIXME: Until Emacs-23, VC was missing a hook to sort out the mode for 375 ;; FIXME: Until Emacs-23, VC was missing a hook to sort out the mode for
364 ;; the buffer, or at least set the regexps right. 376 ;; the buffer, or at least set the regexps right.
365 (unless (fboundp 'vc-default-log-view-mode) 377 (unless (fboundp 'vc-default-log-view-mode)
366 (add-hook 'log-view-mode-hook 'vc-bzr-log-view-mode))) 378 (add-hook 'log-view-mode-hook 'vc-bzr-log-view-mode)))
367 379
375 387
376 (autoload 'vc-diff-switches-list "vc" nil nil t) 388 (autoload 'vc-diff-switches-list "vc" nil nil t)
377 389
378 (defun vc-bzr-diff (files &optional rev1 rev2 buffer) 390 (defun vc-bzr-diff (files &optional rev1 rev2 buffer)
379 "VC bzr backend for diff." 391 "VC bzr backend for diff."
380 (let ((working (vc-working-revision (if (consp files) (car files) files)))) 392 ;; `bzr diff' exits with code 1 if diff is non-empty
381 (if (and (equal rev1 working) (not rev2)) 393 (apply #'vc-bzr-command "diff" (or buffer "*vc-diff*") 1 files
382 (setq rev1 nil)) 394 "--diff-options" (mapconcat 'identity
383 (if (and (not rev1) rev2) 395 (vc-diff-switches-list bzr)
384 (setq rev1 working)) 396 " ")
385 ;; bzr diff produces condition code 1 for some reason. 397 (list "-r" (format "%s..%s"
386 (apply #'vc-bzr-command "diff" (or buffer "*vc-diff*") 1 files 398 (or rev1 "revno:-1")
387 "--diff-options" (mapconcat 'identity (vc-diff-switches-list bzr) 399 (or rev2 "")))))
388 " ")
389 (when rev1
390 (if rev2
391 (list "-r" (format "%s..%s" rev1 rev2))
392 (list "-r" rev1))))))
393
394 400
395 401
396 ;; FIXME: vc-{next,previous}-revision need fixing in vc.el to deal with 402 ;; FIXME: vc-{next,previous}-revision need fixing in vc.el to deal with
397 ;; straight integer revisions. 403 ;; straight integer revisions.
398 404
435 'mouse-face 'highlight)) 441 'mouse-face 'highlight))
436 (puthash key tag vc-bzr-annotation-table)) 442 (puthash key tag vc-bzr-annotation-table))
437 (replace-match "") 443 (replace-match "")
438 (insert tag " |"))))) 444 (insert tag " |")))))
439 445
440 ;; Definition from Emacs 22
441 (unless (fboundp 'vc-annotate-convert-time)
442 (defun vc-annotate-convert-time (time)
443 "Convert a time value to a floating-point number of days.
444 The argument TIME is a list as returned by `current-time' or
445 `encode-time', only the first two elements of that list are considered."
446 (/ (+ (* (float (car time)) (lsh 1 16)) (cadr time)) 24 3600)))
447
448 (defun vc-bzr-annotate-time () 446 (defun vc-bzr-annotate-time ()
449 (when (re-search-forward "^ *[0-9]+ |" nil t) 447 (when (re-search-forward "^ *[0-9]+ |" nil t)
450 (let ((prop (get-text-property (line-beginning-position) 'help-echo))) 448 (let ((prop (get-text-property (line-beginning-position) 'help-echo)))
451 (string-match "[0-9]+\\'" prop) 449 (string-match "[0-9]+\\'" prop)
452 (vc-annotate-convert-time 450 (vc-annotate-convert-time
461 Return nil if current line isn't annotated." 459 Return nil if current line isn't annotated."
462 (save-excursion 460 (save-excursion
463 (beginning-of-line) 461 (beginning-of-line)
464 (if (looking-at " *\\([0-9]+\\) | ") 462 (if (looking-at " *\\([0-9]+\\) | ")
465 (match-string-no-properties 1)))) 463 (match-string-no-properties 1))))
466
467 ;; Not needed for Emacs 22
468 (defun vc-bzr-annotate-difference (point)
469 (let ((next-time (vc-bzr-annotate-time)))
470 (if next-time
471 (- (vc-annotate-convert-time (current-time)) next-time))))
472 464
473 (defun vc-bzr-command-discarding-stderr (command &rest args) 465 (defun vc-bzr-command-discarding-stderr (command &rest args)
474 "Execute shell command COMMAND (with ARGS); return its output and exitcode. 466 "Execute shell command COMMAND (with ARGS); return its output and exitcode.
475 Return value is a cons (EXITCODE . OUTPUT), where EXITCODE is 467 Return value is a cons (EXITCODE . OUTPUT), where EXITCODE is
476 the (numerical) exit code of the process, and OUTPUT is a string 468 the (numerical) exit code of the process, and OUTPUT is a string
506 (setq at-start nil) 498 (setq at-start nil)
507 (let ((file (expand-file-name 499 (let ((file (expand-file-name
508 (buffer-substring-no-properties 500 (buffer-substring-no-properties
509 (line-beginning-position) (line-end-position)) 501 (line-beginning-position) (line-end-position))
510 bzr-root-directory))) 502 bzr-root-directory)))
503 ;; files are up-to-date unless they appear in the `bzr
504 ;; status' output below
511 (vc-file-setprop file 'vc-state 'up-to-date) 505 (vc-file-setprop file 'vc-state 'up-to-date)
512 ;; XXX: is this correct? what happens if one 506 ;; XXX: is this correct? what happens if one
513 ;; mixes different SCMs in the same dir? 507 ;; mixes different SCMs in the same dir?
508 ;; Anyway, we're looking at the output of `bzr ls --versioned',
509 ;; so we know these files are registered with Bzr.
514 (vc-file-setprop file 'vc-backend 'Bzr)))) 510 (vc-file-setprop file 'vc-backend 'Bzr))))
515 ;; `bzr status' reports on added/modified/renamed and unknown/ignored files 511 ;; `bzr status' reports on added/modified/renamed and unknown/ignored files
516 (setq at-start t) 512 (setq at-start t)
517 (with-temp-buffer 513 (with-temp-buffer
518 (vc-bzr-command "status" t 0 nil) 514 (vc-bzr-command "status" t 0 nil)
563 (setq current-bzr-state nil))))))) 559 (setq current-bzr-state nil)))))))
564 560
565 (defun vc-bzr-dired-state-info (file) 561 (defun vc-bzr-dired-state-info (file)
566 "Bzr-specific version of `vc-dired-state-info'." 562 "Bzr-specific version of `vc-dired-state-info'."
567 (if (eq 'edited (vc-state file)) 563 (if (eq 'edited (vc-state file))
568 (let ((bzr-state (vc-file-getprop file 'vc-bzr-state))) 564 (concat "(" (symbol-name (or (vc-file-getprop file 'vc-bzr-state)
569 (if bzr-state 565 'edited)) ")")
570 (concat "(" (symbol-name bzr-state) ")") 566 ;; else fall back to default vc.el representation
571 ;; else fall back to default vc representation 567 (vc-default-dired-state-info 'Bzr file)))
572 (vc-default-dired-state-info 'Bzr file)))))
573 568
574 (eval-after-load "vc" 569 (eval-after-load "vc"
575 '(add-to-list 'vc-directory-exclusion-list vc-bzr-admin-dirname t)) 570 '(add-to-list 'vc-directory-exclusion-list vc-bzr-admin-dirname t))
576 571
577 (provide 'vc-bzr) 572 (provide 'vc-bzr)