merge with hg-churn
authorBenoit Boissinot <benoit.boissinot@ens-lyon.org>
Mon, 04 Sep 2006 23:27:14 +0200
changeset 3053 60094899dfc9
parent 3039 77637938d43d (diff)
parent 3052 51083c31db04 (current diff)
child 3058 11e3396e3a2b
merge with hg-churn
--- a/.hgignore	Mon Sep 04 16:02:25 2006 -0400
+++ b/.hgignore	Mon Sep 04 23:27:14 2006 +0200
@@ -21,6 +21,7 @@
 MANIFEST
 patches
 mercurial/__version__.py
+.DS_Store
 
 syntax: regexp
 ^\.pc/
--- a/contrib/mercurial.el	Mon Sep 04 16:02:25 2006 -0400
+++ b/contrib/mercurial.el	Mon Sep 04 23:27:14 2006 +0200
@@ -1,6 +1,6 @@
 ;;; mercurial.el --- Emacs support for the Mercurial distributed SCM
 
-;; Copyright (C) 2005 Bryan O'Sullivan
+;; Copyright (C) 2005, 2006 Bryan O'Sullivan
 
 ;; Author: Bryan O'Sullivan <bos@serpentine.com>
 
@@ -289,7 +289,7 @@
 
 (defsubst hg-chomp (str)
   "Strip trailing newlines from a string."
-  (hg-replace-in-string str "[\r\n]+\'" ""))
+  (hg-replace-in-string str "[\r\n]+\\'" ""))
 
 (defun hg-run-command (command &rest args)
   "Run the shell command COMMAND, returning (EXIT-CODE . COMMAND-OUTPUT).
@@ -502,6 +502,43 @@
 			     (or default "tip")))
 	rev))))
 
+(defun hg-parents-for-mode-line (root)
+  "Format the parents of the working directory for the mode line."
+  (let ((parents (split-string (hg-chomp
+				(hg-run0 "--cwd" root "parents" "--template"
+					 "{rev}\n")) "\n")))
+    (mapconcat 'identity parents "+")))
+
+(defun hg-buffers-visiting-repo (&optional path)
+  "Return a list of buffers visiting the repository containing PATH."
+  (let ((root-name (hg-root (or path (buffer-file-name))))
+	bufs)
+    (save-excursion
+      (dolist (buf (buffer-list) bufs)
+	(set-buffer buf)
+	(let ((name (buffer-file-name)))
+	  (when (and hg-status name (equal (hg-root name) root-name))
+	    (setq bufs (cons buf bufs))))))))
+
+(defun hg-update-mode-lines (path)
+  "Update the mode lines of all buffers visiting the same repository as PATH."
+  (let* ((root (hg-root path))
+	 (parents (hg-parents-for-mode-line root)))
+    (save-excursion
+      (dolist (info (hg-path-status
+		     root
+		     (mapcar
+		      (function
+		       (lambda (buf)
+			 (substring (buffer-file-name buf) (length root))))
+		      (hg-buffers-visiting-repo root))))
+	(let* ((name (car info))
+	       (status (cdr info))
+	       (buf (find-buffer-visiting (concat root name))))
+	  (when buf
+	    (set-buffer buf)
+	    (hg-mode-line-internal status parents)))))))
+  
 (defmacro hg-do-across-repo (path &rest body)
   (let ((root-name (gensym "root-"))
 	(buf-name (gensym "buf-")))
@@ -548,13 +585,31 @@
 			    '(("M " . modified)
 			      ("A " . added)
 			      ("R " . removed)
+			      ("! " . deleted)
 			      ("? " . nil)))))
 	  (if state
 	      (cdr state)
 	    'normal)))))
 
-(defun hg-tip ()
-  (split-string (hg-chomp (hg-run0 "-q" "tip")) ":"))
+(defun hg-path-status (root paths)
+  "Return status of PATHS in repo ROOT as an alist.
+Each entry is a pair (FILE-NAME . STATUS)."
+  (let ((s (apply 'hg-run "--cwd" root "status" "-marduc" paths))
+	result)
+    (dolist (entry (split-string (hg-chomp (cdr s)) "\n") (nreverse result))
+      (let (state name)
+	(if (equal (substring entry 1 2) " ")
+	    (setq state (cdr (assoc (substring entry 0 2)
+				    '(("M " . modified)
+				      ("A " . added)
+				      ("R " . removed)
+				      ("! " . deleted)
+				      ("C " . normal)
+				      ("I " . ignored)
+				      ("? " . nil))))
+		  name (substring entry 2))
+	  (setq name (substring entry 0 (search ": " entry :from-end t))))
+	(setq result (cons (cons name state) result))))))
 
 (defmacro hg-view-output (args &rest body)
   "Execute BODY in a clean buffer, then quickly display that buffer.
@@ -589,7 +644,7 @@
 
 (put 'hg-view-output 'lisp-indent-function 1)
 
-;;; Context save and restore across revert.
+;;; Context save and restore across revert and other operations.
 
 (defun hg-position-context (pos)
   "Return information to help find the given position again."
@@ -631,22 +686,28 @@
 
 ;;; Hooks.
 
+(defun hg-mode-line-internal (status parents)
+  (setq hg-status status
+	hg-mode (and status (concat " Hg:"
+				    parents
+				    (cdr (assq status
+					       '((normal . "")
+						 (removed . "r")
+						 (added . "a")
+						 (deleted . "!")
+						 (modified . "m"))))))))
+  
 (defun hg-mode-line (&optional force)
   "Update the modeline with the current status of a file.
 An update occurs if optional argument FORCE is non-nil,
 hg-update-modeline is non-nil, or we have not yet checked the state of
 the file."
-  (when (and (hg-root) (or force hg-update-modeline (not hg-mode)))
-    (let ((status (hg-file-status buffer-file-name)))
-      (setq hg-status status
-	    hg-mode (and status (concat " Hg:"
-					(car (hg-tip))
-					(cdr (assq status
-						   '((normal . "")
-						     (removed . "r")
-						     (added . "a")
-						     (modified . "m")))))))
-      status)))
+  (let ((root (hg-root)))
+    (when (and root (or force hg-update-modeline (not hg-mode)))
+      (let ((status (hg-file-status buffer-file-name))
+	    (parents (hg-parents-for-mode-line root)))
+	(hg-mode-line-internal status parents)
+	status))))
 
 (defun hg-mode (&optional toggle)
   "Minor mode for Mercurial distributed SCM integration.
@@ -724,6 +785,13 @@
 		 default-directory)
 	(cd hg-root-dir)))))
 
+(defun hg-fix-paths ()
+  "Fix paths reported by some Mercurial commands."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward " \\.\\.." nil t)
+      (replace-match " " nil nil))))
+
 (defun hg-add (path)
   "Add PATH to the Mercurial repository on the next commit.
 With a prefix argument, prompt for the path to add."
@@ -732,9 +800,8 @@
 	(update (equal buffer-file-name path)))
     (hg-view-output (hg-output-buffer-name)
       (apply 'call-process (hg-binary) nil t nil (list "add" path))
-      ;; "hg add" shows pathes relative NOT TO ROOT BUT TO REPOSITORY
-      (replace-regexp " \\.\\.." " " nil 0 (buffer-size))
-      (goto-char 0)
+      (hg-fix-paths)
+      (goto-char (point-min))
       (cd (hg-root path)))
     (when update
       (unless vc-make-backup-files
@@ -820,8 +887,7 @@
       (let ((buf hg-prev-buffer))
 	(kill-buffer nil)
 	(switch-to-buffer buf))
-      (hg-do-across-repo root
-	(hg-mode-line)))))
+      (hg-update-mode-lines root))))
 
 (defun hg-commit-mode ()
   "Mode for describing a commit of changes to a Mercurial repository.
@@ -973,8 +1039,8 @@
     (hg-view-output (hg-output-buffer-name)
       (apply 'call-process (hg-binary) nil t nil (list "forget" path))
       ;; "hg forget" shows pathes relative NOT TO ROOT BUT TO REPOSITORY
-      (replace-regexp " \\.\\.." " " nil 0 (buffer-size))
-      (goto-char 0)
+      (hg-fix-paths)
+      (goto-char (point-min))
       (cd (hg-root path)))
     (when update
       (with-current-buffer buf
@@ -1148,6 +1214,21 @@
 	root)
     hg-root))
 
+(defun hg-cwd (&optional path)
+  "Return the current directory of PATH within the repository."
+  (do ((stack nil (cons (file-name-nondirectory
+			 (directory-file-name dir))
+			stack))
+       (prev nil dir)
+       (dir (file-name-directory (or path buffer-file-name
+				     (expand-file-name default-directory)))
+	    (file-name-directory (directory-file-name dir))))
+      ((equal prev dir))
+    (when (file-directory-p (concat dir ".hg"))
+      (let ((cwd (mapconcat 'identity stack "/")))
+	(unless (equal cwd "")
+	  (return (file-name-as-directory cwd)))))))
+
 (defun hg-status (path)
   "Print revision control status of a file or directory.
 With prefix argument, prompt for the path to give status for.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/mq.el	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,281 @@
+;;; mq.el --- Emacs support for Mercurial Queues
+
+;; Copyright (C) 2006 Bryan O'Sullivan
+
+;; Author: Bryan O'Sullivan <bos@serpentine.com>
+
+;; mq.el is free software; you can redistribute it and/or modify it
+;; under the terms of version 2 of the GNU General Public License as
+;; published by the Free Software Foundation.
+
+;; mq.el is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
+;; C-l').  If not, write to the Free Software Foundation, Inc., 59
+;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+(require 'mercurial)
+
+
+(defcustom mq-mode-hook nil
+  "Hook run when a buffer enters mq-mode."
+  :type 'sexp
+  :group 'mercurial)
+
+(defcustom mq-global-prefix "\C-cq"
+  "The global prefix for Mercurial Queues keymap bindings."
+  :type 'sexp
+  :group 'mercurial)
+
+(defcustom mq-edit-mode-hook nil
+  "Hook run after a buffer is populated to edit a patch description."
+  :type 'sexp
+  :group 'mercurial)
+
+
+;;; Internal variables.
+
+(defvar mq-patch-history nil)
+
+(defvar mq-prev-buffer nil)
+(make-variable-buffer-local 'mq-prev-buffer)
+(put 'mq-prev-buffer 'permanent-local t)
+
+
+;;; Global keymap.
+
+(defvar mq-global-map (make-sparse-keymap))
+(fset 'mq-global-map mq-global-map)
+(global-set-key mq-global-prefix 'mq-global-map)
+(define-key mq-global-map "." 'mq-push)
+(define-key mq-global-map ">" 'mq-push-all)
+(define-key mq-global-map "," 'mq-pop)
+(define-key mq-global-map "<" 'mq-pop-all)
+(define-key mq-global-map "r" 'mq-refresh)
+(define-key mq-global-map "e" 'mq-refresh-edit)
+(define-key mq-global-map "n" 'mq-next)
+(define-key mq-global-map "p" 'mq-previous)
+(define-key mq-global-map "t" 'mq-top)
+
+
+;;; Refresh edit mode keymap.
+
+(defvar mq-edit-mode-map (make-sparse-keymap))
+(define-key mq-edit-mode-map "\C-c\C-c" 'mq-edit-finish)
+(define-key mq-edit-mode-map "\C-c\C-k" 'mq-edit-kill)
+
+
+;;; Helper functions.
+
+(defun mq-read-patch-name (&optional source prompt)
+  "Read a patch name to use with a command.
+May return nil, meaning \"use the default\"."
+  (let ((patches (split-string
+		  (hg-chomp (hg-run0 (or source "qseries"))) "\n")))
+    (when current-prefix-arg
+      (completing-read (format "Patch%s: " (or prompt ""))
+		       (map 'list 'cons patches patches)
+		       nil
+		       nil
+		       nil
+		       'mq-patch-history))))
+
+(defun mq-refresh-buffers (root)
+  (save-excursion
+    (dolist (buf (hg-buffers-visiting-repo root))
+      (when (not (verify-visited-file-modtime buf))
+	(set-buffer buf)
+	(let ((ctx (hg-buffer-context)))
+	  (message "Refreshing %s..." (buffer-name))
+	  (revert-buffer t t t)
+	  (hg-restore-context ctx)
+	  (message "Refreshing %s...done" (buffer-name))))))
+  (hg-update-mode-lines root))
+
+(defun mq-last-line ()
+  (goto-char (point-max))
+  (beginning-of-line)
+  (when (looking-at "^$")
+    (forward-line -1))
+  (let ((bol (point)))
+    (end-of-line)
+    (let ((line (buffer-substring bol (point))))
+      (when (> (length line) 0)
+	line))))
+  
+(defun mq-push (&optional patch)
+  "Push patches until PATCH is reached.
+If PATCH is nil, push at most one patch."
+  (interactive (list (mq-read-patch-name "qunapplied" " to push")))
+  (let ((root (hg-root))
+	(prev-buf (current-buffer))
+	last-line ok)
+    (unless root
+      (error "Cannot push outside a repository!"))
+    (hg-sync-buffers root)
+    (let ((buf-name (format "MQ: Push %s" (or patch "next patch"))))
+      (kill-buffer (get-buffer-create buf-name))
+      (split-window-vertically)
+      (other-window 1)
+      (switch-to-buffer (get-buffer-create buf-name))
+      (cd root)
+      (message "Pushing...")
+      (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpush"
+			   (if patch (list patch))))
+	    last-line (mq-last-line))
+      (let ((lines (count-lines (point-min) (point-max))))
+	(if (and (equal lines 2) (string-match "Now at:" last-line))
+	    (progn
+	      (kill-buffer (current-buffer))
+	      (delete-window))
+	  (hg-view-mode prev-buf))))
+    (mq-refresh-buffers root)
+    (sit-for 0)
+    (when last-line
+      (if ok
+	  (message "Pushing... %s" last-line)
+	(error "Pushing... %s" last-line)))))
+  
+(defun mq-push-all ()
+  "Push patches until all are applied."
+  (interactive)
+  (mq-push "-a"))
+
+(defun mq-pop (&optional patch)
+  "Pop patches until PATCH is reached.
+If PATCH is nil, pop at most one patch."
+  (interactive (list (mq-read-patch-name "qapplied" " to pop to")))
+  (let ((root (hg-root))
+	last-line ok)
+    (unless root
+      (error "Cannot pop outside a repository!"))
+    (hg-sync-buffers root)
+    (set-buffer (generate-new-buffer "qpop"))
+    (cd root)
+    (message "Popping...")
+    (setq ok (= 0 (apply 'call-process (hg-binary) nil t t "qpop"
+			 (if patch (list patch))))
+	  last-line (mq-last-line))
+    (kill-buffer (current-buffer))
+    (mq-refresh-buffers root)
+    (sit-for 0)
+    (when last-line
+      (if ok
+	  (message "Popping... %s" last-line)
+	(error "Popping... %s" last-line)))))
+  
+(defun mq-pop-all ()
+  "Push patches until none are applied."
+  (interactive)
+  (mq-pop "-a"))
+
+(defun mq-refresh-internal (root &rest args)
+  (hg-sync-buffers root)
+  (let ((patch (mq-patch-info "qtop")))
+    (message "Refreshing %s..." patch)
+    (let ((ret (apply 'hg-run "qrefresh" args)))
+      (if (equal (car ret) 0)
+	  (message "Refreshing %s... done." patch)
+	(error "Refreshing %s... %s" patch (hg-chomp (cdr ret)))))))
+
+(defun mq-refresh ()
+  "Refresh the topmost applied patch."
+  (interactive)
+  (let ((root (hg-root)))
+    (unless root
+      (error "Cannot refresh outside of a repository!"))
+  (mq-refresh-internal root)))
+
+(defun mq-patch-info (cmd &optional msg)
+  (let* ((ret (hg-run cmd))
+	 (info (hg-chomp (cdr ret))))
+    (if (equal (car ret) 0)
+	(if msg
+	    (message "%s patch: %s" msg info)
+	  info)
+      (error "%s" info))))
+
+(defun mq-top ()
+  "Print the name of the topmost applied patch."
+  (interactive)
+  (mq-patch-info "qtop" "Top"))
+
+(defun mq-next ()
+  "Print the name of the next patch to be pushed."
+  (interactive)
+  (mq-patch-info "qnext" "Next"))
+
+(defun mq-previous ()
+  "Print the name of the first patch below the topmost applied patch.
+This would become the active patch if popped to."
+  (interactive)
+  (mq-patch-info "qprev" "Previous"))
+
+(defun mq-edit-finish ()
+  "Finish editing the description of this patch, and refresh the patch."
+  (interactive)
+  (unless (equal (mq-patch-info "qtop") mq-top)
+    (error "Topmost patch has changed!"))
+  (hg-sync-buffers hg-root)
+  (mq-refresh-internal hg-root "-m" (buffer-substring (point-min) (point-max)))
+  (let ((buf mq-prev-buffer))
+    (kill-buffer nil)
+    (switch-to-buffer buf)))
+  
+(defun mq-edit-kill ()
+  "Kill the edit currently being prepared."
+  (interactive)
+  (when (or (not (buffer-modified-p)) (y-or-n-p "Really kill this edit? "))
+    (let ((buf mq-prev-buffer))
+      (kill-buffer nil)
+      (switch-to-buffer buf))))
+
+(defun mq-edit-mode ()
+  "Mode for editing the description of a patch.
+
+Key bindings
+------------
+\\[mq-edit-finish]	use this description
+\\[mq-edit-kill]	abandon this description"
+  (interactive)
+  (use-local-map mq-edit-mode-map)
+  (set-syntax-table text-mode-syntax-table)
+  (setq local-abbrev-table text-mode-abbrev-table
+	major-mode 'mq-edit-mode
+	mode-name "MQ-Edit")
+  (set-buffer-modified-p nil)
+  (setq buffer-undo-list nil)
+  (run-hooks 'text-mode-hook 'mq-edit-mode-hook))
+  
+(defun mq-refresh-edit ()
+  "Refresh the topmost applied patch, editing the patch description."
+  (interactive)
+  (while mq-prev-buffer
+    (set-buffer mq-prev-buffer))
+  (let ((root (hg-root))
+	(prev-buffer (current-buffer))
+	(patch (mq-patch-info "qtop")))
+    (hg-sync-buffers root)
+    (let ((buf-name (format "*MQ: Edit description of %s*" patch)))
+      (switch-to-buffer (get-buffer-create buf-name))
+      (when (= (point-min) (point-max))
+	(set (make-local-variable 'hg-root) root)
+	(set (make-local-variable 'mq-top) patch)
+	(setq mq-prev-buffer prev-buffer)
+	(insert (hg-run0 "qheader"))
+	(goto-char (point-min)))
+      (mq-edit-mode)
+      (cd root)))
+  (message "Type `C-c C-c' to finish editing and refresh the patch."))
+
+
+(provide 'mq)
+
+
+;;; Local Variables:
+;;; prompt-to-byte-compile: nil
+;;; end:
--- a/doc/hg.1.txt	Mon Sep 04 16:02:25 2006 -0400
+++ b/doc/hg.1.txt	Mon Sep 04 23:27:14 2006 +0200
@@ -193,6 +193,10 @@
     global /etc/mercurial/hgrc configuration.  See hgrc(5) for details of
     the contents and format of these files.
 
+Some commands (e.g. revert) produce backup files ending in .orig, if
+the .orig file already exists and is not tracked by Mercurial, it
+will be overwritten.
+
 BUGS
 ----
 Probably lots, please post them to the mailing list (See Resources below)
--- a/doc/hgrc.5.txt	Mon Sep 04 16:02:25 2006 -0400
+++ b/doc/hgrc.5.txt	Mon Sep 04 23:27:14 2006 +0200
@@ -50,6 +50,8 @@
     particular repository.  This file is not version-controlled, and
     will not get transferred during a "clone" operation.  Options in
     this file override options in all other configuration files.
+    On Unix, this file is only read if it belongs to a trusted user
+    or to a trusted group.
 
 SYNTAX
 ------
@@ -133,6 +135,21 @@
     # them to the working dir
     **.txt = tempfile: unix2dos -n INFILE OUTFILE
 
+defaults::
+  Use the [defaults] section to define command defaults, i.e. the 
+  default options/arguments to pass to the specified commands.
+  
+  The following example makes 'hg log' run in verbose mode, and
+  'hg status' show only the modified files, by default.
+  
+    [defaults]
+    log = -v
+    status = -m
+  
+  The actual commands, instead of their aliases, must be used when 
+  defining command defaults. The command defaults will also be
+  applied to the aliases of the commands defined.
+
 email::
   Settings for extensions that send email messages.
   from;;
@@ -349,6 +366,16 @@
     6Mbps), uncompressed streaming is slower, because of the extra
     data transfer overhead.  Default is False.
 
+trusted::
+  Mercurial will only read the .hg/hgrc file from a repository if
+  it belongs to a trusted user or to a trusted group. This section
+  specifies what users and groups are trusted. To trust everybody,
+  list a user or a group with name "*".
+  users;;
+    Comma-separated list of trusted users.
+  groups;;
+    Comma-separated list of trusted groups.
+
 ui::
   User interface controls.
   debug;;
@@ -377,6 +404,9 @@
     remote command to use for clone/push/pull operations. Default is 'hg'.
   ssh;;
     command to use for SSH connections. Default is 'ssh'.
+  strict;;
+    Require exact command names, instead of allowing unambiguous
+    abbreviations.  True or False.  Default is False.
   timeout;;
     The timeout used when a lock is held (in seconds), a negative value
     means no timeout. Default is 600.
--- a/hgeditor	Mon Sep 04 16:02:25 2006 -0400
+++ b/hgeditor	Mon Sep 04 23:27:14 2006 +0200
@@ -41,13 +41,15 @@
 
 cat "$1" > "$HGTMP/msg"
 
-CHECKSUM=`md5sum "$HGTMP/msg"`
+MD5=$(which md5sum 2>/dev/null) || \
+    MD5=$(which md5 2>/dev/null) 
+[ -x "${MD5}" ] && CHECKSUM=`${MD5} "$HGTMP/msg"`
 if [ -s "$HGTMP/diff" ]; then
     $EDITOR "$HGTMP/msg" "$HGTMP/diff" || exit $?
 else
     $EDITOR "$HGTMP/msg" || exit $?
 fi
-echo "$CHECKSUM" | md5sum -c >/dev/null 2>&1 && exit 13
+[ -x "${MD5}" ] && (echo "$CHECKSUM" | ${MD5} -c >/dev/null 2>&1 && exit 13)
 
 mv "$HGTMP/msg" "$1"
 
--- a/hgext/hgk.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/hgext/hgk.py	Mon Sep 04 23:27:14 2006 +0200
@@ -46,18 +46,20 @@
         if f in mmap:
             to = repo.file(f).read(mmap[f])
         tn = read(f)
+        opts = mdiff.diffopts()
+        opts.text = text
         fp.write("diff --git a/%s b/%s\n" % (f, f))
-        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
+        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
     for f in added:
         to = None
         tn = read(f)
         fp.write("diff --git /dev/null b/%s\n" % (f))
-        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
+        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
     for f in removed:
         to = repo.file(f).read(mmap[f])
         tn = None
         fp.write("diff --git a/%s /dev/null\n" % (f))
-        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
+        fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, opts=opts))
 
 def difftree(ui, repo, node1=None, node2=None, **opts):
     """diff trees from two commits"""
--- a/hgext/mq.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/hgext/mq.py	Mon Sep 04 23:27:14 2006 +0200
@@ -31,8 +31,9 @@
 
 from mercurial.demandload import *
 from mercurial.i18n import gettext as _
+from mercurial import commands
 demandload(globals(), "os sys re struct traceback errno bz2")
-demandload(globals(), "mercurial:cmdutil,commands,hg,patch,revlog,ui,util")
+demandload(globals(), "mercurial:cmdutil,hg,patch,revlog,ui,util")
 
 commands.norepo += " qclone qversion"
 
@@ -915,16 +916,16 @@
     def refresh(self, repo, pats=None, **opts):
         if len(self.applied) == 0:
             self.ui.write("No patches applied\n")
-            return
+            return 1
         wlock = repo.wlock()
         self.check_toppatch(repo)
-        (top, patch) = (self.applied[-1].rev, self.applied[-1].name)
+        (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
         top = revlog.bin(top)
         cparents = repo.changelog.parents(top)
         patchparent = self.qparents(repo, top)
-        message, comments, user, date, patchfound = self.readheaders(patch)
+        message, comments, user, date, patchfound = self.readheaders(patchfn)
 
-        patchf = self.opener(patch, "w")
+        patchf = self.opener(patchfn, "w")
         msg = opts.get('msg', '').rstrip()
         if msg:
             if comments:
@@ -994,8 +995,9 @@
             r = list(util.unique(dd))
             a = list(util.unique(aa))
             filelist = filter(matchfn, util.unique(m + r + a))
-            self.printdiff(repo, patchparent, files=filelist,
-                           changes=(m, a, r, [], u), fp=patchf)
+            patch.diff(repo, patchparent, files=filelist, match=matchfn,
+                       fp=patchf, changes=(m, a, r, [], u),
+                       opts=self.diffopts())
             patchf.close()
 
             changes = repo.changelog.read(tip)
@@ -1018,7 +1020,7 @@
 
             if not msg:
                 if not message:
-                    message = "patch queue: %s\n" % patch
+                    message = "patch queue: %s\n" % patchfn
                 else:
                     message = "\n".join(message)
             else:
@@ -1026,7 +1028,7 @@
 
             self.strip(repo, top, update=False, backup='strip', wlock=wlock)
             n = repo.commit(filelist, message, changes[1], force=1, wlock=wlock)
-            self.applied[-1] = statusentry(revlog.hex(n), patch)
+            self.applied[-1] = statusentry(revlog.hex(n), patchfn)
             self.applied_dirty = 1
         else:
             self.printdiff(repo, patchparent, fp=patchf)
@@ -1237,11 +1239,13 @@
             self.ui.write(p + '\n')
         else:
             self.ui.write("No patches applied\n")
+            return 1
 
     def next(self, repo):
         end = self.series_end()
         if end == len(self.series):
             self.ui.write("All patches applied\n")
+            return 1
         else:
             p = self.series[end]
             if self.ui.verbose:
@@ -1254,8 +1258,10 @@
             self.ui.write(p + '\n')
         elif len(self.applied) == 1:
             self.ui.write("Only one patch applied\n")
+            return 1
         else:
             self.ui.write("No patches applied\n")
+            return 1
 
     def qimport(self, repo, files, patch=None, existing=None, force=None):
         if len(files) > 1 and patch:
@@ -1402,18 +1408,15 @@
 
 def top(ui, repo, **opts):
     """print the name of the current patch"""
-    repo.mq.top(repo)
-    return 0
+    return repo.mq.top(repo)
 
 def next(ui, repo, **opts):
     """print the name of the next patch"""
-    repo.mq.next(repo)
-    return 0
+    return repo.mq.next(repo)
 
 def prev(ui, repo, **opts):
     """print the name of the previous patch"""
-    repo.mq.prev(repo)
-    return 0
+    return repo.mq.prev(repo)
 
 def new(ui, repo, patch, **opts):
     """create a new patch
@@ -1449,9 +1452,9 @@
         patch = q.applied[-1].name
         (message, comment, user, date, hasdiff) = q.readheaders(patch)
         message = ui.edit('\n'.join(message), user or ui.username())
-    q.refresh(repo, pats, msg=message, **opts)
+    ret = q.refresh(repo, pats, msg=message, **opts)
     q.save_dirty()
-    return 0
+    return ret
 
 def diff(ui, repo, *pats, **opts):
     """diff of the current patch"""
@@ -1571,7 +1574,7 @@
     else:
         if not q.applied:
             ui.write('No patches applied\n')
-            return
+            return 1
         patch = q.lookup('qtip')
     message = repo.mq.readheaders(patch)[0]
 
--- a/hgext/notify.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/hgext/notify.py	Mon Sep 04 23:27:14 2006 +0200
@@ -238,7 +238,7 @@
             return
         fp = templater.stringio()
         prev = self.repo.changelog.parents(node)[0]
-        patch.diff(self.repo, fp, prev, ref)
+        patch.diff(self.repo, prev, ref, fp=fp)
         difflines = fp.getvalue().splitlines(1)
         if maxdiff > 0 and len(difflines) > maxdiff:
             self.sio.write(_('\ndiffs (truncated from %d to %d lines):\n\n') %
--- a/hgext/patchbomb.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/hgext/patchbomb.py	Mon Sep 04 23:27:14 2006 +0200
@@ -205,7 +205,8 @@
 
     commands.export(ui, repo, *revs, **{'output': exportee(patches),
                                         'switch_parent': False,
-                                        'text': None})
+                                        'text': None,
+                                        'git': opts.get('git')})
 
     jumbo = []
     msgs = []
@@ -322,6 +323,7 @@
       ('', 'bcc', [], 'email addresses of blind copy recipients'),
       ('c', 'cc', [], 'email addresses of copy recipients'),
       ('d', 'diffstat', None, 'add diffstat output to messages'),
+      ('g', 'git', None, _('use git extended diff format')),
       ('f', 'from', '', 'email address of sender'),
       ('', 'plain', None, 'omit hg patch header'),
       ('n', 'test', None, 'print messages that would be sent'),
--- a/mercurial/commands.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/commands.py	Mon Sep 04 23:27:14 2006 +0200
@@ -505,7 +505,7 @@
         if with_version:
             show_version(ui)
             ui.write('\n')
-        aliases, i = findcmd(name)
+        aliases, i = findcmd(ui, name)
         # synopsis
         ui.write("%s\n\n" % i[2])
 
@@ -818,6 +818,7 @@
         parent = p1
     hg.clean(repo, node, show_stats=False)
     revert_opts = opts.copy()
+    revert_opts['all'] = True
     revert_opts['rev'] = hex(parent)
     revert(ui, repo, **revert_opts)
     commit_opts = opts.copy()
@@ -1151,7 +1152,7 @@
         options = []
         otables = [globalopts]
         if cmd:
-            aliases, entry = findcmd(cmd)
+            aliases, entry = findcmd(ui, cmd)
             otables.append(entry[1])
         for t in otables:
             for o in t:
@@ -1161,7 +1162,7 @@
         ui.write("%s\n" % "\n".join(options))
         return
 
-    clist = findpossible(cmd).keys()
+    clist = findpossible(ui, cmd).keys()
     clist.sort()
     ui.write("%s\n" % "\n".join(clist))
 
@@ -2271,8 +2272,8 @@
     Modified files are saved with a .orig suffix before reverting.
     To disable these backups, use --no-backup.
 
-    Using the -r option, revert the given files or directories to
-    their contents as of a specific revision.  This can be helpful to"roll
+    Using the -r option, revert the given files or directories to their
+    contents as of a specific revision. This can be helpful to "roll
     back" some or all of a change that should not have been committed.
 
     Revert modifies the working directory.  It does not commit any
@@ -2286,8 +2287,13 @@
 
     If names are given, all files matching the names are reverted.
 
-    If no arguments are given, all files in the repository are reverted.
+    If no arguments are given, no files are reverted.
     """
+
+    if not pats and not opts['all']:
+        raise util.Abort(_('no files or directories specified; '
+                           'use --all to revert the whole repo'))
+
     parent, p2 = repo.dirstate.parents()
     if opts['rev']:
         node = repo.lookup(opts['rev'])
@@ -2881,6 +2887,7 @@
         (export,
          [('o', 'output', '', _('print output to file with formatted name')),
           ('a', 'text', None, _('treat all files as text')),
+          ('g', 'git', None, _('use git extended diff format')),
           ('', 'switch-parent', None, _('diff against the second parent'))],
          _('hg export [-a] [-o OUTFILESPEC] REV...')),
     "debugforget|forget":
@@ -3046,7 +3053,8 @@
          _('hg rename [OPTION]... SOURCE... DEST')),
     "^revert":
         (revert,
-         [('r', 'rev', '', _('revision to revert to')),
+         [('a', 'all', None, _('revert all changes when no arguments given')),
+          ('r', 'rev', '', _('revision to revert to')),
           ('', 'no-backup', None, _('do not save backup copies of files')),
           ('I', 'include', [], _('include names matching given patterns')),
           ('X', 'exclude', [], _('exclude names matching given patterns')),
@@ -3145,7 +3153,7 @@
           " debugindex debugindexdot")
 optionalrepo = ("paths serve debugconfig")
 
-def findpossible(cmd):
+def findpossible(ui, cmd):
     """
     Return cmd -> (aliases, command table entry)
     for each matching command.
@@ -3158,7 +3166,7 @@
         found = None
         if cmd in aliases:
             found = cmd
-        else:
+        elif not ui.config("ui", "strict"):
             for a in aliases:
                 if a.startswith(cmd):
                     found = a
@@ -3174,9 +3182,9 @@
 
     return choice
 
-def findcmd(cmd):
+def findcmd(ui, cmd):
     """Return (aliases, command table entry) for command string."""
-    choice = findpossible(cmd)
+    choice = findpossible(ui, cmd)
 
     if choice.has_key(cmd):
         return choice[cmd]
@@ -3211,7 +3219,7 @@
 
     if args:
         cmd, args = args[0], args[1:]
-        aliases, i = findcmd(cmd)
+        aliases, i = findcmd(ui, cmd)
         cmd = aliases[0]
         defaults = ui.config("defaults", cmd)
         if defaults:
@@ -3299,12 +3307,14 @@
         if num: signal.signal(num, catchterm)
 
     try:
-        u = ui.ui(traceback='--traceback' in sys.argv[1:],
-                  readhooks=[load_extensions])
+        u = ui.ui(traceback='--traceback' in sys.argv[1:])
     except util.Abort, inst:
         sys.stderr.write(_("abort: %s\n") % inst)
         return -1
 
+    load_extensions(u)
+    u.addreadhook(load_extensions)
+
     try:
         cmd, func, args, options, cmdoptions = parse(u, args)
         if options["time"]:
--- a/mercurial/hg.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/hg.py	Mon Sep 04 23:27:14 2006 +0200
@@ -127,12 +127,7 @@
             if self.dir_:
                 self.rmtree(self.dir_, True)
 
-    dest_repo = None
-    try:
-        dest_repo = repository(ui, dest)
-        raise util.Abort(_("destination '%s' already exists." % dest))
-    except RepoError:
-        dest_repo = repository(ui, dest, create=True)
+    dest_repo = repository(ui, dest, create=True)
 
     dest_path = None
     dir_cleanup = None
--- a/mercurial/localrepo.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/localrepo.py	Mon Sep 04 23:27:14 2006 +0200
@@ -31,8 +31,16 @@
             path = p
         self.path = os.path.join(path, ".hg")
 
-        if not create and not os.path.isdir(self.path):
-            raise repo.RepoError(_("repository %s not found") % path)
+        if not os.path.isdir(self.path):
+            if create:
+                if not os.path.exists(path):
+                    os.mkdir(path)
+                os.mkdir(self.path)
+                os.mkdir(self.join("data"))
+            else:
+                raise repo.RepoError(_("repository %s not found") % path)
+        elif create:
+            raise repo.RepoError(_("repository %s already exists") % path)
 
         self.root = os.path.abspath(path)
         self.origroot = path
@@ -75,12 +83,6 @@
         self.decodepats = None
         self.transhandle = None
 
-        if create:
-            if not os.path.exists(path):
-                os.mkdir(path)
-            os.mkdir(self.path)
-            os.mkdir(self.join("data"))
-
         self.dirstate = dirstate.dirstate(self.opener, self.ui, self.root)
 
     def url(self):
@@ -641,7 +643,11 @@
         if node:
             fdict = dict.fromkeys(files)
             for fn in self.manifest.read(self.changelog.read(node)[0]):
-                fdict.pop(fn, None)
+                for ffn in fdict:
+                    # match if the file is the exact name or a directory
+                    if ffn == fn or fn.startswith("%s/" % ffn):
+                        del fdict[ffn]
+                        break
                 if match(fn):
                     yield 'm', fn
             for fn in fdict:
--- a/mercurial/mdiff.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/mdiff.py	Mon Sep 04 23:27:14 2006 +0200
@@ -50,6 +50,9 @@
 defaultopts = diffopts()
 
 def unidiff(a, ad, b, bd, fn, r=None, opts=defaultopts):
+    def datetag(date):
+        return opts.git and '\n' or '\t%s\n' % date
+
     if not a and not b: return ""
     epoch = util.datestr((0, 0))
 
@@ -58,19 +61,19 @@
     elif not a:
         b = splitnewlines(b)
         if a is None:
-            l1 = "--- %s\t%s\n" % ("/dev/null", epoch)
+            l1 = '--- /dev/null%s' % datetag(epoch)
         else:
-            l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
-        l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
+            l1 = "--- %s%s" % ("a/" + fn, datetag(ad))
+        l2 = "+++ %s%s" % ("b/" + fn, datetag(bd))
         l3 = "@@ -0,0 +1,%d @@\n" % len(b)
         l = [l1, l2, l3] + ["+" + e for e in b]
     elif not b:
         a = splitnewlines(a)
-        l1 = "--- %s\t%s\n" % ("a/" + fn, ad)
+        l1 = "--- %s%s" % ("a/" + fn, datetag(ad))
         if b is None:
-            l2 = "+++ %s\t%s\n" % ("/dev/null", epoch)
+            l2 = '+++ /dev/null%s' % datetag(epoch)
         else:
-            l2 = "+++ %s\t%s\n" % ("b/" + fn, bd)
+            l2 = "+++ %s%s" % ("b/" + fn, datetag(bd))
         l3 = "@@ -1,%d +0,0 @@\n" % len(a)
         l = [l1, l2, l3] + ["-" + e for e in a]
     else:
@@ -79,8 +82,8 @@
         l = list(bunidiff(a, b, al, bl, "a/" + fn, "b/" + fn, opts=opts))
         if not l: return ""
         # difflib uses a space, rather than a tab
-        l[0] = "%s\t%s\n" % (l[0][:-2], ad)
-        l[1] = "%s\t%s\n" % (l[1][:-2], bd)
+        l[0] = "%s%s" % (l[0][:-2], datetag(ad))
+        l[1] = "%s%s" % (l[1][:-2], datetag(bd))
 
     for ln in xrange(len(l)):
         if l[ln][-1] != '\n':
--- a/mercurial/merge.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/merge.py	Mon Sep 04 23:27:14 2006 +0200
@@ -8,7 +8,7 @@
 from node import *
 from i18n import gettext as _
 from demandload import *
-demandload(globals(), "util os tempfile")
+demandload(globals(), "errno util os tempfile")
 
 def fmerge(f, local, other, ancestor):
     """merge executable flags"""
@@ -168,7 +168,8 @@
                     repo.ui.debug(_(" updating permissions for %s\n") % f)
                     util.set_exec(repo.wjoin(f), m2.execf(f))
                 else:
-                    if fmerge(f, m1, m2, ma) != m1.execf(f):
+                    mode = fmerge(f, m1, m2, ma)
+                    if mode != m1.execf(f):
                         repo.ui.debug(_(" updating permissions for %s\n")
                                       % f)
                         util.set_exec(repo.wjoin(f), mode)
--- a/mercurial/packagescan.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/packagescan.py	Mon Sep 04 23:27:14 2006 +0200
@@ -26,6 +26,7 @@
         foo            import foo
         foo bar        import foo, bar
         foo.bar        import foo.bar
+        foo@bar        import foo as bar
         foo:bar        from foo import bar
         foo:bar,quux   from foo import bar, quux
         foo.bar:quux   from foo.bar import quux"""
@@ -38,6 +39,9 @@
         except:
             module = m
             fromlist = []
+        as_ = None
+        if '@' in module:
+            module, as_ = module.split('@')
         mod = __import__(module, scope, scope, fromlist)
         if fromlist == []:
             # mod is only the top package, but we need all packages
@@ -46,7 +50,9 @@
             mn = comp[0]
             while True:
                 # mn and mod.__name__ might not be the same
-                scope[mn] = mod
+                if not as_:
+                    as_ = mn
+                scope[as_] = mod
                 requiredmodules[mod.__name__] = 1
                 if len(comp) == i: break
                 mod = getattr(mod,comp[i])
--- a/mercurial/sshrepo.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/sshrepo.py	Mon Sep 04 23:27:14 2006 +0200
@@ -34,9 +34,10 @@
         if create:
             try:
                 self.validate_repo(ui, sshcmd, args, remotecmd)
-                return # the repo is good, nothing more to do
             except hg.RepoError:
                 pass
+            else:
+                raise hg.RepoError(_("repository %s already exists") % path)
 
             cmd = '%s %s "%s init %s"'
             cmd = cmd % (sshcmd, args, remotecmd, self.path)
@@ -52,6 +53,9 @@
         return self._url
 
     def validate_repo(self, ui, sshcmd, args, remotecmd):
+        # cleanup up previous run
+        self.cleanup()
+
         cmd = '%s %s "%s -R %s serve --stdio"'
         cmd = cmd % (sshcmd, args, remotecmd, self.path)
 
@@ -90,7 +94,7 @@
             if not l: break
             self.ui.status(_("remote: "), l)
 
-    def __del__(self):
+    def cleanup(self):
         try:
             self.pipeo.close()
             self.pipei.close()
@@ -101,6 +105,8 @@
         except:
             pass
 
+    __del__ = cleanup
+
     def do_cmd(self, cmd, **args):
         self.ui.debug(_("sending %s command\n") % cmd)
         self.pipeo.write("%s\n" % cmd)
--- a/mercurial/ui.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/ui.py	Mon Sep 04 23:27:14 2006 +0200
@@ -12,13 +12,14 @@
 
 class ui(object):
     def __init__(self, verbose=False, debug=False, quiet=False,
-                 interactive=True, traceback=False, parentui=None,
-                 readhooks=[]):
+                 interactive=True, traceback=False, parentui=None):
         self.overlay = {}
         if parentui is None:
             # this is the parent of all ui children
             self.parentui = None
-            self.readhooks = list(readhooks)
+            self.readhooks = []
+            self.trusted_users = {}
+            self.trusted_groups = {}
             self.cdata = ConfigParser.SafeConfigParser()
             self.readconfig(util.rcpath())
 
@@ -36,7 +37,9 @@
         else:
             # parentui may point to an ui object which is already a child
             self.parentui = parentui.parentui or parentui
-            self.readhooks = list(parentui.readhooks or readhooks)
+            self.readhooks = parentui.readhooks[:]
+            self.trusted_users = parentui.trusted_users.copy()
+            self.trusted_groups = parentui.trusted_groups.copy()
             parent_cdata = self.parentui.cdata
             self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
             # make interpolation work
@@ -51,7 +54,7 @@
     def updateopts(self, verbose=False, debug=False, quiet=False,
                    interactive=True, traceback=False, config=[]):
         self.quiet = (self.quiet or quiet) and not verbose and not debug
-        self.verbose = (self.verbose or verbose) or debug
+        self.verbose = ((self.verbose or verbose) or debug) and not self.quiet
         self.debugflag = (self.debugflag or debug)
         self.interactive = (self.interactive and interactive)
         self.traceback = self.traceback or traceback
@@ -72,7 +75,22 @@
             fn = [fn]
         for f in fn:
             try:
-                self.cdata.read(f)
+                fp = open(f)
+            except IOError:
+                continue
+            if ((self.trusted_users or self.trusted_groups) and
+                '*' not in self.trusted_users and
+                '*' not in self.trusted_groups):
+                st = util.fstat(fp)
+                user = util.username(st.st_uid)
+                group = util.groupname(st.st_gid)
+                if (user not in self.trusted_users and
+                    group not in self.trusted_groups):
+                    self.warn(_('not reading file %s from untrusted '
+                                'user %s, group %s\n') % (f, user, group))
+                    continue
+            try:
+                self.cdata.readfp(fp, f)
             except ConfigParser.ParsingError, inst:
                 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
         # translate paths relative to root (or home) into absolute paths
@@ -81,9 +99,19 @@
         for name, path in self.configitems("paths"):
             if path and "://" not in path and not os.path.isabs(path):
                 self.cdata.set("paths", name, os.path.join(root, path))
+        user = util.username()
+        if user is not None:
+            self.trusted_users[user] = 1
+            for user in self.configlist('trusted', 'users'):
+                self.trusted_users[user] = 1
+            for group in self.configlist('trusted', 'groups'):
+                self.trusted_groups[group] = 1
         for hook in self.readhooks:
             hook(self)
 
+    def addreadhook(self, hook):
+        self.readhooks.append(hook)
+
     def setconfig(self, section, name, val):
         self.overlay[(section, name)] = val
 
--- a/mercurial/util.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/mercurial/util.py	Mon Sep 04 23:27:14 2006 +0200
@@ -15,7 +15,7 @@
 from i18n import gettext as _
 from demandload import *
 demandload(globals(), "cStringIO errno getpass popen2 re shutil sys tempfile")
-demandload(globals(), "os threading time")
+demandload(globals(), "os threading time pwd grp")
 
 # used by parsedate
 defaultdateformats = ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M',
@@ -509,6 +509,38 @@
     raise Abort(_('user name not available - set USERNAME '
                   'environment variable'))
 
+def username(uid=None):
+    """Return the name of the user with the given uid.
+
+    If uid is None, return the name of the current user."""
+    try:
+        # force an ImportError if there's no module pwd
+        getpwuid = pwd.getpwuid
+        if uid is None:
+            uid = os.getuid()
+        try:
+            return getpwuid(uid)[0]
+        except KeyError:
+            return str(uid)
+    except ImportError:
+        return None
+
+def groupname(gid=None):
+    """Return the name of the group with the given gid.
+
+    If gid is None, return the name of the current group."""
+    try:
+        # force an ImportError if there's no module grp
+        getgrgid = grp.getgrgid
+        if gid is None:
+            gid = os.getgid()
+        try:
+            return getgrgid(gid)[0]
+        except KeyError:
+            return str(gid)
+    except ImportError:
+        return None
+
 # Platform specific variants
 if os.name == 'nt':
     demandload(globals(), "msvcrt")
--- a/templates/map-gitweb	Mon Sep 04 16:02:25 2006 -0400
+++ b/templates/map-gitweb	Mon Sep 04 23:27:14 2006 +0200
@@ -8,7 +8,7 @@
 naventry = '<a href="?cmd=changelog;rev=#rev#;style=gitweb">#label|escape#</a> '
 navshortentry = '<a href="?cmd=shortlog;rev=#rev#;style=gitweb">#label|escape#</a> '
 filedifflink = '<a href="?cmd=filediff;node=#node#;file=#file|urlescape#;style=gitweb">#file|escape#</a> '
-filenodelink = '<tr class="light"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?cmd=file;filenode=#filenode#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#filenode|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
+filenodelink = '<tr class="light"><td><a class="list" href="">#file|escape#</a></td><td></td><td class="link"><a href="?cmd=file;filenode=#filenode#;file=#file|urlescape#;style=gitweb">file</a> | <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> | <!-- FIXME: <a href="?fd=#filenode|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?cmd=filelog;filenode=#filenode|short#;file=#file|urlescape#;style=gitweb">revisions</a></td></tr>'
 fileellipses = '...'
 changelogentry = changelogentry-gitweb.tmpl
 searchentry = changelogentry-gitweb.tmpl
@@ -19,12 +19,12 @@
 filerevision = filerevision-gitweb.tmpl
 fileannotate = fileannotate-gitweb.tmpl
 filelog = filelog-gitweb.tmpl
-fileline = '<div style="font-family:monospace; white-space: pre;" class="parity#parity#"><span class="linenr">   #linenumber#</span> #line|escape#</div>'
-annotateline = '<tr style="font-family:monospace; white-space: pre;" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?cs=#node|short#;style=gitweb">#author|obfuscate#@#rev#</a></td><td>#line|escape#</td></tr>'
-difflineplus = '<div class="pre" style="color:#008800;">#line|escape#</div>'
-difflineminus = '<div class="pre" style="color:#cc0000;">#line|escape#</div>'
-difflineat = '<div class="pre" style="color:#990099;">#line|escape#</div>'
-diffline = '<div class="pre">#line|escape#</div>'
+fileline = '<div style="font-family:monospace" class="parity#parity#"><pre><span class="linenr">   #linenumber#</span> #line|escape#</pre></div>'
+annotateline = '<tr style="font-family:monospace" class="parity#parity#"><td class="linenr" style="text-align: right;"><a href="?cs=#node|short#;style=gitweb">#author|obfuscate#@#rev#</a></td><td><pre>#line|escape#</pre></td></tr>'
+difflineplus = '<div style="color:#008800;">#line|escape#</div>'
+difflineminus = '<div style="color:#cc0000;">#line|escape#</div>'
+difflineat = '<div style="color:#990099;">#line|escape#</div>'
+diffline = '<div>#line|escape#</div>'
 changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
 changesetparent = '<tr><td>parent</td><td style="font-family:monospace"><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb">#node|short#</a></td></tr>'
 filerevparent = '<tr><td class="metatag">parent:</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
@@ -37,7 +37,7 @@
 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="?cmd=annotate;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
 tags = tags-gitweb.tmpl
 tagentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#tag|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> | <a href="?cmd=changelog;rev=#node|short#;style=gitweb">changelog</a> |  <a href="?mf=#tagmanifest|short#;path=/;style=gitweb">manifest</a></td></tr>'
-diffblock = '#lines#'
+diffblock = '<pre>#lines#</pre>'
 changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
 changesettag = '<tr><td>tag</td><td>#tag|escape#</td></tr>'
 filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="?cmd=changeset;node=#node#;style=gitweb">#node|short#</a></td></tr>'
@@ -46,5 +46,5 @@
 filelogchild = '<tr><td align="right">child #rev#:&nbsp;</td><td><a href="?cmd=file;file=#file|urlescape#;filenode=#node#;style=gitweb">#node|short#</a></td></tr>'
 shortlog = shortlog-gitweb.tmpl
 shortlogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><i>#author#</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?cmd=changeset;node=#node|short#;style=gitweb">changeset</a> |  <a href="?cmd=manifest;manifest=#manifest|short#;path=/;style=gitweb">manifest</a></td></tr>'
-filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
+filelogentry = '<tr class="parity#parity#"><td class="age"><i>#date|age# ago</i></td><td><a class="list" href="?cmd=changeset;node=#node|short#;style=gitweb"><b>#desc|strip|firstline|escape#</b></a></td><td class="link"><a href="?f=#node|short#;file=#file|urlescape#;style=gitweb">file</a> | <!-- FIXME: <a href="?fd=#node|short#;file=#file|urlescape#;style=gitweb">diff</a> | --> <a href="?fa=#filenode|short#;file=#file|urlescape#;style=gitweb">annotate</a> #rename%filelogrename#</td></tr>'
 archiveentry = ' | <a href="?ca=#node|short#;type=#type|urlescape#">#type|escape#</a> '
--- a/templates/static/style-gitweb.css	Mon Sep 04 16:02:25 2006 -0400
+++ b/templates/static/style-gitweb.css	Mon Sep 04 23:27:14 2006 +0200
@@ -47,3 +47,4 @@
 	text-align:center; text-decoration:none;
 }
 a.rss_logo:hover { background-color:#ee5500; }
+pre { margin: 0; }
--- a/tests/README	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/README	Mon Sep 04 23:27:14 2006 +0200
@@ -31,3 +31,65 @@
   use hg diff | sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
                     -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/"
   to strip dates
+
+- You can append your own hgrc settings to the file that the environment
+  variable HGRCPATH points to. This file is cleared before running a test.
+
+You also need to be careful that the tests are portable from one platform
+to another.  You're probably working on Linux, where the GNU toolchain has
+more (or different) functionality than on MacOS, *BSD, Solaris, AIX, etc.
+While testing on all platforms is the only sure-fire way to make sure that
+you've written portable code, here's a list of problems that have been
+found and fixed in the tests.  Another, more comprehensive list may be
+found in the GNU Autoconf manual, online here:
+
+    http://www.gnu.org/software/autoconf/manual/html_node/Portable-Shell.html
+
+sh:
+
+The Bourne shell is a very basic shell.  /bin/sh on Linux is typically
+bash, which even in Bourne-shell mode has many features that Bourne shells
+on other Unix systems don't have (and even on Linux /bin/sh isn't
+guaranteed to be bash).  You'll need to be careful about constructs that
+seem ubiquitous, but are actually not available in the least common
+denominator.  While using another shell (ksh, bash explicitly, posix shell,
+etc.) explicitly may seem like another option, these may not exist in a
+portable location, and so are generally probably not a good idea.  You may
+find that rewriting the test in python will be easier.
+
+- don't use pushd/popd; save the output of "pwd" and use "cd" in place of
+  the pushd, and cd back to the saved pwd instead of popd.
+
+- don't use math expressions like let, (( ... )), or $(( ... )); use "expr"
+  instead.
+
+grep:
+
+- don't use the -q option; redirect stdout to /dev/null instead.
+
+- don't use extended regular expressions with grep; use egrep instead, and
+  don't escape any regex operators.
+
+sed:
+
+- make sure that the beginning-of-line matcher ("^") is at the very
+  beginning of the expression -- it may not be supported inside parens.
+
+echo:
+
+- echo may interpret "\n" and print a newline; use printf instead if you
+  want a literal "\n" (backslash + n).
+
+false:
+
+- false is guaranteed only to return a non-zero value; you cannot depend on
+  it being 1.  On Solaris in particular, /bin/false returns 255.  Rewrite
+  your test to not depend on a particular return value, or create a
+  temporary "false" executable, and call that instead.
+
+diff:
+
+- don't use the -N option.  There's no particularly good workaround short
+  of writing a reasonably complicated replacement script, but substituting
+  gdiff for diff if you can't rewrite the test not to need -N will probably
+  do.
--- a/tests/run-tests.py	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/run-tests.py	Mon Sep 04 23:27:14 2006 +0200
@@ -211,6 +211,10 @@
         sys.stdout.write('.')
         sys.stdout.flush()
 
+    # create a fresh hgrc
+    hgrc = file(HGRCPATH, 'w+')
+    hgrc.close()
+
     err = os.path.join(TESTDIR, test+".err")
     ref = os.path.join(TESTDIR, test+".out")
 
@@ -319,11 +323,11 @@
 os.environ["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
 os.environ["HGMERGE"]  = sys.executable + ' -c "import sys; sys.exit(0)"'
 os.environ["HGUSER"]   = "test"
-os.environ["HGRCPATH"] = ""
 
 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
 HGTMP   = os.environ["HGTMP"]   = tempfile.mkdtemp("", "hgtests.")
 DAEMON_PIDS = os.environ["DAEMON_PIDS"] = os.path.join(HGTMP, 'daemon.pids')
+HGRCPATH = os.environ["HGRCPATH"] = os.path.join(HGTMP, '.hgrc')
 
 vlog("# Using TESTDIR", TESTDIR)
 vlog("# Using HGTMP", HGTMP)
--- a/tests/test-abort-checkin	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-abort-checkin	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 cat > $HGTMP/false <<EOF
 #!/bin/sh
 exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-bad-extension	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+echo 'syntax error' > badext.py
+abspath=`pwd`/badext.py
+
+echo '[extensions]' >> $HGRCPATH
+echo "badext = $abspath" >> $HGRCPATH
+
+hg -q help help
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-bad-extension.out	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,4 @@
+*** failed to import extension badext: invalid syntax (badext.py, line 1)
+hg help [COMMAND]
+
+show help for a command, extension, or list of commands
--- a/tests/test-bisect	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-bisect	Mon Sep 04 23:27:14 2006 +0200
@@ -2,9 +2,8 @@
 
 set -e
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "hbisect=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "hbisect=" >> $HGRCPATH
 
 echo % init
 hg init
--- a/tests/test-confused-revert	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-confused-revert	Mon Sep 04 23:27:14 2006 +0200
@@ -13,7 +13,7 @@
 hg status
 
 echo "reverting..."
-hg revert
+hg revert --all
 
 echo "%%% should show b unknown and a back to normal"
 hg status
@@ -42,10 +42,10 @@
 hg status
 
 echo "%%% revert should fail"
-hg revert
+hg revert --all
 
 echo "%%% revert should be ok now"
-hg revert -r2
+hg revert -r2 --all
 
 echo "%%% should show b unknown and a marked modified (merged)"
 hg status
--- a/tests/test-extdiff	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-extdiff	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "extdiff=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "extdiff=" >> $HGRCPATH
 
 hg init a
 cd a
@@ -14,9 +13,9 @@
 fi
 hg extdiff -o -Nr $opt
 
-echo "[extdiff]" >> $HGTMP/.hgrc
-echo "cmd.falabala=echo" >> $HGTMP/.hgrc
-echo "opts.falabala=diffing" >> $HGTMP/.hgrc
+echo "[extdiff]" >> $HGRCPATH
+echo "cmd.falabala=echo" >> $HGRCPATH
+echo "opts.falabala=diffing" >> $HGRCPATH
 
 hg falabala
 
--- a/tests/test-fetch	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-fetch	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "fetch=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "fetch=" >> $HGRCPATH
 
 hg init a
 echo a > a/a
--- a/tests/test-http	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-http	Mon Sep 04 23:27:14 2006 +0200
@@ -11,7 +11,7 @@
 
 echo % clone via stream
 http_proxy= hg clone --uncompressed http://localhost:20059/ copy 2>&1 | \
-  sed -e 's/[0-9][0-9.]*/XXX/g'
+  sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
 hg verify -R copy
 
 echo % try to clone via stream, should use pull instead
--- a/tests/test-http-proxy	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-http-proxy	Mon Sep 04 23:27:14 2006 +0200
@@ -15,7 +15,7 @@
 
 echo %% url for proxy, stream
 http_proxy=http://localhost:20060/ hg --config http_proxy.always=True clone --uncompressed http://localhost:20059/ b | \
-  sed -e 's/[0-9][0-9.]*/XXX/g'
+  sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
 cd b
 hg verify
 cd ..
--- a/tests/test-http-proxy.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-http-proxy.out	Mon Sep 04 23:27:14 2006 +0200
@@ -2,7 +2,7 @@
 %% url for proxy, stream
 streaming all changes
 XXX files to transfer, XXX bytes of data
-transferred XXX bytes in XXX seconds (XXX KB/sec)
+transferred XXX bytes in XXX seconds (XXX XB/sec)
 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
 checking changesets
 checking manifests
--- a/tests/test-http.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-http.out	Mon Sep 04 23:27:14 2006 +0200
@@ -2,7 +2,7 @@
 % clone via stream
 streaming all changes
 XXX files to transfer, XXX bytes of data
-transferred XXX bytes in XXX seconds (XXX KB/sec)
+transferred XXX bytes in XXX seconds (XXX XB/sec)
 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
 checking changesets
 checking manifests
--- a/tests/test-init	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-init	Mon Sep 04 23:27:14 2006 +0200
@@ -27,6 +27,9 @@
 echo this > local/foo
 hg ci --cwd local -A -m "init" -d "1000000 0"
 
+echo "#test failure"
+hg init local
+
 echo "# init+push to remote2"
 hg init -e ./dummyssh ssh://user@dummy/remote2
 hg incoming -R remote2 local
@@ -35,6 +38,12 @@
 echo "# clone to remote1"
 hg clone -e ./dummyssh local ssh://user@dummy/remote1
 
+echo "# init to existing repo"
+hg init -e ./dummyssh ssh://user@dummy/remote1
+
+echo "# clone to existing repo"
+hg clone -e ./dummyssh local ssh://user@dummy/remote1
+
 echo "# output of dummyssh"
 cat dummylog
 
--- a/tests/test-init.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-init.out	Mon Sep 04 23:27:14 2006 +0200
@@ -1,6 +1,9 @@
 # creating 'local'
 adding foo
+#test failure
+abort: repository local already exists!
 # init+push to remote2
+remote: abort: repository remote2 not found!
 changeset:   0:c4e059d443be
 tag:         tip
 user:        test
@@ -14,20 +17,25 @@
 remote: adding file changes
 remote: added 1 changesets with 1 changes to 1 files
 # clone to remote1
+remote: abort: repository remote1 not found!
 searching for changes
-remote: abort: repository remote1 not found!
 remote: adding changesets
 remote: adding manifests
 remote: adding file changes
 remote: added 1 changesets with 1 changes to 1 files
+# init to existing repo
+abort: repository ssh://user@dummy/remote1 already exists!
+# clone to existing repo
+abort: repository ssh://user@dummy/remote1 already exists!
 # output of dummyssh
 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
 Got arguments 1:user@dummy 2:hg init remote2 3: 4: 5:
 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
 Got arguments 1:user@dummy 2:hg -R remote2 serve --stdio 3: 4: 5:
 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
+Got arguments 1:user@dummy 2:hg init remote1 3: 4: 5:
 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
-Got arguments 1:user@dummy 2:hg init remote1 3: 4: 5:
+Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
 Got arguments 1:user@dummy 2:hg -R remote1 serve --stdio 3: 4: 5:
 # comparing repositories
 0:c4e059d443be
--- a/tests/test-merge-revert	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-merge-revert	Mon Sep 04 23:27:14 2006 +0200
@@ -15,7 +15,7 @@
 hg id
 echo "changed file1" >> file1
 hg id
-hg revert
+hg revert --all
 hg diff
 hg status
 hg id
@@ -29,11 +29,11 @@
 hg diff
 hg status
 hg id
-hg revert
+hg revert --all
 hg diff
 hg status
 hg id
-hg revert -r tip
+hg revert -r tip --all
 hg diff
 hg status
 hg id
--- a/tests/test-merge-revert2	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-merge-revert2	Mon Sep 04 23:27:14 2006 +0200
@@ -16,7 +16,7 @@
 hg id
 echo "changed file1" >> file1
 hg id
-hg revert --no-backup
+hg revert --no-backup --all
 hg diff
 hg status
 hg id
@@ -31,11 +31,11 @@
               -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" -e "s/\(>>>>>>>\) .*/\1/"
 hg status
 hg id
-hg revert --no-backup
+hg revert --no-backup --all
 hg diff
 hg status
 hg id
-hg revert -r tip --no-backup
+hg revert -r tip --no-backup --all
 hg diff
 hg status
 hg id
--- a/tests/test-mq	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 echo % help
 hg help mq
@@ -127,7 +126,28 @@
 hg strip tip 2>&1 | sed 's/\(saving bundle to \).*/\1/'
 hg unbundle .hg/strip-backup/*
 
-cat >>$HGTMP/.hgrc <<EOF
+echo '% cd b; hg qrefresh'
+hg init refresh
+cd refresh
+echo a > a
+hg ci -Ama -d'0 0'
+hg qnew -mfoo foo
+echo a >> a
+hg qrefresh
+mkdir b
+cd b
+echo f > f
+hg add f
+hg qrefresh
+sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
+    -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" ../.hg/patches/foo
+echo % hg qrefresh .
+hg qrefresh .
+sed -e "s/\(+++ [a-zA-Z0-9_/.-]*\).*/\1/" \
+    -e "s/\(--- [a-zA-Z0-9_/.-]*\).*/\1/" ../.hg/patches/foo
+hg status
+
+cat >>$HGRCPATH <<EOF
 [diff]
 git = True
 EOF
--- a/tests/test-mq-guards	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq-guards	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 hg init
 hg qinit
--- a/tests/test-mq-qdiff	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq-qdiff	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 echo % init
 hg init a
--- a/tests/test-mq-qnew-twice	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq-qnew-twice	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 hg init a
 cd a
--- a/tests/test-mq-qrefresh-replace-log-message	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq-qrefresh-replace-log-message	Mon Sep 04 23:27:14 2006 +0200
@@ -1,9 +1,8 @@
 #!/bin/sh
 
 # Environement setup for MQ
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 #Repo init
 hg init
--- a/tests/test-mq-qsave	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq-qsave	Mon Sep 04 23:27:14 2006 +0200
@@ -1,8 +1,7 @@
 #!/bin/sh
 
-HGRCPATH=$HGTMP/.hgrc; export HGRCPATH
-echo "[extensions]" >> $HGTMP/.hgrc
-echo "mq=" >> $HGTMP/.hgrc
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
 
 hg init a
 cd a
--- a/tests/test-mq.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-mq.out	Mon Sep 04 23:27:14 2006 +0200
@@ -127,6 +127,30 @@
 adding file changes
 added 1 changesets with 1 changes to 1 files
 (run 'hg update' to get a working copy)
+% cd b; hg qrefresh
+adding a
+foo
+
+diff -r cb9a9f314b8b a
+--- a/a
++++ b/a
+@@ -1,1 +1,2 @@ a
+ a
++a
+diff -r cb9a9f314b8b b/f
+--- /dev/null
++++ b/b/f
+@@ -0,0 +1,1 @@
++f
+% hg qrefresh .
+foo
+
+diff -r cb9a9f314b8b b/f
+--- /dev/null
++++ b/b/f
+@@ -0,0 +1,1 @@
++f
+M a
 new file
 
 diff --git a/new b/new
--- a/tests/test-nested-repo	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-nested-repo	Mon Sep 04 23:27:14 2006 +0200
@@ -14,6 +14,6 @@
 echo '# should print A b/x'
 hg st
 echo '# should forget b/x'
-hg revert
+hg revert --all
 echo '# should print nothing'
 hg st b
--- a/tests/test-remove	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-remove	Mon Sep 04 23:27:14 2006 +0200
@@ -9,7 +9,7 @@
 hg remove
 rm foo
 hg remove foo
-hg revert
+hg revert --all
 rm foo
 hg remove --after
 hg commit -m 2 -d "1000000 0"
--- a/tests/test-revert	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-revert	Mon Sep 04 23:27:14 2006 +0200
@@ -31,7 +31,7 @@
 ls
 echo %% should verbosely save backup to e.orig
 echo z > e
-hg revert -v
+hg revert --all -v
 echo %% should say no changes needed
 hg revert a
 echo %% should say file not managed
@@ -46,9 +46,9 @@
 hg add z
 hg st
 echo %% should add a, forget z
-hg revert -r0
+hg revert --all -r0
 echo %% should forget a
-hg revert -rtip
+hg revert --all -rtip
 rm -f a *.orig
 echo %% should silently add a
 hg revert -r0 a
@@ -56,7 +56,7 @@
 
 hg update -C
 chmod +x c
-hg revert
+hg revert --all
 echo %% should print non-executable
 test -x c || echo non-executable
 
@@ -64,7 +64,7 @@
 hg commit -d '1000001 0' -m exe
 
 chmod -x c
-hg revert
+hg revert --all
 echo %% should print executable
 test -x c && echo executable
 
@@ -78,6 +78,15 @@
 hg update 0
 mkdir b
 echo b > b/b
+
+echo % should fail - no arguments
 hg revert -rtip
 
+echo % should succeed
+hg revert --all -rtip
+
+echo %% issue332
+hg ci -A -m b -d '1000001 0'
+echo foobar > b/b
+hg revert b
 true
--- a/tests/test-revert-unknown	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-revert-unknown	Mon Sep 04 23:27:14 2006 +0200
@@ -13,7 +13,7 @@
 
 echo %% Should show unknown
 hg status
-hg revert -r 0
+hg revert -r 0 --all
 echo %% Should show unknown and b removed
 hg status
 echo %% Should show a and unknown
--- a/tests/test-revert.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-revert.out	Mon Sep 04 23:27:14 2006 +0200
@@ -54,4 +54,10 @@
 %% issue 241
 adding a
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% should fail - no arguments
+abort: no files or directories specified; use --all to revert the whole repo
+% should succeed
 reverting a
+%% issue332
+adding b/b
+reverting b/b
--- a/tests/test-ssh	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-ssh	Mon Sep 04 23:27:14 2006 +0200
@@ -38,7 +38,7 @@
 
 echo "# clone remote via stream"
 hg clone -e ./dummyssh --uncompressed ssh://user@dummy/remote local-stream 2>&1 | \
-  sed -e 's/[0-9][0-9.]*/XXX/g'
+  sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/'
 cd local-stream
 hg verify
 cd ..
--- a/tests/test-ssh.out	Mon Sep 04 16:02:25 2006 -0400
+++ b/tests/test-ssh.out	Mon Sep 04 23:27:14 2006 +0200
@@ -2,7 +2,7 @@
 # clone remote via stream
 streaming all changes
 XXX files to transfer, XXX bytes of data
-transferred XXX bytes in XXX seconds (XXX KB/sec)
+transferred XXX bytes in XXX seconds (XXX XB/sec)
 XXX files updated, XXX files merged, XXX files removed, XXX files unresolved
 checking changesets
 checking manifests
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-strict	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+hg init
+
+echo a > a
+hg ci -d '0 0' -Ama
+
+hg an a
+
+echo "[ui]" >> $HGRCPATH
+echo "strict=True" >> $HGRCPATH
+
+hg an a
+hg annotate a
+
+echo % should succeed - up is an alias, not an abbreviation
+
+hg up
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-strict.out	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,26 @@
+adding a
+0: a
+hg: unknown command 'an'
+Mercurial Distributed SCM
+
+basic commands (use "hg help" for the full list or option "-v" for details):
+
+ add        add the specified files on the next commit
+ annotate   show changeset information per file line
+ clone      make a copy of an existing repository
+ commit     commit the specified files or all outstanding changes
+ diff       diff repository (or selected files)
+ export     dump the header and diffs for one or more changesets
+ init       create a new repository in the given directory
+ log        show revision history of entire repository or files
+ parents    show the parents of the working dir or revision
+ pull       pull changes from the specified source
+ push       push changes to the specified destination
+ remove     remove the specified files on the next commit
+ revert     revert files or dirs to their states as of some revision
+ serve      export the repository via HTTP
+ status     show changed files in the working directory
+ update     update or merge working directory
+0: a
+% should succeed - up is an alias, not an abbreviation
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-trusted.py	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# Since it's not easy to write a test that portably deals
+# with files from different users/groups, we cheat a bit by
+# monkey-patching some functions in the util module
+
+import os
+from mercurial import ui, util
+
+hgrc = os.environ['HGRCPATH']
+
+def testui(user='foo', group='bar', tusers=(), tgroups=(),
+           cuser='foo', cgroup='bar'):
+    # user, group => owners of the file
+    # tusers, tgroups => trusted users/groups
+    # cuser, cgroup => user/group of the current process
+
+    # write a global hgrc with the list of trusted users/groups and
+    # some setting so that we can be sure it was read
+    f = open(hgrc, 'w')
+    f.write('[paths]\n')
+    f.write('global = /some/path\n\n')
+
+    if tusers or tgroups:
+        f.write('[trusted]\n')
+        if tusers:
+            f.write('users = %s\n' % ', '.join(tusers))
+        if tgroups:
+            f.write('groups = %s\n' % ', '.join(tgroups))
+    f.close()
+
+    # override the functions that give names to uids and gids
+    def username(uid=None):
+        if uid is None:
+            return cuser
+        return user
+    util.username = username
+
+    def groupname(gid=None):
+        if gid is None:
+            return 'bar'
+        return group
+    util.groupname = groupname
+
+    # try to read everything
+    #print '# File belongs to user %s, group %s' % (user, group)
+    #print '# trusted users = %s; trusted groups = %s' % (tusers, tgroups)
+    kind = ('different', 'same')
+    who = ('', 'user', 'group', 'user and the group')
+    trusted = who[(user in tusers) + 2*(group in tgroups)]
+    if trusted:
+        trusted = ', but we trust the ' + trusted
+    print '# %s user, %s group%s' % (kind[user == cuser], kind[group == cgroup],
+                                     trusted)
+
+    parentui = ui.ui()
+    u = ui.ui(parentui=parentui)
+    u.readconfig('.hg/hgrc')
+    for name, path in u.configitems('paths'):
+        print name, '=', path
+    print
+
+    return u
+
+os.mkdir('repo')
+os.chdir('repo')
+os.mkdir('.hg')
+f = open('.hg/hgrc', 'w')
+f.write('[paths]\n')
+f.write('local = /another/path\n\n')
+f.close()
+
+#print '# Everything is run by user foo, group bar\n'
+
+# same user, same group
+testui()
+# same user, different group
+testui(group='def')
+# different user, same group
+testui(user='abc')
+# ... but we trust the group
+testui(user='abc', tgroups=['bar'])
+# different user, different group
+testui(user='abc', group='def')
+# ... but we trust the user
+testui(user='abc', group='def', tusers=['abc'])
+# ... but we trust the group
+testui(user='abc', group='def', tgroups=['def'])
+# ... but we trust the user and the group
+testui(user='abc', group='def', tusers=['abc'], tgroups=['def'])
+# ... but we trust all users
+print '# we trust all users'
+testui(user='abc', group='def', tusers=['*'])
+# ... but we trust all groups
+print '# we trust all groups'
+testui(user='abc', group='def', tgroups=['*'])
+# ... but we trust the whole universe
+print '# we trust all users and groups'
+testui(user='abc', group='def', tusers=['*'], tgroups=['*'])
+# ... check that users and groups are in different namespaces
+print "# we don't get confused by users and groups with the same name"
+testui(user='abc', group='def', tusers=['def'], tgroups=['abc'])
+# ... lists of user names work
+print "# list of user names"
+testui(user='abc', group='def', tusers=['foo', 'xyz', 'abc', 'bleh'],
+       tgroups=['bar', 'baz', 'qux'])
+# ... lists of group names work
+print "# list of group names"
+testui(user='abc', group='def', tusers=['foo', 'xyz', 'bleh'],
+       tgroups=['bar', 'def', 'baz', 'qux'])
+
+print "# Can't figure out the name of the user running this process"
+testui(user='abc', group='def', cuser=None)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-trusted.py.out	Mon Sep 04 23:27:14 2006 +0200
@@ -0,0 +1,67 @@
+# same user, same group
+global = /some/path
+local = /another/path
+
+# same user, different group
+global = /some/path
+local = /another/path
+
+# different user, same group
+not reading file .hg/hgrc from untrusted user abc, group bar
+global = /some/path
+
+# different user, same group, but we trust the group
+global = /some/path
+local = /another/path
+
+# different user, different group
+not reading file .hg/hgrc from untrusted user abc, group def
+global = /some/path
+
+# different user, different group, but we trust the user
+global = /some/path
+local = /another/path
+
+# different user, different group, but we trust the group
+global = /some/path
+local = /another/path
+
+# different user, different group, but we trust the user and the group
+global = /some/path
+local = /another/path
+
+# we trust all users
+# different user, different group
+global = /some/path
+local = /another/path
+
+# we trust all groups
+# different user, different group
+global = /some/path
+local = /another/path
+
+# we trust all users and groups
+# different user, different group
+global = /some/path
+local = /another/path
+
+# we don't get confused by users and groups with the same name
+# different user, different group
+not reading file .hg/hgrc from untrusted user abc, group def
+global = /some/path
+
+# list of user names
+# different user, different group, but we trust the user
+global = /some/path
+local = /another/path
+
+# list of group names
+# different user, different group, but we trust the group
+global = /some/path
+local = /another/path
+
+# Can't figure out the name of the user running this process
+# different user, different group
+global = /some/path
+local = /another/path
+