1

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."

SimpleApp
  • 506
  • 4
  • 17
  • The real answer for those with app sandboxing enabled https://stackoverflow.com/questions/7018354/remove-sandboxing – amleszk Aug 23 '20 at 11:31
  • The real answer for those with app sandboxing enabled https://stackoverflow.com/questions/7018354/remove-sandboxing – amleszk Aug 23 '20 at 11:31

2 Answers2

1

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.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Thanks for clarification. What you said makes sense. Unfortunately I am still having no luck with this. When I type in Terminal: "which git" i get "/usr/bin/git" so I guess I should use this instead of "/usr/local/bin/git" for the launchPath. But still I get "launch path not accessible" error. Also when I add "currentDirectoryPath" I get message "launch path not accessible". Is there any way I can see what is being written to the prompt and in which folder? In order to debug this? – SimpleApp Apr 25 '17 at 06:59
  • I don't think there is any output, because the `NSTask` itself isn't getting started. It sounds like there's a permissions or `$PATH` problem, but I can't imagine that /usr/bin isn't in the `$PATH`. – jscs Apr 25 '17 at 13:31
  • In Termainal I can call git from any folder. Also when I type "echo $PATH" i get "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" – SimpleApp Apr 25 '17 at 19:18
1

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.

pkamb
  • 33,281
  • 23
  • 160
  • 191
SimpleApp
  • 506
  • 4
  • 17
  • Glad you figured it out; feel free to award the checkmark to your own answer, since it seems to be more complete than mine. – jscs Apr 26 '17 at 00:02
  • As for the path, you probably want to use `-[NSURL path]` rather than `absolutePath`. You'll notice that the spaces are unescaped, and the scheme (`file://`) is not included. – jscs Apr 26 '17 at 00:05