mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 12:00:09 +02:00
👌 Fake FS: ~ and intermediate directories
This commit is contained in:
@ -574,6 +574,14 @@
|
|||||||
C4D3660D29113F20006BD146 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660A29113F20006BD146 /* System.swift */; };
|
C4D3660D29113F20006BD146 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660A29113F20006BD146 /* System.swift */; };
|
||||||
C4D3660E29113F20006BD146 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660A29113F20006BD146 /* System.swift */; };
|
C4D3660E29113F20006BD146 /* System.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660A29113F20006BD146 /* System.swift */; };
|
||||||
C4D36611291140BE006BD146 /* TestableFileSystemTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660F291140BE006BD146 /* TestableFileSystemTest.swift */; };
|
C4D36611291140BE006BD146 /* TestableFileSystemTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D3660F291140BE006BD146 /* TestableFileSystemTest.swift */; };
|
||||||
|
C4D36615291160A1006BD146 /* WIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36614291160A1006BD146 /* WIP.swift */; };
|
||||||
|
C4D36616291160A1006BD146 /* WIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36614291160A1006BD146 /* WIP.swift */; };
|
||||||
|
C4D36617291160A1006BD146 /* WIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36614291160A1006BD146 /* WIP.swift */; };
|
||||||
|
C4D36618291160A1006BD146 /* WIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36614291160A1006BD146 /* WIP.swift */; };
|
||||||
|
C4D3661A291173EA006BD146 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36619291173EA006BD146 /* DictionaryExtension.swift */; };
|
||||||
|
C4D3661B291173EA006BD146 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36619291173EA006BD146 /* DictionaryExtension.swift */; };
|
||||||
|
C4D3661C291173EA006BD146 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36619291173EA006BD146 /* DictionaryExtension.swift */; };
|
||||||
|
C4D3661D291173EA006BD146 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D36619291173EA006BD146 /* DictionaryExtension.swift */; };
|
||||||
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
||||||
C4D5CFCB27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
C4D5CFCB27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */; };
|
||||||
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
|
||||||
@ -858,6 +866,8 @@
|
|||||||
C4D366052911331E006BD146 /* EmptyProxyScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyProxyScanner.swift; sourceTree = "<group>"; };
|
C4D366052911331E006BD146 /* EmptyProxyScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyProxyScanner.swift; sourceTree = "<group>"; };
|
||||||
C4D3660A29113F20006BD146 /* System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = System.swift; sourceTree = "<group>"; };
|
C4D3660A29113F20006BD146 /* System.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = System.swift; sourceTree = "<group>"; };
|
||||||
C4D3660F291140BE006BD146 /* TestableFileSystemTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestableFileSystemTest.swift; sourceTree = "<group>"; };
|
C4D3660F291140BE006BD146 /* TestableFileSystemTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestableFileSystemTest.swift; sourceTree = "<group>"; };
|
||||||
|
C4D36614291160A1006BD146 /* WIP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WIP.swift; sourceTree = "<group>"; };
|
||||||
|
C4D36619291173EA006BD146 /* DictionaryExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryExtension.swift; sourceTree = "<group>"; };
|
||||||
C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationFile.swift; sourceTree = "<group>"; };
|
C4D5CFC927E0F9CD00035329 /* NginxConfigurationFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationFile.swift; sourceTree = "<group>"; };
|
||||||
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
|
||||||
C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = "<group>"; };
|
C4D89BC52783C99400A02B68 /* ComposerJson.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposerJson.swift; sourceTree = "<group>"; };
|
||||||
@ -1364,6 +1374,7 @@
|
|||||||
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */,
|
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */,
|
||||||
C4B5635D276AB09000F12CCB /* VersionExtractor.swift */,
|
C4B5635D276AB09000F12CCB /* VersionExtractor.swift */,
|
||||||
C4D3660A29113F20006BD146 /* System.swift */,
|
C4D3660A29113F20006BD146 /* System.swift */,
|
||||||
|
C4D36614291160A1006BD146 /* WIP.swift */,
|
||||||
);
|
);
|
||||||
path = Helpers;
|
path = Helpers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1704,6 +1715,7 @@
|
|||||||
C4EB53E628553117006F9937 /* ArrayExtension.swift */,
|
C4EB53E628553117006F9937 /* ArrayExtension.swift */,
|
||||||
C44B3A4528E5C70100718CB1 /* TimeIntervalExtension.swift */,
|
C44B3A4528E5C70100718CB1 /* TimeIntervalExtension.swift */,
|
||||||
C4E2E84928FC1E70003B070C /* DataExtension.swift */,
|
C4E2E84928FC1E70003B070C /* DataExtension.swift */,
|
||||||
|
C4D36619291173EA006BD146 /* DictionaryExtension.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1932,6 +1944,7 @@
|
|||||||
files = (
|
files = (
|
||||||
C47699EF28A2F2A30060FEB8 /* WarningManager.swift in Sources */,
|
C47699EF28A2F2A30060FEB8 /* WarningManager.swift in Sources */,
|
||||||
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */,
|
C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */,
|
||||||
|
C4D3661A291173EA006BD146 /* DictionaryExtension.swift in Sources */,
|
||||||
C4C8900728F0E3EF00CE5E97 /* ActiveFileSystem.swift in Sources */,
|
C4C8900728F0E3EF00CE5E97 /* ActiveFileSystem.swift in Sources */,
|
||||||
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */,
|
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */,
|
||||||
C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */,
|
C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */,
|
||||||
@ -2054,6 +2067,7 @@
|
|||||||
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
C476FF9822B0DD830098105B /* Alert.swift in Sources */,
|
||||||
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */,
|
||||||
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */,
|
C4D5CFCA27E0F9CD00035329 /* NginxConfigurationFile.swift in Sources */,
|
||||||
|
C4D36615291160A1006BD146 /* WIP.swift in Sources */,
|
||||||
C485707028BF452300539B36 /* WarningsWindowController.swift in Sources */,
|
C485707028BF452300539B36 /* WarningsWindowController.swift in Sources */,
|
||||||
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */,
|
C4CE3BBA27B31F670086CA49 /* ComposerWindow.swift in Sources */,
|
||||||
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
C4D9ADC8277611A0007277F4 /* InternalSwitcher.swift in Sources */,
|
||||||
@ -2130,6 +2144,7 @@
|
|||||||
C471E85428F9BB650021E251 /* StatusMenu.swift in Sources */,
|
C471E85428F9BB650021E251 /* StatusMenu.swift in Sources */,
|
||||||
C471E85528F9BB650021E251 /* StatusMenu+Items.swift in Sources */,
|
C471E85528F9BB650021E251 /* StatusMenu+Items.swift in Sources */,
|
||||||
C471E85628F9BB650021E251 /* DomainListCellProtocol.swift in Sources */,
|
C471E85628F9BB650021E251 /* DomainListCellProtocol.swift in Sources */,
|
||||||
|
C4D36617291160A1006BD146 /* WIP.swift in Sources */,
|
||||||
C471E85728F9BB650021E251 /* DomainListTLSCell.swift in Sources */,
|
C471E85728F9BB650021E251 /* DomainListTLSCell.swift in Sources */,
|
||||||
C4D366082911331E006BD146 /* EmptyProxyScanner.swift in Sources */,
|
C4D366082911331E006BD146 /* EmptyProxyScanner.swift in Sources */,
|
||||||
C471E85828F9BB650021E251 /* DomainListNameCell.swift in Sources */,
|
C471E85828F9BB650021E251 /* DomainListNameCell.swift in Sources */,
|
||||||
@ -2237,6 +2252,7 @@
|
|||||||
C471E7D628F9BA8F0021E251 /* RealFileSystem.swift in Sources */,
|
C471E7D628F9BA8F0021E251 /* RealFileSystem.swift in Sources */,
|
||||||
C471E81728F9BAE80021E251 /* NSMenuExtension.swift in Sources */,
|
C471E81728F9BAE80021E251 /* NSMenuExtension.swift in Sources */,
|
||||||
C471E81328F9BAE80021E251 /* XibLoadable.swift in Sources */,
|
C471E81328F9BAE80021E251 /* XibLoadable.swift in Sources */,
|
||||||
|
C4D3661C291173EA006BD146 /* DictionaryExtension.swift in Sources */,
|
||||||
C471E7F128F9BAC70021E251 /* PhpVersionNumber.swift in Sources */,
|
C471E7F128F9BAC70021E251 /* PhpVersionNumber.swift in Sources */,
|
||||||
C471E7DC28F9BA8F0021E251 /* ShellProtocol.swift in Sources */,
|
C471E7DC28F9BA8F0021E251 /* ShellProtocol.swift in Sources */,
|
||||||
);
|
);
|
||||||
@ -2300,6 +2316,7 @@
|
|||||||
C471E8C028F9BB8F0021E251 /* DomainListVC.swift in Sources */,
|
C471E8C028F9BB8F0021E251 /* DomainListVC.swift in Sources */,
|
||||||
C471E8C128F9BB8F0021E251 /* DomainListVC+ContextMenu.swift in Sources */,
|
C471E8C128F9BB8F0021E251 /* DomainListVC+ContextMenu.swift in Sources */,
|
||||||
C471E8C228F9BB8F0021E251 /* DomainListVC+Actions.swift in Sources */,
|
C471E8C228F9BB8F0021E251 /* DomainListVC+Actions.swift in Sources */,
|
||||||
|
C4D36618291160A1006BD146 /* WIP.swift in Sources */,
|
||||||
C471E8C328F9BB8F0021E251 /* SelectionVC.swift in Sources */,
|
C471E8C328F9BB8F0021E251 /* SelectionVC.swift in Sources */,
|
||||||
C471E8C428F9BB8F0021E251 /* AddSiteVC.swift in Sources */,
|
C471E8C428F9BB8F0021E251 /* AddSiteVC.swift in Sources */,
|
||||||
C471E8C528F9BB8F0021E251 /* AddProxyVC.swift in Sources */,
|
C471E8C528F9BB8F0021E251 /* AddProxyVC.swift in Sources */,
|
||||||
@ -2392,6 +2409,7 @@
|
|||||||
C4181F1128FAF9330042EA28 /* UITestCase.swift in Sources */,
|
C4181F1128FAF9330042EA28 /* UITestCase.swift in Sources */,
|
||||||
C471E81F28F9BB290021E251 /* NginxConfigurationFile.swift in Sources */,
|
C471E81F28F9BB290021E251 /* NginxConfigurationFile.swift in Sources */,
|
||||||
C471E7BF28F9B90F0021E251 /* StartupTest.swift in Sources */,
|
C471E7BF28F9B90F0021E251 /* StartupTest.swift in Sources */,
|
||||||
|
C4D3661D291173EA006BD146 /* DictionaryExtension.swift in Sources */,
|
||||||
C471E80D28F9BAE80021E251 /* ArrayExtension.swift in Sources */,
|
C471E80D28F9BAE80021E251 /* ArrayExtension.swift in Sources */,
|
||||||
C471E7CD28F9BA600021E251 /* ShellProtocol.swift in Sources */,
|
C471E7CD28F9BA600021E251 /* ShellProtocol.swift in Sources */,
|
||||||
C471E7EC28F9BAC30021E251 /* Events.swift in Sources */,
|
C471E7EC28F9BAC30021E251 /* Events.swift in Sources */,
|
||||||
@ -2424,6 +2442,7 @@
|
|||||||
C415D3B82770F294005EF286 /* Actions.swift in Sources */,
|
C415D3B82770F294005EF286 /* Actions.swift in Sources */,
|
||||||
54B48B60275F66AE006D90C5 /* Application.swift in Sources */,
|
54B48B60275F66AE006D90C5 /* Application.swift in Sources */,
|
||||||
C4FE011228084FC200D1DE6D /* SelectionVC.swift in Sources */,
|
C4FE011228084FC200D1DE6D /* SelectionVC.swift in Sources */,
|
||||||
|
C4D3661B291173EA006BD146 /* DictionaryExtension.swift in Sources */,
|
||||||
C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */,
|
C4F780C825D80B75000DBC97 /* DateExtension.swift in Sources */,
|
||||||
C493084B279F331F009C240B /* AddSiteVC.swift in Sources */,
|
C493084B279F331F009C240B /* AddSiteVC.swift in Sources */,
|
||||||
C44A874928905BB000498BC4 /* ProgressVC.swift in Sources */,
|
C44A874928905BB000498BC4 /* ProgressVC.swift in Sources */,
|
||||||
@ -2507,6 +2526,7 @@
|
|||||||
5489625928313231004F647A /* CreatedFromFile.swift in Sources */,
|
5489625928313231004F647A /* CreatedFromFile.swift in Sources */,
|
||||||
C471E79328F9B21F0021E251 /* ActiveFileSystem.swift in Sources */,
|
C471E79328F9B21F0021E251 /* ActiveFileSystem.swift in Sources */,
|
||||||
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
|
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
|
||||||
|
C4D36616291160A1006BD146 /* WIP.swift in Sources */,
|
||||||
03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */,
|
03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */,
|
||||||
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
|
||||||
C4E2E86528FC2F1B003B070C /* XCPMApplication.swift in Sources */,
|
C4E2E86528FC2F1B003B070C /* XCPMApplication.swift in Sources */,
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "--configuration:~/.phpmon_fconf_working.json"
|
argument = "--configuration:~/.phpmon_fconf_working.json"
|
||||||
isEnabled = "NO">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
<CommandLineArgument
|
<CommandLineArgument
|
||||||
argument = "--configuration:~/.phpmon_fconf_broken.json"
|
argument = "--configuration:~/.phpmon_fconf_broken.json"
|
||||||
|
@ -62,12 +62,16 @@ public class Paths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static var homePath: String {
|
public static var homePath: String {
|
||||||
// TODO: Depending on the filesystem abstraction, return the correct information
|
if FileSystem is RealFileSystem {
|
||||||
if Shell is RealShell {
|
|
||||||
return NSHomeDirectory()
|
return NSHomeDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
return "/Users/\(Paths.whoami)"
|
if FileSystem is TestableFileSystem {
|
||||||
|
let fs = FileSystem as! TestableFileSystem
|
||||||
|
return fs.homeDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
fatalError("A valid FileSystem must be allowed to return the home path")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static var cellarPath: String {
|
public static var cellarPath: String {
|
||||||
|
17
phpmon/Common/Extensions/DictionaryExtension.swift
Normal file
17
phpmon/Common/Extensions/DictionaryExtension.swift
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// DictionaryExtension.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 01/11/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Dictionary {
|
||||||
|
mutating func renameKey(fromKey: Key, toKey: Key) {
|
||||||
|
if let entry = removeValue(forKey: fromKey) {
|
||||||
|
self[toKey] = entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ var FileSystem: FileSystemProtocol {
|
|||||||
class ActiveFileSystem {
|
class ActiveFileSystem {
|
||||||
static var shared: FileSystemProtocol = RealFileSystem()
|
static var shared: FileSystemProtocol = RealFileSystem()
|
||||||
|
|
||||||
|
/** Note: Intermediate directories are not automatically inferred and have to be manually declared. */
|
||||||
public static func useTestable(_ files: [String: FakeFile]) {
|
public static func useTestable(_ files: [String: FakeFile]) {
|
||||||
Self.shared = TestableFileSystem(files: files)
|
Self.shared = TestableFileSystem(files: files)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ protocol FileSystemProtocol {
|
|||||||
|
|
||||||
func getStringFromFile(_ path: String) throws -> String
|
func getStringFromFile(_ path: String) throws -> String
|
||||||
|
|
||||||
func getContentsOfDirectory(_ path: String) throws -> [String]
|
func getShallowContentsOfDirectory(_ path: String) throws -> [String]
|
||||||
|
|
||||||
func getDestinationOfSymlink(_ path: String) throws -> String
|
func getDestinationOfSymlink(_ path: String) throws -> String
|
||||||
|
|
||||||
|
@ -40,12 +40,14 @@ class RealFileSystem: FileSystemProtocol {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContentsOfDirectory(_ path: String) throws -> [String] {
|
func getShallowContentsOfDirectory(_ path: String) throws -> [String] {
|
||||||
// TODO
|
todo()
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDestinationOfSymlink(_ path: String) throws -> String {
|
func getDestinationOfSymlink(_ path: String) throws -> String {
|
||||||
// TODO
|
todo()
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Move & Delete Files
|
// MARK: - Move & Delete Files
|
||||||
|
17
phpmon/Common/Helpers/WIP.swift
Normal file
17
phpmon/Common/Helpers/WIP.swift
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// WIP.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 01/11/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func todo(_ context: String = "") {
|
||||||
|
if !context.isEmpty {
|
||||||
|
fatalError("To be implemented: \(context)")
|
||||||
|
}
|
||||||
|
|
||||||
|
fatalError("To be implemented")
|
||||||
|
}
|
@ -26,7 +26,6 @@ public struct TestableConfiguration: Codable {
|
|||||||
ActiveCommand.useTestable(commandOutput)
|
ActiveCommand.useTestable(commandOutput)
|
||||||
Log.info("Applying fake scanner...")
|
Log.info("Applying fake scanner...")
|
||||||
ValetScanners.useFake()
|
ValetScanners.useFake()
|
||||||
Log.separator()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toJson(pretty: Bool = false) -> String {
|
func toJson(pretty: Bool = false) -> String {
|
||||||
|
@ -11,21 +11,40 @@ import Foundation
|
|||||||
class TestableFileSystem: FileSystemProtocol {
|
class TestableFileSystem: FileSystemProtocol {
|
||||||
init(files: [String: FakeFile]) {
|
init(files: [String: FakeFile]) {
|
||||||
self.files = files
|
self.files = files
|
||||||
|
|
||||||
|
for key in files.keys where key.contains("~") {
|
||||||
|
self.files.renameKey(
|
||||||
|
fromKey: key,
|
||||||
|
toKey: key.replacingOccurrences(of: "~", with: self.homeDirectory)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in self.files {
|
||||||
|
self.createIntermediateDirectories(file.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var files: [String: FakeFile]
|
var files: [String: FakeFile]
|
||||||
|
|
||||||
|
private(set) var homeDirectory = "/Users/fake"
|
||||||
|
|
||||||
// MARK: - Basics
|
// MARK: - Basics
|
||||||
|
|
||||||
func createDirectory(_ path: String, withIntermediateDirectories: Bool) throws {
|
func createDirectory(_ path: String, withIntermediateDirectories: Bool) throws {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
if files[path] != nil {
|
if files[path] != nil {
|
||||||
throw TestableFileSystemError.alreadyExists
|
throw TestableFileSystemError.alreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.createIntermediateDirectories(path)
|
||||||
|
|
||||||
self.files[path] = .fake(.directory)
|
self.files[path] = .fake(.directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeAtomicallyToFile(_ path: String, content: String) throws {
|
func writeAtomicallyToFile(_ path: String, content: String) throws {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
if files[path] != nil {
|
if files[path] != nil {
|
||||||
throw TestableFileSystemError.alreadyExists
|
throw TestableFileSystemError.alreadyExists
|
||||||
}
|
}
|
||||||
@ -34,6 +53,8 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getStringFromFile(_ path: String) throws -> String {
|
func getStringFromFile(_ path: String) throws -> String {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
throw TestableFileSystemError.fileMissing
|
throw TestableFileSystemError.fileMissing
|
||||||
}
|
}
|
||||||
@ -41,11 +62,23 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
return file.content ?? ""
|
return file.content ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContentsOfDirectory(_ path: String) throws -> [String] {
|
func getShallowContentsOfDirectory(_ path: String) throws -> [String] {
|
||||||
// TODO
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
|
var seek = path
|
||||||
|
if !seek.hasSuffix("/") {
|
||||||
|
seek = "\(seek)/"
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.files.keys
|
||||||
|
.filter { $0.hasPrefix(seek) }
|
||||||
|
.map { $0.replacingOccurrences(of: seek, with: "") }
|
||||||
|
.filter { !$0.contains("/") }
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDestinationOfSymlink(_ path: String) throws -> String {
|
func getDestinationOfSymlink(_ path: String) throws -> String {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
throw TestableFileSystemError.fileMissing
|
throw TestableFileSystemError.fileMissing
|
||||||
}
|
}
|
||||||
@ -68,16 +101,22 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
// 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 {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
let newPath = newPath.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
func remove(_ path: String) throws {
|
func remove(_ path: String) throws {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: — Attributes
|
// MARK: — Attributes
|
||||||
|
|
||||||
func makeExecutable(_ path: String) throws {
|
func makeExecutable(_ path: String) throws {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
throw TestableFileSystemError.fileMissing
|
throw TestableFileSystemError.fileMissing
|
||||||
}
|
}
|
||||||
@ -88,7 +127,9 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
// MARK: - Checks
|
// MARK: - Checks
|
||||||
|
|
||||||
func isExecutableFile(_ path: String) -> Bool {
|
func isExecutableFile(_ path: String) -> Bool {
|
||||||
guard let file = files[path] else {
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
|
guard let file = files[path.replacingTildeWithHomeDirectory] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +137,9 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isWriteableFile(_ path: String) -> Bool {
|
func isWriteableFile(_ path: String) -> Bool {
|
||||||
guard let file = files[path] else {
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
|
guard let file = files[path.replacingTildeWithHomeDirectory] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +147,14 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func anyExists(_ path: String) -> Bool {
|
func anyExists(_ path: String) -> Bool {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
return files.keys.contains(path)
|
return files.keys.contains(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileExists(_ path: String) -> Bool {
|
func fileExists(_ path: String) -> Bool {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -116,6 +163,8 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func directoryExists(_ path: String) -> Bool {
|
func directoryExists(_ path: String) -> Bool {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -124,6 +173,8 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isSymlink(_ path: String) -> Bool {
|
func isSymlink(_ path: String) -> Bool {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -132,12 +183,40 @@ class TestableFileSystem: FileSystemProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isDirectory(_ path: String) -> Bool {
|
func isDirectory(_ path: String) -> Bool {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
guard let file = files[path] else {
|
guard let file = files[path] else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return file.type == .directory
|
return file.type == .directory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func printContents() {
|
||||||
|
for key in self.files.keys.sorted() {
|
||||||
|
print("\(key) -> \(self.files[key]!.type)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createIntermediateDirectories(_ path: String) {
|
||||||
|
let path = path.replacingTildeWithHomeDirectory
|
||||||
|
|
||||||
|
let items = path.components(separatedBy: "/")
|
||||||
|
|
||||||
|
var preceding = ""
|
||||||
|
|
||||||
|
for item in items {
|
||||||
|
let key = preceding == "/"
|
||||||
|
? "/\(item)"
|
||||||
|
: "\(preceding)/\(item)"
|
||||||
|
|
||||||
|
if !self.files.keys.contains(key) {
|
||||||
|
self.files[key] = .fake(.directory)
|
||||||
|
}
|
||||||
|
|
||||||
|
preceding = key
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FakeFileType: Codable {
|
enum FakeFileType: Codable {
|
||||||
|
@ -13,7 +13,7 @@ class ValetSiteScanner: SiteScanner {
|
|||||||
return paths.map { path in
|
return paths.map { path in
|
||||||
|
|
||||||
let entries = try! FileSystem
|
let entries = try! FileSystem
|
||||||
.getContentsOfDirectory(path)
|
.getShallowContentsOfDirectory(path)
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
.map { self.isSite($0, forPath: path) }
|
.map { self.isSite($0, forPath: path) }
|
||||||
@ -28,7 +28,7 @@ class ValetSiteScanner: SiteScanner {
|
|||||||
|
|
||||||
paths.forEach { path in
|
paths.forEach { path in
|
||||||
let entries = try! FileSystem
|
let entries = try! FileSystem
|
||||||
.getContentsOfDirectory(path)
|
.getShallowContentsOfDirectory(path)
|
||||||
|
|
||||||
return entries.forEach {
|
return entries.forEach {
|
||||||
if let site = self.resolveSite(path: "\(path)/\($0)") {
|
if let site = self.resolveSite(path: "\(path)/\($0)") {
|
||||||
|
@ -26,15 +26,11 @@ class TestableConfigurations {
|
|||||||
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.1.10_1"),
|
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.1.10_1"),
|
||||||
"/opt/homebrew/opt/php@8.1/bin/php"
|
"/opt/homebrew/opt/php@8.1/bin/php"
|
||||||
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.1.10_1/bin/php"),
|
: .fake(.symlink, "/opt/homebrew/Cellar/php/8.1.10_1/bin/php"),
|
||||||
"/opt/homebrew/Cellar/php/8.1.10_1"
|
|
||||||
: .fake(.directory),
|
|
||||||
"/opt/homebrew/Cellar/php/8.1.10_1/bin/php"
|
"/opt/homebrew/Cellar/php/8.1.10_1/bin/php"
|
||||||
: .fake(.binary),
|
: .fake(.binary),
|
||||||
"/opt/homebrew/Cellar/php/8.1.10_1/bin/php-config"
|
"/opt/homebrew/Cellar/php/8.1.10_1/bin/php-config"
|
||||||
: .fake(.binary),
|
: .fake(.binary),
|
||||||
"/Users/user/.config/valet"
|
"~/.config/valet/config.json"
|
||||||
: .fake(.directory),
|
|
||||||
"/Users/user/.config/valet/config.json"
|
|
||||||
: .fake(.text, """
|
: .fake(.text, """
|
||||||
{
|
{
|
||||||
"tld": "test",
|
"tld": "test",
|
||||||
|
@ -12,12 +12,12 @@ class TestableFileSystemTest: XCTestCase {
|
|||||||
|
|
||||||
override class func setUp() {
|
override class func setUp() {
|
||||||
ActiveFileSystem.useTestable([
|
ActiveFileSystem.useTestable([
|
||||||
"/home/user/bin": .fake(.directory),
|
|
||||||
"/home/user/bin/foo": .fake(.binary),
|
"/home/user/bin/foo": .fake(.binary),
|
||||||
"/home/user/documents": .fake(.directory),
|
|
||||||
"/home/user/docs": .fake(.symlink, "/home/user/documents"),
|
"/home/user/docs": .fake(.symlink, "/home/user/documents"),
|
||||||
|
"/home/user/documents/script.sh": .fake(.text, "echo 'cool';"),
|
||||||
"/home/user/documents/nice.txt": .fake(.text, "69"),
|
"/home/user/documents/nice.txt": .fake(.text, "69"),
|
||||||
"/home/user/documents/script.sh": .fake(.text, "echo 'cool';")
|
"/home/user/documents/filters/filter1.txt": .fake(.text, "F1"),
|
||||||
|
"/home/user/documents/filters/filter2.txt": .fake(.text, "F2")
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +25,11 @@ class TestableFileSystemTest: XCTestCase {
|
|||||||
XCTAssertTrue(FileSystem is TestableFileSystem)
|
XCTAssertTrue(FileSystem is TestableFileSystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_binary_directory_exists() {
|
func test_intermediate_directories_are_automatically_created() {
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user/documents"))
|
||||||
XCTAssertTrue(FileSystem.directoryExists("/home/user/bin"))
|
XCTAssertTrue(FileSystem.directoryExists("/home/user/bin"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +57,37 @@ class TestableFileSystemTest: XCTestCase {
|
|||||||
withIntermediateDirectories: true
|
withIntermediateDirectories: true
|
||||||
)
|
)
|
||||||
|
|
||||||
XCTAssertTrue(FileSystem.anyExists("/home/nico/phpmon/config"))
|
XCTAssertTrue(FileSystem
|
||||||
|
.anyExists("/home/nico/phpmon/config"))
|
||||||
XCTAssertTrue(FileSystem.directoryExists("/home/nico/phpmon/config"))
|
XCTAssertTrue(FileSystem.directoryExists("/home/nico/phpmon/config"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func test_can_create_nested_directories() throws {
|
||||||
|
try FileSystem.createDirectory(
|
||||||
|
"/home/user/thing/epic/nested/directories",
|
||||||
|
withIntermediateDirectories: true
|
||||||
|
)
|
||||||
|
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user/thing"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user/thing/epic/nested"))
|
||||||
|
XCTAssertTrue(FileSystem.directoryExists("/home/user/thing/epic/nested/directories"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_can_list_directory_contents() throws {
|
||||||
|
let contents = try! FileSystem.getShallowContentsOfDirectory("/home/user/documents")
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
contents.sorted(),
|
||||||
|
[
|
||||||
|
"script.sh",
|
||||||
|
"nice.txt",
|
||||||
|
"filters"
|
||||||
|
].sorted()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement and test the remove() and move() methods and reorganize method order
|
// TODO: Implement and test the remove() and move() methods and reorganize method order
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user