mirror of
https://github.com/kennethreitz-archive/gitx.git
synced 2026-06-05 23:40:18 +00:00
6c04aea44b
Calling methods which are not properties through use of dot notation is a no-no in Apple's Objective-C 2.0 documentation. According to Apple it might work but the compiler will not warn about any dangerous use cases. The prominent example from the docs of how not to do it is "someObject.retain". Here retain is a method and not a property so proper use is "[someObject retain]". Unfortunately, often it is not clear if something in the API is merely an accessor or a method which acts like an accessor but does more than the name might imply. In this case, we can see this in PBEasyPipe where we have method calls like "NSTask.standardOutput = ...". Even though they may look correct this can be dangerous for obvious reasons. I assume hat this could also play a role in the appearance of the "bad file descriptor" messages.
132 lines
4.1 KiB
Objective-C
132 lines
4.1 KiB
Objective-C
//
|
|
// PBEasyPipe.m
|
|
// GitX
|
|
//
|
|
// Created by Pieter de Bie on 16-06-08.
|
|
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
|
//
|
|
|
|
#import "PBEasyPipe.h"
|
|
|
|
|
|
@implementation PBEasyPipe
|
|
|
|
+ (NSFileHandle*) handleForCommand: (NSString*) cmd withArgs: (NSArray*) args
|
|
{
|
|
return [self handleForCommand:cmd withArgs:args inDir:nil];
|
|
}
|
|
|
|
+ (NSFileHandle*) handleForCommand: (NSString*) cmd withArgs: (NSArray*) args inDir: (NSString*) dir
|
|
{
|
|
NSTask *task = [self taskForCommand:cmd withArgs:args inDir:dir];
|
|
NSFileHandle* handle = [[task standardOutput] fileHandleForReading];
|
|
|
|
[task launch];
|
|
return handle;
|
|
}
|
|
|
|
+ (NSTask *) taskForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir
|
|
{
|
|
NSTask* task = [[NSTask alloc] init];
|
|
[task setLaunchPath:cmd];
|
|
[task setArguments:args];
|
|
if (dir)
|
|
[task setCurrentDirectoryPath:dir];
|
|
|
|
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Show Debug Messages"])
|
|
NSLog(@"Starting command `%@ %@` in dir %@", cmd, [args componentsJoinedByString:@" "], dir);
|
|
#ifdef CLI
|
|
NSLog(@"Starting command `%@ %@` in dir %@", cmd, [args componentsJoinedByString:@" "], dir);
|
|
#endif
|
|
|
|
NSPipe* pipe = [NSPipe pipe];
|
|
[task setStandardOutput:pipe];
|
|
return task;
|
|
}
|
|
|
|
+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir retValue:(int *)ret {
|
|
return [self outputForCommand:cmd withArgs:args inDir:dir byExtendingEnvironment:nil inputString:nil retValue:ret];
|
|
}
|
|
|
|
+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir inputString:(NSString *)input retValue:(int *)ret {
|
|
return [self outputForCommand:cmd withArgs:args inDir:dir byExtendingEnvironment:nil inputString:input retValue:ret];
|
|
}
|
|
|
|
+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir byExtendingEnvironment:(NSDictionary *)dict inputString:(NSString *)input retValue:(int *)ret {
|
|
NSTask * task = [self taskForCommand:cmd withArgs:args inDir:dir];
|
|
|
|
if (dict) {
|
|
NSMutableDictionary * env = [[[NSProcessInfo processInfo] environment] mutableCopy];
|
|
[env addEntriesFromDictionary:dict];
|
|
[task setEnvironment:env];
|
|
}
|
|
|
|
NSFileHandle * handle = [[task standardOutput] fileHandleForReading];
|
|
|
|
if (input) {
|
|
[task setStandardInput:[NSPipe pipe]];
|
|
NSFileHandle * inHandle = [task.standardInput fileHandleForWriting];
|
|
[inHandle writeData:[input dataUsingEncoding:NSUTF8StringEncoding]];
|
|
[inHandle closeFile];
|
|
}
|
|
|
|
[task launch];
|
|
|
|
NSData * data = [handle readDataToEndOfFile];
|
|
NSString * string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
if (!string)
|
|
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
|
|
|
|
// Strip trailing newline
|
|
if ([string hasSuffix:@"\n"])
|
|
string = [string substringToIndex:[string length] - 1];
|
|
|
|
[task waitUntilExit];
|
|
if (ret)
|
|
*ret = [task terminationStatus];
|
|
return string;
|
|
}
|
|
|
|
// We don't use the above function because then we'd have to wait until the program was finished
|
|
// with running
|
|
|
|
+ (NSString*) outputForCommand: (NSString*) cmd withArgs: (NSArray*) args inDir: (NSString*) dir
|
|
{
|
|
NSTask *task = [self taskForCommand:cmd withArgs:args inDir:dir];
|
|
NSFileHandle* handle = [[task standardOutput] fileHandleForReading];
|
|
|
|
[task launch];
|
|
#warning This can cause a "Bad file descriptor"... when?
|
|
NSData *data;
|
|
@try {
|
|
data = [handle readDataToEndOfFile];
|
|
}
|
|
@catch (NSException * e) {
|
|
NSLog(@"Got a bad file descriptor in %s!", _cmd);
|
|
if ([NSThread currentThread] != [NSThread mainThread])
|
|
[task waitUntilExit];
|
|
|
|
return nil;
|
|
}
|
|
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
if (!string)
|
|
string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
|
|
|
|
// Strip trailing newline
|
|
if ([string hasSuffix:@"\n"])
|
|
string = [string substringToIndex:[string length]-1];
|
|
|
|
if ([NSThread currentThread] != [NSThread mainThread])
|
|
[task waitUntilExit];
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
+ (NSString*) outputForCommand: (NSString*) cmd withArgs: (NSArray*) args
|
|
{
|
|
return [self outputForCommand:cmd withArgs:args inDir:nil];
|
|
}
|
|
|
|
@end
|