147 # be printed to console to avoid another IOError/KeyboardInterrupt. |
147 # be printed to console to avoid another IOError/KeyboardInterrupt. |
148 status = -1 |
148 status = -1 |
149 sys.exit(status & 255) |
149 sys.exit(status & 255) |
150 |
150 |
151 |
151 |
152 if pycompat.ispy3: |
152 def initstdio(): |
153 |
153 # stdio streams on Python 3 are io.TextIOWrapper instances proxying another |
154 def initstdio(): |
154 # buffer. These streams will normalize \n to \r\n by default. Mercurial's |
155 # stdio streams on Python 3 are io.TextIOWrapper instances proxying another |
155 # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter |
156 # buffer. These streams will normalize \n to \r\n by default. Mercurial's |
156 # instances, which write to the underlying stdio file descriptor in binary |
157 # preferred mechanism for writing output (ui.write()) uses io.BufferedWriter |
157 # mode. ui.write() uses \n for line endings and no line ending normalization |
158 # instances, which write to the underlying stdio file descriptor in binary |
158 # is attempted through this interface. This "just works," even if the system |
159 # mode. ui.write() uses \n for line endings and no line ending normalization |
159 # preferred line ending is not \n. |
160 # is attempted through this interface. This "just works," even if the system |
160 # |
161 # preferred line ending is not \n. |
161 # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout |
162 # |
162 # and sys.stderr. They will inherit the line ending normalization settings, |
163 # But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout |
163 # potentially causing e.g. \r\n to be emitted. Since emitting \n should |
164 # and sys.stderr. They will inherit the line ending normalization settings, |
164 # "just work," here we change the sys.* streams to disable line ending |
165 # potentially causing e.g. \r\n to be emitted. Since emitting \n should |
165 # normalization, ensuring compatibility with our ui type. |
166 # "just work," here we change the sys.* streams to disable line ending |
166 |
167 # normalization, ensuring compatibility with our ui type. |
167 if sys.stdout is not None: |
168 |
168 # write_through is new in Python 3.7. |
169 if sys.stdout is not None: |
169 kwargs = { |
170 # write_through is new in Python 3.7. |
170 "newline": "\n", |
171 kwargs = { |
171 "line_buffering": sys.stdout.line_buffering, |
172 "newline": "\n", |
172 } |
173 "line_buffering": sys.stdout.line_buffering, |
173 if util.safehasattr(sys.stdout, "write_through"): |
174 } |
174 # pytype: disable=attribute-error |
175 if util.safehasattr(sys.stdout, "write_through"): |
175 kwargs["write_through"] = sys.stdout.write_through |
176 # pytype: disable=attribute-error |
176 # pytype: enable=attribute-error |
177 kwargs["write_through"] = sys.stdout.write_through |
177 sys.stdout = io.TextIOWrapper( |
178 # pytype: enable=attribute-error |
178 sys.stdout.buffer, sys.stdout.encoding, sys.stdout.errors, **kwargs |
179 sys.stdout = io.TextIOWrapper( |
179 ) |
180 sys.stdout.buffer, |
180 |
181 sys.stdout.encoding, |
181 if sys.stderr is not None: |
182 sys.stdout.errors, |
182 kwargs = { |
183 **kwargs |
183 "newline": "\n", |
184 ) |
184 "line_buffering": sys.stderr.line_buffering, |
185 |
185 } |
186 if sys.stderr is not None: |
186 if util.safehasattr(sys.stderr, "write_through"): |
187 kwargs = { |
187 # pytype: disable=attribute-error |
188 "newline": "\n", |
188 kwargs["write_through"] = sys.stderr.write_through |
189 "line_buffering": sys.stderr.line_buffering, |
189 # pytype: enable=attribute-error |
190 } |
190 sys.stderr = io.TextIOWrapper( |
191 if util.safehasattr(sys.stderr, "write_through"): |
191 sys.stderr.buffer, sys.stderr.encoding, sys.stderr.errors, **kwargs |
192 # pytype: disable=attribute-error |
192 ) |
193 kwargs["write_through"] = sys.stderr.write_through |
193 |
194 # pytype: enable=attribute-error |
194 if sys.stdin is not None: |
195 sys.stderr = io.TextIOWrapper( |
195 # No write_through on read-only stream. |
196 sys.stderr.buffer, |
196 sys.stdin = io.TextIOWrapper( |
197 sys.stderr.encoding, |
197 sys.stdin.buffer, |
198 sys.stderr.errors, |
198 sys.stdin.encoding, |
199 **kwargs |
199 sys.stdin.errors, |
200 ) |
200 # None is universal newlines mode. |
201 |
201 newline=None, |
202 if sys.stdin is not None: |
202 line_buffering=sys.stdin.line_buffering, |
203 # No write_through on read-only stream. |
203 ) |
204 sys.stdin = io.TextIOWrapper( |
204 |
205 sys.stdin.buffer, |
205 |
206 sys.stdin.encoding, |
206 def _silencestdio(): |
207 sys.stdin.errors, |
207 for fp in (sys.stdout, sys.stderr): |
208 # None is universal newlines mode. |
208 if fp is None: |
209 newline=None, |
209 continue |
210 line_buffering=sys.stdin.line_buffering, |
210 # Check if the file is okay |
211 ) |
211 try: |
212 |
212 fp.flush() |
213 def _silencestdio(): |
213 continue |
214 for fp in (sys.stdout, sys.stderr): |
214 except IOError: |
215 if fp is None: |
215 pass |
216 continue |
216 # Otherwise mark it as closed to silence "Exception ignored in" |
217 # Check if the file is okay |
217 # message emitted by the interpreter finalizer. |
218 try: |
218 try: |
219 fp.flush() |
219 fp.close() |
220 continue |
220 except IOError: |
221 except IOError: |
221 pass |
222 pass |
|
223 # Otherwise mark it as closed to silence "Exception ignored in" |
|
224 # message emitted by the interpreter finalizer. |
|
225 try: |
|
226 fp.close() |
|
227 except IOError: |
|
228 pass |
|
229 |
|
230 |
|
231 else: |
|
232 |
|
233 def initstdio(): |
|
234 for fp in (sys.stdin, sys.stdout, sys.stderr): |
|
235 procutil.setbinary(fp) |
|
236 |
|
237 def _silencestdio(): |
|
238 pass |
|
239 |
222 |
240 |
223 |
241 def _formatargs(args): |
224 def _formatargs(args): |
242 return b' '.join(procutil.shellquote(a) for a in args) |
225 return b' '.join(procutil.shellquote(a) for a in args) |
243 |
226 |