Bug 6358 - Error message is different depending on whether curses happened to be used or not
Summary: Error message is different depending on whether curses happened to be used or...
Status: RESOLVED FIXED
Alias: None
Product: Mercurial
Classification: Unclassified
Component: Mercurial (show other bugs)
Version: stable branch
Hardware: PC Linux
: wish bug
Assignee: Bugzilla
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-22 00:52 UTC by Manuel Jacob
Modified: 2020-07-07 00:01 UTC (History)
2 users (show)

See Also:
Python Version: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Manuel Jacob 2020-06-22 00:52 UTC
Steps to reproduce:

  $ export LANG=de_DE.utf8  # Any non-English locale
  $ cd $(mktemp -d)
  $ hg init
  $ echo a > a; hg add a; hg ci -m a
  $ chmod -w .hg/store/data
  $ echo b > b; hg add b

  $ hg ci -m b
  Problem beim Speichern von b!
  Abbruch: Permission denied: '/tmp/tmp.DfrYERMZn0/.hg/store/data/b.i'

Most of the error is in German, but the part from the operating system is in English.

  $ hg ci -m b --config ui.interface=curses -i
  starting interactive selection
  Problem beim Speichern von b!
  Abbruch: Keine Berechtigung: '/tmp/tmp.DfrYERMZn0/.hg/store/data/b.i'

All of the error is in German, including the part from the operating system.

Whether curses happened to be used or not should not make a difference. The reason that it makes a difference is that Mercurial calls `locale.setlocale(locale.LC_ALL, '')` before using curses.

If we decide that operating system messages should always be printed in English, `LC_ALL` could be replaced by `LC_CTYPE` in the call.

If we decide that operating system messages should always be printed in the language demanded by the locale settings, the `locale.setlocale(locale.LC_ALL, '')` could be moved at the beginning of the Python process running Mercurial.
Comment 1 Yuya Nishihara 2020-06-22 07:01 UTC
> the `locale.setlocale(locale.LC_ALL, '')` could be moved at the beginning 
> of the Python process running Mercurial.

It will break date formatting/parsing, so I think s/LC_ALL/LC_CTYPE/ is
the way to go.
Comment 2 Manuel Jacob 2020-06-22 07:58 UTC
> > the `locale.setlocale(locale.LC_ALL, '')` could be moved at the beginning 
> > of the Python process running Mercurial.

> It will break date formatting/parsing, so I think s/LC_ALL/LC_CTYPE/ is
> the way to go.

So you think the OS messages should stay untranslated (causing mixed-language error messages)? Personally, I don’t have an opinion on this, as I never used a English-language system and can’t empathize with people not doing this. ;)

What do you think about moving the setlocale call to the beginning of the program, to get consistent and predictable behavior across Python versions? Python 3 initializes LC_CTYPE, but Python 2 does not. I don’t like the fact that global state like this is changed in the middle of the program. Another place which is affected by this is the SVN bindings. That was in fact the original motivation for finding this bug (maybe I should have made that more transparent).

Good point about the date formatting. What do you think about setting LC_TIME explicitly (to "C"?)?
Comment 3 Yuya Nishihara 2020-06-22 08:12 UTC
> So you think the OS messages should stay untranslated (causing mixed-language error messages)?

I don't have strong feeling about the language of strerror messages as I never
set LC_MESSAGE to anything other than "C".

> What do you think about moving the setlocale call to the beginning of
> the program, to get consistent and predictable behavior across Python versions?
> Python 3 initializes LC_CTYPE, but Python 2 does not.

Sounds reasonable to do setlocale() early if Python 3 does that.

> I don’t like the fact that global state like this is changed in the middle of the program. 

Totally agree. I don't know why curses requires that.

> What do you think about setting LC_TIME explicitly (to "C"?)?

I don't have expertise about locale systen since it's useless in east-asian
countries. I don't know if there are other pitfalls like CSV parsing of MS excel.
Comment 4 HG Bot 2020-06-26 11:25 UTC
Fixed by https://mercurial-scm.org/repo/hg/rev/d2227d4c9e6b
Manuel Jacob <me@manueljacob.de>
curses: do not initialize LC_ALL to user settings (issue6358)

701341f57ceb moved the setlocale() call to right before curses was used. This
didn’t fully solve the problem it was supposed to solve (locale-dependent
functions, like date formatting/parsing), but only postponed it.

Initializing LC_CTYPE seems to be sufficient for curses to work correctly.
Luckily this is already done at interpreter startup on modern Python versions
and, since recently, by Mercurial in the pycompat module in all other cases.

(please test the fix)
Comment 5 Manuel Jacob 2020-06-28 16:46 UTC
The fix will be reverted and a different fix was already submitted for inclusion in the stable branch.
Comment 6 HG Bot 2020-06-29 14:55 UTC
Fixed by https://mercurial-scm.org/repo/hg/rev/1bab6b61b62b
Manuel Jacob <me@manueljacob.de>
curses: do not initialize LC_ALL to user settings (issue6358)

701341f57ceb moved the setlocale() call to right before curses was used. This
didn’t fully solve the problem it was supposed to solve (locale-dependent
functions, like date formatting/parsing and str methods on Python 2), but only
postponed it.

Initializing LC_CTYPE seems to be sufficient for curses to work correctly.
Therefore LC_CTYPE is set while curses is used and reset afterwards. Some
locale-dependent str methods might behave differently on Python 2 while curses
is used, but that shouldn’d be a problem.

(please test the fix)
Comment 7 Bugzilla 2020-07-07 00:01 UTC
Bug was set to TESTING for 7 days, resolving