Merge commit 'pieter/master' into grapher

Conflicts:

	ApplicationController.m
	GitX.xcodeproj/project.pbxproj
	PBGitRepository.m
	PBGitRevList.m
This commit is contained in:
Ciarán Walsh
2008-08-19 13:09:43 +01:00
24 changed files with 5204 additions and 4384 deletions
+1
View File
@@ -1 +1,2 @@
English.lproj/MainMenu.xib -diff
English.lproj/RepositoryWindow.xib -diff
+3
View File
@@ -1,3 +1,6 @@
build
*.xcodeproj/*.pbxuser
*.xcodeproj/*.perspectivev3
*.xcodeproj/*.mode1v3
*.xcodeproj/*.tm_build_errors
*.tmproj
+11 -7
View File
@@ -9,22 +9,26 @@
#import <Cocoa/Cocoa.h>
#import "PBGitRepository.h"
@class PBCLIProxy;
@interface ApplicationController : NSObject
{
IBOutlet NSWindow *window;
IBOutlet PBGitRepository* repository;
IBOutlet NSWindow *window;
IBOutlet id firstResponder;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
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;
@property (retain) PBGitRepository* repository;
@end
+71 -32
View File
@@ -8,41 +8,91 @@
#import "ApplicationController.h"
#import "PBGitRevisionCell.h"
#import "PBDetailController.h"
#import "PBRepositoryDocumentController.h"
#import "PBCLIProxy.h"
@implementation ApplicationController
@synthesize cliProxy;
@synthesize repository;
- (ApplicationController*) init
- (ApplicationController*)init
{
if([[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
NSLog(@"Quick Look loaded!");
#ifndef NDEBUG
[NSApp activateIgnoringOtherApps:YES];
#endif
// Find the current repository
char* a = getenv("PWD");
NSString* path;
if (a != nil)
path = [NSString stringWithCString:a];
else {
// Show an open dialog
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:NO];
[openDlg setCanChooseDirectories:YES];
if ( [openDlg runModalForDirectory:nil file:nil] == NSOKButton )
path = [openDlg filename];
else
exit(1);
if(self = [super init]) {
if([[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
NSLog(@"Quick Look loaded!");
self.cliProxy = [PBCLIProxy new];
}
self.repository = [PBGitRepository repositoryWithPath:path];
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
// Only try to open a default document if there are no documents open already.
// For example, the application might have been launched by double-clicking a .git repository,
// or by dragging a folder to the app icon
if ([[[PBRepositoryDocumentController sharedDocumentController] documents] count] == 0) {
// Try to open the current directory as a git repository
NSURL *url = nil;
if([[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"])
url = [NSURL fileURLWithPath:[[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"]];
NSError *error = nil;
if (!url || [[PBRepositoryDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:&error] == NO) {
// The current directory could not be opened (most likely its not a git repository)
// so show an open panel for the user to select a repository to view
[[PBRepositoryDocumentController sharedDocumentController] openDocument:self];
}
}
}
- (void) windowWillClose: sender
{
[firstResponder terminate: sender];
}
- (IBAction)installCliTool:(id)sender;
{
BOOL success = NO;
NSString* installationPath = @"/usr/bin/gitx";
NSString* toolPath = [[NSBundle mainBundle] pathForResource:@"gitx" ofType:@""];
if (toolPath) {
AuthorizationRef auth;
if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth) == errAuthorizationSuccess) {
char const* arguments[] = { "-s", [toolPath UTF8String], [installationPath UTF8String], NULL };
char const* helperTool = "/bin/ln";
if (AuthorizationExecuteWithPrivileges(auth, helperTool, kAuthorizationFlagDefaults, (char**)arguments, NULL) == errAuthorizationSuccess) {
int status;
int pid = wait(&status);
if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
success = true;
else
errno = WEXITSTATUS(status);
}
AuthorizationFree(auth, kAuthorizationFlagDefaults);
}
}
if (success) {
[[NSAlert alertWithMessageText:@"Installation Complete"
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"The gitx tool has been installed to %@", installationPath] runModal];
} else {
[[NSAlert alertWithMessageText:@"Installation Failed"
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"Installation to %@ failed", installationPath] runModal];
}
}
- (IBAction) switchBranch: sender
{
[[NSAlert alertWithMessageText:@"Not Supported" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"Sorry, switching branches is not supported yet"] runModal];
@@ -219,15 +269,4 @@
[managedObjectModel release], managedObjectModel = nil;
[super dealloc];
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if (![[aTableColumn identifier] isEqualToString:@"subject"])
return;
if (self.repository.revisionList.grapher) {
PBGitGrapher* g = self.repository.revisionList.grapher;
[aCell setCellInfo: [g cellInfoForRow:rowIndex]];
}
}
@end
+670 -4304
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+148
View File
@@ -12,6 +12,12 @@
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
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 */; };
911112370E5A097800BF76B4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 911112360E5A097800BF76B4 /* Security.framework */; };
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 */; };
@@ -35,6 +41,16 @@
F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E790E082E440006317A /* PBGitGrapher.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>"; };
@@ -48,6 +64,14 @@
77C8280C06725ACE000B614F /* ApplicationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApplicationController.m; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* GitX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GitX.app; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
911112360E5A097800BF76B4 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
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>"; };
@@ -91,6 +115,14 @@
files = (
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
F56526240E03D85900F03B52 /* WebKit.framework in Frameworks */,
911112370E5A097800BF76B4 /* Security.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
913D5E470E55644600CECEA2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -116,6 +148,7 @@
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
isa = PBXGroup;
children = (
911112360E5A097800BF76B4 /* Security.framework */,
77C82804067257F0000B614F /* CoreData.framework */,
29B97325FDCFA39411CA2CEA /* Foundation.framework */,
29B97324FDCFA39411CA2CEA /* AppKit.framework */,
@@ -127,6 +160,7 @@
isa = PBXGroup;
children = (
8D1107320486CEB800E47090 /* GitX.app */,
913D5E490E55644600CECEA2 /* gitx */,
);
name = Products;
sourceTree = "<group>";
@@ -134,6 +168,7 @@
29B97314FDCFA39411CA2CEA /* GitTest */ = {
isa = PBXGroup;
children = (
913D5E420E5563FD00CECEA2 /* cli */,
F57CC43E0E05E472000472E2 /* Aux */,
F57CC3850E05DDC1000472E2 /* Controllers */,
F561777C0E05C88E001DCD79 /* DetailView.png */,
@@ -164,6 +199,7 @@
8D1107310486CEB800E47090 /* Info.plist */,
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
F5B721C20E05CF7E00AF29DC /* MainMenu.xib */,
911111E00E58BD5A00BF76B4 /* RepositoryWindow.xib */,
);
name = Resources;
sourceTree = "<group>";
@@ -185,6 +221,14 @@
name = Models;
sourceTree = "<group>";
};
913D5E420E5563FD00CECEA2 /* cli */ = {
isa = PBXGroup;
children = (
913D5E440E55640C00CECEA2 /* gitx.mm */,
);
name = cli;
sourceTree = "<group>";
};
F56174540E05887E001DCD79 /* Git */ = {
isa = PBXGroup;
children = (
@@ -211,6 +255,10 @@
77C8280C06725ACE000B614F /* ApplicationController.m */,
F57CC43F0E05E496000472E2 /* PBDetailController.h */,
F57CC4400E05E496000472E2 /* PBDetailController.m */,
911111F60E594F3F00BF76B4 /* PBRepositoryDocumentController.h */,
911111F70E594F3F00BF76B4 /* PBRepositoryDocumentController.m */,
913D5E5D0E556A9300CECEA2 /* PBCLIProxy.h */,
913D5E5E0E556A9300CECEA2 /* PBCLIProxy.mm */,
);
name = Controllers;
sourceTree = "<group>";
@@ -260,6 +308,7 @@
buildRules = (
);
dependencies = (
913D5E5A0E5564F400CECEA2 /* PBXTargetDependency */,
);
name = GitX;
productInstallPath = "$(HOME)/Applications";
@@ -267,6 +316,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 */
@@ -280,6 +345,7 @@
projectRoot = "";
targets = (
8D1107260486CEB800E47090 /* GitX */,
913D5E480E55644600CECEA2 /* cli tool */,
);
};
/* End PBXProject section */
@@ -289,6 +355,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 */,
@@ -298,6 +365,7 @@
F58A8F280E043698007E3FC0 /* commits.css in Resources */,
F561777D0E05C88E001DCD79 /* DetailView.png in Resources */,
F5B721C40E05CF7E00AF29DC /* MainMenu.xib in Resources */,
911111E20E58BD5A00BF76B4 /* RepositoryWindow.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -323,11 +391,29 @@
F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */,
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */,
F5FF4E7A0E082E440006317A /* PBGitGrapher.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;
@@ -337,6 +423,14 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
911111E00E58BD5A00BF76B4 /* RepositoryWindow.xib */ = {
isa = PBXVariantGroup;
children = (
911111E10E58BD5A00BF76B4 /* English */,
);
name = RepositoryWindow.xib;
sourceTree = "<group>";
};
F5B721C20E05CF7E00AF29DC /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
@@ -408,6 +502,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 */
@@ -429,6 +568,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 */;
+21 -1
View File
@@ -1,11 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>git</string>
<string></string>
</array>
<key>CFBundleTypeIconFile</key>
<string></string>
<key>CFBundleTypeName</key>
<string>Git Repository</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<true/>
<key>NSDocumentClass</key>
<string>PBGitRepository</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
+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
+6 -1
View File
@@ -7,15 +7,17 @@
//
#import <Cocoa/Cocoa.h>
#import "PBGitRepository.h"
#import "PBGitCommit.h"
#import "PBGitTree.h"
@interface PBDetailController : NSObject {
@interface PBDetailController : NSWindowController {
IBOutlet NSNumber* selectedTab;
IBOutlet NSArrayController* commitController;
IBOutlet NSTreeController* treeController;
IBOutlet NSOutlineView* fileBrowser;
PBGitRepository* repository;
PBGitTree* gitTree;
PBGitCommit* webCommit;
PBGitCommit* rawCommit;
@@ -23,10 +25,13 @@
}
@property (copy) NSNumber* selectedTab;
@property (retain) PBGitRepository* repository;
@property (retain) PBGitCommit* webCommit;
@property (retain) PBGitCommit* rawCommit;
@property (retain) PBGitTree* gitTree;
- (id)initWithRepository:(PBGitRepository*)theRepository;
- (IBAction) setDetailedView: sender;
- (IBAction) setRawView: sender;
- (IBAction) setTreeView: sender;
+22 -1
View File
@@ -8,13 +8,24 @@
#import "PBDetailController.h"
#import "CWQuickLook.h"
#import "PBGitGrapher.h"
#define QLPreviewPanel NSClassFromString(@"QLPreviewPanel")
@implementation PBDetailController
@synthesize selectedTab, webCommit, rawCommit, gitTree;
@synthesize repository, selectedTab, webCommit, rawCommit, gitTree;
- (id)initWithRepository:(PBGitRepository*)theRepository;
{
if(self = [self initWithWindowNibName:@"RepositoryWindow"])
{
self.repository = theRepository;
[self showWindow:nil];
}
return self;
}
- awakeFromNib
{
@@ -129,4 +140,14 @@
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if (![[aTableColumn identifier] isEqualToString:@"subject"])
return;
if (self.repository.revisionList.grapher) {
PBGitGrapher* g = self.repository.revisionList.grapher;
[aCell setCellInfo: [g cellInfoForRow:rowIndex]];
}
}
@end
+18 -10
View File
@@ -9,22 +9,30 @@
#import <Cocoa/Cocoa.h>
#import "PBGitRevList.h"
@interface PBGitRepository : NSObject {
NSString* path;
extern NSString* PBGitRepositoryErrorDomain;
@interface PBGitRepository : NSDocument {
PBGitRevList* revisionList;
NSArray* branches;
NSString* currentBranch;
}
+ (void) setGitPath;
+ (PBGitRepository*) repositoryWithPath:(NSString*) path;
- (PBGitRepository*) initWithPath:(NSString*) path;
- (NSFileHandle*) handleForCommand:(NSString*) cmd;
- (NSFileHandle*) handleForArguments:(NSArray*) args;
- (void) initializeCommits;
- (void) addCommit: (id)obj;
- (NSString*) outputForCommand:(NSString*) cmd;
- (NSString*) outputForArguments:(NSArray*) args;
- (void) readBranches;
- (void) readCurrentBranch;
- (NSString*) parseSymbolicReference:(NSString*) ref;
- (NSString*) parseReference:(NSString*) ref;
+ (NSURL*)gitDirForURL:(NSURL*)repositoryURL;
+ (NSURL*)baseDirForURL:(NSURL*)repositoryURL;
@property (copy) NSString* path;
@property (readonly) PBGitRevList* revisionList;
@property (assign) NSArray* branches;
@property (assign) NSString* currentBranch;
@end
+149 -21
View File
@@ -8,13 +8,16 @@
#import "PBGitRepository.h"
#import "PBGitCommit.h"
#import "PBDetailController.h"
#import "NSFileHandleExt.h"
#import "PBEasyPipe.h"
NSString* PBGitRepositoryErrorDomain = @"GitXErrorDomain";
@implementation PBGitRepository
@synthesize path, revisionList;
@synthesize revisionList, branches, currentBranch;
static NSString* gitPath;
+ (void) initialize
@@ -28,41 +31,142 @@ static NSString* gitPath;
// No explicit path. Try it with "which"
gitPath = [PBEasyPipe outputForCommand:@"/usr/bin/which" withArgs:[NSArray arrayWithObject:@"git"]];
if (gitPath.length > 0)
return;
if (gitPath.length == 0) {
NSLog(@"Git path not found. Defaulting to /opt/pieter/bin/git");
gitPath = @"/opt/pieter/bin/git";
// Still no path. Let's try some default locations.
NSArray* locations = [NSArray arrayWithObjects:@"/opt/local/bin/git", @"/sw/bin/git", @"/opt/git/bin/git", nil];
for (NSString* location in locations) {
if ([[NSFileManager defaultManager] fileExistsAtPath:location]) {
gitPath = location;
return;
}
}
NSLog(@"Could not find a git binary!");
}
+ (PBGitRepository*) repositoryWithPath:(NSString*) path
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
PBGitRepository* repo = [[PBGitRepository alloc] initWithPath: path];
return repo;
if (outError) {
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain
code:0
userInfo:[NSDictionary dictionaryWithObject:@"Reading files is not supported." forKey:NSLocalizedFailureReasonErrorKey]];
}
return NO;
}
- (PBGitRepository*) initWithPath: (NSString*) p
+ (NSURL*)gitDirForURL:(NSURL*)repositoryURL;
{
if ([p hasSuffix:@".git"])
self.path = p;
else {
NSString* newPath = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--git-dir", nil] inDir:p];
if ([newPath isEqualToString:@".git"])
self.path = [p stringByAppendingPathComponent:@".git"];
else
self.path = newPath;
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];
}
}
NSLog(@"Git path is: %@", self.path);
revisionList = [[PBGitRevList alloc] initWithRepository:self andRevListParameters:[NSArray array]];
return self;
return gitDirURL;
}
// For a given path inside a repository, return either the .git dir
// (for a bare repo) or the directory above the .git dir otherwise
+ (NSURL*)baseDirForURL:(NSURL*)repositoryURL;
{
NSURL* gitDirURL = [self gitDirForURL:repositoryURL];
NSString* repositoryPath = [gitDirURL path];
if (![[PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"rev-parse", @"--is-bare-repository", nil] inDir:repositoryPath] isEqualToString:@"true"]) {
repositoryURL = [NSURL fileURLWithPath:[[repositoryURL path] stringByDeletingLastPathComponent]];
}
return repositoryURL;
}
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError
{
BOOL success = NO;
if (![fileWrapper isDirectory]) {
if (outError) {
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Reading files is not supported.", [fileWrapper filename]]
forKey:NSLocalizedRecoverySuggestionErrorKey];
*outError = [NSError errorWithDomain:PBGitRepositoryErrorDomain code:0 userInfo:userInfo];
}
} else {
NSURL* gitDirURL = [PBGitRepository gitDirForURL:[self fileURL]];
if (gitDirURL) {
[self setFileURL:gitDirURL];
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];
}
if (success) {
[self readBranches];
[self readCurrentBranch];
revisionList = [[PBGitRevList alloc] initWithRepository:self andRevListParameters:[NSArray array]];
}
}
return success;
}
// The fileURL the document keeps is to the .git dir, but thats pretty
// useless for display in the window title bar, so we show the directory above
- (NSString*)displayName
{
NSString* displayName = self.fileURL.path.lastPathComponent;
if ([displayName isEqualToString:@".git"])
displayName = [self.fileURL.path stringByDeletingLastPathComponent].lastPathComponent;
return displayName;
}
// Overridden to create our custom window controller
- (void)makeWindowControllers
{
PBDetailController* controller = [[PBDetailController alloc] initWithRepository:self];
[self addWindowController:controller];
[controller release];
}
- (void) readBranches
{
NSString* output = [PBEasyPipe outputForCommand:gitPath withArgs:[NSArray arrayWithObjects:@"for-each-ref", @"refs/heads", nil] inDir: self.fileURL.path];
NSArray* lines = [output componentsSeparatedByString:@"\n"];
NSMutableArray* newBranches = [NSMutableArray array];
for (NSString* line in lines) {
NSString* substr = [line substringWithRange: NSMakeRange(40,19)];
if (![substr isEqualToString:@" commit\trefs/heads/"]) {
NSLog(@"Cannot parse branch %@. (%@)", line, substr);
continue;
}
NSString* branch = [line substringFromIndex:59];
[newBranches addObject: branch];
}
self.branches = newBranches;
}
- (void) readCurrentBranch
{
NSString* branch = [self parseSymbolicReference: @"HEAD"];
if (branch && [branch hasPrefix:@"refs/heads/"])
self.currentBranch = [branch substringFromIndex:11];
}
- (NSFileHandle*) handleForArguments:(NSArray *)args
{
NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:path];
NSString* gitDirArg = [@"--git-dir=" stringByAppendingString:self.fileURL.path];
NSMutableArray* arguments = [NSMutableArray arrayWithObject: gitDirArg];
[arguments addObjectsFromArray: args];
return [PBEasyPipe handleForCommand:gitPath withArgs:arguments];
@@ -74,4 +178,28 @@ static NSString* gitPath;
return [self handleForArguments:arguments];
}
- (NSString*) outputForCommand:(NSString *)cmd
{
NSArray* arguments = [cmd componentsSeparatedByString:@" "];
return [self outputForArguments: arguments];
}
- (NSString*) outputForArguments:(NSArray*) arguments
{
return [PBEasyPipe outputForCommand:gitPath withArgs:arguments inDir: self.fileURL.path];
}
- (NSString*) parseReference:(NSString *)reference
{
return [self outputForArguments:[NSArray arrayWithObjects: @"rev-parse", reference, nil]];
}
- (NSString*) parseSymbolicReference:(NSString*) reference
{
NSString* ref = [self outputForArguments:[NSArray arrayWithObjects: @"symbolic-ref", reference, nil]];
if ([ref hasPrefix:@"refs/"])
return ref;
return nil;
}
@end
+2
View File
@@ -14,9 +14,11 @@
NSArray* parameters;
id grapher;
id repository;
NSString* currentRef;
}
- initWithRepository:(id)repo andRevListParameters:(NSArray*) params;
- readCommits;
@property(retain) NSArray* commits;
@property(retain) id grapher;
+31 -2
View File
@@ -18,9 +18,38 @@
{
parameters = params;
repository = repo;
[self readCommits];
[repository addObserver:self forKeyPath:@"currentBranch" options:0 context:nil];
return self;
}
- (void) readCommits
{
// We use refparse to get the commit sha that we will parse. That way,
// we can check if the current branch is the same as the previous one
// and in that case we don't have to reload the revision list.
// If no branch was selected, use the current HEAD
NSString* newRef = [repository currentBranch];
if (!newRef || [newRef isEqualToString:@""])
newRef = @"HEAD";
newRef = [repository parseReference:newRef];
if ([newRef isEqualToString:currentRef])
return;
currentRef = newRef;
NSThread * commitThread = [[NSThread alloc] initWithTarget: self selector: @selector(walkRevisionList) object:nil];
[commitThread start];
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if (object == repository)
[self readCommits];
}
- (void) walkRevisionList
@@ -28,7 +57,7 @@
NSMutableArray * newArray = [NSMutableArray array];
NSDate* start = [NSDate date];
NSFileHandle* handle = [repository handleForCommand:@"log --topo-order --pretty=format:%H\01%an\01%s\01%P\01%at HEAD"];
NSFileHandle* handle = [repository handleForArguments:[NSArray arrayWithObjects:@"log", @"--pretty=format:%H\01%an\01%s\01%P\01%at", currentRef, nil]];
int fd = [handle fileDescriptor];
FILE* f = fdopen(fd, "r");
+1 -1
View File
@@ -124,7 +124,7 @@
return localFileName;
if (!localFileName)
localFileName = [PBEasyFS tmpNameWithSuffix: path];
localFileName = [[PBEasyFS tmpDirWithPrefix: sha] stringByAppendingPathComponent:path];
NSFileHandle* handle = [repository handleForArguments:[NSArray arrayWithObjects:@"show", [self refSpec], nil]];
NSData* data = [handle readDataToEndOfFile];
+17
View File
@@ -0,0 +1,17 @@
//
// PBRepositoryDocumentController.h
// GitX
//
// Created by Ciarán Walsh on 15/08/2008.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface PBRepositoryDocumentController : NSDocumentController
{
}
@end
+32
View File
@@ -0,0 +1,32 @@
//
// PBRepositoryDocumentController.mm
// GitX
//
// Created by Ciarán Walsh on 15/08/2008.
// Copyright 2008 __MyCompanyName__. All rights reserved.
//
#import "PBRepositoryDocumentController.h"
#import "PBGitRepository.h"
@implementation PBRepositoryDocumentController
// This method is overridden to configure the open panel to only allow
// selection of directories
- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)extensions
{
[openPanel setCanChooseFiles:NO];
[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]];
}
- (void)noteNewRecentDocumentURL:(NSURL*)url
{
[super noteNewRecentDocumentURL:[PBGitRepository baseDirForURL:url]];
}
@end
-1
View File
@@ -13,7 +13,6 @@
#import <WebKit/WebKit.h>
@interface PBWebGitController : NSObject {
IBOutlet ApplicationController* controller;
IBOutlet WebView* view;
IBOutlet PBDetailController* detailController;
NSString* currentSha;
+1 -1
View File
@@ -65,7 +65,7 @@
- (void) selectCommit: (NSString*) sha
{
NSPredicate* selection = [NSPredicate predicateWithFormat:@"sha == %@", sha];
NSArray* selectedCommits = [controller.repository.revisionList.commits filteredArrayUsingPredicate:selection];
NSArray* selectedCommits = [detailController.repository.revisionList.commits filteredArrayUsingPredicate:selection];
// TODO: reimplement this. How can we set the new commit? Our detailscontroller is read-only
}
+59
View File
@@ -0,0 +1,59 @@
require 'ftools'
target_locations = [
File::expand_path("~/Applications/"),
"/Applications/"
]
desc "Build and install (or upgrade) GitX"
task :install => [:uninstall_app, :build_app, :install_app]
desc "Clean build directory, uninstall application"
task :uninstall => [:clean_app, :uninstall_app]
desc "Clean build directory"
task :clean => [:clean_app]
desc "Build gitX using XCode"
task :build_app do
system("xcodebuild")
end
task :clean_app do
system("xcodebuild -alltargets clean OBJROOT=build/ SYMROOT=build/")
end
desc "Copies the built GitX.app to the application folder"
task :install_app do
target_locations.each do |loc|
if File.directory?(loc)
puts "Copying to (#{loc})"
File.copy("build/Release/GitX.app/", loc)
break
end
end
end
desc "Remove GitX.app from ~/Applications/ or /Applications/"
task :uninstall_app do
found = false
target_locations.each do |loc|
cur_path = File.join(loc, "GitX.app")
puts "Checking #{cur_path}"
if File.exists?( cur_path )
puts "Removing GitX.app from #{cur_path}"
system("rm", "-rf", cur_path)
found = true
break
end
end
puts "Couldn't find installed GitX.app" unless found
end
desc "Creates a zip file with current GitX"
task :create_zip do
delete = File.directory?("build/Release")
system("xcodebuild")
system("cd build/Release && zip -r GitX.app.zip GitX.app")
system("mv build/Release/GitX.app.zip .")
system("rm -rf build/Release") if delete
system("upload GitX.app.zip") # This is a local script -- Pieter
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");
}
}
}
+2 -2
View File
@@ -9,8 +9,8 @@ var highlightDiffs = function() {
var start = new Date();
lines.each(function(l) {
if (l.length > 100)
l = l.substring(0, 100);
if (l.length > 250)
l = l.substring(0, 250);
l = l.gsub("\t", " ");