In rare cases (ex. chg), encoding may change on the fly and existing i18n
msgcache needs to be cleared.
With demandimport disabled, test-commit-interactive.t now fails consistently
with and without chg.
| lothiraldan |
| hg-reviewers |
In rare cases (ex. chg), encoding may change on the fly and existing i18n
msgcache needs to be cleared.
With demandimport disabled, test-commit-interactive.t now fails consistently
with and without chg.
| Lint Skipped |
| Unit Tests Skipped |
| mercurial/encoding.py | ||
|---|---|---|
| 596 | Should we catch exceptions here if a callback fails? | |
In D958#16241, @ryanmce wrote:Is there a bugzilla bug where I can see what issue this addresses?
There isn't. This series is to make test-commit-interactive.t pass with chg.
| mercurial/encoding.py | ||
|---|---|---|
| 596 | I think it's the callback's responsibility to catch exceptions if they need to. Besides, we don't do that for hg.wirepeersetupfuncs. | |
| Path | Packages | |||
|---|---|---|---|---|
| M | mercurial/dispatch.py (6 lines) | |||
| M | mercurial/encoding.py (14 lines) | |||
| M | mercurial/hgweb/hgweb_mod.py (2 lines) | |||
| M | mercurial/hgweb/hgwebdir_mod.py (2 lines) | |||
| M | mercurial/i18n.py (2 lines) | |||
| M | tests/test-commit-interactive.t (2 lines) | |||
| M | tests/test-i18n.t (20 lines) |
| raise error.Abort(_("option --config may not be abbreviated!")) | raise error.Abort(_("option --config may not be abbreviated!")) | ||||
| if options["cwd"]: | if options["cwd"]: | ||||
| raise error.Abort(_("option --cwd may not be abbreviated!")) | raise error.Abort(_("option --cwd may not be abbreviated!")) | ||||
| if options["repository"]: | if options["repository"]: | ||||
| raise error.Abort(_( | raise error.Abort(_( | ||||
| "option -R has to be separated from other options (e.g. not " | "option -R has to be separated from other options (e.g. not " | ||||
| "-qR) and --repository may only be abbreviated as --repo!")) | "-qR) and --repository may only be abbreviated as --repo!")) | ||||
| if options["encoding"]: | encoding.setencoding(options["encoding"], options["encodingmode"]) | ||||
| encoding.encoding = options["encoding"] | |||||
| if options["encodingmode"]: | |||||
| encoding.encodingmode = options["encodingmode"] | |||||
| if options["time"]: | if options["time"]: | ||||
| def get_times(): | def get_times(): | ||||
| t = os.times() | t = os.times() | ||||
| if t[4] == 0.0: | if t[4] == 0.0: | ||||
| # Windows leaves this as zero, so use time.clock() | # Windows leaves this as zero, so use time.clock() | ||||
| t = (t[0], t[1], t[2], t[3], time.clock()) | t = (t[0], t[1], t[2], t[3], time.clock()) | ||||
| return t | return t | ||||
| s = get_times() | s = get_times() | ||||
| with profiling.profile(repo.ui, enabled=profile): | with profiling.profile(repo.ui, enabled=profile): | ||||
| for r in self._runwsgi(req, repo): | for r in self._runwsgi(req, repo): | ||||
| yield r | yield r | ||||
| def _runwsgi(self, req, repo): | def _runwsgi(self, req, repo): | ||||
| rctx = requestcontext(self, repo) | rctx = requestcontext(self, repo) | ||||
| # This state is global across all threads. | # This state is global across all threads. | ||||
| encoding.encoding = rctx.config('web', 'encoding') | encoding.setencoding(rctx.config('web', 'encoding')) | ||||
| rctx.repo.ui.environ = req.env | rctx.repo.ui.environ = req.env | ||||
| if rctx.csp: | if rctx.csp: | ||||
| # hgwebdir may have added CSP header. Since we generate our own, | # hgwebdir may have added CSP header. Since we generate our own, | ||||
| # replace it. | # replace it. | ||||
| req.headers = [h for h in req.headers | req.headers = [h for h in req.headers | ||||
| if h[0] != 'Content-Security-Policy'] | if h[0] != 'Content-Security-Policy'] | ||||
| req.headers.append(('Content-Security-Policy', rctx.csp)) | req.headers.append(('Content-Security-Policy', rctx.csp)) | ||||
| repo = os.path.normpath(path) | repo = os.path.normpath(path) | ||||
| name = util.pconvert(repo) | name = util.pconvert(repo) | ||||
| if name.startswith(prefix): | if name.startswith(prefix): | ||||
| name = name[len(prefix):] | name = name[len(prefix):] | ||||
| repos.append((name.lstrip('/'), repo)) | repos.append((name.lstrip('/'), repo)) | ||||
| self.repos = repos | self.repos = repos | ||||
| self.ui = u | self.ui = u | ||||
| encoding.encoding = self.ui.config('web', 'encoding') | encoding.setencoding(self.ui.config('web', 'encoding')) | ||||
| self.style = self.ui.config('web', 'style') | self.style = self.ui.config('web', 'style') | ||||
| self.templatepath = self.ui.config('web', 'templates', untrusted=False) | self.templatepath = self.ui.config('web', 'templates', untrusted=False) | ||||
| self.stripecount = self.ui.config('web', 'stripes') | self.stripecount = self.ui.config('web', 'stripes') | ||||
| if self.stripecount: | if self.stripecount: | ||||
| self.stripecount = int(self.stripecount) | self.stripecount = int(self.stripecount) | ||||
| self._baseurl = self.ui.config('web', 'baseurl') | self._baseurl = self.ui.config('web', 'baseurl') | ||||
| prefix = self.ui.config('web', 'prefix') | prefix = self.ui.config('web', 'prefix') | ||||
| if prefix.startswith('/'): | if prefix.startswith('/'): | ||||
| global _ugettext | global _ugettext | ||||
| try: | try: | ||||
| _ugettext = t.ugettext | _ugettext = t.ugettext | ||||
| except AttributeError: | except AttributeError: | ||||
| _ugettext = t.gettext | _ugettext = t.gettext | ||||
| _msgcache = {} | _msgcache = {} | ||||
| encoding.setencodingcallbacks.append(_msgcache.clear) | |||||
| def gettext(message): | def gettext(message): | ||||
| """Translate message. | """Translate message. | ||||
| The message is looked up in the catalog to get a Unicode string, | The message is looked up in the catalog to get a Unicode string, | ||||
| which is encoded in the local encoding before being returned. | which is encoded in the local encoding before being returned. | ||||
| Important: message is restricted to characters in the encoding | Important: message is restricted to characters in the encoding | ||||
| given by sys.getdefaultencoding() which is most likely 'ascii'. | given by sys.getdefaultencoding() which is most likely 'ascii'. | ||||
| > for l in sys.stdin: | > for l in sys.stdin: | ||||
| > sys.stdout.write(''.join(escape(c) for c in l)) | > sys.stdout.write(''.join(escape(c) for c in l)) | ||||
| > EOF | > EOF | ||||
| $ hg commit -i --encoding cp932 2>&1 <<EOF | $PYTHON $TESTTMP/escape.py | grep '^y - ' | $ hg commit -i --encoding cp932 2>&1 <<EOF | $PYTHON $TESTTMP/escape.py | grep '^y - ' | ||||
| > ? | > ? | ||||
| > q | > q | ||||
| > EOF | > EOF | ||||
| y - \x82\xb1\x82\xcc\x95\xcf\x8dX\x82\xf0\x8bL\x98^(yes) | y - ???????(yes) | ||||
| $ LANGUAGE= | $ LANGUAGE= | ||||
| #endif | #endif | ||||
| Skip | Skip | ||||
| $ hg commit -i <<EOF | $ hg commit -i <<EOF | ||||
| > s | > s | ||||
| Check Mercurial specific translation problems in each *.po files, and | Check Mercurial specific translation problems in each *.po files, and | ||||
| tool itself by doctest | tool itself by doctest | ||||
| $ cd "$TESTDIR"/../i18n | $ cd "$TESTDIR"/../i18n | ||||
| $ $PYTHON check-translation.py *.po | $ $PYTHON check-translation.py *.po | ||||
| $ $PYTHON check-translation.py --doctest | $ $PYTHON check-translation.py --doctest | ||||
| $ cd $TESTTMP | $ cd $TESTTMP | ||||
| Check i18n cache gets invalidated correctly with encoding change: | |||||
| $ cat > $TESTTMP/encodingchange.py << EOF | |||||
| > from mercurial import encoding, registrar | |||||
| > from mercurial.i18n import _ | |||||
| > cmdtable = {} | |||||
| > command = registrar.command(cmdtable) | |||||
| > @command('encodingchange', norepo=True) | |||||
| > def encodingchange(ui): | |||||
| > for encode in ('ascii', 'UTF-8', 'ascii', 'UTF-8'): | |||||
| > encoding.setencoding(encode) | |||||
| > ui.write('%s\n' % encoding.jsonescape(_('(EXPERIMENTAL)'))) | |||||
| > EOF | |||||
| $ LANGUAGE=ja hg --config extensions.encodingchange=$TESTTMP/encodingchange.py encodingchange | |||||
| (?????) | |||||
| (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc) | |||||
| (?????) | |||||
| (\xe5\xae\x9f\xe9\xa8\x93\xe7\x9a\x84\xe5\xae\x9f\xe8\xa3\x85) (esc) | |||||
Should we catch exceptions here if a callback fails?