Commits

Jens Alfke  committed 67c16e6

Fixed bug #10: Failed to find 'hg' tool if there wasn't a $PYTHONPATH environment variable. Also cleaned up the whole tool-location code.

  • Participants
  • Parent commits 7f420b0

Comments (0)

Files changed (3)

File Source/HgOperation.m

 #import "HgDir.h"
 
 
-@implementation HgOperation
-
-
 static NSString *sHgToolPath;
 static NSMutableDictionary *sEnvironment;
 
 
-+ (BOOL) findHgTool
+static NSString* runShell( NSString* command, NSError **outError) {
+    HgTask *sh = [[HgTask alloc] initWithCommand: [sEnvironment objectForKey: @"SHELL"]
+                                       arguments: [NSArray arrayWithObjects: @"-c", command ,nil]];
+    if ([sh run: outError])
+        return [sh.output stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+    else {
+        if (outError)
+            NSLog(@"Warning: Shell command '%@' failed with output: '%@'", command,sh.output);
+        return nil;
+    }
+}
+
+
+@implementation HgOperation
+
+
++ (void) setupEnvironment {
+    sEnvironment = [[[NSProcessInfo processInfo] environment] mutableCopy];
+
+    // hg may need a custom PYTHONPATH. If so, the user's shell will set up that variable, so
+    // to get it, fire up a shell and ask it:
+    NSString *pythonPath = runShell(@"echo $PYTHONPATH", NULL);
+    NSLog(@"PYTHONPATH = '%@'", pythonPath);
+    if (pythonPath.length > 0)
+        [sEnvironment setObject: pythonPath forKey: @"PYTHONPATH"];
+}
+
+
++ (NSString*) findHgTool
 {
-    HgTask *which = [[HgTask alloc] initWithCommand: [sEnvironment objectForKey: @"SHELL"]
-                                          arguments: [NSArray arrayWithObjects: @"-c",@"which hg && echo $PYTHONPATH",nil]];
-    NSError *error;
-    if( [which run: &error] ) {
-        NSArray *output = [which.output componentsSeparatedByString: @"\n"];
-        if( output.count >= 2 ) {
-            sHgToolPath = [output objectAtIndex: 0];
-            NSString *pythonPath = [output objectAtIndex: 1];
-            if( pythonPath.length > 0 )
-                [sEnvironment setObject: pythonPath forKey: @"PYTHONPATH"];
-            NSLog(@"tool='%@', pythonPath='%@'",sHgToolPath,pythonPath);
-            return YES;
-        }
+    // See if there's a custom hg path configured:
+    NSString *hgPath = [[NSUserDefaults standardUserDefaults] objectForKey: @"HgToolPath"];
+    if( hgPath ) {
+        // If so, it may come with a custom python path:
+        NSString *pythonPath = [[NSUserDefaults standardUserDefaults] objectForKey: @"HgPythonPath"];
+        if( pythonPath )
+            [sEnvironment setObject: pythonPath forKey: @"PYTHONPATH"];
+        return hgPath;
     }
-    return NO;
+        
+    // Ask the shell where 'hg' is. (Note that we can't check the PATH env var directly,
+    // because it's not set up by the app's parent, launchd. Only shells define it.)
+    NSError *error = nil;
+    hgPath = runShell(@"which hg", &error);
+    if (hgPath) {
+        NSLog(@"'hg' path = '%@'", hgPath);
+        if ([hgPath hasPrefix: @"/"])
+            return hgPath;
+        else
+            NSLog(@"...which isn't a path! Ignoring it");
+    }
+    
+    // As a last resort, guess that it's /usr/local/bin/hg:
+    hgPath = @"/usr/local/bin/hg";
+    NSLog(@"Warning: Couldn't locate hg via shell ... assuming it's at %@", hgPath);
+    return hgPath;
 }
 
 
 + (void) initialize
 {
     if( self == [HgOperation class] ) {
-        sEnvironment = [[[NSProcessInfo processInfo] environment] mutableCopy];
-        
-        // Get the location of the 'hg' tool and its Python libraries, from user defaults:
-        sHgToolPath = [[NSUserDefaults standardUserDefaults] objectForKey: @"HgToolPath"];
-        if( sHgToolPath ) {
-            NSString *pythonPath = [[NSUserDefaults standardUserDefaults] objectForKey: @"HgPythonPath"];
-            if( pythonPath )
-                [sEnvironment setObject: pythonPath forKey: @"PYTHONPATH"];
-        } else if( ! [self findHgTool] ) {
-            NSLog(@"Warning: Couldn't find 'hg' tool; assuming it's in /usr/local/bin");
-            sHgToolPath = @"/usr/local/bin/hg";
-        }
+        [self setupEnvironment];
+        sHgToolPath = [self findHgTool];
     }
 }
 

File Source/HgTask.h

 
 @property (copy) NSString* currentDirectoryPath;
 
+/** Prettified description of command string. Doesn't do full shell-style quoting, though. */
+- (NSString*) commandLine;
+
 - (BOOL) run;
 - (BOOL) run: (NSError**)outError;
 

File Source/HgTask.m

 }
 
 
+- (NSString*) commandLine {
+    NSMutableString *desc = [NSMutableString stringWithString: _command];
+    for (NSString *arg in _arguments) {
+        [desc appendString: @" "];
+        if ([arg rangeOfString: @" "].length > 0)
+            arg = [NSString stringWithFormat: @"'%@'", arg];
+        [desc appendString: arg];
+    }
+    return desc;
+}
+
+
 - (void) ignoreOutput
 {
     _ignoreOutput = YES;
     _task = [self createTask];
     NSAssert(_task,@"createTask returned nil");
     
-    NSLog(@"Task: %@ %@",_task.launchPath,[_task.arguments componentsJoinedByString: @" "]);
+    NSLog(@"Task: %@", self.commandLine);
     
     _task.standardOutput = [self _openPipeAndHandle: &_outHandle notifying: @selector(_gotOutput:)];
     _outputData =  [[NSMutableData alloc] init];