7
7
//
8
8
9
9
#import " ApplicationController.h"
10
+ #import " PBGitRepository.h"
10
11
#import " PBGitRevisionCell.h"
11
12
#import " PBGitWindowController.h"
12
13
#import " PBRepositoryDocumentController.h"
13
14
#import " PBServicesController.h"
14
15
#import " PBGitXProtocol.h"
15
- #import " PBPrefsWindowController.h"
16
16
#import " PBNSURLPathUserDefaultsTransfomer.h"
17
17
#import " PBGitDefaults.h"
18
18
19
19
20
20
21
21
@implementation ApplicationController
22
22
23
- - (ApplicationController * )init {
23
+ - (id )init {
24
24
#ifdef DEBUG_BUILD
25
25
[NSApp activateIgnoringOtherApps: YES ];
26
26
#endif
@@ -59,55 +59,23 @@ - (void)registerServices
59
59
- (void )applicationDidFinishLaunching : (NSNotification *)notification
60
60
{
61
61
// Make sure Git's SSH password requests get forwarded to our little UI tool:
62
- setenv ( " SSH_ASKPASS" , [[[NSBundle mainBundle ] pathForResource: @" gitx_askpasswd" ofType: @" " ] UTF8String ], 1 );
62
+ setenv ( " SSH_ASKPASS" , [[[NSBundle mainBundle ] pathForResource: @" gitx_askpasswd" ofType: @" " ] UTF8String ], 1 );
63
63
setenv ( " DISPLAY" , " localhost:0" , 1 );
64
64
65
65
[self registerServices ];
66
66
67
- BOOL hasOpenedDocuments = NO ;
68
- NSArray *launchedDocuments = [[[PBRepositoryDocumentController sharedDocumentController ] documents ] copy ];
69
-
70
- // Only try to open a default document if there are no documents open already.
71
- // For example, the application might have been launched by double-clicking a .git repository,
72
- // or by dragging a folder to the app icon
73
- if ([launchedDocuments count ])
74
- hasOpenedDocuments = YES ;
75
-
76
- // Try to find the current directory, to open that as a repository
77
- if ([PBGitDefaults openCurDirOnLaunch ] && !hasOpenedDocuments) {
78
- NSString *curPath = [[[NSProcessInfo processInfo ] environment ] objectForKey: @" PWD" ];
79
- NSURL *url = nil ;
80
- if (curPath)
81
- url = [NSURL fileURLWithPath: curPath];
82
- // Try to open the found URL
83
- NSError *error = nil ;
84
- if (url && [[PBRepositoryDocumentController sharedDocumentController ] openDocumentWithContentsOfURL: url display: YES error: &error])
85
- hasOpenedDocuments = YES ;
86
- }
67
+ NSArray *launchedDocuments = [[PBRepositoryDocumentController sharedDocumentController ] documents ];
87
68
88
69
// to bring the launched documents to the front
89
70
for (PBGitRepository *document in launchedDocuments)
90
71
[document showWindows ];
91
-
92
- if (![[NSApplication sharedApplication ] isActive ])
93
- return ;
94
-
95
- // The current directory was not enabled or could not be opened (most likely it’s not a git repository).
96
- // show an open panel for the user to select a repository to view
97
- if ([PBGitDefaults showOpenPanelOnLaunch ] && !hasOpenedDocuments)
98
- [[PBRepositoryDocumentController sharedDocumentController ] openDocument: self ];
99
72
}
100
73
101
74
- (void )windowWillClose :sender
102
75
{
103
76
[firstResponder terminate: sender];
104
77
}
105
78
106
- - (IBAction )openPreferencesWindow : (id )sender
107
- {
108
- [[PBPrefsWindowController sharedPrefsWindowController ] showWindow: nil ];
109
- }
110
-
111
79
- (IBAction )showAboutPanel : (id )sender
112
80
{
113
81
NSString *gitversion = [[[NSBundle mainBundle ] infoDictionary ] objectForKey: @" CFBundleGitVersion" ];
@@ -122,144 +90,87 @@ - (IBAction)showAboutPanel:(id)sender
122
90
[NSApp orderFrontStandardAboutPanelWithOptions: dict];
123
91
}
124
92
125
- - (IBAction )installCliTool : (id )sender ;
126
- {
127
- BOOL success = NO ;
128
- NSString * installationPath = @" /usr/local/bin/" ;
129
- NSString * installationName = @" gitx" ;
130
- NSString * toolPath = [[NSBundle mainBundle ] pathForResource: @" gitx" ofType: @" " ];
131
- if (toolPath) {
132
- AuthorizationRef auth;
133
- if (AuthorizationCreate (NULL , kAuthorizationEmptyEnvironment , kAuthorizationFlagDefaults , &auth) == errAuthorizationSuccess) {
134
- char const * mkdir_arg[] = { " -p" , [installationPath UTF8String ], NULL };
135
- char const * mkdir = " /bin/mkdir" ;
136
- AuthorizationExecuteWithPrivileges (auth, mkdir, kAuthorizationFlagDefaults , (char **)mkdir_arg, NULL );
137
- char const * arguments[] = { " -f" , " -s" , [toolPath UTF8String ], [[installationPath stringByAppendingString: installationName] UTF8String ], NULL };
138
- char const * helperTool = " /bin/ln" ;
139
- if (AuthorizationExecuteWithPrivileges (auth, helperTool, kAuthorizationFlagDefaults , (char **)arguments, NULL ) == errAuthorizationSuccess) {
140
- int status;
141
- int pid = wait (&status);
142
- if (pid != -1 && WIFEXITED (status) && WEXITSTATUS (status) == 0 )
143
- success = true ;
144
- else
145
- errno = WEXITSTATUS (status);
146
- }
147
-
148
- AuthorizationFree (auth, kAuthorizationFlagDefaults );
149
- }
150
- }
151
-
152
- if (success) {
153
- [[NSAlert alertWithMessageText: @" Installation Complete"
154
- defaultButton: nil
155
- alternateButton: nil
156
- otherButton: nil
157
- informativeTextWithFormat: @" The gitx tool has been installed to %@ " , installationPath] runModal ];
158
- } else {
159
- [[NSAlert alertWithMessageText: @" Installation Failed"
160
- defaultButton: nil
161
- alternateButton: nil
162
- otherButton: nil
163
- informativeTextWithFormat: @" Installation to %@ failed" , installationPath] runModal ];
164
- }
165
- }
166
-
167
- - (NSString *)applicationSupportFolder {
168
-
169
- NSArray *paths = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory, NSUserDomainMask, YES );
170
- NSString *basePath = ([paths count ] > 0 ) ? [paths objectAtIndex: 0 ] : NSTemporaryDirectory ();
171
- return [basePath stringByAppendingPathComponent: @" GitTest" ];
172
- }
173
-
174
- - (NSManagedObjectModel *)managedObjectModel {
175
- return managedObjectModel ?: (managedObjectModel = [NSManagedObjectModel mergedModelFromBundles: nil ]);
176
- }
177
-
178
- - (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
179
- if (!persistentStoreCoordinator) {
180
- NSFileManager *fileManager;
181
- NSString *applicationSupportFolder = nil ;
182
- NSURL *url;
183
- NSError *error;
184
-
185
- fileManager = [NSFileManager defaultManager ];
186
- applicationSupportFolder = [self applicationSupportFolder ];
187
- if ( ![fileManager fileExistsAtPath: applicationSupportFolder isDirectory: NULL ] ) {
188
- [fileManager createDirectoryAtPath: applicationSupportFolder withIntermediateDirectories: YES attributes: nil error: nil ];
189
- }
190
-
191
- url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @" GitTest.xml" ]];
192
- persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc ] initWithManagedObjectModel: [self managedObjectModel ]];
193
- if (![persistentStoreCoordinator addPersistentStoreWithType: NSXMLStoreType configuration: nil URL: url options: nil error: &error]){
194
- [[NSApplication sharedApplication ] presentError: error];
195
- }
196
- }
197
-
198
- return persistentStoreCoordinator;
199
- }
200
-
201
- - (NSManagedObjectContext *) managedObjectContext {
202
- if (!managedObjectContext) {
203
- managedObjectContext = [NSManagedObjectContext new ];
204
- managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator ;
93
+ - (BOOL )needsRoot {
94
+ NSFileManager *fm = [NSFileManager defaultManager ];
95
+
96
+ if ([fm fileExistsAtPath: @" /usr/local/bin/gitx" ] && ![fm isWritableFileAtPath: @" /usr/local/bin/gitx" ])
97
+ return YES ;
98
+
99
+ if ([fm isWritableFileAtPath: @" /usr/local/bin" ]) {
100
+ BOOL isdir;
101
+ if (![fm fileExistsAtPath: @" /usr/local/bin" isDirectory: &isdir] && !isdir)
102
+ @throw @" /usr/local/bin is not a directory." ;
103
+ return NO ;
205
104
}
206
- return managedObjectContext;
207
- }
208
-
209
- - (NSUndoManager *)windowWillReturnUndoManager : (NSWindow *)window {
210
- return self.managedObjectContext .undoManager ;
211
- }
212
-
213
- - (IBAction ) saveAction : (id )sender {
214
- id error = nil ;
215
- if (![[self managedObjectContext ] save: &error]) {
216
- [NSApp presentError: error];
105
+ if ([fm isWritableFileAtPath: @" /usr/local" ]) {
106
+ BOOL isdir;
107
+ if (![fm fileExistsAtPath: @" /usr/local" isDirectory: &isdir] && !isdir)
108
+ @throw @" /usr/local is not a directory." ;
109
+ return NO ;
217
110
}
111
+
112
+ return YES ;
218
113
}
219
114
220
- - (NSApplicationTerminateReply ) applicationShouldTerminate : ( NSApplication * )sender {
221
- NSError *error ;
222
- int reply = NSTerminateNow ;
115
+ - (IBAction ) installCliTool : ( id )sender {
116
+ id from = [[ NSBundle mainBundle ] pathForResource: @" gitx " ofType: @" " ] ;
117
+ id to = @" /usr/local/bin/gitx " ;
223
118
224
- if (managedObjectContext != nil ) {
225
- if ([managedObjectContext commitEditing ]) {
226
- if ([managedObjectContext hasChanges ] && ![managedObjectContext save: &error]) {
227
-
228
- // This error handling simply presents error information in a panel with an
229
- // "Ok" button, which does not include any attempt at error recovery (meaning,
230
- // attempting to fix the error.) As a result, this implementation will
231
- // present the information to the user and then follow up with a panel asking
232
- // if the user wishes to "Quit Anyway", without saving the changes.
233
-
234
- // Typically, this process should be altered to include application-specific
235
- // recovery steps.
236
-
237
- BOOL errorResult = [[NSApplication sharedApplication ] presentError: error];
238
-
239
- if (errorResult == YES ) {
240
- reply = NSTerminateCancel;
241
- }
242
-
243
- else {
244
-
245
- int alertReturn = NSRunAlertPanel (nil , @" Could not save changes while quitting. Quit anyway?" , @" Quit anyway" , @" Cancel" , nil );
246
- if (alertReturn == NSAlertAlternateReturn ) {
247
- reply = NSTerminateCancel;
248
- }
249
- }
119
+ @try {
120
+ if (self.needsRoot ) {
121
+ AuthorizationRef auth;
122
+ if (AuthorizationCreate (NULL , kAuthorizationEmptyEnvironment , kAuthorizationFlagDefaults , &auth) == errAuthorizationSuccess)
123
+ {
124
+ char const * mkdir_arg[] = { " -p" , [[to stringByDeletingLastPathComponent ] UTF8String ], NULL };
125
+ AuthorizationExecuteWithPrivileges (auth, " /bin/mkdir" , kAuthorizationFlagDefaults , (char **)mkdir_arg, NULL );
126
+
127
+ char const * arguments[] = { " -f" , " -s" , [from UTF8String ], [to UTF8String ], NULL };
128
+ if (AuthorizationExecuteWithPrivileges (auth, " /bin/ln" , kAuthorizationFlagDefaults , (char **)arguments, NULL ) == errAuthorizationSuccess) {
129
+ int status;
130
+ int pid = wait (&status);
131
+ if (!(pid != -1 && WIFEXITED (status) && WEXITSTATUS (status) == 0 ))
132
+ @throw @" Could not create gitx symlink :(" ;
133
+ } else
134
+ @throw @" You canceled authorisation." ;
135
+
136
+ AuthorizationFree (auth, kAuthorizationFlagDefaults );
250
137
}
251
- }
252
-
253
- else {
254
- reply = NSTerminateCancel;
138
+ } else {
139
+ // FIXME this is a hard link, root-route is symlink, should be same, hard links are better IMO
140
+
141
+ [[NSFileManager defaultManager ] removeItemAtPath: to error: nil ];
142
+
143
+ id error = nil ;
144
+ [[NSFileManager defaultManager ] linkItemAtPath: from toPath: to error: &error];
145
+ if (error)
146
+ @throw error;
255
147
}
148
+
149
+ [[NSAlert alertWithMessageText: @" Command Line Tool Installed Successfully"
150
+ defaultButton: nil
151
+ alternateButton: nil
152
+ otherButton: nil
153
+ informativeTextWithFormat: @" You now have: %@ ." , to] runModal ];
154
+ }
155
+ @catch (id errmsg) {
156
+ if ([errmsg isKindOfClass: [NSError class ]])
157
+ errmsg = [errmsg localizedFailureReason ];
158
+
159
+ [[NSAlert alertWithMessageText: @" Could Not Install Command Line Tool"
160
+ defaultButton: nil
161
+ alternateButton: nil
162
+ otherButton: nil
163
+ informativeTextWithFormat: @" %@ " , errmsg] runModal ];
256
164
}
257
-
258
- return reply;
259
165
}
260
166
261
- - (void )applicationWillTerminate : (NSNotification *)aNotification
262
- {
167
+ - (NSString *)applicationSupportFolder {
168
+ NSArray *paths = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory, NSUserDomainMask, YES );
169
+ NSString *basePath = ([paths count ] > 0 ) ? [paths objectAtIndex: 0 ] : NSTemporaryDirectory ();
170
+ return [basePath stringByAppendingPathComponent: @" GitTest" ];
171
+ }
172
+
173
+ - (void )applicationWillTerminate : (NSNotification *)aNotification {
263
174
[PBGitDefaults removePreviousDocumentPaths ];
264
175
265
176
if ([PBGitDefaults openPreviousDocumentsOnLaunch ]) {
@@ -274,29 +185,12 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification
274
185
}
275
186
}
276
187
277
- /* *
278
- Implementation of dealloc, to release the retained variables.
279
- */
280
-
281
- - (void ) dealloc {
282
-
283
- managedObjectContext = nil ;
284
- persistentStoreCoordinator = nil ;
285
- managedObjectModel = nil ;
286
- }
287
-
288
- #pragma mark Help menu
289
-
290
- - (IBAction )showHelp : (id )sender
291
- {
188
+ - (IBAction )showHelp : (id )sender {
292
189
[[NSWorkspace sharedWorkspace ] openURL: [NSURL URLWithString: @" http://gitx.frim.nl/user_manual.html" ]];
293
190
}
294
191
295
- - (IBAction )reportAProblem : (id )sender
296
- {
297
- [[NSWorkspace sharedWorkspace ] openURL: [NSURL URLWithString: @" http://gitx.lighthouseapp.com/tickets" ]];
192
+ - (IBAction )reportAProblem : (id )sender {
193
+ [[
NSWorkspace sharedWorkspace ]
openURL: [
NSURL URLWithString: @" mailto:[email protected] " ]];
298
194
}
299
195
300
-
301
-
302
196
@end
0 commit comments