--- a/mercurial/filemerge.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/filemerge.py Wed Nov 04 15:17:52 2015 -0600
@@ -175,9 +175,12 @@
ui = repo.ui
fd = fcd.path()
- if ui.promptchoice(_(" no tool found to merge %s\n"
- "keep (l)ocal or take (o)ther?"
- "$$ &Local $$ &Other") % fd, 0):
+ index = ui.promptchoice(_(" no tool found to merge %s\n"
+ "keep (l)ocal or take (o)ther?"
+ "$$ &Local $$ &Other") % fd, 0)
+ choice = ['local', 'other'][index]
+
+ if choice == 'other':
return _iother(repo, mynode, orig, fcd, fco, fca, toolconf)
else:
return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf)
--- a/mercurial/help.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/help.py Wed Nov 04 15:17:52 2015 -0600
@@ -115,20 +115,20 @@
doclines = docs.splitlines()
if doclines:
summary = doclines[0]
- cmdname = cmd.split('|')[0].lstrip('^')
+ cmdname = cmd.partition('|')[0].lstrip('^')
results['commands'].append((cmdname, summary))
for name, docs in itertools.chain(
extensions.enabled(False).iteritems(),
extensions.disabled().iteritems()):
# extensions.load ignores the UI argument
mod = extensions.load(None, name, '')
- name = name.split('.')[-1]
+ name = name.rpartition('.')[-1]
if lowercontains(name) or lowercontains(docs):
# extension docs are already translated
results['extensions'].append((name, docs.splitlines()[0]))
for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
- cmdname = cmd.split('|')[0].lstrip('^')
+ cmdname = cmd.partition('|')[0].lstrip('^')
if entry[0].__doc__:
cmddoc = gettext(entry[0].__doc__).splitlines()[0]
else:
@@ -330,7 +330,7 @@
h = {}
cmds = {}
for c, e in commands.table.iteritems():
- f = c.split("|", 1)[0]
+ f = c.partition("|")[0]
if select and not select(f):
continue
if (not select and name != 'shortlist' and
@@ -445,7 +445,7 @@
head, tail = doc, ""
else:
head, tail = doc.split('\n', 1)
- rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
+ rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
if tail:
rst.extend(tail.splitlines(True))
rst.append('\n')
@@ -460,7 +460,7 @@
ct = mod.cmdtable
except AttributeError:
ct = {}
- modcmds = set([c.split('|', 1)[0] for c in ct])
+ modcmds = set([c.partition('|')[0] for c in ct])
rst.extend(helplist(modcmds.__contains__))
else:
rst.append(_('(use "hg help extensions" for information on enabling'
--- a/mercurial/hgweb/hgweb_mod.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/hgweb/hgweb_mod.py Wed Nov 04 15:17:52 2015 -0600
@@ -304,8 +304,8 @@
parts = parts[len(repo_parts):]
query = '/'.join(parts)
else:
- query = req.env['QUERY_STRING'].split('&', 1)[0]
- query = query.split(';', 1)[0]
+ query = req.env['QUERY_STRING'].partition('&')[0]
+ query = query.partition(';')[0]
# process this if it's a protocol request
# protocol bits don't need to create any URLs
--- a/mercurial/hgweb/request.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/hgweb/request.py Wed Nov 04 15:17:52 2015 -0600
@@ -80,7 +80,7 @@
if self._start_response is not None:
self.headers.append(('Content-Type', type))
if filename:
- filename = (filename.split('/')[-1]
+ filename = (filename.rpartition('/')[-1]
.replace('\\', '\\\\').replace('"', '\\"'))
self.headers.append(('Content-Disposition',
'inline; filename="%s"' % filename))
--- a/mercurial/hgweb/server.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/hgweb/server.py Wed Nov 04 15:17:52 2015 -0600
@@ -197,47 +197,6 @@
self.wfile.write('0\r\n\r\n')
self.wfile.flush()
-class _httprequesthandleropenssl(_httprequesthandler):
- """HTTPS handler based on pyOpenSSL"""
-
- url_scheme = 'https'
-
- @staticmethod
- def preparehttpserver(httpserver, ssl_cert):
- try:
- import OpenSSL
- OpenSSL.SSL.Context
- except ImportError:
- raise error.Abort(_("SSL support is unavailable"))
- ctx = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
- ctx.use_privatekey_file(ssl_cert)
- ctx.use_certificate_file(ssl_cert)
- sock = socket.socket(httpserver.address_family, httpserver.socket_type)
- httpserver.socket = OpenSSL.SSL.Connection(ctx, sock)
- httpserver.server_bind()
- httpserver.server_activate()
-
- def setup(self):
- self.connection = self.request
- self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
- self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
-
- def do_write(self):
- import OpenSSL
- try:
- _httprequesthandler.do_write(self)
- except OpenSSL.SSL.SysCallError as inst:
- if inst.args[0] != errno.EPIPE:
- raise
-
- def handle_one_request(self):
- import OpenSSL
- try:
- _httprequesthandler.handle_one_request(self)
- except (OpenSSL.SSL.SysCallError, OpenSSL.SSL.ZeroReturnError):
- self.close_connection = True
- pass
-
class _httprequesthandlerssl(_httprequesthandler):
"""HTTPS handler based on Python's ssl module"""
@@ -311,10 +270,7 @@
def create_server(ui, app):
if ui.config('web', 'certificate'):
- if sys.version_info >= (2, 6):
- handler = _httprequesthandlerssl
- else:
- handler = _httprequesthandleropenssl
+ handler = _httprequesthandlerssl
else:
handler = _httprequesthandler
--- a/mercurial/hgweb/webcommands.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/hgweb/webcommands.py Wed Nov 04 15:17:52 2015 -0600
@@ -1248,7 +1248,7 @@
def _getdoc(e):
doc = e[0].__doc__
if doc:
- doc = _(doc).split('\n')[0]
+ doc = _(doc).partition('\n')[0]
else:
doc = _('(no help text available)')
return doc
@@ -1278,7 +1278,7 @@
yield {'topic': entries[0], 'summary': summary}
early, other = [], []
- primary = lambda s: s.split('|')[0]
+ primary = lambda s: s.partition('|')[0]
for c, e in commands.table.iteritems():
doc = _getdoc(e)
if 'DEPRECATED' in doc or c.startswith('debug'):
--- a/mercurial/templatefilters.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/templatefilters.py Wed Nov 04 15:17:52 2015 -0600
@@ -223,7 +223,7 @@
raise TypeError('cannot encode type %s' % obj.__class__.__name__)
def _uescape(c):
- if ord(c) < 0x80:
+ if 0x20 <= ord(c) < 0x80:
return c
else:
return '\\u%04x' % ord(c)
--- a/mercurial/util.py Tue Nov 03 17:13:27 2015 -0800
+++ b/mercurial/util.py Wed Nov 04 15:17:52 2015 -0600
@@ -91,39 +91,7 @@
def safehasattr(thing, attr):
return getattr(thing, attr, _notset) is not _notset
-def sha1(s=''):
- '''
- Low-overhead wrapper around Python's SHA support
-
- >>> f = _fastsha1
- >>> a = sha1()
- >>> a = f()
- >>> a.hexdigest()
- 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
- '''
-
- return _fastsha1(s)
-
-def _fastsha1(s=''):
- # This function will import sha1 from hashlib or sha (whichever is
- # available) and overwrite itself with it on the first call.
- # Subsequent calls will go directly to the imported function.
- if sys.version_info >= (2, 5):
- from hashlib import sha1 as _sha1
- else:
- from sha import sha as _sha1
- global _fastsha1, sha1
- _fastsha1 = sha1 = _sha1
- return _sha1(s)
-
-def md5(s=''):
- try:
- from hashlib import md5 as _md5
- except ImportError:
- from md5 import md5 as _md5
- global md5
- md5 = _md5
- return _md5(s)
+from hashlib import md5, sha1
DIGESTS = {
'md5': md5,
--- a/tests/hghave.py Tue Nov 03 17:13:27 2015 -0800
+++ b/tests/hghave.py Wed Nov 04 15:17:52 2015 -0600
@@ -463,3 +463,12 @@
@check("slow", "allow slow tests")
def has_slow():
return os.environ.get('HGTEST_SLOW') == 'slow'
+
+@check("hypothesis", "is Hypothesis installed")
+def has_hypothesis():
+ try:
+ import hypothesis
+ hypothesis.given
+ return True
+ except ImportError:
+ return False
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/hypothesishelpers.py Wed Nov 04 15:17:52 2015 -0600
@@ -0,0 +1,62 @@
+# Helper module to use the Hypothesis tool in tests
+#
+# Copyright 2015 David R. MacIver
+#
+# For details see http://hypothesis.readthedocs.org
+
+import os
+import sys
+import traceback
+
+from hypothesis.settings import set_hypothesis_home_dir
+import hypothesis.strategies as st
+from hypothesis import given, Settings
+
+# hypothesis store data regarding generate example and code
+set_hypothesis_home_dir(os.path.join(
+ os.getenv('TESTTMP'), ".hypothesis"
+))
+
+def check(*args, **kwargs):
+ """decorator to make a function a hypothesis test
+
+ Decorated function are run immediately (to be used doctest style)"""
+ def accept(f):
+ # Workaround for https://github.com/DRMacIver/hypothesis/issues/206
+ # Fixed in version 1.13 (released 2015 october 29th)
+ f.__module__ = '__anon__'
+ try:
+ given(*args, settings=Settings(max_examples=2000), **kwargs)(f)()
+ except Exception:
+ traceback.print_exc(file=sys.stdout)
+ sys.exit(1)
+ return accept
+
+
+def roundtrips(data, decode, encode):
+ """helper to tests function that must do proper encode/decode roundtripping
+ """
+ @given(data)
+ def testroundtrips(value):
+ encoded = encode(value)
+ decoded = decode(encoded)
+ if decoded != value:
+ raise ValueError(
+ "Round trip failed: %s(%r) -> %s(%r) -> %r" % (
+ encode.__name__, value, decode.__name__, encoded,
+ decoded
+ ))
+ try:
+ testroundtrips()
+ except Exception:
+ # heredoc swallow traceback, we work around it
+ traceback.print_exc(file=sys.stdout)
+ raise
+ print("Round trip OK")
+
+
+# strategy for generating bytestring that might be an issue for Mercurial
+bytestrings = (
+ st.builds(lambda s, e: s.encode(e), st.text(), st.sampled_from([
+ 'utf-8', 'utf-16',
+ ]))) | st.binary()
--- a/tests/test-convert-filemap.t Tue Nov 03 17:13:27 2015 -0800
+++ b/tests/test-convert-filemap.t Wed Nov 04 15:17:52 2015 -0600
@@ -740,4 +740,48 @@
- converted/a
- toberemoved
+ $ cd ..
+Test case where cleanp2 contains a file that doesn't exist in p2 - for
+example because filemap changed.
+
+ $ hg init cleanp2
+ $ cd cleanp2
+ $ touch f f1 f2 && hg ci -Aqm '0'
+ $ echo f1 > f1 && echo >> f && hg ci -m '1'
+ $ hg up -qr0 && echo f2 > f2 && echo >> f && hg ci -qm '2'
+ $ echo "include f" > filemap
+ $ hg convert --filemap filemap .
+ assuming destination .-hg
+ initializing destination .-hg repository
+ scanning source...
+ sorting...
+ converting...
+ 2 0
+ 1 1
+ 0 2
+ $ hg merge && hg ci -qm '3'
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+ $ echo "include ." > filemap
+ $ hg convert --filemap filemap .
+ assuming destination .-hg
+ scanning source...
+ sorting...
+ converting...
+ 0 3
+ $ hg -R .-hg log -G -T '{shortest(node)} {desc}\n{files % "- {file}\n"}\n'
+ o e9ed 3
+ |\
+ | o 33a0 2
+ | | - f
+ | |
+ o | f73e 1
+ |/ - f
+ |
+ o d681 0
+ - f
+
+ $ hg -R .-hg mani -r tip
+ f
+ $ cd ..
--- a/tests/test-merge-prompt.t Tue Nov 03 17:13:27 2015 -0800
+++ b/tests/test-merge-prompt.t Wed Nov 04 15:17:52 2015 -0600
@@ -148,3 +148,25 @@
changed
*** file2 does not exist
+Non-interactive linear update
+
+ $ hg co -C 0
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo changed >> file1
+ $ hg rm file2
+ $ hg update 1 -y
+ local changed file1 which remote deleted
+ use (c)hanged version or (d)elete? c
+ remote changed file2 which local deleted
+ use (c)hanged version or leave (d)eleted? c
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ status
+ --- status ---
+ A file1
+ C file2
+ --- file1 ---
+ 1
+ changed
+ --- file2 ---
+ 2
+ changed
--- a/tests/test-pathencode.py Tue Nov 03 17:13:27 2015 -0800
+++ b/tests/test-pathencode.py Wed Nov 04 15:17:52 2015 -0600
@@ -9,9 +9,6 @@
import binascii, itertools, math, os, random, sys, time
import collections
-if sys.version_info[:2] < (2, 6):
- sys.exit(0)
-
validchars = set(map(chr, range(0, 256)))
alphanum = range(ord('A'), ord('Z'))
--- a/tests/test-template-engine.t Tue Nov 03 17:13:27 2015 -0800
+++ b/tests/test-template-engine.t Wed Nov 04 15:17:52 2015 -0600
@@ -44,4 +44,17 @@
0 97e5f848f0936960273bbf75be6388cd0350a32b -1 0000000000000000000000000000000000000000
-1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000
+Fuzzing the unicode escaper to ensure it produces valid data
+
+#if hypothesis
+
+ >>> from hypothesishelpers import *
+ >>> import mercurial.templatefilters as tf
+ >>> import json
+ >>> @check(st.text().map(lambda s: s.encode('utf-8')))
+ ... def testtfescapeproducesvalidjson(text):
+ ... json.loads('"' + tf.jsonescape(text) + '"')
+
+#endif
+
$ cd ..