'From Pharo1.4a of ''16 June 2011'' [Latest update: #14109] on 25 August 2011 at 6:53:41 pm'! ByteString variableByteSubclass: #MCVersionName instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Monticello-Modeling'! !MCVersionName commentStamp: 'cmm 3/4/2011 13:32' prior: 0! A MCVersionName models the Monticello file / version name, in the format [Package]-[Author].[version-number]([ancestorAuthor.ancestorVersionNumber]).[mc?]. Any file-extension, if present, is ignored.! !CodeLoader commentStamp: '' prior: 0! CodeLoader provides a simple facility for loading code from the network. Examples: | loader | loader := CodeLoader new. loader baseURL:'http://isgwww.cs.uni-magdeburg.de/~raab/test/'. loader localCache: #('.cache' 'source'). "Sources and segments can be loaded in parallel" loader loadSourceFiles: #('file1.st' 'file2.st.gz'). loader localCache: #('.cache' 'segments'). loader loadSegments: #('is1.extseg' 'is2.extseg.gz'). "Install sources first - will wait until the files are actually loaded" loader installSourceFiles. "And then the segments" loader installSegments.! !ByteString methodsFor: '*monticello' stamp: 'cmm 3/3/2011 14:35'! asMCVersionName ^ MCVersionName on: self! ! !MCVersionName methodsFor: 'testing' stamp: 'cmm 3/3/2011 14:56'! isValid ^ [ self packageName notEmpty and: [ self author notEmpty and: [ self versionNumber > 0 ] ] ] on: Error do: [ : err | false ]! ! !MCVersionName methodsFor: 'private' stamp: 'cmm 3/3/2011 14:22'! ancestry "If I am a in the diffy-format which includes the ancestor attributes, answer them as a single String, separated by a dot." ^ (self copyAfterLast: $() copyUpTo: $)! ! !MCVersionName methodsFor: 'private' stamp: 'cmm 3/4/2011 10:12'! species ^ ByteString! ! !MCVersionName methodsFor: 'converting' stamp: 'cmm 3/3/2011 14:33'! asMCVersionName ^ self! ! !MCVersionName methodsFor: 'comparing' stamp: 'cmm 3/12/2011 11:48'! = aByteString "Ignore any file-extension for comparison of MCVersionNames." | myVersionName | aByteString isString ifFalse: [ ^ false ]. myVersionName := self versionName. ^ (myVersionName compare: myVersionName with: aByteString asMCVersionName versionName collated: AsciiOrder) = 2! ! !MCVersionName methodsFor: 'comparing' stamp: 'cmm 3/4/2011 10:36'! hash ^ self versionName hash! ! !MCVersionName methodsFor: 'accessing' stamp: 'ul 3/23/2011 04:55'! ancestorAuthor "The author of the ancestor, if this is a Diffy filename." ^self ancestry copyUpTo: $.! ! !MCVersionName methodsFor: 'accessing' stamp: 'ul 3/23/2011 04:55'! ancestorVersionNumber "The author of the ancestor, if this is a Diffy filename." ^(self ancestry copyAfter: $.) asInteger ifNil: [ 0 ]! ! !MCVersionName methodsFor: 'accessing' stamp: 'ul 3/23/2011 04:55'! author "The author initials embedded in the filename." ^(self versionName copyAfterLast: $-) copyUpTo: $.! ! !MCVersionName methodsFor: 'accessing' stamp: 'ul 3/23/2011 04:56'! packageName "The MC Package name embedded into this filename." ^self versionName copyUpToLast: $-! ! !MCVersionName methodsFor: 'accessing' stamp: 'cmm 4/24/2011 22:12'! versionName "Answer my version name as a ByteString, without the file suffix or any ancestor-attributes." | end | self isEmpty ifTrue: [^ String empty]. (self last between: $0 and: $9) ifTrue: [ end := self size ] ifFalse: [ end := (self lastIndexOf: $. ifAbsent: [ self size + 1 ]) - 1. end := end min: (self indexOf: $( ifAbsent: [ self size + 1 ]) - 1 ]. ^self first: end! ! !MCVersionName methodsFor: 'accessing' stamp: 'cmm 3/4/2011 13:40'! versionNumber "The Integer version number identified by this filename." ^ ((self versionName copyAfterLast: $-) copyAfter: $.) asInteger ifNil: [ 0 ]! ! !ByteSymbol methodsFor: '*monticello' stamp: 'cmm 3/7/2011 14:23'! asMCVersionName ^ self asString asMCVersionName! ! !MCRepository methodsFor: 'versions' stamp: 'cmm 3/3/2011 14:45'! versionNamesForPackageNamed: aString "Answer a collection of MCVersionNames whose Package is named aString." self subclassResponsibility! ! !MCFileBasedRepository methodsFor: 'versions' stamp: 'cmm 3/5/2011 18:31'! versionNamesForPackageNamed: packageName ^ Array streamContents: [ : stream | self allFileNamesOrCache do: [ : each | | mcVersionName | mcVersionName := each asMCVersionName. mcVersionName packageName = packageName ifTrue: [ stream nextPut: mcVersionName ] ] ]! ! !MCGOODSRepository methodsFor: 'as yet unclassified' stamp: 'cmm 3/6/2011 17:03'! versionNamesForPackageNamed: aString ^ Array streamContents: [ : stream | self root keysDo: [ : each | each versionName packageName = aString ifTrue: [ stream nextPut: each ] ] ]! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 12/24/2008 08:15'! installLastMonticelloFor: aList "Install the previously loaded source files" aList do: [:packName | self lookLastVersion: packName]. sourceFiles := nil! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 9/17/2009 18:24'! installMonticelloFor: aList "Install the previously loaded source files" aList do: [:packName | self lookMonticelloVersion: packName]. sourceFiles := nil! ! !CodeLoader methodsFor: 'installing' stamp: 'RAA 2/19/2001 08:23'! installProject "Assume that we're loading a single file and it's a project" | aStream | aStream := sourceFiles first contentStream. aStream ifNil:[^self error:'Project was not loaded']. ProjectLoading openName: nil "<--do we want to cache this locally? Need a name if so" stream: aStream fromDirectory: nil withProjectView: nil. ! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 7/2/2008 10:16'! installSegment: reqEntry "Install the previously loaded segment" | contentStream contents trusted inputStream | contentStream := reqEntry value contentStream. contentStream ifNil:[^self error:'No content to install: ', reqEntry key printString]. trusted := SecurityManager default positionToSecureContentsOf: contentStream. trusted ifFalse:[(SecurityManager default enterRestrictedMode) ifFalse:[ contentStream close. ^self error:'Insecure content encountered: ', reqEntry key printString]]. contents := contentStream ascii upToEnd unzipped. (contentStream respondsTo: #close) ifTrue:[contentStream close]. inputStream := (MultiByteBinaryOrTextStream with: contents) reset . inputStream setConverterForCode. (inputStream fileInObjectAndCode ) inspect! ! !CodeLoader methodsFor: 'installing' stamp: 'mir 1/20/2000 13:37'! installSegments "Install the previously loaded segments" segments == nil ifTrue:[^self]. segments do:[:req| self installSegment: req]. segments := nil.! ! !CodeLoader methodsFor: 'installing' stamp: 'sd 1/30/2004 15:16'! installSourceFile: aStream "Install the previously loaded source file" | contents trusted | aStream ifNil:[^self error:'No content to install']. trusted := SecurityManager default positionToSecureContentsOf: aStream. trusted ifFalse:[(SecurityManager default enterRestrictedMode) ifFalse:[ aStream close. ^ self error:'Insecure content encountered']]. contents := aStream ascii upToEnd unzipped. (aStream respondsTo: #close) ifTrue:[aStream close]. ^(RWBinaryOrTextStream with: contents) reset fileIn! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 10/12/2010 08:12'! installSourceFiles | packName pos | "Install the previously loaded source files" sourceFiles == nil ifTrue: [^ self]. sourceFiles do: [:req | (req url endsWith: '.mcz') ifTrue: [ pos := req url lastIndexOf: $/. packName := req url copyFrom: pos + 1 to: req url size. self tryVersion: packName ]. (req url endsWith: '.sar') ifTrue: [ SARInstaller new fileInFrom: req contentStream]. (req url endsWith: '.cs') |(req url endsWith: 'st') ifTrue: [self installSourceFile: req contentStream]]. sourceFiles := nil! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 8/25/2011 10:50'! lookLastVersion: packageName | mcw montiNames package version | mcw := MCWorkingCopyBrowser new repository: (MCHttpRepository location: baseURL user: 'squeak' password: 'squeak'). mcw repository ifNotNilDo: [:repos | montiNames := repos versionNamesForPackageNamed: packageName]. package := montiNames detectMax: [ : pkg | pkg versionNumber ] . package ifNotNil: [UIManager default informUser: 'Installing' during: [version := mcw repository loadVersionFromFileNamed: package. version load]]. MCPackageManager managersForCategory: packageName do: [:wc | wc repositoryGroup addRepository: (MCHttpRepository new location: baseURL)]! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 12/12/2009 07:13'! lookMonticelloVersion: packageName | mcw montiNames package version pN | pN := packageName , '.mcz'. mcw := MCWorkingCopyBrowser new repository: (MCHttpRepository location: baseURL user: 'squeak' password: 'squeak'). mcw repository ifNotNilDo: [:repos | montiNames := repos readableFileNames]. package := montiNames detect: [:any | any = pN] ifNone: []. package ifNotNil: [Utilities informUser: 'Installing ' , packageName printString during: [version := mcw repository loadVersionFromFileNamed: package. version load]]. MCPackageManager managersForCategory: packageName do: [:wc | wc repositoryGroup addRepository: (MCHttpRepository new location: baseURL)]! ! !CodeLoader methodsFor: 'installing' stamp: 'edc 7/2/2008 10:27'! readObject: reqEntry "Install the previously loaded segment" | contentStream contents trusted inputStream | contentStream := reqEntry value contentStream. contentStream ifNil:[^self error:'No content to install: ', reqEntry key printString]. trusted := SecurityManager default positionToSecureContentsOf: contentStream. trusted ifFalse:[(SecurityManager default enterRestrictedMode) ifFalse:[ contentStream close. ^self error:'Insecure content encountered: ', reqEntry key printString]]. contents := contentStream ascii upToEnd unzipped. (contentStream respondsTo: #close) ifTrue:[contentStream close]. inputStream := (MultiByteBinaryOrTextStream with: contents) reset . inputStream setConverterForCode. ^(inputStream fileInObjectAndCode ) ! ! !CodeLoader methodsFor: 'loading' stamp: 'mir 10/13/2000 12:24'! loadSegments: anArray "Load all the source files in the given array." | loader request reqName | loader := HTTPLoader default. segments := anArray collect:[:name | reqName := (FileDirectory extensionFor: name) isEmpty ifTrue: [FileDirectory fileName: name extension: ImageSegment compressedFileExtension] ifFalse: [name]. request := self createRequestFor: reqName in: loader. name->request]. ! ! !CodeLoader methodsFor: 'loading' stamp: 'ar 12/14/1999 14:40'! loadSourceFiles: anArray "Load all the source files in the given array." | loader request | loader := HTTPLoader default. sourceFiles := anArray collect:[:name| request := self createRequestFor: name in: loader. request]. ! ! !CodeLoader methodsFor: 'private' stamp: 'mir 2/2/2001 14:44'! createRequestFor: name in: aLoader "Create a URL request for the given string, which can be cached locally." | request | request := HTTPLoader httpRequestClass for: self baseURL , name in: aLoader. aLoader addRequest: request. "fetch from URL" ^request! ! !CodeLoader methodsFor: 'private' stamp: 'avi 4/30/2004 01:40'! httpRequestClass ^HTTPDownloadRequest! ! !CodeLoader methodsFor: 'accessing' stamp: 'ar 12/13/1999 18:19'! baseURL ^baseURL! ! !CodeLoader methodsFor: 'accessing' stamp: 'ar 12/13/1999 18:19'! baseURL: aString baseURL := aString.! ! !CodeLoader methodsFor: 'accessing' stamp: 'ar 12/22/1999 15:07'! publicKey ^publicKey! ! !CodeLoader methodsFor: 'accessing' stamp: 'ar 12/22/1999 15:07'! publicKey: aPublicKey publicKey := aPublicKey! ! !CodeLoader methodsFor: 'accessing' stamp: 'edc 7/2/2008 10:37'! segments ^ segments! ! !CodeLoader methodsFor: 'initialize-release' stamp: 'mir 1/11/2000 13:47'! initialize publicKey := DefaultKey. baseURL := self class defaultBaseURL! ! !CodeLoader methodsFor: 'debugging' stamp: 'edc 7/10/2008 06:09'! tryVersion: packageName | mcw montiNames package version | mcw := MCWorkingCopyBrowser new repository: (MCHttpRepository location: baseURL user: '' password: ''). mcw repository ifNotNilDo: [:repos | montiNames := repos readableFileNames ]. package := (montiNames detect:[:ea| ea beginsWith: packageName] ifNone:[] ) . package ifNotNil: [MCWorkingCopy allManagers do: [:each | each repositoryGroup addRepository: (MCHttpRepository new location: baseURL)].. version := mcw repository loadVersionFromFileNamed: package. version load]. ^version! ! !CodeLoader class methodsFor: 'accessing' stamp: 'mir 1/11/2000 13:45'! defaultBaseURL ^DefaultBaseURL ifNil: ['']! ! !CodeLoader class methodsFor: 'accessing' stamp: 'mir 1/11/2000 13:45'! defaultBaseURL: aURLString DefaultBaseURL := aURLString! ! !CodeLoader class methodsFor: 'accessing' stamp: 'ar 12/22/1999 15:08'! defaultKey "Return the default key used for verifying signatures of loaded code" ^DefaultKey! ! !CodeLoader class methodsFor: 'accessing' stamp: 'mir 1/10/2000 18:16'! defaultKey: aPublicKey "Store the default key used for verifying signatures of loaded code" DefaultKey := aPublicKey "CodeLoader defaultKey: DOLPublicKey" "CodeLoader defaultKey: (DigitalSignatureAlgorithm testKeySet at: 2)"! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 9/6/2000 15:03'! compressFileNamed: aFileName self compressFileNamed: aFileName in: FileDirectory default! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 10/13/2000 13:27'! compressFileNamed: aFileName in: aDirectory "Compress the currently selected file" | zipped buffer unzipped zipFileName | unzipped := aDirectory readOnlyFileNamed: (aDirectory fullNameFor: aFileName). unzipped binary. zipFileName := aFileName copyUpToLast: $. . zipped := aDirectory newFileNamed: (zipFileName, FileDirectory dot, ImageSegment compressedFileExtension). zipped binary. zipped := GZipWriteStream on: zipped. buffer := ByteArray new: 50000. 'Compressing ', zipFileName displayProgressAt: Sensor cursorPoint from: 0 to: unzipped size during:[:bar| [unzipped atEnd] whileFalse:[ bar value: unzipped position. zipped nextPutAll: (unzipped nextInto: buffer)]. zipped close. unzipped close]. ! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 1/18/2000 16:22'! exportCategories: catList to: aFileName "CodeLoader exportCategories: #( 'Game-Animation' 'Game-Framework' ) to: 'Game-Framework'" | list classList | classList := OrderedCollection new. catList do: [:catName | list := SystemOrganization listAtCategoryNamed: catName asSymbol. list do: [:nm | classList add: (Smalltalk at: nm); add: (Smalltalk at: nm) class]]. self exportCodeSegment: aFileName classes: classList keepSource: true! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 1/18/2000 20:53'! exportCategoryNamed: catName "CodeLoader exportCategoryNamed: 'OceanicPanic' " | list | list := SystemOrganization listAtCategoryNamed: catName asSymbol. self exportClassesNamed: list to: catName! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 1/18/2000 20:53'! exportClassesNamed: classNameList to: aFileName | classList | classList := OrderedCollection new. classNameList do: [:nm | classList add: (Smalltalk at: nm); add: (Smalltalk at: nm) class]. self exportCodeSegment: aFileName classes: classList keepSource: true! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 10/11/2000 19:12'! exportCodeSegment: exportName classes: aClassList keepSource: keepSources "Code for writing out a specific category of classes as an external image segment. Perhaps this should be a method." | is oldMethods newMethods m oldCodeString argsAndTemps classList symbolHolder fileName | keepSources ifTrue: [ self confirm: 'We are going to abandon sources. Quit without saving after this has run.' orCancel: [^self]]. classList := aClassList asArray. "Strong pointers to symbols" symbolHolder := Symbol allInstances. oldMethods := OrderedCollection new: classList size * 150. newMethods := OrderedCollection new: classList size * 150. keepSources ifTrue: [ classList do: [:cl | cl selectors do: [:selector | m := cl compiledMethodAt: selector. m fileIndex > 0 ifTrue: [oldCodeString := cl sourceCodeAt: selector. argsAndTemps := (cl compilerClass new parse: oldCodeString in: cl notifying: nil) tempNames. oldMethods addLast: m. newMethods addLast: (m copyWithTempNames: argsAndTemps)]]]]. oldMethods asArray elementsExchangeIdentityWith: newMethods asArray. oldMethods := newMethods := m := oldCodeString := argsAndTemps := nil. Smalltalk garbageCollect. is := ImageSegment new copyFromRootsForExport: classList. "Classes and MetaClasses" fileName := FileDirectory fileName: exportName extension: ImageSegment fileExtension. is writeForExport: fileName. self compressFileNamed: fileName ! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 10/12/2000 17:39'! loadCode: codeSegmentName from: baseURL ifClassNotLoaded: testClass CodeLoader defaultBaseURL: baseURL. (Smalltalk includesKey: testClass) ifFalse: [CodeLoader loadCodeSegment: codeSegmentName]. ! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 2/2/2001 14:56'! loadCodeSegment: segmentName | loader | loader := self new. loader loadSegments: (Array with: segmentName). loader installSegments.! ! !CodeLoader class methodsFor: 'utilities' stamp: 'asm 12/6/2002 08:11'! signFile: fileName renameAs: destFile key: privateKey dsa: dsa "Sign the given file using the private key." | in out | in := FileStream readOnlyFileNamed: fileName. in binary. out := FileStream newFileNamed: destFile. out binary. [in atEnd] whileFalse:[out nextPutAll: (in next: 4096)]. in close. out close. FileDirectory activeDirectoryClass splitName: destFile to:[:path :file| SecurityManager default signFile: file directory: (FileDirectory on: path). ]. ! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 2/14/2000 16:47'! signFiles: fileNames in: dirName key: privateKey "Sign the files in the current directory and put them into a folder signed." | newNames oldNames | oldNames := fileNames collect:[:fileName | dirName , FileDirectory slash, fileName]. newNames := fileNames collect:[:fileName | dirName , FileDirectory slash, 'signed', FileDirectory slash, fileName]. CodeLoader signFilesFrom: oldNames to: newNames key: privateKey! ! !CodeLoader class methodsFor: 'utilities' stamp: 'mir 1/18/2000 18:49'! signFiles: fileNames key: privateKey "Sign the files in the current directory and put them into a folder signed." | newNames | newNames := fileNames collect:[:fileName | 'signed', FileDirectory slash, fileName]. CodeLoader signFilesFrom: fileNames to: newNames key: privateKey! ! !CodeLoader class methodsFor: 'utilities' stamp: 'ads 7/31/2003 14:00'! signFilesFrom: sourceNames to: destNames key: privateKey "Sign all the given files using the private key. This will add an 's' to the extension of the file." "| fd oldNames newNames | fd := FileDirectory default directoryNamed:'unsigned'. oldNames := fd fileNames. newNames := oldNames collect:[:name| 'signed', FileDirectory slash, name]. oldNames := oldNames collect:[:name| 'unsigned', FileDirectory slash, name]. CodeLoader signFilesFrom: oldNames to: newNames key: DOLPrivateKey." | dsa | dsa := DigitalSignatureAlgorithm new. dsa initRandomNonInteractively. 'Signing files...' displayProgressAt: Sensor cursorPoint from: 1 to: sourceNames size during:[:bar| 1 to: sourceNames size do:[:i| bar value: i. self signFile: (sourceNames at: i) renameAs: (destNames at: i) key: privateKey dsa: dsa]]. ! ! !MCVersionName class methodsFor: 'instance creation' stamp: 'cmm 3/3/2011 14:19'! on: aString "aString may be with or without a mc? extension." ^ (self new: aString size) replaceFrom: 1 to: aString size with: aString startingAt: 1 ; yourself! !