Mercurial > hg
changeset 26901:0e3d093c468e
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 11 Nov 2015 15:08:08 -0600 |
parents | d1c741644d25 (diff) a45821a808ab (current diff) |
children | 7ffebbdcb371 |
files | mercurial/posix.py |
diffstat | 32 files changed, 536 insertions(+), 235 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/rebase.py Mon Nov 09 16:24:13 2015 -0600 +++ b/hgext/rebase.py Wed Nov 11 15:08:08 2015 -0600 @@ -220,6 +220,7 @@ abortf = opts.get('abort') collapsef = opts.get('collapse', False) collapsemsg = cmdutil.logmessage(ui, opts) + date = opts.get('date', None) e = opts.get('extrafn') # internal, used by e.g. hgsubversion extrafns = [_savegraft] if e: @@ -454,7 +455,8 @@ editor = cmdutil.getcommiteditor(editform=editform, **opts) newnode = concludenode(repo, rev, p1, p2, extrafn=extrafn, editor=editor, - keepbranches=keepbranchesf) + keepbranches=keepbranchesf, + date=date) else: # Skip commit if we are collapsing repo.dirstate.beginparentchange() @@ -505,7 +507,8 @@ editor = cmdutil.getcommiteditor(edit=editopt, editform=editform) newnode = concludenode(repo, rev, p1, external, commitmsg=commitmsg, extrafn=extrafn, editor=editor, - keepbranches=keepbranchesf) + keepbranches=keepbranchesf, + date=date) if newnode is None: newrev = target else: @@ -586,7 +589,7 @@ ', '.join(str(p) for p in sorted(parents)))) def concludenode(repo, rev, p1, p2, commitmsg=None, editor=None, extrafn=None, - keepbranches=False): + keepbranches=False, date=None): '''Commit the wd changes with parents p1 and p2. Reuse commit info from rev but also store useful information in extra. Return node of committed revision.''' @@ -608,8 +611,10 @@ if keepbranch: repo.ui.setconfig('ui', 'allowemptycommit', True) # Commit might fail if unresolved files exist + if date is None: + date = ctx.date() newnode = repo.commit(text=commitmsg, user=ctx.user(), - date=ctx.date(), extra=extra, editor=editor) + date=date, extra=extra, editor=editor) finally: repo.ui.restoreconfig(backup)
--- a/mercurial/commands.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/commands.py Wed Nov 11 15:08:08 2015 -0600 @@ -5655,7 +5655,11 @@ else: # backup pre-resolve (merge uses .orig for its own purposes) a = repo.wjoin(f) - util.copyfile(a, a + ".resolve") + try: + util.copyfile(a, a + ".resolve") + except (IOError, OSError) as inst: + if inst.errno != errno.ENOENT: + raise try: # preresolve file @@ -5673,7 +5677,11 @@ # replace filemerge's .orig file with our resolve file # for files in tocomplete, ms.resolve will not overwrite # .orig -- only preresolve does - util.rename(a + ".resolve", a + ".orig") + try: + util.rename(a + ".resolve", a + ".orig") + except OSError as inst: + if inst.errno != errno.ENOENT: + raise for f in tocomplete: try: @@ -6578,10 +6586,10 @@ tr.close() except error.BundleUnknownFeatureError as exc: raise error.Abort(_('%s: unknown bundle feature, %s') - % (fname, exc), - hint=_("see https://mercurial-scm.org/" - "wiki/BundleFeature for more " - "information")) + % (fname, exc), + hint=_("see https://mercurial-scm.org/" + "wiki/BundleFeature for more " + "information")) finally: if tr: tr.release()
--- a/mercurial/discovery.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/discovery.py Wed Nov 11 15:08:08 2015 -0600 @@ -238,6 +238,23 @@ unsynced = set() return {None: (oldheads, newheads, unsynced)} +def _nowarnheads(repo, remote, newbookmarks): + # Compute newly pushed bookmarks. We don't warn about bookmarked heads. + localbookmarks = repo._bookmarks + remotebookmarks = remote.listkeys('bookmarks') + bookmarkedheads = set() + for bm in localbookmarks: + rnode = remotebookmarks.get(bm) + if rnode and rnode in repo: + lctx, rctx = repo[bm], repo[rnode] + if bookmarks.validdest(repo, rctx, lctx): + bookmarkedheads.add(lctx.node()) + else: + if bm in newbookmarks and bm not in remotebookmarks: + bookmarkedheads.add(repo[bm].node()) + + return bookmarkedheads + def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False, newbookmarks=[]): """Check that a push won't add any outgoing head @@ -268,19 +285,8 @@ hint=_("use 'hg push --new-branch' to create" " new remote branches")) - # 2. Compute newly pushed bookmarks. We don't warn about bookmarked heads. - localbookmarks = repo._bookmarks - remotebookmarks = remote.listkeys('bookmarks') - bookmarkedheads = set() - for bm in localbookmarks: - rnode = remotebookmarks.get(bm) - if rnode and rnode in repo: - lctx, rctx = repo[bm], repo[rnode] - if bookmarks.validdest(repo, rctx, lctx): - bookmarkedheads.add(lctx.node()) - else: - if bm in newbookmarks and bm not in remotebookmarks: - bookmarkedheads.add(repo[bm].node()) + # 2. Find heads that we need not warn about + nowarnheads = _nowarnheads(repo, remote, newbookmarks) # 3. Check for new heads. # If there are more heads after the push than before, a suitable @@ -366,7 +372,7 @@ " pushing new heads") elif len(newhs) > len(oldhs): # remove bookmarked or existing remote heads from the new heads list - dhs = sorted(newhs - bookmarkedheads - oldhs) + dhs = sorted(newhs - nowarnheads - oldhs) if dhs: if errormsg is None: if branch not in ('default', None):
--- a/mercurial/encoding.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/encoding.py Wed Nov 11 15:08:08 2015 -0600 @@ -414,6 +414,25 @@ return ''.join(_jsonmap[c] for c in toutf8b(s)) +_utf8len = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 4] + +def getutf8char(s, pos): + '''get the next full utf-8 character in the given string, starting at pos + + Raises a UnicodeError if the given location does not start a valid + utf-8 character. + ''' + + # find how many bytes to attempt decoding from first nibble + l = _utf8len[ord(s[pos]) >> 4] + if not l: # ascii + return s[pos] + + c = s[pos:pos + l] + # validate with attempted decode + c.decode("utf-8") + return c + def toutf8b(s): '''convert a local, possibly-binary string into UTF-8b @@ -444,24 +463,32 @@ internal surrogate encoding as a UTF-8 string.) ''' - if isinstance(s, localstr): - return s._utf8 + if "\xed" not in s: + if isinstance(s, localstr): + return s._utf8 + try: + s.decode('utf-8') + return s + except UnicodeDecodeError: + pass - try: - s.decode('utf-8') - return s - except UnicodeDecodeError: - # surrogate-encode any characters that don't round-trip - s2 = s.decode('utf-8', 'ignore').encode('utf-8') - r = "" - pos = 0 - for c in s: - if s2[pos:pos + 1] == c: - r += c + r = "" + pos = 0 + l = len(s) + while pos < l: + try: + c = getutf8char(s, pos) + if "\xed\xb0\x80" <= c <= "\xed\xb3\xbf": + # have to re-escape existing U+DCxx characters + c = unichr(0xdc00 + ord(s[pos])).encode('utf-8') pos += 1 else: - r += unichr(0xdc00 + ord(c)).encode('utf-8') - return r + pos += len(c) + except UnicodeDecodeError: + c = unichr(0xdc00 + ord(s[pos])).encode('utf-8') + pos += 1 + r += c + return r def fromutf8b(s): '''Given a UTF-8b string, return a local, possibly-binary string. @@ -485,7 +512,7 @@ u = s.decode("utf-8") r = "" for c in u: - if ord(c) & 0xff00 == 0xdc00: + if ord(c) & 0xffff00 == 0xdc00: r += chr(ord(c) & 0xff) else: r += c.encode("utf-8")
--- a/mercurial/error.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/error.py Wed Nov 11 15:08:08 2015 -0600 @@ -72,6 +72,12 @@ class UpdateAbort(Abort): """Raised when an update is aborted for destination issue""" +class ResponseExpected(Abort): + """Raised when an EOF is received for a prompt""" + def __init__(self): + from .i18n import _ + Abort.__init__(self, _('response expected')) + class OutOfBandError(Exception): """Exception raised when a remote repo reports failure"""
--- a/mercurial/filemerge.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/filemerge.py Wed Nov 11 15:08:08 2015 -0600 @@ -175,12 +175,19 @@ 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): - return _iother(repo, mynode, orig, fcd, fco, fca, toolconf) - else: - return _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf) + try: + 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) + except error.ResponseExpected: + ui.write("\n") + return 1 @internaltool('local', nomerge) def _ilocal(repo, mynode, orig, fcd, fco, fca, toolconf): @@ -305,16 +312,12 @@ """ assert localorother is not None tool, toolpath, binary, symlink = toolconf - if symlink: - repo.ui.warn(_('warning: :merge-%s cannot merge symlinks ' - 'for %s\n') % (localorother, fcd.path())) - return False, 1 a, b, c, back = files r = simplemerge.simplemerge(repo.ui, a, b, c, label=labels, localorother=localorother) return True, r -@internaltool('merge-local', mergeonly) +@internaltool('merge-local', mergeonly, precheck=_symlinkcheck) def _imergelocal(*args, **kwargs): """ Like :merge, but resolve all conflicts non-interactively in favor @@ -322,7 +325,7 @@ success, status = _imergeauto(localorother='local', *args, **kwargs) return success, status -@internaltool('merge-other', mergeonly) +@internaltool('merge-other', mergeonly, precheck=_symlinkcheck) def _imergeother(*args, **kwargs): """ Like :merge, but resolve all conflicts non-interactively in favor
--- a/mercurial/help.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/help.py Wed Nov 11 15:08:08 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 Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/hgweb/hgweb_mod.py Wed Nov 11 15:08:08 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 Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/hgweb/request.py Wed Nov 11 15:08:08 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 Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/hgweb/server.py Wed Nov 11 15:08:08 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 Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/hgweb/webcommands.py Wed Nov 11 15:08:08 2015 -0600 @@ -264,8 +264,8 @@ yield tmpl('searchentry', parity=parity.next(), author=ctx.user(), - parent=webutil.parents(ctx), - child=webutil.children(ctx), + parent=lambda **x: webutil.parents(ctx), + child=lambda **x: webutil.children(ctx), changelogtag=showtags, desc=ctx.description(), extra=ctx.extra(), @@ -1000,8 +1000,8 @@ "author": iterfctx.user(), "date": iterfctx.date(), "rename": webutil.renamelink(iterfctx), - "parent": webutil.parents(iterfctx), - "child": webutil.children(iterfctx), + "parent": lambda **x: webutil.parents(iterfctx), + "child": lambda **x: webutil.children(iterfctx), "desc": iterfctx.description(), "extra": iterfctx.extra(), "tags": webutil.nodetagsdict(repo, iterfctx.node()), @@ -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/hgweb/webutil.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/hgweb/webutil.py Wed Nov 11 15:08:08 2015 -0600 @@ -297,8 +297,8 @@ return { "author": ctx.user(), - "parent": parents(ctx, rev - 1), - "child": children(ctx, rev + 1), + "parent": lambda **x: parents(ctx, rev - 1), + "child": lambda **x: children(ctx, rev + 1), "changelogtag": showtags, "desc": ctx.description(), "extra": ctx.extra(),
--- a/mercurial/manifest.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/manifest.py Wed Nov 11 15:08:08 2015 -0600 @@ -334,36 +334,44 @@ # zero copy representation of base as a buffer addbuf = util.buffer(base) - # start with a readonly loop that finds the offset of - # each line and creates the deltas - for f, todelete in changes: - # bs will either be the index of the item or the insert point - start, end = _msearch(addbuf, f, start) - if not todelete: - h, fl = self._lm[f] - l = "%s\0%s%s\n" % (f, revlog.hex(h), fl) - else: - if start == end: - # item we want to delete was not found, error out - raise AssertionError( - _("failed to remove %s from manifest") % f) - l = "" - if dstart is not None and dstart <= start and dend >= start: - if dend < end: + changes = list(changes) + if len(changes) < 1000: + # start with a readonly loop that finds the offset of + # each line and creates the deltas + for f, todelete in changes: + # bs will either be the index of the item or the insert point + start, end = _msearch(addbuf, f, start) + if not todelete: + h, fl = self._lm[f] + l = "%s\0%s%s\n" % (f, revlog.hex(h), fl) + else: + if start == end: + # item we want to delete was not found, error out + raise AssertionError( + _("failed to remove %s from manifest") % f) + l = "" + if dstart is not None and dstart <= start and dend >= start: + if dend < end: + dend = end + if l: + dline.append(l) + else: + if dstart is not None: + delta.append([dstart, dend, "".join(dline)]) + dstart = start dend = end - if l: - dline.append(l) - else: - if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) - dstart = start - dend = end - dline = [l] + dline = [l] - if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) - # apply the delta to the base, and get a delta for addrevision - deltatext, arraytext = _addlistdelta(base, delta) + if dstart is not None: + delta.append([dstart, dend, "".join(dline)]) + # apply the delta to the base, and get a delta for addrevision + deltatext, arraytext = _addlistdelta(base, delta) + else: + # For large changes, it's much cheaper to just build the text and + # diff it. + arraytext = array.array('c', self.text()) + deltatext = mdiff.textdiff(base, arraytext) + return arraytext, deltatext def _msearch(m, s, lo=0, hi=None):
--- a/mercurial/merge.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/merge.py Wed Nov 11 15:08:08 2015 -0600 @@ -395,10 +395,15 @@ return complete, r def preresolve(self, dfile, wctx, labels=None): + """run premerge process for dfile + + Returns whether the merge is complete, and the exit code.""" return self._resolve(True, dfile, wctx, labels=labels) def resolve(self, dfile, wctx, labels=None): - """rerun merge process for file path `dfile`""" + """run merge process (assuming premerge was run) for dfile + + Returns the exit code of the merge.""" return self._resolve(False, dfile, wctx, labels=labels)[1] def _checkunknownfile(repo, wctx, mctx, f, f2=None):
--- a/mercurial/posix.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/posix.py Wed Nov 11 15:08:08 2015 -0600 @@ -261,40 +261,17 @@ except UnicodeDecodeError: # OS X percent-encodes any bytes that aren't valid utf-8 s = '' - g = '' - l = 0 - for c in path: - o = ord(c) - if l and o < 128 or o >= 192: - # we want a continuation byte, but didn't get one - s += ''.join(["%%%02X" % ord(x) for x in g]) - g = '' - l = 0 - if l == 0 and o < 128: - # ascii - s += c - elif l == 0 and 194 <= o < 245: - # valid leading bytes - if o < 224: - l = 1 - elif o < 240: - l = 2 - else: - l = 3 - g = c - elif l > 0 and 128 <= o < 192: - # valid continuations - g += c - l -= 1 - if not l: - s += g - g = '' - else: - # invalid - s += "%%%02X" % o + pos = 0 + l = len(s) + while pos < l: + try: + c = encoding.getutf8char(path, pos) + pos += len(c) + except ValueError: + c = '%%%%02X' % path[pos] + pos += 1 + s += c - # any remaining partial characters - s += ''.join(["%%%02X" % ord(x) for x in g]) u = s.decode('utf-8') # Decompose then lowercase (HFS+ technote specifies lower)
--- a/mercurial/templatefilters.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/templatefilters.py Wed Nov 11 15:08:08 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/templates/static/mercurial.js Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/templates/static/mercurial.js Wed Nov 11 15:08:08 2015 -0600 @@ -50,18 +50,6 @@ this.cell_height = this.box_size; } - function colorPart(num) { - num *= 255 - num = num < 0 ? 0 : num; - num = num > 255 ? 255 : num; - var digits = Math.round(num).toString(16); - if (num < 16) { - return '0' + digits; - } else { - return digits; - } - } - this.setColor = function(color, bg, fg) { // Set the colour.
--- a/mercurial/ui.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/ui.py Wed Nov 11 15:08:08 2015 -0600 @@ -756,7 +756,7 @@ self.write(r, "\n") return r except EOFError: - raise error.Abort(_('response expected')) + raise error.ResponseExpected() @staticmethod def extractchoices(prompt): @@ -803,7 +803,7 @@ else: return getpass.getpass('') except EOFError: - raise error.Abort(_('response expected')) + raise error.ResponseExpected() def status(self, *msg, **opts): '''write status message to output (if ui.quiet is False)
--- a/mercurial/util.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/util.py Wed Nov 11 15:08:08 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/mercurial/verify.py Mon Nov 09 16:24:13 2015 -0600 +++ b/mercurial/verify.py Wed Nov 11 15:08:08 2015 -0600 @@ -35,6 +35,17 @@ f = f.replace('//', '/') return f +def _validpath(repo, path): + """Returns False if a path should NOT be treated as part of a repo. + + For all in-core cases, this returns True, as we have no way for a + path to be mentioned in the history but not actually be + relevant. For narrow clones, this is important because many + filelogs will be missing, and changelog entries may mention + modified files that are outside the narrow scope. + """ + return True + def _verify(repo): repo = repo.unfiltered() mflinkrevs = {} @@ -154,7 +165,8 @@ mflinkrevs.setdefault(changes[0], []).append(i) refersmf = True for f in changes[3]: - filelinkrevs.setdefault(_normpath(f), []).append(i) + if _validpath(repo, f): + filelinkrevs.setdefault(_normpath(f), []).append(i) except Exception as inst: refersmf = True exc(i, _("unpacking changeset %s") % short(n), inst) @@ -181,7 +193,9 @@ if not f: err(lr, _("file without name in manifest")) elif f != "/dev/null": # ignore this in very old repos - filenodes.setdefault(_normpath(f), {}).setdefault(fn, lr) + if _validpath(repo, f): + filenodes.setdefault( + _normpath(f), {}).setdefault(fn, lr) except Exception as inst: exc(lr, _("reading manifest delta %s") % short(n), inst) ui.progress(_('checking'), None)
--- a/tests/hghave.py Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/hghave.py Wed Nov 11 15:08:08 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 11 15:08:08 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-commit-interactive.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-commit-interactive.t Wed Nov 11 15:08:08 2015 -0600 @@ -153,7 +153,7 @@ Add binary file - $ hg bundle --base -2 tip.bundle + $ hg bundle --type v1 --base -2 tip.bundle 1 changesets found $ hg add tip.bundle $ hg commit -i -d '4 0' -m binary<<EOF @@ -178,7 +178,7 @@ Change binary file - $ hg bundle --base -2 tip.bundle + $ hg bundle --base -2 --type v1 tip.bundle 1 changesets found $ hg commit -i -d '5 0' -m binary-change<<EOF > y @@ -202,7 +202,7 @@ Rename and change binary file $ hg mv tip.bundle top.bundle - $ hg bundle --base -2 top.bundle + $ hg bundle --base -2 --type v1 top.bundle 1 changesets found $ hg commit -i -d '6 0' -m binary-change-rename<<EOF > y
--- a/tests/test-convert-filemap.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-convert-filemap.t Wed Nov 11 15:08:08 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-debugbundle.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-debugbundle.t Wed Nov 11 15:08:08 2015 -0600 @@ -6,7 +6,7 @@ $ touch a ; hg add a ; hg ci -ma $ touch b ; hg add b ; hg ci -mb $ touch c ; hg add c ; hg ci -mc - $ hg bundle --base 0 --rev tip bundle.hg -v + $ hg bundle --base 0 --rev tip bundle.hg -v --type v1 2 changesets found uncompressed size of bundle content: 332 (changelog)
--- a/tests/test-generaldelta.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-generaldelta.t Wed Nov 11 15:08:08 2015 -0600 @@ -62,7 +62,7 @@ o 0 3903 a $ cd .. - $ hg init client + $ hg init client --config format.generaldelta=false $ cd client $ hg pull -q ../server -r 4 $ hg debugindex x
--- a/tests/test-merge-prompt.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-merge-prompt.t Wed Nov 11 15:08:08 2015 -0600 @@ -5,6 +5,9 @@ 840e2b315c1f: Fix misleading error and prompts during update/merge (issue556) +Make sure HGMERGE doesn't interfere with the test + $ unset HGMERGE + $ status() { > echo "--- status ---" > hg st -A file1 file2 @@ -148,3 +151,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-merge-tools.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-merge-tools.t Wed Nov 11 15:08:08 2015 -0600 @@ -50,6 +50,8 @@ > cat f > echo "# hg stat" > hg stat + > echo "# hg resolve --list" + > hg resolve --list > rm -f f.orig > } @@ -82,6 +84,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f simplest hgrc using false for merge: @@ -103,6 +107,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f #if unix-permissions @@ -150,6 +156,8 @@ space # hg stat M f + # hg resolve --list + R f unless lowered on command line: @@ -171,6 +179,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f or false set higher on command line: @@ -192,6 +202,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f or true set to disabled: $ beforemerge @@ -212,6 +224,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f or true.executable not found in PATH: @@ -233,6 +247,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f or true.executable with bogus path: @@ -254,6 +270,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f but true.executable set to cat found in PATH works: @@ -280,6 +298,8 @@ space # hg stat M f + # hg resolve --list + R f and true.executable set to cat with path works: @@ -305,6 +325,8 @@ space # hg stat M f + # hg resolve --list + R f #if unix-permissions @@ -330,6 +352,8 @@ space # hg stat M f + # hg resolve --list + R f #endif @@ -356,6 +380,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f merge-patterns specifies executable not found in PATH and gets warning: @@ -380,6 +406,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f merge-patterns specifies executable with bogus path and gets warning: @@ -404,6 +432,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f ui.merge overrules priority @@ -428,6 +458,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f ui.merge specifies internal:fail: @@ -447,6 +479,8 @@ space # hg stat M f + # hg resolve --list + U f ui.merge specifies :local (without internal prefix): @@ -465,6 +499,8 @@ space # hg stat M f + # hg resolve --list + R f ui.merge specifies internal:other: @@ -483,6 +519,8 @@ space # hg stat M f + # hg resolve --list + R f ui.merge specifies internal:prompt: @@ -503,6 +541,70 @@ space # hg stat M f + # hg resolve --list + R f + +prompt with EOF + + $ beforemerge + [merge-tools] + false.whatever= + true.priority=1 + true.executable=cat + # hg update -C 1 + $ hg merge -r 2 --config ui.merge=internal:prompt --config ui.interactive=true + no tool found to merge f + keep (l)ocal or take (o)ther? + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ aftermerge + # cat f + revision 1 + space + # hg stat + M f + # hg resolve --list + U f + $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true + no tool found to merge f + keep (l)ocal or take (o)ther? + [1] + $ aftermerge + # cat f + revision 1 + space + # hg stat + M f + ? f.orig + # hg resolve --list + U f + $ rm f + $ hg resolve --all --config ui.merge=internal:prompt --config ui.interactive=true + no tool found to merge f + keep (l)ocal or take (o)ther? + [1] + $ aftermerge + # cat f + revision 1 + space + # hg stat + M f + # hg resolve --list + U f + $ hg resolve --all --config ui.merge=internal:prompt + no tool found to merge f + keep (l)ocal or take (o)ther? l + (no more unresolved files) + $ aftermerge + # cat f + revision 1 + space + # hg stat + M f + ? f.orig + # hg resolve --list + R f ui.merge specifies internal:dump: @@ -527,6 +629,8 @@ ? f.local ? f.orig ? f.other + # hg resolve --list + U f f.base: @@ -568,6 +672,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f Premerge @@ -592,6 +698,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f HGMERGE specifies internal:other but is overruled by --tool=false @@ -615,6 +723,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests @@ -671,6 +781,8 @@ space # hg stat M f + # hg resolve --list + R f update should also have --tool @@ -712,6 +824,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f Default is silent simplemerge: @@ -732,6 +846,8 @@ revision 3 # hg stat M f + # hg resolve --list + R f .premerge=True is same: @@ -752,6 +868,8 @@ revision 3 # hg stat M f + # hg resolve --list + R f .premerge=False executes merge-tool: @@ -778,6 +896,8 @@ space # hg stat M f + # hg resolve --list + R f premerge=keep keeps conflict markers in: @@ -810,6 +930,8 @@ >>>>>>> other: 81448d39c9a0 - test: revision 4 # hg stat M f + # hg resolve --list + R f premerge=keep-merge3 keeps conflict markers with base content: @@ -848,6 +970,8 @@ >>>>>>> other: 81448d39c9a0 - test: revision 4 # hg stat M f + # hg resolve --list + R f Tool execution @@ -886,6 +1010,8 @@ space # hg stat M f + # hg resolve --list + R f Merge with "echo mergeresult > $local": @@ -904,6 +1030,8 @@ mergeresult # hg stat M f + # hg resolve --list + R f - and $local is the file f: @@ -922,6 +1050,8 @@ mergeresult # hg stat M f + # hg resolve --list + R f Merge with "echo mergeresult > $output" - the variable is a bit magic: @@ -940,6 +1070,8 @@ mergeresult # hg stat M f + # hg resolve --list + R f Merge using tool with a path that must be quoted: @@ -969,6 +1101,8 @@ space # hg stat M f + # hg resolve --list + R f Issue3581: Merging a filename that needs to be quoted (This test doesn't work on Windows filesystems even on Linux, so check @@ -1029,6 +1163,8 @@ # hg stat M f ? f.orig + # hg resolve --list + U f #if symlink
--- a/tests/test-merge-types.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-merge-types.t Wed Nov 11 15:08:08 2015 -0600 @@ -105,6 +105,50 @@ a is an executable file with content: a + $ hg update -C 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg merge --debug --tool :merge-local + searching for copies back to rev 1 + resolving manifests + branchmerge: True, force: False, partial: False + ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f + preserving a for resolve of a + a: versions differ -> m (premerge) + picked tool ':merge-local' for a (binary False symlink True) + merging a + my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da + warning: internal :merge-local cannot merge symlinks for a + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + + $ tellmeabout a + a is an executable file with content: + a + + $ hg update -C 1 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg merge --debug --tool :merge-other + searching for copies back to rev 1 + resolving manifests + branchmerge: True, force: False, partial: False + ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f + preserving a for resolve of a + a: versions differ -> m (premerge) + picked tool ':merge-other' for a (binary False symlink True) + merging a + my a@3574f3e69b1c+ other a@521a1e40188f ancestor a@c334dc3be0da + warning: internal :merge-other cannot merge symlinks for a + 0 files updated, 0 files merged, 0 files removed, 1 files unresolved + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + + $ tellmeabout a + a is an executable file with content: + a + Update to link without local change should get us a symlink (issue3316): $ hg up -C 0
--- a/tests/test-pathencode.py Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-pathencode.py Wed Nov 11 15:08:08 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-push-cgi.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-push-cgi.t Wed Nov 11 15:08:08 2015 -0600 @@ -31,7 +31,7 @@ $ . "$TESTDIR/cgienv" $ REQUEST_METHOD="POST"; export REQUEST_METHOD $ CONTENT_TYPE="application/octet-stream"; export CONTENT_TYPE - $ hg bundle --all bundle.hg + $ hg bundle --type v1 --all bundle.hg 1 changesets found $ CONTENT_LENGTH=279; export CONTENT_LENGTH;
--- a/tests/test-template-engine.t Mon Nov 09 16:24:13 2015 -0600 +++ b/tests/test-template-engine.t Wed Nov 11 15:08:08 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 ..