SystemOrganization addCategory: #'Filesystem-Core'! SystemOrganization addCategory: #'Filesystem-Disk'! SystemOrganization addCategory: #'Filesystem-Memory'! SystemOrganization addCategory: #'Filesystem-Streams'! SystemOrganization addCategory: #'Filesystem-Tests'! SystemOrganization addCategory: #'Filesystem-Zip'! !String methodsFor: '*filesystem-converting' stamp: 'cwp 8/7/2009 09:25'! asPath ^ FSPath fromString: self! ! !String methodsFor: '*filesystem-converting' stamp: 'cwp 9/22/2009 09:28'! asResolvedBy: anObject ^ anObject resolvePath: self asPath! ! Object subclass: #FSFilePluginPrims instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Disk'! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:26'! atEnd: id "Answer true if the file position is at the end of the file." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:27'! close: id "Close this file." ! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:20'! createDirectory: fullPath "Create a directory named by the given path. Fail if the path is bad or if a file or directory by that name already exists." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:21'! deleteDirectory: fullPath "Delete the directory named by the given path. Fail if the path is bad or if a directory by that name does not exist." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:22'! deleteFile: aFileName "Delete the file of the given name. Return self if the primitive succeeds, nil otherwise." ^ nil ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:27'! flush: id "Flush pending changes to the disk" | p | "In some OS's seeking to 0 and back will do a flush" p := self position. self position: 0; position: p! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:23'! getMacFile: fileName type: typeString creator: creatorString "Get the Macintosh file type and creator info for the file with the given name. Fails if the file does not exist or if the type and creator type arguments are not strings of length 4. This primitive is Mac specific; it is a noop on other platforms." ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:27'! getPosition: id "Get this files current position." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:24'! lookupEntryIn: fullPath index: index "Look up the index-th entry of the directory with the given fully-qualified path (i.e., starting from the root of the file hierarchy) and return an array containing: The empty string enumerates the top-level files or drives. (For example, on Unix, the empty path enumerates the contents of '/'. On Macs and PCs, it enumerates the mounted volumes/drives.) The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad." ^ #badDirectoryPath ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:27'! open: fileName writable: writableFlag "Open a file of the given name, and return the file ID obtained. If writableFlag is true, then if there is none with this name, then create one else prepare to overwrite the existing from the beginning otherwise if the file exists, open it read-only else return nil" ^ nil ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:28'! read: id into: byteArray startingAt: startIndex count: count "Read up to count bytes of data from this file into the given string or byte array starting at the given index. Answer the number of bytes actually read." self primitiveFailed! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:24'! rename: oldFileFullName to: newFileFullName "Rename the file of the given name to the new name. Fail if there is no file of the old name or if there is an existing file with the new name." ^nil! ! !FSFilePluginPrims methodsFor: 'path primitives' stamp: 'cwp 7/20/2009 17:25'! setMacFileNamed: fileName type: typeString creator: creatorString "Set the Macintosh file type and creator info for the file with the given name. Fails if the file does not exist or if the type and creator type arguments are not strings of length 4. This primitive is Mac specific; it is a noop on other platforms." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:30'! setPosition: id to: anInteger "Set this file to the given position." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:30'! size: id "Answer the size of this file." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/22/2009 07:10'! sizeOrNil: id "Answer the size of this file." ^ nil! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:33'! truncate: id to: anInteger "Truncate this file to the given position." self primitiveFailed ! ! !FSFilePluginPrims methodsFor: 'file primitives' stamp: 'cwp 7/20/2009 17:33'! write: id from: stringOrByteArray startingAt: startIndex count: count "Write count bytes onto this file from the given string or byte array starting at the given index. Answer the number of bytes written." self primitiveFailed! ! Object subclass: #FSFilesystem instanceVariableNames: 'workingDirectory' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Core'! FSFilesystem subclass: #FSDiskFilesystem instanceVariableNames: '' classVariableNames: 'Primitives' poolDictionaries: '' category: 'Filesystem-Disk'! !FSDiskFilesystem classSide methodsFor: 'accessing' stamp: 'cwp 9/22/2009 09:41'! / anObject ^ self current root / anObject! ! !FSDiskFilesystem classSide methodsFor: 'instance creation' stamp: 'cwp 7/20/2009 07:19'! current ^ self currentClass new! ! !FSDiskFilesystem classSide methodsFor: 'instance creation' stamp: 'cwp 7/20/2009 07:28'! currentClass ^ SmalltalkImage current platformName = 'Win32' ifTrue:[FSWindowsFilesystem] ifFalse: [FSUnixFilesystem]! ! !FSDiskFilesystem classSide methodsFor: 'initialize-release' stamp: 'cwp 7/20/2009 17:46'! initialize self useFilePlugin! ! !FSDiskFilesystem classSide methodsFor: 'accessing' stamp: 'cwp 9/17/2009 10:42'! root ^ self current referenceTo: FSPath root! ! !FSDiskFilesystem classSide methodsFor: 'initialize-release' stamp: 'cwp 7/20/2009 17:39'! useFilePlugin Primitives := FSFilePluginPrims new! ! !FSDiskFilesystem methodsFor: 'comparing' stamp: 'cwp 7/24/2009 00:41'! = other ^ self species = other species! ! !FSDiskFilesystem methodsFor: 'private' stamp: 'cwp 7/18/2009 01:26'! basicIsDirectory: anEntry ^ anEntry at: 4! ! !FSDiskFilesystem methodsFor: 'private' stamp: 'cwp 7/18/2009 01:29'! basicIsFile: anEntry ^ (anEntry at: 4) not! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 7/22/2009 22:30'! basicOpen: aPath writable: aBoolean ^ Primitives open: (self pathToString: aPath) writable: aBoolean! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 16:02'! createDirectory: anObject | parent path | self halt. path := self resolve: anObject. parent := path parent. (self isDirectory: parent) ifFalse: [self createDirectory: parent]. Primitives createDirectory: (self pathToString: path)! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 7/20/2009 17:48'! delete: anObject | path pathString | path := self resolve: anObject. pathString := self pathToString: path. (self isDirectory: path) ifTrue: [Primitives deleteDirectory: (self pathToString: path)] ifFalse: [StandardFileStream retryWithGC:[Primitives deleteFile: pathString] until: [:result | result notNil] forFileNamed: pathString]! ! !FSDiskFilesystem methodsFor: 'private' stamp: 'cwp 7/20/2009 17:46'! directoryAt: aPath ifAbsent: absentBlock entriesDo: aBlock | index pathString entry | index := 1. pathString := self pathToString: aPath. entry := Primitives lookupEntryIn: pathString index: index. entry = #badDirectoryPath ifTrue: [ ^ absentBlock value ]. [entry isNil] whileFalse: [aBlock value: entry. index := index + 1. entry := Primitives lookupEntryIn: pathString index: index]! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 00:44'! entriesAt: anObject | path | path := self resolve: anObject asPath. ^ Array streamContents: [:out | self directoryAt: path ifAbsent: [self invalidDirectory: path] entriesDo: [:entry | out nextPut: (self referenceTo: path / entry first)]]! ! !FSDiskFilesystem methodsFor: 'private' stamp: 'cwp 10/10/2009 00:35'! entryAt: aPath ifPresent: presentBlock ifAbsent: absentBlock | name | aPath isRoot ifTrue: [^ presentBlock value: self rootEntry]. name := aPath basename. self directoryAt: aPath parent ifAbsent: absentBlock entriesDo: [ :entry | (self entryName: (entry at: 1) matches: name) ifTrue: [ ^ presentBlock value: entry ] ]. ^ absentBlock value! ! !FSDiskFilesystem methodsFor: 'comparing' stamp: 'cwp 7/24/2009 00:41'! hash ^ self species hash! ! !FSDiskFilesystem methodsFor: 'initialize-release' stamp: 'cwp 9/16/2009 11:25'! initialize workingDirectory := FSPath imageFile parent! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 7/22/2009 22:31'! open: anObject writable: aBoolean | path | path := self resolve: anObject asPath. ^ FSFileHandle open: (FSReference filesystem: self path: path) writable: aBoolean ! ! !FSDiskFilesystem methodsFor: 'public' stamp: 'cwp 7/22/2009 22:01'! openFileStream: anObject writable: aBoolean | fullPath | fullPath := (self resolve: anObject asPath) asString. ^ StandardFileStream new open: fullPath forWrite: aBoolean! ! !FSDiskFilesystem methodsFor: 'private' stamp: 'cwp 10/10/2009 00:41'! rootEntry ^ #('' 0 0 true 0)! ! FSDiskFilesystem subclass: #FSUnixFilesystem instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Disk'! !FSUnixFilesystem methodsFor: 'public' stamp: 'cwp 1/13/2009 21:35'! delimiter ^ $/! ! !FSUnixFilesystem methodsFor: 'private' stamp: 'cwp 1/13/2009 21:34'! forReferencePrintOn: aStream aStream nextPutAll: 'unix'! ! FSDiskFilesystem subclass: #FSWindowsFilesystem instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Disk'! !FSWindowsFilesystem methodsFor: 'as yet unclassified' stamp: 'cwp 7/17/2009 19:19'! delimiter ^ $\! ! !FSWindowsFilesystem methodsFor: 'as yet unclassified' stamp: 'cwp 7/17/2009 19:19'! forReferencePrintOn: aStream aStream nextPutAll: 'win'! ! !FSFilesystem classSide methodsFor: 'as yet unclassified' stamp: 'cwp 9/22/2009 09:41'! / anObject ^ self new root / anObject! ! !FSFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 09:47'! basicCopy: source ifAbsent: aBlock to: destination ifPresent: pBlock | in out buffer | [in := self readStreamOn: source. in ifNil: [aBlock value]. (self exists: destination) ifTrue: pBlock. out := self writeStreamOn: destination. buffer := ByteArray new: 1024. [in atEnd] whileFalse: [buffer := in nextInto: buffer. out nextPutAll: buffer]] ensure: [in ifNotNil: [in close]. out ifNotNil: [out close]]! ! !FSFilesystem methodsFor: 'accessing' stamp: 'cwp 7/18/2009 00:53'! changeDirectory: aPath self workingDirectory: (self resolve: aPath)! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 9/21/2009 15:18'! close "Some kinds of filesystems need to open connections to external resources"! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/24/2009 00:24'! copy: sourcePath ifAbsent: aBlock to: destPath ifPresent: pBlock | source destination | source := self resolve: sourcePath asPath. destination := self resolve: destPath asPath. self basicCopy: source ifAbsent: aBlock to: destination ifPresent: pBlock! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/24/2009 00:27'! copy: sourcePath to: destPath self copy: sourcePath ifAbsent: [self fileDoesNotExist: sourcePath] to: destPath ifPresent: [self fileExists: destPath]! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/18/2009 01:15'! createDirectory: aPath self subclassResponsibility! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/20/2009 08:39'! delete: aPath self subclassResponsibility ! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/17/2009 19:20'! delimiter self subclassResponsibility! ! !FSFilesystem methodsFor: 'private' stamp: 'cwp 7/17/2009 19:20'! directoryAt: aPath ifAbsent: absentBlock entriesDo: aBlock self subclassResponsibility! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/17/2009 19:22'! ensureDirectory: aPath (self isDirectory: aPath) ifFalse: [self createDirectory: aPath]! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 10/8/2009 23:49'! entriesAt: anObject self subclassResponsibility! ! !FSFilesystem methodsFor: 'private' stamp: 'cwp 7/17/2009 19:20'! entryAt: aPath ifPresent: presentBlock ifAbsent: absentBlock self subclassResponsibility! ! !FSFilesystem methodsFor: 'private' stamp: 'cwp 7/17/2009 19:24'! entryName: aByteString matches: aByteString2 ^ aByteString = aByteString2! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 00:34'! exists: anObject | path | path := self resolve: anObject. self entryAt: path ifPresent: [ :entry | ^ true ] ifAbsent: [ ^ false ]! ! !FSFilesystem methodsFor: 'error handling' stamp: 'cwp 7/24/2009 00:26'! fileDoesNotExist: path ^ (FileDoesNotExistException fileName: path asString) signal! ! !FSFilesystem methodsFor: 'error handling' stamp: 'cwp 7/24/2009 00:27'! fileExists: path ^ (FileExistsException fileName: path asString) signal! ! !FSFilesystem methodsFor: 'printing' stamp: 'cwp 7/17/2009 19:20'! forReferencePrintOn: aStream self subclassResponsibility! ! !FSFilesystem methodsFor: 'initialize-release' stamp: 'cwp 7/18/2009 00:54'! initialize workingDirectory := FSPath root! ! !FSFilesystem methodsFor: 'error handling' stamp: 'cwp 8/29/2009 10:20'! invalidDirectory: path ^ (InvalidDirectoryError pathName: (self pathToString: path)) signal! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 16:10'! isDirectory: anObject | path | path := self resolve: anObject asPath. path isRoot ifTrue: [^ true]. self entryAt: path ifPresent: [ :entry | ^ self basicIsDirectory: entry ] ifAbsent: [ ^ false ]! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 00:31'! isFile: anObject | path | path := self resolve: anObject. self entryAt: path ifPresent: [ :entry | ^ self basicIsFile: entry ] ifAbsent: [ ^ false ]! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 9/21/2009 15:17'! open "Some kinds of filesystems need to open connections to external resources"! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/22/2009 08:21'! open: aPath writable: aBoolean self subclassResponsibility! ! !FSFilesystem methodsFor: 'private' stamp: 'cwp 7/17/2009 19:24'! pathToString: aPath ^ aPath printWithDelimiter: self delimiter! ! !FSFilesystem methodsFor: 'printing' stamp: 'cwp 7/17/2009 19:21'! printPath: aPath on: aStream aPath printOn: aStream delimiter: self delimiter! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/31/2009 00:26'! readStreamOn: anObject ^ (self open: anObject writable: false) readStream.! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/20/2009 09:11'! referenceTo: anObject ^ FSReference filesystem: self path: anObject asPath! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 10/10/2009 00:17'! resolve: anObject ^ workingDirectory resolve: anObject! ! !FSFilesystem methodsFor: 'accessing' stamp: 'cwp 9/20/2009 22:27'! root ^ self referenceTo: FSPath root! ! !FSFilesystem methodsFor: 'accessing' stamp: 'cwp 7/18/2009 00:53'! workingDirectory ^ workingDirectory! ! !FSFilesystem methodsFor: 'accessing' stamp: 'cwp 7/18/2009 00:59'! workingDirectory: aPath aPath isAbsolute ifFalse: [self error: 'Cannot set the working directory to a relative path']. workingDirectory := aPath! ! !FSFilesystem methodsFor: 'public' stamp: 'cwp 7/28/2009 22:59'! writeStreamOn: anObject ^ (self open: anObject writable: true) writeStream.! ! FSFilesystem subclass: #FSMemoryFilesystem instanceVariableNames: 'root' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Memory'! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/24/2009 00:37'! basicCopy: source ifAbsent: aBlock to: destination ifPresent: pBlock self entryAt: source ifPresent: [:bytes | (self basicIsFile: bytes) ifFalse: aBlock. self entryAt: destination parent ifPresent: [:dict | (self basicIsDirectory: dict) ifFalse: [self invalidDirectory: destination parent]. (dict includesKey: destination basename) ifTrue: pBlock. dict at: destination basename put: bytes copy] ifAbsent: [self invalidDirectory: destination parent]] ifAbsent: aBlock! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/18/2009 01:31'! basicIsDirectory: entry ^ entry isDictionary! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/18/2009 01:31'! basicIsFile: entry ^ entry isDictionary not! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/26/2009 13:14'! basicOpen: anObject writable: aBoolean | path | path := self resolve: anObject. ^ self entryAt: path ifPresent: [:bytes | bytes] ifAbsent: [aBoolean ifFalse: [self fileDoesNotExist: path] ifTrue: [self createFile: path]]! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 7/18/2009 01:22'! createDirectory: anObject | parent path | path := self resolve: anObject. parent := path parent. self entryAt: parent ifPresent: [:dict | dict at: path basename put: Dictionary new] ifAbsent: [self createDirectory: parent. self createDirectory: path]! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/26/2009 13:13'! createFile: path ^ self entryAt: path parent ifPresent: [ :dict | (self basicIsDirectory: dict) ifTrue: [ dict at: path basename put: ByteArray new ] ] ifAbsent: [ self invalidDirectory: path parent ]! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 7/18/2009 01:24'! delete: anObject | path | path := self resolve: anObject. self entryAt: path parent ifPresent: [:dict | dict removeKey: path basename] ifAbsent: []! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 7/17/2009 19:29'! delimiter ^ $/! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 8/29/2009 10:21'! directoryAt: aPath ifAbsent: absentBlock entriesDo: aBlock self entryAt: aPath ifPresent: [:directory | directory isDictionary ifFalse: [^ absentBlock value]. directory keysAndValuesDo: [:name :entry | aBlock value: name -> entry]] ifAbsent: aBlock! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 8/23/2009 22:26'! entriesAt: anObject | path entry | path := self resolve: anObject. ^ Array streamContents: [:out | self directoryAt: path ifAbsent: [self invalidDirectory: path] entriesDo: [:association | entry := self referenceTo: path / association key. out nextPut: entry]]! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/17/2009 23:33'! entryAt: aPath ifPresent: presentBlock ifAbsent: absentBlock | current | current := root. aPath do: [:segment | current isDictionary ifTrue: [current := current at: segment ifAbsent: [^ absentBlock value]] ifFalse: [^ absentBlock value]]. ^ presentBlock value: current! ! !FSMemoryFilesystem methodsFor: 'printing' stamp: 'cwp 7/19/2009 22:16'! forReferencePrintOn: aStream aStream nextPutAll: 'memory'! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/19/2009 22:12'! growFile: anObject to: anInteger ^ self replaceFile: anObject in: [:bytes | (bytes class new: anInteger) replaceFrom: 1 to: bytes size with: bytes startingAt: 1; yourself]! ! !FSMemoryFilesystem methodsFor: 'initialize-release' stamp: 'cwp 7/18/2009 01:11'! initialize super initialize. root := Dictionary new! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 8/29/2009 10:15'! open: anObject writable: aBoolean | path | path := self resolve: anObject. ^ FSMemoryHandle open: (self referenceTo: path) writable: aBoolean ! ! !FSMemoryFilesystem methodsFor: 'public' stamp: 'cwp 7/26/2009 13:13'! openFileStream: aPath writable: aBoolean | path bytes | path := self resolve: aPath. bytes := self entryAt: path ifPresent: [ :array | array ] ifAbsent: [ self createFile: path ]. ^ FSMemoryFileStream on: bytes filesystem: self path: path! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/19/2009 22:04'! replaceFile: anObject in: aBlock | path | path := self resolve: anObject asPath. ^ self entryAt: path parent ifPresent: [:dict || old new | (self basicIsDirectory: dict) ifFalse: [self fileDoesNotExist: path]. old := dict at: path basename ifAbsent: [self fileDoesNotExist: path]. new := aBlock value: old. dict at: path basename put: new] ifAbsent: [self fileDoesNotExist: path]! ! !FSMemoryFilesystem methodsFor: 'private' stamp: 'cwp 7/19/2009 22:13'! truncateFile: anObject to: anInteger ^ self replaceFile: anObject in: [ :bytes | bytes first: anInteger ]! ! FSFilesystem subclass: #FSZipFilesystem instanceVariableNames: 'reference archive directories' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Zip'! !FSZipFilesystem classSide methodsFor: 'as yet unclassified' stamp: 'cwp 9/21/2009 15:12'! atReference: aReference ^ self new setReference: aReference! ! !FSZipFilesystem methodsFor: 'accessing' stamp: 'cwp 9/20/2009 23:38'! archive ^ archive! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 8/30/2009 13:54'! basicCopy: source ifAbsent: aBlock to: destination ifPresent: pBlock | destname copy | self entryAt: source ifPresent: [:smember | destname := self pathToString: destination. copy := self copyFile: smember as: destname. self entryAt: destination ifPresent: [:dmember | pBlock value ] ifAbsent: [archive addMember: copy]] ifAbsent: aBlock! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 13:12'! basicIsDirectory: aPath ^ directories includes: aPath! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 13:31'! basicIsFile: anObject ^ (anObject isKindOf: ArchiveMember) and: [anObject isDirectory not]! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 8/30/2009 13:23'! basicOpen: anObject writable: aBoolean | path stream | path := self resolve: anObject. ^ self entryAt: path ifPresent: [:member | stream := RWBinaryOrTextStream on: (ByteArray new: member uncompressedSize). member extractTo: stream. stream binary; contents] ifAbsent: [aBoolean ifFalse: [self fileDoesNotExist: path] ifTrue: [self createFile: path]]! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/21/2009 15:20'! close archive writeToFileNamed: reference pathString. archive close. archive := nil! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 8/30/2009 15:39'! copyFile: aZipMember as: aString ^ aZipMember class newFromString: aZipMember contents named: aString! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/22/2009 13:10'! createDirectory: anObject directories add: (self resolve: anObject) ! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/21/2009 18:22'! createFile: aPath archive addDeflateString: '' as: (self pathToString: aPath). ^ ByteArray new! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/22/2009 13:40'! delete: anObject | path | path := self resolve: anObject. (directories includes: path) ifTrue: [directories remove: path] ifFalse: [self entryAt: path ifPresent: [:member | archive removeMember: member] ifAbsent: []]! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 8/29/2009 11:36'! delimiter ^ $/! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 14:47'! directoriesAt: aPath | paths | paths := directories select: [:ea | ea size = (aPath size + 1) and: [aPath contains: ea]]. ^ paths collect: [:ea | self referenceTo: ea] ! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 10/10/2009 00:42'! directoryAt: aPath ifPresent: presentBlock ifAbsent: absentBlock ^ (aPath isRoot or: [directories includes: aPath]) ifTrue: presentBlock ifFalse: absentBlock! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/22/2009 14:44'! entriesAt: anObject | path | path := self resolve: anObject. ^ (self filesAt: path) addAll: (self directoriesAt: path)! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 13:43'! entryAt: aPath ifPresent: presentBlock ifAbsent: absentBlock | name | ^ self directoryAt: aPath ifPresent: [ presentBlock value: aPath ] ifAbsent: [ name := self pathToString: aPath. (archive memberNamed: name) ifNotNil: [ presentBlock value: (archive memberNamed: name) ] ifNil: absentBlock ]! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 14:46'! filesAt: aPath | all | all := archive members collect: [:ea | ea fileName asPath]. all := all select: [:ea | ea size = (aPath size + 1) and: [aPath contains: ea]]. ^ all collect: [:ea | self referenceTo: ea] ! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/20/2009 23:01'! forReferencePrintOn: aStream aStream nextPutAll: 'zip'! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 23:31'! initializeArchive (archive members select: [ :ea | ea isDirectory ]) do: [ :ea | directories add: (self pathFromMember: ea). archive removeMember: ea ]. archive members do: [ :ea | directories add: (self pathFromMember: ea) parent ]! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 13:41'! memberAt: aPath ifPresent: presentBlock ifAbsent: absentBlock | name | name := self pathToString: aPath. ^ (archive memberNamed: name) ifNotNil: [ presentBlock value: (archive memberNamed: name) ] ifNil: absentBlock! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/22/2009 23:21'! open archive := ZipArchive new. reference exists ifTrue: [reference fileStreamDo: [:in | archive readFrom: in]. self initializeArchive]! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 8/30/2009 10:28'! open: anObject writable: aBoolean | path | path := self resolve: anObject. ^ FSZipHandle open: (self referenceTo: path) writable: aBoolean ! ! !FSZipFilesystem methodsFor: 'public' stamp: 'cwp 9/21/2009 22:47'! openFileStream: anObject writable: aBoolean | path member name | path := self resolve: anObject. member := self entryAt: path ifPresent: [:entry | entry] ifAbsent: [name := self pathToString: path. archive addDeflateString: '' as: name]. ^ FSZipFileStream on: member contents filesystem: self path: path! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/22/2009 23:29'! pathFromMember: anArchiveMember | path | path := FSPath root resolve: anArchiveMember fileName. ^ path basename isEmpty ifTrue: [path parent] ifFalse: [path]! ! !FSZipFilesystem methodsFor: 'accessing' stamp: 'cwp 9/21/2009 17:48'! reference ^ reference! ! !FSZipFilesystem methodsFor: 'private' stamp: 'cwp 9/21/2009 18:22'! setFile: aPath to: bytes | path | path := self resolve: aPath. self entryAt: path ifPresent: [:member | (archive member: member) contents: bytes] ifAbsent: [ archive addDeflateString: bytes as: (self pathToString: path) ]! ! !FSZipFilesystem methodsFor: 'initialize-release' stamp: 'cwp 9/22/2009 13:10'! setReference: aReference directories := Set new. reference := aReference.! ! Object subclass: #FSHandle instanceVariableNames: 'reference writable' classVariableNames: 'Primitives' poolDictionaries: '' category: 'Filesystem-Core'! FSHandle subclass: #FSFileHandle instanceVariableNames: 'id' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Disk'! !FSFileHandle classSide methodsFor: 'class initialization' stamp: 'cwp 7/22/2009 07:11'! initialize self useFilePlugin! ! !FSFileHandle classSide methodsFor: 'class initialization' stamp: 'cwp 7/22/2009 07:11'! useFilePlugin Primitives := FSFilePluginPrims new! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/31/2009 00:05'! at: index read: buffer startingAt: start count: count ^ Primitives setPosition: id to: index - 1; read: id into: buffer startingAt: start count: count ! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 14:15'! at: index write: buffer startingAt: start count: count Primitives setPosition: id to: index - 1; write: id from: buffer startingAt: start count: count ! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/22/2009 07:12'! close Primitives close: id! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/22/2009 07:49'! flush Primitives flush: id! ! !FSFileHandle methodsFor: 'testing' stamp: 'cwp 7/22/2009 07:10'! isOpen ^ (Primitives sizeOrNil: id) notNil! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 9/21/2009 23:07'! open id := reference filesystem basicOpen: reference path writable: writable. id ifNil: [(writable or: [reference exists]) ifTrue: [self error: 'Unable to open file ', reference printString] ifFalse: [(FileDoesNotExistException fileName: reference path) signal]]! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/22/2009 07:44'! size ^ Primitives size: id! ! !FSFileHandle methodsFor: 'public' stamp: 'cwp 7/22/2009 08:17'! truncateTo: anInteger Primitives truncate: id to: anInteger. self reopen! ! !FSHandle classSide methodsFor: 'instance creation' stamp: 'cwp 7/26/2009 12:52'! on: aReference writable: aBoolean ^ self new setReference: aReference writable: aBoolean! ! !FSHandle classSide methodsFor: 'instance creation' stamp: 'cwp 7/26/2009 12:52'! open: aReference writable: aBoolean ^ (self on: aReference writable: aBoolean) open! ! !FSHandle classSide methodsFor: 'class initialization' stamp: 'cwp 7/26/2009 12:50'! useFilePlugin self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/29/2009 22:19'! at: index | buffer | buffer := ByteArray new: 1. self at: index read: buffer startingAt: 1 count: 1. ^ buffer at: 1! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/29/2009 22:19'! at: index put: anObject | buffer | buffer := ByteArray with: anObject. self at: index write: buffer startingAt: 1 count: 1. ! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! at: offset read: buffer startingAt: start count: count self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! at: offset write: buffer startingAt: start count: count self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! close self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! flush self subclassResponsibility! ! !FSHandle methodsFor: 'testing' stamp: 'cwp 7/26/2009 12:50'! isOpen self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! open self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/31/2009 00:32'! readStream ^ self isOpen ifTrue: [FSReadStream onHandle: self]! ! !FSHandle methodsFor: 'accessing' stamp: 'cwp 7/26/2009 12:51'! reference ^ reference! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:51'! reopen self close. self open! ! !FSHandle methodsFor: 'initialize-release' stamp: 'cwp 7/26/2009 12:51'! setReference: aReference writable: aBoolean reference := aReference. writable := aBoolean! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 12:50'! truncateTo: anInteger self subclassResponsibility! ! !FSHandle methodsFor: 'public' stamp: 'cwp 7/28/2009 23:06'! writeStream ^ FSWriteStream onHandle: self! ! FSHandle subclass: #FSMemoryHandle instanceVariableNames: 'bytes size' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Memory'! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/29/2009 22:07'! at: index ^ bytes at: index! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/31/2009 00:18'! at: index put: anObject index > bytes size ifTrue: [self grow]. bytes at: index put: anObject. size := size max: index! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/31/2009 00:16'! at: index read: aCollection startingAt: start count: count | stop | stop := (start + count - 1) min: (start + size - 1). aCollection replaceFrom: start to: stop with: bytes startingAt: index. ^ stop - start + 1! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/29/2009 22:17'! at: first write: aCollection startingAt: start count: count | last | writable ifFalse: [ self primitiveFailed ]. last := first + count - 1. last > bytes size ifTrue: [self grow]. bytes replaceFrom: first to: last with: aCollection startingAt: start. size := last! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/28/2009 23:10'! close self truncateTo: size. bytes := nil! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/29/2009 22:23'! flush self truncateTo: size! ! !FSMemoryHandle methodsFor: 'private' stamp: 'cwp 8/30/2009 10:29'! grow bytes := reference filesystem growFile: reference path to: self newSize! ! !FSMemoryHandle methodsFor: 'testing' stamp: 'cwp 7/26/2009 14:08'! isOpen ^ bytes notNil! ! !FSMemoryHandle methodsFor: 'private' stamp: 'cwp 8/30/2009 10:29'! newSize ^ (bytes size min: 20) max: 1024! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 14:26'! open bytes := reference filesystem basicOpen: reference path writable: writable. size := bytes size.! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 14:27'! size ^ size! ! !FSMemoryHandle methodsFor: 'public' stamp: 'cwp 7/26/2009 14:29'! truncateTo: anInteger bytes := reference filesystem truncateFile: reference path to: anInteger. size := anInteger! ! FSMemoryHandle subclass: #FSZipHandle instanceVariableNames: 'archive' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Zip'! !FSZipHandle methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 15:37'! close reference filesystem setFile: reference path to: (bytes first: size)! ! !FSZipHandle methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 10:37'! grow | grown | grown := bytes class new: self newSize. grown replaceFrom: 1 to: bytes size with: bytes. bytes := grown! ! Object variableSubclass: #FSPath instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Core'! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/23/2008 14:15'! / aString ^ self root / aString! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/23/2008 18:41'! canonicalizeElements: aCollection | result | result := OrderedCollection new. aCollection do: [:element | element = '..' ifTrue: [result isEmpty ifFalse: [result removeLast]] ifFalse: [element = '.' ifFalse: [result add: element]]]. ^ result! ! !FSPath classSide methodsFor: 'accessing' stamp: 'cwp 12/13/2008 13:30'! delimiter ^ self primDelimiter! ! !FSPath classSide methodsFor: 'accessing' stamp: 'cwp 10/10/2009 15:42'! delimiters ^ '/\'! ! !FSPath classSide methodsFor: 'accessing' stamp: 'cwp 12/23/2008 11:23'! extensionDelimiter ^ $.! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 10/10/2009 15:43'! fromString: aString | delimiters in segments out ch | delimiters := self delimiters. segments := OrderedCollection new. in := aString readStream. out := (String new: 10) writeStream. [in atEnd] whileFalse: [ch := in next. (delimiters includes: ch) ifFalse: [out nextPut: ch] ifTrue: [segments add: out contents. out := (String new: 10) writeStream]]. segments add: out contents. ^ self withAll: segments.! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/13/2008 20:56'! imageFile ^ self fromString: (self primImageName)! ! !FSPath classSide methodsFor: 'primitives' stamp: 'cwp 12/13/2008 13:30'! primDelimiter "Return the path delimiter for the underlying platform's file system." self primitiveFailed ! ! !FSPath classSide methodsFor: 'primitives' stamp: 'cwp 12/13/2008 13:25'! primImageName "Answer the full path name for the current image." self primitiveFailed! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/23/2008 14:11'! resolve: anObject ^ self defaultDirectory resolve: anObject asPath! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/13/2008 21:12'! root ^ self withAll: #('')! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 12/13/2008 13:33'! withAll: aCollection | inst | inst := self new: aCollection size. aCollection withIndexDo: [:segment :index | inst at: index put: segment]. ^ inst! ! !FSPath classSide methodsFor: 'instance creation' stamp: 'cwp 9/16/2009 10:43'! workingDirectory ^ self new! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 12/15/2008 14:05'! , extension | base path | base := (self at: self size) copyUpToLast: self extensionDelimiter. path := self copy. path at: self size put: base , '.' , extension. ^ path! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 12/13/2008 21:11'! / aString | path | path := self class new: self size + 1. path copyFrom: self. path at: path size put: aString. ^ path! ! !FSPath methodsFor: 'comparing' stamp: 'cwp 12/14/2008 17:36'! = other ^ self species = other species and: [self size = other size and: [(1 to: self size) allSatisfy: [:i | (self at: i) = (other at: i)]]]! ! !FSPath methodsFor: 'converting' stamp: 'cwp 12/15/2008 12:40'! asPath ^ self! ! !FSPath methodsFor: 'converting' stamp: 'cwp 9/21/2009 22:58'! asReference ^ FSDiskFilesystem current referenceTo: self! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:08'! asResolvedBy: anObject ^ anObject resolvePath: self! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 7/17/2009 05:15'! assureExtension: aString | extension | extension := (aString first = self extensionDelimiter) ifTrue: [aString] ifFalse: [aString copyWithFirst: self extensionDelimiter]. ^ (self basename endsWith: extension) ifTrue: [self] ifFalse: [self copy at: self size put: (self basename, extension); yourself]! ! !FSPath methodsFor: 'accessing' stamp: 'cwp 12/15/2008 14:02'! basename ^ self at: self size! ! !FSPath methodsFor: 'comparing' stamp: 'cwp 8/30/2009 15:10'! contains: other self size < other size ifFalse: [^ false]. 1 to: self size do: [:i | (self at: i) = (other at: i) ifFalse: [^ false]]. ^ true! ! !FSPath methodsFor: 'private' stamp: 'cwp 12/13/2008 21:08'! copyFrom: aPath | size | size := aPath size min: self size. 1 to: size do: [:i | self at: i put: (aPath at: i)]. ! ! !FSPath methodsFor: 'accessing' stamp: 'cwp 12/13/2008 13:34'! delimiter ^ self class delimiter! ! !FSPath methodsFor: 'accessing' stamp: 'cwp 7/18/2009 01:13'! do: aBlock 1 to: self size do: [ :index || segment | segment := self at: index. segment isEmpty ifFalse: [ aBlock value: segment ] ]! ! !FSPath methodsFor: 'accessing' stamp: 'cwp 12/23/2008 11:25'! extensionDelimiter ^ self class extensionDelimiter! ! !FSPath methodsFor: 'comparing' stamp: 'cwp 12/14/2008 17:06'! hash | hash | hash := self class identityHash. 1 to: self size do: [:i | hash := String stringHash: (self at: i) initialHash: hash]. ^ hash! ! !FSPath methodsFor: 'testing' stamp: 'cwp 7/18/2009 01:03'! isAbsolute ^ self size > 0 and: [(self at: 1) = '']! ! !FSPath methodsFor: 'testing' stamp: 'cwp 9/20/2009 22:21'! isContainedByReference: aReference ^ aReference path contains: self! ! !FSPath methodsFor: 'testing' stamp: 'cwp 12/13/2008 21:00'! isRelative ^ self isAbsolute not! ! !FSPath methodsFor: 'testing' stamp: 'cwp 7/18/2009 00:41'! isRoot ^ self size = 1 and: [self isAbsolute]! ! !FSPath methodsFor: 'testing' stamp: 'cwp 7/18/2009 00:42'! isWorkingDirectory ^ self size = 0! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 7/18/2009 00:43'! parent | size parent | self isRoot ifTrue: [^ self]. self isWorkingDirectory ifTrue: [^ self]. size := self size - 1. parent := self class new: size. 1 to: size do: [:i | parent at: i put: (self at: i)]. ^ parent! ! !FSPath methodsFor: 'printing' stamp: 'cwp 1/13/2009 21:27'! printOn: aStream ^ self printOn: aStream delimiter: self delimiter! ! !FSPath methodsFor: 'printing' stamp: 'cwp 7/18/2009 01:07'! printOn: aStream delimiter: aCharacter self isRoot ifTrue: [aStream nextPut: $/. ^ self]. self isWorkingDirectory ifTrue: [aStream nextPut: $.. ^ self]. (1 to: self size) do: [:index | aStream nextPutAll: (self at: index)] separatedBy: [aStream nextPut: aCharacter]! ! !FSPath methodsFor: 'printing' stamp: 'cwp 1/13/2009 21:27'! printWithDelimiter: aCharacter ^ String streamContents: [:out | self printOn: out delimiter: aCharacter]! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:06'! resolve: anObject ^ anObject asResolvedBy: self! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:04'! resolvePath: aPath | elements | aPath isAbsolute ifTrue: [^ aPath]. elements := Array new: self size + aPath size. 1 to: self size do: [:i | elements at: i put: (self at: i)]. 1 to: aPath size do: [:i | elements at: self size + i put: (aPath at: i)]. ^ self class withAll: (self class canonicalizeElements: elements)! ! !FSPath methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:06'! resolveReference: aReference ^ aReference! ! Object variableSubclass: #FSReference instanceVariableNames: 'filesystem path' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Core'! !FSReference classSide methodsFor: 'instance creation' stamp: 'cwp 9/16/2009 10:58'! defaultDirectory ^ self imageFile parent! ! !FSReference classSide methodsFor: 'instance creation' stamp: 'cwp 1/13/2009 21:11'! filesystem: aFilesystem path: aPath ^ self new setFilesystem: aFilesystem path: aPath! ! !FSReference classSide methodsFor: 'instance creation' stamp: 'cwp 9/16/2009 11:22'! imageFile ^ FSDiskFilesystem current referenceTo: FSPath imageFile! ! !FSReference classSide methodsFor: 'primitives' stamp: 'cwp 9/16/2009 10:58'! primImageName "Answer the full path name for the current image." self primitiveFailed! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 7/20/2009 09:20'! , aString ^ self navigateWith: [path, aString]! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 7/20/2009 09:36'! / anObject ^ self navigateWith: [path / anObject]! ! !FSReference methodsFor: 'comparing' stamp: 'cwp 7/20/2009 09:22'! = other ^ self species = other species and: [self path = other path and: [self filesystem = other filesystem]]! ! !FSReference methodsFor: 'converting' stamp: 'cwp 7/22/2009 08:33'! asAbsolute ^ self isAbsolute ifTrue: [self] ifFalse: [filesystem referenceTo: (filesystem resolve: path)]! ! !FSReference methodsFor: 'converting' stamp: 'cwp 7/20/2009 09:07'! asPath ^ path! ! !FSReference methodsFor: 'converting' stamp: 'cwp 7/20/2009 09:08'! asReference ^ self! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:03'! asResolvedBy: anObject ^ anObject resolveReference: self! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 7/20/2009 09:19'! assureExtension: aString ^ self navigateWith: [path assureExtension: aString]! ! !FSReference methodsFor: 'accessing' stamp: 'cwp 7/20/2009 09:17'! basename ^ path basename! ! !FSReference methodsFor: 'private' stamp: 'cwp 9/22/2009 09:56'! basicCopyTo: aReference | in out buffer | [in := filesystem readStreamOn: (filesystem resolve: path). in ifNil: [filesystem fileDoesNotExist: path]. aReference exists ifTrue: [aReference filesystem fileExists: path]. out := aReference writeStream. buffer := ByteArray new: 1024. [in atEnd] whileFalse: [buffer := in nextInto: buffer. out nextPutAll: buffer]] ensure: [in ifNotNil: [in close]. out ifNotNil: [out close]]! ! !FSReference methodsFor: 'testing' stamp: 'cwp 9/20/2009 22:15'! contains: anObject ^ anObject isContainedByReference: self! ! !FSReference methodsFor: 'public' stamp: 'cwp 9/22/2009 09:48'! copyTo: aReference filesystem = aReference filesystem ifTrue: [filesystem copy: path to: aReference path] ifFalse: [self basicCopyTo: aReference]! ! !FSReference methodsFor: 'private' stamp: 'cwp 7/22/2009 06:56'! createHandle ^ filesystem createHandleFor: self! ! !FSReference methodsFor: 'public' stamp: 'cwp 7/22/2009 07:42'! delete filesystem delete: path! ! !FSReference methodsFor: 'public' stamp: 'cwp 1/13/2009 22:04'! ensureDirectory filesystem ensureDirectory: path ! ! !FSReference methodsFor: 'public' stamp: 'cwp 10/8/2009 23:50'! entries ^ filesystem entriesAt: self! ! !FSReference methodsFor: 'public' stamp: 'cwp 1/13/2009 20:52'! exists ^ filesystem exists: path! ! !FSReference methodsFor: 'public' stamp: 'cwp 7/24/2009 00:47'! fileStreamDo: aBlock | stream | [stream := filesystem openFileStream: path writable: true. aBlock value: stream] ensure: [stream ifNotNil: [stream close]] ! ! !FSReference methodsFor: 'accessing' stamp: 'cwp 7/18/2009 22:53'! filesystem ^ filesystem! ! !FSReference methodsFor: 'comparing' stamp: 'cwp 9/16/2009 23:54'! hash ^ path hash bitXor: filesystem hash! ! !FSReference methodsFor: 'testing' stamp: 'cwp 7/20/2009 09:24'! isAbsolute ^ path isAbsolute! ! !FSReference methodsFor: 'testing' stamp: 'cwp 9/20/2009 22:18'! isContainedByReference: aReference ^ aReference filesystem = filesystem and: [aReference path contains: path]! ! !FSReference methodsFor: 'public' stamp: 'cwp 1/13/2009 21:39'! isDirectory ^ filesystem isDirectory: path! ! !FSReference methodsFor: 'public' stamp: 'cwp 1/13/2009 21:57'! isFile ^ filesystem isFile: path! ! !FSReference methodsFor: 'testing' stamp: 'cwp 7/20/2009 09:25'! isRelative ^ path isRelative! ! !FSReference methodsFor: 'testing' stamp: 'cwp 7/20/2009 09:26'! isRoot ^ path isRoot! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 7/20/2009 09:19'! navigateWith: aBlock | newPath | newPath := aBlock value. ^ path == newPath ifTrue: [self] ifFalse: [filesystem referenceTo: newPath]! ! !FSReference methodsFor: 'public' stamp: 'cwp 7/22/2009 22:05'! openWritable: aBoolean ^ filesystem open: path writable: aBoolean! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 7/20/2009 09:28'! parent ^ self navigateWith: [path parent]! ! !FSReference methodsFor: 'accessing' stamp: 'cwp 7/18/2009 22:53'! path ^ path! ! !FSReference methodsFor: 'public' stamp: 'cwp 7/22/2009 08:24'! pathString ^ filesystem pathToString: (filesystem resolve: path)! ! !FSReference methodsFor: 'printing' stamp: 'cwp 1/13/2009 21:34'! printOn: aStream filesystem forReferencePrintOn: aStream. aStream nextPut: $:. filesystem printPath: path on: aStream! ! !FSReference methodsFor: 'public' stamp: 'cwp 9/22/2009 09:55'! readStream ^ filesystem readStreamOn: path! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:03'! resolve: anObject ^ anObject asResolvedBy: self! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:03'! resolvePath: anObject ^ self navigateWith: [path resolve: anObject]! ! !FSReference methodsFor: 'navigating' stamp: 'cwp 9/22/2009 09:23'! resolveReference: aReference ^ (filesystem = aReference filesystem or: [aReference isRelative]) ifTrue: [filesystem referenceTo: (path resolvePath: aReference path)] ifFalse: [aReference]! ! !FSReference methodsFor: 'initialize-release' stamp: 'cwp 1/13/2009 21:12'! setFilesystem: aFilesystem path: aPath filesystem := aFilesystem. path := aPath! ! !FSReference methodsFor: 'public' stamp: 'cwp 7/28/2009 23:01'! writeStream ^ filesystem writeStreamOn: path! ! !FSReference methodsFor: 'public' stamp: 'cwp 9/22/2009 20:33'! writeStreamDo: aBlock | stream | stream := self writeStream. [aBlock value: stream] ensure: [stream ifNotNil: [stream close]]! ! Object subclass: #FSStream instanceVariableNames: 'handle position' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Streams'! FSStream subclass: #FSReadStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Streams'! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 22:45'! atEnd ^ position - 1 = handle size! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 22:58'! do: aBlock [self atEnd] whileFalse: [aBlock value: self next]! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 22:59'! next | result | result := handle at: position. position := position + 1. ^ result! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 23:03'! next: count | result | result := ByteArray new: count. handle at: position read: result startingAt: 1 count: count. position := position + 1. ^ result! ! !FSReadStream methodsFor: 'squeak' stamp: 'cwp 7/31/2009 00:24'! nextInto: aCollection | count | count := handle at: position read: aCollection startingAt: 1 count: aCollection size. position := position + count. ^ count < aCollection size ifTrue: [aCollection first: count] ifFalse: [aCollection]! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 23:31'! nextLine | char | ^ ByteArray streamContents: [:out | [self atEnd or: [#(13 10) includes: (char := self next)]] whileFalse: [out nextPut: char]. (char = 13 and: [self peek = 10]) ifTrue: [position := position + 1]]. ! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/30/2009 23:03'! nextMatchFor: anObject ^ self next = anObject! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/29/2009 23:27'! peek ^ handle at: position! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/30/2009 23:06'! peekFor: anObject ^ self peek = anObject! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/30/2009 23:19'! skip: anInteger position := position + anInteger min: handle size + 1! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/30/2009 23:27'! skipTo: anObject | result | [self atEnd or: [result := (self next = anObject)]] whileFalse. ^ result! ! !FSReadStream methodsFor: 'ansi' stamp: 'cwp 7/30/2009 23:37'! upTo: anObject | byte | ^ ByteArray streamContents: [:out | [self atEnd or: [(byte := self next) = anObject]] whileFalse: [out nextPut: byte]] ! ! !FSStream classSide methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:30'! onHandle: aHandle ^ self new setHandle: aHandle ! ! !FSStream methodsFor: 'public' stamp: 'cwp 7/29/2009 22:29'! close handle close! ! !FSStream methodsFor: 'public' stamp: 'cwp 7/29/2009 22:29'! contents | size contents | size := handle size. contents := ByteArray new: size. handle at: 1 read: contents startingAt: 1 count: size. ^ contents! ! !FSStream methodsFor: 'public' stamp: 'cwp 7/29/2009 22:32'! position ^ position! ! !FSStream methodsFor: 'public' stamp: 'cwp 7/29/2009 22:32'! position: anInteger position := anInteger! ! !FSStream methodsFor: 'initialize-release' stamp: 'cwp 7/29/2009 22:30'! setHandle: aHandle handle := aHandle. position := 1! ! FSStream subclass: #FSWriteStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Streams'! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/28/2009 22:25'! cr self nextPut: 13! ! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/28/2009 22:22'! flush handle flush! ! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/23/2009 17:03'! nextPut: anObject handle at: position put: anObject. position := position + 1. ^ anObject! ! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/23/2009 22:51'! nextPutAll: aCollection handle at: position write: aCollection startingAt: 1 count: aCollection size. position := position + aCollection size. ^ aCollection! ! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/28/2009 22:26'! space self nextPut: 32! ! !FSWriteStream methodsFor: 'ansi puttable' stamp: 'cwp 7/28/2009 22:28'! tab self nextPut: 9! ! RWBinaryOrTextStream subclass: #FSFileStream instanceVariableNames: 'reference' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Streams'! !FSFileStream classSide methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:28'! on: aCollection filesystem: aFilesystem path: aPath ^ self on: aCollection reference: (FSReference filesystem: aFilesystem path: aPath)! ! !FSFileStream classSide methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:28'! on: aCollection reference: aFileReference ^ (self on: aCollection) reference: aFileReference yourself! ! !FSFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:28'! on: aCollection super on: aCollection. readLimit := collection size.! ! !FSFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:14'! reference: aFileReference reference := aFileReference! ! FSFileStream subclass: #FSMemoryFileStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Memory'! !FSMemoryFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 7/19/2009 22:21'! close reference filesystem truncateFile: reference path to: position. ! ! !FSMemoryFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 7/19/2009 22:11'! growTo: anInteger collection := reference filesystem growFile: reference path to: anInteger. writeLimit := collection size. ! ! !FSMemoryFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 7/19/2009 09:56'! pastEndPut: anObject | oldSize newSize | oldSize := collection size. newSize := oldSize + ((oldSize max: 20) min: 1000000). collection := reference filesystem growFile: reference path to: newSize. writeLimit := collection size. collection at: (position := position + 1) put: anObject. ^ anObject! ! FSFileStream subclass: #FSZipFileStream instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Zip'! !FSZipFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:31'! close self flush! ! !FSZipFileStream methodsFor: 'as yet unclassified' stamp: 'cwp 8/30/2009 18:30'! flush reference filesystem setFile: reference path to: self contents! ! TestCase subclass: #FSFilesystemTest instanceVariableNames: 'filesystem toDelete' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! FSFilesystemTest subclass: #FSDiskFilesystemTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSDiskFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 7/20/2009 08:38'! createFilesystem ^ FSDiskFilesystem current! ! !FSDiskFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 08:58'! testDefaultWorkingDirectory self assert: filesystem workingDirectory asString = SmalltalkImage current imagePath! ! !FSDiskFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/24/2009 00:40'! testEqual | other | other := self createFilesystem. self assert: filesystem = other! ! !FSDiskFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 16:07'! testIsDirectory self halt. self assert: (filesystem isDirectory: FSReference defaultDirectory path)! ! !FSFilesystemTest classSide methodsFor: 'as yet unclassified' stamp: 'cwp 7/20/2009 08:56'! isAbstract ^ self name = #FSFilesystemTest! ! !FSFilesystemTest classSide methodsFor: 'as yet unclassified' stamp: 'cwp 7/20/2009 08:56'! shouldInheritSelectors ^ true ! ! !FSFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 7/20/2009 07:31'! createFilesystem self subclassResponsibility ! ! !FSFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 8/23/2009 23:09'! delete: anObject toDelete add: anObject asPath! ! !FSFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 8/23/2009 23:10'! setUp filesystem := self createFilesystem. toDelete := OrderedCollection new.! ! !FSFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 8/23/2009 23:09'! tearDown toDelete do: [:path | filesystem delete: path]! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:57'! testChangeDirectory filesystem workingDirectory: '/plonk' asPath. filesystem changeDirectory: 'griffle' asPath. self assert: (filesystem workingDirectory printWithDelimiter: $/) = '/plonk/griffle'! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:57'! testChangeDirectoryString filesystem workingDirectory: '/plonk' asPath. filesystem changeDirectory: 'griffle'. self assert: (filesystem workingDirectory printWithDelimiter: $/) = '/plonk/griffle'! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/30/2009 23:49'! testCopy | out in contents | [out := filesystem writeStreamOn: 'gooly'. [out nextPutAll: 'gooly'] ensure: [out close]. filesystem copy: 'gooly' to: 'plonk'. in := filesystem readStreamOn: 'plonk'. [contents := in contents asString] ensure: [in close]. self assert: contents = 'gooly'] ensure: [filesystem delete: 'gooly'; delete: 'plonk']! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/28/2009 22:53'! testCopyDestExists | out | [out := (filesystem open: 'gooly' writable: true) writeStream. [out nextPutAll: 'gooly'] ensure: [out close]. out := filesystem open: 'plonk' writable: true. out close. self should: [filesystem copy: 'gooly' to: 'plonk'] raise: FileExistsException] ensure: [filesystem delete: 'gooly'; delete: 'plonk']! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/24/2009 00:29'! testCopySourceDoesntExist self should: [filesystem copy: 'plonk' to: 'griffle'] raise: FileDoesNotExistException! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 07:30'! testDefaultWorkingDirectory self assert: filesystem workingDirectory isRoot! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 07:30'! testDelimiter self assert: filesystem delimiter isCharacter! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 07:30'! testDirectory | path | path := 'plonk' asPath. filesystem createDirectory: path. self assert: (filesystem exists: path). self assert: (filesystem isDirectory: path). self deny: (filesystem isFile: path). filesystem delete: path. self deny: (filesystem exists: path)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 8/29/2009 10:21'! testEntries | directory entries | directory := 'plonk' asPath. filesystem createDirectory: directory. filesystem createDirectory: directory / 'griffle'. filesystem createDirectory: directory / 'bint'. self delete: directory / 'griffle'. self delete: directory / 'bint'. self delete: directory. entries := filesystem entriesAt: directory. self assert: entries size = 2. entries do: [:ea | self assert: (ea isKindOf: FSReference). self assert: ea parent path = (filesystem resolve: directory). self assert: (#('griffle' 'bint') includes: ea basename)]! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/22/2009 22:32'! testFile | path out | path := 'gooly' asPath. out := filesystem open: path writable: true. out close. self assert: (filesystem exists: path). self deny: (filesystem isDirectory: path). self assert: (filesystem isFile: path). filesystem delete: path. self deny: (filesystem exists: path)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 13:11'! testFileStream | path out | path := 'gooly' asPath. out := filesystem openFileStream: path writable: true. out close. self assert: (filesystem exists: path). self deny: (filesystem isDirectory: path). self assert: (filesystem isFile: path). filesystem delete: path. self deny: (filesystem exists: path)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 8/30/2009 15:40'! testFileStreamContents | path out in contents | path := 'gooly' asPath. self delete: path. out := filesystem openFileStream: path writable: true. [out nextPutAll: 'gooly'] ensure: [out close]. in := filesystem openFileStream: path writable: false. [contents := in ascii; contentsOfEntireFile] ensure: [in close]. self assert: contents = 'gooly'! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 00:33'! testRootExists self assert: (filesystem exists: FSPath root)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 00:25'! testRootIsDirectory self assert: (filesystem isDirectory: FSPath root)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 00:33'! testRootIsNotAFile self deny: (filesystem isFile: FSPath root)! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 07:30'! testSetRelativeWorkingDirectory self should: [filesystem workingDirectory: 'plonk' asPath] raise: Error ! ! !FSFilesystemTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:57'! testSetWorkingDirectory filesystem workingDirectory: '/plonk' asPath. self assert: (filesystem workingDirectory printWithDelimiter: $/) = '/plonk'.! ! FSFilesystemTest subclass: #FSMemoryFilesystemTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSMemoryFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 7/20/2009 07:29'! createFilesystem ^ FSMemoryFilesystem new! ! !FSMemoryFilesystemTest methodsFor: 'tests' stamp: 'cwp 7/24/2009 00:41'! testEqual | other | other := self createFilesystem. self deny: filesystem = other! ! FSFilesystemTest subclass: #FSZipFilesystemTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSZipFilesystemTest methodsFor: 'initialize-release' stamp: 'cwp 9/21/2009 22:59'! createFilesystem | ref | ref := FSDiskFilesystem current referenceTo: 'fs.zip'. ^ (FSZipFilesystem atReference: ref) open; yourself! ! TestCase subclass: #FSHandleTest instanceVariableNames: 'filesystem handle reference' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! FSHandleTest subclass: #FSFileHandleTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSFileHandleTest methodsFor: 'running' stamp: 'cwp 7/26/2009 12:22'! createFilesystem ^ FSDiskFilesystem current! ! !FSHandleTest classSide methodsFor: 'as yet unclassified' stamp: 'cwp 7/26/2009 12:46'! isAbstract ^ self name = #FSHandleTest! ! !FSHandleTest classSide methodsFor: 'as yet unclassified' stamp: 'cwp 7/26/2009 12:46'! shouldInheritSelectors ^ true! ! !FSHandleTest methodsFor: 'running' stamp: 'cwp 7/26/2009 12:22'! setUp filesystem := self createFilesystem. reference := filesystem referenceTo: 'plonk'. handle := reference openWritable: true! ! !FSHandleTest methodsFor: 'running' stamp: 'cwp 7/26/2009 12:23'! tearDown handle close. reference delete! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 22:06'! testAt handle at: 1 write: (ByteArray with: 3) startingAt: 1 count: 1. self assert: (handle at: 1) = 3! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 22:03'! testAtPut | in | handle at: 1 put: 3. in := ByteArray new: 1. handle at: 1 read: in startingAt: 1 count: 1. self assert: in first = 3! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 12:23'! testClose handle close. self deny: handle isOpen ! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 12:23'! testCreatedOpen self assert: handle isOpen! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 14:15'! testIO | out in | out := #(1 2 3) asByteArray. in := ByteArray new: 3. handle at: 1 write: out startingAt: 1 count: 3. handle at: 1 read: in startingAt: 1 count: 3. self assert: out = in.! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/31/2009 00:13'! testReadBufferTooLarge | out in result | out := #(1 2 3) asByteArray. in := ByteArray new: 5. in atAllPut: 9. handle at: 1 write: out startingAt: 1 count: 3. result := handle at: 1 read: in startingAt: 2 count: 4. self assert: result = 3. self assert: in = #(9 1 2 3 9) asByteArray.! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 14:16'! testReadOnly handle close. handle := reference openWritable: false. self should: [ handle at: 1 write: #(1 2 3 ) startingAt: 1 count: 3 ] raise: Error! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 12:45'! testReference self assert: handle reference = reference asAbsolute! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 22:11'! testSizeAfterGrow | out | out := #(1 2 3) asByteArray. handle at: 1 write: out startingAt: 1 count: 3. self assert: handle size = 3! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 22:13'! testSizeNoGrow | bytes | bytes := #(1 2 3 4) asByteArray. handle at: 1 write: bytes startingAt: 1 count: 3. handle at: 4 write: bytes startingAt: 4 count: 1. self assert: handle size = 4! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/26/2009 14:16'! testTruncate | out | out := #(1 2 3 4 5) asByteArray. handle at: 1 write: out startingAt: 1 count: 5. handle truncateTo: 3. self assert: handle size = 3! ! !FSHandleTest methodsFor: 'tests' stamp: 'cwp 7/28/2009 22:40'! testWriteStream | stream | stream := handle writeStream. self assert: (stream respondsTo: #nextPut:)! ! FSHandleTest subclass: #FSMemoryHandleTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSMemoryHandleTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/26/2009 12:47'! createFilesystem ^ FSMemoryFilesystem new! ! TestCase variableSubclass: #FSPathTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:10'! testAsPath | a b | a := 'plonk' asPath. b := a asPath. self assert: a == b! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 8/7/2009 09:25'! testAsReference | path reference | path := 'plonk' asPath. reference := path asReference. self assert: reference class = FSReference ! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:16'! testAssureExtentionAddsExtension | path result | path := 'plonk' asPath. result := path assureExtension: 'griffle'. self assert: result asString = 'plonk.griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:16'! testAssureExtentionNoDuplicates | path result | path := 'plonk.griffle' asPath. result := path assureExtension: 'griffle'. self assert: result asString = 'plonk.griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:17'! testAssureExtentionWithDot | path result | path := 'plonk' asPath. result := path assureExtension: '.griffle'. self assert: result asString = 'plonk.griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:18'! testBasename | path | path := 'plonk/griffle' asPath. self assert: path basename = 'griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:04'! testCommaAddsExtension | path result | path := 'plonk' asPath. result := path, 'griffle'. self assert: result asString = 'plonk.griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:06'! testCommaReplacesExtension | path result | path := 'plonk.griffle' asPath. result := path, 'nurp'. self assert: result asString = 'plonk.nurp'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 8/30/2009 15:07'! testContains | ancestor descendent | ancestor := FSPath / 'plonk'. descendent := FSPath / 'plonk' / 'griffle' / 'bork'. self assert: (ancestor contains: descendent). self deny: (descendent contains: ancestor)! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:09'! testEqual | a b | a := 'plonk' asPath. b := 'plonk' asPath. self deny: a == b. self assert: a = b.! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:21'! testIsAbsolute self assert: '/plonk' asPath isAbsolute! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:21'! testIsNotAbsolute self deny: 'plonk' asPath isAbsolute! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:22'! testIsNotRelative self deny: '/plonk' asPath isRelative! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:23'! testIsNotRoot self deny: (FSPath root / 'plonk') isRoot! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:22'! testIsRelative self assert: 'plonk' asPath isRelative! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:23'! testIsRoot self assert: FSPath root isRoot! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:19'! testParent | path parent | path := 'plonk/griffle' asPath. parent := path parent. self assert: parent class = path class. self assert: parent asString = 'plonk'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:47'! testParentResolution | base relative absolute | base := '/plonk/pinto' asPath. relative := '../griffle/zonk' asPath. absolute := base resolve: relative. self assert: (absolute printWithDelimiter: $/) = '/plonk/griffle/zonk'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:20'! testPrintWithDelimiter | path | path := 'plonk/griffle' asPath. self assert: (path printWithDelimiter: $%) = 'plonk%griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 23:40'! testRootParent | root | root := FSPath root. self assert: root parent == root! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:46'! testSimpleResolution | base relative absolute | base := '/plonk' asPath. relative := 'griffle/zonk' asPath. absolute := base resolve: relative. self assert: (absolute printWithDelimiter: $/) = '/plonk/griffle/zonk'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:46'! testSlash | path actual | path := 'plonk' asPath. actual := path / 'griffle'. self assert: actual class = FSPath. self assert: (actual printWithDelimiter: $/) = 'plonk/griffle'! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:09'! testUnequalContent | a b | a := 'plonk' asPath. b := 'griffle' asPath. self deny: a = b.! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 05:09'! testUnequalSize | a b | a := 'plonk' asPath. b := 'plonk/griffle' asPath. self deny: a = b.! ! !FSPathTest methodsFor: 'tests' stamp: 'cwp 7/17/2009 23:41'! testWorkingDirectoryParent | wd | wd := FSPath new. self assert: wd parent == wd! ! TestCase subclass: #FSReadStreamTest instanceVariableNames: 'filesystem stream' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:43'! contents: aByteArray stream := filesystem writeStreamOn: 'griffle'. stream nextPutAll: aByteArray. stream close. stream := filesystem readStreamOn: 'griffle'! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:40'! setUp filesystem := FSMemoryFilesystem new. ! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:38'! testAtEnd self contents: #(). self assert: stream atEnd! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:57'! testDo | contents | self contents: #(1 2 3). contents := Array streamContents: [:out | stream do: [:ea | out nextPut: ea]]. self assert: contents = #(1 2 3)! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 23:00'! testNext self contents: #(1 2 3). self assert: stream next = 1! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 23:07'! testNextColon | result | self contents: #(1 2 3 4 5). result := stream next: 3. self assert: result = #(1 2 3) asByteArray.! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:54'! testNextInto | result buffer | self contents: #(1 2 3 4 5). buffer := ByteArray new: 3. result := stream nextInto: buffer. self assert: result == buffer. self assert: result = #(1 2 3) asByteArray! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 23:30'! testNextLineCR | result tail | self contents: #(97 97 97 13 98 98 98). result := stream nextLine. self assert: result = #(97 97 97) asByteArray. tail := stream next: 3. self assert: tail = #(98 98 98) asByteArray! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 23:31'! testNextLineCRLF | line tail | self contents: #(97 97 97 13 10 98 98 98). line := stream nextLine. self assert: line = #(97 97 97) asByteArray. tail := stream next: 3. self assert: tail = #(98 98 98) asByteArray! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 23:31'! testNextLineLF | result tail | self contents: #(97 97 97 10 98 98 98). result := stream nextLine. self assert: result = #(97 97 97) asByteArray. tail := stream next: 3. self assert: tail = #(98 98 98) asByteArray! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:04'! testNextMatchFalse self contents: #(1 2 3). self deny: (stream nextMatchFor: 5)! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:01'! testNextMatchTrue self contents: #(1 2 3). self assert: (stream nextMatchFor: 1)! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/29/2009 22:46'! testNotAtEnd self contents: #(1 2 3). self deny: stream atEnd! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:05'! testPeek self contents: #(1 2 3). self assert: stream peek = 1. self assert: stream next = 1.! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:06'! testPeekForFalse self contents: #(1 2 3). self deny: (stream peekFor: 5) ! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:06'! testPeekForTrue self contents: #(1 2 3). self assert: (stream peekFor: 1) ! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:17'! testSkip self contents: #(1 2 3 4 5). stream skip: 3. self assert: stream position = 4! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:18'! testSkipPastEnd self contents: #(1 2 3 4 5). stream skip: 10. self assert: stream atEnd! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:20'! testSkipTo self contents: #(1 2 3 4 5). stream skipTo: 3. self assert: stream position = 4! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:24'! testSkipToEnd self contents: #(1 2 3 4 5). stream skipTo: 10. self assert: stream atEnd! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:27'! testSkipToFalse self contents: #(1 2 3 4 5). self deny: (stream skipTo: 10). ! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:25'! testSkipToTrue self contents: #(1 2 3 4 5). self assert: (stream skipTo: 4). ! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:38'! testUpTo | result | self contents: #(1 2 3 4 5). result := stream upTo: 4. self assert: result = #(1 2 3) asByteArray! ! !FSReadStreamTest methodsFor: 'as yet unclassified' stamp: 'cwp 7/30/2009 23:38'! testUpToEnd | result | self contents: #(1 2 3 4 5). result := stream upTo: 7. self assert: result = #(1 2 3 4 5) asByteArray! ! TestCase variableSubclass: #FSReferenceTest instanceVariableNames: 'filesystem' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSReferenceTest methodsFor: 'running' stamp: 'cwp 7/20/2009 09:06'! setUp filesystem := FSMemoryFilesystem new.! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/22/2009 08:33'! testAsAbsoluteConverted | ref absolute | ref := filesystem referenceTo: 'plonk'. absolute := ref asAbsolute. self assert: absolute isAbsolute. self assert: absolute asString = 'memory:/plonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/22/2009 08:30'! testAsAbsoluteIdentity | ref | ref := filesystem referenceTo: '/plonk'. self assert: ref asAbsolute == ref! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:07'! testAsPath | ref path | ref := filesystem referenceTo: 'plonk'. path := ref asPath. self assert: path class = FSPath. self assert: path asString = 'plonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:08'! testAsReference | ref | ref := filesystem referenceTo: 'plonk'. self assert: ref asReference == ref! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:10'! testAssureExtentionAddsExtension | ref result | ref := filesystem referenceTo: 'plonk'. result := ref assureExtension: 'griffle'. self assert: result asString = 'memory:plonk.griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:16'! testAssureExtentionNoDuplicates | ref result | ref := filesystem referenceTo: 'plonk.griffle'. result := ref assureExtension: 'griffle'. self assert: result asString = 'memory:plonk.griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:16'! testAssureExtentionWithDot | ref result | ref := filesystem referenceTo: 'plonk.griffle'. result := ref assureExtension: '.griffle'. self assert: result asString = 'memory:plonk.griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:17'! testBasename | ref | ref := filesystem referenceTo: 'plonk/griffle'. self assert: ref basename = 'griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:18'! testCommaAddsExtension | ref result | ref := filesystem referenceTo: 'plonk'. result := ref, 'griffle'. self assert: result asString = 'memory:plonk.griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:20'! testCommaReplacesExtension | ref result | ref := filesystem referenceTo: 'plonk.griffle'. result := ref, 'nurp'. self assert: result asString = 'memory:plonk.nurp'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:21'! testEqual | a b | a := filesystem referenceTo: 'plonk'. b := filesystem referenceTo: 'plonk'. self deny: a == b. self assert: a = b.! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:23'! testIsAbsolute self assert: (filesystem referenceTo: '/plonk') isAbsolute! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:24'! testIsNotAbsolute self deny: (filesystem referenceTo: 'plonk') isAbsolute! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:25'! testIsNotRelative self deny: (filesystem referenceTo: '/plonk') isRelative! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:26'! testIsNotRoot self deny: (filesystem referenceTo: FSPath root / 'plonk') isRoot! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:26'! testIsRelative self assert: (filesystem referenceTo: 'plonk') isRelative! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:27'! testIsRoot self assert: (filesystem referenceTo: FSPath root) isRoot! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:27'! testParent | ref parent | ref := (filesystem referenceTo: 'plonk/griffle'). parent := ref parent. self assert: parent class = ref class. self assert: parent asString = 'memory:plonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 10/10/2009 15:56'! testParentResolutionWithAbsoluteReference | base relative absolute | base := (filesystem referenceTo: '/plonk/pinto'). relative := (FSDiskFilesystem current referenceTo: '/griffle/zonk'). absolute := base resolve: relative. self assert: absolute filesystem == relative filesystem. self assert: (absolute path printWithDelimiter: $/) = '/griffle/zonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:29'! testParentResolutionWithPath | base relative absolute | base := (filesystem referenceTo: '/plonk/pinto'). relative := '../griffle/zonk' asPath. absolute := base resolve: relative. self assert: absolute asString = 'memory:/plonk/griffle/zonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:31'! testParentResolutionWithReference | base relative absolute | base := (filesystem referenceTo: '/plonk/pinto'). relative := (filesystem referenceTo: '../griffle/zonk'). absolute := base resolve: relative. self assert: absolute asString = 'memory:/plonk/griffle/zonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:33'! testParentResolutionWithRemoteReference | base relative absolute | base := (filesystem referenceTo: '/plonk/pinto'). relative := (FSDiskFilesystem current referenceTo: '../griffle/zonk'). absolute := base resolve: relative. self assert: absolute asString = 'memory:/plonk/griffle/zonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:34'! testRootParent | root | root := filesystem referenceTo: FSPath root. self assert: root parent == root! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:35'! testSimpleResolution | base relative absolute | base := filesystem referenceTo: '/plonk'. relative := 'griffle/zonk' asPath. absolute := base resolve: relative. self assert: absolute asString = 'memory:/plonk/griffle/zonk'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:36'! testSlash | ref result | ref := filesystem referenceTo: 'plonk'. result := ref / 'griffle'. self assert: result class = FSReference. self assert: result asString = 'memory:plonk/griffle'! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:37'! testUnequalContent | a b | a := filesystem referenceTo: 'plonk'. b := filesystem referenceTo: 'griffle'. self deny: a = b.! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:56'! testUnequalSize | a b | a := filesystem referenceTo: 'plonk'. b := filesystem referenceTo: 'plonk/griffle'. self deny: a = b.! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/20/2009 09:57'! testWorkingDirectoryParent | wd | wd := filesystem referenceTo: FSPath new. self assert: wd parent == wd! ! !FSReferenceTest methodsFor: 'tests' stamp: 'cwp 7/28/2009 23:05'! testWriteStream | ref stream | ref := filesystem referenceTo: 'plonk'. [stream := ref writeStream. self assert: (stream respondsTo: #nextPut:)] ensure: [stream ifNotNil: [stream close]]! ! TestCase subclass: #FSWriteStreamTest instanceVariableNames: 'filesystem stream' classVariableNames: '' poolDictionaries: '' category: 'Filesystem-Tests'! !FSWriteStreamTest methodsFor: 'accessing' stamp: 'cwp 7/29/2009 22:21'! contents ^ filesystem entryAt: FSPath / 'giffle' ifPresent: [:bytes | bytes] ifAbsent: [self signalFailure: 'No file!!']! ! !FSWriteStreamTest methodsFor: 'running' stamp: 'cwp 7/29/2009 21:57'! setUp filesystem := FSMemoryFilesystem new. stream := filesystem writeStreamOn: 'giffle'! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/28/2009 22:48'! testClose self shouldnt: [stream close] raise: Error! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 21:55'! testContents stream nextPutAll: #(42 43 44). self assert: stream contents = #(42 43 44) asByteArray! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 21:55'! testCr stream cr. self assert: self contents first = 13! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/28/2009 22:21'! testFlush self shouldnt: [stream flush] raise: Error! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 21:55'! testNextPut stream nextPut: 42. self assert: self contents first = 42! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 22:23'! testNextPutAll stream nextPutAll: #(42 43 44). stream flush. self assert: self contents = #(42 43 44) asByteArray! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 21:55'! testSpace stream space. self assert: self contents first = 32! ! !FSWriteStreamTest methodsFor: 'tests' stamp: 'cwp 7/29/2009 21:56'! testTab stream tab. self assert: self contents first = 9! ! FSDiskFilesystem initialize! FSFileHandle initialize!