##// END OF EJS Templates
Merge with BOS
mpm@selenic.com -
r948:ffb06650 merge default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (590 lines changed) Show them Hide them
@@ -0,0 +1,590 b''
1 ;;; mercurial.el --- Emacs support for the Mercurial distributed SCM
2
3 ;; Copyright (C) 2005 Bryan O'Sullivan
4
5 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
6
7 ;; $Id$
8
9 ;; mercurial.el is free software; you can redistribute it and/or
10 ;; modify it under the terms of version 2 of the GNU General Public
11 ;; License as published by the Free Software Foundation.
12
13 ;; mercurial.el is distributed in the hope that it will be useful, but
14 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ;; General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with mercurial.el, GNU Emacs, or XEmacs; see the file COPYING
20 ;; (`C-h C-l'). If not, write to the Free Software Foundation, Inc.,
21 ;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 ;;; Commentary:
24
25 ;; This mode builds upon Emacs's VC mode to provide flexible
26 ;; integration with the Mercurial distributed SCM tool.
27
28 ;; To get going as quickly as possible, load mercurial.el into Emacs and
29 ;; type `C-c h h'; this runs hg-help-overview, which prints a helpful
30 ;; usage overview.
31
32 ;; Much of the inspiration for mercurial.el comes from Rajesh
33 ;; Vaidheeswarran's excellent p4.el, which does an admirably thorough
34 ;; job for the commercial Perforce SCM product. In fact, substantial
35 ;; chunks of code are adapted from p4.el.
36
37 ;; This code has been developed under XEmacs 21.5, and may will not
38 ;; work as well under GNU Emacs (albeit tested under 21.2). Patches
39 ;; to enhance the portability of this code, fix bugs, and add features
40 ;; are most welcome. You can clone a Mercurial repository for this
41 ;; package from http://www.serpentine.com/hg/hg-emacs
42
43 ;; Please send problem reports and suggestions to bos@serpentine.com.
44
45
46 ;;; Code:
47
48 (require 'advice)
49 (require 'cl)
50 (require 'diff-mode)
51 (require 'easymenu)
52 (require 'vc)
53
54
55 ;;; XEmacs has view-less, while GNU Emacs has view. Joy.
56
57 (condition-case nil
58 (require 'view-less)
59 (error nil))
60 (condition-case nil
61 (require 'view)
62 (error nil))
63
64
65 ;;; Variables accessible through the custom system.
66
67 (defgroup mercurial nil
68 "Mercurial distributed SCM."
69 :group 'tools)
70
71 (defcustom hg-binary
72 (dolist (path '("~/bin/hg"
73 "/usr/bin/hg"
74 "/usr/local/bin/hg"))
75 (when (file-executable-p path)
76 (return path)))
77 "The path to Mercurial's hg executable."
78 :type '(file :must-match t)
79 :group 'mercurial)
80
81 (defcustom hg-mode-hook nil
82 "Hook run when a buffer enters hg-mode."
83 :type 'sexp
84 :group 'mercurial)
85
86 (defcustom hg-global-prefix "\C-ch"
87 "The global prefix for Mercurial keymap bindings."
88 :type 'sexp
89 :group 'mercurial)
90
91 (defcustom hg-rev-completion-limit 100
92 "The maximum number of revisions that hg-read-rev will offer to complete.
93 This affects memory usage and performance when prompting for revisions
94 in a repository with a lot of history."
95 :type 'integer
96 :group 'mercurial)
97
98 (defcustom hg-log-limit 50
99 "The maximum number of revisions that hg-log will display."
100 :type 'integer
101 :group 'mercurial)
102
103
104 ;;; Other variables.
105
106 (defconst hg-running-xemacs (string-match "XEmacs" emacs-version)
107 "Is mercurial.el running under XEmacs?")
108
109 (defvar hg-mode nil
110 "Is this file managed by Mercurial?")
111 (make-variable-buffer-local 'hg-mode)
112 (put 'hg-mode 'permanent-local t)
113
114 (defvar hg-status nil)
115 (make-variable-buffer-local 'hg-status)
116 (put 'hg-status 'permanent-local t)
117
118 (defvar hg-output-buffer-name "*Hg*"
119 "The name to use for Mercurial output buffers.")
120
121 (defvar hg-file-history nil)
122 (defvar hg-rev-history nil)
123
124
125 ;;; hg-mode keymap.
126
127 (defvar hg-prefix-map
128 (let ((map (copy-keymap vc-prefix-map)))
129 (set-keymap-name map 'hg-prefix-map)
130 map)
131 "This keymap overrides some default vc-mode bindings.")
132 (fset 'hg-prefix-map hg-prefix-map)
133 (define-key hg-prefix-map "=" 'hg-diff)
134 (define-key hg-prefix-map "c" 'hg-undo)
135 (define-key hg-prefix-map "g" 'hg-annotate)
136 (define-key hg-prefix-map "l" 'hg-log)
137 (define-key hg-prefix-map "n" 'hg-commit-file)
138 ;; (define-key hg-prefix-map "r" 'hg-update)
139 (define-key hg-prefix-map "u" 'hg-revert-file)
140 (define-key hg-prefix-map "~" 'hg-version-other-window)
141
142 (defvar hg-mode-map (make-sparse-keymap))
143 (define-key hg-mode-map "\C-xv" 'hg-prefix-map)
144
145 (add-minor-mode 'hg-mode 'hg-mode hg-mode-map)
146
147
148 ;;; Global keymap.
149
150 (global-set-key "\C-xvi" 'hg-add)
151
152 (defvar hg-global-map (make-sparse-keymap))
153 (fset 'hg-global-map hg-global-map)
154 (global-set-key hg-global-prefix 'hg-global-map)
155 (define-key hg-global-map "," 'hg-incoming)
156 (define-key hg-global-map "." 'hg-outgoing)
157 (define-key hg-global-map "<" 'hg-pull)
158 (define-key hg-global-map "=" 'hg-diff)
159 (define-key hg-global-map ">" 'hg-push)
160 (define-key hg-global-map "?" 'hg-help-overview)
161 (define-key hg-global-map "A" 'hg-addremove)
162 (define-key hg-global-map "U" 'hg-revert)
163 (define-key hg-global-map "a" 'hg-add)
164 (define-key hg-global-map "c" 'hg-commit)
165 (define-key hg-global-map "f" 'hg-forget)
166 (define-key hg-global-map "h" 'hg-help-overview)
167 (define-key hg-global-map "i" 'hg-init)
168 (define-key hg-global-map "l" 'hg-log)
169 (define-key hg-global-map "r" 'hg-root)
170 (define-key hg-global-map "s" 'hg-status)
171 (define-key hg-global-map "u" 'hg-update)
172
173
174 ;;; View mode keymap.
175
176 (defvar hg-view-mode-map
177 (let ((map (copy-keymap (if (boundp 'view-minor-mode-map)
178 view-minor-mode-map
179 view-mode-map))))
180 (set-keymap-name map 'hg-view-mode-map)
181 map))
182 (fset 'hg-view-mode-map hg-view-mode-map)
183 (define-key hg-view-mode-map
184 (if hg-running-xemacs [button2] [mouse-2])
185 'hg-buffer-mouse-clicked)
186
187
188 ;;; Convenience functions.
189
190 (defun hg-binary ()
191 (if hg-binary
192 hg-binary
193 (error "No `hg' executable found!")))
194
195 (defun hg-replace-in-string (str regexp newtext &optional literal)
196 "Replace all matches in STR for REGEXP with NEWTEXT string.
197 Return the new string. Optional LITERAL non-nil means do a literal
198 replacement.
199
200 This function bridges yet another pointless impedance gap between
201 XEmacs and GNU Emacs."
202 (if (fboundp 'replace-in-string)
203 (replace-in-string str regexp newtext literal)
204 (replace-regexp-in-string regexp newtext str nil literal)))
205
206 (defun hg-chomp (str)
207 "Strip trailing newlines from a string."
208 (hg-replace-in-string str "[\r\n]+$" ""))
209
210 (defun hg-run-command (command &rest args)
211 "Run the shell command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT).
212 The list ARGS contains a list of arguments to pass to the command."
213 (let* (exit-code
214 (output
215 (with-output-to-string
216 (with-current-buffer
217 standard-output
218 (setq exit-code
219 (apply 'call-process command nil t nil args))))))
220 (cons exit-code output)))
221
222 (defun hg-run (command &rest args)
223 "Run the Mercurial command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT)."
224 (apply 'hg-run-command (hg-binary) command args))
225
226 (defun hg-run0 (command &rest args)
227 "Run the Mercurial command COMMAND, returning its output.
228 If the command does not exit with a zero status code, raise an error."
229 (let ((res (apply 'hg-run-command (hg-binary) command args)))
230 (if (not (eq (car res) 0))
231 (error "Mercurial command failed %s - exit code %s"
232 (cons command args)
233 (car res))
234 (cdr res))))
235
236 (defun hg-buffer-commands (pnt)
237 "Use the properties of a character to do something sensible."
238 (interactive "d")
239 (let ((rev (get-char-property pnt 'rev))
240 (file (get-char-property pnt 'file))
241 (date (get-char-property pnt 'date))
242 (user (get-char-property pnt 'user))
243 (host (get-char-property pnt 'host))
244 (prev-buf (current-buffer)))
245 (cond
246 (file
247 (find-file-other-window file))
248 (rev
249 (hg-diff hg-view-file-name rev rev prev-buf))
250 ((message "I don't know how to do that yet")))))
251
252 (defun hg-buffer-mouse-clicked (event)
253 "Translate the mouse clicks in a HG log buffer to character events.
254 These are then handed off to `hg-buffer-commands'.
255
256 Handle frickin' frackin' gratuitous event-related incompatibilities."
257 (interactive "e")
258 (if hg-running-xemacs
259 (progn
260 (select-window (event-window event))
261 (hg-buffer-commands (event-point event)))
262 (select-window (posn-window (event-end event)))
263 (hg-buffer-commands (posn-point (event-start event)))))
264
265 (unless (fboundp 'view-minor-mode)
266 (defun view-minor-mode (prev-buffer exit-func)
267 (view-mode)))
268
269 (defun hg-abbrev-file-name (file)
270 (if hg-running-xemacs
271 (abbreviate-file-name file t)
272 (abbreviate-file-name file)))
273
274 (defun hg-read-file-name (&optional prompt default)
275 "Read a file or directory name, or a pattern, to use with a command."
276 (let ((path (or default (buffer-file-name))))
277 (if (or (not path) current-prefix-arg)
278 (expand-file-name
279 (read-file-name (format "File, directory or pattern%s: "
280 (or prompt ""))
281 (and path (file-name-directory path))
282 nil nil
283 (and path (file-name-nondirectory path))
284 'hg-file-history))
285 path)))
286
287 (defun hg-read-rev (&optional prompt default)
288 "Read a revision or tag, offering completions."
289 (let ((rev (or default "tip")))
290 (if (or (not rev) current-prefix-arg)
291 (let ((revs (split-string (hg-chomp
292 (hg-run0 "-q" "log" "-r"
293 (format "-%d"
294 hg-rev-completion-limit)
295 "-r" "tip"))
296 "[\n:]")))
297 (dolist (line (split-string (hg-chomp (hg-run0 "tags")) "\n"))
298 (setq revs (cons (car (split-string line "\\s-")) revs)))
299 (completing-read (format "Revision%s (%s): "
300 (or prompt "")
301 (or default "tip"))
302 (map 'list 'cons revs revs)
303 nil
304 nil
305 nil
306 'hg-rev-history
307 (or default "tip")))
308 rev)))
309
310 ;;; View mode bits.
311
312 (defun hg-exit-view-mode (buf)
313 "Exit from hg-view-mode.
314 We delete the current window if entering hg-view-mode split the
315 current frame."
316 (when (and (eq buf (current-buffer))
317 (> (length (window-list)) 1))
318 (delete-window))
319 (when (buffer-live-p buf)
320 (kill-buffer buf)))
321
322 (defun hg-view-mode (prev-buffer &optional file-name)
323 (goto-char (point-min))
324 (set-buffer-modified-p nil)
325 (toggle-read-only t)
326 (view-minor-mode prev-buffer 'hg-exit-view-mode)
327 (use-local-map hg-view-mode-map)
328 (setq truncate-lines t)
329 (when file-name
330 (set (make-local-variable 'hg-view-file-name)
331 (hg-abbrev-file-name file-name))))
332
333 (defun hg-file-status (file)
334 "Return status of FILE, or nil if FILE does not exist or is unmanaged."
335 (let* ((s (hg-run "status" file))
336 (exit (car s))
337 (output (cdr s)))
338 (if (= exit 0)
339 (let ((state (assoc (substring output 0 (min (length output) 2))
340 '(("M " . modified)
341 ("A " . added)
342 ("R " . removed)))))
343 (if state
344 (cdr state)
345 'normal)))))
346
347 (defun hg-tip ()
348 (split-string (hg-chomp (hg-run0 "-q" "tip")) ":"))
349
350 (defmacro hg-view-output (args &rest body)
351 "Execute BODY in a clean buffer, then quickly display that buffer.
352 If the buffer contains one line, its contents are displayed in the
353 minibuffer. Otherwise, the buffer is displayed in view-mode.
354 ARGS is of the form (BUFFER-NAME &optional FILE), where BUFFER-NAME is
355 the name of the buffer to create, and FILE is the name of the file
356 being viewed."
357 (let ((prev-buf (gensym "prev-buf-"))
358 (v-b-name (car args))
359 (v-m-rest (cdr args)))
360 `(let ((view-buf-name ,v-b-name)
361 (,prev-buf (current-buffer)))
362 (get-buffer-create view-buf-name)
363 (kill-buffer view-buf-name)
364 (get-buffer-create view-buf-name)
365 (set-buffer view-buf-name)
366 (save-excursion
367 ,@body)
368 (case (count-lines (point-min) (point-max))
369 ((0)
370 (kill-buffer view-buf-name)
371 (message "(No output)"))
372 ((1)
373 (let ((msg (hg-chomp (buffer-substring (point-min) (point-max)))))
374 (kill-buffer view-buf-name)
375 (message "%s" msg)))
376 (t
377 (pop-to-buffer view-buf-name)
378 (hg-view-mode ,prev-buf ,@v-m-rest))))))
379
380 (put 'hg-view-output 'lisp-indent-function 1)
381
382 ;;; Hooks.
383
384 (defun hg-mode-line ()
385 (when (hg-root)
386 (let ((status (hg-file-status buffer-file-name)))
387 (setq hg-status status
388 hg-mode (and status (concat " Hg:"
389 (car (hg-tip))
390 (cdr (assq status
391 '((normal . "")
392 (removed . "r")
393 (added . "a")
394 (modified . "m")))))))
395 status)))
396
397 (defun hg-find-file-hook ()
398 (when (hg-mode-line)
399 (run-hooks 'hg-mode-hook)))
400
401 (add-hook 'find-file-hooks 'hg-find-file-hook)
402
403 (defun hg-after-save-hook ()
404 (let ((old-status hg-status))
405 (hg-mode-line)
406 (if (and (not old-status) hg-status)
407 (run-hooks 'hg-mode-hook))))
408
409 (add-hook 'after-save-hook 'hg-after-save-hook)
410
411
412 ;;; User interface functions.
413
414 (defun hg-help-overview ()
415 "This is an overview of the Mercurial SCM mode for Emacs.
416
417 You can find the source code, license (GPL v2), and credits for this
418 code by typing `M-x find-library mercurial RET'.
419
420 The Mercurial mode user interface is based on that of the older VC
421 mode, so if you're already familiar with VC, the same keybindings and
422 functions will generally work.
423
424 Below is a list of common SCM tasks, with the key bindings needed to
425 perform them, and the command names. This list is not exhaustive.
426
427 In the list below, `G/L' indicates whether a key binding is global (G)
428 or local (L). Global keybindings work on any file inside a Mercurial
429 repository. Local keybindings only apply to files under the control
430 of Mercurial. Many commands take a prefix argument.
431
432
433 SCM Task G/L Key Binding Command Name
434 -------- --- ----------- ------------
435 Help overview (what you are reading) G C-c h h hg-help-overview
436
437 Tell Mercurial to manage a file G C-c h a hg-add
438 Commit changes to current file only L C-x v n hg-commit
439 Undo changes to file since commit L C-x v u hg-revert-file
440
441 Diff file vs last checkin L C-x v = hg-diff
442
443 View file change history L C-x v l hg-log
444 View annotated file L C-x v a hg-annotate
445
446 Diff repo vs last checkin G C-c h = hg-diff
447 View status of files in repo G C-c h s hg-status
448 Commit all changes G C-c h c hg-commit
449
450 Undo all changes since last commit G C-c h U hg-revert
451 View repo change history G C-c h l hg-log
452
453 See changes that can be pulled G C-c h , hg-incoming
454 Pull changes G C-c h < hg-pull
455 Update working directory after pull G C-c h u hg-update
456 See changes that can be pushed G C-c h . hg-outgoing
457 Push changes G C-c h > hg-push"
458 (interactive)
459 (hg-view-output ("Mercurial Help Overview")
460 (insert (documentation 'hg-help-overview))))
461
462 (defun hg-add (path)
463 (interactive (list (hg-read-file-name " to add")))
464 (let ((buf (current-buffer))
465 (update (equal buffer-file-name path)))
466 (hg-view-output (hg-output-buffer-name)
467 (apply 'call-process (hg-binary) nil t nil (list "add" path)))
468 (when update
469 (with-current-buffer buf
470 (hg-mode-line)))))
471
472 (defun hg-addremove ()
473 (interactive)
474 (error "not implemented"))
475
476 (defun hg-annotate ()
477 (interactive)
478 (error "not implemented"))
479
480 (defun hg-commit ()
481 (interactive)
482 (error "not implemented"))
483
484 (defun hg-diff (path &optional rev1 rev2)
485 (interactive (list (hg-read-file-name " to diff")
486 (hg-read-rev " to start with")
487 (let ((rev2 (hg-read-rev " to end with" 'working-dir)))
488 (and (not (eq rev2 'working-dir)) rev2))))
489 (let ((a-path (hg-abbrev-file-name path)))
490 (hg-view-output ((if (equal rev1 rev2)
491 (format "Mercurial: Rev %s of %s" rev1 a-path)
492 (format "Mercurial: Rev %s to %s of %s"
493 rev1 (or rev2 "Current") a-path)))
494 (if rev2
495 (call-process (hg-binary) nil t nil "diff" "-r" rev1 "-r" rev2 path)
496 (call-process (hg-binary) nil t nil "diff" "-r" rev1 path))
497 (diff-mode)
498 (font-lock-fontify-buffer))))
499
500 (defun hg-forget (path)
501 (interactive (list (hg-read-file-name " to forget")))
502 (let ((buf (current-buffer))
503 (update (equal buffer-file-name path)))
504 (hg-view-output (hg-output-buffer-name)
505 (apply 'call-process (hg-binary) nil t nil (list "forget" path)))
506 (when update
507 (with-current-buffer buf
508 (hg-mode-line)))))
509
510 (defun hg-incoming ()
511 (interactive)
512 (error "not implemented"))
513
514 (defun hg-init ()
515 (interactive)
516 (error "not implemented"))
517
518 (defun hg-log (path &optional rev1 rev2)
519 (interactive (list (hg-read-file-name " to log")
520 (hg-read-rev " to start with" "-1")
521 (hg-read-rev " to end with" (format "-%d" hg-log-limit))))
522 (message "log %s %s" rev1 rev2)
523 (sit-for 1)
524 (let ((a-path (hg-abbrev-file-name path)))
525 (hg-view-output ((if (equal rev1 rev2)
526 (format "Mercurial: Rev %s of %s" rev1 a-path)
527 (format "Mercurial: Rev %s to %s of %s"
528 rev1 (or rev2 "Current") a-path)))
529 (call-process (hg-binary) nil t nil "log" "-r" rev1 "-r" rev2 path)
530 (diff-mode)
531 (font-lock-fontify-buffer))))
532
533 (defun hg-outgoing ()
534 (interactive)
535 (error "not implemented"))
536
537 (defun hg-pull ()
538 (interactive)
539 (error "not implemented"))
540
541 (defun hg-push ()
542 (interactive)
543 (error "not implemented"))
544
545 (defun hg-revert ()
546 (interactive)
547 (error "not implemented"))
548
549 (defun hg-revert-file ()
550 (interactive)
551 (error "not implemented"))
552
553 (defun hg-root (&optional path)
554 (interactive (list (hg-read-file-name)))
555 (let ((root (do ((prev nil dir)
556 (dir (file-name-directory (or path (buffer-file-name)))
557 (file-name-directory (directory-file-name dir))))
558 ((equal prev dir))
559 (when (file-directory-p (concat dir ".hg"))
560 (return dir)))))
561 (when (interactive-p)
562 (if root
563 (message "The root of this repository is `%s'." root)
564 (message "The path `%s' is not in a Mercurial repository."
565 (abbreviate-file-name path t))))
566 root))
567
568 (defun hg-status (path)
569 (interactive (list (hg-read-file-name " for status" (hg-root))))
570 (let ((root (hg-root)))
571 (hg-view-output (hg-output-buffer-name)
572 (apply 'call-process (hg-binary) nil t nil
573 (list "-C" root "status" path)))))
574
575 (defun hg-undo ()
576 (interactive)
577 (error "not implemented"))
578
579 (defun hg-version-other-window ()
580 (interactive)
581 (error "not implemented"))
582
583
584 (provide 'mercurial)
585
586
587 ;;; Local Variables:
588 ;;; mode: emacs-lisp
589 ;;; prompt-to-byte-compile: nil
590 ;;; end:
@@ -1,3 +1,4 b''
1 \.elc$
1 \.orig$
2 \.orig$
2 \.rej$
3 \.rej$
3 ~$
4 ~$
@@ -42,9 +42,10 b' def matchpats(repo, cwd, pats = [], opts'
42 def makewalk(repo, pats, opts, head = ''):
42 def makewalk(repo, pats, opts, head = ''):
43 cwd = repo.getcwd()
43 cwd = repo.getcwd()
44 files, matchfn = matchpats(repo, cwd, pats, opts, head)
44 files, matchfn = matchpats(repo, cwd, pats, opts, head)
45 exact = dict(zip(files, files))
45 def walk():
46 def walk():
46 for src, fn in repo.walk(files = files, match = matchfn):
47 for src, fn in repo.walk(files = files, match = matchfn):
47 yield src, fn, util.pathto(cwd, fn)
48 yield src, fn, util.pathto(cwd, fn), fn in exact
48 return files, matchfn, walk()
49 return files, matchfn, walk()
49
50
50 def walk(repo, pats, opts, head = ''):
51 def walk(repo, pats, opts, head = ''):
@@ -375,9 +376,8 b' def help_(ui, cmd=None):'
375 def add(ui, repo, *pats, **opts):
376 def add(ui, repo, *pats, **opts):
376 '''add the specified files on the next commit'''
377 '''add the specified files on the next commit'''
377 names = []
378 names = []
378 q = dict(zip(pats, pats))
379 for src, abs, rel, exact in walk(repo, pats, opts):
379 for src, abs, rel in walk(repo, pats, opts):
380 if exact:
380 if rel in q or abs in q:
381 names.append(abs)
381 names.append(abs)
382 elif repo.dirstate.state(abs) == '?':
382 elif repo.dirstate.state(abs) == '?':
383 ui.status('adding %s\n' % rel)
383 ui.status('adding %s\n' % rel)
@@ -386,15 +386,14 b' def add(ui, repo, *pats, **opts):'
386
386
387 def addremove(ui, repo, *pats, **opts):
387 def addremove(ui, repo, *pats, **opts):
388 """add all new files, delete all missing files"""
388 """add all new files, delete all missing files"""
389 q = dict(zip(pats, pats))
390 add, remove = [], []
389 add, remove = [], []
391 for src, abs, rel in walk(repo, pats, opts):
390 for src, abs, rel, exact in walk(repo, pats, opts):
392 if src == 'f' and repo.dirstate.state(abs) == '?':
391 if src == 'f' and repo.dirstate.state(abs) == '?':
393 add.append(abs)
392 add.append(abs)
394 if rel not in q: ui.status('adding ', rel, '\n')
393 if not exact: ui.status('adding ', rel, '\n')
395 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
394 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
396 remove.append(abs)
395 remove.append(abs)
397 if rel not in q: ui.status('removing ', rel, '\n')
396 if not exact: ui.status('removing ', rel, '\n')
398 repo.add(add)
397 repo.add(add)
399 repo.remove(remove)
398 repo.remove(remove)
400
399
@@ -432,7 +431,7 b' def annotate(ui, repo, *pats, **opts):'
432 node = repo.dirstate.parents()[0]
431 node = repo.dirstate.parents()[0]
433 change = repo.changelog.read(node)
432 change = repo.changelog.read(node)
434 mmap = repo.manifest.read(change[0])
433 mmap = repo.manifest.read(change[0])
435 for src, abs, rel in walk(repo, pats, opts):
434 for src, abs, rel, exact in walk(repo, pats, opts):
436 if abs not in mmap:
435 if abs not in mmap:
437 ui.warn("warning: %s is not in the repository!\n" % rel)
436 ui.warn("warning: %s is not in the repository!\n" % rel)
438 continue
437 continue
@@ -629,8 +628,12 b' def debugindexdot(ui, file_):'
629 def debugwalk(ui, repo, *pats, **opts):
628 def debugwalk(ui, repo, *pats, **opts):
630 items = list(walk(repo, pats, opts))
629 items = list(walk(repo, pats, opts))
631 if not items: return
630 if not items: return
632 fmt = '%%s %%-%ds %%s' % max([len(abs) for (src, abs, rel) in items])
631 fmt = '%%s %%-%ds %%-%ds %%s' % (
633 for i in items: print fmt % i
632 max([len(abs) for (src, abs, rel, exact) in items]),
633 max([len(rel) for (src, abs, rel, exact) in items]))
634 exactly = {True: 'exact', False: ''}
635 for src, abs, rel, exact in items:
636 print fmt % (src, abs, rel, exactly[exact])
634
637
635 def diff(ui, repo, *pats, **opts):
638 def diff(ui, repo, *pats, **opts):
636 """diff working directory (or selected files)"""
639 """diff working directory (or selected files)"""
@@ -645,7 +648,7 b' def diff(ui, repo, *pats, **opts):'
645 match = util.always
648 match = util.always
646 if pats:
649 if pats:
647 roots, match, results = makewalk(repo, pats, opts)
650 roots, match, results = makewalk(repo, pats, opts)
648 for src, abs, rel in results:
651 for src, abs, rel, exact in results:
649 files.append(abs)
652 files.append(abs)
650 dodiff(sys.stdout, ui, repo, files, *revs, **{'match': match})
653 dodiff(sys.stdout, ui, repo, files, *revs, **{'match': match})
651
654
@@ -687,12 +690,11 b' def export(ui, repo, *changesets, **opts'
687
690
688 def forget(ui, repo, *pats, **opts):
691 def forget(ui, repo, *pats, **opts):
689 """don't add the specified files on the next commit"""
692 """don't add the specified files on the next commit"""
690 q = dict(zip(pats, pats))
691 forget = []
693 forget = []
692 for src, abs, rel in walk(repo, pats, opts):
694 for src, abs, rel, exact in walk(repo, pats, opts):
693 if repo.dirstate.state(abs) == 'a':
695 if repo.dirstate.state(abs) == 'a':
694 forget.append(abs)
696 forget.append(abs)
695 if rel not in q: ui.status('forgetting ', rel, '\n')
697 if not exact: ui.status('forgetting ', rel, '\n')
696 repo.forget(forget)
698 repo.forget(forget)
697
699
698 def heads(ui, repo, **opts):
700 def heads(ui, repo, **opts):
@@ -809,7 +811,7 b' def locate(ui, repo, *pats, **opts):'
809 end = '\n'
811 end = '\n'
810 if opts['print0']: end = '\0'
812 if opts['print0']: end = '\0'
811
813
812 for src, abs, rel in walk(repo, pats, opts, '(?:.*/|)'):
814 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
813 if repo.dirstate.state(abs) == '?': continue
815 if repo.dirstate.state(abs) == '?': continue
814 if opts['fullpath']:
816 if opts['fullpath']:
815 ui.write(os.path.join(repo.root, abs), end)
817 ui.write(os.path.join(repo.root, abs), end)
@@ -1402,6 +1404,7 b" globalopts = [('v', 'verbose', None, 've"
1402 ('', 'debug', None, 'debug mode'),
1404 ('', 'debug', None, 'debug mode'),
1403 ('q', 'quiet', None, 'quiet mode'),
1405 ('q', 'quiet', None, 'quiet mode'),
1404 ('', 'profile', None, 'profile'),
1406 ('', 'profile', None, 'profile'),
1407 ('C', 'cwd', '', 'change working directory'),
1405 ('R', 'repository', "", 'repository root directory'),
1408 ('R', 'repository', "", 'repository root directory'),
1406 ('', 'traceback', None, 'print traceback on exception'),
1409 ('', 'traceback', None, 'print traceback on exception'),
1407 ('y', 'noninteractive', None, 'run non-interactively'),
1410 ('y', 'noninteractive', None, 'run non-interactively'),
@@ -1490,6 +1493,14 b' def dispatch(args):'
1490 help_(u, 'shortlist')
1493 help_(u, 'shortlist')
1491 sys.exit(1)
1494 sys.exit(1)
1492
1495
1496 if options['cwd']:
1497 try:
1498 os.chdir(options['cwd'])
1499 except OSError, inst:
1500 u = ui.ui()
1501 u.warn('abort: %s: %s\n' % (options['cwd'], inst.strerror))
1502 sys.exit(1)
1503
1493 if options["time"]:
1504 if options["time"]:
1494 def get_times():
1505 def get_times():
1495 t = os.times()
1506 t = os.times()
@@ -12,76 +12,76 b' adding mammals/skunk'
12 adding mammals/Procyonidae/cacomistle
12 adding mammals/Procyonidae/cacomistle
13 adding mammals/Procyonidae/coatimundi
13 adding mammals/Procyonidae/coatimundi
14 adding mammals/Procyonidae/raccoon
14 adding mammals/Procyonidae/raccoon
15 f fennel fennel
15 f fennel fennel
16 f fenugreek fenugreek
16 f fenugreek fenugreek
17 f fiddlehead fiddlehead
17 f fiddlehead fiddlehead
18 f glob:glob glob:glob
18 f glob:glob glob:glob
19 f beans/black beans/black
19 f beans/black beans/black
20 f beans/borlotti beans/borlotti
20 f beans/borlotti beans/borlotti
21 f beans/kidney beans/kidney
21 f beans/kidney beans/kidney
22 f beans/navy beans/navy
22 f beans/navy beans/navy
23 f beans/pinto beans/pinto
23 f beans/pinto beans/pinto
24 f beans/turtle beans/turtle
24 f beans/turtle beans/turtle
25 f mammals/skunk mammals/skunk
25 f mammals/skunk mammals/skunk
26 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
26 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
27 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
27 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
28 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
28 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
29 f mammals/skunk skunk
29 f mammals/skunk skunk
30 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
30 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
31 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
31 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
32 f mammals/Procyonidae/raccoon Procyonidae/raccoon
32 f mammals/Procyonidae/raccoon Procyonidae/raccoon
33 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
33 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
34 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
34 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
35 f mammals/Procyonidae/raccoon Procyonidae/raccoon
35 f mammals/Procyonidae/raccoon Procyonidae/raccoon
36 f mammals/Procyonidae/cacomistle cacomistle
36 f mammals/Procyonidae/cacomistle cacomistle
37 f mammals/Procyonidae/coatimundi coatimundi
37 f mammals/Procyonidae/coatimundi coatimundi
38 f mammals/Procyonidae/raccoon raccoon
38 f mammals/Procyonidae/raccoon raccoon
39 f mammals/skunk ../skunk
39 f mammals/skunk ../skunk
40 f mammals/Procyonidae/cacomistle cacomistle
40 f mammals/Procyonidae/cacomistle cacomistle
41 f mammals/Procyonidae/coatimundi coatimundi
41 f mammals/Procyonidae/coatimundi coatimundi
42 f mammals/Procyonidae/raccoon raccoon
42 f mammals/Procyonidae/raccoon raccoon
43 f beans/black ../beans/black
43 f beans/black ../beans/black
44 f beans/borlotti ../beans/borlotti
44 f beans/borlotti ../beans/borlotti
45 f beans/kidney ../beans/kidney
45 f beans/kidney ../beans/kidney
46 f beans/navy ../beans/navy
46 f beans/navy ../beans/navy
47 f beans/pinto ../beans/pinto
47 f beans/pinto ../beans/pinto
48 f beans/turtle ../beans/turtle
48 f beans/turtle ../beans/turtle
49 f mammals/skunk skunk
49 f mammals/skunk skunk
50 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
50 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
51 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
51 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
52 f mammals/Procyonidae/raccoon Procyonidae/raccoon
52 f mammals/Procyonidae/raccoon Procyonidae/raccoon
53 f beans/black beans/black
53 f beans/black beans/black
54 f beans/borlotti beans/borlotti
54 f beans/borlotti beans/borlotti
55 f beans/kidney beans/kidney
55 f beans/kidney beans/kidney
56 f beans/navy beans/navy
56 f beans/navy beans/navy
57 f beans/pinto beans/pinto
57 f beans/pinto beans/pinto
58 f beans/turtle beans/turtle
58 f beans/turtle beans/turtle
59 f beans/black beans/black
59 f beans/black beans/black
60 f beans/borlotti beans/borlotti
60 f beans/borlotti beans/borlotti
61 f mammals/skunk mammals/skunk
61 f mammals/skunk mammals/skunk
62 f mammals/skunk mammals/skunk
62 f mammals/skunk mammals/skunk
63 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
63 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
64 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
64 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
65 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
65 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
66 abort: .. not under repository root
66 abort: .. not under repository root
67 abort: beans/../.. not under repository root
67 abort: beans/../.. not under repository root
68 f fennel fennel
68 f fennel fennel
69 f fenugreek fenugreek
69 f fenugreek fenugreek
70 f fiddlehead fiddlehead
70 f fiddlehead fiddlehead
71 f glob:glob glob:glob
71 f glob:glob glob:glob
72 f fenugreek fenugreek
72 f fenugreek fenugreek
73 f glob:glob glob:glob
73 f glob:glob glob:glob
74 f beans/black beans/black
74 f beans/black beans/black
75 f mammals/skunk mammals/skunk
75 f mammals/skunk mammals/skunk
76 f beans/black beans/black
76 f beans/black beans/black
77 f beans/black beans/black
77 f beans/black beans/black
78 f beans/borlotti beans/borlotti
78 f beans/borlotti beans/borlotti
79 f beans/kidney beans/kidney
79 f beans/kidney beans/kidney
80 f beans/navy beans/navy
80 f beans/navy beans/navy
81 f beans/pinto beans/pinto
81 f beans/pinto beans/pinto
82 f beans/turtle beans/turtle
82 f beans/turtle beans/turtle
83 NOEXIST: No such file or directory
83 NOEXIST: No such file or directory
84 fifo: unsupported file type (type is fifo)
84 fifo: unsupported file type (type is fifo)
85 m fenugreek fenugreek
85 m fenugreek fenugreek exact
86 m fenugreek fenugreek
86 m fenugreek fenugreek exact
87 f new new
87 f new new exact
General Comments 0
You need to be logged in to leave comments. Login now