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

🏗 WIP: Shell rework

This commit is contained in:
2022-09-27 20:26:11 +02:00
parent 5399bddfeb
commit 3483569410
27 changed files with 93 additions and 87 deletions

View File

@ -7,8 +7,8 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
03E36FE728D9219000636F7F /* NxtShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* NxtShell.swift */; }; 03E36FE728D9219000636F7F /* ActiveShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* ActiveShell.swift */; };
03E36FE828D9219000636F7F /* NxtShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* NxtShell.swift */; }; 03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E36FE628D9219000636F7F /* ActiveShell.swift */; };
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; }; 5420395926135DC100FB00FA /* PrefsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395826135DC100FB00FA /* PrefsVC.swift */; };
5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; }; 5420395F2613607600FB00FA /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5420395E2613607600FB00FA /* Preferences.swift */; };
5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5489625728312FAD004F647A /* CreatedFromFile.swift */; }; 5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5489625728312FAD004F647A /* CreatedFromFile.swift */; };
@ -101,8 +101,8 @@
C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1527DFDE7900862737 /* nginx-site.test */; }; C42CFB1627DFDE7900862737 /* nginx-site.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1527DFDE7900862737 /* nginx-site.test */; };
C42CFB1827DFDFDC00862737 /* nginx-site-isolated.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */; }; C42CFB1827DFDFDC00862737 /* nginx-site-isolated.test in Resources */ = {isa = PBXBuildFile; fileRef = C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */; };
C42CFB1A27DFE8BD00862737 /* NginxConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */; }; C42CFB1A27DFE8BD00862737 /* NginxConfigurationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */; };
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */; }; C42E3BF428A9BF5100AFECFC /* LegacyShell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* LegacyShell+PATH.swift */; };
C42E3BF528A9BF5100AFECFC /* Shell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */; }; C42E3BF528A9BF5100AFECFC /* LegacyShell+PATH.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42E3BF328A9BF5100AFECFC /* LegacyShell+PATH.swift */; };
C42F26732805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; }; C42F26732805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; };
C42F26742805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; }; C42F26742805B4B400938AC7 /* DomainListable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C42F26722805B4B400938AC7 /* DomainListable.swift */; };
C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */; }; C42F26762805FEE200938AC7 /* nginx-secure-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */; };
@ -216,8 +216,8 @@
C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */; }; C4B56362276AB0A500F12CCB /* VersionExtractorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */; };
C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853B2770FE3900DA4FBE /* Paths.swift */; }; C4B5853E2770FE3900DA4FBE /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853B2770FE3900DA4FBE /* Paths.swift */; };
C4B5853F2770FE3900DA4FBE /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853B2770FE3900DA4FBE /* Paths.swift */; }; C4B5853F2770FE3900DA4FBE /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853B2770FE3900DA4FBE /* Paths.swift */; };
C4B585412770FE3900DA4FBE /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853C2770FE3900DA4FBE /* Shell.swift */; }; C4B585412770FE3900DA4FBE /* LegacyShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853C2770FE3900DA4FBE /* LegacyShell.swift */; };
C4B585422770FE3900DA4FBE /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853C2770FE3900DA4FBE /* Shell.swift */; }; C4B585422770FE3900DA4FBE /* LegacyShell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853C2770FE3900DA4FBE /* LegacyShell.swift */; };
C4B585442770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; }; C4B585442770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; };
C4B585452770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; }; C4B585452770FE3900DA4FBE /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B5853D2770FE3900DA4FBE /* Command.swift */; };
C4B6091A2853AAD300C95265 /* SectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B609192853AAD300C95265 /* SectionHeaderView.swift */; }; C4B6091A2853AAD300C95265 /* SectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4B609192853AAD300C95265 /* SectionHeaderView.swift */; };
@ -331,7 +331,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
03E36FE628D9219000636F7F /* NxtShell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NxtShell.swift; sourceTree = "<group>"; }; 03E36FE628D9219000636F7F /* ActiveShell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveShell.swift; sourceTree = "<group>"; };
5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = "<group>"; }; 5420395826135DC100FB00FA /* PrefsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsVC.swift; sourceTree = "<group>"; };
5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; }; 5420395E2613607600FB00FA /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = "<group>"; };
5489625728312FAD004F647A /* CreatedFromFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatedFromFile.swift; sourceTree = "<group>"; }; 5489625728312FAD004F647A /* CreatedFromFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatedFromFile.swift; sourceTree = "<group>"; };
@ -396,7 +396,7 @@
C42CFB1527DFDE7900862737 /* nginx-site.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site.test"; sourceTree = "<group>"; }; C42CFB1527DFDE7900862737 /* nginx-site.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site.test"; sourceTree = "<group>"; };
C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site-isolated.test"; sourceTree = "<group>"; }; C42CFB1727DFDFDC00862737 /* nginx-site-isolated.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-site-isolated.test"; sourceTree = "<group>"; };
C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationTest.swift; sourceTree = "<group>"; }; C42CFB1927DFE8BD00862737 /* NginxConfigurationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NginxConfigurationTest.swift; sourceTree = "<group>"; };
C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Shell+PATH.swift"; sourceTree = "<group>"; }; C42E3BF328A9BF5100AFECFC /* LegacyShell+PATH.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LegacyShell+PATH.swift"; sourceTree = "<group>"; };
C42F26722805B4B400938AC7 /* DomainListable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListable.swift; sourceTree = "<group>"; }; C42F26722805B4B400938AC7 /* DomainListable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomainListable.swift; sourceTree = "<group>"; };
C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy.test"; sourceTree = "<group>"; }; C42F26752805FEE200938AC7 /* nginx-secure-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-secure-proxy.test"; sourceTree = "<group>"; };
C436039F275E67610028EFC6 /* AppDelegate+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Notifications.swift"; sourceTree = "<group>"; }; C436039F275E67610028EFC6 /* AppDelegate+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Notifications.swift"; sourceTree = "<group>"; };
@ -458,7 +458,7 @@
C4B5635D276AB09000F12CCB /* VersionExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionExtractor.swift; sourceTree = "<group>"; }; C4B5635D276AB09000F12CCB /* VersionExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionExtractor.swift; sourceTree = "<group>"; };
C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionExtractorTest.swift; sourceTree = "<group>"; }; C4B56360276AB0A500F12CCB /* VersionExtractorTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionExtractorTest.swift; sourceTree = "<group>"; };
C4B5853B2770FE3900DA4FBE /* Paths.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Paths.swift; sourceTree = "<group>"; }; C4B5853B2770FE3900DA4FBE /* Paths.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Paths.swift; sourceTree = "<group>"; };
C4B5853C2770FE3900DA4FBE /* Shell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = "<group>"; }; C4B5853C2770FE3900DA4FBE /* LegacyShell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyShell.swift; sourceTree = "<group>"; };
C4B5853D2770FE3900DA4FBE /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; }; C4B5853D2770FE3900DA4FBE /* Command.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
C4B609192853AAD300C95265 /* SectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderView.swift; sourceTree = "<group>"; }; C4B609192853AAD300C95265 /* SectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderView.swift; sourceTree = "<group>"; };
C4B6091C2853AB9700C95265 /* ServicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesView.swift; sourceTree = "<group>"; }; C4B6091C2853AB9700C95265 /* ServicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesView.swift; sourceTree = "<group>"; };
@ -873,7 +873,7 @@
C46EBC3F28DB9550007ACC74 /* Next */ = { C46EBC3F28DB9550007ACC74 /* Next */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
03E36FE628D9219000636F7F /* NxtShell.swift */, 03E36FE628D9219000636F7F /* ActiveShell.swift */,
C46EBC4628DB9644007ACC74 /* SystemShell.swift */, C46EBC4628DB9644007ACC74 /* SystemShell.swift */,
C46EBC4928DB966A007ACC74 /* TestableShell.swift */, C46EBC4928DB966A007ACC74 /* TestableShell.swift */,
C46EBC4328DB95F0007ACC74 /* Shellable.swift */, C46EBC4328DB95F0007ACC74 /* Shellable.swift */,
@ -884,8 +884,8 @@
C46EBC4C28DB9F43007ACC74 /* Pending Removal */ = { C46EBC4C28DB9F43007ACC74 /* Pending Removal */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
C4B5853C2770FE3900DA4FBE /* Shell.swift */, C4B5853C2770FE3900DA4FBE /* LegacyShell.swift */,
C42E3BF328A9BF5100AFECFC /* Shell+PATH.swift */, C42E3BF328A9BF5100AFECFC /* LegacyShell+PATH.swift */,
); );
path = "Pending Removal"; path = "Pending Removal";
sourceTree = "<group>"; sourceTree = "<group>";
@ -1358,7 +1358,7 @@
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */, C4D8016622B1584700C6DA1B /* Startup.swift in Sources */,
C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */, C42C49DB27C2806F0074ABAC /* MainMenu+FixMyValet.swift in Sources */,
C48D6C70279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */, C48D6C70279CD2AC00F26D7E /* PhpVersionNumber.swift in Sources */,
C4B585412770FE3900DA4FBE /* Shell.swift in Sources */, C4B585412770FE3900DA4FBE /* LegacyShell.swift in Sources */,
C4998F0A2617633900B2526E /* PreferencesWindowController.swift in Sources */, C4998F0A2617633900B2526E /* PreferencesWindowController.swift in Sources */,
C46FA9882822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */, C46FA9882822EFDC00D78807 /* PhpConfigurationFile.swift in Sources */,
C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */, C4F8C0A422D4F12C002EFE61 /* DateExtension.swift in Sources */,
@ -1432,7 +1432,7 @@
C41CA5ED2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */, C41CA5ED2774F8EE00A2C80E /* DomainListVC+Actions.swift in Sources */,
C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */, C46E206D28299B3800D909D6 /* AppUpdateChecker.swift in Sources */,
C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */,
03E36FE728D9219000636F7F /* NxtShell.swift in Sources */, 03E36FE728D9219000636F7F /* ActiveShell.swift in Sources */,
C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */, C4D9ADBF277610E1007277F4 /* PhpSwitcher.swift in Sources */,
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */, C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */,
C46EBC4728DB9644007ACC74 /* SystemShell.swift in Sources */, C46EBC4728DB9644007ACC74 /* SystemShell.swift in Sources */,
@ -1481,7 +1481,7 @@
C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */, C40508AF28ADA23D008FAC1F /* NoDomainResultsView.swift in Sources */,
C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */, C4D89BC62783C99400A02B68 /* ComposerJson.swift in Sources */,
C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */, C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */,
C42E3BF428A9BF5100AFECFC /* Shell+PATH.swift in Sources */, C42E3BF428A9BF5100AFECFC /* LegacyShell+PATH.swift in Sources */,
C42337A3281F19F000459A48 /* Xdebug.swift in Sources */, C42337A3281F19F000459A48 /* Xdebug.swift in Sources */,
C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */, C4B97B75275CF08C003F3378 /* AppDelegate+MenuOutlets.swift in Sources */,
C41C02A627E60D7A009F26CB /* SiteScanner.swift in Sources */, C41C02A627E60D7A009F26CB /* SiteScanner.swift in Sources */,
@ -1534,7 +1534,7 @@
C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */, C4FBFC532616485F00CDB8E1 /* PhpVersionDetectionTest.swift in Sources */,
C43A8A2425D9D20D00591B77 /* HomebrewPackageTest.swift in Sources */, C43A8A2425D9D20D00591B77 /* HomebrewPackageTest.swift in Sources */,
C485707928BF456C00539B36 /* ArrayExtension.swift in Sources */, C485707928BF456C00539B36 /* ArrayExtension.swift in Sources */,
C42E3BF528A9BF5100AFECFC /* Shell+PATH.swift in Sources */, C42E3BF528A9BF5100AFECFC /* LegacyShell+PATH.swift in Sources */,
C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */, C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */,
C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */, C4C8E81C276F54E5003AC782 /* PhpConfigWatcher.swift in Sources */,
C4F319C927B034A500AFF46F /* Stats.swift in Sources */, C4F319C927B034A500AFF46F /* Stats.swift in Sources */,
@ -1586,7 +1586,7 @@
C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */, C4B97B7C275CF20A003F3378 /* App+GlobalHotkey.swift in Sources */,
5489625928313231004F647A /* CreatedFromFile.swift in Sources */, 5489625928313231004F647A /* CreatedFromFile.swift in Sources */,
54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */, 54D9E0B327E4F51E003B9AD9 /* HotKeysController.swift in Sources */,
03E36FE828D9219000636F7F /* NxtShell.swift in Sources */, 03E36FE828D9219000636F7F /* ActiveShell.swift in Sources */,
C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */, C4B97B79275CF1B5003F3378 /* App+ActivationPolicy.swift in Sources */,
C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */, C4CE3BBB27B324230086CA49 /* MainMenu+Switcher.swift in Sources */,
C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */, C46E20702829D27F00D909D6 /* AppUpdaterCheckTest.swift in Sources */,
@ -1636,7 +1636,7 @@
C4A6957728D23EE300A14CF8 /* EnvironmentManager.swift in Sources */, C4A6957728D23EE300A14CF8 /* EnvironmentManager.swift in Sources */,
C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */, C4E0F7EE27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */,
C4A81CA528C67101008DD9D1 /* PMTableView.swift in Sources */, C4A81CA528C67101008DD9D1 /* PMTableView.swift in Sources */,
C4B585422770FE3900DA4FBE /* Shell.swift in Sources */, C4B585422770FE3900DA4FBE /* LegacyShell.swift in Sources */,
C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */, C45E76152854A65300B4FE0C /* ServicesManager.swift in Sources */,
C464ADAD275A7A3F003FCD53 /* DomainListWindowController.swift in Sources */, C464ADAD275A7A3F003FCD53 /* DomainListWindowController.swift in Sources */,
C40C7F1F2772136000DDDCDC /* PhpEnv.swift in Sources */, C40C7F1F2772136000DDDCDC /* PhpEnv.swift in Sources */,

View File

@ -10,14 +10,14 @@ import XCTest
class ShellTest: XCTestCase { class ShellTest: XCTestCase {
func test_default_shell_is_system_shell() { func test_default_shell_is_system_shell() {
XCTAssertTrue(NxtShell.shared is SystemShell) XCTAssertTrue(Shell is SystemShell)
XCTAssertTrue(NxtShell.shared.syncPipe("php -v") XCTAssertTrue(Shell.syncPipe("php -v")
.contains("Copyright (c) The PHP Group")) .contains("Copyright (c) The PHP Group"))
} }
func test_system_shell_has_path() { func test_system_shell_has_path() {
let systemShell = NxtShell.shared as! SystemShell let systemShell = Shell as! SystemShell
XCTAssertTrue(systemShell.PATH.contains(":/usr/local/bin")) XCTAssertTrue(systemShell.PATH.contains(":/usr/local/bin"))
XCTAssertTrue(systemShell.PATH.contains(":/usr/bin")) XCTAssertTrue(systemShell.PATH.contains(":/usr/bin"))
@ -38,15 +38,15 @@ class ShellTest: XCTestCase {
isError: false isError: false
) )
NxtShell.useTestable([ ActiveShell.useTestable([
"php -v": expectedPhpOutput, "php -v": expectedPhpOutput,
"php --version": slowVersionOutput "php --version": slowVersionOutput
]) ])
XCTAssertTrue(NxtShell.shared is TestableShell) XCTAssertTrue(Shell is TestableShell)
XCTAssertEqual(expectedPhpOutput, NxtShell.shared.syncPipe("php -v")) XCTAssertEqual(expectedPhpOutput, Shell.syncPipe("php -v"))
XCTAssertEqual(expectedPhpOutput, NxtShell.shared.syncPipe("php --version")) XCTAssertEqual(expectedPhpOutput, Shell.syncPipe("php --version"))
} }
} }

View File

@ -56,7 +56,7 @@ class HomebrewPackageTest: XCTestCase {
func testCanParseServicesJsonFromCliOutput() throws { func testCanParseServicesJsonFromCliOutput() throws {
let services = try! JSONDecoder().decode( let services = try! JSONDecoder().decode(
[HomebrewService].self, [HomebrewService].self,
from: Shell.pipe( from: LegacyShell.pipe(
"sudo \(Paths.brew) services info --all --json", "sudo \(Paths.brew) services info --all --json",
requiresPath: true requiresPath: true
).data(using: .utf8)! ).data(using: .utf8)!
@ -77,7 +77,7 @@ class HomebrewPackageTest: XCTestCase {
func testCanLoadExtensionJsonFromCliOutput() throws { func testCanLoadExtensionJsonFromCliOutput() throws {
let package = try! JSONDecoder().decode( let package = try! JSONDecoder().decode(
[HomebrewPackage].self, [HomebrewPackage].self,
from: Shell.pipe("\(Paths.brew) info php --json", requiresPath: true).data(using: .utf8)! from: LegacyShell.pipe("\(Paths.brew) info php --json", requiresPath: true).data(using: .utf8)!
).first! ).first!
XCTAssertTrue(package.name == "php") XCTAssertTrue(package.name == "php")

View File

@ -124,7 +124,7 @@ class Actions {
try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8) try! "<?php phpinfo();".write(toFile: "/tmp/phpmon_phpinfo.php", atomically: true, encoding: .utf8)
// Tell php-cgi to run the PHP and output as an .html file // Tell php-cgi to run the PHP and output as an .html file
Shell.run("\(Paths.binPath)/php-cgi -q /tmp/phpmon_phpinfo.php > /tmp/phpmon_phpinfo.html") LegacyShell.run("\(Paths.binPath)/php-cgi -q /tmp/phpmon_phpinfo.php > /tmp/phpmon_phpinfo.html")
return URL(string: "file:///private/tmp/phpmon_phpinfo.html")! return URL(string: "file:///private/tmp/phpmon_phpinfo.html")!
} }

View File

@ -12,14 +12,14 @@
Runs a `valet` command. Defaults to running as superuser. Runs a `valet` command. Defaults to running as superuser.
*/ */
func valet(_ command: String, sudo: Bool = true) -> String { func valet(_ command: String, sudo: Bool = true) -> String {
return Shell.pipe("\(sudo ? "sudo " : "")" + "\(Paths.valet) \(command)", requiresPath: true) return LegacyShell.pipe("\(sudo ? "sudo " : "")" + "\(Paths.valet) \(command)", requiresPath: true)
} }
/** /**
Runs a `brew` command. Can run as superuser. Runs a `brew` command. Can run as superuser.
*/ */
func brew(_ command: String, sudo: Bool = false) { func brew(_ command: String, sudo: Bool = false) {
Shell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)") LegacyShell.run("\(sudo ? "sudo " : "")" + "\(Paths.brew) \(command)")
} }
/** /**
@ -33,9 +33,9 @@ func sed(file: String, original: String, replacement: String) {
// Check if gsed exists; it is able to follow symlinks, // Check if gsed exists; it is able to follow symlinks,
// which we want to do to toggle the extension // which we want to do to toggle the extension
if Filesystem.fileExists("\(Paths.binPath)/gsed") { if Filesystem.fileExists("\(Paths.binPath)/gsed") {
Shell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)") LegacyShell.run("\(Paths.binPath)/gsed -i --follow-symlinks 's/\(e_original)/\(e_replacement)/g' \(file)")
} else { } else {
Shell.run("sed -i '' 's/\(e_original)/\(e_replacement)/g' \(file)") LegacyShell.run("sed -i '' 's/\(e_original)/\(e_replacement)/g' \(file)")
} }
} }
@ -43,7 +43,7 @@ func sed(file: String, original: String, replacement: String) {
Uses `grep` to determine whether a particular query string can be found in a particular file. Uses `grep` to determine whether a particular query string can be found in a particular file.
*/ */
func grepContains(file: String, query: String) -> Bool { func grepContains(file: String, query: String) -> Bool {
return Shell.pipe(""" return LegacyShell.pipe("""
grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO" grep -q '\(query)' \(file); [ $? -eq 0 ] && echo "YES" || echo "NO"
""") """)
.trimmingCharacters(in: .whitespacesAndNewlines) .trimmingCharacters(in: .whitespacesAndNewlines)

View File

@ -21,7 +21,7 @@ public class Paths {
init() { init() {
baseDir = App.architecture != "x86_64" ? .opt : .usr baseDir = App.architecture != "x86_64" ? .opt : .usr
userName = String(Shell.pipe("id -un").split(separator: "\n")[0]) userName = String(LegacyShell.pipe("id -un").split(separator: "\n")[0])
} }
public func detectBinaryPaths() { public func detectBinaryPaths() {

View File

@ -34,13 +34,13 @@ class Application {
(This will open the app if it isn't open yet.) (This will open the app if it isn't open yet.)
*/ */
@objc public func openDirectory(file: String) { @objc public func openDirectory(file: String) {
return Shell.run("/usr/bin/open -a \"\(name)\" \"\(file)\"") return LegacyShell.run("/usr/bin/open -a \"\(name)\" \"\(file)\"")
} }
/** Checks if the app is installed. */ /** Checks if the app is installed. */
func isInstalled() -> Bool { func isInstalled() -> Bool {
// If this script does not complain, the app exists! // If this script does not complain, the app exists!
return Shell.user.executeSynchronously( return LegacyShell.user.executeSynchronously(
"/usr/bin/open -Ra \"\(name)\"", "/usr/bin/open -Ra \"\(name)\"",
requiresPath: false requiresPath: false
).task.terminationStatus == 0 ).task.terminationStatus == 0

View File

@ -129,7 +129,7 @@ class ActivePhpInstallation {
if self.version.short == "5.6" { if self.version.short == "5.6" {
// The main PHP config file should contain `valet.sock` and then we're probably fine? // The main PHP config file should contain `valet.sock` and then we're probably fine?
let fileName = "\(Paths.etcPath)/php/5.6/php-fpm.conf" let fileName = "\(Paths.etcPath)/php/5.6/php-fpm.conf"
return Shell.pipe("cat \(fileName)").contains("valet.sock") return LegacyShell.pipe("cat \(fileName)").contains("valet.sock")
} }
// Make sure to check if valet-fpm.conf exists. If it does, we should be fine :) // Make sure to check if valet-fpm.conf exists. If it does, we should be fine :)

View File

@ -15,7 +15,7 @@ class PhpEnv {
init() { init() {
self.currentInstall = ActivePhpInstallation() self.currentInstall = ActivePhpInstallation()
let brewPhpAlias = Shell.pipe("\(Paths.brew) info php --json") let brewPhpAlias = LegacyShell.pipe("\(Paths.brew) info php --json")
self.homebrewPackage = try! JSONDecoder().decode( self.homebrewPackage = try! JSONDecoder().decode(
[HomebrewPackage].self, [HomebrewPackage].self,
@ -84,7 +84,7 @@ class PhpEnv {
Detects which versions of PHP are installed. Detects which versions of PHP are installed.
*/ */
public func detectPhpVersions() -> [String] { public func detectPhpVersions() -> [String] {
let files = Shell.pipe("ls \(Paths.optPath) | grep php@") let files = LegacyShell.pipe("ls \(Paths.optPath) | grep php@")
var versionsOnly = extractPhpVersions(from: files.components(separatedBy: "\n")) var versionsOnly = extractPhpVersions(from: files.components(separatedBy: "\n"))

View File

@ -20,13 +20,13 @@ class PhpHelper {
let destination = "\(Paths.homePath)/.config/phpmon/bin/pm\(dotless)" let destination = "\(Paths.homePath)/.config/phpmon/bin/pm\(dotless)"
// Check if the ~/.config/phpmon/bin directory is in the PATH // Check if the ~/.config/phpmon/bin directory is in the PATH
let inPath = Shell.user.PATH.contains("\(Paths.homePath)/.config/phpmon/bin") let inPath = LegacyShell.user.PATH.contains("\(Paths.homePath)/.config/phpmon/bin")
// Check if we can create symlinks (`/usr/local/bin` must be writable) // Check if we can create symlinks (`/usr/local/bin` must be writable)
let canWriteSymlinks = FileManager.default.isWritableFile(atPath: "/usr/local/bin/") let canWriteSymlinks = FileManager.default.isWritableFile(atPath: "/usr/local/bin/")
do { do {
Shell.run("mkdir -p ~/.config/phpmon/bin") LegacyShell.run("mkdir -p ~/.config/phpmon/bin")
if FileManager.default.fileExists(atPath: destination) { if FileManager.default.fileExists(atPath: destination) {
let contents = try String(contentsOfFile: destination) let contents = try String(contentsOfFile: destination)
@ -61,7 +61,7 @@ class PhpHelper {
) )
// Make sure the file is executable // Make sure the file is executable
Shell.run("chmod +x \(destination)") LegacyShell.run("chmod +x \(destination)")
// Create a symlink if the folder is not in the PATH // Create a symlink if the folder is not in the PATH
if !inPath { if !inPath {
@ -86,13 +86,13 @@ class PhpHelper {
if !Filesystem.fileExists(destination) { if !Filesystem.fileExists(destination) {
Log.info("Creating new symlink: \(destination)") Log.info("Creating new symlink: \(destination)")
Shell.run("ln -s \(source) \(destination)") LegacyShell.run("ln -s \(source) \(destination)")
return return
} }
if !Filesystem.fileIsSymlink(destination) { if !Filesystem.fileIsSymlink(destination) {
Log.info("Overwriting existing file with new symlink: \(destination)") Log.info("Overwriting existing file with new symlink: \(destination)")
Shell.run("ln -fs \(source) \(destination)") LegacyShell.run("ln -fs \(source) \(destination)")
return return
} }

View File

@ -115,7 +115,7 @@ class InternalSwitcher: PhpSwitcher {
if Valet.enabled(feature: .isolatedSites) && primary { if Valet.enabled(feature: .isolatedSites) && primary {
let socketVersion = version.replacingOccurrences(of: ".", with: "") let socketVersion = version.replacingOccurrences(of: ".", with: "")
Shell.run("ln -sF ~/.config/valet/valet\(socketVersion).sock ~/.config/valet/valet.sock") LegacyShell.run("ln -sF ~/.config/valet/valet\(socketVersion).sock ~/.config/valet/valet.sock")
Log.info("Symlinked new socket version (valet\(socketVersion).sock → valet.sock).") Log.info("Symlinked new socket version (valet\(socketVersion).sock → valet.sock).")
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
extension Shell { extension LegacyShell {
var PATH: String { var PATH: String {
let task = Process() let task = Process()

View File

@ -8,8 +8,8 @@
import Cocoa import Cocoa
// TODO: Enable this to see where deprecations and replacements are needed. // TODO: Enable this to see where deprecations and replacements are needed.
// @available(*, deprecated, message: "Use the new replacement `NxtShell` instead") // @available(*, deprecated, message: "Use the new replacement `Shell` instead")
public class Shell { public class LegacyShell {
// MARK: - Invoke static functions // MARK: - Invoke static functions
@ -17,14 +17,14 @@ public class Shell {
_ command: String, _ command: String,
requiresPath: Bool = false requiresPath: Bool = false
) { ) {
Shell.user.run(command, requiresPath: requiresPath) LegacyShell.user.run(command, requiresPath: requiresPath)
} }
public static func pipe( public static func pipe(
_ command: String, _ command: String,
requiresPath: Bool = false requiresPath: Bool = false
) -> String { ) -> String {
return Shell.user.pipe(command, requiresPath: requiresPath) return LegacyShell.user.pipe(command, requiresPath: requiresPath)
} }
// MARK: - Singleton // MARK: - Singleton
@ -40,7 +40,7 @@ public class Shell {
/** /**
Singleton to access a user shell (with --login) Singleton to access a user shell (with --login)
*/ */
public static let user = Shell() public static let user = LegacyShell()
/** /**
Runs a shell command without using the output. Runs a shell command without using the output.
@ -54,7 +54,7 @@ public class Shell {
requiresPath: Bool = false requiresPath: Bool = false
) { ) {
// Equivalent of piping to /dev/null; don't do anything with the string // Equivalent of piping to /dev/null; don't do anything with the string
_ = Shell.pipe(command, requiresPath: requiresPath) _ = LegacyShell.pipe(command, requiresPath: requiresPath)
} }
/** /**
@ -85,7 +85,7 @@ public class Shell {
public func executeSynchronously( public func executeSynchronously(
_ command: String, _ command: String,
requiresPath: Bool = false requiresPath: Bool = false
) -> Shell.Output { ) -> LegacyShell.Output {
let outputPipe = Pipe() let outputPipe = Pipe()
let errorPipe = Pipe() let errorPipe = Pipe()
@ -96,7 +96,7 @@ public class Shell {
task.launch() task.launch()
task.waitUntilExit() task.waitUntilExit()
let output = Shell.Output( let output = LegacyShell.Output(
standardOutput: String( standardOutput: String(
data: outputPipe.fileHandleForReading.readDataToEndOfFile(), data: outputPipe.fileHandleForReading.readDataToEndOfFile(),
encoding: .utf8 encoding: .utf8

View File

@ -18,7 +18,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
(invoked by PHP Monitor) shell commands. It is used to (invoked by PHP Monitor) shell commands. It is used to
invoke all commands in this application. invoke all commands in this application.
*/ */
let sharedShell: Shell let sharedShell: LegacyShell
/** /**
The App singleton contains information about the state of The App singleton contains information about the state of
@ -77,7 +77,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
Log.info("Version \(App.version)") Log.info("Version \(App.version)")
Log.separator(as: .info) Log.separator(as: .info)
self.sharedShell = Shell.user self.sharedShell = LegacyShell.user
self.state = App.shared self.state = App.shared
self.menu = MainMenu.shared self.menu = MainMenu.shared
self.paths = Paths.shared self.paths = Paths.shared

View File

@ -32,7 +32,7 @@ class AppUpdateChecker {
command = "curl -s --max-time 5" command = "curl -s --max-time 5"
} }
return Shell.pipe( return LegacyShell.pipe(
"\(command) '\(caskFile)' | grep version" "\(command) '\(caskFile)' | grep version"
) )
} }

View File

@ -24,7 +24,7 @@ class ServicesManager: ObservableObject {
] ]
DispatchQueue.global(qos: .background).async { DispatchQueue.global(qos: .background).async {
let data = Shell let data = LegacyShell
.pipe("sudo \(Paths.brew) services info --all --json", requiresPath: true) .pipe("sudo \(Paths.brew) services info --all --json", requiresPath: true)
.data(using: .utf8)! .data(using: .utf8)!
@ -44,7 +44,7 @@ class ServicesManager: ObservableObject {
} }
DispatchQueue.global(qos: .background).async { DispatchQueue.global(qos: .background).async {
let data = Shell let data = LegacyShell
.pipe("\(Paths.brew) services info --all --json", requiresPath: true) .pipe("\(Paths.brew) services info --all --json", requiresPath: true)
.data(using: .utf8)! .data(using: .utf8)!

View File

@ -115,7 +115,7 @@ class Startup {
// Make sure we can detect one or more PHP installations. // Make sure we can detect one or more PHP installations.
// ================================================================================= // =================================================================================
EnvironmentCheck( EnvironmentCheck(
command: { return !Shell.pipe("ls \(Paths.optPath) | grep php").contains("php") }, command: { return !LegacyShell.pipe("ls \(Paths.optPath) | grep php").contains("php") },
name: "`ls \(Paths.optPath) | grep php` returned php result", name: "`ls \(Paths.optPath) | grep php` returned php result",
titleText: "startup.errors.php_opt.title".localized, titleText: "startup.errors.php_opt.title".localized,
subtitleText: "startup.errors.php_opt.subtitle".localized( subtitleText: "startup.errors.php_opt.subtitle".localized(
@ -143,14 +143,14 @@ class Startup {
// functioning correctly. Let the user know that they need to run `valet trust`. // functioning correctly. Let the user know that they need to run `valet trust`.
// ================================================================================= // =================================================================================
EnvironmentCheck( EnvironmentCheck(
command: { return !Shell.pipe("cat /private/etc/sudoers.d/brew").contains(Paths.brew) }, command: { return !LegacyShell.pipe("cat /private/etc/sudoers.d/brew").contains(Paths.brew) },
name: "`/private/etc/sudoers.d/brew` contains brew", name: "`/private/etc/sudoers.d/brew` contains brew",
titleText: "startup.errors.sudoers_brew.title".localized, titleText: "startup.errors.sudoers_brew.title".localized,
subtitleText: "startup.errors.sudoers_brew.subtitle".localized, subtitleText: "startup.errors.sudoers_brew.subtitle".localized,
descriptionText: "startup.errors.sudoers_brew.desc".localized descriptionText: "startup.errors.sudoers_brew.desc".localized
), ),
EnvironmentCheck( EnvironmentCheck(
command: { return !Shell.pipe("cat /private/etc/sudoers.d/valet").contains(Paths.valet) }, command: { return !LegacyShell.pipe("cat /private/etc/sudoers.d/valet").contains(Paths.valet) },
name: "`/private/etc/sudoers.d/valet` contains valet", name: "`/private/etc/sudoers.d/valet` contains valet",
titleText: "startup.errors.sudoers_valet.title".localized, titleText: "startup.errors.sudoers_valet.title".localized,
subtitleText: "startup.errors.sudoers_valet.subtitle".localized, subtitleText: "startup.errors.sudoers_valet.subtitle".localized,
@ -202,7 +202,7 @@ class Startup {
command: { command: {
return App.architecture == "x86_64" return App.architecture == "x86_64"
&& FileManager.default.fileExists(atPath: "/usr/local/bin/which") && FileManager.default.fileExists(atPath: "/usr/local/bin/which")
&& Shell.pipe("which node", requiresPath: false) && LegacyShell.pipe("which node", requiresPath: false)
.contains("env: node: No such file or directory") .contains("env: node: No such file or directory")
}, },
name: "`env: node` issue does not apply", name: "`env: node` issue does not apply",

View File

@ -72,7 +72,7 @@ class AddProxyVC: NSViewController, NSTextFieldDelegate {
App.shared.domainListWindowController?.contentVC.setUIBusy() App.shared.domainListWindowController?.contentVC.setUIBusy()
DispatchQueue.global(qos: .userInitiated).async { DispatchQueue.global(qos: .userInitiated).async {
Shell.run("\(Paths.valet) proxy \(domain) \(proxyName)\(secure)", requiresPath: true) LegacyShell.run("\(Paths.valet) proxy \(domain) \(proxyName)\(secure)", requiresPath: true)
Actions.restartNginx() Actions.restartNginx()
DispatchQueue.main.async { DispatchQueue.main.async {

View File

@ -71,7 +71,7 @@ class AddSiteVC: NSViewController, NSTextFieldDelegate {
// Adding `valet links` is a workaround for Valet malforming the config.json file // Adding `valet links` is a workaround for Valet malforming the config.json file
// TODO: I will have to investigate and report this behaviour if possible // TODO: I will have to investigate and report this behaviour if possible
Shell.run("cd '\(path)' && \(Paths.valet) link '\(name)' && valet links", requiresPath: true) LegacyShell.run("cd '\(path)' && \(Paths.valet) link '\(name)' && valet links", requiresPath: true)
dismissView(outcome: .OK) dismissView(outcome: .OK)

View File

@ -25,11 +25,11 @@ extension DomainListVC {
self.waitAndExecute { self.waitAndExecute {
// 1. Remove the original proxy // 1. Remove the original proxy
Shell.run("\(Paths.valet) unproxy \(selectedProxy.domain)", requiresPath: true) LegacyShell.run("\(Paths.valet) unproxy \(selectedProxy.domain)", requiresPath: true)
// 2. Add a new proxy, which is either secured/unsecured // 2. Add a new proxy, which is either secured/unsecured
let secure = originalSecureStatus ? "" : " --secure" let secure = originalSecureStatus ? "" : " --secure"
Shell.run("\(Paths.valet) proxy \(selectedProxy.domain) \(selectedProxy.target)\(secure)", LegacyShell.run("\(Paths.valet) proxy \(selectedProxy.domain) \(selectedProxy.target)\(secure)",
requiresPath: true) requiresPath: true)
// 3. Restart nginx // 3. Restart nginx
@ -50,7 +50,7 @@ extension DomainListVC {
let command = "cd '\(selectedSite.absolutePath)' && sudo \(Paths.valet) \(action) && exit;" let command = "cd '\(selectedSite.absolutePath)' && sudo \(Paths.valet) \(action) && exit;"
waitAndExecute { waitAndExecute {
Shell.run(command, requiresPath: true) LegacyShell.run(command, requiresPath: true)
} completion: { [self] in } completion: { [self] in
selectedSite.determineSecured() selectedSite.determineSecured()
if selectedSite.secured == originalSecureStatus { if selectedSite.secured == originalSecureStatus {
@ -100,11 +100,11 @@ extension DomainListVC {
} }
@objc func openInFinder() { @objc func openInFinder() {
Shell.run("open '\(selectedSite!.absolutePath)'") LegacyShell.run("open '\(selectedSite!.absolutePath)'")
} }
@objc func openInTerminal() { @objc func openInTerminal() {
Shell.run("open -b com.apple.terminal '\(selectedSite!.absolutePath)'") LegacyShell.run("open -b com.apple.terminal '\(selectedSite!.absolutePath)'")
} }
@objc func openWithEditor(sender: EditorMenuItem) { @objc func openWithEditor(sender: EditorMenuItem) {
@ -157,7 +157,7 @@ extension DomainListVC {
style: .critical, style: .critical,
onFirstButtonPressed: { onFirstButtonPressed: {
self.waitAndExecute { self.waitAndExecute {
Shell.run("valet unlink '\(site.name)'", requiresPath: true) LegacyShell.run("valet unlink '\(site.name)'", requiresPath: true)
} completion: { } completion: {
self.reloadDomains() self.reloadDomains()
} }
@ -179,7 +179,7 @@ extension DomainListVC {
style: .critical, style: .critical,
onFirstButtonPressed: { onFirstButtonPressed: {
self.waitAndExecute { self.waitAndExecute {
Shell.run("valet unproxy '\(proxy.domain)'", requiresPath: true) LegacyShell.run("valet unproxy '\(proxy.domain)'", requiresPath: true)
} completion: { } completion: {
self.reloadDomains() self.reloadDomains()
} }
@ -191,7 +191,7 @@ extension DomainListVC {
let rowToReload = tableView.selectedRow let rowToReload = tableView.selectedRow
waitAndExecute { waitAndExecute {
Shell.run(command, requiresPath: true) LegacyShell.run(command, requiresPath: true)
} completion: { [self] in } completion: { [self] in
beforeCellReload() beforeCellReload()
tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0, 1, 2, 3, 4]) tableView.reloadData(forRowIndexes: [rowToReload], columnIndexes: [0, 1, 2, 3, 4])

View File

@ -43,7 +43,7 @@ class ComposerWindow {
window?.setType(info: true) window?.setType(info: true)
DispatchQueue.global(qos: .userInitiated).async { [self] in DispatchQueue.global(qos: .userInitiated).async { [self] in
let task = Shell.user.createTask( let task = LegacyShell.user.createTask(
for: "\(Paths.composer!) global update", requiresPath: true for: "\(Paths.composer!) global update", requiresPath: true
) )

View File

@ -14,7 +14,7 @@ class HomebrewDiagnostics {
Determines the Homebrew taps the user has installed. Determines the Homebrew taps the user has installed.
*/ */
public static var installedTaps: [String] = { public static var installedTaps: [String] = {
return Shell return LegacyShell
.pipe("\(Paths.brew) tap") .pipe("\(Paths.brew) tap")
.split(separator: "\n") .split(separator: "\n")
.map { string in .map { string in
@ -75,7 +75,7 @@ class HomebrewDiagnostics {
Check if the alias conflict as documented in `checkForCaskConflict` actually occurred. Check if the alias conflict as documented in `checkForCaskConflict` actually occurred.
*/ */
private static func hasAliasConflict() -> Bool { private static func hasAliasConflict() -> Bool {
let tapAlias = Shell.pipe("\(Paths.brew) info shivammathur/php/php --json") let tapAlias = LegacyShell.pipe("\(Paths.brew) info shivammathur/php/php --json")
if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") { if tapAlias.contains("brew tap shivammathur/php") || tapAlias.contains("Error") {
Log.info("The user does not appear to have tapped: shivammathur/php") Log.info("The user does not appear to have tapped: shivammathur/php")
@ -134,7 +134,7 @@ class HomebrewDiagnostics {
public static func cannotLoadService(_ name: String = "nginx") -> Bool { public static func cannotLoadService(_ name: String = "nginx") -> Bool {
let serviceInfo = try? JSONDecoder().decode( let serviceInfo = try? JSONDecoder().decode(
[HomebrewService].self, [HomebrewService].self,
from: Shell.pipe( from: LegacyShell.pipe(
"sudo \(Paths.brew) services info \(name) --json", "sudo \(Paths.brew) services info \(name) --json",
requiresPath: true requiresPath: true
).data(using: .utf8)! ).data(using: .utf8)!

View File

@ -44,7 +44,7 @@ struct CustomPrefs: Decodable {
extension Preferences { extension Preferences {
func loadCustomPreferences() { func loadCustomPreferences() {
// Ensure the configuration directory is created if missing // Ensure the configuration directory is created if missing
Shell.run("mkdir -p ~/.config/phpmon") LegacyShell.run("mkdir -p ~/.config/phpmon")
// Move the legacy file // Move the legacy file
moveOutdatedConfigurationFile() moveOutdatedConfigurationFile()
@ -63,7 +63,7 @@ extension Preferences {
func moveOutdatedConfigurationFile() { func moveOutdatedConfigurationFile() {
if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") { if Filesystem.fileExists("~/.phpmon.conf.json") && !Filesystem.fileExists("~/.config/phpmon/config.json") {
Log.info("An outdated configuration file was found. Moving it...") Log.info("An outdated configuration file was found. Moving it...")
Shell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json") LegacyShell.run("cp ~/.phpmon.conf.json ~/.config/phpmon/config.json")
Log.info("The configuration file was copied successfully!") Log.info("The configuration file was copied successfully!")
} }
} }
@ -87,7 +87,7 @@ extension Preferences {
if customPreferences.hasEnvironmentVariables() { if customPreferences.hasEnvironmentVariables() {
Log.info("Configuring the additional exports...") Log.info("Configuring the additional exports...")
Shell.user.exports = customPreferences.getEnvironmentVariables() LegacyShell.user.exports = customPreferences.getEnvironmentVariables()
} }
} catch { } catch {
Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.") Log.warn("The ~/.config/phpmon/config.json file seems to be missing or malformed.")

View File

@ -260,7 +260,7 @@ struct Preset: Codable, Equatable {
private func persistRevert() { private func persistRevert() {
let data = try! JSONEncoder().encode(self.revertSnapshot) let data = try! JSONEncoder().encode(self.revertSnapshot)
Shell.run("mkdir -p ~/.config/phpmon") LegacyShell.run("mkdir -p ~/.config/phpmon")
try! String(data: data, encoding: .utf8)! try! String(data: data, encoding: .utf8)!
.write( .write(

View File

@ -22,7 +22,7 @@ class WarningManager {
public let evaluations: [Warning] = [ public let evaluations: [Warning] = [
Warning( Warning(
command: { command: {
return Shell.pipe("sysctl -n sysctl.proc_translated") return LegacyShell.pipe("sysctl -n sysctl.proc_translated")
.trimmingCharacters(in: .whitespacesAndNewlines) == "1" .trimmingCharacters(in: .whitespacesAndNewlines) == "1"
}, },
name: "Running PHP Monitor with Rosetta on M1", name: "Running PHP Monitor with Rosetta on M1",
@ -32,7 +32,7 @@ class WarningManager {
), ),
Warning( Warning(
command: { command: {
return !Shell.user.PATH.contains("\(Paths.homePath)/.config/phpmon/bin") && return !LegacyShell.user.PATH.contains("\(Paths.homePath)/.config/phpmon/bin") &&
!FileManager.default.isWritableFile(atPath: "/usr/local/bin/") !FileManager.default.isWritableFile(atPath: "/usr/local/bin/")
}, },
name: "Helpers cannot be symlinked and not in PATH", name: "Helpers cannot be symlinked and not in PATH",

View File

@ -8,7 +8,11 @@
import Foundation import Foundation
class NxtShell { var Shell: Shellable {
return ActiveShell.shared
}
class ActiveShell {
static var shared: Shellable = SystemShell() static var shared: Shellable = SystemShell()
/// Uses a testable shell with predefined responses. You specify the terminal's output. /// Uses a testable shell with predefined responses. You specify the terminal's output.

View File

@ -9,7 +9,9 @@
import Foundation import Foundation
protocol Shellable { protocol Shellable {
// TODO: Rework this so it supports listening for updates (when piping) and typealias Output = String
func syncPipe(_ command: String) -> String
func pipe(_ command: String) async -> String func syncPipe(_ command: String) -> Output
func pipe(_ command: String) async -> Output
} }