Merge commit 'ciaran/cli'

* commit 'ciaran/cli':
  Adding a menu item to install the CLI tool.
  The repository is owned by the window controller now, and PBWebGitController shouldn't need to use the ApplicationController
  The ApplicationController does not own a repository any more
  Amend the CLI tool to use the distributed objects system to try opening the current path when invoked.
  Overriding -documentForURL: to use +gitDirForURL: to convert incoming URLs to the .git dir before checking for an open document, so that open a repository from subdirectories won’t open duplicate windows.
  Separating out the logic for finding the .git dir for a given path in a repository, so it can be used in other places.
  Adding a basic command-line tool to interface with the application through distributed objects.
This commit is contained in:
Pieter de Bie
2008-08-18 20:44:22 +02:00
10 changed files with 938 additions and 688 deletions
+7
View File
@@ -9,6 +9,8 @@
#import <Cocoa/Cocoa.h>
#import "PBGitRepository.h"
@class PBCLIProxy;
@interface ApplicationController : NSObject
{
IBOutlet NSWindow *window;
@@ -16,12 +18,17 @@
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
PBCLIProxy *cliProxy;
}
@property (retain) PBCLIProxy* cliProxy;
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator;
- (NSManagedObjectModel *)managedObjectModel;
- (NSManagedObjectContext *)managedObjectContext;
- (IBAction)installCliTool:(id)sender;
- (IBAction)saveAction:sender;
- (IBAction)switchBranch:sender;
@end
+9
View File
@@ -10,8 +10,10 @@
#import "PBGitRevisionCell.h"
#import "PBDetailController.h"
#import "PBRepositoryDocumentController.h"
#import "PBCLIProxy.h"
@implementation ApplicationController
@synthesize cliProxy;
- (ApplicationController*)init
{
@@ -22,6 +24,8 @@
if(self = [super init]) {
if([[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
NSLog(@"Quick Look loaded!");
self.cliProxy = [PBCLIProxy new];
}
return self;
@@ -51,6 +55,11 @@
[firstResponder terminate: sender];
}
- (IBAction)installCliTool:(id)sender;
{
NSLog(@"[%@ installCliTool:%@]", [self class], sender);
}
- (IBAction) switchBranch: sender
{
[[NSAlert alertWithMessageText:@"Not Supported" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"Sorry, switching branches is not supported yet"] runModal];
+647 -668
View File
File diff suppressed because it is too large Load Diff
+126
View File
@@ -14,6 +14,9 @@
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
911111E20E58BD5A00BF76B4 /* RepositoryWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 911111E00E58BD5A00BF76B4 /* RepositoryWindow.xib */; };
911111F80E594F3F00BF76B4 /* PBRepositoryDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 911111F70E594F3F00BF76B4 /* PBRepositoryDocumentController.m */; };
913D5E4D0E55644E00CECEA2 /* gitx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 913D5E440E55640C00CECEA2 /* gitx.mm */; };
913D5E500E55645900CECEA2 /* gitx in Resources */ = {isa = PBXBuildFile; fileRef = 913D5E490E55644600CECEA2 /* gitx */; };
913D5E5F0E556A9300CECEA2 /* PBCLIProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 913D5E5E0E556A9300CECEA2 /* PBCLIProxy.mm */; };
F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F50FE0E20E07BE9600854FCD /* PBGitRevisionCell.m */; };
F513085B0E0740F2000C8BCD /* PBQLOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = F513085A0E0740F2000C8BCD /* PBQLOutlineView.m */; };
F561727F0E056A11001DCD79 /* diff_style.css in Resources */ = {isa = PBXBuildFile; fileRef = F561727C0E056A11001DCD79 /* diff_style.css */; };
@@ -36,6 +39,16 @@
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
913D5E590E5564F400CECEA2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 913D5E480E55644600CECEA2;
remoteInfo = "cli tool";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
@@ -52,6 +65,10 @@
911111E10E58BD5A00BF76B4 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/RepositoryWindow.xib; sourceTree = "<group>"; };
911111F60E594F3F00BF76B4 /* PBRepositoryDocumentController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBRepositoryDocumentController.h; sourceTree = "<group>"; };
911111F70E594F3F00BF76B4 /* PBRepositoryDocumentController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBRepositoryDocumentController.m; sourceTree = "<group>"; };
913D5E440E55640C00CECEA2 /* gitx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = gitx.mm; sourceTree = "<group>"; };
913D5E490E55644600CECEA2 /* gitx */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gitx; sourceTree = BUILT_PRODUCTS_DIR; };
913D5E5D0E556A9300CECEA2 /* PBCLIProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCLIProxy.h; sourceTree = "<group>"; };
913D5E5E0E556A9300CECEA2 /* PBCLIProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PBCLIProxy.mm; sourceTree = "<group>"; };
F50FE0E10E07BE9600854FCD /* PBGitRevisionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevisionCell.h; sourceTree = "<group>"; };
F50FE0E20E07BE9600854FCD /* PBGitRevisionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRevisionCell.m; sourceTree = "<group>"; };
F51308590E0740F2000C8BCD /* PBQLOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBQLOutlineView.h; sourceTree = "<group>"; };
@@ -96,6 +113,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
913D5E470E55644600CECEA2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -129,6 +153,7 @@
isa = PBXGroup;
children = (
8D1107320486CEB800E47090 /* GitX.app */,
913D5E490E55644600CECEA2 /* gitx */,
);
name = Products;
sourceTree = "<group>";
@@ -136,6 +161,7 @@
29B97314FDCFA39411CA2CEA /* GitTest */ = {
isa = PBXGroup;
children = (
913D5E420E5563FD00CECEA2 /* cli */,
F57CC43E0E05E472000472E2 /* Aux */,
F57CC3850E05DDC1000472E2 /* Controllers */,
F561777C0E05C88E001DCD79 /* DetailView.png */,
@@ -188,6 +214,14 @@
name = Models;
sourceTree = "<group>";
};
913D5E420E5563FD00CECEA2 /* cli */ = {
isa = PBXGroup;
children = (
913D5E440E55640C00CECEA2 /* gitx.mm */,
);
name = cli;
sourceTree = "<group>";
};
F56174540E05887E001DCD79 /* Git */ = {
isa = PBXGroup;
children = (
@@ -214,6 +248,8 @@
F57CC4400E05E496000472E2 /* PBDetailController.m */,
911111F60E594F3F00BF76B4 /* PBRepositoryDocumentController.h */,
911111F70E594F3F00BF76B4 /* PBRepositoryDocumentController.m */,
913D5E5D0E556A9300CECEA2 /* PBCLIProxy.h */,
913D5E5E0E556A9300CECEA2 /* PBCLIProxy.mm */,
);
name = Controllers;
sourceTree = "<group>";
@@ -263,6 +299,7 @@
buildRules = (
);
dependencies = (
913D5E5A0E5564F400CECEA2 /* PBXTargetDependency */,
);
name = GitX;
productInstallPath = "$(HOME)/Applications";
@@ -270,6 +307,22 @@
productReference = 8D1107320486CEB800E47090 /* GitX.app */;
productType = "com.apple.product-type.application";
};
913D5E480E55644600CECEA2 /* cli tool */ = {
isa = PBXNativeTarget;
buildConfigurationList = 913D5E570E55646100CECEA2 /* Build configuration list for PBXNativeTarget "cli tool" */;
buildPhases = (
913D5E460E55644600CECEA2 /* Sources */,
913D5E470E55644600CECEA2 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "cli tool";
productName = "cli tool";
productReference = 913D5E490E55644600CECEA2 /* gitx */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -283,6 +336,7 @@
projectRoot = "";
targets = (
8D1107260486CEB800E47090 /* GitX */,
913D5E480E55644600CECEA2 /* cli tool */,
);
};
/* End PBXProject section */
@@ -292,6 +346,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
913D5E500E55645900CECEA2 /* gitx in Resources */,
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
F565265A0E03E71B00F03B52 /* commit.html in Resources */,
F56173280E056ED2001DCD79 /* diffHighlighter.js in Resources */,
@@ -327,11 +382,28 @@
F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */,
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */,
911111F80E594F3F00BF76B4 /* PBRepositoryDocumentController.m in Sources */,
913D5E5F0E556A9300CECEA2 /* PBCLIProxy.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
913D5E460E55644600CECEA2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
913D5E4D0E55644E00CECEA2 /* gitx.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
913D5E5A0E5564F400CECEA2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 913D5E480E55644600CECEA2 /* cli tool */;
targetProxy = 913D5E590E5564F400CECEA2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
@@ -420,6 +492,51 @@
};
name = Release;
};
913D5E4B0E55644600CECEA2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
"-framework",
Foundation,
"-framework",
AppKit,
);
PREBINDING = NO;
PRODUCT_NAME = gitx;
ZERO_LINK = YES;
};
name = Debug;
};
913D5E4C0E55644600CECEA2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
INSTALL_PATH = /usr/local/bin;
OTHER_LDFLAGS = (
"-framework",
Foundation,
"-framework",
AppKit,
);
PREBINDING = NO;
PRODUCT_NAME = gitx;
ZERO_LINK = NO;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -441,6 +558,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
913D5E570E55646100CECEA2 /* Build configuration list for PBXNativeTarget "cli tool" */ = {
isa = XCConfigurationList;
buildConfigurations = (
913D5E4B0E55644600CECEA2 /* Debug */,
913D5E4C0E55644600CECEA2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+24
View File
@@ -0,0 +1,24 @@
//
// PBCLIProxy.h
// GitX
//
// Created by Ciarán Walsh on 15/08/2008.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface PBCLIProxy : NSObject
{
NSConnection *connection;
}
@property (retain) NSConnection* connection;
@end
#define ConnectionName @"GitX DO Connection"
#define PBCLIProxyErrorDomain @"PBCLIProxyErrorDomain"
@protocol GitXCliToolProtocol
- (BOOL)openRepository:(NSURL*)repositoryPath error:(NSError**)error;
@end
+40
View File
@@ -0,0 +1,40 @@
//
// PBCLIProxy.mm
// GitX
//
// Created by Ciarán Walsh on 15/08/2008.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBCLIProxy.h"
#import "PBRepositoryDocumentController.h"
@implementation PBCLIProxy
@synthesize connection;
- (id)init
{
if (self = [super init]) {
self.connection = [NSConnection new];
[self.connection setRootObject:self];
if ([self.connection registerName:ConnectionName] == NO)
NSBeep();
}
return self;
}
- (BOOL)openRepository:(NSURL*)repositoryPath error:(NSError**)error;
{
// FIXME I found that creating this redundant NSURL reference was necessary to
// work around an apparent bug with GC and Distributed Objects
// I am not familiar with GC though, so perhaps I was doing something wrong.
NSURL* url = [NSURL fileURLWithPath:[repositoryPath path]];
if (id document = [[PBRepositoryDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:nil]) {
[NSApp activateIgnoringOtherApps:YES];
return YES;
}
return NO;
}
@end
-1
View File
@@ -21,7 +21,6 @@ extern NSString* PBGitRepositoryErrorDomain;
- (NSFileHandle*) handleForCommand:(NSString*) cmd;
- (NSFileHandle*) handleForArguments:(NSArray*) args;
@property (copy) NSString* path;
@property (readonly) PBGitRevList* revisionList;
@end
+27 -18
View File
@@ -56,6 +56,26 @@ static NSString* gitPath;
return NO;
}
+ (NSURL*)gitDirForURL:(NSURL*)repositoryURL;
{
NSString* repositoryPath = [repositoryURL path];
NSURL* gitDirURL = nil;
if ([repositoryPath hasSuffix:@".git"]) {
gitDirURL = [NSURL fileURLWithPath:repositoryPath];
} else {
// 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];
if ([newPath isEqualToString:@".git"]) {
gitDirURL = [NSURL fileURLWithPath:[repositoryPath stringByAppendingPathComponent:@".git"]];
} else if ([newPath length] > 0) {
gitDirURL = [NSURL fileURLWithPath:newPath];
}
}
return gitDirURL;
}
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError
{
BOOL success = NO;
@@ -67,25 +87,14 @@ static NSString* gitPath;
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
} else {
NSString* repositoryPath = [[self fileURL] path];
if ([repositoryPath hasSuffix:@".git"]) {
[self setFileURL:[NSURL fileURLWithPath:repositoryPath]];
NSURL* gitDirURL = [PBGitRepository gitDirForURL:[self fileURL]];
if (gitDirURL) {
[self setFileURL:gitDirURL];
success = YES;
} else {
// 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];
if ([newPath isEqualToString:@".git"]) {
[self setFileURL:[NSURL fileURLWithPath:[repositoryPath stringByAppendingPathComponent:@".git"]]];
success = YES;
} else if ([newPath length] > 0) {
[self setFileURL:[NSURL fileURLWithPath:newPath]];
success = YES;
} else if (outError) {
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%@ does not appear to be a git repository.", [fileWrapper filename]]
forKey:NSLocalizedRecoverySuggestionErrorKey];
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
} else if (outError) {
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%@ does not appear to be a git repository.", [fileWrapper filename]]
forKey:NSLocalizedRecoverySuggestionErrorKey];
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
if (success) {
+7 -1
View File
@@ -7,7 +7,7 @@
//
#import "PBRepositoryDocumentController.h"
#import "PBGitRepository.h"
@implementation PBRepositoryDocumentController
// This method is overridden to configure the open panel to only allow
@@ -18,4 +18,10 @@
[openPanel setCanChooseDirectories:YES];
return [openPanel runModalForDirectory:nil file:nil types:nil];
}
// Convert paths to the .git dir before searching for an already open document
- (id)documentForURL:(NSURL *)URL
{
return [super documentForURL:[PBGitRepository gitDirForURL:URL]];
}
@end
+51
View File
@@ -0,0 +1,51 @@
//
// gitx.mm
// GitX
//
// Created by Ciarán Walsh on 15/08/2008.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBCLIProxy.h"
NSDistantObject* connect()
{
id proxy = [NSConnection rootProxyForConnectionWithRegisteredName:ConnectionName host:nil];
[proxy setProtocolForProxy:@protocol(GitXCliToolProtocol)];
return proxy;
}
int main(int argc, const char* argv)
{
// Attempt to connect to the app
id proxy = connect();
if (!proxy) {
// If the connection failed, try to launch the app
[[NSWorkspace sharedWorkspace] launchApplication:@"GitX"];
// Now attempt to connect, allowing the app time to startup
for (int attempt = 0; proxy == nil && attempt < 50; ++attempt){
if (proxy = connect())
break;
usleep(15000);
}
}
if (!proxy) {
fprintf(stderr, "Couldn't connect to app server!\n");
exit(1);
}
if ([[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"]) {
NSURL* url = [NSURL fileURLWithPath:[[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"]];
NSError* error = nil;
if (![proxy openRepository:url error:&error]) {
fprintf(stderr, "Error opening repository at %s", [[url path] UTF8String]);
if (error) {
fprintf(stderr, ": %s", [[error localizedFailureReason] UTF8String]);
}
fprintf(stderr, "\n");
}
}
}