From 8c9697968be3d802c1ae409118a6a2cf94ac93fc Mon Sep 17 00:00:00 2001 From: Pieter de Bie Date: Sat, 4 Oct 2008 21:46:04 +0200 Subject: [PATCH] Better handle the cases when a Git binary can't be found --- GitX.xcodeproj/project.pbxproj | 10 +++++ PBCLIProxy.mm | 7 +++- PBGitBinary.h | 19 ++++++++++ PBGitBinary.m | 69 ++++++++++++++++++++++++++++++++++ PBGitRepository.m | 68 +++++++++++++-------------------- gitx.mm | 6 +++ 6 files changed, 137 insertions(+), 42 deletions(-) create mode 100644 PBGitBinary.h create mode 100644 PBGitBinary.m diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index c5b56ab..e3eefb3 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -25,6 +25,9 @@ F5140DC90E8A8EB20091E9F3 /* RoundedRectangle.m in Sources */ = {isa = PBXBuildFile; fileRef = F5140DC80E8A8EB20091E9F3 /* RoundedRectangle.m */; }; F52BCE030E84208300AA3741 /* PBGitHistoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F52BCE020E84208300AA3741 /* PBGitHistoryView.xib */; }; F52BCE070E84211300AA3741 /* PBGitHistoryController.m in Sources */ = {isa = PBXBuildFile; fileRef = F52BCE060E84211300AA3741 /* PBGitHistoryController.m */; }; + F53C4DF70E97FC630022AD59 /* PBGitBinary.m in Sources */ = {isa = PBXBuildFile; fileRef = F53C4DF60E97FC630022AD59 /* PBGitBinary.m */; }; + F53C4DF80E97FCA70022AD59 /* PBGitBinary.m in Sources */ = {isa = PBXBuildFile; fileRef = F53C4DF60E97FC630022AD59 /* PBGitBinary.m */; }; + F53C4DF90E97FCAD0022AD59 /* PBEasyPipe.m in Sources */ = {isa = PBXBuildFile; fileRef = F57CC3900E05DDF2000472E2 /* PBEasyPipe.m */; }; F53FF2050E7ABB5300389171 /* PBGitRevSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = F53FF2040E7ABB5300389171 /* PBGitRevSpecifier.m */; }; F561727F0E056A11001DCD79 /* diff_style.css in Resources */ = {isa = PBXBuildFile; fileRef = F561727C0E056A11001DCD79 /* diff_style.css */; }; F56173280E056ED2001DCD79 /* diffHighlighter.js in Resources */ = {isa = PBXBuildFile; fileRef = F56173270E056ED2001DCD79 /* diffHighlighter.js */; }; @@ -123,6 +126,8 @@ F52BCE020E84208300AA3741 /* PBGitHistoryView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PBGitHistoryView.xib; sourceTree = ""; }; F52BCE050E84211300AA3741 /* PBGitHistoryController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitHistoryController.h; sourceTree = ""; }; F52BCE060E84211300AA3741 /* PBGitHistoryController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitHistoryController.m; sourceTree = ""; }; + F53C4DF50E97FC630022AD59 /* PBGitBinary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitBinary.h; sourceTree = ""; }; + F53C4DF60E97FC630022AD59 /* PBGitBinary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitBinary.m; sourceTree = ""; }; F53EE3590E06BBA00022B925 /* CWQuickLook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CWQuickLook.h; sourceTree = ""; }; F53FF2030E7ABB5300389171 /* PBGitRevSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevSpecifier.h; sourceTree = ""; }; F53FF2040E7ABB5300389171 /* PBGitRevSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRevSpecifier.m; sourceTree = ""; }; @@ -323,6 +328,8 @@ F5E927E10E883D2E00056E75 /* History */, F5945E150E02B0C200706420 /* PBGitRepository.h */, F5945E160E02B0C200706420 /* PBGitRepository.m */, + F53C4DF50E97FC630022AD59 /* PBGitBinary.h */, + F53C4DF60E97FC630022AD59 /* PBGitBinary.m */, ); name = Git; sourceTree = ""; @@ -568,6 +575,7 @@ 91B103CC0E898EC300C84364 /* PBIconAndTextCell.mm in Sources */, F5140DC90E8A8EB20091E9F3 /* RoundedRectangle.m in Sources */, F56244090E9684B0002B6C44 /* PBUnsortableTableHeader.m in Sources */, + F53C4DF70E97FC630022AD59 /* PBGitBinary.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -575,6 +583,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F53C4DF90E97FCAD0022AD59 /* PBEasyPipe.m in Sources */, + F53C4DF80E97FCA70022AD59 /* PBGitBinary.m in Sources */, 913D5E4D0E55644E00CECEA2 /* gitx.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/PBCLIProxy.mm b/PBCLIProxy.mm index 938b4d2..99d3a42 100644 --- a/PBCLIProxy.mm +++ b/PBCLIProxy.mm @@ -37,8 +37,13 @@ NSArray* arguments = [NSArray arrayWithArray:args]; PBGitRepository *document = [[PBRepositoryDocumentController sharedDocumentController] documentForLocation:url]; - if (!document) + if (!document) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"Could not create document. Perhaps GitX can't find you git binary?" forKey:NSLocalizedFailureReasonErrorKey]; + *error = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:2 userInfo:userInfo]; + } return NO; + } if ([arguments count] > 0 && ([[arguments objectAtIndex:0] isEqualToString:@"--commit"] || [[arguments objectAtIndex:0] isEqualToString:@"-c"])) diff --git a/PBGitBinary.h b/PBGitBinary.h new file mode 100644 index 0000000..83c31e8 --- /dev/null +++ b/PBGitBinary.h @@ -0,0 +1,19 @@ +// +// PBGitBinary.h +// GitX +// +// Created by Pieter de Bie on 04-10-08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import + + +@interface PBGitBinary : NSObject { + +} + ++ (NSString *) path; ++ (NSArray *) searchLocations; ++ (NSString *) notFoundError; +@end diff --git a/PBGitBinary.m b/PBGitBinary.m new file mode 100644 index 0000000..df51893 --- /dev/null +++ b/PBGitBinary.m @@ -0,0 +1,69 @@ +// +// PBGitBinary.m +// GitX +// +// Created by Pieter de Bie on 04-10-08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "PBGitBinary.h" +#import "PBEasyPipe.h" + +@implementation PBGitBinary + +static NSString* gitPath; + ++ (void) initialize +{ + gitPath = nil; + + // Try to find the path of the Git binary + char* path = getenv("GIT_PATH"); + if (path != nil) { + gitPath = [NSString stringWithCString:path]; + return; + } + + // No explicit path. Try it with "which" + gitPath = [PBEasyPipe outputForCommand:@"/usr/bin/which" withArgs:[NSArray arrayWithObject:@"git"]]; + if (gitPath.length > 0) + return; + + // Still no path. Let's try some default locations. + for (NSString* location in [PBGitBinary searchLocations]) { + if ([[NSFileManager defaultManager] fileExistsAtPath:location]) { + gitPath = location; + return; + } + } + + NSLog(@"Could not find a git binary!"); +} + ++ (NSString *) path; +{ + return gitPath; +} + ++ (NSArray *) searchLocations +{ + NSArray* locations = [NSArray arrayWithObjects:@"/opt/local/bin/git", + @"/sw/bin/git", + @"/opt/git/bin/git", + @"/usr/local/bin/git", + nil]; + return locations; +} + ++ (NSString *) notFoundError +{ + NSMutableString *error = [NSMutableString stringWithString: + @"Could not find a git binary\n" + "Please make sure there is a git binary in one of the following locations:\n\n"]; + for (NSString *location in [PBGitBinary searchLocations]) { + [error appendFormat:@"\t%@\n", location]; + } + return error; +} + +@end diff --git a/PBGitRepository.m b/PBGitRepository.m index fcae003..ff78170 100644 --- a/PBGitRepository.m +++ b/PBGitRepository.m @@ -9,6 +9,7 @@ #import "PBGitRepository.h" #import "PBGitCommit.h" #import "PBGitWindowController.h" +#import "PBGitBinary.h" #import "NSFileHandleExt.h" #import "PBEasyPipe.h" @@ -20,37 +21,6 @@ NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain"; @implementation PBGitRepository @synthesize revisionList, branches, currentBranch, refs, hasChanged; -static NSString* gitPath; - -+ (void) initialize -{ - // Try to find the path of the Git binary - char* path = getenv("GIT_PATH"); - if (path != nil) { - gitPath = [NSString stringWithCString:path]; - return; - } - - // No explicit path. Try it with "which" - gitPath = [PBEasyPipe outputForCommand:@"/usr/bin/which" withArgs:[NSArray arrayWithObject:@"git"]]; - if (gitPath.length > 0) - return; - - // Still no path. Let's try some default locations. - NSArray* locations = [NSArray arrayWithObjects:@"/opt/local/bin/git", - @"/sw/bin/git", - @"/opt/git/bin/git", - @"/usr/local/bin/git", - nil]; - for (NSString* location in locations) { - if ([[NSFileManager defaultManager] fileExistsAtPath:location]) { - gitPath = location; - return; - } - } - - NSLog(@"Could not find a git binary!"); -} - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { @@ -64,11 +34,14 @@ static NSString* gitPath; + (BOOL) isBareRepository: (NSString*) path { - return [[PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--is-bare-repository", nil] inDir:path] isEqualToString:@"true"]; + return [[PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--is-bare-repository", nil] inDir:path] isEqualToString:@"true"]; } + (NSURL*)gitDirForURL:(NSURL*)repositoryURL; { + if (![PBGitBinary path]) + return nil; + NSString* repositoryPath = [repositoryURL path]; if ([self isBareRepository:repositoryPath]) @@ -76,7 +49,7 @@ static NSString* gitPath; // Use rev-parse to find the .git dir for the repository being opened - NSString* newPath = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:repositoryPath]; + NSString* newPath = [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:repositoryPath]; if ([newPath isEqualToString:@".git"]) return [NSURL fileURLWithPath:[repositoryPath stringByAppendingPathComponent:@".git"]]; if ([newPath length] > 0) @@ -103,6 +76,16 @@ static NSString* gitPath; { BOOL success = NO; + if (![PBGitBinary path]) + { + if (outError) { + NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[PBGitBinary notFoundError] + forKey:NSLocalizedRecoverySuggestionErrorKey]; + *outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo]; + } + return NO; + } + if (![fileWrapper isDirectory]) { if (outError) { NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Reading files is not supported.", [fileWrapper filename]] @@ -138,6 +121,9 @@ static NSString* gitPath; - (id) initWithURL: (NSURL*) path { + if (![PBGitBinary path]) + return nil; + NSURL* gitDirURL = [PBGitRepository gitDirForURL:path]; if (!gitDirURL) return nil; @@ -206,7 +192,7 @@ static NSString* gitPath; refs = [NSMutableDictionary dictionary]; - NSString* output = [PBEasyPipe outputForCommand:gitPath + NSString* output = [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:[NSArray arrayWithObjects:@"for-each-ref", @"--format=%(refname) %(objecttype) %(objectname)" " %(*objectname)", @"refs", nil] inDir: self.fileURL.path]; @@ -304,7 +290,7 @@ static NSString* gitPath; if ([self.fileURL.path hasSuffix:@"/.git"]) return [self.fileURL.path substringToIndex:[self.fileURL.path length] - 5]; else if ([[self outputForCommand:@"rev-parse --is-inside-work-tree"] isEqualToString:@"true"]) - return gitPath; + return [PBGitBinary path]; return nil; } @@ -321,7 +307,7 @@ static NSString* gitPath; NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:self.fileURL.path]; NSMutableArray* arguments = [NSMutableArray arrayWithObject: gitDirArg]; [arguments addObjectsFromArray: args]; - return [PBEasyPipe handleForCommand:gitPath withArgs:arguments]; + return [PBEasyPipe handleForCommand:[PBGitBinary path] withArgs:arguments]; } - (NSFileHandle*) handleInWorkDirForArguments:(NSArray *)args @@ -329,7 +315,7 @@ static NSString* gitPath; NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:self.fileURL.path]; NSMutableArray* arguments = [NSMutableArray arrayWithObject: gitDirArg]; [arguments addObjectsFromArray: args]; - return [PBEasyPipe handleForCommand:gitPath withArgs:arguments inDir:[self workingDirectory]]; + return [PBEasyPipe handleForCommand:[PBGitBinary path] withArgs:arguments inDir:[self workingDirectory]]; } - (NSFileHandle*) handleForCommand:(NSString *)cmd @@ -352,23 +338,23 @@ static NSString* gitPath; - (NSString*) outputForArguments:(NSArray*) arguments { - return [PBEasyPipe outputForCommand:gitPath withArgs:arguments inDir: self.fileURL.path]; + return [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: self.fileURL.path]; } - (NSString*) outputInWorkdirForArguments:(NSArray*) arguments { - return [PBEasyPipe outputForCommand:gitPath withArgs:arguments inDir: [self workingDirectory]]; + return [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: [self workingDirectory]]; } - (NSString*) outputForArguments:(NSArray *)arguments retValue:(int *)ret; { - return [PBEasyPipe outputForCommand:gitPath withArgs:arguments inDir: self.fileURL.path retValue: ret]; + return [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: self.fileURL.path retValue: ret]; } - (NSString*) outputForArguments:(NSArray *)arguments inputString:(NSString *)input retValue:(int *)ret; { - return [PBEasyPipe outputForCommand:gitPath + return [PBEasyPipe outputForCommand:[PBGitBinary path] withArgs:arguments inDir: self.fileURL.path inputString:input diff --git a/gitx.mm b/gitx.mm index 3e9456a..2d1d3fa 100644 --- a/gitx.mm +++ b/gitx.mm @@ -7,6 +7,7 @@ // #import "PBCLIProxy.h" +#import "PBGitBinary.h" NSDistantObject* connect() { @@ -39,6 +40,11 @@ int main(int argc, const char** argv) if (argc >= 2 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) usage(argv[0]); + if (![PBGitBinary path]) { + printf("%s\n", [[PBGitBinary notFoundError] cStringUsingEncoding:NSUTF8StringEncoding]); + exit(2); + } + // Attempt to connect to the app id proxy = connect();