"Launch path not accessible" using NSTask to create Git commit - objective-c

I am trying to use NSTask to create a Git commit and to add a message to that commit.
This is the code I have tried.
NSString *projectPath = #"file:///Users/MYNAME/Desktop/MYPROJECT/";
//stage files
NSPipe *pipe = [NSPipe pipe];
NSTask *task = [[NSTask alloc] init];
task.launchPath = projectPath;
task.arguments = #[#"git", #"add", #"."];
task.standardOutput = pipe;
[task launch];
//commit
NSPipe *pipe2 = [NSPipe pipe];
NSTask *task2 = [[NSTask alloc] init];
task2.launchPath = projectPath;
task2.arguments = #[#"git", #"commit", #"-m",#"\"Some Message\""];
task2.standardOutput = pipe2;
[task2 launch];
I received projectPath by using NSOpenPanel (standard OS X open dialog).
In the Xcode terminal, I get the message
"launch path not accessible"
So what am I doing wrong?
Update
After comment from Josh Caswell this is my code
NSString *projectPath = #"file:///Users/MYNAME/Desktop/MYPROJECT/";
NSString *gitPath = #"/usr/local/bin/git"; //location of the GIT on my mac
//stage
NSPipe *pipe = [NSPipe pipe];
NSTask *task = [[NSTask alloc] init];
task.launchPath = gitPath;
task.currentDirectoryPath = projectPath;
task.arguments = #[#"add", #"."];
task.standardOutput = pipe;
[task launch];
After [task launch]; I get error message in terminal "working directory doesn't exist."

The task's launchPath is the path to the program you want to run: that's Git here, so that path probably needs to be /usr/local/bin/git. And remove #"git" from the arguments; it's not an argument, it's the executable.
The path to your project should be used for the task's currentDirectoryPath so that it has the correct working directory.

With the pointers from Josh Casswell's answer I managed to figure it out. I found out that I have to remove the file:// part from the projectPath. So project path should be #"/Users/MYNAME/Desktop/MYPROJECT/".
Also it should not contain spaces because it does not work with %20 escape character. Which is kind of strange because when you use NSOpenPanel you get NSURL and when you call absolute path on it you get the "file://" at the start and "%20" instead of spaces inside of the path.
TLDR;
This code works in Xcode 8:
NSString *projectPath = #"/Users/MYNAME/Desktop/MYPROJECT/"; //be careful that it does not contain %20
NSString *gitPath = #"/usr/local/bin/git";
NSString *message = #"this is commit message";
//stage
NSPipe *pipe = [NSPipe pipe];
NSTask *task = [[NSTask alloc] init];
task.launchPath = gitPath;
task.currentDirectoryPath = projectPath;
task.arguments = #[#"add", #"."];
task.standardOutput = pipe;
[task launch];
[task waitUntilExit];
//commit
NSPipe *pipe2 = [NSPipe pipe];
NSTask *task2 = [[NSTask alloc] init];
task2.launchPath = gitPath;
task2.currentDirectoryPath = projectPath;
task2.arguments = #[#"commit", #"-m", message];
task2.standardOutput = pipe2;
[task2 launch];
[task2 waitUntilExit];
Update
Add [task waitUntilExit];
if you keep getting the message
fatal: Unable to create
'/Users/MYNAME/Desktop/MYPROJECT/.git/index.lock': File exists.
Another git process seems to be running in this repository, e.g. an
editor opened by 'git commit'. Please make sure all processes are
terminated then try again. If it still fails, a git process may have
crashed in this repository earlier: remove the file manually to
continue.

Related

Using NSTask to launch a Ruby script (Shenzhen)

I am trying to generate an IPA with the Shenzhen script: https://github.com/nomad/shenzhen
Here is the code I currently have:
-(void)startBuildIPAForProject:(NSString*)path
{
task = [[NSTask alloc] init];
[task setLaunchPath:#"/bin/bash"];
[task setCurrentDirectoryPath:path];
[task setArguments:#[#"ipa build",#"-c",#"Release"]];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSLog(#"task output: %#",string);
[task waitUntilExit];
}
When executing [task launch] I get the following output from the console:
/bin/bash: ipa build: No such file or directory
When I use the regular terminal ipa build is working (that is, it tells me there exists no Xcode project in the current dir)
I'm a bit lost, so any help is greatly appreciated.
The ipa script will need to be in your application's PATH environment variable (or in the same directory as your binary.) An easy fix would be to specify the full, absolute path to ipa in your arguments. i.e. change:
[task setArguments:#[#"ipa build",#"-c",#"Release"]];
to
[task setArguments:#[#"/full/path/to/ipa build",#"-c",#"Release"]];

Executing a command from Objective C

I want to execute a command from objective C (Cocoa framework). The command I am trying is as below. I tried with NSTask but it says "launch path not accessible" when I execute it.
sudo ifconfig en0 down
My code is:
- (void)testme {
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"sudo ifconfig en0 down"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"foo", #"bar.txt", nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"command returned:\n%#", string);
[string release];
[task release];
}
sudo ifconfig en0 down is not a sensible launch path. The correct launch path for this command would be /usr/sbin/sudo.
Once that is done, you still need to pass the correct arguments to setArguments:. foo and bar.txt look like example code that you copied without reading.
MORE IMPORTANTLY, THOUGH, running sudo from NSTask will not work. You will need to use Authorization Services to launch a privileged command.
You need to specify the full executable path and you should specify the arguments as the arguments, not along with the launch path. NSTask ain't a shell, it internally uses syscalls (execv(), I guess) to invoke the command.
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/sudo"];
NSArray *arguments = #[#"ifconfig", #"en0", #"down"];
[task setArguments:arguments];

Call shell script with argument in Mac application

I'm having trouble calling a shell script which takes an argument from my Cocoa application for Mac.
I have created the shell script, and put it in the app's local repository. It is called SCRIPT. It takes one argument which is a URL address.
I call the script as follows but nothing happens, no errors or messages, just the script stops after doing nothing.
NSString *address = [_addressField stringValue];
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: [NSString stringWithFormat:#"%#/SCRIPT", resPath]];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: address, nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *status;
status = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"%#", status);
Thanks in advance everyone
The Objective-C code seams to work fine for me if i try with /bin/echo as launch path. So i guess the problem is with the script. Can you include the script in your question? note that the environment when running from a Cocoa application is probably quite different from when running in a interactive shell.
Could it be a permissions issue? Try invoking /bin/sh and setting the script path as the first argument.

NSTask and FFMpeg losing output

I'm trying to call ffmpeg from NSTask in objective-c. I execute the ffmpeg command in terminal and it works flawlessly every time. I make the same command using NSTask, and it never gives me the whole output. It cuts it off half way through the output, at a seemingly random spot every time. Here is my code.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString* ffmpegPath = [[NSBundle mainBundle] pathForResource:#"ffmpeg" ofType:#""];
NSString* path = #"test.mov";
NSTask *task = [[NSTask alloc] init];
NSArray *arguments = [NSArray arrayWithObjects: #"-i", path, nil];
NSPipe *pipe = [NSPipe pipe];
NSFileHandle * read = [pipe fileHandleForReading];
[task setLaunchPath: ffmpegPath];
[task setArguments: arguments];
[task setStandardOutput: pipe];
[task launch];
[task waitUntilExit];
NSData* data = [read readDataToEndOfFile];
NSString* stringOutput = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", stringOutput);
NSLog(#"%i", [task terminationStatus]);
NSLog(#"DONE");
}
And just like that I figured it out. Apparently the output had non UTF8Characters in it. Switched it over to NSASCIIStringEncoding and voila. Magic.

Run terminal command with NSTask

I want to run a Terminal command in my program.
The command looks like this:
cd /path/to/file/; ./foo HTTPProxy 127.0.0.1
It works with system() but it doesn't work when I use NSTask.
system("cd /path/to/file/; ./foo HTTPProxy 127.0.0.1");
works fine but
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/path/to/file/./foo"];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task setArguments:[NSArray arrayWithObjects:#"HTTPProxy 127.0.0.1", nil]];
[task launch];
NSData *data = [file readDataToEndOfFile];
NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(string);
doesn't.
Output:
Command-line option 'HTTPProxy 127.0.0.1' with no value. Failing.
Has anybody an idea?
Now I think I have got it:
[task setArguments:[NSArray arrayWithObjects:#"HTTPProxy", #"127.0.0.1", nil]];
those are separate arguments in your invocation from the command line...
OLD ANSWER:
You could trying setting the current directory for execution:
– setCurrentDirectoryPath:
This is basically the effect of cd in the system version of your code.