'From Squeak3.3alpha of 28 January 2002 [latest update: #4653] on 29 January 2002 at 11:39:51 am'! "Change Set: deltaImprovements-hg Date: 27 January 2002 Author: Henrik Gedenryd Tests for DeltaModules and storage, fixes that make them pass, and more." "some classes weren't exported due to an intermediate state" Module root deepSubmodulesDo: [:m | m definedNames keysAndValuesDo: [:k :v | (m exportedNames at: k ifAbsent: [nil]) ifNil: [ (m ~~ Module smalltalk and: [v isKindOf: Class]) ifTrue: [m exportName: k]]]].! Association subclass: #DeltaAssociation instanceVariableNames: 'previousValue deactivatedValue ' classVariableNames: '' module: #(Squeak Language Modules)! Class subclass: #DeltaClass instanceVariableNames: 'deltaForMetaOrNonMeta changesClassFormat ' classVariableNames: '' module: #(Squeak Language Modules)! Module subclass: #DeltaModule instanceVariableNames: 'baseModule isActive baseModuleRef ' classVariableNames: '' module: #(Squeak Language Modules)! !DeltaModule commentStamp: '' prior: 0! The mojo of this class is that it unifies a number of different functionalities (once complete): - Each DeltaModule is relative one other module, its baseModule (a defined version of it), hence Delta. A DM should be able to define any to the baseModule. Unlike change sets, it should not record the changes, but define the final state, although it does this in a diff-format to avoid redundancy problems. Hence, it still provides an exact snapshot definition of a module, but in a relative (delta) format. It is meant to subsume change sets while being more rigorous and also module-aware. This is meant to avoid the problems with change sets without the unnecessary and non-Smalltalk-style baggage of a "declarative" model. - When loaded into the image, a DeltaModule can be activated (installed) or not. -- Ie. its changes wrt the base may be installed into the base module or not. -- It is perfectly reversible and can be de/activated any number of times and be easily unistalled. -- Activation is separated from code loading; this avoids inconsistent states during loading or in the case of an error. Thus, there should also be no need for hand-editing things to load correctly. - Installing a DeltaModule creates a new version (number) of the base module. -- It should be possible to tie a DM to a specific base module version. - Class extensions Deltas are meant to be used for holding class extensions (things like String>>asUrl or Object>>isDraggableMorph). - De/activate can be used a form of "layers" that can be switched on and off to handle package conflicts. No such layers are implemented however. - DeltaModules (and regular Modules) should subsume the PackageBrowser, as a package can be read into the image, edited, etc. without being active--the usual tools should handle it. - Because DMs are derived from regular Modules, they work within the module loading and dependency system, work with repositories, versions, and so on. In the long run, the design goal of DeltaModules and -classes should be to use a minimal amount of memory to represent differences w r t the base, while being virtually indistinguishable from a normal module/class, at least in terms of usability. (Ie. no special tools or restrictions.)! Object subclass: #ModuleInstaller instanceVariableNames: 'startModuleRef operation createdModules downloadedModules loadedModules activatedModules progressIndicator progressValue withRecovery definedModules ' classVariableNames: '' module: #(Squeak Language Modules Repositories)! ModuleReference subclass: #DeltaModuleReference instanceVariableNames: 'baseModule ' classVariableNames: '' module: #(Squeak Language Modules)! !DeltaModuleReference commentStamp: '' prior: 0! I handle the loading/definition of DeltaModules.! DeltaModuleTests subclass: #ModuleStorageTests instanceVariableNames: 'installerObject ' classVariableNames: '' module: #(Squeak Language Modules Tests)! ModuleStorageTests subclass: #RemoteModuleStorageTests instanceVariableNames: '' classVariableNames: '' module: #(Squeak Language Modules Tests)! !ClassDescription methodsFor: 'fileIn/Out' stamp: 'hg 1/29/2002 11:06'! definitionST80 "Answer a String that defines the receiver." | aStream path | aStream _ WriteStream on: (String new: 300). superclass == nil ifTrue: [aStream nextPutAll: 'nil'] ifFalse: [ path _ Preferences strongModules ifTrue: [(self module qualifiedPrefixForName: superclass name andValue: superclass), ' '] ifFalse: ['']. aStream nextPutAll: path, superclass name]. aStream nextPutAll: self kindOfSubclass; store: self name. aStream cr; tab; nextPutAll: 'instanceVariableNames: '; store: self instanceVariablesString. aStream cr; tab; nextPutAll: 'classVariableNames: '; store: self classVariablesString. Preferences modularClassDefinitions ifFalse: [ aStream cr; tab; nextPutAll: 'poolDictionaries: '; store: self sharedPoolsString. aStream cr; tab; nextPutAll: 'category: '; store: self module simulatedCategory asString] ifTrue: [ aStream cr; tab; nextPutAll: 'module: ', self module path literalPrintString]. ^ aStream contents! ! !Class methodsFor: 'initialize-release' stamp: 'hg 1/8/2002 11:45'! declare: varString "Declare class variables common to all instances. Answer whether recompilation is advisable." | newVars conflicts | newVars _ (Scanner new scanFieldNames: varString) collect: [:x | x asSymbol]. newVars do: [:var | var first isLowercase ifTrue: [self error: var, ' class variable name should be capitalized; proceed to include anyway.']]. conflicts _ false. classPool == nil ifFalse: [(classPool keys reject: [:x | newVars includes: x]) do: [:var | self removeClassVarName: var]]. (newVars reject: [:var | self classPool includesKey: var]) do: [:var | "adding" "check if new vars defined elsewhere" (self scopeHas: var ifTrue: [:ignored | ignored]) ifTrue: [self notify: var , ' is defined elsewhere. Selected proceed to define this class variable anyway, or Cancel, to avoid defining it.']]. newVars size > 0 ifTrue: [classPool _ self classPool. "in case it was nil" newVars do: [:var | classPool declare: var from: Undeclared]]. ^conflicts! ! !CompiledMethod methodsFor: 'printing' stamp: 'hg 1/8/2002 13:09'! who "Answer an Array of the class in which the receiver is defined and the selector to which it corresponds." | sel | Module root allBehaviorsDo: [:class | (sel _ class methodDict keyAtIdentityValue: self ifAbsent: [nil]) ifNotNil: [^Array with: class with: sel]]. ^ Array with: #unknown with: #unknown ! ! !DeltaAssociation methodsFor: 'accessing' stamp: 'hg 1/12/2002 19:31'! deactivatedValue ^deactivatedValue! ! !DeltaAssociation methodsFor: 'accessing' stamp: 'hg 1/12/2002 19:32'! deactivatedValue: anObject deactivatedValue _ anObject! ! !DeltaAssociation methodsFor: 'accessing' stamp: 'hg 1/12/2002 19:32'! preserveCurrentValue: currentValue before: shouldBeActive shouldBeActive ifTrue: [self deactivatedValue: currentValue] ifFalse: [self value: currentValue]. ! ! !DeltaAssociation methodsFor: 'accessing' stamp: 'hg 1/12/2002 19:32'! valueWhenActive: returnActiveValue ^returnActiveValue ifTrue: [value] ifFalse: [deactivatedValue]! ! !DeltaAssociation methodsFor: 'printing' stamp: 'hg 1/12/2002 19:52'! printOn: aStream super printOn: aStream. aStream nextPutAll: ' / '. deactivatedValue printOn: aStream! ! !DeltaAssociation class methodsFor: 'instance creation' stamp: 'hg 1/12/2002 19:33'! key: newKey value: newValue deactivatedValue: deactivatedValue ^(self new key: newKey value: newValue) deactivatedValue: deactivatedValue! ! !DeltaClass methodsFor: 'accessing' stamp: 'hg 1/14/2002 20:17'! name ^self isMeta ifTrue: [self theNonMetaClass name, ' deltaForMetaclass'] ifFalse: [name]! ! !DeltaClass methodsFor: 'testing' stamp: 'hg 11/25/2001 19:28'! changesClassFormat ^changesClassFormat! ! !DeltaClass methodsFor: 'initialize-release' stamp: 'hg 11/25/2001 18:53'! initializeDelta "clean out methods and categories. Use regular dictionaries to allow for DeltaAssociations" changesClassFormat _ false. methodDict _ Dictionary new. self zapOrganization! ! !DeltaClass methodsFor: 'de/activate' stamp: 'hg 1/12/2002 16:23'! activateMethodsIn: class asActive: shouldBeActive "return an instance of my baseClass where method changes have been (de)activated. Handle both class and metaclass." self installMethodChangesIntoClass: class asActive: shouldBeActive. self deltaForMetaclass installMethodChangesIntoClass: class class asActive: shouldBeActive.! ! !DeltaClass methodsFor: 'de/activate' stamp: 'hg 1/12/2002 16:30'! basicDerivedBaseClassWhenActive: shouldBeActive "return an instance of my baseClass which has the format that I specify" | basicMetaclassAfter basicBaseClassAfter | self isMeta ifTrue: [^self error: 'should not be sent to a metaclass']. shouldBeActive ifFalse: [ ^self error: 'Can''t deactivate class format change in the current implementation']. basicMetaclassAfter _ self deltaForMetaclass basicMetaclassWhenActive: shouldBeActive. basicBaseClassAfter _ self as: basicMetaclassAfter new. ^basicBaseClassAfter! ! !DeltaClass methodsFor: 'de/activate' stamp: 'hg 11/25/2001 20:05'! basicMetaclassWhenActive: shouldBeActive "return an instance of my (meta) baseClass which has the class format that I specify" | metaclassWithMyFormat | self isMeta ifFalse: [^self error: 'should not be sent to a non-metaclass']. shouldBeActive ifFalse: [ ^self error: 'Can''t deactivate class format change in the current implementation']. metaclassWithMyFormat _ self as: Metaclass. ^metaclassWithMyFormat! ! !DeltaClass methodsFor: 'de/activate' stamp: 'hg 11/25/2001 20:22'! derivedBaseClassWhenActive: shouldBeActive "return an instance of my baseClass where my changes have been (de)activated. Install if shouldBeActive is true, otherwise uninstall changes. Handle both class and metaclass. This method should get more sophisticated over time to handle (de)activating 1. method additions, removals and modifications 2. class var additions (removals ?) 3. inst var additions (removals ?) -- how handle existing instances? 4. deeper class format changes, e.g. changed superclass The hard part of 2-4 is to handle converting existing instances. This is now handled by ordinary recompilation (ie. a non-atomical operation)." | after | after _ self basicDerivedBaseClassWhenActive: shouldBeActive. self installMethodChangesIntoClass: after asActive: shouldBeActive. self deltaForMetaclass installMethodChangesIntoClass: after class asActive: shouldBeActive. ^Array with: after with: after class! ! !DeltaClass methodsFor: 'de/activate' stamp: 'hg 1/26/2002 14:04'! installMethodChangesIntoClass: classOrMeta asActive: shouldBeActive | value selector | self methodDict associationsDo: [:deltaAssoc | selector _ deltaAssoc key. value _ deltaAssoc valueWhenActive: shouldBeActive. deltaAssoc preserveCurrentValue: (self baseClass compiledMethodAt: selector ifAbsent: [DeltaModule valueForUndefined]) before: shouldBeActive. value = DeltaModule valueForUndefined ifTrue: [classOrMeta removeSelectorUnlogged: selector] ifFalse: [ classOrMeta addSelector: selector withMethod: value. classOrMeta organization classify: selector under: (self organization categoryOfElement: selector)]]! ! !DeltaClass methodsFor: 'delta contents' stamp: 'hg 1/12/2002 19:33'! redefineSelector: selector withMethod: methodOrNil previousVersion: oldMethodOrNil self methodDict add: (DeltaAssociation key: selector value: methodOrNil deactivatedValue: oldMethodOrNil)! ! !DeltaClass methodsFor: 'delta contents' stamp: 'hg 1/26/2002 13:59'! removedSelectors | selectors | selectors _ Set new. self methodDict keysAndValuesDo: [:selector :cm | cm = DeltaModule valueForUndefined ifTrue: [selectors add: selector]]. ^selectors! ! !DeltaClass methodsFor: 'delta contents' stamp: 'hg 1/26/2002 13:55'! undefinedSelectors: selectors selectors do: [:sel | self redefineSelector: sel withMethod: DeltaModule valueForUndefined previousVersion: (self baseClass compiledMethodAt: sel ifAbsent: [DeltaModule valueForUndefined])]! ! !DeltaClass methodsFor: 'compatibility' stamp: 'hg 1/26/2002 13:55'! addSelector: selector withMethod: compiledMethod "override to use DeltaAssociations" self redefineSelector: selector withMethod: compiledMethod previousVersion: DeltaModule valueForUndefined ! ! !FileList methodsFor: 'to be transformed in registration' stamp: 'hg 1/8/2002 11:20'! fileContentsMenu: aMenu shifted: shifted | shiftMenu | ^ shifted ifFalse: [aMenu labels: 'get entire file view as hex fileIn file into new change set browse changes browse code find...(f) find again (g) set search string (h) do again (j) undo (z) copy (c) cut (x) paste (v) paste... do it (d) print it (p) inspect it (i) accept (s) cancel (l) more...' lines: #(2 6 9 11 15 18 20) selections: #(get getHex fileInSelection fileIntoNewChangeSet browseChanges browseFile find findAgain setSearchString again undo copySelection cut paste pasteRecent doIt printIt inspectIt accept cancel shiftedYellowButtonActivity)] ifTrue: [shiftMenu _ ParagraphEditor shiftedYellowButtonMenu. aMenu labels: shiftMenu labelString lines: shiftMenu lineArray selections: shiftMenu selections] ! ! !FileList methodsFor: 'menu messages' stamp: 'hg 1/13/2002 17:39'! copyName listIndex = 0 ifTrue: [^ self]. ParagraphEditor new clipboardTextPut: self fullName asText. self flag: #ViolateNonReferenceToOtherClasses. ! ! !MethodReference methodsFor: 'queries' stamp: 'hg 1/8/2002 12:09'! actualClassForModule: module | actualClass | actualClass _ module definitionFor: classSymbol ifAbsent: [^nil]. classIsMeta ifTrue: [^actualClass class]. ^actualClass ! ! !ModularSystemOrganizer methodsFor: 'handled SysOrg methods' stamp: 'hg 1/27/2002 13:51'! categories "return cached list or if none compute it here. Use this to clear the cache:" "SystemOrganization invalidateCaches" | newList | cachedCategoryList ifNotNil: [^ cachedCategoryList]. newList _ OrderedCollection new. Module root deepSubAndDeltaModules do: [:m | newList add: m simulatedCategory]. newList removeAll: self excludedCategories. "Cache the result while valid for later queries." cachedCategoryList _ newList asArray. ^ cachedCategoryList! ! !Module methodsFor: 'testing' stamp: 'hg 1/27/2002 12:18'! hasNeighborOrImportedModule: module (self neighborModules includes: module) ifTrue: [^true]. self deepImportedModulesDo: [:mod | module == mod ifTrue: [^true]]. ^false! ! !Module methodsFor: 'testing' stamp: 'hg 1/19/2002 22:24'! shouldExport: module "should the module be exported by default? Could test for kind of module here." ^false! ! !Module methodsFor: 'changing defined names' stamp: 'hg 1/27/2002 13:30'! redefineName: aString as: value export: exportIt "Be careful about the identity of the associations used, so as to preserve literal bindings of capitalized variable references. " | reusedAssoc key putInSmalltalk | aString first isUppercase ifFalse: [ self notify: 'Global names should be Capitalized, but "', aString asText allBold, '" is not. This could cause various problems. Cancel to avoid creating this global name.']. key _ aString asSymbol. self adoptIfUndeclared: key. reusedAssoc _ self localAssocFor: key ifAbsent: [ ReadOnlyVariableBinding key: key value: value]. [reusedAssoc value: value] on: AttemptToWriteReadOnlyGlobal do: [:ex | ex resume: true]. "with weak modules, retain compatibility by also putting globals in Smalltalk. " putInSmalltalk _ Preferences strongModules not and: [Module smalltalk notNil and: [(value isKindOf: Module) not]]. putInSmalltalk ifTrue: [ Module smalltalk definesName: key ifTrue: [:a | Module smalltalk removeName: key]. Module smalltalk addAssoc: reusedAssoc export: false]. self addAssoc: reusedAssoc export: exportIt. ! ! !Module methodsFor: 'module definition protocol' stamp: 'hg 1/19/2002 22:27'! deltaModuleOn: baseModule alias: aString version: versionOrNil importNames: shouldImport "use this message to declare that this module has a delta module" | ref symOrNil basePath | symOrNil _ aString ifNotNil: [aString asSymbol]. basePath _ (baseModule isKindOf: Module) ifTrue: [baseModule path] ifFalse: [baseModule]. ref _ (DeltaModuleReference new name: symOrNil version: versionOrNil module: basePath import: shouldImport) ensureReferenceFrom: self. ref parentModule: self. ^ref ! ! !Module methodsFor: 'module definition protocol' stamp: 'hg 1/27/2002 12:02'! externalModule: moduleOrPath alias: aString version: versionOrNil importNames: shouldImport "use this message to declare that this module depends on an external module." | ref symOrNil | symOrNil _ aString ifNotNil: [aString asSymbol]. ref _ ModuleReference new name: symOrNil version: versionOrNil module: moduleOrPath import: shouldImport. self addNeighborModule: ref export: nil. ^ref ! ! !Module methodsFor: 'module definition protocol' stamp: 'hg 1/27/2002 12:02'! parameterModuleWithDefault: moduleOrPathOrNil version: versionOrNil alias: moduleName importNames: shouldImport "use this message to declare a module parameter. Set its module value to the default." | ref | ref _ ModuleParameter new name: moduleName module: moduleOrPathOrNil import: shouldImport defaultModule: moduleOrPathOrNil version: versionOrNil. self addNeighborModule: ref export: nil. ^ref ! ! !Module methodsFor: 'module composition' stamp: 'hg 1/27/2002 12:16'! deepImportedModulesDo: aBlock "iterate recursively over all my imported modules and their imported modules in turn" self importedModulesDo: [:mod | aBlock value: mod. mod importedModulesDo: aBlock]! ! !Module methodsFor: 'module composition' stamp: 'hg 1/11/2002 22:27'! deltaModuleFor: baseModule | path | baseModule ifNil: [^nil]. path _ (baseModule isKindOf: Array) ifFalse: [baseModule path] ifTrue: [baseModule]. ^self deltaModules detect: [:mod | path = ((mod baseModule isKindOf: Array) ifFalse: [mod baseModule path] ifTrue: [mod baseModule])] ifNone: [nil]! ! !Module methodsFor: 'module composition' stamp: 'hg 1/13/2002 20:03'! importedModulesDo: aBlock "iterate non-recursively over my included modules, in the correct order for name lookup" self neighborModuleRefs do: [:ref | (ref importNames and: [ref isModuleResolved]) ifTrue: [aBlock value: ref module]]! ! !Module methodsFor: 'module composition' stamp: 'hg 1/19/2002 21:11'! neighborModules "return a collection of all modules that I reference" ^self neighborModuleRefs "this just to avoid problems in rare sensitive special cases" select: [:ref | ref isModuleResolved] thenCollect: [:ref | ref module]! ! !Module methodsFor: 'changing module composition' stamp: 'hg 1/19/2002 21:15'! deltaModuleForBase: baseModule forceCreate: create asActive: markedAsActive "return the DeltaModule associated with this module that has the given base module. If not found, create one if asked to, otherwise return nil." | ref | (self deltaModuleFor: baseModule) ifNotNilDo: [:mod | ^mod]. ^create ifTrue: [ ref _ self deltaModuleOn: baseModule alias: nil version: nil importNames: false. ref createModuleFromPathAndVersion baseModuleRef resolveModule. ref module markAsActive: markedAsActive. ref module]! ! !Module methodsFor: 'changing module composition' stamp: 'hg 1/27/2002 12:22'! ensureExternalModule: module (self hasNeighborOrImportedModule: module) ifFalse: [ self externalModule: module alias: nil version: nil importNames: false]! ! !Module methodsFor: 'fileIn/Out' stamp: 'hg 1/26/2002 14:36'! definition "Answer a String that builds the definition of the receiver as messages to it (don't print the receiver)." | aStream | aStream _ WriteStream on: (String new: 300). "Keep flag: messages with used selectors here so that this code will be updated if the selectors are changed." self flag: #version: . aStream crtab; nextPutAll:'version: '; print: self verbatimVersion. self neighborDefinitionsOn: aStream. ^ aStream contents! ! !Module methodsFor: 'un/loading' stamp: 'hg 11/26/2001 20:00'! objectsBeforeAndAfter: shouldBeInstalled ^nil! ! !Module methodsFor: 'code analysis' stamp: 'hg 1/27/2002 13:24'! deepIncomingRefsFromOutside: module "(Module fromPath: #(EToy Experimental)) localUniqueMessagesToOutside: (Module fromPath: #(EToy))" | refs insideModules n total | refs _ IdentityDictionary new. insideModules _ IdentitySet new. module deepSubmodulesDo: [:mod | insideModules add: mod]. self deepSubmodulesDo: [:mod | mod exportedNames keysAndValuesDo: [:key :value | (value isKindOf: Module) ifTrue: [ "Transcript show: 'References to Module name ', key, ' ignored.';cr"] ifFalse: [refs at: key put: Set new]]]. total _ 0. self class root deepClassesDo: [:cl | total _ total + 1]. 'Locating outside references to global definitions ...' displayProgressAt: Sensor cursorPoint from: 0 to: total during: [:bar | n _ 0. self class root deepClassesDo: [:cl | bar value: (n_ n+1). (insideModules includes: cl module) ifFalse: [ cl selectorsAndMethodsDo: [:sel :cm | cm literals do: [:lit | (lit respondsTo: #key) ifTrue: [ refs at: lit key ifPresent: [:set | set add: (MethodReference new setStandardClass: cl methodSymbol: sel)]]]]]]]. refs copy keysAndValuesDo: [:key :value | value isEmpty ifTrue: [refs removeKey: key]]. ^refs! ! !Module methodsFor: 'code analysis' stamp: 'hg 1/27/2002 13:38'! deepUnresolvedRefsWithScheme: bindingScheme | list n localList | list _ OrderedCollection new. 'Locating methods with unresolved global references...' displayProgressAt: Sensor cursorPoint from: 0 to: self deepSubAndDeltaModules size during: [:bar | n _ 0. self deepSubAndDeltaModules do: [:mod | bar value: (n_ n+1). localList _ mod localUnresolvedRefsWithScheme: bindingScheme. list addAll: localList. "mod setUnresolvedCount: localList size."]]. self zeroOutOfScopeCache. ^list asSortedCollection! ! !Module methodsFor: 'code analysis' stamp: 'hg 1/27/2002 14:35'! localUnresolvedRefsWithScheme: bindingScheme "check that all used globals (global literals in CompiledMethods) will be bound to the exact same association object if recompiled (this is stronger than just the same name or value). Return the bad ones as MethodReferences." | badRefs ok sup isBad isUninterestingClass isUninterestingDelta | badRefs _ OrderedCollection new. self resetOutOfScopeCache. self allClassesDo: [:c | {c. (c isKindOf: DeltaClass) ifFalse: [c class] ifTrue: [c deltaForMetaclass] } do: [:cl | cl methodDict keysAndValuesDo: [:selector :cm | isBad _ cm ~~ DeltaModule valueForUndefined and: [ cm literals anySatisfy: [:lit | lit isVariableBinding and: [lit key notNil] and: [ ((c definesName: lit key lookInSuper: true ifTrue: [:a |]) or: [ (self definesName: lit key usingScheme: bindingScheme withCache: OutOfScopeCache ifTrue: [:ass | ok _ ass == lit or: [self isKindOf: DeltaModule]]) and: [ok]]) not]]]. isBad ifTrue: [ badRefs add: ( MethodReference new setStandardClass: cl methodSymbol: selector)]]]]. self allClassesDo: [:c | sup _ c superclass. isBad _ ((self definesName: sup name usingScheme: bindingScheme withCache: OutOfScopeCache ifTrue: [:ass | ok _ ass value == sup]) and: [ok]) not. isUninterestingClass _ c isObsolete | sup isNil. isUninterestingDelta _ (self isKindOf: DeltaModule) and: [ (self isDeltaClass: c) and: [c changesClassFormat not]]. isBad & (isUninterestingClass | isUninterestingDelta) not ifTrue: [ badRefs add: ( MethodReference new setStandardClass: c methodSymbol: #'')]]. ^badRefs ! ! !Module methodsFor: 'code analysis' stamp: 'hg 1/27/2002 13:34'! viewDeepUnresolvedRefs "Root viewDeepUnresolvedRefs" Smalltalk browseMessageList: self deepUnresolvedRefs name: 'Unresolved Global References from ', self pathAsMessages autoSelect: nil! ! !Module methodsFor: 'system conversion' stamp: 'hg 1/13/2002 19:54'! declareDefaultExternalModules (self hasNeighborModule: Module @ #(Squeak Language Core)) ifFalse: [ self externalModule: Module @ #(Squeak Language Core) alias: nil version: nil importNames: true]. (self hasNeighborModule: Module @ #(Squeak Language Collections)) ifFalse: [ self externalModule: Module @ #(Squeak Language Collections) alias: nil version: nil importNames: true]! ! !Module methodsFor: 'system conversion' stamp: 'hg 1/27/2002 13:47'! deepDeclareExternalRefs "Root deepDeclareExternalRefs" | n | 'Declaring all external references...' displayProgressAt: Sensor cursorPoint from: 0 to: self deepSubAndDeltaModules size during: [:bar | n _ 0. self deepSubAndDeltaModules do: [:mod | mod localDeclareExternalRefsWithScheme: self weakOrStrongBindingScheme. bar value: (n_ n+1)]]. self zeroOutOfScopeCache. ! ! !Module methodsFor: 'system conversion' stamp: 'hg 1/27/2002 10:30'! defineClassExtensionsOutside: homeModule "Collect class extensions from this module as DeltaModules of this module. Class extensions are here detected as methods outside this module that contain references to global names defined by this module (note that this finds far from all eligible methods). Find all such methods in all classes outside homeModule, then add to this module DeltaModules with classes referring to those methods. This does not at all affect the actual classes or methods." | incoming deltaModule deltaClass method n | incoming _ self deepIncomingRefsFromOutside: homeModule. self repository useChangeSetNamed: self name, 'Reorganization', Time now printString during: [ 'Collecting extension methods ...' displayProgressAt: Sensor cursorPoint from: 0 to: incoming size during: [:bar | n _ 0. incoming keysAndValuesDo: [:key :upstreamMethodRefs | bar value: (n _ n + 1). upstreamMethodRefs do: [:mref | deltaModule _ self deltaModuleForBase: mref actualClass module forceCreate: true asActive: true. deltaClass _ deltaModule deltaClassFor: mref actualClass forceCreate: true. method _ mref actualClass compiledMethodAt: mref methodSymbol. deltaClass addSelector: mref methodSymbol withMethod: method]]]]. ^incoming! ! !Module methodsFor: 'system conversion' stamp: 'hg 1/27/2002 15:59'! localDeclareExternalRefsWithScheme: bindingScheme "For all classes in this module, identify all references to unresolved globals. For each of these, call another method to declare the global's defining module." | refsList | refsList _ self localUnresolvedRefsWithScheme: bindingScheme. self resetOutOfScopeCache. self declareDefaultExternalModules. refsList do: [:ref | ref methodSymbol == #'' ifFalse: [ self declareExternalRefsForSelector: ref methodSymbol inClass: (ref actualClassForModule: self)] ifTrue: [ self ensureExternalModule: (ref actualClassForModule: self) superclass module]]. self zeroOutOfScopeCache. ^refsList size! ! !Module methodsFor: 'private' stamp: 'hg 1/27/2002 12:30'! privateAddNeighborModuleRef: moduleReference neighborModules _ self privateNeighborModuleRefs copyWith: moduleReference. self invalidateCaches. ! ! !Module methodsFor: 'private' stamp: 'hg 1/27/2002 12:27'! privateNeighborModuleRefs ^neighborModules ifNil: [#()]! ! !Module methodsFor: 'private' stamp: 'hg 1/27/2002 12:29'! privateRemoveNeighborModuleRef: moduleReference neighborModules _ self privateNeighborModuleRefs copyWithout: moduleReference. self invalidateCaches. ! ! !DeltaModule methodsFor: 'accessing' stamp: 'hg 1/19/2002 18:34'! baseModule ^baseModuleRef module! ! !DeltaModule methodsFor: 'accessing' stamp: 'hg 1/19/2002 20:45'! baseModuleRef ^baseModuleRef! ! !DeltaModule methodsFor: 'accessing' stamp: 'hg 1/19/2002 18:34'! baseModuleRef: moduleRef baseModuleRef _ moduleRef! ! !DeltaModule methodsFor: 'accessing' stamp: 'hg 1/26/2002 21:51'! name | path pathAsMessages | path _ self baseModuleRef ensuredPath literalPrintString. pathAsMessages _ path allButLast allButFirst: 2. ^(pathAsMessages, ' delta') asSymbol ! ! !DeltaModule methodsFor: 'initializing' stamp: 'hg 1/19/2002 18:53'! baseModuleRef: baseRef parentModule: parent baseModuleRef _ baseRef. parentModule _ parent. self markAsActive: false.! ! !DeltaModule methodsFor: 'changing defined names' stamp: 'hg 1/26/2002 13:57'! addAssoc: assoc export: exportIt "by default add DeltaAssociation with previousValue indicating undefined" | deltaAssoc | deltaAssoc _ DeltaAssociation key: assoc key value: assoc value deactivatedValue: DeltaModule valueForUndefined. ^super addAssoc: deltaAssoc export: exportIt ! ! !DeltaModule methodsFor: 'changing defined names' stamp: 'hg 1/12/2002 17:33'! redefineName: aString as: value export: exportIt "special version so as not to also put globals in Smalltalk" aString first isUppercase ifFalse: [ self notify: 'Global names should be Capitalized, but "', aString asText allBold, '" is not. This could cause various problems. Cancel to avoid creating this global name.']. self addAssoc: (aString asSymbol)->value export: exportIt ! ! !DeltaModule methodsFor: 'module composition' stamp: 'hg 1/27/2002 14:20'! deepSubAndDeltaModules ^{self}! ! !DeltaModule methodsFor: 'fileIn/Out' stamp: 'hg 1/26/2002 14:30'! variableDefinitionFor: definedName "return a string with a message that defines the given variable in this module" | valueString | self flag: #defineName:as:export:; flag: #valueForUndefined. valueString _ (self definitionFor: definedName ifAbsent: [nil]) = self class valueForUndefined ifTrue: [DeltaModule valueForUndefined printString] ifFalse: ['nil']. ^'defineName: ', definedName printString, ' as: ', valueString, ' export: ', (self exportsName: definedName) printString! ! !DeltaModule methodsFor: 'delta representations' stamp: 'hg 1/12/2002 21:41'! deltaClassFor: baseClass | deltaClass | deltaClass _ DeltaClass on: baseClass inDeltaModule: self. self redefineName: baseClass name as: deltaClass export: true. "note that class was already here, so it won't be removed on deactivation" (self definedNames associationAt: baseClass name) deactivatedValue: deltaClass. ^deltaClass. ! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 11/26/2001 19:56'! classObjectsBeforeAndAfter: shouldBeActive "class modification is done in two separate stages: 1. change the instance format, including recompiling self (and subclasses) 2. install method changes (done atomically)" | preSwitchObjects postSwitchObjects formatChange baseClassBeforeSwitch baseClassNow | preSwitchObjects _ OrderedCollection new. postSwitchObjects _ OrderedCollection new. self deltaClassesDo: [:deltaClass | formatChange _ deltaClass changesClassFormat or: [deltaClass deltaForMetaclass changesClassFormat]. baseClassBeforeSwitch _ deltaClass basicDerivedBaseClassWhenActive: shouldBeActive. formatChange ifTrue: [ baseClassNow _ deltaClass baseClass. ClassBuilder new reshapeClass: baseClassNow to: baseClassBeforeSwitch super: baseClassBeforeSwitch superclass]. preSwitchObjects add: baseClassBeforeSwitch; add: baseClassBeforeSwitch class. postSwitchObjects addAll: (deltaClass activateMethodsIn: baseClassBeforeSwitch asActive: shouldBeActive)]. ^Array with: preSwitchObjects with: postSwitchObjects! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/12/2002 15:43'! effectClassChangesConservatively: shouldBeActive "class modification is done in two separate stages: 1. change the instance format, including recompiling self (and subclasses) 2. install method changes" | formatChange baseClassBeforeSwitch baseClassNow | self deltaClassesDo: [:deltaClass | formatChange _ deltaClass changesClassFormat or: [deltaClass deltaForMetaclass changesClassFormat]. baseClassBeforeSwitch _ deltaClass basicDerivedBaseClassWhenActive: shouldBeActive. formatChange ifTrue: [ baseClassNow _ deltaClass baseClass. ClassBuilder new reshapeClass: baseClassNow to: baseClassBeforeSwitch super: baseClassBeforeSwitch superclass]. deltaClass activateMethodsIn: baseClassBeforeSwitch asActive: shouldBeActive]! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/12/2002 16:31'! effectClassFormatChanges: shouldBeActive "change the class format, including recompilation and instance mutations" | formatChange baseClassBeforeSwitch baseClassNow | self deltaClassesDo: [:deltaClass | formatChange _ deltaClass changesClassFormat or: [deltaClass deltaForMetaclass changesClassFormat]. formatChange ifTrue: [ baseClassNow _ deltaClass baseClass. baseClassBeforeSwitch _ deltaClass basicDerivedBaseClassWhenActive: shouldBeActive. ClassBuilder new recompile: false from: baseClassNow to: baseClassBeforeSwitch mutate: false]]! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/26/2002 13:50'! effectDefinitionChanges: shouldBeActive into: module "hack to preserve the association if deleted and later reinstalled" | value currentValue currentAssoc | self definedNames associationsDo: [:assoc | value _ assoc valueWhenActive: shouldBeActive. value isBehavior ifFalse: [ currentAssoc _ module localAssocFor: assoc key ifAbsent: [nil]. currentValue _ currentAssoc ifNil: [self class valueForUndefined] ifNotNil: [currentAssoc value]. assoc preserveCurrentValue: currentValue before: shouldBeActive. value = self class valueForUndefined ifFalse: [ ((value isKindOf: LookupKey) and:[value key == assoc key]) ifTrue: [ module addAssoc: value export: false. value _ value value]. [module redefineName: assoc key as: value export: (self exportsName: assoc key)] on: AttemptToWriteReadOnlyGlobal do: [:ex | ex resume: true]] ifTrue: [ (module localAssocFor: assoc key ifAbsent: [nil]) ifNotNilDo: [:a | assoc preserveCurrentValue: a before: shouldBeActive. module removeName: assoc key]]]].! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/12/2002 16:05'! effectMethodChangesConservatively: shouldBeActive "install method changes" self deltaClassesDo: [:deltaClass | deltaClass activateMethodsIn: deltaClass baseClass asActive: shouldBeActive]! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/12/2002 15:32'! objectsBeforeAndAfter: shouldBeActive "Make me be active or inactive. A DeltaModule is a modified version of its baseModule. Activating a DM means to modify its baseModule by installing its changes into it. Phase 1 prepares before- and after-versions of all objects in the baseModule that should be changed. This is done without actually modifying the current baseModule. Then Phase 2 makes a quick and safe atomic switch between the before and after versions to enforce the activation." | preSwitchObjects postSwitchObjects beforeAfter moduleAfter | self isActive = shouldBeActive ifTrue: [^nil]. preSwitchObjects _ OrderedCollection new. postSwitchObjects _ OrderedCollection new. moduleAfter _ self baseModule veryDeepCopy. self effectDefinitionChanges: shouldBeActive into: moduleAfter. preSwitchObjects add: self baseModule. postSwitchObjects add: moduleAfter. beforeAfter _ self classObjectsBeforeAndAfter: shouldBeActive. preSwitchObjects addAll: beforeAfter first. postSwitchObjects addAll: beforeAfter second. ^Array with: preSwitchObjects with: postSwitchObjects! ! !DeltaModule methodsFor: 'de/activating' stamp: 'hg 1/12/2002 16:12'! simplyEffectChanges: shouldBeActive "Make me be active or inactive. A DeltaModule is a modified version of its baseModule. Activating a DM means to modify its baseModule by installing its changes into it." self isActive = shouldBeActive ifTrue: [^nil]. self effectDefinitionChanges: shouldBeActive into: self baseModule. self effectMethodChangesConservatively: shouldBeActive. self effectClassFormatChanges: shouldBeActive.! ! !Module class methodsFor: 'class initialization' stamp: 'hg 1/29/2002 11:09'! createModularClassDefinitionsPreference Preferences addPreference: #modularClassDefinitions category: #modules default: true balloonHelp: 'Sholud browsers display modular or traditional class definitions?'! ! !Module class methodsFor: 'virtual hierarchy' stamp: 'hg 1/27/2002 14:05'! pathFromCategory: catString create: allowCreate "Module pathFromCategory:'Morphic-Demo'" "Convert a category name into a module path, taking dashes and spaces as level separators. Put it under top-level module Squeak" | categoryPath stringToUse isSqueakModule | (allowCreate and: [catString includes: Character space]) ifTrue: [ PopUpMenu confirm: 'Bad category name: ''', catString, '''. Module names should be proper symbols. OK to strip non-alphanumerical characters?' orCancel: [self halt]]. stringToUse _ allowCreate ifTrue: [catString select: [:c | c isAlphaNumeric | (c = $-)]] ifFalse: [catString]. categoryPath _ (stringToUse findTokens: '-') collect: [:str | str capitalized asSymbol]. isSqueakModule _ Module squeak submodules anySatisfy: [:mod | mod name = categoryPath first]. ^isSqueakModule ifTrue: [self squeak path , categoryPath] ifFalse: [categoryPath] ! ! !DeltaModule class methodsFor: 'instance creation' stamp: 'hg 1/19/2002 18:57'! baseModuleRef: baseRef parentModule: parent ^self new baseModuleRef: baseRef parentModule: parent! ! !DeltaModule class methodsFor: 'instance creation' stamp: 'hg 1/26/2002 14:29'! valueForUndefined ^#shouldBeUndefined! ! !ModuleExplorer methodsFor: 'as yet unclassified' stamp: 'hg 1/29/2002 11:17'! trash "some example expressions to try" ^'NOTE: You may close this window at any time. will get a new one "try these on some modules (cmd-p / cmd-I)..." self deepDeclareExternalRefs. self viewDeepUnresolvedRefs. self path self deepIncomingRefsFromOutside: self self deepIncomingRefsFromOutside: parentModule self deepUniqueMessagesToOutside: self self defineClassExtensionsOutside: self self repository beStandalone self repository directory url self repository repositoryToUse ensureDeepUpload ModuleInstaller fullyInstallFromPath: #(Temporary TestModule) ModuleInstaller unload: self Repository importChangesFromFileNamed: ''sample.cs'' intoModuleAt: #(Temporary TestModule) ' ! ! !ModuleInstaller methodsFor: 'initialize-reset' stamp: 'hg 1/26/2002 19:57'! clearDefinedModules definedModules _ OrderedCollection new! ! !ModuleInstaller methodsFor: 'initialize-reset' stamp: 'hg 1/26/2002 19:57'! initialize self clearLoadedModules. self clearDefinedModules. self clearDownloadedModules. self clearLoadedModules. self clearActivatedModules. ! ! !ModuleInstaller methodsFor: 'accessing' stamp: 'hg 1/26/2002 19:58'! definedModules ^definedModules! ! !ModuleInstaller methodsFor: 'accessing' stamp: 'hg 1/26/2002 19:58'! loadedModules ^loadedModules! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 12/18/2001 09:36'! allModulesNeededBy: module exceptForNeedsOf: excludedModules "Answer all modules needed by the given module, applied recursively, not considering the needs of excludedModules. This means all modules that are (indirectly) reachable from the given module. This is a basic breadth-first graph traversal algorithm." | all remaining current newRemaining neighbors excludedSet | all _ Set with: module. excludedSet _ excludedModules asSet. remaining _ all asOrderedCollection. [remaining isEmpty] whileFalse: [ current _ remaining removeFirst. neighbors _ self directlyNeededModulesFor: current. newRemaining _ (neighbors difference: excludedSet) difference: all. all addAll: neighbors. remaining addAll: newRemaining]. ^all copyWithout: module! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 23:00'! checkForCircularDependencies: dependencies "Need to allow circular dependencies or virtually no part of the existing class library will (un)load. References to undefined names during loading, which result from circular dependencies, are handled via Undeclared, so dual definitions of the same name will be confused, also a subclass loaded before superclass will be bad." | circularities uses circular | circularities _ dependencies keys collect: [:dependent | uses _ dependencies at: dependent. circular _ uses select: [:used | (dependencies at: used ifAbsent: [#()]) includes: dependent]. dependent -> circular asArray] thenSelect: [:ass | ass value isEmpty not]. circularities isEmpty ifFalse: [ self note: 'Circular dependencies: '. circularities do: [:circ | self note: String tab, circ printString]. self notify: 'Some modules have circular dependencies. Module contents may not load correctly.'.]! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 23:18'! compositeLoadingDependenciesFor: module except: excludedModules | all | all _ IdentitySet new. module repository compositeModules do: [:mod | all addAll: ((self allModulesNeededBy: mod exceptForNeedsOf: excludedModules) copyWithoutAll: mod deepSubmodules)]. ^all copyWithout: module! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/9/2002 14:29'! directlyNeededModulesFor: module "neighbors except start module's ref from its parent" | start reachable | reachable _ self directlyReachableModulesFor: module. start _ self startModule. ^module == start parentModule ifFalse: [reachable] ifTrue: [reachable copyWithout: start]! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/26/2002 13:10'! directlyReachableModulesFor: module "just preliminary" ^module isDeltaModule ifFalse: [module neighborModules] ifTrue: [Array with: module baseModule]! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 22:05'! loadingOrderFor: modules | dependencies | dependencies _ modules collect: [:mod | mod -> (self compositeLoadingDependenciesFor: mod except: modules)]. ^self modules: modules inDependencyOrderFrom: dependencies! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 21:45'! module: module1 dependsOn: module2 says: dependencies ^(dependencies at: module1) includes: module2! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 22:53'! modules: modules inDependencyOrderFrom: dependencies "a module may load before another if it doesn't depend on the other, OR if they have a circular dependency." | dependencyDictionary | dependencyDictionary _ Dictionary newFrom: dependencies. self checkForCircularDependencies: dependencyDictionary. ^modules topologicallySortedUsing: [:module1 :module2 | (self module: module1 dependsOn: module2 says: dependencyDictionary) ==> [self module: module2 dependsOn: module1 says: dependencyDictionary]]! ! !ModuleInstaller methodsFor: 'graph computation' stamp: 'hg 1/27/2002 21:42'! orderWithinCompositeFor: modules | dependencies | dependencies _ modules collect: [:mod | mod -> ((self allModulesNeededBy: mod exceptForNeedsOf: modules) copyWithoutAll: mod deepSubmodules)]. ^self modules: modules inDependencyOrderFrom: dependencies! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/25/2002 21:15'! addReferencesToResolve: moduleRefs to: remaining "Trivially just the reference itself would be added. However, you need to make sure that all its parent modules are defined before it, so this happens here." | path | moduleRefs do: [:moduleRef | path _ moduleRef ensuredPath. 1 to: path size-1 do: [:level | remaining add: (ModuleReference onPath: (path first: level))]. remaining add: moduleRef]. ! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/26/2002 21:32'! ensureAllModulesDefined "ensure that the Module objects for all involved modules are is in the image. Take ModuleReferences and ensure their definitions are loaded." self phase: 'Loading definitions for all needed modules.' progressTotal: 0. self ensureAllReachableModulesResolved: startModuleRef. ! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/25/2002 20:30'! ensureAllReachableModulesResolved: firstModuleRef "Ensure that all recursively reachable modules are defined. This is a basic breadth-first graph traversal algorithm. Note that moduleRefs at first are unresolved, i.e. have paths instead of modules in their module slot." | remaining refToResolve modulesDefined neighborRefsToScan | remaining _ OrderedCollection new. self addReferencesToResolve: (Array with: firstModuleRef) to: remaining. remaining add: firstModuleRef. [remaining isEmpty] whileFalse: [ refToResolve _ remaining removeFirst. modulesDefined _ self ensureModuleResolved: refToResolve. neighborRefsToScan _ self refsToScanFrom: modulesDefined. self addReferencesToResolve: neighborRefsToScan to: remaining]! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/27/2002 18:54'! ensureModuleResolved: moduleRef "ensure that the Module object for the moduleRef is in the image and correctly defined. First ask the moduleRef to find a matching module for its path and version. If none, I first need to ensure that the module definition file is in the cache, then create the Module object from the definition. Return all modules that were defined--note that a composite repository may define more than one module at once. If module is created here, then assume it has a standalone repository since it must be loaded as itself, if it were part of another repository then it would have to be loaded together with it." | module modulesDefined definingRepository | moduleRef resolveModule ifNotNil: [^#()]. module _ moduleRef createModuleFromPathAndVersion. module repository repositoryToUse defineAsStandaloneOrNotFromDirectoryStructure. definingRepository _ module repository repositoryToUse standaloneRepository. self note: 'Loading definition for ', definingRepository module pathAndVersion literalPrintString,'...'. modulesDefined _ definingRepository defineCompositeModulesFromFile. "mark that modules were created" definedModules addAll: modulesDefined. moduleRef isModuleResolved ifFalse: [self error: 'Loading module definition failed.']. self noteDone. ^modulesDefined ! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/26/2002 13:19'! refsToScanFrom: modules ^(modules inject: #() into: [:all :module | all, module neighborModuleRefs]) asIdentitySet.! ! !ModuleInstaller methodsFor: 'defining modules' stamp: 'hg 1/26/2002 19:58'! reverseDefinedModules self removeModules: definedModules reversed. self clearDefinedModules ! ! !ModuleInstaller methodsFor: 'resolving conflicts' stamp: 'hg 1/26/2002 22:20'! identifyConflicts "match all needed modules against each other (in both directions) but not against themselves, and check them for conflicts with the other" | allModules conflicts conflictingPair | allModules _ self allModulesNeededBy: self startModule exceptForNeedsOf: #(). conflicts _ OrderedCollection new. self phase: 'Searching for module conflicts... ' progressTotal: allModules size squared. allModules _ allModules asOrderedCollection. allModules with: allModules do: [:first :second | self progressAdd: 1. (first ~= second and: [first conflictsWith: second]) ifTrue: [ conflictingPair _ (Array with: first with: second). conflicts add: conflictingPair. self note: ' ', first printString, ' marks a conflict with: ', second printString]]. conflicts isEmpty ifFalse: [ self error: 'Internal conflicts among the needed modules have been detected.']. self noteDone ! ! !ModuleInstaller methodsFor: 'downloading modules' stamp: 'hg 1/27/2002 18:20'! downloadModuleIntoCache: module | size | self note: 'Downloading ', module printString, '...'. size _ module repository sizeOfContentsFilesToDownload. module repository ensureCompleteModuleContentsInCache. self progressAdd: size. downloadedModules add: module. "record that module was downloaded" self noteDone ! ! !ModuleInstaller methodsFor: 'downloading modules' stamp: 'hg 1/27/2002 18:42'! ensureAllModulesInRepository "ensure that all loaded modules needing to be loaded have their necessary files in the repository." | modulesToDownload totalSize missingModules | modulesToDownload _ definedModules reject: [:mod | mod repository repositoryToUse checkCompleteModuleContentsOK]. self workOffline ifFalse: [ totalSize _ modulesToDownload inject: 0 into: [:subTotal :mod | subTotal + mod repository sizeOfContentsFilesToDownload]. self phase: 'Downloading module files.' progressTotal: totalSize. modulesToDownload do: [:mod | self downloadModuleIntoCache: mod]]. missingModules _ definedModules reject: [:mod | mod repository cache checkCompleteModuleContentsOK]. missingModules notEmpty ifTrue: [ missingModules do: [:mod | self note: 'Complete contents for ', mod printString, ' not in cache.']. self error: 'Some modules missing in cache']. ! ! !ModuleInstaller methodsFor: 'downloading modules' stamp: 'hg 1/27/2002 18:06'! workOffline ^Preferences accessOnlineModuleRepositories not! ! !ModuleInstaller methodsFor: '(un)loading' stamp: 'hg 1/27/2002 21:38'! ensureAllModulesLoaded "load the contents for all modules that need to be loaded" | totalSize modulesToLoad | modulesToLoad _ self modulesToLoad. totalSize _ modulesToLoad inject: 0 into: [:subTotal :module | subTotal + module repository sizeOfContentsFiles]. self phase: 'Loading all needed modules into image. ' progressTotal: totalSize. (self loadingOrderFor: modulesToLoad) do: [:module | self loadContentsForModule: module]! ! !ModuleInstaller methodsFor: '(un)loading' stamp: 'hg 1/26/2002 22:16'! initializeLoadedModules self note: 'Initializing loaded modules...'. loadedModules do: [:mod | mod allClassesDo: [:cl | (cl class includesSelector: #initialize) ifTrue: [ self note: ' Initializing class ', cl name, '.'. cl initialize]]]. self noteDone ! ! !ModuleInstaller methodsFor: '(un)loading' stamp: 'hg 1/26/2002 22:16'! loadContentsForModule: module | allLoadedModules | self note: 'Loading contents for ', module printString, '...'. allLoadedModules _ module repository loadModuleContents. self progressAdd: module repository sizeOfContentsFiles. loadedModules addAll: allLoadedModules. self noteDone ! ! !ModuleInstaller methodsFor: '(un)loading' stamp: 'hg 1/26/2002 19:58'! modulesToLoad ^(definedModules collect: [:mod | mod repository standaloneRepository module]) asSet! ! !ModuleInstaller methodsFor: '(un)loading' stamp: 'hg 1/26/2002 13:20'! modulesToLoadFor: module ^module neighborModules! ! !ModuleInstaller methodsFor: 'public' stamp: 'hg 1/19/2002 21:33'! fullyInstallModule "carry out all actions necessary to fully instate the module" self gracefullyExecute: [ self ensureAllModulesDefined. self preserveUninstallInformation. self identifyConflicts. self ensureAllModulesInRepository. self ensureAllModulesLoaded. self ensureAllModulesActive. self initializeLoadedModules]! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/12/2002 16:56'! deactivateModule self deactivateModules: self startModule deepSubAndDeltaModules ! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/26/2002 22:13'! deactivateModules: modules | allModulesToDeactivate | allModulesToDeactivate _ self modulesToDeactivate: modules. self ensureNoUsersOf: allModulesToDeactivate. allModulesToDeactivate isEmpty ifTrue: [ ^self note: 'No modules to deactivate.']. self phase: 'Deactivating modules...' progressTotal: allModulesToDeactivate size. Preferences conservativeModuleDeActivation ifFalse: [self switchModulesWithBecome: allModulesToDeactivate beActive: false] ifTrue: [self switchModulesConservatively: allModulesToDeactivate beActive: false]. self noteDone ! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/26/2002 22:21'! ensureAllModulesActive "Ensure that all necessary modules are active. Note that this is not symmetric with ensureDeactivate, external, non-submodules may be activated." | modulesToActivate | modulesToActivate _ self allModulesNeededBy: self startModule exceptForNeedsOf: #(). modulesToActivate _ modulesToActivate reject: [:module | module isActive]. self phase: 'Activating modules...' progressTotal: modulesToActivate size. Preferences conservativeModuleDeActivation ifFalse: [self switchModulesWithBecome: modulesToActivate beActive: true] ifTrue: [self switchModulesConservatively: modulesToActivate beActive: true]. activatedModules _ modulesToActivate. self noteDone! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/12/2002 16:57'! modulesToDeactivate: eligibleModules ^eligibleModules select: [:mod | mod isActive]! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/12/2002 21:33'! switchModulesConservatively: modules beActive: beActive "Switch the activation status of all given modules. Classes are modified by directly modifying method dictionaries, and recompiling classes to effect format changes." modules do: [:mod | "mod == modules asOrderedCollection second & beActive & (mod == DeltaModuleTests new deltaForBeta) & (DeltaModuleTests new betaModule TestModuleVariable = 43) ifTrue: [self halt]." mod isDeltaModule ifTrue: [mod simplyEffectChanges: beActive]. "mod == modules asOrderedCollection first & beActive & (mod == DeltaModuleTests new deltaForAlpha) & (DeltaModuleTests new betaModule TestModuleVariable = 43) ifTrue: [self halt]." mod markAsActive: beActive. self activate: beActive classesIn: mod. self progressAdd: 1].! ! !ModuleInstaller methodsFor: '(de)activating' stamp: 'hg 1/26/2002 22:17'! switchModulesWithBecome: modules beActive: beActive "Switch the activation status of all given modules. Classes are modified by creating new versions of all changed objects and then replacing the originals with a become operation." | before after beforeAndAfter | self error: 'This code is not in a runnable state. You should not try to run it.'. before _ OrderedCollection new. after _ OrderedCollection new. modules do: [:mod | self progressAdd: 1. beforeAndAfter _ mod objectsBeforeAndAfter: beActive. beforeAndAfter ifNotNil: [ before addAll: beforeAndAfter first. after addAll: beforeAndAfter second]]. "the critical step:" self note: 'Switching...'. self atomicallySwitch: before to: after. modules do: [:mod | mod markAsActive: beActive. self activate: beActive classesIn: mod]. self noteDone. ^after! ! !ModuleInstaller methodsFor: 'utilities' stamp: 'hg 1/27/2002 23:26'! cleanup "Erase everything except my information about what is needed in order to undo this installation." progressIndicator _ progressValue _ nil! ! !ModuleInstaller methodsFor: 'utilities' stamp: 'hg 1/26/2002 22:22'! done "wrap things up here" self cleanup. self note: '---- Module Installer Done.'! ! !ModuleInstaller methodsFor: 'utilities' stamp: 'hg 1/26/2002 22:14'! ensureNoUsersOf: unsafeModules "safeness is defined as no other loaded modules depending on the given modules, i.e. declaring any of them as an external module." | allNeeded unsafeToUnload | allNeeded _ self allModulesNeededBy: Module root exceptForNeedsOf: unsafeModules. unsafeToUnload _ allNeeded intersection: unsafeModules. unsafeToUnload isEmpty ifFalse: [ unsafeToUnload do: [:mod | self note: '>> Module ', mod pathAsMessages, ' is used by other modules.']. self error: unsafeToUnload size printString, ' modules are used by other modules.']. ! ! !ModuleInstaller methodsFor: 'utilities' stamp: 'hg 1/26/2002 22:16'! revertGracefullyToStableState self notify: 'Operation failed, select Proceed to perform recovery.'. self note: '>>>> Recovering from error...'. self fullyUninstallModule. self note: '>>>> Error recovery done.'. ! ! !ModuleInstaller methodsFor: 'user interface' stamp: 'hg 1/26/2002 22:23'! noteDone "notify the user. Only use transcript for now." Transcript show: ' done.'.! ! !ModuleInstaller methodsFor: 'user interface' stamp: 'hg 1/26/2002 22:09'! phase: phaseDescriptionString progressTotal: max Transcript cr; show: phaseDescriptionString. progressValue _ 0. "progressIndicator message: phaseDescriptionString; maxVal: max"! ! !ModuleInstaller methodsFor: 'user interface' stamp: 'hg 1/27/2002 22:00'! showProgressDuring: aBlock "use a simple, oldstyle progress bar" | titleString | titleString _ operation asString, ' ', startModuleRef ensuredPath literalPrintString. progressValue _ 0. self note: '---- Module Installer Starting...'. self note: 'Performing ', titleString. titleString displayProgressAt: Sensor cursorPoint from: 0 to: 0 during: [:bar | progressIndicator _ bar. aBlock value]! ! !ModuleInstaller class methodsFor: 'debugging' stamp: 'hg 1/12/2002 20:20'! testActivate: mod ^self do: #ensureAllModulesActive forModuleRef: (mod parentModule refForNeighborModule: mod) withRecovery: false! ! !ModuleInstaller class methodsFor: 'debugging' stamp: 'hg 1/12/2002 20:20'! testDeactivate: mod ^self do: #deactivateModule forModuleRef: (mod parentModule refForNeighborModule: mod) withRecovery: false! ! !ModuleInstaller class methodsFor: 'preferences' stamp: 'hg 1/29/2002 11:02'! createAccessOnlineModuleRepositoriesPreference Preferences addPreference: #accessOnlineModuleRepositories category: #modules default: false balloonHelp: 'Should module installation try to access remote network servers? (Otherwise it just uses the local cache.)'! ! !ModuleInstaller class methodsFor: 'preferences' stamp: 'hg 1/29/2002 11:01'! createConservativeModuleDeActivationPreference Preferences addPreference: #conservativeModuleDeActivation category: #modules default: true balloonHelp: 'Use a more conservative and more stable way of installing modifications from DeltaModules into their base modules.'! ! !ModuleInstaller class methodsFor: 'preferences' stamp: 'hg 1/27/2002 17:53'! initialize self createConservativeModuleDeActivationPreference; createAccessOnlineModuleRepositoriesPreference! ! !ModuleRefactorer methodsFor: 'public' stamp: 'hg 1/27/2002 10:33'! runRefactorings "Trigger the whole set of refactorings in this class." self ensurePrerequisiteVersions. self module repository useChangeSetNamed: self class name, ' Reorganization' during: [ self putAwayUnknownModules; moveModules; reorderModules. self moveGlobalsToModules. self installModuleDeclarations. self refactorClasses. self convertPools. self removeModules. self installRepositories. self incrementVersions. Preferences strongModules ifTrue: [Module root rewriteIndirectRefs]. ] ! ! !ModuleRefactorer methodsFor: 'external module declarations' stamp: 'hg 1/27/2002 12:03'! copyDeclarationsFromParent: module module parentModule ifNotNil: [ module parentModule neighborModuleRefs do: [:ref | ref refersToExternalModule ifTrue: [ module addNeighborModule: ref export: nil]]] ! ! !FromVersion0p0000to0001 methodsFor: 'utilities' stamp: 'hg 1/26/2002 18:27'! installRepositories VirtualRootRepository initialize. "Make sure that top-level modules get their own standalone repositories." Module root submodulesDo: [:mod | mod repository beStandalone]. Module squeak submodulesDo: [:mod | mod repository beStandalone]. Module @ #(Squeak Morphic) submodulesDo: [:mod | mod repository beStandalone].! ! !ModuleReference methodsFor: 'resolving' stamp: 'hg 1/19/2002 20:35'! specifiedPath self ensureUnresolved. ^module! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/19/2002 19:48'! createModuleFromPathAndVersion ^self createModuleWithParent: self ensuredParent! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/19/2002 22:50'! createModuleWithParent: parent | mod | mod _ Module fromPath: self specifiedPath forceCreate: true. mod version: self specifiedVersion. self resolveModule. ^mod ! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/27/2002 12:03'! ensureReferenceFrom: mod ^mod neighborModuleRefs detect: [:r | r = self] ifNone: [ mod addNeighborModule: self export: nil. self] ! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/19/2002 19:47'! ensuredParent ^Module fromPath: self specifiedPath allButLast forceCreate: true! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/25/2002 20:35'! ensuredPath "give the path regardless of whether I'm resolved or not" ^self isModuleResolved ifTrue: [self module path] ifFalse: [self module]! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/14/2002 20:41'! resolveModule self isModuleResolved ifFalse: [self findModuleFromPathAndVersion]. ^self isModuleResolved ifTrue: [module]! ! !ModuleReference methodsFor: 'installer support' stamp: 'hg 1/19/2002 19:41'! resolvedModule: mod module _ mod ! ! !ModuleReference methodsFor: 'private' stamp: 'hg 1/19/2002 20:35'! ensureUnresolved (module isKindOf: Array) ifFalse: [ self error: 'Only use this method when I hold a path in my module instvar.'].! ! !DeltaModuleReference methodsFor: 'testing' stamp: 'hg 1/19/2002 22:11'! = otherRef ^(otherRef isMemberOf: self class) and: [ otherRef module = self module]! ! !DeltaModuleReference methodsFor: 'resolving' stamp: 'hg 1/19/2002 20:48'! createModuleWithParent: parentModule | delta | delta _ DeltaModule baseModuleRef: (ModuleReference onPath: self specifiedPathAndVersion) parentModule: parentModule. self parentModule: nil. self resolvedModule: delta. ^self module! ! !DeltaModuleReference methodsFor: 'resolving' stamp: 'hg 1/19/2002 20:39'! ensuredParent "a special trick since deltas can't have aliases anyway" self ensureUnresolved. ^name! ! !DeltaModuleReference methodsFor: 'resolving' stamp: 'hg 1/19/2002 20:36'! parentModule: mod "a special trick since deltas can't have aliases anyway" self ensureUnresolved. name _ mod! ! !DeltaModuleReference methodsFor: 'accessing' stamp: 'hg 1/19/2002 19:51'! alias "DeltaModules can't have aliases" ^nil! ! !DeltaModuleReference methodsFor: 'accessing' stamp: 'hg 1/19/2002 20:47'! hasAlias ^false! ! !ModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/25/2002 21:16'! testCreateModule self setupHomeModule. self verifyHomeModuleExists! ! !ModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/19/2002 19:56'! verifyHomeModuleExists self should: [self homeModule notNil]. self should: [self homeModule parentModule notNil]. self should: [self homeModule parentModule path = self pathForTestModules allButLast].! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 17:39'! globalValue ^42! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 17:38'! globalVarName ^#TestModuleVariable! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 21:43'! globalVarName2 ^(self globalVarName, '2') asSymbol! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 18:26'! testCreateAllModuleContents self setupAllModulesAndContents. self verifyAllModuleContentsSet! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:17'! testCreateClassMethods self testCreateClasses. self toCreateClassMethods. self verifyMetaMethodsWork ! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:08'! testCreateClasses self setupAllModules. self toCreateClasses. self verifyClassesExist! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 18:22'! testCreateGlobals self setupAllModules. self toCreateGlobals. self verifyGlobalsExist; verifyGlobalValues! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 20:21'! testCreateMethods self testCreateClasses. self toCreateMethods. self verifyMethodsWork ! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 21:44'! toCreateAllModuleContents self toCreateClasses; toCreateClassMethods; toCreateMethods; toCreateGlobals! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:24'! toCreateClassMethods self accessParentClass class copy: #parentString from: ModuleTests. self accessDaughterClass class copy: #daughterString from: ModuleTests. self accessDaughterClass class copy: #methodToDelete from: ModuleTests. self accessGrandDaughterClass class copy: #grandDaughterString from: ModuleTests.! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:08'! toCreateClasses self setupParentClass. self setupDaughterClass. self setupGrandDaughterClass.! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 21:44'! toCreateGlobals self betaModule defineName: self globalVarName as: self globalValue export: true. self betaModule defineName: self globalVarName2 as: self globalValue export: true. ! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 21:56'! toCreateMethods self accessParentClass copy: #parentString from: ModuleTests. self accessDaughterClass copy: #daughterString from: ModuleTests. self accessDaughterClass copy: #methodToDelete from: ModuleTests. self accessGrandDaughterClass copy: #grandDaughterString from: ModuleTests.! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/26/2002 13:34'! verifyAllModuleContentsExist self verifyClassesExist; verifyGlobalsExist; "globals should not be initialized" verifyMethodsWork; verifyMetaMethodsWork! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 18:25'! verifyAllModuleContentsSet self verifyAllModuleContentsExist; verifyGlobalValues! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 18:21'! verifyGlobalValues self should: [(self betaModule definitionFor: self globalVarName ifAbsent: [nil]) = self globalValue]. self should: [(self betaModule definitionFor: self globalVarName2 ifAbsent: [nil]) = self globalValue]! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 18:22'! verifyGlobalsExist self should: [self betaModule definesName: self globalVarName ifTrue: [:a|]]. self should: [self betaModule definesName: self globalVarName2 ifTrue: [:a|]]. ! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:28'! verifyMetaMethodsWork self should: [self accessParentClass parentString = self parentString]. self should: [self accessDaughterClass daughterString = self daughterString]. self should: [self accessDaughterClass methodToDelete]. self should: [self accessGrandDaughterClass grandDaughterString = self grandDaughterString]. self should: [self accessDaughterClass parentString = self parentString]. self should: [self accessDaughterClass parentString = self parentString]. self should: [self accessGrandDaughterClass methodToDelete]. ! ! !ModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:28'! verifyMethodsWork self should: [self accessParentClass new parentString = self parentString]. self should: [self accessDaughterClass new daughterString = self daughterString]. self should: [self accessDaughterClass new methodToDelete]. self should: [self accessGrandDaughterClass new grandDaughterString = self grandDaughterString]. self should: [self accessDaughterClass new parentString = self parentString]. self should: [self accessDaughterClass new parentString = self parentString]. self should: [self accessGrandDaughterClass new methodToDelete]. ! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/26/2002 19:59'! allModules ^{self betaModule. self alphaModule. self homeModule}! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 18:16'! betaModule ^Module @ self betaModulePath ! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 18:15'! betaModulePath ^self pathForTestModules copyWith: self betaModuleName! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/12/2002 20:13'! setUp self tearDown ! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/13/2002 18:06'! setupAllModulesAndContents self setupAllModules. self toCreateAllModuleContents. ! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 19:19'! setupHomeModule | testHomePath | testHomePath _ self pathForTestModules. self assert: self homeModule isNil. Module fromPath: testHomePath forceCreate: true. self deny: self homeModule isNil. ! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/26/2002 20:00'! tearDown self shield: [ Module smalltalk removeName: self pathForTestModules last; removeName: self alphaModuleName; removeName: self betaModuleName; removeName: self globalVarName; removeName: self parentClassName; removeName: self daughterClassName; removeName: self grandDaughterClassName]. self allModules do: [:module | (module notNil and: [module isKindOf: Module]) ifTrue: [self shield: [module cleanOutModule]]]. Module @ self pathForTestModules allButLast ifNotNilDo: [:m | self shield: [ m removeNeighborModule: self homeModule]]. self allModules do: [:module | self assert: module isNil].! ! !ModuleTests methodsFor: 'sample modules' stamp: 'hg 1/13/2002 21:54'! unloadModules self assert: self homeModule notNil. ModuleInstaller unload: self homeModule. ! ! !ModuleTests methodsFor: 'sample methods' stamp: 'hg 1/11/2002 20:18'! daughterString ^'daughter'! ! !ModuleTests methodsFor: 'sample methods' stamp: 'hg 1/11/2002 20:18'! grandDaughterString ^'grandDaughter'! ! !ModuleTests methodsFor: 'sample methods' stamp: 'hg 1/12/2002 21:56'! methodToDelete ^true! ! !ModuleTests methodsFor: 'sample methods' stamp: 'hg 1/11/2002 20:17'! parentString ^'parent'! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:14'! accessDaughterDeltaClass ^self deltaForBeta deltaClassFor: self accessDaughterClass forceCreate: false! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:14'! accessGrandDaughterDeltaClass ^self deltaForAlpha deltaClassFor: self accessGrandDaughterClass forceCreate: false! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 18:39'! deltaGlobalValue ^43! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:09'! toCreateDeltaClasses self deltaForBeta deltaClassFor: self accessDaughterClass forceCreate: true. self deltaForAlpha deltaClassFor: self accessGrandDaughterClass forceCreate: true. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/26/2002 13:46'! toCreateDeltaGlobals "to modify" self deltaForBeta defineName: self globalVarName as: self deltaGlobalValue export: true. "to remove" self deltaForBeta defineName: self globalVarName2 as: DeltaModule valueForUndefined export: true. "to create (doesn't exist)" self deltaForAlpha defineName: self globalVarName as: self deltaGlobalValue export: true. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 21:31'! toCreateDeltaMethods | impl | impl _ self class classThatUnderstands: #daughterString. self accessDaughterDeltaClass copy: #daughterString from: impl. self accessDaughterDeltaClass copy: #methodToAdd from: DeltaModuleTests. self accessDaughterDeltaClass undefinedSelectors: #(methodToDelete). self accessGrandDaughterDeltaClass copy: #grandDaughterString from: impl.! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/19/2002 21:25'! toCreateDeltaModuleContents self toCreateAllModuleContents; toCreateDeltaClasses; toCreateDeltaMethods; toCreateMetaDeltaMethods; toCreateDeltaGlobals. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 21:33'! toCreateMetaDeltaMethods | impl | impl _ self class classThatUnderstands: #daughterString. self accessDaughterDeltaClass deltaForMetaclass copy: #daughterString from: impl. self accessDaughterDeltaClass deltaForMetaclass copy: #methodToAdd from: DeltaModuleTests. self accessDaughterDeltaClass deltaForMetaclass undefinedSelectors: #(methodToDelete). self accessGrandDaughterDeltaClass deltaForMetaclass copy: #grandDaughterString from: impl.! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:28'! validateDeltaClasses self should: [self accessDaughterDeltaClass notNil]. self should: [self accessGrandDaughterDeltaClass notNil]. self should: [self accessDaughterDeltaClass superclass == self accessParentClass]. self should: [self accessGrandDaughterDeltaClass superclass == self accessDaughterClass]. self shouldnt: [self accessDaughterDeltaClass deltaForMetaclass == self accessDaughterDeltaClass superclass]. self shouldnt: [self accessGrandDaughterDeltaClass deltaForMetaclass == self accessGrandDaughterDeltaClass superclass]. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/11/2002 22:38'! verifyClassMethodsWork self should: [self accessParentClass parentString = super parentString]. self should: [self accessDaughterClass daughterString = super daughterString]. self should: [self accessGrandDaughterClass grandDaughterString = super grandDaughterString].! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/26/2002 14:01'! verifyDeltaGlobalsExist self should: [self deltaForBeta definesName: self globalVarName ifTrue: [:a|]]. self should: [self deltaForBeta definesName: self globalVarName2 ifTrue: [:a|]]. self should: [(self deltaForBeta definitionFor: self globalVarName2 ifAbsent: [nil]) == DeltaModule valueForUndefined]. self should: [self deltaForAlpha definesName: self globalVarName ifTrue: [:a|]]. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/13/2002 21:38'! verifyDeltaGlobalsSet self should: [(self deltaForBeta definitionFor: self globalVarName ifAbsent: [nil]) = self deltaGlobalValue]. self should: [(self deltaForAlpha definitionFor: self globalVarName ifAbsent: [nil]) = self deltaGlobalValue]! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/26/2002 14:18'! verifyDeltaModuleContents self validateDeltaClasses; verifyMethodsInDelta; verifyMethodsInMetaDelta; verifyDeltaGlobalsExist . ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:32'! verifyMetaMethodsWork self should: [self accessParentClass parentString = super parentString]. self should: [self accessDaughterClass daughterString = super daughterString]. self should: [self accessDaughterClass methodToDelete]. self shouldnt: [self accessDaughterClass respondsTo: #methodToAdd]. self should: [self accessGrandDaughterClass grandDaughterString = super grandDaughterString]. self should: [self accessGrandDaughterClass daughterString = super daughterString]. self should: [self accessGrandDaughterClass methodToDelete]. ! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:10'! verifyMethodsInDelta self shouldnt: [(self accessDaughterDeltaClass methodDict at: #daughterString ifAbsent: [nil]) isNil]. self shouldnt: [(self accessDaughterDeltaClass methodDict at: #methodToAdd ifAbsent: [nil]) isNil]. self shouldnt: [(self accessDaughterDeltaClass methodDict at: #methodToDelete ifAbsent: [3]) = 3]. self shouldnt: [(self accessGrandDaughterDeltaClass methodDict at: #grandDaughterString ifAbsent: [nil]) isNil].! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:13'! verifyMethodsInMetaDelta self shouldnt: [(self accessDaughterDeltaClass deltaForMetaclass methodDict at: #daughterString ifAbsent: [nil]) isNil]. self shouldnt: [(self accessDaughterDeltaClass deltaForMetaclass methodDict at: #methodToAdd ifAbsent: [nil]) isNil]. self shouldnt: [(self accessDaughterDeltaClass deltaForMetaclass methodDict at: #methodToDelete ifAbsent: [3]) = 3]. self shouldnt: [(self accessGrandDaughterDeltaClass deltaForMetaclass methodDict at: #grandDaughterString ifAbsent: [nil]) isNil].! ! !DeltaModuleTests methodsFor: 'module contents' stamp: 'hg 1/12/2002 22:31'! verifyMethodsWork self should: [self accessParentClass new parentString = super parentString]. self should: [self accessDaughterClass new daughterString = super daughterString]. self should: [self accessDaughterClass new methodToDelete]. self shouldnt: [self accessDaughterClass new respondsTo: #methodToAdd]. self should: [self accessGrandDaughterClass new grandDaughterString = super grandDaughterString]. self should: [self accessGrandDaughterClass new daughterString = super daughterString]. self should: [self accessGrandDaughterClass new methodToDelete]. ! ! !DeltaModuleTests methodsFor: 'sample methods' stamp: 'hg 1/11/2002 22:35'! daughterString ^'daughter2'! ! !DeltaModuleTests methodsFor: 'sample methods' stamp: 'hg 1/11/2002 22:35'! grandDaughterString ^'grandDaughter2'! ! !DeltaModuleTests methodsFor: 'sample methods' stamp: 'hg 1/12/2002 22:03'! methodToAdd ^true! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/26/2002 20:07'! allDeltaTestModules ^{self deltaForAlpha. self deltaForBeta. self ownerModule}! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 20:58'! deltaForAlpha ^self deltaForAlphaRef ifNotNilDo: [:ref | ref module]! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 20:58'! deltaForBeta ^self deltaForBetaRef ifNotNilDo: [:ref | ref module]! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/11/2002 20:28'! ownerModule ^Module @ self ownerModulePath! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/11/2002 22:22'! ownerModulePath ^#(Temporary DeltaModuleTestingRange)! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/13/2002 21:50'! setupDeltaModules self setupOwnerModule. self ownerModule deltaModuleForBase: self alphaModule forceCreate: true asActive: false. self ownerModule deltaModuleForBase: self betaModule forceCreate: true asActive: false. ! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/13/2002 21:50'! setupOwnerModule self assert: self ownerModule isNil. Module fromPath: self ownerModulePath forceCreate: true. ! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/26/2002 20:07'! tearDown super tearDown. self shield: [ Module smalltalk removeName: self ownerModulePath last]. self allDeltaTestModules do: [:module | (module notNil and: [module isKindOf: Module]) ifTrue: [self shield: [module cleanOutModule]]]. Module @ self ownerModulePath allButLast ifNotNilDo: [:m | self shield: [ m removeNeighborModule: self ownerModule]]. self allDeltaTestModules do: [:module | self assert: module isNil]! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/14/2002 20:34'! unloadModules super unloadModules. self ownerModule ifNotNil: [ ModuleInstaller unload: self ownerModule]. ! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 18:09'! verifyDeltaModuleRefs self should: [self deltaForAlphaRef notNil]. self should: [self deltaForBetaRef notNil]. self shouldnt: [self deltaForAlphaRef isModuleResolved]. self shouldnt: [self deltaForBetaRef isModuleResolved].! ! !DeltaModuleTests methodsFor: 'sample modules' stamp: 'hg 1/19/2002 18:32'! verifyDeltaModules self should: [self deltaForAlpha notNil]. self should: [self deltaForBeta notNil]. self should: [self ownerModule deltaModules size = 2]. self should: [self deltaForAlpha baseModule = self alphaModule]. self should: [self deltaForBeta baseModule = self betaModule]. ! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/11/2002 22:17'! testCreateDeltaClasses self testCreateDeltaModules. self toCreateClasses; toCreateDeltaClasses. self validateDeltaClasses! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/19/2002 21:30'! testCreateDeltaGlobals self testCreateDeltaModules. self toCreateGlobals; toCreateDeltaGlobals. self verifyDeltaGlobalsExist; verifyDeltaGlobalsSet! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/11/2002 22:44'! testCreateDeltaMethods self testCreateDeltaClasses. self toCreateDeltaMethods. self verifyMethodsInDelta ! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/12/2002 18:29'! testCreateDeltaModuleContents self testCreateDeltaModules. self toCreateDeltaModuleContents. self verifyDeltaModuleContents! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/19/2002 18:32'! testCreateDeltaModules self testResolveDeltaBaseModuleRefs. self verifyDeltaModules! ! !DeltaModuleTests methodsFor: 'module creation tests' stamp: 'hg 1/12/2002 22:14'! testCreateMetaDeltaMethods self testCreateDeltaClasses. self toCreateMetaDeltaMethods. self verifyMethodsInMetaDelta ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 17:59'! testActivateDeactivateDeltaModules self testActivateDeltaModules. ModuleInstaller deactivate: self ownerModule. self verifyDeactivatedDeltaModulesWork! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 21:36'! testActivateDeactivateDeltaModulesThreeTimes | assoc | self testActivateDeactivateDeltaModules. ModuleInstaller testActivate: self ownerModule. self verifyActivatedDeltaModulesWork. assoc _ self alphaModule associationFor: self globalVarName ifAbsent: [nil]. ModuleInstaller testDeactivate: self ownerModule. self verifyDeactivatedDeltaModulesWork. ModuleInstaller testActivate: self ownerModule. self verifyActivatedDeltaModulesWork. self should: [assoc == (self alphaModule associationFor: self globalVarName ifAbsent: [])]. ModuleInstaller testDeactivate: self ownerModule. self verifyDeactivatedDeltaModulesWork! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/13/2002 21:04'! testActivateDeltaGlobals self testCreateDeltaGlobals. ModuleInstaller testActivate: self ownerModule. self verifyActivatedDeltaGlobals! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:15'! testActivateDeltaMethods self testCreateDeltaMethods; toCreateMetaDeltaMethods; toCreateMethods. ModuleInstaller testActivate: self ownerModule. self verifyActivatedDeltaMethodsWork; verifyActivatedMetaDeltaMethodsWork! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 20:22'! testActivateDeltaModules self testCreateDeltaModuleContents. ModuleInstaller testActivate: self ownerModule. self verifyActivatedDeltaModulesWork! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:25'! testDeactivateDeltaMethods self testCreateDeltaMethods; toCreateMetaDeltaMethods; toCreateMethods; toCreateClassMethods. ModuleInstaller deactivate: self ownerModule. self verifyDeactivatedDeltaMethodsWork; verifyDeactivatedMetaDeltaMethodsWork! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 17:58'! testDeactivateDeltaModules self testCreateDeltaModules; toCreateDeltaModuleContents. ModuleInstaller deactivate: self ownerModule. self verifyDeactivatedDeltaModulesWork ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/26/2002 14:02'! verifyActivatedDeltaGlobals self should: [(self betaModule perform: self globalVarName) = self deltaGlobalValue]. self shouldnt: [self betaModule definesName: self globalVarName2 ifTrue: [:a | ]]. self should: [(self alphaModule perform: self globalVarName) = self deltaGlobalValue]. self should: [(self deltaForBeta localAssocFor: self globalVarName ifAbsent: []) deactivatedValue = self globalValue]. self should: [(self deltaForBeta localAssocFor: self globalVarName2 ifAbsent: []) deactivatedValue isKindOf: LookupKey]. "should preserve the association" self should: [(self deltaForAlpha localAssocFor: self globalVarName ifAbsent: []) deactivatedValue = DeltaModule valueForUndefined]. ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:29'! verifyActivatedDeltaMethodsWork self should: [self accessDaughterClass new daughterString = self daughterString]. self should: [self accessDaughterClass new methodToAdd]. self shouldnt: [self accessDaughterClass new respondsTo: #methodToDelete]. self should: [self accessGrandDaughterClass new grandDaughterString = self grandDaughterString]. self should: [self accessGrandDaughterClass new daughterString = self daughterString]. self should: [self accessGrandDaughterClass new methodToAdd]. ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 18:04'! verifyActivatedDeltaModulesWork self verifyActivatedDeltaMethodsWork; verifyActivatedDeltaGlobals! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:30'! verifyActivatedMetaDeltaMethodsWork self should: [self accessDaughterClass daughterString = self daughterString]. self should: [self accessDaughterClass methodToAdd]. self shouldnt: [self accessDaughterClass respondsTo: #methodToDelete]. self should: [self accessGrandDaughterClass grandDaughterString = self grandDaughterString]. self should: [self accessGrandDaughterClass daughterString = self daughterString]. self should: [self accessGrandDaughterClass methodToAdd]. ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 21:51'! verifyDeactivatedDeltaGlobals self should: [(self betaModule localAssocFor: self globalVarName ifAbsent: [nil]) notNil]. self should: [(self betaModule localAssocFor: self globalVarName2 ifAbsent: [nil]) notNil]. self should: [(self betaModule perform: self globalVarName) = self globalValue]. self should: [(self betaModule perform: self globalVarName2) = self globalValue]. self should: [(self alphaModule localAssocFor: self globalVarName ifAbsent: [nil]) isNil]. ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:02'! verifyDeactivatedDeltaMethodsWork self verifyMethodsWork ! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 18:04'! verifyDeactivatedDeltaModulesWork self verifyDeactivatedDeltaMethodsWork; verifyDeactivatedDeltaGlobals! ! !DeltaModuleTests methodsFor: 'de/activate tests' stamp: 'hg 1/12/2002 22:16'! verifyDeactivatedMetaDeltaMethodsWork self verifyMetaMethodsWork ! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/25/2002 20:37'! deltaForAlphaRef self ownerModule ifNil: [^nil]. ^self ownerModule neighborModuleRefs detect: [:ref | (ref isModuleResolved ifFalse: [ref module] ifTrue: [ref module baseModuleRef ensuredPath]) = self alphaModulePath] ifNone: [nil]! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/25/2002 20:39'! deltaForBetaRef self ownerModule ifNil: [^nil]. ^self ownerModule neighborModuleRefs detect: [:ref | (ref isModuleResolved ifFalse: [ref module] ifTrue: [ref module baseModuleRef ensuredPath]) = self betaModulePath] ifNone: [nil]! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/19/2002 20:52'! setupDeltaModuleRefs self assert: self ownerModule deltaModules isEmpty. self ownerModule deltaModuleOn: self alphaModulePath alias: nil version: nil importNames: false. self ownerModule deltaModuleOn: self betaModulePath alias: nil version: nil importNames: false. ! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/19/2002 20:16'! setupDeltaModulesDirectly self assert: self ownerModule deltaModules isEmpty. self verifySubmodulesExist. self ownerModule deltaModuleForBase: self alphaModule forceCreate: true asActive: false. self ownerModule deltaModuleForBase: self betaModule forceCreate: true asActive: false. ! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/19/2002 20:51'! testCreateDeltaModuleRefs "test creating ModuleReferences that should be unresolved unless they are asked to resolve themselves" self setupOwnerModule. self setupDeltaModuleRefs. self verifyDeltaModuleRefs ! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/19/2002 20:16'! testCreateDeltaModulesDirectly "test creating ModuleReferences that should be unresolved unless they are asked to resolve themselves" self testCreateSubmodules. self setupOwnerModule. self setupDeltaModulesDirectly. self verifyDeltaModules ! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/19/2002 20:54'! testResolveDeltaBaseModuleRefs self testResolveDeltaModuleRefs. self should: [self deltaForAlpha baseModuleRef findModuleFromPathAndVersion isNil]. self should: [self deltaForBeta baseModuleRef findModuleFromPathAndVersion isNil]. self testCreateSubmodules. self should: [self deltaForAlpha baseModuleRef findModuleFromPathAndVersion notNil]. self should: [self deltaForBeta baseModuleRef findModuleFromPathAndVersion notNil]. self should: [self deltaForAlpha baseModuleRef isModuleResolved]. self should: [self deltaForBeta baseModuleRef isModuleResolved].! ! !DeltaModuleTests methodsFor: 'module resolution' stamp: 'hg 1/26/2002 13:30'! testResolveDeltaModuleRefs self testCreateDeltaModuleRefs. self should: [self deltaForAlphaRef findModuleFromPathAndVersion isNil]. self should: [self deltaForBetaRef findModuleFromPathAndVersion isNil]. self should: [self deltaForAlphaRef createModuleFromPathAndVersion notNil]. self should: [self deltaForBetaRef createModuleFromPathAndVersion notNil]. self should: [self deltaForAlphaRef isModuleResolved]. self should: [self deltaForBetaRef isModuleResolved]. ! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/16/2002 21:26'! testCompositeStoreDeltaModulesInCache self toTestStoreModules: false deltas: true inCache: true! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/9/2002 18:30'! testCompositeStoreModulesInCache self toTestStoreModules: false inCache: true! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/29/2002 10:49'! testLoadModulesFromCache "this is just a test to verify that loading problems are unrelated to the ModuleInstaller. The code here is not how loading is meant to be done." self testCompositeStoreModulesInCache. self unloadModules. self setupHomeModule. Preferences setFlag: #accessOnlineModuleRepositories toValue: false during: [ self homeModule repository cache defineCompositeModulesFromFile; loadModuleContents]. self verifyAllModuleContentsExist! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/16/2002 21:27'! testStandaloneStoreDeltaModulesInCache self toTestStoreModules: true deltas: true inCache: true! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/9/2002 18:31'! testStandaloneStoreModulesInCache self toTestStoreModules: true inCache: true! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/29/2002 10:42'! toTestStoreModules: standalone deltas: includeDeltas inCache: inCache | warnings repository deltaRepository repositoryCount deltaRepositoryCount allRepositories | includeDeltas ifTrue: [self testCreateDeltaModuleContents] ifFalse: [self testCreateAllModuleContents]. standalone ifTrue: [self setupStandaloneRepositories]. repository _ self homeModule repository. includeDeltas ifTrue: [deltaRepository _ self ownerModule repository]. inCache ifTrue: [ repository _ repository cache. includeDeltas ifTrue: [deltaRepository _ deltaRepository cache]]. repositoryCount _ standalone ifTrue: [3] ifFalse: [1]. deltaRepositoryCount _ standalone ifTrue: [3] ifFalse: [1]. allRepositories _ standalone ifTrue: [self allModules collect: [:m | m repository]] ifFalse: [{self homeModule repository}]. includeDeltas ifTrue: [ allRepositories _ allRepositories , (standalone ifTrue: [self allDeltaTestModules collect: [:m | m repository]] ifFalse: [{self ownerModule repository}])]. inCache ifTrue: [allRepositories _ allRepositories collect: [:r | r cache]]. self shouldnt: [repository checkRepositoryExists]. self shouldnt: [repository checkDefinitionFileOK]. "self shouldnt: [repository checkContentsFilesOK]." self shouldnt: [repository checkCompleteModuleContentsOK]. "catch missing dependencies warning and verify the number of times it occurs" warnings _ 0. Preferences setFlag: #accessOnlineModuleRepositories toValue: inCache not during: [ [repository ensureDeepUpload] on: Warning do: [:ex | warnings _ warnings + 1. ex resume: true]. self should: [warnings = repositoryCount]. warnings _ 0. includeDeltas ifTrue: [ [deltaRepository ensureDeepUpload] on: Warning do: [:ex | warnings _ warnings + 1. ex resume: true]. self should: [warnings = 0]]. allRepositories do: [:rep | self should: [rep checkRepositoryExists]. self should: [rep checkDefinitionFileOK]. self should: [rep checkContentsFilesOK]. self should: [rep checkCompleteModuleContentsOK]]. ]. self should: [standalone = (repository compositeModules size = 1)]. self should: [includeDeltas ==> [standalone = (deltaRepository compositeModules size = 1)]]. self should: [repository compositeModules ~~ repositoryCount]. self should: [ includeDeltas ==> [deltaRepository compositeModules ~~ deltaRepositoryCount]]. ! ! !ModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/13/2002 20:57'! toTestStoreModules: standalone inCache: inCache self toTestStoreModules: standalone deltas: false inCache: inCache! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/9/2002 18:33'! testInstallCompositeModulesFromCache self toTestInstallModulesStandalone: false fromCache: true forPath: self pathForTestModules ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/9/2002 18:33'! testInstallCompositeModulesOutOfOrderFromCache self toTestInstallModulesStandalone: false fromCache: true forPath: self alphaModulePath ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/9/2002 18:34'! testInstallStandaloneModulesFromCache self toTestInstallModulesStandalone: true fromCache: true forPath: self pathForTestModules ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/9/2002 18:34'! testInstallStandaloneModulesOutOfOrderFromCache self toTestInstallModulesStandalone: true fromCache: true forPath: self alphaModulePath ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/29/2002 10:43'! toTestInstallModulesStandalone: standalone fromCache: fromCache forPath: path self toTestStoreModules: standalone inCache: fromCache. self unloadModules. self verifyTestModulesNotPresent. fromCache ifFalse: [self deleteCacheDirectories]. Preferences setFlag: #accessOnlineModuleRepositories toValue: fromCache not during: [ installerObject _ ModuleInstaller testFullyInstallFromPath: path]. self verifyAllModuleDefinitionsLoaded. self verifyAllModuleContentsLoaded. self verifyAllModuleContentsExist ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/26/2002 20:11'! verifyAllModuleContentsLoaded self should: [installerObject loadedModules asSet = self allModules asSet] ! ! !ModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/26/2002 20:12'! verifyAllModuleDefinitionsLoaded self should: [installerObject definedModules asSet = self allModules asSet] ! ! !ModuleStorageTests methodsFor: 'repository tests' stamp: 'hg 1/26/2002 18:27'! testStandaloneRepository self setupAllModules. self alphaModule repository beStandalone. self should: [self alphaModule repository isStandalone]. self shouldnt: [self alphaModule repository isImplicit]. self should: [self alphaModule repository standaloneRepository == self alphaModule repository]. ! ! !ModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/26/2002 19:08'! deleteCacheDirectories super tearDown. self setupAllModules. self shield: [self homeModule repository cache deepDeleteDirectory]. self deny: self homeModule repository cache directory exists. self setupDeltaModules. self shield: [self ownerModule repository cache deepDeleteDirectory]. self deny: self ownerModule repository cache directory exists! ! !ModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/26/2002 20:02'! setupStandaloneRepositories self allModules do: [:module | module repository beStandalone]. self ownerModule ifNotNil: [ self allDeltaTestModules do: [:module | module repository beStandalone]]. self verifyStandaloneRepositories! ! !ModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/13/2002 17:51'! tearDown self deleteCacheDirectories. super tearDown.! ! !ModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/26/2002 20:06'! verifyStandaloneRepositories self allModules do: [:m | self assert: m repository isStandalone]. self ownerModule ifNotNil: [ self allDeltaTestModules do: [:m | self assert: m repository isStandalone]].! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/14/2002 20:49'! testInstallCompositeDeltaModulesFromCache self toTestInstallDeltaModulesStandalone: false fromCache: true forPath: self ownerModulePath ! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/14/2002 20:49'! testInstallStandaloneDeltaModulesFromCache self toTestInstallDeltaModulesStandalone: true fromCache: true forPath: self ownerModulePath ! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/29/2002 10:49'! testLoadDeltaModulesFromCache "this is just a test to verify that loading problems are unrelated to the ModuleInstaller. The code here is not how loading is meant to be done." self testCompositeStoreDeltaModulesInCache. self unloadModules. self setupHomeModule. Preferences setFlag: #accessOnlineModuleRepositories toValue: false during: [ self homeModule repository cache defineCompositeModulesFromFile; loadModuleContents. self verifyAllModuleContentsExist. self setupOwnerModule. self ownerModule repository cache defineCompositeModulesFromFile. self deltaForAlpha baseModuleRef resolveModule. self deltaForBeta baseModuleRef resolveModule. self ownerModule repository cache loadModuleContents]. self verifyDeltaModuleContents! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/29/2002 10:54'! toTestInstallDeltaModulesStandalone: standalone fromCache: fromCache forPath: path self toTestStoreModules: standalone deltas: true inCache: fromCache. self unloadModules. self verifyTestModulesNotPresent. fromCache ifFalse: [self deleteCacheDirectories]. Preferences setFlag: #accessOnlineModuleRepositories toValue: false during: [ installerObject _ ModuleInstaller testFullyInstallFromPath: path]. self verifyAllDeltaModuleDefinitionsLoaded. self verifyAllDeltaModuleContentsLoaded. self verifyDeltaModuleContents ! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/26/2002 20:11'! verifyAllDeltaModuleContentsLoaded self should: [installerObject loadedModules asSet = (self allModules, self allDeltaTestModules) asSet] ! ! !ModuleStorageTests methodsFor: 'delta tests' stamp: 'hg 1/26/2002 20:11'! verifyAllDeltaModuleDefinitionsLoaded self should: [installerObject definedModules asSet = (self allModules, self allDeltaTestModules) asSet] ! ! !Preferences class methodsFor: 'misc' stamp: 'hg 1/29/2002 10:42'! setFlag: prefSymbol toValue: aBoolean during: aBlock "Set the flag to the given value for the duration of aBlock" | existing | existing _ self valueOfFlag: prefSymbol. existing == aBoolean ifFalse: [self setPreference: prefSymbol toValue: aBoolean]. aBlock ensure: [ existing == aBoolean ifFalse: [self setPreference: prefSymbol toValue: existing]]! ! !RemoteModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/13/2002 17:49'! testCompositeStoreModulesRemotely self toTestStoreModules: false inCache: false! ! !RemoteModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/29/2002 10:55'! testLoadModulesRemotely "this is just a test to verify that loading problems are unrelated to the ModuleInstaller. The code here is not how loading is meant to be done." self testStandaloneStoreModulesRemotely. self unloadModules. self deleteCacheDirectories. self setupHomeModule. Preferences setFlag: #accessOnlineModuleRepositories toValue: false during: [ self homeModule repository defineCompositeModulesFromFile; loadModuleContents]. ! ! !RemoteModuleStorageTests methodsFor: 'storage tests' stamp: 'hg 1/13/2002 17:48'! testStandaloneStoreModulesRemotely self toTestStoreModules: true inCache: false! ! !RemoteModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/13/2002 17:49'! testInstallCompositeModulesOutOfOrderRemotely self toTestInstallModulesStandalone: false fromCache: false forPath: self alphaModulePath ! ! !RemoteModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/13/2002 17:49'! testInstallCompositeModulesRemotely self toTestInstallModulesStandalone: false fromCache: false forPath: self pathForTestModules ! ! !RemoteModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/13/2002 17:50'! testInstallStandaloneModulesOutOfOrderRemotely self toTestInstallModulesStandalone: true fromCache: false forPath: self alphaModulePath ! ! !RemoteModuleStorageTests methodsFor: 'installer tests' stamp: 'hg 1/13/2002 17:50'! testInstallStandaloneModulesRemotely self toTestInstallModulesStandalone: true fromCache: false forPath: self pathForTestModules ! ! !RemoteModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/13/2002 17:50'! deleteRemoteDirectories super tearDown. self setupAllModules. self shield: [self homeModule repository deepDeleteDirectory]. self deny: self homeModule repository directory exists! ! !RemoteModuleStorageTests methodsFor: 'sample repositories' stamp: 'hg 1/13/2002 17:50'! tearDown self deleteCacheDirectories; deleteRemoteDirectories. super tearDown.! ! !Repository methodsFor: 'accessing' stamp: 'hg 1/16/2002 21:49'! subrepositories "need to handle repository cache here" ^self module submodules, self module deltaModules collect: [:mod | self isCache ifFalse: [mod repository] ifTrue: [mod repository cache]]! ! !Repository methodsFor: 'file names' stamp: 'hg 1/16/2002 21:58'! localName "be semi-sophisticated about shortening" | str max name | str _ self module name asString. max _ FileDirectory maxFileNameLength. name _ str size > max ifFalse: [str] ifTrue: [(str first: 4), '=', (str last: max - 4 - 1)]. ^name! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/27/2002 21:55'! compositeContentsOn: aStream "take various measures to ensure that necessary preconditions are met." | n compositeModulesInOrder | self standaloneCheck. self ensurePreconditionsForUpload. compositeModulesInOrder _ ModuleInstaller new orderWithinCompositeFor: self compositeModules. 'Uploading ', self module pathAsMessages displayProgressAt: Sensor cursorPoint from: 0 to: self compositeModules size during: [:bar | n _ 0. aStream timeStamp. compositeModulesInOrder do: [:mod | aStream cr; cr; nextChunkPut: '#nextCompositeModule'; space; nextChunkPut: (self prefixForModule: mod); cr; cr. mod repository contentsOn: aStream. bar value: (n_ n+1). aStream flush]]! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/26/2002 19:38'! compositeDefinitionsOn: aStream "Write a complete definition of all the modules in this repository, with metainformation and a timestamp." | idPrefix | aStream timeStamp; cr. aStream nextChunkPut: self metaPrerequisites; cr; cr. self compositeModules do: [:mod | idPrefix _ self prefixForModule: mod. aStream nextPutAll: idPrefix, mod definition; nextPut: $;; crtab; nextChunkPut: 'yourself.'; cr; cr].! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/27/2002 11:49'! contentsOn: aStream "Write a complete definition of this module, with metainformation and a timestamp." | classes | self module definedNames keysAndValuesDo: [:key :value | (value isBehavior or: [value isKindOf: Module]) ifFalse: [ aStream nextChunkPut: 'self ', (self module variableDefinitionFor: key); cr; cr]]. classes _ OrderedCollection new. self module allClassesDo: [:class | classes add: class]. (ChangeSet superclassOrder: classes) do: [:class | aStream nextChunkPut: (self module classDefinitionFor: class); cr; cr]. self module fileOutMethodsOn: aStream moveSource: false toFile: 0! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/27/2002 10:20'! fileInModuleContentsFileInto: topModule | targetModule value | "self notify: 'Warning: You are about to load the contents of module ', topModule pathAsMessages asText allBold, ' from the repository. Any unsaved contents in this module will be lost.'." self useChangeSetNamed: 'Module Loading' during: [ self namesOfContentsFiles do: [:name | targetModule _ topModule. "make name lookup be done in the scope of the target module" Module scopeModuleInstance: targetModule. self fileInChunks: (self oldStreamNamed: name) into: topModule chunkBlock: [:string :stream :isClassCategory | value _ Compiler evaluate: string for: targetModule logged: false. "Class category chunk followed by method definition" isClassCategory ifTrue: [value scanFrom: stream]. "tag indicating that new (composite) module should receive definitions, followed by expression defining the new receiver" value = #nextCompositeModule ifTrue: [ targetModule allClassesDo: [ :cl | cl removeSelectorSimply: #DoIt; removeSelectorSimply: #DoItIn:]. Module scopeModuleInstance: topModule. targetModule _ Compiler evaluate: stream nextChunk for: topModule logged: false. Module scopeModuleInstance: targetModule]]. Module scopeModuleInstance: nil. targetModule allClassesDo: [ :cl | cl removeSelectorSimply: #DoIt; removeSelectorSimply: #DoItIn:]. topModule class removeSelectorSimply: #DoIt; removeSelectorSimply: #DoItIn:. ]]. "answer the modules that were loaded" ^self compositeModules ! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/26/2002 19:17'! fileInModuleDefinitionFile: mod | fileName result | fileName _ mod repository moduleFileNameForExtension: self moduleDefinitionExtension. self fileInChunks: (self oldStreamNamed: fileName) into: mod chunkBlock: [:string :stream :isCategory | result _ Compiler evaluate: string for: mod logged: false. (result isKindOf: Module) ifTrue: [ self prepareForCompositeLoading: result]. (result isKindOf: Array) ifTrue: [ self metaPrerequisites: result]]. self cleanupAfterCompositeLoading. ! ! !Repository methodsFor: 'fileIn/Out' stamp: 'hg 1/27/2002 11:25'! useChangeSetNamed: changeSetName during: aBlock | priorChanges | priorChanges _ Smalltalk changes. Smalltalk newChanges: (ChangeSorter existingOrNewChangeSetNamed: changeSetName). aBlock ensure: [Smalltalk newChanges: priorChanges] ! ! !Repository methodsFor: 'testing' stamp: 'hg 1/27/2002 18:39'! workOffline ^Preferences accessOnlineModuleRepositories not! ! !Repository methodsFor: 'composite repositories' stamp: 'hg 1/27/2002 18:43'! cleanupAfterCompositeLoading "cf. prepareForCompositeLoading: -- need to remove non-composite module objects that were created." | modulesToDestroy ref | "first ensure that I have no 'spurious' composite modules" self compositeModules do: [:mod | mod repository repositoryToUse defineAsStandaloneOrNotFromDirectoryStructure]. modulesToDestroy _ self module deepSubAndDeltaModules difference: self compositeModules. modulesToDestroy do: [:mod | ref _ mod parentModule refForNeighborModule: mod. ref refersToDeltaModule ifFalse: [ref resolvedModule: mod path] ifTrue: [ ref resolvedModule: mod baseModuleRef ensuredPath. ref parentModule: mod parentModule]].! ! !Repository methodsFor: 'composite repositories' stamp: 'hg 1/27/2002 18:48'! defineAsStandaloneOrNotFromDirectoryStructure "Define the correct status of this repository by looking on disk etc., to find out if I am standalone or not" "if I am already defined as standalone then I am ok" self isStandalone ifTrue: [^self]. "ensure that my parent is ok" self parentRepository defineAsStandaloneOrNotFromDirectoryStructure. "perform the actual check and operation" (self checkRepositoryExists and: [self checkDefinitionExists]) ifTrue: [self module repository beStandalone]. ! ! !Repository methodsFor: 'composite repositories' stamp: 'hg 1/16/2002 21:54'! prefixForModule: mod | relativePath prefix prefixModule | self flag: #deltaModuleFor: . mod == self module ifTrue: [^'self ']. prefixModule _ mod isDeltaModule ifFalse: [mod] ifTrue: [mod parentModule]. relativePath _ prefixModule path allButFirst: self module path size. prefix _ 'self ', (relativePath inject: '' into: [:str :local | str, local, ' ']). ^mod isDeltaModule ifFalse: [prefix] ifTrue: [ '(', prefix, 'deltaModuleFor: ', mod baseModule path literalPrintString, ') '] ! ! !Repository methodsFor: 'installer support' stamp: 'hg 1/27/2002 17:43'! checkDefinitionExists ^self checkDefinitionFileOK "or: -- e.g. an ImageSegment"! ! !Repository methodsFor: 'installer support' stamp: 'hg 12/16/2001 22:46'! detectImproperlyDeclaredModules: modulesToCheck | unresolved n incomplete | 'Detecting incomplete module dependencies...' displayProgressAt: Sensor cursorPoint from: 0 to: modulesToCheck size during: [:bar | n _ 0. incomplete _ modulesToCheck select: [:mod | unresolved _ mod localUnresolvedRefsWithScheme: mod weakOrStrongBindingScheme. bar value: (n_ n+1). unresolved isEmpty not]]. ^incomplete ! ! !Repository methodsFor: 'up- and downloading' stamp: 'hg 1/26/2002 18:48'! defineCompositeModulesFromFile self isImplicit ifTrue: [^self standaloneRepository defineCompositeModulesFromFile]. self ensureDefinitionOK. self fileInModuleDefinitionFile: self module. ^self compositeModules! ! !Repository methodsFor: 'up- and downloading' stamp: 'hg 12/16/2001 22:36'! ensureDeepUpload "take various measures to ensure that necessary preconditions are met." self isStandalone ifTrue: [ self ensurePreconditionsForUpload. self ensureModuleDependenciesDeclared: self compositeModules. self storeModuleComposite]. self subrepositories do: [:rep | rep ensureDeepUpload] ! ! !Repository methodsFor: 'up- and downloading' stamp: 'hg 1/26/2002 18:50'! loadModuleContents "load the files that define the contents of this module" ^self isStandalone ifFalse: [self standaloneRepository loadModuleContents] ifTrue: [self fileInModuleContentsFileInto: self module]! ! !Repository methodsFor: 'up- and downloading' stamp: 'hg 1/26/2002 18:19'! storeModuleComposite "store the files that define this (composite) module" | defStream contentsStream | [ defStream _ self streamNamed: (self moduleFileNameForExtension: self moduleDefinitionExtension). self compositeDefinitionsOn: defStream. ] ensure: [defStream close]. [ contentsStream _ self streamNamed: (self moduleFileNameForExtension: self moduleContentsExtension). self compositeContentsOn: contentsStream. ] ensure: [contentsStream close].! ! !Repository methodsFor: 'system conversion' stamp: 'hg 1/27/2002 10:35'! importChangesFrom2: aStream into: mod | deltaModule deltaClass resultWithinModule resultPath | self useChangeSetNamed: 'Import Changes into ', mod pathAsMessages during: [ self fileIn: aStream into: mod chunkBlock: [:result :stream :chunkIsClassCategory | chunkIsClassCategory ifTrue: [ (result isKindOf: ClassCategoryReader) ifTrue: [ resultPath _ result targetClass module path. resultWithinModule _ mod path = (resultPath first: (mod path size min: resultPath size)). resultWithinModule ifFalse: [ deltaModule _ mod deltaModuleForBase: result targetClass module forceCreate: true asActive: false. deltaClass _ deltaModule deltaClassFor: result targetClass forceCreate: true. result setClass: deltaClass]]. "Class category chunk followed by method definition" result scanFrom: stream] ifFalse: [ self halt. resultPath _ result module path. resultWithinModule _ mod path = (resultPath first: (mod path size min: resultPath size)). resultWithinModule ifFalse: [ deltaModule _ mod deltaModuleForBase: result targetClass module forceCreate: true asActive: false. deltaClass _ deltaModule deltaClassFor: result targetClass forceCreate: true. deltaClass copySameFrom: result]]]]. ! ! !Repository methodsFor: 'system conversion' stamp: 'hg 1/27/2002 10:35'! importChangesFrom3: aStream into: mod | deltaModule deltaClass resultWithinModule resultPath result parseTree messageNode | self useChangeSetNamed: 'Import Changes into ', mod pathAsMessages during: [ self fileInChunks: aStream into: mod chunkBlock: [:string :stream :isClassCategory | isClassCategory ifTrue: [ "a class category chunk followed by a method" result _ Compiler evaluate: string for: mod logged: false. (result isKindOf: ClassCategoryReader) ifTrue: [ resultPath _ result targetClass module path. resultWithinModule _ mod path = (resultPath first: (mod path size min: resultPath size)). resultWithinModule ifFalse: [ deltaModule _ mod deltaModuleForBase: result targetClass module forceCreate: true asActive: false. deltaClass _ deltaModule deltaClassFor: result targetClass forceCreate: true. result setClass: deltaClass]]. "Class category chunk followed by method definition" result scanFrom: stream] ifFalse: [ "could be many things sent to a class" result _ Compiler evaluate: string for: mod logged: false. self halt. parseTree _ Compiler new compileNoPattern: string in: mod class context: nil notifying: nil ifFail: []. messageNode _ parseTree block statements first ]]].! ! !Repository methodsFor: 'system conversion' stamp: 'hg 1/27/2002 10:35'! importChangesFrom: aStream into: mod | deltaModule deltaClass resultWithinModule resultPath result parseTree | self useChangeSetNamed: 'Import Changes into ', mod pathAsMessages during: [ self fileInChunks: aStream into: mod chunkBlock: [:string :stream :isClassCategory | isClassCategory ifTrue: [ "a class category chunk followed by a method" result _ Compiler evaluate: string for: mod logged: false. (result isKindOf: ClassCategoryReader) ifTrue: [ resultPath _ result targetClass module path. resultWithinModule _ mod path = (resultPath first: (mod path size min: resultPath size)). resultWithinModule ifFalse: [ deltaModule _ mod deltaModuleForBase: result targetClass module forceCreate: true asActive: false. deltaClass _ deltaModule deltaClassFor: result targetClass forceCreate: true. result setClass: deltaClass]]. "Class category chunk followed by method definition" result scanFrom: stream] ifFalse: [ "could be many things sent to a class" result _ Compiler evaluate: string for: mod logged: false. parseTree _ Compiler new compileNoPattern: string in: mod class context: nil notifying: nil ifFail: []. ]]]. ! ! !RemoteRepository methodsFor: 'accessing' stamp: 'hg 1/27/2002 18:38'! repositoryToUse ^self workOffline ifFalse: [self] ifTrue: [self cache]! ! !RemoteRepository methodsFor: 'up- and downloading' stamp: 'hg 1/26/2002 18:49'! fileInModuleContentsFileInto: mod ^self cache fileInModuleContentsFileInto: mod! ! !RemoteRepository methodsFor: 'installer support' stamp: 'hg 1/27/2002 18:03'! checkRepositoryExists "does the repository exist that defines my module?" ^self cache checkRepositoryExists or: [ super checkRepositoryExists "just do this to mirror remote structure in cache" ==> [self cache ensureDirectory. true]]! ! !RemoteRepository methodsFor: 'installer support' stamp: 'hg 1/26/2002 18:44'! defineCompositeModulesFromFile self isImplicit ifTrue: [^self standaloneRepository defineCompositeModulesFromFile]. self ensureDefinitionInCache. ^self cache defineCompositeModulesFromFile. ! ! !Repository class methodsFor: 'fileIn/Out' stamp: 'hg 1/13/2002 17:35'! importChangesFromFileNamed: fileName intoModuleAt: importRootPath | homeModule aStream | homeModule _ Module fromPath: importRootPath forceCreate: true. aStream _ FileStream fileNamed: fileName. homeModule repository importChangesFrom: aStream into: homeModule. ModuleInstaller activate: homeModule. ^homeModule! ! !SubmoduleReference methodsFor: 'testing' stamp: 'hg 1/19/2002 22:09'! = otherRef ^(otherRef isMemberOf: self class) and: [ otherRef module = self module]! ! !SubmoduleReference methodsFor: 'printing' stamp: 'hg 1/26/2002 14:35'! storeOn: aStream "write a message string that will create myself if sent to a module" "Keep flag: messages with used selectors here so that this code will be updated if the selectors are changed." self flag: #submodule:name:version:importNames: . aStream nextPutAll: 'submodule: nil'; nextPutAll: ' name: '; print: self name; nextPutAll: ' version: '; print: specifiedVersion; nextPutAll: ' importNames: '; print: self importNames. ! ! !VirtualRootModule methodsFor: 'lookups' stamp: 'hg 1/8/2002 13:08'! allBehaviorsDo: aBlock "Evaluate the argument, aBlock, for each kind of Behavior in the system (that is, Object and its subclasses). ar 7/15/1999: The code below will not enumerate any obsolete or anonymous behaviors for which the following should be executed: Smalltalk allObjectsDo:[:obj| obj isBehavior ifTrue:[aBlock value: obj]]. but what follows is way faster than enumerating all objects." self deepSubmodulesDo: [:mod | mod allClassesDo: aBlock].! ! !VirtualRootModule methodsFor: 'lookups' stamp: 'hg 1/27/2002 14:10'! allDefinitionsFor: aString onlyExported: onlyExported detect: aBlock "look up all definitions for the given symbol in all modules. If found, evaluate aBlock for the defined value and defining module. Terminate lookup and return defined value if block returns true. This method is meant for handling the possibility of multiple definitions by the same name, which arises whenever a search for an unqualified global name is done." | assoc found | self deepSubAndDeltaModules do: [:mod | assoc _ onlyExported ifFalse: [mod localAssocFor: aString ifAbsent: [nil]] ifTrue: [mod localExportedAssocFor: aString ifAbsent: [nil]]. assoc ifNotNil: [ found _ aBlock value: assoc value value: mod. found == true ifTrue: [^assoc value]]]. ^nil! ! !VirtualRootRepository methodsFor: 'initializing' stamp: 'hg 1/9/2002 18:57'! initialize Module root repository: nil. self standaloneOn: Module root. self directory: self defaultServer. " self setCache"! ! !VirtualRootRepository class methodsFor: 'default repository locations' stamp: 'hg 1/9/2002 18:25'! defaultRepositoryAltURL "URL for http access" ^'http://modules.squeakfoundation.org/'! ! !VirtualRootRepository class methodsFor: 'default repository locations' stamp: 'hg 1/9/2002 18:25'! defaultRepositoryURL "URL for FTP access (this allows for password protection, for reading etc." ^'ftp://ftp.squeakfoundation.org//'! ! VirtualRootRepository removeSelector: #setCache! !VirtualRootModule reorganize! ('module name and path' longName path pathAsMessages) ('initializing' invalidateCaches) ('testing' <) ('accessing defined names' allModules classNames computeClassNames definesName:ifTrue: importedAssocFor:ifPresent:) ('module composition' importedModulesDo: incomingNeighborsOf:) ('printing' printOn:) ('private' checkImportForCircularity:) ('lookups' allBehaviorsDo: allDefinitionsFor:onlyExported:detect: allDuplicateDefinitions allDuplicateExports browseAllReferencesTo: moduleDefining: modulesDefining: modulesExporting:) ! RemoteRepository removeSelector: #defineModuleFromFile! RemoteRepository removeSelector: #loadCompositeModuleContentsInto:! Repository removeSelector: #defineFromDirectoryStructure! Repository removeSelector: #defineModule:! Repository removeSelector: #defineModuleFromFile! Repository removeSelector: #loadCompositeModuleContentsInto:! Repository removeSelector: #storeModule:! ModuleStorageTests removeSelector: #toTestInstallModulesFromCache:forPath:! ModuleStorageTests removeSelector: #toTestStoreModulesInCache:! ModuleStorageTests removeSelector: #unloadModules! DeltaModuleTests removeSelector: #testIntegrityOfMetaClasses! DeltaModuleReference removeSelector: #in:name:version:baseModule:import:! DeltaModuleReference removeSelector: #isModuleResolved! DeltaModuleReference removeSelector: #resolvedModule:! DeltaModuleReference removeSelector: #specifiedPath! ModuleReference subclass: #DeltaModuleReference instanceVariableNames: '' classVariableNames: '' module: #(Squeak Language Modules)! !ModuleReference reorganize! ('accessing' alias importNames importNames: module name pathAndVersionDefinition) ('resolving' acceptAnyVersion specifiedPath specifiedPathAndVersion specifiedVersion versionIdenticalTo:) ('installer support' createModuleFromPathAndVersion createModuleWithParent: ensureReferenceFrom: ensuredParent ensuredPath findModuleFromPathAndVersion resolveModule resolvedModule:) ('initializing' name:version:module:import: onPath:) ('printing' explorerContents printOn: storeOn:) ('testing' <= hasAlias isModuleResolved refersToDeltaModule refersToExternalModule refersToSubmodule specifiesVersion) ('private' ensureUnresolved) ! ModuleInstaller initialize! ModuleInstaller removeSelector: #clearCreatedModules! ModuleInstaller removeSelector: #compositeLoadingOrderFor:! ModuleInstaller removeSelector: #ensureModuleInRepository:! ModuleInstaller removeSelector: #loadingDependenciesFor:! ModuleInstaller removeSelector: #switchModules:beActive:! Object subclass: #ModuleInstaller instanceVariableNames: 'startModuleRef operation definedModules downloadedModules loadedModules activatedModules progressIndicator progressValue withRecovery ' classVariableNames: '' module: #(Squeak Language Modules Repositories)! DeltaModule class removeSelector: #baseModule:parentModule:! DeltaModule removeSelector: #addNeighborModuleRef:! DeltaModule removeSelector: #baseModule:! DeltaModule removeSelector: #baseModule:parentModule:! DeltaModule removeSelector: #changedNeighborModuleRefs! DeltaModule removeSelector: #hasBaseModule! DeltaModule removeSelector: #switchActiveStatePhase1:! DeltaModule removeSelector: #switchDefinitions:! DeltaModule removeSelector: #switchDeltaClasses:! Module subclass: #DeltaModule instanceVariableNames: 'baseModuleRef isActive ' classVariableNames: '' module: #(Squeak Language Modules)! Module removeSelector: #switchActiveStatePhase1:! !DeltaClass reorganize! ('accessing' baseClass deltaForMetaclass metaOrNonMeta metaOrNonMeta: module name theNonMetaClass) ('testing' changesClassFormat isMeta nonTrivial) ('initialize-release' initializeDelta) ('de/activate' activateMethodsIn:asActive: basicDerivedBaseClassWhenActive: basicMetaclassWhenActive: derivedBaseClassWhenActive: installMethodChangesIntoClass:asActive:) ('delta contents' redefineSelector:withMethod:previousVersion: removedSelectors undefinedSelectors:) ('fileIn/out' fileOutContentsOn:moveSource:toFile: fileOutMethodRemovalsOn: printOn:) ('compatibility' addSelector:withMethod: definesName:lookInSuper:ifTrue: scopeHas:ifTrue: selectorsForCategory:) ! DeltaAssociation class removeSelector: #key:value:previousValue:! DeltaAssociation removeSelector: #previousValue! DeltaAssociation removeSelector: #previousValue:! Association subclass: #DeltaAssociation instanceVariableNames: 'deactivatedValue ' classVariableNames: '' module: #(Squeak Language Modules)! Smalltalk removeClassNamed: #PoolTests! "Postscript:" Preferences setPreference: #modularClassDefinitions toValue: true.!