GitCommitController: clean up index functions
[GitX.git] / ApplicationController.m
blob3a86d38a00ed069acbe5ce92b78d0c8d6e204f7d
1 //
2 //  GitTest_AppDelegate.m
3 //  GitTest
4 //
5 //  Created by Pieter de Bie on 13-06-08.
6 //  Copyright __MyCompanyName__ 2008 . All rights reserved.
7 //
9 #import "ApplicationController.h"
10 #import "PBGitRevisionCell.h"
11 #import "PBGitWindowController.h"
12 #import "PBRepositoryDocumentController.h"
13 #import "PBCLIProxy.h"
14 #import "PBServicesController.h"
15 #import "PBGitXProtocol.h"
16 #import "PBPrefsWindowController.h"
17 #import "PBNSURLPathUserDefaultsTransfomer.h"
19 @implementation ApplicationController
20 @synthesize cliProxy;
22 - (ApplicationController*)init
24 #ifdef DEBUG_BUILD
25         [NSApp activateIgnoringOtherApps:YES];
26 #endif
28         if(self = [super init]) {
29                 if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
30                         NSLog(@"Could not load QuickLook");
32                 self.cliProxy = [PBCLIProxy new];
33         }
35         /* Value Transformers */
36         NSValueTransformer *transformer = [[PBNSURLPathUserDefaultsTransfomer alloc] init];
37         [NSValueTransformer setValueTransformer:transformer forName:@"PBNSURLPathUserDefaultsTransfomer"];
38         
39         return self;
42 - (void)registerServices
44         // Register URL
45         [NSURLProtocol registerClass:[PBGitXProtocol class]];
47         // Register the service class
48         PBServicesController *services = [[PBServicesController alloc] init];
49         [NSApp setServicesProvider:services];
51         // Force update the services menu if we have a new services version
52         int serviceVersion = [[NSUserDefaults standardUserDefaults] integerForKey:@"Services Version"];
53         if (serviceVersion < 2)
54         {
55                 NSLog(@"Updating services menu…");
56                 NSUpdateDynamicServices();
57                 [[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"Services Version"];
58         }
61 - (void)applicationDidFinishLaunching:(NSNotification*)notification
63         [self registerServices];
65         // Only try to open a default document if there are no documents open already.
66         // For example, the application might have been launched by double-clicking a .git repository,
67         // or by dragging a folder to the app icon
68         if ([[[PBRepositoryDocumentController sharedDocumentController] documents] count] == 0 && [[NSApplication sharedApplication] isActive]) {
69                 // Try to open the current directory as a git repository
70                 NSURL *url = nil;
71                 if([[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"])
72                         url = [NSURL fileURLWithPath:[[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"]];
73                 NSError *error = nil;
74                 if (!url || [[PBRepositoryDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:&error] == NO) {
75                         // The current directory could not be opened (most likely it’s not a git repository)
76                         // so show an open panel for the user to select a repository to view
77                         [[PBRepositoryDocumentController sharedDocumentController] openDocument:self];
78                 }
79         }
82 - (void) windowWillClose: sender
84         [firstResponder terminate: sender];
87 - (IBAction)openPreferencesWindow:(id)sender
89         [[PBPrefsWindowController sharedPrefsWindowController] showWindow:nil];
92 - (IBAction)installCliTool:(id)sender;
94         BOOL success               = NO;
95         NSString* installationPath = @"/usr/local/bin/";
96         NSString* installationName = @"gitx";
97         NSString* toolPath         = [[NSBundle mainBundle] pathForResource:@"gitx" ofType:@""];
98         if (toolPath) {
99                 AuthorizationRef auth;
100                 if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth) == errAuthorizationSuccess) {
101                         char const* mkdir_arg[] = { "-p", [installationPath UTF8String], NULL};
102                         char const* mkdir       = "/bin/mkdir";
103                         AuthorizationExecuteWithPrivileges(auth, mkdir, kAuthorizationFlagDefaults, (char**)mkdir_arg, NULL);
104                         char const* arguments[] = { "-f", "-s", [toolPath UTF8String], [[installationPath stringByAppendingString: installationName] UTF8String],  NULL };
105                         char const* helperTool  = "/bin/ln";
106                         if (AuthorizationExecuteWithPrivileges(auth, helperTool, kAuthorizationFlagDefaults, (char**)arguments, NULL) == errAuthorizationSuccess) {
107                                 int status;
108                                 int pid = wait(&status);
109                                 if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
110                                         success = true;
111                                 else
112                                         errno = WEXITSTATUS(status);
113                         }
115                         AuthorizationFree(auth, kAuthorizationFlagDefaults);
116                 }
117         }
119         if (success) {
120                 [[NSAlert alertWithMessageText:@"Installation Complete"
121                             defaultButton:nil
122                           alternateButton:nil
123                               otherButton:nil
124                 informativeTextWithFormat:@"The gitx tool has been installed to %@", installationPath] runModal];
125         } else {
126                 [[NSAlert alertWithMessageText:@"Installation Failed"
127                             defaultButton:nil
128                           alternateButton:nil
129                               otherButton:nil
130                 informativeTextWithFormat:@"Installation to %@ failed", installationPath] runModal];
131         }
135     Returns the support folder for the application, used to store the Core Data
136     store file.  This code uses a folder named "GitTest" for
137     the content, either in the NSApplicationSupportDirectory location or (if the
138     former cannot be found), the system's temporary directory.
139  */
141 - (IBAction) showHelp:(id) sender
143         [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://gitx.frim.nl/user_manual.html"]];
146 - (NSString *)applicationSupportFolder {
148     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
149     NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
150     return [basePath stringByAppendingPathComponent:@"GitTest"];
155     Creates, retains, and returns the managed object model for the application 
156     by merging all of the models found in the application bundle.
157  */
159 - (NSManagedObjectModel *)managedObjectModel {
161     if (managedObjectModel != nil) {
162         return managedObjectModel;
163     }
164         
165     managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
166     return managedObjectModel;
171     Returns the persistent store coordinator for the application.  This 
172     implementation will create and return a coordinator, having added the 
173     store for the application to it.  (The folder for the store is created, 
174     if necessary.)
175  */
177 - (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
179     if (persistentStoreCoordinator != nil) {
180         return persistentStoreCoordinator;
181     }
183     NSFileManager *fileManager;
184     NSString *applicationSupportFolder = nil;
185     NSURL *url;
186     NSError *error;
187     
188     fileManager = [NSFileManager defaultManager];
189     applicationSupportFolder = [self applicationSupportFolder];
190     if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
191         [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil];
192     }
193     
194     url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"GitTest.xml"]];
195     persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
196     if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]){
197         [[NSApplication sharedApplication] presentError:error];
198     }    
200     return persistentStoreCoordinator;
205     Returns the managed object context for the application (which is already
206     bound to the persistent store coordinator for the application.) 
207  */
209 - (NSManagedObjectContext *) managedObjectContext {
211     if (managedObjectContext != nil) {
212         return managedObjectContext;
213     }
215     NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
216     if (coordinator != nil) {
217         managedObjectContext = [[NSManagedObjectContext alloc] init];
218         [managedObjectContext setPersistentStoreCoordinator: coordinator];
219     }
220     
221     return managedObjectContext;
226     Returns the NSUndoManager for the application.  In this case, the manager
227     returned is that of the managed object context for the application.
228  */
230 - (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
231     return [[self managedObjectContext] undoManager];
236     Performs the save action for the application, which is to send the save:
237     message to the application's managed object context.  Any encountered errors
238     are presented to the user.
239  */
241 - (IBAction) saveAction:(id)sender {
243     NSError *error = nil;
244     if (![[self managedObjectContext] save:&error]) {
245         [[NSApplication sharedApplication] presentError:error];
246     }
251     Implementation of the applicationShouldTerminate: method, used here to
252     handle the saving of changes in the application managed object context
253     before the application terminates.
254  */
256 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
258     NSError *error;
259     int reply = NSTerminateNow;
260     
261     if (managedObjectContext != nil) {
262         if ([managedObjectContext commitEditing]) {
263             if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
264                                 
265                 // This error handling simply presents error information in a panel with an 
266                 // "Ok" button, which does not include any attempt at error recovery (meaning, 
267                 // attempting to fix the error.)  As a result, this implementation will 
268                 // present the information to the user and then follow up with a panel asking 
269                 // if the user wishes to "Quit Anyway", without saving the changes.
271                 // Typically, this process should be altered to include application-specific 
272                 // recovery steps.  
274                 BOOL errorResult = [[NSApplication sharedApplication] presentError:error];
275                                 
276                 if (errorResult == YES) {
277                     reply = NSTerminateCancel;
278                 } 
280                 else {
281                                         
282                     int alertReturn = NSRunAlertPanel(nil, @"Could not save changes while quitting. Quit anyway?" , @"Quit anyway", @"Cancel", nil);
283                     if (alertReturn == NSAlertAlternateReturn) {
284                         reply = NSTerminateCancel;      
285                     }
286                 }
287             }
288         } 
289         
290         else {
291             reply = NSTerminateCancel;
292         }
293     }
294     
295     return reply;
300     Implementation of dealloc, to release the retained variables.
301  */
303 - (void) dealloc {
305     [managedObjectContext release], managedObjectContext = nil;
306     [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
307     [managedObjectModel release], managedObjectModel = nil;
308     [super dealloc];
310 @end