     ///   - dataPath: The path for the workspace data files, if explicitly provided.
     ///   - editablesPath: The path where editable packages should be placed, if explicitly provided.
     ///   - manifestLoader: The manifest loader.
+    ///   - fileSystem: The file system to operate on.
     /// - Throws: If the state was present, but could not be loaded.
     public init(
         rootPackage path: AbsolutePath,
         dataPath: AbsolutePath? = nil,
         editablesPath: AbsolutePath? = nil,
         manifestLoader: ManifestLoaderProtocol,
-        delegate: WorkspaceDelegate
+        delegate: WorkspaceDelegate,
+        fileSystem: FileSystem = localFileSystem
     ) throws {
         self.delegate = delegate
         self.rootPackagePath = path

        data["dependencies"] = .array(dependencies.map{ $0.toJSON() })

        // FIXME: This should write atomically.
        try localFileSystem.writeFileContents(statePath, bytes: JSON.dictionary(data).toBytes())
    }
}

        // Clone the repository into the checkouts.
        let path = checkoutsPath.appending(component: repository.fileSystemIdentifier)
        // Ensure the destination is free.
        fileSystem.removeFileTree(path)
        // Inform the delegate that we're starting cloning.
        delegate.cloning(repository: handle.repository.url)
        try handle.cloneCheckout(to: path, editable: false)
