Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 420 lines (328 sloc) 14.652 kb
2763141 @pieter Initial commit
pieter authored
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 //
8
154b78b @pieter Rename to GitX
pieter authored
9 #import "ApplicationController.h"
fe8f173 @pieter Add custom cell
pieter authored
10 #import "PBGitRevisionCell.h"
708c08a @pieter First part of splitting views
pieter authored
11 #import "PBGitWindowController.h"
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
12 #import "PBRepositoryDocumentController.h"
19f4d94 @pieter Add a Complete SHA service
pieter authored
13 #import "PBServicesController.h"
e232181 @pieter Add a GitX:// protocol handler
pieter authored
14 #import "PBGitXProtocol.h"
0f09401 @clj Add a preferences window
clj authored
15 #import "PBPrefsWindowController.h"
16 #import "PBNSURLPathUserDefaultsTransfomer.h"
c00f736 @pieter Add preference to ignore whitespace differences in history view
pieter authored
17 #import "PBGitDefaults.h"
0ad9234 @brotherbard Add Clone Repository
authored
18 #import "PBCloneRepositoryPanel.h"
7747361 @pieter Update Sparkle Framework
pieter authored
19 #import "Sparkle/SUUpdater.h"
2763141 @pieter Initial commit
pieter authored
20
154b78b @pieter Rename to GitX
pieter authored
21 @implementation ApplicationController
2763141 @pieter Initial commit
pieter authored
22
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
23 - (ApplicationController*)init
0fda285 @pieter Use a separate Git class
pieter authored
24 {
48b0fc8 ApplicationController: Use a debug symbol that actually works
Pieter de Bie authored
25 #ifdef DEBUG_BUILD
18e2a51 @ciaran Force activation of the application after launch in debug builds.
ciaran authored
26 [NSApp activateIgnoringOtherApps:YES];
27 #endif
28
e60bb32 @brotherbard Refactor the gitx CLI to use apple events and the scripting bridge
authored
29 if(!(self = [super init]))
30 return nil;
0bb4cbc @ciaran Adding a basic command-line tool to interface with the application th…
ciaran authored
31
e60bb32 @brotherbard Refactor the gitx CLI to use apple events and the scripting bridge
authored
32 if(![[NSBundle bundleWithPath:@"/System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework"] load])
33 if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
34 NSLog(@"Could not load QuickLook");
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
35
0f09401 @clj Add a preferences window
clj authored
36 /* Value Transformers */
37 NSValueTransformer *transformer = [[PBNSURLPathUserDefaultsTransfomer alloc] init];
38 [NSValueTransformer setValueTransformer:transformer forName:@"PBNSURLPathUserDefaultsTransfomer"];
39
c00f736 @pieter Add preference to ignore whitespace differences in history view
pieter authored
40 // Make sure the PBGitDefaults is initialized, by calling a random method
41 [PBGitDefaults class];
0fda285 @pieter Use a separate Git class
pieter authored
42 return self;
2763141 @pieter Initial commit
pieter authored
43 }
44
19f4d94 @pieter Add a Complete SHA service
pieter authored
45 - (void)registerServices
46 {
e232181 @pieter Add a GitX:// protocol handler
pieter authored
47 // Register URL
48 [NSURLProtocol registerClass:[PBGitXProtocol class]];
49
19f4d94 @pieter Add a Complete SHA service
pieter authored
50 // Register the service class
51 PBServicesController *services = [[PBServicesController alloc] init];
52 [NSApp setServicesProvider:services];
53
54 // Force update the services menu if we have a new services version
55 int serviceVersion = [[NSUserDefaults standardUserDefaults] integerForKey:@"Services Version"];
56 if (serviceVersion < 2)
57 {
58 NSLog(@"Updating services menu…");
59 NSUpdateDynamicServices();
60 [[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"Services Version"];
61 }
62 }
63
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
64 - (void)applicationDidFinishLaunching:(NSNotification*)notification
65 {
7747361 @pieter Update Sparkle Framework
pieter authored
66 [[SUUpdater sharedUpdater] setSendsSystemProfile:YES];
0807099 @brotherbard Send the CFBundleGitVersion string along with the other sparkle profi…
authored
67 [[SUUpdater sharedUpdater] setDelegate:self];
a6b5705 @uliwitness First stab at an executable that can be put into the SSH_ASKPASS envi…
uliwitness authored
68
69 // Make sure Git's SSH password requests get forwarded to our little UI tool:
70 setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 );
71 setenv( "DISPLAY", "localhost:0", 1 );
72
19f4d94 @pieter Add a Complete SHA service
pieter authored
73 [self registerServices];
74
f2a395d @brotherbard Add Reopen all repositories from last session
authored
75 BOOL hasOpenedDocuments = NO;
76 NSArray *launchedDocuments = [[[PBRepositoryDocumentController sharedDocumentController] documents] copy];
77
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
78 // Only try to open a default document if there are no documents open already.
79 // For example, the application might have been launched by double-clicking a .git repository,
80 // or by dragging a folder to the app icon
f2a395d @brotherbard Add Reopen all repositories from last session
authored
81 if ([launchedDocuments count])
82 hasOpenedDocuments = YES;
83
84 // open any documents that were open the last time the app quit
85 if ([PBGitDefaults openPreviousDocumentsOnLaunch]) {
86 for (NSString *path in [PBGitDefaults previousDocumentPaths]) {
87 NSURL *url = [NSURL fileURLWithPath:path isDirectory:YES];
88 NSError *error = nil;
89 if (url && [[PBRepositoryDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:&error])
90 hasOpenedDocuments = YES;
91 }
92 }
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
93
94 // Try to find the current directory, to open that as a repository
f2a395d @brotherbard Add Reopen all repositories from last session
authored
95 if ([PBGitDefaults openCurDirOnLaunch] && !hasOpenedDocuments) {
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
96 NSString *curPath = [[[NSProcessInfo processInfo] environment] objectForKey:@"PWD"];
f2a395d @brotherbard Add Reopen all repositories from last session
authored
97 NSURL *url = nil;
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
98 if (curPath)
99 url = [NSURL fileURLWithPath:curPath];
f2a395d @brotherbard Add Reopen all repositories from last session
authored
100 // Try to open the found URL
101 NSError *error = nil;
102 if (url && [[PBRepositoryDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:&error])
103 hasOpenedDocuments = YES;
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
104 }
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
105
f2a395d @brotherbard Add Reopen all repositories from last session
authored
106 // to bring the launched documents to the front
107 for (PBGitRepository *document in launchedDocuments)
108 [document showWindows];
109
110 if (![[NSApplication sharedApplication] isActive])
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
111 return;
112
113 // The current directory was not enabled or could not be opened (most likely it’s not a git repository).
114 // show an open panel for the user to select a repository to view
f2a395d @brotherbard Add Reopen all repositories from last session
authored
115 if ([PBGitDefaults showOpenPanelOnLaunch] && !hasOpenedDocuments)
8532272 Add preferences for opening things at launch.
Stonewall Ballard authored
116 [[PBRepositoryDocumentController sharedDocumentController] openDocument:self];
b85a205 @ciaran Completing the document-based app setup.
ciaran authored
117 }
118
60e0684 @pieter Quit on closing the window
pieter authored
119 - (void) windowWillClose: sender
120 {
121 [firstResponder terminate: sender];
122 }
123
0f09401 @clj Add a preferences window
clj authored
124 - (IBAction)openPreferencesWindow:(id)sender
125 {
126 [[PBPrefsWindowController sharedPrefsWindowController] showWindow:nil];
127 }
128
0b81911 @heipei About-Panel: Show git-describe using Info.plist
heipei authored
129 - (IBAction)showAboutPanel:(id)sender
130 {
131 NSString *gitversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGitVersion"];
132 NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
133 if (gitversion)
134 [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:gitversion, @"Version", nil]];
135
136 #ifdef DEBUG_BUILD
137 [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:@"GitX (DEBUG)", @"ApplicationName", nil]];
138 #endif
139
140 [NSApp orderFrontStandardAboutPanelWithOptions:dict];
141 }
142
0ad9234 @brotherbard Add Clone Repository
authored
143 - (IBAction) showCloneRepository:(id)sender
144 {
145 if (!cloneRepositoryPanel)
146 cloneRepositoryPanel = [PBCloneRepositoryPanel panel];
147
148 [cloneRepositoryPanel showWindow:self];
149 }
150
3773a73 @ciaran Adding a menu item to install the CLI tool.
ciaran authored
151 - (IBAction)installCliTool:(id)sender;
152 {
6f6b1e3 @ciaran Installation of the gitx command-line tool.
ciaran authored
153 BOOL success = NO;
b18d9af @heipei ApplicationController: Make sure gitx installation-path exists
heipei authored
154 NSString* installationPath = @"/usr/local/bin/";
155 NSString* installationName = @"gitx";
6f6b1e3 @ciaran Installation of the gitx command-line tool.
ciaran authored
156 NSString* toolPath = [[NSBundle mainBundle] pathForResource:@"gitx" ofType:@""];
157 if (toolPath) {
158 AuthorizationRef auth;
159 if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth) == errAuthorizationSuccess) {
b18d9af @heipei ApplicationController: Make sure gitx installation-path exists
heipei authored
160 char const* mkdir_arg[] = { "-p", [installationPath UTF8String], NULL};
161 char const* mkdir = "/bin/mkdir";
162 AuthorizationExecuteWithPrivileges(auth, mkdir, kAuthorizationFlagDefaults, (char**)mkdir_arg, NULL);
163 char const* arguments[] = { "-f", "-s", [toolPath UTF8String], [[installationPath stringByAppendingString: installationName] UTF8String], NULL };
6f6b1e3 @ciaran Installation of the gitx command-line tool.
ciaran authored
164 char const* helperTool = "/bin/ln";
165 if (AuthorizationExecuteWithPrivileges(auth, helperTool, kAuthorizationFlagDefaults, (char**)arguments, NULL) == errAuthorizationSuccess) {
166 int status;
167 int pid = wait(&status);
168 if (pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
169 success = true;
170 else
171 errno = WEXITSTATUS(status);
172 }
173
174 AuthorizationFree(auth, kAuthorizationFlagDefaults);
175 }
176 }
177
178 if (success) {
179 [[NSAlert alertWithMessageText:@"Installation Complete"
180 defaultButton:nil
181 alternateButton:nil
182 otherButton:nil
183 informativeTextWithFormat:@"The gitx tool has been installed to %@", installationPath] runModal];
184 } else {
185 [[NSAlert alertWithMessageText:@"Installation Failed"
186 defaultButton:nil
187 alternateButton:nil
188 otherButton:nil
189 informativeTextWithFormat:@"Installation to %@ failed", installationPath] runModal];
190 }
3773a73 @ciaran Adding a menu item to install the CLI tool.
ciaran authored
191 }
192
2763141 @pieter Initial commit
pieter authored
193 /**
194 Returns the support folder for the application, used to store the Core Data
195 store file. This code uses a folder named "GitTest" for
196 the content, either in the NSApplicationSupportDirectory location or (if the
197 former cannot be found), the system's temporary directory.
198 */
199
200 - (NSString *)applicationSupportFolder {
201
202 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
203 NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
204 return [basePath stringByAppendingPathComponent:@"GitTest"];
205 }
206
207
208 /**
209 Creates, retains, and returns the managed object model for the application
210 by merging all of the models found in the application bundle.
211 */
212
213 - (NSManagedObjectModel *)managedObjectModel {
214
215 if (managedObjectModel != nil) {
216 return managedObjectModel;
217 }
218
219 managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
220 return managedObjectModel;
221 }
222
223
224 /**
225 Returns the persistent store coordinator for the application. This
226 implementation will create and return a coordinator, having added the
227 store for the application to it. (The folder for the store is created,
228 if necessary.)
229 */
230
231 - (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
232
233 if (persistentStoreCoordinator != nil) {
234 return persistentStoreCoordinator;
235 }
236
237 NSFileManager *fileManager;
238 NSString *applicationSupportFolder = nil;
239 NSURL *url;
240 NSError *error;
241
242 fileManager = [NSFileManager defaultManager];
243 applicationSupportFolder = [self applicationSupportFolder];
244 if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) {
245 [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil];
246 }
247
248 url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"GitTest.xml"]];
249 persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
250 if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]){
251 [[NSApplication sharedApplication] presentError:error];
252 }
253
254 return persistentStoreCoordinator;
255 }
256
257
258 /**
259 Returns the managed object context for the application (which is already
260 bound to the persistent store coordinator for the application.)
261 */
262
263 - (NSManagedObjectContext *) managedObjectContext {
264
265 if (managedObjectContext != nil) {
266 return managedObjectContext;
267 }
268
269 NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
270 if (coordinator != nil) {
271 managedObjectContext = [[NSManagedObjectContext alloc] init];
272 [managedObjectContext setPersistentStoreCoordinator: coordinator];
273 }
274
275 return managedObjectContext;
276 }
277
278
279 /**
280 Returns the NSUndoManager for the application. In this case, the manager
281 returned is that of the managed object context for the application.
282 */
283
284 - (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
285 return [[self managedObjectContext] undoManager];
286 }
287
288
289 /**
290 Performs the save action for the application, which is to send the save:
291 message to the application's managed object context. Any encountered errors
292 are presented to the user.
293 */
294
295 - (IBAction) saveAction:(id)sender {
296
297 NSError *error = nil;
298 if (![[self managedObjectContext] save:&error]) {
299 [[NSApplication sharedApplication] presentError:error];
300 }
301 }
302
303
304 /**
305 Implementation of the applicationShouldTerminate: method, used here to
306 handle the saving of changes in the application managed object context
307 before the application terminates.
308 */
309
310 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
311
312 NSError *error;
313 int reply = NSTerminateNow;
314
315 if (managedObjectContext != nil) {
316 if ([managedObjectContext commitEditing]) {
317 if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
318
319 // This error handling simply presents error information in a panel with an
320 // "Ok" button, which does not include any attempt at error recovery (meaning,
321 // attempting to fix the error.) As a result, this implementation will
322 // present the information to the user and then follow up with a panel asking
323 // if the user wishes to "Quit Anyway", without saving the changes.
324
325 // Typically, this process should be altered to include application-specific
326 // recovery steps.
327
328 BOOL errorResult = [[NSApplication sharedApplication] presentError:error];
329
330 if (errorResult == YES) {
331 reply = NSTerminateCancel;
332 }
333
334 else {
335
336 int alertReturn = NSRunAlertPanel(nil, @"Could not save changes while quitting. Quit anyway?" , @"Quit anyway", @"Cancel", nil);
337 if (alertReturn == NSAlertAlternateReturn) {
338 reply = NSTerminateCancel;
339 }
340 }
341 }
342 }
343
344 else {
345 reply = NSTerminateCancel;
346 }
347 }
348
349 return reply;
350 }
351
f2a395d @brotherbard Add Reopen all repositories from last session
authored
352 - (void)applicationWillTerminate:(NSNotification *)aNotification
353 {
354 [PBGitDefaults removePreviousDocumentPaths];
355
356 if ([PBGitDefaults openPreviousDocumentsOnLaunch]) {
357 NSArray *documents = [[PBRepositoryDocumentController sharedDocumentController] documents];
358 if ([documents count] > 0) {
359 NSMutableArray *paths = [NSMutableArray array];
360 for (PBGitRepository *repository in documents)
361 [paths addObject:[repository workingDirectory]];
362
363 [PBGitDefaults setPreviousDocumentPaths:paths];
364 }
365 }
366 }
2763141 @pieter Initial commit
pieter authored
367
368 /**
369 Implementation of dealloc, to release the retained variables.
370 */
371
372 - (void) dealloc {
373
374 [managedObjectContext release], managedObjectContext = nil;
375 [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
376 [managedObjectModel release], managedObjectModel = nil;
377 [super dealloc];
378 }
0807099 @brotherbard Send the CFBundleGitVersion string along with the other sparkle profi…
authored
379
380
381 #pragma mark Sparkle delegate methods
382
383 - (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile
384 {
385 NSArray *keys = [NSArray arrayWithObjects:@"key", @"displayKey", @"value", @"displayValue", nil];
386 NSMutableArray *feedParameters = [NSMutableArray array];
387
388 // only add parameters if the profile is being sent this time
389 if (sendingProfile) {
390 NSString *CFBundleGitVersion = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleGitVersion"];
391 if (CFBundleGitVersion)
392 [feedParameters addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"CFBundleGitVersion", @"Full Version", CFBundleGitVersion, CFBundleGitVersion, nil]
393 forKeys:keys]];
394
395 NSString *gitVersion = [PBGitBinary version];
396 if (gitVersion)
397 [feedParameters addObject:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"gitVersion", @"git Version", gitVersion, gitVersion, nil]
398 forKeys:keys]];
399 }
400
401 return feedParameters;
402 }
403
7123fd6 @brotherbard Add a "Report a problem" item to the Help menu
authored
404
405 #pragma mark Help menu
406
407 - (IBAction)showHelp:(id)sender
408 {
409 [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://gitx.frim.nl/user_manual.html"]];
410 }
411
412 - (IBAction)reportAProblem:(id)sender
413 {
414 [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://gitx.lighthouseapp.com/tickets"]];
415 }
416
417
418
2763141 @pieter Initial commit
pieter authored
419 @end
Something went wrong with that request. Please try again.