--- a/contrib/hg-relink Wed Nov 04 22:14:26 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2007 Brendan Cully <brendan@kublai.com>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2, incorporated herein by reference.
-
-import os, sys
-
-class ConfigError(Exception): pass
-
-def usage():
- print """relink <source> <destination>
- Recreate hard links between source and destination repositories"""
-
-class Config:
- def __init__(self, args):
- if len(args) != 3:
- raise ConfigError("wrong number of arguments")
- self.src = os.path.abspath(args[1])
- self.dst = os.path.abspath(args[2])
- for d in (self.src, self.dst):
- if not os.path.exists(os.path.join(d, '.hg')):
- raise ConfigError("%s: not a mercurial repository" % d)
-
-def collect(src):
- seplen = len(os.path.sep)
- candidates = []
- for dirpath, dirnames, filenames in os.walk(src):
- relpath = dirpath[len(src) + seplen:]
- for filename in filenames:
- if not filename.endswith('.i'):
- continue
- st = os.stat(os.path.join(dirpath, filename))
- candidates.append((os.path.join(relpath, filename), st))
-
- return candidates
-
-def prune(candidates, dst):
- def getdatafile(path):
- if not path.endswith('.i'):
- return None, None
- df = path[:-1] + 'd'
- try:
- st = os.stat(df)
- except OSError:
- return None, None
- return df, st
-
- def linkfilter(dst, st):
- try:
- ts = os.stat(dst)
- except OSError:
- # Destination doesn't have this file?
- return False
- if st.st_ino == ts.st_ino:
- return False
- if st.st_dev != ts.st_dev:
- # No point in continuing
- raise Exception('Source and destination are on different devices')
- if st.st_size != ts.st_size:
- # TODO: compare revlog heads
- return False
- return st
-
- targets = []
- for fn, st in candidates:
- tgt = os.path.join(dst, fn)
- ts = linkfilter(tgt, st)
- if not ts:
- continue
- targets.append((fn, ts.st_size))
- df, ts = getdatafile(tgt)
- if df:
- targets.append((fn[:-1] + 'd', ts.st_size))
-
- return targets
-
-def relink(src, dst, files):
- def relinkfile(src, dst):
- bak = dst + '.bak'
- os.rename(dst, bak)
- try:
- os.link(src, dst)
- except OSError:
- os.rename(bak, dst)
- raise
- os.remove(bak)
-
- CHUNKLEN = 65536
- relinked = 0
- savedbytes = 0
-
- for f, sz in files:
- source = os.path.join(src, f)
- tgt = os.path.join(dst, f)
- sfp = file(source)
- dfp = file(tgt)
- sin = sfp.read(CHUNKLEN)
- while sin:
- din = dfp.read(CHUNKLEN)
- if sin != din:
- break
- sin = sfp.read(CHUNKLEN)
- if sin:
- continue
- try:
- relinkfile(source, tgt)
- print 'Relinked %s' % f
- relinked += 1
- savedbytes += sz
- except OSError, inst:
- print '%s: %s' % (tgt, str(inst))
-
- print 'Relinked %d files (%d bytes reclaimed)' % (relinked, savedbytes)
-
-try:
- cfg = Config(sys.argv)
-except ConfigError, inst:
- print str(inst)
- usage()
- sys.exit(1)
-
-src = os.path.join(cfg.src, '.hg')
-dst = os.path.join(cfg.dst, '.hg')
-candidates = collect(src)
-targets = prune(candidates, dst)
-relink(src, dst, targets)
--- a/contrib/shrink-revlog.py Wed Nov 04 22:14:26 2009 +0100
+++ b/contrib/shrink-revlog.py Sat Nov 07 14:13:15 2009 -0600
@@ -87,12 +87,12 @@
count += 1
finally:
write('\n')
-
+
def report(olddatafn, newdatafn):
oldsize = float(os.stat(olddatafn).st_size)
newsize = float(os.stat(newdatafn).st_size)
- # argh: have to pass an int to %d, because a float >= 2^32
+ # argh: have to pass an int to %d, because a float >= 2^32
# blows up under Python 2.5 or earlier
sys.stdout.write('old file size: %12d bytes (%6.1f MiB)\n'
% (int(oldsize), oldsize/1024/1024))
--- a/doc/Makefile Wed Nov 04 22:14:26 2009 +0100
+++ b/doc/Makefile Sat Nov 07 14:13:15 2009 -0600
@@ -1,6 +1,7 @@
SOURCES=$(wildcard *.[0-9].txt)
MAN=$(SOURCES:%.txt=%)
HTML=$(SOURCES:%.txt=%.html)
+GENDOC=gendoc.py ../mercurial/commands.py ../mercurial/help.py ../help/*.txt
PREFIX=/usr/local
MANDIR=$(PREFIX)/share/man
INSTALL=install -c -m 644
@@ -16,7 +17,7 @@
hg.1.txt: hg.1.gendoc.txt
touch hg.1.txt
-hg.1.gendoc.txt: gendoc.py ../mercurial/commands.py ../mercurial/help.py
+hg.1.gendoc.txt: $(GENDOC)
${PYTHON} gendoc.py > $@.tmp
mv $@.tmp $@
--- a/doc/hg.1.txt Wed Nov 04 22:14:26 2009 +0100
+++ b/doc/hg.1.txt Sat Nov 07 14:13:15 2009 -0600
@@ -30,7 +30,7 @@
files...
indicates one or more filename or relative path filenames; see
- "FILE NAME PATTERNS" for information on pattern matching
+ `File Name Patterns`_ for information on pattern matching
path
indicates a path on the local machine
@@ -72,7 +72,7 @@
BUGS
----
-Probably lots, please post them to the mailing list (See Resources
+Probably lots, please post them to the mailing list (see Resources_
below) when you find them.
SEE ALSO
@@ -93,7 +93,7 @@
COPYING
-------
-Copyright \(C) 2005-2009 Matt Mackall.
+Copyright (C) 2005-2009 Matt Mackall.
Free use of this software is granted under the terms of the GNU General
Public License version 2.
--- a/doc/hgrc.5.txt Wed Nov 04 22:14:26 2009 +0100
+++ b/doc/hgrc.5.txt Sat Nov 07 14:13:15 2009 -0600
@@ -29,50 +29,9 @@
The names of these files depend on the system on which Mercurial is
installed. ``*.rc`` files from a single directory are read in
alphabetical order, later ones overriding earlier ones. Where multiple
-paths are given below, settings from later paths override earlier
+paths are given below, settings from earlier paths override later
ones.
-| (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
-| (Unix) ``<install-root>/etc/mercurial/hgrc``
-
- Per-installation configuration files, searched for in the
- directory where Mercurial is installed. ``<install-root>`` is the
- parent directory of the **hg** executable (or symlink) being run. For
- example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
- in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
- to all Mercurial commands executed by any user in any directory.
-
-| (Unix) ``/etc/mercurial/hgrc.d/*.rc``
-| (Unix) ``/etc/mercurial/hgrc``
-
- Per-system configuration files, for the system on which Mercurial
- is running. Options in these files apply to all Mercurial commands
- executed by any user in any directory. Options in these files
- override per-installation options.
-
-| (Windows) ``<install-dir>\Mercurial.ini`` or else
-| (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` or else
-| (Windows) ``C:\Mercurial\Mercurial.ini``
-
- Per-installation/system configuration files, for the system on
- which Mercurial is running. Options in these files apply to all
- Mercurial commands executed by any user in any directory. Registry
- keys contain PATH-like strings, every part of which must reference
- a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
- be read.
-
-| (Unix) ``$HOME/.hgrc``
-| (Windows) ``%HOME%\Mercurial.ini``
-| (Windows) ``%HOME%\.hgrc``
-| (Windows) ``%USERPROFILE%\Mercurial.ini``
-| (Windows) ``%USERPROFILE%\.hgrc``
-
- Per-user configuration file(s), for the user running Mercurial. On
- Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
- files apply to all Mercurial commands executed by this user in any
- directory. Options in these files override per-installation and
- per-system options.
-
| (Unix, Windows) ``<repo>/.hg/hgrc``
Per-repository configuration options that only apply in a
@@ -81,7 +40,48 @@
this file override options in all other configuration files. On
Unix, most of this file will be ignored if it doesn't belong to a
trusted user or to a trusted group. See the documentation for the
- trusted section below for more details.
+ trusted_ section below for more details.
+
+| (Unix) ``$HOME/.hgrc``
+| (Windows) ``%USERPROFILE%\.hgrc``
+| (Windows) ``%USERPROFILE%\Mercurial.ini``
+| (Windows) ``%HOME%\.hgrc``
+| (Windows) ``%HOME%\Mercurial.ini``
+
+ Per-user configuration file(s), for the user running Mercurial. On
+ Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
+ files apply to all Mercurial commands executed by this user in any
+ directory. Options in these files override per-system and per-installation
+ options.
+
+| (Unix) ``/etc/mercurial/hgrc``
+| (Unix) ``/etc/mercurial/hgrc.d/*.rc``
+
+ Per-system configuration files, for the system on which Mercurial
+ is running. Options in these files apply to all Mercurial commands
+ executed by any user in any directory. Options in these files
+ override per-installation options.
+
+| (Unix) ``<install-root>/etc/mercurial/hgrc``
+| (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
+
+ Per-installation configuration files, searched for in the
+ directory where Mercurial is installed. ``<install-root>`` is the
+ parent directory of the **hg** executable (or symlink) being run. For
+ example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
+ in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
+ to all Mercurial commands executed by any user in any directory.
+
+| (Windows) ``C:\Mercurial\Mercurial.ini``
+| (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
+| (Windows) ``<install-dir>\Mercurial.ini``
+
+ Per-installation/system configuration files, for the system on
+ which Mercurial is running. Options in these files apply to all
+ Mercurial commands executed by any user in any directory. Registry
+ keys contain PATH-like strings, every part of which must reference
+ a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
+ be read.
SYNTAX
------
@@ -97,12 +97,9 @@
eggs
Each line contains one entry. If the lines that follow are indented,
-they are treated as continuations of that entry.
-
-Leading whitespace is removed from values. Empty lines are skipped.
-
-Lines beginning with ``#`` or ``;`` are ignored and may be used to provide
-comments.
+they are treated as continuations of that entry. Leading whitespace is
+removed from values. Empty lines are skipped. Lines beginning with
+``#`` or ``;`` are ignored and may be used to provide comments.
A line of the form ``%include file`` will include ``file`` into the
current configuration file. The inclusion is recursive, which means
@@ -139,9 +136,9 @@
stable5 = latest -b stable
-NOTE: It is possible to create aliases with the same names as existing
-commands, which will then override the original definitions. This is
-almost always a bad idea!
+.. note:: It is possible to create aliases with the same names as
+ existing commands, which will then override the original
+ definitions. This is almost always a bad idea!
``auth``
@@ -232,9 +229,9 @@
of an empty temporary file, where the filtered data must be written by
the command.
-NOTE: the tempfile mechanism is recommended for Windows systems, where
-the standard shell I/O redirection operators often have strange
-effects and may corrupt the contents of your files.
+.. note:: The tempfile mechanism is recommended for Windows systems,
+ where the standard shell I/O redirection operators often have
+ strange effects and may corrupt the contents of your files.
The most common usage is for LF <-> CRLF translation on Windows. For
this, use the "smart" converters which check for binary files::
@@ -264,8 +261,8 @@
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::
+The following example makes ``hg log`` run in verbose mode, and ``hg
+status`` show only the modified files, by default::
[defaults]
log = -v
@@ -312,7 +309,7 @@
email addresses. Cannot be set interactively.
``method``
Optional. Method to use to send email messages. If value is "smtp"
- (default), use SMTP (see section "[smtp]" for configuration).
+ (default), use SMTP (see the SMTP_ section for configuration).
Otherwise, use as name of program to run that acts like sendmail
(takes "-f" option for sender, list of recipients on command line,
message on stdin). Normally, setting this to "sendmail" or
@@ -326,13 +323,13 @@
conversion fails, the text in question is sent as is. Defaults to
empty (explicit) list.
-Order of outgoing email character sets::
+ Order of outgoing email character sets:
- us-ascii always first, regardless of settings
- email.charsets in order given by user
- ui.fallbackencoding if not in email.charsets
- $HGENCODING if not in email.charsets
- utf-8 always last, regardless of settings
+ 1. ``us-ascii``: always first, regardless of settings
+ 2. ``email.charsets``: in order given by user
+ 3. ``ui.fallbackencoding``: if not in email.charsets
+ 4. ``$HGENCODING``: if not in email.charsets
+ 5. ``utf-8``: always last, regardless of settings
Email example::
@@ -494,7 +491,7 @@
Most hooks are run with environment variables set that give useful
additional information. For each hook below, the environment
-variables it is passed are listed with names of the form "$HG_foo".
+variables it is passed are listed with names of the form ``$HG_foo``.
``changegroup``
Run after a changegroup has been added via push, pull or unbundle.
@@ -575,16 +572,16 @@
in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
-NOTE: it is generally better to use standard hooks rather than the
-generic pre- and post- command hooks as they are guaranteed to be
-called in the appropriate contexts for influencing transactions.
-Also, hooks like "commit" will be called in all contexts that
-generate a commit (e.g. tag) and not just the commit command.
+.. note:: It is generally better to use standard hooks rather than the
+ generic pre- and post- command hooks as they are guaranteed to be
+ called in the appropriate contexts for influencing transactions.
+ Also, hooks like "commit" will be called in all contexts that
+ generate a commit (e.g. tag) and not just the commit command.
-NOTE: Environment variables with empty values may not be passed to
-hooks on platforms such as Windows. As an example, ``$HG_PARENT2`` will
-have an empty value under Unix-like platforms for non-merge
-changesets, while it will not be available at all under Windows.
+.. note:: Environment variables with empty values may not be passed to
+ hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
+ will have an empty value under Unix-like platforms for non-merge
+ changesets, while it will not be available at all under Windows.
The syntax for Python hooks is as follows::
@@ -649,7 +646,7 @@
``eol``
When set to 'strict' patch content and patched files end of lines
- are preserved. When set to 'lf' or 'crlf', both files end of lines
+ are preserved. When set to ``lf`` or ``crlf``, both files end of lines
are ignored when patching and the result line endings are
normalized to either LF (Unix) or CRLF (Windows).
Default: strict.
@@ -738,17 +735,17 @@
Whether to include the .hg_archival.txt file containing meta data
(hashes for the repository base and for tip) in archives created
by the hg archive command or downloaded via hgweb.
- Default is true.
+ Default is True.
``askusername``
Whether to prompt for a username when committing. If True, and
neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
be prompted to enter a username. If no username is entered, the
- default USER@HOST is used instead.
+ default ``USER@HOST`` is used instead.
Default is False.
``debug``
Print debugging information. True or False. Default is False.
``editor``
- The editor to use during a commit. Default is ``$EDITOR`` or "vi".
+ The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
``fallbackencoding``
Encoding to try if it's not possible to decode the changelog using
UTF-8. Default is ISO-8859-1.
@@ -777,15 +774,15 @@
fail to merge
For more information on configuring merge tools see the
-merge-tools section.
+merge-tools_ section.
``patch``
- command to use to apply patches. Look for 'gpatch' or 'patch' in
+ command to use to apply patches. Look for ``gpatch`` or ``patch`` in
PATH if unset.
``quiet``
Reduce the amount of output printed. True or False. Default is False.
``remotecmd``
- remote command to use for clone/push/pull operations. Default is 'hg'.
+ remote command to use for clone/push/pull operations. Default is ``hg``.
``report_untrusted``
Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
trusted user or group. True or False. Default is True.
@@ -796,7 +793,7 @@
backslash character (``\``)).
Default is False.
``ssh``
- command to use for SSH connections. Default is '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.
@@ -805,13 +802,18 @@
``timeout``
The timeout used when a lock is held (in seconds), a negative value
means no timeout. Default is 600.
+``traceback``
+ Mercurial always prints a traceback when an unknown exception
+ occurs. Setting this to True will make Mercurial print a traceback
+ on all exceptions, even those recognized by Mercurial (such as
+ IOError or MemoryError). Default is False.
``username``
The committer of a changeset created when running "commit".
- Typically a person's name and email address, e.g. "Fred Widget
- <fred@example.com>". Default is ``$EMAIL`` or username@hostname. If
+ Typically a person's name and email address, e.g. ``Fred Widget
+ <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
the username in hgrc is empty, it has to be specified manually or
in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
- "username =" in the system hgrc).
+ ``username =`` in the system hgrc).
``verbose``
Increase the amount of output printed. True or False. Default is False.
@@ -830,19 +832,19 @@
``allowbz2``
(DEPRECATED) Whether to allow .tar.bz2 downloading of repository
revisions.
- Default is false.
+ Default is False.
``allowgz``
(DEPRECATED) Whether to allow .tar.gz downloading of repository
revisions.
- Default is false.
+ Default is False.
``allowpull``
- Whether to allow pulling from the repository. Default is true.
+ Whether to allow pulling from the repository. Default is True.
``allow_push``
Whether to allow pushing to the repository. If empty or not set,
push is not allowed. If the special value ``*``, any remote user can
push, including unauthenticated users. Otherwise, the remote user
must have been authenticated, and the authenticated user name must
- be present in this list (separated by whitespace or ","). The
+ be present in this list (separated by whitespace or ``,``). The
contents of the allow_push list are examined after the deny_push
list.
``allow_read``
@@ -850,7 +852,7 @@
the contents of deny_read, this list determines whether to grant
repository access to the user. If this list is not empty, and the
user is unauthenticated or not present in the list (separated by
- whitespace or ","), then access is denied for the user. If the
+ whitespace or ``,``), then access is denied for the user. If the
list is empty or not set, then access is permitted to all users by
default. Setting allow_read to the special value ``*`` is equivalent
to it not being set (i.e. access is permitted to all users). The
@@ -858,11 +860,11 @@
list.
``allowzip``
(DEPRECATED) Whether to allow .zip downloading of repository
- revisions. Default is false. This feature creates temporary files.
+ revisions. Default is False. This feature creates temporary files.
``baseurl``
Base URL to use when publishing URLs in other locations, so
third-party tools like email notification hooks can construct
- URLs. Example: "http://hgserver/repos/"
+ URLs. Example: ``http://hgserver/repos/``.
``contact``
Name or email address of the person in charge of the repository.
Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
@@ -871,13 +873,13 @@
push is not denied. If the special value ``*``, all remote users are
denied push. Otherwise, unauthenticated users are all denied, and
any authenticated user name present in this list (separated by
- whitespace or ",") is also denied. The contents of the deny_push
+ whitespace or ``,``) is also denied. The contents of the deny_push
list are examined before the allow_push list.
``deny_read``
Whether to deny reading/viewing of the repository. If this list is
not empty, unauthenticated users are all denied, and any
authenticated user name present in this list (separated by
- whitespace or ",") is also denied access to the repository. If set
+ whitespace or ``,``) is also denied access to the repository. If set
to the special value ``*``, all remote users are denied access
(rarely needed ;). If deny_read is empty or not set, the
determination of repository access depends on the presence and
@@ -902,9 +904,9 @@
Where to output the error log. Default is stderr.
``hidden``
Whether to hide the repository in the hgwebdir index.
- Default is false.
+ Default is False.
``ipv6``
- Whether to use IPv6. Default is false.
+ Whether to use IPv6. Default is False.
``name``
Repository name to use in the web interface. Default is current
working directory.
@@ -918,12 +920,12 @@
Prefix path to serve from. Default is '' (server root).
``push_ssl``
Whether to require that inbound pushes be transported over SSL to
- prevent password sniffing. Default is true.
+ prevent password sniffing. Default is True.
``staticurl``
Base URL to use for static files. If unset, static files (e.g. the
hgicon.png favicon) will be served by the CGI script itself. Use
this setting to serve them directly with the HTTP server.
- Example: "http://hgserver/static/"
+ Example: ``http://hgserver/static/``.
``stripes``
How many lines a "zebra stripe" should span in multiline output.
Default is 1; set to 0 to disable.
--- a/doc/rst2man.py Wed Nov 04 22:14:26 2009 +0100
+++ b/doc/rst2man.py Sat Nov 07 14:13:15 2009 -0600
@@ -8,7 +8,7 @@
Simple man page writer for reStructuredText.
Man pages (short for "manual pages") contain system documentation on unix-like
-systems. The pages are grouped in numbered sections:
+systems. The pages are grouped in numbered sections:
1 executable programs and shell commands
2 system calls
@@ -140,7 +140,7 @@
text.append('|%s|.\n' % ('|'.join(self._coldefs)))
for row in self._rows:
# row = array of cells. cell = array of lines.
- text.append('_\n') # line above
+ text.append('_\n') # line above
text.append('T{\n')
for i in range(len(row)):
cell = row[i]
@@ -184,8 +184,8 @@
"title" : "", "title_upper": "",
"subtitle" : "",
"manual_section" : "", "manual_group" : "",
- "author" : [],
- "date" : "",
+ "author" : [],
+ "date" : "",
"copyright" : "",
"version" : "",
}
@@ -216,7 +216,7 @@
'literal_block' : ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'),
'option_list_item' : ('.TP\n', ''),
-
+
'reference' : (r'\%', r'\:'),
'emphasis': ('\\fI', '\\fP'),
'strong' : ('\\fB', '\\fP'),
@@ -263,7 +263,7 @@
elif (self.body[i-1][:3] == '.B ' and
self.body[i-2][:4] == '.TP\n'):
self.body[i] = '.\n'
- elif (self.body[i-1] == '\n' and
+ elif (self.body[i-1] == '\n' and
self.body[i-2][0] != '.' and
(self.body[i-3][:7] == '.TP\n.B '
or self.body[i-3][:4] == '\n.B ')
@@ -564,10 +564,10 @@
def depart_document(self, node):
if self._docinfo['author']:
- self.body.append('.SH AUTHOR\n%s\n'
+ self.body.append('.SH AUTHOR\n%s\n'
% ', '.join(self._docinfo['author']))
skip = ('author', 'copyright', 'date',
- 'manual_group', 'manual_section',
+ 'manual_group', 'manual_section',
'subtitle',
'title', 'title_upper', 'version')
for name in self._docinfo_keys:
@@ -587,7 +587,7 @@
label = self.language.labels.get(name, name)
self.body.append("\n%s: %s\n" % (label, self._docinfo[name]) )
if self._docinfo['copyright']:
- self.body.append('.SH COPYRIGHT\n%s\n'
+ self.body.append('.SH COPYRIGHT\n%s\n'
% self._docinfo['copyright'])
self.body.append( self.comment(
'Generated by docutils manpage writer.\n' ) )
@@ -896,7 +896,7 @@
def visit_paragraph(self, node):
# ``.PP`` : Start standard indented paragraph.
# ``.LP`` : Start block paragraph, all except the first.
- # ``.P [type]`` : Start paragraph type.
+ # ``.P [type]`` : Start paragraph type.
# NOTE dont use paragraph starts because they reset indentation.
# ``.sp`` is only vertical space
self.ensure_eol()
--- a/help/environment.txt Wed Nov 04 22:14:26 2009 +0100
+++ b/help/environment.txt Sat Nov 07 14:13:15 2009 -0600
@@ -50,7 +50,7 @@
- hgrc files from the HGRCPATH
- EMAIL
- interactive prompt
- - LOGNAME (with '@hostname' appended)
+ - LOGNAME (with ``@hostname`` appended)
(deprecated, use .hgrc)
--- a/help/templates.txt Wed Nov 04 22:14:26 2009 +0100
+++ b/help/templates.txt Sat Nov 07 14:13:15 2009 -0600
@@ -75,11 +75,11 @@
the timezone: "Mon Sep 04 15:13:13 2006 0700".
:domain: Any text. Finds the first string that looks like an
email address, and extracts just the domain
- component. Example: 'User <user@example.com>' becomes
- 'example.com'.
+ component. Example: ``User <user@example.com>`` becomes
+ ``example.com``.
:email: Any text. Extracts the first string that looks like
- an email address. Example: 'User <user@example.com>'
- becomes 'user@example.com'.
+ an email address. Example: ``User <user@example.com>``
+ becomes ``user@example.com``.
:escape: Any text. Replaces the special XML/XHTML characters
"&", "<" and ">" with XML entities.
:fill68: Any text. Wraps the text to fit in 68 columns.
--- a/hgext/churn.py Wed Nov 04 22:14:26 2009 +0100
+++ b/hgext/churn.py Sat Nov 07 14:13:15 2009 -0600
@@ -23,14 +23,15 @@
return t
def changedlines(ui, repo, ctx1, ctx2, fns):
- lines = 0
+ added, removed = 0, 0
fmatch = cmdutil.matchfiles(repo, fns)
diff = ''.join(patch.diff(repo, ctx1.node(), ctx2.node(), fmatch))
for l in diff.split('\n'):
- if (l.startswith("+") and not l.startswith("+++ ") or
- l.startswith("-") and not l.startswith("--- ")):
- lines += 1
- return lines
+ if l.startswith("+") and not l.startswith("+++ "):
+ added += 1
+ elif l.startswith("-") and not l.startswith("--- "):
+ removed += 1
+ return (added, removed)
def countrate(ui, repo, amap, *pats, **opts):
"""Calculate stats"""
@@ -47,43 +48,43 @@
tmpl.show(ctx)
return ui.popbuffer()
- count = pct = 0
+ state = {'count': 0, 'pct': 0}
rate = {}
df = False
if opts.get('date'):
df = util.matchdate(opts['date'])
m = cmdutil.match(repo, pats, opts)
- for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, m, opts):
- if not st == 'add':
- continue
-
+ def prep(ctx, fns):
rev = ctx.rev()
if df and not df(ctx.date()[0]): # doesn't match date format
- continue
+ return
key = getkey(ctx)
key = amap.get(key, key) # alias remap
if opts.get('changesets'):
- rate[key] = rate.get(key, 0) + 1
+ rate[key] = (rate.get(key, (0,))[0] + 1, 0)
else:
parents = ctx.parents()
if len(parents) > 1:
ui.note(_('Revision %d is a merge, ignoring...\n') % (rev,))
- continue
+ return
ctx1 = parents[0]
lines = changedlines(ui, repo, ctx1, ctx, fns)
- rate[key] = rate.get(key, 0) + lines
+ rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
if opts.get('progress'):
- count += 1
- newpct = int(100.0 * count / max(len(repo), 1))
- if pct < newpct:
- pct = newpct
- ui.write("\r" + _("generating stats: %d%%") % pct)
+ state['count'] += 1
+ newpct = int(100.0 * state['count'] / max(len(repo), 1))
+ if state['pct'] < newpct:
+ state['pct'] = newpct
+ ui.write("\r" + _("generating stats: %d%%") % state['pct'])
sys.stdout.flush()
+ for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
+ continue
+
if opts.get('progress'):
ui.write("\r")
sys.stdout.flush()
@@ -143,20 +144,35 @@
if not rate:
return
- sortkey = ((not opts.get('sort')) and (lambda x: -x[1]) or None)
+ sortkey = ((not opts.get('sort')) and (lambda x: -sum(x[1])) or None)
rate.sort(key=sortkey)
# Be careful not to have a zero maxcount (issue833)
- maxcount = float(max(v for k, v in rate)) or 1.0
+ maxcount = float(max(sum(v) for k, v in rate)) or 1.0
maxname = max(len(k) for k, v in rate)
ttywidth = util.termwidth()
ui.debug("assuming %i character terminal\n" % ttywidth)
- width = ttywidth - maxname - 2 - 6 - 2 - 2
+ width = ttywidth - maxname - 2 - 2 - 2
- for date, count in rate:
- print "%s %6d %s" % (pad(date, maxname), count,
- "*" * int(count * width / maxcount))
+ if opts.get('diffstat'):
+ width -= 15
+ def format(name, (added, removed)):
+ return "%s %15s %s%s\n" % (pad(name, maxname),
+ '+%d/-%d' % (added, removed),
+ '+' * charnum(added),
+ '-' * charnum(removed))
+ else:
+ width -= 6
+ def format(name, count):
+ return "%s %6d %s\n" % (pad(name, maxname), sum(count),
+ '*' * charnum(sum(count)))
+
+ def charnum(count):
+ return int(round(count*width/maxcount))
+
+ for name, count in rate:
+ ui.write(format(name, count))
cmdtable = {
@@ -169,6 +185,7 @@
_('strftime-compatible format for grouping by date')),
('c', 'changesets', False, _('count rate by number of changesets')),
('s', 'sort', False, _('sort by key (default: sort by count)')),
+ ('', 'diffstat', False, _('display added/removed lines separately')),
('', 'aliases', '', _('file with email aliases')),
('', 'progress', None, _('show progress'))],
_("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
--- a/hgext/color.py Wed Nov 04 22:14:26 2009 +0100
+++ b/hgext/color.py Sat Nov 07 14:13:15 2009 -0600
@@ -235,7 +235,7 @@
'changed': ['white'],
'trailingwhitespace': ['bold', 'red_background']}
-def uisetup(ui):
+def extsetup(ui):
'''Initialize the extension.'''
_setupcmd(ui, 'diff', commands.table, colordiff, _diff_effects)
_setupcmd(ui, 'incoming', commands.table, None, _diff_effects)
@@ -249,15 +249,17 @@
_setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects)
_setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
except KeyError:
- # The mq extension is not enabled
- pass
+ mq = None
try:
rec = extensions.find('record')
_setupcmd(ui, 'record', rec.cmdtable, colordiff, _diff_effects)
except KeyError:
- # The record extension is not enabled
- pass
+ rec = None
+
+ if mq and rec:
+ _setupcmd(ui, 'qrecord', rec.cmdtable, colordiff, _diff_effects)
+
def _setupcmd(ui, cmd, table, func, effectsmap):
'''patch in command to command table and load effect map'''
--- a/hgext/convert/darcs.py Wed Nov 04 22:14:26 2009 +0100
+++ b/hgext/convert/darcs.py Sat Nov 07 14:13:15 2009 -0600
@@ -118,7 +118,7 @@
output, status = self.run('revert', all=True, repodir=self.tmppath)
self.checkexit(status, output)
- def getchanges(self, rev):
+ def getchanges(self, rev):
copies = {}
changes = []
man = None
--- a/hgext/mq.py Wed Nov 04 22:14:26 2009 +0100
+++ b/hgext/mq.py Sat Nov 07 14:13:15 2009 -0600
@@ -1129,8 +1129,12 @@
self.ui.write(_("no patches applied\n"))
return
qp = self.qparents(repo, top)
+ if opts.get('inverse'):
+ node1, node2 = None, qp
+ else:
+ node1, node2 = qp, None
self._diffopts = patch.diffopts(self.ui, opts)
- self.printdiff(repo, qp, files=pats, opts=opts)
+ self.printdiff(repo, node1, node2, files=pats, opts=opts)
def refresh(self, repo, pats=None, **opts):
if len(self.applied) == 0:
@@ -1910,11 +1914,10 @@
summary=opts.get('summary'))
def setupheaderopts(ui, opts):
- def do(opt, val):
- if not opts[opt] and opts['current' + opt]:
- opts[opt] = val
- do('user', ui.username())
- do('date', "%d %d" % util.makedate())
+ if not opts.get('user') and opts.get('currentuser'):
+ opts['user'] = ui.username()
+ if not opts.get('date') and opts.get('currentdate'):
+ opts['date'] = "%d %d" % util.makedate()
def new(ui, repo, patch, *args, **opts):
"""create a new patch
--- a/hgext/record.py Wed Nov 04 22:14:26 2009 +0100
+++ b/hgext/record.py Sat Nov 07 14:13:15 2009 -0600
@@ -315,6 +315,7 @@
return ret
pos, total = 0, len(chunks) - 1
while chunks:
+ pos = total - len(chunks) + 1
chunk = chunks.pop()
if isinstance(chunk, header):
# new-file mark
@@ -350,7 +351,6 @@
applied[chunk.filename()].append(chunk)
else:
fixoffset += chunk.removed - chunk.added
- pos = pos + 1
return reduce(operator.add, [h for h in applied.itervalues()
if h[0].special() or len(h) > 1], [])
@@ -531,7 +531,7 @@
}
-def extsetup():
+def uisetup(ui):
try:
mq = extensions.find('mq')
except KeyError:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/relink.py Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,149 @@
+# Mercurial extension to provide 'hg relink' command
+#
+# Copyright (C) 2007 Brendan Cully <brendan@kublai.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+"""recreates hardlinks between repository clones"""
+
+from mercurial import cmdutil, hg, util
+from mercurial.i18n import _
+import os, stat
+
+def relink(ui, repo, origin=None, **opts):
+ """recreate hardlinks between two repositories
+
+ When repositories are cloned locally, their data files will be hardlinked
+ so that they only use the space of a single repository.
+
+ Unfortunately, subsequent pulls into either repository will break hardlinks
+ for any files touched by the new changesets, even if both repositories end
+ up pulling the same changes.
+
+ Similarly, passing --rev to "hg clone" will fail to use
+ any hardlinks, falling back to a complete copy of the source repository.
+
+ This command lets you recreate those hardlinks and reclaim that wasted
+ space.
+
+ This repository will be relinked to share space with ORIGIN, which must be
+ on the same local disk. If ORIGIN is omitted, looks for "default-relink",
+ then "default", in [paths].
+
+ Do not attempt any read operations on this repository while the command is
+ running. (Both repositories will be locked against writes.)
+ """
+ src = hg.repository(
+ cmdutil.remoteui(repo, opts),
+ ui.expandpath(origin or 'default-relink', origin or 'default'))
+ if not src.local():
+ raise util.Abort('must specify local origin repository')
+ ui.status(_('relinking %s to %s\n') % (src.store.path, repo.store.path))
+ locallock = repo.lock()
+ try:
+ remotelock = src.lock()
+ try:
+ candidates = collect(src.store.path, ui)
+ targets = prune(candidates, repo.store.path, ui)
+ do_relink(src.store.path, repo.store.path, targets, ui)
+ finally:
+ remotelock.release()
+ finally:
+ locallock.release()
+
+def collect(src, ui):
+ seplen = len(os.path.sep)
+ candidates = []
+ for dirpath, dirnames, filenames in os.walk(src):
+ relpath = dirpath[len(src) + seplen:]
+ for filename in filenames:
+ if not filename[-2:] in ('.d', '.i'):
+ continue
+ st = os.stat(os.path.join(dirpath, filename))
+ if not stat.S_ISREG(st.st_mode):
+ continue
+ candidates.append((os.path.join(relpath, filename), st))
+
+ ui.status(_('collected %d candidate storage files\n') % len(candidates))
+ return candidates
+
+def prune(candidates, dst, ui):
+ def linkfilter(dst, st):
+ try:
+ ts = os.stat(dst)
+ except OSError:
+ # Destination doesn't have this file?
+ return False
+ if st.st_ino == ts.st_ino:
+ return False
+ if st.st_dev != ts.st_dev:
+ # No point in continuing
+ raise util.Abort(
+ _('source and destination are on different devices'))
+ if st.st_size != ts.st_size:
+ return False
+ return st
+
+ targets = []
+ for fn, st in candidates:
+ tgt = os.path.join(dst, fn)
+ ts = linkfilter(tgt, st)
+ if not ts:
+ ui.debug(_('not linkable: %s\n') % fn)
+ continue
+ targets.append((fn, ts.st_size))
+
+ ui.status(_('pruned down to %d probably relinkable files\n') % len(targets))
+ return targets
+
+def do_relink(src, dst, files, ui):
+ def relinkfile(src, dst):
+ bak = dst + '.bak'
+ os.rename(dst, bak)
+ try:
+ os.link(src, dst)
+ except OSError:
+ os.rename(bak, dst)
+ raise
+ os.remove(bak)
+
+ CHUNKLEN = 65536
+ relinked = 0
+ savedbytes = 0
+
+ pos = 0
+ total = len(files)
+ for f, sz in files:
+ pos += 1
+ source = os.path.join(src, f)
+ tgt = os.path.join(dst, f)
+ sfp = file(source)
+ dfp = file(tgt)
+ sin = sfp.read(CHUNKLEN)
+ while sin:
+ din = dfp.read(CHUNKLEN)
+ if sin != din:
+ break
+ sin = sfp.read(CHUNKLEN)
+ if sin:
+ ui.debug(_('not linkable: %s\n') % f)
+ continue
+ try:
+ relinkfile(source, tgt)
+ ui.progress(_('relink'), pos, f, _(' files'), total)
+ relinked += 1
+ savedbytes += sz
+ except OSError, inst:
+ ui.warn(_('%s: %s\n') % (tgt, str(inst)))
+
+ ui.status(_('relinked %d files (%d bytes reclaimed)\n') %
+ (relinked, savedbytes))
+
+cmdtable = {
+ 'relink': (
+ relink,
+ [],
+ _('[ORIGIN]')
+ )
+}
--- a/mercurial/bundlerepo.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/bundlerepo.py Sat Nov 07 14:13:15 2009 -0600
@@ -74,12 +74,12 @@
return False
return rev in self.basemap
def bundlebase(self, rev): return self.basemap[rev]
- def chunk(self, rev, df=None, cachelen=4096):
+ def _chunk(self, rev):
# Warning: in case of bundle, the diff is against bundlebase,
# not against rev - 1
# XXX: could use some caching
if not self.bundle(rev):
- return revlog.revlog.chunk(self, rev, df)
+ return revlog.revlog._chunk(self, rev)
self.bundlefile.seek(self.start(rev))
return self.bundlefile.read(self.length(rev))
@@ -89,7 +89,7 @@
# hot path for bundle
revb = self.rev(self.bundlebase(rev2))
if revb == rev1:
- return self.chunk(rev2)
+ return self._chunk(rev2)
elif not self.bundle(rev1) and not self.bundle(rev2):
return revlog.revlog.revdiff(self, rev1, rev2)
@@ -116,7 +116,7 @@
text = revlog.revlog.revision(self, iter_node)
while chain:
- delta = self.chunk(chain.pop())
+ delta = self._chunk(chain.pop())
text = mdiff.patches(text, [delta])
p1, p2 = self.parents(node)
--- a/mercurial/byterange.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/byterange.py Sat Nov 07 14:13:15 2009 -0600
@@ -261,6 +261,8 @@
host, port = splitport(host)
if port is None:
port = ftplib.FTP_PORT
+ else:
+ port = int(port)
# username/password handling
user, host = splituser(host)
--- a/mercurial/changelog.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/changelog.py Sat Nov 07 14:13:15 2009 -0600
@@ -198,7 +198,7 @@
return (manifest, user, (time, timezone), files, desc, extra)
def add(self, manifest, files, desc, transaction, p1, p2,
- user, date=None, extra={}):
+ user, date=None, extra=None):
user = user.strip()
# An empty username or a username with a "\n" will make the
# revision text contain two "\n\n" sequences -> corrupt
--- a/mercurial/cmdutil.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/cmdutil.py Sat Nov 07 14:13:15 2009 -0600
@@ -1022,24 +1022,26 @@
def finddate(ui, repo, date):
"""Find the tipmost changeset that matches the given date spec"""
+
df = util.matchdate(date)
- get = util.cachefunc(lambda r: repo[r])
m = matchall(repo)
results = {}
- for st, rev, fns in walkchangerevs(ui, repo, m, get, {'rev':None}):
- if st == 'add':
- d = get(rev).date()
- if df(d[0]):
- results[rev] = d
- elif st == 'iter':
- if rev in results:
- ui.status(_("Found revision %s from %s\n") %
- (rev, util.datestr(results[rev])))
- return str(rev)
+
+ def prep(ctx, fns):
+ d = ctx.date()
+ if df(d[0]):
+ results[ctx.rev()] = d
+
+ for ctx in walkchangerevs(repo, m, {'rev': None}, prep):
+ rev = ctx.rev()
+ if rev in results:
+ ui.status(_("Found revision %s from %s\n") %
+ (rev, util.datestr(results[rev])))
+ return str(rev)
raise util.Abort(_("revision matching date not found"))
-def walkchangerevs(ui, repo, match, opts):
+def walkchangerevs(repo, match, opts, prepare):
'''Iterate over files and the revs in which they changed.
Callers most commonly need to iterate backwards over the history
@@ -1050,15 +1052,9 @@
window, we first walk forwards to gather data, then in the desired
order (usually backwards) to display it.
- This function returns an iterator. The iterator yields 3-tuples.
- They will be of one of the following forms:
-
- "add", rev, fns: out-of-order traversal of the given filenames
- fns, which changed during revision rev - use to gather data for
- possible display
-
- "iter", rev, None: in-order traversal of the revs earlier iterated
- over with "add" - use to display data'''
+ This function returns an iterator yielding contexts. Before
+ yielding each context, the iterator will first call the prepare
+ function on each context in the window in forward order.'''
def increasing_windows(start, end, windowsize=8, sizelimit=512):
if start < end:
@@ -1093,6 +1089,7 @@
# No files, no patterns. Display all revs.
wanted = set(revs)
copies = []
+
if not slowpath:
# Only files, no patterns. Check the history of each file.
def filerevgen(filelog, node):
@@ -1129,8 +1126,6 @@
slowpath = True
break
else:
- ui.warn(_('%s:%s copy source revision cannot be found!\n')
- % (file_, short(node)))
continue
for rev, copied in filerevgen(filelog, node):
if rev <= maxrev:
@@ -1215,6 +1210,7 @@
return rev in wanted
for i, window in increasing_windows(0, len(revs)):
+ change = util.cachefunc(repo.changectx)
nrevs = [rev for rev in revs[i:i+window] if want(rev)]
for rev in sorted(nrevs):
fns = fncache.get(rev)
@@ -1225,9 +1221,9 @@
if match(f):
yield f
fns = fns_generator()
- yield 'add', ctx, fns
+ prepare(ctx, fns)
for rev in nrevs:
- yield 'iter', change(rev), None
+ yield change(rev)
return iterate()
def commit(ui, repo, commitfunc, pats, opts):
--- a/mercurial/commands.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/commands.py Sat Nov 07 14:13:15 2009 -0600
@@ -8,8 +8,8 @@
from node import hex, nullid, nullrev, short
from lock import release
from i18n import _, gettext
-import os, re, sys, subprocess, difflib, time, tempfile
-import hg, util, revlog, bundlerepo, extensions, copies, context, error
+import os, re, sys, difflib, time, tempfile
+import hg, util, revlog, bundlerepo, extensions, copies, error
import patch, help, mdiff, url, encoding
import archival, changegroup, cmdutil, sshserver, hbisect
from hgweb import server
@@ -31,7 +31,6 @@
"""
bad = []
- exacts = {}
names = []
m = cmdutil.match(repo, pats, opts)
oldbad = m.bad
@@ -371,14 +370,14 @@
# update state
node = repo.lookup(rev or '.')
- if good:
- state['good'].append(node)
- elif bad:
- state['bad'].append(node)
- elif skip:
- state['skip'].append(node)
-
- hbisect.save_state(repo, state)
+ if good or bad or skip:
+ if good:
+ state['good'].append(node)
+ elif bad:
+ state['bad'].append(node)
+ elif skip:
+ state['skip'].append(node)
+ hbisect.save_state(repo, state)
if not check_state(state):
return
@@ -450,8 +449,7 @@
"""
hexfunc = ui.debugflag and hex or short
- activebranches = [encoding.tolocal(repo[n].branch())
- for n in repo.heads()]
+ activebranches = [repo[n].branch() for n in repo.heads()]
def testactive(tag, node):
realhead = tag in activebranches
open = node in repo.branchheads(tag, closed=False)
@@ -462,8 +460,9 @@
for isactive, node, tag in branches:
if (not active) or isactive:
+ encodedtag = encoding.tolocal(tag)
if ui.quiet:
- ui.write("%s\n" % tag)
+ ui.write("%s\n" % encodedtag)
else:
hn = repo.lookup(node)
if isactive:
@@ -474,8 +473,8 @@
notice = ' (closed)'
else:
notice = ' (inactive)'
- rev = str(node).rjust(31 - encoding.colwidth(tag))
- data = tag, rev, hexfunc(hn), notice
+ rev = str(node).rjust(31 - encoding.colwidth(encodedtag))
+ data = encodedtag, rev, hexfunc(hn), notice
ui.write("%s %s:%s%s\n" % data)
def bundle(ui, repo, fname, dest=None, **opts):
@@ -591,22 +590,36 @@
The location of the source is added to the new repository's
.hg/hgrc file, as the default to be used for future pulls.
- If you use the -r/--rev option to clone up to a specific revision,
- no subsequent revisions (including subsequent tags) will be
- present in the cloned repository. This option implies --pull, even
- on local repositories.
-
- By default, clone will check out the head of the 'default' branch.
- If the -U/--noupdate option is used, the new clone will contain
- only a repository (.hg) and no working copy (the working copy
- parent is the null revision).
-
See 'hg help urls' for valid source format details.
It is possible to specify an ssh:// URL as the destination, but no
.hg/hgrc and working directory will be created on the remote side.
Please see 'hg help urls' for important details about ssh:// URLs.
+ If the -U/--noupdate option is specified, the new clone will contain
+ only a repository (.hg) and no working copy (the working copy parent
+ will be the null changeset). Otherwise, clone will initially check
+ out (in order of precedence):
+
+ a) the changeset, tag or branch specified with -u/--updaterev
+ b) the changeset, tag or branch given with the first -r/--rev
+ c) the head of the default branch
+
+ Use 'hg clone -u . src dst' to checkout the source repository's
+ parent changeset (applicable for local source repositories only).
+
+ A set of changesets (tags, or branch names) to pull may be specified
+ by listing each changeset (tag, or branch name) with -r/--rev.
+ If -r/--rev is used, the cloned repository will contain only a subset
+ of the changesets of the source repository. Only the set of changesets
+ defined by all -r/--rev options (including their direct and indirect
+ parent changesets) will be pulled into the destination repository.
+ No subsequent changesets (including subsequent tags) will be present
+ in the destination.
+
+ Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
+ local source repositories.
+
For efficiency, hardlinks are used for cloning whenever the source
and destination are on the same filesystem (note this applies only
to the repository data, not to the checked out files). Some
@@ -626,11 +639,14 @@
this is not compatible with certain extensions that place their
metadata under the .hg directory, such as mq.
"""
+ if opts.get('noupdate') and opts.get('updaterev'):
+ raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
+
hg.clone(cmdutil.remoteui(ui, opts), source, dest,
pull=opts.get('pull'),
stream=opts.get('uncompressed'),
rev=opts.get('rev'),
- update=not opts.get('noupdate'))
+ update=opts.get('updaterev') or not opts.get('noupdate'))
def commit(ui, repo, *pats, **opts):
"""commit the specified files or all outstanding changes
@@ -1013,15 +1029,12 @@
# check username
ui.status(_("Checking username...\n"))
- user = os.environ.get("HGUSER")
- if user is None:
- user = ui.config("ui", "username")
- if user is None:
- user = os.environ.get("EMAIL")
- if not user:
- ui.warn(" ")
- ui.username()
+ try:
+ user = ui.username()
+ except util.Abort, e:
+ ui.write(" %s\n" % e)
ui.write(_(" (specify a username in your .hgrc file)\n"))
+ problems += 1
if not problems:
ui.status(_("No problems detected\n"))
@@ -1086,6 +1099,7 @@
revs = opts.get('rev')
change = opts.get('change')
stat = opts.get('stat')
+ inv = opts.get('inverse')
if revs and change:
msg = _('cannot specify --rev and --change at the same time')
@@ -1096,6 +1110,9 @@
else:
node1, node2 = cmdutil.revpair(repo, revs)
+ if inv:
+ node1, node2 = node2, node1
+
if stat:
opts['unified'] = '0'
diffopts = patch.diffopts(ui, opts)
@@ -1302,61 +1319,62 @@
matchfn = cmdutil.match(repo, pats, opts)
found = False
follow = opts.get('follow')
- for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, matchfn, opts):
- if st == 'add':
- rev = ctx.rev()
- pctx = ctx.parents()[0]
- parent = pctx.rev()
- matches.setdefault(rev, {})
- matches.setdefault(parent, {})
- files = revfiles.setdefault(rev, [])
- for fn in fns:
- flog = getfile(fn)
+
+ def prep(ctx, fns):
+ rev = ctx.rev()
+ pctx = ctx.parents()[0]
+ parent = pctx.rev()
+ matches.setdefault(rev, {})
+ matches.setdefault(parent, {})
+ files = revfiles.setdefault(rev, [])
+ for fn in fns:
+ flog = getfile(fn)
+ try:
+ fnode = ctx.filenode(fn)
+ except error.LookupError:
+ continue
+
+ copied = flog.renamed(fnode)
+ copy = follow and copied and copied[0]
+ if copy:
+ copies.setdefault(rev, {})[fn] = copy
+ if fn in skip:
+ if copy:
+ skip[copy] = True
+ continue
+ files.append(fn)
+
+ if fn not in matches[rev]:
+ grepbody(fn, rev, flog.read(fnode))
+
+ pfn = copy or fn
+ if pfn not in matches[parent]:
try:
- fnode = ctx.filenode(fn)
+ fnode = pctx.filenode(pfn)
+ grepbody(pfn, parent, flog.read(fnode))
except error.LookupError:
- continue
-
- copied = flog.renamed(fnode)
- copy = follow and copied and copied[0]
+ pass
+
+ for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
+ rev = ctx.rev()
+ parent = ctx.parents()[0].rev()
+ for fn in sorted(revfiles.get(rev, [])):
+ states = matches[rev][fn]
+ copy = copies.get(rev, {}).get(fn)
+ if fn in skip:
if copy:
- copies.setdefault(rev, {})[fn] = copy
- if fn in skip:
+ skip[copy] = True
+ continue
+ pstates = matches.get(parent, {}).get(copy or fn, [])
+ if pstates or states:
+ r = display(fn, ctx, pstates, states)
+ found = found or r
+ if r and not opts.get('all'):
+ skip[fn] = True
if copy:
skip[copy] = True
- continue
- files.append(fn)
-
- if fn not in matches[rev]:
- grepbody(fn, rev, flog.read(fnode))
-
- pfn = copy or fn
- if pfn not in matches[parent]:
- try:
- fnode = pctx.filenode(pfn)
- grepbody(pfn, parent, flog.read(fnode))
- except error.LookupError:
- pass
- elif st == 'iter':
- rev = ctx.rev()
- parent = ctx.parents()[0].rev()
- for fn in sorted(revfiles.get(rev, [])):
- states = matches[rev][fn]
- copy = copies.get(rev, {}).get(fn)
- if fn in skip:
- if copy:
- skip[copy] = True
- continue
- pstates = matches.get(parent, {}).get(copy or fn, [])
- if pstates or states:
- r = display(fn, ctx, pstates, states)
- found = found or r
- if r and not opts.get('all'):
- skip[fn] = True
- if copy:
- skip[copy] = True
- del matches[rev]
- del revfiles[rev]
+ del matches[rev]
+ del revfiles[rev]
def heads(ui, repo, *branchrevs, **opts):
"""show current repository heads or show branch heads
@@ -1400,21 +1418,22 @@
heads = []
visitedset = set()
for branchrev in branchrevs:
- branch = repo[branchrev].branch()
+ branch = repo[encoding.fromlocal(branchrev)].branch()
+ encodedbranch = encoding.tolocal(branch)
if branch in visitedset:
continue
visitedset.add(branch)
bheads = repo.branchheads(branch, start, closed=closed)
if not bheads:
if not opts.get('rev'):
- ui.warn(_("no open branch heads on branch %s\n") % branch)
+ ui.warn(_("no open branch heads on branch %s\n") % encodedbranch)
elif branch != branchrev:
ui.warn(_("no changes on branch %s containing %s are "
"reachable from %s\n")
- % (branch, branchrev, opts.get('rev')))
+ % (encodedbranch, branchrev, opts.get('rev')))
else:
ui.warn(_("no changes on branch %s are reachable from %s\n")
- % (branch, opts.get('rev')))
+ % (encodedbranch, opts.get('rev')))
if hideinactive:
bheads = [bhead for bhead in bheads if bhead in _heads]
heads.extend(bheads)
@@ -2034,54 +2053,44 @@
if opts["date"]:
df = util.matchdate(opts["date"])
- only_branches = opts.get('only_branch')
-
displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
- for st, ctx, fns in cmdutil.walkchangerevs(ui, repo, matchfn, opts):
+ def prep(ctx, fns):
rev = ctx.rev()
- if st == 'add':
- parents = [p for p in repo.changelog.parentrevs(rev)
- if p != nullrev]
- if opts.get('no_merges') and len(parents) == 2:
- continue
- if opts.get('only_merges') and len(parents) != 2:
- continue
-
- if only_branches and ctx.branch() not in only_branches:
- continue
-
- if df and not df(ctx.date()[0]):
- continue
-
- if opts.get('keyword'):
- miss = 0
- for k in [kw.lower() for kw in opts['keyword']]:
- if not (k in ctx.user().lower() or
- k in ctx.description().lower() or
- k in " ".join(ctx.files()).lower()):
- miss = 1
- break
- if miss:
- continue
-
- if opts['user']:
- if not [k for k in opts['user'] if k in ctx.user()]:
- continue
-
- copies = []
- if opts.get('copies') and rev:
- for fn in ctx.files():
- rename = getrenamed(fn, rev)
- if rename:
- copies.append((fn, rename[0]))
-
- displayer.show(ctx, copies=copies)
-
- elif st == 'iter':
- if count == limit: break
-
- if displayer.flush(rev):
- count += 1
+ parents = [p for p in repo.changelog.parentrevs(rev)
+ if p != nullrev]
+ if opts.get('no_merges') and len(parents) == 2:
+ return
+ if opts.get('only_merges') and len(parents) != 2:
+ return
+ if opts.get('only_branch') and ctx.branch() not in opts['only_branch']:
+ return
+ if df and not df(ctx.date()[0]):
+ return
+ if opts['user'] and not [k for k in opts['user'] if k in ctx.user()]:
+ return
+ if opts.get('keyword'):
+ for k in [kw.lower() for kw in opts['keyword']]:
+ if (k in ctx.user().lower() or
+ k in ctx.description().lower() or
+ k in " ".join(ctx.files()).lower()):
+ break
+ else:
+ return
+
+ copies = []
+ if opts.get('copies') and rev:
+ for fn in ctx.files():
+ rename = getrenamed(fn, rev)
+ if rename:
+ copies.append((fn, rename[0]))
+
+ displayer.show(ctx, copies=copies)
+
+ for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
+ if count == limit:
+ break
+ if displayer.flush(ctx.rev()):
+ count += 1
def manifest(ui, repo, node=None, rev=None):
"""output the current or given revision of the project manifest
@@ -2446,13 +2455,15 @@
"""retry file merges from a merge or update
This command can cleanly retry unresolved file merges using file
- revisions preserved from the last update or merge. To attempt to
- resolve all unresolved files, use the -a/--all switch.
+ revisions preserved from the last update or merge.
If a conflict is resolved manually, please note that the changes
will be overwritten if the merge is retried with resolve. The
-m/--mark switch should be used to mark the file as resolved.
+ You can specify a set of files to operate on, or use the -a/-all
+ switch to select all unresolved files.
+
This command also allows listing resolved files and manually
indicating whether or not files are resolved. All files must be
marked as resolved before a commit is permitted.
@@ -3129,30 +3140,32 @@
"""update working directory
Update the repository's working directory to the specified
- revision, or the tip of the current branch if none is specified.
- Use null as the revision to remove the working copy (like 'hg
+ changeset.
+
+ If no changeset is specified, attempt to update to the head of the
+ current branch. If this head is a descendant of the working
+ directory's parent, update to it, otherwise abort.
+
+ The following rules apply when the working directory contains
+ uncommitted changes:
+
+ 1. If neither -c/--check nor -C/--clean is specified, uncommitted
+ changes are merged into the requested changeset, and the merged result
+ is left uncommitted. Updating and merging will occur only if the
+ requested changeset is an ancestor or descendant of the parent
+ changeset. Otherwise, the update is aborted and the uncommitted changes
+ are preserved.
+
+ 2. With the -c/--check option, the update is aborted and the
+ uncommitted changes are preserved.
+
+ 3. With the -C/--clean option, uncommitted changes are discarded and
+ the working directory is updated to the requested changeset.
+
+ Use null as the changeset to remove the working directory (like 'hg
clone -U').
- When the working directory contains no uncommitted changes, it
- will be replaced by the state of the requested revision from the
- repository. When the requested revision is on a different branch,
- the working directory will additionally be switched to that
- branch.
-
- When there are uncommitted changes, use option -C/--clean to
- discard them, forcibly replacing the state of the working
- directory with the requested revision. Alternately, use -c/--check
- to abort.
-
- When there are uncommitted changes and option -C/--clean is not
- used, and the parent revision and requested revision are on the
- same branch, and one of them is an ancestor of the other, then the
- new working directory will contain the requested revision merged
- with the uncommitted changes. Otherwise, the update will fail with
- a suggestion to use 'merge' or 'update -C' instead.
-
- If you want to update just one file to an older revision, use
- revert.
+ If you want to update just one file to an older changeset, use 'hg revert'.
See 'hg help dates' for a list of formats valid for -d/--date.
"""
@@ -3220,7 +3233,7 @@
('', 'encoding', encoding.encoding, _('set the charset encoding')),
('', 'encodingmode', encoding.encodingmode,
_('set the charset encoding mode')),
- ('', 'traceback', None, _('print traceback on exception')),
+ ('', 'traceback', None, _('always print a traceback on exception')),
('', 'time', None, _('time how long the command takes')),
('', 'profile', None, _('print command execution profile')),
('', 'version', None, _('output version information and exit')),
@@ -3270,6 +3283,7 @@
diffopts2 = [
('p', 'show-function', None, _('show which function each change is in')),
+ ('', 'inverse', None, _('produce a diff that undoes the changes')),
('w', 'ignore-all-space', None,
_('ignore white space when comparing lines')),
('b', 'ignore-space-change', None,
@@ -3364,6 +3378,8 @@
(clone,
[('U', 'noupdate', None,
_('the clone will only contain a repository (no working copy)')),
+ ('u', 'updaterev', '',
+ _('revision, tag or branch to check out')),
('r', 'rev', [],
_('a changeset you would like to have after cloning')),
('', 'pull', None, _('use pull protocol to copy metadata')),
@@ -3587,7 +3603,7 @@
_('[OPTION]... SOURCE... DEST')),
"resolve":
(resolve,
- [('a', 'all', None, _('remerge all unresolved files')),
+ [('a', 'all', None, _('select all unresolved files')),
('l', 'list', None, _('list state of files needing merge')),
('m', 'mark', None, _('mark files as resolved')),
('u', 'unmark', None, _('unmark files as resolved')),
@@ -3672,11 +3688,11 @@
_('[-u] FILE...')),
"^update|up|checkout|co":
(update,
- [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
+ [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
('c', 'check', None, _('check for uncommitted changes')),
('d', 'date', '', _('tipmost revision matching date')),
('r', 'rev', '', _('revision'))],
- _('[-C] [-d DATE] [[-r] REV]')),
+ _('[-c] [-C] [-d DATE] [[-r] REV]')),
"verify": (verify, []),
"version": (version_, []),
}
--- a/mercurial/context.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/context.py Sat Nov 07 14:13:15 2009 -0600
@@ -451,6 +451,15 @@
find the common ancestor file context, if any, of self, and fc2
"""
+ actx = self.changectx().ancestor(fc2.changectx())
+
+ # the trivial case: changesets are unrelated, files must be too
+ if not actx:
+ return None
+
+ # the easy case: no (relevant) renames
+ if fc2.path() == self.path() and self.path() in actx:
+ return actx[self.path()]
acache = {}
# prime the ancestor cache for the working directory
--- a/mercurial/dirstate.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/dirstate.py Sat Nov 07 14:13:15 2009 -0600
@@ -9,7 +9,7 @@
from i18n import _
import util, ignore, osutil, parsers
import struct, os, stat, errno
-import cStringIO, sys
+import cStringIO
_unknown = ('?', 0, 0, 0)
_format = ">cllll"
--- a/mercurial/dispatch.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/dispatch.py Sat Nov 07 14:13:15 2009 -0600
@@ -194,8 +194,6 @@
args = shlex.split(self.definition)
cmd = args.pop(0)
- opts = []
- help = ''
try:
self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
@@ -358,17 +356,7 @@
extensions.loadall(lui)
exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
- # (uisetup is handled in extensions.loadall)
-
- for name, module in exts:
- extsetup = getattr(module, 'extsetup', None)
- if extsetup:
- try:
- extsetup(ui)
- except TypeError:
- if extsetup.func_code.co_argcount != 0:
- raise
- extsetup() # old extsetup with no ui argument
+ # (uisetup and extsetup are handled in extensions.loadall)
for name, module in exts:
cmdtable = getattr(module, 'cmdtable', {})
--- a/mercurial/extensions.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/extensions.py Sat Nov 07 14:13:15 2009 -0600
@@ -93,6 +93,16 @@
if uisetup:
uisetup(ui)
+ for name in _order[newindex:]:
+ extsetup = getattr(_extensions[name], 'extsetup', None)
+ if extsetup:
+ try:
+ extsetup(ui)
+ except TypeError:
+ if extsetup.func_code.co_argcount != 0:
+ raise
+ extsetup() # old extsetup with no ui argument
+
def wrapcommand(table, command, wrapper):
aliases, entry = cmdutil.findcmd(command, table)
for alias, e in table.iteritems():
@@ -171,7 +181,6 @@
'''return a dict of {name: desc} of extensions, and the max name length'''
exts = {}
maxlength = 0
- exthelps = []
for ename, ext in extensions():
doc = (gettext(ext.__doc__) or _('(no help text available)'))
ename = ename.split('.')[-1]
--- a/mercurial/filemerge.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/filemerge.py Sat Nov 07 14:13:15 2009 -0600
@@ -186,6 +186,7 @@
env = dict(HG_FILE=fd,
HG_MY_NODE=short(mynode),
HG_OTHER_NODE=str(fco.changectx()),
+ HG_BASE_NODE=str(fca.changectx()),
HG_MY_ISLINK='l' in fcd.flags(),
HG_OTHER_ISLINK='l' in fco.flags(),
HG_BASE_ISLINK='l' in fca.flags())
--- a/mercurial/graphmod.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/graphmod.py Sat Nov 07 14:13:15 2009 -0600
@@ -48,7 +48,7 @@
parents = [f.linkrev() for f in fctx.parents() if f.path() == path]
rev = fctx.rev()
if rev <= start:
- yield (rev, CHANGESET, fctx, sorted(parents))
+ yield (rev, CHANGESET, fctx.changectx(), sorted(parents))
if rev <= stop:
break
filerev -= 1
--- a/mercurial/help.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/help.py Sat Nov 07 14:13:15 2009 -0600
@@ -7,7 +7,7 @@
from i18n import gettext, _
import sys, os
-import extensions, util
+import extensions
def moduledoc(file):
--- a/mercurial/hg.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hg.py Sat Nov 07 14:13:15 2009 -0600
@@ -309,6 +309,8 @@
if update:
if update is not True:
checkout = update
+ if src_repo.local():
+ checkout = src_repo.lookup(update)
for test in (checkout, 'default', 'tip'):
if test is None:
continue
--- a/mercurial/hgweb/common.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hgweb/common.py Sat Nov 07 14:13:15 2009 -0600
@@ -31,8 +31,8 @@
responses = BaseHTTPRequestHandler.responses
return responses.get(code, ('Error', 'Unknown error'))[0]
-def statusmessage(code):
- return '%d %s' % (code, _statusmessage(code))
+def statusmessage(code, message=None):
+ return '%d %s' % (code, message or _statusmessage(code))
def get_mtime(repo_path):
store_path = os.path.join(repo_path, ".hg")
--- a/mercurial/hgweb/hgweb_mod.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hgweb/hgweb_mod.py Sat Nov 07 14:13:15 2009 -0600
@@ -151,6 +151,10 @@
if args:
req.form['file'] = args
+ ua = req.env.get('HTTP_USER_AGENT', '')
+ if cmd == 'rev' and 'mercurial' in ua:
+ req.form['style'] = ['raw']
+
if cmd == 'archive':
fn = req.form['node'][0]
for type_, spec in self.archive_specs.iteritems():
--- a/mercurial/hgweb/hgwebdir_mod.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py Sat Nov 07 14:13:15 2009 -0600
@@ -20,7 +20,7 @@
return [(util.pconvert(name).strip('/'), path) for name, path in items]
def findrepos(paths):
- repos = {}
+ repos = []
for prefix, root in cleannames(paths):
roothead, roottail = os.path.split(root)
# "foo = /bar/*" makes every subrepo of /bar/ to be
@@ -30,7 +30,7 @@
try:
recurse = {'*': False, '**': True}[roottail]
except KeyError:
- repos[prefix] = root
+ repos.append((prefix, root))
continue
roothead = os.path.normpath(roothead)
for path in util.walkrepos(roothead, followsym=True, recurse=recurse):
@@ -38,8 +38,8 @@
name = util.pconvert(path[len(roothead):]).strip('/')
if prefix:
name = prefix + '/' + name
- repos[name] = path
- return repos.items()
+ repos.append((name, path))
+ return repos
class hgwebdir(object):
refreshinterval = 20
@@ -89,7 +89,6 @@
name = name[len(prefix):]
self.repos.append((name.lstrip('/'), repo))
- self.repos.sort()
self.lastrefresh = time.time()
def run(self):
@@ -196,7 +195,7 @@
yield {"type" : i[0], "extension": i[1],
"node": nodeid, "url": url}
- sortdefault = 'name', False
+ sortdefault = None, False
def entries(sortcolumn="", descending=False, subdir="", **map):
rows = []
--- a/mercurial/hgweb/protocol.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hgweb/protocol.py Sat Nov 07 14:13:15 2009 -0600
@@ -5,7 +5,7 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
-import cStringIO, zlib, tempfile, errno, os, sys, urllib
+import cStringIO, zlib, tempfile, errno, os, sys, urllib, copy
from mercurial import util, streamclone
from mercurial.node import bin, hex
from mercurial import changegroup as changegroupmod
@@ -21,6 +21,7 @@
]
HGTYPE = 'application/mercurial-0.1'
+basecaps = 'lookup changegroupsubset branchmap'.split()
def lookup(repo, req):
try:
@@ -109,7 +110,7 @@
yield z.flush()
def capabilities(repo, req):
- caps = ['lookup', 'changegroupsubset', 'branchmap']
+ caps = copy.copy(basecaps)
if repo.ui.configbool('server', 'uncompressed', untrusted=True):
caps.append('stream=%d' % repo.changelog.version)
if changegroupmod.bundlepriority:
@@ -181,18 +182,19 @@
except ValueError, inst:
raise ErrorResponse(HTTP_OK, inst)
except (OSError, IOError), inst:
- filename = getattr(inst, 'filename', '')
- # Don't send our filesystem layout to the client
- if filename.startswith(repo.root):
- filename = filename[len(repo.root)+1:]
- else:
- filename = ''
error = getattr(inst, 'strerror', 'Unknown error')
if inst.errno == errno.ENOENT:
code = HTTP_NOT_FOUND
else:
code = HTTP_SERVER_ERROR
- raise ErrorResponse(code, '%s: %s' % (error, filename))
+ filename = getattr(inst, 'filename', '')
+ # Don't send our filesystem layout to the client
+ if filename and filename.startswith(repo.root):
+ filename = filename[len(repo.root)+1:]
+ text = '%s: %s' % (error, filename)
+ else:
+ text = error.replace(repo.root + os.path.sep, '')
+ raise ErrorResponse(code, text)
finally:
fp.close()
os.unlink(tempname)
--- a/mercurial/hgweb/request.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hgweb/request.py Sat Nov 07 14:13:15 2009 -0600
@@ -77,7 +77,7 @@
if isinstance(status, ErrorResponse):
self.header(status.headers)
- status = statusmessage(status.code)
+ status = statusmessage(status.code, status.message)
elif status == 200:
status = '200 Script output follows'
elif isinstance(status, int):
--- a/mercurial/hook.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/hook.py Sat Nov 07 14:13:15 2009 -0600
@@ -106,10 +106,14 @@
def hook(ui, repo, name, throw=False, **args):
r = False
+ oldstdout = -1
if _redirect:
- # temporarily redirect stdout to stderr
- oldstdout = os.dup(sys.__stdout__.fileno())
- os.dup2(sys.__stderr__.fileno(), sys.__stdout__.fileno())
+ stdoutno = sys.__stdout__.fileno()
+ stderrno = sys.__stderr__.fileno()
+ # temporarily redirect stdout to stderr, if possible
+ if stdoutno >= 0 and stderrno >= 0:
+ oldstdout = os.dup(stdoutno)
+ os.dup2(stderrno, stdoutno)
try:
for hname, cmd in ui.configitems('hooks'):
@@ -128,8 +132,8 @@
else:
r = _exthook(ui, repo, hname, cmd, args, throw) or r
finally:
- if _redirect:
- os.dup2(oldstdout, sys.__stdout__.fileno())
+ if _redirect and oldstdout >= 0:
+ os.dup2(oldstdout, stdoutno)
os.close(oldstdout)
return r
--- a/mercurial/httprepo.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/httprepo.py Sat Nov 07 14:13:15 2009 -0600
@@ -106,8 +106,9 @@
proto.startswith('text/plain') or
proto.startswith('application/hg-changegroup')):
self.ui.debug("requested URL: '%s'\n" % url.hidepassword(cu))
- raise error.RepoError(_("'%s' does not appear to be an hg repository")
- % safeurl)
+ raise error.RepoError(_("'%s' does not appear to be an hg repository:\n"
+ "---%%<--- (%s)\n%s\n---%%<---\n")
+ % (safeurl, proto, resp.read()))
if proto.startswith('application/mercurial-'):
try:
--- a/mercurial/keepalive.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/keepalive.py Sat Nov 07 14:13:15 2009 -0600
@@ -23,6 +23,9 @@
# - import md5 function from a local util module
# Modified by Martin Geisler:
# - moved md5 function from local util module to this module
+# Modified by Augie Fackler:
+# - add safesend method and use it to prevent broken pipe errors
+# on large POST requests
"""An HTTP handler for urllib2 that supports HTTP 1.1 and keepalive.
@@ -108,10 +111,11 @@
# $Id: keepalive.py,v 1.14 2006/04/04 21:00:32 mstenner Exp $
-import urllib2
+import errno
import httplib
import socket
import thread
+import urllib2
DEBUG = None
@@ -495,10 +499,76 @@
break
return list
+def safesend(self, str):
+ """Send `str' to the server.
+
+ Shamelessly ripped off from httplib to patch a bad behavior.
+ """
+ # _broken_pipe_resp is an attribute we set in this function
+ # if the socket is closed while we're sending data but
+ # the server sent us a response before hanging up.
+ # In that case, we want to pretend to send the rest of the
+ # outgoing data, and then let the user use getresponse()
+ # (which we wrap) to get this last response before
+ # opening a new socket.
+ if getattr(self, '_broken_pipe_resp', None) is not None:
+ return
+
+ if self.sock is None:
+ if self.auto_open:
+ self.connect()
+ else:
+ raise httplib.NotConnected()
+
+ # send the data to the server. if we get a broken pipe, then close
+ # the socket. we want to reconnect when somebody tries to send again.
+ #
+ # NOTE: we DO propagate the error, though, because we cannot simply
+ # ignore the error... the caller will know if they can retry.
+ if self.debuglevel > 0:
+ print "send:", repr(str)
+ try:
+ blocksize=8192
+ if hasattr(str,'read') :
+ if self.debuglevel > 0: print "sendIng a read()able"
+ data=str.read(blocksize)
+ while data:
+ self.sock.sendall(data)
+ data=str.read(blocksize)
+ else:
+ self.sock.sendall(str)
+ except socket.error, v:
+ reraise = True
+ if v[0] == errno.EPIPE: # Broken pipe
+ if self._HTTPConnection__state == httplib._CS_REQ_SENT:
+ self._broken_pipe_resp = None
+ self._broken_pipe_resp = self.getresponse()
+ reraise = False
+ self.close()
+ if reraise:
+ raise
+
+def wrapgetresponse(cls):
+ """Wraps getresponse in cls with a broken-pipe sane version.
+ """
+ def safegetresponse(self):
+ # In safesend() we might set the _broken_pipe_resp
+ # attribute, in which case the socket has already
+ # been closed and we just need to give them the response
+ # back. Otherwise, we use the normal response path.
+ r = getattr(self, '_broken_pipe_resp', None)
+ if r is not None:
+ return r
+ return cls.getresponse(self)
+ safegetresponse.__doc__ = cls.getresponse.__doc__
+ return safegetresponse
class HTTPConnection(httplib.HTTPConnection):
# use the modified response class
response_class = HTTPResponse
+ send = safesend
+ getresponse = wrapgetresponse(httplib.HTTPConnection)
+
#########################################################################
##### TEST FUNCTIONS
--- a/mercurial/localrepo.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/localrepo.py Sat Nov 07 14:13:15 2009 -0600
@@ -98,8 +98,7 @@
self._tags = None
self._tagtypes = None
- self.branchcache = None
- self._ubranchcache = None # UTF-8 version of branchcache
+ self._branchcache = None # in UTF-8
self._branchcachetip = None
self.nodetagscache = None
self.filterpats = {}
@@ -321,31 +320,22 @@
def branchmap(self):
tip = self.changelog.tip()
- if self.branchcache is not None and self._branchcachetip == tip:
- return self.branchcache
+ if self._branchcache is not None and self._branchcachetip == tip:
+ return self._branchcache
oldtip = self._branchcachetip
self._branchcachetip = tip
- if self.branchcache is None:
- self.branchcache = {} # avoid recursion in changectx
- else:
- self.branchcache.clear() # keep using the same dict
if oldtip is None or oldtip not in self.changelog.nodemap:
partial, last, lrev = self._readbranchcache()
else:
lrev = self.changelog.rev(oldtip)
- partial = self._ubranchcache
+ partial = self._branchcache
self._branchtags(partial, lrev)
# this private cache holds all heads (not just tips)
- self._ubranchcache = partial
+ self._branchcache = partial
- # the branch cache is stored on disk as UTF-8, but in the local
- # charset internally
- for k, v in partial.iteritems():
- self.branchcache[encoding.tolocal(k)] = v
- return self.branchcache
-
+ return self._branchcache
def branchtags(self):
'''return a dict where branch names map to the tipmost head of
@@ -566,7 +556,7 @@
# abort here if the journal already exists
if os.path.exists(self.sjoin("journal")):
- raise error.RepoError(_("journal already exists - run hg recover"))
+ raise error.RepoError(_("abandoned transaction found - run hg recover"))
# save dirstate for rollback
try:
@@ -631,8 +621,7 @@
self._tags = None
self._tagtypes = None
self.nodetagscache = None
- self.branchcache = None
- self._ubranchcache = None
+ self._branchcache = None # in UTF-8
self._branchcachetip = None
def _lock(self, lockname, wait, releasefn, acquirefn, desc):
@@ -914,7 +903,7 @@
self.changelog.finalize(trp)
tr.close()
- if self.branchcache:
+ if self._branchcache:
self.branchtags()
self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
--- a/mercurial/lock.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/lock.py Sat Nov 07 14:13:15 2009 -0600
@@ -105,7 +105,7 @@
return locker
try:
pid = int(pid)
- except:
+ except ValueError:
return locker
if util.testpid(pid):
return locker
@@ -122,13 +122,14 @@
def release(self):
if self.held > 1:
self.held -= 1
- elif self.held is 1:
+ elif self.held == 1:
self.held = 0
if self.releasefn:
self.releasefn()
try:
os.unlink(self.f)
- except: pass
+ except OSError:
+ pass
def release(*locks):
for lock in locks:
--- a/mercurial/mail.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/mail.py Sat Nov 07 14:13:15 2009 -0600
@@ -169,7 +169,7 @@
try:
acc, dom = addr.split('@')
acc = acc.encode('ascii')
- dom = dom.encode('idna')
+ dom = dom.decode(encoding.encoding).encode('idna')
addr = '%s@%s' % (acc, dom)
except UnicodeDecodeError:
raise util.Abort(_('invalid email address: %s') % addr)
--- a/mercurial/merge.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/merge.py Sat Nov 07 14:13:15 2009 -0600
@@ -397,11 +397,38 @@
"""
Perform a merge between the working directory and the given node
+ node = the node to update to, or None if unspecified
branchmerge = whether to merge between branches
force = whether to force branch merging or file overwriting
partial = a function to filter file lists (dirstate not updated)
+
+ The table below shows all the behaviors of the update command
+ given the -c and -C or no options, whether the working directory
+ is dirty, whether a revision is specified, and the relationship of
+ the parent rev to the target rev (linear, on the same named
+ branch, or on another named branch).
+
+ This logic is tested by test-update-branches.
+
+ -c -C dirty rev | linear same cross
+ n n n n | ok (1) x
+ n n n y | ok ok ok
+ n n y * | merge (2) (2)
+ n y * * | --- discard ---
+ y n y * | --- (3) ---
+ y n n * | --- ok ---
+ y y * * | --- (4) ---
+
+ x = can't happen
+ * = don't-care
+ 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
+ 2 = abort: crosses branches (use 'hg merge' to merge or
+ use 'hg update -C' to discard changes)
+ 3 = abort: uncommitted local changes
+ 4 = incompatible options (checked in commands.py)
"""
+ onode = node
wlock = repo.wlock()
try:
wc = repo[None]
@@ -439,17 +466,14 @@
elif not overwrite:
if pa == p1 or pa == p2: # linear
pass # all good
- elif p1.branch() == p2.branch():
- if wc.files() or wc.deleted():
- raise util.Abort(_("crosses branches (use 'hg merge' or "
- "'hg update -C' to discard changes)"))
- raise util.Abort(_("crosses branches (use 'hg merge' "
- "or 'hg update -C')"))
elif wc.files() or wc.deleted():
- raise util.Abort(_("crosses named branches (use "
- "'hg update -C' to discard changes)"))
+ raise util.Abort(_("crosses branches (use 'hg merge' to merge "
+ "or use 'hg update -C' to discard changes)"))
+ elif onode is None:
+ raise util.Abort(_("crosses branches (use 'hg merge' or use "
+ "'hg update -c')"))
else:
- # Allow jumping branches if there are no changes
+ # Allow jumping branches if clean and specific rev given
overwrite = True
### calculate phase
--- a/mercurial/minirst.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/minirst.py Sat Nov 07 14:13:15 2009 -0600
@@ -16,19 +16,23 @@
It only supports a small subset of reStructuredText:
+- sections
+
- paragraphs
-- definition lists (must use ' ' to indent definitions)
+- literal blocks
+
+- definition lists
-- lists (items must start with '-')
+- bullet lists (items must start with '-')
+
+- enumerated lists (no autonumbering)
- field lists (colons cannot be escaped)
-- literal blocks
-
- option lists (supports only long options without arguments)
-- inline markup is not recognized at all.
+- inline literals (no other inline markup is not recognized)
"""
import re, sys, textwrap
@@ -94,9 +98,10 @@
# correct for this here while we still have the original
# information on the indentation of the subsequent literal
# blocks available.
- if blocks[i]['lines'][0].startswith('- '):
- indent += 2
- adjustment -= 2
+ m = _bulletre.match(blocks[i]['lines'][0])
+ if m:
+ indent += m.end()
+ adjustment -= m.end()
# Mark the following indented blocks.
while i+1 < len(blocks) and blocks[i+1]['indent'] > indent:
@@ -106,6 +111,53 @@
i += 1
return blocks
+_bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)) ')
+_optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$')
+_fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):( +)(.*)')
+_definitionre = re.compile(r'[^ ]')
+
+def splitparagraphs(blocks):
+ """Split paragraphs into lists."""
+ # Tuples with (list type, item regexp, single line items?). Order
+ # matters: definition lists has the least specific regexp and must
+ # come last.
+ listtypes = [('bullet', _bulletre, True),
+ ('option', _optionre, True),
+ ('field', _fieldre, True),
+ ('definition', _definitionre, False)]
+
+ def match(lines, i, itemre, singleline):
+ """Does itemre match an item at line i?
+
+ A list item can be followed by an idented line or another list
+ item (but only if singleline is True).
+ """
+ line1 = lines[i]
+ line2 = i+1 < len(lines) and lines[i+1] or ''
+ if not itemre.match(line1):
+ return False
+ if singleline:
+ return line2 == '' or line2[0] == ' ' or itemre.match(line2)
+ else:
+ return line2.startswith(' ')
+
+ i = 0
+ while i < len(blocks):
+ if blocks[i]['type'] == 'paragraph':
+ lines = blocks[i]['lines']
+ for type, itemre, singleline in listtypes:
+ if match(lines, 0, itemre, singleline):
+ items = []
+ for j, line in enumerate(lines):
+ if match(lines, j, itemre, singleline):
+ items.append(dict(type=type, lines=[],
+ indent=blocks[i]['indent']))
+ items[-1]['lines'].append(line)
+ blocks[i:i+1] = items
+ break
+ i += 1
+ return blocks
+
def findsections(blocks):
"""Finds sections.
@@ -127,139 +179,6 @@
return blocks
-def findbulletlists(blocks):
- """Finds bullet lists.
-
- The blocks must have a 'type' field, i.e., they should have been
- run through findliteralblocks first.
- """
- i = 0
- while i < len(blocks):
- # Searching for a paragraph that looks like this:
- #
- # +------+-----------------------+
- # | "- " | list item |
- # +------| (body elements)+ |
- # +-----------------------+
- if (blocks[i]['type'] == 'paragraph' and
- blocks[i]['lines'][0].startswith('- ')):
- items = []
- for line in blocks[i]['lines']:
- if line.startswith('- '):
- items.append(dict(type='bullet', lines=[],
- indent=blocks[i]['indent']))
- line = line[2:]
- items[-1]['lines'].append(line)
- blocks[i:i+1] = items
- i += len(items) - 1
- i += 1
- return blocks
-
-
-_optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$')
-def findoptionlists(blocks):
- """Finds option lists.
-
- The blocks must have a 'type' field, i.e., they should have been
- run through findliteralblocks first.
- """
- i = 0
- while i < len(blocks):
- # Searching for a paragraph that looks like this:
- #
- # +----------------------------+-------------+
- # | "--" option " " | description |
- # +-------+--------------------+ |
- # | (body elements)+ |
- # +----------------------------------+
- if (blocks[i]['type'] == 'paragraph' and
- _optionre.match(blocks[i]['lines'][0])):
- options = []
- for line in blocks[i]['lines']:
- m = _optionre.match(line)
- if m:
- option, arg, rest = m.groups()
- width = len(option) + len(arg)
- options.append(dict(type='option', lines=[],
- indent=blocks[i]['indent'],
- width=width))
- options[-1]['lines'].append(line)
- blocks[i:i+1] = options
- i += len(options) - 1
- i += 1
- return blocks
-
-
-_fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):( +)(.*)')
-def findfieldlists(blocks):
- """Finds fields lists.
-
- The blocks must have a 'type' field, i.e., they should have been
- run through findliteralblocks first.
- """
- i = 0
- while i < len(blocks):
- # Searching for a paragraph that looks like this:
- #
- #
- # +--------------------+----------------------+
- # | ":" field name ":" | field body |
- # +-------+------------+ |
- # | (body elements)+ |
- # +-----------------------------------+
- if (blocks[i]['type'] == 'paragraph' and
- _fieldre.match(blocks[i]['lines'][0])):
- indent = blocks[i]['indent']
- fields = []
- for line in blocks[i]['lines']:
- m = _fieldre.match(line)
- if m:
- key, spaces, rest = m.groups()
- width = 2 + len(key) + len(spaces)
- fields.append(dict(type='field', lines=[],
- indent=indent, width=width))
- # Turn ":foo: bar" into "foo bar".
- line = '%s %s%s' % (key, spaces, rest)
- fields[-1]['lines'].append(line)
- blocks[i:i+1] = fields
- i += len(fields) - 1
- i += 1
- return blocks
-
-
-def finddefinitionlists(blocks):
- """Finds definition lists.
-
- The blocks must have a 'type' field, i.e., they should have been
- run through findliteralblocks first.
- """
- i = 0
- while i < len(blocks):
- # Searching for a paragraph that looks like this:
- #
- # +----------------------------+
- # | term |
- # +--+-------------------------+--+
- # | definition |
- # | (body elements)+ |
- # +----------------------------+
- if (blocks[i]['type'] == 'paragraph' and
- len(blocks[i]['lines']) > 1 and
- not blocks[i]['lines'][0].startswith(' ') and
- blocks[i]['lines'][1].startswith(' ')):
- definitions = []
- for line in blocks[i]['lines']:
- if not line.startswith(' '):
- definitions.append(dict(type='definition', lines=[],
- indent=blocks[i]['indent']))
- definitions[-1]['lines'].append(line)
- definitions[-1]['hang'] = len(line) - len(line.lstrip())
- blocks[i:i+1] = definitions
- i += len(definitions) - 1
- i += 1
- return blocks
-
-
def inlineliterals(blocks):
for b in blocks:
if b['type'] == 'paragraph':
@@ -291,30 +210,41 @@
indent = ' ' * block['indent']
if block['type'] == 'margin':
return ''
- elif block['type'] == 'literal':
+ if block['type'] == 'literal':
indent += ' '
return indent + ('\n' + indent).join(block['lines'])
- elif block['type'] == 'section':
+ if block['type'] == 'section':
return indent + ('\n' + indent).join(block['lines'])
- elif block['type'] == 'definition':
+ if block['type'] == 'definition':
term = indent + block['lines'][0]
- defindent = indent + block['hang'] * ' '
+ hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
+ defindent = indent + hang * ' '
text = ' '.join(map(str.strip, block['lines'][1:]))
return "%s\n%s" % (term, textwrap.fill(text, width=width,
initial_indent=defindent,
subsequent_indent=defindent))
- else:
- initindent = subindent = indent
- text = ' '.join(map(str.strip, block['lines']))
- if block['type'] == 'bullet':
- initindent = indent + '- '
- subindent = indent + ' '
- elif block['type'] in ('option', 'field'):
- subindent = indent + block['width'] * ' '
+ initindent = subindent = indent
+ if block['type'] == 'bullet':
+ m = _bulletre.match(block['lines'][0])
+ if m:
+ subindent = indent + m.end() * ' '
+ elif block['type'] == 'field':
+ m = _fieldre.match(block['lines'][0])
+ if m:
+ key, spaces, rest = m.groups()
+ # Turn ":foo: bar" into "foo bar".
+ block['lines'][0] = '%s %s%s' % (key, spaces, rest)
+ subindent = indent + (2 + len(key) + len(spaces)) * ' '
+ elif block['type'] == 'option':
+ m = _optionre.match(block['lines'][0])
+ if m:
+ option, arg, rest = m.groups()
+ subindent = indent + (len(option) + len(arg)) * ' '
- return textwrap.fill(text, width=width,
- initial_indent=initindent,
- subsequent_indent=subindent)
+ text = ' '.join(map(str.strip, block['lines']))
+ return textwrap.fill(text, width=width,
+ initial_indent=initindent,
+ subsequent_indent=subindent)
def format(text, width, indent=0):
@@ -324,11 +254,8 @@
b['indent'] += indent
blocks = findliteralblocks(blocks)
blocks = inlineliterals(blocks)
+ blocks = splitparagraphs(blocks)
blocks = findsections(blocks)
- blocks = findbulletlists(blocks)
- blocks = findoptionlists(blocks)
- blocks = findfieldlists(blocks)
- blocks = finddefinitionlists(blocks)
blocks = addmargins(blocks)
return '\n'.join(formatblock(b, width) for b in blocks)
@@ -346,10 +273,7 @@
text = open(sys.argv[1]).read()
blocks = debug(findblocks, text)
blocks = debug(findliteralblocks, blocks)
+ blocks = debug(splitparagraphs, blocks)
blocks = debug(findsections, blocks)
- blocks = debug(findbulletlists, blocks)
- blocks = debug(findoptionlists, blocks)
- blocks = debug(findfieldlists, blocks)
- blocks = debug(finddefinitionlists, blocks)
blocks = debug(addmargins, blocks)
print '\n'.join(formatblock(b, 30) for b in blocks)
--- a/mercurial/patch.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/patch.py Sat Nov 07 14:13:15 2009 -0600
@@ -300,7 +300,7 @@
finally:
fp.close()
- def writelines(self, fname, lines):
+ def writelines(self, fname, lines):
# Ensure supplied data ends in fname, being a regular file or
# a symlink. updatedir() will -too magically- take care of
# setting it to the proper type afterwards.
@@ -342,11 +342,7 @@
# result is a list of line numbers sorted based on distance
# from linenum
- try:
- cand = self.hash[l]
- except:
- return []
-
+ cand = self.hash.get(l, [])
if len(cand) > 1:
# resort our list of potentials forward then back.
cand.sort(key=lambda x: abs(x - linenum))
@@ -484,6 +480,8 @@
self.hunk = [ desc ]
self.a = []
self.b = []
+ self.starta = self.lena = None
+ self.startb = self.lenb = None
if context:
self.read_context_hunk(lr)
else:
@@ -1007,12 +1005,12 @@
return -1
return err
-def diffopts(ui, opts={}, untrusted=False):
+def diffopts(ui, opts=None, untrusted=False):
def get(key, name=None, getter=ui.configbool):
- return (opts.get(key) or
+ return ((opts and opts.get(key)) or
getter('diff', name or key, None, untrusted=untrusted))
return mdiff.diffopts(
- text=opts.get('text'),
+ text=opts and opts.get('text'),
git=get('git'),
nodates=get('nodates'),
showfunc=get('show_function', 'showfunc'),
@@ -1098,10 +1096,12 @@
util.explain_exit(code)[0])
return fuzz
-def internalpatch(patchobj, ui, strip, cwd, files={}, eolmode='strict'):
+def internalpatch(patchobj, ui, strip, cwd, files=None, eolmode='strict'):
"""use builtin patch to apply <patchobj> to the working directory.
returns whether patch was applied with fuzz factor."""
+ if files is None:
+ files = {}
if eolmode is None:
eolmode = ui.config('patch', 'eol', 'strict')
try:
@@ -1125,7 +1125,7 @@
raise PatchError
return ret > 0
-def patch(patchname, ui, strip=1, cwd=None, files={}, eolmode='strict'):
+def patch(patchname, ui, strip=1, cwd=None, files=None, eolmode='strict'):
"""Apply <patchname> to the working directory.
'eolmode' specifies how end of lines should be handled. It can be:
@@ -1139,6 +1139,8 @@
"""
patcher = ui.config('ui', 'patch')
args = []
+ if files is None:
+ files = {}
try:
if patcher:
return externalpatch(patcher, args, patchname, ui, strip, cwd,
@@ -1214,7 +1216,7 @@
if opts is None:
opts = mdiff.defaultopts
- if not node1:
+ if not node1 and not node2:
node1 = repo.dirstate.parents()[0]
def lrugetfilectx():
@@ -1225,7 +1227,7 @@
if f not in cache:
if len(cache) > 20:
del cache[order.pop(0)]
- cache[f] = fctx._filelog
+ cache[f] = fctx.filelog()
else:
order.remove(f)
order.append(f)
--- a/mercurial/revlog.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/revlog.py Sat Nov 07 14:13:15 2009 -0600
@@ -466,7 +466,7 @@
if i:
try:
d = self._io.parseindex(f, i, self._inline)
- except (ValueError, IndexError), e:
+ except (ValueError, IndexError):
raise RevlogError(_("index %s is corrupted") % (self.indexfile))
self.index, self.nodemap, self._chunkcache = d
if not self._chunkcache:
--- a/mercurial/sshserver.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/sshserver.py Sat Nov 07 14:13:15 2009 -0600
@@ -9,9 +9,12 @@
from i18n import _
from node import bin, hex
import streamclone, util, hook
-import os, sys, tempfile, urllib
+import os, sys, tempfile, urllib, copy
class sshserver(object):
+
+ caps = 'unbundle lookup changegroupsubset branchmap'.split()
+
def __init__(self, ui, repo):
self.ui = ui
self.repo = repo
@@ -85,8 +88,7 @@
capabilities: space separated list of tokens
'''
-
- caps = ['unbundle', 'lookup', 'changegroupsubset', 'branchmap']
+ caps = copy.copy(self.caps)
if self.ui.configbool('server', 'uncompressed'):
caps.append('stream=%d' % self.repo.changelog.version)
self.respond("capabilities: %s\n" % (' '.join(caps),))
@@ -179,11 +181,9 @@
self.respond('')
# write bundle data to temporary file because it can be big
- tempname = fp = None
+ fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
+ fp = os.fdopen(fd, 'wb+')
try:
- fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
- fp = os.fdopen(fd, 'wb+')
-
count = int(self.fin.readline())
while count:
fp.write(self.fin.read(count))
@@ -210,10 +210,8 @@
self.lock.release()
self.lock = None
finally:
- if fp is not None:
- fp.close()
- if tempname is not None:
- os.unlink(tempname)
+ fp.close()
+ os.unlink(tempname)
def do_stream_out(self):
try:
--- a/mercurial/subrepo.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/subrepo.py Sat Nov 07 14:13:15 2009 -0600
@@ -27,7 +27,7 @@
if '.hgsubstate' in ctx:
try:
for l in ctx['.hgsubstate'].data().splitlines():
- revision, path = l.split()
+ revision, path = l.split(" ", 1)
rev[path] = revision
except IOError, err:
if err.errno != errno.ENOENT:
--- a/mercurial/tags.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/tags.py Sat Nov 07 14:13:15 2009 -0600
@@ -10,7 +10,6 @@
# Eventually, it could take care of updating (adding/removing/moving)
# tags too.
-import os
from node import nullid, bin, hex, short
from i18n import _
import encoding
--- a/mercurial/templatefilters.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/templatefilters.py Sat Nov 07 14:13:15 2009 -0600
@@ -40,10 +40,13 @@
return 'in the future'
delta = max(1, int(now - then))
+ if delta > agescales[0][1] * 2:
+ return util.shortdate(date)
+
for t, s in agescales:
n = delta // s
if n >= 2 or s == 1:
- return fmt(t, n)
+ return '%s ago' % fmt(t, n)
para_re = None
space_re = None
--- a/mercurial/transaction.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/transaction.py Sat Nov 07 14:13:15 2009 -0600
@@ -28,14 +28,14 @@
if o or not unlink:
try:
opener(f, 'a').truncate(o)
- except:
+ except IOError:
report(_("failed to truncate %s\n") % f)
raise
else:
try:
fn = opener(f).name
os.unlink(fn)
- except IOError, inst:
+ except (IOError, OSError), inst:
if inst.errno != errno.ENOENT:
raise
os.unlink(journal)
@@ -59,8 +59,7 @@
def __del__(self):
if self.journal:
- if self.entries: self._abort()
- self.file.close()
+ self._abort()
@active
def startgroup(self):
@@ -126,7 +125,7 @@
self.entries = []
if self.after:
self.after()
- else:
+ if os.path.isfile(self.journal):
os.unlink(self.journal)
self.journal = None
@@ -141,7 +140,10 @@
self.count = 0
self.file.close()
- if not self.entries: return
+ if not self.entries:
+ if self.journal:
+ os.unlink(self.journal)
+ return
self.report(_("transaction abort!\n"))
--- a/mercurial/ui.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/ui.py Sat Nov 07 14:13:15 2009 -0600
@@ -377,7 +377,7 @@
if total:
pct = 100.0 * pos / total
- ui.debug('%s:%s %s/%s%s (%4.2g%%)\n'
+ self.debug('%s:%s %s/%s%s (%4.2g%%)\n'
% (topic, item, pos, total, unit, pct))
else:
- ui.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
+ self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
--- a/mercurial/url.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/url.py Sat Nov 07 14:13:15 2009 -0600
@@ -408,10 +408,14 @@
self.close_all()
if has_https:
- class httpsconnection(httplib.HTTPSConnection):
+ class BetterHTTPS(httplib.HTTPSConnection):
+ send = keepalive.safesend
+
+ class httpsconnection(BetterHTTPS):
response_class = keepalive.HTTPResponse
# must be able to send big bundle as stream.
- send = _gen_sendfile(httplib.HTTPSConnection)
+ send = _gen_sendfile(BetterHTTPS)
+ getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
def __init__(self, ui):
--- a/mercurial/util.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/util.py Sat Nov 07 14:13:15 2009 -0600
@@ -1116,6 +1116,7 @@
seen_dirs = []
_add_dir_if_not_there(seen_dirs, path)
for root, dirs, files in os.walk(path, topdown=True, onerror=errhandler):
+ dirs.sort()
if '.hg' in dirs:
yield root # found a repository
qroot = os.path.join(root, '.hg', 'patches')
@@ -1223,11 +1224,11 @@
return array.array('h', arri)[1]
except ValueError:
pass
- except IOError, e:
- if e[0] == errno.EINVAL:
- pass
- else:
- raise
+ except IOError, e:
+ if e[0] == errno.EINVAL:
+ pass
+ else:
+ raise
except ImportError:
pass
return 80
--- a/mercurial/verify.py Wed Nov 04 22:14:26 2009 +0100
+++ b/mercurial/verify.py Sat Nov 07 14:13:15 2009 -0600
@@ -7,6 +7,7 @@
from node import nullid, short
from i18n import _
+import os
import revlog, util, error
def verify(repo):
@@ -105,6 +106,9 @@
seen[n] = i
return lr
+ if os.path.exists(repo.sjoin("journal")):
+ ui.warn(_("abandoned transaction found - run hg recover\n"))
+
revlogv1 = cl.version != revlog.REVLOGV0
if ui.verbose or not revlogv1:
ui.status(_("repository uses revlog format %d\n") %
--- a/templates/gitweb/changelogentry.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/gitweb/changelogentry.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -1,5 +1,5 @@
<div>
-<a class="title" href="{url}rev/{node|short}{sessionvars%urlparameter}"><span class="age">{date|age} ago</span>{desc|strip|firstline|escape|nonempty}<span class="logtags"> {inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
+<a class="title" href="{url}rev/{node|short}{sessionvars%urlparameter}"><span class="age">{date|age}</span>{desc|strip|firstline|escape|nonempty}<span class="logtags"> {inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a>
</div>
<div class="title_text">
<div class="log_link">
--- a/templates/gitweb/changeset.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/gitweb/changeset.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -29,7 +29,7 @@
<div class="title_text">
<table cellspacing="0">
<tr><td>author</td><td>{author|obfuscate}</td></tr>
-<tr><td></td><td>{date|date} ({date|age} ago)</td></tr>
+<tr><td></td><td>{date|date} ({date|age})</td></tr>
{branch%changesetbranch}
<tr><td>changeset {rev}</td><td style="font-family:monospace">{node|short}</td></tr>
{parent%changesetparent}
--- a/templates/gitweb/fileannotate.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/gitweb/fileannotate.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -36,7 +36,7 @@
<td>{author|obfuscate}</td></tr>
<tr>
<td></td>
- <td>{date|date} ({date|age} ago)</td></tr>
+ <td>{date|date} ({date|age})</td></tr>
{branch%filerevbranch}
<tr>
<td>changeset {rev}</td>
--- a/templates/gitweb/filerevision.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/gitweb/filerevision.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -36,7 +36,7 @@
<td>{author|obfuscate}</td></tr>
<tr>
<td></td>
- <td>{date|date} ({date|age} ago)</td></tr>
+ <td>{date|date} ({date|age})</td></tr>
{branch%filerevbranch}
<tr>
<td>changeset {rev}</td>
--- a/templates/gitweb/map Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/gitweb/map Sat Nov 07 14:13:15 2009 -0600
@@ -150,7 +150,7 @@
tags = tags.tmpl
tagentry = '
<tr class="parity{parity}">
- <td class="age"><i>{date|age} ago</i></td>
+ <td class="age"><i>{date|age}</i></td>
<td><a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}"><b>{tag|escape}</b></a></td>
<td class="link">
<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
@@ -161,7 +161,7 @@
branches = branches.tmpl
branchentry = '
<tr class="parity{parity}">
- <td class="age"><i>{date|age} ago</i></td>
+ <td class="age"><i>{date|age}</i></td>
<td><a class="list" href="{url}shortlog/{node|short}{sessionvars%urlparameter}"><b>{node|short}</b></a></td>
<td class="{status}">{branch|escape}</td>
<td class="link">
@@ -204,7 +204,7 @@
inbranchtag = '<span class="inbranchtag" title="{name}">{name}</span> '
shortlogentry = '
<tr class="parity{parity}">
- <td class="age"><i>{date|age} ago</i></td>
+ <td class="age"><i>{date|age}</i></td>
<td><i>{author|person}</i></td>
<td>
<a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
@@ -219,7 +219,7 @@
</tr>'
filelogentry = '
<tr class="parity{parity}">
- <td class="age"><i>{date|age} ago</i></td>
+ <td class="age"><i>{date|age}</i></td>
<td>
<a class="list" href="{url}rev/{node|short}{sessionvars%urlparameter}">
<b>{desc|strip|firstline|escape|nonempty}</b>
@@ -238,7 +238,7 @@
</td>
<td>{description}</td>
<td>{contact|obfuscate}</td>
- <td class="age">{lastchange|age} ago</td>
+ <td class="age">{lastchange|age}</td>
<td class="indexlinks">{archives%indexarchiveentry}</td>
<td><div class="rss_logo"><a href="{url}rss-log">RSS</a> <a href="{url}atom-log">Atom</a></div></td>
</tr>\n'
--- a/templates/monoblue/changelogentry.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/monoblue/changelogentry.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -1,6 +1,6 @@
<h3 class="changelog"><a class="title" href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}<span class="logtags"> {inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a></h3>
<ul class="changelog-entry">
- <li class="age">{date|age} ago</li>
+ <li class="age">{date|age}</li>
<li>by <span class="name">{author|obfuscate}</span> <span class="revdate">[{date|rfc822date}] rev {rev}</span></li>
<li class="description">{desc|strip|escape|addbreaks|nonempty}</li>
</ul>
--- a/templates/monoblue/changeset.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/monoblue/changeset.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -36,7 +36,7 @@
<h2 class="no-link no-border">changeset</h2>
<h3 class="changeset"><a href="{url}raw-rev/{node|short}">{desc|strip|escape|firstline|nonempty} <span class="logtags">{inbranch%inbranchtag}{branches%branchtag}{tags%tagtag}</span></a></h3>
- <p class="changeset-age"><span>{date|age} ago</span></p>
+ <p class="changeset-age"><span>{date|age}</span></p>
<dl class="overview">
<dt>author</dt>
--- a/templates/monoblue/fileannotate.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/monoblue/fileannotate.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -38,7 +38,7 @@
<h2 class="no-link no-border">{file|escape}@{node|short} (annotated)</h2>
<h3 class="changeset">{file|escape}</h3>
- <p class="changeset-age"><span>{date|age} ago</span></p>
+ <p class="changeset-age"><span>{date|age}</span></p>
<dl class="overview">
<dt>author</dt>
--- a/templates/monoblue/filerevision.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/monoblue/filerevision.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -38,7 +38,7 @@
<h2 class="no-link no-border">{file|escape}@{node|short}</h2>
<h3 class="changeset">{file|escape}</h3>
- <p class="changeset-age"><span>{date|age} ago</span></p>
+ <p class="changeset-age"><span>{date|age}</span></p>
<dl class="overview">
<dt>author</dt>
--- a/templates/monoblue/map Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/monoblue/map Sat Nov 07 14:13:15 2009 -0600
@@ -127,7 +127,7 @@
tags = tags.tmpl
tagentry = '
<tr class="parity{parity}">
- <td class="nowrap">{date|age} ago</td>
+ <td class="nowrap">{date|age}</td>
<td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{tag|escape}</a></td>
<td class="nowrap">
<a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a> |
@@ -138,7 +138,7 @@
branches = branches.tmpl
branchentry = '
<tr class="parity{parity}">
- <td class="nowrap">{date|age} ago</td>
+ <td class="nowrap">{date|age}</td>
<td><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{node|short}</a></td>
<td class="{status}">{branch|escape}</td>
<td class="nowrap">
@@ -170,7 +170,7 @@
inbranchtag = '<span class="inbranchtag" title="{name}">{name}</span> '
shortlogentry = '
<tr class="parity{parity}">
- <td class="nowrap">{date|age} ago</td>
+ <td class="nowrap">{date|age}</td>
<td>{author|person}</td>
<td>
<a href="{url}rev/{node|short}{sessionvars%urlparameter}">
@@ -185,7 +185,7 @@
</tr>'
filelogentry = '
<tr class="parity{parity}">
- <td class="nowrap">{date|age} ago</td>
+ <td class="nowrap">{date|age}</td>
<td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a></td>
<td class="nowrap">
<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a> | <a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a> | <a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a>
@@ -198,7 +198,7 @@
<td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
<td>{description}</td>
<td>{contact|obfuscate}</td>
- <td>{lastchange|age} ago</td>
+ <td>{lastchange|age}</td>
<td class="indexlinks">{archives%indexarchiveentry}</td>
<td>
<div class="rss_logo">
--- a/templates/paper/changeset.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/paper/changeset.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -45,7 +45,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td></tr>
+ <td class="date">{date|date} ({date|age})</td></tr>
<tr>
<th class="author">parents</th>
<td class="author">{parent%changesetparent}</td>
--- a/templates/paper/fileannotate.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/paper/fileannotate.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -22,6 +22,7 @@
</ul>
<ul>
<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
+<li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
<li class="active">annotate</li>
<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
@@ -49,7 +50,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td>
+ <td class="date">{date|date} ({date|age})</td>
</tr>
<tr>
<th class="author">parents</th>
--- a/templates/paper/filediff.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/paper/filediff.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -21,6 +21,7 @@
</ul>
<ul>
<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
+<li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
<li class="active">diff</li>
<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
@@ -48,7 +49,7 @@
</tr>
<tr>
<th>date</th>
- <td>{date|date} ({date|age} ago)</td>
+ <td>{date|date} ({date|age})</td>
</tr>
<tr>
<th>parents</th>
--- a/templates/paper/filerevision.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/paper/filerevision.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -21,6 +21,7 @@
</ul>
<ul>
<li class="active">file</li>
+<li><a href="{url}file/tip/{file|urlescape}{sessionvars%urlparameter}">latest</a></li>
<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
@@ -48,7 +49,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td>
+ <td class="date">{date|date} ({date|age})</td>
</tr>
<tr>
<th class="author">parents</th>
--- a/templates/paper/map Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/paper/map Sat Nov 07 14:13:15 2009 -0600
@@ -176,7 +176,7 @@
<td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td>
<td>{description}</td>
<td>{contact|obfuscate}</td>
- <td class="age">{lastchange|age} ago</td>
+ <td class="age">{lastchange|age}</td>
<td class="indexlinks">{archives%indexarchiveentry}</td>
</tr>\n'
indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}"> ↓{type|escape}</a>'
--- a/templates/spartan/changelogentry.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/spartan/changelogentry.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -1,6 +1,6 @@
<table class="logEntry parity{parity}">
<tr>
- <th class="age">{date|age} ago:</th>
+ <th class="age">{date|age}:</th>
<th class="firstline">{desc|strip|firstline|escape|nonempty}</th>
</tr>
<tr>
--- a/templates/spartan/changeset.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/spartan/changeset.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -30,7 +30,7 @@
</tr>
<tr>
<th class="date">date:</th>
- <td class="date">{date|date} ({date|age} ago)</td>
+ <td class="date">{date|date} ({date|age})</td>
</tr>
<tr>
<th class="files">files:</th>
--- a/templates/spartan/fileannotate.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/spartan/fileannotate.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -29,7 +29,7 @@
<td>{author|obfuscate}</td></tr>
<tr>
<td class="metatag">date:</td>
- <td>{date|date} ({date|age} ago)</td>
+ <td>{date|date} ({date|age})</td>
</tr>
<tr>
<td class="metatag">permissions:</td>
--- a/templates/spartan/filelogentry.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/spartan/filelogentry.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -1,6 +1,6 @@
<table class="logEntry parity{parity}">
<tr>
- <th class="age">{date|age} ago:</th>
+ <th class="age">{date|age}:</th>
<th class="firstline"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a></th>
</tr>
<tr>
--- a/templates/spartan/filerevision.tmpl Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/spartan/filerevision.tmpl Sat Nov 07 14:13:15 2009 -0600
@@ -29,7 +29,7 @@
<td>{author|obfuscate}</td></tr>
<tr>
<td class="metatag">date:</td>
- <td>{date|date} ({date|age} ago)</td></tr>
+ <td>{date|date} ({date|age})</td></tr>
<tr>
<td class="metatag">permissions:</td>
<td>{permissions|permissions}</td></tr>
--- a/templates/static/style-paper.css Wed Nov 04 22:14:26 2009 +0100
+++ b/templates/static/style-paper.css Sat Nov 07 14:13:15 2009 -0600
@@ -161,7 +161,7 @@
border-bottom: 1px solid #999;
}
.bigtable tr { border: none; }
-.bigtable .age { width: 6em; }
+.bigtable .age { width: 7em; }
.bigtable .author { width: 12em; }
.bigtable .description { }
.bigtable .node { width: 5em; font-family: monospace;}
--- a/tests/get-with-headers.py Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/get-with-headers.py Sat Nov 07 14:13:15 2009 -0600
@@ -22,7 +22,6 @@
print "%s: %s" % (h, response.getheader(h))
print
data = response.read()
-data = re.sub('\d+ years', 'many years', data)
sys.stdout.write(data)
if 200 <= response.status <= 299:
--- a/tests/hghave Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/hghave Sat Nov 07 14:13:15 2009 -0600
@@ -121,8 +121,8 @@
return matchoutput('git --version 2>&1', r'^git version')
def has_rst2html():
- return matchoutput('rst2html --version', r'^rst2html \(Docutils') or \
- matchoutput('rst2html.py --version', r'^rst2html.py \(Docutils')
+ return matchoutput('rst2html --version 2>&1', r'^rst2html \(Docutils') or \
+ matchoutput('rst2html.py --version 2>&1', r'^rst2html.py \(Docutils')
def has_svn():
#return matchoutput('svn --version 2>&1', r'^svn, version') and \
--- a/tests/run-tests.py Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/run-tests.py Sat Nov 07 14:13:15 2009 -0600
@@ -93,8 +93,13 @@
parser.add_option("-k", "--keywords",
help="run tests matching keywords")
parser.add_option("--keep-tmpdir", action="store_true",
- help="keep temporary directory after running tests"
- " (best used with --tmpdir)")
+ help="keep temporary directory after running tests")
+ parser.add_option("--tmpdir", type="string",
+ help="run tests in the given temporary directory"
+ " (implies --keep-tmpdir)")
+ parser.add_option("-d", "--debug", action="store_true",
+ help="debug mode: write output of test scripts to console"
+ " rather than capturing and diff'ing it (disables timeout)")
parser.add_option("-R", "--restart", action="store_true",
help="restart at last error")
parser.add_option("-p", "--port", type="int",
@@ -109,8 +114,6 @@
parser.add_option("-t", "--timeout", type="int",
help="kill errant tests after TIMEOUT seconds"
" (default: $%s or %d)" % defaults['timeout'])
- parser.add_option("--tmpdir", type="string",
- help="run tests in the given temporary directory")
parser.add_option("-v", "--verbose", action="store_true",
help="output verbose messages")
parser.add_option("-n", "--nodiff", action="store_true",
@@ -168,22 +171,25 @@
for m in msg:
print m,
print
+ sys.stdout.flush()
else:
vlog = lambda *msg: None
if options.tmpdir:
options.tmpdir = os.path.expanduser(options.tmpdir)
- try:
- os.makedirs(options.tmpdir)
- except OSError, err:
- if err.errno != errno.EEXIST:
- raise
if options.jobs < 1:
parser.error('--jobs must be positive')
if options.interactive and options.jobs > 1:
print '(--interactive overrides --jobs)'
options.jobs = 1
+ if options.interactive and options.debug:
+ parser.error("-i/--interactive and -d/--debug are incompatible")
+ if options.debug:
+ if options.timeout != defaults['timeout']:
+ sys.stderr.write(
+ 'warning: --timeout option ignored with --debug\n')
+ options.timeout = 0
if options.py3k_warnings:
if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
parser.error('--py3k-warnings can only be used on Python 2.6+')
@@ -379,8 +385,13 @@
def run(cmd, options):
"""Run command in a sub-process, capturing the output (stdout and stderr).
- Return the exist code, and output."""
+ Return a tuple (exitcode, output). output is None in debug mode."""
# TODO: Use subprocess.Popen if we're running on Python 2.4
+ if options.debug:
+ proc = subprocess.Popen(cmd, shell=True)
+ ret = proc.wait()
+ return (ret, None)
+
if os.name == 'nt' or sys.platform.startswith('java'):
tochild, fromchild = os.popen4(cmd)
tochild.close()
@@ -492,16 +503,24 @@
mark = '.'
skipped = (ret == SKIPPED_STATUS)
- # If reference output file exists, check test output against it
- if os.path.exists(ref):
+ # If we're not in --debug mode and reference output file exists,
+ # check test output against it.
+ if options.debug:
+ refout = None # to match out == None
+ elif os.path.exists(ref):
f = open(ref, "r")
refout = splitnewlines(f.read())
f.close()
else:
refout = []
+
if skipped:
mark = 's'
- missing, failed = parsehghaveoutput(out)
+ if out is None: # debug mode: nothing to parse
+ missing = ['unknown']
+ failed = None
+ else:
+ missing, failed = parsehghaveoutput(out)
if not missing:
missing = ['irrelevant']
if failed:
@@ -526,7 +545,7 @@
sys.stdout.write(mark)
sys.stdout.flush()
- if ret != 0 and not skipped:
+ if ret != 0 and not skipped and not options.debug:
# Save errors to a file for diagnosis
f = open(err, "wb")
for line in out:
@@ -765,8 +784,24 @@
global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
TESTDIR = os.environ["TESTDIR"] = os.getcwd()
- HGTMP = os.environ['HGTMP'] = os.path.realpath(tempfile.mkdtemp('', 'hgtests.',
- options.tmpdir))
+ if options.tmpdir:
+ options.keep_tmpdir = True
+ tmpdir = options.tmpdir
+ if os.path.exists(tmpdir):
+ # Meaning of tmpdir has changed since 1.3: we used to create
+ # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if
+ # tmpdir already exists.
+ sys.exit("error: temp dir %r already exists" % tmpdir)
+
+ # Automatically removing tmpdir sounds convenient, but could
+ # really annoy anyone in the habit of using "--tmpdir=/tmp"
+ # or "--tmpdir=$HOME".
+ #vlog("# Removing temp dir", tmpdir)
+ #shutil.rmtree(tmpdir)
+ os.makedirs(tmpdir)
+ else:
+ tmpdir = tempfile.mkdtemp('', 'hgtests.')
+ HGTMP = os.environ['HGTMP'] = os.path.realpath(tmpdir)
DAEMON_PIDS = None
HGRCPATH = None
--- a/tests/test-archive.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-archive.out Sat Nov 07 14:13:15 2009 -0600
@@ -5,20 +5,20 @@
% gz allowed should give 200
200 Script output follows
% tar.bz2 and zip disallowed should both give 403
-403 Forbidden
-403 Forbidden
+403 Archive type not allowed: bz2
+403 Archive type not allowed: zip
% bz2 allowed should give 200
200 Script output follows
% zip and tar.gz disallowed should both give 403
-403 Forbidden
-403 Forbidden
+403 Archive type not allowed: zip
+403 Archive type not allowed: gz
% zip allowed should give 200
200 Script output follows
% tar.gz and tar.bz2 disallowed should both give 403
-403 Forbidden
-403 Forbidden
+403 Archive type not allowed: gz
+403 Archive type not allowed: bz2
% invalid arch type should give 404
-404 Not Found
+404 Unsupported archive type: None
test-archive-TIP/.hg_archival.txt
test-archive-TIP/bar
--- a/tests/test-bisect Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-bisect Sat Nov 07 14:13:15 2009 -0600
@@ -87,7 +87,7 @@
echo % test invalid command
hg bisect -r
-hg bisect --command 'foobar'
+hg bisect --command './foobar' 2>&1 | sed 's|\(/bin/sh: \./foobar:\).*|\1 not found|'
echo % test bisecting command
cat > script.py <<EOF
--- a/tests/test-bisect.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-bisect.out Sat Nov 07 14:13:15 2009 -0600
@@ -304,8 +304,8 @@
summary: msg 6
% test invalid command
-/bin/sh: foobar: command not found
-abort: failed to execute foobar
+/bin/sh: ./foobar: not found
+abort: failed to execute ./foobar
% test bisecting command
Testing changeset 15:e7fa0811edb0 (31 changesets remaining, ~4 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-branchmap Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+hgserve()
+{
+ hg serve -a localhost -p $HGPORT1 -d --pid-file=hg.pid -E errors.log -v $@ \
+ | sed -e 's/:[0-9][0-9]*//g' -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
+ cat hg.pid >> "$DAEMON_PIDS"
+}
+
+hg init a
+hg --encoding utf-8 -R a branch æ
+echo foo > a/foo
+hg -R a ci -Am foo
+
+hgserve -R a --config web.push_ssl=False --config web.allow_push=* --encoding latin1
+hg clone http://localhost:$HGPORT1 b
+hg --encoding utf-8 -R b log
+echo bar >> b/foo
+hg -R b ci -m bar
+hg --encoding utf-8 -R b push | sed "s/$HGPORT1/PORT/"
+hg -R a --encoding utf-8 log
+
+kill `cat hg.pid`
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-branchmap.out Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,36 @@
+marked working directory as branch æ
+adding foo
+listening at http://localhost/ (bound to 127.0.0.1)
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+updating working directory
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+changeset: 0:867c11ce77b8
+branch: æ
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: foo
+
+pushing to http://localhost:PORT
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+changeset: 1:58e7c90d67cb
+branch: æ
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: bar
+
+changeset: 0:867c11ce77b8
+branch: æ
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: foo
+
--- a/tests/test-churn Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-churn Sat Nov 07 14:13:15 2009 -0600
@@ -50,6 +50,14 @@
echo % churn by hour
hg churn -f '%H' -s
+echo % churn with separated added/removed lines
+hg rm d/g/f2.txt
+hg ci -Am "removed d/g/f2.txt" -u user1 -d 14:00 d/g/f2.txt
+hg churn --diffstat
+
+echo % changeset number churn
+hg churn -c
+
cd ..
# issue 833: ZeroDivisionError
--- a/tests/test-churn.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-churn.out Sat Nov 07 14:13:15 2009 -0600
@@ -10,7 +10,7 @@
user2 2 ******************************************
% churn up to rev 2
user2 2 ***************************************************************
-user1 1 *******************************
+user1 1 ********************************
% churn with aliases
alias3 3 **************************************************************
alias1 3 **************************************************************
@@ -24,9 +24,17 @@
user1 3 ***********************
user2 2 ***************
% churn by hour
-06 1 ****************
+06 1 *****************
09 2 *********************************
12 4 ******************************************************************
-13 1 ****************
+13 1 *****************
+% churn with separated added/removed lines
+user1 +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
+user3 +3/-0 +++++++++++++++++++++++++++++++++++++++++
+user2 +2/-0 +++++++++++++++++++++++++++
+% changeset number churn
+user1 4 ***************************************************************
+user3 3 ***********************************************
+user2 2 ********************************
adding foo
test 0
--- a/tests/test-clone Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-clone Sat Nov 07 14:13:15 2009 -0600
@@ -67,4 +67,136 @@
hg clone ../a .
cd ..
+echo
+echo
+echo % "*** tests for option -u ***"
+echo
+
+
+echo
+echo % "adding some more history to repo a"
+cd a
+echo % "tag ref1"
+hg tag ref1
+echo the quick brown fox >a
+hg ci -m "hacked default"
+echo % "updating back to ref1"
+hg up ref1
+echo
+echo % "add branch 'stable' to repo a for later tests"
+hg branch stable
+echo some text >a
+hg ci -m "starting branch stable"
+echo % "tag ref2"
+hg tag ref2
+echo some more text >a
+hg ci -m "another change for branch stable"
+echo
+echo % "updating back to ref2"
+hg up ref2
+echo
+echo % "parents of repo a"
+hg parents
+echo
+echo % "repo a has two heads"
+hg heads
+cd ..
+
+echo
+echo % "testing clone -U -u 1 a ua (must abort)"
+hg clone -U -u 1 a ua
+
+echo
+echo % "testing clone -u . a ua"
+hg clone -u . a ua
+echo
+echo % "repo ua has both heads"
+hg -R ua heads
+echo
+echo % "same revision checked out in repo a and ua"
+hg -R a parents --template "{node|short}\n"
+hg -R ua parents --template "{node|short}\n"
+rm -r ua
+
+echo
+echo % "testing clone --pull -u . a ua"
+hg clone --pull -u . a ua
+echo
+echo % "repo ua has both heads"
+hg -R ua heads
+echo
+echo % "same revision checked out in repo a and ua"
+hg -R a parents --template "{node|short}\n"
+hg -R ua parents --template "{node|short}\n"
+rm -r ua
+
+echo
+echo % "testing clone -u stable a ua"
+hg clone -u stable a ua
+echo
+echo % "repo ua has both heads"
+hg -R ua heads
+echo
+echo % "branch stable is checked out"
+hg -R ua parents
+rm -r ua
+
+echo
+echo % "testing clone a ua"
+hg clone a ua
+echo
+echo % "repo ua has both heads"
+hg -R ua heads
+echo
+echo % "branch default is checked out"
+hg -R ua parents
+rm -r ua
+
+echo
+echo % "testing clone -u . a#stable ua"
+hg clone -u . a#stable ua
+echo
+echo % "repo ua has only branch stable"
+hg -R ua heads
+echo
+echo % "same revision checked out in repo a and ua"
+hg -R a parents --template "{node|short}\n"
+hg -R ua parents --template "{node|short}\n"
+rm -r ua
+
+echo
+echo % "testing clone -u . -r stable a ua"
+hg clone -u . -r stable a ua
+echo
+echo % "repo ua has only branch stable"
+hg -R ua heads
+echo
+echo % "same revision checked out in repo a and ua"
+hg -R a parents --template "{node|short}\n"
+hg -R ua parents --template "{node|short}\n"
+rm -r ua
+
+echo
+echo % "testing clone -r stable a ua"
+hg clone -r stable a ua
+echo
+echo % "repo ua has only branch stable"
+hg -R ua heads
+echo
+echo % "branch stable is checked out"
+hg -R ua parents
+rm -r ua
+
+echo
+echo % "testing clone -u . -r stable -r default a ua"
+hg clone -u . -r stable -r default a ua
+echo
+echo % "repo ua has two heads"
+hg -R ua heads
+echo
+echo % "same revision checked out in repo a and ua"
+hg -R a parents --template "{node|short}\n"
+hg -R ua parents --template "{node|short}\n"
+rm -r ua
+
exit 0
--- a/tests/test-clone.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-clone.out Sat Nov 07 14:13:15 2009 -0600
@@ -54,3 +54,246 @@
% clone to .
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+
+% *** tests for option -u ***
+
+
+% adding some more history to repo a
+% tag ref1
+% updating back to ref1
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+% add branch 'stable' to repo a for later tests
+marked working directory as branch stable
+created new head
+% tag ref2
+
+% updating back to ref2
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+% parents of repo a
+changeset: 13:e8ece76546a6
+branch: stable
+tag: ref2
+parent: 10:a7949464abda
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: starting branch stable
+
+
+% repo a has two heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% testing clone -U -u 1 a ua (must abort)
+abort: cannot specify both --noupdate and --updaterev
+
+% testing clone -u . a ua
+updating to branch stable
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has both heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% same revision checked out in repo a and ua
+e8ece76546a6
+e8ece76546a6
+
+% testing clone --pull -u . a ua
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 16 changesets with 16 changes to 3 files (+1 heads)
+updating to branch stable
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has both heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% same revision checked out in repo a and ua
+e8ece76546a6
+e8ece76546a6
+
+% testing clone -u stable a ua
+updating to branch stable
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has both heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% branch stable is checked out
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+
+% testing clone a ua
+updating to branch default
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has both heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% branch default is checked out
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% testing clone -u . a#stable ua
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 14 changesets with 14 changes to 3 files
+updating to branch stable
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has only branch stable
+changeset: 13:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+
+% same revision checked out in repo a and ua
+e8ece76546a6
+e8ece76546a6
+
+% testing clone -u . -r stable a ua
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 14 changesets with 14 changes to 3 files
+updating to branch stable
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has only branch stable
+changeset: 13:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+
+% same revision checked out in repo a and ua
+e8ece76546a6
+e8ece76546a6
+
+% testing clone -r stable a ua
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 14 changesets with 14 changes to 3 files
+updating to branch stable
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has only branch stable
+changeset: 13:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+
+% branch stable is checked out
+changeset: 13:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+
+% testing clone -u . -r stable -r default a ua
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 16 changesets with 16 changes to 3 files (+1 heads)
+updating to branch stable
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+% repo ua has two heads
+changeset: 15:0aae7cf88f0d
+branch: stable
+tag: tip
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: another change for branch stable
+
+changeset: 12:f21241060d6a
+user: test
+date: Thu Jan 01 00:00:00 1970 +0000
+summary: hacked default
+
+
+% same revision checked out in repo a and ua
+e8ece76546a6
+e8ece76546a6
--- a/tests/test-debugcomplete.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-debugcomplete.out Sat Nov 07 14:13:15 2009 -0600
@@ -165,9 +165,9 @@
% Show all commands + options
add: include, exclude, dry-run
annotate: rev, follow, text, user, date, number, changeset, line-number, include, exclude
-clone: noupdate, rev, pull, uncompressed, ssh, remotecmd
+clone: noupdate, updaterev, rev, pull, uncompressed, ssh, remotecmd
commit: addremove, close-branch, include, exclude, message, logfile, date, user
-diff: rev, change, text, git, nodates, show-function, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
+diff: rev, change, text, git, nodates, show-function, inverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude
export: output, switch-parent, text, git, nodates
forget: include, exclude
init: ssh, remotecmd
--- a/tests/test-diff-color Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-diff-color Sat Nov 07 14:13:15 2009 -0600
@@ -51,3 +51,14 @@
y
EOF
echo
+
+echo "[extensions]" >> $HGRCPATH
+echo "mq=" >> $HGRCPATH
+
+hg rollback
+echo % qrecord
+hg qrecord --color=always -m moda patch <<EOF
+y
+y
+EOF
+echo
--- a/tests/test-diff-color.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-diff-color.out Sat Nov 07 14:13:15 2009 -0600
@@ -41,3 +41,19 @@
a
c
record this change to 'a'? [Ynsfdaq?]
+rolling back last transaction
+% qrecord
+[0;1mdiff --git a/a b/a[0m
+[0;36;1mold mode 100644[0m
+[0;36;1mnew mode 100755[0m
+1 hunks, 2 lines changed
+examine changes to 'a'? [Ynsfdaq?] [0;35m@@ -2,7 +2,7 @@[0m
+ c
+ a
+ a
+[0;31m-b[0m
+[0;32m+dd[0m
+ a
+ a
+ c
+record this change to 'a'? [Ynsfdaq?]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-inverse Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+hg init
+cat > a <<EOF
+a
+b
+c
+EOF
+hg ci -Am adda
+
+cat > a <<EOF
+d
+e
+f
+EOF
+hg ci -m moda
+
+hg diff --inverse -r0 -r1
+
+cat >> a <<EOF
+g
+h
+EOF
+hg diff --inverse --nodates
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-inverse.out Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,20 @@
+adding a
+diff -r 2855cdcfcbb7 -r 8e1805a3cf6e a
+--- a/a Thu Jan 01 00:00:00 1970 +0000
++++ b/a Thu Jan 01 00:00:00 1970 +0000
+@@ -1,3 +1,3 @@
+-d
+-e
+-f
++a
++b
++c
+diff -r 2855cdcfcbb7 a
+--- a/a
++++ b/a
+@@ -1,5 +1,3 @@
+ d
+ e
+ f
+-g
+-h
--- a/tests/test-extension Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-extension Sat Nov 07 14:13:15 2009 -0600
@@ -75,6 +75,20 @@
# command with no output, we just want to see the extensions loaded
hg paths
+# check hgweb's load order
+echo '% hgweb.cgi'
+cat > hgweb.cgi <<EOF
+#!/usr/bin/env python
+from mercurial import demandimport; demandimport.enable()
+from mercurial.hgweb import hgweb
+from mercurial.hgweb import wsgicgi
+
+application = hgweb('.', 'test repo')
+wsgicgi.launch(application)
+EOF
+SCRIPT_NAME='/' SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
+ | grep '^[[:digit:]]) [[:alnum:] ]*$' # ignores HTML output
+
echo 'foo = !' >> $HGRCPATH
echo 'bar = !' >> $HGRCPATH
--- a/tests/test-extension.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-extension.out Sat Nov 07 14:13:15 2009 -0600
@@ -24,6 +24,17 @@
3) bar extsetup
4) foo reposetup
4) bar reposetup
+% hgweb.cgi
+1) foo imported
+1) bar imported
+2) foo uisetup
+2) bar uisetup
+3) foo extsetup
+3) bar extsetup
+4) foo reposetup
+4) bar reposetup
+4) foo reposetup
+4) bar reposetup
empty extension - empty cmdtable
no commands defined
@@ -54,7 +65,7 @@
--debugger start debugger
--encoding set the charset encoding (default: ascii)
--encodingmode set the charset encoding mode (default: strict)
- --traceback print traceback on exception
+ --traceback always print a traceback on exception
--time time how long the command takes
--profile print command execution profile
--version output version information and exit
@@ -84,7 +95,7 @@
--debugger start debugger
--encoding set the charset encoding (default: ascii)
--encodingmode set the charset encoding mode (default: strict)
- --traceback print traceback on exception
+ --traceback always print a traceback on exception
--time time how long the command takes
--profile print command execution profile
--version output version information and exit
--- a/tests/test-glog Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-glog Sat Nov 07 14:13:15 2009 -0600
@@ -165,6 +165,9 @@
hg commit -mmore
hg glog two
+echo "% file log with explicit style (issue 1896)"
+hg glog --style=default one
+
echo % incoming and outgoing
cd ..
hg clone -U -r31 repo repo2
--- a/tests/test-glog.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-glog.out Sat Nov 07 14:13:15 2009 -0600
@@ -575,6 +575,12 @@
date: Thu Jan 01 00:00:00 1970 +0000
summary: two
+% file log with explicit style (issue 1896)
+o changeset: 0:3d578b4a1f53
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: one
+
% incoming and outgoing
requesting all changes
adding changesets
--- a/tests/test-help.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-help.out Sat Nov 07 14:13:15 2009 -0600
@@ -237,6 +237,7 @@
-g --git use git extended diff format
--nodates don't include dates in diff headers
-p --show-function show which function each change is in
+ --inverse produce a diff that undoes the changes
-w --ignore-all-space ignore white space when comparing lines
-b --ignore-space-change ignore changes in the amount of white space
-B --ignore-blank-lines ignore changes whose lines are all blank
--- a/tests/test-hgweb-commands.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgweb-commands.out Sat Nov 07 14:13:15 2009 -0600
@@ -210,17 +210,17 @@
<th class="description">description</th>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/1d22e65f027e">branch</a><span class="branchhead">stable</span> <span class="tag">tip</span> </td>
</tr>
<tr class="parity1">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/a4f92ed23982">Added tag 1.0 for changeset 2ef0ac749a14</a><span class="branchhead">default</span> </td>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/2ef0ac749a14">base</a><span class="tag">1.0</span> </td>
</tr>
@@ -291,7 +291,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td></tr>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
<tr>
<th class="author">parents</th>
<td class="author"></td>
@@ -394,6 +394,7 @@
</ul>
<ul>
<li class="active">file</li>
+<li><a href="/file/tip/foo">latest</a></li>
<li><a href="/diff/a4f92ed23982/foo">diff</a></li>
<li><a href="/annotate/a4f92ed23982/foo">annotate</a></li>
<li><a href="/log/a4f92ed23982/foo">file log</a></li>
@@ -421,7 +422,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th class="author">parents</th>
@@ -522,7 +523,7 @@
<table cellspacing="0">
<tr class="parity0">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
<td class="open">stable</td>
<td class="link">
@@ -532,7 +533,7 @@
</td>
</tr>
<tr class="parity1">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
<td class="inactive">default</td>
<td class="link">
@@ -607,7 +608,7 @@
<table cellspacing="0">
<tr class="parity0">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><i>test</i></td>
<td>
<a class="list" href="/rev/1d22e65f027e?style=gitweb">
@@ -621,7 +622,7 @@
</td>
</tr>
<tr class="parity1">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><i>test</i></td>
<td>
<a class="list" href="/rev/a4f92ed23982?style=gitweb">
@@ -635,7 +636,7 @@
</td>
</tr>
<tr class="parity0">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><i>test</i></td>
<td>
<a class="list" href="/rev/2ef0ac749a14?style=gitweb">
@@ -655,7 +656,7 @@
<table cellspacing="0">
<tr class="parity0">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><a class="list" href="/rev/2ef0ac749a14?style=gitweb"><b>1.0</b></a></td>
<td class="link">
<a href="/rev/2ef0ac749a14?style=gitweb">changeset</a> |
@@ -670,7 +671,7 @@
<table cellspacing="0">
<tr class="parity0">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><a class="list" href="/shortlog/1d22e65f027e?style=gitweb"><b>1d22e65f027e</b></a></td>
<td class="">stable</td>
<td class="link">
@@ -680,7 +681,7 @@
</td>
</tr>
<tr class="parity1">
-<td class="age"><i>many years ago</i></td>
+<td class="age"><i>1970-01-01</i></td>
<td><a class="list" href="/shortlog/a4f92ed23982?style=gitweb"><b>a4f92ed23982</b></a></td>
<td class="">default</td>
<td class="link">
@@ -763,7 +764,7 @@
<script>
<!-- hide script content
-var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "many years", ["stable", true], ["tip"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "many years", ["default", true], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "many years", ["default", false], ["1.0"]]];
+var data = [["1d22e65f027e", [0, 1], [[0, 0, 1]], "branch", "test", "1970-01-01", ["stable", true], ["tip"]], ["a4f92ed23982", [0, 1], [[0, 0, 1]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"]]];
var graph = new Graph();
graph.scale(39);
@@ -875,7 +876,7 @@
1
% failing unbundle, requires POST request
-405 Method Not Allowed
+405 push requires POST request
0
push requires POST request
--- a/tests/test-hgweb-diffs Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgweb-diffs Sat Nov 07 14:13:15 2009 -0600
@@ -38,5 +38,11 @@
echo % diff removed file
"$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
+cd ..
+echo % test import rev as raw-rev
+hg clone -r0 test test1
+cd test1
+hg import -q --exact http://localhost:$HGPORT/rev/1
+
echo % errors
-cat errors.log
+cat ../test/errors.log
--- a/tests/test-hgweb-diffs.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgweb-diffs.out Sat Nov 07 14:13:15 2009 -0600
@@ -59,7 +59,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td></tr>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
<tr>
<th class="author">parents</th>
<td class="author"></td>
@@ -149,6 +149,7 @@
</ul>
<ul>
<li><a href="/file/78e4ebad7cdf/a">file</a></li>
+<li><a href="/file/tip/a">latest</a></li>
<li class="active">diff</li>
<li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
<li><a href="/log/78e4ebad7cdf/a">file log</a></li>
@@ -176,7 +177,7 @@
</tr>
<tr>
<th>date</th>
- <td>Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th>parents</th>
@@ -263,7 +264,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td></tr>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
<tr>
<th class="author">parents</th>
<td class="author"></td>
@@ -357,6 +358,7 @@
</ul>
<ul>
<li><a href="/file/78e4ebad7cdf/a">file</a></li>
+<li><a href="/file/tip/a">latest</a></li>
<li class="active">diff</li>
<li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
<li><a href="/log/78e4ebad7cdf/a">file log</a></li>
@@ -384,7 +386,7 @@
</tr>
<tr>
<th>date</th>
- <td>Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th>parents</th>
@@ -415,4 +417,12 @@
</body>
</html>
+% test import rev as raw-rev
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 2 changes to 2 files
+updating to branch default
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
% errors
--- a/tests/test-hgweb-filelog.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgweb-filelog.out Sat Nov 07 14:13:15 2009 -0600
@@ -148,12 +148,12 @@
<th class="description">description</th>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/01de2d66a28d">second a</a></td>
</tr>
<tr class="parity1">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/5ed941583260">first a</a></td>
</tr>
@@ -231,12 +231,12 @@
<th class="description">description</th>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/01de2d66a28d">second a</a></td>
</tr>
<tr class="parity1">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/5ed941583260">first a</a></td>
</tr>
@@ -314,7 +314,7 @@
<th class="description">description</th>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/5ed941583260">first a</a></td>
</tr>
@@ -392,7 +392,7 @@
<th class="description">description</th>
</tr>
<tr class="parity0">
- <td class="age">many years</td>
+ <td class="age">1970-01-01</td>
<td class="author">test</td>
<td class="description"><a href="/rev/5ed941583260">first a</a></td>
</tr>
@@ -499,7 +499,7 @@
<table class="logEntry parity0">
<tr>
- <th class="age">many years ago:</th>
+ <th class="age">1970-01-01:</th>
<th class="firstline"><a href="/rev/38d962e6234d?style=spartan">change c</a></th>
</tr>
<tr>
@@ -524,7 +524,7 @@
<table class="logEntry parity1">
<tr>
- <th class="age">many years ago:</th>
+ <th class="age">1970-01-01:</th>
<th class="firstline"><a href="/rev/a3b6a9e4507e?style=spartan">mv b</a></th>
</tr>
<tr>
--- a/tests/test-hgweb-removed.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgweb-removed.out Sat Nov 07 14:13:15 2009 -0600
@@ -57,7 +57,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td></tr>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td></tr>
<tr>
<th class="author">parents</th>
<td class="author"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a> </td>
@@ -121,6 +121,7 @@
</ul>
<ul>
<li><a href="/file/c78f6c5cbea9/a">file</a></li>
+<li><a href="/file/tip/a">latest</a></li>
<li class="active">diff</li>
<li><a href="/annotate/c78f6c5cbea9/a">annotate</a></li>
<li><a href="/log/c78f6c5cbea9/a">file log</a></li>
@@ -148,7 +149,7 @@
</tr>
<tr>
<th>date</th>
- <td>Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th>parents</th>
--- a/tests/test-hgwebdir.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-hgwebdir.out Sat Nov 07 14:13:15 2009 -0600
@@ -29,6 +29,7 @@
200 Script output follows
+/t/a/
/b/
/coll/a/
/coll/a/.hg/patches/
@@ -39,7 +40,6 @@
/rcoll/b/
/rcoll/b/d/
/rcoll/c/
-/t/a/
200 Script output follows
@@ -64,7 +64,7 @@
<table class="bigtable">
<tr>
- <th><a href="?sort=-name">Name</a></th>
+ <th><a href="?sort=name">Name</a></th>
<th><a href="?sort=description">Description</a></th>
<th><a href="?sort=contact">Contact</a></th>
<th><a href="?sort=lastchange">Last change</a></th>
@@ -72,7 +72,7 @@
</tr>
<tr class="parity0">
-<td><a href="/b/?style=paper">b</a></td>
+<td><a href="/t/a/?style=paper">t/a</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -80,7 +80,7 @@
</tr>
<tr class="parity1">
-<td><a href="/coll/a/?style=paper">coll/a</a></td>
+<td><a href="/b/?style=paper">b</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -88,7 +88,7 @@
</tr>
<tr class="parity0">
-<td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
+<td><a href="/coll/a/?style=paper">coll/a</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -96,7 +96,7 @@
</tr>
<tr class="parity1">
-<td><a href="/coll/b/?style=paper">coll/b</a></td>
+<td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -104,7 +104,7 @@
</tr>
<tr class="parity0">
-<td><a href="/coll/c/?style=paper">coll/c</a></td>
+<td><a href="/coll/b/?style=paper">coll/b</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -112,7 +112,7 @@
</tr>
<tr class="parity1">
-<td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
+<td><a href="/coll/c/?style=paper">coll/c</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -120,7 +120,7 @@
</tr>
<tr class="parity0">
-<td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
+<td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -128,7 +128,7 @@
</tr>
<tr class="parity1">
-<td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
+<td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -136,7 +136,7 @@
</tr>
<tr class="parity0">
-<td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
+<td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -144,7 +144,7 @@
</tr>
<tr class="parity1">
-<td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
+<td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -152,7 +152,7 @@
</tr>
<tr class="parity0">
-<td><a href="/t/a/?style=paper">t/a</a></td>
+<td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
<td>unknown</td>
<td>Foo Bar <foo.bar@example.com></td>
<td class="age">seconds ago</td>
@@ -200,7 +200,7 @@
<table class="bigtable">
<tr>
- <th><a href="?sort=-name">Name</a></th>
+ <th><a href="?sort=name">Name</a></th>
<th><a href="?sort=description">Description</a></th>
<th><a href="?sort=contact">Contact</a></th>
<th><a href="?sort=lastchange">Last change</a></th>
--- a/tests/test-highlight.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-highlight.out Sat Nov 07 14:13:15 2009 -0600
@@ -33,6 +33,7 @@
</ul>
<ul>
<li class="active">file</li>
+<li><a href="/file/tip/primes.py">latest</a></li>
<li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li>
<li><a href="/annotate/853dcd4de2a6/primes.py">annotate</a></li>
<li><a href="/log/853dcd4de2a6/primes.py">file log</a></li>
@@ -60,7 +61,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th class="author">parents</th>
@@ -152,6 +153,7 @@
</ul>
<ul>
<li><a href="/file/853dcd4de2a6/primes.py">file</a></li>
+<li><a href="/file/tip/primes.py">latest</a></li>
<li><a href="/diff/853dcd4de2a6/primes.py">diff</a></li>
<li class="active">annotate</li>
<li><a href="/log/853dcd4de2a6/primes.py">file log</a></li>
@@ -179,7 +181,7 @@
</tr>
<tr>
<th class="date">date</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (many years ago)</td>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (1970-01-01)</td>
</tr>
<tr>
<th class="author">parents</th>
--- a/tests/test-install Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-install Sat Nov 07 14:13:15 2009 -0600
@@ -1,3 +1,10 @@
#!/bin/sh
+echo '% hg debuginstall'
hg debuginstall
+
+echo '% hg debuginstall with no username'
+HGUSER= hg debuginstall
+
+# Happy End
+true
--- a/tests/test-install.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-install.out Sat Nov 07 14:13:15 2009 -0600
@@ -1,3 +1,4 @@
+% hg debuginstall
Checking encoding (ascii)...
Checking extensions...
Checking templates...
@@ -5,3 +6,13 @@
Checking commit editor...
Checking username...
No problems detected
+% hg debuginstall with no username
+Checking encoding (ascii)...
+Checking extensions...
+Checking templates...
+Checking patch...
+Checking commit editor...
+Checking username...
+ Please specify a username.
+ (specify a username in your .hgrc file)
+1 problems detected, please check your install!
--- a/tests/test-journal-exists Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-journal-exists Sat Nov 07 14:13:15 2009 -0600
@@ -3,6 +3,7 @@
hg init
echo a > a
hg ci -Am0
+hg -q clone . foo
touch .hg/store/journal
@@ -10,3 +11,10 @@
hg ci -Am0
hg recover
+
+echo % check that zero-size journals are correctly aborted
+hg bundle -qa repo.hg
+chmod -w foo/.hg/store/00changelog.i
+hg -R foo unbundle repo.hg 2>&1 | sed 's/\(abort: Permission denied\).*/\1/'
+if test -f foo/.hg/store/journal; then echo 'journal exists :-('; fi
+exit 0
--- a/tests/test-journal-exists.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-journal-exists.out Sat Nov 07 14:13:15 2009 -0600
@@ -1,8 +1,11 @@
adding a
-abort: journal already exists - run hg recover!
+abort: abandoned transaction found - run hg recover!
rolling back interrupted transaction
checking changesets
checking manifests
crosschecking files in changesets and manifests
checking files
1 files, 1 changesets, 1 total revisions
+% check that zero-size journals are correctly aborted
+adding changesets
+abort: Permission denied
--- a/tests/test-merge5.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-merge5.out Sat Nov 07 14:13:15 2009 -0600
@@ -2,6 +2,6 @@
removing b
created new head
% should abort
-abort: crosses branches (use 'hg merge' or 'hg update -C' to discard changes)
+abort: crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes)
% should succeed
-abort: crosses branches (use 'hg merge' or 'hg update -C')
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-minirst.py Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-minirst.py Sat Nov 07 14:13:15 2009 -0600
@@ -12,28 +12,13 @@
paragraphs = """
This is some text in the first paragraph.
- An indented paragraph
- with just two lines.
-
-
-The third paragraph. It is followed by some
-random lines with spurious spaces.
+ A small indented paragraph.
+ It is followed by some lines
+ containing random whitespace.
-
-
-No indention
- here, despite
-the uneven left
- margin.
-
- Only the
- left-most line
- (this line!)
- is significant
- for the indentation
-
+The third and final paragraph.
"""
debugformat('paragraphs', paragraphs, 60)
@@ -108,6 +93,15 @@
Literal block with no indentation (apart from
the two spaces added to all literal blocks).
+
+1. This is an enumerated list (first item).
+2. Continuing with the second item.
+
+(1) foo
+(2) bar
+
+1) Another
+2) List
"""
debugformat('lists', lists, 60)
--- a/tests/test-minirst.py.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-minirst.py.out Sat Nov 07 14:13:15 2009 -0600
@@ -2,15 +2,10 @@
----------------------------------------------------------------------
This is some text in the first paragraph.
- An indented paragraph with just two lines.
-
-The third paragraph. It is followed by some random lines
-with spurious spaces.
+ A small indented paragraph. It is followed by some lines
+ containing random whitespace.
-No indention here, despite the uneven left margin.
-
- Only the left-most line (this line!) is significant for
- the indentation
+The third and final paragraph.
----------------------------------------------------------------------
paragraphs formatted to fit within 30 characters:
@@ -18,19 +13,12 @@
This is some text in the first
paragraph.
- An indented paragraph with
- just two lines.
-
-The third paragraph. It is
-followed by some random lines
-with spurious spaces.
+ A small indented paragraph.
+ It is followed by some lines
+ containing random
+ whitespace.
-No indention here, despite the
-uneven left margin.
-
- Only the left-most line
- (this line!) is significant
- for the indentation
+The third and final paragraph.
----------------------------------------------------------------------
definitions formatted to fit within 60 characters:
@@ -125,6 +113,13 @@
Literal block with no indentation (apart from
the two spaces added to all literal blocks).
+
+1. This is an enumerated list (first item).
+2. Continuing with the second item.
+(1) foo
+(2) bar
+1) Another
+2) List
----------------------------------------------------------------------
lists formatted to fit within 30 characters:
@@ -153,6 +148,15 @@
Literal block with no indentation (apart from
the two spaces added to all literal blocks).
+
+1. This is an enumerated list
+ (first item).
+2. Continuing with the second
+ item.
+(1) foo
+(2) bar
+1) Another
+2) List
----------------------------------------------------------------------
options formatted to fit within 60 characters:
--- a/tests/test-mq-qdiff Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-mq-qdiff Sat Nov 07 14:13:15 2009 -0600
@@ -55,5 +55,8 @@
echo % qdiff -U 1 -B
hg qdiff --nodates -U 1 -B
-echo qdiff -w
+echo % qdiff -w
hg qdiff --nodates -w
+
+echo % qdiff --inverse
+hg qdiff --nodates --inverse
--- a/tests/test-mq-qdiff.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-mq-qdiff.out Sat Nov 07 14:13:15 2009 -0600
@@ -76,7 +76,7 @@
+hello world
+ goodbye world
7
-qdiff -w
+% qdiff -w
diff -r 35fb829491c1 lines
--- a/lines
+++ b/lines
@@ -86,3 +86,21 @@
1
2
3
+% qdiff --inverse
+diff -r 35fb829491c1 lines
+--- a/lines
++++ b/lines
+@@ -1,11 +1,9 @@
+-
+-
+ 1
+ 2
+ 3
+ 4
+-hello world
+- goodbye world
++hello world
++goodbye world
+ 7
+ 8
+ 9
--- a/tests/test-mq-qnew Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-mq-qnew Sat Nov 07 14:13:15 2009 -0600
@@ -54,3 +54,7 @@
hg st
hg qnew -g -f p
cat ../.hg/patches/p
+
+echo '% qnew -u with no username configured'
+HGUSER= hg qnew -u blue red
+cat ../.hg/patches/red
--- a/tests/test-mq-qnew.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-mq-qnew.out Sat Nov 07 14:13:15 2009 -0600
@@ -32,3 +32,6 @@
@@ -1,1 +1,2 @@
b
+b
+% qnew -u with no username configured
+From: blue
+
--- a/tests/test-patchbomb Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-patchbomb Sat Nov 07 14:13:15 2009 -0600
@@ -170,3 +170,10 @@
echo "% test multiple flags for multiple patches"
hg email --date '1970-1-1 0:1' -n --flag fooFlag --flag barFlag -f quux -t foo \
-c bar -s test -r 0:1 | fixheaders
+
+echo "% test multi-byte domain parsing"
+UUML=`printf '\374'`
+export HGENCODING=iso-8859-1
+hg email --date '1980-1-1 0:1' -m tmp.mbox -f quux -t "bar@${UUML}nicode.com" \
+ -s test -r 0
+cat tmp.mbox | fixheaders
--- a/tests/test-patchbomb.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-patchbomb.out Sat Nov 07 14:13:15 2009 -0600
@@ -1469,3 +1469,34 @@
@@ -0,0 +1,1 @@
+b
+% test multi-byte domain parsing
+This patch series consists of 1 patches.
+
+
+Writing [PATCH] test ...
+From quux Tue Jan 1 00:01:01 1980
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH] test
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.315532860@
+User-Agent: Mercurial-patchbomb
+Date: Tue, 01 Jan 1980 00:01:00 +0000
+From: quux
+To: bar@xn--nicode-2ya.com
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent 0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/a Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+
--- a/tests/test-repair-strip.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-repair-strip.out Sat Nov 07 14:13:15 2009 -0600
@@ -10,6 +10,7 @@
rollback failed - please run hg recover
abort: Permission denied .hg/store/data/b.i
% after update 0, strip 2
+abandoned transaction found - run hg recover
checking changesets
checking manifests
crosschecking files in changesets and manifests
@@ -59,6 +60,7 @@
rollback failed - please run hg recover
abort: Permission denied .hg/store/00manifest.i
% after update 0, strip 2
+abandoned transaction found - run hg recover
checking changesets
checking manifests
manifest@?: rev 2 points to nonexistent changeset 2
--- a/tests/test-up-local-change.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-up-local-change.out Sat Nov 07 14:13:15 2009 -0600
@@ -111,7 +111,7 @@
date: Mon Jan 12 13:46:40 1970 +0000
summary: 2
-abort: crosses branches (use 'hg merge' or 'hg update -C' to discard changes)
+abort: crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes)
failed
abort: outstanding uncommitted changes (use 'hg status' to list changes)
failed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-update-branches Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+# Construct the following history tree:
+#
+# @ 5:e1bb631146ca b1
+# |
+# o 4:a4fdb3b883c4 0:b608b9236435 b1
+# |
+# | o 3:4b57d2520816 1:44592833ba9f
+# | |
+# | | o 2:063f31070f65
+# | |/
+# | o 1:44592833ba9f
+# |/
+# o 0:b608b9236435
+
+hg init
+echo foo > foo
+echo zero > a
+hg ci -qAm0
+echo one > a ; hg ci -m1
+echo two > a ; hg ci -m2
+hg up -q 1
+echo three > a ; hg ci -qm3
+hg up -q 0
+hg branch -q b1
+echo four > a ; hg ci -qm4
+echo five > a ; hg ci -qm5
+
+echo % initial repo state
+echo
+hg --config 'extensions.graphlog=' \
+ glog --template '{rev}:{node|short} {parents} {branches}\n'
+
+# Test helper functions.
+
+revtest () {
+ msg=$1
+ dirtyflag=$2 # 'clean' or 'dirty'
+ startrev=$3
+ targetrev=$4
+ opt=$5
+ echo % revtest $msg $startrev $targetrev
+ hg up -qC $startrev
+ test $dirtyflag = dirty && echo dirty > foo
+ hg up $opt $targetrev
+ hg parent --template 'parent={rev}\n'
+ hg stat
+}
+
+norevtest () {
+ msg=$1
+ dirtyflag=$2 # 'clean' or 'dirty'
+ startrev=$3
+ opt=$4
+ echo % norevtest $msg $startrev
+ hg up -qC $startrev
+ test $dirtyflag = dirty && echo dirty > foo
+ hg up $opt
+ hg parent --template 'parent={rev}\n'
+ hg stat
+}
+
+# Test cases are documented in a table in the update function of merge.py.
+# Cases are run as shown in that table, row by row.
+
+norevtest 'none clean linear' clean 4
+norevtest 'none clean same' clean 2
+
+revtest 'none clean linear' clean 1 2
+revtest 'none clean same' clean 2 3
+revtest 'none clean cross' clean 3 4
+
+revtest 'none dirty linear' dirty 1 2
+revtest 'none dirty same' dirty 2 3
+revtest 'none dirty cross' dirty 3 4
+
+revtest '-C dirty linear' dirty 1 2 -C
+revtest '-c dirty linear' dirty 1 2 -c
+norevtest '-c clean same' clean 2 -c
+revtest '-cC dirty linear' dirty 1 2 -cC
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-update-branches.out Sat Nov 07 14:13:15 2009 -0600
@@ -0,0 +1,55 @@
+% initial repo state
+
+@ 5:e1bb631146ca b1
+|
+o 4:a4fdb3b883c4 0:b608b9236435 b1
+|
+| o 3:4b57d2520816 1:44592833ba9f
+| |
+| | o 2:063f31070f65
+| |/
+| o 1:44592833ba9f
+|/
+o 0:b608b9236435
+
+% norevtest none clean linear 4
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=5
+% norevtest none clean same 2
+abort: crosses branches (use 'hg merge' or use 'hg update -c')
+parent=2
+% revtest none clean linear 1 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+% revtest none clean same 2 3
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=3
+% revtest none clean cross 3 4
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=4
+% revtest none dirty linear 1 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+M foo
+% revtest none dirty same 2 3
+abort: crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes)
+parent=2
+M foo
+% revtest none dirty cross 3 4
+abort: crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes)
+parent=3
+M foo
+% revtest -C dirty linear 1 2
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=2
+% revtest -c dirty linear 1 2
+abort: uncommitted local changes
+parent=1
+M foo
+% norevtest -c clean same 2
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+parent=3
+% revtest -cC dirty linear 1 2
+abort: cannot specify both -c/--check and -C/--clean
+parent=1
+M foo
--- a/tests/test-verify Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-verify Sat Nov 07 14:13:15 2009 -0600
@@ -14,6 +14,12 @@
hg verify
echo
+echo % verify with journal
+touch .hg/store/journal
+hg verify
+rm .hg/store/journal
+
+echo
echo % introduce some bugs in repo
cd .hg/store/data
mv _f_o_o.txt.i X_f_o_o.txt.i
--- a/tests/test-verify.out Wed Nov 04 22:14:26 2009 +0100
+++ b/tests/test-verify.out Sat Nov 07 14:13:15 2009 -0600
@@ -10,6 +10,14 @@
checking files
3 files, 1 changesets, 3 total revisions
+% verify with journal
+abandoned transaction found - run hg recover
+checking changesets
+checking manifests
+crosschecking files in changesets and manifests
+checking files
+3 files, 1 changesets, 3 total revisions
+
% introduce some bugs in repo
% verify