--- 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#: </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
+