1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-11 13:30:07 +02:00

👌 Removed remaining FileManager.default usage

This commit is contained in:
2022-11-01 14:11:34 +01:00
parent 8417d637fe
commit fa2d2105c5
10 changed files with 82 additions and 37 deletions

View File

@@ -16,7 +16,11 @@ protocol FileSystemProtocol {
func writeAtomicallyToFile(_ path: String, content: String) throws func writeAtomicallyToFile(_ path: String, content: String) throws
func readStringFromFile(_ path: String) throws -> String func getStringFromFile(_ path: String) throws -> String
func getContentsOfDirectory(_ path: String) throws -> [String]
func getDestinationOfSymlink(_ path: String) throws -> String
// MARK: - Move & Delete Files // MARK: - Move & Delete Files
@@ -40,5 +44,7 @@ protocol FileSystemProtocol {
func directoryExists(_ path: String) -> Bool func directoryExists(_ path: String) -> Bool
func fileIsSymlink(_ path: String) -> Bool func isSymlink(_ path: String) -> Bool
func isDirectory(_ path: String) -> Bool
} }

View File

@@ -33,13 +33,21 @@ class RealFileSystem: FileSystemProtocol {
) )
} }
func readStringFromFile(_ path: String) throws -> String { func getStringFromFile(_ path: String) throws -> String {
return try String( return try String(
contentsOf: URL(fileURLWithPath: path.replacingTildeWithHomeDirectory), contentsOf: URL(fileURLWithPath: path.replacingTildeWithHomeDirectory),
encoding: .utf8 encoding: .utf8
) )
} }
func getContentsOfDirectory(_ path: String) throws -> [String] {
// TODO
}
func getDestinationOfSymlink(_ path: String) throws -> String {
// TODO
}
// MARK: - Move & Delete Files // MARK: - Move & Delete Files
func move(from path: String, to newPath: String) throws { func move(from path: String, to newPath: String) throws {
@@ -96,7 +104,7 @@ class RealFileSystem: FileSystemProtocol {
return exists && isDirectory.boolValue return exists && isDirectory.boolValue
} }
func fileIsSymlink(_ path: String) -> Bool { func isSymlink(_ path: String) -> Bool {
do { do {
let attribs = try FileManager.default.attributesOfItem(atPath: path) let attribs = try FileManager.default.attributesOfItem(atPath: path)
return attribs[.type] as! FileAttributeType == FileAttributeType.typeSymbolicLink return attribs[.type] as! FileAttributeType == FileAttributeType.typeSymbolicLink
@@ -104,4 +112,13 @@ class RealFileSystem: FileSystemProtocol {
return false return false
} }
} }
func isDirectory(_ path: String) -> Bool {
do {
let attribs = try FileManager.default.attributesOfItem(atPath: path)
return attribs[.type] as! FileAttributeType == FileAttributeType.typeDirectory
} catch {
return false
}
}
} }

View File

@@ -93,7 +93,7 @@ class PhpHelper {
return return
} }
if !FileSystem.fileIsSymlink(destination) { if !FileSystem.isSymlink(destination) {
Log.info("Overwriting existing file with new symlink: \(destination)") Log.info("Overwriting existing file with new symlink: \(destination)")
await Shell.quiet("ln -fs \(source) \(destination)") await Shell.quiet("ln -fs \(source) \(destination)")
return return

View File

@@ -33,7 +33,7 @@ class TestableFileSystem: FileSystemProtocol {
self.files[path] = .fake(.text, content) self.files[path] = .fake(.text, content)
} }
func readStringFromFile(_ path: String) throws -> String { func getStringFromFile(_ path: String) throws -> String {
guard let file = files[path] else { guard let file = files[path] else {
throw TestableFileSystemError.fileMissing throw TestableFileSystemError.fileMissing
} }
@@ -41,6 +41,30 @@ class TestableFileSystem: FileSystemProtocol {
return file.content ?? "" return file.content ?? ""
} }
func getContentsOfDirectory(_ path: String) throws -> [String] {
// TODO
}
func getDestinationOfSymlink(_ path: String) throws -> String {
guard let file = files[path] else {
throw TestableFileSystemError.fileMissing
}
if file.type != .symlink {
throw TestableFileSystemError.notSymlink
}
guard let pathToSymlink = file.content else {
throw TestableFileSystemError.invalidSymlink
}
if !files.keys.contains(pathToSymlink) {
throw TestableFileSystemError.invalidSymlink
}
return pathToSymlink
}
// MARK: - Move & Delete Files // MARK: - Move & Delete Files
func move(from path: String, to newPath: String) throws { func move(from path: String, to newPath: String) throws {
@@ -99,13 +123,21 @@ class TestableFileSystem: FileSystemProtocol {
return [.directory].contains(file.type) return [.directory].contains(file.type)
} }
func fileIsSymlink(_ path: String) -> Bool { func isSymlink(_ path: String) -> Bool {
guard let file = files[path] else { guard let file = files[path] else {
return false return false
} }
return file.type == .symlink return file.type == .symlink
} }
func isDirectory(_ path: String) -> Bool {
guard let file = files[path] else {
return false
}
return file.type == .directory
}
} }
enum FakeFileType: Codable { enum FakeFileType: Codable {
@@ -139,4 +171,6 @@ class FakeFile: Codable {
enum TestableFileSystemError: Error { enum TestableFileSystemError: Error {
case fileMissing case fileMissing
case alreadyExists case alreadyExists
case notSymlink
case invalidSymlink
} }

View File

@@ -86,7 +86,7 @@ class Startup {
// The Homebrew binary must exist. // The Homebrew binary must exist.
// ================================================================================= // =================================================================================
EnvironmentCheck( EnvironmentCheck(
command: { return !FileManager.default.fileExists(atPath: Paths.brew) }, command: { return !FileSystem.fileExists(Paths.brew) },
name: "`\(Paths.brew)` exists", name: "`\(Paths.brew)` exists",
titleText: "alert.homebrew_missing.title".localized, titleText: "alert.homebrew_missing.title".localized,
subtitleText: "alert.homebrew_missing.subtitle".localized, subtitleText: "alert.homebrew_missing.subtitle".localized,
@@ -205,7 +205,7 @@ class Startup {
command: { command: {
let nodePath = await Shell.pipe("which node").out let nodePath = await Shell.pipe("which node").out
return App.architecture == "x86_64" return App.architecture == "x86_64"
&& FileManager.default.fileExists(atPath: "/usr/local/bin/which") && FileSystem.fileExists("/usr/local/bin/which")
&& nodePath.contains("env: node: No such file or directory") && nodePath.contains("env: node: No such file or directory")
}, },
name: "`env: node` issue does not apply", name: "`env: node` issue does not apply",

View File

@@ -12,8 +12,8 @@ class ValetSiteScanner: SiteScanner {
func resolveSiteCount(paths: [String]) -> Int { func resolveSiteCount(paths: [String]) -> Int {
return paths.map { path in return paths.map { path in
let entries = try! FileManager.default let entries = try! FileSystem
.contentsOfDirectory(atPath: path) .getContentsOfDirectory(path)
return entries return entries
.map { self.isSite($0, forPath: path) } .map { self.isSite($0, forPath: path) }
@@ -27,8 +27,8 @@ class ValetSiteScanner: SiteScanner {
var sites: [ValetSite] = [] var sites: [ValetSite] = []
paths.forEach { path in paths.forEach { path in
let entries = try! FileManager.default let entries = try! FileSystem
.contentsOfDirectory(atPath: path) .getContentsOfDirectory(path)
return entries.forEach { return entries.forEach {
if let site = self.resolveSite(path: "\(path)/\($0)") { if let site = self.resolveSite(path: "\(path)/\($0)") {
@@ -48,24 +48,19 @@ class ValetSiteScanner: SiteScanner {
// Get the TLD from the global Valet object // Get the TLD from the global Valet object
let tld = Valet.shared.config.tld let tld = Valet.shared.config.tld
// See if the file is a symlink, if so, resolve it if !FileSystem.anyExists(path) {
guard let attrs = try? FileManager.default.attributesOfItem(atPath: path) else {
Log.warn("Could not parse the site: \(path), skipping!") Log.warn("Could not parse the site: \(path), skipping!")
return nil
} }
// We can also determine whether the thing at the path is a directory, too
let type = attrs[FileAttributeKey.type] as! FileAttributeType
// We should also check that we can interpret the path correctly // We should also check that we can interpret the path correctly
if URL(fileURLWithPath: path).lastPathComponent == "" { if URL(fileURLWithPath: path).lastPathComponent == "" {
Log.warn("Could not parse the site: \(path), skipping!") Log.warn("Could not parse the site: \(path), skipping!")
return nil return nil
} }
if type == FileAttributeType.typeSymbolicLink { if FileSystem.isSymlink(path) {
return ValetSite(aliasPath: path, tld: tld) return ValetSite(aliasPath: path, tld: tld)
} else if type == FileAttributeType.typeDirectory { } else if FileSystem.isDirectory(path) {
return ValetSite(absolutePath: path, tld: tld) return ValetSite(absolutePath: path, tld: tld)
} }
@@ -79,14 +74,6 @@ class ValetSiteScanner: SiteScanner {
private func isSite(_ entry: String, forPath path: String) -> Bool { private func isSite(_ entry: String, forPath path: String) -> Bool {
let siteDir = path + "/" + entry let siteDir = path + "/" + entry
let attrs = try! FileManager.default.attributesOfItem(atPath: siteDir) return (FileSystem.isDirectory(siteDir) || FileSystem.isSymlink(siteDir))
let type = attrs[FileAttributeKey.type] as! FileAttributeType
if type == FileAttributeType.typeSymbolicLink || type == FileAttributeType.typeDirectory {
return true
}
return false
} }
} }

View File

@@ -94,7 +94,7 @@ class ValetSite: DomainListable {
convenience init(aliasPath: String, tld: String) { convenience init(aliasPath: String, tld: String) {
let name = URL(fileURLWithPath: aliasPath).lastPathComponent let name = URL(fileURLWithPath: aliasPath).lastPathComponent
let absolutePath = try! FileManager.default.destinationOfSymbolicLink(atPath: aliasPath) let absolutePath = try! FileSystem.getDestinationOfSymlink(aliasPath)
self.init(name: name, tld: tld, absolutePath: absolutePath, aliasPath: aliasPath) self.init(name: name, tld: tld, absolutePath: absolutePath, aliasPath: aliasPath)
} }

View File

@@ -101,7 +101,7 @@ class Valet {
do { do {
config = try JSONDecoder().decode( config = try JSONDecoder().decode(
Valet.Configuration.self, Valet.Configuration.self,
from: FileSystem.readStringFromFile("~/.config/valet/config.json").data(using: .utf8)! from: FileSystem.getStringFromFile("~/.config/valet/config.json").data(using: .utf8)!
) )
} catch { } catch {
Log.err(error) Log.err(error)
@@ -206,10 +206,7 @@ class Valet {
proxies = ValetScanners.proxyScanner proxies = ValetScanners.proxyScanner
.resolveProxies( .resolveProxies(
directoryPath: FileManager.default directoryPath: "~/.config/valet/Nginx".replacingTildeWithHomeDirectory
.homeDirectoryForCurrentUser
.appendingPathComponent(".config/valet/Nginx")
.path
) )
if let defaultPath = Valet.shared.config.defaultSite, if let defaultPath = Valet.shared.config.defaultSite,

View File

@@ -33,7 +33,7 @@ class WarningManager {
Warning( Warning(
command: { command: {
return !Shell.PATH.contains("\(Paths.homePath)/.config/phpmon/bin") && return !Shell.PATH.contains("\(Paths.homePath)/.config/phpmon/bin") &&
!FileManager.default.isWritableFile(atPath: "/usr/local/bin/") !FileSystem.isWriteableFile("/usr/local/bin/")
}, },
name: "Helpers cannot be symlinked and not in PATH", name: "Helpers cannot be symlinked and not in PATH",
title: "warnings.helper_permissions.title", title: "warnings.helper_permissions.title",

View File

@@ -21,6 +21,10 @@ class PhpConfigWatcher {
var watchers: [FSWatcher] = [] var watchers: [FSWatcher] = []
init(for url: URL) { init(for url: URL) {
if FileSystem is TestableFileSystem {
fatalError("PhpConfigWatcher is not compatible with testable FS! You are not allowed to instantiate these while using a testable FS.")
}
self.url = url self.url = url
// Add a watcher for php.ini // Add a watcher for php.ini