1. Jens Alfke
  2. Murky
  3. Issues
Issue #10 open

path to hg binary hardcoded

Benjamin Bock
created an issue

The path to hg is currently hardcoded to /usr/local/bin/hg, but mine (and I guess most MacPorts Mercurial installations) are located in /opt/local/bin.

This should find the binary via "which" or make it configurable.

Comments (40)

  1. Jens Alfke repo owner
    • changed status to open

    Hm, it's supposed to be able to find hg using 'which'. Take a look at +[HgOperation findHgTool]. Would you mind tracing through that and seeing why it doesn't work for you? I do remember testing it when I first wrote it, but there might be some reason it only works on my machine.

    (In addition, you can override the path by setting the user default HgToolPath.)

  2. Anonymous

    I would guess this has nothing to do with Murky, but rather the fact that on my machine at least, the MacPorts path is not available to GUI applications. In other words, OS X does not seem to source .profile when setting up the UI shell. From the Terminal command line, everything works.

    I will try some .bash_profile trickery and see how things go.

  3. Jens Alfke repo owner

    There isn't a "UI shell" — there's no shell at all when running GUI apps, so .profile won't affect them.

    HgOperation explicitly launches a shell and asks it where the 'hg' command is, so it should work. And IIRC, it worked for me when I wrote it...

  4. Jens Alfke repo owner

    I just ran Murky and the log messages show that it successfully located 'hg' and the Python path:

    5/1/09 10:43:42 PM Murky[14923] Task: /bin/csh -c which hg && echo $PYTHONPATH 
    5/1/09 10:43:42 PM Murky[14923] tool='/usr/local/bin/hg', pythonPath='/Users/snej/lib/python' 
    

    What do you get when you run it?

  5. Sören Kuklau

    I get:

    5/2/09 10:29:40 AM Murky[4932] Task: /bin/bash -c which hg && echo $PYTHONPATH 
    5/2/09 10:29:40 AM Murky[4932]     *** task returned 1: (null) 
    5/2/09 10:29:40 AM Murky[4932] Warning: Couldn't find 'hg' tool; assuming it's in /usr/local/bin 
    

    I don't think bash's which can be called like that, because it is a builtin. If I manually run that line, I get which's help:

    $ /bin/bash -c which hg && echo $PYTHONPATH
    Usage: which [options] [--] COMMAND [...]
    Write the full path of COMMAND(s) to standard output.
    [..]
    

    Whereas, if I call which directly, it works:

    $ which hg && echo $PYTHONPATH
    /Gentoo/usr/bin/hg
    

    Since you're using tcsh, you're probably getting a different version of which.

  6. Benjamin Bock reporter

    I'm getting this

    2009-05-02 11:04:21.124 Murky[65338:10b] Task: /bin/bash -c which hg && echo $PYTHONPATH
    

    I didn't get "task returned 1: (null)" as chucker did. After the above came a popup window saying it couldn't find hg, then (again on the console):

    The Debugger has exited with status 0.
    

    In the Terminal:

    $ /bin/bash -c which hg && echo $PYTHONPATH
    usage: which [-as] program ...
    $ which hg && echo $PYTHONPATH
    /opt/local/bin/hg
    

    This bash -c thing doesn't seem to work, but my which is different from chucker's.

  7. Jens Alfke repo owner

    The "-c" flag only evaluates the single next argument. If you look at the source code, everything after "-c" is a single argument; so if you want to reproduce this on the command line you have to quote it. Here's what I get:

    $ bin/bash -c 'which hg && echo $PYTHONPATH'
    /usr/local/bin/hg
    /Users/snej/lib/python
    
  8. Jens Alfke repo owner

    Ah, I found the problem: if there's no environment variable PYTHONPATH, the shell returns an error "PYTHONPATH: Undefined variable". Since this variable is optional to Murky, I need to find a way to check it without incurring an error, or at least to distinguish this error from a more serious one.

  9. Daniel Myers

    Even with the changes made above. I was still having this issue where it wasn't finding hg in path (might be the way I am adding /opt/local/bin path to env PATH). Either way it was still throwing can not find hg at /usr/local/bin/hg. I did make a few changes to the code that searches typical paths for standard installation, macports and fink and tests if hg was there then returns that path, I am including the proposed patch (it might be a little rough hack as I am still learning a bit of objective C).

  10. Jens Alfke repo owner

    Daniel — I really don't want to start searching through directories. Instead let's fix the problem that keeps the existing code from working on your system. First, turn on some logging by setting the command line arguments -Log YES -LogMYTask YES. When Murky starts you should get some console output like:

    17:50:46.508| MYTask: $ /bin/csh -c 'echo $PYTHONPATH'
    17:50:46.545| PYTHONPATH = '/Users/snej/lib/python'
    17:50:46.545| MYTask: $ /bin/csh -c 'which hg'
    17:50:46.570| 'hg' path = '/usr/local/bin/hg'
    

    Take a look at what you get instead, and if there are any error messages. The code for this is at the top of HgOperation.m; you could try single-stepping through it to see where it goes wrong.

  11. Daniel Myers

    Ok, first my path to /opt/local/bin is located in /etc/paths file if I open murky directly from a terminal then it doesn't have any issues. But adding the switches to xcode came up with this:

    08:35:32.085| Logging mode 2 enabled in domains: {MYTask}

    08:35:32.085| MYTask: $ /bin/bash -c 'echo $PYTHONPATH'

    and that was all it showed, I have tried stepping through the program in that particular spot but didn't find out what was going on, its like its sending the command to the shell but not getting a response back at this point. I will look a little deeper once I have a little more caffeine in my system. As for the patch really it was an alternative that was working on my system as a fall back when the other mechanisms didn't work. As I wrote it pretty late and it was really the first objective c I had written, may not have been the best approach in general.

  12. Jonathan Wight
    23:09:08.425| Logging mode 2 enabled in domains: {MYTask}
    23:09:08.425| MYTask: $ /bin/bash -c 'echo $PYTHONPATH'
    

    Failing for me as well. Why not just make it a preference?

    You're never going to get it right for 100% of all users. So just make a pref and be done with it.

  13. Anonymous

    Yes, I can see two options: either making people add their hg path to /.MacOSX/environment.plist or having a preference. The latter seems a lot more reasonable.

    You can still try and find it at /usr/local/bin/hg since it seems to be where the binary packages put it.

  14. Daniel Myers

    Honestly, I think that searching for it is just plain ok, there is no guarantees to other people's environments and relying on their environment being setup a specific way just to find hg isn't a good way to go. Even though which is reliable on even my terminal something in my setup is causing which to return null after being ran from murky. I agree with Jonathan that it should be a preference either way even if the searching for it is still being done. I don't agree with the returning /usr/local/bin/hg if which can't find it, not a lot different than searching a few dir for the program and then return nil. Basically what I am saying is a preference should be given even if hg is still be searched for, if the preference is set then the searching wouldn't have to be done so the cost of trying to find hg would only happen once, or when the location changed.

    I did step through it the other day, it doesn't give any real clues other than which return's null when it gets to running that.

  15. Jens Alfke repo owner

    Well, it already is searching — that's what the "which" command does. I'm just letting the shell do it because it knows where to look. The idea is that if Mercurial is installed, "hg" must already be on your search path or you wouldn't be able to run it from the command line.

    There is some kind of bug that keeps the 'which' command from working in some cases; I want to fix that.

    I have no problem with adding a pref, though. It should be easy to do, and some people might have a need to run a different copy of hg than the one in their search path. But it should be a fallback.

  16. Jens Alfke repo owner

    Daniel, Jonathan — What happens after it logs "MYTask: $ /bin/bash -c 'echo $PYTHONPATH'"? Does it hang, or crash, or fail to open a window, or what?

    If it got to the point of logging that message (MYOperation.m:17, called from line 37) then the next thing after the task completes must be logging the path that it found (line 38). If it's not doing that, then either an exception was thrown, or it crashed, or it's locked up.

    (And note that getting PYTHONPATH is independent of locating 'hg' ... it has to be done also, even if you know where 'hg' is, for Mercurial to be able to run in some configurations. So using a pref for the location of 'hg' won't resolve this problem.)

    Could you please dig into this a bit more? Send me a backtrace of where it's hung, or where the exception gets thrown from? This might be a bug in MYTask, in which case it could cause other problems as well. Thanks.

  17. Daniel Myers

    After it logs the MyTask, its like the rest is skipped and the window that says /usr/local/bin/hg is not found pops up. No errors, no crashing, no other failures...

  18. Olivier Scherler

    I made a few tests. What happens to Daniel and Jonathan (logging that stops working after MYTask: $ /bin/bash -c 'echo $PYTHONPATH') happens to me too if I hardcode the shell in runShell to /bin/bash or /bin/sh. With the shell set to /bin/tcsh or /bin/csh the problem does not occur.

    My PATH is still /Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin though, so which doesn't find hg which is in /usr/local/bin.

  19. Jens Alfke repo owner

    Olivier — Oh, good clue. I tried making it run /bin/bash, and what I find is that after HgTask returns, stderr is hosed! Nothing happens when writing to stderr anymore, which is why none of the rest of the logging shows up. That is really scary … is it a bug in NSTask? How could a child process mess up the parent's stderr pipe? And why would bash do it but not tcsh?

  20. Jens Alfke repo owner

    Found the key problem: Bash has an incredibly confusing set of different modes it runs in depending on how it's invoked, whether stdio connects to a terminal, the phase of the moon, etc. Turns out that when run non-interactively the way I'm calling it, it doesn't read any of the user startup files like .bash_profile. Gee, thanks. The fix is to prefix a "--login" argument.

    I still don't know WTF is going on with stderr. It only happens when running in Xcode, too — if I run Murky from the Finder and look at its output in Console.app, all the logging appears.

  21. Olivier Scherler
    • changed status to open

    I have finally found what kept Murky from finding hg in my case (I use tcsh):

    I setup my environment using the instructions in /usr/share/tcsh/examples/README, which ends up reading files in /Library/init/tcsh/ for environment, aliases, path etc instead of putting everything in /.tcshrc.

    The problem is that the path file is read by .login, and non-login tcsh shells don't read .login. Moreover you can't make the shell in your NSTask a login shell (as you now do with bash) because the -l option to do that must be the only option.

    You could of course decide that my setup is a special case, that you can't handle all of them and it's therefore my responsibility to make sure Murky finds hg (e.g. with the HgToolPath hidden pref), but I don't think I'm doing anything out of the ordinary, I just followed the instructions given in example tcsh configuration files that shipped with Mac OS X.

    As far as I'm concerned, the way you're doing it now, with a hidden pref, asking the shell and testing /usr/local/bin/hg is perfectly fine. It works for me because I have hg in /usr/local/bin/ and I wouldn't mind setting a preference, hidden or not. However, given the complexity of the problem of finding hg that we discovered in this thread (and we only saw the problems with bash and tcsh, there are many other shells), maybe it would be better to have a setting in the preferences window. It could be empty be default, in which case Murky tries and find hg like it does now and maybe displays the path it's using, in grey text, above the text field where you would specify an alternate path. What do you think? I volunteer to implement this if you like it.

    As a side note, in a BBEdit worksheet my path is set correctly, I wonder how they did it. Jim Correia is following the project, maybe if we ask nicely… :-)

  22. Jens Alfke repo owner

    Olivier — Hm. I use tcsh and I always set up the path in .tcshrc so that it'll be set up in non-interactive shellscripts no matter where they're run from. It seems weird how that tcsh setup only has the .login script setting up the path. Still, it's installed on the system, and Fred Sanchez is a dude, so I can't argue.

    Maybe I could add a "source /.login" statement to the command string...

  23. Jens Alfke repo owner
    • ping* Could some of you bash users confirm/deny whether the latest patches fix the problems you were having? I'd like to know before I put out a binary build.
  24. Olivier Scherler

    It seems weird how that tcsh setup only has the .login script setting up the path.

    Yes, I only discovered yesterday that it was the case. I fixed it by setting up the path in rc if it wasn't done in login. It should save me some headaches in the future.

    Maybe I could add a "source /.login" statement to the command string...

    It seems to work. However, if you start doing this kind of thing you might end up having to deal with specificities for every shell there is. Unless you decide to consider only bash and tcsh since they are the new and old default shells of Mac OS X.

    I think you can reasonably go with:

    • Adding -l to bash
    • Adding source ~/.login to tcsh
    • Fallback with looking in /usr/local/bin as that's where the binary packages put hg
    • If nothing works require the user to provide the path in a preference, either via the GUI of the Terminal. Mercurial users with an exotic shell or setup (I consider my setup as exotic even though it's based on OS-provided examples) should find it reasonable.
  25. dwt

    I'd like to add that with my zsh setup this also doesn't work. zsh keeps its settings in .zshrc (and with the zsh-lovers setup in .zshrc.local) but zsh only reads those files if it's in an interactive session (zsh --interactive).

    I've been able to fix this by adding this:

    diff -r 6dbaffc46001 Source/HgOperation.m
    --- a/Source/HgOperation.m	Thu May 28 21:23:27 2009 -0700
    +++ b/Source/HgOperation.m	Sun May 31 14:30:58 2009 +0200
    @@ -24,6 +24,9 @@
         if ($equal(shellPath,@"/bin/bash"))
             [sh prependArguments: @"--login",nil];  // To get @*%&$ bash to read its .profile script
         
    +	if ($equal(shellPath,@"/bin/zsh"))
    +		[sh prependArguments: @"--interactive",nil]; // To get zsh to read all its config files
    +	
         if ([sh run: outError])
             return [sh.output stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
         else {
    

    unfortunately however, that makes each shell command load the interactive environment, which is quite slow. :-/

  26. Jens Alfke repo owner

    dwt — Thanks for the info. Is the slowdown really a problem? The shell is only run at launch to find the 'hg' tool and get the PYTHONPATH variable. The runtime calls to 'hg' are made directly and don't use a shell.

  27. Anonymous

    FWIW, this is still an issue in Murky 0.6 for me on Snow Leopard. Why not just give us an option to type in the path? Wouldn't that be a million times easier?

  28. Jens Alfke repo owner

    Anonymous -- Because it's not Mac-like? I'd much rather fix the bug than add a workaround that requires more work on the user's part.

    If you can turn on logging, by setting the default Log to YES, and provide any relevant messages that get printed at launch, that would help.

  29. Anonymous

    I'm getting:

    Unable to find or run the 'hg' command.

    Exception launching /etc/profile /etc/bashrc /Users/Shared/bashrc .bash_profile /usr/local/bin/hg: launch path not accessible

    The lines "/etc/bashrc", "/Users/Shared/bashrc" and ".bash_profile" appear to be my echo statements in those startup files identifying them, so this dialog is capturing the shell output. Not sure why it says the path is not accessible, because that's exactly where my hg binary is.

    I'd rather have a pref to put the path into that would make it work now rather than wait an unknown amount of time until it does work.

  30. Anonymous

    Okay, so it seems the code to use the shell to do a 'which hg' is assuming that the only text output will be the which output, but if the user startup scripts (invoked with --login to make sure the full PATH is in effect) put out any other text, it screws it. I've changed my messages to echo to stderr, which dodges the problem.

  31. Jens Alfke repo owner

    I'd rather have a pref to put the path into that would make it work now

    There is one, actually, there's just no GUI for it. You can set it from a shell:

    defaults write com.mooseyard.Murky HgToolPath /path/to/hg

    (See HgOperation.m line 55.)

  32. Alan Staniforth

    As anonymous says in #36 (and as i found out the hard way) at least one cause of the problem is a command in .bash_profile (or whatever) producing output. The code in runShell() at the moment just grabs the first line of output and if something like 'fortune' has been called by the sourced login script then that line does not contain the output of 'which hg'/'echo $PYTHONPATH'.

    A fix is to break the shell output up into an NSArray of component lines and simply grab the last one. Here's a diff of a possible patch:

    diff -u HgOperation.m.orig HgOperation.m
    --- HgOperation.m.orig	2009-12-28 23:12:44.000000000 +0000
    +++ HgOperation.m	2009-12-29 17:17:02.000000000 +0000
    @@ -24,9 +24,14 @@
         if ($equal(shellPath,@"/bin/bash"))
             [sh prependArguments: @"--login",nil];  // To get @*%&$ bash to read its .profile script
         
    -    if ([sh run: outError])
    -        return [sh.output stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
    -    else {
    +    if ([sh run: outError]) {
    +		// if your shell login script runs a command that produces output, such as fortune, then sh's output may 
    +		// contain an unpredictable number of lines. Split the response into an array of separate lines.
    + 		NSArray *resultLines = [sh.output componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    +		
    +		// the response to the "echo $PYTHONPATH" or "which hg" command will be the last but one line.
    +		return [[resultLines objectAtIndex:([resultLines count] - 2)] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
    +	} else {
             if (outError)
                 Warn(@"Shell command '%@' failed with output: '%@'", command,sh.output);
             return nil;
    
    

    Hope this is of use.

  33. Anonymous

    I still have this problem. With 200.7.1.zip even though hg is in /usr/local/bin

    [barry-smiths-macbook-pro:] barrysmith% ls -l /usr/local/bin/hg -rwxr-xr-x 1 root wheel 860 Jan 8 12:52 /usr/local/bin/hg*

    [barry-smiths-macbook-pro:] barrysmith% uname -a Darwin barry-smiths-macbook-pro.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.41/RELEASE_I386 i386

    [barry-smiths-macbook-pro:] barrysmith% bash bash-3.2$ which hg /usr/local/bin/hg bash-3.2$ exit exit [barry-smiths-macbook-pro:] barrysmith% which hg /usr/local/bin/hg [barry-smiths-macbook-pro:] barrysmith%

  34. Norman Gray

    The preference quoted in comment 37 _half_ works for me. Murky starts up successfully, but is apparently unable to actually run 'hg', presumably because it can't find the Python support.

    My case: I don't have hg in /usr/local/bin and don't have hg automatically added to my path by my shell startup scripts (so 'which' isn't going to work, nor is anything like it). [For what it's worth, I routinely do this with software I install, so that I can switch between installed versions without confusing myself]

    At the moment, if Murky can't find the hg binary it just flat refuses to start; with the preference set, it starts, but can't show repository contents.

    Suggestion: add an advanced preference for indicating the relevant binary and python paths. If Murky starts up and can't find the hg binary by the means discussed above, then it says something like "I can't find your Mercurial program: go to the preference panel? OK/Cancel" (or words to that effect).

    As you remark, Jens, in comment 34, this requires work on the user's part, but (a) if such a setting is necessary then it's because the user has (presumably deliberately) done something non-standard, so they're unlikely to object to further configuration; and (b) if they're techie enough to have done this, then they're likely to understand the question 'where is the installed pythonpath?', in case it doesn't exist at /path/to/bin/../lib/python-2.6/ (which is the layout created by 'make PREFIX=/path/to install' when installing hg from source). That is, users likely to be inconvenienced by this preference are unlikely ever to see it.

    This isn't necessarily un-macish. A number of other applications, including for example iPhoto when started with the option key, produce a 'where is X?' dialogue when they first start, presenting a file open dialogue to allow the user to navigate to the location of the artefact of interest. If I thus lead Murky to the hg binary it is to use, and it can from there find ../lib/python-2.6/site-packages, then everything's sweetness and light.

    Best wishes,

    Norman

  35. Log in to comment