Mercurial > hg
changeset 18891:bd6aed2ad5ee
merge with i18n
Note: i18n work should normally be done on stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 08 Apr 2013 17:57:42 -0500 |
parents | 8c64c4af21a4 (diff) 537e869b17e9 (current diff) |
children | 46c0ca1ef7e1 |
files | |
diffstat | 27 files changed, 305 insertions(+), 117 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgsigs Fri Apr 05 17:04:37 2013 +0200 +++ b/.hgsigs Mon Apr 08 17:57:42 2013 -0500 @@ -67,3 +67,5 @@ a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 0 iD8DBQBRDDROywK+sNU5EO8RAh75AJ9uJCGoCWnP0Lv/+XuYs4hvUl+sAgCcD36QgAnuw8IQXrvv684BAXAnHcA= 7511d4df752e61fe7ae4f3682e0a0008573b0402 0 iD8DBQBRFYaoywK+sNU5EO8RAuErAJoDyhXn+lptU3+AevVdwAIeNFyR2gCdHzPHyWd+JDeWCUR+pSOBi8O2ppM= 5b7175377babacce80a6c1e12366d8032a6d4340 0 iD8DBQBRMCYgywK+sNU5EO8RAq1/AKCWKlt9ysibyQgYwoxxIOZv5J8rpwCcDSHQaaf1fFZUTnQsOePwcM2Y/Sg= +50c922c1b5145dab8baefefb0437d363b6a6c21c 0 iD8DBQBRWnUnywK+sNU5EO8RAuQRAJwM42cJqJPeqJ0jVNdMqKMDqr4dSACeP0cRVGz1gitMuV0x8f3mrZrqc7I= +8a7bd2dccd44ed571afe7424cd7f95594f27c092 0 iD8DBQBRXfBvywK+sNU5EO8RAn+LAKCsMmflbuXjYRxlzFwId5ptm8TZcwCdGkyLbZcASBOkzQUm/WW1qfknJHU=
--- a/.hgtags Fri Apr 05 17:04:37 2013 +0200 +++ b/.hgtags Mon Apr 08 17:57:42 2013 -0500 @@ -80,3 +80,5 @@ a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 2.5 7511d4df752e61fe7ae4f3682e0a0008573b0402 2.5.1 5b7175377babacce80a6c1e12366d8032a6d4340 2.5.2 +50c922c1b5145dab8baefefb0437d363b6a6c21c 2.5.3 +8a7bd2dccd44ed571afe7424cd7f95594f27c092 2.5.4
--- a/contrib/perf.py Fri Apr 05 17:04:37 2013 +0200 +++ b/contrib/perf.py Mon Apr 08 17:57:42 2013 -0500 @@ -2,7 +2,7 @@ '''helper extension to measure performance''' from mercurial import cmdutil, scmutil, util, match, commands, obsolete -from mercurial import repoview, branchmap, merge +from mercurial import repoview, branchmap, merge, copies import time, os, sys cmdtable = {} @@ -54,6 +54,15 @@ # False)))) timer(lambda: sum(map(len, repo.status(**opts)))) +@command('perfaddremove') +def perfaddremove(ui, repo): + try: + oldquiet = repo.ui.quiet + repo.ui.quiet = True + timer(lambda: scmutil.addremove(repo, dry_run=True)) + finally: + repo.ui.quiet = oldquiet + def clearcaches(cl): # behave somewhat consistently across internal API changes if util.safehasattr(cl, 'clearcaches'): @@ -99,6 +108,15 @@ rev in s timer(d) +@command('perfdirs') +def perfdirs(ui, repo): + dirstate = repo.dirstate + 'a' in dirstate + def d(): + dirstate.dirs() + del dirstate._dirs + timer(d) + @command('perfdirstate') def perfdirstate(ui, repo): "a" in repo.dirstate @@ -140,6 +158,14 @@ acceptremote=True) timer(d) +@command('perfpathcopies', [], "REV REV") +def perfpathcopies(ui, repo, rev1, rev2): + ctx1 = scmutil.revsingle(repo, rev1, rev1) + ctx2 = scmutil.revsingle(repo, rev2, rev2) + def d(): + copies.pathcopies(ctx1, ctx2) + timer(d) + @command('perfmanifest') def perfmanifest(ui, repo): def d():
--- a/hgext/patchbomb.py Fri Apr 05 17:04:37 2013 +0200 +++ b/hgext/patchbomb.py Mon Apr 08 17:57:42 2013 -0500 @@ -540,7 +540,13 @@ fp.close() else: if not sendmail: - sendmail = mail.connect(ui, mbox=mbox) + verifycert = ui.config('smtp', 'verifycert') + if opts.get('insecure'): + ui.setconfig('smtp', 'verifycert', 'loose') + try: + sendmail = mail.connect(ui, mbox=mbox) + finally: + ui.setconfig('smtp', 'verifycert', verifycert) ui.status(_('sending '), subj, ' ...\n') ui.progress(_('sending'), i, item=subj, total=len(msgs)) if not mbox:
--- a/mercurial/bookmarks.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/bookmarks.py Mon Apr 08 17:57:42 2013 -0500 @@ -221,14 +221,13 @@ finally: w.release() -def updatefromremote(ui, repo, remote, path): +def updatefromremote(ui, repo, remotemarks, path): ui.debug("checking for updated bookmarks\n") - rb = remote.listkeys('bookmarks') changed = False localmarks = repo._bookmarks - for k in sorted(rb): + for k in sorted(remotemarks): if k in localmarks: - nr, nl = rb[k], localmarks[k] + nr, nl = remotemarks[k], localmarks[k] if nr in repo: cr = repo[nr] cl = repo[nl] @@ -257,9 +256,9 @@ localmarks[n] = cr.node() changed = True ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n)) - elif rb[k] in repo: + elif remotemarks[k] in repo: # add remote bookmarks for changes we already have - localmarks[k] = repo[rb[k]].node() + localmarks[k] = repo[remotemarks[k]].node() changed = True ui.status(_("adding remote bookmark %s\n") % k)
--- a/mercurial/cmdutil.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/cmdutil.py Mon Apr 08 17:57:42 2013 -0500 @@ -1590,10 +1590,13 @@ forgot.extend(forget) return bad, forgot -def duplicatecopies(repo, rev, p1): - "Reproduce copies found in the source revision in the dirstate for grafts" - for dst, src in copies.pathcopies(repo[p1], repo[rev]).iteritems(): - repo.dirstate.copy(src, dst) +def duplicatecopies(repo, rev, fromrev): + '''reproduce copies from fromrev to rev in the dirstate''' + for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems(): + # copies.pathcopies returns backward renames, so dst might not + # actually be in the dirstate + if repo.dirstate[dst] in "nma": + repo.dirstate.copy(src, dst) def commit(ui, repo, commitfunc, pats, opts): '''commit the specified files or all outstanding changes'''
--- a/mercurial/commands.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/commands.py Mon Apr 08 17:57:42 2013 -0500 @@ -2095,7 +2095,7 @@ def debugobsolete(ui, repo, precursor=None, *successors, **opts): """create arbitrary obsolete marker - With no arguments it it display the list obsolescence marker.""" + With no arguments, displays the list of obsolescence markers.""" def parsenodeid(s): try: # We do not use revsingle/revrange functions here to accept @@ -2917,9 +2917,13 @@ return -1 # check for ancestors of dest branch - for rev in repo.revs('::. and %ld', revs): - ui.warn(_('skipping ancestor revision %s\n') % rev) - revs.remove(rev) + crev = repo['.'].rev() + ancestors = repo.changelog.ancestors([crev], inclusive=True) + # don't mutate while iterating, create a copy + for rev in list(revs): + if rev in ancestors: + ui.warn(_('skipping ancestor revision %s\n') % rev) + revs.remove(rev) if not revs: return -1 @@ -2933,7 +2937,9 @@ # check ancestors for earlier grafts ui.debug('scanning for duplicate grafts\n') - for ctx in repo.set("::. - ::%ld", revs): + + for rev in repo.changelog.findmissingrevs(revs, [crev]): + ctx = repo[rev] n = ctx.extra().get('source') if n in ids: r = repo[n].rev() @@ -2947,7 +2953,7 @@ elif ctx.hex() in ids: r = ids[ctx.hex()] ui.warn(_('skipping already grafted revision %s ' - '(was grafted from %d)\n') % (r, ctx.rev())) + '(was grafted from %d)\n') % (r, rev)) revs.remove(r) if not revs: return -1 @@ -4496,14 +4502,15 @@ ui.status(_('pulling from %s\n') % util.hidepassword(source)) revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev')) + remotebookmarks = other.listkeys('bookmarks') + if opts.get('bookmark'): if not revs: revs = [] - rb = other.listkeys('bookmarks') for b in opts['bookmark']: - if b not in rb: + if b not in remotebookmarks: raise util.Abort(_('remote bookmark %s not found!') % b) - revs.append(rb[b]) + revs.append(remotebookmarks[b]) if revs: try: @@ -4514,7 +4521,7 @@ raise util.Abort(err) modheads = repo.pull(other, heads=revs, force=opts.get('force')) - bookmarks.updatefromremote(ui, repo, other, source) + bookmarks.updatefromremote(ui, repo, remotebookmarks, source) if checkout: checkout = str(repo.changelog.rev(other.lookup(checkout))) repo._subtoppath = source @@ -4530,7 +4537,7 @@ for b in opts['bookmark']: # explicit pull overrides local bookmark if any ui.status(_("importing bookmark %s\n") % b) - marks[b] = repo[rb[b]].node() + marks[b] = repo[remotebookmarks[b]].node() marks.write() return ret
--- a/mercurial/context.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/context.py Mon Apr 08 17:57:42 2013 -0500 @@ -291,16 +291,16 @@ try: return self._manifest[path], self._manifest.flags(path) except KeyError: - raise error.LookupError(self._node, path, - _('not found in manifest')) + raise error.ManifestLookupError(self._node, path, + _('not found in manifest')) if '_manifestdelta' in self.__dict__ or path in self.files(): if path in self._manifestdelta: return (self._manifestdelta[path], self._manifestdelta.flags(path)) node, flag = self._repo.manifest.find(self._changeset[0], path) if not node: - raise error.LookupError(self._node, path, - _('not found in manifest')) + raise error.ManifestLookupError(self._node, path, + _('not found in manifest')) return node, flag
--- a/mercurial/copies.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/copies.py Mon Apr 08 17:57:42 2013 -0500 @@ -133,11 +133,13 @@ # we currently don't try to find where old files went, too expensive # this means we can miss a case like 'hg rm b; hg cp a b' cm = {} - for f in b: - if f not in a: - ofctx = _tracefile(b[f], a) - if ofctx: - cm[f] = ofctx.path() + missing = set(b.manifest().iterkeys()) + missing.difference_update(a.manifest().iterkeys()) + + for f in missing: + ofctx = _tracefile(b[f], a) + if ofctx: + cm[f] = ofctx.path() # combine copies from dirstate if necessary if w is not None:
--- a/mercurial/dicthelpers.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/dicthelpers.py Mon Apr 08 17:57:42 2013 -0500 @@ -5,20 +5,46 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -def _diffjoin(d1, d2, default, compare): +def diff(d1, d2, default=None): + '''Return all key-value pairs that are different between d1 and d2. + + This includes keys that are present in one dict but not the other, and + keys whose values are different. The return value is a dict with values + being pairs of values from d1 and d2 respectively, and missing values + represented as default.''' res = {} - if d1 is d2 and compare: + if d1 is d2: # same dict, so diff is empty return res for k1, v1 in d1.iteritems(): if k1 in d2: v2 = d2[k1] - if not compare or v1 != v2: + if v1 != v2: res[k1] = (v1, v2) else: res[k1] = (v1, default) + for k2 in d2: + if k2 not in d1: + res[k2] = (default, d2[k2]) + + return res + +def join(d1, d2, default=None): + '''Return all key-value pairs from both d1 and d2. + + This is akin to an outer join in relational algebra. The return value is a + dict with values being pairs of values from d1 and d2 respectively, and + missing values represented as default.''' + res = {} + + for k1, v1 in d1.iteritems(): + if k1 in d2: + res[k1] = (v1, d2[k1]) + else: + res[k1] = (v1, default) + if d1 is d2: return res @@ -27,9 +53,3 @@ res[k2] = (default, d2[k2]) return res - -def diff(d1, d2, default=None): - return _diffjoin(d1, d2, default, True) - -def join(d1, d2, default=None): - return _diffjoin(d1, d2, default, False)
--- a/mercurial/dirstate.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/dirstate.py Mon Apr 08 17:57:42 2013 -0500 @@ -154,11 +154,14 @@ def flagfunc(self, buildfallback): if self._checklink and self._checkexec: def f(x): - p = self._join(x) - if os.path.islink(p): - return 'l' - if util.isexec(p): - return 'x' + try: + st = os.lstat(self._join(x)) + if util.statislink(st): + return 'l' + if util.statisexec(st): + return 'x' + except OSError: + pass return '' return f
--- a/mercurial/error.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/error.py Mon Apr 08 17:57:42 2013 -0500 @@ -27,6 +27,9 @@ def __str__(self): return RevlogError.__str__(self) +class ManifestLookupError(LookupError): + pass + class CommandError(Exception): """Exception raised on errors in parsing the command line."""
--- a/mercurial/help/config.txt Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/help/config.txt Mon Apr 08 17:57:42 2013 -0500 @@ -1052,6 +1052,16 @@ Optional. Method to enable TLS when connecting to mail server: starttls, smtps or none. Default: none. +``verifycert`` + Optional. Verification for the certificate of mail server, when + ``tls`` is starttls or smtps. "strict", "loose" or False. For + "strict" or "loose", the certificate is verified as same as the + verification for HTTPS connections (see ``[hostfingerprints]`` and + ``[web] cacerts`` also). For "strict", sending email is also + aborted, if there is no configuration for mail server in + ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for + :hg:`email` overwrites this as "loose". Default: "strict". + ``username`` Optional. User name for authenticating with the SMTP server. Default: none.
--- a/mercurial/hgweb/hgweb_mod.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/hgweb/hgweb_mod.py Mon Apr 08 17:57:42 2013 -0500 @@ -250,7 +250,8 @@ except (error.LookupError, error.RepoLookupError), err: req.respond(HTTP_NOT_FOUND, ctype) msg = str(err) - if util.safehasattr(err, 'name') and 'manifest' not in msg: + if (util.safehasattr(err, 'name') and + not isinstance(err, error.ManifestLookupError)): msg = 'revision not found: %s' % err.name return tmpl('error', error=msg) except (error.RepoError, error.RevlogError), inst:
--- a/mercurial/mail.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/mail.py Mon Apr 08 17:57:42 2013 -0500 @@ -6,7 +6,7 @@ # GNU General Public License version 2 or any later version. from i18n import _ -import util, encoding +import util, encoding, sslutil import os, smtplib, socket, quopri, time import email.Header, email.MIMEText, email.Utils @@ -30,6 +30,59 @@ email.Header.Header.__dict__['__init__'] = _unifiedheaderinit +class STARTTLS(smtplib.SMTP): + '''Derived class to verify the peer certificate for STARTTLS. + + This class allows to pass any keyword arguments to SSL socket creation. + ''' + def __init__(self, sslkwargs, **kwargs): + smtplib.SMTP.__init__(self, **kwargs) + self._sslkwargs = sslkwargs + + def starttls(self, keyfile=None, certfile=None): + if not self.has_extn("starttls"): + msg = "STARTTLS extension not supported by server" + raise smtplib.SMTPException(msg) + (resp, reply) = self.docmd("STARTTLS") + if resp == 220: + self.sock = sslutil.ssl_wrap_socket(self.sock, keyfile, certfile, + **self._sslkwargs) + if not util.safehasattr(self.sock, "read"): + # using httplib.FakeSocket with Python 2.5.x or earlier + self.sock.read = self.sock.recv + self.file = smtplib.SSLFakeFile(self.sock) + self.helo_resp = None + self.ehlo_resp = None + self.esmtp_features = {} + self.does_esmtp = 0 + return (resp, reply) + +if util.safehasattr(smtplib.SMTP, '_get_socket'): + class SMTPS(smtplib.SMTP): + '''Derived class to verify the peer certificate for SMTPS. + + This class allows to pass any keyword arguments to SSL socket creation. + ''' + def __init__(self, sslkwargs, keyfile=None, certfile=None, **kwargs): + self.keyfile = keyfile + self.certfile = certfile + smtplib.SMTP.__init__(self, **kwargs) + self.default_port = smtplib.SMTP_SSL_PORT + self._sslkwargs = sslkwargs + + def _get_socket(self, host, port, timeout): + if self.debuglevel > 0: + print >> stderr, 'connect:', (host, port) + new_socket = socket.create_connection((host, port), timeout) + new_socket = sslutil.ssl_wrap_socket(new_socket, + self.keyfile, self.certfile, + **self._sslkwargs) + self.file = smtplib.SSLFakeFile(new_socket) + return new_socket +else: + def SMTPS(sslkwargs, keyfile=None, certfile=None, **kwargs): + raise util.Abort(_('SMTPS requires Python 2.6 or later')) + def _smtp(ui): '''build an smtp connection and return a function to send mail''' local_hostname = ui.config('smtp', 'local_hostname') @@ -39,14 +92,25 @@ smtps = tls == 'smtps' if (starttls or smtps) and not util.safehasattr(socket, 'ssl'): raise util.Abort(_("can't use TLS: Python SSL support not installed")) - if smtps: - ui.note(_('(using smtps)\n')) - s = smtplib.SMTP_SSL(local_hostname=local_hostname) - else: - s = smtplib.SMTP(local_hostname=local_hostname) mailhost = ui.config('smtp', 'host') if not mailhost: raise util.Abort(_('smtp.host not configured - cannot send mail')) + verifycert = ui.config('smtp', 'verifycert', 'strict') + if verifycert not in ['strict', 'loose']: + if util.parsebool(verifycert) is not False: + raise util.Abort(_('invalid smtp.verifycert configuration: %s') + % (verifycert)) + if (starttls or smtps) and verifycert: + sslkwargs = sslutil.sslkwargs(ui, mailhost) + else: + sslkwargs = {} + if smtps: + ui.note(_('(using smtps)\n')) + s = SMTPS(sslkwargs, local_hostname=local_hostname) + elif starttls: + s = STARTTLS(sslkwargs, local_hostname=local_hostname) + else: + s = smtplib.SMTP(local_hostname=local_hostname) mailport = util.getport(ui.config('smtp', 'port', 25)) ui.note(_('sending mail: smtp host %s, port %s\n') % (mailhost, mailport)) @@ -56,6 +120,9 @@ s.ehlo() s.starttls() s.ehlo() + if (starttls or smtps) and verifycert: + ui.note(_('(verifying remote certificate)\n')) + sslutil.validator(ui, mailhost)(s.sock, verifycert == 'strict') username = ui.config('smtp', 'username') password = ui.config('smtp', 'password') if username and not password:
--- a/mercurial/posix.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/posix.py Mon Apr 08 17:57:42 2013 -0500 @@ -557,3 +557,11 @@ if self.realpath != self.path: okayifmissing(os.unlink, self.realpath) okayifmissing(os.rmdir, os.path.dirname(self.realpath)) + +def statislink(st): + '''check whether a stat result is a symlink''' + return st and stat.S_ISLNK(st.st_mode) + +def statisexec(st): + '''check whether a stat result is an executable file''' + return st and (st.st_mode & 0100 != 0)
--- a/mercurial/scmutil.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/scmutil.py Mon Apr 08 17:57:42 2013 -0500 @@ -676,26 +676,32 @@ m.bad = lambda x, y: rejected.append(x) ctx = repo[None] - walkresults = repo.dirstate.walk(m, sorted(ctx.substate), True, False) - for abs in sorted(walkresults): - st = walkresults[abs] - dstate = repo.dirstate[abs] + dirstate = repo.dirstate + walkresults = dirstate.walk(m, sorted(ctx.substate), True, False) + for abs, st in walkresults.iteritems(): + dstate = dirstate[abs] if dstate == '?' and audit_path.check(abs): unknown.append(abs) - if repo.ui.verbose or not m.exact(abs): - rel = m.rel(abs) - repo.ui.status(_('adding %s\n') % ((pats and rel) or abs)) - elif (dstate != 'r' and (not st or - (stat.S_ISDIR(st.st_mode) and not stat.S_ISLNK(st.st_mode)))): + elif dstate != 'r' and not st: deleted.append(abs) - if repo.ui.verbose or not m.exact(abs): - rel = m.rel(abs) - repo.ui.status(_('removing %s\n') % ((pats and rel) or abs)) # for finding renames elif dstate == 'r': removed.append(abs) elif dstate == 'a': added.append(abs) + + unknownset = set(unknown) + toprint = unknownset.copy() + toprint.update(deleted) + for abs in sorted(toprint): + if repo.ui.verbose or not m.exact(abs): + rel = m.rel(abs) + if abs in unknownset: + status = _('adding %s\n') % ((pats and rel) or abs) + else: + status = _('removing %s\n') % ((pats and rel) or abs) + repo.ui.status(status) + copies = {} if similarity > 0: for old, new, score in similar.findrenames(repo, @@ -722,49 +728,6 @@ return 1 return 0 -def updatedir(ui, repo, patches, similarity=0): - '''Update dirstate after patch application according to metadata''' - if not patches: - return [] - copies = [] - removes = set() - cfiles = patches.keys() - cwd = repo.getcwd() - if cwd: - cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()] - for f in patches: - gp = patches[f] - if not gp: - continue - if gp.op == 'RENAME': - copies.append((gp.oldpath, gp.path)) - removes.add(gp.oldpath) - elif gp.op == 'COPY': - copies.append((gp.oldpath, gp.path)) - elif gp.op == 'DELETE': - removes.add(gp.path) - - wctx = repo[None] - for src, dst in copies: - dirstatecopy(ui, repo, wctx, src, dst, cwd=cwd) - if (not similarity) and removes: - wctx.remove(sorted(removes), True) - - for f in patches: - gp = patches[f] - if gp and gp.mode: - islink, isexec = gp.mode - dst = repo.wjoin(gp.path) - # patch won't create empty files - if gp.op == 'ADD' and not os.path.lexists(dst): - flags = (isexec and 'x' or '') + (islink and 'l' or '') - repo.wwrite(gp.path, '', flags) - util.setflags(dst, islink, isexec) - addremove(repo, cfiles, similarity=similarity) - files = patches.keys() - files.extend([r for r in removes if r not in files]) - return sorted(files) - def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None): """Update the dirstate to reflect the intent of copying src to dst. For different reasons it might not end with dst being marked as copied from src.
--- a/mercurial/sslutil.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/sslutil.py Mon Apr 08 17:57:42 2013 -0500 @@ -99,7 +99,7 @@ self.ui = ui self.host = host - def __call__(self, sock): + def __call__(self, sock, strict=False): host = self.host cacerts = self.ui.config('web', 'cacerts') hostfingerprint = self.ui.config('hostfingerprints', host) @@ -107,13 +107,22 @@ if hostfingerprint: raise util.Abort(_("host fingerprint for %s can't be " "verified (Python too old)") % host) + if strict: + raise util.Abort(_("certificate for %s can't be verified " + "(Python too old)") % host) if self.ui.configbool('ui', 'reportoldssl', True): self.ui.warn(_("warning: certificate for %s can't be verified " "(Python too old)\n") % host) return + if not sock.cipher(): # work around http://bugs.python.org/issue13721 raise util.Abort(_('%s ssl connection error') % host) - peercert = sock.getpeercert(True) + try: + peercert = sock.getpeercert(True) + peercert2 = sock.getpeercert() + except AttributeError: + raise util.Abort(_('%s ssl connection error') % host) + if not peercert: raise util.Abort(_('%s certificate error: ' 'no certificate received') % host) @@ -129,13 +138,18 @@ self.ui.debug('%s certificate matched fingerprint %s\n' % (host, nicefingerprint)) elif cacerts: - msg = _verifycert(sock.getpeercert(), host) + msg = _verifycert(peercert2, host) if msg: raise util.Abort(_('%s certificate error: %s') % (host, msg), hint=_('configure hostfingerprint %s or use ' '--insecure to connect insecurely') % nicefingerprint) self.ui.debug('%s certificate successfully verified\n' % host) + elif strict: + raise util.Abort(_('%s certificate with fingerprint %s not ' + 'verified') % (host, nicefingerprint), + hint=_('check hostfingerprints or web.cacerts ' + 'config setting')) else: self.ui.warn(_('warning: %s certificate with fingerprint %s not ' 'verified (check hostfingerprints or web.cacerts '
--- a/mercurial/subrepo.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/subrepo.py Mon Apr 08 17:57:42 2013 -0500 @@ -547,9 +547,10 @@ else: self._repo.ui.status(_('pulling subrepo %s from %s\n') % (subrelpath(self), srcurl)) + remotebookmarks = other.listkeys('bookmarks') self._repo.pull(other) - bookmarks.updatefromremote(self._repo.ui, self._repo, other, - srcurl) + bookmarks.updatefromremote(self._repo.ui, self._repo, + remotebookmarks, srcurl) @annotatesubrepoerror def get(self, state, overwrite=False):
--- a/mercurial/templater.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/templater.py Mon Apr 08 17:57:42 2013 -0500 @@ -66,7 +66,10 @@ break pos += 1 sym = program[s:pos] - yield ('symbol', sym, s) + try: + yield ('string', str(int(sym)), s) + except ValueError: + yield ('symbol', sym, s) pos -= 1 elif c == '}': pos += 1
--- a/mercurial/util.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/util.py Mon Apr 08 17:57:42 2013 -0500 @@ -65,6 +65,8 @@ split = platform.split sshargs = platform.sshargs statfiles = getattr(osutil, 'statfiles', platform.statfiles) +statisexec = platform.statisexec +statislink = platform.statislink termwidth = platform.termwidth testpid = platform.testpid umask = platform.umask
--- a/mercurial/windows.py Fri Apr 05 17:04:37 2013 +0200 +++ b/mercurial/windows.py Mon Apr 08 17:57:42 2013 -0500 @@ -337,3 +337,11 @@ pass expandglobs = True + +def statislink(st): + '''check whether a stat result is a symlink''' + return False + +def statisexec(st): + '''check whether a stat result is an executable file''' + return False
--- a/setup.py Fri Apr 05 17:04:37 2013 +0200 +++ b/setup.py Mon Apr 08 17:57:42 2013 -0500 @@ -148,7 +148,7 @@ # fine, we don't want to load it anyway. Python may warn about # a missing __init__.py in mercurial/locale, we also ignore that. err = [e for e in err.splitlines() - if not e.startswith(b('Not trusting file')) \ + if not e.startswith(b('not trusting file')) \ and not e.startswith(b('warning: Not importing')) \ and not e.startswith(b('obsolete feature not enabled'))] if err:
--- a/tests/test-bookmarks-pushpull.t Fri Apr 05 17:04:37 2013 +0200 +++ b/tests/test-bookmarks-pushpull.t Mon Apr 08 17:57:42 2013 -0500 @@ -204,6 +204,39 @@ Y 3:f6fc62dde3c0 Z 1:0d2164f0ce0d +update a bookmark in the middle of a client pulling changes + + $ cd .. + $ hg clone -q a pull-race + $ hg clone -q pull-race pull-race2 + $ cd pull-race + $ hg up -q Y + $ echo c4 > f2 + $ hg ci -Am4 + $ echo c5 > f3 + $ cat <<EOF > .hg/hgrc + > [hooks] + > outgoing.makecommit = hg ci -Am5; echo committed in pull-race + > EOF + $ cd ../pull-race2 + $ hg pull + pulling from $TESTTMP/pull-race (glob) + searching for changes + adding changesets + adding f3 + committed in pull-race + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + updating bookmark Y + (run 'hg update' to get a working copy) + $ hg book + * @ 1:0d2164f0ce0d + X 1:0d2164f0ce0d + Y 4:b0a5eff05604 + Z 1:0d2164f0ce0d + $ cd ../b + diverging a remote bookmark fails $ hg up -q 4e3505fd9583
--- a/tests/test-command-template.t Fri Apr 05 17:04:37 2013 +0200 +++ b/tests/test-command-template.t Mon Apr 08 17:57:42 2013 -0500 @@ -1360,6 +1360,12 @@ $ hg log -l1 --template '{date|age}\n' 7 years from now +Filter with int function argument: + + $ hg log --template '{fill(author, 20)}\n' -r 0 + User Name + <user@hostname> + Error on syntax: $ echo 'x = "f' >> t
--- a/tests/test-hook.t Fri Apr 05 17:04:37 2013 +0200 +++ b/tests/test-hook.t Mon Apr 08 17:57:42 2013 -0500 @@ -198,7 +198,6 @@ listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} no changes found listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'} - listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'} adding remote bookmark bar importing bookmark bar $ cd ../a @@ -232,6 +231,7 @@ abort: prelistkeys hook exited with status 1 [255] $ cd ../a + $ rm .hg/hgrc prechangegroup hook can prevent incoming changes