34#if OO_OXP_VERIFIER_ENABLED
39#pragma push_macro("interface")
41#define interface struct
47#pragma pop_macro("interface")
65@interface OOOXPVerifier (OOPrivate)
67- (id)initWithPath:(NSString *)path;
76- (BOOL)setUpDependencies:(NSSet *)dependencies
79- (void)setUpDependents:(NSSet *)dependents
96+ (BOOL)runVerificationIfRequested
98 NSArray *arguments =
nil;
99 NSEnumerator *argEnum =
nil;
101 NSString *foundPath =
nil;
102 BOOL exists, isDirectory;
104 NSAutoreleasePool *pool =
nil;
106 pool = [[NSAutoreleasePool alloc] init];
108 arguments = [[NSProcessInfo processInfo] arguments];
111 for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
113 if ([arg isEqual:
@"-verify-oxp"] || [arg isEqual:@"--verify-oxp"])
115 foundPath = [argEnum nextObject];
116 if (foundPath ==
nil)
118 OOLog(
@"verifyOXP.noPath",
@"***** ERROR: %@ passed without path argument; nothing to verify.", arg);
122 foundPath = [foundPath stringByExpandingTildeInPath];
127 if (foundPath ==
nil)
134 exists = [[NSFileManager defaultManager] fileExistsAtPath:foundPath isDirectory:&isDirectory];
137 OOLog(
@"verifyOXP.badPath",
@"***** ERROR: no OXP exists at path \"%@\
"; nothing to verify.", foundPath);
139 else if (!isDirectory)
141 OOLog(
@"verifyOXP.badPath",
@"***** ERROR: \"%@\
" is a file, not an OXP directory; nothing to verify.", foundPath);
147 pool = [[NSAutoreleasePool alloc] init];
160 [_verifierPList release];
162 [_displayName release];
163 [_stagesByName release];
164 [_waitingStages release];
172 NSString *name =
nil;
176 if (stage ==
nil)
return;
180 OOLog(
@"verifyOXP.registration.failed",
@"Attempt to register class %@ as a verifier stage, but it is not a subclass of OOOXPVerifierStage; ignoring.", [stage
class]);
184 if (!_openForRegistration)
186 OOLog(
@"verifyOXP.registration.failed",
@"Attempt to register verifier stage %@ after registration closed, ignoring.", stage);
193 OOLog(
@"verifyOXP.registration.failed",
@"Attempt to register verifier stage %@ with nil name, ignoring.", stage);
198 existing = [_stagesByName objectForKey:name];
199 if (existing == stage)
return;
202 OOLog(
@"verifyOXP.registration.failed",
@"Attempt to register verifier stage %@ with same name as stage %@, ignoring.", stage, existing);
208 [_stagesByName setObject:stage forKey:name];
209 [_waitingStages addObject:stage];
215 return [[_basePath retain] autorelease];
219- (NSString *)oxpDisplayName
221 return [[_displayName retain] autorelease];
225- (id)stageWithName:(NSString *)name
227 if (name ==
nil)
return nil;
229 return [_stagesByName objectForKey:name];
233- (id)configurationValueForKey:(NSString *)key
235 return [_verifierPList objectForKey:key];
239- (NSArray *)configurationArrayForKey:(NSString *)key
241 return [_verifierPList oo_arrayForKey:key];
245- (NSDictionary *)configurationDictionaryForKey:(NSString *)key
247 return [_verifierPList oo_dictionaryForKey:key];
251- (NSString *)configurationStringForKey:(NSString *)key
253 return [_verifierPList oo_stringForKey:key];
257- (NSSet *)configurationSetForKey:(NSString *)key
259 NSArray *array = [_verifierPList oo_arrayForKey:key];
260 return array !=
nil ? [NSSet setWithArray:array] :
nil;
266@implementation OOOXPVerifier (OOPrivate)
268- (id)initWithPath:(NSString *)path
274 NSString *verifierPListPath = [[[
ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"verifyOXP.plist"];
275 _verifierPList = [[NSDictionary dictionaryWithContentsOfFile:verifierPListPath] retain];
277 _basePath = [path copy];
278 _displayName = [[NSFileManager defaultManager] displayNameAtPath:_basePath];
279 if (_displayName ==
nil) _displayName = [_basePath lastPathComponent];
280 [_displayName retain];
282 _stagesByName = [[NSMutableDictionary alloc] init];
283 _waitingStages = [[NSMutableSet alloc] init];
285 if (_verifierPList ==
nil ||
288 OOLog(
@"verifyOXP.setup.failed",
@"%@",
@"***** ERROR: failed to set up OXP verifier.");
293 _openForRegistration = YES;
303 [
self setUpLogOverrides];
317 OOLog(
@"verifyOXP.start",
@"Running OXP verifier for %@", _basePath);
319 [
self registerBaseStages];
320 [
self buildDependencyGraph];
324 OOLog(
@"verifyOXP.done",
@"%@",
@"OXP verification complete.");
332 NSDictionary *overrides =
nil;
333 NSString *messageClass =
nil;
338 overrides = [_verifierPList oo_dictionaryForKey:@"logControlOverride"];
348 verbose = [[NSUserDefaults standardUserDefaults] objectForKey:@"oxp-verifier-verbose-logging"];
355 NSAutoreleasePool *pool =
nil;
357 NSSet *excludeStages =
nil;
358 NSString *stageName =
nil;
359 Class stageClass = Nil;
362 pool = [[NSAutoreleasePool alloc] init];
365 stages = [
self configurationSetForKey:@"stages"];
366 excludeStages = [
self configurationSetForKey:@"excludeStages"];
367 if ([excludeStages
count] != 0)
369 stages = [[stages mutableCopy] autorelease];
370 [(NSMutableSet *)stages minusSet:excludeStages];
372 foreach (stageName, stages)
374 if ([stageName isKindOfClass:[NSString class]])
376 stageClass = NSClassFromString(stageName);
377 if (stageClass == Nil)
379 OOLog(
@"verifyOXP.registration.failed",
@"Attempt to register unknown class %@ as a verifier stage, ignoring.", stageName);
382 stage = [[stageClass alloc] init];
383 [
self registerStage:stage];
394 NSAutoreleasePool *pool =
nil;
395 NSArray *stageKeys =
nil;
396 NSString *stageKey =
nil;
398 NSString *name =
nil;
399 NSMutableDictionary *dependenciesByStage =
nil,
400 *dependentsByStage =
nil;
401 NSSet *dependencies =
nil,
405 pool = [[NSAutoreleasePool alloc] init];
411 dependenciesByStage = [NSMutableDictionary dictionary];
412 dependentsByStage = [NSMutableDictionary dictionary];
420 stage = [_waitingStages anyObject];
421 if (stage ==
nil)
break;
422 [_waitingStages removeObject:stage];
424 key = [NSValue valueWithNonretainedObject:stage];
427 if (dependencies !=
nil)
429 [dependenciesByStage setObject:dependencies
434 if (dependents !=
nil)
436 [dependentsByStage setObject:dependents
440 [_waitingStages release];
441 _waitingStages =
nil;
442 _openForRegistration = NO;
445 stageKeys = [_stagesByName allKeys];
447 foreach (stageKey, stageKeys)
449 stage = [_stagesByName objectForKey:stageKey];
450 if (stage ==
nil)
continue;
454 if (![stageKey isEqualToString:name])
456 OOLog(
@"verifyOXP.buildDependencyGraph.badName",
@"***** Stage name appears to have changed from \"%@\
" to \"%@\" for verifier stage %@, removing.", stageKey, name, stage);
457 [_stagesByName removeObjectForKey:stageKey];
462 key = [NSValue valueWithNonretainedObject:stage];
463 dependencies = [dependenciesByStage objectForKey:key];
465 if (dependencies !=
nil && ![
self setUpDependencies:dependencies forStage:stage])
467 [_stagesByName removeObjectForKey:stageKey];
475 stageKeys = [_stagesByName allKeys];
477 foreach (stageKey, stageKeys)
479 stage = [_stagesByName objectForKey:stageKey];
480 if (stage ==
nil)
continue;
483 key = [NSValue valueWithNonretainedObject:stage];
484 dependents = [dependentsByStage objectForKey:key];
486 if (dependents !=
nil)
488 [
self setUpDependents:dependents forStage:stage];
492 _waitingStages = [[NSMutableSet alloc] initWithArray:[_stagesByName allValues]];
493 [_waitingStages makeObjectsPerformSelector:@selector(dependencyRegistrationComplete)];
495 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"oxp-verifier-dump-debug-graphviz"])
497 [
self dumpDebugGraphviz];
506 NSAutoreleasePool *pool =
nil;
509 NSString *stageName =
nil;
514 pool = [[NSAutoreleasePool alloc] init];
518 foreach (candidateStage, _waitingStages)
520 if ([candidateStage canRun])
522 stageToRun = candidateStage;
526 if (stageToRun ==
nil)
537 stageName = [stageToRun name];
538 if ([stageToRun shouldRun])
541 OOLog(
@"verifyOXP.runStage",
@"%@", stageName);
543 [stageToRun performRun];
547 OOLog(
@"verifyOXP.verbose.skipStage",
@"- Skipping stage: %@ (nothing to do).", stageName);
548 [stageToRun noteSkipped];
551 @catch (NSException *exception)
553 if (stageName ==
nil) stageName = [[stageToRun class] description];
554 OOLog(
@"verifyOXP.exception",
@"***** Exception occurred when running OXP verifier stage \"%@\
": %@: %@", stageName, [exception name], [exception reason]);
558 [_waitingStages removeObject:stageToRun];
562 pool = [[NSAutoreleasePool alloc] init];
564 if ([_waitingStages
count] != 0)
566 OOLog(
@"verifyOXP.incomplete",
@"%@",
@"Some verifier stages could not be run:");
568 foreach (candidateStage, _waitingStages)
570 OOLog(
@"verifyOXP.incomplete.item",
@"%@", candidateStage);
574 [_waitingStages release];
575 _waitingStages =
nil;
581- (BOOL)setUpDependencies:(NSSet *)dependencies
584 NSString *depName =
nil;
588 foreach (depName, dependencies)
590 depStage = [_stagesByName objectForKey:depName];
593 OOLog(
@"verifyOXP.buildDependencyGraph.unresolved",
@"Verifier stage %@ has unresolved dependency \"%@\
", skipping.", stage, depName);
597 if ([depStage isDependentOf:stage])
599 OOLog(
@"verifyOXP.buildDependencyGraph.circularReference",
@"Verifier stages %@ and %@ have a dependency loop, skipping.", stage, depStage);
600 [_stagesByName removeObjectForKey:depName];
611- (void)setUpDependents:(NSSet *)dependents
614 NSString *depName =
nil;
618 foreach (depName, dependents)
620 depStage = [_stagesByName objectForKey:depName];
623 OOLog(
@"verifyOXP.buildDependencyGraph.unresolved",
@"Verifier stage %@ has unresolved dependent \"%@\
".", stage, depName);
627 if ([stage isDependentOf:depStage])
629 OOLog(
@"verifyOXP.buildDependencyGraph.circularReference",
@"Verifier stage %@ lists %@ as both dependent and dependency (possibly indirectly); will execute %@ after %@.", stage, depStage, stage, depStage);
640 NSMutableString *graphViz =
nil;
641 NSDictionary *graphVizTemplate =
nil;
642 NSString *
template =
nil,
643 *startTemplate =
nil,
649 graphVizTemplate = [
self configurationDictionaryForKey:@"debugGraphvizTempate"];
650 graphViz = [NSMutableString stringWithFormat:[graphVizTemplate oo_stringForKey:@"preamble"], [NSDate date]];
655 template = [graphVizTemplate oo_stringForKey:@"node"];
656 foreach (stage, [_stagesByName allValues])
658 [graphViz appendFormat:template, stage, [stage class], [stage
name]];
661 [graphViz appendString:[graphVizTemplate oo_stringForKey:@"forwardPreamble"]];
665 template = [graphVizTemplate oo_stringForKey:@"forwardArc"];
666 startTemplate = [graphVizTemplate oo_stringForKey:@"startArc"];
667 foreach (stage, [_stagesByName allValues])
670 if ([deps
count] != 0)
674 [graphViz appendFormat:template, dep, stage];
679 [graphViz appendFormat:startTemplate, stage];
683 [graphViz appendString:[graphVizTemplate oo_stringForKey:@"backwardPreamble"]];
687 template = [graphVizTemplate oo_stringForKey:@"backwardArc"];
688 endTemplate = [graphVizTemplate oo_stringForKey:@"endArc"];
689 foreach (stage, [_stagesByName allValues])
692 if ([deps
count] != 0)
696 [graphViz appendFormat:template, dep, stage];
701 [graphViz appendFormat:endTemplate, stage];
705 [graphViz appendString:[graphVizTemplate oo_stringForKey:@"postamble"]];
720 name = [name stringByAppendingPathExtension:@"log"];
721 OOLog(
@"verifyOXP.switchingLog",
@"Switching log files -- logging to \"%@\
".", name);
740 if ([[NSUserDefaults standardUserDefaults] oo_boolForKey:
@"oxp-verifier-open-log" defaultValue:YES])
743 [[NSWorkspace sharedWorkspace] openFile:OOLogHandlerGetLogPath()];
#define foreachkey(VAR, DICT)
void OOSetStandardsForOXPVerifierMode(void)
NSString * OOLogHandlerGetLogPath(void)
void OOLogOutputHandlerChangeLogFile(NSString *newLogName)
void OOLogPushIndent(void)
void OOLogPopIndent(void)
#define OOLog(class, format,...)
void OOLogSetDisplayMessagesInClass(NSString *inClass, BOOL inFlag)
void OOLogSetShowMessageClassTemporary(BOOL flag)
static void SwitchLogFile(NSString *name)
static void NoteVerificationStage(NSString *displayName, NSString *stage)
static void OpenLogFile(NSString *name)
void registerBaseStages()
void buildDependencyGraph()
GameController * sharedController()
void logProgress:(NSString *message)
void setAllowCacheWrites:(BOOL flag)
OOCacheManager * sharedCache()
NSSet * resolvedDependents()
void setVerifier:(OOOXPVerifier *verifier)
void registerDependency:(OOOXPVerifierStage *dependency)
NSSet * resolvedDependencies()
BOOL writeDiagnosticString:toFileNamed:(NSString *string,[toFileNamed] NSString *name)
void setUseAddOns:(NSString *useAddOns)