| 58 | * With no mounted file systems, `MountableFileSystem` acts as a simple `InMemory` filesystem. |
| 59 | */ |
| 60 | export default class MountableFileSystem extends BaseFileSystem implements FileSystem { |
| 61 | public static readonly Name = "MountableFileSystem"; |
| 62 | |
| 63 | public static readonly Options: FileSystemOptions = {}; |
| 64 | |
| 65 | /** |
| 66 | * Creates a MountableFileSystem instance with the given options. |
| 67 | */ |
| 68 | public static Create(opts: MountableFileSystemOptions, cb: BFSCallback<MountableFileSystem>): void { |
| 69 | const fs = new MountableFileSystem(); |
| 70 | Object.keys(opts).forEach((mountPoint) => { |
| 71 | fs.mount(mountPoint, opts[mountPoint]); |
| 72 | }); |
| 73 | cb(null, fs); |
| 74 | } |
| 75 | public static isAvailable(): boolean { |
| 76 | return true; |
| 77 | } |
| 78 | |
| 79 | private mntMap: {[path: string]: FileSystem}; |
| 80 | // Contains the list of mount points in mntMap, sorted by string length in decreasing order. |
| 81 | // Ensures that we scan the most specific mount points for a match first, which lets us |
| 82 | // nest mount points. |
| 83 | private mountList: string[] = []; |
| 84 | private rootFs: FileSystem; |
| 85 | |
| 86 | /** |
| 87 | * Creates a new, empty MountableFileSystem. |
| 88 | */ |
| 89 | constructor() { |
| 90 | super(); |
| 91 | this.mntMap = {}; |
| 92 | // The InMemory file system serves purely to provide directory listings for |
| 93 | // mounted file systems. |
| 94 | this.rootFs = new InMemoryFileSystem(); |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * Mounts the file system at the given mount point. |
| 99 | */ |
| 100 | public mount(mountPoint: string, fs: FileSystem): void { |
| 101 | if (mountPoint[0] !== '/') { |
| 102 | mountPoint = `/${mountPoint}`; |
| 103 | } |
| 104 | mountPoint = path.resolve(mountPoint); |
| 105 | if (this.mntMap[mountPoint]) { |
| 106 | throw new ApiError(ErrorCode.EINVAL, "Mount point " + mountPoint + " is already taken."); |
| 107 | } |
| 108 | mkdirpSync(mountPoint, 0x1ff, this.rootFs); |
| 109 | this.mntMap[mountPoint] = fs; |
| 110 | this.mountList.push(mountPoint); |
| 111 | this.mountList = this.mountList.sort((a, b) => b.length - a.length); |
| 112 | } |
| 113 | |
| 114 | public umount(mountPoint: string): void { |
| 115 | if (mountPoint[0] !== '/') { |
| 116 | mountPoint = `/${mountPoint}`; |
| 117 | } |
nothing calls this directly
no outgoing calls
no test coverage detected