This week, I had to test my new implementation of getting the current working directory and I happen to stumble upon some of the file system classes and its implementation. Though there is a thorough documentation for the end user about using the filesystem there is still gap about its implementation. In this blog, I would like to fill that gap.
To start with the file system, File System class in Pharo provides a lot of functionalities to the IDE. It plays an important role in a lot of file operations like creating a file, reading a file, modifying a file, moving a file, copying a file, deleting a file, accessing the properties of a file, and much more. The filesystem class hierarchy is as follows:
The FileSystem class is used in creating a file system. The FileSystemDirectoryEntry is used in getting more information from a file or directory. FileSystemPermissions is used in setting permissions for a file or directory. The AbstractFileReference is a super class for FileLocator and FileReference. The AbstractFileReference class avoid code duplication between its subclasses. The FileLocator class is used in looking up the current location of the origin and it resolves the path against it. While the FileReference class is a reference to folder or file and is used in navigating and performing operations on files or folders. More about these classes can be found here.
Going into the internals of the FileSystem, the FileSystem API has the path and filesystems at the lowest level. The FileReference class provides a simpler protocol by combining the path and filesystems into a single object. The FileReference class has all the methods for navigating filesystems, performing filesystem operations, etc. The current implementation of the workingDirectory is as follows. The FileSystem class has the method ‘workingDirectory’ which references to the method ‘workingDirectoryPath’ in the same class. The ‘workingDirectorPath’ is implemented as follows
^ store defaultWorkingDirectory
The defaultWorkingDirectory is a method in the FileSystemStore class. And the store is a subinstance of the FileSystemStore class and the FileSystem class holds a reference to it. The FileSystem class resolves the paths before sending it to store. The store instance has platform specific methods and implements accordingly. The DiskStore class is as follows:
The ‘defaultWorkingDirectory’ implementation is as follows
| pathString |
pathString := Primitives decode: Primitives imageFile.
^ (self pathFromString: pathString) parent
In this, Primitives is a class variable of DiskStore and it is an instance of FilePluginPrims. This implementations uses the current image file and gets the location of the file, converts the string into path. And it returns the parent of the path i.e it returns the path without the image string which is the directory of the image. And this is what is being changed in the new implementation. When workingdirectory is asked, the new method will give the exact directory instead of the location of the image.
Coming to Paths, paths are the high level protocol to deal with directory and file paths instead of strings. Paths help in manipulating with extensions, navigating through files, etc. The method ‘referenceTo’ is used to link a path with the actual filesystem. More examples on Path can be found in here.
Apart from the FileSystem-Core package, there other important packages ( filesystems ) namely FileSystem-Disk, FileSystem-Memory and FileSystem-Zip. FileSystem-Disk refers to actual filesystem on the harddisk. It has a singleton instance and has platform specific subclasses. The above mentioned DiskStore and its subclasses are present in this FileSystem-Disk. The FileSystem-Memory refers to a virtual filesystem like a Random Access Memory disk in the Pharo image. This helps in experimenting and testing the code on a virtual system rather than touching the actual filesystem. The FileSystem-Zip package represents a ZIP archive on another filesystem. More about these filesystems and its methods can be found here.
So, this is a brief of filesystem classes. The classes look complex, but they enable the user to play with filesystem methods without any difficulty.