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