smsvn -> ssc-hg glue: rearrange directory structure
This commit is contained in:
@@ -0,0 +1,364 @@
|
||||
#import "Upgrader.h"
|
||||
#import "CopyFiles.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@implementation Upgrader
|
||||
|
||||
// Generate English strings using: genstring -o en.lproj Upgrader.m
|
||||
|
||||
static NSString *CHOOSE_FILE;
|
||||
static NSString *PATCH_FILE;
|
||||
static NSString *PATCH_COMPLETE;
|
||||
static NSString *QUIT;
|
||||
static NSString *ERROR;
|
||||
static NSString *ERROR_MESSAGE;
|
||||
static NSString *PATCH_FILES_MISSING;
|
||||
static NSString *PATCHER_CORRUPTED;
|
||||
static NSString *CORRUPT_TITLE;
|
||||
static NSString *PATCHING;
|
||||
static NSString *SEARCHING;
|
||||
static NSString *SELECTION;
|
||||
static NSString *WINDOW_TITLE;
|
||||
|
||||
static NSOpenPanel *panel = nil;
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"Identification" ofType:@"txt"];
|
||||
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||
NSString *stringData = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
|
||||
|
||||
CHOOSE_FILE = NSLocalizedString( @"Choose file to patch.", nil );
|
||||
PATCH_FILE = NSLocalizedString( @"Patch file.", nil );
|
||||
PATCH_COMPLETE = NSLocalizedString( @"Patch complete.", nil );
|
||||
QUIT = NSLocalizedString( @"Quit", nil );
|
||||
ERROR = NSLocalizedString( @"Error", nil );
|
||||
ERROR_MESSAGE = NSLocalizedString( @"Patching failed:\n%@", nil );
|
||||
PATCH_FILES_MISSING = NSLocalizedString( @"Patch files missing.", nil );
|
||||
PATCHER_CORRUPTED = NSLocalizedString( @"This patcher has become corrupted.", nil );
|
||||
CORRUPT_TITLE = NSLocalizedString( @"Corrupt Patcher", nil );
|
||||
PATCHING = NSLocalizedString( @"Patching", nil );
|
||||
SEARCHING = NSLocalizedString( @"Searching for %@...", nil );
|
||||
SELECTION = NSLocalizedString( @"You have chosen to patch \"%@\" in the folder:\n%@", nil );
|
||||
WINDOW_TITLE = NSLocalizedString( @"StepMania Patcher", nil );
|
||||
|
||||
if( !data )
|
||||
{
|
||||
NSRunCriticalAlertPanel( CORRUPT_TITLE, PATCHER_CORRUPTED, @"OK", nil, nil );
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
m_sName = nil;
|
||||
m_sAppID = nil;
|
||||
m_vVersions = nil;
|
||||
|
||||
NSArray *lines = [stringData componentsSeparatedByString:@"\n"];
|
||||
NSEnumerator *iter = [lines objectEnumerator];
|
||||
NSString *line;
|
||||
NSMutableArray *versions = [NSMutableArray array];
|
||||
|
||||
while( (line = [iter nextObject]) )
|
||||
{
|
||||
line = [line stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if( [line length] == 0 || [line characterAtIndex:0] == '#' )
|
||||
continue;
|
||||
if( m_sName == nil )
|
||||
{
|
||||
m_sName = [line retain];
|
||||
}
|
||||
else if( m_sAppID == nil )
|
||||
{
|
||||
m_sAppID = [line retain];
|
||||
}
|
||||
else if( [line isEqualToString:@"-ALL-"] )
|
||||
{
|
||||
versions = nil;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
[versions addObject:line];
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_sName || !m_sAppID )
|
||||
{
|
||||
NSRunCriticalAlertPanel( CORRUPT_TITLE, PATCHER_CORRUPTED, @"OK", nil, nil );
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
|
||||
if( versions && [versions count] )
|
||||
m_vVersions = [versions retain];
|
||||
|
||||
// Set strings.
|
||||
[m_StatusText setStringValue:[NSString stringWithFormat:SEARCHING, m_sName]];
|
||||
[m_SelectionText setStringValue:@""];
|
||||
[m_PatchingText setStringValue:PATCHING];
|
||||
|
||||
[m_Searching setUsesThreadedAnimation:YES];
|
||||
[m_ProgressBar setUsesThreadedAnimation:YES];
|
||||
[m_Window setTitle:WINDOW_TITLE];
|
||||
|
||||
[NSThread detachNewThreadSelector:@selector(findApp:) toTarget:self withObject:nil];
|
||||
[m_Choose setEnabled:YES];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[m_sName release];
|
||||
[m_sAppID release];
|
||||
[m_vVersions release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBAction) chooseFile:(id)sender
|
||||
{
|
||||
if( !panel )
|
||||
{
|
||||
panel = [[NSOpenPanel openPanel] retain];
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setDelegate:self];
|
||||
[panel setDirectory:@"/Applications"];
|
||||
}
|
||||
|
||||
if( [panel runModal] == NSFileHandlingPanelOKButton )
|
||||
{
|
||||
NSString *dir, *app;
|
||||
|
||||
[m_StatusText setStringValue:PATCH_FILE];
|
||||
[m_Okay setEnabled:YES];
|
||||
[m_sPath release];
|
||||
m_sPath = [[panel filename] retain];
|
||||
dir = [m_sPath stringByDeletingLastPathComponent];
|
||||
app = [[m_sPath lastPathComponent] stringByDeletingPathExtension];
|
||||
[m_SelectionText setStringValue:[NSString stringWithFormat:SELECTION, app, dir]];
|
||||
[m_Okay setTitle:@"OK"];
|
||||
[m_Okay setAction:@selector(upgrade:)];
|
||||
[m_Okay setTarget:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction) upgrade:(id)sender
|
||||
{
|
||||
[NSApp beginSheet:m_Panel
|
||||
modalForWindow:[sender window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(sheetEnded:returnCode:contextInfo:)
|
||||
contextInfo:NULL];
|
||||
[NSThread detachNewThreadSelector:@selector(upgradeFile:) toTarget:self withObject:m_sPath];
|
||||
}
|
||||
|
||||
- (void) findApp:(id)obj
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[m_Searching startAnimation:self];
|
||||
|
||||
// Find ITG
|
||||
CFStringRef key = CFSTR( "ApplicationBundlePath" );
|
||||
CFPropertyListRef list = CFPreferencesCopyAppValue( key, (CFStringRef)m_sAppID );
|
||||
|
||||
NSString *sPath = nil;
|
||||
|
||||
if( list && CFGetTypeID(list) != CFDictionaryGetTypeID() )
|
||||
{
|
||||
CFRelease( list );
|
||||
list = NULL;
|
||||
}
|
||||
if( list )
|
||||
{
|
||||
CFTypeRef value;
|
||||
CFDictionaryRef dict = (CFDictionaryRef)list;
|
||||
|
||||
if( m_vVersions )
|
||||
{
|
||||
NSEnumerator *iter = [m_vVersions objectEnumerator];
|
||||
id version;
|
||||
|
||||
while( (version = [iter nextObject]) )
|
||||
{
|
||||
if( CFDictionaryGetValueIfPresent(dict, (CFStringRef)version, &value) &&
|
||||
CFGetTypeID(value) == CFStringGetTypeID() &&
|
||||
[self checkPath:(NSString *)value] )
|
||||
{
|
||||
sPath = (NSString *)CFRetain( value );
|
||||
[sPath autorelease];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDictionary *dict = (NSDictionary *)list;
|
||||
NSEnumerator *iter = [dict objectEnumerator];
|
||||
id path;
|
||||
|
||||
while( (path = [iter nextObject]) )
|
||||
{
|
||||
if( ![path isKindOfClass:[NSString class]] || ![self checkPath:path] )
|
||||
continue;
|
||||
sPath = [[path retain] autorelease];
|
||||
break;
|
||||
}
|
||||
}
|
||||
CFRelease( list );
|
||||
}
|
||||
if( !sPath )
|
||||
{
|
||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||
|
||||
[ws findApplications];
|
||||
sPath = [ws fullPathForApplication:m_sName];
|
||||
|
||||
if( ![self checkPath:sPath] )
|
||||
sPath = nil;
|
||||
}
|
||||
[self performSelectorOnMainThread:@selector(foundApp:) withObject:sPath waitUntilDone:YES];
|
||||
[m_Searching stopAnimation:self];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
- (void) foundApp:(id)obj
|
||||
{
|
||||
NSString *path = (NSString *)obj;
|
||||
|
||||
if( path ) // found
|
||||
{
|
||||
NSString *dir = [path stringByDeletingLastPathComponent];
|
||||
NSString *app = [[path lastPathComponent] stringByDeletingPathExtension];
|
||||
|
||||
[m_sPath release];
|
||||
m_sPath = [path retain];
|
||||
[m_Okay setEnabled:YES];
|
||||
[m_StatusText setStringValue:PATCH_FILE];
|
||||
[m_SelectionText setStringValue:[NSString stringWithFormat:SELECTION, app, dir]];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sPath = @"";
|
||||
[m_StatusText setStringValue:CHOOSE_FILE];
|
||||
}
|
||||
[m_Choose setEnabled:YES];
|
||||
[m_Choose setNeedsDisplay:YES];
|
||||
[m_Okay setNeedsDisplay:YES];
|
||||
[m_StatusText setNeedsDisplay:YES];
|
||||
[m_SelectionText setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void) upgradeFile:(id)path
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *patch = [bundle pathForResource:@"Contents" ofType:@"" inDirectory:@"Patch"];
|
||||
NSArray *parentFiles = [bundle pathsForResourcesOfType:@"" inDirectory:@"Patch/ParentContents"];
|
||||
|
||||
if( patch && parentFiles)
|
||||
{
|
||||
[m_ProgressBar startAnimation:self];
|
||||
|
||||
if( NeedsPrivs(path) )
|
||||
m_sError = CopyWithPrivs( patch, path );
|
||||
else
|
||||
m_sError = Copy( patch, path );
|
||||
|
||||
path = [path stringByDeletingLastPathComponent];
|
||||
NSEnumerator *enumerator = [parentFiles objectEnumerator];
|
||||
while( !m_sError && (patch = [enumerator nextObject]) )
|
||||
{
|
||||
if( NeedsPrivs(path) )
|
||||
m_sError = CopyWithPrivs( patch, path );
|
||||
else
|
||||
m_sError = Copy( patch, path );
|
||||
}
|
||||
|
||||
[m_ProgressBar stopAnimation:self];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sError = PATCH_FILES_MISSING;
|
||||
}
|
||||
[NSApp performSelectorOnMainThread:@selector(endSheet:) withObject:m_Panel waitUntilDone:YES];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
- (void) sheetEnded:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[m_Panel orderOut:self];
|
||||
if( m_sError )
|
||||
{
|
||||
NSRunCriticalAlertPanel( ERROR, ERROR_MESSAGE, @"OK", nil, nil, m_sError );
|
||||
return;
|
||||
}
|
||||
[m_StatusText setStringValue:PATCH_COMPLETE];
|
||||
[m_Okay setTitle:QUIT];
|
||||
[m_Okay setAction:@selector(terminate:)];
|
||||
[m_Okay setTarget:NSApp];
|
||||
}
|
||||
|
||||
- (BOOL) panel:(id)sender isValidFilename:(NSString *)filename
|
||||
{
|
||||
return [filename hasSuffix:@".app"] && [self checkPath:filename];
|
||||
}
|
||||
|
||||
- (BOOL) panel:(id)sender shouldShowFilename:(NSString *)filename
|
||||
{
|
||||
if( [filename hasSuffix:@".app"] )
|
||||
return [self checkPath:filename];
|
||||
|
||||
struct stat sb;
|
||||
|
||||
if( stat([filename UTF8String], &sb) )
|
||||
return NO;
|
||||
return (sb.st_mode & S_IFDIR) == S_IFDIR;
|
||||
}
|
||||
|
||||
- (BOOL) checkPath:(NSString *)path
|
||||
{
|
||||
NSBundle *b = [NSBundle bundleWithPath:path];
|
||||
|
||||
if( !b )
|
||||
return NO;
|
||||
if( ![[b objectForInfoDictionaryKey:@"CFBundleIdentifier"] isEqualToString:m_sAppID] )
|
||||
return NO;
|
||||
if( m_vVersions == nil )
|
||||
return YES;
|
||||
|
||||
NSString *bundleVersion = [b objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
NSEnumerator *iter = [m_vVersions objectEnumerator];
|
||||
NSString *version;
|
||||
|
||||
while( (version = [iter nextObject]) )
|
||||
if( [bundleVersion isEqualToString:version] )
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
* (c) 2006 Steve Checkoway
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user