stdout strangeness

Steve Borho steve at borho.org
Wed Jul 8 09:37:53 CDT 2009


On Wed, Jul 8, 2009 at 7:59 AM, Robert Bauck Hamar<r.b.hamar at usit.uio.no> wrote:
> *Steve Borho:
>>
>> Can anyone explain this behavior?
>> % echo "[hooks]\nprechangegroup.locked = echo REPOSITORY IS LOCKED &&
>> exit 1" >> .hg/hgrc
>
> [...]
>>
>> % hg push -v ../foo
>> pushing to ../foo
>> searching for changes
>> 1 changesets found
>> running hook prechangegroup.locked: echo REPOSITORY IS LOCKED && exit 1
>> REPOSITORY IS LOCKED
>> abort: prechangegroup.locked hook exited with status 1
>>
>> This is exactly what you would expect.  Now if you run 'hgtk synch',
>> enter the path, and press the 'push' button, you get this in the
>> dialog:
>>
>> pushing to ../foo
>> searching for changes
>> 1 changesets found
>> running hook prechangegroup.locked: echo REPOSITORY IS LOCKED && exit 1
>> abort: prechangegroup.locked hook exited with status 1
>>
>> Notice the hook output is missing.  If you look in your console
>> window, you'll find the missing 'REPOSITORY IS LOCKED' message.
>
> Let me take a guess: hgtk just replaces sys.std* to get output from hg, or
> something?

For the most part, Mercurial directs all output to ui.write, so
implementing our own version of that class gets us 99% of what we
need.  For tools that do http connections, we've had to redirect
sys.stdout and sys.stderr to point to our dialog which implements
write() methods.  Otherwise http tracebacks and error messages get
lost.
The hook mechanism seems to go a layer deeper.

>> The thing is, the synchronize tool is doing everything I can think of to
>> get the output of these commands.  I'm subclassing ui and redirecting write
>> calls to my output window.  I'm redirecting sys.stdout and sys.stderr to my
>> output window, and I've even tested with redirecting sys.__stdout__ and
>> sys.__stderr__ to no effect.
>
> The real solution must be to close the file descriptors, and reopen these to
> a pipe you can use. Something in the line of:
>
> readfd, writefd = os.pipe()
> os.dup2(writefd, sys.__stdout__.fileno())
>
> The second line here will close the connection between sys.__stdout__ and
> the shell. That might be harmful. A better idea might be to monkeypatch
> os.system to use subprocess.Popen or something.

Aha, that's what I've been missing.  The hook mechanism spawns another
process and it inherits the original stdout file descriptor.  Thanks
for pointing out the obvious.

--
Steve Borho



More information about the Mercurial mailing list