Repository: mxcl/Cake Branch: master Commit: a826004f7149 Files: 225 Total size: 1.1 MB Directory structure: gitextract_0x5usrq0/ ├── .cake/ │ ├── Batter.swift │ ├── Cake.swift │ ├── Cake.xcconfig │ ├── Cake.xcodeproj/ │ │ ├── project.pbxproj │ │ └── project.xcworkspace/ │ │ ├── WorkspaceSettings.xcsettings │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ ├── Dependencies.swift │ └── Package.resolved ├── .gitignore ├── .travis.yml ├── Cake.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata/ │ └── xcschemes/ │ └── Cake.xcscheme ├── Cakefile.swift ├── Dependencies/ │ ├── PromiseKit∕Foundation-3.3.1/ │ │ ├── NSNotificationCenter+Promise.swift │ │ ├── NSObject+Promise.swift │ │ ├── NSURLSession+Promise.swift │ │ ├── Process+Promise.swift │ │ └── afterlife.swift │ ├── Weebly∕OrderedSet-3.1.0.swift │ ├── kylef∕PathKit-0.9.2.swift │ ├── mxcl∕AppUpdater-1.0.3.swift │ ├── mxcl∕LegibleError-1.0.1.swift │ ├── mxcl∕Path.swift-0.16.1/ │ │ ├── Extensions.swift │ │ ├── Path+Attributes.swift │ │ ├── Path+Codable.swift │ │ ├── Path+CommonDirectories.swift │ │ ├── Path+FileManager.swift │ │ ├── Path+StringConvertibles.swift │ │ ├── Path+ls.swift │ │ ├── Path->Bool.swift │ │ └── Path.swift │ ├── mxcl∕PromiseKit-6.8.3/ │ │ ├── Box.swift │ │ ├── Catchable.swift │ │ ├── Configuration.swift │ │ ├── CustomStringConvertible.swift │ │ ├── Error.swift │ │ ├── Guarantee.swift │ │ ├── LogEvent.swift │ │ ├── Promise.swift │ │ ├── Resolver.swift │ │ ├── Thenable.swift │ │ ├── after.swift │ │ ├── firstly.swift │ │ ├── hang.swift │ │ ├── race.swift │ │ └── when.swift │ ├── mxcl∕Version-1.0.3/ │ │ ├── Version+Codable.swift │ │ ├── Version+Comparable.swift │ │ ├── Version+Foundation.swift │ │ ├── Version+Range.swift │ │ └── Version.swift │ ├── soffes∕HotKey-0.1.1/ │ │ ├── HotKey.swift │ │ ├── HotKeysController.swift │ │ ├── Key.swift │ │ ├── KeyCombo.swift │ │ └── NSEventModifierFlags+HotKey.swift │ ├── tadija∕AEXML-4.3.3/ │ │ ├── Document.swift │ │ ├── Element.swift │ │ ├── Error.swift │ │ ├── Options.swift │ │ └── Parser.swift │ └── tuist∕xcodeproj-6.6.0/ │ ├── Errors/ │ │ └── Errors.swift │ ├── Extensions/ │ │ ├── AEXML+XcodeFormat.swift │ │ ├── Bool+Extras.swift │ │ ├── Dictionary+Enumerate.swift │ │ ├── Dictionary+Extras.swift │ │ ├── KeyedDecodingContainer+Additions.swift │ │ ├── NSRecursiveLock+Sync.swift │ │ ├── OSLog+Extras.swift │ │ ├── Path+Extras.swift │ │ ├── String+Utils.swift │ │ └── String+md5.swift │ ├── Objects/ │ │ ├── BuildPhase/ │ │ │ ├── BuildPhase.swift │ │ │ ├── PBXBuildFile.swift │ │ │ ├── PBXBuildPhase.swift │ │ │ ├── PBXBuildRule.swift │ │ │ ├── PBXCopyFilesBuildPhase.swift │ │ │ ├── PBXFrameworksBuildPhase.swift │ │ │ ├── PBXHeadersBuildPhase.swift │ │ │ ├── PBXResourcesBuildPhase.swift │ │ │ ├── PBXRezBuildPhase.swift │ │ │ ├── PBXShellScriptBuildPhase.swift │ │ │ └── PBXSourcesBuildPhase.swift │ │ ├── Configuration/ │ │ │ ├── BuildSettings.swift │ │ │ ├── XCBuildConfiguration.swift │ │ │ └── XCConfigurationList.swift │ │ ├── Files/ │ │ │ ├── PBXContainerItem.swift │ │ │ ├── PBXContainerItemProxy.swift │ │ │ ├── PBXFileElement.swift │ │ │ ├── PBXFileReference.swift │ │ │ ├── PBXGroup.swift │ │ │ ├── PBXSourceTree.swift │ │ │ ├── PBXVariantGroup.swift │ │ │ └── XCVersionGroup.swift │ │ ├── Project/ │ │ │ ├── PBXObject.swift │ │ │ ├── PBXObjectParser.swift │ │ │ ├── PBXObjectReference.swift │ │ │ ├── PBXObjects.swift │ │ │ ├── PBXOutputSettings.swift │ │ │ ├── PBXProj.swift │ │ │ ├── PBXProjEncoder.swift │ │ │ └── PBXProject.swift │ │ ├── Sourcery/ │ │ │ ├── Equality.generated.swift │ │ │ └── Sourcery.swift │ │ └── Targets/ │ │ ├── PBXAggregateTarget.swift │ │ ├── PBXLegacyTarget.swift │ │ ├── PBXNativeTarget.swift │ │ ├── PBXProductType.swift │ │ ├── PBXReferenceProxy.swift │ │ ├── PBXTarget.swift │ │ └── PBXTargetDependency.swift │ ├── Project/ │ │ ├── WorkspaceSettings.swift │ │ ├── XCBreakpointList.swift │ │ ├── XCSharedData.swift │ │ ├── Xcode.swift │ │ └── XcodeProj.swift │ ├── Protocols/ │ │ └── Writable.swift │ ├── Scheme/ │ │ ├── XCScheme+AditionalOption.swift │ │ ├── XCScheme+AnalyzeAction.swift │ │ ├── XCScheme+ArchiveAction.swift │ │ ├── XCScheme+BuildAction.swift │ │ ├── XCScheme+BuildableProductRunnable.swift │ │ ├── XCScheme+BuildableReference.swift │ │ ├── XCScheme+CommandLineArguments.swift │ │ ├── XCScheme+EnvironmentVariable.swift │ │ ├── XCScheme+ExecutionAction.swift │ │ ├── XCScheme+LaunchAction.swift │ │ ├── XCScheme+LocationScenarioReference.swift │ │ ├── XCScheme+ProfileAction.swift │ │ ├── XCScheme+SerialAction.swift │ │ ├── XCScheme+SkippedTests.swift │ │ ├── XCScheme+TestAction.swift │ │ ├── XCScheme+TestableReference.swift │ │ └── XCScheme.swift │ ├── Utils/ │ │ ├── BuildSettingsProvider.swift │ │ ├── CommentedString.swift │ │ ├── Decoders.swift │ │ ├── JSONDecoding.swift │ │ ├── OSLogger.swift │ │ ├── PlistValue.swift │ │ ├── ReferenceGenerator.swift │ │ └── XCConfig.swift │ └── Workspace/ │ ├── XCWorkspace.swift │ ├── XCWorkspaceData.swift │ ├── XCWorkspaceDataElement.swift │ ├── XCWorkspaceDataElementLocationType.swift │ ├── XCWorkspaceDataFileRef.swift │ └── XCWorkspaceDataGroup.swift ├── Documents/ │ ├── Advanced-Module-Hierarchies.md │ ├── Cakefile.md │ ├── FAQ.md │ ├── Suggested-Usage.md │ └── Troubleshooting.md ├── LICENSE ├── README.md ├── Sources/ │ ├── AppKit/ │ │ ├── AppDelegate+NSMenu.swift │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ └── NSStatusBarItem.imageset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ └── Main.storyboard │ │ ├── Bundled Files/ │ │ │ └── iOS.LaunchScreen.storyboard │ │ ├── Cake.entitlements │ │ ├── Info.plist │ │ ├── Menu·$CAKE.swift │ │ ├── Menu·New Cake.swift │ │ ├── Menu·Xcode.swift │ │ └── alert().swift │ ├── Kitchenware/ │ │ ├── Makefile │ │ └── Package.swift │ ├── Mixer/ │ │ ├── Makefile │ │ ├── Modelize/ │ │ │ ├── etc.swift │ │ │ └── modelize().swift │ │ ├── Package.resolved │ │ ├── Package.swift │ │ ├── README.md │ │ └── main.swift │ ├── Model/ │ │ ├── Base/ │ │ │ ├── Modelizer/ │ │ │ │ ├── Dependencies.json.swift │ │ │ │ ├── Module.swift │ │ │ │ └── modelize().swift │ │ │ ├── Path+inreplace().swift │ │ │ ├── Process+facade.swift │ │ │ ├── Sequence+KeyPath.swift │ │ │ ├── StreamReader.swift │ │ │ ├── SwiftVersion.swift │ │ │ ├── XcodeObserver/ │ │ │ │ ├── Diff.swift │ │ │ │ ├── XcodeObserver.swift │ │ │ │ └── XcodeScriptingBridge.swift │ │ │ ├── XcodeProject/ │ │ │ │ ├── *Target.swift │ │ │ │ ├── +functions.swift │ │ │ │ ├── +platforms.swift │ │ │ │ ├── Group.swift │ │ │ │ ├── XcakeProject/ │ │ │ │ │ ├── +functions.swift │ │ │ │ │ ├── Processor/ │ │ │ │ │ │ ├── Cakefile.swift │ │ │ │ │ │ ├── Dependencies.swift │ │ │ │ │ │ ├── Kitchen/ │ │ │ │ │ │ │ ├── CakeProject.swift │ │ │ │ │ │ │ ├── FSWatcher.swift │ │ │ │ │ │ │ ├── Kitchen.swift │ │ │ │ │ │ │ └── KitchenDelegate.swift │ │ │ │ │ │ ├── Self.swift │ │ │ │ │ │ ├── SwiftVersion.swift │ │ │ │ │ │ ├── TemporaryDirectory.swift │ │ │ │ │ │ └── etc.swift │ │ │ │ │ ├── XcakeProject.swift │ │ │ │ │ ├── deintegrate().swift │ │ │ │ │ ├── etc.swift │ │ │ │ │ └── scaffold().swift │ │ │ │ ├── XcodeProject.swift │ │ │ │ ├── _PathDisambiguation.swift │ │ │ │ ├── z+buildSettings.swift │ │ │ │ └── z.etc.swift │ │ │ └── topologicalSort().swift │ │ └── CakefileDescription/ │ │ ├── CakefileDescription.swift │ │ └── Version+.swift │ └── cake-build/ │ └── main.swift └── Tests/ ├── CakefileDescriptionTests.swift ├── Info.plist ├── MixerTests.swift ├── ModelizerTests.swift ├── Utility.swift └── XcakeprojTests.swift ================================================ FILE CONTENTS ================================================ ================================================ FILE: .cake/Batter.swift ================================================ // Generated by Cake. Regeneration will occur! Edits will be lost! // Modules are sorted *topologically*. @_exported import Kitchen @_exported import Processor @_exported import XcakeProject @_exported import XcodeProject @_exported import XcodeObserver @_exported import Modelizer @_exported import Base @_exported import CakefileDescription ================================================ FILE: .cake/Cake.swift ================================================ @_exported import Dependencies @_exported import Batter ================================================ FILE: .cake/Cake.xcconfig ================================================ #include? "Version.xcconfig" ================================================ FILE: .cake/Cake.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 51; objects = { /* Begin PBXAggregateTarget section */ 27CCC44DFA86333E66FEE34EA8063784 /* Versionator */ = { isa = PBXAggregateTarget; buildPhases = ( B0CCAA5D1D192F6963E1F5560239A386 /* Determine Version */, ); dependencies = ( ); name = Versionator; }; 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */ = { isa = PBXAggregateTarget; buildConfigurationList = FB1419C517BF03EBE4B57BA190D11DA2 /* Build configuration list for PBXAggregateTarget "Cakefile" */; buildPhases = ( 6F67EDB0066A07EA8ACEC9D4D60F4E3F /* Regenerate Cake.xcodeproj */, ); dependencies = ( ); name = Cakefile; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ 0009CA61F364BD503A015792C9A7D2DB /* Utils/XCConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB67A28ADBD062CE337B8DF5E1ABA3B4 /* Utils/XCConfig.swift */; }; 00E35D78B4FC58C677091AACE488F66C /* Scheme/XCScheme+TestableReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DB4EE450B414ECE6DEDAAB4F40019D /* Scheme/XCScheme+TestableReference.swift */; }; 0126D7996A8929E3D9BA9BC71806216C /* NSNotificationCenter+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E32B9B4F0137DD729D7F3D74688CF6D /* NSNotificationCenter+Promise.swift */; }; 0144937EEB86C307B33A65EB2B058FFC /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD06ECAE4D53F31C5FF63EB1A4FAA0F1 /* Dependencies.swift */; }; 02A46975791D4B6AF393E02BFC7B4FA7 /* Cake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F867ED701FF56BC9AA1829B4888F2F /* Cake.swift */; }; 03B4231C554E2D2E022A5351927EA1E5 /* CakefileDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = A931901826EAFC85E24FC30A1708944E /* CakefileDescription.swift */; }; 09418BE9EF8A8148100DCB62874E428F /* Module.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A565382D53C145048B6FC0422270BC1 /* Module.swift */; }; 096E09CF05DC89BF84A52E377522B07A /* Scheme/XCScheme+BuildableReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DCF2ACDC813D1597DCDDFE3EA904191 /* Scheme/XCScheme+BuildableReference.swift */; }; 0D24E42A01A5B57AE961FAF8C817687C /* Project/Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B89F8E5109BA12DC10ED95129E77944 /* Project/Xcode.swift */; }; 0D607F811A55D6665B3CD26DA7EEF595 /* Path+FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A77AFC4AE522827E286DEA7B38C2C006 /* Path+FileManager.swift */; }; 0DED5DA8786393351690A30A1BCCA529 /* Scheme/XCScheme+BuildAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3AD59FD7C82A5F84B7C248687AB331 /* Scheme/XCScheme+BuildAction.swift */; }; 0EF5EC3E38F3F4D8F51F23394EDE32D5 /* Project/XCSharedData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C408218005B7BC75A3ABD08133612D9 /* Project/XCSharedData.swift */; }; 0F331239AFB8578C44E0FD3CC8A66D01 /* Objects/Files/PBXContainerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D719F3BC31505ACB101E7D6737CE1E5 /* Objects/Files/PBXContainerItem.swift */; }; 0FE036E5308002A02EE147D00659CB89 /* Objects/Configuration/XCConfigurationList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31C617BEA32F179B393AF1D212E944A9 /* Objects/Configuration/XCConfigurationList.swift */; }; 109244311B8CF9298C2586C085606327 /* Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F48703B70EEA7E7DCC6D2D2F06C9B8 /* Path.swift */; }; 13A12CCBECF26AF3B18468E445CEF598 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9667E7EC96A4E5AF6C72D9DDD7ACC033 /* Promise.swift */; }; 1494290E678712CC86B906C2DB6FB93D /* Extensions/Dictionary+Enumerate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB463DC57B0C69C11B869C0D1D1CE34 /* Extensions/Dictionary+Enumerate.swift */; }; 14E416B908FBFCEBBF146F35813A1A4B /* *Target.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB353A7BFBF179F59387515435E68F1B /* *Target.swift */; }; 14E42FB6998F4B82759AA499D800F15C /* Utils/ReferenceGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C0E03F6E6EECCE50817B52C201AEAA4 /* Utils/ReferenceGenerator.swift */; }; 15934D6E5683C82DBE917FB0A535918C /* PromiseKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 53E3B23BDD8E313D1CCE46BCBA847860 /* PromiseKit.a */; }; 173AC44E5DDAF718CE86EE5D54DB1A23 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53C5D7D1835891126DAC0217D2976BB3 /* Configuration.swift */; }; 194436C50CBF102CE54CD461191FCD0D /* NSObject+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38AC374D097346CE8B4226D78BA0156F /* NSObject+Promise.swift */; }; 1AFCBFBEF3EE85C4735EB8CD7919633F /* Extensions/String+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0917A3E0211FADCA757E973E033A8CE /* Extensions/String+Utils.swift */; }; 1B8DDA4AC227EC58E450FF52FA21B600 /* Cakefile.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAF60D50AF8D2A0115E908C973003A12 /* Cakefile.swift */; }; 1C2035785DAAE2D64C8ECA6619C181D7 /* Project/XCBreakpointList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B41FF1790C8AA4E84A29A33DAE05468B /* Project/XCBreakpointList.swift */; }; 1D4E36D03223E04D12357D0E3E9E4F06 /* LegibleError.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DBCAEFF3AB28195D7B5E09B52FDBDA9 /* LegibleError.a */; }; 1E85BDB96874D3515EED27E275942738 /* Extensions/String+md5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ED4F4E164410F7A62B935BAC757997 /* Extensions/String+md5.swift */; }; 20C156247AA940F1663C87213EB9C7AD /* StreamReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05103104AE592402CB93C1FFE5E2D1CD /* StreamReader.swift */; }; 217FABB189F4D49A3DD1422949D0C8E8 /* Dependencies.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A7E89000FDF44A3427FBD44B878A9C1 /* Dependencies.a */; }; 2239144EE9AC530773FD403B4EF8BE35 /* Workspace/XCWorkspaceDataElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32BB1D0A32744ECAA417C6154B85B6D /* Workspace/XCWorkspaceDataElement.swift */; }; 22CB02677F3EC68D952CDC73F88B79B9 /* Utils/PlistValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B52A49D89C35234D21902B915BB0DB7 /* Utils/PlistValue.swift */; }; 238D7E0FA67C18E872F921129F546762 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF0430C986F4136EE13A64A2653D32D9 /* Version.swift */; }; 23A997BC2064A2B26B67A7A75C7A6FD5 /* Objects/Files/PBXGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B38B8ED5DB9DCC0B70E3CC1E44402A /* Objects/Files/PBXGroup.swift */; }; 23B2B8C2D650E5A33B73053661E5F544 /* Scheme/XCScheme+AnalyzeAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2274AC91D7F94448E0AF2969D9BCDA58 /* Scheme/XCScheme+AnalyzeAction.swift */; }; 23DFC276FAE69CBFA8C76347EF724B84 /* Objects/Targets/PBXTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AF5A7DF8CE28184F27C6599C742AC25 /* Objects/Targets/PBXTarget.swift */; }; 264255B2DC375A38E16541D5A507613F /* Objects/Files/PBXFileElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5FDDB74202F0211F67EAD9C489FA153 /* Objects/Files/PBXFileElement.swift */; }; 29AEB14B8E509CE62DD39ADF72760600 /* Objects/Targets/PBXNativeTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3C314B487A12D0E1C0D029FE36371D /* Objects/Targets/PBXNativeTarget.swift */; }; 29D6CA4B5F8DEB04CADCCCDF08E5B9C2 /* Objects/BuildPhase/PBXBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531404CEBE08B993CDAD51AF95383C04 /* Objects/BuildPhase/PBXBuildPhase.swift */; }; 2B35177067A9C34EDEB33A8164DE4588 /* Resolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F4FC690CAF8E887E4358E57F7AFBC1 /* Resolver.swift */; }; 31BB6F1989688A30CC2AA71C1067102B /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = F487E1726D5CE70C1C4B0223DF5AFFDF /* Diff.swift */; }; 31E2AAD0BE0B7ADFD948BB0CFFC57C1B /* Objects/Project/PBXObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 722A12F4645B5D35D39B45AFA1D76983 /* Objects/Project/PBXObjects.swift */; }; 32BFB1DD9292D0F15B2D465C68898EBE /* Scheme/XCScheme+EnvironmentVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B6CC87C2DDD9FDBA1C2CBD27071D4AC /* Scheme/XCScheme+EnvironmentVariable.swift */; }; 3514CFE553B87C0B30A58801F8271A27 /* Version+Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB24F5AA5F9F47F5FE894B8910CCD3F /* Version+Comparable.swift */; }; 35CBA8E95F73F7C579D312B15F0D498F /* Path+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA500C91598D251A97067F063150DC2A /* Path+Codable.swift */; }; 35D4B501F6E7D131FA2E4C2EA4C4FA98 /* Scheme/XCScheme+ExecutionAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 576C9C9EE9D61D301635A94562588667 /* Scheme/XCScheme+ExecutionAction.swift */; }; 37638F440D45770EB2821116E0E870D8 /* Scheme/XCScheme+LocationScenarioReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76C9275C1BF293F18BCC5970643036F9 /* Scheme/XCScheme+LocationScenarioReference.swift */; }; 37C01C838BE8DE1C664691AA547031E5 /* after.swift in Sources */ = {isa = PBXBuildFile; fileRef = E682DCE6918902D7DDF557BBEE1F747C /* after.swift */; }; 3823977F02656605E34F410252572C97 /* z+buildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE28E6555AA9082953164CAB96DC7EAA /* z+buildSettings.swift */; }; 382812E7E9599D9487DB1B4EFF573337 /* Objects/Files/PBXSourceTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B70D9747ECEC5C6AC9E6368CFB36889 /* Objects/Files/PBXSourceTree.swift */; }; 3E3B8B3CAC69F14B8ACADC5E7FC66059 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA37F59BD9DAFFD0F15694AABCF3B54C /* Extensions.swift */; }; 3E61D76C08BB1902E0D0D05A19835679 /* Processor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5744C074FEF959972A62160544D24F0 /* Processor.a */; }; 3F5CEF2D4DDC859B3FC26CDBEFEC015A /* XcodeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6A3C3E306641683ED6A2DEA9A9CEDFA /* XcodeObserver.swift */; }; 41CDD68A2C49542AC87B2D654662F8C2 /* Objects/BuildPhase/PBXFrameworksBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E74C31BCB0D74EF97C4278031E8034D /* Objects/BuildPhase/PBXFrameworksBuildPhase.swift */; }; 421A097788CD15E31F890B1C9EC609DF /* Utils/Decoders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F661909381C2B72260EC5E92EB852 /* Utils/Decoders.swift */; }; 4296C1974AB9D91026CA47FD9BBA5C52 /* +functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52A4C823A8934B7C4408E5A47FF4FECB /* +functions.swift */; }; 4719E9FAA93FD3E79F912CA463A0640A /* Objects/Project/PBXProjEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50CE25F21E57E92B7A610699FA83BC1 /* Objects/Project/PBXProjEncoder.swift */; }; 471B2B419524B9D1842BC520539060D6 /* Path+inreplace().swift in Sources */ = {isa = PBXBuildFile; fileRef = E81FE693D4FBCAC3084891079AC322C9 /* Path+inreplace().swift */; }; 478F14753835EFC15EE98084B682FD28 /* Workspace/XCWorkspaceDataFileRef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949BF795030FD942ABF42746C69282A2 /* Workspace/XCWorkspaceDataFileRef.swift */; }; 48AE346FE31B6E30412FC556CC270BEC /* TemporaryDirectory.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C16154EA6E8025D3F05AC2433A61BE /* TemporaryDirectory.swift */; }; 4AEC1425A72131B2D9A01091B98794E0 /* Version+Range.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A6EF02B86E86BA90A2AD45729B1EA6A /* Version+Range.swift */; }; 4BA6617EF1A234421360DA3D234D522E /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E28C010F6CDF44DDB15986B219FCDB2 /* Options.swift */; }; 4CFAE96FAE35BAFB253A76001331128D /* Objects/BuildPhase/PBXShellScriptBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852615CA271D363F36FCE47BCF0265AD /* Objects/BuildPhase/PBXShellScriptBuildPhase.swift */; }; 4DAA0F96F543E4A6D90BDB8AC22BC759 /* CustomStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30BDDCCB89500DCBDD7BBA0272926DD0 /* CustomStringConvertible.swift */; }; 55623940F01DAE4B639B481D91CF88E9 /* Workspace/XCWorkspaceData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755B5AE0CCEBAD76024C7BACFD3769CF /* Workspace/XCWorkspaceData.swift */; }; 5613D97DEBC1E4931C7CA4E1F053D4B6 /* Utils/JSONDecoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D18DB9B60F9CAE6DB1EE58AA5CDCA1C /* Utils/JSONDecoding.swift */; }; 5633CA07142F6FC4A6C648E4C90225ED /* Batter.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F573D976FA9A0403F17F22F1A4DAA55 /* Batter.a */; }; 56DFD2E22C495FA82E39886F365DC33A /* Cakefile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DD6BC9A2C80C818AD36364182F42223 /* Cakefile.swift */; }; 57D07CE56DF2981508F693E48A3CFD54 /* CakefileDescription.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 11D3B38D3F7DA37A8300F924107470ED /* CakefileDescription.a */; }; 58998CE0A4E32171CF4950F2639F378A /* Objects/Files/PBXFileReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B557836B8BE6B8B5590ABD761653BA /* Objects/Files/PBXFileReference.swift */; }; 5DBB296966043F75007BBF4EB1C2DE76 /* Objects/Project/PBXProj.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87FA10E492A0664C5F376C3AADA117AB /* Objects/Project/PBXProj.swift */; }; 5ED3ED0B77A5F3EF6B01955153AD6064 /* Project/WorkspaceSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A946331648AD8B89896F7F8669B8E51 /* Project/WorkspaceSettings.swift */; }; 5F9F2D38AABF99927BA45359420DD85D /* Process+facade.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC29E1DAC3B9B8D9CD1097C65196C1C /* Process+facade.swift */; }; 600AB0C92CD900012CA02DE69AB001B9 /* Path.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A49E0E264A02682CCE9A823B02A46706 /* Path.a */; }; 619608298AB26ADA9558192FF85A703F /* etc.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDA44BF315E7E72F7AF8D8FFAB5D39F6 /* etc.swift */; }; 629230A8B878757F42804737F332AF0D /* Workspace/XCWorkspace.swift in Sources */ = {isa = PBXBuildFile; fileRef = B30144F1A4CC788F25022BF92EA083F6 /* Workspace/XCWorkspace.swift */; }; 653928F76893E06F6C79ECE7A573380B /* Project/XcodeProj.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9CC5027FFDDFF68DBEF95C7EC0B2677 /* Project/XcodeProj.swift */; }; 656A6AF815F06DF3D24C506289398B6D /* mxcl∕LegibleError-1.0.1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4144D0D13AB2A191101B99B2DEDE581C /* mxcl∕LegibleError-1.0.1.swift */; }; 66B12F7477B5AC215FDB2A2EBE445EFD /* Sequence+KeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 804B783359D6CCE7145742C88183EA36 /* Sequence+KeyPath.swift */; }; 67A0030B6C4B30446D3B7DF510D2AC95 /* Objects/Files/PBXContainerItemProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD0C6AC2F04C53C676703889CB39A3FA /* Objects/Files/PBXContainerItemProxy.swift */; }; 67F5E702253087EF74E83502C0FB55E6 /* Extensions/KeyedDecodingContainer+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F87D5D97095DA0BD5E5541E880541B51 /* Extensions/KeyedDecodingContainer+Additions.swift */; }; 6A041CF38BC28A5262F4A2C130435DA8 /* Batter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05D33FD3DDE7FE2483580EF428D7DE21 /* Batter.swift */; }; 6ABA75F07503C93AB3B3C7F0B38CCCB3 /* modelize().swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA174BA4C5F72220DACB263A133F3A1 /* modelize().swift */; }; 6B38FB50EC08F4DF74CF1EC447A2D496 /* deintegrate().swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3944D256EB9C28558C204F63F624B5 /* deintegrate().swift */; }; 6C310B5FEEC48AFC22A70CEFB2CBC38A /* Weebly∕OrderedSet-3.1.0.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F70701A65B3979718758A9C96B7E74 /* Weebly∕OrderedSet-3.1.0.swift */; }; 6DD8B2226655E5DED755A1BDC37C2588 /* NSEventModifierFlags+HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A124F661FEA3E444A56EA4D521A515A /* NSEventModifierFlags+HotKey.swift */; }; 6F224F8B3EC4EF42D0BD03AC5A01CF9C /* Errors/Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1426181F4046DE0C27F56E6BD5910905 /* Errors/Errors.swift */; }; 7114D9D184985B859F50ED13FE2C6FC7 /* HotKey.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F2CA03F28361DA2CD3C82B19DE28C91 /* HotKey.a */; }; 71612AAB6911E5BEC04F9B2258C187CA /* Scheme/XCScheme+AditionalOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80158EAEB4E68B546727248C48EF0F17 /* Scheme/XCScheme+AditionalOption.swift */; }; 73F5DBA5C3DF8C27AD93C9DF7F8B616D /* topologicalSort().swift in Sources */ = {isa = PBXBuildFile; fileRef = 749A8E67AC5834C6A956EAADEB64557B /* topologicalSort().swift */; }; 742C6B1F749FF4B6CDFBB53EFA544C37 /* Objects/BuildPhase/BuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0670D14B0D218E1BB9BE836B9392C7 /* Objects/BuildPhase/BuildPhase.swift */; }; 748E5C904992666724C802B55121D231 /* Path->Bool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D32C35009D5CF449E0D419124474C625 /* Path->Bool.swift */; }; 79C7F45017C7722A800FFE0401AD9277 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5D258EA5994282BD85C7216EB317673 /* Group.swift */; }; 7E1152B6B2580D8CF2CAD150E04E60A8 /* HotKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A81CC9DD3104D5CFAB0E095D7A73FDE /* HotKey.swift */; }; 7EC2598830532F6C856E584A4E66B0CB /* Scheme/XCScheme+BuildableProductRunnable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C8796C21F96CBC0C0A4E13733B4CD0E /* Scheme/XCScheme+BuildableProductRunnable.swift */; }; 8086409EA5DD7B797084592C543D5EB3 /* Process+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F0D8DD1958D7B1AF9E5930838B61C63 /* Process+Promise.swift */; }; 80978F6C6C23060316D787E18C24BFC9 /* Objects/Project/PBXOutputSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B14C812ADA5BF5033A67333BAF077A7A /* Objects/Project/PBXOutputSettings.swift */; }; 8132BA30BD6E920DDBD31451E9400E45 /* XcodeProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B014E5511BA57DD4C34DEC96713FCC0F /* XcodeProject.swift */; }; 853B75D491EC42D972FC45BC6A062A2B /* Scheme/XCScheme+LaunchAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9164B58D3D030AD7DD1D4633988ECCA /* Scheme/XCScheme+LaunchAction.swift */; }; 896F7E7C12011CA77277E7BACBB7F99C /* Objects/BuildPhase/PBXSourcesBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830FE1BA33BC05A8FF3C2ED99884F684 /* Objects/BuildPhase/PBXSourcesBuildPhase.swift */; }; 898163FBB3101F0C1FAE974B73CB7271 /* Objects/Files/XCVersionGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B09953A76D3C953D379A46546E39FC8D /* Objects/Files/XCVersionGroup.swift */; }; 8A7FBCE750BACE16FA0C7D24A8E0FC26 /* Guarantee.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF647C9C376ED858DE3D33BD092CCA7F /* Guarantee.swift */; }; 8A8B0E9BDA830045CCAF38F0E83A5761 /* +platforms.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618FDE59E88C49B7C9ADE5C5A9159A06 /* +platforms.swift */; }; 8B8A210C9BB8D8109AD1AC239AB9552F /* Kitchen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BF52CA51D11D9A90EF84861A2B5938B1 /* Kitchen.a */; }; 8C9643A4FA9E488BCB63EBDA4286C997 /* Kitchen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3142C0085C1236B2B3772F4960DBB8D9 /* Kitchen.swift */; }; 8D090FE4A3B4FAED3A0490D986C15C85 /* Version+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40CA625F76FE45EABC6548E7FA9081C9 /* Version+Codable.swift */; }; 8EB5125F4FEFF56B991C39CB731DE87E /* kylef∕PathKit-0.9.2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8936109BF1AA3578412FAD3077209014 /* kylef∕PathKit-0.9.2.swift */; }; 8EF6B805944AE9C3AEB822AFCA5B852B /* +functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7A4900D64F8DD98FAE29B44BAC9C49 /* +functions.swift */; }; 90E680E24018A067844D7A6860BDD036 /* LogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D25EA9B892F8852C3D86F85B8647FAE /* LogEvent.swift */; }; 9149D0D156D1A47AD9708C11EDBFC16E /* Workspace/XCWorkspaceDataGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD8483ADF0C01E41D32E3BEA6C2F50FF /* Workspace/XCWorkspaceDataGroup.swift */; }; 931B8B12E76BBFF3D918AD5F204D0FD6 /* XcodeProject.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 937C922F7F6999DF1895EB3DC82906E9 /* XcodeProject.a */; }; 93ABEAC4A39B97F1DAD8B82CF4A66A3D /* Version+Foundation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F32012741B387F7AD9EB83C1E2AF212 /* Version+Foundation.swift */; }; 93B314409224678C08B72E61C1056C2C /* Scheme/XCScheme+ProfileAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3185556D97EDCF571118B9C60F3D4DCB /* Scheme/XCScheme+ProfileAction.swift */; }; 947BC673F4E249FE2276A9A7C9354813 /* Objects/Project/PBXObjectReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91D674DA388038DB2C7C2DCC6B13CA11 /* Objects/Project/PBXObjectReference.swift */; }; 953FA1F79CB127104231051399E7F96E /* Scheme/XCScheme+SerialAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A909F2285D6BB302E831CD131B206FB1 /* Scheme/XCScheme+SerialAction.swift */; }; 954EDC5169A2DAA27CD7EBCB0D9AE5D9 /* Objects/BuildPhase/PBXBuildFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21B018E286AB818EEF5EA83B02C86E0 /* Objects/BuildPhase/PBXBuildFile.swift */; }; 95B9262AE9089B839547533D20E7BFE7 /* Objects/Project/PBXProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559797E564267A36E62DE4ADF60465B7 /* Objects/Project/PBXProject.swift */; }; 962D45FFD864AA7F6C523E102A1046E0 /* FSWatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46348EB9B861968F7D43E2F325955D37 /* FSWatcher.swift */; }; 96CAE3141B8C653FF20D854469F10C2C /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858CCCCD45F434A16E8D273190765092 /* Dependencies.swift */; }; 976C83FEFB06BCAD121AAEEE1C719482 /* XcakeProject.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F8732C7CBD899BD5F0398A832669E75 /* XcakeProject.a */; }; 97C035E3EF4FD8C90AA7FF8D9057B91F /* Scheme/XCScheme+ArchiveAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49E819CC92D95188B91ABBEDA33B46C3 /* Scheme/XCScheme+ArchiveAction.swift */; }; 9809C7CF76A4546695F8874775FFC18B /* Base.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 372DAB40CDD5A8EEE06A79D6C8AC5536 /* Base.a */; }; 98DBDE552368194486604B4E85BD8EDD /* Objects/Sourcery/Equality.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 675FB47A04E79CDCC955D8FCF3A4BF80 /* Objects/Sourcery/Equality.generated.swift */; }; 9AD25944060C73EBC3D7D4B8ED647F55 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97EAFD505287A688648A6F468128EEEC /* Error.swift */; }; 9B85910EE0235B89957B660EF71DD726 /* Workspace/XCWorkspaceDataElementLocationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669A914005810A46DA64A779CE45E521 /* Workspace/XCWorkspaceDataElementLocationType.swift */; }; 9C7533C705D0687317351F2003399A02 /* Element.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA0BC07DF161138B4D7A43E6A219B05 /* Element.swift */; }; 9D4FA985555FAD0E3D818DD15FDEEE9A /* Utils/BuildSettingsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01B73C1D9BBF582F1B4CA11D1FD2BCD5 /* Utils/BuildSettingsProvider.swift */; }; 9EC43026A52EADC5AE278DAC71294A6F /* Path+StringConvertibles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D39E04B4AC317B13678FFB83CE930458 /* Path+StringConvertibles.swift */; }; 9EDD872806677188A87EFED76893CFF5 /* Objects/Targets/PBXLegacyTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8581BD4238C94C7B078D7E65968660C0 /* Objects/Targets/PBXLegacyTarget.swift */; }; A27CBDCEC8A2496D7214446F54EBCFFD /* OrderedSet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C62C6619223819ED3301991617A91BD /* OrderedSet.a */; }; A297A74AC30EA716F40100BBA29D7C00 /* Objects/Project/PBXObjectParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94C0950C8BC14BB473DDD0C09FDEB12 /* Objects/Project/PBXObjectParser.swift */; }; A2A8C2A61706862AF67AB27B2D159F04 /* Catchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FDA939D602AC0EF1F3928012DDA0DC /* Catchable.swift */; }; A308AD5923DF4D916E0F13D2E6F95D39 /* Objects/BuildPhase/PBXResourcesBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B1F1175C209C392F423782054651ED5 /* Objects/BuildPhase/PBXResourcesBuildPhase.swift */; }; A56DC1AF5566E19B4D632345C9866CCA /* xcodeproj.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E05502AA06041ADF62F3BF7E7659260 /* xcodeproj.a */; }; AA8312CFC7EBB6F598BAF659D0B693EB /* Extensions/NSRecursiveLock+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 308336D6CA83EAE1E8D36F4DE09DE65E /* Extensions/NSRecursiveLock+Sync.swift */; }; AC0DAA07C9191967E505AE9B19BC007B /* Objects/Targets/PBXProductType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BE47230D3E16F17B6C53D4CD9ABF0A7 /* Objects/Targets/PBXProductType.swift */; }; ADC757B7E9013417B979D184C8EA439D /* SwiftVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72C3939CC65CE41D34872BE7C25A01C5 /* SwiftVersion.swift */; }; B13883DB62175193381A7119D4F9CD64 /* Extensions/Path+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6B09E05AFC6DA8F82260DFC1ABE4BDB /* Extensions/Path+Extras.swift */; }; B29D6314F9D634233005F3BB6C0BCF82 /* Modelizer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAD9493581EF0180B01D541DF06A6E4B /* Modelizer.a */; }; B363F49F2AF887172600F5CD67F7C4F2 /* hang.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7AEA2479B3032443714E1D228FADF0C /* hang.swift */; }; B56602EC4F80DEC5337994B59B3FE640 /* NSURLSession+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = A365FC1A53413924C32E4651E9D67AA9 /* NSURLSession+Promise.swift */; }; B5709AC26DC8F5D630260A3F1DB425DC /* Objects/Configuration/BuildSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3875F50A4E88DECD4C85498B13194B4D /* Objects/Configuration/BuildSettings.swift */; }; B59EF1525752B4039C257C311422F13C /* Extensions/OSLog+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29EB733203A51041BAF8B7325873B8F8 /* Extensions/OSLog+Extras.swift */; }; B6DC0EF01401A3BED2CBBF306449424F /* AppUpdater.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F01C205BDC9FA3129D8949BE2CB5C4 /* AppUpdater.a */; }; B7FC5A115B5F3955E30EF15EC52D6EED /* Utils/CommentedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD7DF2A21452F6F3764E31A50E68AF2 /* Utils/CommentedString.swift */; }; B80D12E0404E0D4FE891853C54CC0298 /* Version.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD62726177028C4BC3DCB2230AD84705 /* Version.a */; }; B888FA01811554E0AF55D0A54886A893 /* Extensions/AEXML+XcodeFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BD24A5E56306FA76A42CE38A938E0C /* Extensions/AEXML+XcodeFormat.swift */; }; B932800411795A587A5D035B3F67E937 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835E3CF62D03CBDD1679F357A3702A9C /* Error.swift */; }; B965111421F5F7EA96A6384139DB4AD1 /* race.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41AA2ABCDA2F333EBC153257903CCFFA /* race.swift */; }; BB63582548DBD2F5B1E488AC04FFFDB4 /* Scheme/XCScheme+TestAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7784500AEAF00A3954F252BF7EB9186 /* Scheme/XCScheme+TestAction.swift */; }; BBEF2E8BE5E69BA2026069C53E90CB13 /* Utils/OSLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04110D4A7CD13051C705542C94A0A7A9 /* Utils/OSLogger.swift */; }; BD0BA7D75497180DD3012CA784CC7BCA /* PMKFoundation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69787F8145CACFA492EC131CC2A0AA1D /* PMKFoundation.a */; }; BEC710FA022A69539DE83D3DA26D2D46 /* Thenable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C217681598D56FE79A522A8D0D7CB7C7 /* Thenable.swift */; }; BF795C7DC798F6DDEB96C936AAE3A38D /* PathKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C29E76D627B188CA3643C87B68EC436 /* PathKit.a */; }; C5C90186A870052853053FE8BDE97F81 /* Objects/BuildPhase/PBXRezBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835B1909D4EA60D2CF046ED021E060E7 /* Objects/BuildPhase/PBXRezBuildPhase.swift */; }; C973731BD5D1ADF0B68DC9A8B71371AA /* Objects/BuildPhase/PBXBuildRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FFC5A15BE7FEEA7952C65C2124CDB1C /* Objects/BuildPhase/PBXBuildRule.swift */; }; CA4D400E3DDC6CBC15A3D71ECB3CD4DA /* Objects/Configuration/XCBuildConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7713E4DEB1439F6B933AD7032A4CB4A4 /* Objects/Configuration/XCBuildConfiguration.swift */; }; CB172787F2E9E15E6E4D0069701694ED /* Scheme/XCScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DB38989A054A4EA67BEB37294BFDC38 /* Scheme/XCScheme.swift */; }; CD29B1158D97E7F2767B742E15BB5F1B /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D70A7A1D451A574394BE9D849EF26BD /* Box.swift */; }; CEBEADC323399BF84D2A2A41841A8DBC /* z.etc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719A91C09C4BD993022462D57904F4E /* z.etc.swift */; }; CF94FDBF239BD77C694AFB7B9C375141 /* Objects/BuildPhase/PBXHeadersBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435DE35726152C660A49F9A23B51B7E3 /* Objects/BuildPhase/PBXHeadersBuildPhase.swift */; }; CFBB1B1AD3BABF755259E1B5ABF0B453 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = B828EC0B6BCB9E838EF8719A040E05FB /* Parser.swift */; }; D079F107A87BDA6D93E3B909821C6AA2 /* Version+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930A6BD4B016A2539E9D5013E3FCA04A /* Version+.swift */; }; D10A7E8D4601C0821314BCB968F68F73 /* SwiftVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDDFD13C38B75004170652473061F3A /* SwiftVersion.swift */; }; D3395990728EE7111BEE0C57ED111C98 /* Objects/Files/PBXVariantGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 410CE76CF11E01AD634AF853AB480845 /* Objects/Files/PBXVariantGroup.swift */; }; D51C1066BCE4EB4087BAF0686C5AA8B4 /* Path+ls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC126C205BC396E4B52986041911E1A /* Path+ls.swift */; }; D59C5DFA9636F14344F65784AC4AF22E /* AEXML.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FA20E1A308B36BD34D4F6FA38D3BF30 /* AEXML.a */; }; D620D9DF46FAD133FAD0654540D93506 /* Objects/BuildPhase/PBXCopyFilesBuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA48C5FCF10729DBC5E19A78CD728387 /* Objects/BuildPhase/PBXCopyFilesBuildPhase.swift */; }; D884582231287F0F5274AA2BA4A0BC2C /* Dependencies.json.swift in Sources */ = {isa = PBXBuildFile; fileRef = 902419C27FD761BCEFE0A9AB8BF4FE87 /* Dependencies.json.swift */; }; D8FF5F97208C6033DC9443168546626F /* Scheme/XCScheme+SkippedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57A5610558926A1003CFFD244AA5DA23 /* Scheme/XCScheme+SkippedTests.swift */; }; D93F5CCFC45D073036572B8910C27C33 /* _PathDisambiguation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB66A0A047C8351A0114D24BF9C84D4 /* _PathDisambiguation.swift */; }; DA00E6F1BBD45869C0D4178FD7737F15 /* KeyCombo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB6EB63265EF5234402E15E3F05EE1C0 /* KeyCombo.swift */; }; DB218EF8F94D531927B2D342E41BA5E3 /* Scheme/XCScheme+CommandLineArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9AB41547E4057E3F4F4398F9B8E294 /* Scheme/XCScheme+CommandLineArguments.swift */; }; DBF24B2F67D4AD415385D407F78EBFE7 /* firstly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C473431F71F14C0C7B094C7AFC1BCB1 /* firstly.swift */; }; DC560344DF4532BABE105E25771A2285 /* XcodeObserver.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F9CD3F23A3EB056C8061881D18FBD601 /* XcodeObserver.a */; }; DC86CA0F4A8831D94959D21DD78C26C0 /* mxcl∕AppUpdater-1.0.3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EACC5F861EC78E815F715FE0D7F0DB8 /* mxcl∕AppUpdater-1.0.3.swift */; }; DD2127A7693447EA31FC5844269A5476 /* when.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2FA622D9453DC325EF8DD4097AB2C2B /* when.swift */; }; DEBA5D57958559217B612C305D80D18B /* Self.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63FED00F5F6CA5AA95D6FD33264CC27E /* Self.swift */; }; DF2738497A69CFC60A7BFF7546A79383 /* scaffold().swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFD929CD18BA53DE82AB2B4BC7F03E3 /* scaffold().swift */; }; E08267E7A19CE4F86CF11AE46F1F9CFE /* KitchenDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89B0D3A65F18AC6AE103808E1EF9054 /* KitchenDelegate.swift */; }; E1BA243CAB80D7B010397756DE150F4E /* CakeProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE016ECFF05687BA82A5550BE83957F /* CakeProject.swift */; }; E2FAA3397719FA0DC93535F286C47BDC /* Path+CommonDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94BE46F8140D74E37611092ADBEB53BE /* Path+CommonDirectories.swift */; }; E39FA5C4830B1C6286C4B8B0A11A6279 /* Objects/Targets/PBXTargetDependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB42F45DDB75F843BD744639C008C84B /* Objects/Targets/PBXTargetDependency.swift */; }; E641E4491384EBC7ED294BF3AFBFA63B /* XcakeProject.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF0DABA4951DF1D4D2F4308EA9757D27 /* XcakeProject.swift */; }; ED25BB88C9183FDB03E55618895F3A3E /* Objects/Targets/PBXAggregateTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76149DDC4F8A2B10AC9F40DC12C04A01 /* Objects/Targets/PBXAggregateTarget.swift */; }; F10ECD50FB9CDB0EF1F3ED6535B00F79 /* Objects/Project/PBXObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF68BD1B8B7E31E3692084703149A9F4 /* Objects/Project/PBXObject.swift */; }; F1773AE9122717504710FDE32E039B2B /* HotKeysController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 293B693F5D2B905EAB9D47603FF004E0 /* HotKeysController.swift */; }; F1A9E165928095B7FB7D9C8664C2B533 /* Extensions/Bool+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1529B0E38393D8746B29EC816E6FBD3 /* Extensions/Bool+Extras.swift */; }; F2EDD3CF836DCC600B513BFBB755CF5D /* Protocols/Writable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 381C3BC031CA52785EC98BBE0F7D2F6F /* Protocols/Writable.swift */; }; F5CA27B2477A402F4A5820741101B61C /* Objects/Targets/PBXReferenceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31102E62D8DBA38978DFFDA3A5FF6AD9 /* Objects/Targets/PBXReferenceProxy.swift */; }; F7E7A799FBAE4D353AE3728E97367F61 /* Key.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18FDE6CB448ECB4CA03C90F660EB53D /* Key.swift */; }; F8373135B8E73DC04E741253EF8538AF /* afterlife.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA87092A5BDAB632904A61E928DE49B9 /* afterlife.swift */; }; F967CC7B7762819FA7DC1F4ACA76DA87 /* Path+Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE8AEF64C23D070DC58781BE7913BE2C /* Path+Attributes.swift */; }; FAD7EFC6A9B1B2F1AA0A4A1548B922BB /* Extensions/Dictionary+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023860B7D6084F6464BEA7B2304B2114 /* Extensions/Dictionary+Extras.swift */; }; FB72D613AD5B0AAF539728B89A41FB8E /* XcodeScriptingBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278A53C448758EECE7FD6B78133E40C8 /* XcodeScriptingBridge.swift */; }; FD4509FBDBD52F99ED185069192B4611 /* Objects/Sourcery/Sourcery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B08A9630C2EF6944BF3EE3F4CD8A04 /* Objects/Sourcery/Sourcery.swift */; }; FDC90EB1D93E3B5852C55A9F0C16EB8C /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48324EC36DFA0B91BEB4A8CF50E6133F /* Document.swift */; }; FEB9BA4D068A75074CBA587AFBC15867 /* etc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C15151125E344471378CB5346737FA7 /* etc.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 0116FC39B24582BEE9036286F9430EA1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = AC6B4791DEE2977626A076B8F9A7666F; remoteInfo = "Deps·OrderedSet"; }; 0EFDF076DBC213F64A00B6683D0E6B67 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = A49235A78CF83BF260878E68B866C986; remoteInfo = "Batter·Base"; }; 144BDEC13717CB09678A9A83D9431ADF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = B49CC989FC5BE99773DFD32B46D8E82C; remoteInfo = "Deps·PathKit"; }; 17D5F07BC8B5B3BC93A4EE4B2B28AD4A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = DF69393E8DED4E7C87625E2008C40E41; remoteInfo = "Batter·XcodeProject"; }; 18BB34364DC319E58561C144CFB5F85E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = C8AC307C08B1141701DFEAAD12667716; remoteInfo = "Batter·Modelizer"; }; 1AD18862BE00E9D273C5119993BF1EF7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; 1C49E795CA5C037A31C025E2A56C01F7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = B4280F358AD4C3799414724EE00E6812; remoteInfo = "Deps·PMKFoundation"; }; 1EE1EF930A5BF3D0012B58E4A1D22BB8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = B4280F358AD4C3799414724EE00E6812; remoteInfo = "Deps·PMKFoundation"; }; 2271E804C9C352B20C61ABBC68327426 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 8B4D032D3EA2708E1BF1B498E5AAC085; remoteInfo = "Deps·LegibleError"; }; 25BC92DB11B4440F7308DC364B2A9CC8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 76CCBFA038A347F71E7B5BFB1521AC8A; remoteInfo = "Deps·Path"; }; 26A6089A74D49C04CCF423ED317665CF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D1CE66C2AF312DCD9A12B6444FB0D2EA; remoteInfo = "Deps·AEXML"; }; 2AB7C8C5BF907C9BECA079EDED1FFC18 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 8FEBB13B61D6321603EC90A5606F8C4F; remoteInfo = "Deps·HotKey"; }; 2D6EDF33EC661363ED1E5889EA9EF52F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = DCF843C187E023E2097ACF9EABA93DD6; remoteInfo = Dependencies; }; 3609D632CDBAAFD820788391BA3977DC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; 3A6C290700F171F09F36630EAE33952A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = DCF843C187E023E2097ACF9EABA93DD6; remoteInfo = Dependencies; }; 3B18052B44E98025F6CED9B8801DAF2A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; 3CA790475701796546AEC8C8F9BEC467 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D4D58EF887FC75ADD1D795BF5B47A879; remoteInfo = "Batter·CakefileDescription"; }; 3D570B61F4B7B186FBD4FB45CAB2344D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = BD398413C05B07BBE2B6E2D14C9EE8D9; remoteInfo = "Deps·PromiseKit"; }; 466D0E195DB547397C597EF346516148 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D4D58EF887FC75ADD1D795BF5B47A879; remoteInfo = "Batter·CakefileDescription"; }; 5EDA6990A1DDBE6E9B607D100EF8A5DA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = BD398413C05B07BBE2B6E2D14C9EE8D9; remoteInfo = "Deps·PromiseKit"; }; 67AEDC266F822DBF18B34C4E257EE1E9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; 71C00BC3AFA055F16733B467637C32E6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D4D58EF887FC75ADD1D795BF5B47A879; remoteInfo = "Batter·CakefileDescription"; }; 756891CE29B59469D117CB86600830B4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = F5D94DE7A2DF28D8FD6E0C310044455E; remoteInfo = Batter; }; 7E33F2A58E0B9F911C5089934C28196D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = DCF843C187E023E2097ACF9EABA93DD6; remoteInfo = Dependencies; }; 80644EB6FD3773EE45376C2EC9869F30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 50A4D32099C32D3207892A9614D37B66; remoteInfo = "Batter·Processor"; }; 8CF6B72EF378FFC5EDCD3344A04E6912 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = C8AC307C08B1141701DFEAAD12667716; remoteInfo = "Batter·Modelizer"; }; 924C0BA9D531ACB667362E847E2C2ED1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = A49235A78CF83BF260878E68B866C986; remoteInfo = "Batter·Base"; }; 9552D2A44C21251174A336F563E786A6 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 0F64CBB97351A503B1F408F40AB7E996; remoteInfo = "Batter·Kitchen"; }; 96CF6D0F301321DD90DAAA34150AF9C8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 76CCBFA038A347F71E7B5BFB1521AC8A; remoteInfo = "Deps·Path"; }; A0AD5420B6DC1AB939BC61EDDB8218B7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = C1038750BB9B8EA5926C885645506714; remoteInfo = "Batter·XcodeObserver"; }; A374EA6D4F5157415110C114CB7D2C2C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = ED829D4B109C4E4B415B8F01358C62F3; remoteInfo = "Batter·XcakeProject"; }; A451E2841D294632F1518CB0121B3EE9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = C1038750BB9B8EA5926C885645506714; remoteInfo = "Batter·XcodeObserver"; }; A6534538102624A3BAD54587BBECFEF5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; B01E0633294DEAFA1B9F52960E14C230 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = A49235A78CF83BF260878E68B866C986; remoteInfo = "Batter·Base"; }; B06116E54C8217994FD5F06F7E592CF2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; C9302B77BC2BA2C40C288B30160EB8D2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; CDAE6F16BFD0F82E6454C65CB8F164D2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 9CF1FA8024CC8159DE776A7595DC3523; remoteInfo = "Deps·Version"; }; D46696C0AE71459DAAF917F866D13018 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D4D58EF887FC75ADD1D795BF5B47A879; remoteInfo = "Batter·CakefileDescription"; }; D98236A2D881CAC7928673239C8BFD51 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = D1CE66C2AF312DCD9A12B6444FB0D2EA; remoteInfo = "Deps·AEXML"; }; E19C66FA1ADEB89F9061C2604746306D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 5D1C4ECF6D5347A44CB1E59E5BB558E0; remoteInfo = "Deps·AppUpdater"; }; EB36CF19BE9565CD2F536DD00DB99F43 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = B4EB89E549B6ADCED02958295D4FAD21; remoteInfo = "Deps·xcodeproj"; }; ED11063682340B41D483263E6FE5EED7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = B49CC989FC5BE99773DFD32B46D8E82C; remoteInfo = "Deps·PathKit"; }; EFB035A45795006B3E0D3D4C5A2F75D9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 9CF1FA8024CC8159DE776A7595DC3523; remoteInfo = "Deps·Version"; }; F312C1044F70834D556FB7F4802D1893 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 27CCC44DFA86333E66FEE34EA8063784; remoteInfo = Versionator; }; FC06ED7DAB16B02502FC9309C805AAA3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; proxyType = 1; remoteGlobalIDString = 818A4854C95B333066E8C4A9D0FE3104; remoteInfo = Cakefile; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 01B73C1D9BBF582F1B4CA11D1FD2BCD5 /* Utils/BuildSettingsProvider.swift */ = {isa = PBXFileReference; path = Utils/BuildSettingsProvider.swift; sourceTree = ""; }; 023860B7D6084F6464BEA7B2304B2114 /* Extensions/Dictionary+Extras.swift */ = {isa = PBXFileReference; path = "Extensions/Dictionary+Extras.swift"; sourceTree = ""; }; 04110D4A7CD13051C705542C94A0A7A9 /* Utils/OSLogger.swift */ = {isa = PBXFileReference; path = Utils/OSLogger.swift; sourceTree = ""; }; 05103104AE592402CB93C1FFE5E2D1CD /* StreamReader.swift */ = {isa = PBXFileReference; path = StreamReader.swift; sourceTree = ""; }; 05D33FD3DDE7FE2483580EF428D7DE21 /* Batter.swift */ = {isa = PBXFileReference; path = Batter.swift; sourceTree = ""; }; 06BD24A5E56306FA76A42CE38A938E0C /* Extensions/AEXML+XcodeFormat.swift */ = {isa = PBXFileReference; path = "Extensions/AEXML+XcodeFormat.swift"; sourceTree = ""; }; 0B6CC87C2DDD9FDBA1C2CBD27071D4AC /* Scheme/XCScheme+EnvironmentVariable.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+EnvironmentVariable.swift"; sourceTree = ""; }; 0C15151125E344471378CB5346737FA7 /* etc.swift */ = {isa = PBXFileReference; path = etc.swift; sourceTree = ""; }; 0E05502AA06041ADF62F3BF7E7659260 /* xcodeproj.a */ = {isa = PBXFileReference; path = xcodeproj.a; sourceTree = ""; }; 0E3AD59FD7C82A5F84B7C248687AB331 /* Scheme/XCScheme+BuildAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+BuildAction.swift"; sourceTree = ""; }; 0EB24F5AA5F9F47F5FE894B8910CCD3F /* Version+Comparable.swift */ = {isa = PBXFileReference; path = "Version+Comparable.swift"; sourceTree = ""; }; 0EFD929CD18BA53DE82AB2B4BC7F03E3 /* scaffold().swift */ = {isa = PBXFileReference; path = "scaffold().swift"; sourceTree = ""; }; 11D3B38D3F7DA37A8300F924107470ED /* CakefileDescription.a */ = {isa = PBXFileReference; path = CakefileDescription.a; sourceTree = ""; }; 1426181F4046DE0C27F56E6BD5910905 /* Errors/Errors.swift */ = {isa = PBXFileReference; path = Errors/Errors.swift; sourceTree = ""; }; 19F01C205BDC9FA3129D8949BE2CB5C4 /* AppUpdater.a */ = {isa = PBXFileReference; path = AppUpdater.a; sourceTree = ""; }; 1AF5A7DF8CE28184F27C6599C742AC25 /* Objects/Targets/PBXTarget.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXTarget.swift; sourceTree = ""; }; 1B52A49D89C35234D21902B915BB0DB7 /* Utils/PlistValue.swift */ = {isa = PBXFileReference; path = Utils/PlistValue.swift; sourceTree = ""; }; 1C0E03F6E6EECCE50817B52C201AEAA4 /* Utils/ReferenceGenerator.swift */ = {isa = PBXFileReference; path = Utils/ReferenceGenerator.swift; sourceTree = ""; }; 1C473431F71F14C0C7B094C7AFC1BCB1 /* firstly.swift */ = {isa = PBXFileReference; path = firstly.swift; sourceTree = ""; }; 1DBCAEFF3AB28195D7B5E09B52FDBDA9 /* LegibleError.a */ = {isa = PBXFileReference; path = LegibleError.a; sourceTree = ""; }; 1F0D8DD1958D7B1AF9E5930838B61C63 /* Process+Promise.swift */ = {isa = PBXFileReference; path = "Process+Promise.swift"; sourceTree = ""; }; 1FFC5A15BE7FEEA7952C65C2124CDB1C /* Objects/BuildPhase/PBXBuildRule.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXBuildRule.swift; sourceTree = ""; }; 2274AC91D7F94448E0AF2969D9BCDA58 /* Scheme/XCScheme+AnalyzeAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+AnalyzeAction.swift"; sourceTree = ""; }; 25F48703B70EEA7E7DCC6D2D2F06C9B8 /* Path.swift */ = {isa = PBXFileReference; path = Path.swift; sourceTree = ""; }; 278A53C448758EECE7FD6B78133E40C8 /* XcodeScriptingBridge.swift */ = {isa = PBXFileReference; path = XcodeScriptingBridge.swift; sourceTree = ""; }; 293B693F5D2B905EAB9D47603FF004E0 /* HotKeysController.swift */ = {isa = PBXFileReference; path = HotKeysController.swift; sourceTree = ""; }; 29EB733203A51041BAF8B7325873B8F8 /* Extensions/OSLog+Extras.swift */ = {isa = PBXFileReference; path = "Extensions/OSLog+Extras.swift"; sourceTree = ""; }; 2A565382D53C145048B6FC0422270BC1 /* Module.swift */ = {isa = PBXFileReference; path = Module.swift; sourceTree = ""; }; 2B1F1175C209C392F423782054651ED5 /* Objects/BuildPhase/PBXResourcesBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXResourcesBuildPhase.swift; sourceTree = ""; }; 2B70D9747ECEC5C6AC9E6368CFB36889 /* Objects/Files/PBXSourceTree.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXSourceTree.swift; sourceTree = ""; }; 2BE47230D3E16F17B6C53D4CD9ABF0A7 /* Objects/Targets/PBXProductType.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXProductType.swift; sourceTree = ""; }; 2C62C6619223819ED3301991617A91BD /* OrderedSet.a */ = {isa = PBXFileReference; path = OrderedSet.a; sourceTree = ""; }; 308336D6CA83EAE1E8D36F4DE09DE65E /* Extensions/NSRecursiveLock+Sync.swift */ = {isa = PBXFileReference; path = "Extensions/NSRecursiveLock+Sync.swift"; sourceTree = ""; }; 30BDDCCB89500DCBDD7BBA0272926DD0 /* CustomStringConvertible.swift */ = {isa = PBXFileReference; path = CustomStringConvertible.swift; sourceTree = ""; }; 31102E62D8DBA38978DFFDA3A5FF6AD9 /* Objects/Targets/PBXReferenceProxy.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXReferenceProxy.swift; sourceTree = ""; }; 3142C0085C1236B2B3772F4960DBB8D9 /* Kitchen.swift */ = {isa = PBXFileReference; path = Kitchen.swift; sourceTree = ""; }; 3185556D97EDCF571118B9C60F3D4DCB /* Scheme/XCScheme+ProfileAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+ProfileAction.swift"; sourceTree = ""; }; 31C617BEA32F179B393AF1D212E944A9 /* Objects/Configuration/XCConfigurationList.swift */ = {isa = PBXFileReference; path = Objects/Configuration/XCConfigurationList.swift; sourceTree = ""; }; 36F4FC690CAF8E887E4358E57F7AFBC1 /* Resolver.swift */ = {isa = PBXFileReference; path = Resolver.swift; sourceTree = ""; }; 372DAB40CDD5A8EEE06A79D6C8AC5536 /* Base.a */ = {isa = PBXFileReference; path = Base.a; sourceTree = ""; }; 381C3BC031CA52785EC98BBE0F7D2F6F /* Protocols/Writable.swift */ = {isa = PBXFileReference; path = Protocols/Writable.swift; sourceTree = ""; }; 3875F50A4E88DECD4C85498B13194B4D /* Objects/Configuration/BuildSettings.swift */ = {isa = PBXFileReference; path = Objects/Configuration/BuildSettings.swift; sourceTree = ""; }; 38AC374D097346CE8B4226D78BA0156F /* NSObject+Promise.swift */ = {isa = PBXFileReference; path = "NSObject+Promise.swift"; sourceTree = ""; }; 3A81CC9DD3104D5CFAB0E095D7A73FDE /* HotKey.swift */ = {isa = PBXFileReference; path = HotKey.swift; sourceTree = ""; }; 3C29E76D627B188CA3643C87B68EC436 /* PathKit.a */ = {isa = PBXFileReference; path = PathKit.a; sourceTree = ""; }; 3C408218005B7BC75A3ABD08133612D9 /* Project/XCSharedData.swift */ = {isa = PBXFileReference; path = Project/XCSharedData.swift; sourceTree = ""; }; 3D18DB9B60F9CAE6DB1EE58AA5CDCA1C /* Utils/JSONDecoding.swift */ = {isa = PBXFileReference; path = Utils/JSONDecoding.swift; sourceTree = ""; }; 3D70A7A1D451A574394BE9D849EF26BD /* Box.swift */ = {isa = PBXFileReference; path = Box.swift; sourceTree = ""; }; 3EACC5F861EC78E815F715FE0D7F0DB8 /* mxcl∕AppUpdater-1.0.3.swift */ = {isa = PBXFileReference; path = "mxcl∕AppUpdater-1.0.3.swift"; sourceTree = ""; }; 3F573D976FA9A0403F17F22F1A4DAA55 /* Batter.a */ = {isa = PBXFileReference; path = Batter.a; sourceTree = ""; }; 3FA20E1A308B36BD34D4F6FA38D3BF30 /* AEXML.a */ = {isa = PBXFileReference; path = AEXML.a; sourceTree = ""; }; 40B08A9630C2EF6944BF3EE3F4CD8A04 /* Objects/Sourcery/Sourcery.swift */ = {isa = PBXFileReference; path = Objects/Sourcery/Sourcery.swift; sourceTree = ""; }; 40CA625F76FE45EABC6548E7FA9081C9 /* Version+Codable.swift */ = {isa = PBXFileReference; path = "Version+Codable.swift"; sourceTree = ""; }; 410CE76CF11E01AD634AF853AB480845 /* Objects/Files/PBXVariantGroup.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXVariantGroup.swift; sourceTree = ""; }; 4144D0D13AB2A191101B99B2DEDE581C /* mxcl∕LegibleError-1.0.1.swift */ = {isa = PBXFileReference; path = "mxcl∕LegibleError-1.0.1.swift"; sourceTree = ""; }; 41AA2ABCDA2F333EBC153257903CCFFA /* race.swift */ = {isa = PBXFileReference; path = race.swift; sourceTree = ""; }; 435DE35726152C660A49F9A23B51B7E3 /* Objects/BuildPhase/PBXHeadersBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXHeadersBuildPhase.swift; sourceTree = ""; }; 43DB4EE450B414ECE6DEDAAB4F40019D /* Scheme/XCScheme+TestableReference.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+TestableReference.swift"; sourceTree = ""; }; 43F867ED701FF56BC9AA1829B4888F2F /* Cake.swift */ = {isa = PBXFileReference; path = Cake.swift; sourceTree = ""; }; 46348EB9B861968F7D43E2F325955D37 /* FSWatcher.swift */ = {isa = PBXFileReference; path = FSWatcher.swift; sourceTree = ""; }; 48324EC36DFA0B91BEB4A8CF50E6133F /* Document.swift */ = {isa = PBXFileReference; path = Document.swift; sourceTree = ""; }; 49E819CC92D95188B91ABBEDA33B46C3 /* Scheme/XCScheme+ArchiveAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+ArchiveAction.swift"; sourceTree = ""; }; 4A7E89000FDF44A3427FBD44B878A9C1 /* Dependencies.a */ = {isa = PBXFileReference; path = Dependencies.a; sourceTree = ""; }; 4B89F8E5109BA12DC10ED95129E77944 /* Project/Xcode.swift */ = {isa = PBXFileReference; path = Project/Xcode.swift; sourceTree = ""; }; 4CD7DF2A21452F6F3764E31A50E68AF2 /* Utils/CommentedString.swift */ = {isa = PBXFileReference; path = Utils/CommentedString.swift; sourceTree = ""; }; 4F2CA03F28361DA2CD3C82B19DE28C91 /* HotKey.a */ = {isa = PBXFileReference; path = HotKey.a; sourceTree = ""; }; 52A4C823A8934B7C4408E5A47FF4FECB /* +functions.swift */ = {isa = PBXFileReference; path = "+functions.swift"; sourceTree = ""; }; 531404CEBE08B993CDAD51AF95383C04 /* Objects/BuildPhase/PBXBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXBuildPhase.swift; sourceTree = ""; }; 53C5D7D1835891126DAC0217D2976BB3 /* Configuration.swift */ = {isa = PBXFileReference; path = Configuration.swift; sourceTree = ""; }; 53E3B23BDD8E313D1CCE46BCBA847860 /* PromiseKit.a */ = {isa = PBXFileReference; path = PromiseKit.a; sourceTree = ""; }; 559797E564267A36E62DE4ADF60465B7 /* Objects/Project/PBXProject.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXProject.swift; sourceTree = ""; }; 576C9C9EE9D61D301635A94562588667 /* Scheme/XCScheme+ExecutionAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+ExecutionAction.swift"; sourceTree = ""; }; 57A5610558926A1003CFFD244AA5DA23 /* Scheme/XCScheme+SkippedTests.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+SkippedTests.swift"; sourceTree = ""; }; 5DA0BC07DF161138B4D7A43E6A219B05 /* Element.swift */ = {isa = PBXFileReference; path = Element.swift; sourceTree = ""; }; 618FDE59E88C49B7C9ADE5C5A9159A06 /* +platforms.swift */ = {isa = PBXFileReference; path = "+platforms.swift"; sourceTree = ""; }; 63FED00F5F6CA5AA95D6FD33264CC27E /* Self.swift */ = {isa = PBXFileReference; path = Self.swift; sourceTree = ""; }; 64ED4F4E164410F7A62B935BAC757997 /* Extensions/String+md5.swift */ = {isa = PBXFileReference; path = "Extensions/String+md5.swift"; sourceTree = ""; }; 669A914005810A46DA64A779CE45E521 /* Workspace/XCWorkspaceDataElementLocationType.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspaceDataElementLocationType.swift; sourceTree = ""; }; 675FB47A04E79CDCC955D8FCF3A4BF80 /* Objects/Sourcery/Equality.generated.swift */ = {isa = PBXFileReference; path = Objects/Sourcery/Equality.generated.swift; sourceTree = ""; }; 69787F8145CACFA492EC131CC2A0AA1D /* PMKFoundation.a */ = {isa = PBXFileReference; path = PMKFoundation.a; sourceTree = ""; }; 6A6EF02B86E86BA90A2AD45729B1EA6A /* Version+Range.swift */ = {isa = PBXFileReference; path = "Version+Range.swift"; sourceTree = ""; }; 6F32012741B387F7AD9EB83C1E2AF212 /* Version+Foundation.swift */ = {isa = PBXFileReference; path = "Version+Foundation.swift"; sourceTree = ""; }; 6FDDFD13C38B75004170652473061F3A /* SwiftVersion.swift */ = {isa = PBXFileReference; path = SwiftVersion.swift; sourceTree = ""; }; 71B38B8ED5DB9DCC0B70E3CC1E44402A /* Objects/Files/PBXGroup.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXGroup.swift; sourceTree = ""; }; 722A12F4645B5D35D39B45AFA1D76983 /* Objects/Project/PBXObjects.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXObjects.swift; sourceTree = ""; }; 72C3939CC65CE41D34872BE7C25A01C5 /* SwiftVersion.swift */ = {isa = PBXFileReference; path = SwiftVersion.swift; sourceTree = ""; }; 749A8E67AC5834C6A956EAADEB64557B /* topologicalSort().swift */ = {isa = PBXFileReference; path = "topologicalSort().swift"; sourceTree = ""; }; 755B5AE0CCEBAD76024C7BACFD3769CF /* Workspace/XCWorkspaceData.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspaceData.swift; sourceTree = ""; }; 76149DDC4F8A2B10AC9F40DC12C04A01 /* Objects/Targets/PBXAggregateTarget.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXAggregateTarget.swift; sourceTree = ""; }; 76C9275C1BF293F18BCC5970643036F9 /* Scheme/XCScheme+LocationScenarioReference.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+LocationScenarioReference.swift"; sourceTree = ""; }; 7713E4DEB1439F6B933AD7032A4CB4A4 /* Objects/Configuration/XCBuildConfiguration.swift */ = {isa = PBXFileReference; path = Objects/Configuration/XCBuildConfiguration.swift; sourceTree = ""; }; 7A124F661FEA3E444A56EA4D521A515A /* NSEventModifierFlags+HotKey.swift */ = {isa = PBXFileReference; path = "NSEventModifierFlags+HotKey.swift"; sourceTree = ""; }; 7A946331648AD8B89896F7F8669B8E51 /* Project/WorkspaceSettings.swift */ = {isa = PBXFileReference; path = Project/WorkspaceSettings.swift; sourceTree = ""; }; 7C8796C21F96CBC0C0A4E13733B4CD0E /* Scheme/XCScheme+BuildableProductRunnable.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+BuildableProductRunnable.swift"; sourceTree = ""; }; 7D3C314B487A12D0E1C0D029FE36371D /* Objects/Targets/PBXNativeTarget.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXNativeTarget.swift; sourceTree = ""; }; 7E28C010F6CDF44DDB15986B219FCDB2 /* Options.swift */ = {isa = PBXFileReference; path = Options.swift; sourceTree = ""; }; 7E32B9B4F0137DD729D7F3D74688CF6D /* NSNotificationCenter+Promise.swift */ = {isa = PBXFileReference; path = "NSNotificationCenter+Promise.swift"; sourceTree = ""; }; 7F8732C7CBD899BD5F0398A832669E75 /* XcakeProject.a */ = {isa = PBXFileReference; path = XcakeProject.a; sourceTree = ""; }; 80158EAEB4E68B546727248C48EF0F17 /* Scheme/XCScheme+AditionalOption.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+AditionalOption.swift"; sourceTree = ""; }; 804B783359D6CCE7145742C88183EA36 /* Sequence+KeyPath.swift */ = {isa = PBXFileReference; path = "Sequence+KeyPath.swift"; sourceTree = ""; }; 830FE1BA33BC05A8FF3C2ED99884F684 /* Objects/BuildPhase/PBXSourcesBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXSourcesBuildPhase.swift; sourceTree = ""; }; 835B1909D4EA60D2CF046ED021E060E7 /* Objects/BuildPhase/PBXRezBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXRezBuildPhase.swift; sourceTree = ""; }; 835E3CF62D03CBDD1679F357A3702A9C /* Error.swift */ = {isa = PBXFileReference; path = Error.swift; sourceTree = ""; }; 852615CA271D363F36FCE47BCF0265AD /* Objects/BuildPhase/PBXShellScriptBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXShellScriptBuildPhase.swift; sourceTree = ""; }; 8581BD4238C94C7B078D7E65968660C0 /* Objects/Targets/PBXLegacyTarget.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXLegacyTarget.swift; sourceTree = ""; }; 858CCCCD45F434A16E8D273190765092 /* Dependencies.swift */ = {isa = PBXFileReference; path = Dependencies.swift; sourceTree = ""; }; 85B557836B8BE6B8B5590ABD761653BA /* Objects/Files/PBXFileReference.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXFileReference.swift; sourceTree = ""; }; 87FA10E492A0664C5F376C3AADA117AB /* Objects/Project/PBXProj.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXProj.swift; sourceTree = ""; }; 8936109BF1AA3578412FAD3077209014 /* kylef∕PathKit-0.9.2.swift */ = {isa = PBXFileReference; path = "kylef∕PathKit-0.9.2.swift"; sourceTree = ""; }; 8D3944D256EB9C28558C204F63F624B5 /* deintegrate().swift */ = {isa = PBXFileReference; path = "deintegrate().swift"; sourceTree = ""; }; 8D719F3BC31505ACB101E7D6737CE1E5 /* Objects/Files/PBXContainerItem.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXContainerItem.swift; sourceTree = ""; }; 8DB463DC57B0C69C11B869C0D1D1CE34 /* Extensions/Dictionary+Enumerate.swift */ = {isa = PBXFileReference; path = "Extensions/Dictionary+Enumerate.swift"; sourceTree = ""; }; 8E74C31BCB0D74EF97C4278031E8034D /* Objects/BuildPhase/PBXFrameworksBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXFrameworksBuildPhase.swift; sourceTree = ""; }; 902419C27FD761BCEFE0A9AB8BF4FE87 /* Dependencies.json.swift */ = {isa = PBXFileReference; path = Dependencies.json.swift; sourceTree = ""; }; 91D674DA388038DB2C7C2DCC6B13CA11 /* Objects/Project/PBXObjectReference.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXObjectReference.swift; sourceTree = ""; }; 930A6BD4B016A2539E9D5013E3FCA04A /* Version+.swift */ = {isa = PBXFileReference; path = "Version+.swift"; sourceTree = ""; }; 937C922F7F6999DF1895EB3DC82906E9 /* XcodeProject.a */ = {isa = PBXFileReference; path = XcodeProject.a; sourceTree = ""; }; 949BF795030FD942ABF42746C69282A2 /* Workspace/XCWorkspaceDataFileRef.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspaceDataFileRef.swift; sourceTree = ""; }; 94BE46F8140D74E37611092ADBEB53BE /* Path+CommonDirectories.swift */ = {isa = PBXFileReference; path = "Path+CommonDirectories.swift"; sourceTree = ""; }; 9667E7EC96A4E5AF6C72D9DDD7ACC033 /* Promise.swift */ = {isa = PBXFileReference; path = Promise.swift; sourceTree = ""; }; 97EAFD505287A688648A6F468128EEEC /* Error.swift */ = {isa = PBXFileReference; path = Error.swift; sourceTree = ""; }; 9A4F661909381C2B72260EC5E92EB852 /* Utils/Decoders.swift */ = {isa = PBXFileReference; path = Utils/Decoders.swift; sourceTree = ""; }; 9D25EA9B892F8852C3D86F85B8647FAE /* LogEvent.swift */ = {isa = PBXFileReference; path = LogEvent.swift; sourceTree = ""; }; 9DB38989A054A4EA67BEB37294BFDC38 /* Scheme/XCScheme.swift */ = {isa = PBXFileReference; path = Scheme/XCScheme.swift; sourceTree = ""; }; 9DCF2ACDC813D1597DCDDFE3EA904191 /* Scheme/XCScheme+BuildableReference.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+BuildableReference.swift"; sourceTree = ""; }; 9DD6BC9A2C80C818AD36364182F42223 /* Cakefile.swift */ = {isa = PBXFileReference; name = Cakefile.swift; path = ../Cakefile.swift; sourceTree = ""; }; 9EC126C205BC396E4B52986041911E1A /* Path+ls.swift */ = {isa = PBXFileReference; path = "Path+ls.swift"; sourceTree = ""; }; A365FC1A53413924C32E4651E9D67AA9 /* NSURLSession+Promise.swift */ = {isa = PBXFileReference; path = "NSURLSession+Promise.swift"; sourceTree = ""; }; A49E0E264A02682CCE9A823B02A46706 /* Path.a */ = {isa = PBXFileReference; path = Path.a; sourceTree = ""; }; A4B1E5C1B830E94800A96F72DE371A05 /* Cake.a */ = {isa = PBXFileReference; path = Cake.a; sourceTree = ""; }; A50CE25F21E57E92B7A610699FA83BC1 /* Objects/Project/PBXProjEncoder.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXProjEncoder.swift; sourceTree = ""; }; A6A3C3E306641683ED6A2DEA9A9CEDFA /* XcodeObserver.swift */ = {isa = PBXFileReference; path = XcodeObserver.swift; sourceTree = ""; }; A7784500AEAF00A3954F252BF7EB9186 /* Scheme/XCScheme+TestAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+TestAction.swift"; sourceTree = ""; }; A77AFC4AE522827E286DEA7B38C2C006 /* Path+FileManager.swift */ = {isa = PBXFileReference; path = "Path+FileManager.swift"; sourceTree = ""; }; A7C16154EA6E8025D3F05AC2433A61BE /* TemporaryDirectory.swift */ = {isa = PBXFileReference; path = TemporaryDirectory.swift; sourceTree = ""; }; A909F2285D6BB302E831CD131B206FB1 /* Scheme/XCScheme+SerialAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+SerialAction.swift"; sourceTree = ""; }; A931901826EAFC85E24FC30A1708944E /* CakefileDescription.swift */ = {isa = PBXFileReference; path = CakefileDescription.swift; sourceTree = ""; }; AA87092A5BDAB632904A61E928DE49B9 /* afterlife.swift */ = {isa = PBXFileReference; path = afterlife.swift; sourceTree = ""; }; AAB66A0A047C8351A0114D24BF9C84D4 /* _PathDisambiguation.swift */ = {isa = PBXFileReference; path = _PathDisambiguation.swift; sourceTree = ""; }; AB353A7BFBF179F59387515435E68F1B /* *Target.swift */ = {isa = PBXFileReference; path = "*Target.swift"; sourceTree = ""; }; AF0DABA4951DF1D4D2F4308EA9757D27 /* XcakeProject.swift */ = {isa = PBXFileReference; path = XcakeProject.swift; sourceTree = ""; }; B014E5511BA57DD4C34DEC96713FCC0F /* XcodeProject.swift */ = {isa = PBXFileReference; path = XcodeProject.swift; sourceTree = ""; }; B09953A76D3C953D379A46546E39FC8D /* Objects/Files/XCVersionGroup.swift */ = {isa = PBXFileReference; path = Objects/Files/XCVersionGroup.swift; sourceTree = ""; }; B14C812ADA5BF5033A67333BAF077A7A /* Objects/Project/PBXOutputSettings.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXOutputSettings.swift; sourceTree = ""; }; B1529B0E38393D8746B29EC816E6FBD3 /* Extensions/Bool+Extras.swift */ = {isa = PBXFileReference; path = "Extensions/Bool+Extras.swift"; sourceTree = ""; }; B1F70701A65B3979718758A9C96B7E74 /* Weebly∕OrderedSet-3.1.0.swift */ = {isa = PBXFileReference; path = "Weebly∕OrderedSet-3.1.0.swift"; sourceTree = ""; }; B30144F1A4CC788F25022BF92EA083F6 /* Workspace/XCWorkspace.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspace.swift; sourceTree = ""; }; B3CDEF324226D91C75D2BCBA3E3D7952 /* Cakefile·Completion */ = {isa = PBXFileReference; path = "Cakefile·Completion"; sourceTree = ""; }; B41FF1790C8AA4E84A29A33DAE05468B /* Project/XCBreakpointList.swift */ = {isa = PBXFileReference; path = Project/XCBreakpointList.swift; sourceTree = ""; }; B7AEA2479B3032443714E1D228FADF0C /* hang.swift */ = {isa = PBXFileReference; path = hang.swift; sourceTree = ""; }; B828EC0B6BCB9E838EF8719A040E05FB /* Parser.swift */ = {isa = PBXFileReference; path = Parser.swift; sourceTree = ""; }; BAD9493581EF0180B01D541DF06A6E4B /* Modelizer.a */ = {isa = PBXFileReference; path = Modelizer.a; sourceTree = ""; }; BB42F45DDB75F843BD744639C008C84B /* Objects/Targets/PBXTargetDependency.swift */ = {isa = PBXFileReference; path = Objects/Targets/PBXTargetDependency.swift; sourceTree = ""; }; BE28E6555AA9082953164CAB96DC7EAA /* z+buildSettings.swift */ = {isa = PBXFileReference; path = "z+buildSettings.swift"; sourceTree = ""; }; BF52CA51D11D9A90EF84861A2B5938B1 /* Kitchen.a */ = {isa = PBXFileReference; path = Kitchen.a; sourceTree = ""; }; C217681598D56FE79A522A8D0D7CB7C7 /* Thenable.swift */ = {isa = PBXFileReference; path = Thenable.swift; sourceTree = ""; }; C21B018E286AB818EEF5EA83B02C86E0 /* Objects/BuildPhase/PBXBuildFile.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXBuildFile.swift; sourceTree = ""; }; C5744C074FEF959972A62160544D24F0 /* Processor.a */ = {isa = PBXFileReference; path = Processor.a; sourceTree = ""; }; C89B0D3A65F18AC6AE103808E1EF9054 /* KitchenDelegate.swift */ = {isa = PBXFileReference; path = KitchenDelegate.swift; sourceTree = ""; }; CAF60D50AF8D2A0115E908C973003A12 /* Cakefile.swift */ = {isa = PBXFileReference; path = Cakefile.swift; sourceTree = ""; }; CB67A28ADBD062CE337B8DF5E1ABA3B4 /* Utils/XCConfig.swift */ = {isa = PBXFileReference; path = Utils/XCConfig.swift; sourceTree = ""; }; CD06ECAE4D53F31C5FF63EB1A4FAA0F1 /* Dependencies.swift */ = {isa = PBXFileReference; path = Dependencies.swift; sourceTree = ""; }; CDA44BF315E7E72F7AF8D8FFAB5D39F6 /* etc.swift */ = {isa = PBXFileReference; path = etc.swift; sourceTree = ""; }; CEE016ECFF05687BA82A5550BE83957F /* CakeProject.swift */ = {isa = PBXFileReference; path = CakeProject.swift; sourceTree = ""; }; CF647C9C376ED858DE3D33BD092CCA7F /* Guarantee.swift */ = {isa = PBXFileReference; path = Guarantee.swift; sourceTree = ""; }; D0FDA939D602AC0EF1F3928012DDA0DC /* Catchable.swift */ = {isa = PBXFileReference; path = Catchable.swift; sourceTree = ""; }; D32C35009D5CF449E0D419124474C625 /* Path->Bool.swift */ = {isa = PBXFileReference; path = "Path->Bool.swift"; sourceTree = ""; }; D39E04B4AC317B13678FFB83CE930458 /* Path+StringConvertibles.swift */ = {isa = PBXFileReference; path = "Path+StringConvertibles.swift"; sourceTree = ""; }; D719A91C09C4BD993022462D57904F4E /* z.etc.swift */ = {isa = PBXFileReference; path = z.etc.swift; sourceTree = ""; }; DCA174BA4C5F72220DACB263A133F3A1 /* modelize().swift */ = {isa = PBXFileReference; path = "modelize().swift"; sourceTree = ""; }; DD8483ADF0C01E41D32E3BEA6C2F50FF /* Workspace/XCWorkspaceDataGroup.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspaceDataGroup.swift; sourceTree = ""; }; DD9AB41547E4057E3F4F4398F9B8E294 /* Scheme/XCScheme+CommandLineArguments.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+CommandLineArguments.swift"; sourceTree = ""; }; DE8AEF64C23D070DC58781BE7913BE2C /* Path+Attributes.swift */ = {isa = PBXFileReference; path = "Path+Attributes.swift"; sourceTree = ""; }; DF0430C986F4136EE13A64A2653D32D9 /* Version.swift */ = {isa = PBXFileReference; path = Version.swift; sourceTree = ""; }; DF68BD1B8B7E31E3692084703149A9F4 /* Objects/Project/PBXObject.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXObject.swift; sourceTree = ""; }; E0917A3E0211FADCA757E973E033A8CE /* Extensions/String+Utils.swift */ = {isa = PBXFileReference; path = "Extensions/String+Utils.swift"; sourceTree = ""; }; E18FDE6CB448ECB4CA03C90F660EB53D /* Key.swift */ = {isa = PBXFileReference; path = Key.swift; sourceTree = ""; }; E32BB1D0A32744ECAA417C6154B85B6D /* Workspace/XCWorkspaceDataElement.swift */ = {isa = PBXFileReference; path = Workspace/XCWorkspaceDataElement.swift; sourceTree = ""; }; E5D258EA5994282BD85C7216EB317673 /* Group.swift */ = {isa = PBXFileReference; path = Group.swift; sourceTree = ""; }; E5FDDB74202F0211F67EAD9C489FA153 /* Objects/Files/PBXFileElement.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXFileElement.swift; sourceTree = ""; }; E682DCE6918902D7DDF557BBEE1F747C /* after.swift */ = {isa = PBXFileReference; path = after.swift; sourceTree = ""; }; E81FE693D4FBCAC3084891079AC322C9 /* Path+inreplace().swift */ = {isa = PBXFileReference; path = "Path+inreplace().swift"; sourceTree = ""; }; E9164B58D3D030AD7DD1D4633988ECCA /* Scheme/XCScheme+LaunchAction.swift */ = {isa = PBXFileReference; path = "Scheme/XCScheme+LaunchAction.swift"; sourceTree = ""; }; E94C0950C8BC14BB473DDD0C09FDEB12 /* Objects/Project/PBXObjectParser.swift */ = {isa = PBXFileReference; path = Objects/Project/PBXObjectParser.swift; sourceTree = ""; }; EA37F59BD9DAFFD0F15694AABCF3B54C /* Extensions.swift */ = {isa = PBXFileReference; path = Extensions.swift; sourceTree = ""; }; EA48C5FCF10729DBC5E19A78CD728387 /* Objects/BuildPhase/PBXCopyFilesBuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/PBXCopyFilesBuildPhase.swift; sourceTree = ""; }; EA500C91598D251A97067F063150DC2A /* Path+Codable.swift */ = {isa = PBXFileReference; path = "Path+Codable.swift"; sourceTree = ""; }; EB7A4900D64F8DD98FAE29B44BAC9C49 /* +functions.swift */ = {isa = PBXFileReference; path = "+functions.swift"; sourceTree = ""; }; F2FA622D9453DC325EF8DD4097AB2C2B /* when.swift */ = {isa = PBXFileReference; path = when.swift; sourceTree = ""; }; F487E1726D5CE70C1C4B0223DF5AFFDF /* Diff.swift */ = {isa = PBXFileReference; path = Diff.swift; sourceTree = ""; }; F6B09E05AFC6DA8F82260DFC1ABE4BDB /* Extensions/Path+Extras.swift */ = {isa = PBXFileReference; path = "Extensions/Path+Extras.swift"; sourceTree = ""; }; F87D5D97095DA0BD5E5541E880541B51 /* Extensions/KeyedDecodingContainer+Additions.swift */ = {isa = PBXFileReference; path = "Extensions/KeyedDecodingContainer+Additions.swift"; sourceTree = ""; }; F9CC5027FFDDFF68DBEF95C7EC0B2677 /* Project/XcodeProj.swift */ = {isa = PBXFileReference; path = Project/XcodeProj.swift; sourceTree = ""; }; F9CD3F23A3EB056C8061881D18FBD601 /* XcodeObserver.a */ = {isa = PBXFileReference; path = XcodeObserver.a; sourceTree = ""; }; FB0670D14B0D218E1BB9BE836B9392C7 /* Objects/BuildPhase/BuildPhase.swift */ = {isa = PBXFileReference; path = Objects/BuildPhase/BuildPhase.swift; sourceTree = ""; }; FB6EB63265EF5234402E15E3F05EE1C0 /* KeyCombo.swift */ = {isa = PBXFileReference; path = KeyCombo.swift; sourceTree = ""; }; FD0C6AC2F04C53C676703889CB39A3FA /* Objects/Files/PBXContainerItemProxy.swift */ = {isa = PBXFileReference; path = Objects/Files/PBXContainerItemProxy.swift; sourceTree = ""; }; FD62726177028C4BC3DCB2230AD84705 /* Version.a */ = {isa = PBXFileReference; path = Version.a; sourceTree = ""; }; FEC29E1DAC3B9B8D9CD1097C65196C1C /* Process+facade.swift */ = {isa = PBXFileReference; path = "Process+facade.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 0B026A614C2516F4FCE621E12A0C2BBD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 5633CA07142F6FC4A6C648E4C90225ED /* Batter.a in Frameworks */, 217FABB189F4D49A3DD1422949D0C8E8 /* Dependencies.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 110D4C6492AD4DAAB8F0701D634714CF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( A56DC1AF5566E19B4D632345C9866CCA /* xcodeproj.a in Frameworks */, BF795C7DC798F6DDEB96C936AAE3A38D /* PathKit.a in Frameworks */, A27CBDCEC8A2496D7214446F54EBCFFD /* OrderedSet.a in Frameworks */, 1D4E36D03223E04D12357D0E3E9E4F06 /* LegibleError.a in Frameworks */, 7114D9D184985B859F50ED13FE2C6FC7 /* HotKey.a in Frameworks */, B6DC0EF01401A3BED2CBBF306449424F /* AppUpdater.a in Frameworks */, B80D12E0404E0D4FE891853C54CC0298 /* Version.a in Frameworks */, 600AB0C92CD900012CA02DE69AB001B9 /* Path.a in Frameworks */, BD0BA7D75497180DD3012CA784CC7BCA /* PMKFoundation.a in Frameworks */, 15934D6E5683C82DBE917FB0A535918C /* PromiseKit.a in Frameworks */, D59C5DFA9636F14344F65784AC4AF22E /* AEXML.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; B48E25CDFE3DC639D59FCE85ECC280D9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 8B8A210C9BB8D8109AD1AC239AB9552F /* Kitchen.a in Frameworks */, 3E61D76C08BB1902E0D0D05A19835679 /* Processor.a in Frameworks */, 976C83FEFB06BCAD121AAEEE1C719482 /* XcakeProject.a in Frameworks */, 931B8B12E76BBFF3D918AD5F204D0FD6 /* XcodeProject.a in Frameworks */, DC560344DF4532BABE105E25771A2285 /* XcodeObserver.a in Frameworks */, B29D6314F9D634233005F3BB6C0BCF82 /* Modelizer.a in Frameworks */, 9809C7CF76A4546695F8874775FFC18B /* Base.a in Frameworks */, 57D07CE56DF2981508F693E48A3CFD54 /* CakefileDescription.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 0DEFA17E751F338E5C334A3E676D734E /* XcakeProject */ = { isa = PBXGroup; children = ( 52A4C823A8934B7C4408E5A47FF4FECB /* +functions.swift */, 8D3944D256EB9C28558C204F63F624B5 /* deintegrate().swift */, CDA44BF315E7E72F7AF8D8FFAB5D39F6 /* etc.swift */, 0EFD929CD18BA53DE82AB2B4BC7F03E3 /* scaffold().swift */, AF0DABA4951DF1D4D2F4308EA9757D27 /* XcakeProject.swift */, ); name = XcakeProject; path = Base/XcodeProject/XcakeProject; sourceTree = ""; }; 11E4BAB2730301EFC996AE1C090EA04E /* mxcl/Path.swift-0.16.1 */ = { isa = PBXGroup; children = ( EA37F59BD9DAFFD0F15694AABCF3B54C /* Extensions.swift */, D32C35009D5CF449E0D419124474C625 /* Path->Bool.swift */, 25F48703B70EEA7E7DCC6D2D2F06C9B8 /* Path.swift */, DE8AEF64C23D070DC58781BE7913BE2C /* Path+Attributes.swift */, EA500C91598D251A97067F063150DC2A /* Path+Codable.swift */, 94BE46F8140D74E37611092ADBEB53BE /* Path+CommonDirectories.swift */, A77AFC4AE522827E286DEA7B38C2C006 /* Path+FileManager.swift */, 9EC126C205BC396E4B52986041911E1A /* Path+ls.swift */, D39E04B4AC317B13678FFB83CE930458 /* Path+StringConvertibles.swift */, ); name = "mxcl/Path.swift-0.16.1"; path = "mxcl∕Path.swift-0.16.1"; sourceTree = ""; }; 16D9CDF666A9E6EE114E86B1D728EB67 /* XcodeProject */ = { isa = PBXGroup; children = ( AAB66A0A047C8351A0114D24BF9C84D4 /* _PathDisambiguation.swift */, AB353A7BFBF179F59387515435E68F1B /* *Target.swift */, EB7A4900D64F8DD98FAE29B44BAC9C49 /* +functions.swift */, 618FDE59E88C49B7C9ADE5C5A9159A06 /* +platforms.swift */, E5D258EA5994282BD85C7216EB317673 /* Group.swift */, B014E5511BA57DD4C34DEC96713FCC0F /* XcodeProject.swift */, D719A91C09C4BD993022462D57904F4E /* z.etc.swift */, BE28E6555AA9082953164CAB96DC7EAA /* z+buildSettings.swift */, ); name = XcodeProject; path = Base/XcodeProject; sourceTree = ""; }; 1717C67F49587A83891553ABA9B0E3CD /* Kitchenware */ = { isa = PBXGroup; children = ( 05D33FD3DDE7FE2483580EF428D7DE21 /* Batter.swift */, CD06ECAE4D53F31C5FF63EB1A4FAA0F1 /* Dependencies.swift */, 43F867ED701FF56BC9AA1829B4888F2F /* Cake.swift */, ); name = Kitchenware; path = ""; sourceTree = ""; }; 190054F2AD8B53FAE15AE8A14391B137 /* mxcl/PromiseKit-6.8.3 */ = { isa = PBXGroup; children = ( E682DCE6918902D7DDF557BBEE1F747C /* after.swift */, 3D70A7A1D451A574394BE9D849EF26BD /* Box.swift */, D0FDA939D602AC0EF1F3928012DDA0DC /* Catchable.swift */, 53C5D7D1835891126DAC0217D2976BB3 /* Configuration.swift */, 30BDDCCB89500DCBDD7BBA0272926DD0 /* CustomStringConvertible.swift */, 97EAFD505287A688648A6F468128EEEC /* Error.swift */, 1C473431F71F14C0C7B094C7AFC1BCB1 /* firstly.swift */, CF647C9C376ED858DE3D33BD092CCA7F /* Guarantee.swift */, B7AEA2479B3032443714E1D228FADF0C /* hang.swift */, 9D25EA9B892F8852C3D86F85B8647FAE /* LogEvent.swift */, 9667E7EC96A4E5AF6C72D9DDD7ACC033 /* Promise.swift */, 41AA2ABCDA2F333EBC153257903CCFFA /* race.swift */, 36F4FC690CAF8E887E4358E57F7AFBC1 /* Resolver.swift */, C217681598D56FE79A522A8D0D7CB7C7 /* Thenable.swift */, F2FA622D9453DC325EF8DD4097AB2C2B /* when.swift */, ); name = "mxcl/PromiseKit-6.8.3"; path = "mxcl∕PromiseKit-6.8.3"; sourceTree = ""; }; 1C4FCF6098FC3226B2546E8140B7A700 /* Products */ = { isa = PBXGroup; children = ( B3CDEF324226D91C75D2BCBA3E3D7952 /* Cakefile·Completion */, 0E05502AA06041ADF62F3BF7E7659260 /* xcodeproj.a */, 3C29E76D627B188CA3643C87B68EC436 /* PathKit.a */, 2C62C6619223819ED3301991617A91BD /* OrderedSet.a */, 1DBCAEFF3AB28195D7B5E09B52FDBDA9 /* LegibleError.a */, 4F2CA03F28361DA2CD3C82B19DE28C91 /* HotKey.a */, 19F01C205BDC9FA3129D8949BE2CB5C4 /* AppUpdater.a */, FD62726177028C4BC3DCB2230AD84705 /* Version.a */, A49E0E264A02682CCE9A823B02A46706 /* Path.a */, 69787F8145CACFA492EC131CC2A0AA1D /* PMKFoundation.a */, 53E3B23BDD8E313D1CCE46BCBA847860 /* PromiseKit.a */, 3FA20E1A308B36BD34D4F6FA38D3BF30 /* AEXML.a */, 4A7E89000FDF44A3427FBD44B878A9C1 /* Dependencies.a */, BF52CA51D11D9A90EF84861A2B5938B1 /* Kitchen.a */, C5744C074FEF959972A62160544D24F0 /* Processor.a */, 7F8732C7CBD899BD5F0398A832669E75 /* XcakeProject.a */, 937C922F7F6999DF1895EB3DC82906E9 /* XcodeProject.a */, F9CD3F23A3EB056C8061881D18FBD601 /* XcodeObserver.a */, BAD9493581EF0180B01D541DF06A6E4B /* Modelizer.a */, 372DAB40CDD5A8EEE06A79D6C8AC5536 /* Base.a */, 11D3B38D3F7DA37A8300F924107470ED /* CakefileDescription.a */, 3F573D976FA9A0403F17F22F1A4DAA55 /* Batter.a */, A4B1E5C1B830E94800A96F72DE371A05 /* Cake.a */, ); name = Products; sourceTree = ""; }; 2B096CC3B26D21065DBBCC42279425A7 /* Kitchen */ = { isa = PBXGroup; children = ( CEE016ECFF05687BA82A5550BE83957F /* CakeProject.swift */, 46348EB9B861968F7D43E2F325955D37 /* FSWatcher.swift */, 3142C0085C1236B2B3772F4960DBB8D9 /* Kitchen.swift */, C89B0D3A65F18AC6AE103808E1EF9054 /* KitchenDelegate.swift */, ); name = Kitchen; path = Base/XcodeProject/XcakeProject/Processor/Kitchen; sourceTree = ""; }; 2D9C8EE4960B9A8646E9915D1E8E527F /* PromiseKit/Foundation-3.3.1 */ = { isa = PBXGroup; children = ( AA87092A5BDAB632904A61E928DE49B9 /* afterlife.swift */, 7E32B9B4F0137DD729D7F3D74688CF6D /* NSNotificationCenter+Promise.swift */, 38AC374D097346CE8B4226D78BA0156F /* NSObject+Promise.swift */, A365FC1A53413924C32E4651E9D67AA9 /* NSURLSession+Promise.swift */, 1F0D8DD1958D7B1AF9E5930838B61C63 /* Process+Promise.swift */, ); name = "PromiseKit/Foundation-3.3.1"; path = "PromiseKit∕Foundation-3.3.1"; sourceTree = ""; }; 4E61B53DB50DF6EB8EA193F7CFCB3EF8 /* Modelizer */ = { isa = PBXGroup; children = ( 902419C27FD761BCEFE0A9AB8BF4FE87 /* Dependencies.json.swift */, DCA174BA4C5F72220DACB263A133F3A1 /* modelize().swift */, 2A565382D53C145048B6FC0422270BC1 /* Module.swift */, ); name = Modelizer; path = Base/Modelizer; sourceTree = ""; }; 50DCC4186C454A8A35C359EBE7E6484B /* */ = { isa = PBXGroup; children = ( 9DD6BC9A2C80C818AD36364182F42223 /* Cakefile.swift */, FF9225349CD1E19735206C8679F1CCA6 /* Dependencies */, A954EB6899ABE9AAB9499DFC4B34F9A5 /* Batter */, 1717C67F49587A83891553ABA9B0E3CD /* Kitchenware */, 1C4FCF6098FC3226B2546E8140B7A700 /* Products */, ); path = ""; sourceTree = SOURCE_ROOT; }; 6939D6F5712F4440359CFEF39DD7D5AA /* tadija/AEXML-4.3.3 */ = { isa = PBXGroup; children = ( 48324EC36DFA0B91BEB4A8CF50E6133F /* Document.swift */, 5DA0BC07DF161138B4D7A43E6A219B05 /* Element.swift */, 835E3CF62D03CBDD1679F357A3702A9C /* Error.swift */, 7E28C010F6CDF44DDB15986B219FCDB2 /* Options.swift */, B828EC0B6BCB9E838EF8719A040E05FB /* Parser.swift */, ); name = "tadija/AEXML-4.3.3"; path = "tadija∕AEXML-4.3.3"; sourceTree = ""; }; 7201B1D348675238ED3B979060D4330C /* Processor */ = { isa = PBXGroup; children = ( CAF60D50AF8D2A0115E908C973003A12 /* Cakefile.swift */, 858CCCCD45F434A16E8D273190765092 /* Dependencies.swift */, 0C15151125E344471378CB5346737FA7 /* etc.swift */, 63FED00F5F6CA5AA95D6FD33264CC27E /* Self.swift */, 6FDDFD13C38B75004170652473061F3A /* SwiftVersion.swift */, A7C16154EA6E8025D3F05AC2433A61BE /* TemporaryDirectory.swift */, ); name = Processor; path = Base/XcodeProject/XcakeProject/Processor; sourceTree = ""; }; A954EB6899ABE9AAB9499DFC4B34F9A5 /* Batter */ = { isa = PBXGroup; children = ( 2B096CC3B26D21065DBBCC42279425A7 /* Kitchen */, 7201B1D348675238ED3B979060D4330C /* Processor */, 0DEFA17E751F338E5C334A3E676D734E /* XcakeProject */, 16D9CDF666A9E6EE114E86B1D728EB67 /* XcodeProject */, D4CCC802C372135B66030BC32FFBAB2E /* XcodeObserver */, 4E61B53DB50DF6EB8EA193F7CFCB3EF8 /* Modelizer */, FFD2E5EF8107E15A82A521FDB473524F /* Base */, E2FEFEF0660D278EDD39D2DE868810FF /* CakefileDescription */, ); name = Batter; path = ../Sources/Model; sourceTree = ""; }; C7D91F2BBBEF05D5A7E012382449D80C /* soffes/HotKey-0.1.1 */ = { isa = PBXGroup; children = ( 3A81CC9DD3104D5CFAB0E095D7A73FDE /* HotKey.swift */, 293B693F5D2B905EAB9D47603FF004E0 /* HotKeysController.swift */, E18FDE6CB448ECB4CA03C90F660EB53D /* Key.swift */, FB6EB63265EF5234402E15E3F05EE1C0 /* KeyCombo.swift */, 7A124F661FEA3E444A56EA4D521A515A /* NSEventModifierFlags+HotKey.swift */, ); name = "soffes/HotKey-0.1.1"; path = "soffes∕HotKey-0.1.1"; sourceTree = ""; }; D4CCC802C372135B66030BC32FFBAB2E /* XcodeObserver */ = { isa = PBXGroup; children = ( F487E1726D5CE70C1C4B0223DF5AFFDF /* Diff.swift */, A6A3C3E306641683ED6A2DEA9A9CEDFA /* XcodeObserver.swift */, 278A53C448758EECE7FD6B78133E40C8 /* XcodeScriptingBridge.swift */, ); name = XcodeObserver; path = Base/XcodeObserver; sourceTree = ""; }; E2FEFEF0660D278EDD39D2DE868810FF /* CakefileDescription */ = { isa = PBXGroup; children = ( A931901826EAFC85E24FC30A1708944E /* CakefileDescription.swift */, 930A6BD4B016A2539E9D5013E3FCA04A /* Version+.swift */, ); name = CakefileDescription; path = CakefileDescription; sourceTree = ""; }; E5CE8DDF1C7AE826DA871BE9AD9AC15F /* tuist/xcodeproj-6.6.0 */ = { isa = PBXGroup; children = ( 1426181F4046DE0C27F56E6BD5910905 /* Errors/Errors.swift */, 06BD24A5E56306FA76A42CE38A938E0C /* Extensions/AEXML+XcodeFormat.swift */, B1529B0E38393D8746B29EC816E6FBD3 /* Extensions/Bool+Extras.swift */, 8DB463DC57B0C69C11B869C0D1D1CE34 /* Extensions/Dictionary+Enumerate.swift */, 023860B7D6084F6464BEA7B2304B2114 /* Extensions/Dictionary+Extras.swift */, F87D5D97095DA0BD5E5541E880541B51 /* Extensions/KeyedDecodingContainer+Additions.swift */, 308336D6CA83EAE1E8D36F4DE09DE65E /* Extensions/NSRecursiveLock+Sync.swift */, 29EB733203A51041BAF8B7325873B8F8 /* Extensions/OSLog+Extras.swift */, F6B09E05AFC6DA8F82260DFC1ABE4BDB /* Extensions/Path+Extras.swift */, 64ED4F4E164410F7A62B935BAC757997 /* Extensions/String+md5.swift */, E0917A3E0211FADCA757E973E033A8CE /* Extensions/String+Utils.swift */, FB0670D14B0D218E1BB9BE836B9392C7 /* Objects/BuildPhase/BuildPhase.swift */, C21B018E286AB818EEF5EA83B02C86E0 /* Objects/BuildPhase/PBXBuildFile.swift */, 531404CEBE08B993CDAD51AF95383C04 /* Objects/BuildPhase/PBXBuildPhase.swift */, 1FFC5A15BE7FEEA7952C65C2124CDB1C /* Objects/BuildPhase/PBXBuildRule.swift */, EA48C5FCF10729DBC5E19A78CD728387 /* Objects/BuildPhase/PBXCopyFilesBuildPhase.swift */, 8E74C31BCB0D74EF97C4278031E8034D /* Objects/BuildPhase/PBXFrameworksBuildPhase.swift */, 435DE35726152C660A49F9A23B51B7E3 /* Objects/BuildPhase/PBXHeadersBuildPhase.swift */, 2B1F1175C209C392F423782054651ED5 /* Objects/BuildPhase/PBXResourcesBuildPhase.swift */, 835B1909D4EA60D2CF046ED021E060E7 /* Objects/BuildPhase/PBXRezBuildPhase.swift */, 852615CA271D363F36FCE47BCF0265AD /* Objects/BuildPhase/PBXShellScriptBuildPhase.swift */, 830FE1BA33BC05A8FF3C2ED99884F684 /* Objects/BuildPhase/PBXSourcesBuildPhase.swift */, 3875F50A4E88DECD4C85498B13194B4D /* Objects/Configuration/BuildSettings.swift */, 7713E4DEB1439F6B933AD7032A4CB4A4 /* Objects/Configuration/XCBuildConfiguration.swift */, 31C617BEA32F179B393AF1D212E944A9 /* Objects/Configuration/XCConfigurationList.swift */, 8D719F3BC31505ACB101E7D6737CE1E5 /* Objects/Files/PBXContainerItem.swift */, FD0C6AC2F04C53C676703889CB39A3FA /* Objects/Files/PBXContainerItemProxy.swift */, E5FDDB74202F0211F67EAD9C489FA153 /* Objects/Files/PBXFileElement.swift */, 85B557836B8BE6B8B5590ABD761653BA /* Objects/Files/PBXFileReference.swift */, 71B38B8ED5DB9DCC0B70E3CC1E44402A /* Objects/Files/PBXGroup.swift */, 2B70D9747ECEC5C6AC9E6368CFB36889 /* Objects/Files/PBXSourceTree.swift */, 410CE76CF11E01AD634AF853AB480845 /* Objects/Files/PBXVariantGroup.swift */, B09953A76D3C953D379A46546E39FC8D /* Objects/Files/XCVersionGroup.swift */, DF68BD1B8B7E31E3692084703149A9F4 /* Objects/Project/PBXObject.swift */, E94C0950C8BC14BB473DDD0C09FDEB12 /* Objects/Project/PBXObjectParser.swift */, 91D674DA388038DB2C7C2DCC6B13CA11 /* Objects/Project/PBXObjectReference.swift */, 722A12F4645B5D35D39B45AFA1D76983 /* Objects/Project/PBXObjects.swift */, B14C812ADA5BF5033A67333BAF077A7A /* Objects/Project/PBXOutputSettings.swift */, 87FA10E492A0664C5F376C3AADA117AB /* Objects/Project/PBXProj.swift */, 559797E564267A36E62DE4ADF60465B7 /* Objects/Project/PBXProject.swift */, A50CE25F21E57E92B7A610699FA83BC1 /* Objects/Project/PBXProjEncoder.swift */, 675FB47A04E79CDCC955D8FCF3A4BF80 /* Objects/Sourcery/Equality.generated.swift */, 40B08A9630C2EF6944BF3EE3F4CD8A04 /* Objects/Sourcery/Sourcery.swift */, 76149DDC4F8A2B10AC9F40DC12C04A01 /* Objects/Targets/PBXAggregateTarget.swift */, 8581BD4238C94C7B078D7E65968660C0 /* Objects/Targets/PBXLegacyTarget.swift */, 7D3C314B487A12D0E1C0D029FE36371D /* Objects/Targets/PBXNativeTarget.swift */, 2BE47230D3E16F17B6C53D4CD9ABF0A7 /* Objects/Targets/PBXProductType.swift */, 31102E62D8DBA38978DFFDA3A5FF6AD9 /* Objects/Targets/PBXReferenceProxy.swift */, 1AF5A7DF8CE28184F27C6599C742AC25 /* Objects/Targets/PBXTarget.swift */, BB42F45DDB75F843BD744639C008C84B /* Objects/Targets/PBXTargetDependency.swift */, 7A946331648AD8B89896F7F8669B8E51 /* Project/WorkspaceSettings.swift */, B41FF1790C8AA4E84A29A33DAE05468B /* Project/XCBreakpointList.swift */, 4B89F8E5109BA12DC10ED95129E77944 /* Project/Xcode.swift */, F9CC5027FFDDFF68DBEF95C7EC0B2677 /* Project/XcodeProj.swift */, 3C408218005B7BC75A3ABD08133612D9 /* Project/XCSharedData.swift */, 381C3BC031CA52785EC98BBE0F7D2F6F /* Protocols/Writable.swift */, 9DB38989A054A4EA67BEB37294BFDC38 /* Scheme/XCScheme.swift */, 80158EAEB4E68B546727248C48EF0F17 /* Scheme/XCScheme+AditionalOption.swift */, 2274AC91D7F94448E0AF2969D9BCDA58 /* Scheme/XCScheme+AnalyzeAction.swift */, 49E819CC92D95188B91ABBEDA33B46C3 /* Scheme/XCScheme+ArchiveAction.swift */, 7C8796C21F96CBC0C0A4E13733B4CD0E /* Scheme/XCScheme+BuildableProductRunnable.swift */, 9DCF2ACDC813D1597DCDDFE3EA904191 /* Scheme/XCScheme+BuildableReference.swift */, 0E3AD59FD7C82A5F84B7C248687AB331 /* Scheme/XCScheme+BuildAction.swift */, DD9AB41547E4057E3F4F4398F9B8E294 /* Scheme/XCScheme+CommandLineArguments.swift */, 0B6CC87C2DDD9FDBA1C2CBD27071D4AC /* Scheme/XCScheme+EnvironmentVariable.swift */, 576C9C9EE9D61D301635A94562588667 /* Scheme/XCScheme+ExecutionAction.swift */, E9164B58D3D030AD7DD1D4633988ECCA /* Scheme/XCScheme+LaunchAction.swift */, 76C9275C1BF293F18BCC5970643036F9 /* Scheme/XCScheme+LocationScenarioReference.swift */, 3185556D97EDCF571118B9C60F3D4DCB /* Scheme/XCScheme+ProfileAction.swift */, A909F2285D6BB302E831CD131B206FB1 /* Scheme/XCScheme+SerialAction.swift */, 57A5610558926A1003CFFD244AA5DA23 /* Scheme/XCScheme+SkippedTests.swift */, 43DB4EE450B414ECE6DEDAAB4F40019D /* Scheme/XCScheme+TestableReference.swift */, A7784500AEAF00A3954F252BF7EB9186 /* Scheme/XCScheme+TestAction.swift */, 01B73C1D9BBF582F1B4CA11D1FD2BCD5 /* Utils/BuildSettingsProvider.swift */, 4CD7DF2A21452F6F3764E31A50E68AF2 /* Utils/CommentedString.swift */, 9A4F661909381C2B72260EC5E92EB852 /* Utils/Decoders.swift */, 3D18DB9B60F9CAE6DB1EE58AA5CDCA1C /* Utils/JSONDecoding.swift */, 04110D4A7CD13051C705542C94A0A7A9 /* Utils/OSLogger.swift */, 1B52A49D89C35234D21902B915BB0DB7 /* Utils/PlistValue.swift */, 1C0E03F6E6EECCE50817B52C201AEAA4 /* Utils/ReferenceGenerator.swift */, CB67A28ADBD062CE337B8DF5E1ABA3B4 /* Utils/XCConfig.swift */, B30144F1A4CC788F25022BF92EA083F6 /* Workspace/XCWorkspace.swift */, 755B5AE0CCEBAD76024C7BACFD3769CF /* Workspace/XCWorkspaceData.swift */, E32BB1D0A32744ECAA417C6154B85B6D /* Workspace/XCWorkspaceDataElement.swift */, 669A914005810A46DA64A779CE45E521 /* Workspace/XCWorkspaceDataElementLocationType.swift */, 949BF795030FD942ABF42746C69282A2 /* Workspace/XCWorkspaceDataFileRef.swift */, DD8483ADF0C01E41D32E3BEA6C2F50FF /* Workspace/XCWorkspaceDataGroup.swift */, ); name = "tuist/xcodeproj-6.6.0"; path = "tuist∕xcodeproj-6.6.0"; sourceTree = ""; }; FF166AA65D3F9C011EA163E87B9A8DCE /* mxcl/Version-1.0.3 */ = { isa = PBXGroup; children = ( DF0430C986F4136EE13A64A2653D32D9 /* Version.swift */, 40CA625F76FE45EABC6548E7FA9081C9 /* Version+Codable.swift */, 0EB24F5AA5F9F47F5FE894B8910CCD3F /* Version+Comparable.swift */, 6F32012741B387F7AD9EB83C1E2AF212 /* Version+Foundation.swift */, 6A6EF02B86E86BA90A2AD45729B1EA6A /* Version+Range.swift */, ); name = "mxcl/Version-1.0.3"; path = "mxcl∕Version-1.0.3"; sourceTree = ""; }; FF9225349CD1E19735206C8679F1CCA6 /* Dependencies */ = { isa = PBXGroup; children = ( E5CE8DDF1C7AE826DA871BE9AD9AC15F /* tuist/xcodeproj-6.6.0 */, 8936109BF1AA3578412FAD3077209014 /* kylef∕PathKit-0.9.2.swift */, B1F70701A65B3979718758A9C96B7E74 /* Weebly∕OrderedSet-3.1.0.swift */, 4144D0D13AB2A191101B99B2DEDE581C /* mxcl∕LegibleError-1.0.1.swift */, C7D91F2BBBEF05D5A7E012382449D80C /* soffes/HotKey-0.1.1 */, 3EACC5F861EC78E815F715FE0D7F0DB8 /* mxcl∕AppUpdater-1.0.3.swift */, FF166AA65D3F9C011EA163E87B9A8DCE /* mxcl/Version-1.0.3 */, 11E4BAB2730301EFC996AE1C090EA04E /* mxcl/Path.swift-0.16.1 */, 2D9C8EE4960B9A8646E9915D1E8E527F /* PromiseKit/Foundation-3.3.1 */, 190054F2AD8B53FAE15AE8A14391B137 /* mxcl/PromiseKit-6.8.3 */, 6939D6F5712F4440359CFEF39DD7D5AA /* tadija/AEXML-4.3.3 */, ); name = Dependencies; path = ../Dependencies; sourceTree = ""; }; FFD2E5EF8107E15A82A521FDB473524F /* Base */ = { isa = PBXGroup; children = ( E81FE693D4FBCAC3084891079AC322C9 /* Path+inreplace().swift */, FEC29E1DAC3B9B8D9CD1097C65196C1C /* Process+facade.swift */, 804B783359D6CCE7145742C88183EA36 /* Sequence+KeyPath.swift */, 05103104AE592402CB93C1FFE5E2D1CD /* StreamReader.swift */, 72C3939CC65CE41D34872BE7C25A01C5 /* SwiftVersion.swift */, 749A8E67AC5834C6A956EAADEB64557B /* topologicalSort().swift */, ); name = Base; path = Base; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 0F64CBB97351A503B1F408F40AB7E996 /* Batter·Kitchen */ = { isa = PBXNativeTarget; buildConfigurationList = 75705B7E4DE90E787B5587BB39A9C36B /* Build configuration list for PBXNativeTarget "Batter·Kitchen" */; buildPhases = ( A9A4A9984792079405DBB34A1D20B75B /* Sources */, ); buildRules = ( ); dependencies = ( 86F70278902535F201592D638128287A /* PBXTargetDependency */, ); name = "Batter·Kitchen"; productName = Kitchen; productReference = BF52CA51D11D9A90EF84861A2B5938B1 /* Kitchen.a */; productType = "com.apple.product-type.library.static"; }; 50A4D32099C32D3207892A9614D37B66 /* Batter·Processor */ = { isa = PBXNativeTarget; buildConfigurationList = 7081C02CA5D1323B9B25721C60922C92 /* Build configuration list for PBXNativeTarget "Batter·Processor" */; buildPhases = ( 3BD3E2AB91B7EC4954112ECB41545554 /* Sources */, ); buildRules = ( ); dependencies = ( FCE6F711BDA27F1587A676EA4E1A223E /* PBXTargetDependency */, ); name = "Batter·Processor"; productName = Processor; productReference = C5744C074FEF959972A62160544D24F0 /* Processor.a */; productType = "com.apple.product-type.library.static"; }; 5D1C4ECF6D5347A44CB1E59E5BB558E0 /* Deps·AppUpdater */ = { isa = PBXNativeTarget; buildConfigurationList = 1CB785113119F8BC5FF59CA4741AA37B /* Build configuration list for PBXNativeTarget "Deps·AppUpdater" */; buildPhases = ( 01DD71F8D6077C0F16AA033CB312695C /* Sources */, ); buildRules = ( ); dependencies = ( DE622C7A094011A28248907BDAFD9AD7 /* PBXTargetDependency */, C2464976BABCABAA3A72863AE3E78F30 /* PBXTargetDependency */, 47F528038C3330D21B21869C0B0FB0A9 /* PBXTargetDependency */, ); name = "Deps·AppUpdater"; productName = AppUpdater; productReference = 19F01C205BDC9FA3129D8949BE2CB5C4 /* AppUpdater.a */; productType = "com.apple.product-type.library.static"; }; 76CCBFA038A347F71E7B5BFB1521AC8A /* Deps·Path */ = { isa = PBXNativeTarget; buildConfigurationList = F96FF9FDA0DC746E15BB01A0E5531883 /* Build configuration list for PBXNativeTarget "Deps·Path" */; buildPhases = ( 9E7097A7C3D241A0B2CCA4D3B78A8A83 /* Sources */, ); buildRules = ( ); dependencies = ( B05A9D037029AAFBD5DCAD6ECBF89F09 /* PBXTargetDependency */, ); name = "Deps·Path"; productName = Path; productReference = A49E0E264A02682CCE9A823B02A46706 /* Path.a */; productType = "com.apple.product-type.library.static"; }; 8B4D032D3EA2708E1BF1B498E5AAC085 /* Deps·LegibleError */ = { isa = PBXNativeTarget; buildConfigurationList = 5375538FF4A3E415410EE0F07030C0A4 /* Build configuration list for PBXNativeTarget "Deps·LegibleError" */; buildPhases = ( 0D2313C56B49445FFFBAFA66F386B894 /* Sources */, ); buildRules = ( ); dependencies = ( FDED9CB4A42F8E451B9CD92A9214BED0 /* PBXTargetDependency */, ); name = "Deps·LegibleError"; productName = LegibleError; productReference = 1DBCAEFF3AB28195D7B5E09B52FDBDA9 /* LegibleError.a */; productType = "com.apple.product-type.library.static"; }; 8B942976617019A6C464818315598CC1 /* Cake */ = { isa = PBXNativeTarget; buildPhases = ( 9D57241684611D5226E52EBD3A97727C /* Sources */, 0B026A614C2516F4FCE621E12A0C2BBD /* Frameworks */, ); buildRules = ( ); dependencies = ( CB56305824BFCA6B67740F6043A4B9E2 /* PBXTargetDependency */, 3366830391752771A1D8AFE2C77B8DC4 /* PBXTargetDependency */, 6F2865C025F7F740FF65DBD4991157C8 /* PBXTargetDependency */, ); name = Cake; productReference = A4B1E5C1B830E94800A96F72DE371A05 /* Cake.a */; productType = "com.apple.product-type.library.static"; }; 8FEBB13B61D6321603EC90A5606F8C4F /* Deps·HotKey */ = { isa = PBXNativeTarget; buildConfigurationList = 525C58D15460DD55EAC5A3285814107D /* Build configuration list for PBXNativeTarget "Deps·HotKey" */; buildPhases = ( 61C5A1E04CE0BF1806F68D0A00D9CA69 /* Sources */, ); buildRules = ( ); dependencies = ( A6D31631D95C3A51C9FAABBAA253F1D7 /* PBXTargetDependency */, ); name = "Deps·HotKey"; productName = HotKey; productReference = 4F2CA03F28361DA2CD3C82B19DE28C91 /* HotKey.a */; productType = "com.apple.product-type.library.static"; }; 9CF1FA8024CC8159DE776A7595DC3523 /* Deps·Version */ = { isa = PBXNativeTarget; buildConfigurationList = B372C3FDAB1008B4B28D830E0B8DF1A9 /* Build configuration list for PBXNativeTarget "Deps·Version" */; buildPhases = ( E2BAB0B95B059BB004904ECA59F68448 /* Sources */, ); buildRules = ( ); dependencies = ( 8FE2AD32E33987A961C4396477BA6D4D /* PBXTargetDependency */, ); name = "Deps·Version"; productName = Version; productReference = FD62726177028C4BC3DCB2230AD84705 /* Version.a */; productType = "com.apple.product-type.library.static"; }; A49235A78CF83BF260878E68B866C986 /* Batter·Base */ = { isa = PBXNativeTarget; buildConfigurationList = 54C3D682088F52A98460F95C69B3AB03 /* Build configuration list for PBXNativeTarget "Batter·Base" */; buildPhases = ( 89F171C5C55F88CECBB4D9F919595B44 /* Sources */, ); buildRules = ( ); dependencies = ( C94339126C714AD460BE58DB6BE8A056 /* PBXTargetDependency */, ); name = "Batter·Base"; productName = Base; productReference = 372DAB40CDD5A8EEE06A79D6C8AC5536 /* Base.a */; productType = "com.apple.product-type.library.static"; }; AC6B4791DEE2977626A076B8F9A7666F /* Deps·OrderedSet */ = { isa = PBXNativeTarget; buildConfigurationList = 12501F7CC58BB1124BB427E6ACE8AAFD /* Build configuration list for PBXNativeTarget "Deps·OrderedSet" */; buildPhases = ( A51B210879B02EBF2327F37032BF81B3 /* Sources */, ); buildRules = ( ); dependencies = ( 0565BAB4E438C2EA664F8C83EB0CE946 /* PBXTargetDependency */, ); name = "Deps·OrderedSet"; productName = OrderedSet; productReference = 2C62C6619223819ED3301991617A91BD /* OrderedSet.a */; productType = "com.apple.product-type.library.static"; }; B03189C2563DE1C075659DC03EF81210 /* Cakefile·Completion */ = { isa = PBXNativeTarget; buildConfigurationList = 3A3934967D7790F017425C98A64CD375 /* Build configuration list for PBXNativeTarget "Cakefile·Completion" */; buildPhases = ( A55DDFC1E192780D65C32457CB5F07F8 /* Sources */, ); buildRules = ( ); dependencies = ( ); name = "Cakefile·Completion"; productReference = B3CDEF324226D91C75D2BCBA3E3D7952 /* Cakefile·Completion */; productType = "com.apple.product-type.tool"; }; B4280F358AD4C3799414724EE00E6812 /* Deps·PMKFoundation */ = { isa = PBXNativeTarget; buildConfigurationList = D6F76942AA26F8FE33C0B9E559F048A3 /* Build configuration list for PBXNativeTarget "Deps·PMKFoundation" */; buildPhases = ( DD25F76D9BF91196996408AAA2D08CA6 /* Sources */, ); buildRules = ( ); dependencies = ( C92758E700B37ED68776342F73765D28 /* PBXTargetDependency */, ); name = "Deps·PMKFoundation"; productName = PMKFoundation; productReference = 69787F8145CACFA492EC131CC2A0AA1D /* PMKFoundation.a */; productType = "com.apple.product-type.library.static"; }; B49CC989FC5BE99773DFD32B46D8E82C /* Deps·PathKit */ = { isa = PBXNativeTarget; buildConfigurationList = DC551BFA9E078B27003D39F40946DE59 /* Build configuration list for PBXNativeTarget "Deps·PathKit" */; buildPhases = ( DCA5BDE643D482824931150E443818EA /* Sources */, ); buildRules = ( ); dependencies = ( 478D6FA01AC7470AE22A47A14BB76D0E /* PBXTargetDependency */, ); name = "Deps·PathKit"; productName = PathKit; productReference = 3C29E76D627B188CA3643C87B68EC436 /* PathKit.a */; productType = "com.apple.product-type.library.static"; }; B4EB89E549B6ADCED02958295D4FAD21 /* Deps·xcodeproj */ = { isa = PBXNativeTarget; buildConfigurationList = 06F4E05BD565282710B442AE5EA794B4 /* Build configuration list for PBXNativeTarget "Deps·xcodeproj" */; buildPhases = ( 6EA74799AC8908A90D1133CF4872622D /* Sources */, ); buildRules = ( ); dependencies = ( 52375388D4F28520E6EDF71CF9157BD9 /* PBXTargetDependency */, C705D93D65D5402E574821CB2982B55B /* PBXTargetDependency */, ); name = "Deps·xcodeproj"; productName = xcodeproj; productReference = 0E05502AA06041ADF62F3BF7E7659260 /* xcodeproj.a */; productType = "com.apple.product-type.library.static"; }; BD398413C05B07BBE2B6E2D14C9EE8D9 /* Deps·PromiseKit */ = { isa = PBXNativeTarget; buildConfigurationList = B961BFD93B1016266AB52B4C43632B1C /* Build configuration list for PBXNativeTarget "Deps·PromiseKit" */; buildPhases = ( 0330731A9D0FB38F456E61DB3932B0FF /* Sources */, ); buildRules = ( ); dependencies = ( 327C41C1F24B05BA591F163701AC5FFD /* PBXTargetDependency */, ); name = "Deps·PromiseKit"; productName = PromiseKit; productReference = 53E3B23BDD8E313D1CCE46BCBA847860 /* PromiseKit.a */; productType = "com.apple.product-type.library.static"; }; C1038750BB9B8EA5926C885645506714 /* Batter·XcodeObserver */ = { isa = PBXNativeTarget; buildConfigurationList = B12860ED6D40D093F21670917F129409 /* Build configuration list for PBXNativeTarget "Batter·XcodeObserver" */; buildPhases = ( E73EE8C4A3772E20E3C2F0C8C36A37E8 /* Sources */, ); buildRules = ( ); dependencies = ( 9872C58C32FAF03ACEC329FFD2C13162 /* PBXTargetDependency */, B9568118D2B144E528AFACC9A3063C8F /* PBXTargetDependency */, ); name = "Batter·XcodeObserver"; productName = XcodeObserver; productReference = F9CD3F23A3EB056C8061881D18FBD601 /* XcodeObserver.a */; productType = "com.apple.product-type.library.static"; }; C8AC307C08B1141701DFEAAD12667716 /* Batter·Modelizer */ = { isa = PBXNativeTarget; buildConfigurationList = AE6ECBCB9E2BBD1C00E2B864AB33FCFE /* Build configuration list for PBXNativeTarget "Batter·Modelizer" */; buildPhases = ( E5782A25D53239D7365C8040FEACD39D /* Sources */, ); buildRules = ( ); dependencies = ( 7B00EE4575A017E6BDDA5BFB0B5D5383 /* PBXTargetDependency */, 315AE0B2F6C88E934BB5814FD47A2FB0 /* PBXTargetDependency */, ); name = "Batter·Modelizer"; productName = Modelizer; productReference = BAD9493581EF0180B01D541DF06A6E4B /* Modelizer.a */; productType = "com.apple.product-type.library.static"; }; D1CE66C2AF312DCD9A12B6444FB0D2EA /* Deps·AEXML */ = { isa = PBXNativeTarget; buildConfigurationList = F77D98629B64E24B6FFAE21718CA106B /* Build configuration list for PBXNativeTarget "Deps·AEXML" */; buildPhases = ( DEEC3979981A3F4CE78FAB1F8FE83F39 /* Sources */, ); buildRules = ( ); dependencies = ( F47DA310FEED1D577995EC51108D5E92 /* PBXTargetDependency */, ); name = "Deps·AEXML"; productName = AEXML; productReference = 3FA20E1A308B36BD34D4F6FA38D3BF30 /* AEXML.a */; productType = "com.apple.product-type.library.static"; }; D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */ = { isa = PBXNativeTarget; buildConfigurationList = FB3F5BEE27646BEEDCE7AAFF12A2910F /* Build configuration list for PBXNativeTarget "Batter·CakefileDescription" */; buildPhases = ( E8E64701521367922653F85FE4202F81 /* Sources */, ); buildRules = ( ); dependencies = ( F79E560CAF7B3FC1F3068CFE9B10BDE1 /* PBXTargetDependency */, ); name = "Batter·CakefileDescription"; productName = CakefileDescription; productReference = 11D3B38D3F7DA37A8300F924107470ED /* CakefileDescription.a */; productType = "com.apple.product-type.library.static"; }; DCF843C187E023E2097ACF9EABA93DD6 /* Dependencies */ = { isa = PBXNativeTarget; buildPhases = ( 110D4C6492AD4DAAB8F0701D634714CF /* Frameworks */, B72D8CDE7B96F674B97F50DBA7722D81 /* Sources */, ); buildRules = ( ); dependencies = ( 1D8AB91B1934ECA2B505C6183A5FC38B /* PBXTargetDependency */, 3A19463D99686825EC39E9ED03F9589E /* PBXTargetDependency */, BD6D1B5E2089F89F86DB1C2CF90CB984 /* PBXTargetDependency */, FC5D401D66B2304DBCA5DBFCFE9A79CA /* PBXTargetDependency */, CFF9303A30E7F181CB5ED4393B13666C /* PBXTargetDependency */, 47FC00F222C163921E063D31FC5EBDFA /* PBXTargetDependency */, FDB6A7614F45C42C95995739384B5927 /* PBXTargetDependency */, 74ABE28A43D4DE4FF4BC639358381F75 /* PBXTargetDependency */, CCD24D36751009E477715FE65934C8C9 /* PBXTargetDependency */, 5F6E912FB8A1E2C86A4158675E8BB16A /* PBXTargetDependency */, 168122E044F80C89406C3809470BA6C7 /* PBXTargetDependency */, ); name = Dependencies; productReference = 4A7E89000FDF44A3427FBD44B878A9C1 /* Dependencies.a */; productType = "com.apple.product-type.library.static"; }; DF69393E8DED4E7C87625E2008C40E41 /* Batter·XcodeProject */ = { isa = PBXNativeTarget; buildConfigurationList = AA3351F9CE1B4053E2CE65B0FC1809D9 /* Build configuration list for PBXNativeTarget "Batter·XcodeProject" */; buildPhases = ( B32939C0E66AF37C44610611EECFDF0E /* Sources */, ); buildRules = ( ); dependencies = ( A4389FBC591F83984259446503E7520E /* PBXTargetDependency */, 53F2F8E019D9AF0707A740E3371C45D4 /* PBXTargetDependency */, ); name = "Batter·XcodeProject"; productName = XcodeProject; productReference = 937C922F7F6999DF1895EB3DC82906E9 /* XcodeProject.a */; productType = "com.apple.product-type.library.static"; }; ED829D4B109C4E4B415B8F01358C62F3 /* Batter·XcakeProject */ = { isa = PBXNativeTarget; buildConfigurationList = 9CF1F52C15FBC9D5635FDB05C6CF216F /* Build configuration list for PBXNativeTarget "Batter·XcakeProject" */; buildPhases = ( EE6483AD0BF951DAC3964ABABF818D90 /* Sources */, ); buildRules = ( ); dependencies = ( 01A54B9D047FC8AE6C2A5B51C43EA12F /* PBXTargetDependency */, 3184BA9F3D3D5E046B7C5470349375F9 /* PBXTargetDependency */, 13C0C02DD80211AD05DB9A4AB0A60C5D /* PBXTargetDependency */, ); name = "Batter·XcakeProject"; productName = XcakeProject; productReference = 7F8732C7CBD899BD5F0398A832669E75 /* XcakeProject.a */; productType = "com.apple.product-type.library.static"; }; F5D94DE7A2DF28D8FD6E0C310044455E /* Batter */ = { isa = PBXNativeTarget; buildPhases = ( B48E25CDFE3DC639D59FCE85ECC280D9 /* Frameworks */, 86204B913285479790C8B40218A6D01E /* Sources */, ); buildRules = ( ); dependencies = ( ACABA24C3D2AB0E217E730CCFD32A5C1 /* PBXTargetDependency */, 8C19EF95D17BAD3069694292CEA096BB /* PBXTargetDependency */, CE7201A86F96504B6EA253FE9AD95394 /* PBXTargetDependency */, E19D06FB14E30A3A83D27D6B41D47C4C /* PBXTargetDependency */, ); name = Batter; productReference = 3F573D976FA9A0403F17F22F1A4DAA55 /* Batter.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */ = { isa = PBXProject; attributes = { TargetAttributes = { 5D1C4ECF6D5347A44CB1E59E5BB558E0 = { LastSwiftMigration = 9999; }; 76CCBFA038A347F71E7B5BFB1521AC8A = { LastSwiftMigration = 9999; }; 8B4D032D3EA2708E1BF1B498E5AAC085 = { LastSwiftMigration = 9999; }; 8FEBB13B61D6321603EC90A5606F8C4F = { LastSwiftMigration = 9999; }; 9CF1FA8024CC8159DE776A7595DC3523 = { LastSwiftMigration = 9999; }; AC6B4791DEE2977626A076B8F9A7666F = { LastSwiftMigration = 9999; }; B4280F358AD4C3799414724EE00E6812 = { LastSwiftMigration = 9999; }; B49CC989FC5BE99773DFD32B46D8E82C = { LastSwiftMigration = 9999; }; B4EB89E549B6ADCED02958295D4FAD21 = { LastSwiftMigration = 9999; }; BD398413C05B07BBE2B6E2D14C9EE8D9 = { LastSwiftMigration = 9999; }; D1CE66C2AF312DCD9A12B6444FB0D2EA = { LastSwiftMigration = 9999; }; }; }; buildConfigurationList = E7FAEEC4302D535402308E4CA6048DBC /* Build configuration list for PBXProject "Cake" */; compatibilityVersion = "Xcode 9.3"; hasScannedForEncodings = 0; mainGroup = 50DCC4186C454A8A35C359EBE7E6484B /* */; productRefGroup = 1C4FCF6098FC3226B2546E8140B7A700 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */, B03189C2563DE1C075659DC03EF81210 /* Cakefile·Completion */, B4EB89E549B6ADCED02958295D4FAD21 /* Deps·xcodeproj */, B49CC989FC5BE99773DFD32B46D8E82C /* Deps·PathKit */, AC6B4791DEE2977626A076B8F9A7666F /* Deps·OrderedSet */, 8B4D032D3EA2708E1BF1B498E5AAC085 /* Deps·LegibleError */, 8FEBB13B61D6321603EC90A5606F8C4F /* Deps·HotKey */, 5D1C4ECF6D5347A44CB1E59E5BB558E0 /* Deps·AppUpdater */, 9CF1FA8024CC8159DE776A7595DC3523 /* Deps·Version */, 76CCBFA038A347F71E7B5BFB1521AC8A /* Deps·Path */, B4280F358AD4C3799414724EE00E6812 /* Deps·PMKFoundation */, BD398413C05B07BBE2B6E2D14C9EE8D9 /* Deps·PromiseKit */, D1CE66C2AF312DCD9A12B6444FB0D2EA /* Deps·AEXML */, DCF843C187E023E2097ACF9EABA93DD6 /* Dependencies */, 0F64CBB97351A503B1F408F40AB7E996 /* Batter·Kitchen */, 50A4D32099C32D3207892A9614D37B66 /* Batter·Processor */, ED829D4B109C4E4B415B8F01358C62F3 /* Batter·XcakeProject */, DF69393E8DED4E7C87625E2008C40E41 /* Batter·XcodeProject */, C1038750BB9B8EA5926C885645506714 /* Batter·XcodeObserver */, C8AC307C08B1141701DFEAAD12667716 /* Batter·Modelizer */, A49235A78CF83BF260878E68B866C986 /* Batter·Base */, D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */, F5D94DE7A2DF28D8FD6E0C310044455E /* Batter */, 27CCC44DFA86333E66FEE34EA8063784 /* Versionator */, 8B942976617019A6C464818315598CC1 /* Cake */, ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ 6F67EDB0066A07EA8ACEC9D4D60F4E3F /* Regenerate Cake.xcodeproj */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "$(PROJECT_DIR)/../Cakefile.swift", ); name = "Regenerate Cake.xcodeproj"; outputPaths = ( "$(PROJECT_DIR)/Cakefile.json", "$(PROJECT_DIR)/Dependencies.json", ); runOnlyForDeploymentPostprocessing = 0; shellPath = "$(DT_TOOLCHAIN_DIR)/usr/bin/swift"; shellScript = "import func Darwin.fputs\nimport var Darwin.stderr\nimport ScriptingBridge\nimport AppKit\n\nfunc print(_ objs: Any...) {\n let str = objs.reduce(into: \"\") { $0.append(\" \\($1)\") }\n fputs(str, stderr)\n}\n\nlet apps = NSRunningApplication.runningApplications(withBundleIdentifier: \"dev.mxcl.Cake\")\n\nswitch apps.count {\ncase 0:\n print(\"warning: Cake.app not running, Cakefile changes will not take effect\")\ncase 1:\n guard let bundle = apps[0].bundleURL else {\n print(\"Failed to obtain Cake.app location\")\n exit(1)\n }\n guard let projectDir = ProcessInfo.processInfo.environment[\"PROJECT_DIR\"] else {\n print(\"Failed to obtain PROJECT_DIR\")\n exit(2)\n }\n let path = bundle.appendingPathComponent(\"Contents/MacOS/cake-build\").path\n let task = Process()\n task.launchPath = path\n task.arguments = [String(apps[0].processIdentifier), projectDir]\n try task.run()\n task.waitUntilExit()\n exit(task.terminationStatus)\ndefault:\n print(\"error: More than one instance of Cake.app is running\")\n exit(3)\n}\n"; showEnvVarsInLog = 0; }; B0CCAA5D1D192F6963E1F5560239A386 /* Determine Version */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ../.git/refs/tags, ); name = "Determine Version"; outputPaths = ( Version.xcconfig, ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "v=$(git describe --tags --always --abbrev=0)\nn=$(git rev-list HEAD --count)\n\nif [[ -z $v ]]; then v=\"0.0.0\"; fi\nif [[ -z $n ]]; then n=\"0\"; fi\n\necho \"CURRENT_PROJECT_VERSION = $n\" > Version.xcconfig\necho \"SEMANTIC_PROJECT_VERSION = $v\" >> Version.xcconfig\necho \"SEMANTIC_PROJECT_VERSION[config=Debug] = $v-debug\" >> Version.xcconfig\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 01DD71F8D6077C0F16AA033CB312695C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( DC86CA0F4A8831D94959D21DD78C26C0 /* mxcl∕AppUpdater-1.0.3.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0330731A9D0FB38F456E61DB3932B0FF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 37C01C838BE8DE1C664691AA547031E5 /* after.swift in Sources */, CD29B1158D97E7F2767B742E15BB5F1B /* Box.swift in Sources */, A2A8C2A61706862AF67AB27B2D159F04 /* Catchable.swift in Sources */, 173AC44E5DDAF718CE86EE5D54DB1A23 /* Configuration.swift in Sources */, 4DAA0F96F543E4A6D90BDB8AC22BC759 /* CustomStringConvertible.swift in Sources */, 9AD25944060C73EBC3D7D4B8ED647F55 /* Error.swift in Sources */, DBF24B2F67D4AD415385D407F78EBFE7 /* firstly.swift in Sources */, 8A7FBCE750BACE16FA0C7D24A8E0FC26 /* Guarantee.swift in Sources */, B363F49F2AF887172600F5CD67F7C4F2 /* hang.swift in Sources */, 90E680E24018A067844D7A6860BDD036 /* LogEvent.swift in Sources */, 13A12CCBECF26AF3B18468E445CEF598 /* Promise.swift in Sources */, B965111421F5F7EA96A6384139DB4AD1 /* race.swift in Sources */, 2B35177067A9C34EDEB33A8164DE4588 /* Resolver.swift in Sources */, BEC710FA022A69539DE83D3DA26D2D46 /* Thenable.swift in Sources */, DD2127A7693447EA31FC5844269A5476 /* when.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0D2313C56B49445FFFBAFA66F386B894 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 656A6AF815F06DF3D24C506289398B6D /* mxcl∕LegibleError-1.0.1.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 3BD3E2AB91B7EC4954112ECB41545554 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1B8DDA4AC227EC58E450FF52FA21B600 /* Cakefile.swift in Sources */, 96CAE3141B8C653FF20D854469F10C2C /* Dependencies.swift in Sources */, FEB9BA4D068A75074CBA587AFBC15867 /* etc.swift in Sources */, DEBA5D57958559217B612C305D80D18B /* Self.swift in Sources */, D10A7E8D4601C0821314BCB968F68F73 /* SwiftVersion.swift in Sources */, 48AE346FE31B6E30412FC556CC270BEC /* TemporaryDirectory.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 61C5A1E04CE0BF1806F68D0A00D9CA69 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7E1152B6B2580D8CF2CAD150E04E60A8 /* HotKey.swift in Sources */, F1773AE9122717504710FDE32E039B2B /* HotKeysController.swift in Sources */, F7E7A799FBAE4D353AE3728E97367F61 /* Key.swift in Sources */, DA00E6F1BBD45869C0D4178FD7737F15 /* KeyCombo.swift in Sources */, 6DD8B2226655E5DED755A1BDC37C2588 /* NSEventModifierFlags+HotKey.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 6EA74799AC8908A90D1133CF4872622D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6F224F8B3EC4EF42D0BD03AC5A01CF9C /* Errors/Errors.swift in Sources */, B888FA01811554E0AF55D0A54886A893 /* Extensions/AEXML+XcodeFormat.swift in Sources */, F1A9E165928095B7FB7D9C8664C2B533 /* Extensions/Bool+Extras.swift in Sources */, 1494290E678712CC86B906C2DB6FB93D /* Extensions/Dictionary+Enumerate.swift in Sources */, FAD7EFC6A9B1B2F1AA0A4A1548B922BB /* Extensions/Dictionary+Extras.swift in Sources */, 67F5E702253087EF74E83502C0FB55E6 /* Extensions/KeyedDecodingContainer+Additions.swift in Sources */, AA8312CFC7EBB6F598BAF659D0B693EB /* Extensions/NSRecursiveLock+Sync.swift in Sources */, B59EF1525752B4039C257C311422F13C /* Extensions/OSLog+Extras.swift in Sources */, B13883DB62175193381A7119D4F9CD64 /* Extensions/Path+Extras.swift in Sources */, 1E85BDB96874D3515EED27E275942738 /* Extensions/String+md5.swift in Sources */, 1AFCBFBEF3EE85C4735EB8CD7919633F /* Extensions/String+Utils.swift in Sources */, 742C6B1F749FF4B6CDFBB53EFA544C37 /* Objects/BuildPhase/BuildPhase.swift in Sources */, 954EDC5169A2DAA27CD7EBCB0D9AE5D9 /* Objects/BuildPhase/PBXBuildFile.swift in Sources */, 29D6CA4B5F8DEB04CADCCCDF08E5B9C2 /* Objects/BuildPhase/PBXBuildPhase.swift in Sources */, C973731BD5D1ADF0B68DC9A8B71371AA /* Objects/BuildPhase/PBXBuildRule.swift in Sources */, D620D9DF46FAD133FAD0654540D93506 /* Objects/BuildPhase/PBXCopyFilesBuildPhase.swift in Sources */, 41CDD68A2C49542AC87B2D654662F8C2 /* Objects/BuildPhase/PBXFrameworksBuildPhase.swift in Sources */, CF94FDBF239BD77C694AFB7B9C375141 /* Objects/BuildPhase/PBXHeadersBuildPhase.swift in Sources */, A308AD5923DF4D916E0F13D2E6F95D39 /* Objects/BuildPhase/PBXResourcesBuildPhase.swift in Sources */, C5C90186A870052853053FE8BDE97F81 /* Objects/BuildPhase/PBXRezBuildPhase.swift in Sources */, 4CFAE96FAE35BAFB253A76001331128D /* Objects/BuildPhase/PBXShellScriptBuildPhase.swift in Sources */, 896F7E7C12011CA77277E7BACBB7F99C /* Objects/BuildPhase/PBXSourcesBuildPhase.swift in Sources */, B5709AC26DC8F5D630260A3F1DB425DC /* Objects/Configuration/BuildSettings.swift in Sources */, CA4D400E3DDC6CBC15A3D71ECB3CD4DA /* Objects/Configuration/XCBuildConfiguration.swift in Sources */, 0FE036E5308002A02EE147D00659CB89 /* Objects/Configuration/XCConfigurationList.swift in Sources */, 0F331239AFB8578C44E0FD3CC8A66D01 /* Objects/Files/PBXContainerItem.swift in Sources */, 67A0030B6C4B30446D3B7DF510D2AC95 /* Objects/Files/PBXContainerItemProxy.swift in Sources */, 264255B2DC375A38E16541D5A507613F /* Objects/Files/PBXFileElement.swift in Sources */, 58998CE0A4E32171CF4950F2639F378A /* Objects/Files/PBXFileReference.swift in Sources */, 23A997BC2064A2B26B67A7A75C7A6FD5 /* Objects/Files/PBXGroup.swift in Sources */, 382812E7E9599D9487DB1B4EFF573337 /* Objects/Files/PBXSourceTree.swift in Sources */, D3395990728EE7111BEE0C57ED111C98 /* Objects/Files/PBXVariantGroup.swift in Sources */, 898163FBB3101F0C1FAE974B73CB7271 /* Objects/Files/XCVersionGroup.swift in Sources */, F10ECD50FB9CDB0EF1F3ED6535B00F79 /* Objects/Project/PBXObject.swift in Sources */, A297A74AC30EA716F40100BBA29D7C00 /* Objects/Project/PBXObjectParser.swift in Sources */, 947BC673F4E249FE2276A9A7C9354813 /* Objects/Project/PBXObjectReference.swift in Sources */, 31E2AAD0BE0B7ADFD948BB0CFFC57C1B /* Objects/Project/PBXObjects.swift in Sources */, 80978F6C6C23060316D787E18C24BFC9 /* Objects/Project/PBXOutputSettings.swift in Sources */, 5DBB296966043F75007BBF4EB1C2DE76 /* Objects/Project/PBXProj.swift in Sources */, 95B9262AE9089B839547533D20E7BFE7 /* Objects/Project/PBXProject.swift in Sources */, 4719E9FAA93FD3E79F912CA463A0640A /* Objects/Project/PBXProjEncoder.swift in Sources */, 98DBDE552368194486604B4E85BD8EDD /* Objects/Sourcery/Equality.generated.swift in Sources */, FD4509FBDBD52F99ED185069192B4611 /* Objects/Sourcery/Sourcery.swift in Sources */, ED25BB88C9183FDB03E55618895F3A3E /* Objects/Targets/PBXAggregateTarget.swift in Sources */, 9EDD872806677188A87EFED76893CFF5 /* Objects/Targets/PBXLegacyTarget.swift in Sources */, 29AEB14B8E509CE62DD39ADF72760600 /* Objects/Targets/PBXNativeTarget.swift in Sources */, AC0DAA07C9191967E505AE9B19BC007B /* Objects/Targets/PBXProductType.swift in Sources */, F5CA27B2477A402F4A5820741101B61C /* Objects/Targets/PBXReferenceProxy.swift in Sources */, 23DFC276FAE69CBFA8C76347EF724B84 /* Objects/Targets/PBXTarget.swift in Sources */, E39FA5C4830B1C6286C4B8B0A11A6279 /* Objects/Targets/PBXTargetDependency.swift in Sources */, 5ED3ED0B77A5F3EF6B01955153AD6064 /* Project/WorkspaceSettings.swift in Sources */, 1C2035785DAAE2D64C8ECA6619C181D7 /* Project/XCBreakpointList.swift in Sources */, 0D24E42A01A5B57AE961FAF8C817687C /* Project/Xcode.swift in Sources */, 653928F76893E06F6C79ECE7A573380B /* Project/XcodeProj.swift in Sources */, 0EF5EC3E38F3F4D8F51F23394EDE32D5 /* Project/XCSharedData.swift in Sources */, F2EDD3CF836DCC600B513BFBB755CF5D /* Protocols/Writable.swift in Sources */, CB172787F2E9E15E6E4D0069701694ED /* Scheme/XCScheme.swift in Sources */, 71612AAB6911E5BEC04F9B2258C187CA /* Scheme/XCScheme+AditionalOption.swift in Sources */, 23B2B8C2D650E5A33B73053661E5F544 /* Scheme/XCScheme+AnalyzeAction.swift in Sources */, 97C035E3EF4FD8C90AA7FF8D9057B91F /* Scheme/XCScheme+ArchiveAction.swift in Sources */, 7EC2598830532F6C856E584A4E66B0CB /* Scheme/XCScheme+BuildableProductRunnable.swift in Sources */, 096E09CF05DC89BF84A52E377522B07A /* Scheme/XCScheme+BuildableReference.swift in Sources */, 0DED5DA8786393351690A30A1BCCA529 /* Scheme/XCScheme+BuildAction.swift in Sources */, DB218EF8F94D531927B2D342E41BA5E3 /* Scheme/XCScheme+CommandLineArguments.swift in Sources */, 32BFB1DD9292D0F15B2D465C68898EBE /* Scheme/XCScheme+EnvironmentVariable.swift in Sources */, 35D4B501F6E7D131FA2E4C2EA4C4FA98 /* Scheme/XCScheme+ExecutionAction.swift in Sources */, 853B75D491EC42D972FC45BC6A062A2B /* Scheme/XCScheme+LaunchAction.swift in Sources */, 37638F440D45770EB2821116E0E870D8 /* Scheme/XCScheme+LocationScenarioReference.swift in Sources */, 93B314409224678C08B72E61C1056C2C /* Scheme/XCScheme+ProfileAction.swift in Sources */, 953FA1F79CB127104231051399E7F96E /* Scheme/XCScheme+SerialAction.swift in Sources */, D8FF5F97208C6033DC9443168546626F /* Scheme/XCScheme+SkippedTests.swift in Sources */, 00E35D78B4FC58C677091AACE488F66C /* Scheme/XCScheme+TestableReference.swift in Sources */, BB63582548DBD2F5B1E488AC04FFFDB4 /* Scheme/XCScheme+TestAction.swift in Sources */, 9D4FA985555FAD0E3D818DD15FDEEE9A /* Utils/BuildSettingsProvider.swift in Sources */, B7FC5A115B5F3955E30EF15EC52D6EED /* Utils/CommentedString.swift in Sources */, 421A097788CD15E31F890B1C9EC609DF /* Utils/Decoders.swift in Sources */, 5613D97DEBC1E4931C7CA4E1F053D4B6 /* Utils/JSONDecoding.swift in Sources */, BBEF2E8BE5E69BA2026069C53E90CB13 /* Utils/OSLogger.swift in Sources */, 22CB02677F3EC68D952CDC73F88B79B9 /* Utils/PlistValue.swift in Sources */, 14E42FB6998F4B82759AA499D800F15C /* Utils/ReferenceGenerator.swift in Sources */, 0009CA61F364BD503A015792C9A7D2DB /* Utils/XCConfig.swift in Sources */, 629230A8B878757F42804737F332AF0D /* Workspace/XCWorkspace.swift in Sources */, 55623940F01DAE4B639B481D91CF88E9 /* Workspace/XCWorkspaceData.swift in Sources */, 2239144EE9AC530773FD403B4EF8BE35 /* Workspace/XCWorkspaceDataElement.swift in Sources */, 9B85910EE0235B89957B660EF71DD726 /* Workspace/XCWorkspaceDataElementLocationType.swift in Sources */, 478F14753835EFC15EE98084B682FD28 /* Workspace/XCWorkspaceDataFileRef.swift in Sources */, 9149D0D156D1A47AD9708C11EDBFC16E /* Workspace/XCWorkspaceDataGroup.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 86204B913285479790C8B40218A6D01E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6A041CF38BC28A5262F4A2C130435DA8 /* Batter.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 89F171C5C55F88CECBB4D9F919595B44 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 471B2B419524B9D1842BC520539060D6 /* Path+inreplace().swift in Sources */, 5F9F2D38AABF99927BA45359420DD85D /* Process+facade.swift in Sources */, 66B12F7477B5AC215FDB2A2EBE445EFD /* Sequence+KeyPath.swift in Sources */, 20C156247AA940F1663C87213EB9C7AD /* StreamReader.swift in Sources */, ADC757B7E9013417B979D184C8EA439D /* SwiftVersion.swift in Sources */, 73F5DBA5C3DF8C27AD93C9DF7F8B616D /* topologicalSort().swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 9D57241684611D5226E52EBD3A97727C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 02A46975791D4B6AF393E02BFC7B4FA7 /* Cake.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 9E7097A7C3D241A0B2CCA4D3B78A8A83 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3E3B8B3CAC69F14B8ACADC5E7FC66059 /* Extensions.swift in Sources */, 748E5C904992666724C802B55121D231 /* Path->Bool.swift in Sources */, 109244311B8CF9298C2586C085606327 /* Path.swift in Sources */, F967CC7B7762819FA7DC1F4ACA76DA87 /* Path+Attributes.swift in Sources */, 35CBA8E95F73F7C579D312B15F0D498F /* Path+Codable.swift in Sources */, E2FAA3397719FA0DC93535F286C47BDC /* Path+CommonDirectories.swift in Sources */, 0D607F811A55D6665B3CD26DA7EEF595 /* Path+FileManager.swift in Sources */, D51C1066BCE4EB4087BAF0686C5AA8B4 /* Path+ls.swift in Sources */, 9EC43026A52EADC5AE278DAC71294A6F /* Path+StringConvertibles.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A51B210879B02EBF2327F37032BF81B3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6C310B5FEEC48AFC22A70CEFB2CBC38A /* Weebly∕OrderedSet-3.1.0.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A55DDFC1E192780D65C32457CB5F07F8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 56DFD2E22C495FA82E39886F365DC33A /* Cakefile.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; A9A4A9984792079405DBB34A1D20B75B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E1BA243CAB80D7B010397756DE150F4E /* CakeProject.swift in Sources */, 962D45FFD864AA7F6C523E102A1046E0 /* FSWatcher.swift in Sources */, 8C9643A4FA9E488BCB63EBDA4286C997 /* Kitchen.swift in Sources */, E08267E7A19CE4F86CF11AE46F1F9CFE /* KitchenDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; B32939C0E66AF37C44610611EECFDF0E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( D93F5CCFC45D073036572B8910C27C33 /* _PathDisambiguation.swift in Sources */, 14E416B908FBFCEBBF146F35813A1A4B /* *Target.swift in Sources */, 8EF6B805944AE9C3AEB822AFCA5B852B /* +functions.swift in Sources */, 8A8B0E9BDA830045CCAF38F0E83A5761 /* +platforms.swift in Sources */, 79C7F45017C7722A800FFE0401AD9277 /* Group.swift in Sources */, 8132BA30BD6E920DDBD31451E9400E45 /* XcodeProject.swift in Sources */, CEBEADC323399BF84D2A2A41841A8DBC /* z.etc.swift in Sources */, 3823977F02656605E34F410252572C97 /* z+buildSettings.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; B72D8CDE7B96F674B97F50DBA7722D81 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 0144937EEB86C307B33A65EB2B058FFC /* Dependencies.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; DCA5BDE643D482824931150E443818EA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8EB5125F4FEFF56B991C39CB731DE87E /* kylef∕PathKit-0.9.2.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; DD25F76D9BF91196996408AAA2D08CA6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( F8373135B8E73DC04E741253EF8538AF /* afterlife.swift in Sources */, 0126D7996A8929E3D9BA9BC71806216C /* NSNotificationCenter+Promise.swift in Sources */, 194436C50CBF102CE54CD461191FCD0D /* NSObject+Promise.swift in Sources */, B56602EC4F80DEC5337994B59B3FE640 /* NSURLSession+Promise.swift in Sources */, 8086409EA5DD7B797084592C543D5EB3 /* Process+Promise.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; DEEC3979981A3F4CE78FAB1F8FE83F39 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( FDC90EB1D93E3B5852C55A9F0C16EB8C /* Document.swift in Sources */, 9C7533C705D0687317351F2003399A02 /* Element.swift in Sources */, B932800411795A587A5D035B3F67E937 /* Error.swift in Sources */, 4BA6617EF1A234421360DA3D234D522E /* Options.swift in Sources */, CFBB1B1AD3BABF755259E1B5ABF0B453 /* Parser.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E2BAB0B95B059BB004904ECA59F68448 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 238D7E0FA67C18E872F921129F546762 /* Version.swift in Sources */, 8D090FE4A3B4FAED3A0490D986C15C85 /* Version+Codable.swift in Sources */, 3514CFE553B87C0B30A58801F8271A27 /* Version+Comparable.swift in Sources */, 93ABEAC4A39B97F1DAD8B82CF4A66A3D /* Version+Foundation.swift in Sources */, 4AEC1425A72131B2D9A01091B98794E0 /* Version+Range.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E5782A25D53239D7365C8040FEACD39D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( D884582231287F0F5274AA2BA4A0BC2C /* Dependencies.json.swift in Sources */, 6ABA75F07503C93AB3B3C7F0B38CCCB3 /* modelize().swift in Sources */, 09418BE9EF8A8148100DCB62874E428F /* Module.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E73EE8C4A3772E20E3C2F0C8C36A37E8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 31BB6F1989688A30CC2AA71C1067102B /* Diff.swift in Sources */, 3F5CEF2D4DDC859B3FC26CDBEFEC015A /* XcodeObserver.swift in Sources */, FB72D613AD5B0AAF539728B89A41FB8E /* XcodeScriptingBridge.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E8E64701521367922653F85FE4202F81 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 03B4231C554E2D2E022A5351927EA1E5 /* CakefileDescription.swift in Sources */, D079F107A87BDA6D93E3B909821C6AA2 /* Version+.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; EE6483AD0BF951DAC3964ABABF818D90 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 4296C1974AB9D91026CA47FD9BBA5C52 /* +functions.swift in Sources */, 6B38FB50EC08F4DF74CF1EC447A2D496 /* deintegrate().swift in Sources */, 619608298AB26ADA9558192FF85A703F /* etc.swift in Sources */, DF2738497A69CFC60A7BFF7546A79383 /* scaffold().swift in Sources */, E641E4491384EBC7ED294BF3AFBFA63B /* XcakeProject.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 01A54B9D047FC8AE6C2A5B51C43EA12F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Modelizer"; target = C8AC307C08B1141701DFEAAD12667716 /* Batter·Modelizer */; targetProxy = 8CF6B72EF378FFC5EDCD3344A04E6912 /* PBXContainerItemProxy */; }; 0565BAB4E438C2EA664F8C83EB0CE946 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = B06116E54C8217994FD5F06F7E592CF2 /* PBXContainerItemProxy */; }; 13C0C02DD80211AD05DB9A4AB0A60C5D /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·XcodeProject"; target = DF69393E8DED4E7C87625E2008C40E41 /* Batter·XcodeProject */; targetProxy = 17D5F07BC8B5B3BC93A4EE4B2B28AD4A /* PBXContainerItemProxy */; }; 168122E044F80C89406C3809470BA6C7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·xcodeproj"; target = B4EB89E549B6ADCED02958295D4FAD21 /* Deps·xcodeproj */; targetProxy = EB36CF19BE9565CD2F536DD00DB99F43 /* PBXContainerItemProxy */; }; 1D8AB91B1934ECA2B505C6183A5FC38B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PromiseKit"; target = BD398413C05B07BBE2B6E2D14C9EE8D9 /* Deps·PromiseKit */; targetProxy = 5EDA6990A1DDBE6E9B607D100EF8A5DA /* PBXContainerItemProxy */; }; 315AE0B2F6C88E934BB5814FD47A2FB0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·CakefileDescription"; target = D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */; targetProxy = 466D0E195DB547397C597EF346516148 /* PBXContainerItemProxy */; }; 3184BA9F3D3D5E046B7C5470349375F9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·XcodeObserver"; target = C1038750BB9B8EA5926C885645506714 /* Batter·XcodeObserver */; targetProxy = A0AD5420B6DC1AB939BC61EDDB8218B7 /* PBXContainerItemProxy */; }; 327C41C1F24B05BA591F163701AC5FFD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = A6534538102624A3BAD54587BBECFEF5 /* PBXContainerItemProxy */; }; 3366830391752771A1D8AFE2C77B8DC4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Versionator; target = 27CCC44DFA86333E66FEE34EA8063784 /* Versionator */; targetProxy = F312C1044F70834D556FB7F4802D1893 /* PBXContainerItemProxy */; }; 3A19463D99686825EC39E9ED03F9589E /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PMKFoundation"; target = B4280F358AD4C3799414724EE00E6812 /* Deps·PMKFoundation */; targetProxy = 1EE1EF930A5BF3D0012B58E4A1D22BB8 /* PBXContainerItemProxy */; }; 478D6FA01AC7470AE22A47A14BB76D0E /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = 3609D632CDBAAFD820788391BA3977DC /* PBXContainerItemProxy */; }; 47F528038C3330D21B21869C0B0FB0A9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·Version"; target = 9CF1FA8024CC8159DE776A7595DC3523 /* Deps·Version */; targetProxy = CDAE6F16BFD0F82E6454C65CB8F164D2 /* PBXContainerItemProxy */; }; 47FC00F222C163921E063D31FC5EBDFA /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·HotKey"; target = 8FEBB13B61D6321603EC90A5606F8C4F /* Deps·HotKey */; targetProxy = 2AB7C8C5BF907C9BECA079EDED1FFC18 /* PBXContainerItemProxy */; }; 52375388D4F28520E6EDF71CF9157BD9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·AEXML"; target = D1CE66C2AF312DCD9A12B6444FB0D2EA /* Deps·AEXML */; targetProxy = D98236A2D881CAC7928673239C8BFD51 /* PBXContainerItemProxy */; }; 53F2F8E019D9AF0707A740E3371C45D4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·CakefileDescription"; target = D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */; targetProxy = 71C00BC3AFA055F16733B467637C32E6 /* PBXContainerItemProxy */; }; 5F6E912FB8A1E2C86A4158675E8BB16A /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PathKit"; target = B49CC989FC5BE99773DFD32B46D8E82C /* Deps·PathKit */; targetProxy = ED11063682340B41D483263E6FE5EED7 /* PBXContainerItemProxy */; }; 6F2865C025F7F740FF65DBD4991157C8 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Dependencies; target = DCF843C187E023E2097ACF9EABA93DD6 /* Dependencies */; targetProxy = 2D6EDF33EC661363ED1E5889EA9EF52F /* PBXContainerItemProxy */; }; 74ABE28A43D4DE4FF4BC639358381F75 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·OrderedSet"; target = AC6B4791DEE2977626A076B8F9A7666F /* Deps·OrderedSet */; targetProxy = 0116FC39B24582BEE9036286F9430EA1 /* PBXContainerItemProxy */; }; 7B00EE4575A017E6BDDA5BFB0B5D5383 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Base"; target = A49235A78CF83BF260878E68B866C986 /* Batter·Base */; targetProxy = 0EFDF076DBC213F64A00B6683D0E6B67 /* PBXContainerItemProxy */; }; 86F70278902535F201592D638128287A /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Processor"; target = 50A4D32099C32D3207892A9614D37B66 /* Batter·Processor */; targetProxy = 80644EB6FD3773EE45376C2EC9869F30 /* PBXContainerItemProxy */; }; 8C19EF95D17BAD3069694292CEA096BB /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Modelizer"; target = C8AC307C08B1141701DFEAAD12667716 /* Batter·Modelizer */; targetProxy = 18BB34364DC319E58561C144CFB5F85E /* PBXContainerItemProxy */; }; 8FE2AD32E33987A961C4396477BA6D4D /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = 67AEDC266F822DBF18B34C4E257EE1E9 /* PBXContainerItemProxy */; }; 9872C58C32FAF03ACEC329FFD2C13162 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Base"; target = A49235A78CF83BF260878E68B866C986 /* Batter·Base */; targetProxy = B01E0633294DEAFA1B9F52960E14C230 /* PBXContainerItemProxy */; }; A4389FBC591F83984259446503E7520E /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Base"; target = A49235A78CF83BF260878E68B866C986 /* Batter·Base */; targetProxy = 924C0BA9D531ACB667362E847E2C2ED1 /* PBXContainerItemProxy */; }; A6D31631D95C3A51C9FAABBAA253F1D7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = 1AD18862BE00E9D273C5119993BF1EF7 /* PBXContainerItemProxy */; }; ACABA24C3D2AB0E217E730CCFD32A5C1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·CakefileDescription"; target = D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */; targetProxy = 3CA790475701796546AEC8C8F9BEC467 /* PBXContainerItemProxy */; }; B05A9D037029AAFBD5DCAD6ECBF89F09 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = FC06ED7DAB16B02502FC9309C805AAA3 /* PBXContainerItemProxy */; }; B9568118D2B144E528AFACC9A3063C8F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·CakefileDescription"; target = D4D58EF887FC75ADD1D795BF5B47A879 /* Batter·CakefileDescription */; targetProxy = D46696C0AE71459DAAF917F866D13018 /* PBXContainerItemProxy */; }; BD6D1B5E2089F89F86DB1C2CF90CB984 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·Path"; target = 76CCBFA038A347F71E7B5BFB1521AC8A /* Deps·Path */; targetProxy = 96CF6D0F301321DD90DAAA34150AF9C8 /* PBXContainerItemProxy */; }; C2464976BABCABAA3A72863AE3E78F30 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·Path"; target = 76CCBFA038A347F71E7B5BFB1521AC8A /* Deps·Path */; targetProxy = 25BC92DB11B4440F7308DC364B2A9CC8 /* PBXContainerItemProxy */; }; C705D93D65D5402E574821CB2982B55B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PathKit"; target = B49CC989FC5BE99773DFD32B46D8E82C /* Deps·PathKit */; targetProxy = 144BDEC13717CB09678A9A83D9431ADF /* PBXContainerItemProxy */; }; C92758E700B37ED68776342F73765D28 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PromiseKit"; target = BD398413C05B07BBE2B6E2D14C9EE8D9 /* Deps·PromiseKit */; targetProxy = 3D570B61F4B7B186FBD4FB45CAB2344D /* PBXContainerItemProxy */; }; C94339126C714AD460BE58DB6BE8A056 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Dependencies; target = DCF843C187E023E2097ACF9EABA93DD6 /* Dependencies */; targetProxy = 3A6C290700F171F09F36630EAE33952A /* PBXContainerItemProxy */; }; CB56305824BFCA6B67740F6043A4B9E2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Batter; target = F5D94DE7A2DF28D8FD6E0C310044455E /* Batter */; targetProxy = 756891CE29B59469D117CB86600830B4 /* PBXContainerItemProxy */; }; CCD24D36751009E477715FE65934C8C9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·AEXML"; target = D1CE66C2AF312DCD9A12B6444FB0D2EA /* Deps·AEXML */; targetProxy = 26A6089A74D49C04CCF423ED317665CF /* PBXContainerItemProxy */; }; CE7201A86F96504B6EA253FE9AD95394 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·XcodeObserver"; target = C1038750BB9B8EA5926C885645506714 /* Batter·XcodeObserver */; targetProxy = A451E2841D294632F1518CB0121B3EE9 /* PBXContainerItemProxy */; }; CFF9303A30E7F181CB5ED4393B13666C /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·AppUpdater"; target = 5D1C4ECF6D5347A44CB1E59E5BB558E0 /* Deps·AppUpdater */; targetProxy = E19C66FA1ADEB89F9061C2604746306D /* PBXContainerItemProxy */; }; DE622C7A094011A28248907BDAFD9AD7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·PMKFoundation"; target = B4280F358AD4C3799414724EE00E6812 /* Deps·PMKFoundation */; targetProxy = 1C49E795CA5C037A31C025E2A56C01F7 /* PBXContainerItemProxy */; }; E19D06FB14E30A3A83D27D6B41D47C4C /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·Kitchen"; target = 0F64CBB97351A503B1F408F40AB7E996 /* Batter·Kitchen */; targetProxy = 9552D2A44C21251174A336F563E786A6 /* PBXContainerItemProxy */; }; F47DA310FEED1D577995EC51108D5E92 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = 3B18052B44E98025F6CED9B8801DAF2A /* PBXContainerItemProxy */; }; F79E560CAF7B3FC1F3068CFE9B10BDE1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Dependencies; target = DCF843C187E023E2097ACF9EABA93DD6 /* Dependencies */; targetProxy = 7E33F2A58E0B9F911C5089934C28196D /* PBXContainerItemProxy */; }; FC5D401D66B2304DBCA5DBFCFE9A79CA /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·Version"; target = 9CF1FA8024CC8159DE776A7595DC3523 /* Deps·Version */; targetProxy = EFB035A45795006B3E0D3D4C5A2F75D9 /* PBXContainerItemProxy */; }; FCE6F711BDA27F1587A676EA4E1A223E /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Batter·XcakeProject"; target = ED829D4B109C4E4B415B8F01358C62F3 /* Batter·XcakeProject */; targetProxy = A374EA6D4F5157415110C114CB7D2C2C /* PBXContainerItemProxy */; }; FDB6A7614F45C42C95995739384B5927 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Deps·LegibleError"; target = 8B4D032D3EA2708E1BF1B498E5AAC085 /* Deps·LegibleError */; targetProxy = 2271E804C9C352B20C61ABBC68327426 /* PBXContainerItemProxy */; }; FDED9CB4A42F8E451B9CD92A9214BED0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cakefile; target = 818A4854C95B333066E8C4A9D0FE3104 /* Cakefile */; targetProxy = C9302B77BC2BA2C40C288B30160EB8D2 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 01749ADF071445F3D44FE9321492F1DF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PromiseKit; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 0CAA1B24A1677E42C56C03ED4DA25A52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = LegibleError; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 0F006438EBC883D6DAF7464CC0DDABF6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcodeProject; }; name = Debug; }; 14B4BDC3A8A21514BA38D5A922B852AF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcakeProject; }; name = Release; }; 1542C6C2D7059A7EEC04A25093C8FB37 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Version; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 1FDF228DCFCECD2E29608D6651871DC8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcodeProject; }; name = Release; }; 2844F622FC5B65DAF12AC70D4AFF5996 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { SDKROOT = macosx; SUPPORTED_PLATFORMS = ( macosx, ); }; name = Debug; }; 29E540EA274DAA3506C22D6A88BE09A8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Kitchen; }; name = Release; }; 32D6FC9C351006942233B9CFE73E4993 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = HotKey; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Debug; }; 36FDC3D030F4546E2131F29F814A5F55 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = AEXML; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Release; }; 3C084769932C95D3A2801BCDC01C9B14 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Version; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; 3E37F9EC3C830D4424F936E9DF318A0D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PathKit; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Release; }; 3EC07005C8E3F33BC0190690803F509E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Base; }; name = Release; }; 410BFEF56CC5175724CEE7B0902B8F89 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = AppUpdater; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 41146688A2C9C1ADC6CE5ECF08220617 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcodeObserver; }; name = Release; }; 4F22B98D5732335D56A43BBA2E277916 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = OrderedSet; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Release; }; 53A5ED01504F5692461D83AC41FED6AF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Modelizer; }; name = Debug; }; 5414DEBB5462ADF390A78B4FB3176ACA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = xcodeproj; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Release; }; 54504CD556F9BCA94769A4E0404EC81A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Kitchen; }; name = Debug; }; 5B0253CF35CA61DC4C802193B10AE866 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { LD = /usr/bin/true; OTHER_SWIFT_FLAGS = ( "-I", "$(HOME)/Library/Developer/Cake/DerivedData/$(XCODE_PRODUCT_BUILD_VERSION)/lib", "-L", "$(HOME)/Library/Developer/Cake/DerivedData/$(XCODE_PRODUCT_BUILD_VERSION)/lib", ); PRODUCT_MODULE_NAME = Script; PRODUCT_NAME = CakefileScript; SDKROOT = macosx; SUPPORTED_PLATFORMS = ( macosx, ); }; name = Debug; }; 5C8E84147B6537BD038619517173D299 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = HotKey; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Release; }; 5D6B9672AD5355F3F9519229CDA07709 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcakeProject; }; name = Debug; }; 5FB2846AECAA7414D01A3C49C15041BB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PathKit; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Debug; }; 6DC3C515934279B0C9ADFDB208AD4DDC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Modelizer; }; name = Release; }; 787C252C3F61DAE6E109B354CEC2AAF2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = CakefileDescription; }; name = Release; }; 81D3D4DB9973AC28F206BDCD037C6B74 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PMKFoundation; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; 84967217740F703D00B507627CF65AD9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = xcodeproj; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Debug; }; 97A193D0B309D29E270701A52EF85AB1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PMKFoundation; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; AAA43370FFAEBDAB6ADCE93C1A2E0385 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = CakefileDescription; }; name = Debug; }; BF01A86C4D19E080F58AF28A3610DF80 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { LD = /usr/bin/true; OTHER_SWIFT_FLAGS = ( "-I", "$(HOME)/Library/Developer/Cake/DerivedData/$(XCODE_PRODUCT_BUILD_VERSION)/lib", "-L", "$(HOME)/Library/Developer/Cake/DerivedData/$(XCODE_PRODUCT_BUILD_VERSION)/lib", ); PRODUCT_MODULE_NAME = Script; PRODUCT_NAME = CakefileScript; SDKROOT = macosx; SUPPORTED_PLATFORMS = ( macosx, ); }; name = Release; }; C01BD67412F7D01E7E37440909A3CB04 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = s; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14.0; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = ( macosx, ); SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( Cake, ); SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; USE_HEADERMAP = NO; }; name = Release; }; C410D3BA7B21321C1380A8F61AF726E5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = XcodeObserver; }; name = Debug; }; CC732CD549C750F7CD04EDBC7ADB55A0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Processor; }; name = Release; }; D49614ABEFCDEB137B8860ACDE9FA8A5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = LegibleError; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; D4A347FDE8735E33183BC68A9E6DB430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Path; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Release; }; D62CF9D1772A1414748B609CFFEA1559 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Path; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; D85DB4BAEAF6C73A25136BE3DF43F204 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = AppUpdater; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; DA49F997348D1FD710E75C7ABD77D37B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Processor; }; name = Debug; }; E05BAB2BDFF639B0BF23680409C4D9A0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = PromiseKit; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; F217A8AA6DBABB214741C52ABC90012B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = AEXML; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Debug; }; F5934BDF56DD92BB93D0C5E53B4140B9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = OrderedSet; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( "$(inherited)", SWIFT_PACKAGE, ); SWIFT_SUPPRESS_WARNINGS = YES; SWIFT_VERSION = 4.2; }; name = Debug; }; F6BCBDB02D5733D803C90FCC60A48E00 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { SDKROOT = macosx; SUPPORTED_PLATFORMS = ( macosx, ); }; name = Release; }; F7770844F3B732A8F6817F4CB5DE795E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_NS_ASSERTIONS = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = ( macosx, ); SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( Cake, DEBUG, ); SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; USE_HEADERMAP = NO; }; name = Debug; }; FD451F7448C7B2F7682282B733D7ADD1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = Base; }; name = Debug; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 06F4E05BD565282710B442AE5EA794B4 /* Build configuration list for PBXNativeTarget "Deps·xcodeproj" */ = { isa = XCConfigurationList; buildConfigurations = ( 84967217740F703D00B507627CF65AD9 /* Debug */, 5414DEBB5462ADF390A78B4FB3176ACA /* Release */, ); defaultConfigurationIsVisible = 0; }; 12501F7CC58BB1124BB427E6ACE8AAFD /* Build configuration list for PBXNativeTarget "Deps·OrderedSet" */ = { isa = XCConfigurationList; buildConfigurations = ( F5934BDF56DD92BB93D0C5E53B4140B9 /* Debug */, 4F22B98D5732335D56A43BBA2E277916 /* Release */, ); defaultConfigurationIsVisible = 0; }; 1CB785113119F8BC5FF59CA4741AA37B /* Build configuration list for PBXNativeTarget "Deps·AppUpdater" */ = { isa = XCConfigurationList; buildConfigurations = ( D85DB4BAEAF6C73A25136BE3DF43F204 /* Debug */, 410BFEF56CC5175724CEE7B0902B8F89 /* Release */, ); defaultConfigurationIsVisible = 0; }; 3A3934967D7790F017425C98A64CD375 /* Build configuration list for PBXNativeTarget "Cakefile·Completion" */ = { isa = XCConfigurationList; buildConfigurations = ( 5B0253CF35CA61DC4C802193B10AE866 /* Debug */, BF01A86C4D19E080F58AF28A3610DF80 /* Release */, ); defaultConfigurationIsVisible = 0; }; 525C58D15460DD55EAC5A3285814107D /* Build configuration list for PBXNativeTarget "Deps·HotKey" */ = { isa = XCConfigurationList; buildConfigurations = ( 32D6FC9C351006942233B9CFE73E4993 /* Debug */, 5C8E84147B6537BD038619517173D299 /* Release */, ); defaultConfigurationIsVisible = 0; }; 5375538FF4A3E415410EE0F07030C0A4 /* Build configuration list for PBXNativeTarget "Deps·LegibleError" */ = { isa = XCConfigurationList; buildConfigurations = ( D49614ABEFCDEB137B8860ACDE9FA8A5 /* Debug */, 0CAA1B24A1677E42C56C03ED4DA25A52 /* Release */, ); defaultConfigurationIsVisible = 0; }; 54C3D682088F52A98460F95C69B3AB03 /* Build configuration list for PBXNativeTarget "Batter·Base" */ = { isa = XCConfigurationList; buildConfigurations = ( FD451F7448C7B2F7682282B733D7ADD1 /* Debug */, 3EC07005C8E3F33BC0190690803F509E /* Release */, ); defaultConfigurationIsVisible = 0; }; 7081C02CA5D1323B9B25721C60922C92 /* Build configuration list for PBXNativeTarget "Batter·Processor" */ = { isa = XCConfigurationList; buildConfigurations = ( DA49F997348D1FD710E75C7ABD77D37B /* Debug */, CC732CD549C750F7CD04EDBC7ADB55A0 /* Release */, ); defaultConfigurationIsVisible = 0; }; 75705B7E4DE90E787B5587BB39A9C36B /* Build configuration list for PBXNativeTarget "Batter·Kitchen" */ = { isa = XCConfigurationList; buildConfigurations = ( 54504CD556F9BCA94769A4E0404EC81A /* Debug */, 29E540EA274DAA3506C22D6A88BE09A8 /* Release */, ); defaultConfigurationIsVisible = 0; }; 9CF1F52C15FBC9D5635FDB05C6CF216F /* Build configuration list for PBXNativeTarget "Batter·XcakeProject" */ = { isa = XCConfigurationList; buildConfigurations = ( 5D6B9672AD5355F3F9519229CDA07709 /* Debug */, 14B4BDC3A8A21514BA38D5A922B852AF /* Release */, ); defaultConfigurationIsVisible = 0; }; AA3351F9CE1B4053E2CE65B0FC1809D9 /* Build configuration list for PBXNativeTarget "Batter·XcodeProject" */ = { isa = XCConfigurationList; buildConfigurations = ( 0F006438EBC883D6DAF7464CC0DDABF6 /* Debug */, 1FDF228DCFCECD2E29608D6651871DC8 /* Release */, ); defaultConfigurationIsVisible = 0; }; AE6ECBCB9E2BBD1C00E2B864AB33FCFE /* Build configuration list for PBXNativeTarget "Batter·Modelizer" */ = { isa = XCConfigurationList; buildConfigurations = ( 53A5ED01504F5692461D83AC41FED6AF /* Debug */, 6DC3C515934279B0C9ADFDB208AD4DDC /* Release */, ); defaultConfigurationIsVisible = 0; }; B12860ED6D40D093F21670917F129409 /* Build configuration list for PBXNativeTarget "Batter·XcodeObserver" */ = { isa = XCConfigurationList; buildConfigurations = ( C410D3BA7B21321C1380A8F61AF726E5 /* Debug */, 41146688A2C9C1ADC6CE5ECF08220617 /* Release */, ); defaultConfigurationIsVisible = 0; }; B372C3FDAB1008B4B28D830E0B8DF1A9 /* Build configuration list for PBXNativeTarget "Deps·Version" */ = { isa = XCConfigurationList; buildConfigurations = ( 3C084769932C95D3A2801BCDC01C9B14 /* Debug */, 1542C6C2D7059A7EEC04A25093C8FB37 /* Release */, ); defaultConfigurationIsVisible = 0; }; B961BFD93B1016266AB52B4C43632B1C /* Build configuration list for PBXNativeTarget "Deps·PromiseKit" */ = { isa = XCConfigurationList; buildConfigurations = ( E05BAB2BDFF639B0BF23680409C4D9A0 /* Debug */, 01749ADF071445F3D44FE9321492F1DF /* Release */, ); defaultConfigurationIsVisible = 0; }; D6F76942AA26F8FE33C0B9E559F048A3 /* Build configuration list for PBXNativeTarget "Deps·PMKFoundation" */ = { isa = XCConfigurationList; buildConfigurations = ( 81D3D4DB9973AC28F206BDCD037C6B74 /* Debug */, 97A193D0B309D29E270701A52EF85AB1 /* Release */, ); defaultConfigurationIsVisible = 0; }; DC551BFA9E078B27003D39F40946DE59 /* Build configuration list for PBXNativeTarget "Deps·PathKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 5FB2846AECAA7414D01A3C49C15041BB /* Debug */, 3E37F9EC3C830D4424F936E9DF318A0D /* Release */, ); defaultConfigurationIsVisible = 0; }; E7FAEEC4302D535402308E4CA6048DBC /* Build configuration list for PBXProject "Cake" */ = { isa = XCConfigurationList; buildConfigurations = ( F7770844F3B732A8F6817F4CB5DE795E /* Debug */, C01BD67412F7D01E7E37440909A3CB04 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; F77D98629B64E24B6FFAE21718CA106B /* Build configuration list for PBXNativeTarget "Deps·AEXML" */ = { isa = XCConfigurationList; buildConfigurations = ( F217A8AA6DBABB214741C52ABC90012B /* Debug */, 36FDC3D030F4546E2131F29F814A5F55 /* Release */, ); defaultConfigurationIsVisible = 0; }; F96FF9FDA0DC746E15BB01A0E5531883 /* Build configuration list for PBXNativeTarget "Deps·Path" */ = { isa = XCConfigurationList; buildConfigurations = ( D62CF9D1772A1414748B609CFFEA1559 /* Debug */, D4A347FDE8735E33183BC68A9E6DB430 /* Release */, ); defaultConfigurationIsVisible = 0; }; FB1419C517BF03EBE4B57BA190D11DA2 /* Build configuration list for PBXAggregateTarget "Cakefile" */ = { isa = XCConfigurationList; buildConfigurations = ( 2844F622FC5B65DAF12AC70D4AFF5996 /* Debug */, F6BCBDB02D5733D803C90FCC60A48E00 /* Release */, ); defaultConfigurationIsVisible = 0; }; FB3F5BEE27646BEEDCE7AAFF12A2910F /* Build configuration list for PBXNativeTarget "Batter·CakefileDescription" */ = { isa = XCConfigurationList; buildConfigurations = ( AAA43370FFAEBDAB6ADCE93C1A2E0385 /* Debug */, 787C252C3F61DAE6E109B354CEC2AAF2 /* Release */, ); defaultConfigurationIsVisible = 0; }; /* End XCConfigurationList section */ }; rootObject = DAA9F9B983CE55D38B2F125BAD56FC0E /* Project object */; } ================================================ FILE: .cake/Cake.xcodeproj/project.xcworkspace/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: .cake/Cake.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: .cake/Cake.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: .cake/Dependencies.swift ================================================ // Generated by Cake. Regeneration will occur! Edits will be lost! // We only export _directly_specified_ dependencies. @_exported import OrderedSet @_exported import PromiseKit @_exported import Path @_exported import PMKFoundation @_exported import xcodeproj @_exported import LegibleError @_exported import Version @_exported import HotKey @_exported import AppUpdater ================================================ FILE: .cake/Package.resolved ================================================ { "object": { "pins": [ { "package": "AEXML", "repositoryURL": "https://github.com/tadija/AEXML", "state": { "branch": null, "revision": "54bb8ea6fb693dd3f92a89e5fcc19e199fdeedd0", "version": "4.3.3" } }, { "package": "AppUpdater", "repositoryURL": "https://github.com/mxcl/AppUpdater.git", "state": { "branch": null, "revision": "ba6661149dc433ebe9620498063cbce8389de0ba", "version": "1.0.3" } }, { "package": "PMKFoundation", "repositoryURL": "https://github.com/PromiseKit/Foundation.git", "state": { "branch": null, "revision": "04b196a1cb3ce65a404724c4e6e87c43c56542a4", "version": "3.3.1" } }, { "package": "HotKey", "repositoryURL": "https://github.com/soffes/HotKey.git", "state": { "branch": null, "revision": "59d991a951f596236aa2b4f9b1f4b67d4a79e65d", "version": "0.1.1" } }, { "package": "LegibleError", "repositoryURL": "https://github.com/mxcl/LegibleError.git", "state": { "branch": null, "revision": "c615c01e461e8a3495ba4ea75f5d671c76820105", "version": "1.0.1" } }, { "package": "OrderedSet", "repositoryURL": "https://github.com/Weebly/OrderedSet.git", "state": { "branch": null, "revision": "4247c60cc190dbbaff63ecfe42bd7a1f2cbaf225", "version": "3.1.0" } }, { "package": "Path.swift", "repositoryURL": "https://github.com/mxcl/Path.swift.git", "state": { "branch": null, "revision": "7e774b6cf56f3f516df373718bf8fc2b7a9b373c", "version": "0.16.1" } }, { "package": "PathKit", "repositoryURL": "https://github.com/kylef/PathKit", "state": { "branch": null, "revision": "e2f5be30e4c8f531c9c1e8765aa7b71c0a45d7a0", "version": "0.9.2" } }, { "package": "PromiseKit", "repositoryURL": "https://github.com/mxcl/PromiseKit.git", "state": { "branch": null, "revision": "db3b2aaf0b26299c1828e0a302adf1a5523f4af5", "version": "6.8.3" } }, { "package": "Spectre", "repositoryURL": "https://github.com/kylef/Spectre.git", "state": { "branch": null, "revision": "f14ff47f45642aa5703900980b014c2e9394b6e5", "version": "0.9.0" } }, { "package": "SwiftShell", "repositoryURL": "https://github.com/kareman/SwiftShell", "state": { "branch": null, "revision": "beebe43c986d89ea5359ac3adcb42dac94e5e08a", "version": "4.1.2" } }, { "package": "Version", "repositoryURL": "https://github.com/mxcl/Version.git", "state": { "branch": null, "revision": "087c91fedc110f9f833b14ef4c32745dabca8913", "version": "1.0.3" } }, { "package": "xcodeproj", "repositoryURL": "https://github.com/tuist/xcodeproj.git", "state": { "branch": null, "revision": "3fe1bd763072c81050b867d34db56d11cb9085bb", "version": "6.6.0" } } ] }, "version": 1 } ================================================ FILE: .gitignore ================================================ /.cake/swift-pm /.cake/Package.swift /.cake/*.json /.cake/Version.xcconfig /Sources/Mixer/Mixer.xcodeproj /Sources/Mixer/.build **/xcuserdata .DS_Store ================================================ FILE: .travis.yml ================================================ # only run for: merge commits, releases and pull-requests if: type != push OR branch = master OR branch =~ /^\d+\.\d+(\.\d+)?(-\S*)?$/ os: osx language: swift osx_image: xcode10.2 script: set -o pipefail && xcodebuild -scheme Cake PROVISIONING_PROFILE="" DEVELOPMENT_TEAM="" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty ================================================ FILE: Cake.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 50; objects = { /* Begin PBXAggregateTarget section */ 63537994220E8343008449E9 /* mixer */ = { isa = PBXAggregateTarget; buildConfigurationList = 63537995220E8343008449E9 /* Build configuration list for PBXAggregateTarget "mixer" */; buildPhases = ( 63537998220E8350008449E9 /* swift build */, ); dependencies = ( ); name = mixer; productName = mixer2; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ 6307663221CE716600236F1C /* Menu·Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6307663121CE716600236F1C /* Menu·Xcode.swift */; }; 63402FC121B87602003F1B8E /* CakefileDescriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63402FC021B87602003F1B8E /* CakefileDescriptionTests.swift */; }; 6343042521858C7D004A45F0 /* XcakeprojTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6343042421858C7D004A45F0 /* XcakeprojTests.swift */; }; 6371BA8021EA767E00AB2A41 /* iOS.LaunchScreen.storyboard in Copy Template Files (without compilation step) */ = {isa = PBXBuildFile; fileRef = 6371BA6B21EA75AE00AB2A41 /* iOS.LaunchScreen.storyboard */; }; 63756DC32209E43100DA9D7B /* TemporaryDirectory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63756DAF2209E43100DA9D7B /* TemporaryDirectory.swift */; }; 6378B33E21B603D4000DC86B /* Menu·$CAKE.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6378B33D21B603D4000DC86B /* Menu·$CAKE.swift */; }; 63983C6721CAFE8C00487B21 /* Cake.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6378B34C21B606B8000DC86B /* Cake.a */; }; 63983CAD21CB0A9C00487B21 /* Cake.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6378B34C21B606B8000DC86B /* Cake.a */; }; 63B53DB121877F7800D863E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B53DB021877F7800D863E0 /* AppDelegate.swift */; }; 63B53DB521877F7900D863E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 63B53DB421877F7900D863E0 /* Assets.xcassets */; }; 63B53DB821877F7900D863E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 63B53DB621877F7900D863E0 /* Main.storyboard */; }; 63B53DD42187B3EC00D863E0 /* alert().swift in Sources */ = {isa = PBXBuildFile; fileRef = 63B53DD32187B3EC00D863E0 /* alert().swift */; }; 63C0A9EE2185614900A00C8E /* Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C0A9ED2185614900A00C8E /* Utility.swift */; }; 63C9152B22282ADD006492A3 /* Cake.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 63C9151222282ADC006492A3 /* Cake.xcconfig */; }; 63D49E3621BC81740023DB0E /* AppDelegate+NSMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D49E3521BC81740023DB0E /* AppDelegate+NSMenu.swift */; }; 63D7C3DB2208CA6C0096BF63 /* MixerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63D7C3DA2208CA6C0096BF63 /* MixerTests.swift */; }; 63DB0B9C220DC78F00CEF31A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63DB0B9B220DC78F00CEF31A /* main.swift */; }; 63DB0BB9220DCCBD00CEF31A /* cake-build in Copy `cake-build` */ = {isa = PBXBuildFile; fileRef = 63DB0B99220DC78F00CEF31A /* cake-build */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 63E342E9218508FA008CF796 /* ModelizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E342E8218508FA008CF796 /* ModelizerTests.swift */; }; 63EEA08C2188F2B70056E113 /* Menu·New Cake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EEA08B2188F2B70056E113 /* Menu·New Cake.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 632378E32215B4B000CA2E13 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 4F2CA03F28361DA2CD3C82B19DE28C91; remoteInfo = "Deps·HotKey"; }; 632B988721E5391F00FE1FAA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = B3CDEF324226D91C75D2BCBA3E3D7952; remoteInfo = "Cakefile·Completion"; }; 633E10ED21C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Batter·Base::Product"; remoteInfo = "Batter·Base"; }; 633E10EF21C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Batter·CakefileDescription::Product"; remoteInfo = "Batter·CakefileDescription"; }; 633E10F121C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Batter·Modelizer::Product"; remoteInfo = "Batter·Modelizer"; }; 633E10F921C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Deps·AEXML::Product"; remoteInfo = "Deps·AEXML"; }; 633E10FB21C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Deps·OrderedSet::Product"; remoteInfo = "Deps·OrderedSet"; }; 633E10FD21C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Deps·PathKit::Product"; remoteInfo = "Deps·PathKit"; }; 633E110121C17FAD00BF5956 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Deps·xcodeproj::Product"; remoteInfo = "Deps·xcodeproj"; }; 634604D321DDAC11009FF5A4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = C5744C074FEF959972A62160544D24F0; remoteInfo = "Batter·Processor"; }; 63537999220E83A4008449E9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 63E342C52185029C008CF796 /* Project object */; proxyType = 1; remoteGlobalIDString = 63537994220E8343008449E9; remoteInfo = mixer; }; 6366DAB921B73475009BD71D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Dependencies::Product"; remoteInfo = Dependencies; }; 636FB04E2210B62F007CE1CF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = FD62726177028C4BC3DCB2230AD84705; remoteInfo = "Deps·Version"; }; 6371BA7C21EA75AE00AB2A41 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = A49E0E264A02682CCE9A823B02A46706; remoteInfo = "Batter·Path"; }; 63730F3F21B704CE00F2F2AD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 1; remoteGlobalIDString = 8B942976617019A6C464818315598CC1; remoteInfo = Cake; }; 6378B34921B606B8000DC86B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Batter::Product"; remoteInfo = Batter; }; 6378B34B21B606B8000DC86B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = "Cake::Product"; remoteInfo = Cake; }; 63983C6421CAFE8800487B21 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 1; remoteGlobalIDString = 8B942976617019A6C464818315598CC1; remoteInfo = Cake; }; 63A0742921CDB35100FA09EA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 7F8732C7CBD899BD5F0398A832669E75; remoteInfo = "Batter·XcakeProject"; }; 63A0742B21CDB35100FA09EA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 937C922F7F6999DF1895EB3DC82906E9; remoteInfo = "Batter·XcodeProject"; }; 63A0742D21CDB35100FA09EA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = F9CD3F23A3EB056C8061881D18FBD601; remoteInfo = "Batter·XcodeObserver"; }; 63B66A7C21CD1DA300CAC566 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = BF52CA51D11D9A90EF84861A2B5938B1; remoteInfo = "Batter·Kitchen"; }; 63C9152922282ADC006492A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 19F01C205BDC9FA3129D8949BE2CB5C4; remoteInfo = "Deps·AppUpdater"; }; 63D6506722305A370088523B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 1; remoteGlobalIDString = DCF843C187E023E2097ACF9EABA93DD6; remoteInfo = Dependencies; }; 63DB0BB3220DC78F00CEF31A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 1DBCAEFF3AB28195D7B5E09B52FDBDA9; remoteInfo = "Deps·LegibleError"; }; 63DB0BB6220DC81D00CEF31A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 63E342C52185029C008CF796 /* Project object */; proxyType = 1; remoteGlobalIDString = 63DB0B98220DC78F00CEF31A; remoteInfo = "cake-build"; }; 63E99EF321F8AF68009B72CE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 69787F8145CACFA492EC131CC2A0AA1D; remoteInfo = "Deps·PMKFoundation"; }; 63E99EF521F8AF68009B72CE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; proxyType = 2; remoteGlobalIDString = 53E3B23BDD8E313D1CCE46BCBA847860; remoteInfo = "Deps·PromiseKit"; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 6371BA7F21EA767500AB2A41 /* Copy Template Files (without compilation step) */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 7; files = ( 6371BA8021EA767E00AB2A41 /* iOS.LaunchScreen.storyboard in Copy Template Files (without compilation step) */, ); name = "Copy Template Files (without compilation step)"; runOnlyForDeploymentPostprocessing = 0; }; 63DB0B97220DC78F00CEF31A /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 63DB0BB8220DCCAD00CEF31A /* Copy `cake-build` */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 6; files = ( 63DB0BB9220DCCBD00CEF31A /* cake-build in Copy `cake-build` */, ); name = "Copy `cake-build`"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 6307663121CE716600236F1C /* Menu·Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Menu·Xcode.swift"; sourceTree = ""; }; 632B98B921E63B2500FE1FAA /* Documents */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Documents; sourceTree = ""; }; 63402FA321B86FE3003F1B8E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 63402FC021B87602003F1B8E /* CakefileDescriptionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CakefileDescriptionTests.swift; sourceTree = ""; }; 6343042421858C7D004A45F0 /* XcakeprojTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcakeprojTests.swift; sourceTree = ""; }; 6371BA6B21EA75AE00AB2A41 /* iOS.LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = iOS.LaunchScreen.storyboard; sourceTree = ""; }; 63756DAF2209E43100DA9D7B /* TemporaryDirectory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TemporaryDirectory.swift; path = ../Sources/Model/Base/XcodeProject/XcakeProject/Processor/TemporaryDirectory.swift; sourceTree = ""; }; 6378B33D21B603D4000DC86B /* Menu·$CAKE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Menu·$CAKE.swift"; sourceTree = ""; }; 6378B33F21B606B7000DC86B /* Cake.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Cake.xcodeproj; path = .cake/Cake.xcodeproj; sourceTree = ""; }; 6378B35521B60700000DC86B /* Model */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Model; path = Sources/Model; sourceTree = ""; }; 639FB0D321BB179500DAE087 /* modelize().swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "modelize().swift"; path = "Sources/Mixer/Modelize/modelize().swift"; sourceTree = SOURCE_ROOT; }; 639FB0D421BB179500DAE087 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = main.swift; path = Sources/Mixer/main.swift; sourceTree = SOURCE_ROOT; }; 639FB0D521BB179500DAE087 /* etc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = etc.swift; path = Sources/Mixer/Mixer/etc.swift; sourceTree = SOURCE_ROOT; }; 63B53DAE21877F7800D863E0 /* Cake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Cake.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63B53DB021877F7800D863E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 63B53DB421877F7900D863E0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 63B53DB721877F7900D863E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63B53DB921877F7900D863E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63B53DD32187B3EC00D863E0 /* alert().swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "alert().swift"; sourceTree = ""; }; 63C0A9ED2185614900A00C8E /* Utility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utility.swift; sourceTree = ""; }; 63C9151222282ADC006492A3 /* Cake.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Cake.xcconfig; path = .cake/Cake.xcconfig; sourceTree = ""; }; 63D49D7921BC782A0023DB0E /* libSwiftPM.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libSwiftPM.dylib; sourceTree = ""; }; 63D49D7A21BC782A0023DB0E /* mixer */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = mixer; sourceTree = ""; }; 63D49E3521BC81740023DB0E /* AppDelegate+NSMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+NSMenu.swift"; sourceTree = ""; }; 63D7C3DA2208CA6C0096BF63 /* MixerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MixerTests.swift; sourceTree = ""; }; 63DB0B99220DC78F00CEF31A /* cake-build */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "cake-build"; sourceTree = BUILT_PRODUCTS_DIR; }; 63DB0B9B220DC78F00CEF31A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 63DB6E4D222ACF0700E69628 /* Cake.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Cake.entitlements; sourceTree = ""; }; 63E342E6218508FA008CF796 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63E342E8218508FA008CF796 /* ModelizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelizerTests.swift; sourceTree = ""; }; 63E342EA218508FA008CF796 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63EEA08B2188F2B70056E113 /* Menu·New Cake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Menu·New Cake.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 63B53DAB21877F7800D863E0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63983C6721CAFE8C00487B21 /* Cake.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DB0B96220DC78F00CEF31A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 63E342E3218508FA008CF796 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 63983CAD21CB0A9C00487B21 /* Cake.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 636FB05D2210B855007CE1CF /* Frameworks */ = { isa = PBXGroup; children = ( ); name = Frameworks; sourceTree = ""; }; 6371BA6A21EA75AE00AB2A41 /* Bundled Files */ = { isa = PBXGroup; children = ( 6371BA6B21EA75AE00AB2A41 /* iOS.LaunchScreen.storyboard */, ); path = "Bundled Files"; sourceTree = ""; }; 63756DC42209E43700DA9D7B /* Utility */ = { isa = PBXGroup; children = ( 63756DAF2209E43100DA9D7B /* TemporaryDirectory.swift */, 63C0A9ED2185614900A00C8E /* Utility.swift */, ); name = Utility; sourceTree = ""; }; 6378B34021B606B7000DC86B /* Products */ = { isa = PBXGroup; children = ( 632B988821E5391F00FE1FAA /* Cakefile·Completion */, 633E110221C17FAD00BF5956 /* xcodeproj.a */, 633E10FE21C17FAD00BF5956 /* PathKit.a */, 633E10FC21C17FAD00BF5956 /* OrderedSet.a */, 63DB0BB4220DC78F00CEF31A /* LegibleError.a */, 632378E42215B4B000CA2E13 /* HotKey.a */, 63C9152A22282ADC006492A3 /* AppUpdater.a */, 636FB04F2210B62F007CE1CF /* Version.a */, 6371BA7D21EA75AE00AB2A41 /* Path.a */, 63E99EF421F8AF68009B72CE /* PMKFoundation.a */, 63E99EF621F8AF68009B72CE /* PromiseKit.a */, 633E10FA21C17FAD00BF5956 /* AEXML.a */, 6366DABA21B73475009BD71D /* Dependencies.a */, 63B66A7D21CD1DA300CAC566 /* Kitchen.a */, 634604D421DDAC11009FF5A4 /* Processor.a */, 63A0742A21CDB35100FA09EA /* XcakeProject.a */, 63A0742C21CDB35100FA09EA /* XcodeProject.a */, 63A0742E21CDB35100FA09EA /* XcodeObserver.a */, 633E10F221C17FAD00BF5956 /* Modelizer.a */, 633E10EE21C17FAD00BF5956 /* Base.a */, 633E10F021C17FAD00BF5956 /* CakefileDescription.a */, 6378B34A21B606B8000DC86B /* Batter.a */, 6378B34C21B606B8000DC86B /* Cake.a */, ); name = Products; sourceTree = ""; }; 6378B3A021B60D54000DC86B /* Targets */ = { isa = PBXGroup; children = ( 63E342CF2185029C008CF796 /* AppKit */, 63DB0B9A220DC78F00CEF31A /* cake-build */, 639FB0CF21BB176300DAE087 /* Mixer */, ); name = Targets; path = Sources; sourceTree = ""; }; 639FB0CF21BB176300DAE087 /* Mixer */ = { isa = PBXGroup; children = ( 639FB0D421BB179500DAE087 /* main.swift */, 639FB0D521BB179500DAE087 /* etc.swift */, 639FB0D321BB179500DAE087 /* modelize().swift */, 639FB0DD21BB1BD100DAE087 /* Products */, ); path = Mixer; sourceTree = ""; }; 639FB0DD21BB1BD100DAE087 /* Products */ = { isa = PBXGroup; children = ( 63D49D7921BC782A0023DB0E /* libSwiftPM.dylib */, 63D49D7A21BC782A0023DB0E /* mixer */, ); name = Products; path = "Sources/Mixer/.build/x86_64-apple-macosx/debug"; sourceTree = SOURCE_ROOT; }; 63B53DC7218782A600D863E0 /* Detritus */ = { isa = PBXGroup; children = ( 63DB6E4D222ACF0700E69628 /* Cake.entitlements */, 63B53DB421877F7900D863E0 /* Assets.xcassets */, 63B53DB621877F7900D863E0 /* Main.storyboard */, 63B53DB921877F7900D863E0 /* Info.plist */, ); name = Detritus; sourceTree = ""; }; 63DB0B9A220DC78F00CEF31A /* cake-build */ = { isa = PBXGroup; children = ( 63DB0B9B220DC78F00CEF31A /* main.swift */, ); path = "cake-build"; sourceTree = ""; }; 63E342C42185029C008CF796 = { isa = PBXGroup; children = ( 63402FA321B86FE3003F1B8E /* README.md */, 6378B35521B60700000DC86B /* Model */, 632B98B921E63B2500FE1FAA /* Documents */, 6378B3A021B60D54000DC86B /* Targets */, 63E342E7218508FA008CF796 /* Tests */, 6378B33F21B606B7000DC86B /* Cake.xcodeproj */, 63C9151222282ADC006492A3 /* Cake.xcconfig */, 63E342CE2185029C008CF796 /* Products */, 636FB05D2210B855007CE1CF /* Frameworks */, ); sourceTree = ""; }; 63E342CE2185029C008CF796 /* Products */ = { isa = PBXGroup; children = ( 63E342E6218508FA008CF796 /* Tests.xctest */, 63B53DAE21877F7800D863E0 /* Cake.app */, 63DB0B99220DC78F00CEF31A /* cake-build */, ); name = Products; sourceTree = ""; }; 63E342CF2185029C008CF796 /* AppKit */ = { isa = PBXGroup; children = ( 63B53DB021877F7800D863E0 /* AppDelegate.swift */, 63D49E3521BC81740023DB0E /* AppDelegate+NSMenu.swift */, 6378B33D21B603D4000DC86B /* Menu·$CAKE.swift */, 63EEA08B2188F2B70056E113 /* Menu·New Cake.swift */, 6307663121CE716600236F1C /* Menu·Xcode.swift */, 63B53DD32187B3EC00D863E0 /* alert().swift */, 6371BA6A21EA75AE00AB2A41 /* Bundled Files */, 63B53DC7218782A600D863E0 /* Detritus */, ); path = AppKit; sourceTree = ""; }; 63E342E7218508FA008CF796 /* Tests */ = { isa = PBXGroup; children = ( 63D7C3DA2208CA6C0096BF63 /* MixerTests.swift */, 6343042421858C7D004A45F0 /* XcakeprojTests.swift */, 63E342E8218508FA008CF796 /* ModelizerTests.swift */, 63402FC021B87602003F1B8E /* CakefileDescriptionTests.swift */, 63756DC42209E43700DA9D7B /* Utility */, 63E342EA218508FA008CF796 /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 63B53DAD21877F7800D863E0 /* Cake.app */ = { isa = PBXNativeTarget; buildConfigurationList = 63B53DBB21877F7900D863E0 /* Build configuration list for PBXNativeTarget "Cake.app" */; buildPhases = ( 63B53DAA21877F7800D863E0 /* Sources */, 63B53DAB21877F7800D863E0 /* Frameworks */, 63B53DAC21877F7800D863E0 /* Resources */, 6371BA7F21EA767500AB2A41 /* Copy Template Files (without compilation step) */, 63DB0BB8220DCCAD00CEF31A /* Copy `cake-build` */, 633AA206220F2D8F004AB319 /* Copy & Fix Install Names for mixer */, 633860D42229ADE5005BED0E /* Kitchenware */, ); buildRules = ( ); dependencies = ( 63D6506822305A370088523B /* PBXTargetDependency */, 6353799A220E83A4008449E9 /* PBXTargetDependency */, 63983C6521CAFE8800487B21 /* PBXTargetDependency */, 63DB0BB7220DC81D00CEF31A /* PBXTargetDependency */, ); name = Cake.app; productName = Cake; productReference = 63B53DAE21877F7800D863E0 /* Cake.app */; productType = "com.apple.product-type.application"; }; 63DB0B98220DC78F00CEF31A /* cake-build */ = { isa = PBXNativeTarget; buildConfigurationList = 63DB0BB5220DC78F00CEF31A /* Build configuration list for PBXNativeTarget "cake-build" */; buildPhases = ( 63DB0B95220DC78F00CEF31A /* Sources */, 63DB0B96220DC78F00CEF31A /* Frameworks */, 63DB0B97220DC78F00CEF31A /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = "cake-build"; productName = "cake-build"; productReference = 63DB0B99220DC78F00CEF31A /* cake-build */; productType = "com.apple.product-type.tool"; }; 63E342E5218508FA008CF796 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 63E342EE218508FA008CF796 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 63E342E2218508FA008CF796 /* Sources */, 63E342E3218508FA008CF796 /* Frameworks */, ); buildRules = ( ); dependencies = ( 63730F4021B704CE00F2F2AD /* PBXTargetDependency */, ); name = Tests; productName = ModelizerTests; productReference = 63E342E6218508FA008CF796 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 63E342C52185029C008CF796 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1020; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Max Howell"; TargetAttributes = { 63537994220E8343008449E9 = { CreatedOnToolsVersion = 10.2; }; 63B53DAD21877F7800D863E0 = { CreatedOnToolsVersion = 10.0; SystemCapabilities = { com.apple.HardenedRuntime = { enabled = 1; }; com.apple.Sandbox = { enabled = 0; }; }; }; 63DB0B98220DC78F00CEF31A = { CreatedOnToolsVersion = 10.2; }; 63E342E5218508FA008CF796 = { CreatedOnToolsVersion = 10.0; }; }; }; buildConfigurationList = 63E342C82185029C008CF796 /* Build configuration list for PBXProject "Cake" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 63E342C42185029C008CF796; productRefGroup = 63E342CE2185029C008CF796 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = 6378B34021B606B7000DC86B /* Products */; ProjectRef = 6378B33F21B606B7000DC86B /* Cake.xcodeproj */; }, ); projectRoot = ""; targets = ( 63B53DAD21877F7800D863E0 /* Cake.app */, 63DB0B98220DC78F00CEF31A /* cake-build */, 63537994220E8343008449E9 /* mixer */, 63E342E5218508FA008CF796 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ 632378E42215B4B000CA2E13 /* HotKey.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = HotKey.a; path = libHotKey.a; remoteRef = 632378E32215B4B000CA2E13 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 632B988821E5391F00FE1FAA /* Cakefile·Completion */ = { isa = PBXReferenceProxy; fileType = text; name = "Cakefile·Completion"; path = CakefileScript; remoteRef = 632B988721E5391F00FE1FAA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10EE21C17FAD00BF5956 /* Base.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Base.a; path = libBase.a; remoteRef = 633E10ED21C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10F021C17FAD00BF5956 /* CakefileDescription.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = CakefileDescription.a; path = libCakefileDescription.a; remoteRef = 633E10EF21C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10F221C17FAD00BF5956 /* Modelizer.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Modelizer.a; path = libModelizer.a; remoteRef = 633E10F121C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10FA21C17FAD00BF5956 /* AEXML.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = AEXML.a; path = libAEXML.a; remoteRef = 633E10F921C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10FC21C17FAD00BF5956 /* OrderedSet.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = OrderedSet.a; path = libOrderedSet.a; remoteRef = 633E10FB21C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E10FE21C17FAD00BF5956 /* PathKit.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = PathKit.a; path = libPathKit.a; remoteRef = 633E10FD21C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 633E110221C17FAD00BF5956 /* xcodeproj.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = xcodeproj.a; path = libxcodeproj.a; remoteRef = 633E110121C17FAD00BF5956 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 634604D421DDAC11009FF5A4 /* Processor.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Processor.a; path = libProcessor.a; remoteRef = 634604D321DDAC11009FF5A4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 6366DABA21B73475009BD71D /* Dependencies.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Dependencies.a; path = libDependencies.a; remoteRef = 6366DAB921B73475009BD71D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 636FB04F2210B62F007CE1CF /* Version.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Version.a; path = libVersion.a; remoteRef = 636FB04E2210B62F007CE1CF /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 6371BA7D21EA75AE00AB2A41 /* Path.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Path.a; path = libPath.a; remoteRef = 6371BA7C21EA75AE00AB2A41 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 6378B34A21B606B8000DC86B /* Batter.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Batter.a; path = libBatter.a; remoteRef = 6378B34921B606B8000DC86B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 6378B34C21B606B8000DC86B /* Cake.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Cake.a; path = libCake.a; remoteRef = 6378B34B21B606B8000DC86B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63A0742A21CDB35100FA09EA /* XcakeProject.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = XcakeProject.a; path = libXcakeProject.a; remoteRef = 63A0742921CDB35100FA09EA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63A0742C21CDB35100FA09EA /* XcodeProject.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = XcodeProject.a; path = libXcodeProject.a; remoteRef = 63A0742B21CDB35100FA09EA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63A0742E21CDB35100FA09EA /* XcodeObserver.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = XcodeObserver.a; path = libXcodeObserver.a; remoteRef = 63A0742D21CDB35100FA09EA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63B66A7D21CD1DA300CAC566 /* Kitchen.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = Kitchen.a; path = libKitchen.a; remoteRef = 63B66A7C21CD1DA300CAC566 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63C9152A22282ADC006492A3 /* AppUpdater.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = AppUpdater.a; path = libAppUpdater.a; remoteRef = 63C9152922282ADC006492A3 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63DB0BB4220DC78F00CEF31A /* LegibleError.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = LegibleError.a; path = libLegibleError.a; remoteRef = 63DB0BB3220DC78F00CEF31A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63E99EF421F8AF68009B72CE /* PMKFoundation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = PMKFoundation.a; path = libPMKFoundation.a; remoteRef = 63E99EF321F8AF68009B72CE /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 63E99EF621F8AF68009B72CE /* PromiseKit.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; name = PromiseKit.a; path = libPromiseKit.a; remoteRef = 63E99EF521F8AF68009B72CE /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 63B53DAC21877F7800D863E0 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 63B53DB521877F7900D863E0 /* Assets.xcassets in Resources */, 63B53DB821877F7900D863E0 /* Main.storyboard in Resources */, 63C9152B22282ADD006492A3 /* Cake.xcconfig in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 633860D42229ADE5005BED0E /* Kitchenware */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = Kitchenware; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "set -euxo pipefail\n\nrm -rf \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH\"/Kitchenware\n\ncp -pR \"$PROJECT_DIR\"/Sources/Kitchenware \"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH\"\nsrc=\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH\"/Kitchenware/Sources\n\nmkdir \"$src\"\ncp -pR \"$PROJECT_DIR\"/Sources/Model/CakefileDescription \"$src\"/Cakefile\n\npkd=\"$OBJROOT\"/mixer.build/checkouts/swift-package-manager/Sources/PackageDescription4\ncp -pR \"$pkd\" \"$src\"/PackageDescription\n"; showEnvVarsInLog = 0; }; 633AA206220F2D8F004AB319 /* Copy & Fix Install Names for mixer */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "$(OBJROOT)/mixer.build/x86_64-apple-macosx/$(CONFIGURATION:lower)/mixer", "$(OBJROOT)/mixer.build/x86_64-apple-macosx/$(CONFIGURATION:lower)/libSwiftPM.dylib", ); name = "Copy & Fix Install Names for mixer"; outputFileListPaths = ( ); outputPaths = ( "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_FOLDER_PATH)/mixer", "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/libSwiftPM.dylib", "$(DERIVED_FILE_DIR)/mixer.done", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "set -exo pipefail\n\n# sigh\nrm -f \"$SCRIPT_OUTPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_1\"\n\ncp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\ncp \"$SCRIPT_INPUT_FILE_1\" \"$SCRIPT_OUTPUT_FILE_1\"\n\n# In CI we don’t code sign\nif [[ -n \"$EXPANDED_CODE_SIGN_IDENTITY\" ]]; then\n /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --preserve-metadata=identifier,entitlements,flags --timestamp=none \"$SCRIPT_OUTPUT_FILE_0\"\n /usr/bin/codesign --force --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" --preserve-metadata=identifier,entitlements,flags --timestamp=none \"$SCRIPT_OUTPUT_FILE_1\"\nfi\n\ninstall_name_tool -rpath \\\n \"$DT_TOOLCHAIN_DIR\"/usr/lib/swift/macosx \\\n @executable_path/../Frameworks \\\n \"$SCRIPT_OUTPUT_FILE_0\"\n\n#install_name_tool -rpath \\\n# \"$DT_TOOLCHAIN_DIR\"/usr/lib/swift/macosx \\\n# @executable_path/../Frameworks \\\n# \"$SCRIPT_OUTPUT_FILE_1\"\n# ^^ Xcode 10.2-beta4 stopped setting this rpath\n\ninstall_name_tool -change \\\n \"$SCRIPT_INPUT_FILE_1\" \\\n @rpath/$(basename \"$SCRIPT_INPUT_FILE_1\") \\\n \"$SCRIPT_OUTPUT_FILE_0\"\ninstall_name_tool -id \\\n @rpath/$(basename \"$SCRIPT_OUTPUT_FILE_1\") \\\n \"$SCRIPT_OUTPUT_FILE_1\"\n\n# build systems AMIRITE?\ntouch \"$SCRIPT_OUTPUT_FILE_2\" \n"; showEnvVarsInLog = 0; }; 63537998220E8350008449E9 /* swift build */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( ); name = "swift build"; outputFileListPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cd \"$PROJECT_DIR\"/Sources/Mixer\nconf=$(echo \"$CONFIGURATION\" | awk '{print tolower($0)}')\n\"$DT_TOOLCHAIN_DIR\"/usr/bin/swift build \\\n --configuration $conf \\\n --skip-update \\\n --disable-index-store \\\n -Xswiftc -suppress-warnings \\\n --build-path \"$OBJROOT\"/mixer.build\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 63B53DAA21877F7800D863E0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63B53DB121877F7800D863E0 /* AppDelegate.swift in Sources */, 63B53DD42187B3EC00D863E0 /* alert().swift in Sources */, 63D49E3621BC81740023DB0E /* AppDelegate+NSMenu.swift in Sources */, 6378B33E21B603D4000DC86B /* Menu·$CAKE.swift in Sources */, 6307663221CE716600236F1C /* Menu·Xcode.swift in Sources */, 63EEA08C2188F2B70056E113 /* Menu·New Cake.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63DB0B95220DC78F00CEF31A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63DB0B9C220DC78F00CEF31A /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 63E342E2218508FA008CF796 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 63756DC32209E43100DA9D7B /* TemporaryDirectory.swift in Sources */, 6343042521858C7D004A45F0 /* XcakeprojTests.swift in Sources */, 63402FC121B87602003F1B8E /* CakefileDescriptionTests.swift in Sources */, 63D7C3DB2208CA6C0096BF63 /* MixerTests.swift in Sources */, 63E342E9218508FA008CF796 /* ModelizerTests.swift in Sources */, 63C0A9EE2185614900A00C8E /* Utility.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 6353799A220E83A4008449E9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 63537994220E8343008449E9 /* mixer */; targetProxy = 63537999220E83A4008449E9 /* PBXContainerItemProxy */; }; 63730F4021B704CE00F2F2AD /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cake; targetProxy = 63730F3F21B704CE00F2F2AD /* PBXContainerItemProxy */; }; 63983C6521CAFE8800487B21 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Cake; targetProxy = 63983C6421CAFE8800487B21 /* PBXContainerItemProxy */; }; 63D6506822305A370088523B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Dependencies; targetProxy = 63D6506722305A370088523B /* PBXContainerItemProxy */; }; 63DB0BB7220DC81D00CEF31A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 63DB0B98220DC78F00CEF31A /* cake-build */; targetProxy = 63DB0BB6220DC81D00CEF31A /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 63B53DB621877F7900D863E0 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 63B53DB721877F7900D863E0 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 63537996220E8343008449E9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = TEQMQBRC7B; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 63537997220E8343008449E9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = TEQMQBRC7B; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 63B53DBC21877F7900D863E0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Sources/AppKit/Cake.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = TEQMQBRC7B; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Sources/AppKit/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = dev.mxcl.Cake; PRODUCT_MODULE_NAME = App; PRODUCT_NAME = Cake; SWIFT_VERSION = 5.0; }; name = Debug; }; 63B53DBD21877F7900D863E0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Sources/AppKit/Cake.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = TEQMQBRC7B; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Sources/AppKit/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = dev.mxcl.Cake; PRODUCT_MODULE_NAME = App; PRODUCT_NAME = Cake; SWIFT_VERSION = 5.0; }; name = Release; }; 63DB0B9D220DC78F00CEF31A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = TEQMQBRC7B; LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Debug; }; 63DB0B9E220DC78F00CEF31A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = TEQMQBRC7B; LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 63E342D22185029C008CF796 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 63C9151222282ADC006492A3 /* Cake.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = Debug; }; 63E342D32185029C008CF796 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 63C9151222282ADC006492A3 /* Cake.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; }; name = Release; }; 63E342EF218508FA008CF796 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = TEQMQBRC7B; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = dev.mxcl.ModelizerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Debug; }; 63E342F0218508FA008CF796 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = TEQMQBRC7B; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = dev.mxcl.ModelizerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 63537995220E8343008449E9 /* Build configuration list for PBXAggregateTarget "mixer" */ = { isa = XCConfigurationList; buildConfigurations = ( 63537996220E8343008449E9 /* Debug */, 63537997220E8343008449E9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63B53DBB21877F7900D863E0 /* Build configuration list for PBXNativeTarget "Cake.app" */ = { isa = XCConfigurationList; buildConfigurations = ( 63B53DBC21877F7900D863E0 /* Debug */, 63B53DBD21877F7900D863E0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63DB0BB5220DC78F00CEF31A /* Build configuration list for PBXNativeTarget "cake-build" */ = { isa = XCConfigurationList; buildConfigurations = ( 63DB0B9D220DC78F00CEF31A /* Debug */, 63DB0B9E220DC78F00CEF31A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63E342C82185029C008CF796 /* Build configuration list for PBXProject "Cake" */ = { isa = XCConfigurationList; buildConfigurations = ( 63E342D22185029C008CF796 /* Debug */, 63E342D32185029C008CF796 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 63E342EE218508FA008CF796 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 63E342EF218508FA008CF796 /* Debug */, 63E342F0218508FA008CF796 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 63E342C52185029C008CF796 /* Project object */; } ================================================ FILE: Cake.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Cake.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Cake.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Cake.xcodeproj/xcshareddata/xcschemes/Cake.xcscheme ================================================ ================================================ FILE: Cakefile.swift ================================================ import Cakefile dependencies = [ .cake(~>Version(1,0,0, prereleaseIdentifiers: ["debug"])), .github("Weebly/OrderedSet" ~> 3.1), .github("mxcl/PromiseKit" ~> 6.8), .github("mxcl/Path.swift" ~> 0.13), .github("PromiseKit/Foundation" ~> 3), .github("tuist/xcodeproj" ~> 6.5), .github("mxcl/LegibleError" ~> 1), .github("mxcl/Version" ~> 1), .github("soffes/HotKey" ~> 0.1), .github("mxcl/AppUpdater" ~> 1.0), ] options.suppressDependencyWarnings = true // this is the default ================================================ FILE: Dependencies/PromiseKit∕Foundation-3.3.1/NSNotificationCenter+Promise.swift ================================================ import Foundation #if !PMKCocoaPods import PromiseKit #endif /** To import the `NSNotificationCenter` category: use_frameworks! pod "PromiseKit/Foundation" Or `NSNotificationCenter` is one of the categories imported by the umbrella pod: use_frameworks! pod "PromiseKit" And then in your sources: import PromiseKit */ extension NotificationCenter { /// Observe the named notification once public func observe(once name: Notification.Name, object: Any? = nil) -> Guarantee { let (promise, fulfill) = Guarantee.pending() #if os(Linux) && ((swift(>=4.0) && !swift(>=4.0.1)) || (swift(>=3.0) && !swift(>=3.2.1))) let id = addObserver(forName: name, object: object, queue: nil, usingBlock: fulfill) #else let id = addObserver(forName: name, object: object, queue: nil, using: fulfill) #endif promise.done { _ in self.removeObserver(id) } return promise } } ================================================ FILE: Dependencies/PromiseKit∕Foundation-3.3.1/NSObject+Promise.swift ================================================ import Foundation #if !PMKCocoaPods import PromiseKit #endif /** To import the `NSObject` category: use_frameworks! pod "PromiseKit/Foundation" Or `NSObject` is one of the categories imported by the umbrella pod: use_frameworks! pod "PromiseKit" And then in your sources: import PromiseKit */ extension NSObject { /** - Returns: A promise that resolves when the provided keyPath changes. - Warning: *Important* The promise must not outlive the object under observation. - SeeAlso: Apple’s KVO documentation. */ public func observe(_: PMKNamespacer, keyPath: String) -> Guarantee { return Guarantee { KVOProxy(observee: self, keyPath: keyPath, resolve: $0) } } } private class KVOProxy: NSObject { var retainCycle: KVOProxy? let fulfill: (Any?) -> Void @discardableResult init(observee: NSObject, keyPath: String, resolve: @escaping (Any?) -> Void) { fulfill = resolve super.init() observee.addObserver(self, forKeyPath: keyPath, options: NSKeyValueObservingOptions.new, context: pointer) retainCycle = self } fileprivate override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if let change = change, context == pointer { defer { retainCycle = nil } fulfill(change[NSKeyValueChangeKey.newKey]) if let object = object as? NSObject, let keyPath = keyPath { object.removeObserver(self, forKeyPath: keyPath) } } } private lazy var pointer: UnsafeMutableRawPointer = { return Unmanaged.passUnretained(self).toOpaque() }() } ================================================ FILE: Dependencies/PromiseKit∕Foundation-3.3.1/NSURLSession+Promise.swift ================================================ import Foundation #if !PMKCocoaPods import PromiseKit #endif /** To import the `NSURLSession` category: use_frameworks! pod "PromiseKit/Foundation" Or `NSURLSession` is one of the categories imported by the umbrella pod: use_frameworks! pod "PromiseKit" And then in your sources: import PromiseKit */ extension URLSession { /** Example usage: firstly { URLSession.shared.dataTask(.promise, with: rq) }.compactMap { data, _ in try JSONSerialization.jsonObject(with: data) as? [String: Any] }.then { json in //… } We recommend the use of [OMGHTTPURLRQ] which allows you to construct correct REST requests: firstly { let rq = OMGHTTPURLRQ.POST(url, json: parameters) URLSession.shared.dataTask(.promise, with: rq) }.then { data, urlResponse in //… } We provide a convenience initializer for `String` specifically for this promise: firstly { URLSession.shared.dataTask(.promise, with: rq) }.compactMap(String.init).then { string in // decoded per the string encoding specified by the server }.then { string in print("response: string") } Other common types can be easily decoded using compactMap also: firstly { URLSession.shared.dataTask(.promise, with: rq) }.compactMap { UIImage(data: $0) }.then { self.imageView.image = $0 } Though if you do decode the image this way, we recommend inflating it on a background thread first as this will improve main thread performance when rendering the image: firstly { URLSession.shared.dataTask(.promise, with: rq) }.compactMap(on: QoS.userInitiated) { data, _ in guard let img = UIImage(data: data) else { return nil } _ = cgImage?.dataProvider?.data return img }.then { self.imageView.image = $0 } - Parameter convertible: A URL or URLRequest. - Returns: A promise that represents the URL request. - SeeAlso: [OMGHTTPURLRQ] - Remark: We deliberately don’t provide a `URLRequestConvertible` for `String` because in our experience, you should be explicit with this error path to make good apps. [OMGHTTPURLRQ]: https://github.com/mxcl/OMGHTTPURLRQ */ public func dataTask(_: PMKNamespacer, with convertible: URLRequestConvertible) -> Promise<(data: Data, response: URLResponse)> { return Promise { dataTask(with: convertible.pmkRequest, completionHandler: adapter($0)).resume() } } public func uploadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, from data: Data) -> Promise<(data: Data, response: URLResponse)> { return Promise { uploadTask(with: convertible.pmkRequest, from: data, completionHandler: adapter($0)).resume() } } public func uploadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, fromFile file: URL) -> Promise<(data: Data, response: URLResponse)> { return Promise { uploadTask(with: convertible.pmkRequest, fromFile: file, completionHandler: adapter($0)).resume() } } /// - Remark: we force a `to` parameter because Apple deletes the downloaded file immediately after the underyling completion handler returns. /// - Note: we do not create the destination directory for you, because we move the file with FileManager.moveItem which changes it behavior depending on the directory status of the URL you provide. So create your own directory first! public func downloadTask(_: PMKNamespacer, with convertible: URLRequestConvertible, to saveLocation: URL) -> Promise<(saveLocation: URL, response: URLResponse)> { return Promise { seal in downloadTask(with: convertible.pmkRequest, completionHandler: { tmp, rsp, err in if let error = err { seal.reject(error) } else if let rsp = rsp, let tmp = tmp { do { try FileManager.default.moveItem(at: tmp, to: saveLocation) seal.fulfill((saveLocation, rsp)) } catch { seal.reject(error) } } else { seal.reject(PMKError.invalidCallingConvention) } }).resume() } } } public protocol URLRequestConvertible { var pmkRequest: URLRequest { get } } extension URLRequest: URLRequestConvertible { public var pmkRequest: URLRequest { return self } } extension URL: URLRequestConvertible { public var pmkRequest: URLRequest { return URLRequest(url: self) } } #if !os(Linux) public extension String { /** - Remark: useful when converting a `URLSession` response into a `String` firstly { URLSession.shared.dataTask(.promise, with: rq) }.map(String.init).done { print($0) } */ init?(data: Data, urlResponse: URLResponse) { guard let str = String(bytes: data, encoding: urlResponse.stringEncoding ?? .utf8) else { return nil } self.init(str) } } private extension URLResponse { var stringEncoding: String.Encoding? { guard let encodingName = textEncodingName else { return nil } let encoding = CFStringConvertIANACharSetNameToEncoding(encodingName as CFString) guard encoding != kCFStringEncodingInvalidId else { return nil } return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(encoding)) } } #endif private func adapter(_ seal: Resolver<(data: T, response: U)>) -> (T?, U?, Error?) -> Void { return { t, u, e in if let t = t, let u = u { seal.fulfill((t, u)) } else if let e = e { seal.reject(e) } else { seal.reject(PMKError.invalidCallingConvention) } } } #if swift(>=3.1) public enum PMKHTTPError: Error, LocalizedError, CustomStringConvertible { case badStatusCode(Int, Data, HTTPURLResponse) public var errorDescription: String? { func url(_ rsp: URLResponse) -> String { return rsp.url?.absoluteString ?? "nil" } switch self { case .badStatusCode(401, _, let response): return "Unauthorized (\(url(response))" case .badStatusCode(let code, _, let response): return "Invalid HTTP response (\(code)) for \(url(response))." } } #if swift(>=4.0) public func decodeResponse(_ t: T.Type, decoder: JSONDecoder = JSONDecoder()) -> T? { switch self { case .badStatusCode(_, let data, _): return try? decoder.decode(t, from: data) } } #endif //TODO rename responseJSON public var jsonDictionary: Any? { switch self { case .badStatusCode(_, let data, _): return try? JSONSerialization.jsonObject(with: data) } } var responseBodyString: String? { switch self { case .badStatusCode(_, let data, _): return String(data: data, encoding: .utf8) } } public var failureReason: String? { return responseBodyString } public var description: String { switch self { case .badStatusCode(let code, let data, let response): var dict: [String: Any] = [ "Status Code": code, "Body": String(data: data, encoding: .utf8) ?? "\(data.count) bytes" ] dict["URL"] = response.url dict["Headers"] = response.allHeaderFields return " \(NSDictionary(dictionary: dict))" // as NSDictionary makes the output look like NSHTTPURLResponse looks } } } public extension Promise where T == (data: Data, response: URLResponse) { func validate() -> Promise { return map { guard let response = $0.response as? HTTPURLResponse else { return $0 } switch response.statusCode { case 200..<300: return $0 case let code: throw PMKHTTPError.badStatusCode(code, $0.data, response) } } } } #endif ================================================ FILE: Dependencies/PromiseKit∕Foundation-3.3.1/Process+Promise.swift ================================================ import Foundation #if !PMKCocoaPods import PromiseKit #endif #if os(macOS) /** To import the `Process` category: use_frameworks! pod "PromiseKit/Foundation" Or `Process` is one of the categories imported by the umbrella pod: use_frameworks! pod "PromiseKit" And then in your sources: import PromiseKit */ extension Process { /** Launches the receiver and resolves when it exits. let proc = Process() proc.launchPath = "/bin/ls" proc.arguments = ["/bin"] proc.launch(.promise).compactMap { std in String(data: std.out.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) }.then { stdout in print(str) } */ public func launch(_: PMKNamespacer) -> Promise<(out: Pipe, err: Pipe)> { let (stdout, stderr) = (Pipe(), Pipe()) do { standardOutput = stdout standardError = stderr #if swift(>=4.0) if #available(OSX 10.13, *) { try run() } else if let path = launchPath, FileManager.default.isExecutableFile(atPath: path) { launch() } else { throw PMKError.notExecutable(launchPath) } #else guard let path = launchPath, FileManager.default.isExecutableFile(atPath: path) else { throw PMKError.notExecutable(launchPath) } launch() #endif } catch { return Promise(error: error) } var q: DispatchQueue { if #available(macOS 10.10, iOS 8.0, tvOS 9.0, watchOS 2.0, *) { return DispatchQueue.global(qos: .default) } else { return DispatchQueue.global(priority: .default) } } return Promise { seal in q.async { self.waitUntilExit() guard self.terminationReason == .exit, self.terminationStatus == 0 else { let stdoutData = try? self.readDataFromPipe(stdout) let stderrData = try? self.readDataFromPipe(stderr) let stdoutString = stdoutData.flatMap { (data: Data) -> String? in String(data: data, encoding: .utf8) } let stderrString = stderrData.flatMap { (data: Data) -> String? in String(data: data, encoding: .utf8) } return seal.reject(PMKError.execution(process: self, standardOutput: stdoutString, standardError: stderrString)) } seal.fulfill((stdout, stderr)) } } } private func readDataFromPipe(_ pipe: Pipe) throws -> Data { let handle = pipe.fileHandleForReading defer { handle.closeFile() } // Someday, NSFileHandle will probably be updated with throwing equivalents to its read and write methods, // as NSTask has, to avoid raising exceptions and crashing the app. // Unfortunately that day has not yet come, so use the underlying BSD calls for now. let fd = handle.fileDescriptor let bufsize = 1024 * 8 let buf = UnsafeMutablePointer.allocate(capacity: bufsize) #if swift(>=4.1) defer { buf.deallocate() } #else defer { buf.deallocate(capacity: bufsize) } #endif var data = Data() while true { let bytesRead = read(fd, buf, bufsize) if bytesRead == 0 { break } if bytesRead < 0 { throw POSIXError.Code(rawValue: errno).map { POSIXError($0) } ?? CocoaError(.fileReadUnknown) } data.append(buf, count: bytesRead) } return data } /** The error generated by PromiseKit’s `Process` extension */ public enum PMKError { /// NOT AVAILABLE ON 10.13 and above because Apple provide this error handling themselves case notExecutable(String?) case execution(process: Process, standardOutput: String?, standardError: String?) } } extension Process.PMKError: LocalizedError { public var errorDescription: String? { switch self { case .notExecutable(let path?): return "File not executable: \(path)" case .notExecutable(nil): return "No launch path specified" case .execution(process: let task, standardOutput: _, standardError: _): return "Failed executing: `\(task)` (\(task.terminationStatus))." } } } public extension Promise where T == (out: Pipe, err: Pipe) { func print() -> Promise { return tap { result in switch result { case .fulfilled(let raw): let stdout = String(data: raw.out.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) let stderr = String(data: raw.err.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) Swift.print("stdout: `\(stdout ?? "")`") Swift.print("stderr: `\(stderr ?? "")`") case .rejected(let err): Swift.print(err) } } } } extension Process { /// Provided because Foundation’s is USELESS open override var description: String { let launchPath = self.launchPath ?? "$0" var args = [launchPath] arguments.flatMap{ args += $0 } return args.map { arg in let contains: Bool #if swift(>=3.2) contains = arg.contains(" ") #else contains = arg.characters.contains(" ") #endif if contains { return "\"\(arg)\"" } else if arg == "" { return "\"\"" } else { return arg } }.joined(separator: " ") } } #endif ================================================ FILE: Dependencies/PromiseKit∕Foundation-3.3.1/afterlife.swift ================================================ import Foundation #if !PMKCocoaPods import PromiseKit #endif /** - Returns: A promise that resolves when the provided object deallocates - Important: The promise is not guarenteed to resolve immediately when the provided object is deallocated. So you cannot write code that depends on exact timing. */ public func after(life object: NSObject) -> Guarantee { var reaper = objc_getAssociatedObject(object, &handle) as? GrimReaper if reaper == nil { reaper = GrimReaper() objc_setAssociatedObject(object, &handle, reaper, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } return reaper!.promise } private var handle: UInt8 = 0 private class GrimReaper: NSObject { deinit { fulfill(()) } let (promise, fulfill) = Guarantee.pending() } ================================================ FILE: Dependencies/Weebly∕OrderedSet-3.1.0.swift ================================================ // Copyright (c) 2014 James Richard. // Distributed under the MIT License (http://opensource.org/licenses/MIT). /// An ordered, unique collection of objects. public class OrderedSet { fileprivate var contents = [T: Index]() // Needs to have a value of Index instead of Void for fast removals fileprivate var sequencedContents = [UnsafeMutablePointer]() /** Inititalizes an empty ordered set. - returns: An empty ordered set. */ public init() { } deinit { removeAllObjects() } /** Initializes a new ordered set with the order and contents of sequence. If an object appears more than once in the sequence it will only appear once in the ordered set, at the position of its first occurance. - parameter sequence: The sequence to initialize the ordered set with. - returns: An initialized ordered set with the contents of sequence. */ public init(sequence: S) where S.Iterator.Element == T { for object in sequence where contents[object] == nil { contents[object] = contents.count let pointer = UnsafeMutablePointer.allocate(capacity: 1) pointer.initialize(to: object) sequencedContents.append(pointer) } } public required init(arrayLiteral elements: T...) { for object in elements where contents[object] == nil { contents[object] = contents.count let pointer = UnsafeMutablePointer.allocate(capacity: 1) pointer.initialize(to: object) sequencedContents.append(pointer) } } /** Locate the index of an object in the ordered set. It is preferable to use this method over the global find() for performance reasons. - parameter object: The object to find the index for. - returns: The index of the object, or nil if the object is not in the ordered set. */ public func index(of object: T) -> Index? { if let index = contents[object] { return index } return nil } /** Appends an object to the end of the ordered set. - parameter object: The object to be appended. */ public func append(_ object: T) { if let lastIndex = index(of: object) { remove(object) insert(object, at: lastIndex) } else { contents[object] = contents.count let pointer = UnsafeMutablePointer.allocate(capacity: 1) pointer.initialize(to: object) sequencedContents.append(pointer) } } /** Appends a sequence of objects to the end of the ordered set. - parameter sequence: The sequence of objects to be appended. */ public func append(contentsOf sequence: S) where S.Iterator.Element == T { var gen = sequence.makeIterator() while let object: T = gen.next() { append(object) } } /** Removes an object from the ordered set. If the object exists in the ordered set, it will be removed. If it is not the last object in the ordered set, subsequent objects will be shifted down one position. - parameter object: The object to be removed. - returns: The former index position of the object. */ @discardableResult public func remove(_ object: T) -> Index? { if let index = contents[object] { contents[object] = nil sequencedContents[index].deinitialize(count: 1) sequencedContents[index].deallocate() sequencedContents.remove(at: index) for (object, i) in contents { if i < index { continue } contents[object] = i - 1 } return index } return nil } /** Removes the given objects from the ordered set. - parameter objects: The objects to be removed. - returns: A collection of the former index positions of the objects. An index position is not provided for objects that were not found. */ @discardableResult public func remove(_ objects: S) -> [Index]? where S.Iterator.Element == T { var indexes = [Index]() objects.forEach { object in if let index = index(of: object) { indexes.append(index) } } var gen = objects.makeIterator() while let object: T = gen.next() { remove(object) } return indexes } /** Removes an object at a given index. This method will cause a fatal error if you attempt to move an object to an index that is out of bounds. - parameter index: The index of the object to be removed. */ public func removeObject(at index: Index) { if index < 0 || index >= count { fatalError("Attempting to remove an object at an index that does not exist") } remove(sequencedContents[index].pointee) } /** Removes all objects in the ordered set. */ public func removeAllObjects() { contents.removeAll() for sequencedContent in sequencedContents { sequencedContent.deinitialize(count: 1) sequencedContent.deallocate() } sequencedContents.removeAll() } /** Swaps two objects contained within the ordered set. Both objects must exist within the set, or the swap will not occur. - parameter first: The first object to be swapped. - parameter second: The second object to be swapped. */ public func swapObject(_ first: T, with second: T) { if let firstPosition = contents[first] { if let secondPosition = contents[second] { contents[first] = secondPosition contents[second] = firstPosition sequencedContents[firstPosition].pointee = second sequencedContents[secondPosition].pointee = first } } } /** Tests if the ordered set contains any objects within a sequence. - parameter other: The sequence to look for the intersection in. - returns: Returns true if the sequence and set contain any equal objects, otherwise false. */ public func intersects(_ other: S) -> Bool where S.Iterator.Element == T { var gen = other.makeIterator() while let object: T = gen.next() { if contains(object) { return true } } return false } /** Tests if a the ordered set is a subset of another sequence. - parameter sequence: The sequence to check. - returns: true if the sequence contains all objects contained in the receiver, otherwise false. */ public func isSubset(of sequence: S) -> Bool where S.Iterator.Element == T { for (object, _) in contents { if !sequence.contains(object) { return false } } return true } /** Moves an object to a different index, shifting all objects in between the movement. This method is a no-op if the object doesn't exist in the set or the index is the same that the object is currently at. This method will cause a fatal error if you attempt to move an object to an index that is out of bounds. - parameter object: The object to be moved - parameter index: The index that the object should be moved to. */ public func moveObject(_ object: T, toIndex index: Index) { if index < 0 || index >= count { fatalError("Attempting to move an object at an index that does not exist") } if let position = contents[object] { // Return if the client attempted to move to the current index if position == index { return } let adjustment = position > index ? -1 : 1 var currentIndex = position while currentIndex != index { let nextIndex = currentIndex + adjustment let firstObject = sequencedContents[currentIndex].pointee let secondObject = sequencedContents[nextIndex].pointee sequencedContents[currentIndex].pointee = secondObject sequencedContents[nextIndex].pointee = firstObject contents[firstObject] = nextIndex contents[secondObject] = currentIndex currentIndex += adjustment } } } /** Moves an object from one index to a different index, shifting all objects in between the movement. This method is a no-op if the index is the same that the object is currently at. This method will cause a fatal error if you attempt to move an object fro man index that is out of bounds or to an index that is out of bounds. - parameter index: The index of the object to be moved. - parameter toIndex: The index that the object should be moved to. */ public func moveObject(at index: Index, to toIndex: Index) { if (index < 0 || index >= count) || (toIndex < 0 || toIndex >= count) { fatalError("Attempting to move an object at or to an index that does not exist") } moveObject(self[index], toIndex: toIndex) } /** Inserts an object at a given index, shifting all objects above it up one. This method will cause a fatal error if you attempt to insert the object out of bounds. If the object already exists in the OrderedSet, this operation is a no-op. - parameter object: The object to be inserted. - parameter index: The index to be inserted at. */ public func insert(_ object: T, at index: Index) { if index > count || index < 0 { fatalError("Attempting to insert an object at an index that does not exist") } if contents[object] != nil { return } // Append our object, then swap them until its at the end. append(object) for i in (index..(_ objects: S, at index: Index) where S.Iterator.Element == T { if index > count || index < 0 { fatalError("Attempting to insert an object at an index that does not exist") } var addedObjectCount = 0 for object in objects where contents[object] == nil { let seqIdx = index + addedObjectCount let element = UnsafeMutablePointer.allocate(capacity: 1) element.initialize(to: object) sequencedContents.insert(element, at: seqIdx) contents[object] = seqIdx addedObjectCount += 1 } // Now we'll remove duplicates and update the shifted objects position in the contents // dictionary. for i in index + addedObjectCount.. OrderedSet { return OrderedSet(sequence: self) } /// Returns the last object in the set, or `nil` if the set is empty. public var last: T? { return sequencedContents.last?.pointee } } extension OrderedSet: ExpressibleByArrayLiteral { } extension OrderedSet where T: Comparable {} extension OrderedSet { public var count: Int { return contents.count } public var isEmpty: Bool { return count == 0 } public var first: T? { guard count > 0 else { return nil } return sequencedContents[0].pointee } public func index(after index: Int) -> Int { return sequencedContents.index(after: index) } public typealias Index = Int public var startIndex: Int { return 0 } public var endIndex: Int { return contents.count } public subscript(index: Index) -> T { get { return sequencedContents[index].pointee } set { let previousCount = contents.count contents[sequencedContents[index].pointee] = nil contents[newValue] = index // If the count is reduced we used an existing value, and need to sync up sequencedContents if contents.count == previousCount { sequencedContents[index].pointee = newValue } else { sequencedContents[index].deinitialize(count: 1) sequencedContents[index].deallocate() sequencedContents.remove(at: index) } } } } extension OrderedSet: Sequence { public typealias Iterator = OrderedSetGenerator public func makeIterator() -> Iterator { return OrderedSetGenerator(set: self) } } public struct OrderedSetGenerator: IteratorProtocol { public typealias Element = T private var generator: IndexingIterator<[UnsafeMutablePointer]> public init(set: OrderedSet) { generator = set.sequencedContents.makeIterator() } public mutating func next() -> Element? { return generator.next()?.pointee } } extension OrderedSetGenerator where T: Comparable {} public func + (lhs: OrderedSet, rhs: S) -> OrderedSet where S.Element == T { let joinedSet = lhs.copy() joinedSet.append(contentsOf: rhs) return joinedSet } public func += (lhs: inout OrderedSet, rhs: S) where S.Element == T { lhs.append(contentsOf: rhs) } public func - (lhs: OrderedSet, rhs: S) -> OrderedSet where S.Element == T { let purgedSet = lhs.copy() purgedSet.remove(rhs) return purgedSet } public func -= (lhs: inout OrderedSet, rhs: S) where S.Element == T { lhs.remove(rhs) } extension OrderedSet: Equatable { } public func == (lhs: OrderedSet, rhs: OrderedSet) -> Bool { if lhs.count != rhs.count { return false } for object in lhs where lhs.contents[object] != rhs.contents[object] { return false } return true } extension OrderedSet: CustomStringConvertible { public var description: String { let children = map({ "\($0)" }).joined(separator: ", ") return "OrderedSet (\(count) object(s)): [\(children)]" } } ================================================ FILE: Dependencies/kylef∕PathKit-0.9.2.swift ================================================ // PathKit - Effortless path operations #if os(Linux) import Glibc let system_glob = Glibc.glob #else import Darwin let system_glob = Darwin.glob #endif import Foundation /// Represents a filesystem path. public struct Path { /// The character used by the OS to separate two path elements public static let separator = "/" /// The underlying string representation internal var path: String internal static var fileManager = FileManager.default internal var fileSystemInfo: FileSystemInfo = DefaultFileSystemInfo() // MARK: Init public init() { self.path = "" } /// Create a Path from a given String public init(_ path: String) { self.path = path } /// Create a Path by joining multiple path components together public init(components: S) where S.Iterator.Element == String { if components.isEmpty { path = "." } else if components.first == Path.separator && components.count > 1 { let p = components.joined(separator: Path.separator) path = String(p[p.index(after: p.startIndex)...]) } else { path = components.joined(separator: Path.separator) } } } // MARK: StringLiteralConvertible extension Path : ExpressibleByStringLiteral { public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType public typealias UnicodeScalarLiteralType = StringLiteralType public init(extendedGraphemeClusterLiteral path: StringLiteralType) { self.init(stringLiteral: path) } public init(unicodeScalarLiteral path: StringLiteralType) { self.init(stringLiteral: path) } public init(stringLiteral value: StringLiteralType) { self.path = value } } // MARK: CustomStringConvertible extension Path : CustomStringConvertible { public var description: String { return self.path } } // MARK: Conversion extension Path { public var string: String { return self.path } public var url: URL { return URL(fileURLWithPath: path) } } // MARK: Hashable extension Path : Hashable { public var hashValue: Int { return path.hashValue } } // MARK: Path Info extension Path { /// Test whether a path is absolute. /// /// - Returns: `true` iff the path begings with a slash /// public var isAbsolute: Bool { return path.hasPrefix(Path.separator) } /// Test whether a path is relative. /// /// - Returns: `true` iff a path is relative (not absolute) /// public var isRelative: Bool { return !isAbsolute } /// Concatenates relative paths to the current directory and derives the normalized path /// /// - Returns: the absolute path in the actual filesystem /// public func absolute() -> Path { if isAbsolute { return normalize() } let expandedPath = Path(NSString(string: self.path).expandingTildeInPath) if expandedPath.isAbsolute { return expandedPath.normalize() } return (Path.current + self).normalize() } /// Normalizes the path, this cleans up redundant ".." and ".", double slashes /// and resolves "~". /// /// - Returns: a new path made by removing extraneous path components from the underlying String /// representation. /// public func normalize() -> Path { return Path(NSString(string: self.path).standardizingPath) } /// De-normalizes the path, by replacing the current user home directory with "~". /// /// - Returns: a new path made by removing extraneous path components from the underlying String /// representation. /// public func abbreviate() -> Path { let rangeOptions: String.CompareOptions = fileSystemInfo.isFSCaseSensitiveAt(path: self) ? [.anchored] : [.anchored, .caseInsensitive] let home = Path.home.string guard let homeRange = self.path.range(of: home, options: rangeOptions) else { return self } let withoutHome = Path(self.path.replacingCharacters(in: homeRange, with: "")) if withoutHome.path.isEmpty || withoutHome.path == Path.separator { return Path("~") } else if withoutHome.isAbsolute { return Path("~" + withoutHome.path) } else { return Path("~") + withoutHome.path } } /// Returns the path of the item pointed to by a symbolic link. /// /// - Returns: the path of directory or file to which the symbolic link refers /// public func symlinkDestination() throws -> Path { let symlinkDestination = try Path.fileManager.destinationOfSymbolicLink(atPath: path) let symlinkPath = Path(symlinkDestination) if symlinkPath.isRelative { return self + ".." + symlinkPath } else { return symlinkPath } } } internal protocol FileSystemInfo { func isFSCaseSensitiveAt(path: Path) -> Bool } internal struct DefaultFileSystemInfo: FileSystemInfo { func isFSCaseSensitiveAt(path: Path) -> Bool { #if os(Linux) // URL resourceValues(forKeys:) is not supported on non-darwin platforms... // But we can (fairly?) safely assume for now that the Linux FS is case sensitive. // TODO: refactor when/if resourceValues is available, or look into using something // like stat or pathconf to determine if the mountpoint is case sensitive. return true #else var isCaseSensitive = false // Calling resourceValues will fail if the path does not exist on the filesystem, which // makes sense, but means we can only guarantee the return value is correct if the // path actually exists. if let resourceValues = try? path.url.resourceValues(forKeys: [.volumeSupportsCaseSensitiveNamesKey]) { isCaseSensitive = resourceValues.volumeSupportsCaseSensitiveNames ?? isCaseSensitive } return isCaseSensitive #endif } } // MARK: Path Components extension Path { /// The last path component /// /// - Returns: the last path component /// public var lastComponent: String { return NSString(string: path).lastPathComponent } /// The last path component without file extension /// /// - Note: This returns "." for ".." on Linux, and ".." on Apple platforms. /// /// - Returns: the last path component without file extension /// public var lastComponentWithoutExtension: String { return NSString(string: lastComponent).deletingPathExtension } /// Splits the string representation on the directory separator. /// Absolute paths remain the leading slash as first component. /// /// - Returns: all path components /// public var components: [String] { return NSString(string: path).pathComponents } /// The file extension behind the last dot of the last component. /// /// - Returns: the file extension /// public var `extension`: String? { let pathExtension = NSString(string: path).pathExtension if pathExtension.isEmpty { return nil } return pathExtension } } // MARK: File Info extension Path { /// Test whether a file or directory exists at a specified path /// /// - Returns: `false` iff the path doesn't exist on disk or its existence could not be /// determined /// public var exists: Bool { return Path.fileManager.fileExists(atPath: self.path) } /// Test whether a path is a directory. /// /// - Returns: `true` if the path is a directory or a symbolic link that points to a directory; /// `false` if the path is not a directory or the path doesn't exist on disk or its existence /// could not be determined /// public var isDirectory: Bool { var directory = ObjCBool(false) guard Path.fileManager.fileExists(atPath: normalize().path, isDirectory: &directory) else { return false } #if !os(Linux) || swift(>=4.1) return directory.boolValue #else return directory #endif } /// Test whether a path is a regular file. /// /// - Returns: `true` if the path is neither a directory nor a symbolic link that points to a /// directory; `false` if the path is a directory or a symbolic link that points to a /// directory or the path doesn't exist on disk or its existence /// could not be determined /// public var isFile: Bool { var directory = ObjCBool(false) guard Path.fileManager.fileExists(atPath: normalize().path, isDirectory: &directory) else { return false } #if !os(Linux) || swift(>=4.1) return !directory.boolValue #else return !directory #endif } /// Test whether a path is a symbolic link. /// /// - Returns: `true` if the path is a symbolic link; `false` if the path doesn't exist on disk /// or its existence could not be determined /// public var isSymlink: Bool { do { let _ = try Path.fileManager.destinationOfSymbolicLink(atPath: path) return true } catch { return false } } /// Test whether a path is readable /// /// - Returns: `true` if the current process has read privileges for the file at path; /// otherwise `false` if the process does not have read privileges or the existence of the /// file could not be determined. /// public var isReadable: Bool { return Path.fileManager.isReadableFile(atPath: self.path) } /// Test whether a path is writeable /// /// - Returns: `true` if the current process has write privileges for the file at path; /// otherwise `false` if the process does not have write privileges or the existence of the /// file could not be determined. /// public var isWritable: Bool { return Path.fileManager.isWritableFile(atPath: self.path) } /// Test whether a path is executable /// /// - Returns: `true` if the current process has execute privileges for the file at path; /// otherwise `false` if the process does not have execute privileges or the existence of the /// file could not be determined. /// public var isExecutable: Bool { return Path.fileManager.isExecutableFile(atPath: self.path) } /// Test whether a path is deletable /// /// - Returns: `true` if the current process has delete privileges for the file at path; /// otherwise `false` if the process does not have delete privileges or the existence of the /// file could not be determined. /// public var isDeletable: Bool { return Path.fileManager.isDeletableFile(atPath: self.path) } } // MARK: File Manipulation extension Path { /// Create the directory. /// /// - Note: This method fails if any of the intermediate parent directories does not exist. /// This method also fails if any of the intermediate path elements corresponds to a file and /// not a directory. /// public func mkdir() throws -> () { try Path.fileManager.createDirectory(atPath: self.path, withIntermediateDirectories: false, attributes: nil) } /// Create the directory and any intermediate parent directories that do not exist. /// /// - Note: This method fails if any of the intermediate path elements corresponds to a file and /// not a directory. /// public func mkpath() throws -> () { try Path.fileManager.createDirectory(atPath: self.path, withIntermediateDirectories: true, attributes: nil) } /// Delete the file or directory. /// /// - Note: If the path specifies a directory, the contents of that directory are recursively /// removed. /// public func delete() throws -> () { try Path.fileManager.removeItem(atPath: self.path) } /// Move the file or directory to a new location synchronously. /// /// - Parameter destination: The new path. This path must include the name of the file or /// directory in its new location. /// public func move(_ destination: Path) throws -> () { try Path.fileManager.moveItem(atPath: self.path, toPath: destination.path) } /// Copy the file or directory to a new location synchronously. /// /// - Parameter destination: The new path. This path must include the name of the file or /// directory in its new location. /// public func copy(_ destination: Path) throws -> () { try Path.fileManager.copyItem(atPath: self.path, toPath: destination.path) } /// Creates a hard link at a new destination. /// /// - Parameter destination: The location where the link will be created. /// public func link(_ destination: Path) throws -> () { try Path.fileManager.linkItem(atPath: self.path, toPath: destination.path) } /// Creates a symbolic link at a new destination. /// /// - Parameter destintation: The location where the link will be created. /// public func symlink(_ destination: Path) throws -> () { try Path.fileManager.createSymbolicLink(atPath: self.path, withDestinationPath: destination.path) } } // MARK: Current Directory extension Path { /// The current working directory of the process /// /// - Returns: the current working directory of the process /// public static var current: Path { get { return self.init(Path.fileManager.currentDirectoryPath) } set { _ = Path.fileManager.changeCurrentDirectoryPath(newValue.description) } } /// Changes the current working directory of the process to the path during the execution of the /// given block. /// /// - Note: The original working directory is restored when the block returns or throws. /// - Parameter closure: A closure to be executed while the current directory is configured to /// the path. /// public func chdir(closure: () throws -> ()) rethrows { let previous = Path.current Path.current = self defer { Path.current = previous } try closure() } } // MARK: Temporary extension Path { /// - Returns: the path to either the user’s or application’s home directory, /// depending on the platform. /// public static var home: Path { return Path(NSHomeDirectory()) } /// - Returns: the path of the temporary directory for the current user. /// public static var temporary: Path { return Path(NSTemporaryDirectory()) } /// - Returns: the path of a temporary directory unique for the process. /// - Note: Based on `NSProcessInfo.globallyUniqueString`. /// public static func processUniqueTemporary() throws -> Path { let path = temporary + ProcessInfo.processInfo.globallyUniqueString if !path.exists { try path.mkdir() } return path } /// - Returns: the path of a temporary directory unique for each call. /// - Note: Based on `NSUUID`. /// public static func uniqueTemporary() throws -> Path { let path = try processUniqueTemporary() + UUID().uuidString try path.mkdir() return path } } // MARK: Contents extension Path { /// Reads the file. /// /// - Returns: the contents of the file at the specified path. /// public func read() throws -> Data { return try Data(contentsOf: self.url, options: NSData.ReadingOptions(rawValue: 0)) } /// Reads the file contents and encoded its bytes to string applying the given encoding. /// /// - Parameter encoding: the encoding which should be used to decode the data. /// (by default: `NSUTF8StringEncoding`) /// /// - Returns: the contents of the file at the specified path as string. /// public func read(_ encoding: String.Encoding = String.Encoding.utf8) throws -> String { return try NSString(contentsOfFile: path, encoding: encoding.rawValue).substring(from: 0) as String } /// Write a file. /// /// - Note: Works atomically: the data is written to a backup file, and then — assuming no /// errors occur — the backup file is renamed to the name specified by path. /// /// - Parameter data: the contents to write to file. /// public func write(_ data: Data) throws { try data.write(to: normalize().url, options: .atomic) } /// Reads the file. /// /// - Note: Works atomically: the data is written to a backup file, and then — assuming no /// errors occur — the backup file is renamed to the name specified by path. /// /// - Parameter string: the string to write to file. /// /// - Parameter encoding: the encoding which should be used to represent the string as bytes. /// (by default: `NSUTF8StringEncoding`) /// /// - Returns: the contents of the file at the specified path as string. /// public func write(_ string: String, encoding: String.Encoding = String.Encoding.utf8) throws { try string.write(toFile: normalize().path, atomically: true, encoding: encoding) } } // MARK: Traversing extension Path { /// Get the parent directory /// /// - Returns: the normalized path of the parent directory /// public func parent() -> Path { return self + ".." } /// Performs a shallow enumeration in a directory /// /// - Returns: paths to all files, directories and symbolic links contained in the directory /// public func children() throws -> [Path] { return try Path.fileManager.contentsOfDirectory(atPath: path).map { self + Path($0) } } /// Performs a deep enumeration in a directory /// /// - Returns: paths to all files, directories and symbolic links contained in the directory or /// any subdirectory. /// public func recursiveChildren() throws -> [Path] { return try Path.fileManager.subpathsOfDirectory(atPath: path).map { self + Path($0) } } } // MARK: Globbing extension Path { public static func glob(_ pattern: String) -> [Path] { var gt = glob_t() let cPattern = strdup(pattern) defer { globfree(>) free(cPattern) } let flags = GLOB_TILDE | GLOB_BRACE | GLOB_MARK if system_glob(cPattern, flags, nil, >) == 0 { #if os(Linux) let matchc = gt.gl_pathc #else let matchc = gt.gl_matchc #endif #if swift(>=4.1) return (0.. [Path] { return Path.glob((self + pattern).description) } } // MARK: SequenceType extension Path : Sequence { public struct DirectoryEnumerationOptions : OptionSet { public let rawValue: UInt public init(rawValue: UInt) { self.rawValue = rawValue } public static var skipsSubdirectoryDescendants = DirectoryEnumerationOptions(rawValue: FileManager.DirectoryEnumerationOptions.skipsSubdirectoryDescendants.rawValue) public static var skipsPackageDescendants = DirectoryEnumerationOptions(rawValue: FileManager.DirectoryEnumerationOptions.skipsPackageDescendants.rawValue) public static var skipsHiddenFiles = DirectoryEnumerationOptions(rawValue: FileManager.DirectoryEnumerationOptions.skipsHiddenFiles.rawValue) } /// Represents a path sequence with specific enumeration options public struct PathSequence : Sequence { private var path: Path private var options: DirectoryEnumerationOptions init(path: Path, options: DirectoryEnumerationOptions) { self.path = path self.options = options } public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: path, options: options) } } /// Enumerates the contents of a directory, returning the paths of all files and directories /// contained within that directory. These paths are relative to the directory. public struct DirectoryEnumerator : IteratorProtocol { public typealias Element = Path let path: Path let directoryEnumerator: FileManager.DirectoryEnumerator? init(path: Path, options mask: DirectoryEnumerationOptions = []) { let options = FileManager.DirectoryEnumerationOptions(rawValue: mask.rawValue) self.path = path self.directoryEnumerator = Path.fileManager.enumerator(at: path.url, includingPropertiesForKeys: nil, options: options) } public func next() -> Path? { let next = directoryEnumerator?.nextObject() if let next = next as? URL { return Path(next.path) } return nil } /// Skip recursion into the most recently obtained subdirectory. public func skipDescendants() { directoryEnumerator?.skipDescendants() } } /// Perform a deep enumeration of a directory. /// /// - Returns: a directory enumerator that can be used to perform a deep enumeration of the /// directory. /// public func makeIterator() -> DirectoryEnumerator { return DirectoryEnumerator(path: self) } /// Perform a deep enumeration of a directory. /// /// - Parameter options: FileManager directory enumerator options. /// /// - Returns: a path sequence that can be used to perform a deep enumeration of the /// directory. /// public func iterateChildren(options: DirectoryEnumerationOptions = []) -> PathSequence { return PathSequence(path: self, options: options) } } // MARK: Equatable extension Path : Equatable {} /// Determines if two paths are identical /// /// - Note: The comparison is string-based. Be aware that two different paths (foo.txt and /// ./foo.txt) can refer to the same file. /// public func ==(lhs: Path, rhs: Path) -> Bool { return lhs.path == rhs.path } // MARK: Pattern Matching /// Implements pattern-matching for paths. /// /// - Returns: `true` iff one of the following conditions is true: /// - the paths are equal (based on `Path`'s `Equatable` implementation) /// - the paths can be normalized to equal Paths. /// public func ~=(lhs: Path, rhs: Path) -> Bool { return lhs == rhs || lhs.normalize() == rhs.normalize() } // MARK: Comparable extension Path : Comparable {} /// Defines a strict total order over Paths based on their underlying string representation. public func <(lhs: Path, rhs: Path) -> Bool { return lhs.path < rhs.path } // MARK: Operators /// Appends a Path fragment to another Path to produce a new Path public func +(lhs: Path, rhs: Path) -> Path { return lhs.path + rhs.path } /// Appends a String fragment to another Path to produce a new Path public func +(lhs: Path, rhs: String) -> Path { return lhs.path + rhs } /// Appends a String fragment to another String to produce a new Path internal func +(lhs: String, rhs: String) -> Path { if rhs.hasPrefix(Path.separator) { // Absolute paths replace relative paths return Path(rhs) } else { var lSlice = NSString(string: lhs).pathComponents.fullSlice var rSlice = NSString(string: rhs).pathComponents.fullSlice // Get rid of trailing "/" at the left side if lSlice.count > 1 && lSlice.last == Path.separator { lSlice.removeLast() } // Advance after the first relevant "." lSlice = lSlice.filter { $0 != "." }.fullSlice rSlice = rSlice.filter { $0 != "." }.fullSlice // Eats up trailing components of the left and leading ".." of the right side while lSlice.last != ".." && !lSlice.isEmpty && rSlice.first == ".." { if lSlice.count > 1 || lSlice.first != Path.separator { // A leading "/" is never popped lSlice.removeLast() } if !rSlice.isEmpty { rSlice.removeFirst() } switch (lSlice.isEmpty, rSlice.isEmpty) { case (true, _): break case (_, true): break default: continue } } return Path(components: lSlice + rSlice) } } extension Array { var fullSlice: ArraySlice { return self[self.indices.suffix(from: 0)] } } ================================================ FILE: Dependencies/mxcl∕AppUpdater-1.0.3.swift ================================================ import class AppKit.NSBackgroundActivityScheduler import var AppKit.NSApp import PMKFoundation import Foundation import PromiseKit import Version import Path public class AppUpdater { var active = Promise() #if !DEBUG let activity: NSBackgroundActivityScheduler #endif let owner: String let repo: String var slug: String { return "\(owner)/\(repo)" } public init(owner: String, repo: String) { self.owner = owner self.repo = repo #if DEBUG check().cauterize() #else activity = NSBackgroundActivityScheduler(identifier: "dev.mxcl.AppUpdater") activity.repeats = true activity.interval = 24 * 60 * 60 activity.schedule { [unowned self] completion in guard !self.activity.shouldDefer, self.active.isResolved else { return completion(.deferred) } self.check().cauterize().finally { completion(.finished) } } #endif } #if !DEBUG deinit { activity.invalidate() } #endif private enum Error: Swift.Error { case bundleExecutableURL case codeSigningIdentity case invalidDownloadedBundle } public func check() -> Promise { guard active.isResolved else { return active } guard Bundle.main.executableURL != nil else { return Promise(error: Error.bundleExecutableURL) } let currentVersion = Bundle.main.version func validate(codeSigning b1: Bundle, _ b2: Bundle) -> Promise { return firstly { when(fulfilled: b1.codeSigningIdentity, b2.codeSigningIdentity) }.done { guard $0 == $1 else { throw Error.codeSigningIdentity } } } func update(with asset: Release.Asset) throws -> Promise { #if DEBUG print("notice: AppUpdater dry-run:", asset) return Promise() #else let tmpdir = try FileManager.default.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: Bundle.main.bundleURL, create: true) return firstly { URLSession.shared.downloadTask(.promise, with: asset.browser_download_url, to: tmpdir.appendingPathComponent("download")) }.then { dst, _ in unzip(dst, contentType: asset.content_type) }.compactMap { downloadedAppBundle in Bundle(url: downloadedAppBundle) }.then { downloadedAppBundle in validate(codeSigning: .main, downloadedAppBundle).map{ downloadedAppBundle } }.done { downloadedAppBundle in // UNIX is cool. Delete ourselves, move new one in then restart. let installedAppBundle = Bundle.main guard let exe = downloadedAppBundle.executable, exe.exists else { throw Error.invalidDownloadedBundle } let finalExecutable = installedAppBundle.path/exe.relative(to: downloadedAppBundle.path) try installedAppBundle.path.delete() try downloadedAppBundle.path.move(to: installedAppBundle.path) try FileManager.default.removeItem(at: tmpdir) let proc = Process() if #available(OSX 10.13, *) { proc.executableURL = finalExecutable.url } else { proc.launchPath = finalExecutable.string } proc.launch() // seems to work, though for sure, seems asking a lot for it to be reliable! //TODO be reliable! Probably get an external applescript to ask us this one to quit then exec the new one NSApp.terminate(self) }.ensure { _ = try? FileManager.default.removeItem(at: tmpdir) } #endif } let url = URL(string: "https://api.github.com/repos/\(slug)/releases")! active = firstly { URLSession.shared.dataTask(.promise, with: url).validate() }.map { try JSONDecoder().decode([Release].self, from: $0.data) }.compactMap { releases in try releases.findViableUpdate(appVersion: currentVersion, repo: self.repo) }.then { asset in try update(with: asset) } return active } } private struct Release: Decodable { let tag_name: Version let prerelease: Bool struct Asset: Decodable { let name: String let browser_download_url: URL let content_type: ContentType } let assets: [Asset] func viableAsset(forRepo repo: String) -> Asset? { return assets.first(where: { (asset) -> Bool in let prefix = "\(repo.lowercased())-\(tag_name)" let name = (asset.name as NSString).deletingPathExtension.lowercased() switch (name, asset.content_type) { case ("\(prefix).tar", .tar): return true case (prefix, _): return true default: return false } }) } } private enum ContentType: Decodable { init(from decoder: Decoder) throws { switch try decoder.singleValueContainer().decode(String.self) { case "application/x-bzip2", "application/x-xz", "application/x-gzip": self = .tar case "application/zip": self = .zip default: throw PMKError.badInput } } case zip case tar } extension Release: Comparable { static func < (lhs: Release, rhs: Release) -> Bool { return lhs.tag_name < rhs.tag_name } static func == (lhs: Release, rhs: Release) -> Bool { return lhs.tag_name == rhs.tag_name } } private extension Array where Element == Release { func findViableUpdate(appVersion: Version, repo: String) throws -> Release.Asset? { let properReleases = filter{ !$0.prerelease } guard let latestRelease = properReleases.sorted().last else { return nil } guard appVersion < latestRelease.tag_name else { throw PMKError.cancelled } return latestRelease.viableAsset(forRepo: repo) } } private func unzip(_ url: URL, contentType: ContentType) -> Promise { let proc = Process() if #available(OSX 10.13, *) { proc.currentDirectoryURL = url.deletingLastPathComponent() } else { proc.currentDirectoryPath = url.deletingLastPathComponent().path } switch contentType { case .tar: proc.launchPath = "/usr/bin/tar" proc.arguments = ["xf", url.path] case .zip: proc.launchPath = "/usr/bin/unzip" proc.arguments = [url.path] } func findApp() throws -> URL? { let cnts = try FileManager.default.contentsOfDirectory(at: url.deletingLastPathComponent(), includingPropertiesForKeys: [.isDirectoryKey], options: .skipsSubdirectoryDescendants) for url in cnts { guard url.pathExtension == "app" else { continue } guard let foo = try url.resourceValues(forKeys: [.isDirectoryKey]).isDirectory, foo else { continue } return url } return nil } return firstly { proc.launch(.promise) }.compactMap { _ in try findApp() } } private extension Bundle { var isCodeSigned: Guarantee { let proc = Process() proc.launchPath = "/usr/bin/codesign" proc.arguments = ["-dv", bundlePath] return proc.launch(.promise).map { _ in true }.recover { _ in .value(false) } } var codeSigningIdentity: Promise { let proc = Process() proc.launchPath = "/usr/bin/codesign" proc.arguments = ["-dvvv", bundlePath] return firstly { proc.launch(.promise) }.compactMap { String(data: $0.err.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) }.map { $0.split(separator: "\n") }.filterValues { $0.hasPrefix("Authority=") }.firstValue.map { line in String(line.dropFirst(10)) } } } ================================================ FILE: Dependencies/mxcl∕LegibleError-1.0.1.swift ================================================ import Foundation #if os(Linux) let theOperationCouldNotBeCompleted = "The operation could not be completed" #else let theOperationCouldNotBeCompleted = "The operation couldn’t be completed." #endif extension Error { /// - Returns: A fully qualified representation of this error. public var legibleDescription: String { switch errorType { case .swiftError(.enum?), .swiftLocalizedError(_, .enum?): return "\(type(of: self)).\(self)" case .swiftError(.class?), .swiftLocalizedError(_, .class?): //TODO better return "\(type(of: self))" case .swiftError, .swiftLocalizedError: return String(describing: self) case let .nsError(nsError, domain, code): if let underlyingError = nsError.userInfo[NSUnderlyingErrorKey] as? NSError { return "\(domain)(\(code), \(underlyingError.domain)(\(underlyingError.code)))" } else { return "\(domain)(\(code))" } } } /// - Returns: A fully qualified, user-visible representation of this error. public var legibleLocalizedDescription: String { switch errorType { case .swiftError: return "\(theOperationCouldNotBeCompleted) (\(legibleDescription))" case .swiftLocalizedError(let msg, _): return msg case .nsError(_, "kCLErrorDomain", 0): return "The location could not be determined." // ^^ Apple don’t provide a localized description for this case let .nsError(nsError, domain, code): if !localizedDescription.hasPrefix(theOperationCouldNotBeCompleted) { return localizedDescription //FIXME ^^ for non-EN } else if let underlyingError = nsError.userInfo[NSUnderlyingErrorKey] as? Error { return underlyingError.legibleLocalizedDescription } else { // usually better than the localizedDescription, but not pretty return "\(theOperationCouldNotBeCompleted) (\(domain).\(code))" } } } private var errorType: ErrorType { #if os(Linux) let isNSError = self is NSError #else let foo: Any = self let isNSError = String(cString: object_getClassName(self)) != "_SwiftNativeNSError" && foo is NSObject // ^^ ∵ otherwise implicit bridging implicitly casts as for other tests #endif if isNSError { let nserr = self as NSError return .nsError(nserr, domain: nserr.domain, code: nserr.code) } else if let err = self as? LocalizedError, let msg = err.errorDescription { return .swiftLocalizedError(msg, Mirror(reflecting: self).displayStyle) } else { return .swiftError(Mirror(reflecting: self).displayStyle) } } } private enum ErrorType { case nsError(NSError, domain: String, code: Int) case swiftLocalizedError(String, Mirror.DisplayStyle?) case swiftError(Mirror.DisplayStyle?) } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Extensions.swift ================================================ import Foundation /// Extensions on Foundation’s `Bundle` so you get `Path` rather than `String` or `URL`. public extension Bundle { /// Returns the path for requested resource in this bundle. func path(forResource: String, ofType: String?) -> Path? { let f: (String?, String?) -> String? = path(forResource:ofType:) let str = f(forResource, ofType) return str.flatMap(Path.init) } /** Returns the path for the shared-frameworks directory in this bundle. - Note: This is typically `ShareFrameworks` */ var sharedFrameworks: Path { return sharedFrameworksPath.flatMap(Path.init) ?? defaultSharedFrameworksPath } /** Returns the path for the private-frameworks directory in this bundle. - Note: This is typically `Frameworks` */ var privateFrameworks: Path { return privateFrameworksPath.flatMap(Path.init) ?? defaultSharedFrameworksPath } /// Returns the path for the resources directory in this bundle. var resources: Path { return resourcePath.flatMap(Path.init) ?? defaultResourcesPath } /// Returns the path for this bundle. var path: Path { return Path(string: bundlePath) } /// Returns the executable for this bundle, if there is one, not all bundles have one hence `Optional`. var executable: Path? { return executablePath.flatMap(Path.init) } } /// Extensions on `String` that work with `Path` rather than `String` or `URL` public extension String { /// Initializes this `String` with the contents of the provided path. @inlinable init(contentsOf path: Path) throws { try self.init(contentsOfFile: path.string) } /// - Returns: `to` to allow chaining @inlinable @discardableResult func write(to: Path, atomically: Bool = false, encoding: String.Encoding = .utf8) throws -> Path { try write(toFile: to.string, atomically: atomically, encoding: encoding) return to } } /// Extensions on `Data` that work with `Path` rather than `String` or `URL` public extension Data { /// Initializes this `Data` with the contents of the provided path. @inlinable init(contentsOf path: Path) throws { try self.init(contentsOf: path.url) } /// - Returns: `to` to allow chaining @inlinable @discardableResult func write(to: Path, atomically: Bool = false) throws -> Path { let opts: NSData.WritingOptions if atomically { #if !os(Linux) opts = .atomicWrite #else opts = .atomic #endif } else { opts = [] } try write(to: to.url, options: opts) return to } } /// Extensions on `FileHandle` that work with `Path` rather than `String` or `URL` public extension FileHandle { /// Initializes this `FileHandle` for reading at the location of the provided path. @inlinable convenience init(forReadingAt path: Path) throws { try self.init(forReadingFrom: path.url) } /// Initializes this `FileHandle` for writing at the location of the provided path. @inlinable convenience init(forWritingAt path: Path) throws { try self.init(forWritingTo: path.url) } /// Initializes this `FileHandle` for reading and writing at the location of the provided path. @inlinable convenience init(forUpdatingAt path: Path) throws { try self.init(forUpdating: path.url) } } internal extension Bundle { var defaultSharedFrameworksPath: Path { #if os(macOS) return path.join("Contents/Frameworks") #elseif os(Linux) return path.join("lib") #else return path.join("Frameworks") #endif } var defaultResourcesPath: Path { #if os(macOS) return path.join("Contents/Resources") #elseif os(Linux) return path.join("share") #else return path #endif } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+Attributes.swift ================================================ import Foundation public extension Path { //MARK: Filesystem Attributes /** Returns the creation-time of the file. - Note: Returns `nil` if there is no creation-time, this should only happen if the file doesn’t exist. - Important: On Linux this is filesystem dependendent and may not exist. */ var ctime: Date? { do { let attrs = try FileManager.default.attributesOfItem(atPath: string) return attrs[.creationDate] as? Date } catch { return nil } } /** Returns the modification-time of the file. - Note: If this returns `nil` and the file exists, something is very wrong. */ var mtime: Date? { do { let attrs = try FileManager.default.attributesOfItem(atPath: string) return attrs[.modificationDate] as? Date } catch { return nil } } /** Sets the file’s attributes using UNIX octal notation. Path.home.join("foo").chmod(0o555) */ @discardableResult func chmod(_ octal: Int) throws -> Path { try FileManager.default.setAttributes([.posixPermissions: octal], ofItemAtPath: string) return self } /** Applies the macOS filesystem “lock” attribute. - Note: If file is already locked, does nothing. - Note: If file doesn’t exist, throws. - Important: On Linux does nothing. */ @discardableResult func lock() throws -> Path { #if !os(Linux) var attrs = try FileManager.default.attributesOfItem(atPath: string) let b = attrs[.immutable] as? Bool ?? false if !b { attrs[.immutable] = true try FileManager.default.setAttributes(attrs, ofItemAtPath: string) } #endif return self } /** - Note: If file isn‘t locked, does nothing. - Note: If file doesn’t exist, does nothing. - Important: On Linux does nothing. - SeeAlso: `lock()` */ @discardableResult func unlock() throws -> Path { #if !os(Linux) var attrs: [FileAttributeKey: Any] do { attrs = try FileManager.default.attributesOfItem(atPath: string) } catch CocoaError.fileReadNoSuchFile { return self } let b = attrs[.immutable] as? Bool ?? false if b { attrs[.immutable] = false try FileManager.default.setAttributes(attrs, ofItemAtPath: string) } #endif return self } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+Codable.swift ================================================ import Foundation /** Provided for relative-path coding. See the instructions in our [README](https://github.com/mxcl/Path.swift/#codable). */ public extension CodingUserInfoKey { /** If set on an `Encoder`’s `userInfo` all paths are encoded relative to this path. For example: let encoder = JSONEncoder() encoder.userInfo[.relativePath] = Path.home encoder.encode([Path.home, Path.home/"foo"]) - Remark: See the [README](https://github.com/mxcl/Path.swift/#codable) for more information. */ static let relativePath = CodingUserInfoKey(rawValue: "dev.mxcl.Path.relative")! } /** Provided for relative-path coding. See the instructions in our [README](https://github.com/mxcl/Path.swift/#codable). */ extension Path: Codable { /// - SeeAlso: `CodingUserInfoKey.relativePath` /// :nodoc: public init(from decoder: Decoder) throws { let value = try decoder.singleValueContainer().decode(String.self) if value.hasPrefix("/") { string = value } else { guard let root = decoder.userInfo[.relativePath] as? Path else { throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Path cannot decode a relative path if `userInfo[.relativePath]` not set to a Path object.")) } string = (root/value).string } } /// - SeeAlso: `CodingUserInfoKey.relativePath` /// :nodoc: public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() if let root = encoder.userInfo[.relativePath] as? Path { try container.encode(relative(to: root)) } else { try container.encode(string) } } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+CommonDirectories.swift ================================================ import Foundation extension Path { //MARK: Common Directories /// Returns a `Path` containing `FileManager.default.currentDirectoryPath`. public static var cwd: Path { return Path(string: FileManager.default.currentDirectoryPath) } /// Returns a `Path` representing the root path. public static var root: Path { return Path(string: "/") } /// Returns a `Path` representing the user’s home directory public static var home: Path { let string: String #if os(macOS) if #available(OSX 10.12, *) { string = FileManager.default.homeDirectoryForCurrentUser.path } else { string = NSHomeDirectory() } #else string = NSHomeDirectory() #endif return Path(string: string) } /// Helper to allow search path and domain mask to be passed in. private static func path(for searchPath: FileManager.SearchPathDirectory) -> Path { #if os(Linux) // the urls(for:in:) function is not implemented on Linux //TODO strictly we should first try to use the provided binary tool let foo = { ProcessInfo.processInfo.environment[$0].flatMap(Path.init) ?? $1 } switch searchPath { case .documentDirectory: return Path.home/"Documents" case .applicationSupportDirectory: return foo("XDG_DATA_HOME", Path.home/".local/share") case .cachesDirectory: return foo("XDG_CACHE_HOME", Path.home/".cache") default: fatalError() } #else guard let pathString = FileManager.default.urls(for: searchPath, in: .userDomainMask).first?.path else { return defaultUrl(for: searchPath) } return Path(string: pathString) #endif } /** The root for user documents. - Note: There is no standard location for documents on Linux, thus we return `~/Documents`. - Note: You should create a subdirectory before creating any files. */ public static var documents: Path { return path(for: .documentDirectory) } /** The root for cache files. - Note: On Linux this is `XDG_CACHE_HOME`. - Note: You should create a subdirectory before creating any files. */ public static var caches: Path { return path(for: .cachesDirectory) } /** For data that supports your running application. - Note: On Linux is `XDG_DATA_HOME`. - Note: You should create a subdirectory before creating any files. */ public static var applicationSupport: Path { return path(for: .applicationSupportDirectory) } } #if !os(Linux) func defaultUrl(for searchPath: FileManager.SearchPathDirectory) -> Path { switch searchPath { case .documentDirectory: return Path.home/"Documents" case .applicationSupportDirectory: return Path.home/"Library/Application Support" case .cachesDirectory: return Path.home/"Library/Caches" default: fatalError() } } #endif ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+FileManager.swift ================================================ import Foundation #if os(Linux) import Glibc #endif public extension Path { //MARK: File Management /** Copies a file. try Path.root.join("bar").copy(to: Path.home/"foo") // => "/Users/mxcl/foo" - Note: `throws` if `to` is a directory. - Parameter to: Destination filename. - Parameter overwrite: If `true` and both `self` and `to` are files, overwrites `to`. - Note: If either `self` or `to are directories, `overwrite` is ignored. - Note: Throws if `overwrite` is `false` yet `to` is *already* identical to `self` because even though *Path.swift’s* policy is to noop if the desired end result preexists, checking for this condition is too expensive a trade-off. - Returns: `to` to allow chaining - SeeAlso: `copy(into:overwrite:)` */ @discardableResult func copy(to: Path, overwrite: Bool = false) throws -> Path { if overwrite, to.isFile, isFile { try FileManager.default.removeItem(at: to.url) } #if os(Linux) && !swift(>=5.1) // check if fixed if !overwrite, to.isFile { throw CocoaError.error(.fileWriteFileExists) } #endif try FileManager.default.copyItem(atPath: string, toPath: to.string) return to } /** Copies a file into a directory try Path.root.join("bar").copy(into: .home) // => "/Users/mxcl/bar" // Create ~/.local/bin, copy `ls` there and make the new copy executable try Path.root.join("bin/ls").copy(into: Path.home.join(".local/bin").mkdir(.p)).chmod(0o500) If the destination does not exist, this function creates the directory (including intermediary directories if necessary) first. - Parameter into: Destination directory - Parameter overwrite: If true overwrites any file that already exists at `into`. - Returns: The `Path` of the newly copied file. - Note: `throws` if `into` is a file. - Note: Throws if `overwrite` is `false` yet `to` is *already* identical to `self` because even though *Path.swift’s* policy is to noop if the desired end result preexists, checking for this condition is too expensive a trade-off. - SeeAlso: `copy(to:overwrite:)` */ @discardableResult func copy(into: Path, overwrite: Bool = false) throws -> Path { if !into.exists { try into.mkdir(.p) } let rv = into/basename() if overwrite, rv.isFile { try rv.delete() } #if os(Linux) && !swift(>=5.1) // check if fixed if !overwrite, rv.isFile { throw CocoaError.error(.fileWriteFileExists) } #endif try FileManager.default.copyItem(at: url, to: rv.url) return rv } /** Moves a file. try Path.root.join("bar").move(to: Path.home/"foo") // => "/Users/mxcl/foo" - Parameter to: Destination filename. - Parameter overwrite: If true overwrites any file that already exists at `to`. - Returns: `to` to allow chaining - Note: `throws` if `to` is a directory. - Note: Throws if `overwrite` is `false` yet `to` is *already* identical to `self` because even though *Path.swift’s* policy is to noop if the desired end result preexists, checking for this condition is too expensive a trade-off. - SeeAlso: `move(into:overwrite:)` */ @discardableResult func move(to: Path, overwrite: Bool = false) throws -> Path { if overwrite, to.isFile { try FileManager.default.removeItem(at: to.url) } try FileManager.default.moveItem(at: url, to: to.url) return to } /** Moves a file into a directory try Path.root.join("bar").move(into: .home) // => "/Users/mxcl/bar" If the destination does not exist, this function creates the directory (including intermediary directories if necessary) first. - Parameter into: Destination directory - Parameter overwrite: If true *overwrites* any file that already exists at `into`. - Note: `throws` if `into` is a file. - Returns: The `Path` of destination filename. - SeeAlso: `move(to:overwrite:)` */ @discardableResult func move(into: Path, overwrite: Bool = false) throws -> Path { if !into.exists { try into.mkdir(.p) } else if !into.isDirectory { throw CocoaError.error(.fileWriteFileExists) } let rv = into/basename() if overwrite, rv.isFile { try FileManager.default.removeItem(at: rv.url) } try FileManager.default.moveItem(at: url, to: rv.url) return rv } /** Deletes the path, recursively if a directory. - Note: noop: if the path doesn’t exist ∵ *Path.swift* doesn’t error if desired end result preexists. - Note: On UNIX will this function will succeed if the parent directory is writable and the current user has permission. - Note: This function will fail if the file or directory is “locked” - SeeAlso: `lock()` */ @inlinable func delete() throws { if exists { try FileManager.default.removeItem(at: url) } } /** Creates an empty file at this path or if the file exists, updates its modification time. - Returns: `self` to allow chaining. */ @inlinable @discardableResult func touch() throws -> Path { if !exists { guard FileManager.default.createFile(atPath: string, contents: nil) else { throw CocoaError.error(.fileWriteUnknown) } } else { #if os(Linux) let fd = open(string, O_WRONLY) defer { close(fd) } futimens(fd, nil) #else try FileManager.default.setAttributes([.modificationDate: Date()], ofItemAtPath: string) #endif } return self } /** Creates the directory at this path. - Parameter options: Specify `mkdir(.p)` to create intermediary directories. - Note: We do not error if the directory already exists (even without `.p`) because *Path.swift* noops if the desired end result preexists. - Returns: `self` to allow chaining. */ @discardableResult func mkdir(_ options: MakeDirectoryOptions? = nil) throws -> Path { do { let wid = options == .p try FileManager.default.createDirectory(at: self.url, withIntermediateDirectories: wid, attributes: nil) } catch CocoaError.Code.fileWriteFileExists { //noop (fails to trigger on Linux) } catch { #if os(Linux) let error = error as NSError guard error.domain == NSCocoaErrorDomain, error.code == CocoaError.Code.fileWriteFileExists.rawValue else { throw error } #else throw error #endif } return self } /** Renames the file at path. Path.root.foo.bar.rename(to: "baz") // => /foo/baz - Parameter to: the new basename for the file - Returns: The renamed path. */ @discardableResult func rename(to newname: String) throws -> Path { let newpath = parent/newname try FileManager.default.moveItem(atPath: string, toPath: newpath.string) return newpath } /** Creates a symlink of this file at `as`. - Note: If `self` does not exist, is **not** an error. */ @discardableResult func symlink(as: Path) throws -> Path { try FileManager.default.createSymbolicLink(atPath: `as`.string, withDestinationPath: string) return `as` } /** Creates a symlink of this file with the same filename in the `into` directory. - Note: If into does not exist, creates the directory with intermediate directories if necessary. */ @discardableResult func symlink(into dir: Path) throws -> Path { if !dir.exists { try dir.mkdir(.p) } else if !dir.isDirectory { throw CocoaError.error(.fileWriteFileExists) } let dst = dir/basename() try FileManager.default.createSymbolicLink(atPath: dst.string, withDestinationPath: string) return dst } } /// Options for `Path.mkdir(_:)` public enum MakeDirectoryOptions { /// Creates intermediary directories; works the same as `mkdir -p`. case p } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+StringConvertibles.swift ================================================ extension Path: CustomStringConvertible { /// Returns `Path.string` public var description: String { return string } } extension Path: CustomDebugStringConvertible { /// Returns eg. `Path(string: "/foo")` public var debugDescription: String { return "Path(\(string))" } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path+ls.swift ================================================ import Foundation /** A file entry from a directory listing. - SeeAlso: `ls()` */ public struct Entry { /// The kind of this directory entry. public enum Kind { /// The path is a file. case file /// The path is a directory. case directory } /// The kind of this entry. public let kind: Kind /// The path of this entry. public let path: Path } public extension Path { //MARK: Directory Listings /** Same as the `ls -a` command ∴ output is ”shallow” and unsorted. - Parameter includeHiddenFiles: If `true`, hidden files are included in the results. Defaults to `true`. - Important: `includeHiddenFiles` does not work on Linux */ func ls(includeHiddenFiles: Bool = true) throws -> [Entry] { var opts = FileManager.DirectoryEnumerationOptions() #if !os(Linux) if !includeHiddenFiles { opts.insert(.skipsHiddenFiles) } #endif let paths = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: opts) func convert(url: URL) -> Entry? { guard let path = Path(url.path) else { return nil } return Entry(kind: path.isDirectory ? .directory : .file, path: path) } return paths.compactMap(convert) } } /// Convenience functions for the array return value of `Path.ls()` public extension Array where Element == Entry { /// Filters the list of entries to be a list of Paths that are directories. var directories: [Path] { return compactMap { $0.kind == .directory ? $0.path : nil } } /// Filters the list of entries to be a list of Paths that are files. var files: [Path] { return compactMap { $0.kind == .file ? $0.path : nil } } /// Filters the list of entries to be a list of Paths that are files with the specified extension. func files(withExtension ext: String) -> [Path] { return compactMap { $0.kind == .file && $0.path.extension == ext ? $0.path : nil } } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path->Bool.swift ================================================ import Foundation #if os(Linux) import func Glibc.access #else import Darwin #endif public extension Path { //MARK: Filesystem Properties /// Returns true if the path represents an actual filesystem entry. var exists: Bool { return FileManager.default.fileExists(atPath: string) } /// Returns true if the path represents an actual filesystem entry that is *not* a directory. var isFile: Bool { var isDir: ObjCBool = true return FileManager.default.fileExists(atPath: string, isDirectory: &isDir) && !isDir.boolValue } /// Returns true if the path represents an actual directory. var isDirectory: Bool { var isDir: ObjCBool = false return FileManager.default.fileExists(atPath: string, isDirectory: &isDir) && isDir.boolValue } /// Returns true if the path represents an actual file that is also readable by the current user. var isReadable: Bool { return FileManager.default.isReadableFile(atPath: string) } /// Returns true if the path represents an actual file that is also writable by the current user. var isWritable: Bool { return FileManager.default.isWritableFile(atPath: string) } /// Returns true if the path represents an actual file that is also deletable by the current user. var isDeletable: Bool { #if os(Linux) && !swift(>=5.1) return exists && access(parent.string, W_OK) == 0 #else // FileManager.isDeletableFile returns true if there is *not* a file there return exists && FileManager.default.isDeletableFile(atPath: string) #endif } /// Returns true if the path represents an actual file that is also executable by the current user. var isExecutable: Bool { if access(string, X_OK) == 0 { // FileManager.isExxecutableFile returns true even if there is *not* // a file there *but* if there was it could be *made* executable return FileManager.default.isExecutableFile(atPath: string) } else { return false } } /// Returns `true` if the file is a symbolic-link (symlink). var isSymlink: Bool { var sbuf = stat() lstat(string, &sbuf) return (sbuf.st_mode & S_IFMT) == S_IFLNK } } ================================================ FILE: Dependencies/mxcl∕Path.swift-0.16.1/Path.swift ================================================ import Foundation #if !os(Linux) import func Darwin.realpath let _realpath = Darwin.realpath #else import func Glibc.realpath let _realpath = Glibc.realpath #endif /** A `Path` represents an absolute path on a filesystem. All functions on `Path` are chainable and short to facilitate doing sequences of file operations in a concise manner. `Path` supports `Codable`, and can be configured to [encode paths *relatively*](https://github.com/mxcl/Path.swift/#codable). Sorting a `Sequence` of paths will return the locale-aware sort order, which will give you the same order as Finder. Converting from a `String` is a common first step, here are the recommended ways to do that: let p1 = Path.root/pathString let p2 = Path.root/url.path let p3 = Path.cwd/relativePathString let p4 = Path(userInput) ?? Path.cwd/userInput If you are constructing paths from static-strings we provide support for dynamic members: let p1 = Path.root.usr.bin.ls // => /usr/bin/ls - Note: A `Path` does not necessarily represent an actual filesystem entry. */ @dynamicMemberLookup public struct Path: Equatable, Hashable, Comparable { init(string: String) { assert(string.first == "/") assert(string.last != "/" || string == "/") assert(string.split(separator: "/").contains("..") == false) self.string = string } /** Creates a new absolute, standardized path. - Note: Resolves any .. or . components. - Note: Removes multiple subsequent and trailing occurences of `/`. - Note: Does *not* resolve any symlinks. - Note: On macOS, removes an initial component of “/private/var/automount”, “/var/automount”, or “/private” from the path, if the result still indicates an existing file or directory (checked by consulting the file system). - Returns: The path or `nil` if fed a relative path or a `~foo` string where there is no user `foo`. */ public init?(_ description: S) { var pathComponents = description.split(separator: "/") switch description.first { case "/": #if os(macOS) func ifExists(withPrefix prefix: String, removeFirst n: Int) { assert(prefix.split(separator: "/").count == n) if description.hasPrefix(prefix), FileManager.default.fileExists(atPath: String(description)) { pathComponents.removeFirst(n) } } ifExists(withPrefix: "/private/var/automount", removeFirst: 3) ifExists(withPrefix: "/var/automount", removeFirst: 2) ifExists(withPrefix: "/private", removeFirst: 1) #endif self.string = join_(prefix: "/", pathComponents: pathComponents) case "~": if description == "~" { self = Path.home return } let tilded: String if description.hasPrefix("~/") { tilded = Path.home.string } else { let username = String(pathComponents[0].dropFirst()) #if os(macOS) || os(Linux) if #available(OSX 10.12, *) { guard let url = FileManager.default.homeDirectory(forUser: username) else { return nil } assert(url.scheme == "file") tilded = url.path } else { guard let dir = NSHomeDirectoryForUser(username) else { return nil } tilded = dir } #else return nil // there are no usernames on iOS, etc. #endif } pathComponents.remove(at: 0) self.string = join_(prefix: tilded, pathComponents: pathComponents) default: return nil } } /** Creates a new absolute, standardized path from the provided file-scheme URL. - Note: If the URL is not a file URL, returns `nil`. */ public init?(url: URL) { guard url.scheme == "file" else { return nil } self.init(url.path) //NOTE: URL cannot be a file-reference url, unlike NSURL, so this always works } /** Creates a new absolute, standardized path from the provided file-scheme URL. - Note: If the URL is not a file URL, returns `nil`. - Note: If the URL is a file reference URL, converts it to a POSIX path first. */ public init?(url: NSURL) { guard url.scheme == "file", let path = url.path else { return nil } self.init(string: path) // ^^ works even if the url is a file-reference url } /// :nodoc: public subscript(dynamicMember addendum: String) -> Path { //NOTE it’s possible for the string to be anything if we are invoked via // explicit subscript thus we use our fully sanitized `join` function return Path(string: join_(prefix: string, appending: addendum)) } //MARK: Properties /// The underlying filesystem path public let string: String /// Returns a `URL` representing this file path. public var url: URL { return URL(fileURLWithPath: string) } /** Returns a file-reference URL. - Note: Only NSURL can be a file-reference-URL, hence we return NSURL. - SeeAlso: https://developer.apple.com/documentation/foundation/nsurl/1408631-filereferenceurl - Important: On Linux returns an file scheme NSURL for this path string. */ public var fileReferenceURL: NSURL? { #if !os(Linux) // https://bugs.swift.org/browse/SR-2728 return (url as NSURL).perform(#selector(NSURL.fileReferenceURL))?.takeUnretainedValue() as? NSURL #else return NSURL(fileURLWithPath: string) #endif } /** Returns the parent directory for this path. Path is not aware of the nature of the underlying file, but this is irrlevant since the operation is the same irrespective of this fact. - Note: always returns a valid path, `Path.root.parent` *is* `Path.root`. */ public var parent: Path { let index = string.lastIndex(of: "/")! let substr = string[string.indices.startIndex.. /a Path.root.join("a/b") // => /a/b Path.root.join("a").join("b") // => /a/b Path.root.join("a").join("/b") // => /a/b - Note: `..` and `.` components are interpreted. - Note: pathComponent *may* be multiple components. - Note: symlinks are *not* resolved. - Parameter pathComponent: The string to join with this path. - Returns: A new joined path. - SeeAlso: `Path./(_:_:)` */ public func join(_ addendum: S) -> Path where S: StringProtocol { return Path(string: join_(prefix: string, appending: addendum)) } /** Joins a path and a string to produce a new path. Path.root/"a" // => /a Path.root/"a/b" // => /a/b Path.root/"a"/"b" // => /a/b Path.root/"a"/"/b" // => /a/b - Note: `..` and `.` components are interpreted. - Note: pathComponent *may* be multiple components. - Note: symlinks are *not* resolved. - Parameter lhs: The base path to join with `rhs`. - Parameter rhs: The string to join with this `lhs`. - Returns: A new joined path. - SeeAlso: `join(_:)` */ @inlinable public static func /(lhs: Path, rhs: S) -> Path where S: StringProtocol { return lhs.join(rhs) } /** Returns a string representing the relative path to `base`. - Note: If `base` is not a logical prefix for `self` your result will be prefixed some number of `../` components. - Parameter base: The base to which we calculate the relative path. - ToDo: Another variant that returns `nil` if result would start with `..` */ public func relative(to base: Path) -> String { // Split the two paths into their components. // FIXME: The is needs to be optimized to avoid unncessary copying. let pathComps = (string as NSString).pathComponents let baseComps = (base.string as NSString).pathComponents // It's common for the base to be an ancestor, so try that first. if pathComps.starts(with: baseComps) { // Special case, which is a plain path without `..` components. It // might be an empty path (when self and the base are equal). let relComps = pathComps.dropFirst(baseComps.count) return relComps.joined(separator: "/") } else { // General case, in which we might well need `..` components to go // "up" before we can go "down" the directory tree. var newPathComps = ArraySlice(pathComps) var newBaseComps = ArraySlice(baseComps) while newPathComps.prefix(1) == newBaseComps.prefix(1) { // First component matches, so drop it. newPathComps = newPathComps.dropFirst() newBaseComps = newBaseComps.dropFirst() } // Now construct a path consisting of as many `..`s as are in the // `newBaseComps` followed by what remains in `newPathComps`. var relComps = Array(repeating: "..", count: newBaseComps.count) relComps.append(contentsOf: newPathComps) return relComps.joined(separator: "/") } } /** The basename for the provided file, optionally dropping the file extension. Path.root.join("foo.swift").basename() // => "foo.swift" Path.root.join("foo.swift").basename(dropExtension: true) // => "foo" - Returns: A string that is the filename’s basename. - Parameter dropExtension: If `true` returns the basename without its file extension. */ public func basename(dropExtension: Bool = false) -> String { var lastPathComponent: Substring { let slash = string.lastIndex(of: "/")! let index = string.index(after: slash) return string[index...] } var go: Substring { if !dropExtension { return lastPathComponent } else { let ext = self.extension if !ext.isEmpty { return lastPathComponent.dropLast(ext.count + 1) } else { return lastPathComponent } } } return String(go) } /** If the path represents an actual entry that is a symlink, returns the symlink’s absolute destination. - Important: This is not exhaustive, the resulting path may still contain symlink. - Important: The path will only be different if the last path component is a symlink, any symlinks in prior components are not resolved. - Note: If file exists but isn’t a symlink, returns `self`. - Note: If symlink destination does not exist, is **not** an error. */ public func readlink() throws -> Path { do { let rv = try FileManager.default.destinationOfSymbolicLink(atPath: string) return Path(rv) ?? parent/rv } catch CocoaError.fileReadUnknown { // file is not symlink, return `self` assert(exists) return self } catch { #if os(Linux) // ugh: Swift on Linux let nsError = error as NSError if nsError.domain == NSCocoaErrorDomain, nsError.code == CocoaError.fileReadUnknown.rawValue, exists { return self } #endif throw error } } /// Recursively resolves symlinks in this path. public func realpath() throws -> Path { guard let rv = _realpath(string, nil) else { throw CocoaError.error(.fileNoSuchFile) } defer { free(rv) } guard let rvv = String(validatingUTF8: rv) else { throw CocoaError.error(.fileReadUnknownStringEncoding) } // “Removing an initial component of “/private/var/automount”, “/var/automount”, // or “/private” from the path, if the result still indicates an existing file or // directory (checked by consulting the file system).” // ^^ we do this to not conflict with the results that other Apple APIs give // which is necessary if we are to have equality checks work reliably let rvvv = (rvv as NSString).standardizingPath return Path(string: rvvv) } /// Returns the locale-aware sort order for the two paths. /// :nodoc: @inlinable public static func <(lhs: Path, rhs: Path) -> Bool { return lhs.string.compare(rhs.string, locale: .current) == .orderedAscending } } @inline(__always) private func join_(prefix: String, appending: S) -> String where S: StringProtocol { return join_(prefix: prefix, pathComponents: appending.split(separator: "/")) } private func join_(prefix: String, pathComponents: S) -> String where S: Sequence, S.Element: StringProtocol { assert(prefix.first == "/") var rv = prefix for component in pathComponents { assert(!component.contains("/")) switch component { case "..": let start = rv.indices.startIndex let index = rv.lastIndex(of: "/")! if start == index { rv = "/" } else { rv = String(rv[start.. { case pending(Handlers) case resolved(R) } final class Handlers { var bodies: [(R) -> Void] = [] func append(_ item: @escaping(R) -> Void) { bodies.append(item) } } /// - Remark: not protocol ∵ http://www.russbishop.net/swift-associated-types-cont class Box { func inspect() -> Sealant { fatalError() } func inspect(_: (Sealant) -> Void) { fatalError() } func seal(_: T) {} } final class SealedBox: Box { let value: T init(value: T) { self.value = value } override func inspect() -> Sealant { return .resolved(value) } } class EmptyBox: Box { private var sealant = Sealant.pending(.init()) private let barrier = DispatchQueue(label: "org.promisekit.barrier", attributes: .concurrent) override func seal(_ value: T) { var handlers: Handlers! barrier.sync(flags: .barrier) { guard case .pending(let _handlers) = self.sealant else { return // already fulfilled! } handlers = _handlers self.sealant = .resolved(value) } //FIXME we are resolved so should `pipe(to:)` be called at this instant, “thens are called in order” would be invalid //NOTE we don’t do this in the above `sync` because that could potentially deadlock //THOUGH since `then` etc. typically invoke after a run-loop cycle, this issue is somewhat less severe if let handlers = handlers { handlers.bodies.forEach{ $0(value) } } //TODO solution is an unfortunate third state “sealed” where then's get added // to a separate handler pool for that state // any other solution has potential races } override func inspect() -> Sealant { var rv: Sealant! barrier.sync { rv = self.sealant } return rv } override func inspect(_ body: (Sealant) -> Void) { var sealed = false barrier.sync(flags: .barrier) { switch sealant { case .pending: // body will append to handlers, so we must stay barrier’d body(sealant) case .resolved: sealed = true } } if sealed { // we do this outside the barrier to prevent potential deadlocks // it's safe because we never transition away from this state body(sealant) } } } extension Optional where Wrapped: DispatchQueue { @inline(__always) func async(flags: DispatchWorkItemFlags?, _ body: @escaping() -> Void) { switch self { case .none: body() case .some(let q): if let flags = flags { q.async(flags: flags, execute: body) } else { q.async(execute: body) } } } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Catchable.swift ================================================ import Dispatch /// Provides `catch` and `recover` to your object that conforms to `Thenable` public protocol CatchMixin: Thenable {} public extension CatchMixin { /** The provided closure executes when this promise rejects. Rejecting a promise cascades: rejecting all subsequent promises (unless recover is invoked) thus you will typically place your catch at the end of a chain. Often utility promises will not have a catch, instead delegating the error handling to the caller. - Parameter on: The queue to which the provided closure dispatches. - Parameter policy: The default policy does not execute your handler for cancellation errors. - Parameter execute: The handler to execute if this promise is rejected. - Returns: A promise finalizer. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ @discardableResult func `catch`(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> PMKFinalizer { let finalizer = PMKFinalizer() pipe { switch $0 { case .rejected(let error): guard policy == .allErrors || !error.isCancelled else { fallthrough } on.async(flags: flags) { body(error) finalizer.pending.resolve(()) } case .fulfilled: finalizer.pending.resolve(()) } } return finalizer } } public class PMKFinalizer { let pending = Guarantee.pending() /// `finally` is the same as `ensure`, but it is not chainable public func finally(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Void) { pending.guarantee.done(on: on, flags: flags) { body() } } } public extension CatchMixin { /** The provided closure executes when this promise rejects. Unlike `catch`, `recover` continues the chain. Use `recover` in circumstances where recovering the chain from certain errors is a possibility. For example: firstly { CLLocationManager.requestLocation() }.recover { error in guard error == CLError.unknownLocation else { throw error } return .value(CLLocation.chicago) } - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The handler to execute if this promise is rejected. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> U) -> Promise where U.T == T { let rp = Promise(.pending) pipe { switch $0 { case .fulfilled(let value): rp.box.seal(.fulfilled(value)) case .rejected(let error): if policy == .allErrors || !error.isCancelled { on.async(flags: flags) { do { let rv = try body(error) guard rv !== rp else { throw PMKError.returnedSelf } rv.pipe(to: rp.box.seal) } catch { rp.box.seal(.rejected(error)) } } } else { rp.box.seal(.rejected(error)) } } } return rp } /** The provided closure executes when this promise rejects. This variant of `recover` requires the handler to return a Guarantee, thus it returns a Guarantee itself and your closure cannot `throw`. - Note it is logically impossible for this to take a `catchPolicy`, thus `allErrors` are handled. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The handler to execute if this promise is rejected. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ @discardableResult func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Guarantee) -> Guarantee { let rg = Guarantee(.pending) pipe { switch $0 { case .fulfilled(let value): rg.box.seal(value) case .rejected(let error): on.async(flags: flags) { body(error).pipe(to: rg.box.seal) } } } return rg } /** The provided closure executes when this promise resolves, whether it rejects or not. firstly { UIApplication.shared.networkActivityIndicatorVisible = true }.done { //… }.ensure { UIApplication.shared.networkActivityIndicatorVisible = false }.catch { //… } - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that executes when this promise resolves. - Returns: A new promise, resolved with this promise’s resolution. */ func ensure(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Void) -> Promise { let rp = Promise(.pending) pipe { result in on.async(flags: flags) { body() rp.box.seal(result) } } return rp } /** The provided closure executes when this promise resolves, whether it rejects or not. The chain waits on the returned `Guarantee`. firstly { setup() }.done { //… }.ensureThen { teardown() // -> Guarante }.catch { //… } - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that executes when this promise resolves. - Returns: A new promise, resolved with this promise’s resolution. */ func ensureThen(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping () -> Guarantee) -> Promise { let rp = Promise(.pending) pipe { result in on.async(flags: flags) { body().done { rp.box.seal(result) } } } return rp } /** Consumes the Swift unused-result warning. - Note: You should `catch`, but in situations where you know you don’t need a `catch`, `cauterize` makes your intentions clear. */ @discardableResult func cauterize() -> PMKFinalizer { return self.catch { conf.logHandler(.cauterized($0)) } } } public extension CatchMixin where T == Void { /** The provided closure executes when this promise rejects. This variant of `recover` is specialized for `Void` promises and de-errors your chain returning a `Guarantee`, thus you cannot `throw` and you must handle all errors including cancellation. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The handler to execute if this promise is rejected. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ @discardableResult func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Void) -> Guarantee { let rg = Guarantee(.pending) pipe { switch $0 { case .fulfilled: rg.box.seal(()) case .rejected(let error): on.async(flags: flags) { body(error) rg.box.seal(()) } } } return rg } /** The provided closure executes when this promise rejects. This variant of `recover` ensures that no error is thrown from the handler and allows specifying a catch policy. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The handler to execute if this promise is rejected. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ func recover(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) throws -> Void) -> Promise { let rg = Promise(.pending) pipe { switch $0 { case .fulfilled: rg.box.seal(.fulfilled(())) case .rejected(let error): if policy == .allErrors || !error.isCancelled { on.async(flags: flags) { do { rg.box.seal(.fulfilled(try body(error))) } catch { rg.box.seal(.rejected(error)) } } } else { rg.box.seal(.rejected(error)) } } } return rg } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Configuration.swift ================================================ import Dispatch /** PromiseKit’s configurable parameters. Do not change these after any Promise machinery executes as the configuration object is not thread-safe. We would like it to be, but sadly `Swift` does not expose `dispatch_once` et al. which is what we used to use in order to make the configuration immutable once first used. */ public struct PMKConfiguration { /// The default queues that promises handlers dispatch to public var Q: (map: DispatchQueue?, return: DispatchQueue?) = (map: DispatchQueue.main, return: DispatchQueue.main) /// The default catch-policy for all `catch` and `resolve` public var catchPolicy = CatchPolicy.allErrorsExceptCancellation /// The closure used to log PromiseKit events. /// Not thread safe; change before processing any promises. /// - Note: The default handler calls `print()` public var logHandler: (LogEvent) -> () = { event in switch event { case .waitOnMainThread: print("PromiseKit: warning: `wait()` called on main thread!") case .pendingPromiseDeallocated: print("PromiseKit: warning: pending promise deallocated") case .pendingGuaranteeDeallocated: print("PromiseKit: warning: pending guarantee deallocated") case .cauterized (let error): print("PromiseKit:cauterized-error: \(error)") } } } /// Modify this as soon as possible in your application’s lifetime public var conf = PMKConfiguration() ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/CustomStringConvertible.swift ================================================ extension Promise: CustomStringConvertible { /// - Returns: A description of the state of this promise. public var description: String { switch result { case nil: return "Promise(…\(T.self))" case .rejected(let error)?: return "Promise(\(error))" case .fulfilled(let value)?: return "Promise(\(value))" } } } extension Promise: CustomDebugStringConvertible { /// - Returns: A debug-friendly description of the state of this promise. public var debugDescription: String { switch box.inspect() { case .pending(let handlers): return "Promise<\(T.self)>.pending(handlers: \(handlers.bodies.count))" case .resolved(.rejected(let error)): return "Promise<\(T.self)>.rejected(\(type(of: error)).\(error))" case .resolved(.fulfilled(let value)): return "Promise<\(T.self)>.fulfilled(\(value))" } } } #if !SWIFT_PACKAGE extension AnyPromise { /// - Returns: A description of the state of this promise. override open var description: String { switch box.inspect() { case .pending: return "AnyPromise(…)" case .resolved(let obj?): return "AnyPromise(\(obj))" case .resolved(nil): return "AnyPromise(nil)" } } } #endif ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Error.swift ================================================ import Foundation public enum PMKError: Error { /** The completionHandler with form `(T?, Error?)` was called with `(nil, nil)`. This is invalid as per Cocoa/Apple calling conventions. */ case invalidCallingConvention /** A handler returned its own promise. 99% of the time, this is likely a programming error. It is also invalid per Promises/A+. */ case returnedSelf /** `when()`, `race()` etc. were called with invalid parameters, eg. an empty array. */ case badInput /// The operation was cancelled case cancelled /// `nil` was returned from `flatMap` @available(*, deprecated, message: "See: `compactMap`") case flatMap(Any, Any.Type) /// `nil` was returned from `compactMap` case compactMap(Any, Any.Type) /** The lastValue or firstValue of a sequence was requested but the sequence was empty. Also used if all values of this collection failed the test passed to `firstValue(where:)`. */ case emptySequence } extension PMKError: CustomDebugStringConvertible { public var debugDescription: String { switch self { case .flatMap(let obj, let type): return "Could not `flatMap<\(type)>`: \(obj)" case .compactMap(let obj, let type): return "Could not `compactMap<\(type)>`: \(obj)" case .invalidCallingConvention: return "A closure was called with an invalid calling convention, probably (nil, nil)" case .returnedSelf: return "A promise handler returned itself" case .badInput: return "Bad input was provided to a PromiseKit function" case .cancelled: return "The asynchronous sequence was cancelled" case .emptySequence: return "The first or last element was requested for an empty sequence" } } } extension PMKError: LocalizedError { public var errorDescription: String? { return debugDescription } } //////////////////////////////////////////////////////////// Cancellation /// An error that may represent the cancelled condition public protocol CancellableError: Error { /// returns true if this Error represents a cancelled condition var isCancelled: Bool { get } } extension Error { public var isCancelled: Bool { do { throw self } catch PMKError.cancelled { return true } catch let error as CancellableError { return error.isCancelled } catch URLError.cancelled { return true } catch CocoaError.userCancelled { return true } catch { #if os(macOS) || os(iOS) || os(tvOS) let pair = { ($0.domain, $0.code) }(error as NSError) return ("SKErrorDomain", 2) == pair #else return false #endif } } } /// Used by `catch` and `recover` public enum CatchPolicy { /// Indicates that `catch` or `recover` handle all error types including cancellable-errors. case allErrors /// Indicates that `catch` or `recover` handle all error except cancellable-errors. case allErrorsExceptCancellation } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Guarantee.swift ================================================ import class Foundation.Thread import Dispatch /** A `Guarantee` is a functional abstraction around an asynchronous operation that cannot error. - See: `Thenable` */ public final class Guarantee: Thenable { let box: PromiseKit.Box fileprivate init(box: SealedBox) { self.box = box } /// Returns a `Guarantee` sealed with the provided value. public static func value(_ value: T) -> Guarantee { return .init(box: SealedBox(value: value)) } /// Returns a pending `Guarantee` that can be resolved with the provided closure’s parameter. public init(resolver body: (@escaping(T) -> Void) -> Void) { box = Box() body(box.seal) } /// - See: `Thenable.pipe` public func pipe(to: @escaping(Result) -> Void) { pipe{ to(.fulfilled($0)) } } func pipe(to: @escaping(T) -> Void) { switch box.inspect() { case .pending: box.inspect { switch $0 { case .pending(let handlers): handlers.append(to) case .resolved(let value): to(value) } } case .resolved(let value): to(value) } } /// - See: `Thenable.result` public var result: Result? { switch box.inspect() { case .pending: return nil case .resolved(let value): return .fulfilled(value) } } final private class Box: EmptyBox { deinit { switch inspect() { case .pending: PromiseKit.conf.logHandler(.pendingGuaranteeDeallocated) case .resolved: break } } } init(_: PMKUnambiguousInitializer) { box = Box() } /// Returns a tuple of a pending `Guarantee` and a function that resolves it. public class func pending() -> (guarantee: Guarantee, resolve: (T) -> Void) { return { ($0, $0.box.seal) }(Guarantee(.pending)) } } public extension Guarantee { @discardableResult func done(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> Void) -> Guarantee { let rg = Guarantee(.pending) pipe { (value: T) in on.async(flags: flags) { body(value) rg.box.seal(()) } } return rg } func get(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping (T) -> Void) -> Guarantee { return map(on: on, flags: flags) { body($0) return $0 } } func map(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> U) -> Guarantee { let rg = Guarantee(.pending) pipe { value in on.async(flags: flags) { rg.box.seal(body(value)) } } return rg } @discardableResult func then(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) -> Guarantee) -> Guarantee { let rg = Guarantee(.pending) pipe { value in on.async(flags: flags) { body(value).pipe(to: rg.box.seal) } } return rg } func asVoid() -> Guarantee { return map(on: nil) { _ in } } /** Blocks this thread, so you know, don’t call this on a serial thread that any part of your chain may use. Like the main thread for example. */ func wait() -> T { if Thread.isMainThread { conf.logHandler(.waitOnMainThread) } var result = value if result == nil { let group = DispatchGroup() group.enter() pipe { (foo: T) in result = foo; group.leave() } group.wait() } return result! } } public extension Guarantee where T: Sequence { /** `Guarantee<[T]>` => `T` -> `Guarantee` => `Guaranetee<[U]>` firstly { .value([1,2,3]) }.thenMap { .value($0 * 2) }.done { // $0 => [2,4,6] } */ func thenMap(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) -> Guarantee) -> Guarantee<[U]> { return then(on: on, flags: flags) { when(fulfilled: $0.map(transform)) }.recover { // if happens then is bug inside PromiseKit fatalError(String(describing: $0)) } } } #if swift(>=3.1) public extension Guarantee where T == Void { convenience init() { self.init(box: SealedBox(value: Void())) } } #endif public extension DispatchQueue { /** Asynchronously executes the provided closure on a dispatch queue. DispatchQueue.global().async(.promise) { md5(input) }.done { md5 in //… } - Parameter body: The closure that resolves this promise. - Returns: A new `Guarantee` resolved by the result of the provided closure. - Note: There is no Promise/Thenable version of this due to Swift compiler ambiguity issues. */ @available(macOS 10.10, iOS 2.0, tvOS 10.0, watchOS 2.0, *) final func async(_: PMKNamespacer, group: DispatchGroup? = nil, qos: DispatchQoS = .default, flags: DispatchWorkItemFlags = [], execute body: @escaping () -> T) -> Guarantee { let rg = Guarantee(.pending) async(group: group, qos: qos, flags: flags) { rg.box.seal(body()) } return rg } } #if os(Linux) import func CoreFoundation._CFIsMainThread extension Thread { // `isMainThread` is not implemented yet in swift-corelibs-foundation. static var isMainThread: Bool { return _CFIsMainThread() } } #endif ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/LogEvent.swift ================================================ /** The PromiseKit events which may be logged. ```` /// A promise or guarantee has blocked the main thread case waitOnMainThread /// A promise has been deallocated without being fulfilled case pendingPromiseDeallocated /// An error which occurred while fulfilling a promise was swallowed case cauterized(Error) /// Errors which give a string error message case misc (String) ```` */ public enum LogEvent { /// A promise or guarantee has blocked the main thread case waitOnMainThread /// A promise has been deallocated without being fulfilled case pendingPromiseDeallocated /// A guarantee has been deallocated without being fulfilled case pendingGuaranteeDeallocated /// An error which occurred while fulfilling a promise was swallowed case cauterized(Error) } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Promise.swift ================================================ import class Foundation.Thread import Dispatch /** A `Promise` is a functional abstraction around a failable asynchronous operation. - See: `Thenable` */ public final class Promise: Thenable, CatchMixin { let box: Box> fileprivate init(box: SealedBox>) { self.box = box } /** Initialize a new fulfilled promise. We do not provide `init(value:)` because Swift is “greedy” and would pick that initializer in cases where it should pick one of the other more specific options leading to Promises with `T` that is eg: `Error` or worse `(T->Void,Error->Void)` for uses of our PMK < 4 pending initializer due to Swift trailing closure syntax (nothing good comes without pain!). Though often easy to detect, sometimes these issues would be hidden by other type inference leading to some nasty bugs in production. In PMK5 we tried to work around this by making the pending initializer take the form `Promise(.pending)` but this led to bad migration errors for PMK4 users. Hence instead we quickly released PMK6 and now only provide this initializer for making sealed & fulfilled promises. Usage is still (usually) good: guard foo else { return .value(bar) } */ public class func value(_ value: T) -> Promise { return Promise(box: SealedBox(value: .fulfilled(value))) } /// Initialize a new rejected promise. public init(error: Error) { box = SealedBox(value: .rejected(error)) } /// Initialize a new promise bound to the provided `Thenable`. public init(_ bridge: U) where U.T == T { box = EmptyBox() bridge.pipe(to: box.seal) } /// Initialize a new promise that can be resolved with the provided `Resolver`. public init(resolver body: (Resolver) throws -> Void) { box = EmptyBox() let resolver = Resolver(box) do { try body(resolver) } catch { resolver.reject(error) } } /// - Returns: a tuple of a new pending promise and its `Resolver`. public class func pending() -> (promise: Promise, resolver: Resolver) { return { ($0, Resolver($0.box)) }(Promise(.pending)) } /// - See: `Thenable.pipe` public func pipe(to: @escaping(Result) -> Void) { switch box.inspect() { case .pending: box.inspect { switch $0 { case .pending(let handlers): handlers.append(to) case .resolved(let value): to(value) } } case .resolved(let value): to(value) } } /// - See: `Thenable.result` public var result: Result? { switch box.inspect() { case .pending: return nil case .resolved(let result): return result } } init(_: PMKUnambiguousInitializer) { box = EmptyBox() } } public extension Promise { /** Blocks this thread, so—you know—don’t call this on a serial thread that any part of your chain may use. Like the main thread for example. */ func wait() throws -> T { if Thread.isMainThread { conf.logHandler(LogEvent.waitOnMainThread) } var result = self.result if result == nil { let group = DispatchGroup() group.enter() pipe { result = $0; group.leave() } group.wait() } switch result! { case .rejected(let error): throw error case .fulfilled(let value): return value } } } #if swift(>=3.1) extension Promise where T == Void { /// Initializes a new promise fulfilled with `Void` public convenience init() { self.init(box: SealedBox(value: .fulfilled(Void()))) } } #endif public extension DispatchQueue { /** Asynchronously executes the provided closure on a dispatch queue. DispatchQueue.global().async(.promise) { try md5(input) }.done { md5 in //… } - Parameter body: The closure that resolves this promise. - Returns: A new `Promise` resolved by the result of the provided closure. - Note: There is no Promise/Thenable version of this due to Swift compiler ambiguity issues. */ @available(macOS 10.10, iOS 8.0, tvOS 9.0, watchOS 2.0, *) final func async(_: PMKNamespacer, group: DispatchGroup? = nil, qos: DispatchQoS = .default, flags: DispatchWorkItemFlags = [], execute body: @escaping () throws -> T) -> Promise { let promise = Promise(.pending) async(group: group, qos: qos, flags: flags) { do { promise.box.seal(.fulfilled(try body())) } catch { promise.box.seal(.rejected(error)) } } return promise } } /// used by our extensions to provide unambiguous functions with the same name as the original function public enum PMKNamespacer { case promise } enum PMKUnambiguousInitializer { case pending } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Resolver.swift ================================================ /// An object for resolving promises public final class Resolver { let box: Box> init(_ box: Box>) { self.box = box } deinit { if case .pending = box.inspect() { conf.logHandler(.pendingPromiseDeallocated) } } } public extension Resolver { /// Fulfills the promise with the provided value func fulfill(_ value: T) { box.seal(.fulfilled(value)) } /// Rejects the promise with the provided error func reject(_ error: Error) { box.seal(.rejected(error)) } /// Resolves the promise with the provided result func resolve(_ result: Result) { box.seal(result) } /// Resolves the promise with the provided value or error func resolve(_ obj: T?, _ error: Error?) { if let error = error { reject(error) } else if let obj = obj { fulfill(obj) } else { reject(PMKError.invalidCallingConvention) } } /// Fulfills the promise with the provided value unless the provided error is non-nil func resolve(_ obj: T, _ error: Error?) { if let error = error { reject(error) } else { fulfill(obj) } } /// Resolves the promise, provided for non-conventional value-error ordered completion handlers. func resolve(_ error: Error?, _ obj: T?) { resolve(obj, error) } } #if swift(>=3.1) extension Resolver where T == Void { /// Fulfills the promise unless error is non-nil public func resolve(_ error: Error?) { if let error = error { reject(error) } else { fulfill(()) } } #if false // disabled ∵ https://github.com/mxcl/PromiseKit/issues/990 /// Fulfills the promise public func fulfill() { self.fulfill(()) } #else /// Fulfills the promise /// - Note: underscore is present due to: https://github.com/mxcl/PromiseKit/issues/990 public func fulfill_() { self.fulfill(()) } #endif } #endif public enum Result { case fulfilled(T) case rejected(Error) } public extension PromiseKit.Result { var isFulfilled: Bool { switch self { case .fulfilled: return true case .rejected: return false } } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/Thenable.swift ================================================ import Dispatch /// Thenable represents an asynchronous operation that can be chained. public protocol Thenable: class { /// The type of the wrapped value associatedtype T /// `pipe` is immediately executed when this `Thenable` is resolved func pipe(to: @escaping(Result) -> Void) /// The resolved result or nil if pending. var result: Result? { get } } public extension Thenable { /** The provided closure executes when this promise resolves. This allows chaining promises. The promise returned by the provided closure is resolved before the promise returned by this closure resolves. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that executes when this promise fulfills. It must return a promise. - Returns: A new promise that resolves when the promise returned from the provided closure resolves. For example: firstly { URLSession.shared.dataTask(.promise, with: url1) }.then { response in transform(data: response.data) }.done { transformation in //… } */ func then(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) throws -> U) -> Promise { let rp = Promise(.pending) pipe { switch $0 { case .fulfilled(let value): on.async(flags: flags) { do { let rv = try body(value) guard rv !== rp else { throw PMKError.returnedSelf } rv.pipe(to: rp.box.seal) } catch { rp.box.seal(.rejected(error)) } } case .rejected(let error): rp.box.seal(.rejected(error)) } } return rp } /** The provided closure is executed when this promise is resolved. This is like `then` but it requires the closure to return a non-promise. - Parameter on: The queue to which the provided closure dispatches. - Parameter transform: The closure that is executed when this Promise is fulfilled. It must return a non-promise. - Returns: A new promise that is resolved with the value returned from the provided closure. For example: firstly { URLSession.shared.dataTask(.promise, with: url1) }.map { response in response.data.length }.done { length in //… } */ func map(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T) throws -> U) -> Promise { let rp = Promise(.pending) pipe { switch $0 { case .fulfilled(let value): on.async(flags: flags) { do { rp.box.seal(.fulfilled(try transform(value))) } catch { rp.box.seal(.rejected(error)) } } case .rejected(let error): rp.box.seal(.rejected(error)) } } return rp } /** The provided closure is executed when this promise is resolved. In your closure return an `Optional`, if you return `nil` the resulting promise is rejected with `PMKError.compactMap`, otherwise the promise is fulfilled with the unwrapped value. firstly { URLSession.shared.dataTask(.promise, with: url) }.compactMap { try JSONSerialization.jsonObject(with: $0.data) as? [String: String] }.done { dictionary in //… }.catch { // either `PMKError.compactMap` or a `JSONError` } */ func compactMap(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T) throws -> U?) -> Promise { let rp = Promise(.pending) pipe { switch $0 { case .fulfilled(let value): on.async(flags: flags) { do { if let rv = try transform(value) { rp.box.seal(.fulfilled(rv)) } else { throw PMKError.compactMap(value, U.self) } } catch { rp.box.seal(.rejected(error)) } } case .rejected(let error): rp.box.seal(.rejected(error)) } } return rp } /** The provided closure is executed when this promise is resolved. Equivalent to `map { x -> Void in`, but since we force the `Void` return Swift is happier and gives you less hassle about your closure’s qualification. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that is executed when this Promise is fulfilled. - Returns: A new promise fulfilled as `Void`. firstly { URLSession.shared.dataTask(.promise, with: url) }.done { response in print(response.data) } */ func done(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(T) throws -> Void) -> Promise { let rp = Promise(.pending) pipe { switch $0 { case .fulfilled(let value): on.async(flags: flags) { do { try body(value) rp.box.seal(.fulfilled(())) } catch { rp.box.seal(.rejected(error)) } } case .rejected(let error): rp.box.seal(.rejected(error)) } } return rp } /** The provided closure is executed when this promise is resolved. This is like `done` but it returns the same value that the handler is fed. `get` immutably accesses the fulfilled value; the returned Promise maintains that value. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that is executed when this Promise is fulfilled. - Returns: A new promise that is resolved with the value that the handler is fed. For example: firstly { .value(1) }.get { foo in print(foo, " is 1") }.done { foo in print(foo, " is 1") }.done { foo in print(foo, " is Void") } */ func get(on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping (T) throws -> Void) -> Promise { return map(on: on, flags: flags) { try body($0) return $0 } } /** The provided closure is executed with promise result. This is like `get` but provides the Result of the Promise so you can inspect the value of the chain at this point without causing any side effects. - Parameter on: The queue to which the provided closure dispatches. - Parameter body: The closure that is executed with Result of Promise. - Returns: A new promise that is resolved with the result that the handler is fed. For example: promise.tap{ print($0) }.then{ /*…*/ } */ func tap(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Result) -> Void) -> Promise { return Promise { seal in pipe { result in on.async(flags: flags) { body(result) seal.resolve(result) } } } } /// - Returns: a new promise chained off this promise but with its value discarded. func asVoid() -> Promise { return map(on: nil) { _ in } } } public extension Thenable { /** - Returns: The error with which this promise was rejected; `nil` if this promise is not rejected. */ var error: Error? { switch result { case .none: return nil case .some(.fulfilled): return nil case .some(.rejected(let error)): return error } } /** - Returns: `true` if the promise has not yet resolved. */ var isPending: Bool { return result == nil } /** - Returns: `true` if the promise has resolved. */ var isResolved: Bool { return !isPending } /** - Returns: `true` if the promise was fulfilled. */ var isFulfilled: Bool { return value != nil } /** - Returns: `true` if the promise was rejected. */ var isRejected: Bool { return error != nil } /** - Returns: The value with which this promise was fulfilled or `nil` if this promise is pending or rejected. */ var value: T? { switch result { case .none: return nil case .some(.fulfilled(let value)): return value case .some(.rejected): return nil } } } public extension Thenable where T: Sequence { /** `Promise<[T]>` => `T` -> `U` => `Promise<[U]>` firstly { .value([1,2,3]) }.mapValues { integer in integer * 2 }.done { // $0 => [2,4,6] } */ func mapValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U]> { return map(on: on, flags: flags){ try $0.map(transform) } } /** `Promise<[T]>` => `T` -> `[U]` => `Promise<[U]>` firstly { .value([1,2,3]) }.flatMapValues { integer in [integer, integer] }.done { // $0 => [1,1,2,2,3,3] } */ func flatMapValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U.Iterator.Element]> { return map(on: on, flags: flags){ (foo: T) in try foo.flatMap{ try transform($0) } } } /** `Promise<[T]>` => `T` -> `U?` => `Promise<[U]>` firstly { .value(["1","2","a","3"]) }.compactMapValues { Int($0) }.done { // $0 => [1,2,3] } */ func compactMapValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) throws -> U?) -> Promise<[U]> { return map(on: on, flags: flags) { foo -> [U] in #if !swift(>=3.3) || (swift(>=4) && !swift(>=4.1)) return try foo.flatMap(transform) #else return try foo.compactMap(transform) #endif } } /** `Promise<[T]>` => `T` -> `Promise` => `Promise<[U]>` firstly { .value([1,2,3]) }.thenMap { integer in .value(integer * 2) }.done { // $0 => [2,4,6] } */ func thenMap(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U.T]> { return then(on: on, flags: flags) { when(fulfilled: try $0.map(transform)) } } /** `Promise<[T]>` => `T` -> `Promise<[U]>` => `Promise<[U]>` firstly { .value([1,2,3]) }.thenFlatMap { integer in .value([integer, integer]) }.done { // $0 => [1,1,2,2,3,3] } */ func thenFlatMap(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ transform: @escaping(T.Iterator.Element) throws -> U) -> Promise<[U.T.Iterator.Element]> where U.T: Sequence { return then(on: on, flags: flags) { when(fulfilled: try $0.map(transform)) }.map(on: nil) { $0.flatMap{ $0 } } } /** `Promise<[T]>` => `T` -> Bool => `Promise<[U]>` firstly { .value([1,2,3]) }.filterValues { $0 > 1 }.done { // $0 => [2,3] } */ func filterValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, _ isIncluded: @escaping (T.Iterator.Element) -> Bool) -> Promise<[T.Iterator.Element]> { return map(on: on, flags: flags) { $0.filter(isIncluded) } } } public extension Thenable where T: Collection { /// - Returns: a promise fulfilled with the first value of this `Collection` or, if empty, a promise rejected with PMKError.emptySequence. var firstValue: Promise { return map(on: nil) { aa in if let a1 = aa.first { return a1 } else { throw PMKError.emptySequence } } } func firstValue(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil, where test: @escaping (T.Iterator.Element) -> Bool) -> Promise { return map(on: on, flags: flags) { for x in $0 where test(x) { return x } throw PMKError.emptySequence } } /// - Returns: a promise fulfilled with the last value of this `Collection` or, if empty, a promise rejected with PMKError.emptySequence. var lastValue: Promise { return map(on: nil) { aa in if aa.isEmpty { throw PMKError.emptySequence } else { let i = aa.index(aa.endIndex, offsetBy: -1) return aa[i] } } } } public extension Thenable where T: Sequence, T.Iterator.Element: Comparable { /// - Returns: a promise fulfilled with the sorted values of this `Sequence`. func sortedValues(on: DispatchQueue? = conf.Q.map, flags: DispatchWorkItemFlags? = nil) -> Promise<[T.Iterator.Element]> { return map(on: on, flags: flags){ $0.sorted() } } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/after.swift ================================================ import struct Foundation.TimeInterval import Dispatch /** after(seconds: 1.5).then { //… } - Returns: A guarantee that resolves after the specified duration. */ public func after(seconds: TimeInterval) -> Guarantee { let (rg, seal) = Guarantee.pending() let when = DispatchTime.now() + seconds #if swift(>=4.0) q.asyncAfter(deadline: when) { seal(()) } #else q.asyncAfter(deadline: when, execute: seal) #endif return rg } /** after(.seconds(2)).then { //… } - Returns: A guarantee that resolves after the specified duration. */ public func after(_ interval: DispatchTimeInterval) -> Guarantee { let (rg, seal) = Guarantee.pending() let when = DispatchTime.now() + interval #if swift(>=4.0) q.asyncAfter(deadline: when) { seal(()) } #else q.asyncAfter(deadline: when, execute: seal) #endif return rg } private var q: DispatchQueue { if #available(macOS 10.10, iOS 8.0, tvOS 9.0, watchOS 2.0, *) { return DispatchQueue.global(qos: .default) } else { return DispatchQueue.global(priority: .default) } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/firstly.swift ================================================ import Dispatch /** Judicious use of `firstly` *may* make chains more readable. Compare: URLSession.shared.dataTask(url: url1).then { URLSession.shared.dataTask(url: url2) }.then { URLSession.shared.dataTask(url: url3) } With: firstly { URLSession.shared.dataTask(url: url1) }.then { URLSession.shared.dataTask(url: url2) }.then { URLSession.shared.dataTask(url: url3) } - Note: the block you pass excecutes immediately on the current thread/queue. */ public func firstly(execute body: () throws -> U) -> Promise { do { let rp = Promise(.pending) try body().pipe(to: rp.box.seal) return rp } catch { return Promise(error: error) } } /// - See: firstly() public func firstly(execute body: () -> Guarantee) -> Guarantee { return body() } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/hang.swift ================================================ import Foundation import CoreFoundation /** Runs the active run-loop until the provided promise resolves. This is for debug and is not a generally safe function to use in your applications. We mostly provide it for use in testing environments. Still if you like, study how it works (by reading the sources!) and use at your own risk. - Returns: The value of the resolved promise - Throws: An error, should the promise be rejected - See: `wait()` */ public func hang(_ promise: Promise) throws -> T { #if os(Linux) || os(Android) // isMainThread is not yet implemented on Linux. let runLoopModeRaw = RunLoopMode.defaultRunLoopMode.rawValue._bridgeToObjectiveC() let runLoopMode: CFString = unsafeBitCast(runLoopModeRaw, to: CFString.self) #else guard Thread.isMainThread else { // hang doesn't make sense on threads that aren't the main thread. // use `.wait()` on those threads. fatalError("Only call hang() on the main thread.") } let runLoopMode: CFRunLoopMode = CFRunLoopMode.defaultMode #endif if promise.isPending { var context = CFRunLoopSourceContext() let runLoop = CFRunLoopGetCurrent() let runLoopSource = CFRunLoopSourceCreate(nil, 0, &context) CFRunLoopAddSource(runLoop, runLoopSource, runLoopMode) _ = promise.ensure { CFRunLoopStop(runLoop) } while promise.isPending { CFRunLoopRun() } CFRunLoopRemoveSource(runLoop, runLoopSource, runLoopMode) } switch promise.result! { case .rejected(let error): throw error case .fulfilled(let value): return value } } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/race.swift ================================================ @inline(__always) private func _race(_ thenables: [U]) -> Promise { let rp = Promise(.pending) for thenable in thenables { thenable.pipe(to: rp.box.seal) } return rp } /** Waits for one promise to resolve race(promise1, promise2, promise3).then { winner in //… } - Returns: The promise that resolves first - Warning: If the first resolution is a rejection, the returned promise is rejected */ public func race(_ thenables: U...) -> Promise { return _race(thenables) } /** Waits for one promise to resolve race(promise1, promise2, promise3).then { winner in //… } - Returns: The promise that resolves first - Warning: If the first resolution is a rejection, the returned promise is rejected - Remark: If the provided array is empty the returned promise is rejected with PMKError.badInput */ public func race(_ thenables: [U]) -> Promise { guard !thenables.isEmpty else { return Promise(error: PMKError.badInput) } return _race(thenables) } /** Waits for one guarantee to resolve race(promise1, promise2, promise3).then { winner in //… } - Returns: The guarantee that resolves first */ public func race(_ guarantees: Guarantee...) -> Guarantee { let rg = Guarantee(.pending) for guarantee in guarantees { guarantee.pipe(to: rg.box.seal) } return rg } ================================================ FILE: Dependencies/mxcl∕PromiseKit-6.8.3/when.swift ================================================ import Foundation import Dispatch private func _when(_ thenables: [U]) -> Promise { var countdown = thenables.count guard countdown > 0 else { return .value(Void()) } let rp = Promise(.pending) #if PMKDisableProgress || os(Linux) var progress: (completedUnitCount: Int, totalUnitCount: Int) = (0, 0) #else let progress = Progress(totalUnitCount: Int64(thenables.count)) progress.isCancellable = false progress.isPausable = false #endif let barrier = DispatchQueue(label: "org.promisekit.barrier.when", attributes: .concurrent) for promise in thenables { promise.pipe { result in barrier.sync(flags: .barrier) { switch result { case .rejected(let error): if rp.isPending { progress.completedUnitCount = progress.totalUnitCount rp.box.seal(.rejected(error)) } case .fulfilled: guard rp.isPending else { return } progress.completedUnitCount += 1 countdown -= 1 if countdown == 0 { rp.box.seal(.fulfilled(())) } } } } } return rp } /** Wait for all promises in a set to fulfill. For example: when(fulfilled: promise1, promise2).then { results in //… }.catch { error in switch error { case URLError.notConnectedToInternet: //… case CLError.denied: //… } } - Note: If *any* of the provided promises reject, the returned promise is immediately rejected with that error. - Warning: In the event of rejection the other promises will continue to resolve and, as per any other promise, will either fulfill or reject. This is the right pattern for `getter` style asynchronous tasks, but often for `setter` tasks (eg. storing data on a server), you most likely will need to wait on all tasks and then act based on which have succeeded and which have failed, in such situations use `when(resolved:)`. - Parameter promises: The promises upon which to wait before the returned promise resolves. - Returns: A new promise that resolves when all the provided promises fulfill or one of the provided promises rejects. - Note: `when` provides `NSProgress`. - SeeAlso: `when(resolved:)` */ public func when(fulfilled thenables: [U]) -> Promise<[U.T]> { return _when(thenables).map(on: nil) { thenables.map{ $0.value! } } } /// Wait for all promises in a set to fulfill. public func when(fulfilled promises: U...) -> Promise where U.T == Void { return _when(promises) } /// Wait for all promises in a set to fulfill. public func when(fulfilled promises: [U]) -> Promise where U.T == Void { return _when(promises) } /// Wait for all promises in a set to fulfill. public func when(fulfilled pu: U, _ pv: V) -> Promise<(U.T, V.T)> { return _when([pu.asVoid(), pv.asVoid()]).map(on: nil) { (pu.value!, pv.value!) } } /// Wait for all promises in a set to fulfill. public func when(fulfilled pu: U, _ pv: V, _ pw: W) -> Promise<(U.T, V.T, W.T)> { return _when([pu.asVoid(), pv.asVoid(), pw.asVoid()]).map(on: nil) { (pu.value!, pv.value!, pw.value!) } } /// Wait for all promises in a set to fulfill. public func when(fulfilled pu: U, _ pv: V, _ pw: W, _ px: X) -> Promise<(U.T, V.T, W.T, X.T)> { return _when([pu.asVoid(), pv.asVoid(), pw.asVoid(), px.asVoid()]).map(on: nil) { (pu.value!, pv.value!, pw.value!, px.value!) } } /// Wait for all promises in a set to fulfill. public func when(fulfilled pu: U, _ pv: V, _ pw: W, _ px: X, _ py: Y) -> Promise<(U.T, V.T, W.T, X.T, Y.T)> { return _when([pu.asVoid(), pv.asVoid(), pw.asVoid(), px.asVoid(), py.asVoid()]).map(on: nil) { (pu.value!, pv.value!, pw.value!, px.value!, py.value!) } } /** Generate promises at a limited rate and wait for all to fulfill. For example: func downloadFile(url: URL) -> Promise { // ... } let urls: [URL] = /*…*/ let urlGenerator = urls.makeIterator() let generator = AnyIterator> { guard url = urlGenerator.next() else { return nil } return downloadFile(url) } when(generator, concurrently: 3).done { datas in // ... } No more than three downloads will occur simultaneously. - Note: The generator is called *serially* on a *background* queue. - Warning: Refer to the warnings on `when(fulfilled:)` - Parameter promiseGenerator: Generator of promises. - Returns: A new promise that resolves when all the provided promises fulfill or one of the provided promises rejects. - SeeAlso: `when(resolved:)` */ public func when(fulfilled promiseIterator: It, concurrently: Int) -> Promise<[It.Element.T]> where It.Element: Thenable { guard concurrently > 0 else { return Promise(error: PMKError.badInput) } var generator = promiseIterator var root = Promise<[It.Element.T]>.pending() var pendingPromises = 0 var promises: [It.Element] = [] let barrier = DispatchQueue(label: "org.promisekit.barrier.when", attributes: [.concurrent]) func dequeue() { guard root.promise.isPending else { return } // don’t continue dequeueing if root has been rejected var shouldDequeue = false barrier.sync { shouldDequeue = pendingPromises < concurrently } guard shouldDequeue else { return } var index: Int! var promise: It.Element! barrier.sync(flags: .barrier) { guard let next = generator.next() else { return } promise = next index = promises.count pendingPromises += 1 promises.append(next) } func testDone() { barrier.sync { if pendingPromises == 0 { #if !swift(>=3.3) || (swift(>=4) && !swift(>=4.1)) root.resolver.fulfill(promises.flatMap{ $0.value }) #else root.resolver.fulfill(promises.compactMap{ $0.value }) #endif } } } guard promise != nil else { return testDone() } promise.pipe { resolution in barrier.sync(flags: .barrier) { pendingPromises -= 1 } switch resolution { case .fulfilled: dequeue() testDone() case .rejected(let error): root.resolver.reject(error) } } dequeue() } dequeue() return root.promise } /** Waits on all provided promises. `when(fulfilled:)` rejects as soon as one of the provided promises rejects. `when(resolved:)` waits on all provided promises whatever their result, and then provides an array of `Result` so you can individually inspect the results. As a consequence this function returns a `Guarantee`, ie. errors are lifted from the individual promises into the results array of the returned `Guarantee`. when(resolved: promise1, promise2, promise3).then { results in for result in results where case .fulfilled(let value) { //… } }.catch { error in // invalid! Never rejects } - Returns: A new promise that resolves once all the provided promises resolve. The array is ordered the same as the input, ie. the result order is *not* resolution order. - Note: we do not provide tuple variants for `when(resolved:)` but will accept a pull-request - Remark: Doesn't take Thenable due to protocol `associatedtype` paradox */ public func when(resolved promises: Promise...) -> Guarantee<[Result]> { return when(resolved: promises) } /// - See: `when(resolved: Promise...)` public func when(resolved promises: [Promise]) -> Guarantee<[Result]> { guard !promises.isEmpty else { return .value([]) } var countdown = promises.count let barrier = DispatchQueue(label: "org.promisekit.barrier.join", attributes: .concurrent) let rg = Guarantee<[Result]>(.pending) for promise in promises { promise.pipe { result in barrier.sync(flags: .barrier) { countdown -= 1 } barrier.sync { if countdown == 0 { rg.box.seal(promises.map{ $0.result! }) } } } } return rg } /// Waits on all provided Guarantees. public func when(_ guarantees: Guarantee...) -> Guarantee { return when(guarantees: guarantees) } // Waits on all provided Guarantees. public func when(guarantees: [Guarantee]) -> Guarantee { return when(fulfilled: guarantees).recover{ _ in }.asVoid() } ================================================ FILE: Dependencies/mxcl∕Version-1.0.3/Version+Codable.swift ================================================ extension Version: Codable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let s = try container.decode(String.self) guard let v = Version(s) else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid semantic version") } self = v } public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(description) } } ================================================ FILE: Dependencies/mxcl∕Version-1.0.3/Version+Comparable.swift ================================================ extension Version: Comparable { func isEqualWithoutPrerelease(_ other: Version) -> Bool { return major == other.major && minor == other.minor && patch == other.patch } /** `1.0.0` is less than `1.0.1`, `1.0.1-alpha` is less than `1.0.1` but greater than `1.0.0`. - Returns: `true` if `lhs` is less than `rhs` */ public static func < (lhs: Version, rhs: Version) -> Bool { let lhsComparators = [lhs.major, lhs.minor, lhs.patch] let rhsComparators = [rhs.major, rhs.minor, rhs.patch] if lhsComparators != rhsComparators { return lhsComparators.lexicographicallyPrecedes(rhsComparators) } guard lhs.prereleaseIdentifiers.count > 0 else { return false // Non-prerelease lhs >= potentially prerelease rhs } guard rhs.prereleaseIdentifiers.count > 0 else { return true // Prerelease lhs < non-prerelease rhs } let zippedIdentifiers = zip(lhs.prereleaseIdentifiers, rhs.prereleaseIdentifiers) for (lhsPrereleaseIdentifier, rhsPrereleaseIdentifier) in zippedIdentifiers { if lhsPrereleaseIdentifier == rhsPrereleaseIdentifier { continue } let typedLhsIdentifier: Any = Int(lhsPrereleaseIdentifier) ?? lhsPrereleaseIdentifier let typedRhsIdentifier: Any = Int(rhsPrereleaseIdentifier) ?? rhsPrereleaseIdentifier switch (typedLhsIdentifier, typedRhsIdentifier) { case let (int1 as Int, int2 as Int): return int1 < int2 case let (string1 as String, string2 as String): return string1 < string2 case (is Int, is String): return true // Int prereleases < String prereleases case (is String, is Int): return false default: fatalError("impossi-op") } } return lhs.prereleaseIdentifiers.count < rhs.prereleaseIdentifiers.count } } ================================================ FILE: Dependencies/mxcl∕Version-1.0.3/Version+Foundation.swift ================================================ import struct Foundation.OperatingSystemVersion import class Foundation.ProcessInfo import class Foundation.Bundle /// An extension to Bundle that provides Versions public extension Bundle { /** The version of the bundle. - Remark: We use a tolerant parser, so strings like `10.1` or even `3` will parse. - Note: Uses the value for the key `CFBundleShortVersionString`. - Important: Returns `0.0.0` (`Version.null`) if result is absent or invalid. */ var version: Version { return (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String).flatMap(Version.init(tolerant:)) ?? .null } } /// An extension to ProcessInfo that provides Versions public extension ProcessInfo { /// The version of the operating system on which the process is executing. @available(OSX, introduced: 10.10) @available(iOS, introduced: 8.0) var osVersion: Version { //NOTE cannot call “super” from an extension that replaces that method // tried to use keypaths but couldn’t. This way we are not making the // method ambiguous anyway, so probably better. let v: OperatingSystemVersion = operatingSystemVersion return Version(major: v.majorVersion, minor: v.minorVersion, patch: v.patchVersion) } } ================================================ FILE: Dependencies/mxcl∕Version-1.0.3/Version+Range.swift ================================================ extension ClosedRange where Bound == Version { /** - Returns: `true` if the provided Version exists within this range. - Important: Returns `false` if `version` has prerelease identifiers unless the range *also* contains prerelease identifiers. */ public func contains(_ version: Version) -> Bool { // Special cases if version contains prerelease identifiers. if !version.prereleaseIdentifiers.isEmpty, lowerBound.prereleaseIdentifiers.isEmpty && upperBound.prereleaseIdentifiers.isEmpty { // If the range does not contain prerelease identifiers, return false. return false } // Otherwise, apply normal contains rules. return version >= lowerBound && version <= upperBound } } extension Range where Bound == Version { /** - Returns: `true` if the provided Version exists within this range. - Important: Returns `false` if `version` has prerelease identifiers unless the range *also* contains prerelease identifiers. */ public func contains(_ version: Version) -> Bool { // Special cases if version contains prerelease identifiers. if !version.prereleaseIdentifiers.isEmpty { // If the range does not contain prerelease identifiers, return false. if lowerBound.prereleaseIdentifiers.isEmpty && upperBound.prereleaseIdentifiers.isEmpty { return false } // At this point, one of the bounds contains prerelease identifiers. // Reject 2.0.0-alpha when upper bound is 2.0.0. if upperBound.prereleaseIdentifiers.isEmpty && upperBound.isEqualWithoutPrerelease(version) { return false } } // Otherwise, apply normal contains rules. return version >= lowerBound && version < upperBound } } ================================================ FILE: Dependencies/mxcl∕Version-1.0.3/Version.swift ================================================ /* This source file was modified by Max Howell from its original form that was part of the Swift open source project. This source file is part of the Swift.org open source project Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See http://swift.org/LICENSE.txt for license information See http://swift.org/CONTRIBUTORS.txt for Swift project authors */ /** A struct representing a “semver” version, that is: a Semantic Version. - SeeAlso: https://semver.org */ public struct Version: Hashable { /// The major version. public let major: Int /// The minor version. public let minor: Int /// The patch version. public let patch: Int /// The pre-release identifiers (if any). public let prereleaseIdentifiers: [String] /// The build metadatas (if any). public let buildMetadataIdentifiers: [String] /** Create a version object. - Note: Integers are made absolute since negative integers are not allowed, yet it is conventional Swift to take `Int` over `UInt` where possible. - Remark: This initializer variant provided for more readable code when initializing with static integers. */ @inlinable public init(_ major: Int, _ minor: Int, _ patch: Int, prereleaseIdentifiers: [String] = [], buildMetadataIdentifiers: [String] = []) { self.major = abs(major) self.minor = abs(minor) self.patch = abs(patch) self.prereleaseIdentifiers = prereleaseIdentifiers self.buildMetadataIdentifiers = buildMetadataIdentifiers if major < 0 || minor < 0 || patch < 0 { print("warning: negative component in version: \(major).\(minor).\(patch)") print("notice: negative components were abs’d") } } /** Creates a version object. - Note: Integers are made absolute since negative integers are not allowed, yet it is conventional Swift to take `Int` over `UInt` where possible. - Remark: This initializer variant provided when it would be more readable than the nameless variant. */ @inlinable public init(major: Int, minor: Int, patch: Int, prereleaseIdentifiers: [String] = [], buildMetadataIdentifiers: [String] = []) { self.init(major, minor, patch, prereleaseIdentifiers: prereleaseIdentifiers, buildMetadataIdentifiers: buildMetadataIdentifiers) } /// Represents `0.0.0` public static let null = Version(0,0,0) } extension Version: LosslessStringConvertible { /** Creates a version object from a string. - Note: Returns `nil` if the string is not a valid semantic version. - Parameter string: The string to parse. */ public init?(_ string: String) { let prereleaseStartIndex = string.firstIndex(of: "-") let metadataStartIndex = string.firstIndex(of: "+") let requiredEndIndex = prereleaseStartIndex ?? metadataStartIndex ?? string.endIndex let requiredCharacters = string.prefix(upTo: requiredEndIndex) let requiredComponents = requiredCharacters .split(separator: ".", maxSplits: 2, omittingEmptySubsequences: false) .compactMap{ Int($0) } guard requiredComponents.count == 3 else { return nil } self.major = requiredComponents[0] self.minor = requiredComponents[1] self.patch = requiredComponents[2] func identifiers(start: String.Index?, end: String.Index) -> [String] { guard let start = start else { return [] } let identifiers = string[string.index(after: start).. Void // MARK: - Properties let identifier = UUID() public let keyCombo: KeyCombo public var keyDownHandler: Handler? public var keyUpHandler: Handler? public var isPaused = false { didSet { if isPaused { HotKeysController.unregister(self) } else { HotKeysController.register(self) } } } // MARK: - Initializers public init(keyCombo: KeyCombo, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) { self.keyCombo = keyCombo self.keyDownHandler = keyDownHandler self.keyUpHandler = keyUpHandler HotKeysController.register(self) } public convenience init(carbonKeyCode: UInt32, carbonModifiers: UInt32, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) { let keyCombo = KeyCombo(carbonKeyCode: carbonKeyCode, carbonModifiers: carbonModifiers) self.init(keyCombo: keyCombo, keyDownHandler: keyDownHandler, keyUpHandler: keyUpHandler) } public convenience init(key: Key, modifiers: NSEvent.ModifierFlags, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) { let keyCombo = KeyCombo(key: key, modifiers: modifiers) self.init(keyCombo: keyCombo, keyDownHandler: keyDownHandler, keyUpHandler: keyUpHandler) } deinit { HotKeysController.unregister(self) } } ================================================ FILE: Dependencies/soffes∕HotKey-0.1.1/HotKeysController.swift ================================================ // // HotKeysController.swift // HotKey // // Created by Sam Soffes on 7/21/17. // Copyright © 2017 Sam Soffes. All rights reserved. // import Carbon final class HotKeysController { // MARK: - Types final class HotKeyBox { let identifier: UUID weak var hotKey: HotKey? let carbonHotKeyID: UInt32 var carbonEventHotKey: EventHotKeyRef? init(hotKey: HotKey, carbonHotKeyID: UInt32) { self.identifier = hotKey.identifier self.hotKey = hotKey self.carbonHotKeyID = carbonHotKeyID } } // MARK: - Properties static var hotKeys = [UInt32: HotKeyBox]() static private var hotKeysCount: UInt32 = 0 static let eventHotKeySignature: UInt32 = { let string = "SSHk" var result: FourCharCode = 0 for char in string.utf16 { result = (result << 8) + FourCharCode(char) } return result }() private static let eventSpec = [ EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)), EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyReleased)) ] private static var eventHandler: EventHandlerRef? // MARK: - Registration static func register(_ hotKey: HotKey) { // Don't register an already registered HotKey if hotKeys.values.first(where: { $0.identifier == hotKey.identifier }) != nil { return } // Increment the count which will become out next ID hotKeysCount += 1 // Create a box for our metadata and weak HotKey let box = HotKeyBox(hotKey: hotKey, carbonHotKeyID: hotKeysCount) hotKeys[box.carbonHotKeyID] = box // Register with the system var eventHotKey: EventHotKeyRef? let hotKeyID = EventHotKeyID(signature: eventHotKeySignature, id: box.carbonHotKeyID) let registerError = RegisterEventHotKey( hotKey.keyCombo.carbonKeyCode, hotKey.keyCombo.carbonModifiers, hotKeyID, GetEventDispatcherTarget(), 0, &eventHotKey ) // Ensure registration worked guard registerError == noErr, eventHotKey != nil else { return } // Store the event so we can unregister it later box.carbonEventHotKey = eventHotKey // Setup the event handler if needed updateEventHandler() } static func unregister(_ hotKey: HotKey) { // Find the box guard let box = self.box(for: hotKey) else { return } // Unregister the hot key UnregisterEventHotKey(box.carbonEventHotKey) // Destroy the box box.hotKey = nil hotKeys.removeValue(forKey: box.carbonHotKeyID) } // MARK: - Events static func handleCarbonEvent(_ event: EventRef?) -> OSStatus { // Ensure we have an event guard let event = event else { return OSStatus(eventNotHandledErr) } // Get the hot key ID from the event var hotKeyID = EventHotKeyID() let error = GetEventParameter( event, UInt32(kEventParamDirectObject), UInt32(typeEventHotKeyID), nil, MemoryLayout.size, nil, &hotKeyID ) if error != noErr { return error } // Ensure we have a HotKey registered for this ID guard hotKeyID.signature == eventHotKeySignature, let hotKey = self.hotKey(for: hotKeyID.id) else { return OSStatus(eventNotHandledErr) } // Call the handler switch GetEventKind(event) { case UInt32(kEventHotKeyPressed): if !hotKey.isPaused, let handler = hotKey.keyDownHandler { handler() return noErr } case UInt32(kEventHotKeyReleased): if !hotKey.isPaused, let handler = hotKey.keyUpHandler { handler() return noErr } default: break } return OSStatus(eventNotHandledErr) } private static func updateEventHandler() { if hotKeysCount == 0 || eventHandler != nil { return } // Register for key down and key up let eventSpec = [ EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)), EventTypeSpec(eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyReleased)) ] // Install the handler InstallEventHandler(GetEventDispatcherTarget(), hotKeyEventHandler, 2, eventSpec, nil, &eventHandler) } // MARK: - Querying private static func hotKey(for carbonHotKeyID: UInt32) -> HotKey? { if let hotKey = hotKeys[carbonHotKeyID]?.hotKey { return hotKey } hotKeys.removeValue(forKey: carbonHotKeyID) return nil } private static func box(for hotKey: HotKey) -> HotKeyBox? { for box in hotKeys.values { if box.identifier == hotKey.identifier { return box } } return nil } } private func hotKeyEventHandler(eventHandlerCall: EventHandlerCallRef?, event: EventRef?, userData: UnsafeMutableRawPointer?) -> OSStatus { return HotKeysController.handleCarbonEvent(event) } ================================================ FILE: Dependencies/soffes∕HotKey-0.1.1/Key.swift ================================================ // // Key.swift // HotKey // // Created by Sam Soffes on 7/21/17. // Copyright © 2017 Sam Soffes. All rights reserved. // import Carbon public enum Key { case a case s case d case f case h case g case z case x case c case v case b case q case w case e case r case y case t case one case two case three case four case six case five case equal case nine case seven case minus case eight case zero case rightBracket case o case u case leftBracket case i case p case l case j case quote case k case semicolon case backslash case comma case slash case n case m case period case grave case keypadDecimal case keypadMultiply case keypadPlus case keypadClear case keypadDivide case keypadEnter case keypadMinus case keypadEquals case keypad0 case keypad1 case keypad2 case keypad3 case keypad4 case keypad5 case keypad6 case keypad7 case keypad8 case keypad9 case `return` case tab case space case delete case escape case command case shift case capsLock case option case control case rightCommand case rightShift case rightOption case rightControl case function case f17 case volumeUp case volumeDown case mute case f18 case f19 case f20 case f5 case f6 case f7 case f3 case f8 case f9 case f11 case f13 case f16 case f14 case f10 case f12 case f15 case help case home case pageUp case forwardDelete case f4 case end case f2 case pageDown case f1 case leftArrow case rightArrow case downArrow case upArrow public init?(string: String) { switch string.lowercased() { case "a": self = .a case "s": self = .s case "d": self = .d case "f": self = .f case "h": self = .h case "g": self = .g case "z": self = .z case "x": self = .x case "c": self = .c case "v": self = .v case "b": self = .b case "q": self = .q case "w": self = .w case "e": self = .e case "r": self = .r case "y": self = .y case "t": self = .t case "one", "1": self = .one case "two", "2": self = .two case "three", "3": self = .three case "four", "4": self = .four case "six", "6": self = .six case "five", "5": self = .five case "equal", "=": self = .equal case "nine", "9": self = .nine case "seven", "7": self = .seven case "minus", "-": self = .minus case "eight", "8": self = .eight case "zero", "0": self = .zero case "rightBracket": self = .rightBracket case "o": self = .o case "u": self = .u case "leftBracket": self = .leftBracket case "i": self = .i case "p": self = .p case "l": self = .l case "j": self = .j case "quote", "\"": self = .quote case "k": self = .k case "semicolon", ";": self = .semicolon case "backslash", "\\": self = .backslash case "comma", ",": self = .comma case "slash", "/": self = .slash case "n": self = .n case "m": self = .m case "period", ".": self = .period case "grave": self = .grave case "keypaddecimal": self = .keypadDecimal case "keypadmultiply": self = .keypadMultiply case "keypadplus": self = .keypadPlus case "keypadclear": self = .keypadClear case "keypaddivide": self = .keypadDivide case "keypadenter": self = .keypadEnter case "keypadminus": self = .keypadMinus case "keypadequals": self = .keypadEquals case "keypad0": self = .keypad0 case "keypad1": self = .keypad1 case "keypad2": self = .keypad2 case "keypad3": self = .keypad3 case "keypad4": self = .keypad4 case "keypad5": self = .keypad5 case "keypad6": self = .keypad6 case "keypad7": self = .keypad7 case "keypad8": self = .keypad8 case "keypad9": self = .keypad9 case "return", "\r": self = .return case "tab", "\t": self = .tab case "space", " ": self = .space case "delete": self = .delete case "escape": self = .escape case "command": self = .command case "shift": self = .shift case "capsLock": self = .capsLock case "option": self = .option case "control": self = .control case "rightcommand": self = .rightCommand case "rightshift": self = .rightShift case "rightoption": self = .rightOption case "rightcontrol": self = .rightControl case "function": self = .function case "f17": self = .f17 case "volumeup": self = .volumeUp case "volumedown": self = .volumeDown case "mute": self = .mute case "f18": self = .f18 case "f19": self = .f19 case "f20": self = .f20 case "f5": self = .f5 case "f6": self = .f6 case "f7": self = .f7 case "f3": self = .f3 case "f8": self = .f8 case "f9": self = .f9 case "f11": self = .f11 case "f13": self = .f13 case "f16": self = .f16 case "f14": self = .f14 case "f10": self = .f10 case "f12": self = .f12 case "f15": self = .f15 case "help": self = .help case "home": self = .home case "pageup": self = .pageUp case "forwarddelete": self = .forwardDelete case "f4": self = .f4 case "end": self = .end case "f2": self = .f2 case "pagedown": self = .pageDown case "f1": self = .f1 case "leftarrow": self = .leftArrow case "rightarrow": self = .rightArrow case "downarrow": self = .downArrow case "uparrow": self = .upArrow default: return nil } } public init?(carbonKeyCode: UInt32) { switch carbonKeyCode { case UInt32(kVK_ANSI_A): self = .a case UInt32(kVK_ANSI_S): self = .s case UInt32(kVK_ANSI_D): self = .d case UInt32(kVK_ANSI_F): self = .f case UInt32(kVK_ANSI_H): self = .h case UInt32(kVK_ANSI_G): self = .g case UInt32(kVK_ANSI_Z): self = .z case UInt32(kVK_ANSI_X): self = .x case UInt32(kVK_ANSI_C): self = .c case UInt32(kVK_ANSI_V): self = .v case UInt32(kVK_ANSI_B): self = .b case UInt32(kVK_ANSI_Q): self = .q case UInt32(kVK_ANSI_W): self = .w case UInt32(kVK_ANSI_E): self = .e case UInt32(kVK_ANSI_R): self = .r case UInt32(kVK_ANSI_Y): self = .y case UInt32(kVK_ANSI_T): self = .t case UInt32(kVK_ANSI_1): self = .one case UInt32(kVK_ANSI_2): self = .two case UInt32(kVK_ANSI_3): self = .three case UInt32(kVK_ANSI_4): self = .four case UInt32(kVK_ANSI_6): self = .six case UInt32(kVK_ANSI_5): self = .five case UInt32(kVK_ANSI_Equal): self = .equal case UInt32(kVK_ANSI_9): self = .nine case UInt32(kVK_ANSI_7): self = .seven case UInt32(kVK_ANSI_Minus): self = .minus case UInt32(kVK_ANSI_8): self = .eight case UInt32(kVK_ANSI_0): self = .zero case UInt32(kVK_ANSI_RightBracket): self = .rightBracket case UInt32(kVK_ANSI_O): self = .o case UInt32(kVK_ANSI_U): self = .u case UInt32(kVK_ANSI_LeftBracket): self = .leftBracket case UInt32(kVK_ANSI_I): self = .i case UInt32(kVK_ANSI_P): self = .p case UInt32(kVK_ANSI_L): self = .l case UInt32(kVK_ANSI_J): self = .j case UInt32(kVK_ANSI_Quote): self = .quote case UInt32(kVK_ANSI_K): self = .k case UInt32(kVK_ANSI_Semicolon): self = .semicolon case UInt32(kVK_ANSI_Backslash): self = .backslash case UInt32(kVK_ANSI_Comma): self = .comma case UInt32(kVK_ANSI_Slash): self = .slash case UInt32(kVK_ANSI_N): self = .n case UInt32(kVK_ANSI_M): self = .m case UInt32(kVK_ANSI_Period): self = .period case UInt32(kVK_ANSI_Grave): self = .grave case UInt32(kVK_ANSI_KeypadDecimal): self = .keypadDecimal case UInt32(kVK_ANSI_KeypadMultiply): self = .keypadMultiply case UInt32(kVK_ANSI_KeypadPlus): self = .keypadPlus case UInt32(kVK_ANSI_KeypadClear): self = .keypadClear case UInt32(kVK_ANSI_KeypadDivide): self = .keypadDivide case UInt32(kVK_ANSI_KeypadEnter): self = .keypadEnter case UInt32(kVK_ANSI_KeypadMinus): self = .keypadMinus case UInt32(kVK_ANSI_KeypadEquals): self = .keypadEquals case UInt32(kVK_ANSI_Keypad0): self = .keypad0 case UInt32(kVK_ANSI_Keypad1): self = .keypad1 case UInt32(kVK_ANSI_Keypad2): self = .keypad2 case UInt32(kVK_ANSI_Keypad3): self = .keypad3 case UInt32(kVK_ANSI_Keypad4): self = .keypad4 case UInt32(kVK_ANSI_Keypad5): self = .keypad5 case UInt32(kVK_ANSI_Keypad6): self = .keypad6 case UInt32(kVK_ANSI_Keypad7): self = .keypad7 case UInt32(kVK_ANSI_Keypad8): self = .keypad8 case UInt32(kVK_ANSI_Keypad9): self = .keypad9 case UInt32(kVK_Return): self = .`return` case UInt32(kVK_Tab): self = .tab case UInt32(kVK_Space): self = .space case UInt32(kVK_Delete): self = .delete case UInt32(kVK_Escape): self = .escape case UInt32(kVK_Command): self = .command case UInt32(kVK_Shift): self = .shift case UInt32(kVK_CapsLock): self = .capsLock case UInt32(kVK_Option): self = .option case UInt32(kVK_Control): self = .control case UInt32(kVK_RightCommand): self = .rightCommand case UInt32(kVK_RightShift): self = .rightShift case UInt32(kVK_RightOption): self = .rightOption case UInt32(kVK_RightControl): self = .rightControl case UInt32(kVK_Function): self = .function case UInt32(kVK_F17): self = .f17 case UInt32(kVK_VolumeUp): self = .volumeUp case UInt32(kVK_VolumeDown): self = .volumeDown case UInt32(kVK_Mute): self = .mute case UInt32(kVK_F18): self = .f18 case UInt32(kVK_F19): self = .f19 case UInt32(kVK_F20): self = .f20 case UInt32(kVK_F5): self = .f5 case UInt32(kVK_F6): self = .f6 case UInt32(kVK_F7): self = .f7 case UInt32(kVK_F3): self = .f3 case UInt32(kVK_F8): self = .f8 case UInt32(kVK_F9): self = .f9 case UInt32(kVK_F11): self = .f11 case UInt32(kVK_F13): self = .f13 case UInt32(kVK_F16): self = .f16 case UInt32(kVK_F14): self = .f14 case UInt32(kVK_F10): self = .f10 case UInt32(kVK_F12): self = .f12 case UInt32(kVK_F15): self = .f15 case UInt32(kVK_Help): self = .help case UInt32(kVK_Home): self = .home case UInt32(kVK_PageUp): self = .pageUp case UInt32(kVK_ForwardDelete): self = .forwardDelete case UInt32(kVK_F4): self = .f4 case UInt32(kVK_End): self = .end case UInt32(kVK_F2): self = .f2 case UInt32(kVK_PageDown): self = .pageDown case UInt32(kVK_F1): self = .f1 case UInt32(kVK_LeftArrow): self = .leftArrow case UInt32(kVK_RightArrow): self = .rightArrow case UInt32(kVK_DownArrow): self = .downArrow case UInt32(kVK_UpArrow): self = .upArrow default: return nil } } public var carbonKeyCode: UInt32 { switch self { case .a: return UInt32(kVK_ANSI_A) case .s: return UInt32(kVK_ANSI_S) case .d: return UInt32(kVK_ANSI_D) case .f: return UInt32(kVK_ANSI_F) case .h: return UInt32(kVK_ANSI_H) case .g: return UInt32(kVK_ANSI_G) case .z: return UInt32(kVK_ANSI_Z) case .x: return UInt32(kVK_ANSI_X) case .c: return UInt32(kVK_ANSI_C) case .v: return UInt32(kVK_ANSI_V) case .b: return UInt32(kVK_ANSI_B) case .q: return UInt32(kVK_ANSI_Q) case .w: return UInt32(kVK_ANSI_W) case .e: return UInt32(kVK_ANSI_E) case .r: return UInt32(kVK_ANSI_R) case .y: return UInt32(kVK_ANSI_Y) case .t: return UInt32(kVK_ANSI_T) case .one: return UInt32(kVK_ANSI_1) case .two: return UInt32(kVK_ANSI_2) case .three: return UInt32(kVK_ANSI_3) case .four: return UInt32(kVK_ANSI_4) case .six: return UInt32(kVK_ANSI_6) case .five: return UInt32(kVK_ANSI_5) case .equal: return UInt32(kVK_ANSI_Equal) case .nine: return UInt32(kVK_ANSI_9) case .seven: return UInt32(kVK_ANSI_7) case .minus: return UInt32(kVK_ANSI_Minus) case .eight: return UInt32(kVK_ANSI_8) case .zero: return UInt32(kVK_ANSI_0) case .rightBracket: return UInt32(kVK_ANSI_RightBracket) case .o: return UInt32(kVK_ANSI_O) case .u: return UInt32(kVK_ANSI_U) case .leftBracket: return UInt32(kVK_ANSI_LeftBracket) case .i: return UInt32(kVK_ANSI_I) case .p: return UInt32(kVK_ANSI_P) case .l: return UInt32(kVK_ANSI_L) case .j: return UInt32(kVK_ANSI_J) case .quote: return UInt32(kVK_ANSI_Quote) case .k: return UInt32(kVK_ANSI_K) case .semicolon: return UInt32(kVK_ANSI_Semicolon) case .backslash: return UInt32(kVK_ANSI_Backslash) case .comma: return UInt32(kVK_ANSI_Comma) case .slash: return UInt32(kVK_ANSI_Slash) case .n: return UInt32(kVK_ANSI_N) case .m: return UInt32(kVK_ANSI_M) case .period: return UInt32(kVK_ANSI_Period) case .grave: return UInt32(kVK_ANSI_Grave) case .keypadDecimal: return UInt32(kVK_ANSI_KeypadDecimal) case .keypadMultiply: return UInt32(kVK_ANSI_KeypadMultiply) case .keypadPlus: return UInt32(kVK_ANSI_KeypadPlus) case .keypadClear: return UInt32(kVK_ANSI_KeypadClear) case .keypadDivide: return UInt32(kVK_ANSI_KeypadDivide) case .keypadEnter: return UInt32(kVK_ANSI_KeypadEnter) case .keypadMinus: return UInt32(kVK_ANSI_KeypadMinus) case .keypadEquals: return UInt32(kVK_ANSI_KeypadEquals) case .keypad0: return UInt32(kVK_ANSI_Keypad0) case .keypad1: return UInt32(kVK_ANSI_Keypad1) case .keypad2: return UInt32(kVK_ANSI_Keypad2) case .keypad3: return UInt32(kVK_ANSI_Keypad3) case .keypad4: return UInt32(kVK_ANSI_Keypad4) case .keypad5: return UInt32(kVK_ANSI_Keypad5) case .keypad6: return UInt32(kVK_ANSI_Keypad6) case .keypad7: return UInt32(kVK_ANSI_Keypad7) case .keypad8: return UInt32(kVK_ANSI_Keypad8) case .keypad9: return UInt32(kVK_ANSI_Keypad9) case .`return`: return UInt32(kVK_Return) case .tab: return UInt32(kVK_Tab) case .space: return UInt32(kVK_Space) case .delete: return UInt32(kVK_Delete) case .escape: return UInt32(kVK_Escape) case .command: return UInt32(kVK_Command) case .shift: return UInt32(kVK_Shift) case .capsLock: return UInt32(kVK_CapsLock) case .option: return UInt32(kVK_Option) case .control: return UInt32(kVK_Control) case .rightCommand: return UInt32(kVK_RightCommand) case .rightShift: return UInt32(kVK_RightShift) case .rightOption: return UInt32(kVK_RightOption) case .rightControl: return UInt32(kVK_RightControl) case .function: return UInt32(kVK_Function) case .f17: return UInt32(kVK_F17) case .volumeUp: return UInt32(kVK_VolumeUp) case .volumeDown: return UInt32(kVK_VolumeDown) case .mute: return UInt32(kVK_Mute) case .f18: return UInt32(kVK_F18) case .f19: return UInt32(kVK_F19) case .f20: return UInt32(kVK_F20) case .f5: return UInt32(kVK_F5) case .f6: return UInt32(kVK_F6) case .f7: return UInt32(kVK_F7) case .f3: return UInt32(kVK_F3) case .f8: return UInt32(kVK_F8) case .f9: return UInt32(kVK_F9) case .f11: return UInt32(kVK_F11) case .f13: return UInt32(kVK_F13) case .f16: return UInt32(kVK_F16) case .f14: return UInt32(kVK_F14) case .f10: return UInt32(kVK_F10) case .f12: return UInt32(kVK_F12) case .f15: return UInt32(kVK_F15) case .help: return UInt32(kVK_Help) case .home: return UInt32(kVK_Home) case .pageUp: return UInt32(kVK_PageUp) case .forwardDelete: return UInt32(kVK_ForwardDelete) case .f4: return UInt32(kVK_F4) case .end: return UInt32(kVK_End) case .f2: return UInt32(kVK_F2) case .pageDown: return UInt32(kVK_PageDown) case .f1: return UInt32(kVK_F1) case .leftArrow: return UInt32(kVK_LeftArrow) case .rightArrow: return UInt32(kVK_RightArrow) case .downArrow: return UInt32(kVK_DownArrow) case .upArrow: return UInt32(kVK_UpArrow) } } } ================================================ FILE: Dependencies/soffes∕HotKey-0.1.1/KeyCombo.swift ================================================ // // CarbonKeyCombo.swift // HotKey // // Created by Sam Soffes on 7/21/17. // Copyright © 2017 Sam Soffes. All rights reserved. // import AppKit public struct KeyCombo { // MARK: - Properties public var carbonKeyCode: UInt32 public var carbonModifiers: UInt32 public var key: Key? { get { return Key(carbonKeyCode: carbonKeyCode) } set { carbonKeyCode = newValue?.carbonKeyCode ?? 0 } } public var modifiers: NSEvent.ModifierFlags { get { return NSEvent.ModifierFlags(carbonFlags: carbonModifiers) } set { carbonModifiers = modifiers.carbonFlags } } public var isValid: Bool { return carbonKeyCode >= 0 } // MARK: - Initializers public init(carbonKeyCode: UInt32, carbonModifiers: UInt32 = 0) { self.carbonKeyCode = carbonKeyCode self.carbonModifiers = carbonModifiers } public init(key: Key, modifiers: NSEvent.ModifierFlags = []) { self.carbonKeyCode = key.carbonKeyCode self.carbonModifiers = modifiers.carbonFlags } // MARK: - Converting Keys public static func carbonKeyCodeToString(_ carbonKeyCode: UInt32) -> String? { return nil } } extension KeyCombo { public var dictionary: [String: Any] { return [ "keyCode": Int(carbonKeyCode), "modifiers": Int(carbonModifiers) ] } public init?(dictionary: [String: Any]) { guard let keyCode = dictionary["keyCode"] as? Int, let modifiers = dictionary["modifiers"] as? Int else { return nil } self.init(carbonKeyCode: UInt32(keyCode), carbonModifiers: UInt32(modifiers)) } } extension KeyCombo: Equatable { public static func == (lhs: KeyCombo, rhs: KeyCombo) -> Bool { return lhs.carbonKeyCode == rhs.carbonKeyCode && lhs.carbonModifiers == rhs.carbonModifiers } } ================================================ FILE: Dependencies/soffes∕HotKey-0.1.1/NSEventModifierFlags+HotKey.swift ================================================ // // NSEventModifierFlags+HotKey.swift // HotKey // // Created by Sam Soffes on 7/21/17. // Copyright © 2017 Sam Soffes. All rights reserved. // import AppKit import Carbon extension NSEvent.ModifierFlags { public var carbonFlags: UInt32 { var carbonFlags: UInt32 = 0 if contains(.command) { carbonFlags |= UInt32(cmdKey) } if contains(.option) { carbonFlags |= UInt32(optionKey) } if contains(.control) { carbonFlags |= UInt32(controlKey) } if contains(.shift) { carbonFlags |= UInt32(shiftKey) } return carbonFlags } public init(carbonFlags: UInt32) { self.init() if carbonFlags & UInt32(cmdKey) == UInt32(cmdKey) { insert(.command) } if carbonFlags & UInt32(optionKey) == UInt32(optionKey) { insert(.option) } if carbonFlags & UInt32(controlKey) == UInt32(controlKey) { insert(.control) } if carbonFlags & UInt32(shiftKey) == UInt32(shiftKey) { insert(.shift) } } } ================================================ FILE: Dependencies/tadija∕AEXML-4.3.3/Document.swift ================================================ /** * https://github.com/tadija/AEXML * Copyright (c) Marko Tadić 2014-2018 * Licensed under the MIT license. See LICENSE file. */ import Foundation /** This class is inherited from `AEXMLElement` and has a few addons to represent **XML Document**. XML Parsing is also done with this object. */ open class AEXMLDocument: AEXMLElement { // MARK: - Properties /// Root (the first child element) element of XML Document **(Empty element with error if not exists)**. open var root: AEXMLElement { guard let rootElement = children.first else { let errorElement = AEXMLElement(name: "Error") errorElement.error = AEXMLError.rootElementMissing return errorElement } return rootElement } public let options: AEXMLOptions // MARK: - Lifecycle /** Designated initializer - Creates and returns new XML Document object. - parameter root: Root XML element for XML Document (defaults to `nil`). - parameter options: Options for XML Document header and parser settings (defaults to `AEXMLOptions()`). - returns: Initialized XML Document object. */ public init(root: AEXMLElement? = nil, options: AEXMLOptions = AEXMLOptions()) { self.options = options let documentName = String(describing: AEXMLDocument.self) super.init(name: documentName) // document has no parent element parent = nil // add root element to document (if any) if let rootElement = root { _ = addChild(rootElement) } } /** Convenience initializer - used for parsing XML data (by calling `loadXMLData:` internally). - parameter xmlData: XML data to parse. - parameter options: Options for XML Document header and parser settings (defaults to `AEXMLOptions()`). - returns: Initialized XML Document object containing parsed data. Throws error if data could not be parsed. */ public convenience init(xml: Data, options: AEXMLOptions = AEXMLOptions()) throws { self.init(options: options) try loadXML(xml) } /** Convenience initializer - used for parsing XML string (by calling `init(xmlData:options:)` internally). - parameter xmlString: XML string to parse. - parameter encoding: String encoding for creating `Data` from `xmlString` (defaults to `String.Encoding.utf8`) - parameter options: Options for XML Document header and parser settings (defaults to `AEXMLOptions()`). - returns: Initialized XML Document object containing parsed data. Throws error if data could not be parsed. */ public convenience init(xml: String, encoding: String.Encoding = String.Encoding.utf8, options: AEXMLOptions = AEXMLOptions()) throws { guard let data = xml.data(using: encoding) else { throw AEXMLError.parsingFailed } try self.init(xml: data, options: options) } // MARK: - Parse XML /** Creates instance of `AEXMLParser` (private class which is simple wrapper around `XMLParser`) and starts parsing the given XML data. Throws error if data could not be parsed. - parameter data: XML which should be parsed. */ open func loadXML(_ data: Data) throws { children.removeAll(keepingCapacity: false) let xmlParser = AEXMLParser(document: self, data: data) try xmlParser.parse() } // MARK: - Override /// Override of `xml` property of `AEXMLElement` - it just inserts XML Document header at the beginning. open override var xml: String { var xml = "\(options.documentHeader.xmlString)\n" xml += root.xml return xml } } ================================================ FILE: Dependencies/tadija∕AEXML-4.3.3/Element.swift ================================================ /** * https://github.com/tadija/AEXML * Copyright (c) Marko Tadić 2014-2018 * Licensed under the MIT license. See LICENSE file. */ import Foundation /** This is base class for holding XML structure. You can access its structure by using subscript like this: `element["foo"]["bar"]` which would return `` element from `` XML as an `AEXMLElement` object. */ open class AEXMLElement { // MARK: - Properties /// Every `AEXMLElement` should have its parent element instead of `AEXMLDocument` which parent is `nil`. open internal(set) weak var parent: AEXMLElement? /// Child XML elements. open internal(set) var children = [AEXMLElement]() /// XML Element name. open var name: String /// XML Element value. open var value: String? /// XML Element attributes. open var attributes: [String : String] /// Error value (`nil` if there is no error). open var error: AEXMLError? /// String representation of `value` property (if `value` is `nil` this is empty String). open var string: String { return value ?? String() } /// Boolean representation of `value` property (`nil` if `value` can't be represented as Bool). open var bool: Bool? { return Bool(string) } /// Integer representation of `value` property (`nil` if `value` can't be represented as Integer). open var int: Int? { return Int(string) } /// Double representation of `value` property (`nil` if `value` can't be represented as Double). open var double: Double? { return Double(string) } // MARK: - Lifecycle /** Designated initializer - all parameters are optional. - parameter name: XML element name. - parameter value: XML element value (defaults to `nil`). - parameter attributes: XML element attributes (defaults to empty dictionary). - returns: An initialized `AEXMLElement` object. */ public init(name: String, value: String? = nil, attributes: [String : String] = [String : String]()) { self.name = name self.value = value self.attributes = attributes } // MARK: - XML Read /// The first element with given name **(Empty element with error if not exists)**. open subscript(key: String) -> AEXMLElement { guard let first = children.first(where: { $0.name == key }) else { let errorElement = AEXMLElement(name: key) errorElement.error = AEXMLError.elementNotFound return errorElement } return first } /// Returns all of the elements with equal name as `self` **(nil if not exists)**. open var all: [AEXMLElement]? { return parent?.children.filter { $0.name == self.name } } /// Returns the first element with equal name as `self` **(nil if not exists)**. open var first: AEXMLElement? { return all?.first } /// Returns the last element with equal name as `self` **(nil if not exists)**. open var last: AEXMLElement? { return all?.last } /// Returns number of all elements with equal name as `self`. open var count: Int { return all?.count ?? 0 } /** Returns all elements with given value. - parameter value: XML element value. - returns: Optional Array of found XML elements. */ open func all(withValue value: String) -> [AEXMLElement]? { let found = all?.compactMap { $0.value == value ? $0 : nil } return found } /** Returns all elements containing given attributes. - parameter attributes: Array of attribute names. - returns: Optional Array of found XML elements. */ open func all(containingAttributeKeys keys: [String]) -> [AEXMLElement]? { let found = all?.compactMap { element in keys.reduce(true) { (result, key) in result && Array(element.attributes.keys).contains(key) } ? element : nil } return found } /** Returns all elements with given attributes. - parameter attributes: Dictionary of Keys and Values of attributes. - returns: Optional Array of found XML elements. */ open func all(withAttributes attributes: [String : String]) -> [AEXMLElement]? { let keys = Array(attributes.keys) let found = all(containingAttributeKeys: keys)?.compactMap { element in attributes.reduce(true) { (result, attribute) in result && element.attributes[attribute.key] == attribute.value } ? element : nil } return found } /** Returns all descendant elements which satisfy the given predicate. Searching is done vertically; children are tested before siblings. Elements appear in the list in the order in which they are found. - parameter predicate: Function which returns `true` for a desired element and `false` otherwise. - returns: Array of found XML elements. */ open func allDescendants(where predicate: (AEXMLElement) -> Bool) -> [AEXMLElement] { var result: [AEXMLElement] = [] for child in children { if predicate(child) { result.append(child) } result.append(contentsOf: child.allDescendants(where: predicate)) } return result } /** Returns the first descendant element which satisfies the given predicate, or nil if no such element is found. Searching is done vertically; children are tested before siblings. - parameter predicate: Function which returns `true` for the desired element and `false` otherwise. - returns: Optional AEXMLElement. */ open func firstDescendant(where predicate: (AEXMLElement) -> Bool) -> AEXMLElement? { for child in children { if predicate(child) { return child } else if let descendant = child.firstDescendant(where: predicate) { return descendant } } return nil } /** Indicates whether the element has a descendant satisfying the given predicate. - parameter predicate: Function which returns `true` for the desired element and `false` otherwise. - returns: Bool. */ open func hasDescendant(where predicate: (AEXMLElement) -> Bool) -> Bool { return firstDescendant(where: predicate) != nil } // MARK: - XML Write /** Adds child XML element to `self`. - parameter child: Child XML element to add. - returns: Child XML element with `self` as `parent`. */ @discardableResult open func addChild(_ child: AEXMLElement) -> AEXMLElement { child.parent = self children.append(child) return child } /** Adds child XML element to `self`. - parameter name: Child XML element name. - parameter value: Child XML element value (defaults to `nil`). - parameter attributes: Child XML element attributes (defaults to empty dictionary). - returns: Child XML element with `self` as `parent`. */ @discardableResult open func addChild(name: String, value: String? = nil, attributes: [String : String] = [String : String]()) -> AEXMLElement { let child = AEXMLElement(name: name, value: value, attributes: attributes) return addChild(child) } /** Adds an array of XML elements to `self`. - parameter children: Child XML element array to add. - returns: Child XML elements with `self` as `parent`. */ @discardableResult open func addChildren(_ children: [AEXMLElement]) -> [AEXMLElement] { children.forEach{ addChild($0) } return children } /// Removes `self` from `parent` XML element. open func removeFromParent() { parent?.removeChild(self) } fileprivate func removeChild(_ child: AEXMLElement) { if let childIndex = children.index(where: { $0 === child }) { children.remove(at: childIndex) } } fileprivate var parentsCount: Int { var count = 0 var element = self while let parent = element.parent { count += 1 element = parent } return count } fileprivate func indent(withDepth depth: Int) -> String { var count = depth var indent = String() while count > 0 { indent += "\t" count -= 1 } return indent } /// Complete hierarchy of `self` and `children` in **XML** escaped and formatted String open var xml: String { var xml = String() // open element xml += indent(withDepth: parentsCount - 1) xml += "<\(name)" if attributes.count > 0 { // insert attributes for (key, value) in attributes { xml += " \(key)=\"\(value.xmlEscaped)\"" } } if value == nil && children.count == 0 { // close element xml += " />" } else { if children.count > 0 { // add children xml += ">\n" for child in children { xml += "\(child.xml)\n" } // add indentation xml += indent(withDepth: parentsCount - 1) xml += "" } else { // insert string value and close element xml += ">\(string.xmlEscaped)" } } return xml } /// Same as `xmlString` but without `\n` and `\t` characters open var xmlCompact: String { let chars = CharacterSet(charactersIn: "\n\t") return xml.components(separatedBy: chars).joined(separator: "") } /// Same as `xmlString` but with 4 spaces instead '\t' characters open var xmlSpaces: String { let chars = CharacterSet(charactersIn: "\t") return xml.components(separatedBy: chars).joined(separator: " ") } } public extension String { /// String representation of self with XML special characters escaped. public var xmlEscaped: String { // we need to make sure "&" is escaped first. Not doing this may break escaping the other characters var escaped = replacingOccurrences(of: "&", with: "&", options: .literal) // replace the other four special characters let escapeChars = ["<" : "<", ">" : ">", "'" : "'", "\"" : """] for (char, echar) in escapeChars { escaped = escaped.replacingOccurrences(of: char, with: echar, options: .literal) } return escaped } } ================================================ FILE: Dependencies/tadija∕AEXML-4.3.3/Error.swift ================================================ /** * https://github.com/tadija/AEXML * Copyright (c) Marko Tadić 2014-2018 * Licensed under the MIT license. See LICENSE file. */ import Foundation /// A type representing error value that can be thrown or inside `error` property of `AEXMLElement`. public enum AEXMLError: Error { /// This will be inside `error` property of `AEXMLElement` when subscript is used for not-existing element. case elementNotFound /// This will be inside `error` property of `AEXMLDocument` when there is no root element. case rootElementMissing /// `AEXMLDocument` can throw this error on `init` or `loadXMLData` if parsing with `XMLParser` was not successful. case parsingFailed } ================================================ FILE: Dependencies/tadija∕AEXML-4.3.3/Options.swift ================================================ /** * https://github.com/tadija/AEXML * Copyright (c) Marko Tadić 2014-2018 * Licensed under the MIT license. See LICENSE file. */ import Foundation /// Options used in `AEXMLDocument` public struct AEXMLOptions { /// Values used in XML Document header public struct DocumentHeader { /// Version value for XML Document header (defaults to 1.0). public var version = 1.0 /// Encoding value for XML Document header (defaults to "utf-8"). public var encoding = "utf-8" /// Standalone value for XML Document header (defaults to "no"). public var standalone = "no" /// XML Document header public var xmlString: String { return "" } } /// Settings used by `Foundation.XMLParser` public struct ParserSettings { /// Parser reports the namespaces and qualified names of elements. (defaults to `false`) public var shouldProcessNamespaces = false /// Parser reports the prefixes indicating the scope of namespace declarations. (defaults to `false`) public var shouldReportNamespacePrefixes = false /// Parser reports declarations of external entities. (defaults to `false`) public var shouldResolveExternalEntities = false /// Parser should trim whitespace from text nodes. (defaults to `true`) public var shouldTrimWhitespace = true } /// Values used in XML Document header (defaults to `DocumentHeader()`) public var documentHeader = DocumentHeader() /// Settings used by `Foundation.XMLParser` (defaults to `ParserSettings()`) public var parserSettings = ParserSettings() /// Designated initializer - Creates and returns default `AEXMLOptions`. public init() {} } ================================================ FILE: Dependencies/tadija∕AEXML-4.3.3/Parser.swift ================================================ /** * https://github.com/tadija/AEXML * Copyright (c) Marko Tadić 2014-2018 * Licensed under the MIT license. See LICENSE file. */ import Foundation /// Simple wrapper around `Foundation.XMLParser`. internal class AEXMLParser: NSObject, XMLParserDelegate { // MARK: - Properties let document: AEXMLDocument let data: Data var currentParent: AEXMLElement? var currentElement: AEXMLElement? var currentValue = String() var parseError: Error? private lazy var trimWhitespace: Bool = { let trim = self.document.options.parserSettings.shouldTrimWhitespace return trim }() // MARK: - Lifecycle init(document: AEXMLDocument, data: Data) { self.document = document self.data = data currentParent = document super.init() } // MARK: - API func parse() throws { let parser = XMLParser(data: data) parser.delegate = self parser.shouldProcessNamespaces = document.options.parserSettings.shouldProcessNamespaces parser.shouldReportNamespacePrefixes = document.options.parserSettings.shouldReportNamespacePrefixes parser.shouldResolveExternalEntities = document.options.parserSettings.shouldResolveExternalEntities let success = parser.parse() if !success { guard let error = parseError else { throw AEXMLError.parsingFailed } throw error } } // MARK: - XMLParserDelegate func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) { currentValue = String() currentElement = currentParent?.addChild(name: elementName, attributes: attributeDict) currentParent = currentElement } func parser(_ parser: XMLParser, foundCharacters string: String) { currentValue.append(string) currentElement?.value = currentValue.isEmpty ? nil : currentValue } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { if trimWhitespace { currentElement?.value = currentElement?.value?.trimmingCharacters(in: .whitespacesAndNewlines) } currentParent = currentParent?.parent currentElement = nil } func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) { self.parseError = parseError } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Errors/Errors.swift ================================================ import Foundation import PathKit // MARK: - Xcodeproj /// XcodeProj Errors /// /// - notFound: the project cannot be found. /// - pbxProjNotFound: the .pbxproj file couldn't be found inside the project folder. /// - xcworkspaceNotFound: the workspace cannot be found at the given path. public enum XCodeProjError: Error, CustomStringConvertible { case notFound(path: Path) case pbxprojNotFound(path: Path) case xcworkspaceNotFound(path: Path) public var description: String { switch self { case let .notFound(path): return "The project cannot be found at \(path.string)" case let .pbxprojNotFound(path): return "The project doesn't contain a .pbxproj file at path: \(path.string)" case let .xcworkspaceNotFound(path): return "The project doesn't contain a .xcworkspace at path: \(path.string)" } } } // MARK: - XCSharedData /// XCSharedData errors. /// /// - notFound: the share data hasn't been found. public enum XCSharedDataError: Error, CustomStringConvertible { case notFound(path: Path) public var description: String { switch self { case let .notFound(path): return "xcshareddata not found at path \(path.string)" } } } // MARK: - XCWorkspace /// XCWorkspace Errors /// /// - notFound: the project cannot be found. public enum XCWorkspaceError: Error, CustomStringConvertible { case notFound(path: Path) public var description: String { switch self { case let .notFound(path): return "The project cannot be found at \(path.string)" } } } // MARK: - XCWorkspaceData /// XCWorkspaceData Errors. /// /// - notFound: returned when the .xcworkspacedata cannot be found. public enum XCWorkspaceDataError: Error, CustomStringConvertible { case notFound(path: Path) public var description: String { switch self { case let .notFound(path): return "Workspace not found at \(path.string)" } } } // MARK: - Xcodeproj Editing /// Xcodeproj editing errors. /// /// - unexistingFile: the file doesn't exist. public enum XcodeprojEditingError: Error, CustomStringConvertible { case unexistingFile(Path) public var description: String { switch self { case let .unexistingFile(path): return "The file at path \(path.string) doesn't exist" } } } // MARK: - Xcodeproj Writing /// Xcodeproj writing error. /// /// - invalidType: the type that is being written is invalid. public enum XcodeprojWritingError: Error, CustomStringConvertible { case invalidType(class: String, expected: String) public var description: String { switch self { case let .invalidType(classType, expected): return "Invalid type for object \(classType) that expects a \(expected)" } } } // MARK: - PBXObject /// PBXObject error. /// /// - missingIsa: the isa attribute is missing. /// - unknownElement: the element that is being parsed is not supported. /// - objectsReleased: the project has been released or the object hasn't been added to any project. /// - objectNotFound: the object annot be found in the project. /// - orphaned: the object doesn't belong to any project. public enum PBXObjectError: Error, CustomStringConvertible { case missingIsa case unknownElement(String) case objectsReleased case objectNotFound(String) case orphaned(type: String, reference: String) public var description: String { switch self { case .missingIsa: return "Isa property is missing." case let .unknownElement(element): return "The element \(element) is not supported." case .objectsReleased: return "The PBXObjects instance has been released before saving." case let .objectNotFound(reference): return "PBXObject with reference \"\(reference)\" not found." case let .orphaned(type, reference): return "Trying to use object \(type) with reference '\(reference)' before being added to any project" } } } // MARK: - PBXProjEncoder /// PBXProjEncoder error. /// /// - emptyProjectReference: the project reference is missing. enum PBXProjEncoderError: Error, CustomStringConvertible { case emptyProjectReference var description: String { switch self { case .emptyProjectReference: return "PBXProj should contain a reference to the XcodeProj object that represents the project" } } } // MARK: - PBXProj /// PBXProj error. /// /// - notFound: the .pbxproj cannot be found at the given path. enum PBXProjError: Error, CustomStringConvertible { case notFound(path: Path) var description: String { switch self { case let .notFound(path): return ".pbxproj not found at path \(path.string)" } } } // MARK: - XCBreakpointList /// XCBreakpointList error. /// /// - notFound: returned when the Breakpoints_v2.xcbkptlist cannot be found. /// - missing: returned when there's a property missing in the Breakpoints_v2.xcbkptlist. public enum XCBreakpointListError: Error, CustomStringConvertible { case notFound(path: Path) case missing(property: String) public var description: String { switch self { case let .notFound(path): return "Breakpoints_v2.xcbkptlist couldn't be found at path \(path.string)" case let .missing(property): return "Property \(property) missing" } } } // MARK: - XCConfig /// XCConfig errors. /// /// - notFound: returned when the configuration file couldn't be found. public enum XCConfigError: Error, CustomStringConvertible { case notFound(path: Path) public var description: String { switch self { case let .notFound(path): return ".xcconfig file not found at \(path.string)" } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/AEXML+XcodeFormat.swift ================================================ import AEXML import Foundation extension AEXMLDocument { var xmlXcodeFormat: String { var xml = "\n" xml += root._xmlXcodeFormat + "\n" return xml } } let attributesOrder: [String: [String]] = [ "BuildAction": [ "parallelizeBuildables", "buildImplicitDependencies", ], "BuildActionEntry": [ "buildForTesting", "buildForRunning", "buildForProfiling", "buildForArchiving", "buildForAnalyzing", ], "BuildableReference": [ "BuildableIdentifier", "BlueprintIdentifier", "BuildableName", "BlueprintName", "ReferencedContainer", ], "TestAction": [ "buildConfiguration", "selectedDebuggerIdentifier", "selectedLauncherIdentifier", "language", "region", "codeCoverageEnabled", "shouldUseLaunchSchemeArgsEnv", ], "LaunchAction": [ "buildConfiguration", "selectedDebuggerIdentifier", "selectedLauncherIdentifier", "language", "region", "launchStyle", "useCustomWorkingDirectory", "ignoresPersistentStateOnLaunch", "debugDocumentVersioning", "debugServiceExtension", "enableGPUFrameCaptureMode", "enableGPUValidationMode", "allowLocationSimulation", ], "ProfileAction": [ "buildConfiguration", "shouldUseLaunchSchemeArgsEnv", "savedToolIdentifier", "useCustomWorkingDirectory", "ignoresPersistentStateOnLaunch", "debugDocumentVersioning", "enableTestabilityWhenProfilingTests", ], "ActionContent": [ "title", "scriptText", ], "EnvironmentVariable": [ "key", "value", "isEnabled", ], "TestableReference": [ "skipped", "parallelizable", "testExecutionOrdering", ], ] extension AEXMLElement { fileprivate var _xmlXcodeFormat: String { var xml = String() // open element xml += indent(withDepth: parentsCount - 1) xml += "<\(name)" func print(key: String, value: String) { xml += "\n" xml += indent(withDepth: parentsCount) xml += "\(key) = \"\(value.xmlEscaped)\"" } if !attributes.isEmpty { // insert known attributes in the specified order. var attributes = self.attributes for key in attributesOrder[self.name] ?? [] { if let value = attributes.removeValue(forKey: key) { print(key: key, value: value) } } // Print any remaining attributes. for (key, value) in attributes.sorted(by: { $0.key < $1.key }) { print(key: key, value: value) } } if value == nil, children.isEmpty { // close element xml += ">\n" } else { if !children.isEmpty { // add children xml += ">\n" for child in children { xml += "\(child._xmlXcodeFormat)\n" } } else { // insert string value and close element xml += ">\n" xml += indent(withDepth: parentsCount - 1) xml += ">\n\(string.xmlEscaped)" } } xml += indent(withDepth: parentsCount - 1) xml += "" return xml } private var parentsCount: Int { var count = 0 var element = self while let parent = element.parent { count += 1 element = parent } return count } private func indent(withDepth depth: Int) -> String { var count = depth var indent = String() while count > 0 { indent += " " count -= 1 } return indent } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/Bool+Extras.swift ================================================ import Foundation public extension Bool { /// Returns a XML string value that represents the boolean. var xmlString: String { return self ? "YES" : "NO" } /// Returns a 1 for true and 0 for false var int: UInt { return self ? 1 : 0 } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/Dictionary+Enumerate.swift ================================================ import Foundation extension Dictionary { func enumerateKeysAndObjects( options opts: NSEnumerationOptions = [], using block: (Any, Any, UnsafeMutablePointer) throws -> Void ) throws { var blockError: Error? // For performance it is very important to create a separate dictionary instance. // (self as NSDictionary).enumerateKeys... - works much slower let dictionary = NSDictionary(dictionary: self) dictionary.enumerateKeysAndObjects(options: opts) { key, obj, stops in do { try block(key, obj, stops) } catch { blockError = error stops.pointee = true } } if let error = blockError { throw error } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/Dictionary+Extras.swift ================================================ import Foundation /// Static initializer that creates a Dictionary from a .plist file. /// /// - Parameter path: the path of the .plist file. /// - Returns: initialized dictionary. public func loadPlist(path: String) -> [String: AnyObject]? { return NSDictionary(contentsOfFile: path) as? [String: AnyObject] } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/KeyedDecodingContainer+Additions.swift ================================================ import Foundation extension KeyedDecodingContainer { func decode(_ key: KeyedDecodingContainer.Key) throws -> T where T: Decodable { return try decode(T.self, forKey: key) } func decodeIfPresent(_ key: KeyedDecodingContainer.Key) throws -> T? where T: Decodable { return try decodeIfPresent(T.self, forKey: key) } func decodeIntIfPresent(_ key: KeyedDecodingContainer.Key) throws -> UInt? { guard let string: String = try decodeIfPresent(key) else { return nil } return UInt(string) } func decodeIntBool(_ key: KeyedDecodingContainer.Key) throws -> Bool { guard let int = try decodeIntIfPresent(key) else { return false } return int == 1 } func decodeIntBoolIfPresent(_ key: KeyedDecodingContainer.Key) throws -> Bool? { guard let int = try decodeIntIfPresent(key) else { return nil } return int == 1 } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/NSRecursiveLock+Sync.swift ================================================ import Foundation extension NSRecursiveLock { func whileLocked(closure: () -> (T)) -> T { lock() defer { unlock() } let value = closure() return value } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/OSLog+Extras.swift ================================================ import Foundation import os.signpost extension OSLog { @available(OSX 10.12, *) /// Returns an instance of OSLog with the default xcodeproj subsystem. /// /// - Parameter category: Category the OSLog should be initialized with. /// - Returns: Initialized OSLog. static func xcodeproj(category: String) -> OSLog { return OSLog(subsystem: "io.tuist.xcodeproj", category: category) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/Path+Extras.swift ================================================ import Foundation // swiftlint:disable all import PathKit // MARK: - Path extras. let systemGlob = Darwin.glob extension Path { /// Creates a directory /// /// - Throws: an errof if the directory cannot be created. func mkpath(withIntermediateDirectories: Bool) throws { try FileManager.default.createDirectory(atPath: string, withIntermediateDirectories: withIntermediateDirectories, attributes: nil) } /// Finds files and directories using the given glob pattern. /// /// - Parameter pattern: glob pattern. /// - Returns: found directories and files. func glob(_ pattern: String) -> [Path] { var gt = glob_t() let cPattern = strdup((self + pattern).string) defer { globfree(>) free(cPattern) } let flags = GLOB_TILDE | GLOB_BRACE | GLOB_MARK if systemGlob(cPattern, flags, nil, >) == 0 { let matchc = gt.gl_matchc return (0 ..< Int(matchc)).compactMap { index in if let path = String(validatingUTF8: gt.gl_pathv[index]!) { return Path(path) } return nil } } return [] } func relative(to path: Path) -> Path { return Path(normalize().string.replacingOccurrences(of: "\(path.normalize().string)/", with: "")) } } // swiftlint:enable all ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/String+Utils.swift ================================================ import Foundation #if os(Linux) import SwiftGlibc public func arc4random_uniform(_ max: UInt32) -> Int32 { return (SwiftGlibc.rand() % Int32(max - 1)) } #endif extension String { public var quoted: String { return "\"\(self)\"" } public var isQuoted: Bool { return hasPrefix("\"") && hasSuffix("\"") } public static func random(length: Int = 20) -> String { let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" var randomString: String = "" for _ in 0 ..< length { let randomValue = arc4random_uniform(UInt32(base.count)) randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])" } return randomString } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Extensions/String+md5.swift ================================================ // swiftlint:disable all // // String+MD5.swift // Kingfisher // // To date, adding CommonCrypto to a Swift framework is problematic. See: // http://stackoverflow.com/questions/25248598/importing-commoncrypto-in-a-swift-framework // We're using a subset and modified version of CryptoSwift as an alternative. // The following is an altered source version that only includes MD5. The original software can be found at: // https://github.com/krzyzanowskim/CryptoSwift // This is the original copyright notice: /* Copyright (C) 2014 Marcin Krzyżanowski This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required. - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. - This notice may not be removed or altered from any source or binary distribution. */ import Foundation extension String { var md5: String { if let data = data(using: .utf8, allowLossyConversion: true) { let message = data.withUnsafeBytes { bytes -> [UInt8] in Array(UnsafeBufferPointer(start: bytes, count: data.count)) } let MD5Calculator = MD5(message) let MD5Data = MD5Calculator.calculate() var MD5String = String() for c in MD5Data { MD5String += String(format: "%02x", c) } return MD5String } else { return self } } } /** array of bytes, little-endian representation */ func arrayOfBytes(_ value: T, length: Int? = nil) -> [UInt8] { let totalBytes = length ?? (MemoryLayout.size * 8) let valuePointer = UnsafeMutablePointer.allocate(capacity: 1) valuePointer.pointee = value let bytes = valuePointer.withMemoryRebound(to: UInt8.self, capacity: totalBytes) { (bytesPointer) -> [UInt8] in var bytes = [UInt8](repeating: 0, count: totalBytes) for j in 0 ..< min(MemoryLayout.size, totalBytes) { bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee } return bytes } #if swift(>=4.1) valuePointer.deinitialize(count: 1) valuePointer.deallocate() #else valuePointer.deinitialize() valuePointer.deallocate(capacity: 1) #endif return bytes } extension Int { /** Array of bytes with optional padding (little-endian) */ func bytes(_ totalBytes: Int = MemoryLayout.size) -> [UInt8] { return arrayOfBytes(self, length: totalBytes) } } extension NSMutableData { /** Convenient way to append bytes */ func appendBytes(_ arrayOfBytes: [UInt8]) { append(arrayOfBytes, length: arrayOfBytes.count) } } protocol HashProtocol { var message: [UInt8] { get } /** Common part for hash calculation. Prepare header data. */ func prepare(_ len: Int) -> [UInt8] } extension HashProtocol { func prepare(_ len: Int) -> [UInt8] { var tmpMessage = message // Step 1. Append Padding Bits tmpMessage.append(0x80) // append one bit (UInt8 with one bit) to message // append "0" bit until message length in bits ≡ 448 (mod 512) var msgLength = tmpMessage.count var counter = 0 while msgLength % len != (len - 8) { counter += 1 msgLength += 1 } tmpMessage += [UInt8](repeating: 0, count: counter) return tmpMessage } } func toUInt32Array(_ slice: ArraySlice) -> [UInt32] { var result = [UInt32]() result.reserveCapacity(16) for idx in stride(from: slice.startIndex, to: slice.endIndex, by: MemoryLayout.size) { let d0 = UInt32(slice[idx.advanced(by: 3)]) << 24 let d1 = UInt32(slice[idx.advanced(by: 2)]) << 16 let d2 = UInt32(slice[idx.advanced(by: 1)]) << 8 let d3 = UInt32(slice[idx]) let val: UInt32 = d0 | d1 | d2 | d3 result.append(val) } return result } struct BytesIterator: IteratorProtocol { let chunkSize: Int let data: [UInt8] init(chunkSize: Int, data: [UInt8]) { self.chunkSize = chunkSize self.data = data } var offset = 0 mutating func next() -> ArraySlice? { let end = min(chunkSize, data.count - offset) let result = data[offset ..< offset + end] offset += result.count return !result.isEmpty ? result : nil } } struct BytesSequence: Sequence { let chunkSize: Int let data: [UInt8] func makeIterator() -> BytesIterator { return BytesIterator(chunkSize: chunkSize, data: data) } } func rotateLeft(_ value: UInt32, bits: UInt32) -> UInt32 { return ((value << bits) & 0xFFFF_FFFF) | (value >> (32 - bits)) } class MD5: HashProtocol { static let size = 16 // 128 / 8 let message: [UInt8] init(_ message: [UInt8]) { self.message = message } /** specifies the per-round shift amounts */ private let shifts: [UInt32] = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, ] /** binary integer part of the sines of integers (Radians) */ private let sines: [UInt32] = [ 0xD76A_A478, 0xE8C7_B756, 0x2420_70DB, 0xC1BD_CEEE, 0xF57C_0FAF, 0x4787_C62A, 0xA830_4613, 0xFD46_9501, 0x6980_98D8, 0x8B44_F7AF, 0xFFFF_5BB1, 0x895C_D7BE, 0x6B90_1122, 0xFD98_7193, 0xA679_438E, 0x49B4_0821, 0xF61E_2562, 0xC040_B340, 0x265E_5A51, 0xE9B6_C7AA, 0xD62F_105D, 0x0244_1453, 0xD8A1_E681, 0xE7D3_FBC8, 0x21E1_CDE6, 0xC337_07D6, 0xF4D5_0D87, 0x455A_14ED, 0xA9E3_E905, 0xFCEF_A3F8, 0x676F_02D9, 0x8D2A_4C8A, 0xFFFA_3942, 0x8771_F681, 0x6D9D_6122, 0xFDE5_380C, 0xA4BE_EA44, 0x4BDE_CFA9, 0xF6BB_4B60, 0xBEBF_BC70, 0x289B_7EC6, 0xEAA1_27FA, 0xD4EF_3085, 0x4881D05, 0xD9D4_D039, 0xE6DB_99E5, 0x1FA2_7CF8, 0xC4AC_5665, 0xF429_2244, 0x432A_FF97, 0xAB94_23A7, 0xFC93_A039, 0x655B_59C3, 0x8F0C_CC92, 0xFFEF_F47D, 0x8584_5DD1, 0x6FA8_7E4F, 0xFE2C_E6E0, 0xA301_4314, 0x4E08_11A1, 0xF753_7E82, 0xBD3A_F235, 0x2AD7_D2BB, 0xEB86_D391, ] private let hashes: [UInt32] = [0x6745_2301, 0xEFCD_AB89, 0x98BA_DCFE, 0x1032_5476] func calculate() -> [UInt8] { var tmpMessage = prepare(64) tmpMessage.reserveCapacity(tmpMessage.count + 4) // hash values var hh = hashes // Step 2. Append Length a 64-bit representation of lengthInBits let lengthInBits = (message.count * 8) let lengthBytes = lengthInBits.bytes(64 / 8) tmpMessage += lengthBytes.reversed() // Process the message in successive 512-bit chunks: let chunkSizeBytes = 512 / 8 // 64 for chunk in BytesSequence(chunkSize: chunkSizeBytes, data: tmpMessage) { // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15 var M = toUInt32Array(chunk) assert(M.count == 16, "Invalid array") // Initialize hash value for this chunk: var A: UInt32 = hh[0] var B: UInt32 = hh[1] var C: UInt32 = hh[2] var D: UInt32 = hh[3] var dTemp: UInt32 = 0 // Main loop for j in 0 ..< sines.count { var g = 0 var F: UInt32 = 0 switch j { case 0 ... 15: F = (B & C) | ((~B) & D) g = j case 16 ... 31: F = (D & B) | (~D & C) g = (5 * j + 1) % 16 case 32 ... 47: F = B ^ C ^ D g = (3 * j + 5) % 16 case 48 ... 63: F = C ^ (B | (~D)) g = (7 * j) % 16 default: break } dTemp = D D = C C = B B = B &+ rotateLeft(A &+ F &+ sines[j] &+ M[g], bits: shifts[j]) A = dTemp } hh[0] = hh[0] &+ A hh[1] = hh[1] &+ B hh[2] = hh[2] &+ C hh[3] = hh[3] &+ D } var result = [UInt8]() result.reserveCapacity(hh.count / 4) hh.forEach { let itemLE = $0.littleEndian let r1 = UInt8(itemLE & 0xFF) let r2 = UInt8((itemLE >> 8) & 0xFF) let r3 = UInt8((itemLE >> 16) & 0xFF) let r4 = UInt8((itemLE >> 24) & 0xFF) result += [r1, r2, r3, r4] } return result } } // swiftlint:enable all ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/BuildPhase.swift ================================================ import Foundation /// Enum that encapsulates all kind of build phases available in Xcode. /// /// - sources: sources. /// - frameworks: frameworks. /// - resources: resources. /// - copyFiles: files. /// - runScript: scripts. /// - headers: headers. /// - carbonResources: build legacy Carbon resources. public enum BuildPhase: String { case sources = "Sources" case frameworks = "Frameworks" case resources = "Resources" case copyFiles = "CopyFiles" case runScript = "Run Script" case headers = "Headers" case carbonResources = "Rez" } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXBuildFile.swift ================================================ import Foundation /// This element indicates a file reference that is used in a PBXBuildPhase (either as an include or resource). public final class PBXBuildFile: PBXObject { // MARK: - Attributes /// Element file reference. var fileReference: PBXObjectReference? /// Returns the file the build file refers to. public var file: PBXFileElement? { get { return fileReference?.getObject() } set { fileReference = newValue?.reference } } /// Element settings public var settings: [String: Any]? /// The cached build phase this build file belongs to weak var buildPhase: PBXBuildPhase? // MARK: - Init /// Initializes the build file with its attributes. /// /// - Parameters: /// - file: file the build file refers to. /// - settings: build file settings. public init(file: PBXFileElement, settings: [String: Any]? = nil) { fileReference = file.reference self.settings = settings super.init() } // MARK: - Decodable enum CodingKeys: String, CodingKey { case fileRef case settings } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) if let fileRefString: String = try container.decodeIfPresent(.fileRef) { fileReference = objectReferenceRepository.getOrCreate(reference: fileRefString, objects: objects) } settings = try container.decodeIfPresent([String: Any].self, forKey: .settings) try super.init(from: decoder) } } // MARK: - Internal Helpers extension PBXBuildFile { /// Returns the name of the file the build file points to. /// /// - Returns: file name. /// - Throws: an error if the name cannot be obtained. func fileName() throws -> String? { guard let fileElement: PBXFileElement = fileReference?.getObject() else { return nil } return fileElement.fileName() } /// Returns the type of the build phase the build file belongs to. /// /// - Returns: build phase type. /// - Throws: an error if this method is called before the build file is added to any project. func getBuildPhase() throws -> PBXBuildPhase? { if let buildPhase = buildPhase { return buildPhase } let projectObjects = try objects() if let buildPhase = projectObjects.sourcesBuildPhases.values.first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } else if let buildPhase = projectObjects.frameworksBuildPhases .values.first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } else if let buildPhase = projectObjects .resourcesBuildPhases.values .first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } else if let buildPhase = projectObjects.copyFilesBuildPhases .values.first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } else if let buildPhase = projectObjects.headersBuildPhases .values.first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } else if let buildPhase = projectObjects.carbonResourcesBuildPhases .values.first(where: { $0.fileReferences.map { $0.value }.contains(reference.value) }) { return buildPhase } return nil } /// Returns the name of the build phase the build file belongs to. /// /// - Returns: build phase name. /// - Throws: an error if the name cannot be obtained. func buildPhaseName() throws -> String? { guard let buildPhase = try getBuildPhase() else { return nil } return buildPhase.name() } } // MARK: - PlistSerializable // Helper for serialize the BuildFile with associated BuildPhase final class PBXBuildPhaseFile: PlistSerializable, Equatable { var multiline: Bool { return false } let buildFile: PBXBuildFile let buildPhase: PBXBuildPhase init(buildFile: PBXBuildFile, buildPhase: PBXBuildPhase) { self.buildFile = buildFile self.buildPhase = buildPhase } func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXBuildFile.isa)) if let fileReference = buildFile.fileReference { let fileElement: PBXFileElement? = fileReference.getObject() dictionary["fileRef"] = .string(CommentedString(fileReference.value, comment: fileElement?.fileName())) } if let settings = buildFile.settings { dictionary["settings"] = settings.plist() } let comment = try buildPhase.name().flatMap({ "\(try buildFile.fileName() ?? "(null)") in \($0)" }) return (key: CommentedString(reference, comment: comment), value: .dictionary(dictionary)) } static func == (lhs: PBXBuildPhaseFile, rhs: PBXBuildPhaseFile) -> Bool { return lhs.buildFile == rhs.buildFile && lhs.buildPhase == rhs.buildPhase } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXBuildPhase.swift ================================================ import Foundation /// An absctract class for all the build phase objects public class PBXBuildPhase: PBXContainerItem { /// Default build action mask. public static let defaultBuildActionMask: UInt = 2_147_483_647 /// Element build action mask. public var buildActionMask: UInt /// References to build files. var fileReferences: [PBXObjectReference] /// Build files. public var files: [PBXBuildFile] { get { return fileReferences.objects() } set { newValue.forEach { $0.buildPhase = self } fileReferences = newValue.references() } } /// Paths to the input file lists. /// Note: Introduced in Xcode 10 public var inputFileListPaths: [String]? /// Paths to the output file lists. /// Note: Introduced in Xcode 10 public var outputFileListPaths: [String]? /// Element run only for deployment post processing value. public var runOnlyForDeploymentPostprocessing: Bool /// The build phase type of the build phase public var buildPhase: BuildPhase { fatalError("This property must be overriden") } /// Initializes the build phase. /// /// - Parameters: /// - files: Build files. /// - inputFileListPaths: Input file lists paths. /// - outputFileListPaths: Input file list paths. /// - buildActionMask: Build action mask. /// - runOnlyForDeploymentPostprocessing: When true, it runs the build phase only for deployment post processing. public init(files: [PBXBuildFile] = [], inputFileListPaths: [String]? = nil, outputFileListPaths: [String]? = nil, buildActionMask: UInt = defaultBuildActionMask, runOnlyForDeploymentPostprocessing: Bool = false) { fileReferences = files.references() self.inputFileListPaths = inputFileListPaths self.outputFileListPaths = outputFileListPaths self.buildActionMask = buildActionMask self.runOnlyForDeploymentPostprocessing = runOnlyForDeploymentPostprocessing super.init() files.forEach { $0.buildPhase = self } } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case buildActionMask case files case runOnlyForDeploymentPostprocessing case inputFileListPaths case outputFileListPaths } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) buildActionMask = try container.decodeIntIfPresent(.buildActionMask) ?? PBXBuildPhase.defaultBuildActionMask let fileReferences: [String] = try container.decodeIfPresent(.files) ?? [] self.fileReferences = fileReferences.map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) inputFileListPaths = try container.decodeIfPresent(.inputFileListPaths) outputFileListPaths = try container.decodeIfPresent(.outputFileListPaths) runOnlyForDeploymentPostprocessing = try container.decodeIntBool(.runOnlyForDeploymentPostprocessing) try super.init(from: decoder) } override func plistValues(proj: PBXProj, reference: String) throws -> [CommentedString: PlistValue] { var dictionary = try super.plistValues(proj: proj, reference: reference) dictionary["buildActionMask"] = .string(CommentedString("\(buildActionMask)")) let files: PlistValue = .array(fileReferences.map { fileReference in let buildFile: PBXBuildFile? = fileReference.getObject() let name = buildFile.flatMap { try? $0.fileName() } ?? nil let fileName: String = name ?? "(null)" let type = self.name() let comment = (type.flatMap { "\(fileName) in \($0)" }) ?? name return .string(CommentedString(fileReference.value, comment: comment)) }) dictionary["files"] = files if let inputFileListPaths = inputFileListPaths { dictionary["inputFileListPaths"] = .array(inputFileListPaths.map({ .string(CommentedString($0)) })) } if let outputFileListPaths = outputFileListPaths { dictionary["outputFileListPaths"] = .array(outputFileListPaths.map({ .string(CommentedString($0)) })) } dictionary["runOnlyForDeploymentPostprocessing"] = .string(CommentedString("\(runOnlyForDeploymentPostprocessing.int)")) return dictionary } } // MARK: - Helpers public extension PBXBuildPhase { /// Adds a file to a build phase, creating a proxy build file that points to the given file element. /// /// - Parameter file: file element to be added to the build phase. /// - Returns: proxy build file. /// - Throws: an error if the file cannot be added. func add(file: PBXFileElement) throws -> PBXBuildFile { if let existing = files.first(where: { $0.fileReference == file.reference }) { return existing } let projectObjects = try objects() let buildFile = PBXBuildFile(file: file) projectObjects.add(object: buildFile) files.append(buildFile) return buildFile } } // MARK: - Utils extension PBXBuildPhase { /// Returns the build phase type. /// /// - Returns: build phase type. public func type() -> BuildPhase? { return buildPhase } /// Build phase name. /// /// - Returns: build phase name. func name() -> String? { if self is PBXSourcesBuildPhase { return "Sources" } else if self is PBXFrameworksBuildPhase { return "Frameworks" } else if self is PBXResourcesBuildPhase { return "Resources" } else if let phase = self as? PBXCopyFilesBuildPhase { return phase.name ?? "CopyFiles" } else if let phase = self as? PBXShellScriptBuildPhase { return phase.name ?? "ShellScript" } else if self is PBXHeadersBuildPhase { return "Headers" } else if self is PBXRezBuildPhase { return "Rez" } return nil } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXBuildRule.swift ================================================ import Foundation /// A PBXBuildRule is used to specify a method for transforming an input file in to an output file(s). public final class PBXBuildRule: PBXObject { // MARK: - Attributes /// Element compiler spec. public var compilerSpec: String /// Element file patterns. public var filePatterns: String? /// Element file type. public var fileType: String /// Element is editable. public var isEditable: Bool /// Element name. public var name: String? /// Element output files. public var outputFiles: [String] /// Element output files compiler flags. public var outputFilesCompilerFlags: [String]? /// Element script. public var script: String? // MARK: - Init public init(compilerSpec: String, fileType: String, isEditable: Bool = true, filePatterns: String? = nil, name: String? = nil, outputFiles: [String] = [], outputFilesCompilerFlags: [String]? = nil, script: String? = nil) { self.compilerSpec = compilerSpec self.filePatterns = filePatterns self.fileType = fileType self.isEditable = isEditable self.name = name self.outputFiles = outputFiles self.outputFilesCompilerFlags = outputFilesCompilerFlags self.script = script super.init() } // MARK: - Decodable enum CodingKeys: String, CodingKey { case compilerSpec case filePatterns case fileType case isEditable case name case outputFiles case outputFilesCompilerFlags case script } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) compilerSpec = try container.decodeIfPresent(.compilerSpec) ?? "" filePatterns = try container.decodeIfPresent(.filePatterns) fileType = try container.decodeIfPresent(.fileType) ?? "" isEditable = try container.decodeIntBool(.isEditable) name = try container.decodeIfPresent(.name) outputFiles = try container.decodeIfPresent(.outputFiles) ?? [] outputFilesCompilerFlags = try container.decodeIfPresent(.outputFilesCompilerFlags) script = try container.decodeIfPresent(.script) try super.init(from: decoder) } } // MARK: - PBXBuildRule Extension (PlistSerializable) extension PBXBuildRule: PlistSerializable { var multiline: Bool { return true } func plistKeyAndValue(proj _: PBXProj, reference: String) -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXBuildRule.isa)) dictionary["compilerSpec"] = .string(CommentedString(compilerSpec)) if let filePatterns = filePatterns { dictionary["filePatterns"] = .string(CommentedString(filePatterns)) } dictionary["fileType"] = .string(CommentedString(fileType)) dictionary["isEditable"] = .string(CommentedString("\(isEditable.int)")) if let name = name { dictionary["name"] = .string(CommentedString(name)) } dictionary["outputFiles"] = .array(outputFiles.map { PlistValue.string(CommentedString($0)) }) if let outputFilesCompilerFlags = outputFilesCompilerFlags { dictionary["outputFilesCompilerFlags"] = .array(outputFilesCompilerFlags.map { PlistValue.string(CommentedString($0)) }) } if let script = script { dictionary["script"] = .string(CommentedString(script)) } return (key: CommentedString(reference, comment: PBXBuildRule.isa), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXCopyFilesBuildPhase.swift ================================================ import Foundation /// This is the element for the copy file build phase. public final class PBXCopyFilesBuildPhase: PBXBuildPhase { public enum SubFolder: UInt, Decodable { case absolutePath = 0 case productsDirectory = 16 case wrapper = 1 case executables = 6 case resources = 7 case javaResources = 15 case frameworks = 10 case sharedFrameworks = 11 case sharedSupport = 12 case plugins = 13 case other } // MARK: - Attributes /// Element destination path public var dstPath: String? /// Element destination subfolder spec public var dstSubfolderSpec: SubFolder? /// Copy files build phase name public var name: String? public override var buildPhase: BuildPhase { return .copyFiles } // MARK: - Init /// Initializes the copy files build phase with its attributes. /// /// - Parameters: /// - dstPath: Destination path. /// - dstSubfolderSpec: Destination subfolder spec. /// - buildActionMask: Build action mask. /// - files: Build files to copy. /// - runOnlyForDeploymentPostprocessing: Run only for deployment post processing. public init(dstPath: String? = nil, dstSubfolderSpec: SubFolder? = nil, name: String? = nil, buildActionMask: UInt = defaultBuildActionMask, files: [PBXBuildFile] = [], runOnlyForDeploymentPostprocessing: Bool = false) { self.dstPath = dstPath self.dstSubfolderSpec = dstSubfolderSpec self.name = name super.init(files: files, buildActionMask: buildActionMask, runOnlyForDeploymentPostprocessing: runOnlyForDeploymentPostprocessing) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case dstPath case dstSubfolderSpec case name } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) dstPath = try container.decodeIfPresent(.dstPath) dstSubfolderSpec = try container.decodeIntIfPresent(.dstSubfolderSpec).flatMap(SubFolder.init) name = try container.decodeIfPresent(.name) try super.init(from: decoder) } } // MARK: - PBXCopyFilesBuildPhase Extension (PlistSerializable) extension PBXCopyFilesBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXCopyFilesBuildPhase.isa)) if let dstPath = dstPath { dictionary["dstPath"] = .string(CommentedString(dstPath)) } if let name = name { dictionary["name"] = .string(CommentedString(name)) } if let dstSubfolderSpec = dstSubfolderSpec { dictionary["dstSubfolderSpec"] = .string(CommentedString("\(dstSubfolderSpec.rawValue)")) } return (key: CommentedString(reference, comment: name ?? "CopyFiles"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXFrameworksBuildPhase.swift ================================================ import Foundation /// This is the element for the framework link build phase. public final class PBXFrameworksBuildPhase: PBXBuildPhase { public override var buildPhase: BuildPhase { return .frameworks } } // MARK: - PBXFrameworksBuildPhase Extension (PlistSerializable) extension PBXFrameworksBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXFrameworksBuildPhase.isa)) return (key: CommentedString(reference, comment: "Frameworks"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXHeadersBuildPhase.swift ================================================ import Foundation import PathKit /// This is the element for the framework headers build phase. public final class PBXHeadersBuildPhase: PBXBuildPhase { public override var buildPhase: BuildPhase { return .headers } } // MARK: - PBXHeadersBuildPhase Extension (PlistSerializable) extension PBXHeadersBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXHeadersBuildPhase.isa)) return (key: CommentedString(reference, comment: "Headers"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXResourcesBuildPhase.swift ================================================ import Foundation /// This is the element for the resources copy build phase. public final class PBXResourcesBuildPhase: PBXBuildPhase { public override var buildPhase: BuildPhase { return .resources } } // MARK: - PBXResourcesBuildPhase Extension (PlistSerializable) extension PBXResourcesBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXResourcesBuildPhase.isa)) return (key: CommentedString(reference, comment: "Resources"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXRezBuildPhase.swift ================================================ import Foundation /// This is the element for the Build Carbon Resources build phase. /// These are legacy .r files from the Classic Mac OS era. public final class PBXRezBuildPhase: PBXBuildPhase { public override var buildPhase: BuildPhase { return .carbonResources } } // MARK: - PBXRezBuildPhase Extension (PlistSerializable) extension PBXRezBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXRezBuildPhase.isa)) return (key: CommentedString(reference, comment: "Rez"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXShellScriptBuildPhase.swift ================================================ import Foundation /// This is the element for the shell script build phase. public final class PBXShellScriptBuildPhase: PBXBuildPhase { // MARK: - Attributes /// Build phase name. public var name: String? /// Input paths public var inputPaths: [String] /// Output paths public var outputPaths: [String] /// Path to the shell. public var shellPath: String? /// Shell script. public var shellScript: String? /// Show environment variables in the logs. public var showEnvVarsInLog: Bool public override var buildPhase: BuildPhase { return .runScript } // MARK: - Init /// Initializes the shell script build phase with its attributes. /// /// - Parameters: /// - files: build files. /// - inputPaths: input paths. /// - outputPaths: output paths. /// - inputFileListPaths: input file list paths. /// - outputFileListPaths: output file list paths. /// - shellPath: shell path. /// - shellScript: shell script. /// - buildActionMask: build action mask. public init(files: [PBXBuildFile] = [], name: String? = nil, inputPaths: [String] = [], outputPaths: [String] = [], inputFileListPaths: [String]? = nil, outputFileListPaths: [String]? = nil, shellPath: String = "/bin/sh", shellScript: String? = nil, buildActionMask: UInt = defaultBuildActionMask, runOnlyForDeploymentPostprocessing: Bool = false, showEnvVarsInLog: Bool = true) { self.name = name self.inputPaths = inputPaths self.outputPaths = outputPaths self.shellPath = shellPath self.shellScript = shellScript self.showEnvVarsInLog = showEnvVarsInLog super.init(files: files, inputFileListPaths: inputFileListPaths, outputFileListPaths: outputFileListPaths, buildActionMask: buildActionMask, runOnlyForDeploymentPostprocessing: runOnlyForDeploymentPostprocessing) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case name case inputPaths case outputPaths case shellPath case shellScript case showEnvVarsInLog } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) name = try container.decodeIfPresent(.name) inputPaths = (try container.decodeIfPresent(.inputPaths)) ?? [] outputPaths = (try container.decodeIfPresent(.outputPaths)) ?? [] shellPath = try container.decodeIfPresent(.shellPath) shellScript = try container.decodeIfPresent(.shellScript) showEnvVarsInLog = try container.decodeIntBoolIfPresent(.showEnvVarsInLog) ?? true try super.init(from: decoder) } } // MARK: - PBXShellScriptBuildPhase Extension (PlistSerializable) extension PBXShellScriptBuildPhase: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXShellScriptBuildPhase.isa)) if let shellPath = shellPath { dictionary["shellPath"] = .string(CommentedString(shellPath)) } dictionary["inputPaths"] = .array(inputPaths.map({ .string(CommentedString($0)) })) if let name = name { dictionary["name"] = .string(CommentedString(name)) } dictionary["outputPaths"] = .array(outputPaths.map({ .string(CommentedString($0)) })) if let shellScript = shellScript { dictionary["shellScript"] = .string(CommentedString(shellScript)) } if !showEnvVarsInLog { // Xcode only writes this key if it's set to false; default is true and is omitted dictionary["showEnvVarsInLog"] = .string(CommentedString("\(showEnvVarsInLog.int)")) } return (key: CommentedString(reference, comment: name ?? "ShellScript"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/BuildPhase/PBXSourcesBuildPhase.swift ================================================ import Foundation /// This is the element for the sources compilation build phase. public final class PBXSourcesBuildPhase: PBXBuildPhase { public override var buildPhase: BuildPhase { return .sources } } extension PBXSourcesBuildPhase: PlistSerializable { // MARK: - PlistSerializable func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(PBXSourcesBuildPhase.isa)) return (key: CommentedString(reference, comment: "Sources"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Configuration/BuildSettings.swift ================================================ import Foundation /// Build settings. public typealias BuildSettings = [String: Any] ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Configuration/XCBuildConfiguration.swift ================================================ import Foundation /// This is the element for listing build configurations. public final class XCBuildConfiguration: PBXObject { // MARK: - Attributes /// Base xcconfig file reference. var baseConfigurationReference: PBXObjectReference? /// Base xcconfig file reference. public var baseConfiguration: PBXFileReference? { get { return baseConfigurationReference?.getObject() } set { if let newValue = newValue { baseConfigurationReference = newValue.reference } } } /// A map of build settings. public var buildSettings: BuildSettings /// The configuration name. public var name: String // MARK: - Init /// Initializes a build configuration. /// /// - Parameters: /// - name: build configuration name. /// - baseConfiguration: base configuration. /// - buildSettings: dictionary that contains the build settings for this configuration. public init(name: String, baseConfiguration: PBXFileReference? = nil, buildSettings: BuildSettings = [:]) { baseConfigurationReference = baseConfiguration?.reference self.buildSettings = buildSettings self.name = name super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case baseConfigurationReference case buildSettings case name } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) if let baseConfigurationReference: String = try container.decodeIfPresent(.baseConfigurationReference) { self.baseConfigurationReference = objectReferenceRepository.getOrCreate(reference: baseConfigurationReference, objects: objects) } else { baseConfigurationReference = nil } buildSettings = try container.decode([String: Any].self, forKey: .buildSettings) name = try container.decode(.name) try super.init(from: decoder) } } // MARK: - PlistSerializable extension XCBuildConfiguration: PlistSerializable { func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(XCBuildConfiguration.isa)) dictionary["name"] = .string(CommentedString(name)) dictionary["buildSettings"] = buildSettings.plist() if let baseConfigurationReference = baseConfigurationReference { let fileElement: PBXFileElement? = baseConfigurationReference.getObject() dictionary["baseConfigurationReference"] = .string(CommentedString(baseConfigurationReference.value, comment: fileElement?.fileName())) } return (key: CommentedString(reference, comment: name), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Configuration/XCConfigurationList.swift ================================================ import Foundation /// This is the element for listing build configurations. public final class XCConfigurationList: PBXObject { // MARK: - Attributes /// Element build configurations. var buildConfigurationReferences: [PBXObjectReference] /// Build configurations public var buildConfigurations: [XCBuildConfiguration] { set { buildConfigurationReferences = newValue.references() } get { return buildConfigurationReferences.objects() } } /// Element default configuration is visible. public var defaultConfigurationIsVisible: Bool /// Element default configuration name public var defaultConfigurationName: String? // MARK: - Init /// Initializes the element with its properties. /// /// - Parameters: /// - bbuildConfigurations: build configurations. /// - defaultConfigurationName: element default configuration name. /// - defaultConfigurationIsVisible: default configuration is visible. public init(buildConfigurations: [XCBuildConfiguration] = [], defaultConfigurationName: String? = nil, defaultConfigurationIsVisible: Bool = false) { buildConfigurationReferences = buildConfigurations.references() self.defaultConfigurationName = defaultConfigurationName self.defaultConfigurationIsVisible = defaultConfigurationIsVisible super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case buildConfigurations case defaultConfigurationName case defaultConfigurationIsVisible } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) let buildConfigurationReferencesStrings: [String] = try container.decode(.buildConfigurations) buildConfigurationReferences = buildConfigurationReferencesStrings .map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) defaultConfigurationIsVisible = try container.decodeIntBool(.defaultConfigurationIsVisible) defaultConfigurationName = try container.decodeIfPresent(.defaultConfigurationName) try super.init(from: decoder) } } // MARK: - Helpers extension XCConfigurationList { /// Returns the build configuration with the given name (if it exists) /// /// - Parameter name: configuration name. /// - Returns: build configuration if it exists. public func configuration(name: String) -> XCBuildConfiguration? { return buildConfigurations.first(where: { $0.name == name }) } /// Adds the default configurations, debug and release /// /// - Returns: the created configurations. public func addDefaultConfigurations() throws -> [XCBuildConfiguration] { var configurations: [XCBuildConfiguration] = [] let debug = XCBuildConfiguration(name: "Debug") reference.objects?.add(object: debug) configurations.append(debug) let release = XCBuildConfiguration(name: "Release") reference.objects?.add(object: release) configurations.append(release) buildConfigurations.append(contentsOf: configurations) return configurations } /// Returns the object with the given configuration list (project or target) /// /// - Parameter reference: configuration list reference. /// - Returns: target or project with the given configuration list. public func objectWithConfigurationList() throws -> PBXObject? { let projectObjects = try objects() return projectObjects.projects.first(where: { $0.value.buildConfigurationListReference == reference })?.value ?? projectObjects.nativeTargets.first(where: { $0.value.buildConfigurationListReference == reference })?.value ?? projectObjects.aggregateTargets.first(where: { $0.value.buildConfigurationListReference == reference })?.value ?? projectObjects.legacyTargets.first(where: { $0.value.buildConfigurationListReference == reference })?.value } } // MARK: - PlistSerializable extension XCConfigurationList: PlistSerializable { func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(XCConfigurationList.isa)) dictionary["buildConfigurations"] = .array(buildConfigurationReferences .map { configReference in let config: XCBuildConfiguration? = configReference.getObject() return .string(CommentedString(configReference.value, comment: config?.name)) }) dictionary["defaultConfigurationIsVisible"] = .string(CommentedString("\(defaultConfigurationIsVisible.int)")) if let defaultConfigurationName = defaultConfigurationName { dictionary["defaultConfigurationName"] = .string(CommentedString(defaultConfigurationName)) } return (key: CommentedString(reference, comment: try plistComment()), value: .dictionary(dictionary)) } private func plistComment() throws -> String? { let object = try objectWithConfigurationList() if let project = object as? PBXProject { return "Build configuration list for PBXProject \"\(project.name)\"" } else if let target = object as? PBXTarget { return "Build configuration list for \(type(of: target).isa) \"\(target.name)\"" } return nil } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXContainerItem.swift ================================================ import Foundation /// Class representing an element that may contain other elements. public class PBXContainerItem: PBXObject { /// User comments for the object. var comments: String? // MARK: - Init init(comments: String? = nil) { self.comments = comments super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case comments } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) comments = try container.decodeIfPresent(.comments) try super.init(from: decoder) } func plistValues(proj _: PBXProj, reference _: String) throws -> [CommentedString: PlistValue] { var dictionary = [CommentedString: PlistValue]() if let comments = comments { dictionary["comments"] = .string(CommentedString(comments)) } return dictionary } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXContainerItemProxy.swift ================================================ import Foundation /// This is the element to decorate a target item. public final class PBXContainerItemProxy: PBXObject { public enum ProxyType: UInt, Decodable { case nativeTarget = 1 case reference = 2 case other } /// The object is a reference to a PBXProject element. var containerPortalReference: PBXObjectReference /// Returns the project that contains the remote object. public var containerPortal: PBXProject! { get { return containerPortalReference.getObject() } set { containerPortalReference = newValue.reference } } /// Element proxy type. public var proxyType: ProxyType? /// Element remote global ID reference. var remoteGlobalIDReference: PBXObjectReference? /// Remote global object public var remoteGlobalID: PBXObject? { get { return remoteGlobalIDReference?.getObject() } set { remoteGlobalIDReference = newValue?.reference } } /// Element remote info. public var remoteInfo: String? /// Initializes the container item proxy with its attributes. /// /// - Parameters: /// - containerPortal: container portal. /// - remoteGlobalID: remote global ID. /// - proxyType: proxy type. /// - remoteInfo: remote info. public init(containerPortal: PBXObject, remoteGlobalID: PBXObject? = nil, proxyType: ProxyType? = nil, remoteInfo: String? = nil) { containerPortalReference = containerPortal.reference remoteGlobalIDReference = remoteGlobalID?.reference self.remoteInfo = remoteInfo self.proxyType = proxyType super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case containerPortal case proxyType case remoteGlobalIDString case remoteInfo } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let containerPortalString: String = try container.decode(.containerPortal) containerPortalReference = objectReferenceRepository.getOrCreate(reference: containerPortalString, objects: objects) proxyType = try container.decodeIntIfPresent(.proxyType).flatMap(ProxyType.init) if let remoteGlobalIDString: String = try container.decodeIfPresent(.remoteGlobalIDString) { remoteGlobalIDReference = objectReferenceRepository.getOrCreate(reference: remoteGlobalIDString, objects: objects) } else { remoteGlobalIDReference = nil } remoteInfo = try container.decodeIfPresent(.remoteInfo) try super.init(from: decoder) } } // MARK: - PBXContainerItemProxy Extension (PlistSerializable) extension PBXContainerItemProxy: PlistSerializable { func plistKeyAndValue(proj _: PBXProj, reference: String) -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXContainerItemProxy.isa)) dictionary["containerPortal"] = .string(CommentedString(containerPortalReference.value, comment: "Project object")) if let proxyType = proxyType { dictionary["proxyType"] = .string(CommentedString("\(proxyType.rawValue)")) } if let remoteGlobalIDReference = remoteGlobalIDReference { dictionary["remoteGlobalIDString"] = .string(CommentedString(remoteGlobalIDReference.value)) } if let remoteInfo = remoteInfo { dictionary["remoteInfo"] = .string(CommentedString(remoteInfo)) } return (key: CommentedString(reference, comment: "PBXContainerItemProxy"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXFileElement.swift ================================================ import Foundation import PathKit /// This element is an abstract parent for file and group elements. public class PBXFileElement: PBXContainerItem, PlistSerializable { // MARK: - Attributes /// Element source tree. public var sourceTree: PBXSourceTree? /// Element path. public var path: String? /// Element name. public var name: String? /// Element include in index. public var includeInIndex: Bool? /// Element uses tabs. public var usesTabs: Bool? /// Element indent width. public var indentWidth: UInt? /// Element tab width. public var tabWidth: UInt? /// Element wraps lines. public var wrapsLines: Bool? // MARK: - Init /// Initializes the file element with its properties. /// /// - Parameters: /// - sourceTree: file source tree. /// - path: object relative path from `sourceTree`, if different than `name`. /// - name: object name. /// - includeInIndex: should the IDE index the object? /// - usesTabs: object uses tabs. /// - indentWidth: the number of positions to indent blocks of code /// - tabWidth: the visual width of tab characters /// - wrapsLines: should the IDE wrap lines when editing the object? public init(sourceTree: PBXSourceTree? = nil, path: String? = nil, name: String? = nil, includeInIndex: Bool? = nil, usesTabs: Bool? = nil, indentWidth: UInt? = nil, tabWidth: UInt? = nil, wrapsLines: Bool? = nil) { self.sourceTree = sourceTree self.path = path self.name = name self.includeInIndex = includeInIndex self.usesTabs = usesTabs self.indentWidth = indentWidth self.tabWidth = tabWidth self.wrapsLines = wrapsLines super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case sourceTree case name case path case includeInIndex case usesTabs case indentWidth case tabWidth case wrapsLines } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) sourceTree = try container.decodeIfPresent(String.self, forKey: .sourceTree).map { PBXSourceTree(value: $0) } name = try container.decodeIfPresent(.name) path = try container.decodeIfPresent(.path) includeInIndex = try container.decodeIntBoolIfPresent(.includeInIndex) usesTabs = try container.decodeIntBoolIfPresent(.usesTabs) indentWidth = try container.decodeIntIfPresent(.indentWidth) tabWidth = try container.decodeIntIfPresent(.tabWidth) wrapsLines = try container.decodeIntBoolIfPresent(.wrapsLines) try super.init(from: decoder) } // MARK: - PlistSerializable var multiline: Bool { return true } func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXFileElement.isa)) if let name = name { dictionary["name"] = .string(CommentedString(name)) } if let path = path { dictionary["path"] = .string(CommentedString(path)) } if let sourceTree = sourceTree { dictionary["sourceTree"] = sourceTree.plist() } if let includeInIndex = includeInIndex { dictionary["includeInIndex"] = .string(CommentedString("\(includeInIndex.int)")) } if let usesTabs = usesTabs { dictionary["usesTabs"] = .string(CommentedString("\(usesTabs.int)")) } if let indentWidth = indentWidth { dictionary["indentWidth"] = .string(CommentedString("\(indentWidth)")) } if let tabWidth = tabWidth { dictionary["tabWidth"] = .string(CommentedString("\(tabWidth)")) } if let wrapsLines = wrapsLines { dictionary["wrapsLines"] = .string(CommentedString("\(wrapsLines.int)")) } return (key: CommentedString(reference, comment: name), value: .dictionary(dictionary)) } /// Returns the name that should be used for comments. /// /// - Returns: file name. func fileName() -> String? { return name ?? path } } // MARK: - Helpers public extension PBXFileElement { /// Returns a file absolute path. /// /// - Parameter sourceRoot: project source root. /// - Returns: file element absolute path. /// - Throws: an error if the absolute path cannot be obtained. func fullPath(sourceRoot: Path) throws -> Path? { let projectObjects = try objects() switch sourceTree { case .absolute?: return path.flatMap { Path($0) } case .sourceRoot?: return path.flatMap { sourceRoot + $0 } case .group?: guard let group = projectObjects.groups.first(where: { $0.value.childrenReferences.contains(reference) }) else { return sourceRoot } guard let groupPath = try group.value.fullPath(sourceRoot: sourceRoot) else { return nil } guard let filePath = self is PBXVariantGroup ? try baseVariantGroupPath() : path else { return groupPath } return groupPath + filePath default: return nil } } /// Returns the path to the variant group base file. /// /// - Returns: path to the variant group base file. /// - Throws: an error if the path cannot be obtained. private func baseVariantGroupPath() throws -> String? { guard let variantGroup: PBXVariantGroup = self.reference.getObject() else { return nil } guard let baseReference = try variantGroup .childrenReferences .compactMap({ try $0.getThrowingObject() as PBXFileElement }) .first(where: { $0.name == "Base" }) else { return nil } return baseReference.path } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXFileReference.swift ================================================ import Foundation import PathKit /// A PBXFileReference is used to track every external file referenced by /// the project: source files, resource files, libraries, generated application files, and so on. public final class PBXFileReference: PBXFileElement { // MARK: - Attributes /// Element file encoding. public var fileEncoding: UInt? /// Element explicit file type. public var explicitFileType: String? /// Element last known file type. public var lastKnownFileType: String? /// Element line ending. public var lineEnding: UInt? /// Element language specification identifier public var languageSpecificationIdentifier: String? /// Element xc language specification identifier public var xcLanguageSpecificationIdentifier: String? /// Element plist structure definition identifier public var plistStructureDefinitionIdentifier: String? // MARK: - Init /// Initializes the file reference with its properties. /// /// - Parameters: /// - sourceTree: file source tree. /// - name: file name. /// - fileEncoding: text encoding of file content. /// - explicitFileType: user-specified file type. /// - lastKnownFileType: derived file type. /// - path: file relative path from `sourceTree`, if different than `name`. /// - includeInIndex: should the IDE index the file? /// - wrapsLines: should the IDE wrap lines when editing the file? /// - usesTabs: file uses tabs. /// - indentWidth: the number of positions to indent blocks of code /// - tabWidth: the visual width of tab characters /// - lineEnding: the line ending type for the file. /// - languageSpecificationIdentifier: legacy programming language identifier. /// - xcLanguageSpecificationIdentifier: the programming language identifier. /// - plistStructureDefinitionIdentifier: the plist organizational family identifier. public init(sourceTree: PBXSourceTree? = nil, name: String? = nil, fileEncoding: UInt? = nil, explicitFileType: String? = nil, lastKnownFileType: String? = nil, path: String? = nil, includeInIndex: Bool? = nil, wrapsLines: Bool? = nil, usesTabs: Bool? = nil, indentWidth: UInt? = nil, tabWidth: UInt? = nil, lineEnding: UInt? = nil, languageSpecificationIdentifier: String? = nil, xcLanguageSpecificationIdentifier: String? = nil, plistStructureDefinitionIdentifier: String? = nil) { self.fileEncoding = fileEncoding self.explicitFileType = explicitFileType self.lastKnownFileType = lastKnownFileType self.lineEnding = lineEnding self.languageSpecificationIdentifier = languageSpecificationIdentifier self.xcLanguageSpecificationIdentifier = xcLanguageSpecificationIdentifier self.plistStructureDefinitionIdentifier = plistStructureDefinitionIdentifier super.init(sourceTree: sourceTree, path: path, name: name, includeInIndex: includeInIndex, usesTabs: usesTabs, indentWidth: indentWidth, tabWidth: tabWidth, wrapsLines: wrapsLines) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case fileEncoding case explicitFileType case lastKnownFileType case lineEnding case languageSpecificationIdentifier case xcLanguageSpecificationIdentifier case plistStructureDefinitionIdentifier } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) fileEncoding = try container.decodeIntIfPresent(.fileEncoding) explicitFileType = try container.decodeIfPresent(.explicitFileType) lastKnownFileType = try container.decodeIfPresent(.lastKnownFileType) lineEnding = try container.decodeIntIfPresent(.lineEnding) languageSpecificationIdentifier = try container.decodeIfPresent(.languageSpecificationIdentifier) xcLanguageSpecificationIdentifier = try container.decodeIfPresent(.xcLanguageSpecificationIdentifier) plistStructureDefinitionIdentifier = try container.decodeIfPresent(.plistStructureDefinitionIdentifier) try super.init(from: decoder) } // MARK: - PlistSerializable override var multiline: Bool { return false } override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try super.plistKeyAndValue(proj: proj, reference: reference).value.dictionary ?? [:] dictionary["isa"] = .string(CommentedString(PBXFileReference.isa)) if let lastKnownFileType = lastKnownFileType { dictionary["lastKnownFileType"] = .string(CommentedString(lastKnownFileType)) } if let fileEncoding = fileEncoding { dictionary["fileEncoding"] = .string(CommentedString("\(fileEncoding)")) } if let explicitFileType = self.explicitFileType { dictionary["explicitFileType"] = .string(CommentedString(explicitFileType)) } if let lineEnding = lineEnding { dictionary["lineEnding"] = .string(CommentedString("\(lineEnding)")) } if let languageSpecificationIdentifier = languageSpecificationIdentifier { dictionary["languageSpecificationIdentifier"] = .string(CommentedString(languageSpecificationIdentifier)) } if let xcLanguageSpecificationIdentifier = xcLanguageSpecificationIdentifier { dictionary["xcLanguageSpecificationIdentifier"] = .string(CommentedString(xcLanguageSpecificationIdentifier)) } if let plistStructureDefinitionIdentifier = plistStructureDefinitionIdentifier { dictionary["plistStructureDefinitionIdentifier"] = .string(CommentedString(plistStructureDefinitionIdentifier)) } return (key: CommentedString(reference, comment: name ?? path), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXGroup.swift ================================================ import Foundation import PathKit public class PBXGroup: PBXFileElement { // MARK: - Attributes /// Grou children references. var childrenReferences: [PBXObjectReference] /// Group children. public var children: [PBXFileElement] { set { childrenReferences = newValue.references() } get { return childrenReferences.objects() } } // MARK: - Init /// Initializes the group with its attributes. /// /// - Parameters: /// - children: group children. /// - sourceTree: group source tree. /// - name: group name. /// - path: group relative path from `sourceTree`, if different than `name`. /// - includeInIndex: should the IDE index the files in the group? /// - wrapsLines: should the IDE wrap lines for files in the group? /// - usesTabs: group uses tabs. /// - indentWidth: the number of positions to indent blocks of code /// - tabWidth: the visual width of tab characters public init(children: [PBXFileElement] = [], sourceTree: PBXSourceTree? = nil, name: String? = nil, path: String? = nil, includeInIndex: Bool? = nil, wrapsLines: Bool? = nil, usesTabs: Bool? = nil, indentWidth: UInt? = nil, tabWidth: UInt? = nil) { childrenReferences = children.references() super.init(sourceTree: sourceTree, path: path, name: name, includeInIndex: includeInIndex, usesTabs: usesTabs, indentWidth: indentWidth, tabWidth: tabWidth, wrapsLines: wrapsLines) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case children } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) let childrenReferences: [String] = (try container.decodeIfPresent(.children)) ?? [] self.childrenReferences = childrenReferences.map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) try super.init(from: decoder) } // MARK: - PlistSerializable override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try super.plistKeyAndValue(proj: proj, reference: reference).value.dictionary ?? [:] dictionary["isa"] = .string(CommentedString(type(of: self).isa)) dictionary["children"] = .array(childrenReferences.map({ (fileReference) -> PlistValue in let fileElement: PBXFileElement? = fileReference.getObject() return .string(CommentedString(fileReference.value, comment: fileElement?.fileName())) })) return (key: CommentedString(reference, comment: name ?? path), value: .dictionary(dictionary)) } } // MARK: - Helpers /// Options passed when adding new groups. public struct GroupAddingOptions: OptionSet { /// Raw value. public let rawValue: Int /// Initializes the options with the raw value. /// /// - Parameter rawValue: raw value. public init(rawValue: Int) { self.rawValue = rawValue } /// Create group without reference to folder public static let withoutFolder = GroupAddingOptions(rawValue: 1 << 0) } public extension PBXGroup { /// Returns group with the given name contained in the given parent group. /// /// - Parameter groupName: group name. /// - Returns: group with the given name contained in the given parent group. func group(named name: String) -> PBXGroup? { return childrenReferences .objects() .first(where: { $0.name == name }) } /// Returns the file in the group with the given name. /// /// - Parameter name: file name. /// - Returns: file with the given name contained in the given parent group. func file(named name: String) -> PBXFileReference? { return childrenReferences .objects() .first(where: { $0.name == name }) } /// Creates a group with the given name and returns it. /// /// - Parameters: /// - groupName: group name. /// - options: creation options. /// - Returns: created groups. @discardableResult func addGroup(named groupName: String, options: GroupAddingOptions = []) throws -> [PBXGroup] { let objects = try self.objects() return groupName.components(separatedBy: "/").reduce(into: [PBXGroup](), { groups, name in let group = groups.last ?? self let newGroup = PBXGroup(children: [], sourceTree: .group, name: name, path: options.contains(.withoutFolder) ? nil : name) group.childrenReferences.append(newGroup.reference) objects.add(object: newGroup) groups.append(newGroup) }) } /// Adds file at the give path to the project or returns existing file and its reference. /// /// - Parameters: /// - filePath: path to the file. /// - sourceTree: file sourceTree, default is `.group` /// - sourceRoot: path to project's source root. /// - Returns: new or existing file and its reference. @discardableResult func addFile( at filePath: Path, sourceTree: PBXSourceTree = .group, sourceRoot: Path ) throws -> PBXFileReference { let projectObjects = try objects() guard filePath.exists else { throw XcodeprojEditingError.unexistingFile(filePath) } let groupPath = try fullPath(sourceRoot: sourceRoot) if let existingFileReference = try projectObjects.fileReferences.first(where: { try filePath == $0.value.fullPath(sourceRoot: sourceRoot) }) { if !childrenReferences.contains(existingFileReference.key) { existingFileReference.value.path = groupPath.flatMap({ filePath.relative(to: $0) })?.string childrenReferences.append(existingFileReference.key) } } let path: String? switch sourceTree { case .group: path = groupPath.map({ filePath.relative(to: $0) })?.string case .sourceRoot: path = filePath.relative(to: sourceRoot).string case .absolute: path = filePath.string default: path = nil } let fileReference = PBXFileReference( sourceTree: sourceTree, name: filePath.lastComponent, explicitFileType: filePath.extension.flatMap(Xcode.filetype), lastKnownFileType: filePath.extension.flatMap(Xcode.filetype), path: path ) projectObjects.add(object: fileReference) if !childrenReferences.contains(fileReference.reference) { childrenReferences.append(fileReference.reference) } return fileReference } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXSourceTree.swift ================================================ import Foundation /// Specifies source trees for files /// Corresponds to the "Location" dropdown in Xcode's File Inspector public enum PBXSourceTree: CustomStringConvertible, Equatable, Decodable { case none case absolute case group case sourceRoot case buildProductsDir case sdkRoot case developerDir case custom(String) private static let noneValue = "" private static let absoluteValue = "" private static let groupValue = "" private static let sourceRootValue = "SOURCE_ROOT" private static let buildProductsDirValue = "BUILT_PRODUCTS_DIR" private static let sdkRootValue = "SDKROOT" private static let developerDirValue = "DEVELOPER_DIR" public init(value: String) { switch value { case PBXSourceTree.noneValue: self = .none case PBXSourceTree.absoluteValue: self = .absolute case PBXSourceTree.groupValue: self = .group case PBXSourceTree.sourceRootValue: self = .sourceRoot case PBXSourceTree.buildProductsDirValue: self = .buildProductsDir case PBXSourceTree.sdkRootValue: self = .sdkRoot case PBXSourceTree.developerDirValue: self = .developerDir default: self = .custom(value) } } public init(from decoder: Decoder) throws { try self.init(value: decoder.singleValueContainer().decode(String.self)) } public static func == (lhs: PBXSourceTree, rhs: PBXSourceTree) -> Bool { switch (lhs, rhs) { case (.none, .none), (.absolute, .absolute), (.group, .group), (.sourceRoot, .sourceRoot), (.buildProductsDir, .buildProductsDir), (.sdkRoot, .sdkRoot), (.developerDir, .developerDir): return true case let (.custom(lhsValue), .custom(rhsValue)): return lhsValue == rhsValue case (.none, _), (.absolute, _), (.group, _), (.sourceRoot, _), (.buildProductsDir, _), (.sdkRoot, _), (.developerDir, _), (.custom, _): return false } } public var description: String { switch self { case .none: return PBXSourceTree.noneValue case .absolute: return PBXSourceTree.absoluteValue case .group: return PBXSourceTree.groupValue case .sourceRoot: return PBXSourceTree.sourceRootValue case .buildProductsDir: return PBXSourceTree.buildProductsDirValue case .sdkRoot: return PBXSourceTree.sdkRootValue case .developerDir: return PBXSourceTree.developerDirValue case let .custom(value): return value } } } // MARK: - PBXSourceTree Extension (PlistValue) extension PBXSourceTree { func plist() -> PlistValue { return .string(CommentedString(String(describing: self))) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/PBXVariantGroup.swift ================================================ import Foundation // This is the element for referencing localized resources. public final class PBXVariantGroup: PBXGroup {} ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Files/XCVersionGroup.swift ================================================ import Foundation import PathKit /// Group that contains multiple files references to the different versions of a resource. /// Used to contain the different versions of a xcdatamodel public final class XCVersionGroup: PBXGroup { // MARK: - Attributes /// Current version. var currentVersionReference: PBXObjectReference? /// Returns the current version file reference. public var currentVersion: PBXFileReference? { get { return currentVersionReference?.getObject() } set { currentVersionReference = newValue?.reference } } /// Version group type. public var versionGroupType: String? // MARK: - Init /// Initializes the group with its attributes. /// /// - Parameters: /// - currentVersion: current version file reference. /// - name: group name. /// - path: group relative path from `sourceTree`, if different than `name`. /// - sourceTree: group source tree. /// - versionGroupType: identifier of the group type. /// - children: group children. /// - includeInIndex: should the IDE index the files in the group? /// - wrapsLines: should the IDE wrap lines for files in the group? /// - usesTabs: group uses tabs. /// - indentWidth: the number of positions to indent blocks of code /// - tabWidth: the visual width of tab characters public init(currentVersion: PBXFileReference? = nil, path: String? = nil, name: String? = nil, sourceTree: PBXSourceTree? = nil, versionGroupType: String? = nil, children: [PBXFileElement] = [], includeInIndex: Bool? = nil, wrapsLines: Bool? = nil, usesTabs: Bool? = nil, indentWidth: UInt? = nil, tabWidth: UInt? = nil) { currentVersionReference = currentVersion?.reference self.versionGroupType = versionGroupType super.init(children: children, sourceTree: sourceTree, name: name, path: path, includeInIndex: includeInIndex, wrapsLines: wrapsLines, usesTabs: usesTabs, indentWidth: indentWidth, tabWidth: tabWidth) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case currentVersion case versionGroupType } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) if let currentVersionReference = try container.decodeIfPresent(String.self, forKey: .currentVersion) { self.currentVersionReference = objectReferenceRepository.getOrCreate(reference: currentVersionReference, objects: objects) } else { currentVersionReference = nil } versionGroupType = try container.decodeIfPresent(String.self, forKey: .versionGroupType) try super.init(from: decoder) } // MARK: - XCVersionGroup Extension (PlistSerializable) override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = try super.plistKeyAndValue(proj: proj, reference: reference).value.dictionary ?? [:] dictionary["isa"] = .string(CommentedString(XCVersionGroup.isa)) if let versionGroupType = versionGroupType { dictionary["versionGroupType"] = .string(CommentedString(versionGroupType)) } if let currentVersionReference = currentVersionReference { let fileElement: PBXFileElement? = currentVersionReference.getObject() dictionary["currentVersion"] = .string(CommentedString(currentVersionReference.value, comment: fileElement?.fileName())) } return (key: CommentedString(reference, comment: path?.split(separator: "/").last.map(String.init)), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXObject.swift ================================================ // sourcery:file: skipEquality import Foundation /// Class that represents a project element. public class PBXObject: Hashable, Decodable, Equatable, AutoEquatable { /// Returns the unique identifier. /// Note: The unique identifier of an object might change when the project gets written. /// If you use this identifier from a scheme, make sure the project is written before the project is. public var uuid: String { return reference.value } /// The object reference in the project that contains it. let reference: PBXObjectReference /** Used to differentiate this object from other equatable ones for the purposes of uuid generation. This shouldn't be required to be set in normal circumstances. In some rare cases xcodeproj doesn't have enough context about otherwise equatable objects, so it has to resolve automatic uuid conflicts by appending numbers. This property can be used to provide more context to disambiguate these objects, which will result in more deterministic uuids. */ public var context: String? // MARK: - Init init() { reference = PBXObjectReference() reference.setObject(self) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case reference } /// Initializes the object from its project representation. /// /// - Parameter decoder: XcodeprojPropertyListDecoder decoder. /// - Throws: an error if the object cannot be parsed. public required init(from decoder: Decoder) throws { let referenceRepository = decoder.context.objectReferenceRepository let objects = decoder.context.objects let container = try decoder.container(keyedBy: CodingKeys.self) let reference: String = try container.decode(.reference) self.reference = referenceRepository.getOrCreate(reference: reference, objects: objects) self.reference.setObject(self) } /// Object isa (type id) public static var isa: String { return String(describing: self) } public static func == (lhs: PBXObject, rhs: PBXObject) -> Bool { return lhs.isEqual(to: rhs) } @objc dynamic func isEqual(to _: Any?) -> Bool { return true } public func hash(into hasher: inout Hasher) { hasher.combine(reference) } /// Returns the objects the object belong to. /// /// - Returns: objects the object belongs to. /// - Throws: an error if this method is accessed before the object has been added to a project. func objects() throws -> PBXObjects { guard let objects = self.reference.objects else { let objectType = String(describing: type(of: self)) throw PBXObjectError.orphaned(type: objectType, reference: reference.value) } return objects } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXObjectParser.swift ================================================ import Foundation final class PBXObjectParser { private let userInfo: [CodingUserInfoKey: Any] private let decoder = XcodeprojJSONDecoder() init(userInfo: [CodingUserInfoKey: Any]) { self.userInfo = userInfo } // swiftlint:disable function_body_length public func parse(reference: String, dictionary: [String: Any]) throws -> PBXObject { var mutableDictionary = dictionary mutableDictionary["reference"] = reference let data = try JSONSerialization.data(withJSONObject: mutableDictionary, options: []) guard let isa = dictionary["isa"] as? String else { throw PBXObjectError.missingIsa } // Order is important for performance switch isa { case PBXFileElement.isa: return try decoder.decode(PBXFileElement.self, from: data) case PBXBuildFile.isa: return try decoder.decode(PBXBuildFile.self, from: data) case PBXFileReference.isa: return try decoder.decode(PBXFileReference.self, from: data) case PBXLegacyTarget.isa: return try decoder.decode(PBXLegacyTarget.self, from: data) case PBXNativeTarget.isa: return try decoder.decode(PBXNativeTarget.self, from: data) case PBXAggregateTarget.isa: return try decoder.decode(PBXAggregateTarget.self, from: data) case PBXProject.isa: return try decoder.decode(PBXProject.self, from: data) case PBXGroup.isa: return try decoder.decode(PBXGroup.self, from: data) case PBXHeadersBuildPhase.isa: return try decoder.decode(PBXHeadersBuildPhase.self, from: data) case PBXFrameworksBuildPhase.isa: return try decoder.decode(PBXFrameworksBuildPhase.self, from: data) case XCConfigurationList.isa: return try decoder.decode(XCConfigurationList.self, from: data) case PBXResourcesBuildPhase.isa: return try decoder.decode(PBXResourcesBuildPhase.self, from: data) case PBXShellScriptBuildPhase.isa: return try decoder.decode(PBXShellScriptBuildPhase.self, from: data) case PBXSourcesBuildPhase.isa: return try decoder.decode(PBXSourcesBuildPhase.self, from: data) case PBXTargetDependency.isa: return try decoder.decode(PBXTargetDependency.self, from: data) case PBXVariantGroup.isa: return try decoder.decode(PBXVariantGroup.self, from: data) case XCBuildConfiguration.isa: return try decoder.decode(XCBuildConfiguration.self, from: data) case PBXCopyFilesBuildPhase.isa: return try decoder.decode(PBXCopyFilesBuildPhase.self, from: data) case PBXContainerItemProxy.isa: return try decoder.decode(PBXContainerItemProxy.self, from: data) case PBXReferenceProxy.isa: return try decoder.decode(PBXReferenceProxy.self, from: data) case XCVersionGroup.isa: return try decoder.decode(XCVersionGroup.self, from: data) case PBXRezBuildPhase.isa: return try decoder.decode(PBXRezBuildPhase.self, from: data) case PBXBuildRule.isa: return try decoder.decode(PBXBuildRule.self, from: data) default: throw PBXObjectError.unknownElement(isa) } } // swiftlint:enable function_body_length } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXObjectReference.swift ================================================ import Foundation import os.signpost /// Object used as a reference to PBXObjects from PBXObjects. class PBXObjectReference: NSObject, Comparable, NSCopying { /// Boolean that indicates whether the id is temporary and needs /// to be regenerated when saving it to disk. private(set) var temporary: Bool /// String reference. private(set) var value: String /// Weak reference to the objects instance that contains the project objects. weak var objects: PBXObjects? /// A weak reference to the object private weak var object: PBXObject? /// Initializes a non-temporary reference. /// /// - Parameter reference: reference. init(_ reference: String, objects: PBXObjects) { value = reference temporary = false self.objects = objects } /// Initializes a temporary reference init(objects: PBXObjects? = nil) { value = "TEMP_\(UUID().uuidString)" temporary = true self.objects = objects } /// Initializes the reference without objects. /// /// - Parameter reference: reference. init(_ reference: String) { value = reference temporary = false } /// Initializes the object reference with another object reference, copying its values. /// /// - Parameter objectReference: object reference to be initialized from. required init(_ objectReference: PBXObjectReference) { value = objectReference.value temporary = objectReference.temporary } /// Fixes its value making it permanent. /// /// - Parameter value: value. func fix(_ value: String) { let object = objects?.delete(reference: self) self.value = value temporary = false if let object = object { objects?.add(object: object) } } /// Invalidates the reference making it temporary. func invalidate() { let object = objects?.delete(reference: self) value = "TEMP_\(UUID().uuidString)" temporary = true if let object = object { objects?.add(object: object) } } /// Hash value. override var hash: Int { return value.hashValue } func copy(with _: NSZone? = nil) -> Any { return type(of: self).init(self) } /// Compares two instances of PBXObjectReference /// /// - Parameters: /// - lhs: first instance to be compared. /// - rhs: second instance to be compared. /// - Returns: true if the two instances are equal. static func == (lhs: PBXObjectReference, rhs: PBXObjectReference) -> Bool { return lhs.isEqual(rhs) } /// Compares with another instance of PBXObjectReference. /// /// - Parameters: /// - object: instance to be compared with. /// - Returns: true if the two instances are equal. override func isEqual(_ object: Any?) -> Bool { guard let object = object as? PBXObjectReference else { return false } return value == object.value } /// Compares two instances. /// /// - Parameters: /// - lhs: first instance to be compared. /// - rhs: second instance to be compared. /// - Returns: comparison result. static func < (lhs: PBXObjectReference, rhs: PBXObjectReference) -> Bool { return lhs.value < rhs.value } /// Sets the object so it can be retrieved quickly again later /// /// - Parameter object: The object func setObject(_ object: PBXObject) { self.object = object } /// Returns the object the reference is referfing to. /// /// - Returns: object the reference is referring to. Returns nil if the objects property has been released or the reference doesn't exist func getObject() -> T? { return try? getThrowingObject() } /// Returns the object the reference is referfing to. /// /// - Returns: object the reference is referring to. /// - Throws: an errof it the objects property has been released or the reference doesn't exist. func getThrowingObject() throws -> T { return try OSLogger.instance.log(name: "Materialize Object") { if let object = object as? T { return object } guard let objects = objects else { throw PBXObjectError.objectsReleased } guard let object = objects.get(reference: self) as? T else { throw PBXObjectError.objectNotFound(value) } self.object = object return object } } } extension Array where Element: PBXObject { func references() -> [PBXObjectReference] { return map { $0.reference } } } extension Array where Element: PBXObjectReference { func objects() -> [T] { return compactMap { $0.getObject() } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXObjects.swift ================================================ import Foundation // swiftlint:disable type_body_length class PBXObjects: Equatable { // MARK: - Properties private let lock = NSRecursiveLock() private var unsyncProjects: [PBXObjectReference: PBXProject] = [:] var projects: [PBXObjectReference: PBXProject] { return lock.whileLocked { unsyncProjects } } private var unsyncReferenceProxies: [PBXObjectReference: PBXReferenceProxy] = [:] var referenceProxies: [PBXObjectReference: PBXReferenceProxy] { return lock.whileLocked { unsyncReferenceProxies } } // File elements private var unsyncFileReferences: [PBXObjectReference: PBXFileReference] = [:] var fileReferences: [PBXObjectReference: PBXFileReference] { return lock.whileLocked { unsyncFileReferences } } private var unsyncVersionGroups: [PBXObjectReference: XCVersionGroup] = [:] var versionGroups: [PBXObjectReference: XCVersionGroup] { return lock.whileLocked { unsyncVersionGroups } } private var unsyncVariantGroups: [PBXObjectReference: PBXVariantGroup] = [:] var variantGroups: [PBXObjectReference: PBXVariantGroup] { return lock.whileLocked { unsyncVariantGroups } } private var unsyncGroups: [PBXObjectReference: PBXGroup] = [:] var groups: [PBXObjectReference: PBXGroup] { return lock.whileLocked { unsyncGroups } } // Configuration private var unsyncBuildConfigurations: [PBXObjectReference: XCBuildConfiguration] = [:] var buildConfigurations: [PBXObjectReference: XCBuildConfiguration] { return lock.whileLocked { unsyncBuildConfigurations } } private var unsyncConfigurationLists: [PBXObjectReference: XCConfigurationList] = [:] var configurationLists: [PBXObjectReference: XCConfigurationList] { return lock.whileLocked { unsyncConfigurationLists } } // Targets private var unsyncLegacyTargets: [PBXObjectReference: PBXLegacyTarget] = [:] var legacyTargets: [PBXObjectReference: PBXLegacyTarget] { return lock.whileLocked { unsyncLegacyTargets } } private var unsyncAggregateTargets: [PBXObjectReference: PBXAggregateTarget] = [:] var aggregateTargets: [PBXObjectReference: PBXAggregateTarget] { return lock.whileLocked { unsyncAggregateTargets } } private var unsyncNativeTargets: [PBXObjectReference: PBXNativeTarget] = [:] var nativeTargets: [PBXObjectReference: PBXNativeTarget] { return lock.whileLocked { unsyncNativeTargets } } private var unsyncTargetDependencies: [PBXObjectReference: PBXTargetDependency] = [:] var targetDependencies: [PBXObjectReference: PBXTargetDependency] { return lock.whileLocked { unsyncTargetDependencies } } private var unsyncContainerItemProxies: [PBXObjectReference: PBXContainerItemProxy] = [:] var containerItemProxies: [PBXObjectReference: PBXContainerItemProxy] { return lock.whileLocked { unsyncContainerItemProxies } } private var unsyncBuildRules: [PBXObjectReference: PBXBuildRule] = [:] var buildRules: [PBXObjectReference: PBXBuildRule] { return lock.whileLocked { unsyncBuildRules } } // Build Phases private var unsyncBuildFiles: [PBXObjectReference: PBXBuildFile] = [:] var buildFiles: [PBXObjectReference: PBXBuildFile] { return lock.whileLocked { unsyncBuildFiles } } private var unsyncCopyFilesBuildPhases: [PBXObjectReference: PBXCopyFilesBuildPhase] = [:] var copyFilesBuildPhases: [PBXObjectReference: PBXCopyFilesBuildPhase] { return lock.whileLocked { unsyncCopyFilesBuildPhases } } private var unsyncShellScriptBuildPhases: [PBXObjectReference: PBXShellScriptBuildPhase] = [:] var shellScriptBuildPhases: [PBXObjectReference: PBXShellScriptBuildPhase] { return lock.whileLocked { unsyncShellScriptBuildPhases } } private var unsyncResourcesBuildPhases: [PBXObjectReference: PBXResourcesBuildPhase] = [:] var resourcesBuildPhases: [PBXObjectReference: PBXResourcesBuildPhase] { return lock.whileLocked { unsyncResourcesBuildPhases } } private var unsyncFrameworksBuildPhases: [PBXObjectReference: PBXFrameworksBuildPhase] = [:] var frameworksBuildPhases: [PBXObjectReference: PBXFrameworksBuildPhase] { return lock.whileLocked { unsyncFrameworksBuildPhases } } private var unsyncHeadersBuildPhases: [PBXObjectReference: PBXHeadersBuildPhase] = [:] var headersBuildPhases: [PBXObjectReference: PBXHeadersBuildPhase] { return lock.whileLocked { unsyncHeadersBuildPhases } } private var unsyncSourcesBuildPhases: [PBXObjectReference: PBXSourcesBuildPhase] = [:] var sourcesBuildPhases: [PBXObjectReference: PBXSourcesBuildPhase] { return lock.whileLocked { unsyncSourcesBuildPhases } } private var unsyncCarbonResourcesBuildPhases: [PBXObjectReference: PBXRezBuildPhase] = [:] var carbonResourcesBuildPhases: [PBXObjectReference: PBXRezBuildPhase] { return lock.whileLocked { unsyncCarbonResourcesBuildPhases } } /// Initializes the project objects container /// /// - Parameters: /// - objects: project objects init(objects: [PBXObject] = []) { objects.forEach { _ = self.add(object: $0) } } // MARK: - Equatable public static func == (lhs: PBXObjects, rhs: PBXObjects) -> Bool { return lhs.buildFiles == rhs.buildFiles && lhs.legacyTargets == rhs.legacyTargets && lhs.aggregateTargets == rhs.aggregateTargets && lhs.containerItemProxies == rhs.containerItemProxies && lhs.copyFilesBuildPhases == rhs.copyFilesBuildPhases && lhs.groups == rhs.groups && lhs.configurationLists == rhs.configurationLists && lhs.buildConfigurations == rhs.buildConfigurations && lhs.variantGroups == rhs.variantGroups && lhs.targetDependencies == rhs.targetDependencies && lhs.sourcesBuildPhases == rhs.sourcesBuildPhases && lhs.shellScriptBuildPhases == rhs.shellScriptBuildPhases && lhs.resourcesBuildPhases == rhs.resourcesBuildPhases && lhs.frameworksBuildPhases == rhs.frameworksBuildPhases && lhs.headersBuildPhases == rhs.headersBuildPhases && lhs.nativeTargets == rhs.nativeTargets && lhs.fileReferences == rhs.fileReferences && lhs.projects == rhs.projects && lhs.versionGroups == rhs.versionGroups && lhs.referenceProxies == rhs.referenceProxies && lhs.carbonResourcesBuildPhases == rhs.carbonResourcesBuildPhases && lhs.buildRules == rhs.buildRules } // MARK: - Helpers /// Add a new object. /// /// - Parameters: /// - object: object. func add(object: PBXObject) { lock.lock() defer { lock.unlock() } let objectReference: PBXObjectReference = object.reference objectReference.objects = self switch object { // subclasses of PBXGroup; must be tested before PBXGroup case let object as PBXVariantGroup: unsyncVariantGroups[objectReference] = object case let object as XCVersionGroup: unsyncVersionGroups[objectReference] = object // everything else case let object as PBXBuildFile: unsyncBuildFiles[objectReference] = object case let object as PBXAggregateTarget: unsyncAggregateTargets[objectReference] = object case let object as PBXLegacyTarget: unsyncLegacyTargets[objectReference] = object case let object as PBXContainerItemProxy: unsyncContainerItemProxies[objectReference] = object case let object as PBXCopyFilesBuildPhase: unsyncCopyFilesBuildPhases[objectReference] = object case let object as PBXGroup: unsyncGroups[objectReference] = object case let object as XCConfigurationList: unsyncConfigurationLists[objectReference] = object case let object as XCBuildConfiguration: unsyncBuildConfigurations[objectReference] = object case let object as PBXTargetDependency: unsyncTargetDependencies[objectReference] = object case let object as PBXSourcesBuildPhase: unsyncSourcesBuildPhases[objectReference] = object case let object as PBXShellScriptBuildPhase: unsyncShellScriptBuildPhases[objectReference] = object case let object as PBXResourcesBuildPhase: unsyncResourcesBuildPhases[objectReference] = object case let object as PBXFrameworksBuildPhase: unsyncFrameworksBuildPhases[objectReference] = object case let object as PBXHeadersBuildPhase: unsyncHeadersBuildPhases[objectReference] = object case let object as PBXNativeTarget: unsyncNativeTargets[objectReference] = object case let object as PBXFileReference: unsyncFileReferences[objectReference] = object case let object as PBXProject: unsyncProjects[objectReference] = object case let object as PBXReferenceProxy: unsyncReferenceProxies[objectReference] = object case let object as PBXRezBuildPhase: unsyncCarbonResourcesBuildPhases[objectReference] = object case let object as PBXBuildRule: unsyncBuildRules[objectReference] = object default: fatalError("Unhandled PBXObject type for \(object), this is likely a bug / todo") } } /// Deletes the object with the given reference. /// /// - Parameter reference: referenc of the object to be deleted. /// - Returns: the deleted object. // swiftlint:disable:next function_body_length Note: SwiftLint doesn't disable if @discardable and the function are on different lines. @discardableResult func delete(reference: PBXObjectReference) -> PBXObject? { lock.lock() if let index = buildFiles.index(forKey: reference) { return unsyncBuildFiles.remove(at: index).value } else if let index = aggregateTargets.index(forKey: reference) { return unsyncAggregateTargets.remove(at: index).value } else if let index = legacyTargets.index(forKey: reference) { return unsyncLegacyTargets.remove(at: index).value } else if let index = containerItemProxies.index(forKey: reference) { return unsyncContainerItemProxies.remove(at: index).value } else if let index = groups.index(forKey: reference) { return unsyncGroups.remove(at: index).value } else if let index = configurationLists.index(forKey: reference) { return unsyncConfigurationLists.remove(at: index).value } else if let index = buildConfigurations.index(forKey: reference) { return unsyncBuildConfigurations.remove(at: index).value } else if let index = variantGroups.index(forKey: reference) { return unsyncVariantGroups.remove(at: index).value } else if let index = targetDependencies.index(forKey: reference) { return unsyncTargetDependencies.remove(at: index).value } else if let index = nativeTargets.index(forKey: reference) { return unsyncNativeTargets.remove(at: index).value } else if let index = fileReferences.index(forKey: reference) { return unsyncFileReferences.remove(at: index).value } else if let index = projects.index(forKey: reference) { return unsyncProjects.remove(at: index).value } else if let index = versionGroups.index(forKey: reference) { return unsyncVersionGroups.remove(at: index).value } else if let index = referenceProxies.index(forKey: reference) { return unsyncReferenceProxies.remove(at: index).value } else if let index = copyFilesBuildPhases.index(forKey: reference) { return unsyncCopyFilesBuildPhases.remove(at: index).value } else if let index = shellScriptBuildPhases.index(forKey: reference) { return unsyncShellScriptBuildPhases.remove(at: index).value } else if let index = resourcesBuildPhases.index(forKey: reference) { return unsyncResourcesBuildPhases.remove(at: index).value } else if let index = frameworksBuildPhases.index(forKey: reference) { return unsyncFrameworksBuildPhases.remove(at: index).value } else if let index = headersBuildPhases.index(forKey: reference) { return unsyncHeadersBuildPhases.remove(at: index).value } else if let index = sourcesBuildPhases.index(forKey: reference) { return unsyncSourcesBuildPhases.remove(at: index).value } else if let index = carbonResourcesBuildPhases.index(forKey: reference) { return unsyncCarbonResourcesBuildPhases.remove(at: index).value } else if let index = buildRules.index(forKey: reference) { return unsyncBuildRules.remove(at: index).value } lock.unlock() return nil } /// It returns the object with the given reference. /// /// - Parameter reference: Xcode reference. /// - Returns: object. // swiftlint:disable:next function_body_length func get(reference: PBXObjectReference) -> PBXObject? { // This if-let expression is used because the equivalent chain of `??` separated lookups causes, // with Swift 4, this compiler error: // Expression was too complex to be solved in reasonable time; // consider breaking up the expression into distinct sub-expressions if let object = buildFiles[reference] { return object } else if let object = aggregateTargets[reference] { return object } else if let object = legacyTargets[reference] { return object } else if let object = containerItemProxies[reference] { return object } else if let object = groups[reference] { return object } else if let object = configurationLists[reference] { return object } else if let object = buildConfigurations[reference] { return object } else if let object = variantGroups[reference] { return object } else if let object = targetDependencies[reference] { return object } else if let object = nativeTargets[reference] { return object } else if let object = fileReferences[reference] { return object } else if let object = projects[reference] { return object } else if let object = versionGroups[reference] { return object } else if let object = referenceProxies[reference] { return object } else if let object = copyFilesBuildPhases[reference] { return object } else if let object = shellScriptBuildPhases[reference] { return object } else if let object = resourcesBuildPhases[reference] { return object } else if let object = frameworksBuildPhases[reference] { return object } else if let object = headersBuildPhases[reference] { return object } else if let object = sourcesBuildPhases[reference] { return object } else if let object = carbonResourcesBuildPhases[reference] { return object } else if let object = buildRules[reference] { return object } else { return nil } } } // MARK: - Public extension PBXObjects { /// Returns all the targets with the given name. /// /// - Parameters: /// - name: target name. /// - Returns: targets with the given name. func targets(named name: String) -> [PBXTarget] { var targets: [PBXTarget] = [] let filter = { (targets: [PBXObjectReference: PBXTarget]) -> [PBXTarget] in targets.values.filter({ $0.name == name }) } targets.append(contentsOf: filter(nativeTargets)) targets.append(contentsOf: filter(legacyTargets)) targets.append(contentsOf: filter(aggregateTargets)) return targets } /// Invalidates all the objects references. func invalidateReferences() { forEach { $0.reference.invalidate() } } // MARK: - Computed Properties var buildPhases: [PBXObjectReference: PBXBuildPhase] { var phases: [PBXObjectReference: PBXBuildPhase] = [:] phases.merge(copyFilesBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(sourcesBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(shellScriptBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(resourcesBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(headersBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(carbonResourcesBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) phases.merge(frameworksBuildPhases as [PBXObjectReference: PBXBuildPhase], uniquingKeysWith: { first, _ in first }) return phases } // This dictionary is used to quickly get a connection between the build phase and the build files of this phase. // This is used to decode build files. (we need the name of the build phase) // Otherwise, we would have to go through all the build phases for each file. var buildPhaseFile: [PBXObjectReference: PBXBuildPhaseFile] { let values: [[PBXBuildPhaseFile]] = buildPhases.values.map({ buildPhase in let files = buildPhase.files let buildPhaseFile: [PBXBuildPhaseFile] = files.compactMap({ (file: PBXBuildFile) -> (PBXBuildPhaseFile) in PBXBuildPhaseFile( buildFile: file, buildPhase: buildPhase ) }) return buildPhaseFile }) return Dictionary(uniqueKeysWithValues: values.flatMap({ $0 }).map({ ($0.buildFile.reference, $0) })) } /// Runs the given closure for each of the objects that are part of the project. /// /// - Parameter closure: closure to be run. func forEach(_ closure: (PBXObject) -> Void) { buildFiles.values.forEach(closure) legacyTargets.values.forEach(closure) aggregateTargets.values.forEach(closure) containerItemProxies.values.forEach(closure) groups.values.forEach(closure) configurationLists.values.forEach(closure) versionGroups.values.forEach(closure) buildConfigurations.values.forEach(closure) variantGroups.values.forEach(closure) targetDependencies.values.forEach(closure) nativeTargets.values.forEach(closure) fileReferences.values.forEach(closure) projects.values.forEach(closure) referenceProxies.values.forEach(closure) buildRules.values.forEach(closure) copyFilesBuildPhases.values.forEach(closure) shellScriptBuildPhases.values.forEach(closure) resourcesBuildPhases.values.forEach(closure) frameworksBuildPhases.values.forEach(closure) headersBuildPhases.values.forEach(closure) sourcesBuildPhases.values.forEach(closure) carbonResourcesBuildPhases.values.forEach(closure) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXOutputSettings.swift ================================================ import Foundation /// Code for controlling sorting of files in an pbxproj file. // MARK: - Core sort functions // Because of the number of optional data items in PBXBuildFiles, we've externalised the core code in these two functions. // Note, PBXBuildFile's contains PBXFileElements so this first function is an optional handling wrapper driving the second. // Also note that we use the .fileName() function to retrieve the name as both .path and .name properties can be nil. private func sortUsingNames(_ lhs: PBXBuildFile, _ rhs: PBXBuildFile) -> Bool { if let lhsFile = lhs.file, let rhsFile = rhs.file { return sortUsingNames(lhsFile, rhsFile) } return lhs.uuid < rhs.uuid } private func sortUsingNames(_ lhs: PBXFileElement, _ rhs: PBXFileElement) -> Bool { if let lhsFilename = lhs.fileName(), let rhsFilename = rhs.fileName() { return lhsFilename == rhsFilename ? lhs.uuid < rhs.uuid : lhsFilename < rhsFilename } return lhs.uuid < rhs.uuid } // MARK: - Sorting enums /// Defines the sorting applied to files within the file lists. Defaults to by UUID. public enum PBXFileOrder { /// Sort files by Xcode's UUID case byUUID /// Sort files by their file name. This is a case sensistive sort with lower case names coming after uppercase names. case byFilename internal func sort(lhs: (PBXObjectReference, Object), rhs: (PBXObjectReference, Object)) -> Bool where Object: PlistSerializable & Equatable { return lhs.0 < rhs.0 } internal func sort(lhs: (PBXObjectReference, PBXBuildFile), rhs: (PBXObjectReference, PBXBuildFile)) -> Bool { switch self { case .byFilename: return sortUsingNames(lhs.1, rhs.1) default: return lhs.0 < rhs.0 } } internal func sort(lhs: (PBXObjectReference, PBXBuildPhaseFile), rhs: (PBXObjectReference, PBXBuildPhaseFile)) -> Bool { switch self { case .byFilename: return sortUsingNames(lhs.1.buildFile, rhs.1.buildFile) default: return lhs.0 < rhs.0 } } internal func sort(lhs: (PBXObjectReference, PBXFileReference), rhs: (PBXObjectReference, PBXFileReference)) -> Bool { switch self { case .byFilename: return sortUsingNames(lhs.1, rhs.1) default: return lhs.0 < rhs.0 } } } private extension PBXFileElement { var isGroup: Bool { switch self { case is PBXVariantGroup, is XCVersionGroup: return false case is PBXGroup: return true default: return false } } } /// Defines the sorting applied to groups with the project navigator and various build phases. public enum PBXNavigatorFileOrder { /// Leave the files unsorted. case unsorted /// Sort the file by their file name. This is a case sensitive sort with uppercase name preceeding lowercase names. case byFilename /// Sorts the files by their file names with all groups appear at the top of the list. case byFilenameGroupsFirst internal var sort: ((PBXFileElement, PBXFileElement) -> Bool)? { switch self { case .byFilename: return { sortUsingNames($0, $1) } case .byFilenameGroupsFirst: return { lhs, rhs in let lhsIsGroup = lhs.isGroup if lhsIsGroup != rhs.isGroup { return lhsIsGroup } return sortUsingNames(lhs, rhs) } default: return nil // Don't sort. } } } /// Defines the sorting of file within a build phase. public enum PBXBuildPhaseFileOrder { /// Leave the files unsorted. case unsorted /// Sort the files by their file name. This is a case sensitive sort with uppercase names appearing before lowercase names. case byFilename internal var sort: ((PBXBuildFile, PBXBuildFile) -> Bool)? { switch self { case .byFilename: return { lhs, rhs in sortUsingNames(lhs, rhs) } default: return nil // Don't sort. } } } /// Defines the format of project file references public enum PBXReferenceFormat { /// Adds prefix and suffix characters to the references. /// The prefix characters identify the type of reference generated (e.g. BP for Build Phase). /// The suffix number is only added for uniqueness if clashes occur. case withPrefixAndSuffix /// Standard 32 char format that XCode generates. /// Note: Not guaranteed to be the same as XCode generates - only the format is the same. case xcode } /// Struct of output settings passed to various methods. public struct PBXOutputSettings { /// The sorting order for the list of files in Xcode's project file. let projFileListOrder: PBXFileOrder /// The sort order for files and groups that appear in the Xcode Project Navigator. let projNavigatorFileOrder: PBXNavigatorFileOrder /// The sort order for lists of files in build phases. let projBuildPhaseFileOrder: PBXBuildPhaseFileOrder /// The format of project file references let projReferenceFormat: PBXReferenceFormat /** Default initializer - Parameter projFileListOrder: Defines the sort order for internal file lists in the project file. - Parameter projNavigatorFileOrder: Defines the order of files in the project navigator groups. - Parameter projBuildPhaseFileOrder: Defines the sort order of files in build phases. */ public init(projFileListOrder: PBXFileOrder = .byUUID, projNavigatorFileOrder: PBXNavigatorFileOrder = .unsorted, projBuildPhaseFileOrder: PBXBuildPhaseFileOrder = .unsorted, projReferenceFormat: PBXReferenceFormat = .xcode) { self.projFileListOrder = projFileListOrder self.projNavigatorFileOrder = projNavigatorFileOrder self.projBuildPhaseFileOrder = projBuildPhaseFileOrder self.projReferenceFormat = projReferenceFormat } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXProj.swift ================================================ import Foundation import PathKit /// Represents a .pbxproj file public final class PBXProj: Decodable { // MARK: - Properties let objects: PBXObjects /// Project archive version. public var archiveVersion: UInt /// Project object version. public var objectVersion: UInt /// Project classes. public var classes: [String: Any] /// Project root object. var rootObjectReference: PBXObjectReference? /// Project root object. public var rootObject: PBXProject? { set { rootObjectReference = newValue?.reference } get { return rootObjectReference?.getObject() } } /// Initializes the project with its attributes. /// /// - Parameters: /// - rootObject: project root object. /// - objectVersion: project object version. /// - archiveVersion: project archive version. /// - classes: project classes. /// - objects: project objects public init(rootObject: PBXProject? = nil, objectVersion: UInt = Xcode.LastKnown.objectVersion, archiveVersion: UInt = Xcode.LastKnown.archiveVersion, classes: [String: Any] = [:], objects: [PBXObject] = []) { self.archiveVersion = archiveVersion self.objectVersion = objectVersion self.classes = classes rootObjectReference = rootObject?.reference self.objects = PBXObjects(objects: objects) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case archiveVersion case objectVersion case classes case objects case rootObject } public required init(from decoder: Decoder) throws { let objects = decoder.context.objects let objectReferenceRepository = decoder.context.objectReferenceRepository let container = try decoder.container(keyedBy: CodingKeys.self) let rootObjectReference: String = try container.decode(.rootObject) self.rootObjectReference = objectReferenceRepository.getOrCreate(reference: rootObjectReference, objects: objects) objectVersion = try container.decodeIntIfPresent(.objectVersion) ?? 0 archiveVersion = try container.decodeIntIfPresent(.archiveVersion) ?? 1 classes = try container.decodeIfPresent([String: Any].self, forKey: .classes) ?? [:] let objectsDictionary: [String: Any] = try container.decodeIfPresent([String: Any].self, forKey: .objects) ?? [:] let objectsDictionaries: [String: [String: Any]] = (objectsDictionary as? [String: [String: Any]]) ?? [:] let parser = PBXObjectParser( userInfo: decoder.userInfo ) try objectsDictionaries.enumerateKeysAndObjects(options: .concurrent) { key, obj, _ in // swiftlint:disable force_cast let reference = key as! String let dictionary = obj as! [String: Any] // swiftlint:enable force_cast let object = try parser.parse( reference: reference, dictionary: dictionary ) objects.add(object: object) } self.objects = objects } } // MARK: - Public helpers public extension PBXProj { // MARK: - Properties var projects: [PBXProject] { return Array(objects.projects.values) } var referenceProxies: [PBXReferenceProxy] { return Array(objects.referenceProxies.values) } // File elements var fileReferences: [PBXFileReference] { return Array(objects.fileReferences.values) } var versionGroups: [XCVersionGroup] { return Array(objects.versionGroups.values) } var variantGroups: [PBXVariantGroup] { return Array(objects.variantGroups.values) } var groups: [PBXGroup] { return Array(objects.groups.values) } // Configuration var buildConfigurations: [XCBuildConfiguration] { return Array(objects.buildConfigurations.values) } var configurationLists: [XCConfigurationList] { return Array(objects.configurationLists.values) } // Targets var legacyTargets: [PBXLegacyTarget] { return Array(objects.legacyTargets.values) } var aggregateTargets: [PBXAggregateTarget] { return Array(objects.aggregateTargets.values) } var nativeTargets: [PBXNativeTarget] { return Array(objects.nativeTargets.values) } var targetDependencies: [PBXTargetDependency] { return Array(objects.targetDependencies.values) } var containerItemProxies: [PBXContainerItemProxy] { return Array(objects.containerItemProxies.values) } var buildRules: [PBXBuildRule] { return Array(objects.buildRules.values) } // Build var buildFiles: [PBXBuildFile] { return Array(objects.buildFiles.values) } var copyFilesBuildPhases: [PBXCopyFilesBuildPhase] { return Array(objects.copyFilesBuildPhases.values) } var shellScriptBuildPhases: [PBXShellScriptBuildPhase] { return Array(objects.shellScriptBuildPhases.values) } var resourcesBuildPhases: [PBXResourcesBuildPhase] { return Array(objects.resourcesBuildPhases.values) } var frameworksBuildPhases: [PBXFrameworksBuildPhase] { return Array(objects.frameworksBuildPhases.values) } var headersBuildPhases: [PBXHeadersBuildPhase] { return Array(objects.headersBuildPhases.values) } var sourcesBuildPhases: [PBXSourcesBuildPhase] { return Array(objects.sourcesBuildPhases.values) } var carbonResourcesBuildPhases: [PBXRezBuildPhase] { return Array(objects.carbonResourcesBuildPhases.values) } var buildPhases: [PBXBuildPhase] { return Array(objects.buildPhases.values) } /// Returns root project. func rootProject() throws -> PBXProject? { return try rootObjectReference?.getThrowingObject() } /// Returns root project's root group. func rootGroup() throws -> PBXGroup? { let project = try rootProject() return try project?.mainGroupReference.getThrowingObject() } /// Adds a new object to the project. /// /// - Parameter object: object to be added. func add(object: PBXObject) { objects.add(object: object) } /// Deletes an object from the project. /// /// - Parameter object: object to be deleted. func delete(object: PBXObject) { objects.delete(reference: object.reference) } /// Returns all the targets with the given name. /// /// - Parameters: /// - name: target name. /// - Returns: targets with the given name. func targets(named name: String) -> [PBXTarget] { return objects.targets(named: name) } /// Invalidates all the objects UUIDs. /// Those UUIDs will be generated deterministically when the project is saved. func invalidateUUIDs() { objects.invalidateReferences() } /// Runs the given closure passing each of the objects that are part of the project. /// /// - Parameter closure: closure to be run. func forEach(_ closure: (PBXObject) -> Void) { objects.forEach(closure) } } // MARK: - Internal helpers extension PBXProj { /// Infers project name from Path and sets it as project name /// /// Project name is needed for certain comments when serialising PBXProj /// /// - Parameters: /// - path: path to .xcodeproj directory. func updateProjectName(path: Path) throws { guard path.parent().extension == "xcodeproj" else { return } let projectName = path.parent().lastComponent.split(separator: ".").first try rootProject()?.name = projectName.map(String.init) ?? "" } } // MARK: - Equatable extension PBXProj: Equatable { public static func == (lhs: PBXProj, rhs: PBXProj) -> Bool { let equalClasses = NSDictionary(dictionary: lhs.classes).isEqual(to: rhs.classes) return lhs.archiveVersion == rhs.archiveVersion && lhs.objectVersion == rhs.objectVersion && equalClasses && lhs.objects == rhs.objects } } // MARK: - Writable extension PBXProj: Writable { public func write(path: Path, override: Bool) throws { try write(path: path, override: override, outputSettings: PBXOutputSettings()) } public func write(path: Path, override: Bool, outputSettings: PBXOutputSettings) throws { let encoder = PBXProjEncoder(outputSettings: outputSettings) let output = try encoder.encode(proj: self) if override, path.exists { try path.delete() } try path.write(output) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXProjEncoder.swift ================================================ import Foundation /// Protocol that defines that the element can return a plist element that represents itself. protocol PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) var multiline: Bool { get } } extension PlistSerializable { var multiline: Bool { return true } } final class StateHolder { var indent: UInt = 0 var multiline: Bool = true func increaseIndent() { indent += 1 } func decreaseIndent() { indent -= 1 } } /// Encodes your PBXProj files to String // swiftlint:disable:next type_body_length final class PBXProjEncoder { let outputSettings: PBXOutputSettings let referenceGenerator: ReferenceGenerating init(outputSettings: PBXOutputSettings) { self.outputSettings = outputSettings referenceGenerator = ReferenceGenerator(outputSettings: outputSettings) } // swiftlint:disable function_body_length func encode(proj: PBXProj) throws -> String { try referenceGenerator.generateReferences(proj: proj) guard let rootObject = proj.rootObjectReference else { throw PBXProjEncoderError.emptyProjectReference } sort(buildPhases: proj.objects.copyFilesBuildPhases, outputSettings: outputSettings) sort(buildPhases: proj.objects.frameworksBuildPhases, outputSettings: outputSettings) sort(buildPhases: proj.objects.headersBuildPhases, outputSettings: outputSettings) sort(buildPhases: proj.objects.resourcesBuildPhases, outputSettings: outputSettings) sort(buildPhases: proj.objects.sourcesBuildPhases, outputSettings: outputSettings) sort(navigatorGroups: proj.objects.groups, outputSettings: outputSettings) var output = [String]() var stateHolder = StateHolder() writeUtf8(to: &output) writeNewLine(stateHolder: &stateHolder, to: &output) writeDictionaryStart(stateHolder: &stateHolder, to: &output) write(dictionaryKey: "archiveVersion", dictionaryValue: .string(CommentedString("\(proj.archiveVersion)")), stateHolder: &stateHolder, to: &output) write(dictionaryKey: "classes", dictionaryValue: .dictionary([:]), stateHolder: &stateHolder, to: &output) write(dictionaryKey: "objectVersion", dictionaryValue: .string(CommentedString("\(proj.objectVersion)")), stateHolder: &stateHolder, to: &output) writeIndent(stateHolder: &stateHolder, to: &output) write(string: "objects = {", to: &output) stateHolder.increaseIndent() writeNewLine(stateHolder: &stateHolder, to: &output) try write(section: "PBXAggregateTarget", proj: proj, objects: proj.objects.aggregateTargets, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXBuildFile", proj: proj, objects: proj.objects.buildPhaseFile, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXBuildRule", proj: proj, objects: proj.objects.buildRules, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXContainerItemProxy", proj: proj, objects: proj.objects.containerItemProxies, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXCopyFilesBuildPhase", proj: proj, objects: proj.objects.copyFilesBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXFileReference", proj: proj, objects: proj.objects.fileReferences, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXFrameworksBuildPhase", proj: proj, objects: proj.objects.frameworksBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXGroup", proj: proj, objects: proj.objects.groups, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXHeadersBuildPhase", proj: proj, objects: proj.objects.headersBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXLegacyTarget", proj: proj, objects: proj.objects.legacyTargets, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXNativeTarget", proj: proj, objects: proj.objects.nativeTargets, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXProject", proj: proj, objects: proj.objects.projects, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXReferenceProxy", proj: proj, objects: proj.objects.referenceProxies, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXResourcesBuildPhase", proj: proj, objects: proj.objects.resourcesBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXRezBuildPhase", proj: proj, objects: proj.objects.carbonResourcesBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXShellScriptBuildPhase", proj: proj, objects: proj.objects.shellScriptBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXSourcesBuildPhase", proj: proj, objects: proj.objects.sourcesBuildPhases, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXTargetDependency", proj: proj, objects: proj.objects.targetDependencies, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "PBXVariantGroup", proj: proj, objects: proj.objects.variantGroups, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "XCBuildConfiguration", proj: proj, objects: proj.objects.buildConfigurations, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "XCConfigurationList", proj: proj, objects: proj.objects.configurationLists, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) try write(section: "XCVersionGroup", proj: proj, objects: proj.objects.versionGroups, outputSettings: outputSettings, stateHolder: &stateHolder, to: &output) stateHolder.decreaseIndent() writeIndent(stateHolder: &stateHolder, to: &output) write(string: "};", to: &output) writeNewLine(stateHolder: &stateHolder, to: &output) write(dictionaryKey: "rootObject", dictionaryValue: .string( CommentedString( rootObject.value, comment: "Project object" ) ), stateHolder: &stateHolder, to: &output) writeDictionaryEnd(stateHolder: &stateHolder, to: &output) writeNewLine(stateHolder: &stateHolder, to: &output) // clear reference cache return output.joined() } // MARK: - Private private func writeUtf8(to output: inout [String]) { output.append("// !$*UTF8*$!") } private func writeNewLine(stateHolder: inout StateHolder, to output: inout [String]) { if stateHolder.multiline { output.append("\n") } else { output.append(" ") } } private func write(value: PlistValue, stateHolder: inout StateHolder, to output: inout [String]) { switch value { case let .array(array): write(array: array, stateHolder: &stateHolder, to: &output) case let .dictionary(dictionary): write(dictionary: dictionary, stateHolder: &stateHolder, to: &output) case let .string(commentedString): write(commentedString: commentedString, to: &output) } } private func write(commentedString: CommentedString, to output: inout [String]) { write(string: commentedString.validString, to: &output) if let comment = commentedString.comment { write(string: " ", to: &output) write(comment: comment, to: &output) } } private func write(string: String, to output: inout [String]) { output.append(string) } private func write(comment: String, to output: inout [String]) { output.append("/* \(comment) */") } private func write(section: String, proj: PBXProj, objects: [PBXObjectReference: T], outputSettings: PBXOutputSettings, stateHolder: inout StateHolder, to output: inout [String]) throws where T: PlistSerializable & Equatable { try write(section: section, proj: proj, objects: objects, sort: outputSettings.projFileListOrder.sort, stateHolder: &stateHolder, to: &output) } private func write(section: String, proj: PBXProj, objects: [PBXObjectReference: PBXBuildPhaseFile], outputSettings: PBXOutputSettings, stateHolder: inout StateHolder, to output: inout [String]) throws { try write(section: section, proj: proj, objects: objects, sort: outputSettings.projFileListOrder.sort, stateHolder: &stateHolder, to: &output) } private func write(section: String, proj: PBXProj, objects: [PBXObjectReference: PBXFileReference], outputSettings: PBXOutputSettings, stateHolder: inout StateHolder, to output: inout [String]) throws { try write(section: section, proj: proj, objects: objects, sort: outputSettings.projFileListOrder.sort, stateHolder: &stateHolder, to: &output) } final class PBXProjElement { let key: CommentedString let value: PlistValue let multiline: Bool init(key: CommentedString, value: PlistValue, multiline: Bool) { self.key = key self.value = value self.multiline = multiline } } private func write(section: String, proj: PBXProj, objects: [PBXObjectReference: T], sort: ((PBXObjectReference, T), (PBXObjectReference, T)) -> Bool, stateHolder: inout StateHolder, to output: inout [String]) throws where T: PlistSerializable & Equatable { if objects.isEmpty { return } writeNewLine(stateHolder: &stateHolder, to: &output) write(string: "/* Begin \(section) section */", to: &output) writeNewLine(stateHolder: &stateHolder, to: &output) let sorted = objects.sorted(by: sort) let elements: [PBXProjElement] = try sorted.map { key, value in let element = try value.plistKeyAndValue(proj: proj, reference: key.value) return PBXProjElement(key: element.key, value: element.value, multiline: value.multiline) } let elementsArray = NSArray(array: elements) let lock = NSRecursiveLock() var resultArray = [[String]](repeating: [], count: elementsArray.count) elementsArray.enumerateObjects(options: .concurrent) { arg, index, _ in // swiftlint:disable:next force_cast let element = arg as! PBXProjElement var array = [String]() var tmpStateHolder = StateHolder() write(dictionaryKey: element.key, dictionaryValue: element.value, multiline: element.multiline, stateHolder: &tmpStateHolder, to: &array) lock.whileLocked { resultArray[index] = array } } let joinedArray: [String] = resultArray.flatMap({ $0 }) // should check multiline output.append(contentsOf: joinedArray) write(string: "/* End \(section) section */", to: &output) writeNewLine(stateHolder: &stateHolder, to: &output) } private func write(dictionary: [CommentedString: PlistValue], newLines _: Bool = true, stateHolder: inout StateHolder, to output: inout [String]) { writeDictionaryStart(stateHolder: &stateHolder, to: &output) let sorted = dictionary.sorted(by: { (left, right) -> Bool in if left.key == "isa" { return true } else if right.key == "isa" { return false } else { return left.key.string < right.key.string } }) sorted.forEach({ write(dictionaryKey: $0.key, dictionaryValue: $0.value, multiline: stateHolder.multiline, stateHolder: &stateHolder, to: &output) }) writeDictionaryEnd(stateHolder: &stateHolder, to: &output) } private func write(dictionaryKey: CommentedString, dictionaryValue: PlistValue, multiline: Bool = true, stateHolder: inout StateHolder, to output: inout [String]) { writeIndent(stateHolder: &stateHolder, to: &output) let beforeMultiline = stateHolder.multiline stateHolder.multiline = multiline write(commentedString: dictionaryKey, to: &output) output.append(" = ") write(value: dictionaryValue, stateHolder: &stateHolder, to: &output) output.append(";") stateHolder.multiline = beforeMultiline writeNewLine(stateHolder: &stateHolder, to: &output) } private func writeDictionaryStart(stateHolder: inout StateHolder, to output: inout [String]) { output.append("{") if stateHolder.multiline { writeNewLine(stateHolder: &stateHolder, to: &output) } stateHolder.increaseIndent() } private func writeDictionaryEnd(stateHolder: inout StateHolder, to output: inout [String]) { stateHolder.decreaseIndent() writeIndent(stateHolder: &stateHolder, to: &output) output.append("}") } private func write(array: [PlistValue], stateHolder: inout StateHolder, to output: inout [String]) { writeArrayStart(stateHolder: &stateHolder, to: &output) array.forEach { write(arrayValue: $0, stateHolder: &stateHolder, to: &output) } writeArrayEnd(stateHolder: &stateHolder, to: &output) } private func write(arrayValue: PlistValue, stateHolder: inout StateHolder, to output: inout [String]) { writeIndent(stateHolder: &stateHolder, to: &output) write(value: arrayValue, stateHolder: &stateHolder, to: &output) output.append(",") writeNewLine(stateHolder: &stateHolder, to: &output) } private func writeArrayStart(stateHolder: inout StateHolder, to output: inout [String]) { output.append("(") if stateHolder.multiline { writeNewLine(stateHolder: &stateHolder, to: &output) } stateHolder.increaseIndent() } private func writeArrayEnd(stateHolder: inout StateHolder, to output: inout [String]) { stateHolder.decreaseIndent() writeIndent(stateHolder: &stateHolder, to: &output) output.append(")") } private func writeIndent(stateHolder: inout StateHolder, to output: inout [String]) { if stateHolder.multiline { output.append(String(repeating: "\t", count: Int(stateHolder.indent))) } } private func sort(buildPhases: [PBXObjectReference: PBXBuildPhase], outputSettings: PBXOutputSettings) { if let sort = outputSettings.projBuildPhaseFileOrder.sort { buildPhases.values.forEach { $0.files = $0.files.sorted(by: sort) } } } private func sort(navigatorGroups: [PBXObjectReference: PBXGroup], outputSettings: PBXOutputSettings) { if let sort = outputSettings.projNavigatorFileOrder.sort { navigatorGroups.values.forEach { $0.children = $0.children.sorted(by: sort) } } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Project/PBXProject.swift ================================================ import Foundation public final class PBXProject: PBXObject { // MARK: - Attributes /// Project name public var name: String /// Build configuration list reference. var buildConfigurationListReference: PBXObjectReference /// Build configuration list. public var buildConfigurationList: XCConfigurationList! { set { buildConfigurationListReference = newValue.reference } get { return buildConfigurationListReference.getObject() } } /// A string representation of the XcodeCompatibilityVersion. public var compatibilityVersion: String /// The region of development. public var developmentRegion: String? /// Whether file encodings have been scanned. public var hasScannedForEncodings: Int /// The known regions for localized files. public var knownRegions: [String] /// The object is a reference to a PBXGroup element. var mainGroupReference: PBXObjectReference /// Project main group. public var mainGroup: PBXGroup! { set { mainGroupReference = newValue.reference } get { return mainGroupReference.getObject() } } /// The object is a reference to a PBXGroup element. var productsGroupReference: PBXObjectReference? /// Products group. public var productsGroup: PBXGroup? { set { productsGroupReference = newValue?.reference } get { return productsGroupReference?.getObject() } } /// The relative path of the project. public var projectDirPath: String /// Project references. var projectReferences: [[String: PBXObjectReference]] /// Project projects. // { // ProductGroup = B900DB69213936CC004AEC3E /* Products group reference */; // ProjectRef = B900DB68213936CC004AEC3E /* Project file reference */; // }, public var projects: [[String: PBXFileElement]] { set { projectReferences = newValue.map { project in project.mapValues({ $0.reference }) } } get { return projectReferences.map { project in project.mapValues({ $0.getObject()! }) } } } private static let targetAttributesKey = "TargetAttributes" /// The relative root paths of the project. public var projectRoots: [String] /// The objects are a reference to a PBXTarget element. var targetReferences: [PBXObjectReference] /// Project targets. public var targets: [PBXTarget] { set { targetReferences = newValue.references() } get { return targetReferences.objects() } } /// Project attributes. /// Target attributes will be merged into this public var attributes: [String: Any] /// Target attribute references. var targetAttributeReferences: [PBXObjectReference: [String: Any]] /// Target attributes. public var targetAttributes: [PBXTarget: [String: Any]] { set { targetAttributeReferences = [:] newValue.forEach { targetAttributeReferences[$0.key.reference] = $0.value } } get { var attributes: [PBXTarget: [String: Any]] = [:] targetAttributeReferences.forEach { if let object: PBXTarget = $0.key.getObject() { attributes[object] = $0.value } } return attributes } } /// Sets the attributes for the given target. /// /// - Parameters: /// - attributes: attributes that will be set. /// - target: target. public func setTargetAttributes(_ attributes: [String: Any], target: PBXTarget) { targetAttributeReferences[target.reference] = attributes } /// Removes the attributes for the given target. /// /// - Parameter target: target whose attributes will be removed. public func removeTargetAttributes(target: PBXTarget) { targetAttributeReferences.removeValue(forKey: target.reference) } /// Removes the all the target attributes public func clearAllTargetAttributes() { targetAttributeReferences.removeAll() } /// Returns the attributes of a given target. /// /// - Parameter for: target whose attributes will be returned. /// - Returns: target attributes. public func attributes(for target: PBXTarget) -> [String: Any]? { return targetAttributeReferences[target.reference] } // MARK: - Init /// Initializes the project with its attributes /// /// - Parameters: /// - name: xcodeproj's name. /// - buildConfigurationList: project build configuration list. /// - compatibilityVersion: project compatibility version. /// - mainGroup: project main group. /// - developmentRegion: project has development region. /// - hasScannedForEncodings: project has scanned for encodings. /// - knownRegions: project known regions. /// - productsGroup: products group. /// - projectDirPath: project dir path. /// - projects: projects. /// - projectRoots: project roots. /// - targets: project targets. public init(name: String, buildConfigurationList: XCConfigurationList, compatibilityVersion: String, mainGroup: PBXGroup, developmentRegion: String? = nil, hasScannedForEncodings: Int = 0, knownRegions: [String] = [], productsGroup: PBXGroup? = nil, projectDirPath: String = "", projects: [[String: PBXFileElement]] = [], projectRoots: [String] = [], targets: [PBXTarget] = [], attributes: [String: Any] = [:], targetAttributes: [PBXTarget: [String: Any]] = [:]) { self.name = name buildConfigurationListReference = buildConfigurationList.reference self.compatibilityVersion = compatibilityVersion mainGroupReference = mainGroup.reference self.developmentRegion = developmentRegion self.hasScannedForEncodings = hasScannedForEncodings self.knownRegions = knownRegions productsGroupReference = productsGroup?.reference self.projectDirPath = projectDirPath projectReferences = projects.map({ project in project.mapValues({ $0.reference }) }) self.projectRoots = projectRoots targetReferences = targets.references() self.attributes = attributes targetAttributeReferences = [:] super.init() self.targetAttributes = targetAttributes } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case name case buildConfigurationList case compatibilityVersion case developmentRegion case hasScannedForEncodings case knownRegions case mainGroup case productRefGroup case projectDirPath case projectReferences case projectRoot case projectRoots case targets case attributes } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let referenceRepository = decoder.context.objectReferenceRepository let objects = decoder.context.objects name = (try container.decodeIfPresent(.name)) ?? "" let buildConfigurationListReference: String = try container.decode(.buildConfigurationList) self.buildConfigurationListReference = referenceRepository.getOrCreate(reference: buildConfigurationListReference, objects: objects) compatibilityVersion = try container.decode(.compatibilityVersion) developmentRegion = try container.decodeIfPresent(.developmentRegion) let hasScannedForEncodingsString: String? = try container.decodeIfPresent(.hasScannedForEncodings) hasScannedForEncodings = hasScannedForEncodingsString.flatMap({ Int($0) }) ?? 0 knownRegions = (try container.decodeIfPresent(.knownRegions)) ?? [] let mainGroupReference: String = try container.decode(.mainGroup) self.mainGroupReference = referenceRepository.getOrCreate(reference: mainGroupReference, objects: objects) if let productRefGroupReference: String = try container.decodeIfPresent(.productRefGroup) { productsGroupReference = referenceRepository.getOrCreate(reference: productRefGroupReference, objects: objects) } else { productsGroupReference = nil } projectDirPath = try container.decodeIfPresent(.projectDirPath) ?? "" let projectReferences: [[String: String]] = (try container.decodeIfPresent(.projectReferences)) ?? [] self.projectReferences = projectReferences.map({ references in references.mapValues({ referenceRepository.getOrCreate(reference: $0, objects: objects) }) }) if let projectRoots: [String] = try container.decodeIfPresent(.projectRoots) { self.projectRoots = projectRoots } else if let projectRoot: String = try container.decodeIfPresent(.projectRoot) { projectRoots = [projectRoot] } else { projectRoots = [] } let targetReferences: [String] = (try container.decodeIfPresent(.targets)) ?? [] self.targetReferences = targetReferences.map({ referenceRepository.getOrCreate(reference: $0, objects: objects) }) var attributes = (try container.decodeIfPresent([String: Any].self, forKey: .attributes) ?? [:]) var targetAttributeReferences: [PBXObjectReference: [String: Any]] = [:] if let targetAttributes = attributes[PBXProject.targetAttributesKey] as? [String: [String: Any]] { targetAttributes.forEach { targetAttributeReferences[referenceRepository.getOrCreate(reference: $0.key, objects: objects)] = $0.value } attributes[PBXProject.targetAttributesKey] = nil } self.attributes = attributes self.targetAttributeReferences = targetAttributeReferences try super.init(from: decoder) } } // MARK: - PlistSerializable extension PBXProject: PlistSerializable { // swiftlint:disable:next function_body_length func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXProject.isa)) let buildConfigurationListComment = "Build configuration list for PBXProject \"\(name)\"" let buildConfigurationListCommentedString = CommentedString(buildConfigurationListReference.value, comment: buildConfigurationListComment) dictionary["buildConfigurationList"] = .string(buildConfigurationListCommentedString) dictionary["compatibilityVersion"] = .string(CommentedString(compatibilityVersion)) if let developmentRegion = developmentRegion { dictionary["developmentRegion"] = .string(CommentedString(developmentRegion)) } dictionary["hasScannedForEncodings"] = .string(CommentedString("\(hasScannedForEncodings)")) if !knownRegions.isEmpty { dictionary["knownRegions"] = PlistValue.array(knownRegions .map { .string(CommentedString("\($0)")) }) } let mainGroupObject: PBXGroup? = mainGroupReference.getObject() dictionary["mainGroup"] = .string(CommentedString(mainGroupReference.value, comment: mainGroupObject?.fileName())) if let productsGroupReference = productsGroupReference { let productRefGroupObject: PBXGroup? = productsGroupReference.getObject() dictionary["productRefGroup"] = .string(CommentedString(productsGroupReference.value, comment: productRefGroupObject?.fileName())) } dictionary["projectDirPath"] = .string(CommentedString(projectDirPath)) if projectRoots.count > 1 { dictionary["projectRoots"] = projectRoots.plist() } else { dictionary["projectRoot"] = .string(CommentedString(projectRoots.first ?? "")) } if let projectReferences = try projectReferencesPlistValue(proj: proj) { dictionary["projectReferences"] = projectReferences } dictionary["targets"] = PlistValue.array(targetReferences .map { targetReference in let target: PBXTarget? = targetReference.getObject() return .string(CommentedString(targetReference.value, comment: target?.name)) }) var plistAttributes: [String: Any] = attributes if !targetAttributeReferences.isEmpty { // merge target attributes var plistTargetAttributes: [String: Any] = [:] for (reference, value) in targetAttributeReferences { plistTargetAttributes[reference.value] = value.mapValues { value in (value as? PBXObject)?.reference.value ?? value } } plistAttributes[PBXProject.targetAttributesKey] = plistTargetAttributes } dictionary["attributes"] = plistAttributes.plist() return (key: CommentedString(reference, comment: "Project object"), value: .dictionary(dictionary)) } private func projectReferencesPlistValue(proj _: PBXProj) throws -> PlistValue? { guard !projectReferences.isEmpty else { return nil } return .array(projectReferences.compactMap { reference in guard let productGroupReference = reference["ProductGroup"], let projectRef = reference["ProjectRef"] else { return nil } let producGroup: PBXGroup? = productGroupReference.getObject() let groupName = producGroup?.fileName() let project: PBXFileElement? = projectRef.getObject() let fileRefName = project?.fileName() return [ CommentedString("ProductGroup"): PlistValue.string(CommentedString(productGroupReference.value, comment: groupName)), CommentedString("ProjectRef"): PlistValue.string(CommentedString(projectRef.value, comment: fileRefName)), ] }) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Sourcery/Equality.generated.swift ================================================ // Generated using Sourcery 0.13.1 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import Foundation extension PBXAggregateTarget { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXAggregateTarget else { return false } return super.isEqual(to: rhs) } } extension PBXBuildFile { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXBuildFile else { return false } if fileReference != rhs.fileReference { return false } if !NSDictionary(dictionary: settings ?? [:]).isEqual(to: rhs.settings ?? [:]) { return false } return super.isEqual(to: rhs) } } extension PBXBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXBuildPhase else { return false } if buildActionMask != rhs.buildActionMask { return false } if fileReferences != rhs.fileReferences { return false } if inputFileListPaths != rhs.inputFileListPaths { return false } if outputFileListPaths != rhs.outputFileListPaths { return false } if runOnlyForDeploymentPostprocessing != rhs.runOnlyForDeploymentPostprocessing { return false } return super.isEqual(to: rhs) } } extension PBXBuildRule { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXBuildRule else { return false } if compilerSpec != rhs.compilerSpec { return false } if filePatterns != rhs.filePatterns { return false } if fileType != rhs.fileType { return false } if isEditable != rhs.isEditable { return false } if name != rhs.name { return false } if outputFiles != rhs.outputFiles { return false } if outputFilesCompilerFlags != rhs.outputFilesCompilerFlags { return false } if script != rhs.script { return false } return super.isEqual(to: rhs) } } extension PBXContainerItem { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXContainerItem else { return false } if comments != rhs.comments { return false } return super.isEqual(to: rhs) } } extension PBXContainerItemProxy { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXContainerItemProxy else { return false } if containerPortalReference != rhs.containerPortalReference { return false } if proxyType != rhs.proxyType { return false } if remoteGlobalIDReference != rhs.remoteGlobalIDReference { return false } if remoteInfo != rhs.remoteInfo { return false } return super.isEqual(to: rhs) } } extension PBXCopyFilesBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXCopyFilesBuildPhase else { return false } if dstPath != rhs.dstPath { return false } if dstSubfolderSpec != rhs.dstSubfolderSpec { return false } if name != rhs.name { return false } return super.isEqual(to: rhs) } } extension PBXFileElement { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXFileElement else { return false } if sourceTree != rhs.sourceTree { return false } if path != rhs.path { return false } if name != rhs.name { return false } if includeInIndex != rhs.includeInIndex { return false } if usesTabs != rhs.usesTabs { return false } if indentWidth != rhs.indentWidth { return false } if tabWidth != rhs.tabWidth { return false } if wrapsLines != rhs.wrapsLines { return false } return super.isEqual(to: rhs) } } extension PBXFileReference { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXFileReference else { return false } if fileEncoding != rhs.fileEncoding { return false } if explicitFileType != rhs.explicitFileType { return false } if lastKnownFileType != rhs.lastKnownFileType { return false } if lineEnding != rhs.lineEnding { return false } if languageSpecificationIdentifier != rhs.languageSpecificationIdentifier { return false } if xcLanguageSpecificationIdentifier != rhs.xcLanguageSpecificationIdentifier { return false } if plistStructureDefinitionIdentifier != rhs.plistStructureDefinitionIdentifier { return false } return super.isEqual(to: rhs) } } extension PBXFrameworksBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXFrameworksBuildPhase else { return false } return super.isEqual(to: rhs) } } extension PBXGroup { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXGroup else { return false } if childrenReferences != rhs.childrenReferences { return false } return super.isEqual(to: rhs) } } extension PBXHeadersBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXHeadersBuildPhase else { return false } return super.isEqual(to: rhs) } } extension PBXLegacyTarget { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXLegacyTarget else { return false } if buildToolPath != rhs.buildToolPath { return false } if buildArgumentsString != rhs.buildArgumentsString { return false } if passBuildSettingsInEnvironment != rhs.passBuildSettingsInEnvironment { return false } if buildWorkingDirectory != rhs.buildWorkingDirectory { return false } return super.isEqual(to: rhs) } } extension PBXNativeTarget { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXNativeTarget else { return false } if productInstallPath != rhs.productInstallPath { return false } return super.isEqual(to: rhs) } } extension PBXProject { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXProject else { return false } if name != rhs.name { return false } if buildConfigurationListReference != rhs.buildConfigurationListReference { return false } if compatibilityVersion != rhs.compatibilityVersion { return false } if developmentRegion != rhs.developmentRegion { return false } if hasScannedForEncodings != rhs.hasScannedForEncodings { return false } if knownRegions != rhs.knownRegions { return false } if mainGroupReference != rhs.mainGroupReference { return false } if productsGroupReference != rhs.productsGroupReference { return false } if projectDirPath != rhs.projectDirPath { return false } if projectReferences != rhs.projectReferences { return false } if projectRoots != rhs.projectRoots { return false } if targetReferences != rhs.targetReferences { return false } if !NSDictionary(dictionary: attributes).isEqual(to: rhs.attributes) { return false } if !NSDictionary(dictionary: targetAttributeReferences).isEqual(to: rhs.targetAttributeReferences) { return false } return super.isEqual(to: rhs) } } extension PBXReferenceProxy { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXReferenceProxy else { return false } if fileType != rhs.fileType { return false } if path != rhs.path { return false } if remoteReference != rhs.remoteReference { return false } if sourceTree != rhs.sourceTree { return false } return super.isEqual(to: rhs) } } extension PBXResourcesBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXResourcesBuildPhase else { return false } return super.isEqual(to: rhs) } } extension PBXRezBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXRezBuildPhase else { return false } return super.isEqual(to: rhs) } } extension PBXShellScriptBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXShellScriptBuildPhase else { return false } if name != rhs.name { return false } if inputPaths != rhs.inputPaths { return false } if outputPaths != rhs.outputPaths { return false } if shellPath != rhs.shellPath { return false } if shellScript != rhs.shellScript { return false } if showEnvVarsInLog != rhs.showEnvVarsInLog { return false } return super.isEqual(to: rhs) } } extension PBXSourcesBuildPhase { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXSourcesBuildPhase else { return false } return super.isEqual(to: rhs) } } extension PBXTarget { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXTarget else { return false } if buildConfigurationListReference != rhs.buildConfigurationListReference { return false } if buildPhaseReferences != rhs.buildPhaseReferences { return false } if buildRuleReferences != rhs.buildRuleReferences { return false } if dependencyReferences != rhs.dependencyReferences { return false } if name != rhs.name { return false } if productName != rhs.productName { return false } if productReference != rhs.productReference { return false } if productType != rhs.productType { return false } return super.isEqual(to: rhs) } } extension PBXTargetDependency { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXTargetDependency else { return false } if name != rhs.name { return false } if targetReference != rhs.targetReference { return false } if targetProxyReference != rhs.targetProxyReference { return false } return super.isEqual(to: rhs) } } extension PBXVariantGroup { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? PBXVariantGroup else { return false } return super.isEqual(to: rhs) } } extension XCBuildConfiguration { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? XCBuildConfiguration else { return false } if baseConfigurationReference != rhs.baseConfigurationReference { return false } if !NSDictionary(dictionary: buildSettings).isEqual(to: rhs.buildSettings) { return false } if name != rhs.name { return false } return super.isEqual(to: rhs) } } extension XCConfigurationList { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? XCConfigurationList else { return false } if buildConfigurationReferences != rhs.buildConfigurationReferences { return false } if defaultConfigurationIsVisible != rhs.defaultConfigurationIsVisible { return false } if defaultConfigurationName != rhs.defaultConfigurationName { return false } return super.isEqual(to: rhs) } } extension XCVersionGroup { /// :nodoc: @objc public override func isEqual(to object: Any?) -> Bool { guard let rhs = object as? XCVersionGroup else { return false } if currentVersionReference != rhs.currentVersionReference { return false } if versionGroupType != rhs.versionGroupType { return false } return super.isEqual(to: rhs) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Sourcery/Sourcery.swift ================================================ import Foundation protocol AutoEquatable {} ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXAggregateTarget.swift ================================================ import Foundation /// This is the element for a build target that aggregates several others. public final class PBXAggregateTarget: PBXTarget {} // MARK: - PBXAggregateTarget Extension (PlistSerializable) extension PBXAggregateTarget: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { return try plistValues(proj: proj, isa: PBXAggregateTarget.isa, reference: reference) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXLegacyTarget.swift ================================================ import Foundation /// This is the element for a build target that according to Xcode is an "External Build System". You can use this target to run a script. public final class PBXLegacyTarget: PBXTarget { /// Path to the build tool that is invoked (required) public var buildToolPath: String? /// Build arguments to be passed to the build tool. public var buildArgumentsString: String? /// Whether or not to pass Xcode build settings as environment variables down to the tool when invoked public var passBuildSettingsInEnvironment: Bool /// The directory where the build tool will be invoked during a build public var buildWorkingDirectory: String? /// Initializes the legacy target with its attributes. /// /// - Parameters: /// - name: name. /// - buildToolPath: build tool path. /// - buildArgumentsString: build arguments. /// - passBuildSettingsInEnvironment: pass build settings in environment. /// - buildWorkingDirectory: build working directory. /// - buildConfigurationList: build configuration list. /// - buildPhases: build phases. /// - buildRules: build rules. /// - dependencies: dependencies. /// - productName: product name. /// - product: product file reference. /// - productType: product type. public init(name: String, buildToolPath: String? = nil, buildArgumentsString: String? = nil, passBuildSettingsInEnvironment: Bool = false, buildWorkingDirectory: String? = nil, buildConfigurationList: XCConfigurationList? = nil, buildPhases: [PBXBuildPhase] = [], buildRules: [PBXBuildRule] = [], dependencies: [PBXTargetDependency] = [], productName: String? = nil, product: PBXFileReference? = nil, productType: PBXProductType? = nil) { self.buildToolPath = buildToolPath self.buildArgumentsString = buildArgumentsString self.passBuildSettingsInEnvironment = passBuildSettingsInEnvironment self.buildWorkingDirectory = buildWorkingDirectory super.init(name: name, buildConfigurationList: buildConfigurationList, buildPhases: buildPhases, buildRules: buildRules, dependencies: dependencies, productName: productName, product: product, productType: productType) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case buildToolPath case buildArgumentsString case passBuildSettingsInEnvironment case buildWorkingDirectory } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) buildToolPath = try container.decodeIfPresent(.buildToolPath) buildArgumentsString = try container.decodeIfPresent(.buildArgumentsString) passBuildSettingsInEnvironment = try container.decodeIntBool(.passBuildSettingsInEnvironment) buildWorkingDirectory = try container.decodeIfPresent(.buildWorkingDirectory) try super.init(from: decoder) } override func plistValues(proj: PBXProj, isa _: String, reference: String) throws -> (key: CommentedString, value: PlistValue) { let (key, value) = try super.plistValues(proj: proj, isa: PBXLegacyTarget.isa, reference: reference) var dict: [CommentedString: PlistValue]! switch value { case let .dictionary(dictValue): dict = dictValue if let buildToolPath = buildToolPath { dict["buildToolPath"] = PlistValue.string(CommentedString(buildToolPath)) } if let buildArgumentsString = buildArgumentsString { dict["buildArgumentsString"] = PlistValue.string(CommentedString(buildArgumentsString)) } dict["passBuildSettingsInEnvironment"] = PlistValue.string(CommentedString(passBuildSettingsInEnvironment.int.description)) if let buildWorkingDirectory = buildWorkingDirectory { dict["buildWorkingDirectory"] = PlistValue.string(CommentedString(buildWorkingDirectory)) } default: throw XcodeprojWritingError.invalidType(class: String(describing: type(of: self)), expected: "Dictionary") } return (key: key, value: .dictionary(dict)) } } // MARK: - PBXNativeTarget Extension (PlistSerializable) extension PBXLegacyTarget: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { return try plistValues(proj: proj, isa: PBXLegacyTarget.isa, reference: reference) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXNativeTarget.swift ================================================ import Foundation /// This is the element for a build target that produces a binary content (application or library). public final class PBXNativeTarget: PBXTarget { // Target product install path. public var productInstallPath: String? /// Initializes the native target with its attributes. /// /// - Parameters: /// - name: target name. /// - buildConfigurationList: build configuratino list. /// - buildPhases: build phases. /// - buildRules: build rules. /// - dependencies: dependencies. /// - productInstallPath: product install path. /// - productName: product name. /// - product: product file reference. /// - productType: product type. public init(name: String, buildConfigurationList: XCConfigurationList? = nil, buildPhases: [PBXBuildPhase] = [], buildRules: [PBXBuildRule] = [], dependencies: [PBXTargetDependency] = [], productInstallPath: String? = nil, productName: String? = nil, product: PBXFileReference? = nil, productType: PBXProductType? = nil) { self.productInstallPath = productInstallPath super.init(name: name, buildConfigurationList: buildConfigurationList, buildPhases: buildPhases, buildRules: buildRules, dependencies: dependencies, productName: productName, product: product, productType: productType) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case productInstallPath } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) productInstallPath = try container.decodeIfPresent(.productInstallPath) try super.init(from: decoder) } override func plistValues(proj: PBXProj, isa: String, reference: String) throws -> (key: CommentedString, value: PlistValue) { let (key, value) = try super.plistValues(proj: proj, isa: isa, reference: reference) guard case var PlistValue.dictionary(dict) = value else { throw XcodeprojWritingError.invalidType(class: String(describing: type(of: self)), expected: "Dictionary") } if let productInstallPath = productInstallPath { dict["productInstallPath"] = .string(CommentedString(productInstallPath)) } return (key: key, value: .dictionary(dict)) } } // MARK: - PBXNativeTarget Extension (PlistSerializable) extension PBXNativeTarget: PlistSerializable { func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { return try plistValues(proj: proj, isa: PBXNativeTarget.isa, reference: reference) } } // MARK: - Helpers public extension PBXNativeTarget { /// Adds a dependency to the target. /// /// - Parameter target: dependency target. /// - Returns: target dependency reference. /// - Throws: an error if the dependency cannot be created. func addDependency(target: PBXTarget) throws -> PBXTargetDependency? { let objects = try target.objects() guard let project = objects.projects.first?.value else { return nil } let proxy = PBXContainerItemProxy(containerPortal: project, remoteGlobalID: target, proxyType: .nativeTarget, remoteInfo: target.name) objects.add(object: proxy) let targetDependency = PBXTargetDependency(name: target.name, target: target, targetProxy: proxy) objects.add(object: targetDependency) dependencies.append(targetDependency) return targetDependency } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXProductType.swift ================================================ import Foundation public enum PBXProductType: String, Decodable { case none = "" case application = "com.apple.product-type.application" case framework = "com.apple.product-type.framework" case dynamicLibrary = "com.apple.product-type.library.dynamic" case staticLibrary = "com.apple.product-type.library.static" case bundle = "com.apple.product-type.bundle" case unitTestBundle = "com.apple.product-type.bundle.unit-test" case uiTestBundle = "com.apple.product-type.bundle.ui-testing" case appExtension = "com.apple.product-type.app-extension" case commandLineTool = "com.apple.product-type.tool" case watchApp = "com.apple.product-type.application.watchapp" case watch2App = "com.apple.product-type.application.watchapp2" case watchExtension = "com.apple.product-type.watchkit-extension" case watch2Extension = "com.apple.product-type.watchkit2-extension" case tvExtension = "com.apple.product-type.tv-app-extension" case messagesApplication = "com.apple.product-type.application.messages" case messagesExtension = "com.apple.product-type.app-extension.messages" case stickerPack = "com.apple.product-type.app-extension.messages-sticker-pack" case xpcService = "com.apple.product-type.xpc-service" case ocUnitTestBundle = "com.apple.product-type.bundle.ocunit-test" case xcodeExtension = "com.apple.product-type.xcode-extension" case instrumentsPackage = "com.apple.product-type.instruments-package" case intentsServiceExtension = "com.apple.product-type.app-extension.intents-service" /// Returns the file extension for the given product type. public var fileExtension: String? { switch self { case .application, .watchApp, .watch2App, .messagesApplication: return "app" case .framework: return "framework" case .dynamicLibrary: return "dylib" case .staticLibrary: return "a" case .bundle: return "bundle" case .unitTestBundle, .uiTestBundle: return "xctest" case .appExtension, .tvExtension, .watchExtension, .watch2Extension, .messagesExtension, .stickerPack, .xcodeExtension, .intentsServiceExtension: return "appex" case .commandLineTool: return nil case .xpcService: return "xpc" case .ocUnitTestBundle: return "octest" case .instrumentsPackage: return "instrpkg" case .none: return nil } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXReferenceProxy.swift ================================================ import Foundation /// A proxy for another object which might belong to another project /// contained in the same workspace of the document. /// This class is referenced by PBXTargetDependency. public final class PBXReferenceProxy: PBXFileElement { // MARK: - Attributes /// Element file type public var fileType: String? /// Element remote reference. var remoteReference: PBXObjectReference? /// Element remote. public var remote: PBXContainerItemProxy? { get { return remoteReference?.getObject() } set { remoteReference = newValue?.reference } } // MARK: - Init /// Initializes the reference proxy. /// /// - Parameters: /// - fileType: File type. /// - path: Path. /// - remote: Remote. /// - sourceTree: Source tree. public init(fileType: String? = nil, path: String? = nil, name: String? = nil, remote: PBXContainerItemProxy? = nil, sourceTree: PBXSourceTree? = nil) { self.fileType = fileType remoteReference = remote?.reference super.init(sourceTree: sourceTree, path: path, name: name) } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case fileType case remoteRef } public required init(from decoder: Decoder) throws { let objectReferenceRepository = decoder.context.objectReferenceRepository let objects = decoder.context.objects let container = try decoder.container(keyedBy: CodingKeys.self) if let remoteRefString: String = try container.decodeIfPresent(.remoteRef) { remoteReference = objectReferenceRepository.getOrCreate(reference: remoteRefString, objects: objects) } fileType = try container.decodeIfPresent(.fileType) try super.init(from: decoder) } override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { guard case var .dictionary(dictionary) = try super.plistKeyAndValue(proj: proj, reference: reference).value else { fatalError("super implementation changed and we didn’t realise!") } dictionary["isa"] = .string(CommentedString(PBXReferenceProxy.isa)) if let fileType = fileType { dictionary["fileType"] = .string(CommentedString(fileType)) } if let remoteReference = remoteReference { dictionary["remoteRef"] = .string(CommentedString(remoteReference.value, comment: "PBXContainerItemProxy")) } return (key: CommentedString(reference, comment: path), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXTarget.swift ================================================ import Foundation /// This element is an abstract parent for specialized targets. public class PBXTarget: PBXContainerItem { /// Target build configuration list. var buildConfigurationListReference: PBXObjectReference? /// Build configuration list. public var buildConfigurationList: XCConfigurationList? { get { return buildConfigurationListReference?.getObject() } set { buildConfigurationListReference = newValue?.reference } } /// Target build phase references. var buildPhaseReferences: [PBXObjectReference] /// Target build phases. public var buildPhases: [PBXBuildPhase] { get { return buildPhaseReferences.objects() } set { buildPhaseReferences = newValue.references() } } /// Target build rule references. var buildRuleReferences: [PBXObjectReference] /// Target build rules. public var buildRules: [PBXBuildRule] { get { return buildRuleReferences.objects() } set { buildRuleReferences = newValue.references() } } /// Target dependency references. var dependencyReferences: [PBXObjectReference] /// Target dependencies. public var dependencies: [PBXTargetDependency] { get { return dependencyReferences.objects() } set { dependencyReferences = newValue.references() } } /// Target name. public var name: String /// Target product name. public var productName: String? /// Target product reference. var productReference: PBXObjectReference? /// Target product. public var product: PBXFileReference? { get { return productReference?.getObject() } set { productReference = newValue?.reference } } /// Target product type. public var productType: PBXProductType? /// Initializes the target with dependencies as objects. /// /// - Parameters: /// - name: Target name. /// - buildConfigurationList: Target configuration list. /// - buildPhases: Target build phases. /// - buildRules: Target build rules. /// - dependencies: Target dependencies. /// - productName: Target product name. /// - product: Target product. /// - productType: Target product type. public init(name: String, buildConfigurationList: XCConfigurationList? = nil, buildPhases: [PBXBuildPhase] = [], buildRules: [PBXBuildRule] = [], dependencies: [PBXTargetDependency] = [], productName: String? = nil, product: PBXFileReference? = nil, productType: PBXProductType? = nil) { buildConfigurationListReference = buildConfigurationList?.reference buildPhaseReferences = buildPhases.references() buildRuleReferences = buildRules.references() dependencyReferences = dependencies.references() self.name = name self.productName = productName productReference = product?.reference self.productType = productType super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case buildConfigurationList case buildPhases case buildRules case dependencies case name case productName case productReference case productType } public required init(from decoder: Decoder) throws { let objectReferenceRepository = decoder.context.objectReferenceRepository let objects = decoder.context.objects let container = try decoder.container(keyedBy: CodingKeys.self) name = try container.decode(.name) if let buildConfigurationListReference: String = try container.decodeIfPresent(.buildConfigurationList) { self.buildConfigurationListReference = objectReferenceRepository.getOrCreate(reference: buildConfigurationListReference, objects: objects) } else { buildConfigurationListReference = nil } let buildPhaseReferences: [String] = try container.decodeIfPresent(.buildPhases) ?? [] self.buildPhaseReferences = buildPhaseReferences.map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) let buildRuleReferences: [String] = try container.decodeIfPresent(.buildRules) ?? [] self.buildRuleReferences = buildRuleReferences.map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) let dependencyReferences: [String] = try container.decodeIfPresent(.dependencies) ?? [] self.dependencyReferences = dependencyReferences.map({ objectReferenceRepository.getOrCreate(reference: $0, objects: objects) }) productName = try container.decodeIfPresent(.productName) if let productReferenceString: String = try container.decodeIfPresent(.productReference) { productReference = objectReferenceRepository.getOrCreate(reference: productReferenceString, objects: objects) } else { productReference = nil } productType = try container.decodeIfPresent(.productType) try super.init(from: decoder) } func plistValues(proj: PBXProj, isa: String, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary = try super.plistValues(proj: proj, reference: reference) dictionary["isa"] = .string(CommentedString(isa)) let buildConfigurationListComment = "Build configuration list for \(isa) \"\(name)\"" if let buildConfigurationListReference = buildConfigurationListReference { dictionary["buildConfigurationList"] = .string(CommentedString(buildConfigurationListReference.value, comment: buildConfigurationListComment)) } dictionary["buildPhases"] = .array(buildPhaseReferences .map { (buildPhaseReference: PBXObjectReference) in let buildPhase: PBXBuildPhase? = buildPhaseReference.getObject() return .string(CommentedString(buildPhaseReference.value, comment: buildPhase?.name())) }) // Xcode doesn't write PBXAggregateTarget buildRules or empty PBXLegacyTarget buildRules if !(self is PBXAggregateTarget), !(self is PBXLegacyTarget) || !buildRuleReferences.isEmpty { dictionary["buildRules"] = .array(buildRuleReferences.map { .string(CommentedString($0.value, comment: PBXBuildRule.isa)) }) } dictionary["dependencies"] = .array(dependencyReferences.map { .string(CommentedString($0.value, comment: PBXTargetDependency.isa)) }) dictionary["name"] = .string(CommentedString(name)) if let productName = productName { dictionary["productName"] = .string(CommentedString(productName)) } if let productType = productType { dictionary["productType"] = .string(CommentedString(productType.rawValue)) } if let productReference = productReference { let fileElement: PBXFileElement? = productReference.getObject() dictionary["productReference"] = .string(CommentedString(productReference.value, comment: fileElement?.fileName())) } return (key: CommentedString(reference, comment: name), value: .dictionary(dictionary)) } } // MARK: - Helpers public extension PBXTarget { /// Returns the product name with the extension joined with a period. /// /// - Returns: product name with extension. func productNameWithExtension() -> String? { guard let productName = self.productName else { return nil } guard let fileExtension = self.productType?.fileExtension else { return nil } return "\(productName).\(fileExtension)" } /// Returns the sources build phase. /// /// - Returns: sources build phase. /// - Throws: an error if the build phase cannot be obtained. func sourcesBuildPhase() throws -> PBXSourcesBuildPhase? { return try buildPhaseReferences .compactMap({ try $0.getThrowingObject() as? PBXBuildPhase }) .filter({ $0.buildPhase == .sources }) .compactMap { $0 as? PBXSourcesBuildPhase } .first } /// Returns the resources build phase. /// /// - Returns: sources build phase. /// - Throws: an error if the build phase cannot be obtained. func resourcesBuildPhase() throws -> PBXResourcesBuildPhase? { return try buildPhaseReferences .compactMap({ try $0.getThrowingObject() as? PBXResourcesBuildPhase }) .filter({ $0.buildPhase == .resources }) .first } /// Returns the target source files. /// /// - Returns: source files. /// - Throws: an error if something goes wrong. func sourceFiles() throws -> [PBXFileElement] { return try sourcesBuildPhase()?.fileReferences .compactMap { try $0.getThrowingObject() as? PBXBuildFile } .filter { $0.fileReference != nil } .compactMap { try $0.fileReference!.getThrowingObject() as? PBXFileElement } ?? [] } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Objects/Targets/PBXTargetDependency.swift ================================================ import Foundation /// This is the element for referencing other targets through content proxies. public final class PBXTargetDependency: PBXObject { // MARK: - Attributes /// Target name. public var name: String? /// Target reference. var targetReference: PBXObjectReference? /// Target. public var target: PBXTarget? { get { return targetReference?.getObject() } set { targetReference = newValue?.reference } } /// Target proxy reference. var targetProxyReference: PBXObjectReference? /// Target proxy. public var targetProxy: PBXContainerItemProxy? { get { return targetProxyReference?.getObject() } set { targetProxyReference = newValue?.reference } } // MARK: - Init /// Initializes the target dependency with dependencies as objects. /// /// - Parameters: /// - name: Dependency name. /// - target: Target. /// - targetProxy: Target proxy. public init(name: String? = nil, target: PBXTarget? = nil, targetProxy: PBXContainerItemProxy? = nil) { self.name = name targetReference = target?.reference targetProxyReference = targetProxy?.reference super.init() } // MARK: - Decodable fileprivate enum CodingKeys: String, CodingKey { case name case target case targetProxy } public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let referenceRepository = decoder.context.objectReferenceRepository let objects = decoder.context.objects name = try container.decodeIfPresent(.name) if let targetReference: String = try container.decodeIfPresent(.target) { self.targetReference = referenceRepository.getOrCreate(reference: targetReference, objects: objects) } if let targetProxyReference: String = try container.decodeIfPresent(.targetProxy) { self.targetProxyReference = referenceRepository.getOrCreate(reference: targetProxyReference, objects: objects) } try super.init(from: decoder) } } // MARK: - PlistSerializable extension PBXTargetDependency: PlistSerializable { func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) { var dictionary: [CommentedString: PlistValue] = [:] dictionary["isa"] = .string(CommentedString(PBXTargetDependency.isa)) if let name = name { dictionary["name"] = .string(CommentedString(name)) } if let targetReference = targetReference { let targetObject: PBXTarget? = targetReference.getObject() dictionary["target"] = .string(CommentedString(targetReference.value, comment: targetObject?.name)) } if let targetProxyReference = targetProxyReference { dictionary["targetProxy"] = .string(CommentedString(targetProxyReference.value, comment: "PBXContainerItemProxy")) } return (key: CommentedString(reference, comment: "PBXTargetDependency"), value: .dictionary(dictionary)) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Project/WorkspaceSettings.swift ================================================ import Foundation import PathKit public enum WorkspaceSettingsError: Error { /// thrown when the settings file was not found. case notFound(path: Path) } /// It represents the WorkspaceSettings.xcsettings file under a workspace data directory. public class WorkspaceSettings: Codable, Equatable, Writable { public enum BuildSystem: String { /// Original build system case original = "Original" /// New build system case new } /// Workspace build system. public var buildSystem: BuildSystem /// Decodable coding keys. /// /// - buildSystem: Build system. enum CodingKeys: String, CodingKey { case buildSystem = "BuildSystemType" } /// Initializes the settings with its attributes. /// /// - Parameter buildSystem: Workspace build system. init(buildSystem: BuildSystem = .new) { self.buildSystem = buildSystem } /// Initializes the settings decoding the values from the plist representation. /// /// - Parameter decoder: Propertly list decoder. /// - Throws: An error if required attributes are missing or have a wrong type. public required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let buildSystemString: String = try container.decodeIfPresent(.buildSystem), let buildSystem = BuildSystem(rawValue: buildSystemString) { self.buildSystem = buildSystem } else { buildSystem = .new } } /// Encodes the settings into the given encoder. /// /// - Parameter encoder: Encoder where the settings will be encoded into. /// - Throws: An error if the settings can't be encoded. public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if buildSystem == .original { try container.encode(buildSystem.rawValue, forKey: .buildSystem) } } /// Initializes the settings reading the values from the WorkspaceSettings.xcsettings file. /// /// - Parameter path: Path to the WorkspaceSettings.xcsettings /// - Returns: The initialized workspace settings. /// - Throws: An error if the file doesn't exist or has an invalid format. public static func at(path: Path) throws -> WorkspaceSettings { if !path.exists { throw WorkspaceSettingsError.notFound(path: path) } let data = try Data(contentsOf: path.url) let plistDecoder = PropertyListDecoder() return try plistDecoder.decode(WorkspaceSettings.self, from: data) } /// Compares two instances of WorkspaceSettings and retrus true if the two instances are equal. /// /// - Parameters: /// - lhs: First instance to be compared. /// - rhs: Second instance to be compared. /// - Returns: True if the two instances are the same. public static func == (lhs: WorkspaceSettings, rhs: WorkspaceSettings) -> Bool { return lhs.buildSystem == rhs.buildSystem } /// Writes the workspace settings. /// /// - Parameter path: The path to write to /// - Parameter override: True if the content should be overriden if it already exists. /// - Throws: writing error if something goes wrong. public func write(path: Path, override: Bool) throws { let encoder = PropertyListEncoder() let data = try encoder.encode(self) if override, path.exists { try path.delete() } try path.write(data) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Project/XCBreakpointList.swift ================================================ import AEXML import Foundation import PathKit // swiftlint:disable:next type_body_length public final class XCBreakpointList: Equatable, Writable { // MARK: - Breakpoint Proxy // swiftlint:disable type_body_length public final class BreakpointProxy: Equatable { // MARK: - Breakpoint Content public final class BreakpointContent: Equatable { // MARK: - Breakpoint Action Proxy public final class BreakpointActionProxy: Equatable { // MARK: - Breakpoint Action Content public final class ActionContent: Equatable { // MARK: - Attributes public var consoleCommand: String? public var message: String? public var conveyanceType: String? public var command: String? public var arguments: String? public var waitUntilDone: Bool? public var script: String? public var soundName: String? // MARK: - Init public init(consoleCommand: String? = nil, message: String? = nil, conveyanceType: String? = nil, command: String? = nil, arguments: String? = nil, waitUntilDone: Bool? = nil, script: String? = nil, soundName: String? = nil) { self.consoleCommand = consoleCommand self.message = message self.conveyanceType = conveyanceType self.command = command self.arguments = arguments self.waitUntilDone = waitUntilDone self.script = script self.soundName = soundName } init(element: AEXMLElement) throws { consoleCommand = element.attributes["consoleCommand"] message = element.attributes["message"] conveyanceType = element.attributes["conveyanceType"] command = element.attributes["command"] arguments = element.attributes["arguments"] if let waitUntilDoneString = element.attributes["waitUntilDone"] { waitUntilDone = waitUntilDoneString == "YES" } script = element.attributes["script"] soundName = element.attributes["soundName"] } // MARK: - XML fileprivate func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["consoleCommand"] = consoleCommand attributes["message"] = message attributes["conveyanceType"] = conveyanceType attributes["command"] = command attributes["arguments"] = arguments if let waitUntilDone = waitUntilDone { attributes["waitUntilDone"] = waitUntilDone ? "YES" : "NO" } attributes["script"] = script attributes["soundName"] = soundName let element = AEXMLElement(name: "ActionContent", value: nil, attributes: attributes) return element } // MARK: - Equatable public static func == (lhs: ActionContent, rhs: ActionContent) -> Bool { return lhs.consoleCommand == rhs.consoleCommand && lhs.message == rhs.message && lhs.conveyanceType == rhs.conveyanceType && lhs.command == rhs.command && lhs.arguments == rhs.arguments && lhs.waitUntilDone == rhs.waitUntilDone && lhs.script == rhs.script && lhs.soundName == rhs.soundName } } // MARK: - Breakpoint Action Extension ID public enum ActionExtensionID: String { case debuggerCommand = "Xcode.BreakpointAction.DebuggerCommand" case log = "Xcode.BreakpointAction.Log" case shellCommand = "Xcode.BreakpointAction.ShellCommand" case graphicsTrace = "Xcode.BreakpointAction.GraphicsTrace" case appleScript = "Xcode.BreakpointAction.AppleScript" case sound = "Xcode.BreakpointAction.Sound" case openGLError = "Xcode.BreakpointAction.OpenGLError" } // MARK: - Attributes public var actionExtensionID: ActionExtensionID public var actionContent: ActionContent // MARK: - Init public init(actionExtensionID: ActionExtensionID, actionContent: ActionContent) { self.actionExtensionID = actionExtensionID self.actionContent = actionContent } init(element: AEXMLElement) throws { guard let actionExtensionIDString = element.attributes["ActionExtensionID"], let actionExtensionID = ActionExtensionID(rawValue: actionExtensionIDString) else { throw XCBreakpointListError.missing(property: "ActionExtensionID") } self.actionExtensionID = actionExtensionID actionContent = try ActionContent(element: element["ActionContent"]) } // MARK: - XML fileprivate func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "BreakpointActionProxy", value: nil, attributes: ["ActionExtensionID": actionExtensionID.rawValue]) element.addChild(actionContent.xmlElement()) return element } // MARK: - Equatable public static func == (lhs: BreakpointActionProxy, rhs: BreakpointActionProxy) -> Bool { return lhs.actionExtensionID == rhs.actionExtensionID && lhs.actionContent == rhs.actionContent } } // MARK: - Breakpoint Location Proxy public final class BreakpointLocationProxy: Equatable { public init() {} init(element _: AEXMLElement) throws {} fileprivate func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "BreakpointLocationProxy", value: nil, attributes: [:]) return element } public static func == (_: BreakpointLocationProxy, _: BreakpointLocationProxy) -> Bool { return true } } public static func == (lhs: BreakpointContent, rhs: BreakpointContent) -> Bool { return lhs.enabled == rhs.enabled && lhs.ignoreCount == rhs.ignoreCount && lhs.continueAfterRunningActions == rhs.continueAfterRunningActions && lhs.filePath == rhs.filePath && lhs.timestamp == rhs.timestamp && lhs.startingColumn == rhs.startingColumn && lhs.endingColumn == rhs.endingColumn && lhs.startingLine == rhs.startingLine && lhs.endingLine == rhs.endingLine && lhs.breakpointStackSelectionBehavior == rhs.breakpointStackSelectionBehavior && lhs.symbol == rhs.symbol && lhs.module == rhs.module && lhs.scope == rhs.scope && lhs.stopOnStyle == rhs.stopOnStyle && lhs.condition == rhs.condition && lhs.actions == rhs.actions && lhs.locations == rhs.locations } // MARK: - Attributes public var enabled: Bool public var ignoreCount: String public var continueAfterRunningActions: Bool public var filePath: String? public var timestamp: String? public var startingColumn: String? public var endingColumn: String? public var startingLine: String? public var endingLine: String? public var breakpointStackSelectionBehavior: String? public var symbol: String? public var module: String? public var scope: String? public var stopOnStyle: String? public var condition: String? public var actions: [BreakpointActionProxy] public var locations: [BreakpointLocationProxy] // MARK: - Init public init(enabled: Bool = true, ignoreCount: String = "0", continueAfterRunningActions: Bool = false, filePath: String? = nil, timestamp: String? = nil, startingColumn: String? = nil, endingColumn: String? = nil, startingLine: String? = nil, endingLine: String? = nil, breakpointStackSelectionBehavior: String? = nil, symbol: String? = nil, module: String? = nil, scope: String? = nil, stopOnStyle: String? = nil, condition: String? = nil, actions: [BreakpointActionProxy] = [], locations: [BreakpointLocationProxy] = []) { self.enabled = enabled self.ignoreCount = ignoreCount self.continueAfterRunningActions = continueAfterRunningActions self.filePath = filePath self.timestamp = timestamp self.startingColumn = startingColumn self.endingColumn = endingColumn self.startingLine = startingLine self.endingLine = endingLine self.breakpointStackSelectionBehavior = breakpointStackSelectionBehavior self.symbol = symbol self.module = module self.scope = scope self.stopOnStyle = stopOnStyle self.condition = condition self.actions = actions self.locations = locations } init(element: AEXMLElement) throws { enabled = element.attributes["shouldBeEnabled"] == "Yes" ignoreCount = element.attributes["ignoreCount"] ?? "0" continueAfterRunningActions = element.attributes["continueAfterRunningActions"] == "Yes" filePath = element.attributes["filePath"] timestamp = element.attributes["timestampString"] startingColumn = element.attributes["startingColumnNumber"] endingColumn = element.attributes["endingColumnNumber"] startingLine = element.attributes["startingLineNumber"] endingLine = element.attributes["endingLineNumber"] breakpointStackSelectionBehavior = element.attributes["breakpointStackSelectionBehavior"] symbol = element.attributes["symbolName"] module = element.attributes["moduleName"] scope = element.attributes["scope"] stopOnStyle = element.attributes["stopOnStyle"] condition = element.attributes["condition"] actions = try element["Actions"]["BreakpointActionProxy"] .all? .map(BreakpointActionProxy.init) ?? [] locations = try element["Locations"]["BreakpointLocationProxy"] .all? .map(BreakpointLocationProxy.init) ?? [] } // MARK: - XML fileprivate func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["shouldBeEnabled"] = enabled ? "Yes" : "No" attributes["ignoreCount"] = ignoreCount attributes["continueAfterRunningActions"] = continueAfterRunningActions ? "Yes" : "No" attributes["filePath"] = filePath attributes["timestampString"] = timestamp attributes["startingColumnNumber"] = startingColumn attributes["endingColumnNumber"] = endingColumn attributes["startingLineNumber"] = startingLine attributes["endingLineNumber"] = endingLine attributes["breakpointStackSelectionBehavior"] = breakpointStackSelectionBehavior attributes["symbolName"] = symbol attributes["moduleName"] = module attributes["scope"] = scope attributes["stopOnStyle"] = stopOnStyle attributes["condition"] = condition let element = AEXMLElement(name: "BreakpointContent", value: nil, attributes: attributes) let actions = AEXMLElement(name: "Actions", value: nil, attributes: [:]) self.actions.map({ $0.xmlElement() }).forEach({ actions.addChild($0) }) element.addChild(actions) let locations = AEXMLElement(name: "Locations", value: nil, attributes: [:]) self.locations.map({ $0.xmlElement() }).forEach({ locations.addChild($0) }) element.addChild(locations) return element } } // MARK: - Breakpoint Extension ID public enum BreakpointExtensionID: String { case file = "Xcode.Breakpoint.FileBreakpoint" case exception = "Xcode.Breakpoint.ExceptionBreakpoint" case swiftError = "Xcode.Breakpoint.SwiftErrorBreakpoint" case openGLError = "Xcode.Breakpoint.OpenGLErrorBreakpoint" case symbolic = "Xcode.Breakpoint.SymbolicBreakpoint" case ideConstraintError = "Xcode.Breakpoint.IDEConstraintErrorBreakpoint" case ideTestFailure = "Xcode.Breakpoint.IDETestFailureBreakpoint" } // MARK: - Attributes public var breakpointExtensionID: BreakpointExtensionID public var breakpointContent: BreakpointContent // MARK: - Init public init(breakpointExtensionID: BreakpointExtensionID, breakpointContent: BreakpointContent) { self.breakpointExtensionID = breakpointExtensionID self.breakpointContent = breakpointContent } init(element: AEXMLElement) throws { guard let breakpointExtensionIDString = element.attributes["BreakpointExtensionID"], let breakpointExtensionID = BreakpointExtensionID(rawValue: breakpointExtensionIDString) else { throw XCBreakpointListError.missing(property: "BreakpointExtensionID") } self.breakpointExtensionID = breakpointExtensionID breakpointContent = try BreakpointContent(element: element["BreakpointContent"]) } // MARK: - XML fileprivate func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "BreakpointProxy", value: nil, attributes: ["BreakpointExtensionID": breakpointExtensionID.rawValue]) element.addChild(breakpointContent.xmlElement()) return element } // MARK: - Equatable public static func == (lhs: BreakpointProxy, rhs: BreakpointProxy) -> Bool { return lhs.breakpointExtensionID == rhs.breakpointExtensionID && lhs.breakpointContent == rhs.breakpointContent } } // MARK: - Attributes public var breakpoints: [BreakpointProxy] public var type: String? public var version: String? // MARK: - Init /// Initializes the breakpoints reading the content from the disk. /// /// - Parameters: /// - path: breakpoints path. public init(path: Path) throws { if !path.exists { throw XCBreakpointListError.notFound(path: path) } let document = try AEXMLDocument(xml: try path.read()) let bucket = document["Bucket"] type = bucket.attributes["type"] version = bucket.attributes["version"] breakpoints = try bucket["Breakpoints"]["BreakpointProxy"] .all? .map(BreakpointProxy.init) ?? [] } public init(type: String? = nil, version: String? = nil, breakpoints: [BreakpointProxy] = []) { self.type = type self.version = version self.breakpoints = breakpoints } // MARK: - Helpers public func add(breakpointProxy: BreakpointProxy) -> XCBreakpointList { var breakpoints = self.breakpoints breakpoints.append(breakpointProxy) return XCBreakpointList(type: type, version: version, breakpoints: breakpoints) } // MARK: - Writable public func write(path: Path, override: Bool) throws { let document = AEXMLDocument() var schemeAttributes: [String: String] = [:] schemeAttributes["type"] = type schemeAttributes["version"] = version let bucket = document.addChild(name: "Bucket", value: nil, attributes: schemeAttributes) let breakpoints = AEXMLElement(name: "Breakpoints", value: nil, attributes: [:]) self.breakpoints.map({ $0.xmlElement() }).forEach({ breakpoints.addChild($0) }) bucket.addChild(breakpoints) if override, path.exists { try path.delete() } try path.write(document.xmlXcodeFormat) } // MARK: - Equatable public static func == (lhs: XCBreakpointList, rhs: XCBreakpointList) -> Bool { return lhs.breakpoints == rhs.breakpoints && lhs.type == rhs.type && lhs.version == rhs.version } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Project/XCSharedData.swift ================================================ import Foundation import PathKit public final class XCSharedData: Equatable { // MARK: - Attributes /// Shared data schemes. public var schemes: [XCScheme] /// Shared data breakpoints. public var breakpoints: XCBreakpointList? /// Workspace settings (represents the WorksapceSettings.xcsettings file). public var workspaceSettings: WorkspaceSettings? // MARK: - Init /// Initializes the shared data with its properties. /// /// - Parameters: /// - schemes: Shared data schemes. /// - breakpoints: Shared data breakpoints. /// - workspaceSettings: Workspace settings (represents the WorksapceSettings.xcsettings file). public init(schemes: [XCScheme], breakpoints: XCBreakpointList? = nil, workspaceSettings: WorkspaceSettings? = nil) { self.schemes = schemes self.breakpoints = breakpoints self.workspaceSettings = workspaceSettings } /// Initializes the XCSharedData reading the content from the disk. /// /// - Parameter path: path where the .xcshareddata is. public init(path: Path) throws { if !path.exists { throw XCSharedDataError.notFound(path: path) } schemes = path.glob("xcschemes/*.xcscheme") .compactMap { try? XCScheme(path: $0) } breakpoints = try? XCBreakpointList(path: path + "xcdebugger/Breakpoints_v2.xcbkptlist") let workspaceSettingsPath = path + "WorkspaceSettings.xcsettings" if workspaceSettingsPath.exists { workspaceSettings = try WorkspaceSettings.at(path: workspaceSettingsPath) } else { workspaceSettings = nil } } // MARK: - Equatable public static func == (lhs: XCSharedData, rhs: XCSharedData) -> Bool { return lhs.schemes == rhs.schemes && lhs.breakpoints == rhs.breakpoints && lhs.workspaceSettings == rhs.workspaceSettings } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Project/Xcode.swift ================================================ import Foundation /// Class that contains Xcode constants. public struct Xcode { /// Last known constants. public struct LastKnown { /// Last known SDKs. public struct SDK { /// Last known SDK for iOS. public static let ios: String = "12.0" /// Last known SDK for macOS. public static let macos: String = "10.14" /// Last known SDK for tvOS. public static let tvos: String = "12.0" /// Last known SDK for watchos. public static let watchos: String = "5.0" } /// Last known archive version for Xcodeproj. public static let archiveVersion: UInt = 1 /// Last known Swift version (stable). public static let swiftVersion = "4.2" /// Last known object version for Xcodeproj. public static let objectVersion: UInt = 51 /// Last known upgrade check. public static let upgradeCheck = "1000" /// Last known Swift upgrade check. public static let swiftUpgradeCheck = "1000" } /// Default values. public struct Default { /// The default object version for Xcodeproj. public static let objectVersion: UInt = 50 /// Default compatibility version. public static let compatibilityVersion: String = "Xcode 9.3" /// Default development region. public static let developmentRegion: String = "en" } /// Inherited keywords used in build settings. public static let inheritedKeywords = ["${inherited}", "$(inherited)"] /// Header files extensions. public static let headersExtensions = [".h", ".hh", ".hpp", ".ipp", ".tpp", ".hxx", ".def", ".inl", ".inc"] /// Supported values. public struct Supported { /// The version of `.xcscheme` files supported by Xcodeproj public static let xcschemeFormatVersion = "1.3" } /// Returns the Xcode file type for any given extension. /// /// - Parameter extension: file extension. /// - Returns: Xcode file type. public static func filetype(extension: String) -> String? { return [ "a": "archive.ar", "apns": "text", "app": "wrapper.application", "appex": "wrapper.app-extension", "bundle": "wrapper.plug-in", "dylib": "compiled.mach-o.dylib", "entitlements": "text.plist.entitlements", "framework": "wrapper.framework", "gif": "image.gif", "gpx": "text.xml", "h": "sourcecode.c.h", "m": "sourcecode.c.objc", "markdown": "text", "mdimporter": "wrapper.cfbundle", "modulemap": "sourcecode.module", "mov": "video.quicktime", "mp3": "audio.mp3", "octest": "wrapper.cfbundle", "pch": "sourcecode.c.h", "plist": "text.plist.xml", "png": "image.png", "sh": "text.script.sh", "sks": "file.sks", "storyboard": "file.storyboard", "strings": "text.plist.strings", "swift": "sourcecode.swift", "xcassets": "folder.assetcatalog", "xcconfig": "text.xcconfig", "xcdatamodel": "wrapper.xcdatamodel", "xcodeproj": "wrapper.pb-project", "xctest": "wrapper.cfbundle", "xib": "file.xib", "zip": "archive.zip", ][`extension`] } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Project/XcodeProj.swift ================================================ import Foundation import PathKit /// Model that represents a .xcodeproj project. public final class XcodeProj: Equatable { // MARK: - Properties /// Project workspace public var workspace: XCWorkspace /// .pbxproj representatino public var pbxproj: PBXProj /// Shared data. public var sharedData: XCSharedData? // MARK: - Init public init(path: Path) throws { var pbxproj: PBXProj! var workspace: XCWorkspace! var sharedData: XCSharedData? try OSLogger.instance.log(name: "Write workspace", path.string) { if !path.exists { throw XCodeProjError.notFound(path: path) } let pbxprojPaths = path.glob("*.pbxproj") if pbxprojPaths.isEmpty { throw XCodeProjError.pbxprojNotFound(path: path) } let pbxprojPath = pbxprojPaths.first! let (pbxProjData, pbxProjDictionary) = try XcodeProj.readPBXProj(path: pbxprojPath) let context = ProjectDecodingContext( pbxProjValueReader: { key in pbxProjDictionary[key] } ) let plistDecoder = XcodeprojPropertyListDecoder(context: context) pbxproj = try plistDecoder.decode(PBXProj.self, from: pbxProjData) try pbxproj.updateProjectName(path: pbxprojPaths.first!) let xcworkspacePaths = path.glob("*.xcworkspace") if xcworkspacePaths.isEmpty { workspace = XCWorkspace() } else { workspace = try XCWorkspace(path: xcworkspacePaths.first!) } let sharedDataPath = path + "xcshareddata" sharedData = try? XCSharedData(path: sharedDataPath) } self.pbxproj = pbxproj self.workspace = workspace self.sharedData = sharedData } public convenience init(pathString: String) throws { try self.init(path: Path(pathString)) } /// Initializes the XCodeProj /// /// - Parameters: /// - workspace: project internal workspace. /// - pbxproj: project .pbxproj. public init(workspace: XCWorkspace, pbxproj: PBXProj, sharedData: XCSharedData? = nil) { self.workspace = workspace self.pbxproj = pbxproj self.sharedData = sharedData } // MARK: - Equatable public static func == (lhs: XcodeProj, rhs: XcodeProj) -> Bool { return lhs.workspace == rhs.workspace && lhs.pbxproj == rhs.pbxproj && lhs.sharedData == rhs.sharedData } // MARK: - Private private static func readPBXProj(path: Path) throws -> (Data, [String: Any]) { let plistXML = try Data(contentsOf: path.url) var propertyListFormat = PropertyListSerialization.PropertyListFormat.xml let serialized = try PropertyListSerialization.propertyList( from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListFormat ) // swiftlint:disable:next force_cast let pbxProjDictionary = serialized as! [String: Any] return (plistXML, pbxProjDictionary) } } // MARK: - extension XcodeProj: Writable { /// Writes project to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if project should be overridden. Default is true. /// If false will throw error if project already exists at the given path. public func write(path: Path, override: Bool = true) throws { try write(path: path, override: override, outputSettings: PBXOutputSettings()) } /// Writes project to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if project should be overridden. Default is true. /// - Parameter outputSettings: Controls the writing of various files. /// If false will throw error if project already exists at the given path. public func write(path: Path, override: Bool = true, outputSettings: PBXOutputSettings) throws { try path.mkpath() try OSLogger.instance.log(name: "Write workspace", path.string) { try writeWorkspace(path: path, override: override) } try OSLogger.instance.log(name: "Write pbxproj", path.string) { try writePBXProj(path: path, override: override, outputSettings: outputSettings) } try OSLogger.instance.log(name: "Write schemes", path.string) { try writeSchemes(path: path, override: override) } try OSLogger.instance.log(name: "Write breakpoints", path.string) { try writeBreakPoints(path: path, override: override) } } /// Returns workspace file path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Returns: worspace file path relative to the given path. public static func workspacePath(_ path: Path) -> Path { return path + "project.xcworkspace" } /// Writes workspace to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if workspace should be overridden. Default is true. /// If false will throw error if workspace already exists at the given path. public func writeWorkspace(path: Path, override: Bool = true) throws { try workspace.write(path: XcodeProj.workspacePath(path), override: override) } /// Returns project file path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Returns: project file path relative to the given path. public static func pbxprojPath(_ path: Path) -> Path { return path + "project.pbxproj" } /// Writes project to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if project should be overridden. Default is true. /// - Parameter outputSettings: Controls the writing of various files. /// If false will throw error if project already exists at the given path. public func writePBXProj(path: Path, override: Bool = true, outputSettings: PBXOutputSettings) throws { try pbxproj.write(path: XcodeProj.pbxprojPath(path), override: override, outputSettings: outputSettings) } /// Returns shared data path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Returns: shared data path relative to the given path. public static func sharedDataPath(_ path: Path) -> Path { return path + "xcshareddata" } /// Returns schemes folder path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Returns: schemes folder path relative to the given path. public static func schemesPath(_ path: Path) -> Path { return XcodeProj.sharedDataPath(path) + "xcschemes" } /// Returns scheme file path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Parameter schemeName: scheme name /// - Returns: scheme file path relative to the given path. public static func schemePath(_ path: Path, schemeName: String) -> Path { return XcodeProj.schemesPath(path) + "\(schemeName).xcscheme" } /// Writes all project schemes to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if project should be overridden. Default is true. /// If true will remove all existing schemes before writing. /// If false will throw error if scheme already exists at the given path. public func writeSchemes(path: Path, override: Bool = true) throws { guard let sharedData = sharedData else { return } let schemesPath = XcodeProj.schemesPath(path) if override, schemesPath.exists { try schemesPath.delete() } try schemesPath.mkpath() for scheme in sharedData.schemes { try scheme.write(path: XcodeProj.schemePath(path, schemeName: scheme.name), override: override) } } /// Returns debugger folder path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Parameter schemeName: scheme name /// - Returns: debugger folder path relative to the given path. public static func debuggerPath(_ path: Path) -> Path { return XcodeProj.sharedDataPath(path) + "xcdebugger" } /// Returns breakpoints plist path relative to the given path. /// /// - Parameter path: `.xcodeproj` file path /// - Parameter schemeName: scheme name /// - Returns: breakpoints plist path relative to the given path. public static func breakPointsPath(_ path: Path) -> Path { return XcodeProj.debuggerPath(path) + "Breakpoints_v2.xcbkptlist" } /// Writes all project breakpoints to the given path. /// /// - Parameter path: path to `.xcodeproj` file. /// - Parameter override: if project should be overridden. Default is true. /// If true will remove all existing debugger data before writing. /// If false will throw error if breakpoints file exists at the given path. public func writeBreakPoints(path: Path, override: Bool = true) throws { guard let sharedData = sharedData else { return } let debuggerPath = XcodeProj.debuggerPath(path) if override, debuggerPath.exists { try debuggerPath.delete() } try debuggerPath.mkpath() try sharedData.breakpoints?.write(path: XcodeProj.breakPointsPath(path), override: override) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Protocols/Writable.swift ================================================ import Foundation import PathKit /// Protocol that defines how an entity can be writed into disk public protocol Writable { /// Writes the object that conforms the protocol. /// /// - Parameter path: The path to write to /// - Parameter override: True if the content should be overriden if it already exists. /// - Throws: writing error if something goes wrong. func write(path: Path, override: Bool) throws /// Writes the object that conforms the protocol. /// /// - Parameter pathString: The path string to write to /// - Parameter override: True if the content should be overriden if it already exists. /// - Throws: writing error if something goes wrong. func write(pathString: String, override: Bool) throws } extension Writable { public func write(pathString: String, override: Bool) throws { let path = Path(pathString) try write(path: path, override: override) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+AditionalOption.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class AdditionalOption: Equatable { // MARK: - Attributes public var key: String public var value: String public var isEnabled: Bool // MARK: - Init public init(key: String, value: String, isEnabled: Bool) { self.key = key self.value = value self.isEnabled = isEnabled } init(element: AEXMLElement) throws { key = element.attributes["key"]! value = element.attributes["value"]! isEnabled = element.attributes["isEnabled"] == "YES" } // MARK: - XML func xmlElement() -> AEXMLElement { return AEXMLElement(name: "AdditionalOption", value: nil, attributes: [ "key": key, "value": value, "isEnabled": isEnabled.xmlString, ]) } // MARK: - Equatable public static func == (lhs: AdditionalOption, rhs: AdditionalOption) -> Bool { return lhs.key == rhs.key && lhs.value == rhs.value && lhs.isEnabled == rhs.isEnabled } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+AnalyzeAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class AnalyzeAction: Equatable { // MARK: - Static // Xcode disables PreActions and PostActions for Analyze actions, so this Action // does not exetend SerialAction. private static let defaultBuildConfiguration = "Debug" // MARK: - Attributes public var buildConfiguration: String // MARK: - Init public init(buildConfiguration: String) { self.buildConfiguration = buildConfiguration } init(element: AEXMLElement) throws { buildConfiguration = element.attributes["buildConfiguration"] ?? AnalyzeAction.defaultBuildConfiguration } // MARK: - XML func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["buildConfiguration"] = buildConfiguration return AEXMLElement(name: "AnalyzeAction", value: nil, attributes: attributes) } // MARK: - Equatable public static func == (lhs: AnalyzeAction, rhs: AnalyzeAction) -> Bool { return lhs.buildConfiguration == rhs.buildConfiguration } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+ArchiveAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class ArchiveAction: SerialAction { // MARK: - Static private static let defaultBuildConfiguration = "Release" // MARK: - Attributes public var buildConfiguration: String public var revealArchiveInOrganizer: Bool public var customArchiveName: String? // MARK: - Init public init(buildConfiguration: String, revealArchiveInOrganizer: Bool, customArchiveName: String? = nil, preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = []) { self.buildConfiguration = buildConfiguration self.revealArchiveInOrganizer = revealArchiveInOrganizer self.customArchiveName = customArchiveName super.init(preActions, postActions) } override init(element: AEXMLElement) throws { buildConfiguration = element.attributes["buildConfiguration"] ?? ArchiveAction.defaultBuildConfiguration revealArchiveInOrganizer = element.attributes["revealArchiveInOrganizer"].map { $0 == "YES" } ?? true customArchiveName = element.attributes["customArchiveName"] try super.init(element: element) } // MARK: - XML func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["buildConfiguration"] = buildConfiguration attributes["customArchiveName"] = customArchiveName attributes["revealArchiveInOrganizer"] = revealArchiveInOrganizer.xmlString let element = AEXMLElement(name: "ArchiveAction", value: nil, attributes: attributes) super.writeXML(parent: element) return element } // MARK: - Equatable override func isEqual(to: Any?) -> Bool { guard let rhs = to as? ArchiveAction else { return false } return super.isEqual(to: to) && buildConfiguration == rhs.buildConfiguration && revealArchiveInOrganizer == rhs.revealArchiveInOrganizer && customArchiveName == rhs.customArchiveName } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+BuildAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class BuildAction: SerialAction { public final class Entry: Equatable { public enum BuildFor { case running, testing, profiling, archiving, analyzing public static var `default`: [BuildFor] = [.running, .testing, .archiving, .analyzing] public static var indexing: [BuildFor] = [.testing, .analyzing, .archiving] public static var testOnly: [BuildFor] = [.testing, .analyzing] } // MARK: - Attributes public var buildableReference: BuildableReference public var buildFor: [BuildFor] // MARK: - Init public init(buildableReference: BuildableReference, buildFor: [BuildFor]) { self.buildableReference = buildableReference self.buildFor = buildFor } init(element: AEXMLElement) throws { var buildFor: [BuildFor] = [] if (element.attributes["buildForTesting"].map { $0 == "YES" }) ?? true { buildFor.append(.testing) } if (element.attributes["buildForRunning"].map { $0 == "YES" }) ?? true { buildFor.append(.running) } if (element.attributes["buildForProfiling"].map { $0 == "YES" }) ?? true { buildFor.append(.profiling) } if (element.attributes["buildForArchiving"].map { $0 == "YES" }) ?? true { buildFor.append(.archiving) } if (element.attributes["buildForAnalyzing"].map { $0 == "YES" }) ?? true { buildFor.append(.analyzing) } self.buildFor = buildFor buildableReference = try BuildableReference(element: element["BuildableReference"]) } // MARK: - XML fileprivate func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["buildForTesting"] = buildFor.contains(.testing) ? "YES" : "NO" attributes["buildForRunning"] = buildFor.contains(.running) ? "YES" : "NO" attributes["buildForProfiling"] = buildFor.contains(.profiling) ? "YES" : "NO" attributes["buildForArchiving"] = buildFor.contains(.archiving) ? "YES" : "NO" attributes["buildForAnalyzing"] = buildFor.contains(.analyzing) ? "YES" : "NO" let element = AEXMLElement(name: "BuildActionEntry", value: nil, attributes: attributes) element.addChild(buildableReference.xmlElement()) return element } // MARK: - Equatable public static func == (lhs: Entry, rhs: Entry) -> Bool { return lhs.buildableReference == rhs.buildableReference && lhs.buildFor == rhs.buildFor } } // MARK: - Attributes public var buildActionEntries: [Entry] public var parallelizeBuild: Bool public var buildImplicitDependencies: Bool // MARK: - Init public init(buildActionEntries: [Entry] = [], preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = [], parallelizeBuild: Bool = false, buildImplicitDependencies: Bool = false) { self.buildActionEntries = buildActionEntries self.parallelizeBuild = parallelizeBuild self.buildImplicitDependencies = buildImplicitDependencies super.init(preActions, postActions) } override init(element: AEXMLElement) throws { parallelizeBuild = element.attributes["parallelizeBuildables"].map { $0 == "YES" } ?? true buildImplicitDependencies = element.attributes["buildImplicitDependencies"].map { $0 == "YES" } ?? true buildActionEntries = try element["BuildActionEntries"]["BuildActionEntry"] .all? .map(Entry.init) ?? [] try super.init(element: element) } // MARK: - Helpers public func add(buildActionEntry: Entry) -> BuildAction { var buildActionEntries = self.buildActionEntries buildActionEntries.append(buildActionEntry) return BuildAction(buildActionEntries: buildActionEntries, parallelizeBuild: parallelizeBuild) } // MARK: - XML func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "BuildAction", value: nil, attributes: [ "parallelizeBuildables": parallelizeBuild.xmlString, "buildImplicitDependencies": buildImplicitDependencies.xmlString, ]) super.writeXML(parent: element) let entries = element.addChild(name: "BuildActionEntries") buildActionEntries.forEach { entry in entries.addChild(entry.xmlElement()) } return element } // MARK: - Equatable override func isEqual(to: Any?) -> Bool { guard let rhs = to as? BuildAction else { return false } return super.isEqual(to: to) && buildActionEntries == rhs.buildActionEntries && parallelizeBuild == rhs.parallelizeBuild && buildImplicitDependencies == rhs.buildImplicitDependencies } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+BuildableProductRunnable.swift ================================================ import AEXML import Foundation extension XCScheme { public final class BuildableProductRunnable: Equatable { // MARK: - Attributes public var runnableDebuggingMode: String public var buildableReference: BuildableReference // MARK: - Init public init(buildableReference: BuildableReference, runnableDebuggingMode: String = "0") { self.buildableReference = buildableReference self.runnableDebuggingMode = runnableDebuggingMode } init(element: AEXMLElement) throws { runnableDebuggingMode = element.attributes["runnableDebuggingMode"] ?? "0" buildableReference = try BuildableReference(element: element["BuildableReference"]) } // MARK: - XML func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "BuildableProductRunnable", value: nil, attributes: ["runnableDebuggingMode": runnableDebuggingMode]) element.addChild(buildableReference.xmlElement()) return element } // MARK: - Equatable public static func == (lhs: BuildableProductRunnable, rhs: BuildableProductRunnable) -> Bool { return lhs.runnableDebuggingMode == rhs.runnableDebuggingMode && lhs.buildableReference == rhs.buildableReference } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+BuildableReference.swift ================================================ import AEXML import Foundation extension XCScheme { public final class BuildableReference: Equatable { // MARK: - Attributes public var referencedContainer: String private enum Blueprint: Equatable { case reference(PBXObjectReference) case string(String) var string: String { switch self { case let .reference(object): return object.value case let .string(string): return string } } } public func setBlueprint(_ object: PBXObject) { blueprint = .reference(object.reference) } private var blueprint: Blueprint public var blueprintIdentifier: String { return blueprint.string } public var buildableName: String public var buildableIdentifier: String public var blueprintName: String // MARK: - Init public init(referencedContainer: String, blueprint: PBXObject, buildableName: String, blueprintName: String, buildableIdentifier: String = "primary") { self.referencedContainer = referencedContainer self.blueprint = .reference(blueprint.reference) self.buildableName = buildableName self.buildableIdentifier = buildableIdentifier self.blueprintName = blueprintName } // MARK: - XML init(element: AEXMLElement) throws { guard let buildableIdentifier = element.attributes["BuildableIdentifier"] else { throw XCSchemeError.missing(property: "BuildableIdentifier") } guard let blueprintIdentifier = element.attributes["BlueprintIdentifier"] else { throw XCSchemeError.missing(property: "BlueprintIdentifier") } guard let buildableName = element.attributes["BuildableName"] else { throw XCSchemeError.missing(property: "BuildableName") } guard let blueprintName = element.attributes["BlueprintName"] else { throw XCSchemeError.missing(property: "BlueprintName") } guard let referencedContainer = element.attributes["ReferencedContainer"] else { throw XCSchemeError.missing(property: "ReferencedContainer") } self.buildableIdentifier = buildableIdentifier blueprint = .string(blueprintIdentifier) self.buildableName = buildableName self.blueprintName = blueprintName self.referencedContainer = referencedContainer } func xmlElement() -> AEXMLElement { return AEXMLElement(name: "BuildableReference", value: nil, attributes: [ "BuildableIdentifier": buildableIdentifier, "BlueprintIdentifier": blueprint.string, "BuildableName": buildableName, "BlueprintName": blueprintName, "ReferencedContainer": referencedContainer, ]) } // MARK: - Equatable public static func == (lhs: BuildableReference, rhs: BuildableReference) -> Bool { return lhs.referencedContainer == rhs.referencedContainer && lhs.blueprintIdentifier == rhs.blueprintIdentifier && lhs.buildableName == rhs.buildableName && lhs.blueprint == rhs.blueprint && lhs.blueprintName == rhs.blueprintName } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+CommandLineArguments.swift ================================================ import AEXML import Foundation extension XCScheme { public final class CommandLineArguments: Equatable { // MARK: - Attributes public let arguments: [CommandLineArgument] // MARK: - Init public init(arguments args: [CommandLineArgument]) { arguments = args } init(element: AEXMLElement) throws { arguments = try element.children.map { elt in guard let argName = elt.attributes["argument"] else { throw XCSchemeError.missing(property: "argument") } guard let argEnabledRaw = elt.attributes["isEnabled"] else { throw XCSchemeError.missing(property: "isEnabled") } return CommandLineArgument(name: argName, enabled: argEnabledRaw == "YES") } } // MARK: - XML func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "CommandLineArguments", value: nil) arguments.forEach { arg in element.addChild(arg.xmlElement()) } return element } // MARK: - Equatable public static func == (lhs: CommandLineArguments, rhs: CommandLineArguments) -> Bool { return lhs.arguments == rhs.arguments } } } extension XCScheme.CommandLineArguments { public struct CommandLineArgument: Equatable { // MARK: - Attributes public let name: String public let enabled: Bool // MARK: - Init public init(name: String, enabled: Bool) { self.name = name self.enabled = enabled } // MARK: - XML func xmlElement() -> AEXMLElement { return AEXMLElement(name: "CommandLineArgument", value: nil, attributes: ["argument": name, "isEnabled": enabled ? "YES" : "NO"]) } // MARK: - Equatable public static func == (lhs: CommandLineArgument, rhs: CommandLineArgument) -> Bool { return lhs.name == rhs.name && lhs.enabled == rhs.enabled } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+EnvironmentVariable.swift ================================================ import AEXML import Foundation extension XCScheme { public struct EnvironmentVariable: Equatable { // MARK: - Attributes public let variable: String public let value: String public let enabled: Bool // MARK: - Init public init(variable: String, value: String, enabled: Bool) { self.variable = variable self.value = value self.enabled = enabled } // MARK: - XML func xmlElement() -> AEXMLElement { return AEXMLElement(name: "EnvironmentVariable", value: nil, attributes: ["key": variable, "value": value, "isEnabled": enabled ? "YES" : "NO"]) } static func parseVariables(from element: AEXMLElement) throws -> [EnvironmentVariable] { return try element.children.map { elt in guard let variableKey = elt.attributes["key"] else { throw XCSchemeError.missing(property: "key") } guard let variableValue = elt.attributes["value"] else { throw XCSchemeError.missing(property: "value") } guard let variableEnabledRaw = elt.attributes["isEnabled"] else { throw XCSchemeError.missing(property: "isEnabled") } return EnvironmentVariable(variable: variableKey, value: variableValue, enabled: variableEnabledRaw == "YES") } } static func xmlElement(from variables: [EnvironmentVariable]) -> AEXMLElement { let element = AEXMLElement(name: "EnvironmentVariables", value: nil) variables.forEach { arg in element.addChild(arg.xmlElement()) } return element } // MARK: - Equatable public static func == (lhs: EnvironmentVariable, rhs: EnvironmentVariable) -> Bool { return lhs.variable == rhs.variable && lhs.value == rhs.value && lhs.enabled == rhs.enabled } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+ExecutionAction.swift ================================================ import AEXML import Foundation extension XCScheme { public final class ExecutionAction: Equatable { private static let ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction" // MARK: - Attributes public var title: String public var scriptText: String public var environmentBuildable: BuildableReference? // MARK: - Init public init(scriptText: String, title: String = "Run Script", environmentBuildable: BuildableReference? = nil) { self.scriptText = scriptText self.title = title self.environmentBuildable = environmentBuildable } init(element: AEXMLElement) throws { scriptText = element["ActionContent"].attributes["scriptText"] ?? "" title = element["ActionContent"].attributes["title"] ?? "Run Script" environmentBuildable = try? BuildableReference(element: element["ActionContent"]["EnvironmentBuildable"]["BuildableReference"]) } // MARK: - XML func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "ExecutionAction", value: nil, attributes: ["ActionType": ExecutionAction.ActionType]) let content = AEXMLElement(name: "ActionContent", value: nil, attributes: [ "title": title, "scriptText": scriptText, ]) element.addChild(content) if let environmentBuildable = environmentBuildable { let environment = content.addChild(name: "EnvironmentBuildable") environment.addChild(environmentBuildable.xmlElement()) } return element } // MARK: - Equatable public static func == (lhs: ExecutionAction, rhs: ExecutionAction) -> Bool { return lhs.title == rhs.title && lhs.scriptText == rhs.scriptText && lhs.environmentBuildable == rhs.environmentBuildable } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+LaunchAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { // swiftlint:disable:next type_body_length public final class LaunchAction: SerialAction { public enum Style: String { case auto = "0" case wait = "1" } public enum GPUFrameCaptureMode: String { case autoEnabled = "0" case metal = "1" case openGL = "2" case disabled = "3" } public enum GPUValidationMode: String { case enabled = "0" case disabled = "1" case extended = "2" } // MARK: - Static private static let defaultBuildConfiguration = "Debug" public static let defaultDebugServiceExtension = "internal" private static let defaultLaunchStyle = Style.auto public static let defaultGPUFrameCaptureMode = GPUFrameCaptureMode.autoEnabled public static let defaultGPUValidationMode = GPUValidationMode.enabled // MARK: - Attributes public var buildableProductRunnable: BuildableProductRunnable? public var macroExpansion: BuildableReference? public var selectedDebuggerIdentifier: String public var selectedLauncherIdentifier: String public var buildConfiguration: String public var launchStyle: Style public var useCustomWorkingDirectory: Bool public var ignoresPersistentStateOnLaunch: Bool public var debugDocumentVersioning: Bool public var debugServiceExtension: String public var allowLocationSimulation: Bool public var locationScenarioReference: LocationScenarioReference? public var enableGPUFrameCaptureMode: GPUFrameCaptureMode public var enableGPUValidationMode: GPUValidationMode public var enableAddressSanitizer: Bool public var enableASanStackUseAfterReturn: Bool public var enableThreadSanitizer: Bool public var stopOnEveryThreadSanitizerIssue: Bool public var enableUBSanitizer: Bool public var stopOnEveryUBSanitizerIssue: Bool public var disableMainThreadChecker: Bool public var stopOnEveryMainThreadCheckerIssue: Bool public var additionalOptions: [AdditionalOption] public var commandlineArguments: CommandLineArguments? public var environmentVariables: [EnvironmentVariable]? public var language: String? public var region: String? public var launchAutomaticallySubstyle: String? // MARK: - Init public init(buildableProductRunnable: BuildableProductRunnable?, buildConfiguration: String, preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = [], macroExpansion: BuildableReference? = nil, selectedDebuggerIdentifier: String = XCScheme.defaultDebugger, selectedLauncherIdentifier: String = XCScheme.defaultLauncher, launchStyle: Style = .auto, useCustomWorkingDirectory: Bool = false, ignoresPersistentStateOnLaunch: Bool = false, debugDocumentVersioning: Bool = true, debugServiceExtension: String = LaunchAction.defaultDebugServiceExtension, allowLocationSimulation: Bool = true, locationScenarioReference: LocationScenarioReference? = nil, enableGPUFrameCaptureMode: GPUFrameCaptureMode = LaunchAction.defaultGPUFrameCaptureMode, enableGPUValidationMode: GPUValidationMode = LaunchAction.defaultGPUValidationMode, enableAddressSanitizer: Bool = false, enableASanStackUseAfterReturn: Bool = false, enableThreadSanitizer: Bool = false, stopOnEveryThreadSanitizerIssue: Bool = false, enableUBSanitizer: Bool = false, stopOnEveryUBSanitizerIssue: Bool = false, disableMainThreadChecker: Bool = false, stopOnEveryMainThreadCheckerIssue: Bool = false, additionalOptions: [AdditionalOption] = [], commandlineArguments: CommandLineArguments? = nil, environmentVariables: [EnvironmentVariable]? = nil, language: String? = nil, region: String? = nil, launchAutomaticallySubstyle: String? = nil) { self.buildableProductRunnable = buildableProductRunnable self.macroExpansion = macroExpansion self.buildConfiguration = buildConfiguration self.launchStyle = launchStyle self.selectedDebuggerIdentifier = selectedDebuggerIdentifier self.selectedLauncherIdentifier = selectedLauncherIdentifier self.useCustomWorkingDirectory = useCustomWorkingDirectory self.ignoresPersistentStateOnLaunch = ignoresPersistentStateOnLaunch self.debugDocumentVersioning = debugDocumentVersioning self.debugServiceExtension = debugServiceExtension self.allowLocationSimulation = allowLocationSimulation self.locationScenarioReference = locationScenarioReference self.enableGPUFrameCaptureMode = enableGPUFrameCaptureMode self.enableGPUValidationMode = enableGPUValidationMode self.enableAddressSanitizer = enableAddressSanitizer self.enableASanStackUseAfterReturn = enableASanStackUseAfterReturn self.enableThreadSanitizer = enableThreadSanitizer self.stopOnEveryThreadSanitizerIssue = stopOnEveryThreadSanitizerIssue self.enableUBSanitizer = enableUBSanitizer self.stopOnEveryUBSanitizerIssue = stopOnEveryUBSanitizerIssue self.disableMainThreadChecker = disableMainThreadChecker self.stopOnEveryMainThreadCheckerIssue = stopOnEveryMainThreadCheckerIssue self.additionalOptions = additionalOptions self.commandlineArguments = commandlineArguments self.environmentVariables = environmentVariables self.language = language self.region = region self.launchAutomaticallySubstyle = launchAutomaticallySubstyle super.init(preActions, postActions) } // swiftlint:disable:next function_body_length override init(element: AEXMLElement) throws { buildConfiguration = element.attributes["buildConfiguration"] ?? LaunchAction.defaultBuildConfiguration selectedDebuggerIdentifier = element.attributes["selectedDebuggerIdentifier"] ?? XCScheme.defaultDebugger selectedLauncherIdentifier = element.attributes["selectedLauncherIdentifier"] ?? XCScheme.defaultLauncher launchStyle = element.attributes["launchStyle"].flatMap { Style(rawValue: $0) } ?? .auto useCustomWorkingDirectory = element.attributes["useCustomWorkingDirectory"] == "YES" ignoresPersistentStateOnLaunch = element.attributes["ignoresPersistentStateOnLaunch"] == "YES" debugDocumentVersioning = element.attributes["debugDocumentVersioning"].map { $0 == "YES" } ?? true debugServiceExtension = element.attributes["debugServiceExtension"] ?? LaunchAction.defaultDebugServiceExtension allowLocationSimulation = element.attributes["allowLocationSimulation"].map { $0 == "YES" } ?? true let buildableProductRunnableElement = element["BuildableProductRunnable"] if buildableProductRunnableElement.error == nil { buildableProductRunnable = try BuildableProductRunnable(element: buildableProductRunnableElement) } let buildableReferenceElement = element["MacroExpansion"]["BuildableReference"] if buildableReferenceElement.error == nil { macroExpansion = try BuildableReference(element: buildableReferenceElement) } if element["LocationScenarioReference"].all?.first != nil { locationScenarioReference = try LocationScenarioReference(element: element["LocationScenarioReference"]) } else { locationScenarioReference = nil } enableGPUFrameCaptureMode = element.attributes["enableGPUFrameCaptureMode"] .flatMap { GPUFrameCaptureMode(rawValue: $0) } ?? LaunchAction.defaultGPUFrameCaptureMode enableGPUValidationMode = element.attributes["enableGPUValidationMode"] .flatMap { GPUValidationMode(rawValue: $0) } ?? LaunchAction.defaultGPUValidationMode enableAddressSanitizer = element.attributes["enableAddressSanitizer"] == "YES" enableASanStackUseAfterReturn = element.attributes["enableASanStackUseAfterReturn"] == "YES" enableThreadSanitizer = element.attributes["enableThreadSanitizer"] == "YES" stopOnEveryThreadSanitizerIssue = element.attributes["stopOnEveryThreadSanitizerIssue"] == "YES" enableUBSanitizer = element.attributes["enableUBSanitizer"] == "YES" stopOnEveryUBSanitizerIssue = element.attributes["stopOnEveryUBSanitizerIssue"] == "YES" disableMainThreadChecker = element.attributes["disableMainThreadChecker"] == "YES" stopOnEveryMainThreadCheckerIssue = element.attributes["stopOnEveryMainThreadCheckerIssue"] == "YES" additionalOptions = try element["AdditionalOptions"]["AdditionalOption"] .all? .map(AdditionalOption.init) ?? [] let commandlineOptions = element["CommandLineArguments"] if commandlineOptions.error == nil { commandlineArguments = try CommandLineArguments(element: commandlineOptions) } let environmentVariables = element["EnvironmentVariables"] if environmentVariables.error == nil { self.environmentVariables = try EnvironmentVariable.parseVariables(from: environmentVariables) } language = element.attributes["language"] region = element.attributes["region"] launchAutomaticallySubstyle = element.attributes["launchAutomaticallySubstyle"] try super.init(element: element) } // MARK: - XML private var xmlAttributes: [String: String] { var attributes = [ "buildConfiguration": buildConfiguration, "selectedDebuggerIdentifier": selectedDebuggerIdentifier, "selectedLauncherIdentifier": selectedLauncherIdentifier, "launchStyle": launchStyle.rawValue, "useCustomWorkingDirectory": useCustomWorkingDirectory.xmlString, "ignoresPersistentStateOnLaunch": ignoresPersistentStateOnLaunch.xmlString, "debugDocumentVersioning": debugDocumentVersioning.xmlString, "debugServiceExtension": debugServiceExtension, "allowLocationSimulation": allowLocationSimulation.xmlString, ] if enableGPUFrameCaptureMode != LaunchAction.defaultGPUFrameCaptureMode { attributes["enableGPUFrameCaptureMode"] = enableGPUFrameCaptureMode.rawValue } if enableGPUValidationMode != LaunchAction.defaultGPUValidationMode { attributes["enableGPUValidationMode"] = enableGPUValidationMode.rawValue } if enableAddressSanitizer { attributes["enableAddressSanitizer"] = enableAddressSanitizer.xmlString } if enableASanStackUseAfterReturn { attributes["enableASanStackUseAfterReturn"] = enableASanStackUseAfterReturn.xmlString } if enableThreadSanitizer { attributes["enableThreadSanitizer"] = enableThreadSanitizer.xmlString } if stopOnEveryThreadSanitizerIssue { attributes["stopOnEveryThreadSanitizerIssue"] = stopOnEveryThreadSanitizerIssue.xmlString } if enableUBSanitizer { attributes["enableUBSanitizer"] = enableUBSanitizer.xmlString } if stopOnEveryUBSanitizerIssue { attributes["stopOnEveryUBSanitizerIssue"] = stopOnEveryUBSanitizerIssue.xmlString } if disableMainThreadChecker { attributes["disableMainThreadChecker"] = disableMainThreadChecker.xmlString } if stopOnEveryMainThreadCheckerIssue { attributes["stopOnEveryMainThreadCheckerIssue"] = stopOnEveryMainThreadCheckerIssue.xmlString } return attributes } func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "LaunchAction", value: nil, attributes: xmlAttributes) super.writeXML(parent: element) if let buildableProductRunnable = buildableProductRunnable { element.addChild(buildableProductRunnable.xmlElement()) } if let locationScenarioReference = locationScenarioReference { element.addChild(locationScenarioReference.xmlElement()) } if let macroExpansion = macroExpansion { let macro = element.addChild(name: "MacroExpansion") macro.addChild(macroExpansion.xmlElement()) } if let commandlineArguments = commandlineArguments { element.addChild(commandlineArguments.xmlElement()) } if let environmentVariables = environmentVariables { element.addChild(EnvironmentVariable.xmlElement(from: environmentVariables)) } if let language = language { element.attributes["language"] = language } if let region = region { element.attributes["region"] = region } if let launchAutomaticallySubstyle = launchAutomaticallySubstyle { element.attributes["launchAutomaticallySubstyle"] = launchAutomaticallySubstyle } let additionalOptionsElement = element.addChild(AEXMLElement(name: "AdditionalOptions")) additionalOptions.forEach { additionalOption in additionalOptionsElement.addChild(additionalOption.xmlElement()) } return element } // MARK: - Equatable override func isEqual(to: Any?) -> Bool { guard let rhs = to as? LaunchAction else { return false } return super.isEqual(to: to) && buildableProductRunnable == rhs.buildableProductRunnable && macroExpansion == rhs.macroExpansion && selectedDebuggerIdentifier == rhs.selectedDebuggerIdentifier && selectedLauncherIdentifier == rhs.selectedLauncherIdentifier && buildConfiguration == rhs.buildConfiguration && launchStyle == rhs.launchStyle && useCustomWorkingDirectory == rhs.useCustomWorkingDirectory && ignoresPersistentStateOnLaunch == rhs.ignoresPersistentStateOnLaunch && debugDocumentVersioning == rhs.debugDocumentVersioning && debugServiceExtension == rhs.debugServiceExtension && allowLocationSimulation == rhs.allowLocationSimulation && locationScenarioReference == rhs.locationScenarioReference && enableGPUFrameCaptureMode == rhs.enableGPUFrameCaptureMode && enableGPUValidationMode == rhs.enableGPUValidationMode && enableAddressSanitizer == rhs.enableAddressSanitizer && enableASanStackUseAfterReturn == rhs.enableASanStackUseAfterReturn && enableThreadSanitizer == rhs.enableThreadSanitizer && stopOnEveryThreadSanitizerIssue == rhs.stopOnEveryThreadSanitizerIssue && enableUBSanitizer == rhs.enableUBSanitizer && stopOnEveryUBSanitizerIssue == rhs.stopOnEveryUBSanitizerIssue && disableMainThreadChecker == rhs.disableMainThreadChecker && stopOnEveryMainThreadCheckerIssue == rhs.stopOnEveryMainThreadCheckerIssue && additionalOptions == rhs.additionalOptions && commandlineArguments == rhs.commandlineArguments && environmentVariables == rhs.environmentVariables && language == rhs.language && region == rhs.region && launchAutomaticallySubstyle == rhs.launchAutomaticallySubstyle } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+LocationScenarioReference.swift ================================================ import AEXML import Foundation extension XCScheme { public final class LocationScenarioReference: Equatable { // MARK: - Attributes public var identifier: String public var referenceType: String // MARK: - Init public init(identifier: String, referenceType: String) { self.identifier = identifier self.referenceType = referenceType } init(element: AEXMLElement) throws { identifier = element.attributes["identifier"]! referenceType = element.attributes["referenceType"]! } // MARK: - XML func xmlElement() -> AEXMLElement { return AEXMLElement(name: "LocationScenarioReference", value: nil, attributes: [ "identifier": identifier, "referenceType": referenceType, ]) } // MARK: - Equatable public static func == (lhs: LocationScenarioReference, rhs: LocationScenarioReference) -> Bool { return lhs.identifier == rhs.identifier && lhs.referenceType == rhs.referenceType } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+ProfileAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class ProfileAction: SerialAction { // MARK: - Static private static let defaultBuildConfiguration = "Release" // MARK: - Attributes public var buildableProductRunnable: BuildableProductRunnable? public var buildConfiguration: String public var shouldUseLaunchSchemeArgsEnv: Bool public var savedToolIdentifier: String public var ignoresPersistentStateOnLaunch: Bool public var useCustomWorkingDirectory: Bool public var debugDocumentVersioning: Bool public var commandlineArguments: CommandLineArguments? public var environmentVariables: [EnvironmentVariable]? public var macroExpansion: BuildableReference? public var enableTestabilityWhenProfilingTests: Bool // MARK: - Init public init(buildableProductRunnable: BuildableProductRunnable?, buildConfiguration: String, preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = [], macroExpansion: BuildableReference? = nil, shouldUseLaunchSchemeArgsEnv: Bool = true, savedToolIdentifier: String = "", ignoresPersistentStateOnLaunch: Bool = false, useCustomWorkingDirectory: Bool = false, debugDocumentVersioning: Bool = true, commandlineArguments: CommandLineArguments? = nil, environmentVariables: [EnvironmentVariable]? = nil, enableTestabilityWhenProfilingTests: Bool = true) { self.buildableProductRunnable = buildableProductRunnable self.buildConfiguration = buildConfiguration self.macroExpansion = macroExpansion self.shouldUseLaunchSchemeArgsEnv = shouldUseLaunchSchemeArgsEnv self.savedToolIdentifier = savedToolIdentifier self.useCustomWorkingDirectory = useCustomWorkingDirectory self.debugDocumentVersioning = debugDocumentVersioning self.commandlineArguments = commandlineArguments self.environmentVariables = environmentVariables self.ignoresPersistentStateOnLaunch = ignoresPersistentStateOnLaunch self.enableTestabilityWhenProfilingTests = enableTestabilityWhenProfilingTests super.init(preActions, postActions) } override init(element: AEXMLElement) throws { buildConfiguration = element.attributes["buildConfiguration"] ?? ProfileAction.defaultBuildConfiguration shouldUseLaunchSchemeArgsEnv = element.attributes["shouldUseLaunchSchemeArgsEnv"].map { $0 == "YES" } ?? true savedToolIdentifier = element.attributes["savedToolIdentifier"] ?? "" useCustomWorkingDirectory = element.attributes["useCustomWorkingDirectory"] == "YES" debugDocumentVersioning = element.attributes["debugDocumentVersioning"].map { $0 == "YES" } ?? true ignoresPersistentStateOnLaunch = element.attributes["ignoresPersistentStateOnLaunch"].map { $0 == "YES" } ?? false let buildableProductRunnableElement = element["BuildableProductRunnable"] if buildableProductRunnableElement.error == nil { buildableProductRunnable = try BuildableProductRunnable(element: buildableProductRunnableElement) } let buildableReferenceElement = element["MacroExpansion"]["BuildableReference"] if buildableReferenceElement.error == nil { macroExpansion = try BuildableReference(element: buildableReferenceElement) } let commandlineOptions = element["CommandLineArguments"] if commandlineOptions.error == nil { commandlineArguments = try CommandLineArguments(element: commandlineOptions) } let environmentVariables = element["EnvironmentVariables"] if environmentVariables.error == nil { self.environmentVariables = try EnvironmentVariable.parseVariables(from: environmentVariables) } enableTestabilityWhenProfilingTests = element.attributes["enableTestabilityWhenProfilingTests"].map { $0 != "No" } ?? true try super.init(element: element) } // MARK: - XML func xmlElement() -> AEXMLElement { let element = AEXMLElement(name: "ProfileAction", value: nil, attributes: [ "buildConfiguration": buildConfiguration, "shouldUseLaunchSchemeArgsEnv": shouldUseLaunchSchemeArgsEnv.xmlString, "savedToolIdentifier": savedToolIdentifier, "useCustomWorkingDirectory": useCustomWorkingDirectory.xmlString, "debugDocumentVersioning": debugDocumentVersioning.xmlString, ]) super.writeXML(parent: element) if ignoresPersistentStateOnLaunch { element.attributes["ignoresPersistentStateOnLaunch"] = ignoresPersistentStateOnLaunch.xmlString } if !enableTestabilityWhenProfilingTests { element.attributes["enableTestabilityWhenProfilingTests"] = "No" } if let buildableProductRunnable = buildableProductRunnable { element.addChild(buildableProductRunnable.xmlElement()) } if let commandlineArguments = commandlineArguments { element.addChild(commandlineArguments.xmlElement()) } if let environmentVariables = environmentVariables { element.addChild(EnvironmentVariable.xmlElement(from: environmentVariables)) } if let macroExpansion = macroExpansion { let macro = element.addChild(name: "MacroExpansion") macro.addChild(macroExpansion.xmlElement()) } return element } // MARK: - Equatable override func isEqual(to: Any?) -> Bool { guard let rhs = to as? ProfileAction else { return false } return super.isEqual(to: to) && buildableProductRunnable == rhs.buildableProductRunnable && buildConfiguration == rhs.buildConfiguration && shouldUseLaunchSchemeArgsEnv == rhs.shouldUseLaunchSchemeArgsEnv && savedToolIdentifier == rhs.savedToolIdentifier && ignoresPersistentStateOnLaunch == rhs.ignoresPersistentStateOnLaunch && useCustomWorkingDirectory == rhs.useCustomWorkingDirectory && debugDocumentVersioning == rhs.debugDocumentVersioning && commandlineArguments == rhs.commandlineArguments && environmentVariables == rhs.environmentVariables && macroExpansion == rhs.macroExpansion && enableTestabilityWhenProfilingTests == rhs.enableTestabilityWhenProfilingTests } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+SerialAction.swift ================================================ import AEXML import Foundation extension XCScheme { public class SerialAction: Equatable { // MARK: - Attributes public var preActions: [ExecutionAction] public var postActions: [ExecutionAction] // MARK: - Init init(_ preActions: [ExecutionAction], _ postActions: [ExecutionAction]) { self.preActions = preActions self.postActions = postActions } init(element: AEXMLElement) throws { preActions = try element["PreActions"]["ExecutionAction"].all?.map(ExecutionAction.init) ?? [] postActions = try element["PostActions"]["ExecutionAction"].all?.map(ExecutionAction.init) ?? [] } // MARK: - XML func writeXML(parent element: AEXMLElement) { if !preActions.isEmpty { let preActions = element.addChild(name: "PreActions") self.preActions.forEach { preAction in preActions.addChild(preAction.xmlElement()) } } if !postActions.isEmpty { let postActions = element.addChild(name: "PostActions") self.postActions.forEach { postAction in postActions.addChild(postAction.xmlElement()) } } } // MARK: - Equatable @objc dynamic func isEqual(to: Any?) -> Bool { guard let rhs = to as? SerialAction else { return false } return preActions == rhs.preActions && postActions == rhs.postActions } public static func == (lhs: SerialAction, rhs: SerialAction) -> Bool { return lhs.isEqual(to: rhs) } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+SkippedTests.swift ================================================ import AEXML import Foundation extension XCScheme { public final class SkippedTest: Equatable { // MARK: - Attributes public var identifier: String // MARK: - Init public init(identifier: String) { self.identifier = identifier } init(element: AEXMLElement) throws { identifier = element.attributes["Identifier"]! } // MARK: - XML func xmlElement() -> AEXMLElement { return AEXMLElement(name: "Test", value: nil, attributes: ["Identifier": identifier]) } // MARK: - Equatable public static func == (lhs: SkippedTest, rhs: SkippedTest) -> Bool { return lhs.identifier == rhs.identifier } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+TestAction.swift ================================================ import AEXML import Foundation import PathKit extension XCScheme { public final class TestAction: SerialAction { public enum AttachmentLifetime: String { case keepAlways, keepNever } // MARK: - Static private static let defaultBuildConfiguration = "Debug" // MARK: - Attributes public var testables: [TestableReference] public var buildConfiguration: String public var selectedDebuggerIdentifier: String public var selectedLauncherIdentifier: String public var shouldUseLaunchSchemeArgsEnv: Bool public var codeCoverageEnabled: Bool public var enableAddressSanitizer: Bool public var enableASanStackUseAfterReturn: Bool public var enableThreadSanitizer: Bool public var enableUBSanitizer: Bool public var disableMainThreadChecker: Bool public var macroExpansion: BuildableReference? public var additionalOptions: [AdditionalOption] public var commandlineArguments: CommandLineArguments? public var environmentVariables: [EnvironmentVariable]? public var language: String? public var region: String? public var systemAttachmentLifetime: AttachmentLifetime? public var userAttachmentLifetime: AttachmentLifetime? // MARK: - Init public init(buildConfiguration: String, macroExpansion: BuildableReference?, testables: [TestableReference] = [], preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = [], selectedDebuggerIdentifier: String = XCScheme.defaultDebugger, selectedLauncherIdentifier: String = XCScheme.defaultLauncher, shouldUseLaunchSchemeArgsEnv: Bool = true, codeCoverageEnabled: Bool = false, enableAddressSanitizer: Bool = false, enableASanStackUseAfterReturn: Bool = false, enableThreadSanitizer: Bool = false, enableUBSanitizer: Bool = false, disableMainThreadChecker: Bool = false, additionalOptions: [AdditionalOption] = [], commandlineArguments: CommandLineArguments? = nil, environmentVariables: [EnvironmentVariable]? = nil, language: String? = nil, region: String? = nil, systemAttachmentLifetime: AttachmentLifetime? = nil, userAttachmentLifetime: AttachmentLifetime? = nil) { self.buildConfiguration = buildConfiguration self.macroExpansion = macroExpansion self.testables = testables self.selectedDebuggerIdentifier = selectedDebuggerIdentifier self.selectedLauncherIdentifier = selectedLauncherIdentifier self.shouldUseLaunchSchemeArgsEnv = shouldUseLaunchSchemeArgsEnv self.codeCoverageEnabled = codeCoverageEnabled self.enableAddressSanitizer = enableAddressSanitizer self.enableASanStackUseAfterReturn = enableASanStackUseAfterReturn self.enableThreadSanitizer = enableThreadSanitizer self.enableUBSanitizer = enableUBSanitizer self.disableMainThreadChecker = disableMainThreadChecker self.additionalOptions = additionalOptions self.commandlineArguments = commandlineArguments self.environmentVariables = environmentVariables self.language = language self.region = region self.systemAttachmentLifetime = systemAttachmentLifetime self.userAttachmentLifetime = userAttachmentLifetime super.init(preActions, postActions) } override init(element: AEXMLElement) throws { buildConfiguration = element.attributes["buildConfiguration"] ?? TestAction.defaultBuildConfiguration selectedDebuggerIdentifier = element.attributes["selectedDebuggerIdentifier"] ?? XCScheme.defaultDebugger selectedLauncherIdentifier = element.attributes["selectedLauncherIdentifier"] ?? XCScheme.defaultLauncher shouldUseLaunchSchemeArgsEnv = element.attributes["shouldUseLaunchSchemeArgsEnv"].map { $0 == "YES" } ?? true codeCoverageEnabled = element.attributes["codeCoverageEnabled"] == "YES" enableAddressSanitizer = element.attributes["enableAddressSanitizer"] == "YES" enableASanStackUseAfterReturn = element.attributes["enableASanStackUseAfterReturn"] == "YES" enableThreadSanitizer = element.attributes["enableThreadSanitizer"] == "YES" enableUBSanitizer = element.attributes["enableUBSanitizer"] == "YES" disableMainThreadChecker = element.attributes["disableMainThreadChecker"] == "YES" testables = try element["Testables"]["TestableReference"] .all? .map(TestableReference.init) ?? [] let buildableReferenceElement = element["MacroExpansion"]["BuildableReference"] if buildableReferenceElement.error == nil { macroExpansion = try BuildableReference(element: buildableReferenceElement) } additionalOptions = try element["AdditionalOptions"]["AdditionalOption"] .all? .map(AdditionalOption.init) ?? [] let commandlineOptions = element["CommandLineArguments"] if commandlineOptions.error == nil { commandlineArguments = try CommandLineArguments(element: commandlineOptions) } let environmentVariables = element["EnvironmentVariables"] if environmentVariables.error == nil { self.environmentVariables = try EnvironmentVariable.parseVariables(from: environmentVariables) } language = element.attributes["language"] region = element.attributes["region"] systemAttachmentLifetime = element.attributes["systemAttachmentLifetime"] .flatMap(AttachmentLifetime.init(rawValue:)) userAttachmentLifetime = element.attributes["userAttachmentLifetime"] .flatMap(AttachmentLifetime.init(rawValue:)) try super.init(element: element) } // MARK: - XML func xmlElement() -> AEXMLElement { var attributes: [String: String] = [:] attributes["buildConfiguration"] = buildConfiguration attributes["selectedDebuggerIdentifier"] = selectedDebuggerIdentifier attributes["selectedLauncherIdentifier"] = selectedLauncherIdentifier if let language = language { attributes["language"] = language } attributes["region"] = region attributes["shouldUseLaunchSchemeArgsEnv"] = shouldUseLaunchSchemeArgsEnv.xmlString if codeCoverageEnabled { attributes["codeCoverageEnabled"] = codeCoverageEnabled.xmlString } if enableAddressSanitizer { attributes["enableAddressSanitizer"] = enableAddressSanitizer.xmlString } if enableASanStackUseAfterReturn { attributes["enableASanStackUseAfterReturn"] = enableASanStackUseAfterReturn.xmlString } if enableThreadSanitizer { attributes["enableThreadSanitizer"] = enableThreadSanitizer.xmlString } if enableUBSanitizer { attributes["enableUBSanitizer"] = enableUBSanitizer.xmlString } if disableMainThreadChecker { attributes["disableMainThreadChecker"] = disableMainThreadChecker.xmlString } attributes["systemAttachmentLifetime"] = systemAttachmentLifetime?.rawValue if case .keepAlways? = userAttachmentLifetime { attributes["userAttachmentLifetime"] = userAttachmentLifetime?.rawValue } let element = AEXMLElement(name: "TestAction", value: nil, attributes: attributes) super.writeXML(parent: element) let testablesElement = element.addChild(name: "Testables") testables.forEach { testable in testablesElement.addChild(testable.xmlElement()) } if let macroExpansion = macroExpansion { let macro = element.addChild(name: "MacroExpansion") macro.addChild(macroExpansion.xmlElement()) } if let commandlineArguments = commandlineArguments { element.addChild(commandlineArguments.xmlElement()) } if let environmentVariables = environmentVariables { element.addChild(EnvironmentVariable.xmlElement(from: environmentVariables)) } let additionalOptionsElement = element.addChild(AEXMLElement(name: "AdditionalOptions")) additionalOptions.forEach { additionalOption in additionalOptionsElement.addChild(additionalOption.xmlElement()) } return element } // MARK: - Equatable override func isEqual(to: Any?) -> Bool { guard let rhs = to as? TestAction else { return false } return testables == rhs.testables && buildConfiguration == rhs.buildConfiguration && selectedDebuggerIdentifier == rhs.selectedDebuggerIdentifier && selectedLauncherIdentifier == rhs.selectedLauncherIdentifier && shouldUseLaunchSchemeArgsEnv == rhs.shouldUseLaunchSchemeArgsEnv && codeCoverageEnabled == rhs.codeCoverageEnabled && enableAddressSanitizer == rhs.enableAddressSanitizer && enableASanStackUseAfterReturn == rhs.enableASanStackUseAfterReturn && enableThreadSanitizer == rhs.enableThreadSanitizer && enableUBSanitizer == rhs.enableUBSanitizer && disableMainThreadChecker == rhs.disableMainThreadChecker && macroExpansion == rhs.macroExpansion && additionalOptions == rhs.additionalOptions && commandlineArguments == rhs.commandlineArguments && environmentVariables == rhs.environmentVariables && language == rhs.language && region == rhs.region && systemAttachmentLifetime == rhs.systemAttachmentLifetime && userAttachmentLifetime == rhs.userAttachmentLifetime } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme+TestableReference.swift ================================================ import AEXML import Foundation extension XCScheme { public final class TestableReference: Equatable { // MARK: - Attributes public var skipped: Bool public var parallelizable: Bool public var randomExecutionOrdering: Bool public var buildableReference: BuildableReference public var skippedTests: [SkippedTest] // MARK: - Init public init(skipped: Bool, parallelizable: Bool = false, randomExecutionOrdering: Bool = false, buildableReference: BuildableReference, skippedTests: [SkippedTest] = []) { self.skipped = skipped self.parallelizable = parallelizable self.randomExecutionOrdering = randomExecutionOrdering self.buildableReference = buildableReference self.skippedTests = skippedTests } init(element: AEXMLElement) throws { skipped = element.attributes["skipped"] == "YES" parallelizable = element.attributes["parallelizable"] == "YES" randomExecutionOrdering = element.attributes["testExecutionOrdering"] == "random" buildableReference = try BuildableReference(element: element["BuildableReference"]) if let skippedTests = element["SkippedTests"]["Test"].all, !skippedTests.isEmpty { self.skippedTests = try skippedTests.map(SkippedTest.init) } else { skippedTests = [] } } // MARK: - XML func xmlElement() -> AEXMLElement { var attributes: [String: String] = ["skipped": skipped.xmlString] attributes["parallelizable"] = parallelizable ? parallelizable.xmlString : nil attributes["testExecutionOrdering"] = randomExecutionOrdering ? "random" : nil let element = AEXMLElement(name: "TestableReference", value: nil, attributes: attributes) element.addChild(buildableReference.xmlElement()) if !skippedTests.isEmpty { let skippedTestsElement = element.addChild(name: "SkippedTests") skippedTests.forEach { skippedTest in skippedTestsElement.addChild(skippedTest.xmlElement()) } } return element } // MARK: - Equatable public static func == (lhs: TestableReference, rhs: TestableReference) -> Bool { return lhs.skipped == rhs.skipped && lhs.parallelizable == rhs.parallelizable && lhs.randomExecutionOrdering == rhs.randomExecutionOrdering && lhs.buildableReference == rhs.buildableReference && lhs.skippedTests == rhs.skippedTests } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Scheme/XCScheme.swift ================================================ import AEXML import Foundation import PathKit public enum XCSchemeError: Error, CustomStringConvertible { case notFound(path: Path) case missing(property: String) public var description: String { switch self { case let .notFound(path): return ".xcscheme couldn't be found at path \(path.string)" case let .missing(property): return "Property \(property) missing" } } } public final class XCScheme: Writable, Equatable { // MARK: - Static public static let defaultDebugger = "Xcode.DebuggerFoundation.Debugger.LLDB" public static let defaultLauncher = "Xcode.DebuggerFoundation.Launcher.LLDB" // MARK: - Properties public var buildAction: BuildAction? public var testAction: TestAction? public var launchAction: XCScheme.LaunchAction? public var profileAction: ProfileAction? public var analyzeAction: AnalyzeAction? public var archiveAction: ArchiveAction? public var lastUpgradeVersion: String? public var version: String? public var wasCreatedForAppExtension: Bool? public var name: String // MARK: - Init public init(path: Path) throws { if !path.exists { throw XCSchemeError.notFound(path: path) } name = path.lastComponentWithoutExtension let document = try AEXMLDocument(xml: try path.read()) let scheme = document["Scheme"] lastUpgradeVersion = scheme.attributes["LastUpgradeVersion"] version = scheme.attributes["version"] buildAction = try BuildAction(element: scheme["BuildAction"]) testAction = try TestAction(element: scheme["TestAction"]) launchAction = try XCScheme.LaunchAction(element: scheme["LaunchAction"]) analyzeAction = try AnalyzeAction(element: scheme["AnalyzeAction"]) archiveAction = try ArchiveAction(element: scheme["ArchiveAction"]) profileAction = try ProfileAction(element: scheme["ProfileAction"]) if let wasCreatedForAppExtension = scheme.attributes["wasCreatedForAppExtension"] { self.wasCreatedForAppExtension = wasCreatedForAppExtension == "YES" } } public init(name: String, lastUpgradeVersion: String?, version: String?, buildAction: BuildAction? = nil, testAction: TestAction? = nil, launchAction: XCScheme.LaunchAction? = nil, profileAction: ProfileAction? = nil, analyzeAction: AnalyzeAction? = nil, archiveAction: ArchiveAction? = nil, wasCreatedForAppExtension: Bool? = nil) { self.name = name self.lastUpgradeVersion = lastUpgradeVersion self.version = version self.buildAction = buildAction self.testAction = testAction self.launchAction = launchAction self.profileAction = profileAction self.analyzeAction = analyzeAction self.archiveAction = archiveAction self.wasCreatedForAppExtension = wasCreatedForAppExtension } // MARK: - Writable public func write(path: Path, override: Bool) throws { let document = AEXMLDocument() var schemeAttributes: [String: String] = [:] schemeAttributes["LastUpgradeVersion"] = lastUpgradeVersion schemeAttributes["version"] = version let scheme = document.addChild(name: "Scheme", value: nil, attributes: schemeAttributes) if let buildAction = buildAction { scheme.addChild(buildAction.xmlElement()) } if let testAction = testAction { scheme.addChild(testAction.xmlElement()) } if let launchAction = launchAction { scheme.addChild(launchAction.xmlElement()) } if let profileAction = profileAction { scheme.addChild(profileAction.xmlElement()) } if let analyzeAction = analyzeAction { scheme.addChild(analyzeAction.xmlElement()) } if let archiveAction = archiveAction { scheme.addChild(archiveAction.xmlElement()) } if let wasCreatedForAppExtension = wasCreatedForAppExtension { scheme.attributes["wasCreatedForAppExtension"] = wasCreatedForAppExtension.xmlString } if override, path.exists { try path.delete() } try path.write(document.xmlXcodeFormat) } // MARK: - Equatable public static func == (lhs: XCScheme, rhs: XCScheme) -> Bool { return lhs.buildAction == rhs.buildAction && lhs.testAction == rhs.testAction && lhs.launchAction == rhs.launchAction && lhs.profileAction == rhs.profileAction && lhs.analyzeAction == rhs.analyzeAction && lhs.archiveAction == rhs.archiveAction && lhs.lastUpgradeVersion == rhs.lastUpgradeVersion && lhs.version == rhs.version && lhs.name == rhs.name && lhs.wasCreatedForAppExtension == rhs.wasCreatedForAppExtension } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/BuildSettingsProvider.swift ================================================ import Foundation /// Class that provides default build settings to be used in Xcode projects. public class BuildSettingsProvider { /// Build settings variant. /// /// - all: all (debug & release). /// - debug: debug. /// - release: release. public enum Variant { case all, debug, release } /// Target platform. /// /// - iOS: iOS. /// - macOS: macOS. /// - tvOS: tvOS. /// - watchOS: watchOS. public enum Platform { case iOS, macOS, tvOS, watchOS } /// Target product type. /// /// - framework: framework. /// - staticLibrary: static library. /// - dynamicLibrary: dynamic library. /// - application: application. /// - bundle: bundle. public enum Product { case framework, staticLibrary, dynamicLibrary, application, bundle } /// Returns the default target build settings. /// /// - Parameters: /// - variant: build settings variant. /// - platform: target platform. /// - product: target product. /// - swift: true if the target contains Swift code. /// - Returns: build settings. // swiftlint:disable:next function_body_length public static func targetDefault(variant: Variant? = nil, platform: Platform?, product: Product?, swift: Bool? = nil) -> BuildSettings { var buildSettings: [String: Any] = [:] if let platform = platform, platform == .iOS { buildSettings["SDKROOT"] = "iphoneos" buildSettings["CODE_SIGN_IDENTITY"] = "iPhone Developer" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks" } if let platform = platform, platform == .macOS { buildSettings["SDKROOT"] = "macosx" buildSettings["CODE_SIGN_IDENTITY"] = "-" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks" } if let platform = platform, platform == .watchOS { buildSettings["SDKROOT"] = "watchos" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks" } if let platform = platform, platform == .tvOS { buildSettings["SDKROOT"] = "appletvos" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks" } if let platform = platform, let variant = variant, [.iOS, .watchOS, .tvOS].contains(platform), variant == .release { buildSettings["VALIDATE_PRODUCT"] = "YES" } if let variant = variant, let swift = swift, variant == .debug, swift == true { buildSettings["SWIFT_OPTIMIZATION_LEVEL"] = "-Onone" buildSettings["SWIFT_ACTIVE_COMPILATION_CONDITIONS"] = "DEBUG" } if let variant = variant, let swift = swift, variant == .release, swift == true { buildSettings["SWIFT_OPTIMIZATION_LEVEL"] = "-Owholemodule" buildSettings["SWIFT_ACTIVE_COMPILATION_CONDITIONS"] = "DEBUG" } if let product = product, product == .framework { buildSettings["CODE_SIGN_IDENTITY"] = "" buildSettings["CURRENT_PROJECT_VERSION"] = "1" buildSettings["DEFINES_MODULE"] = "YES" buildSettings["DYLIB_COMPATIBILITY_VERSION"] = "1" buildSettings["DYLIB_CURRENT_VERSION"] = "1" buildSettings["DYLIB_INSTALL_NAME_BASE"] = "@rpath" buildSettings["INSTALL_PATH"] = "$(LOCAL_LIBRARY_DIR)/Frameworks" buildSettings["PRODUCT_NAME"] = "$(TARGET_NAME:c99extidentifier)" buildSettings["SKIP_INSTALL"] = "YES" buildSettings["VERSION_INFO_PREFIX"] = "" buildSettings["VERSIONING_SYSTEM"] = "apple-generic" } if let platform = platform, let product = product, platform == .iOS, product == .framework { buildSettings["TARGETED_DEVICE_FAMILY"] = "1,2" } if let platform = platform, let product = product, platform == .macOS, product == .framework { buildSettings["COMBINE_HIDPI_IMAGES"] = "YES" buildSettings["FRAMEWORK_VERSION"] = "A" } if let platform = platform, let product = product, platform == .watchOS, product == .framework { buildSettings["APPLICATION_EXTENSION_API_ONLY"] = "YES" buildSettings["TARGETED_DEVICE_FAMILY"] = "4" } if let platform = platform, let product = product, platform == .tvOS, product == .framework { buildSettings["TARGETED_DEVICE_FAMILY"] = "3" } if let product = product, let swift = swift, product == .framework, swift == true { buildSettings["DEFINES_MODULE"] = "YES" } if let platform = platform, let product = product, platform == .iOS, product == .staticLibrary { buildSettings["OTHER_LDFLAGS"] = "-ObjC" buildSettings["SKIP_INSTALL"] = "YES" buildSettings["TARGETED_DEVICE_FAMILY"] = "1,2" } if let platform = platform, let product = product, platform == .watchOS, product == .staticLibrary { buildSettings["OTHER_LDFLAGS"] = "-ObjC" buildSettings["SKIP_INSTALL"] = "YES" buildSettings["TARGETED_DEVICE_FAMILY"] = "4" } if let platform = platform, let product = product, platform == .tvOS, product == .staticLibrary { buildSettings["OTHER_LDFLAGS"] = "-ObjC" buildSettings["SKIP_INSTALL"] = "YES" buildSettings["TARGETED_DEVICE_FAMILY"] = "3" } if let platform = platform, let product = product, platform == .macOS, product == .staticLibrary { buildSettings["EXECUTABLE_PREFIX"] = "lib" buildSettings["SKIP_INSTALL"] = "YES" } if let platform = platform, let product = product, platform == .macOS, product == .dynamicLibrary { buildSettings["DYLIB_COMPATIBILITY_VERSION"] = "1" buildSettings["DYLIB_CURRENT_VERSION"] = "1" buildSettings["EXECUTABLE_PREFIX"] = "lib" buildSettings["SKIP_INSTALL"] = "YES" } if let product = product, product == .application { buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] = "AppIcon" } if let platform = platform, let product = product, platform == .iOS, product == .application { buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/Frameworks" buildSettings["TARGETED_DEVICE_FAMILY"] = "1,2" } if let platform = platform, let product = product, platform == .watchOS, product == .application { buildSettings["SKIP_INSTALL"] = "YES" buildSettings["TARGETED_DEVICE_FAMILY"] = "4" } if let platform = platform, let product = product, platform == .tvOS, product == .application { buildSettings["ASSETCATALOG_COMPILER_APPICON_NAME"] = "App Icon & Top Shelf Image" buildSettings["ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME"] = "LaunchImage" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/Frameworks" buildSettings["TARGETED_DEVICE_FAMILY"] = "3" } if let platform = platform, let product = product, platform == .macOS, product == .application { buildSettings["COMBINE_HIDPI_IMAGES"] = "YES" buildSettings["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/../Frameworks" } if let platform = platform, let product = product, let swift = swift, platform == .watchOS, product == .application, swift == true { buildSettings["ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES"] = "YES" } if let product = product, product == .bundle { buildSettings["WRAPPER_EXTENSION"] = "bundle" buildSettings["SKIP_INSTALL"] = "YES" } if let product = product, let platform = platform, product == .bundle, platform == .macOS { buildSettings["COMBINE_HIDPI_IMAGES"] = "YES" buildSettings["INSTALL_PATH"] = "$(LOCAL_LIBRARY_DIR)/Bundles" buildSettings["SDKROOT"] = "macosx" } return buildSettings } /// Returns default build settings that Xcode sets in new projects. /// /// - Returns: build settings. public static func projectDefault(variant: Variant) -> BuildSettings { switch variant { case .all: return projectAll() case .debug: return projectDebug() case .release: return projectRelease() } } // MARK: - Private // swiftlint:disable:next function_body_length private static func projectAll() -> BuildSettings { return [ "ALWAYS_SEARCH_USER_PATHS": "NO", "CLANG_ANALYZER_NONNULL": "YES", "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION": "YES_AGGRESSIVE", "CLANG_CXX_LANGUAGE_STANDARD": "gnu++14", "CLANG_CXX_LIBRARY": "libc++", "CLANG_ENABLE_MODULES": "YES", "CLANG_ENABLE_OBJC_ARC": "YES", "CLANG_ENABLE_OBJC_WEAK": "YES", "CLANG_WARN__DUPLICATE_METHOD_MATCH": "YES", "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING": "YES", "CLANG_WARN_BOOL_CONVERSION": "YES", "CLANG_WARN_COMMA": "YES", "CLANG_WARN_CONSTANT_CONVERSION": "YES", "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS": "YES", "CLANG_WARN_DIRECT_OBJC_ISA_USAGE": "YES_ERROR", "CLANG_WARN_DOCUMENTATION_COMMENTS": "YES", "CLANG_WARN_EMPTY_BODY": "YES", "CLANG_WARN_ENUM_CONVERSION": "YES", "CLANG_WARN_INFINITE_RECURSION": "YES", "CLANG_WARN_INT_CONVERSION": "YES", "CLANG_WARN_NON_LITERAL_NULL_CONVERSION": "YES", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "YES", "CLANG_WARN_OBJC_LITERAL_CONVERSION": "YES", "CLANG_WARN_OBJC_ROOT_CLASS": "YES_ERROR", "CLANG_WARN_RANGE_LOOP_ANALYSIS": "YES", "CLANG_WARN_STRICT_PROTOTYPES": "YES", "CLANG_WARN_SUSPICIOUS_MOVE": "YES", "CLANG_WARN_UNGUARDED_AVAILABILITY": "YES_AGGRESSIVE", "CLANG_WARN_UNREACHABLE_CODE": "YES", "COPY_PHASE_STRIP": "NO", "ENABLE_STRICT_OBJC_MSGSEND": "YES", "GCC_C_LANGUAGE_STANDARD": "gnu11", "GCC_NO_COMMON_BLOCKS": "YES", "GCC_WARN_64_TO_32_BIT_CONVERSION": "YES", "GCC_WARN_ABOUT_RETURN_TYPE": "YES_ERROR", "GCC_WARN_UNDECLARED_SELECTOR": "YES", "GCC_WARN_UNINITIALIZED_AUTOS": "YES_AGGRESSIVE", "GCC_WARN_UNUSED_FUNCTION": "YES", "GCC_WARN_UNUSED_VARIABLE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", ] } private static func projectDebug() -> BuildSettings { return [ "DEBUG_INFORMATION_FORMAT": "dwarf", "ENABLE_TESTABILITY": "YES", "GCC_DYNAMIC_NO_PIC": "NO", "GCC_OPTIMIZATION_LEVEL": "0", "GCC_PREPROCESSOR_DEFINITIONS": ["DEBUG=1", "$(inherited)"], "MTL_ENABLE_DEBUG_INFO": "YES", "ONLY_ACTIVE_ARCH": "YES", ] } private static func projectRelease() -> BuildSettings { return [ "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", "ENABLE_NS_ASSERTIONS": "NO", "MTL_ENABLE_DEBUG_INFO": "NO", ] } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/CommentedString.swift ================================================ import Foundation /// String that includes a comment struct CommentedString { /// Entity string value. let string: String /// String comment. let comment: String? /// Initializes the commented string with the value and the comment. /// /// - Parameters: /// - string: string value. /// - comment: comment. init(_ string: String, comment: String? = nil) { self.string = string self.comment = comment } /// Set of characters that are invalid. private static var invalidCharacters: CharacterSet = { var invalidSet = CharacterSet(charactersIn: "_$") invalidSet.insert(charactersIn: UnicodeScalar(".") ... UnicodeScalar("9")) invalidSet.insert(charactersIn: UnicodeScalar("A") ... UnicodeScalar("Z")) invalidSet.insert(charactersIn: UnicodeScalar("a") ... UnicodeScalar("z")) invalidSet.invert() return invalidSet }() /// Substrings that cause Xcode to quote the string content. private let invalidStrings = [ "___", "//", ] /// Returns a valid string for Xcode projects. var validString: String { switch string { case "": return "".quoted case "false": return "NO" case "true": return "YES" default: break } var escaped = string // escape escape if escaped.contains("\\" as Character) { escaped = escaped.replacingOccurrences(of: "\\", with: "\\\\") } // escape quotes if escaped.contains("\"" as Character) { escaped = escaped.replacingOccurrences(of: "\"", with: "\\\"") } // escape tab if escaped.contains("\t" as Character) { escaped = escaped.replacingOccurrences(of: "\t", with: "\\t") } // escape newlines if escaped.contains("\n" as Character) { escaped = escaped.replacingOccurrences(of: "\n", with: "\\n") } if !escaped.isQuoted, escaped.rangeOfCharacter(from: CommentedString.invalidCharacters) != nil || invalidStrings.contains(where: { escaped.range(of: $0) != nil }) { escaped = escaped.quoted } return escaped } } // MARK: - Hashable extension CommentedString: Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(string) } static func == (lhs: CommentedString, rhs: CommentedString) -> Bool { return lhs.string == rhs.string && lhs.comment == rhs.comment } } // MARK: - ExpressibleByStringLiteral extension CommentedString: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.init(value) } public init(extendedGraphemeClusterLiteral value: String) { self.init(value) } public init(unicodeScalarLiteral value: String) { self.init(value) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/Decoders.swift ================================================ import Foundation /// Project object reference repository. class PBXObjectReferenceRepository { /// References. var references: [String: PBXObjectReference] = [:] let lock = NSRecursiveLock() /// Returns and creates if it doesn't exist an object reference. /// /// - Parameters: /// - reference: reference value. /// - objects: objects. /// - Returns: object reference. func getOrCreate(reference: String, objects: PBXObjects) -> PBXObjectReference { return lock.whileLocked { if let objectReference = references[reference] { return objectReference } let objectReference = PBXObjectReference(reference, objects: objects) references[reference] = objectReference return objectReference } } } /// Context used when the project is being decoded. class ProjectDecodingContext { /// Object reference repository. let objectReferenceRepository: PBXObjectReferenceRepository /// Objects. let objects: PBXObjects let pbxProjValueReader: ((String) -> Any?)? init(pbxProjValueReader: ((String) -> Any?)? = nil) { objectReferenceRepository = PBXObjectReferenceRepository() objects = PBXObjects(objects: []) self.pbxProjValueReader = pbxProjValueReader } } // MARK: - CodingUserInfoKey (Context) extension CodingUserInfoKey { /// Context user info key. static var context: CodingUserInfoKey = CodingUserInfoKey(rawValue: "context")! } /// Xcodeproj JSON decoder. class XcodeprojJSONDecoder: JSONDecoder { /// Default init. init(context: ProjectDecodingContext = ProjectDecodingContext()) { super.init() userInfo = [.context: context] } } /// Xcodeproj property list decoder. class XcodeprojPropertyListDecoder: PropertyListDecoder { /// Default init. init(context: ProjectDecodingContext = ProjectDecodingContext()) { super.init() userInfo = [.context: context] } } // MARK: - Decoder (Context) extension Decoder { /// Returns the decoding context. var context: ProjectDecodingContext { // swiftlint:disable:next force_cast return userInfo[.context] as! ProjectDecodingContext } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/JSONDecoding.swift ================================================ import Foundation // Inspired by https://gist.github.com/mbuchetics/c9bc6c22033014aa0c550d3b4324411a struct JSONCodingKeys: CodingKey { var stringValue: String init?(stringValue: String) { self.stringValue = stringValue } var intValue: Int? init?(intValue: Int) { self.init(stringValue: "\(intValue)") self.intValue = intValue } } extension KeyedDecodingContainer { func decode(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any] { // Optimization for root dictionary decoding if let decoder = try? superDecoder().context, let pbxProjValueReader = decoder.pbxProjValueReader, let result = pbxProjValueReader(key.stringValue) as? [String: Any] { return result } let container = try nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key) return try container.decode(type) } func decodeIfPresent(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any]? { guard contains(key) else { return nil } return try decode(type, forKey: key) } func decode(_ type: [Any].Type, forKey key: K) throws -> [Any] { var container = try nestedUnkeyedContainer(forKey: key) return try container.decode(type) } func decodeIfPresent(_ type: [Any].Type, forKey key: K) throws -> [Any]? { guard contains(key) else { return nil } return try decode(type, forKey: key) } func decode(_: [String: Any].Type) throws -> [String: Any] { var dictionary = [String: Any]() for key in allKeys { // Order is important for performance if let nestedDictionary = try? decode([String: Any].self, forKey: key) { dictionary[key.stringValue] = nestedDictionary } else if let intValue = try? decode(Int.self, forKey: key) { dictionary[key.stringValue] = intValue } else if let unsignedIntValue = try? decode(UInt.self, forKey: key) { dictionary[key.stringValue] = unsignedIntValue } else if let stringValue = try? decode(String.self, forKey: key) { dictionary[key.stringValue] = stringValue } else if let boolValue = try? decode(Bool.self, forKey: key) { dictionary[key.stringValue] = boolValue } else if let doubleValue = try? decode(Double.self, forKey: key) { dictionary[key.stringValue] = doubleValue } else if let nestedArray = try? decode([Any].self, forKey: key) { dictionary[key.stringValue] = nestedArray } else if try decodeNil(forKey: key) { dictionary[key.stringValue] = true } } return dictionary } } extension UnkeyedDecodingContainer { mutating func decode(_: [Any].Type) throws -> [Any] { var array: [Any] = [] while isAtEnd == false { if let value = try? decode(Bool.self) { array.append(value) } else if let value = try? decode(Double.self) { array.append(value) } else if let value = try? decode(String.self) { array.append(value) } else if let nestedDictionary = try? decode([String: Any].self) { array.append(nestedDictionary) } else if let nestedArray = try? decode([Any].self) { array.append(nestedArray) } } return array } mutating func decode(_ type: [String: Any].Type) throws -> [String: Any] { let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self) return try nestedContainer.decode(type) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/OSLogger.swift ================================================ import Foundation import os.signpost /// OSLog wrapper that runs logging functions if logging is enabled through /// environment variables and the feature is available in the system where /// the user is using the project. class OSLogger { /// Shared instance of OSLogger static var instance: OSLogger = OSLogger() /// Logs when the given closure starts and ends. /// /// - Parameters: /// - category: Category of the code being logged. For example, if it's a function in PBXObjectReference, that can be the category. /// - name: Name for the code being logged. If we are logging the time it takes to write a project, the name can be "Project Writing" /// - arguments: Arguments to be passed to the function. /// - closure: Piece of code that will be logged. /// - Throws: An error if the given closure throws. func log(category: String = #file, name: StaticString, _ arguments: CVarArg..., closure: () throws -> Void) throws { if !shouldLog { try closure() return } if #available(OSX 10.14, *) { let log: OSLog = OSLog.xcodeproj(category: category) let signpostID = OSSignpostID(log: log) os_signpost(.begin, log: log, name: name, signpostID: signpostID, "%{public}s", arguments) } try closure() if #available(OSX 10.14, *) { let log: OSLog = OSLog.xcodeproj(category: category) let signpostID = OSSignpostID(log: log) os_signpost(.end, log: log, name: name, signpostID: signpostID, "%{public}s", arguments) } } /// Logs when the given closure starts and ends. /// /// - Parameters: /// - category: Category of the code being logged. For example, if it's a function in PBXObjectReference, that can be the category. /// - name: Name for the code being logged. If we are logging the time it takes to write a project, the name can be "Project Writing" /// - arguments: Arguments to be passed to the function. /// - closure: Piece of code that will be logged. /// - Returns: The value returned by the closure. /// - Throws: An error if the given closure throws. func log(category: String = #file, name: StaticString, _ arguments: CVarArg..., closure: () throws -> T) throws -> T { if !shouldLog { return try closure() } if #available(OSX 10.14, *) { let log: OSLog = OSLog.xcodeproj(category: category) let signpostID = OSSignpostID(log: log) os_signpost(.begin, log: log, name: name, signpostID: signpostID, "%{public}s", arguments) } let result = try closure() if #available(OSX 10.14, *) { let log: OSLog = OSLog.xcodeproj(category: category) let signpostID = OSSignpostID(log: log) os_signpost(.end, log: log, name: name, signpostID: signpostID, "%{public}s", arguments) } return result } /// Returns true if the XCODEPROJ_OSLOG environment variable is defined in the environment. lazy var shouldLog: Bool = { ProcessInfo.processInfo.environment["XCODEPROJ_OSLOG"] != nil }() } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/PlistValue.swift ================================================ import Foundation /// It represents a plist value. /// /// - string: commented string. /// - array: array of plist values. /// - dictionary: dictionary where the keys are a commented strings and the values are a plist values. indirect enum PlistValue { case string(CommentedString) case array([PlistValue]) case dictionary([CommentedString: PlistValue]) var string: CommentedString? { switch self { case let .string(string): return string default: return nil } } var array: [PlistValue]? { switch self { case let .array(array): return array default: return nil } } var dictionary: [CommentedString: PlistValue]? { switch self { case let .dictionary(dictionary): return dictionary default: return nil } } } // MARK: - PlistValue Extension (ExpressibleByArrayLiteral) extension PlistValue: ExpressibleByArrayLiteral { public init(arrayLiteral elements: PlistValue...) { self = .array(elements) } } // MARK: - PlistValue Extension (ExpressibleByDictionaryLiteral) extension PlistValue: ExpressibleByDictionaryLiteral { public init(dictionaryLiteral elements: (CommentedString, PlistValue)...) { var dictionary: [CommentedString: PlistValue] = [:] elements.forEach { dictionary[$0.0] = $0.1 } self = .dictionary(dictionary) } } // MARK: - PlistValue Extension (ExpressibleByStringLiteral) extension PlistValue: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self = .string(CommentedString(value)) } public init(extendedGraphemeClusterLiteral value: String) { self = .string(CommentedString(value)) } public init(unicodeScalarLiteral value: String) { self = .string(CommentedString(value)) } } // MARK: PlistValue Extension (Equatable) extension PlistValue: Equatable { static func == (lhs: PlistValue, rhs: PlistValue) -> Bool { switch (lhs, rhs) { case let (.string(lhsString), .string(rhsString)): return lhsString == rhsString case let (.array(lhsArray), .array(rhsArray)): return lhsArray == rhsArray case let (.dictionary(lhsDictionary), .dictionary(rhsDictionary)): return lhsDictionary == rhsDictionary default: return false } } } // MARK: - Dictionary Extension (PlistValue) extension Dictionary where Key == String { func plist() -> PlistValue { var dictionary: [CommentedString: PlistValue] = [:] forEach { key, value in if let array = value as? [Any] { dictionary[CommentedString(key)] = array.plist() } else if let subDictionary = value as? [String: Any] { dictionary[CommentedString(key)] = subDictionary.plist() } else if let string = value as? CustomStringConvertible { dictionary[CommentedString(key)] = .string(CommentedString(string.description)) } } return .dictionary(dictionary) } } // MARK: - Array Extension (PlistValue) extension Array { func plist() -> PlistValue { return .array(compactMap({ (element) -> PlistValue? in if let array = element as? [Any] { return array.plist() } else if let dictionary = element as? [String: Any] { return dictionary.plist() } else if let string = element as? CustomStringConvertible { return PlistValue.string(CommentedString(string.description)) } return nil })) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/ReferenceGenerator.swift ================================================ import Foundation /// Generates the deterministic references of the project objects that have a temporary reference. /// When objects are added to the project, those are added with a temporary reference that other /// objects can refer to. Before saving the project, we make those references permanent giving them /// a deterministic value that depends on the object itself and its ancestor. protocol ReferenceGenerating: AnyObject { /// Generates the references of the objects of the given project. /// /// - Parameter proj: project whose objects references will be generated. /// - Parameter settings: settings to control the output references func generateReferences(proj: PBXProj) throws } /// Reference generator. final class ReferenceGenerator: ReferenceGenerating { let outputSettings: PBXOutputSettings var references: Set = [] init(outputSettings: PBXOutputSettings) { self.outputSettings = outputSettings } /// Generates the references of the objects of the given project. /// /// - Parameter proj: project whose objects references will be generated. func generateReferences(proj: PBXProj) throws { guard let project: PBXProject = try proj.rootObjectReference?.getThrowingObject() else { return } // cache current reference values var references: Set = [] proj.objects.forEach { object in if !object.reference.temporary { references.insert(object.reference.value) } } self.references = references // Projects, targets, groups and file references. // Note: The references of those type of objects should be generated first. /// We use them to generate the references of the objects that depend on them. /// For instance, the reference of a build file, is generated from the reference of /// the file it refers to. let identifiers = [project.name] generateProjectAndTargets(project: project, identifiers: identifiers) try generateGroupReferences(project.mainGroup, identifiers: identifiers) if let productsGroup: PBXGroup = project.productsGroup { try generateGroupReferences(productsGroup, identifiers: identifiers) } // Targets let targets: [PBXTarget] = project.targets try targets.forEach({ try generateTargetReferences($0, identifiers: identifiers) }) // Project references try project.projectReferences.flatMap({ $0.values }).forEach { objectReference in guard let fileReference: PBXFileReference = objectReference.getObject() else { return } try generateFileReference(fileReference, identifiers: identifiers) } /// Configuration list if let configurationList: XCConfigurationList = project.buildConfigurationListReference.getObject() { try generateConfigurationListReferences(configurationList, identifiers: identifiers) } } /// Generates the reference for the project and its target. /// /// - Parameters: /// - project: project whose reference will be generated. /// - identifiers: list of identifiers. private func generateProjectAndTargets(project: PBXProject, identifiers: [String]) { // Project fixReference(for: project, identifiers: identifiers) // Targets let targets: [PBXTarget] = project.targetReferences.objects() targets.forEach { target in var identifiers = identifiers identifiers.append(target.name) fixReference(for: target, identifiers: identifiers) } } /// Generates the reference for a group object. /// /// - Parameters: /// - group: group instance. /// - identifiers: list of identifiers. private func generateGroupReferences(_ group: PBXGroup, identifiers: [String]) throws { var identifiers = identifiers if let groupName = group.fileName() { identifiers.append(groupName) } // Group fixReference(for: group, identifiers: identifiers) // Children try group.childrenReferences.forEach { child in guard let childFileElement: PBXFileElement = child.getObject() else { return } if let childGroup = childFileElement as? PBXGroup { try generateGroupReferences(childGroup, identifiers: identifiers) } else if let childFileReference = childFileElement as? PBXFileReference { try generateFileReference(childFileReference, identifiers: identifiers) } } } /// Generates the reference for a file reference object. /// /// - Parameters: /// - fileReference: file reference instance. /// - identifiers: list of identifiers. private func generateFileReference(_ fileReference: PBXFileReference, identifiers: [String]) throws { var identifiers = identifiers if let groupName = fileReference.fileName() { identifiers.append(groupName) } fixReference(for: fileReference, identifiers: identifiers) } /// Generates the reference for a configuration list object. /// /// - Parameters: /// - configurationList: configuration list instance. /// - identifiers: list of identifiers. private func generateConfigurationListReferences(_ configurationList: XCConfigurationList, identifiers: [String]) throws { fixReference(for: configurationList, identifiers: identifiers) let buildConfigurations: [XCBuildConfiguration] = configurationList.buildConfigurations buildConfigurations.forEach { configuration in if !configuration.reference.temporary { return } var identifiers = identifiers identifiers.append(configuration.name) fixReference(for: configuration, identifiers: identifiers) } } /// Generates the reference for a target object. /// /// - Parameters: /// - target: target instance. /// - identifiers: list of identifiers. private func generateTargetReferences(_ target: PBXTarget, identifiers: [String]) throws { var identifiers = identifiers identifiers.append(target.name) // Configuration list if let configurationList = target.buildConfigurationList { try generateConfigurationListReferences(configurationList, identifiers: identifiers) } // Build phases let buildPhases: [PBXBuildPhase] = target.buildPhaseReferences.objects() try buildPhases.forEach({ try generateBuildPhaseReferences($0, identifiers: identifiers) }) // Build rules let buildRules: [PBXBuildRule] = target.buildRuleReferences.objects() try buildRules.forEach({ try generateBuildRules($0, identifiers: identifiers) }) // Dependencies let dependencies: [PBXTargetDependency] = target.dependencyReferences.objects() try dependencies.forEach({ try generateTargetDependencyReferences($0, identifiers: identifiers) }) } /// Generates the reference for a target dependency object. /// /// - Parameters: /// - targetDependency: target dependency instance. /// - identifiers: list of identifiers. private func generateTargetDependencyReferences(_ targetDependency: PBXTargetDependency, identifiers: [String]) throws { var identifiers = identifiers // Target proxy if let targetProxyReference = targetDependency.targetProxyReference, targetProxyReference.temporary, let targetProxy = targetDependency.targetProxy, let remoteGlobalIDReference = targetProxy.remoteGlobalIDReference { var identifiers = identifiers identifiers.append(remoteGlobalIDReference.value) fixReference(for: targetProxy, identifiers: identifiers) } // Target dependency if targetDependency.reference.temporary { if let targetReference = targetDependency.targetReference?.value { identifiers.append(targetReference) } if let targetProxyReference = targetDependency.targetProxyReference?.value { identifiers.append(targetProxyReference) } fixReference(for: targetDependency, identifiers: identifiers) } } /// Generates the reference for a build phase object. /// /// - Parameters: /// - buildPhase: build phase instance. /// - identifiers: list of identifiers. private func generateBuildPhaseReferences(_ buildPhase: PBXBuildPhase, identifiers: [String]) throws { var identifiers = identifiers if let name = buildPhase.name() { identifiers.append(name) } // Build phase fixReference(for: buildPhase, identifiers: identifiers) // Build files buildPhase.fileReferences.forEach { buildFileReference in if !buildFileReference.temporary { return } guard let buildFile: PBXBuildFile = buildFileReference.getObject() else { return } var identifiers = identifiers if let fileReference = buildFile.fileReference, let fileReferenceObject: PBXObject = fileReference.getObject() { identifiers.append(fileReferenceObject.reference.value) } fixReference(for: buildFile, identifiers: identifiers) } } /// Generates the reference for a build rule object. /// /// - Parameters: /// - buildRule: build phase instance. /// - identifiers: list of identifiers. private func generateBuildRules(_ buildRule: PBXBuildRule, identifiers: [String]) throws { var identifiers = identifiers if let name = buildRule.name { identifiers.append(name) } // Build rule fixReference(for: buildRule, identifiers: identifiers) } } extension ReferenceGenerator { /// Given a list of identifiers, it generates a deterministic reference for a PBXObject. /// /// - Parameters: /// - object: The object to generate a reference for /// - identifiers: list of identifiers used to generate the reference of the object. func fixReference(for object: T, identifiers: [String]) { if object.reference.temporary { var identifiers = identifiers if let context = object.context { identifiers.append(context) } let typeName = String(describing: type(of: object)) // Get acronym to be used as prefix for the reference. // PBXFileReference is turned to FR. let acronym = typeName .replacingOccurrences(of: "PBX", with: "") .replacingOccurrences(of: "XC", with: "") .filter { String($0).lowercased() != String($0) } var reference = "" var counter = 0 // Get the first reference that doesn't already exist repeat { counter += 1 reference = generateReferenceFrom(acronym: acronym, typeName: typeName, identifiers: identifiers, counter: counter) } while references.contains(reference) references.insert(reference) object.reference.fix(reference) } } private func generateReferenceFrom(acronym: String, typeName: String, identifiers: [String], counter: Int) -> String { let typeNameAndIdentifiers = ([typeName] + identifiers).joined(separator: "-") switch outputSettings.projReferenceFormat { case .withPrefixAndSuffix: let base = "\(acronym)_\(typeNameAndIdentifiers.md5.uppercased())" if counter > 1 { return "\(base)_\(counter)" } else { return base } case .xcode: return "\(acronym)_\(typeNameAndIdentifiers)_\(counter)".md5.uppercased() } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Utils/XCConfig.swift ================================================ import Foundation import PathKit public typealias XCConfigInclude = (include: Path, config: XCConfig) /// .xcconfig configuration file. public final class XCConfig { // MARK: - Attributes /// Configuration file includes. public var includes: [XCConfigInclude] /// Build settings public var buildSettings: BuildSettings // MARK: - Init /// Initializes the XCConfig file with its attributes. /// /// - Parameters: /// - includes: all the .xcconfig file includes. The order determines how the values get overriden. /// - dictionary: dictionary that contains the config. public init(includes: [XCConfigInclude], buildSettings: BuildSettings = [:]) { self.includes = includes self.buildSettings = buildSettings } /// Initializes the XCConfig reading the content from the file at the given path and parsing it. /// /// - Parameter path: path where the .xcconfig file is. /// - Parameter projectPath: path where the .xcodeproj is, for resolving project-relative includes. /// - Throws: an error if the config file cannot be found or it has an invalid format. public init(path: Path, projectPath: Path? = nil) throws { if !path.exists { throw XCConfigError.notFound(path: path) } let fileLines = try path.read().components(separatedBy: "\n") includes = fileLines .compactMap(XCConfigParser.configFrom(path: path, projectPath: projectPath)) var buildSettings: [String: String] = [:] fileLines .compactMap(XCConfigParser.settingFrom) .forEach { buildSettings[$0.key] = $0.value } self.buildSettings = buildSettings } } final class XCConfigParser { /// Given the path the line is being parsed from, it returns a function that parses a line, /// and returns the include path and the config that the include is pointing to. /// /// - Parameter path: path of the config file that the line belongs to. /// - Parameter projectPath: path where the .xcodeproj is, for resolving project-relative includes. /// - Returns: function that parses the line. static func configFrom(path: Path, projectPath: Path?) -> (String) -> (include: Path, config: XCConfig)? { return { line in includeRegex.matches(in: line, options: [], range: NSRange(location: 0, length: line.count)) .compactMap { (match) -> String? in if match.numberOfRanges == 2 { return NSString(string: line).substring(with: match.range(at: 1)) } return nil } .compactMap { pathString in let includePath: Path = Path(pathString) var config: XCConfig? do { // first try to load the included xcconfig relative to the current xcconfig config = try XCConfig(path: path.parent() + includePath, projectPath: projectPath) } catch (XCConfigError.notFound(_)) where projectPath != nil { // if that fails, try to load the included xcconfig relative to the project config = try? XCConfig(path: projectPath!.parent() + includePath, projectPath: projectPath) } catch { config = nil } return config.map { (includePath, $0) } } .first } } static func settingFrom(line: String) -> (key: String, value: String)? { return settingRegex.matches(in: line, options: [], range: NSRange(location: 0, length: line.count)) .compactMap { (match) -> (key: String, value: String)? in if match.numberOfRanges == 3 { let key: String = NSString(string: line).substring(with: match.range(at: 1)) let value: String = NSString(string: line).substring(with: match.range(at: 2)) return (key, value) } return nil } .first } // swiftlint:disable:next force_try private static var includeRegex = try! NSRegularExpression(pattern: "#include\\s+\"(.+\\.xcconfig)\"", options: .caseInsensitive) // swiftlint:disable:next force_try private static var settingRegex = try! NSRegularExpression(pattern: "^([a-zA-Z0-9_\\[\\]=\\*~]+)\\s*=\\s*(\"?.*?\"?)\\s*(?:;\\s*)?$", options: []) } // MARK: - XCConfig Extension (Equatable) extension XCConfig: Equatable { public static func == (lhs: XCConfig, rhs: XCConfig) -> Bool { if lhs.includes.count != rhs.includes.count { return false } for index in 0 ..< lhs.includes.count { let lhsInclude = lhs.includes[index] let rhsInclude = rhs.includes[index] if lhsInclude.config != rhsInclude.config || lhsInclude.include != rhsInclude.include { return false } } return NSDictionary(dictionary: lhs.buildSettings).isEqual(to: rhs.buildSettings) } } // MARK: - XCConfig Extension (Helpers) extension XCConfig { /// It returns the build settings after flattening all the includes. /// /// - Returns: build settings flattening all the includes. public func flattenedBuildSettings() -> [String: Any] { var content: [String: Any] = buildSettings includes .map { $0.1 } .flattened() .map { $0.buildSettings } .forEach { configDictionary in configDictionary.forEach { key, value in if content[key] == nil { content[key] = value } } } return content } } // MARK: - XCConfig Extension (Writable) extension XCConfig: Writable { public func write(path: Path, override: Bool) throws { var content = "" content.append(writeIncludes()) content.append("\n") content.append(writeBuildSettings()) if override, path.exists { try path.delete() } try path.write(content) } private func writeIncludes() -> String { var content = "" includes.forEach { include in content.append("#include \"\(include.0.string)\"\n") } content.append("\n") return content } private func writeBuildSettings() -> String { var content = "" buildSettings.forEach { key, value in content.append("\(key) = \(value)\n") } content.append("\n") return content } } // MARK: - Array Extension (XCConfig) extension Array where Element == XCConfig { /// It returns an array with the XCConfig reversely flattened. It's useful for resolving the build settings. /// /// - Returns: flattened configurations array. func flattened() -> [XCConfig] { let reversed = self.reversed() .flatMap { (config) -> [XCConfig] in var configs = [XCConfig(includes: [], buildSettings: config.buildSettings)] configs.append(contentsOf: config.includes.map { $0.1 }.flattened()) return configs } return reversed } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspace.swift ================================================ import Foundation import PathKit /// Model that represents a Xcode workspace. public final class XCWorkspace: Writable, Equatable { /// Workspace data public var data: XCWorkspaceData // MARK: - Init /// Initializes the workspace with the path where the workspace is. /// The initializer will try to find an .xcworkspacedata inside the workspace. /// If the .xcworkspacedata cannot be found, the init will fail. /// /// - Parameter path: .xcworkspace path. /// - Throws: throws an error if the workspace cannot be initialized. public convenience init(path: Path) throws { if !path.exists { throw XCWorkspaceError.notFound(path: path) } let xcworkspaceDataPaths = path.glob("*.xcworkspacedata") if xcworkspaceDataPaths.isEmpty { self.init() } else { try self.init(data: XCWorkspaceData(path: xcworkspaceDataPaths.first!)) } } /// Initializes a default workspace with a single reference that points to self: public convenience init() { let data = XCWorkspaceData(children: [.file(.init(location: .self("")))]) self.init(data: data) } /// Initializes the workspace with the path string. /// /// - Parameter pathString: path string. /// - Throws: throws an error if the initialization fails. public convenience init(pathString: String) throws { try self.init(path: Path(pathString)) } /// Initializes the workspace with its properties. /// /// - Parameters: /// - data: workspace data. public init(data: XCWorkspaceData) { self.data = data } // MARK: - Writable public func write(path: Path, override: Bool = true) throws { let dataPath = path + "contents.xcworkspacedata" if override, dataPath.exists { try dataPath.delete() } try dataPath.mkpath() try data.write(path: dataPath) } // MARK: - Equatable public static func == (_: XCWorkspace, rhs: XCWorkspace) -> Bool { return rhs.data == rhs.data } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspaceData.swift ================================================ import AEXML import Foundation import PathKit public final class XCWorkspaceData { public var children: [XCWorkspaceDataElement] public init(children: [XCWorkspaceDataElement]) { self.children = children } } extension XCWorkspaceData: Equatable { public static func == (_: XCWorkspaceData, rhs: XCWorkspaceData) -> Bool { return rhs.children == rhs.children } } extension XCWorkspaceData: Writable { /// Initializes the workspace with the path where the workspace is. /// The initializer will try to find an .xcworkspacedata inside the workspace. /// If the .xcworkspacedata cannot be found, the init will fail. /// /// - Parameter path: .xcworkspace path. /// - Throws: throws an error if the workspace cannot be initialized. public convenience init(path: Path) throws { if !path.exists { throw XCWorkspaceDataError.notFound(path: path) } let xml = try AEXMLDocument(xml: path.read()) let children = try xml .root .children .compactMap(XCWorkspaceDataElement.init(element:)) self.init(children: children) } // MARK: - public func write(path: Path, override: Bool = true) throws { let document = AEXMLDocument() let workspace = document.addChild(name: "Workspace", value: nil, attributes: ["version": "1.0"]) _ = children .map({ $0.xmlElement() }) .map(workspace.addChild) if override, path.exists { try path.delete() } try path.write(document.xmlXcodeFormat) } } // MARK: - XCWorkspaceDataElement AEXMLElement decoding and encoding private extension XCWorkspaceDataElement { init(element: AEXMLElement) throws { switch element.name { case "FileRef": self = try .file(XCWorkspaceDataFileRef(element: element)) case "Group": self = try .group(XCWorkspaceDataGroup(element: element)) default: throw Error.unknownName(element.name) } } func xmlElement() -> AEXMLElement { switch self { case let .file(fileRef): return fileRef.xmlElement() case let .group(group): return group.xmlElement() } } } // MARK: - XCWorkspaceDataGroup AEXMLElement decoding and encoding private extension XCWorkspaceDataGroup { enum Error: Swift.Error { case wrongElementName case missingLocationAttribute } convenience init(element: AEXMLElement) throws { guard element.name == "Group" else { throw Error.wrongElementName } guard let location = element.attributes["location"] else { throw Error.missingLocationAttribute } let locationType = try XCWorkspaceDataElementLocationType(string: location) let name = element.attributes["name"] let children = try element.children.map(XCWorkspaceDataElement.init(element:)) self.init(location: locationType, name: name, children: children) } func xmlElement() -> AEXMLElement { var attributes = ["location": location.description] attributes["name"] = name let element = AEXMLElement(name: "Group", value: nil, attributes: attributes) _ = children .map({ $0.xmlElement() }) .map(element.addChild) return element } } // MARK: - XCWorkspaceDataFileRef AEXMLElement decoding and encoding private extension XCWorkspaceDataFileRef { enum Error: Swift.Error { case wrongElementName case missingLocationAttribute } convenience init(element: AEXMLElement) throws { guard element.name == "FileRef" else { throw Error.wrongElementName } guard let location = element.attributes["location"] else { throw Error.missingLocationAttribute } self.init(location: try XCWorkspaceDataElementLocationType(string: location)) } func xmlElement() -> AEXMLElement { return AEXMLElement(name: "FileRef", value: nil, attributes: ["location": location.description]) } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspaceDataElement.swift ================================================ import Foundation public enum XCWorkspaceDataElement { public enum Error: Swift.Error { case unknownName(String) } case file(XCWorkspaceDataFileRef) case group(XCWorkspaceDataGroup) } extension XCWorkspaceDataElement: Equatable { public static func == (lhs: XCWorkspaceDataElement, rhs: XCWorkspaceDataElement) -> Bool { switch (lhs, rhs) { case let (.file(lhs), .file(rhs)): return lhs == rhs case let (.group(lhs), .group(rhs)): return lhs == rhs default: return false } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspaceDataElementLocationType.swift ================================================ import Foundation public enum XCWorkspaceDataElementLocationType { public enum Error: Swift.Error { case missingSchema } case absolute(String) // "Absolute path" case container(String) // "Relative to container" case developer(String) // "Relative to Developer Directory" case group(String) // "Relative to group" case `self`(String) // Single project workspace in xcodeproj directory case other(String, String) public var schema: String { switch self { case .absolute: return "absolute" case .container: return "container" case .developer: return "developer" case .group: return "group" case .self: return "self" case let .other(schema, _): return schema } } public var path: String { switch self { case let .absolute(path): return path case let .container(path): return path case let .developer(path): return path case let .group(path): return path case let .self(path): return path case let .other(_, path): return path } } public init(string: String) throws { let elements = string.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false) guard let schema = elements.first.map(String.init) else { throw Error.missingSchema } let path = String(elements.last ?? "") switch schema { case "absolute": self = .absolute(path) case "container": self = .container(path) case "developer": self = .developer(path) case "group": self = .group(path) case "self": self = .self(path) default: self = .other(schema, path) } } } extension XCWorkspaceDataElementLocationType: CustomStringConvertible { public var description: String { return "\(schema):\(path)" } } extension XCWorkspaceDataElementLocationType: Equatable { public static func == (lhs: XCWorkspaceDataElementLocationType, rhs: XCWorkspaceDataElementLocationType) -> Bool { switch (lhs, rhs) { case let (.absolute(lhs), .absolute(rhs)): return lhs == rhs case let (.container(lhs), .container(rhs)): return lhs == rhs case let (.developer(lhs), .developer(rhs)): return lhs == rhs case let (.group(lhs), .group(rhs)): return lhs == rhs case let (.self(lhs), .self(rhs)): return lhs == rhs case let (.other(lhs), .other(rhs)): return lhs.0 == rhs.0 && lhs.1 == rhs.1 default: return false } } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspaceDataFileRef.swift ================================================ import Foundation public final class XCWorkspaceDataFileRef { public var location: XCWorkspaceDataElementLocationType public init(location: XCWorkspaceDataElementLocationType) { self.location = location } } extension XCWorkspaceDataFileRef: Equatable { public static func == (lhs: XCWorkspaceDataFileRef, rhs: XCWorkspaceDataFileRef) -> Bool { return lhs.location == rhs.location } } ================================================ FILE: Dependencies/tuist∕xcodeproj-6.6.0/Workspace/XCWorkspaceDataGroup.swift ================================================ import Foundation public final class XCWorkspaceDataGroup { public var location: XCWorkspaceDataElementLocationType public var name: String? public var children: [XCWorkspaceDataElement] public init(location: XCWorkspaceDataElementLocationType, name: String?, children: [XCWorkspaceDataElement]) { self.location = location self.name = name self.children = children } } extension XCWorkspaceDataGroup: Equatable { public static func == (lhs: XCWorkspaceDataGroup, rhs: XCWorkspaceDataGroup) -> Bool { return lhs.location == rhs.location && lhs.name == rhs.name && lhs.children == rhs.children } } ================================================ FILE: Documents/Advanced-Module-Hierarchies.md ================================================ # Advanced Module Hierarchies There are some additional rules for hierarchies: . └ Sources └ Model ├ foo.swift ├ Module1 │ ├ a.swift │ └ b.swift └ Module2 ├ c.swift └ d.swift Here `foo.swift` is part of the “base” module that by default is called `Bakeware`, all modules depend on the base-module. . └ Sources └ Model ├ Module1 │ ├ a.swift │ └ b.swift └ Module2 ├ c.swift └ d.swift Here there is no “base” module. `Module1` cannot not import `Module2`. . └ Sources └ Model ├ Module1 │ ├ a.swift │ └ b.swift │ └ Module3 │ ├ c.swift │ └ d.swift └ Module2 ├ c.swift └ d.swift `Module3` has a direct dependency on `Module1`, but also depends on (and can import) `Module1`. A module can always import all of the modules at the level below it. The direct-dependency is your choice and suggests a closer relationship. . └ Sources └ Model ├ Module1 │ ├ a.swift │ ├ b.swift │ └ Module3 │ ├ c.swift │ └ d.swift └ Module2 ├ c.swift ├ d.swift └ Module4 ├ c.swift └ d.swift `Module3` **cannot** import `Module4`. . └ Sources └ Model └ Module1 ├ a.swift ├ b.swift └ Gap | └ Module2 | ├ c.swift | └ d.swift └ Module2 ├ c.swift └ d.swift Here because of the empty `Gap` folder, `Module2` cannot import `Module1`, but still depends on `Module1`. Use gaps where you want to insulate some dependency relationships. ================================================ FILE: Documents/Cakefile.md ================================================ # The Cakefile Your Cakefile defines your dependencies, and some other properties of your generated project. ## The `import` You need the `import`: ```swift import Cakefile ``` ## Dependencies ```swift dependencies = [ .github("mxcl/Path.swift" ~> 0.9), .git("https://mygit.place/repo" == 2.4) ] ``` If you need more specific version specifications, this is possible: ```swift let branch = "fix-remote-target-dependency" var xcodeproj = GitHubPackageSpecification(user: "mxcl", repo: "xcodeproj", constraint: .ref(.branch(branch))) dependencies.append(xcodeproj) let foo = PackageSpecification(url: "https://mygit.place/repo", constraint: .ref(.branch("foo"))) dependencies.append(foo) ``` ## Options We provide some options that change the project generation properties: ```swift options.baseModuleName = "Bakeware" ``` The `baseModuleName` is the name of the root module in your model. ```swift options.suppressDependencyWarnings = true ``` This will suppress all warnings in your dependencies, it defaults to `true` since you have no easy control over them. ================================================ FILE: Documents/FAQ.md ================================================ # FAQ ## What does integration do? Not much. * We create a `.cake` directory and a `Cakefile.swift` (you can delete that if you don’t want Cake to manage your dependencies) in your project directory. * It adds a “blue folder” in your Xcode project for your Model. * It adds a reference to `.cake/Cake.xcodeproj` in your Xcode project. * It makes your application-target link to `Cake.a` and depend on the `Cake` target. * We add a few entries to your `.gitignore` ## How do I deintegrate Cake? 1. Delete `.cake` 2. Delete `Cakefile.swift` 3. Remove the `Cake.xcodeproj` reference from your project 4. Remove the `Model` blue-folder from your project 5. Remove the entries about Cake in your `.gitignore` ## What should I commit? We recommend committing `.cake` and `Dependencies`. This way anyone can check out your project and build your app, and they **don’t** need Cake.app to do so. Specifically ignore: `.cake/*.json` Developers working on your project will benefit from having Cake.app installed, but it *isn’t required*. Working on your project without Cake.app means they will not get any of Cake’s automagical features, eg. buildable model generation. If you don’t want to commit anything that is generated then add `.cake` to your `.gitignore`. > Though this means you are also ignoring `.cake/Package.resolved` which is your dependency-pin-file, without this co-workers may have different versions of their dependencies to you which can make debugging issues harder. Note open a PR to allow configuration of the location of this file in `Cakefile.swift`. ## Should I commit my deps? Yeah, you should. Because your dependencies came from the Internet, and the Internet is not a consistent or stable place. There is no guarantee your deps will exist next week, tomorrow or even five seconds from now. We should never forget [leftpad]. Also, committing your deps *guarantees* everyone on your team is using the same codebase and not some subtely different set of dependencies. And committing your deps means people can clone your project and build it without needing any other tools. [leftpad]: https://arstechnica.com/information-technology/2016/03/rage-quit-coder-unpublished-17-lines-of-javascript-and-broke-the-internet/ ## I don’t want to use Cake for dependencies It’s not mandatory. If you don’t specify dependencies in your `Cakefile` everything works fine and there any ugly build artifacts are either deleted or never created. You could even delete your `Cakefile`. ## Why can modules import ancestors? What we mean is, for the following: . ├─ Foo │ ├─ Bar │ └─ Baz └─ Faz Foo can `import Bar`. Strictly this does not work for a clean build, Xcode will fail to find the module in that case. This happens because the modules are all built to the same directory so they can see each other. We should be able to fix this and [plan to](../../issues/13). ## What Swift version is used for compiling modules? It is extracted from your base project. Dependencies specify their own Swift versions. ## How do I stay up‐to‐date? Follow [mxcl](https://twitter.com/mxcl) on Twitter, he strictly only tweets about Cake, Swift and Open Source. ## Can I make dependencies “editable”? Yes, this is a SwiftPM feature and since we use SwiftPM for dependency mangement, it’s the same: ```bash swift package --package-path .cake --build-path .cake/swift-pm edit foo ``` You will need to force a manual regeneration, ([this is a bug](../../issues/new?title=editable-deps)) but after that you will be able to edit the package in Xcode. Make sure you push your changes and make a pull-request! ================================================ FILE: Documents/Suggested-Usage.md ================================================ # Suggested Usage ## 1 `import` precise Batter modules from within Batter modules. In your app `import Cake`. In Batter import `Dependencies`. This means you are being aware of the right relative encapsulation when working in the different parts of your project. Trying to keep all the different levels in mind at all times is a waste of cognitive load better spent figuring out your actual code. Being precise in your models means you are acutely aware of your internal dependency graph. ## 2 Be judicious with modules. This allows you to use internal access control liberally and have eg. an Error enum per module. If you find yourself needing more than one error enum, maybe this is a hint that it's time to figure out where to split this module into two. ## Precisely specify `import`s If you are only using a small portion of a module specify that, for example, don’t: ```swift import Foo ``` Instead: ``` import enum Foo.Bar ``` This is instructive to you and others using your code, that this file is only concerned with a portion of module `Foo`; not its entirety. If you start importing more and more then switch to `import Foo`, since you are wasting your reader’s time, and also, you now use the majority of `Foo`. Use your judgement: this suggestion is a legibility aid. ## Model Purity Attempt to keep your model “pure”, that is, do not manipulate global state, this includes `UserDefaults`, and controlling the implementations of how input and output occur. Obviously within reason, it would be a pretty lame database module that couldn’t persist and fetch data. Apply this suggestion with common sense. ## Xcode navigation We provide a blue folder for your Model that is the direct directory structure, with this you can see the module heriarchy. In the embedded Cake.xcodeproj there is also a flat, topologically sorted module listing. Use both (along with `⌘⇧O`) when navigating your module structures. ================================================ FILE: Documents/Troubleshooting.md ================================================ Please note, most of the solutions are: **fully clean and then restart Xcode**. # Troubleshooting Xcode builds modules in parallel, it is able to build modules before their dependencies have finished building to a certain extent. This results in spurious errors being output during builds that will later disappear. So the first rule is: **Let the build finish before reacting to errors that don’t make sense** Generally it can help to create schemes for Batter or even individual modules in Batter and build those individually, this will stop Xcode surfacing the wrong errors, and often, deleting the errors that are actually the root cause. *sigh* Xcode 10 seems buggy when it comes to reloading changed projects from disk. If project navigator is wrong, restart Xcode. You may get errors in dependent modules when trying to use new API from higher modules. Xcode doesn’t know about the changes you make in higher modules in the lower ones until you build. So: `⌘B`. ## Beach-balling Cake 1.0.0 is not multi-threaded (I know: lol), so give it a bit, it can take minutes if it is checking out deps. ## Changes are not present in build Sadly Xcode 10.2 seems to have a bug where static libraries that are themselves just accumulations of other static libraries are not always rebuilt. The only easy solution is cleaning the build :( Or you can open the build folder and delete `Cake.a`, `Batter.a` and the `.a` for the module you changed and then build. If this isn’t fixed for 10.2 GM we will build a single Cake.framework instead (for debug builds) which should fix it. ## No syntax highlighting in new files Xcode 10 regressed many aspects of “blue folder” work. One of which is where syntax highlighting and completion will sometimes not work in new files. Restart Xcode. ## No such module 'Foo' This error is misleading, it actually means a dependency of Foo failed to build. Look at the other errors Xcode is showing you, at least one will concern a dependency of Foo, and that is the error you need to tackle. ## “Find selected symbol in workspace” doesn’t work Xcode only searches within the currently selected scheme, eg. if you want to search in your iOS app and the macOS app is selected it will only find references in the macOS codebase. This is an unfortunate “feature” of Xcode. ## No autocomplete when typing `import foo` in Model module We have no known workaround for this yet, if you have one, please submit. For now, type it, the import will succeed if the module exists and your dependency heirarchy is correct. ## New Blue Folders Empty in Xcode 10.x Xcode 10.x broke blue folders pretty substantially, if you blue folders are empty but do *actually* contains files, restart Xcode. ## Regeneration doesn’t produce new Batter modules Xcode 10.x is broken, we *did* regenerate the modules, but Xcode is ignoring the changes. Fully clean and then restart Xcode. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ ![Cake](../gh-pages/Cake.png) **We are aware of Xcode 11, probably don’t commit to Cake at this time** Modules are a powerful Swift feature, yet existing tooling makes modulizing your projects *so* tedious that most people don’t bother. A modular app gains: * **Encapsulation**. Internal scope is a criminally under-utilized Swift feature that makes encapsulation significantly more achievable. * **Namespacing**. Modules have an implicit namespace; fear not about reusing names, modulize instead. * **Hierarchy**. Once you start creating modules you automatically arrange them so that some have more importance than others. This naturally leads to a *structured* codebase where new files nestle into their logical, encapsulated homes, *effortlessly*. * **Organization**. You no longer have to cram everything concerning an area of responsibility into a single file to gain from file-private. Instead separate all that code out into multiple files in its own module and use `internal` access control. * **Testability**. Making a piece of functionality its own module means you can make more of that module internal scope rather than private and this means more of the module can be imported `@testable` making the functionality easier to test without adopting practices that make your code less readable for the sake of testing (like injection). Cake makes working with Swift modules *a breeze*. # Xcode 10.2-beta Required Supporting Swift tools-version-5 and tools-version-4 is not our thing. Cake requires at least Xcode 10.2 to function. # Support Cake’s development Hey there, I’m Max Howell, a prolific producer of open source software and probably you already use some of it (I created [`brew`]). I work full-time on open source and it’s hard; currently *I earn less than minimum wage*. Please help me continue my work, I appreciate it 🙏🏻 [Other ways to say thanks](http://mxcl.dev/#donate). [`brew`]: https://brew.sh # How it works > “The secret of getting ahead is getting started. The secret of getting started > is breaking your complex overwhelming tasks into small, manageable tasks, and > then starting on the first one.” —*Mark Twain* Cake is an app that runs in your menu bar and watches your Xcode projects. If you chose to integrate Cake into your App’s xcodeproj it will automatically generate your module hierarchy based on your directory structure. For example: . └ Sources └ Model ├ Module1 │ ├ a.swift │ └ b.swift └ Module2 ├ c.swift └ d.swift Now **⌘B** and you’ll be able to `import`: ```swift import Module1 import Module2 ``` > **FAQ**: What is a cake project? A Cake project has a `Cakefile.swift` file > in its root. > **Delicious**: All your modules are built *statically* so there’s no > launch-time consequences. > **Curious?** Cake is made with Cake, so is [Workbench], check out the sources > to see more about what a cake‐project looks like. > **Details**: Cake generates a sub-project (Cake.xcodeproj), you *lightly* > integrate this into your app’s project. [Workbench]: https://github.com/mxcl/Workbench ## Module hierarchies > “You’ve got to think about the big things while you’re doing small things, so > that all the small things go in the right direction.” —*Alvin Toffler* Before long you will need some modules to depend on others. This is an important step since you are starting to acknowledge the relationships between components in your codebase. Cake makes declaring dependencies as easy as nesting directories. . └ Sources └ Model └ Base ├ a.swift ├ b.swift └ Foo ├ c.swift └ d.swift Here `Foo` depends on `Base` and thus, `Foo` can *now* import `Base`. *All* other tools require you to specify relationships *cryptically*, either textually or with a confounding GUI. With Cake, use the filesystem, relationships are not only easy to read, but also, trivial to refactor (just move the directory). > **Further Reading**: [Advanced module hierarchies](Documents/Advanced-Module-Hierarchies.md) > **FAQ**: What should go in your `Base` module? Cake’s `Base` module contains > extensions on the standard library. ## Dependencies > “You can do anything, but not everything.” —*David Allen* Cake makes using Swift packages in Xcode easy. Write out your [`Cakefile`](Documents/Cakefile.md), **⌘B**, Cake fetches your deps and integrates them: no muss, no fuss. ```swift import Cakefile dependencies = [ .github("mxcl/Path.swift" ~> 0.8), .github("Weebly/OrderedSet" ~> 3), ] // ^^ naturally, using Cake to manage your deps is entirely optional ``` We figure out your deployment targets, we make your deps available to *all* your targets and we generate a stub module that imports all your deps in one line (`import Dependencies`). We check out your dependencies *tidily*, for example the above `Cakefile` gives you: . └ Dependencies ├ mxcl/Path.swift-0.8.0 │ ├ Path.swift │ └ … └ Weebly∕OrderedSet-3.1.0.swift Which generates this in your `Cake.xcodeproj`: Which you can then commit, *or not commit*: that’s up to you. [Though we suggest you do](Documents/FAQ.md#should-i-commit-my-deps). > **Delicious**: All dependency modules are built *statically* so there are no > launch-time consequences. > **Delicious**: A fresh clone of a Cake project builds with vanilla Xcode, > no other tools (even Cake) are required. Distribute away *without* worry! > **Delicious**: Cake finally makes it possible to use SwiftPM packages for iOS > development! > **FAQ**: [Should I commit my deps?](Documents/FAQ.md#should-i-commit-my-deps) > **Caveat**: We only support SwiftPM dependencies [*at this time*](../../issues/new?title=cocoapods). > **Further Reading**: [Cakefile Reference] [more with your Cakefile]: Documents/Cakefile.md ### Carthage & CocoaPods If your app uses Carthage or CocoaPods we detect that and integrate them so your cake modules (the `Batter`) can use these dependencies. Note, this only applies to cake modules (the `Batter`); for your App target follow the instructions provided by CocoaPods and Carthage themselves; nothing is different. ### Op‐Ed—an era for Swift µ-frameworks? CocoaPods and Carthage libraries tend to be on the *large* side, and this is at least partly because being modular has been historically hard and tedious when developing for Apple platforms and Swift. SwiftPM encourages smaller, tighter frameworks and using Cake means making apps with Swift packages is now possible. Choose small, modular, single‐responsibility libraries with 100% code coverage that take semantic-versioning **seriously**. Reject bloated libraries that don’t know how to say no to feature requests. ## Constructing frameworks/dylibs Since everything Cake builds is a static archive, you can simply link whichever parts you like into whatever Frameworks or dylibs you need for your final binaries. This is a purely optional step, statically linking `Cake.a` into your App (which Cake sets up by default for you) is perfectly fine. This more advanced option is available to make apps with extensions more optimal in terms of disk usage and memory consumption. # Installation 1. [Download it](../../releases). 2. Run it. 3. Check your menu bar: 4. Open a project and integrate Cake; or 5. Create a new Cake. > **FAQ**: [What does integration do?](Documents/FAQ.md#what-does-integration-do) > **Delicious**: We auto-update! # Bonus Features ## Extracting your app’s version from Git Cake determines your App’s version from your git tags, to use them simply set each target’s “Version” to: `$(SEMANTIC_PROJECT_VERSION)` and if you like the “Build” number to: `$(CURRENT_PROJECT_VERSION)`. > *Delicious!* We even append `-debug` to debug builds. ## Xcode Remote Control # Caveats Due to some Xcode bugs Cake is not a complete *Cake‐walk* in use. Please see our [troubleshooting](Documents/Troubleshooting.md) guide for details. # Documentation * Handbook * [FAQ](Documents/FAQ.md) * [Suggested Usage](Documents/Suggested-Usage.md) * [Troubleshooting](Documents/Troubleshooting.md) * Reference * [Cakefile Reference] * [Advanced Module Hierarchies](Documents/Advanced-Module-Hierarchies.md) [Cakefile Reference]: Documents/Cakefile.md # Icons credit Icons made by [Google](https://www.flaticon.com/authors/google) and [Freepik](https://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com) licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/). ================================================ FILE: Sources/AppKit/AppDelegate+NSMenu.swift ================================================ import AppKit import Cake extension AppDelegate: NSMenuDelegate { @objc func regenerate(sender: NSMenuItem) { guard let index = sender.parent?.tag else { return } do { let cake = kitchen.cakes[index] try cake.forceRegenerate() kitchen(regenerated: cake) // shows notification } catch { alert(error) } } func updateStatusItemMenu(cake: [CakeProject], notCake: [String]) { func notCakeMenu(index: Int) -> NSMenu { let menu = NSMenu() menu.addItem(withTitle: "Integrate Cake", action: #selector(integrateCake), keyEquivalent: "") return menu } func cakeMenu(for cake: CakeProject, index: Int) -> NSMenu { let menu = NSMenu() menu.addItem(withTitle: "Update Dependencies", action: #selector(updateDependencies), keyEquivalent: "") menu.addItem(.separator()) menu.addItem(withTitle: "Regenerate Cake.xcodeproj", action: #selector(regenerate), keyEquivalent: "") menu.addItem(withTitle: "", action: nil, keyEquivalent: "") // menu.addItem(.separator()) // menu.addItem(withTitle: "Deintegrate Cake", action: #selector(deintegrateCake), keyEquivalent: "").tag = index menu.delegate = self return menu } menu.removeAllItems() for (index, cake) in cake.enumerated() { let item = menu.addItem(withTitle: cake.name, action: nil, keyEquivalent: "") item.submenu = cakeMenu(for: cake, index: index) item.tag = index } for (index, item) in notCake.enumerated() { let item = menu.addItem(withTitle: item, action: nil, keyEquivalent: "") item.submenu = notCakeMenu(index: index) item.tag = index } if cake.isEmpty, notCake.isEmpty { menu.addItem(withTitle: "No Xcode projects open", action: nil, keyEquivalent: "") } fillMenuBottom() } func fillMenuBottom() { menu.addItem(.separator()) let newCake = menu.addItem(withTitle: "New Cake", action: nil, keyEquivalent: "") let xcode = menu.addItem(withTitle: "Xcode", action: nil, keyEquivalent: "") xcode.submenu = { let menu = NSMenu(title: "Xcode") let item = menu.addItem(withTitle: "Open Active Project in Terminal", action: #selector(openActiveWorkspaceInTerminal), keyEquivalent: "t") item.keyEquivalentModifierMask = [.command, .option, .control] menu.addItem(.separator()) menu.addItem(withTitle: "rm -rf 'Derived Data'", action: #selector(derivedDataDance), keyEquivalent: "") menu.addItem(.separator()) menu.addItem(withTitle: "Quit Xcode", action: #selector(quitXcode), keyEquivalent: "") return menu }() menu.addItem(.separator()) menu.addItem(withTitle: "Quit Cake \(Bundle.main.version)", action: #selector(NSApplication.terminate), keyEquivalent: "") newCake.submenu = NSMenu() newCake.submenu!.addItem(withTitle: "macOS", action: #selector(createNewCake), keyEquivalent: "") newCake.submenu!.addItem(withTitle: "iOS", action: #selector(createNewCake), keyEquivalent: "") } func menuWillOpen(_ menu: NSMenu) { let item = menu.items[3] let index = item.tag let time = kitchen.cakes[index].lastGenerationTime.relativeTimeString item.title = "Last generated \(time)" } } private extension Optional where Wrapped == Date { var relativeTimeString: String { switch self { case .none: return "never" case .some(let date): let formatter = DateFormatter() formatter.dateStyle = .long formatter.timeStyle = .short formatter.doesRelativeDateFormatting = true formatter.formattingContext = .middleOfSentence return formatter.string(from: date) } } } ================================================ FILE: Sources/AppKit/AppDelegate.swift ================================================ import PromiseKit import AppKit import Cake @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { let menu = NSMenu() let statusBarItem = NSStatusBar.system.statusItem(withLength: 22) let kitchen = Kitchen(cake: Bundle.main) let updater = AppUpdater(owner: "mxcl", repo: "Cake") var hotKey: HotKey! override func awakeFromNib() { statusBarItem.button?.appearsDisabled = true statusBarItem.button?.image = NSImage(named: "NSStatusBarItem") statusBarItem.menu = menu PromiseKit.conf.Q.map = .global() let name = Notification.Name(rawValue: "dev.mxcl.Cake.build") DistributedNotificationCenter.default().addObserver(self, selector: #selector(build), name: name, object: nil) } func applicationDidFinishLaunching(_ aNotification: Notification) { kitchen.delegate = self hotKey = HotKey(key: .t, modifiers: [.command, .option, .control]) hotKey.keyDownHandler = { [weak self] in self?.openActiveWorkspaceInTerminal() } } } extension AppDelegate: KitchenDelegate { func xcode(isRunning: Bool) { statusBarItem.button?.appearsDisabled = !isRunning menu.removeAllItems() menu.addItem(withTitle: isRunning ? "Loading…" : "Xcode not open", action: nil, keyEquivalent: "") fillMenuBottom() } func kitchen(cake: [CakeProject], notCake: [String]) { updateStatusItemMenu(cake: cake, notCake: notCake) } func kitchen(error: Error) { alert(error) } func kitchen(regenerated cake: CakeProject) { let note = NSUserNotification() note.title = "Regenerated \(cake.name)’s Cake" NSUserNotificationCenter.default.deliver(note) DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { NSUserNotificationCenter.default.removeDeliveredNotification(note) } } @objc func build(note: Notification) { enum E: Error { case noPROJECT_DIR } var userInfo: [String: Any]! do { guard let path = note.userInfo?["PROJECT_DIR"] as? String else { throw E.noPROJECT_DIR } try kitchen.generate(for: Path.root.join(path).parent) } catch { userInfo = .init() userInfo["error"] = error.legibleLocalizedDescription userInfo["error.userInfo"] = (error as NSError).userInfo } let name = Notification.Name(rawValue: "dev.mxcl.Cake.built") DistributedNotificationCenter.default().postNotificationName(name, object: nil, userInfo: userInfo, options: .deliverImmediately) } @objc func openActiveWorkspaceInTerminal() { guard let path = kitchen.activeWorkspace?.parent else { NSSound.beep() return } let task = Process() task.launchPath = "/usr/bin/open" task.arguments = ["-a", "Terminal", path.string] task.launch(.promise).alert() } } ================================================ FILE: Sources/AppKit/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "16x16", "idiom" : "mac", "filename" : "cake-16.png", "scale" : "1x" }, { "size" : "16x16", "idiom" : "mac", "filename" : "cake-32.png", "scale" : "2x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "cake-33.png", "scale" : "1x" }, { "size" : "32x32", "idiom" : "mac", "filename" : "cake-64.png", "scale" : "2x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "cake-128.png", "scale" : "1x" }, { "size" : "128x128", "idiom" : "mac", "filename" : "cake-256.png", "scale" : "2x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "cake-257.png", "scale" : "1x" }, { "size" : "256x256", "idiom" : "mac", "filename" : "cake-512.png", "scale" : "2x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "cake-513.png", "scale" : "1x" }, { "size" : "512x512", "idiom" : "mac", "filename" : "cake-1024.png", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Sources/AppKit/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Sources/AppKit/Assets.xcassets/NSStatusBarItem.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "mac", "scale" : "1x" }, { "idiom" : "mac", "filename" : "cake-3.png", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "template-rendering-intent" : "template" } } ================================================ FILE: Sources/AppKit/Base.lproj/Main.storyboard ================================================ Default Left to Right Right to Left Default Left to Right Right to Left ================================================ FILE: Sources/AppKit/Bundled Files/iOS.LaunchScreen.storyboard ================================================ ================================================ FILE: Sources/AppKit/Cake.entitlements ================================================ com.apple.security.automation.apple-events ================================================ FILE: Sources/AppKit/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString $(SEMANTIC_PROJECT_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) LSUIElement NSAppleEventsUsageDescription Monitoring loaded Xcode projects. NSAppleScriptEnabled NSHumanReadableCopyright Copyright © 2019‒present Max Howell. All rights reserved. NSMainStoryboardFile Main NSPrincipalClass NSApplication ================================================ FILE: Sources/AppKit/Menu·$CAKE.swift ================================================ import AppKit import Cake extension AppDelegate { @objc func integrateCake(sender: NSMenuItem) { guard let index = sender.parent?.tag else { return } do { let path = kitchen.notCakes[index] let proj = try XcodeProject(existing: path) let (_,_) = try scaffold(.existing(proj), cakeVersion: Bundle.main.version) //TODO update menu items } catch { alert(error) } } @objc func deintegrateCake(sender: NSMenuItem) { guard let index = sender.parent?.tag else { return } do { let item = kitchen.cakes[index] let proj = try XcodeProject(existing: item.xcodeproj) let cake = try XcakeProject(existing: item.prefix/".cake/Cake.xcodeproj") try cake.deintegrate(proj) } catch { alert(error) } } @objc func updateDependencies(sender: NSMenuItem) { guard let index = sender.parent?.tag else { return } do { try kitchen.cakes[index].updateDependencies() } catch ProcessorError.noDependenciesInCakefile { alert(message: "No dependencies in Cakefile.", title: "noop") } catch { alert(error) } } } ================================================ FILE: Sources/AppKit/Menu·New Cake.swift ================================================ import AppKit import Cake extension AppDelegate { @objc func createNewCake(sender: NSMenuItem) { do { //TODO figure out deployment targets from xcodebuild or something let platform: PlatformSpecification switch sender.menu?.index(of: sender) { case 0?: platform = PlatformSpecification(platform: .macOS, version: Version(10,14,0)) case 1?: platform = PlatformSpecification(platform: .iOS, version: Version(12,0,0)) default: return } let name = cakes.randomElement()! let prefix = Path.home/"Desktop"/name enum E: Error { case directoryNameConflict } if prefix.isDirectory { throw E.directoryNameConflict } let (proj, _) = try scaffold(.new(name: name, prefix, platform), cakeVersion: Bundle.main.version) NSWorkspace.shared.open(proj.path.url) } catch { alert(error) } } } private var cakes: [String] { return [ "Madeira Cake", "Torte", "Savarin", "Cherry Cake", "Cheesecake", "Chocolate Cake", "Red Velvet Cake", "Key Lime Pie", "Pound Cake", "Sponge Cake", "Upside Down Cake", "Icecream Cake", "German Chocolate Cake", "Cupcake", "Strawberry Shortcake", "Fruitcake", "Bundt Cake", "Hummingbird Cake", "Black Forest Cake", "Angel Food Cake", "Carrot Cake", "Christmas Pudding", "Yule Log", "Bûche de Noël", "Devil’s Food Cake", "Pumpkin Roll", "Bread Pudding", "Coffee Cake", "Birthday Cake", "Pancake", "Chocolate Lava Cake", "Pineapple Upside‐down Cake" ] } ================================================ FILE: Sources/AppKit/Menu·Xcode.swift ================================================ import AppKit import Cake extension AppDelegate { @objc func derivedDataDance(sender: NSMenuItem) { do { let apps = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dt.Xcode") for app in apps { let xcode = try Xcode(pid: app.processIdentifier) let dd = xcode.derivedData // sanity checks, shouldn’t happen, but we should be careful! guard dd != Path.root, dd != Path.home else { return } if xcode.isRunning { let docs = xcode.documents try xcode.quit() try dd.delete() xcode.open(documents: docs) } else { try dd.delete() } } } catch { alert(error) } } @objc func quitXcode(sender: NSMenuItem) { let apps = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dt.Xcode") for app in apps { if !app.terminate() { print("warning: failed to terminate Xcode") } } } } ================================================ FILE: Sources/AppKit/alert().swift ================================================ import LegibleError import Foundation import AppKit protocol TitledError: LocalizedError { var title: String { get } } private func _alert(error: Error, title: String?, file: StaticString, line: UInt) -> (String, String) { print("\(file):\(line)", error.legibleDescription, error) var computeTitle: String { switch (error as NSError).domain { case "SKErrorDomain": return "App Store Error" case "kCLErrorDomain": return "Core Location Error" case NSCocoaErrorDomain: return "Error" default: return "Unexpected Error" } } let title = title ?? (error as? TitledError)?.title ?? computeTitle return (error.legibleLocalizedDescription, title) } func alert(_ error: Error, title: String? = nil, file: StaticString = #file, line: UInt = #line) { let (msg, title) = _alert(error: error, title: title, file: file, line: line) // we cannot make SKError CancellableError sadly (still) let pair: (String, Int) = { ($0.domain, $0.code) }(error as NSError) guard ("SKErrorDomain", 2) != pair else { return } // user-cancelled guard ("NSOSStatusErrorDomain", -128) != pair else { return } // Apple Script user-cancelled alert(message: msg, title: title) } func alert(message: String, title: String) { func go() { #if os(macOS) let alert = NSAlert() alert.informativeText = message alert.messageText = title alert.addButton(withTitle: "OK") alert.runModal() #else #endif } if Thread.isMainThread { go() } else { DispatchQueue.main.async(execute: go) } } import PromiseKit extension Promise { @discardableResult func alert(title: String? = nil, file: StaticString = #file, line: UInt = #line) -> PMKFinalizer { return self.catch { App.alert($0, title: title, file: file, line: line) } } } ================================================ FILE: Sources/Kitchenware/Makefile ================================================ .PHONY: all BUILD_DIR = $(OUTDIR)/swift-pm/$(CONFIGURATION) CONFIGURATION = release outputs = $(OUTDIR)/lib/pm/4/libPackageDescription.dylib $(OUTDIR)/lib/pm/4_2/libPackageDescription.dylib $(OUTDIR)/lib/Cakefile.swiftmodule $(OUTDIR)/lib/Cakefile.swiftdoc $(OUTDIR)/lib/libCakefile.dylib $(OUTDIR)/lib/Version.swiftmodule $(OUTDIR)/lib/Version.swiftdoc swift_build_outputs = $(BUILD_DIR)/Cakefile.swiftmodule $(BUILD_DIR)/Cakefile.swiftdoc $(BUILD_DIR)/libCakefile.a $(BUILD_DIR)/Version.swiftmodule $(BUILD_DIR)/Version.swiftdoc all: $(outputs) $(OUTDIR)/lib: mkdir -p $@ $(OUTDIR)/lib/pm/4: mkdir -p $@ $(OUTDIR)/lib/pm/4_2: mkdir -p $@ $(swift_build_outputs): $(wildcard Sources/Cakefile/*.swift) swift build --configuration $(CONFIGURATION) --build-path $(OUTDIR)/swift-pm $(OUTDIR)/lib/pm/4_2/libPackageDescription.dylib: $(wildcard Sources/PackageDescription/*.swift) | $(OUTDIR)/lib/pm/4_2 swiftc $^ -emit-library -o $@ -emit-module -module-name PackageDescription -target x86_64-apple-macosx10.10 -suppress-warnings -DPACKAGE_DESCRIPTION_4_2 $(OUTDIR)/lib/pm/4/libPackageDescription.dylib: $(wildcard Sources/PackageDescription/*.swift) | $(OUTDIR)/lib/pm/4 swiftc $^ -emit-library -o $@ -emit-module -module-name PackageDescription -target x86_64-apple-macosx10.10 -suppress-warnings -DPACKAGE_DESCRIPTION_4 $(OUTDIR)/lib/libCakefile.dylib: $(BUILD_DIR)/libCakefile.a | $(OUTDIR)/lib swiftc -Xlinker -dylib -o $@ -Xlinker -all_load $< -target x86_64-apple-macosx10.10 $(OUTDIR)/lib/Cakefile.swiftmodule: $(BUILD_DIR)/Cakefile.swiftmodule | $(OUTDIR)/lib cp $< $@ $(OUTDIR)/lib/Cakefile.swiftdoc: $(BUILD_DIR)/Cakefile.swiftdoc | $(OUTDIR)/lib cp $< $@ $(OUTDIR)/lib/Version.swiftmodule: $(BUILD_DIR)/Version.swiftmodule | $(OUTDIR)/lib cp $< $@ $(OUTDIR)/lib/Version.swiftdoc: $(BUILD_DIR)/Version.swiftdoc | $(OUTDIR)/lib cp $< $@ ================================================ FILE: Sources/Kitchenware/Package.swift ================================================ // swift-tools-version:5.0 import PackageDescription let pkg = Package(name: "Kitchenware") pkg.products = [ .library(name: "Cakefile", type: .static, targets: ["Cakefile"]), ] pkg.dependencies = [ .package(url: "https://github.com/mxcl/Version", from: "1.0.0"), ] pkg.targets = [ .target(name: "Cakefile", dependencies: ["Version"]), ] ================================================ FILE: Sources/Mixer/Makefile ================================================ .PHONY: all all: libCakefileDescription.dylib _build: mkdir $@ libCakefileDescription.dylib: ../Sources/Model/CakefileDescription/* | _build ================================================ FILE: Sources/Mixer/Modelize/etc.swift ================================================ enum Error: Swift.Error { /// Couldn't find all tools needed by the package manager. case invalidToolchain(problem: String) /// The root manifest was not found. case rootManifestFileNotFound /// There were fatal diagnostics during the operation. case hasFatalDiagnostics } import protocol Workspace.WorkspaceDelegate import struct PackageGraph.PackageGraph import struct Basic.Diagnostic import class Workspace.ManagedDependency public class Delegate: WorkspaceDelegate { public init() {} public func packageGraphWillLoad(currentGraph: PackageGraph, dependencies: AnySequence, missingURLs: Set) { } public func fetchingWillBegin(repository: String) { } public func fetchingDidFinish(repository: String, diagnostic: Diagnostic?) { } public func cloning(repository: String) { } public func removing(repository: String) { } public func managedDependenciesDidUpdate(_ dependencies: AnySequence) { } } import struct Basic.Diagnostic extension Diagnostic.Behavior: CustomStringConvertible { public var description: String { switch self { case .error: return "error" case .warning: return "warning" case .note: return "note" case .ignored: return "ignored" } } } import func Darwin.fputs import func Darwin.exit import var Darwin.stderr public func doctor(diagnostic: Diagnostic) { switch diagnostic.id.name { case "org.swift.diags.workspace.PD3DeprecatedDiagnostic": // The consumer cannot help that the Package in question is poorly maintained // we *could* show the warning as it would encourage the consumer to report // the bug or even update the manifest with a PR. But in my experience nobody // does, instead they have to search the Internet for workarounds so that they // can hide this warning. We prioritize DX and user-satisfaction. break case "org.swift.diags.unused-dependency": // Our manifest has no targets so this warning is always emitted break default: fputs("\(diagnostic.behavior): \(diagnostic.data)\n", stderr) } } public func error(_ message: Any) -> Never { fputs("error: \(message)\n", stderr) exit(1) } public func warning(_ message: Any) { fputs("warning: \(message)\n", stderr) } import class PackageModel.ResolvedPackage import class PackageModel.ResolvedTarget public extension ResolvedPackage { var libraryTargets: [ResolvedTarget] { return targets.filter{ $0.type == .library } } } public extension Array where Element == ResolvedPackage { var libraryTargets: [ResolvedTarget] { return flatMap(\.targets).filter{ $0.type == .library } } } ================================================ FILE: Sources/Mixer/Modelize/modelize().swift ================================================ import struct Foundation.URLComponents import struct Foundation.URL import struct Basic.AbsolutePath import PackageModel import Base import Path /// returns topological sorted flat-list of module hierarchy /// also copies sources into visible folders TODO this breaks the responsibility of this method public func modelize(to root: Path, packages: [ResolvedPackage], targets: [ResolvedTarget]) throws -> DependenciesJSON { var map = [ResolvedTarget: (SwiftVersion, ResolvedPackage)]() do { var set = Set() func recursePackage(_ package: ResolvedPackage) { guard !set.contains(package) else { return } set.insert(package) let ver = package.swiftVersions.max() ?? SwiftVersion(package.manifest.manifestVersion) for target in package.targets { map[target] = (ver, package) } package.dependencies.forEach(recursePackage) } packages.forEach(recursePackage) } var roots = Set() var scaffolded = [ResolvedPackage: [ResolvedTarget: (Path, [Path])]]() func scaffold(package: ResolvedPackage) throws -> [ResolvedTarget: (Path, [Path])] { if let sources = scaffolded[package] { return sources } var packageDirname = package.checkoutBasename if let version = package.manifest.version { packageDirname += "-\(version)" } let targets = package.libraryTargets let map = try targets.map { target -> (ResolvedTarget, (Path, [Path])) in let srcroot = Path(absolutePath: target.sources.root) let dir: Path if targets.count > 1 { dir = root/packageDirname/target.name } else if let sourceFile = targets.first?.sources.singleFile { let sourceFile = try sourceFile.copy(to: root.mkdir(.p).join("\(packageDirname).swift"), overwrite: true) roots.insert(sourceFile) return (target, (root, [sourceFile])) } else { dir = root/packageDirname } let sources = try target.sources.paths.map { sourceFile -> Path in let sourceFile = Path(absolutePath: sourceFile) let relativeDir = sourceFile.parent.relative(to: srcroot) let into = try dir.join(relativeDir).mkdir(.p) return try sourceFile.copy(into: into, overwrite: true) } if !sources.isEmpty { roots.insert(dir) } return (target, (dir, sources)) } let dict = Dictionary(uniqueKeysWithValues: map) scaffolded[package] = dict return dict } var modules = [ResolvedTarget: Module]() func recurseTarget(with target: ResolvedTarget) throws -> Module? { if let module = modules[target] { return module } guard target.type == .library else { return nil } guard let (version, package) = map[target] else { error("missing target to (version, pkg) entry for \(target)") } guard let (srcroot, sources) = try scaffold(package: package)[target] else { error("missing scaffolding for \(package)") } let deps = target.dependencies.flatMap { resolvedDependency -> [ResolvedTarget] in switch resolvedDependency { case .product(let product): return product.targets // external dependencies case .target(let target): return [target] // internal to the package these targets came from } } let module = Module( name: target.name, directory: srcroot, dependencies: try deps.compactMap(recurseTarget), files: sources, swift: version ) modules[target] = module return module } let sortedModules = try targets.compactMap(recurseTarget).flattened if sortedModules.isEmpty { // if nothing left then delete entire Dependencies directory (let’s be clean) try root.delete() } else { // delete everything else ∵ old versions //TODO do better, only delete stuff that was here before (read Dependencies.json) for entry in try root.ls() where !roots.contains(entry.path) { try entry.path.delete() } } let pkgs = scaffolded.map { foo in DependenciesJSON.Package( name: foo.key.qualifiedName, path: Path(absolutePath: foo.key.path), version: foo.key.manifest.version, moduleNames: foo.value.keys.map{ modules[$0]!.name }) } let imports = targets.map{ $0.c99name } return DependenciesJSON(modules: sortedModules, imports: imports, packages: pkgs) } private extension ResolvedPackage { var swiftVersions: [SwiftVersion] { return manifest.swiftLanguageVersions?.compactMap(SwiftVersion.init) ?? [] } var qualifiedName: String { if let (user, repo) = URLComponents(string: manifest.url)?.githubPair { return "\(user)/\(repo)" } else { return name } } var checkoutBasename: String { let slash = "∕" // special unicode value that is _not_ the UNIX filesystem slash guard let cc = URLComponents(string: manifest.url) else { fatalError() //TODO } if let (user, repo) = cc.githubPair { return "\(user)\(slash)\(repo)" } guard let host = cc.host else { fatalError() //TODO } var components = cc.path.split(separator: "/") if let last = components.last, last.hasSuffix(".git") { components[components.endIndex - 1] = last.dropLast(4) } func sanitize(_ s: S) -> String where S: StringProtocol { return s.replacingOccurrences(of: ":", with: "%3A") } let path = components.map(sanitize).joined(separator: slash) return sanitize(host) + slash + path } } public extension Path { init(absolutePath path: AbsolutePath) { self = Path.root / path.pathString } } private extension SwiftVersion { init?(spmValue: SwiftLanguageVersion) { if spmValue >= .v5 { self = .v5 } else if spmValue >= .v4_2 { self = .v4_2 } else if spmValue >= .v4 { self = .v4 } else { return nil } } init(_ manifestVersion: ManifestVersion) { switch manifestVersion { case .v4: self = .v4 case .v4_2: self = .v4_2 case .v5: self = .v5 } } } private extension URLComponents { var githubPair: (String.SubSequence, String.SubSequence)? { let cc = self guard let host = cc.host, host.hasSuffix("github.com") else { return nil } let components = cc.path.split(separator: "/") guard components.count == 2 else { return nil } let owner = components[0] var repo = components[1] if repo.hasSuffix(".git") { repo = repo.dropLast(4) } return (owner, repo) } } private extension Sources { var singleFile: Path? { guard relativePaths.count == 1 else { return nil } return Path(absolutePath: root.appending(relativePaths[0])) } } private extension Dictionary { func mapPairs(_ transform: (Element) throws -> (OutKey, OutValue)) rethrows -> [OutKey: OutValue] { return Dictionary(uniqueKeysWithValues: try map(transform)) } } ================================================ FILE: Sources/Mixer/Package.resolved ================================================ { "object": { "pins": [ { "package": "OrderedSet", "repositoryURL": "https://github.com/Weebly/OrderedSet", "state": { "branch": null, "revision": "4247c60cc190dbbaff63ecfe42bd7a1f2cbaf225", "version": "3.1.0" } }, { "package": "Path.swift", "repositoryURL": "https://github.com/mxcl/Path.swift", "state": { "branch": null, "revision": "e915bc0cfb5bcee9d48adfdb9e8208d07291c0e8", "version": "0.16.0" } }, { "package": "llbuild", "repositoryURL": "https://github.com/apple/swift-llbuild.git", "state": { "branch": "master", "revision": "06a25536b8d7f6b43f93139dea15dd8f7873b8d9", "version": null } }, { "package": "SwiftPM", "repositoryURL": "https://github.com/apple/swift-package-manager.git", "state": { "branch": "swift-DEVELOPMENT-SNAPSHOT-2019-02-03-a", "revision": "9b6be668d93829f9ef0727ad2d2490e56487fedc", "version": null } } ] }, "version": 1 } ================================================ FILE: Sources/Mixer/Package.swift ================================================ // swift-tools-version:5.0 import PackageDescription let pkg = Package(name: "Mixer") pkg.products = [ .executable(name: "mixer", targets: ["Mixer"]), ] pkg.dependencies = [ .package(url: "https://github.com/apple/swift-package-manager.git", .branch("swift-DEVELOPMENT-SNAPSHOT-2019-02-03-a")), .package(url: "https://github.com/Weebly/OrderedSet", from: "3.1.0"), .package(url: "https://github.com/mxcl/Path.swift", from: "0.16.0"), ] pkg.targets = [ .target(name: "Mixer", dependencies: ["OrderedSet", "Modelize"], path: ".", sources: ["main.swift"]), .target(name: "Modelize", dependencies: ["SwiftPM", "Base", "Path"], path: "Modelize"), .target(name: "Base", dependencies: ["Path"], path: "Base"), ] pkg.platforms = [ .macOS(.v10_14) ] pkg.swiftLanguageVersions = [ .v5 ] ================================================ FILE: Sources/Mixer/README.md ================================================ Mixer is an independent Swift-Package because it builds its own copy of SwiftPM (since libSwiftPM is not usable from an Xcode installation) and 1. Cake cannot support c-packages yet; 2. adding SwiftPM as a dependency kills clean builds (which we intend to fix); and 3. this would be inefficient since we only need libSwiftPM for Mixer so really we need Cake to support this more advanced use-case. We have a subfolder `Base` that contains symlinks to our Cake base module swift files. This is due to SwiftPM refusing to create modules for directories that are below the `Package.swift` directory. # Getting an Xcodeproj In this directory: swift package generate-xcodeproj --xcconfig-overrides .build/libSwiftPM.xcconfig # Building Cake Bootstrapping SwiftPM requires `ninja`: brew install ninja ================================================ FILE: Sources/Mixer/main.swift ================================================ /* Reads a Package.swift and converts the output to a list of Modules that Cake can embed in Cake.xcodeproj. We tried to use the generated Xcodeproj that SwiftPM can use but that proved overall undesirable since we needed to edit the resulting project to have a dependency on the Cakefile target in our Cake.xcodeproj. This worked but was tedious. Also the generated project only produced dynamic frameworks and we want static ones. This approach is neater and makes it possible to make it possible for Cake projects to be standalone which was a goal of the Cake menifesto. The other attempt was to use SwiftPM’s commands to output the module content for a Package.swift, however these commands do not output all the information we need (most vital was inter-package module dependencies). We may submit this PR to SwiftPM to add the information we need. But since SwiftPM has an annual release cycle, this was no good for our immediate needs. */ import struct Foundation.URL import class Foundation.JSONEncoder import class SourceControl.GitRepositoryProvider import func Darwin.exit import PackageLoading import PackageGraph import SPMUtility import Workspace import Modelize import Basic import Base import Path // hi, this code is hard to understand and really I don’t know what // to do about it other than make a facade wrapper for SwiftPM. guard CommandLine.arguments.count == 3 else { error("error: mixer ") } let root = AbsolutePath(CommandLine.arguments[1]) let pkgpath = root.appending(component: ".cake") let depsPath = root.appending(component: "Dependencies") let swiftPath = try Process.checkNonZeroExit(arguments: ["xcrun", "--sdk", "macosx", "-f", "swift"]).spm_chomp() let sdkroot = try Process.checkNonZeroExit(arguments: ["xcrun", "--sdk", "macosx", "--show-sdk-path"]).spm_chomp() let L = AbsolutePath(CommandLine.arguments[2]) struct UserManifestResources: ManifestResourceProvider { let swiftCompiler: AbsolutePath let libDir: AbsolutePath let sdkRoot: AbsolutePath? } let manifestResources = UserManifestResources( swiftCompiler: AbsolutePath(swiftPath).parentDirectory.appending(component: "swiftc"), libDir: L, sdkRoot: AbsolutePath(sdkroot) ) let loader = ManifestLoader(manifestResources: manifestResources) let delegate = Delegate() let provider = GitRepositoryProvider() let workspace = Workspace( dataPath: pkgpath.appending(component: "swift-pm"), editablesPath: depsPath, pinsFile: pkgpath.appending(component: "Package.resolved"), manifestLoader: loader, toolsVersionLoader: ToolsVersionLoader(), delegate: delegate, repositoryProvider: provider, isResolverPrefetchingEnabled: true, skipUpdate: true ) let diagnostics = DiagnosticsEngine(handlers: [doctor]) let graphRootInput = PackageGraphRootInput(packages: [pkgpath]) workspace.resolve(root: graphRootInput, diagnostics: diagnostics) guard !diagnostics.hasErrors else { exit(2) } let graph = workspace.loadPackageGraph(root: graphRootInput, diagnostics: diagnostics) guard !diagnostics.hasErrors else { exit(3) } let rootPackages = graph.rootPackages.flatMap{ $0.dependencies } let rootTargets = rootPackages.libraryTargets let output = try modelize(to: Path(absolutePath: depsPath), packages: rootPackages, targets: rootTargets) let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted encoder.userInfo[.relativePath] = Path(absolutePath: depsPath) let data = try encoder.encode(output) let outpath = pkgpath.appending(component: "Dependencies.json").pathString try data.write(to: URL(fileURLWithPath: outpath)) print(String(data: data, encoding: .utf8)!) ================================================ FILE: Sources/Model/Base/Modelizer/Dependencies.json.swift ================================================ #if SWIFT_PACKAGE import struct Workspace.Version #else import Version #endif import Path public struct DependenciesJSON { public let modules: [Module] // topologically sorted public let imports: [String] // topologically sorted public let packages: [Package] public struct Package: Codable { public let name: String public let path: Path public let version: Version? //TODO VersionSpecification public let moduleNames: [String] } public var isEmpty: Bool { return modules.isEmpty } } extension DependenciesJSON: Codable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) imports = try container.decode([String].self, forKey: .imports) var arrayContainer = try container.nestedUnkeyedContainer(forKey: .modules) modules = try .decode(from: &arrayContainer) packages = try container.decode([Package].self, forKey: .packages) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(imports, forKey: .imports) var arrayContainer = container.nestedUnkeyedContainer(forKey: .modules) try modules.encode(to: &arrayContainer) try container.encode(packages, forKey: .packages) } enum CodingKeys: CodingKey { case modules, imports, packages } } public extension DependenciesJSON { init() { modules = [] imports = [] packages = [] } } ================================================ FILE: Sources/Model/Base/Modelizer/Module.swift ================================================ import Base import Path public final class Module: Codable { public let name: String public let path: Path public let dependencies: [Module] public let files: [Path] // if nil the SwiftVersion is determined by the project public let swiftVersion: SwiftVersion? var relativeFiles: [String] { return files.map{ $0.relative(to: path) } } init(name: String, directory: Path, dependencies: [Module], files: [Path], swift: SwiftVersion? = nil) { self.name = name self.path = directory self.dependencies = dependencies.sorted() self.files = files.sorted() self.swiftVersion = swift } enum CodingKeys: CodingKey { case name, path, dependencies, files, swiftVersion } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) name = try container.decode(String.self, forKey: .name) path = try container.decode(Path.self, forKey: .path) files = try container.decode([String].self, forKey: .files).map(path.join) dependencies = try container.decode([Module].self, forKey: .dependencies) swiftVersion = try container.decode(SwiftVersion?.self, forKey: .swiftVersion) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try encodeCommon(to: &container) try container.encode(dependencies, forKey: .dependencies) } fileprivate func encodeCommon(to container: inout KeyedEncodingContainer) throws { //TODO no bangs! try container.encode(name, forKey: .name) try container.encode(path, forKey: .path) try container.encode(files.map{ $0.relative(to: path) }, forKey: .files) try container.encode(swiftVersion, forKey: .swiftVersion) } } extension Array where Element == Module { /// encodes dependencies as references, thus avoiding potentially enormous JSON public func encode(to arrayContainer: inout UnkeyedEncodingContainer) throws { var encoded = Set() var stack = self while let module = stack.popLast() { var container = arrayContainer.nestedContainer(keyedBy: Module.CodingKeys.self) try module.encodeCommon(to: &container) try container.encode(module.dependencies.map(\.name), forKey: .dependencies) stack.append(contentsOf: module.dependencies.filter{ !encoded.contains($0) }) encoded.insert(module) } } /// - Note: requires modules to be topographically sorted static public func decode(from arrayContainer: inout UnkeyedDecodingContainer) throws -> [Module] { var decoded: [String: Module] = [:] var rv = [Module]() while !arrayContainer.isAtEnd { let container = try arrayContainer.nestedContainer(keyedBy: Module.CodingKeys.self) let path = try container.decode(Path.self, forKey: .path) let deps = try container.decode([String].self, forKey: .dependencies).map{ decoded[$0]! } let files = try container.decode([String].self, forKey: .files).map(path.join) let name = try container.decode(String.self, forKey: .name) let swift = try container.decode(SwiftVersion?.self, forKey: .swiftVersion) let module = Module(name: name, directory: path, dependencies: deps, files: files, swift: swift) decoded[module.name] = module rv.append(module) } //TODO only return the “tips” (maybe?) return rv } } extension Module: Equatable, Hashable, Comparable { public static func ==(lhs: Module, rhs: Module) -> Bool { return lhs.path == rhs.path && lhs.dependencies == rhs.dependencies && lhs.files == rhs.files } public func hash(into hasher: inout Hasher) { hasher.combine(path) } public static func <(lhs: Module, rhs: Module) -> Bool { return lhs.name.compare(rhs.name) == .orderedAscending } } public extension Array where Element == Module { var flattened: [Module] { return topologicallySorted{ $0.dependencies } } var bases: [Module] { return flattened.filter { $0.dependencies.isEmpty } } } extension Module: CustomStringConvertible { public var description: String { return "" } public func dump() { func recursiveWalk(modules: [Module], prefix: String = "") { var hanger = prefix + "├── " for (index, module) in modules.enumerated() { if index == modules.count - 1 { hanger = prefix + "└── " } print("\(hanger)\(module.name)") if !module.dependencies.isEmpty { let replacement = (index == modules.count - 1) ? " " : "│ " var childPrefix = hanger let startIndex = childPrefix.index(childPrefix.endIndex, offsetBy: -4) childPrefix.replaceSubrange(startIndex.. [Module] { let modelizer = Modelizer(root: root, basename: basename) return try modelizer.go() } public enum ModelizerError: Error { case noSwiftFiles(Path) } private class Modelizer { let root: Path var tips: [Module] = [] let basename: String init(root: Path, basename: String) { self.root = root self.basename = basename } func go() throws -> [Module] { let base = try Module(directory: root, name: basename) let deps = base.map{ [$0] } ?? [] try descend(into: ModuleOrPath(path: root, module: base), deps: deps) if tips.isEmpty { throw ModelizerError.noSwiftFiles(root) } return tips } @discardableResult private func descend(into: ModuleOrPath, deps: [Module]) throws -> Bool { let descendables = try into.path.ls().directories.map { ModuleOrPath(path: $0, module: try Module(directory: $0, deps: deps)) } var consumers = descendables.compactMap(\.module) // if no descendent directories are modules // we push the undelying deps forward instead if consumers.isEmpty { consumers = deps } var validDescendents = false for descendable in descendables { if try descend(into: descendable, deps: consumers) { validDescendents = true } } if let module = into.module { if !module.files.isEmpty { if !validDescendents { tips.append(module) } return true } else { return validDescendents } } else { return validDescendents } } } private enum ModuleOrPath { case path(Path) case module(Module) var path: Path { switch self { case .path(let path): return path case .module(let module): return module.path } } var module: Module? { switch self { case .module(let module): return module case .path: return nil } } init(path: Path, module: Module?) { if let module = module { assert(path == module.path) self = .module(module) } else { self = .path(path) } } } private extension Module { convenience init?(directory: Path, name: String? = nil, deps: [Module] = []) throws { let files = try directory.ls().files(withExtension: "swift").sorted() if files.isEmpty { return nil } self.init( name: name ?? directory.basename(), directory: directory, dependencies: deps, files: files) } } ================================================ FILE: Sources/Model/Base/Path+inreplace().swift ================================================ import Path public extension Path { func inreplace(_ target: String, with replacement: String) throws { //TODO could replace more efficiently if we did it with FileHandle try StreamReader(path: self).map { $0.replacingOccurrences(of: target, with: replacement) }.joined(separator: "\n").write(to: self, atomically: true) } } ================================================ FILE: Sources/Model/Base/Process+facade.swift ================================================ import Foundation public extension Process { class Output { public let data: Data public lazy var string = { [unowned self] () -> String? in guard var str = String(data: self.data, encoding: .utf8) else { return nil } str = str.trimmingCharacters(in: .whitespacesAndNewlines) return str.isEmpty ? nil : str }() fileprivate init(_ data: Data) { self.data = data } } struct ExecutionError: Error { public let stdout: Output public let stderr: Output public let status: Int32 public let arg0: String public let args: [String] } func runSync(tee: Bool = false) throws -> (stdout: Output, stderr: Output) { let q = DispatchQueue(label: "output-queue") var out = Data() var err = Data() let outpipe = Pipe() standardOutput = outpipe let errpipe = Pipe() standardError = errpipe outpipe.fileHandleForReading.readabilityHandler = { handler in q.async { out.append(handler.availableData) } } errpipe.fileHandleForReading.readabilityHandler = { handler in q.async { let data = handler.availableData err.append(data) if tee, let str = String(data: data, encoding: .utf8) { Darwin.fputs(str, stderr) } } } try run() waitUntilExit() outpipe.fileHandleForReading.readabilityHandler = nil errpipe.fileHandleForReading.readabilityHandler = nil return try q.sync { guard terminationStatus == 0, terminationReason == .exit else { throw ExecutionError(stdout: .init(out), stderr: .init(err), status: terminationStatus, arg0: launchPath!, args: arguments ?? []) } return (stdout: Output(out), stderr: Output(err)) } } static func system(_ arg0: String, args: String...) throws { let task = Process() task.launchPath = arg0 task.arguments = args try task.run() task.waitUntilExit() guard task.terminationReason == .exit, task.terminationStatus == 0 else { let output = Output(Data()) throw ExecutionError(stdout: output, stderr: output, status: task.terminationStatus, arg0: arg0, args: args) } } } extension Process.Output: CustomStringConvertible { public var description: String { return string ?? "" } } ================================================ FILE: Sources/Model/Base/Sequence+KeyPath.swift ================================================ public extension Sequence { @inlinable func map(_ keyPath: KeyPath) -> [T] { return map { $0[keyPath: keyPath] } } @inlinable func compactMap(_ keyPath: KeyPath) -> [T] { return compactMap { $0[keyPath: keyPath] } } @inlinable func flatMap(_ keyPath: KeyPath) -> [T] { return flatMap { $0[keyPath: keyPath] } } } ================================================ FILE: Sources/Model/Base/StreamReader.swift ================================================ import Foundation import Path // I confess I copy and pasted this from StackOverflow.com public class StreamReader { public let encoding: String.Encoding public let chunkSize: Int private var fileHandle: FileHandle! private var buffer: Data private var atEof: Bool let delimData: Data public init(path: Path, delimiter: String = "\n", encoding: String.Encoding = .utf8, chunkSize: Int = 4096) throws { guard let fileHandle = FileHandle(forReadingAtPath: path.string), let delimData = delimiter.data(using: encoding) else { throw CocoaError.error(.fileReadNoSuchFile) } self.encoding = encoding self.chunkSize = chunkSize self.fileHandle = fileHandle self.delimData = delimData self.buffer = Data(capacity: chunkSize) self.atEof = false } deinit { close() } /// Return next line, or nil on EOF. func nextLine() -> String? { precondition(fileHandle != nil, "Attempt to read from closed file") // Read data chunks from file until a line delimiter is found: while !atEof { if let range = buffer.range(of: delimData) { // Convert complete line (excluding the delimiter) to a string: let line = String(data: buffer.subdata(in: 0.. 0 { buffer.append(tmpData) } else { // EOF or read error. atEof = true if buffer.count > 0 { // Buffer contains last line in file (not terminated by delimiter). let line = String(data: buffer as Data, encoding: encoding) buffer.count = 0 return line } } } return nil } /// Start reading from the beginning of file. func rewind() -> Void { fileHandle.seek(toFileOffset: 0) buffer.count = 0 atEof = false } /// Close the underlying file. No reading must be done after calling this method. func close() -> Void { fileHandle?.closeFile() fileHandle = nil } } extension StreamReader: Sequence { public func makeIterator() -> AnyIterator { return AnyIterator { return self.nextLine() } } } ================================================ FILE: Sources/Model/Base/SwiftVersion.swift ================================================ /// The Swift version specifications that Xcode supports public enum SwiftVersion: String, Comparable, Codable { case v4 = "4" case v4_2 = "4.2" case v5 = "5.0" private var intValue: Int { switch self { case .v4: return 04_00_00 case .v4_2: return 04_02_00 case .v5: return 05_00_00 } } public static func <(lhs: SwiftVersion, rhs: SwiftVersion) -> Bool { return lhs.intValue < rhs.intValue } #if false public var version: Version { switch self { case .v4: return Version(4,0,0) case .v4_2: return Version(4,2,0) case .v5: return Version(5,0,0) } } #endif #if swift(>=5) public static let `default` = SwiftVersion.v5 #else public static let `default` = SwiftVersion.v4_2 #endif } ================================================ FILE: Sources/Model/Base/XcodeObserver/Diff.swift ================================================ public struct Diff { public let added: Set public let removed: Set public let newValue: Set } extension Diff { init?(old: Set, new: Set) { if old.isEmpty, new.isEmpty { return nil } else if old.isEmpty { added = Set(new) removed = Set() } else if new.isEmpty { added = Set() removed = Set(old) } else { added = Set(new.filter{ !old.contains($0) }) removed = Set(old.filter{ !new.contains($0) }) if added.isEmpty, removed.isEmpty { return nil } } newValue = new } } ================================================ FILE: Sources/Model/Base/XcodeObserver/XcodeObserver.swift ================================================ import Version import Cocoa import Base import Path //TODO we're hiding errors when Xcode objects cannot be made etc. public enum RunStatus { case notRunning case running([Version]) } public enum XcodeError: Error { case unknownVersion case appleScriptBridgeFailed } public protocol XcodeObserverDelegate: class { func xcode(runStatus: RunStatus) func xcode(workspaceDiff: Diff) func xcode(error: Error) } public class XcodeObserver: NSObject { public override init() { runningApplications = NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dt.Xcode") openWorkspaces = Set(runningApplications.compactMap(\.xcode).flatMap(\.workspaces)) super.init() NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(onApplicationDidLaunch), name: NSWorkspace.didLaunchApplicationNotification, object: nil) let rawNames = [ "com.apple.dt.Xcode.notification.IDEActivityReportDistributedDidCompleteNotification", "com.apple.dt.Xcode.notification.IDEEditorCoordinatorDistributedDidCompleteNotification", "IDESchemeRunDestinationsDidUpdateNotification", "com.apple.sharedfilelist.change" //happens when workspaces close for some reason ] for rawName in rawNames { let name = Notification.Name(rawName) DistributedNotificationCenter.default().addObserver(self, selector: #selector(onDistributedNotification), name: name, object: nil) } } public private(set) var openWorkspaces: Set { didSet { if let diff = Diff(old: oldValue, new: openWorkspaces) { delegate?.xcode(workspaceDiff: diff) } } } public var isRunning: Bool { return runningApplications.first(where: { !$0.isTerminated }) != nil } var xcodes: [Xcode] { return runningApplications.compactMap(\.xcode) } func runStatus() throws -> RunStatus { if !isRunning { return .notRunning } else { return .running(xcodes.map{ $0.version ?? .null }) } } public weak var delegate: XcodeObserverDelegate? { didSet { do { delegate?.xcode(runStatus: try runStatus()) delegate?.xcode(workspaceDiff: Diff(added: openWorkspaces, removed: [], newValue: openWorkspaces)) } catch { delegate?.xcode(error: error) } } } private var kvoRefs: [NSKeyValueObservation] = [] private var runningApplications: [NSRunningApplication] = [] { didSet { do { delegate?.xcode(runStatus: try runStatus()) kvoRefs = runningApplications.map{ $0.observe(\.isTerminated) { [unowned self] app, _ in self.delegate?.xcode(runStatus: .notRunning) self.openWorkspaces = [] } } } catch { delegate?.xcode(error: error) kvoRefs = [] } } } @objc func onApplicationDidLaunch(_ note: Notification) { guard let userInfo = note.userInfo else { return } guard userInfo["NSApplicationBundleIdentifier"] as? String == "com.apple.dt.Xcode" else { return } if let app = userInfo["NSWorkspaceApplicationKey"] as? NSRunningApplication { runningApplications.append(app) } delegate?.xcode(workspaceDiff: Diff(added: [], removed: [], newValue: [])) } @objc func onDistributedNotification(_ note: Notification) { //NOTE the distributed notifications we subscribe to all undocumented and coincidental // and thus may be removed at any given Xcode or not behave as we expect at any given // moment. Therefore, this code should be changed! openWorkspaces = Set(xcodes.flatMap(\.workspaces)) } public var activeWorkspace: Path? { guard let xcode = xcodes.first else { return nil } return xcode.activeWorkspace } public var paths: [Path] { return runningApplications.compactMap(\.bundleURL).compactMap(Path.init) } } private extension NSRunningApplication { var xcode: Xcode? { return try? Xcode(pid: processIdentifier) } } ================================================ FILE: Sources/Model/Base/XcodeObserver/XcodeScriptingBridge.swift ================================================ import ScriptingBridge import Foundation import Version import Base import Path // NOTE if this class is NOT in this file, the AppleScript stops working… WTF? public class Xcode { private let bridge: XcodeApplication public init(pid: pid_t) throws { guard let b = SBApplication(processIdentifier: pid) else { throw XcodeError.appleScriptBridgeFailed } bridge = b } /// only works if Xcode is *still* running public var version: Version? { guard bridge.isRunning else { return nil } return bridge.version.flatMap(Version.init(tolerant:)) } public var isRunning: Bool { return bridge.isRunning } public var derivedData: Path { var `default`: Path { return Path.home/"Library/Developer/Xcode/DerivedData" } guard let defaults = UserDefaults(suiteName: "com.apple.dt.Xcode.plist") else { return `default` } if let customPath = defaults.string(forKey: "IDECustomDerivedDataLocation") { return Path.root/customPath } else { return `default` } } public func quit() throws { guard bridge.isRunning else { return } bridge.quitSaving?(.ask) if let err = bridge.lastError() { throw err } } public func open(documents: [Path] = []) { bridge.activate() _ = bridge.open?(documents.map(\.string)) } public var documents: [Path] { guard bridge.isRunning else { // ^^ otherwise causes Xcode to open due to use of scripting bridge return [] } // get() or risks crashing since array is “live” guard let docs = bridge.workspaceDocuments?().get() else { return [] } return docs.compactMap { ($0 as? XcodeWorkspaceDocument)?.path }.compactMap(Path.init) } var workspaces: [Path] { return documents.filter { ["xcodeproj", "xcworkspace"].contains($0.extension) } } public var activeWorkspace: Path? { guard let doc = bridge.activeWorkspaceDocument else { return nil } return doc.path.flatMap(Path.init) } } //MARK: Generated //NOTE: using sdef, sdp and https://github.com/tingraldi/SwiftScripting @objc protocol SBObjectProtocol: NSObjectProtocol { func get() -> Any! func lastError() -> Error? } @objc protocol SBApplicationProtocol: SBObjectProtocol { func activate() var delegate: SBApplicationDelegate! { get set } var isRunning: Bool { get } } // MARK: XcodeSaveOptions @objc enum XcodeSaveOptions : AEKeyword { case yes = 0x79657320 /* 'yes ' */ case no = 0x6e6f2020 /* 'no ' */ case ask = 0x61736b20 /* 'ask ' */ } // MARK: XcodeSchemeActionResultStatus @objc enum XcodeSchemeActionResultStatus : AEKeyword { case notYetStarted = 0x7372736e /* 'srsn' */ case running = 0x73727372 /* 'srsr' */ case cancelled = 0x73727363 /* 'srsc' */ case failed = 0x73727366 /* 'srsf' */ case errorOccurred = 0x73727365 /* 'srse' */ case succeeded = 0x73727373 /* 'srss' */ } // MARK: XcodeGenericMethods @objc protocol XcodeGenericMethods { @objc optional func closeSaving(_ saving: XcodeSaveOptions, savingIn: Any!) // Close a document. @objc optional func delete() // Delete an object. @objc optional func moveTo(_ to: Any!) // Move an object to a new location. @objc optional func build() -> XcodeSchemeActionResult // Invoke the "build" scheme action. This command should be sent to a workspace document. The build will be performed using the workspace document's current active scheme and active run destination. This command does not wait for the action to complete; its progress can be tracked with the returned scheme action result. @objc optional func clean() -> XcodeSchemeActionResult // Invoke the "clean" scheme action. This command should be sent to a workspace document. The clean will be performed using the workspace document's current active scheme and active run destination. This command does not wait for the action to complete; its progress can be tracked with the returned scheme action result. @objc optional func stop() // Stop the active scheme action, if one is running. This command should be sent to a workspace document. This command does not wait for the action to stop. @objc optional func runWithCommandLineArguments(_ withCommandLineArguments: Any!, withEnvironmentVariables: Any!) -> XcodeSchemeActionResult // Invoke the "run" scheme action. This command should be sent to a workspace document. The run action will be performed using the workspace document's current active scheme and active run destination. This command does not wait for the action to complete; its progress can be tracked with the returned scheme action result. @objc optional func testWithCommandLineArguments(_ withCommandLineArguments: Any!, withEnvironmentVariables: Any!) -> XcodeSchemeActionResult // Invoke the "test" scheme action. This command should be sent to a workspace document. The test action will be performed using the workspace document's current active scheme and active run destination. This command does not wait for the action to complete; its progress can be tracked with the returned scheme action result. } // MARK: XcodeApplication @objc protocol XcodeApplication: SBApplicationProtocol { @objc optional func documents() -> SBElementArray @objc optional func windows() -> SBElementArray @objc optional var name: Int { get } // The name of the application. @objc optional var frontmost: Int { get } // Is this the active application? @objc optional var version: String { get } // The version number of the application. @objc optional func `open`(_ x: Any!) -> Any // Open a document. @objc optional func quitSaving(_ saving: XcodeSaveOptions) // Quit the application. @objc optional func exists(_ x: Any!) // Verify that an object exists. @objc optional func fileDocuments() -> SBElementArray @objc optional func sourceDocuments() -> SBElementArray @objc optional func workspaceDocuments() -> SBElementArray @objc optional var activeWorkspaceDocument: XcodeWorkspaceDocument { get } // The active workspace document in Xcode. @objc optional func setActiveWorkspaceDocument(_ activeWorkspaceDocument: XcodeWorkspaceDocument!) // The active workspace document in Xcode. } extension SBApplication: XcodeApplication {} // MARK: XcodeDocument @objc protocol XcodeDocument: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // Its name. @objc optional var modified: Int { get } // Has it been modified since the last save? @objc optional var file: Int { get } // Its location on disk, if it has one. @objc optional var path: String { get } // The document's path. @objc optional func setPath(_ path: Int) // The document's path. } extension SBObject: XcodeDocument {} // MARK: XcodeWindow @objc protocol XcodeWindow: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The title of the window. @objc optional func id() // The unique identifier of the window. @objc optional var index: Int { get } // The index of the window, ordered front to back. @objc optional var bounds: Int { get } // The bounding rectangle of the window. @objc optional var closeable: Int { get } // Does the window have a close button? @objc optional var miniaturizable: Int { get } // Does the window have a minimize button? @objc optional var miniaturized: Int { get } // Is the window minimized right now? @objc optional var resizable: Int { get } // Can the window be resized? @objc optional var visible: Int { get } // Is the window visible right now? @objc optional var zoomable: Int { get } // Does the window have a zoom button? @objc optional var zoomed: Int { get } // Is the window zoomed right now? @objc optional var document: XcodeDocument { get } // The document whose contents are displayed in the window. @objc optional func setIndex(_ index: Int) // The index of the window, ordered front to back. @objc optional func setBounds(_ bounds: Int) // The bounding rectangle of the window. @objc optional func setMiniaturized(_ miniaturized: Int) // Is the window minimized right now? @objc optional func setVisible(_ visible: Int) // Is the window visible right now? @objc optional func setZoomed(_ zoomed: Int) // Is the window zoomed right now? } extension SBObject: XcodeWindow {} // MARK: XcodeFileDocument @objc protocol XcodeFileDocument: XcodeDocument { } extension SBObject: XcodeFileDocument {} // MARK: XcodeTextDocument @objc protocol XcodeTextDocument: XcodeFileDocument { @objc optional var text: Int { get } // The text of the text file referenced. @objc optional var notifiesWhenClosing: Int { get } // Should Xcode notify other apps when this document is closed? @objc optional func setText(_ text: Int) // The text of the text file referenced. @objc optional func setNotifiesWhenClosing(_ notifiesWhenClosing: Int) // Should Xcode notify other apps when this document is closed? } extension SBObject: XcodeTextDocument {} // MARK: XcodeSourceDocument @objc protocol XcodeSourceDocument: XcodeTextDocument { } extension SBObject: XcodeSourceDocument {} // MARK: XcodeWorkspaceDocument @objc protocol XcodeWorkspaceDocument: XcodeDocument { @objc optional func breakpoints() -> SBElementArray @objc optional func projects() @objc optional func schemes() @objc optional func runDestinations() @objc optional var loaded: Int { get } // Whether the workspace document has finsished loading after being opened. Messages sent to a workspace document before it has loaded will result in errors. @objc optional var activeScheme: XcodeScheme { get } // The workspace's scheme that will be used for scheme actions. @objc optional var activeRunDestination: XcodeRunDestination { get } // The workspace's run destination that will be used for scheme actions. @objc optional var lastSchemeActionResult: XcodeSchemeActionResult { get } // The scheme action result for the last scheme action command issued to the workspace document. @objc optional var file: Int { get } // The workspace document's location on disk, if it has one. @objc optional func setLoaded(_ loaded: Int) // Whether the workspace document has finsished loading after being opened. Messages sent to a workspace document before it has loaded will result in errors. @objc optional func setActiveScheme(_ activeScheme: XcodeScheme!) // The workspace's scheme that will be used for scheme actions. @objc optional func setActiveRunDestination(_ activeRunDestination: XcodeRunDestination!) // The workspace's run destination that will be used for scheme actions. @objc optional func setLastSchemeActionResult(_ lastSchemeActionResult: XcodeSchemeActionResult!) // The scheme action result for the last scheme action command issued to the workspace document. } extension SBObject: XcodeWorkspaceDocument {} // MARK: XcodeSchemeActionResult @objc protocol XcodeSchemeActionResult: SBObjectProtocol, XcodeGenericMethods { @objc optional func buildErrors() @objc optional func buildWarnings() @objc optional func analyzerIssues() @objc optional func testFailures() @objc optional func id() // The unique identifier for the scheme. @objc optional var completed: Int { get } // Whether this scheme action has completed (sucessfully or otherwise) or not. @objc optional var status: XcodeSchemeActionResultStatus { get } // Indicates the status of the scheme action. @objc optional var errorMessage: Int { get } // If the result's status is "error occurred", this will be the error message; otherwise, this will be "missing value". @objc optional var buildLog: Int { get } // If this scheme action performed a build, this will be the text of the build log. @objc optional func setStatus(_ status: XcodeSchemeActionResultStatus) // Indicates the status of the scheme action. @objc optional func setErrorMessage(_ errorMessage: Int) // If the result's status is "error occurred", this will be the error message; otherwise, this will be "missing value". @objc optional func setBuildLog(_ buildLog: Int) // If this scheme action performed a build, this will be the text of the build log. } extension SBObject: XcodeSchemeActionResult {} // MARK: XcodeSchemeActionIssue @objc protocol XcodeSchemeActionIssue: SBObjectProtocol, XcodeGenericMethods { @objc optional var message: Int { get } // The text of the issue. @objc optional var filePath: Int { get } // The file path where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional var startingLineNumber: Int { get } // The starting line number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional var endingLineNumber: Int { get } // The ending line number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional var startingColumnNumber: Int { get } // The starting column number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional var endingColumnNumber: Int { get } // The ending column number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional func setMessage(_ message: Int) // The text of the issue. @objc optional func setFilePath(_ filePath: Int) // The file path where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional func setStartingLineNumber(_ startingLineNumber: Int) // The starting line number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional func setEndingLineNumber(_ endingLineNumber: Int) // The ending line number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional func setStartingColumnNumber(_ startingColumnNumber: Int) // The starting column number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. @objc optional func setEndingColumnNumber(_ endingColumnNumber: Int) // The ending column number in the file where the issue occurred. This may be 'missing value' if the issue is not associated with a specific source file. } extension SBObject: XcodeSchemeActionIssue {} // MARK: XcodeBuildError @objc protocol XcodeBuildError: XcodeSchemeActionIssue { } extension SBObject: XcodeBuildError {} // MARK: XcodeBuildWarning @objc protocol XcodeBuildWarning: XcodeSchemeActionIssue { } extension SBObject: XcodeBuildWarning {} // MARK: XcodeAnalyzerIssue @objc protocol XcodeAnalyzerIssue: XcodeSchemeActionIssue { } extension SBObject: XcodeAnalyzerIssue {} // MARK: XcodeTestFailure @objc protocol XcodeTestFailure: XcodeSchemeActionIssue { } extension SBObject: XcodeTestFailure {} // MARK: XcodeScheme @objc protocol XcodeScheme: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The name of the scheme. @objc optional func id() // The unique identifier for the scheme. } extension SBObject: XcodeScheme {} // MARK: XcodeRunDestination @objc protocol XcodeRunDestination: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The name of the run destination, as displayed in Xcode's interface. @objc optional var architecture: Int { get } // The architecture for which this run destination results in execution. @objc optional var platform: Int { get } // The identifier of the platform which this run destination targets, such as "macosx", "iphoneos", "iphonesimulator", etc . @objc optional var device: XcodeDevice { get } // The physical or virtual device which this run destination targets. @objc optional var companionDevice: XcodeDevice { get } // If the run destination's device has a companion (e.g. a paired watch for a phone) which it will use, this is that device. } extension SBObject: XcodeRunDestination {} // MARK: XcodeDevice @objc protocol XcodeDevice: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The name of the device. @objc optional var deviceIdentifier: Int { get } // A stable identifier for the device, as shown in Xcode's "Devices" window. @objc optional var operatingSystemVersion: Int { get } // The version of the operating system installed on the device which this run destination targets. @objc optional var deviceModel: Int { get } // The model of device (e.g. "iPad Air") which this run destination targets. @objc optional var generic: Int { get } // Whether this run destination is generic instead of representing a specific device. Most destinations are not generic, but a generic destination (such as "Generic iOS Device") will be available for some platforms if no physical devices are connected. } extension SBObject: XcodeDevice {} // MARK: XcodeBuildConfiguration @objc protocol XcodeBuildConfiguration: SBObjectProtocol, XcodeGenericMethods { @objc optional func buildSettings() @objc optional func resolvedBuildSettings() @objc optional func id() // The unique identifier for the build configuration. @objc optional var name: Int { get } // The name of the build configuration. } extension SBObject: XcodeBuildConfiguration {} // MARK: XcodeProject @objc protocol XcodeProject: SBObjectProtocol, XcodeGenericMethods { @objc optional func buildConfigurations() @objc optional func targets() @objc optional var name: Int { get } // The name of the project @objc optional func id() // The unique identifier for the project. } extension SBObject: XcodeProject {} // MARK: XcodeBuildSetting @objc protocol XcodeBuildSetting: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The unlocalized build setting name (e.g. DSTROOT). @objc optional var value: Int { get } // A string value for the build setting. @objc optional func setName(_ name: Int) // The unlocalized build setting name (e.g. DSTROOT). @objc optional func setValue(_ value: Int) // A string value for the build setting. } extension SBObject: XcodeBuildSetting {} // MARK: XcodeResolvedBuildSetting @objc protocol XcodeResolvedBuildSetting: SBObjectProtocol, XcodeGenericMethods { @objc optional var name: Int { get } // The unlocalized build setting name (e.g. DSTROOT). @objc optional var value: Int { get } // A string value for the build setting. @objc optional func setName(_ name: Int) // The unlocalized build setting name (e.g. DSTROOT). @objc optional func setValue(_ value: Int) // A string value for the build setting. } extension SBObject: XcodeResolvedBuildSetting {} // MARK: XcodeTarget @objc protocol XcodeTarget: SBObjectProtocol, XcodeGenericMethods { @objc optional func buildConfigurations() @objc optional var name: Int { get } // The name of this target. @objc optional func id() // The unique identifier for the target. @objc optional var project: XcodeProject { get } // The project that contains this target @objc optional func setName(_ name: Int) // The name of this target. } extension SBObject: XcodeTarget {} enum XcodeScripting: String { case analyzerIssue = "analyzer issue" case application = "application" case buildConfiguration = "build configuration" case buildError = "build error" case buildSetting = "build setting" case buildWarning = "build warning" case device = "device" case document = "document" case fileDocument = "file document" case project = "project" case resolvedBuildSetting = "resolved build setting" case runDestination = "run destination" case schemeActionIssue = "scheme action issue" case schemeActionResult = "scheme action result" case scheme = "scheme" case sourceDocument = "source document" case target = "target" case testFailure = "test failure" case textDocument = "text document" case window = "window" case workspaceDocument = "workspace document" } ================================================ FILE: Sources/Model/Base/XcodeProject/*Target.swift ================================================ import xcodeproj import Base public extension XcodeProject { class Target { let owner: XcodeProject let underlyingTarget: PBXTarget init(owner: XcodeProject, underlyingTarget: PBXTarget) { self.owner = owner self.underlyingTarget = underlyingTarget } } class NativeTarget: Target { } } public extension XcodeProject.Target { var name: String { return underlyingTarget.name } var type: PBXProductType? { return underlyingTarget.productType } var hasDependencies: Bool { return !underlyingTarget.dependencies.isEmpty } func add(script: String) -> PBXShellScriptBuildPhase { let phase = PBXShellScriptBuildPhase(shellScript: script, showEnvVarsInLog: false) underlyingTarget.buildPhases.append(phase) owner.add(phase) return phase } } public extension XcodeProject.NativeTarget { func link(to target: XcodeProject.NativeTarget) throws { guard let productRef = target.underlyingTarget.product else { throw XcodeProject.E.nativeTargetHasNoProductReference } if target.owner == owner { _ = try linkPhase.add(file: productRef) } else { let (containerPortal, productsGroup) = try owner._addProjectReference(to: target.owner) let remote = PBXContainerItemProxy(containerPortal: containerPortal, remoteGlobalID: productRef, proxyType: .reference, remoteInfo: target.name) let refProxy = PBXReferenceProxy(fileType: productRef.explicitFileType, path: productRef.path, name: target.name, remote: remote, sourceTree: .buildProductsDir) _ = try linkPhase.add(file: refProxy) owner.add(remote) owner.add(refProxy) productsGroup.children.append(refProxy) } } func build(source: PBXFileReference) throws { _ = try sourcesPhase.add(file: source) } func build(resource: PBXFileReference) throws { _ = try resourcesPhase.add(file: resource) } func depend(on target: XcodeProject.Target) throws { if target.owner == owner { _ = try (underlyingTarget as! PBXNativeTarget).addDependency(target: target.underlyingTarget) } else { let (containerPortal, _) = try owner._addProjectReference(to: target.owner) let proxy = PBXContainerItemProxy(containerPortal: containerPortal, remoteGlobalID: target.underlyingTarget, proxyType: .nativeTarget, remoteInfo: target.name) let dep = PBXTargetDependency(name: target.name, target: target.underlyingTarget, targetProxy: proxy) underlyingTarget.dependencies.append(dep) owner.add(proxy) owner.add(dep) } } func purge(_ dependency: XcodeProject.NativeTarget) { if dependency.owner == owner { fatalError() } else { for dep in owner.pbxproj.targetDependencies where dep.target == dependency.underlyingTarget { owner.remove(dep.targetProxy) owner.remove(dep) if let index = underlyingTarget.dependencies.firstIndex(of: dep) { underlyingTarget.dependencies.remove(at: index) } } //FIXME will create the linkPhase if doesn't exist yet! let linkPhase = self.linkPhase //FIXME needs to compare containerPortal for case let (index, file) in linkPhase.files.reversed().enumerated() { if let ref = file.file, ref.name == dependency.name { linkPhase.files.remove(at: index) owner.remove(ref) } } } } } ================================================ FILE: Sources/Model/Base/XcodeProject/+functions.swift ================================================ import xcodeproj extension XcodeProject { public func preventSwiftMigration(for targets: [NativeTarget]) { let dict = [ "LastSwiftMigration": "9999" ] for target in targets { proj.pbxproj.rootObject!.setTargetAttributes(dict, target: target.underlyingTarget) } } public func addNativeTarget(name: String, type: PBXProductType, productName: String? = nil) -> NativeTarget { var displayName: String { let name = productName ?? name switch type { case .dynamicLibrary: return "\(name).dylib" case .staticLibrary: return "\(name).a" default: return name } } let productRef = PBXFileReference(sourceTree: .group, path: displayName) add(productRef) productsGroup.children.append(productRef) let target = PBXNativeTarget(name: name, buildConfigurationList: nil, buildPhases: [], buildRules: [], dependencies: [], productInstallPath: nil, productName: productName, product: productRef, productType: type) target.product = productRef add(target) pbxproj.rootObject!.targets.append(target) let nativeTarget = NativeTarget(owner: self, underlyingTarget: target) if let productName = productName { nativeTarget["PRODUCT_NAME"] = productName } if type == .dynamicLibrary { nativeTarget["EXECUTABLE_PREFIX"] = "lib" } return nativeTarget } public func addAggregateTarget(name: String) -> Target { let target = PBXAggregateTarget(name: name) add(target) pbxproj.rootObject!.targets.append(target) return Target(owner: self, underlyingTarget: target) } public func addProjectReference(to other: XcodeProject) throws { _ = try _addProjectReference(to: other) } func _addProjectReference(to other: XcodeProject) throws -> (PBXFileReference, PBXGroup) { if let foo = projectReferences[other] { return foo } guard other != self else { throw E.cannotReferenceSelf } let projectfileRef = mainGroup.add(file: other.path, name: .basename, type: .project) projectfileRef.explicitFileType = FileType.project.rawValue let hiddenProductGroup = PBXGroup(name: "Products") add(hiddenProductGroup) add(projectfileRef) // https://github.com/tuist/xcodeproj/issues/352 proj.pbxproj.rootObject!.projects.append([ "ProjectRef": projectfileRef, "ProductGroup": hiddenProductGroup ]) projectReferences[other] = (projectfileRef, hiddenProductGroup) return (projectfileRef, hiddenProductGroup) } public func removeProjectReference(_ proj: XcodeProject) { func isProj(_ ref: PBXFileReference) -> Bool { return ref.lastKnownFileType == FileType.project.rawValue || ref.explicitFileType == FileType.project.rawValue } //FIXME not specific enough //FIXME doesn't remove all necessary objects for (index, dict) in proj.pbxproj.rootObject!.projects.reversed().enumerated() { if let ref = dict["ProjectRef"] as? PBXFileReference, isProj(ref), ref.name == proj.path.basename() { proj.pbxproj.rootObject!.projects.remove(at: index) } } } func add(_ object: PBXObject) { pbxproj.add(object: object) } func remove(_ object: PBXObject?) { if let object = object { pbxproj.delete(object: object) } } } ================================================ FILE: Sources/Model/Base/XcodeProject/+platforms.swift ================================================ import CakefileDescription import xcodeproj import Version import Base public extension XcodeProject { var platforms: Set { func extract(buildConfiguration: XCBuildConfiguration) -> [(Platform, Version)] { return buildConfiguration.platforms.compactMap { guard let v = buildConfiguration.deploymentVersion(for: $0) else { return nil } return ($0, v) } } var rv = [Platform: Version]() for (platform, version) in pbxproj.buildConfigurations.flatMap(extract) { rv[platform] = min(rv[platform, default: version], version) } return Set(rv.map(PlatformSpecification.init)) } var swiftVersion: SwiftVersion { return pbxproj.buildConfigurations.compactMap { $0.buildSettings["SWIFT_VERSION"] as? String }.compactMap(SwiftVersion.init).max() ?? .default } } private extension Platform { init?(buildSetting: Any?) { switch buildSetting as? String { case "maxosx"?: self = .macOS case "iphoneos"?, "iphonesimulator"?: self = .iOS default: return nil } } } extension XCBuildConfiguration { fileprivate var platforms: Set { if let foo = buildSettings["SUPPORTED_PLATFORMS"] as? [String] { return Set(foo.compactMap(Platform.init(buildSetting:))) } else if let foo = buildSettings["SDKROOT"] as? String, let platform = Platform(buildSetting: foo) { return [platform] } else { return [] } } public func deploymentVersion(for platform: Platform) -> Version? { var string: String? { switch platform { case .macOS: return buildSettings["MACOSX_DEPLOYMENT_TARGET"] as? String case .iOS: return buildSettings["IPHONEOS_DEPLOYMENT_TARGET"] as? String } } guard let str = string, let f = Double(str) else { return nil } return Version(floatLiteral: f) } } extension XcodeProject { public func deploymentVersion(for platform: Platform) -> Version? { return pbxproj.buildConfigurations.compactMap { $0.buildSettings[platform.buildConfigurationKey] as? String }.compactMap(Version.init(tolerant:)).max() } public var deploymentTargets: Set { return Set([Platform.iOS, .macOS].compactMap { platform in deploymentVersion(for: platform).map { PlatformSpecification(platform: platform, version: $0) } }) } } private extension Platform { var buildConfigurationKey: String { switch self { case .iOS: return "IPHONEOS_DEPLOYMENT_TARGET" case .macOS: return "MACOSX_DEPLOYMENT_TARGET" } } } ================================================ FILE: Sources/Model/Base/XcodeProject/Group.swift ================================================ import xcodeproj import Path public extension XcodeProject { struct Group { let owner: XcodeProject let parentPath: Path let underlyingGroup: PBXGroup var path: Path { return parentPath/(underlyingGroup.path ?? "") } } } public extension XcodeProject.Group { enum Position { case top, bottom } var name: String { return underlyingGroup.name ?? path.basename() } var subgroups: [XcodeProject.Group] { return underlyingGroup.children.compactMap{ $0 as? PBXGroup }.map { .init(owner: owner, parentPath: path, underlyingGroup: $0) } } private func smartAppend(_ ref: PBXFileElement) { // insert before the Products Group if applicable if underlyingGroup === owner.mainGroup.underlyingGroup, let index = underlyingGroup.children.firstIndex(where: { $0 === owner.productsGroup }) { underlyingGroup.children.insert(ref, at: index) } else { underlyingGroup.children.append(ref) } } @discardableResult func add(file: Path, name: XcodeProject.Name = .inferred, type: XcodeProject.FileType? = nil, at position: Position = .bottom) -> PBXFileReference { let ref = PBXFileReference(sourceTree: .group, name: name.string(path: file), lastKnownFileType: type?.rawValue, path: file.relative(to: path)) owner.add(ref) switch position { case .bottom: smartAppend(ref) case .top: underlyingGroup.children.insert(ref, at: 0) } return ref } func add(group groupPath: Path, name: XcodeProject.Name = .inferred) throws -> XcodeProject.Group { let group = PBXGroup(sourceTree: .group, name: name.string(path: groupPath), path: groupPath.relative(to: path)) smartAppend(group) owner.add(group) return .init(owner: owner, parentPath: self.path, underlyingGroup: group) } // adds a group without a path func addGroup(name: String) -> XcodeProject.Group { let group = PBXGroup(sourceTree: .group, name: name) smartAppend(group) owner.add(group) return .init(owner: owner, parentPath: path, underlyingGroup: group) } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/+functions.swift ================================================ import Modelizer import Path extension XcakeProject { func generateBatterDotSwift(tips: [Module]) throws { var string = """ // Generated by Cake. Regeneration will occur! Edits will be lost! // Modules are sorted *topologically*. """ for module in tips.flattened { string += "@_exported import \(module.name)\n" } try string.write(to: caked.join("Batter.swift").makeWritable()).chmod(0o444) } func generateDependenciesDotSwift(importNames: [String]) throws { var string = """ // Generated by Cake. Regeneration will occur! Edits will be lost! // We only export _directly_specified_ dependencies. """ for moduleName in importNames { string += "@_exported import \(moduleName)\n" } try string.write(to: caked.join("Dependencies.swift").makeWritable()).chmod(0o444) } } private extension Path { func makeWritable() throws -> Path { if isFile { return try chmod(0o600) } else { return self } } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/Cakefile.swift ================================================ import CakefileDescription import Foundation import Version import Path public enum E: Error { case noCakefile case executionFailed(String, args: [String], exit: Int32) case toolkit(required: Range, available: Version) case noDependenciesInCakefile } public typealias ProcessorError = E struct Cakefile { let path: Path let mtime: Date? private let dump: CakefileDump var options: Options { return dump.options } var dependencies: [PackageSpecification] { return dump.dependencies } var platforms: Set { return dump.platforms } var cakeRequirement: Range? { if case .version(.range(let v))? = dump.cake { return v } else { return nil } } init(path: Path, toolkit: Processor.Toolkit) throws { guard path.isFile else { throw E.noCakefile } self.path = path self.dump = try parse(cakefile: path, toolkit: toolkit) self.mtime = path.mtime } } public struct CakefileParseError: LocalizedError { public let errorDescription: String? } private func parse(cakefile path: Path, toolkit: Processor.Toolkit) throws -> CakefileDump { //TODO use stdin to `swift -` var contents = try String(contentsOf: path) contents += """ import Foundation let dump = CakefileDump(platforms: platforms, dependencies: dependencies, options: options) let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let data = try encoder.encode(dump) let str = String(data: data, encoding: .utf8)! print(str) """ let (stdout, stderr) = try Path.mktemp { tmpdir -> (Process.Output, Process.Output) in let tmpfile = tmpdir/"Cakefile.swift" try contents.write(to: tmpfile) let tmppath = tmpdir.join("Cakefile.swift").string let task = Process() task.launchPath = toolkit.swift.string task.arguments = [ "-module-name", "CakefileScript", "-L", toolkit.L.string, "-I", toolkit.I.string, "-lCakefile", tmppath] do { return try task.runSync(tee: true) } catch let error as Process.ExecutionError { guard let str = error.stderr.string else { throw error } let mangledError: [Substring] = str.split(separator: "\n").map { line in if line.hasPrefix(tmpfile.string) { return path.string + line.dropFirst(tmpfile.string.count) } else { return line } } throw CakefileParseError(errorDescription: mangledError.joined(separator: "\n")) } } if !stderr.data.isEmpty, let string = stderr.string { fputs(string, Darwin.stderr) } try stdout.data.write(to: path.parent/".cake/Cakefile.json") return try JSONDecoder().decode(CakefileDump.self, from: stdout.data) } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/Dependencies.swift ================================================ import struct Modelizer.DependenciesJSON import CakefileDescription import Foundation import Path class Dependencies { let cakefileRepresentation: [PackageSpecification] let json: DependenciesJSON var isEmpty: Bool { return json.packages.isEmpty } init(deps: [PackageSpecification], prefix: Path, bindir: Path, libpmdir: Path, DEVELOPER_DIR: Path) throws { cakefileRepresentation = deps guard !deps.isEmpty else { // no need to do all the heavy SwiftPM lifting json = .init() return } var manifest = """ // swift-tools-version:5.0 import PackageDescription let pkg = Package(name: "Dependencies", dependencies: [ """ for dep in deps { manifest += " \(dep),\n" } manifest += "])\n" try manifest.write(to: prefix/".cake/Package.swift") let decoder = JSONDecoder() decoder.userInfo[.relativePath] = prefix/"Dependencies" let task = Process() task.launchPath = bindir.join("mixer").string task.arguments = [prefix.string, libpmdir.string] task.environment = ProcessInfo.processInfo.environment task.environment!["DEVELOPER_DIR"] = DEVELOPER_DIR.string let (stdout, _) = try task.runSync(tee: true) json = try decoder.decode(DependenciesJSON.self, from: stdout.data) } } extension PackageSpecification: CustomStringConvertible { public var description: String { switch constraint { case .version(.range(let range)): let v1 = range.lowerBound let v2 = range.upperBound if v2.major == v1.major + 1, v2.minor == 0, v2.patch == 0 { return """ .package(url: "\(url)", from: "\(v1)") """ } else { return """ .package(url: "\(url)", Version(\(v1.major),\(v1.minor),\(v1.patch)).. Bool { //TODO don't do cakefile too! return try processor.generate() } public func updateDependencies() throws { try processor.updateDependencies() delegate?.cakeProjectDependenciesUpdated(self) } } extension CakeProject: FSWatcherDelegate { func fsWatcherRescanRequired() { delegate?.cakeProjectModulesChanged(self) } func fsWatcher(paths: [String], events: [FSWatcher.Event]) { for (path, event) in zip(paths, events) { if path == cakefile.string { if event == .modified { delegate?.cakeProjectCakefileChanged(self) return // triggers module scan too } } else { delegate?.cakeProjectModulesChanged(self) } } } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/Kitchen/FSWatcher.swift ================================================ import Foundation protocol FSWatcherDelegate: class { func fsWatcherRescanRequired() func fsWatcher(paths: [String], events: [FSWatcher.Event]) } class FSWatcher { private var stream: FSEventStreamRef? weak var delegate: FSWatcherDelegate? { didSet { if delegate == nil { pause() } else { resume() } } } deinit { if let stream = stream { FSEventStreamStop(stream) FSEventStreamInvalidate(stream) FSEventStreamRelease(stream) } } var watchingPaths: Set = [] { didSet { guard watchingPaths != oldValue else { return } pause() stream = nil start() } } private func start() { guard stream == nil, !watchingPaths.isEmpty else { return } let paths = Array(watchingPaths) as CFArray var context = FSEventStreamContext(version: 0, info: UnsafeMutableRawPointer(mutating: Unmanaged.passUnretained(self).toOpaque()), retain: nil, release: nil, copyDescription: nil) stream = FSEventStreamCreate(kCFAllocatorDefault, innerEventCallback, &context, paths, FSEventStreamEventId(kFSEventStreamEventIdSinceNow), 0, UInt32(kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagFileEvents)) FSEventStreamScheduleWithRunLoop(stream!, RunLoop.current.getCFRunLoop(), CFRunLoopMode.defaultMode.rawValue) FSEventStreamStart(stream!) } func resume() { _ = stream.map(FSEventStreamStart) } func pause() { stream.map(FSEventStreamStop) } private let innerEventCallback: FSEventStreamCallback = { (stream, contextInfo, numEvents, eventPaths, eventFlags, eventIds) in let fsWatcher = unsafeBitCast(contextInfo, to: FSWatcher.self) func path(at: Int) -> String { return unsafeBitCast(eventPaths, to: NSArray.self)[at] as! String } var paths: [String] = [] var events: [Event] = [] for x in 0..) { dispatchPrecondition(condition: .onQueue(.main)) cakes.remove(paths: diff.removed) for path in diff.added { do { //TODO path needs to be determined from the Xcode for this project guard let xcodePath = xcodeObserver.paths.first, let toolkit = Processor.Toolkit(cake: cakeBundle, xcode: xcodePath) else { throw E.xcodeVersionUnavailable } let proj = try CakeProject(xcodeproj: path, toolkit: toolkit) proj.delegate = self cakes.append(proj) } catch E.notCake { //noop } catch { delegate?.kitchen(error: error) } } notCakes = xcodeObserver.openWorkspaces.subtracting(cakes.map(\.xcodeproj)).sorted() delegate?.kitchen( cake: cakes, notCake: notCakes.map{ $0.basename(dropExtension: true) }) } public func xcode(error: Error) { dispatchPrecondition(condition: .onQueue(.main)) delegate?.kitchen(error: error) } } extension Kitchen: CakeProjectDelegate { public func cakeProjectCakefileChanged(_ cake: CakeProject) { dispatchPrecondition(condition: .onQueue(.main)) do { try cake.processCakefile() if try cake.generateXcodeproj() { delegate?.kitchen(regenerated: cake) } } catch { delegate?.kitchen(error: error) } } public func cakeProjectModulesChanged(_ cake: CakeProject) { dispatchPrecondition(condition: .onQueue(.main)) do { if try cake.generateXcodeproj() { delegate?.kitchen(regenerated: cake) } } catch { delegate?.kitchen(error: error) } } public func cakeProjectDependenciesUpdated(_ cake: CakeProject) { dispatchPrecondition(condition: .onQueue(.main)) delegate?.kitchen(regenerated: cake) } } private extension Array where Element == CakeProject { mutating func remove(paths: Set) { guard !paths.isEmpty else { return } removeAll { paths.contains($0.xcodeproj) } } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/Kitchen/KitchenDelegate.swift ================================================ public protocol KitchenDelegate: class { func xcode(isRunning: Bool) func kitchen(cake: [CakeProject], notCake: [String]) func kitchen(error: Error) func kitchen(regenerated: CakeProject) } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/Self.swift ================================================ import struct CakefileDescription.PlatformSpecification import enum Base.SwiftVersion import XcakeProject import XcodeProject import Foundation import Modelizer import Path public class Processor { /// path to the Xcode Project that is Cake public let xcodeproj: Path /// time that the last generation attempt *completed* public internal(set) var lastGenerationTime: Date? var cakefile: Cakefile var dependencies: Dependencies var extractedData: ExtractedData var platforms: Set { return cakefile.platforms.union(extractedData.platforms) } public var cakefilePath: Path { return cakefile.path } public var prefix: Path { return xcodeproj.parent } public var modelsPrefix: Path { return prefix/"Sources/Model" } public let toolkit: Toolkit public init(xcodeproj: Path, toolkit: Toolkit) throws { //TODO should load from JSON unless mtime is greater self.toolkit = toolkit self.xcodeproj = xcodeproj (cakefile, dependencies) = try toolkit.foo(prefix: xcodeproj.parent) self.extractedData = try ExtractedData(path: xcodeproj) try _generate(tips: getTips()) } var previousTips = Set() private func getTips() throws -> [Module] { return try modelize(root: modelsPrefix, basename: cakefile.options.baseModuleName) } func _generate(tips: [Module], set: Set? = nil) throws { try XcakeProject( tips: tips, dependencies: dependencies.json, prefix: prefix, platforms: platforms, swift: extractedData.swiftVersion, suppressDependencyWarnings: cakefile.options.suppressDependencyWarnings ).write() previousTips = set ?? Set(tips) lastGenerationTime = Date() } /// - Parameter force: force generation ignoring dependency information /// - Returns: if generation occurred @discardableResult public func generate(force: Bool = false) throws -> Bool { //TODO change detection could be more efficient // no need to calculate modules for eg. if directory structure is identical // FSEvent system provides granular event detail, and we're only interested // in move, rename, create and delete basically and then only if they are // swift files or directories that contain swift files or subdirectories // with swift files var needsGeneration = false guard !force else { (cakefile, dependencies) = try toolkit.foo(prefix: prefix) extractedData = try ExtractedData(path: xcodeproj) let tips = try getTips() previousTips = Set(tips) try _generate(tips: tips) return true } try toolkit.make() if isDirty(input: cakefilePath.mtime, cache: cakefile.mtime) { cakefile = try toolkit.bar(prefix: prefix) needsGeneration = true } if cakefile.dependencies != dependencies.cakefileRepresentation { //FIXME not DRY dependencies = try Dependencies(deps: cakefile.dependencies, prefix: prefix, bindir: toolkit.bindir, libpmdir: toolkit.pm, DEVELOPER_DIR: toolkit.xcodePath) needsGeneration = true //FIXME currently the Mixer writes dependencies.json, but maybe we should? } if isDirty(input: extractedData.path.mtime, cache: extractedData.mtime) { extractedData = try ExtractedData(path: xcodeproj) } let tips = try getTips() let set = Set(tips) needsGeneration = needsGeneration || set != previousTips if needsGeneration { try _generate(tips: tips, set: set) return true } else { return false } } public func updateDependencies() throws { if dependencies.isEmpty { throw E.noDependenciesInCakefile } let task = Process() task.launchPath = toolkit.swift.string task.arguments = ["package", "--build-path", "swift-pm", "update"] task.currentDirectoryPath = prefix.join(".cake").string try task.run() task.waitUntilExit() if task.terminationReason == .uncaughtSignal || task.terminationStatus != 0 { throw CocoaError.error(.executableLoad) } try generate(force: true) } } private extension Processor.Toolkit { func foo(prefix: Path) throws -> (Cakefile, Dependencies) { try make() let cakefile = try bar(prefix: prefix) let dependencies = try Dependencies(deps: cakefile.dependencies, prefix: prefix, bindir: bindir, libpmdir: pm, DEVELOPER_DIR: xcodePath) return (cakefile, dependencies) } func bar(prefix: Path) throws -> Cakefile { let cakefile = try Cakefile(path: prefix/"Cakefile.swift", toolkit: self) if let requirement = cakefile.cakeRequirement, !requirement.contains(cakeVersion) { throw E.toolkit(required: requirement, available: cakeVersion) } return cakefile } } private extension Bundle { var executables: Path { return executablePath.flatMap(Path.init)!.parent } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/SwiftVersion.swift ================================================ import struct CakefileDescription.PlatformSpecification import enum Base.SwiftVersion import XcodeProject import Foundation import Path struct ExtractedData { let path: Path let swiftVersion: Base.SwiftVersion let platforms: Set let mtime: Date? init(path: Path) throws { self.path = path let xcodeproj = try XcodeProject(existing: path) swiftVersion = xcodeproj.swiftVersion platforms = xcodeproj.deploymentTargets mtime = path.mtime } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/TemporaryDirectory.swift ================================================ import Foundation import Path class TemporaryDirectory { let url: URL var path: Path { return Path.root/url.path } var string: String { return url.path } /** Creates a new temporary directory. The directory is recursively deleted when this object deallocates. If you need a temporary directory on a specific volume use the `appropriateFor` parameter. - Important: If you are moving a file, ensure to use the `appropriateFor` parameter, since it is volume aware and moving the file across volumes will take exponentially longer! - Important: The `appropriateFor` parameter does not work on Linux. - Parameter appropriateFor: The temporary directory will be located on this volume. */ init(appropriateFor: URL? = nil) throws { #if !os(Linux) let appropriate: URL if let appropriateFor = appropriateFor { appropriate = appropriateFor } else if #available(OSX 10.12, iOS 10, tvOS 10, watchOS 3, *) { appropriate = FileManager.default.temporaryDirectory } else { appropriate = URL(fileURLWithPath: NSTemporaryDirectory()) } url = try FileManager.default.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: appropriate, create: true) #else let envs = ProcessInfo.processInfo.environment let env = envs["TMPDIR"] ?? envs["TEMP"] ?? envs["TMP"] ?? "/tmp" let dir = Path.root/env/"swift-sh.XXXXXX" var template = [UInt8](dir.string.utf8).map({ Int8($0) }) + [Int8(0)] guard mkdtemp(&template) != nil else { throw CocoaError.error(.featureUnsupported) } url = URL(fileURLWithPath: String(cString: template)) #endif } deinit { _ = try? FileManager.default.removeItem(at: url) } } extension Path { static func mktemp(body: (Path) throws -> T) throws -> T { let tmp = try TemporaryDirectory() return try body(tmp.path) } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/Processor/etc.swift ================================================ import Foundation func warning(_ msg: Any) { fputs("warning: \(msg)\n", stderr) } func error(_ msg: Any) -> Never { fputs("error: \(msg)\n", stderr) exit(1) } import Version import Path public extension Processor { struct Toolkit { let cakePath: Path public let xcodePath: Path public let cakeVersion: Version public let xcodeProductBuildVersion: String static var derivedData: Path { return Path.home.Library.Developer.Cake.DerivedData } var makedir: Path { return Toolkit.derivedData/xcodeProductBuildVersion } var L: Path { return makedir/"lib" } var I: Path { return L } var pm: Path { return L.pm } var bindir: Path { return cakePath.Contents.MacOS } func make() throws { let task = Process() task.launchPath = xcodePath.join("Contents/Developer/usr/bin/make").string task.currentDirectoryPath = cakePath.Contents.KitchenWare.string var env = ProcessInfo.processInfo.environment env["OUTDIR"] = makedir.string task.environment = env try task.run() task.waitUntilExit() if task.terminationReason == .uncaughtSignal || task.terminationStatus != 0 { throw CocoaError.error(.executableLoad) } } public var swift: Path { return xcodePath/"Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift" } public init?(cake: Bundle, xcode: Path) { guard let dict = NSDictionary(contentsOf: xcode.join("Contents/version.plist").url) else { return nil } guard let v = dict["ProductBuildVersion"] as? String else { return nil } xcodeProductBuildVersion = v cakeVersion = cake.version xcodePath = xcode cakePath = cake.path } } } func isDirty(input: Date?, cache: Date?) -> Bool { if let a = input, let b = cache { return a > b } else { return true } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/XcakeProject.swift ================================================ import class Foundation.Bundle import enum Base.SwiftVersion import CakefileDescription import XcodeProject import Modelizer import Path public class XcakeProject: XcodeProject { let tips: [Module] let dependencies: DependenciesJSON var caked: Path { return parentDirectory } var prefix: Path { return caked.parent } var modelPrefix: Path { return prefix/"Sources/Model" } var cakeTarget: NativeTarget! enum E: Error { case modulePathNotInPrefix(Path) case programmerError case pathRelationError case noModules case invalidModuleHeirarchy /// we can support different structures, open a PR without code for discussion case unsupportedDirectoryHierarchy case noPlatforms } /// - Note: Tips and dependencies are **not** accurate override public init(existing: Path) throws { tips = [] dependencies = .init() try super.init(existing: existing) cakeTarget = nativeTargets.first(where: { $0.name == "Cake" }) } /// Creates a cake project without any dependencies determining modules itself /// - Parameter prefix: the directory that contains the `.cake` directory public convenience init(prefix: Path, platforms: Set, swift swiftVersion: SwiftVersion, options: CakefileDescription.Options) throws { guard !platforms.isEmpty else { throw E.noPlatforms } let model = prefix/"Sources/Model" let modules = try modelize(root: model, basename: options.baseModuleName) try self.init(tips: modules, dependencies: .init(), prefix: prefix, platforms: platforms, swift: swiftVersion, suppressDependencyWarnings: options.suppressDependencyWarnings) } /// Creates a cake project for the specified modules and dependencies /// - Parameter prefix: the directory that contains the `.cake` directory public init(tips: [Module], dependencies: DependenciesJSON, prefix: Path, platforms: Set, swift swiftVersion: SwiftVersion, suppressDependencyWarnings: Bool) throws { self.tips = tips self.dependencies = dependencies super.init(name: "Cake", parentDirectory: prefix/".cake", for: platforms, swift: swiftVersion) let cakefileTarget = addAggregateTarget(name: "Cakefile") cakefileTarget["SDKROOT"] = "macosx" cakefileTarget["SUPPORTED_PLATFORMS"] = ["macosx"] let script = cakefileTarget.add(script: .cakefileScript) script.name = "Regenerate Cake.xcodeproj" script.shellPath = "$(DT_TOOLCHAIN_DIR)/usr/bin/swift" script.inputPaths = ["$(PROJECT_DIR)/../Cakefile.swift"] script.outputPaths = [ "$(PROJECT_DIR)/Cakefile.json", "$(PROJECT_DIR)/Dependencies.json"] let libdir = "$(HOME)/Library/Developer/Cake/DerivedData/$(XCODE_PRODUCT_BUILD_VERSION)/lib" let cakefileCompletionTarget = addNativeTarget(name: "Cakefile·Completion", type: .commandLineTool) try cakefileCompletionTarget.build(source: mainGroup.add(file: prefix/"Cakefile.swift", name: .basename)) cakefileCompletionTarget["SDKROOT"] = "macosx" cakefileCompletionTarget["SUPPORTED_PLATFORMS"] = ["macosx"] cakefileCompletionTarget["LD"] = "/usr/bin/true" // prevents link failure cakefileCompletionTarget["OTHER_SWIFT_FLAGS"] = ["-I", libdir, "-L", libdir] cakefileCompletionTarget["PRODUCT_NAME"] = "CakefileScript" cakefileCompletionTarget["PRODUCT_MODULE_NAME"] = "Script" //// third party dependencies let thirdPartyTarget: XcodeProject.NativeTarget?, thirdPartyTargets: [XcodeProject.NativeTarget] if !dependencies.isEmpty { let thirdPartyDepsGroup = try mainGroup.add(group: prefix/"Dependencies", name: .basename) let tips: [XcodeProject.NativeTarget] (tips, thirdPartyTargets) = try add(modules: dependencies.modules, to: { module in try dependencies.group(for: module, root: thirdPartyDepsGroup) }, prefix: "Deps·") for target in thirdPartyTargets { if !target.hasDependencies { try target.depend(on: cakefileTarget) } target["SWIFT_ACTIVE_COMPILATION_CONDITIONS"] = ["$(inherited)", "SWIFT_PACKAGE"] if suppressDependencyWarnings { // we don’t set for false since that is our project default target["SWIFT_SUPPRESS_WARNINGS"] = true } } thirdPartyTarget = addNativeTarget(name: "Dependencies", type: .staticLibrary) for target in tips { try thirdPartyTarget!.depend(on: target) } for target in thirdPartyTargets { try thirdPartyTarget!.link(to: target) } preventSwiftMigration(for: thirdPartyTargets) } else { thirdPartyTarget = nil thirdPartyTargets = [] } //// Model refs & targets let batterTarget: NativeTarget, batterTargets: [NativeTarget] do { let group = try mainGroup.add(group: modelPrefix, name: .custom("Batter")) let batterTips: [NativeTarget] (batterTips, batterTargets) = try add(modules: tips, to: group, prefix: "Batter·") if let thirdPartyTarget = thirdPartyTarget { for target in batterTargets where !target.hasDependencies { try target.depend(on: thirdPartyTarget) } } //// batter target is an aggregate static archive of all modules batterTarget = addNativeTarget(name: "Batter", type: .staticLibrary) for target in batterTips { try batterTarget.depend(on: target) } for target in batterTargets { try batterTarget.link(to: target) } //// we may need to depend on Cakefile if thirdPartyTarget == nil { for target in batterTargets where !target.hasDependencies { try target.depend(on: cakefileTarget) } } //// integrate Carthage stuff if its there if prefix.Carthage.isDirectory, prefix.Cartfile.isFile { for target in batterTargets { for spec in platforms { let platform = spec.platform for sdk in platform.sdks { let key = "FRAMEWORK_SEARCH_PATHS[sdk=\(sdk)*]" let value = "../Carthage/Build/\(platform.carthageDir)" target.debug.buildSettings[key] = value target.release.buildSettings[key] = value } } } } } ////// Kitchenware group let kitchenware = try mainGroup.add(group: caked, name: .custom("Kitchenware")) try batterTarget.build(source: kitchenware.add(file: caked/"Batter.swift")) try thirdPartyTarget?.build(source: kitchenware.add(file: caked/"Dependencies.swift")) ////// integrate Cocoapods if available if prefix.Podfile.isFile, prefix.Pods.isDirectory { let podProject = try XcodeProject(existing: prefix.Pods / "Pods.xcodeproj") if let podTarget = podProject.nativeTargets.first(where: { $0.name.hasPrefix("Pods-") }) { let targetSupportFiles = prefix.Pods/"Target Support Files"/podTarget.name let debugConfigurationFile = kitchenware.add(file: targetSupportFiles/"\(podTarget.name).debug.xcconfig", name: .basename) let releaseConfigurationFile = kitchenware.add(file: targetSupportFiles/"\(podTarget.name).release.xcconfig", name: .basename) for target in batterTargets { try target.depend(on: podTarget) target.debug.baseConfiguration = debugConfigurationFile target.release.baseConfiguration = releaseConfigurationFile } } } ////// Versionator let versionator = addAggregateTarget(name: "Versionator") let vscript = versionator.add(script: """ v=$(git describe --tags --always --abbrev=0) n=$(git rev-list HEAD --count) if [[ -z $v ]]; then v="0.0.0"; fi if [[ -z $n ]]; then n="0"; fi echo "CURRENT_PROJECT_VERSION = $n" > Version.xcconfig echo "SEMANTIC_PROJECT_VERSION = $v" >> Version.xcconfig echo "SEMANTIC_PROJECT_VERSION[config=Debug] = $v-debug" >> Version.xcconfig """) vscript.name = "Determine Version" vscript.outputPaths = ["Version.xcconfig"] vscript.inputPaths = ["../.git/refs/tags"] ////// Cake.a cakeTarget = addNativeTarget(name: "Cake", type: .staticLibrary) try cakeTarget.build(source: kitchenware.add(file: caked/"Cake.swift")) try cakeTarget.depend(on: batterTarget) try cakeTarget.depend(on: versionator) try cakeTarget.link(to: batterTarget) if let thirdPartyTarget = thirdPartyTarget { try cakeTarget.depend(on: thirdPartyTarget) try cakeTarget.link(to: thirdPartyTarget) } } private func add(modules tips: [Module], to parent: Group, prefix: String) throws -> (tips: [NativeTarget], all: [NativeTarget]) { return try add(modules: tips, to: { module in try parent.add(group: module.path, name: .custom(module.name)) }, prefix: prefix) } private func add(modules tips: [Module], to groupFor: (Module) throws -> Group, prefix: String) throws -> (tips: [NativeTarget], all: [NativeTarget]) { var targets = [Module: NativeTarget]() let modules = tips.flattened for module in modules { let group = try groupFor(module) let target = addNativeTarget(name: "\(prefix)\(module.name)", type: .staticLibrary, productName: module.name) if let v = module.swiftVersion { target["SWIFT_VERSION"] = v.rawValue } for file in module.files { try target.build(source: group.add(file: file)) } targets[module] = target } for module in modules { for dep in module.dependencies { guard let dep = targets[dep] else { throw E.programmerError } try targets[module]!.depend(on: dep) } } // return in order we received them to prevent the pbxproj // diff changing every time we generate return (tips.map{ targets[$0]! }, modules.map{ targets[$0]! }) } override open func write() throws { try super.write() try generateBatterDotSwift(tips: tips) if !dependencies.isEmpty { try generateDependenciesDotSwift(importNames: dependencies.imports) } else { // no deps, so delete generated files (if any) func rm(root: Path, prefix: String, extnames: [String]) throws { for extname in extnames { let path = root/"\(prefix).\(extname)" if path.exists { try path.delete() } } } try rm(root: caked, prefix: "Dependencies", extnames: ["swift", "json"]) try rm(root: caked, prefix: "Package", extnames: ["swift", "resolved"]) } try generateDependenciesDotSwift(importNames: dependencies.imports) } } private extension DependenciesJSON { func group(for module: Module, root: XcodeProject.Group) throws -> XcodeProject.Group { func findOrCreate(_ package: Package, _ module: Module) throws -> XcodeProject.Group { for packageGroup in root.subgroups where packageGroup.name == package.displayName { return try packageGroup.add(group: module.path, name: .custom(module.name)) } if package.moduleNames.count <= 1 { if module.files.count <= 1 { return root } else { return try root.add(group: module.path, name: .custom(package.displayName)) } } else { return try root .add(group: package.path, name: .custom(package.displayName)) .add(group: module.path, name: .custom(module.name)) } } for package in packages where package.moduleNames.contains(module.name) { return try findOrCreate(package, module) } fatalError("FIXME: throw") } } private extension DependenciesJSON.Package { var displayName: String { if let version = version { return "\(name)-\(version)" } else { return name } } } private extension Platform { var sdks: [String] { switch self { case .iOS: return ["iphoneos", "iphonesimulator"] case .macOS: return ["macosx"] } } var carthageDir: String { switch self { case .iOS: return "iOS" case .macOS: return "Mac" } } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/deintegrate().swift ================================================ import XcodeProject public extension XcakeProject { func deintegrate(_ proj: XcodeProject) throws { for target in proj.nativeTargets { target.purge(cakeTarget) } proj.removeProjectReference(self) try proj.write() } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/etc.swift ================================================ import class Foundation.Bundle import enum CakefileDescription.Platform import Path extension Path { public static var xcode: Path { //TODO use scripting bridge or something duh return Path.root/"Applications/Xcode.app" } fileprivate static func template(for os: Platform) -> Path { switch os { case .iOS: return xcode/"Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application/Cocoa Touch App Base.xctemplate" case .macOS: return xcode/"Contents/Developer/Library/Xcode/Templates/Project Templates/Mac/Application/Cocoa App Storyboard.xctemplate" } } } extension Platform { var storyboardName: String { switch self { case .iOS: return "LaunchScreen.storyboard" case .macOS: return "Main.storyboard" } } var storyboard: Path { switch self { case .macOS: return Path.template(for: self).join(storyboardName) case .iOS: return Bundle.main.resources/"iOS.Launchscreen.storyboard" } } var rpath: String { switch self { case .iOS: return "Frameworks" case .macOS: return "../Frameworks" } } var infoPlist: String { switch self { case .iOS: return """ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString $(SEMANTIC_PROJECT_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait """ case .macOS: return """ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString $(SEMANTIC_PROJECT_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSMainStoryboardFile Main NSPrincipalClass NSApplication """ } } var appDelegate: String { switch self { case .iOS: return """ import UIKit import Cake @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_: UIApplication, didFinishLaunchingWithOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { window = UIWindow() window!.rootViewController = UIViewController() window!.makeKeyAndVisible() return true } } """ case .macOS: return """ import AppKit import Cake @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ note: Notification) { } } """ } } } extension String { static var cakefileScript: String { return #""" import func Darwin.fputs import var Darwin.stderr import ScriptingBridge import AppKit func print(_ objs: Any...) { let str = objs.reduce(into: "") { $0.append(" \($1)") } fputs(str, stderr) } let apps = NSRunningApplication.runningApplications(withBundleIdentifier: "dev.mxcl.Cake") switch apps.count { case 0: print("warning: Cake.app not running, Cakefile changes will not take effect") case 1: guard let bundle = apps[0].bundleURL else { print("Failed to obtain Cake.app location") exit(1) } guard let projectDir = ProcessInfo.processInfo.environment["PROJECT_DIR"] else { print("Failed to obtain PROJECT_DIR") exit(2) } let path = bundle.appendingPathComponent("Contents/MacOS/cake-build").path let task = Process() task.launchPath = path task.arguments = [String(apps[0].processIdentifier), projectDir] try task.run() task.waitUntilExit() exit(task.terminationStatus) default: print("error: More than one instance of Cake.app is running") exit(3) } """# } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcakeProject/scaffold().swift ================================================ import enum Base.SwiftVersion import CakefileDescription import XcodeProject import Foundation import Version import Path private enum E: Error { case directoryExists(Path) } public enum ScaffoldingOption { case new(name: String, Path, PlatformSpecification) case existing(XcodeProject) } public func scaffold(_ option: ScaffoldingOption, cakeVersion: Version) throws -> (XcodeProject, XcakeProject) { if case .new(_, let prefix, _) = option, prefix.exists { throw E.directoryExists(prefix) } let mainProject: XcodeProject let platforms: Set let targets: [XcodeProject.NativeTarget] let swiftVersion: SwiftVersion let detritus: XcodeProject.Group? switch option { case .existing(let proj): mainProject = proj swiftVersion = mainProject.swiftVersion platforms = mainProject.platforms targets = mainProject.nativeTargets.filter{ $0.type == .application } //TODO read gitignore and ensure we don’t add duplicates try """ /.cake/swift-pm /.cake/*.json /.cake/Package.swift /.cake/Version.xcconfig """.concatenate(to: mainProject.parentDirectory/".gitignore") detritus = nil case .new(let name, let prefix, let platspec): swiftVersion = .default platforms = [platspec] mainProject = XcodeProject(name: name, parentDirectory: prefix, for: platforms, swift: swiftVersion) let os = platspec.platform let srcdir = try prefix.Sources.App.mkdir(.p) try """ xcuserdata *.xcscmblueprint .DS_Store # In case you are using Carthage too /Carthage # In case you are using CocoaPods too /Pods # In case you have a root SwiftPM manifest too /.build # SwiftPM metadata when resolving dependencies /.cake/swift-pm # intermediary files for Cake.xcodeproj /.cake/*.json /.cake/Package.swift /.cake/Version.xcconfig """.write(to: prefix/".gitignore") try prefix.join("Documents").mkdir(.p) try prefix.join("Tests").mkdir(.p) try mainProject.path.mkdir(.p) let sources = try mainProject.mainGroup.add(group: srcdir, name: .custom("Sources·App")) detritus = try mainProject.mainGroup.add(group: srcdir, name: .custom("Detritus")) detritus!.add(file: try os.infoPlist.write(to: srcdir/"Info.plist")) let storyboard = try os.storyboard.copy(to: srcdir/os.storyboardName) let target = mainProject.addNativeTarget(name: name, type: .application) try target.build(source: sources.add(file: os.appDelegate.write(to: srcdir/"AppDelegate.swift"))) try target.build(resource: detritus!.add(file: storyboard)) if os == .macOS { try storyboard.inreplace("___PACKAGENAMEASXML___", with: name) } target["INFOPLIST_FILE"] = "Sources/App/Info.plist" target["ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES"] = "YES" target["SKIP_INSTALL"] = "NO" target["PRODUCT_MODULE_NAME"] = "App" target["LD_RUNPATH_SEARCH_PATHS"] = ["$(inherited)", "@executable_path/\(os.rpath)"] var bids = ["dev"] bids += NSUserName().domainSafed.reversed().map{ $0.lowercased() } bids += [name.domainSafed.joined(separator: "-")] target["PRODUCT_BUNDLE_IDENTIFIER"] = bids.joined(separator: ".") targets = [target] // this prevents autocreation of schemes // this prevents listing Cakeproj’s schemes in the scheme selector mainProject.schemify(target: target) } try """ import Cakefile dependencies = [ // add your dependencies here, for example: //.github("mxcl/PromiseKit" ~> 6.7), // dependencies must be Swift packages, we will add support for // CocoaPods and Carthage provided our donation goals are met: // https://patreon.com/mxcl // this is optional, but you should leave it ∵ if you work in a team, // you should all be using the same version of Cake. .cake(~>\(cakeVersion.constraintStringValue)) ] // you can specify your platforms and deployment targets like so // NOTE: if unspecified we mirror the app-project’s settings // platforms = [\(platforms.map(\.description).joined(separator: ", "))] // uncomment if you want to change the base-module-name // options.baseModuleName = "Bakeware" """.write(to: mainProject.parentDirectory/"Cakefile.swift") let models = try mainProject.parentDirectory.Sources.Model.mkdir(.p) try """ #if canImport(Dependencies) // to add 3rd-party dependencies, edit `Cakefile.swift` (in the project’s root directory) import Dependencies #endif /// Base model module """.write(to: models/"Base.swift") let cakeProject = try XcakeProject(prefix: mainProject.parentDirectory, platforms: platforms, swift: swiftVersion, options: Options()) try cakeProject.path.mkdir(.p) try cakeProject.write() try """ @_exported import Batter #if canImport(Dependencies) // to add 3rd-party dependencies, edit `Cakefile.swift` (in the project’s root directory) @_exported import Dependencies #endif """.write(to: cakeProject.parentDirectory/"Cake.swift").chmod(0o444) let cakeXCConfig = cakeProject.caked/"Cake.xcconfig" try """ #include? "Version.xcconfig" """.write(to: cakeXCConfig) //FIXME we are writing this anyway due to bug: https://github.com/mxcl/Cake/issues/49 // we need to do a proper fix, which may require this to be build-phase in the App’s // project: https://gist.github.com/mbinna/4068616#gistcomment-2734031 try """ CURRENT_PROJECT_VERSION = 0 SEMANTIC_PROJECT_VERSION = 0.0.0 SEMANTIC_PROJECT_VERSION[config=Debug] = 0.0.0-debug """.write(to: cakeProject.caked/"Version.xcconfig") if let detritus = detritus { mainProject.baseConfiguration = detritus.add(file: cakeXCConfig, name: .basename) } mainProject.mainGroup.add(file: models, name: .custom("Sources·Model"), type: .folder, at: .top) if case .new(let name, let prefix, _) = option { //TODO describe each directory in the generated project try mainProject.mainGroup.add(file: """ # \(name) This project is “Made with Cake”. Cake is a delicious, quality‑of‑life supplement for your app‑development toolbox. You do not need to install Cake.app to work with this project, but there are numerous advantages if you do so. https://github.com/mxcl/cake """.write(to: prefix/"README.md"), at: .top) } for target in targets { try target.depend(on: cakeProject.cakeTarget) try target.link(to: cakeProject.cakeTarget) } try mainProject.write() return (mainProject, cakeProject) } private extension Version { var constraintStringValue: String { if prereleaseIdentifiers.isEmpty { return "\(major).\(minor)" } else { let pi = prereleaseIdentifiers.map{ "\"\($0)\"" }.joined(separator: ", ") return "Version(\(major),\(minor),\(patch), prereleaseIdentifiers: [\(pi)])" } } } private extension String { // justified due to `String` having `write(to:)` func concatenate(to path: Path, encoding: String.Encoding = .utf8) throws { // we need to know if end of file is a newline or not, but I couldn't figure out // how to do that efficiently, so we wrap the input in newlines let str = "\n\(self)\n" guard let data = str.data(using: .utf8) else { throw CocoaError.error(.fileReadInapplicableStringEncoding) } if let fileHandle = try? FileHandle(forWritingTo: path.url) { fileHandle.seekToEndOfFile() fileHandle.write(data) fileHandle.closeFile() } else { try data.write(to: path) } } var domainSafed: [String] { return folding(options: .diacriticInsensitive, locale: .init(identifier: "en_US")) .components(separatedBy: CharacterSet.alphanumerics.inverted) } } ================================================ FILE: Sources/Model/Base/XcodeProject/XcodeProject.swift ================================================ /** tuist/xcodeproj is a very literal implementation of the PBXProject file-format. This makes using it error-prone and unreadable, this is a facade pattern for tuist/xcodeproj. However we only implemented what we needed so don’t expect it to be everything *you* might need in your own projects! */ import enum Base.SwiftVersion import CakefileDescription import xcodeproj import Path open class XcodeProject { let proj: XcodeProj var projectReferences: [XcodeProject: (PBXFileReference, PBXGroup)] = [:] public let parentDirectory: Path /// pass the path to the .xcodeproj *directory* public init(existing: Path) throws { if existing.extension == "xcworkspace" { let wsp = try XCWorkspace(pathString: existing.string) let prj: [String] = wsp.data.children.compactMap { switch $0 { case .file(let ref) where ref.location.path == "Pods/Pods.xcodeproj": return nil case .file(let ref): return ref.location.path default: return nil } } guard prj.count == 1 else { throw E.workspaceHasTooManyProjects } proj = try XcodeProj(pathString: existing.parent.join(prj[0]).string) } else { proj = try XcodeProj(pathString: existing.string) } parentDirectory = existing.parent guard proj.pbxproj.rootObject != nil else { throw E.readNoRootObject } guard proj.pbxproj.rootObject!.mainGroup != nil else { throw E.readNoMainGroup } guard proj.pbxproj.rootObject!.productsGroup != nil else { throw E.readNoProductsGroup } } /// for a _not_yet_existing_ project, however parentDirectory must exist public init(name: String, parentDirectory: Path, for platforms: Set, swift swiftVersion: SwiftVersion) { let common = [String: Any].commonBuildSettings(for: platforms, swift: swiftVersion) let debug = XCBuildConfiguration(name: "Debug", buildSettings: common.merging(.debugBuildSettings){ $1 }) let release = XCBuildConfiguration(name: "Release", buildSettings: common.merging(.releaseBuildSettings){ $1 }) let confs = XCConfigurationList(buildConfigurations: [debug, release], defaultConfigurationName: "Release") let mainGroup = PBXGroup(sourceTree: .sourceRoot, path: "") let rootObject = PBXProject( name: name, buildConfigurationList: confs, compatibilityVersion: "Xcode 9.3", mainGroup: mainGroup ) let pbxProj = PBXProj(rootObject: rootObject) let productsGroup = PBXGroup(sourceTree: .group, name: "Products") rootObject.productsGroup = productsGroup mainGroup.children.append(productsGroup) pbxProj.add(object: mainGroup) pbxProj.add(object: rootObject) pbxProj.add(object: productsGroup) pbxProj.add(object: confs) pbxProj.add(object: debug) pbxProj.add(object: release) self.proj = XcodeProj(workspace: XCWorkspace(), pbxproj: pbxProj) self.parentDirectory = parentDirectory } open func write() throws { try proj.write(path: PathKitPath(path)) // we don’t want this, but tuist/xcodeproj cannot *not* create it try path.join("project.xcworkspace/contents.xcworkspacedata").delete() try """ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded """.write(to: path.join("project.xcworkspace/xcshareddata").mkdir(.p).join("WorkspaceSettings.xcsettings")) if let target = xcschememanagementPlistTarget { let d = path/"xcshareddata/xcschemes" try d.mkdir(.p) try """ SchemeUserState \(target.name).xcscheme_^#shared#^_ orderHint 0 SuppressBuildableAutocreation \(target.uuid) primary """.write(to: d/"xcschememanagement.plist") } } private var xcschememanagementPlistTarget: PBXTarget? /// configures project to have a single scheme for the specified target public func schemify(target: NativeTarget) { let scheme = XCScheme(name: name, lastUpgradeVersion: nil, version: nil) scheme.buildAction = XCScheme.BuildAction() scheme.buildAction!.parallelizeBuild = true scheme.buildAction!.buildImplicitDependencies = false let ref = XCScheme.BuildableReference( referencedContainer: "container:\(name).xcodeproj", blueprint: target.underlyingTarget, buildableName: "\(target.name).app", blueprintName: target.name) scheme.buildAction!.buildActionEntries = [ XCScheme.BuildAction.Entry(buildableReference: ref, buildFor: XCScheme.BuildAction.Entry.BuildFor.default) ] let runnable = XCScheme.BuildableProductRunnable(buildableReference: ref) scheme.launchAction = XCScheme.LaunchAction(buildableProductRunnable: runnable, buildConfiguration: "Debug") scheme.launchAction!.environmentVariables = [ // prevents the log filling with junk and garbage XCScheme.EnvironmentVariable(variable: "OS_ACTIVITY_MODE", value: "disable", enabled: true) ] proj.sharedData = XCSharedData(schemes: [scheme]) xcschememanagementPlistTarget = target.underlyingTarget } } public extension XcodeProject { var name: String { return proj.pbxproj.rootObject!.name } var path: Path { return parentDirectory/"\(name).xcodeproj" } var mainGroup: Group { return Group(owner: self, parentPath: parentDirectory, underlyingGroup: proj.pbxproj.rootObject!.mainGroup!) } var nativeTargets: [NativeTarget] { return proj.pbxproj.nativeTargets.map { NativeTarget(owner: self, underlyingTarget: $0) } } enum E: Error { case readNoRootObject case readNoMainGroup case cannotReferenceSelf case nativeTargetHasNoProductReference case readNoProductsGroup case groupHasNoPath case invalidBuildConfigurations case workspaceHasTooManyProjects } enum Name { case inferred case basename case custom(String) func string(path: Path) -> String? { switch self { case .basename: return path.basename() case .inferred: return nil case .custom(let name): return name } } } enum FileType: String { case project = "wrapper.pb-project" case folder = "folder" } var baseConfiguration: PBXFileReference { set { guard let confs = pbxproj.rootObject?.buildConfigurationList?.buildConfigurations else { fatalError() } for conf in confs { conf.baseConfiguration = newValue } } get { fatalError() } } } internal extension XcodeProject { var pbxproj: PBXProj { return proj.pbxproj } var productsGroup: PBXGroup { return pbxproj.rootObject!.productsGroup! } } extension XcodeProject: Equatable, Hashable { public static func ==(lhs: XcodeProject, rhs: XcodeProject) -> Bool { return lhs.name == rhs.name && lhs.parentDirectory == rhs.parentDirectory } public func hash(into hasher: inout Hasher) { hasher.combine(name) hasher.combine(parentDirectory) } } ================================================ FILE: Sources/Model/Base/XcodeProject/_PathDisambiguation.swift ================================================ import struct Path.Path typealias PathType = Path ================================================ FILE: Sources/Model/Base/XcodeProject/z+buildSettings.swift ================================================ import CakefileDescription import xcodeproj import Base import Path public extension XcodeProject.Target { var debug: XCBuildConfiguration { return find(name: "Debug") } var release: XCBuildConfiguration { return find(name: "Release") } subscript(key: String) -> Any? { set { //TODO if nil don’t create configurations if so far they aren't created (which can happen easily for eg. target specific configuration lists) debug.buildSettings[key] = newValue release.buildSettings[key] = newValue } get { fatalError() } } private func find(name: String) -> XCBuildConfiguration { if let c = underlyingTarget.buildConfigurationList?.configuration(name: name) { return c } else { let c = XCBuildConfiguration(name: name) owner.add(c) if let list = underlyingTarget.buildConfigurationList { list.buildConfigurations.append(c) } else { let list = XCConfigurationList(buildConfigurations: [c]) underlyingTarget.buildConfigurationList = list owner.add(list) } return c } } } extension Dictionary where Key == String, Value == Any { static func commonBuildSettings(for platforms: Set, swift swiftVersion: SwiftVersion) -> [String: Any] { var foo: [String: Any] = [ "PRODUCT_NAME": "$(TARGET_NAME)", "COMBINE_HIDPI_IMAGES": "YES", //prevents Xcode warning "SUPPORTED_PLATFORMS": platforms.flatMap(\.platform.supportedPlatforms), "SDKROOT": platforms.suggestedSdkRoot, "SWIFT_ACTIVE_COMPILATION_CONDITIONS": ["Cake"], "USE_HEADERMAP": "NO", // copied from SwiftPM which provides rationale "CLANG_ENABLE_OBJC_WEAK": "YES", "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING": "YES", "CLANG_WARN_BOOL_CONVERSION": "YES", "CLANG_WARN_COMMA": "YES", "CLANG_WARN_CONSTANT_CONVERSION": "YES", "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS": "YES", "CLANG_WARN_EMPTY_BODY": "YES", "CLANG_WARN_ENUM_CONVERSION": "YES", "CLANG_WARN_INFINITE_RECURSION": "YES", "CLANG_WARN_INT_CONVERSION": "YES", "CLANG_WARN_NON_LITERAL_NULL_CONVERSION": "YES", "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "YES", "CLANG_WARN_OBJC_LITERAL_CONVERSION": "YES", "CLANG_WARN_RANGE_LOOP_ANALYSIS": "YES", "CLANG_WARN_STRICT_PROTOTYPES": "YES", "CLANG_WARN_SUSPICIOUS_MOVE": "YES", "CLANG_WARN_UNREACHABLE_CODE": "YES", "CLANG_WARN__DUPLICATE_METHOD_MATCH": "YES", "ENABLE_STRICT_OBJC_MSGSEND": "YES", "GCC_NO_COMMON_BLOCKS": "YES", "GCC_WARN_64_TO_32_BIT_CONVERSION": "YES", "GCC_WARN_ABOUT_RETURN_TYPE": "YES", "GCC_WARN_UNDECLARED_SELECTOR": "YES", "GCC_WARN_UNINITIALIZED_AUTOS": "YES", "GCC_WARN_UNUSED_FUNCTION": "YES", "GCC_WARN_UNUSED_VARIABLE": "YES", "SWIFT_VERSION": swiftVersion.rawValue, "SKIP_INSTALL": "YES" ] for spec in platforms { switch spec.platform { case .iOS: foo["IPHONEOS_DEPLOYMENT_TARGET"] = spec.version.description case .macOS: foo["MACOSX_DEPLOYMENT_TARGET"] = spec.version.description } } return foo } static var debugBuildSettings: [String: Any] { return [ "COPY_PHASE_STRIP": "NO", "DEBUG_INFORMATION_FORMAT": "dwarf", "ENABLE_NS_ASSERTIONS": "YES", "GCC_OPTIMIZATION_LEVEL": "0", "ONLY_ACTIVE_ARCH": "YES", "SWIFT_OPTIMIZATION_LEVEL": "-Onone", "SWIFT_ACTIVE_COMPILATION_CONDITIONS": ["Cake", "DEBUG"], "ENABLE_TESTABILITY": "YES", ] } static var releaseBuildSettings: [String: Any] { return [ "COPY_PHASE_STRIP": "YES", "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", "GCC_OPTIMIZATION_LEVEL": "s", "SWIFT_OPTIMIZATION_LEVEL": "-Owholemodule", "SWIFT_COMPILATION_MODE": "wholemodule", ] } } private extension Platform { var supportedPlatforms: [String] { switch self { case .iOS: return ["iphoneos", "iphonesimulator"] case .macOS: return ["macosx"] } } } private extension Set where Element == PlatformSpecification { var suggestedSdkRoot: String { if map(\.platform).contains(.macOS) { return "macosx" } else { return "iphoneos" } } } ================================================ FILE: Sources/Model/Base/XcodeProject/z.etc.swift ================================================ import struct PathKit.Path import struct Path.Path import Foundation import xcodeproj typealias PathKitPath = PathKit.Path extension PathKitPath { init(_ path: PathType) { self.init(path.string) } } extension XcodeProject.NativeTarget { var linkPhase: PBXFrameworksBuildPhase { if let phase = underlyingTarget.buildPhases.first(where: { $0 is PBXFrameworksBuildPhase }) { return phase as! PBXFrameworksBuildPhase } else { let phase = PBXFrameworksBuildPhase() underlyingTarget.buildPhases.append(phase) owner.add(phase) return phase } } var sourcesPhase: PBXSourcesBuildPhase { if let phase = try? underlyingTarget.sourcesBuildPhase() { return phase } else { let phase = PBXSourcesBuildPhase() underlyingTarget.buildPhases.append(phase) owner.add(phase) return phase } } var resourcesPhase: PBXResourcesBuildPhase { if let phase = try? underlyingTarget.resourcesBuildPhase() { return phase } else { let phase = PBXResourcesBuildPhase() underlyingTarget.buildPhases.append(phase) owner.add(phase) return phase } } } ================================================ FILE: Sources/Model/Base/topologicalSort().swift ================================================ import OrderedSet extension Array where Element: Hashable, Element: Comparable { public func topologicallySorted(successors: (Element) -> [Element]) -> [Element] { // Implements a topological sort via recursion and reverse postorder DFS. func visit(_ node: Element, _ stack: inout OrderedSet, _ visited: inout Set, _ result: inout [Element], _ successors: (Element) -> [Element]) { // Mark this node as visited -- we are done if it already was. if !visited.insert(node).inserted { return } // Otherwise, visit each adjacent node. for succ in successors(node).sorted() { assert(stack.index(of: succ) == nil) stack.append(succ) visit(succ, &stack, &visited, &result, successors) stack.removeLast() } // Add to the result. result.append(node) } var visited = Set() var result = [Element]() var stack = OrderedSet() for node in sorted() { precondition(stack.isEmpty) stack.append(node) visit(node, &stack, &visited, &result, successors) stack.removeLast() } return result.reversed() } } private extension OrderedSet { func removeLast() { remove(last!) // is efficient in implementation } } ================================================ FILE: Sources/Model/CakefileDescription/CakefileDescription.swift ================================================ #if !Cake @_exported import struct Foundation.URL #endif import Foundation import Version #if !Cake // ^^ Defined when building Batter, thus when building dylib for consumption // by Cake Projects is *not* defined, thus anything here is available to // all users of Cake except inside the mxcl/Cake project itself. /// Dependencies for your Model (can be used by App too, but we will eventually add a separate public var dependencies: [Dependency] = [] /// Checks out the dependency but does not integrate, integration is up to you public var vendors: [Vendor] = [] /** Will also build executables and then make those executables available for scripts possibly make it possible for these tools to define their own scripts for user benefit */ public var buildDependencies: [Dependency] = [] /// Configures the build targets for model modules public var platforms: Set = [] /// Configurable parameters for your Cake. public var options = Options() #endif /// Various configurable properties. public struct Options: Codable { /// The name of the base model module, if there is only one. public var baseModuleName = "Bakeware" /// If `true`, warnings in dependencies are suppressed. public var suppressDependencyWarnings = true #if Cake public init() {} #endif } public enum Dependency { case github(GitHubPackageSpecification) case git(PackageSpecification) //TODO case xcode(VersionSpecification) case cake(Range) } public enum VersionSpecification: Codable, Equatable { case version(Constraint) case ref(Ref) public enum Constraint { case range(Range) case exact(Version) } public enum Ref { case branch(String) case tag(String) case revision(String) } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if container.contains(.version) { let str = try container.decode(String.self, forKey: .version) let parts = str.components(separatedBy: "..<") switch parts.count { case 2: guard let v1 = Version(parts[0]), let v2 = Version(parts[1]) else { fallthrough } self = .version(.range(v1.. Bool { switch (lhs, rhs) { case (.version(.range(let range1)), .version(.range(let range2))): return range1 == range2 case (.version(.exact(let v1)), .version(.exact(let v2))): return v1 == v2 case (.ref(.branch(let b1)), .ref(.branch(let b2))): return b1 == b2 case (.ref(.tag(let b1)), .ref(.tag(let b2))): return b1 == b2 case (.ref(.revision(let b1)), .ref(.revision(let b2))): return b1 == b2 default: return false } } } public struct PackageSpecification: Codable, Equatable { public init(url: URL, constraint: VersionSpecification) { self.url = url self.constraint = constraint } public var url: URL public var constraint: VersionSpecification enum CodingKeys: CodingKey { case url } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(url, forKey: .url) try constraint.encode(to: encoder) } public init(from decoder: Decoder) throws { url = try decoder.container(keyedBy: CodingKeys.self).decode(URL.self, forKey: .url) constraint = try VersionSpecification(from: decoder) } } public struct GitHubPackageSpecification { public var user: String public var repo: String public var constraint: VersionSpecification fileprivate var packageSpecification: PackageSpecification { let url = URL(string: "https://github.com/\(user)/\(repo).git")! return .init(url: url, constraint: constraint) } public init(user: String, repo: String, constraint: VersionSpecification) { self.user = user self.repo = repo self.constraint = constraint } } public enum Platform: String, Codable, Hashable, Equatable { case iOS, macOS } public struct PlatformSpecification: Codable, Equatable, Hashable { public let platform: Platform public let version: Version //FIXME Set semantics may make this bad in practice func hasher(into hasher: inout Hasher) { hasher.combine(platform) } public init(platform: Platform, version: Version) { self.platform = platform self.version = version } } extension PlatformSpecification: CustomStringConvertible { public var description: String { var str = ".\(platform) ~> \(version.major).\(version.minor)" if version.patch > 0 { str += ".\(version.patch)" } return str } } extension GitHubPackageSpecification: ExpressibleByStringLiteral { public init(stringLiteral value: String) { (user, repo) = value.githubPair self.constraint = .version(.range(Version(0,0,0)..) fetches the newest release, which while seemingly convenient—in extreme cases—may lead to irritable co‐workers.") } } extension PackageSpecification: ExpressibleByStringLiteral { public init(stringLiteral value: String) { self.url = URL(string: "https://github.com/\(value.githubPair).git")! self.constraint = .ref(.branch("master")) warning("Specifying packages without a version constraint (~>) fetches `master` which—in extreme cases—may lead to irritable co‐workers.") } } extension VersionSpecification: ExpressibleByFloatLiteral { @inlinable public init(floatLiteral value: FloatLiteralType) { self = .version(.exact(Version(value))) } } public enum Vendor { case github(PackageSpecification) } public func ~> (lhs: String, rhs: Double) -> GitHubPackageSpecification { let (user, repo) = lhs.githubPair return .init(user: user, repo: repo, constraint: .version(.range(~>rhs))) } public func ~> (lhs: String, rhs: Version) -> GitHubPackageSpecification { let (user, repo) = lhs.githubPair return .init(user: user, repo: repo, constraint: .version(.range(~>rhs))) } public func ~> (lhs: Platform, rhs: Double) -> PlatformSpecification { return .init(platform: lhs, version: Version(floatLiteral: rhs)) } public func ~> (lhs: Platform, rhs: Version) -> PlatformSpecification { return .init(platform: lhs, version: rhs) } prefix operator ~> public prefix func ~> (value: Double) -> Range { let v = Version(floatLiteral: value) return v.. (value: Version) -> Range { return value.. 2 { warning("ignoring components in package specification beyond 2") } return (String(split[0]), String(split[1])) } } public struct CakefileDump: Codable { public let platforms: Set public let dependencies: [PackageSpecification] public let options: Options public let cake: VersionSpecification? // ^^ not Range as Range is not codable, and we cannot // make it codable without a public impl which would infect // the entire app. Swift 5 has a Codable impl though. public init(platforms: Set, dependencies: [Dependency], options: Options) { self.platforms = platforms self.dependencies = dependencies.compactMap { if case .github(let spec) = $0 { return spec.packageSpecification } else { return nil } } self.options = options self.cake = dependencies.compactMap { if case .cake(let range) = $0 { return .version(.range(range)) } else { return nil } }.last } } ================================================ FILE: Sources/Model/CakefileDescription/Version+.swift ================================================ #if !Cake @_exported import Version #else import Version #endif extension Version: ExpressibleByFloatLiteral { @inlinable public init(_ value: FloatLiteralType) { self.init(floatLiteral: value) } @inlinable public init(floatLiteral value: FloatLiteralType) { self = Version("\(value).0") ?? .null } } ================================================ FILE: Sources/cake-build/main.swift ================================================ import AppKit /** Using distributed notifications. We tried AppleEvents (ie. AppleScript) but due to the AEpocalypse this was extremely fickle. Which is a pity. If there’s a better XPC system that allows blocking that we can use, please let us know. */ let pid = pid_t(CommandLine.arguments[1])! let PROJECT_DIR = CommandLine.arguments[2] guard let app = NSRunningApplication(processIdentifier: pid) else { fputs("error: no such pid: \(pid)\n", stderr) exit(1) } let name = Notification.Name(rawValue: "dev.mxcl.Cake.build") let center = DistributedNotificationCenter.default() let userInfo = ["PROJECT_DIR": PROJECT_DIR] center.postNotificationName(name, object: nil, userInfo: userInfo, options: .deliverImmediately) class Waiter: NSObject { override init() { super.init() let name = Notification.Name(rawValue: "dev.mxcl.Cake.built") center.addObserver(self, selector: #selector(result), name: name, object: nil) } @objc func result(notification: Notification) { if let userInfo = notification.userInfo, let error = userInfo["error"] as? String { fputs("error: \(error)\n", stderr) if let userInfo = userInfo["error.userInfo"] { fputs("notice: \(userInfo)\n", stderr) } exit(2) } else { exit(0) } } } let waiter = Waiter() RunLoop.main.run() ================================================ FILE: Tests/CakefileDescriptionTests.swift ================================================ import CakefileDescription import XCTest //TODO good opportunity to use cake’s test generators // eg. could replace warning() so it injects, thus making it testable // eg. could make the variables not global class CakefileDescriptionTests: XCTestCase { func test() { let cakefile = """ import Cakefile dependencies = [ .github("mxcl/PromiseKit" ~> 6) ] platforms = [.macOS ~> 10.14, .iOS ~> 12] """ _ = cakefile //TODO } } ================================================ FILE: Tests/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Tests/MixerTests.swift ================================================ @testable import Processor import Modelizer import Version import XCTest import Path class MixerTests: XCTestCase { var tmpdir: TemporaryDirectory! override func setUp() { tmpdir = try! TemporaryDirectory() FileManager.default.changeCurrentDirectoryPath(tmpdir.string) } override func tearDown() { tmpdir = nil FileManager.default.changeCurrentDirectoryPath("/") } func testCanFindBinary() { XCTAssertTrue(Path.mixer.isExecutable) XCTAssertTrue(Path.mixer.isFile) } func testOutput() throws { let buildDir = Bundle(for: MixerTests.self).path.parent guard let cake = Bundle(path: buildDir.join("Cake.app").string), let xcodePath = Path.xcode else { return XCTFail() } guard let toolkit = Processor.Toolkit(cake: cake, xcode: xcodePath) else { return XCTFail() } try toolkit.make() let deps = try tmpdir.path.join(".cake").mkdir() try """ // swift-tools-version:4.2 import PackageDescription let pkg = Package(name: "Dependencies", dependencies: [ .package(url: "https://github.com/Weebly/OrderedSet.git", .exact("3.1.0")), ]) """.write(to: deps/"Package.swift") let task = Process() task.launchPath = Path.mixer.string task.arguments = [tmpdir.string, toolkit.pm.string] let stdout = try task.runSync(tee: true).stdout let decoder = JSONDecoder() decoder.userInfo[.relativePath] = tmpdir.path/"Dependencies" let output = try decoder.decode(DependenciesJSON.self, from: stdout.data) XCTAssertEqual(output.imports, ["OrderedSet"]) XCTAssertEqual(output.modules.count, 1) XCTAssertEqual(output.modules.first?.name, "OrderedSet") XCTAssertEqual(output.modules.first?.files.count, 1) XCTAssertEqual(output.modules.first?.dependencies.count, 0) XCTAssertEqual(output.modules.first?.path, tmpdir.path/"Dependencies") } } private extension Path { static var mixer: Path { return Bundle(for: MixerTests.self).path.parent/"Cake.app/Contents/MacOS/mixer" } static var xcode: Path? { return ProcessInfo.processInfo .environment["PATH"]? .split(separator: ":") .first.flatMap(Path.init)? .parent.parent.parent.parent } } ================================================ FILE: Tests/ModelizerTests.swift ================================================ @testable import Modelizer import XCTest import Base import Path class ModelizerTests: XCTestCase { func testOneModule() throws { try createFixture("a.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 1) XCTAssertEqual(modules.bases, modules) let base = try modules.get("Base") XCTAssertEqual(base.relativeFiles, ["a.swift"]) XCTAssertEqual(base.dependencies.count, 0) } } func testOneModuleButGapped() throws { try createFixture("a/b/c.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 1) let b = try modules.get("b") XCTAssertEqual(b.path, root/"a/b") XCTAssertEqual(b.relativeFiles, ["c.swift"]) XCTAssertEqual(b.dependencies.count, 0) } } func testOneModuleButGappedWithRedHerrings() throws { try createFixture("gap/b/c.swift", "d/e/foo", "a/f/goo") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 1) let b = try modules.get("b") XCTAssertEqual(b.relativeFiles, ["c.swift"]) XCTAssertEqual(b.dependencies.count, 0) } } func testTwoNestedModules() throws { try createFixture("a.swift", "b/b.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 2) let b = try modules.get("b") XCTAssertEqual(b.path, root/"b") XCTAssertEqual(b.relativeFiles, ["b.swift"]) XCTAssertEqual(b.dependencies.count, 1) let base = try b.dep("Base") XCTAssertEqual(base.path, root) XCTAssertEqual(base.relativeFiles, ["a.swift"]) XCTAssertEqual(base.dependencies.count, 0) } } func testTwoNestedModulesWithAGap() throws { try createFixture("a.swift", "gap/c/c.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 2) let c = try modules.get("c") XCTAssertEqual(c.dependencies.count, 1) let base = try c.dep("Base") XCTAssertEqual(base.relativeFiles, ["a.swift"]) } } func testThreeNestedModulesWithAGap_IgnoredRule() throws { //NOTE disabled for now, maybe this isn’t a good idea? // describe: c should not depend on b try createFixture("a.swift", "gap/c/c.swift", "b/b.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 2) XCTAssertEqual(modules.flattened.count, 3) let c = try modules.get("c") XCTAssertEqual(c.dependencies.count, 1) let b = try modules.get("b") XCTAssertEqual(b.dependencies.count, 1) let base1 = try c.dep("Base") let base2 = try b.dep("Base") XCTAssertEqual(base1.relativeFiles, ["a.swift"]) XCTAssertEqual(base2.relativeFiles, base1.relativeFiles) XCTAssertEqual(base1, base2) } } func testRegression1() throws { try createFixture("a/a.swift", "b/b.swift", "b/c/d/d.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 2) XCTAssertEqual(modules.flattened.count, 3) let d = try modules.get("d") let a = try modules.get("a") let b = try d.dep("b") XCTAssertEqual(d.dependencies, [a, b]) } } func testRegression2() throws { try createFixture("a/a.swift", "b/b.swift", "b/c/c.swift", "b/d/d.swift", "b/d/e/e.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 3) let a = try modules.get("a") XCTAssertEqual(a.relativeFiles, ["a.swift"]) XCTAssertEqual(a.path, root/"a") let e = try modules.get("e") XCTAssertEqual(e.relativeFiles, ["e.swift"]) XCTAssertEqual(e.path, root/"b/d/e") let c = try modules.get("c") XCTAssertEqual(c.relativeFiles, ["c.swift"]) XCTAssertEqual(c.path, root/"b/c") let b = try c.dep("b") let d = try e.dep("d") XCTAssertEqual(d.dependencies, [a, b]) XCTAssertEqual(c.dependencies, [a, b]) } } func testThreeNestedModules() throws { try createFixture("a.swift", "b/b.swift", "b/c/c.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 3) let c = try modules.get("c") XCTAssertEqual(c.path, root/"b/c") XCTAssertEqual(c.relativeFiles, ["c.swift"]) XCTAssertEqual(c.dependencies.count, 1) let b = try c.dep("b") XCTAssertEqual(b.path, root/"b") XCTAssertEqual(b.relativeFiles, ["b.swift"]) XCTAssertEqual(b.dependencies.count, 1) let base = try b.dep("Base") XCTAssertEqual(base.path, root) XCTAssertEqual(base.relativeFiles, ["a.swift"]) XCTAssertEqual(base.dependencies.count, 0) } } func testFiveModulesSplitOverTwoLevels() throws { try createFixture("a.swift", "b/b.swift", "c/c.swift", "b/d/d.swift") { root, paths in let modules = try modelize(root: root) XCTAssertEqual(modules.count, 2) XCTAssertEqual(modules.flattened.count, 4) let c = try modules.get("c") XCTAssertEqual(c.path, root/"c") XCTAssertEqual(c.relativeFiles, ["c.swift"]) XCTAssertEqual(c.dependencies.count, 1) let base = try c.dep("Base") XCTAssertEqual(base.path, root) XCTAssertEqual(base.relativeFiles, ["a.swift"]) XCTAssertEqual(base.dependencies.count, 0) let d = try modules.get("d") XCTAssertEqual(d.path, root/"b/d") XCTAssertEqual(d.relativeFiles, ["d.swift"]) XCTAssertEqual(d.dependencies.count, 2) let b = try d.dep("b") XCTAssertEqual(b.path, root/"b") XCTAssertEqual(b.relativeFiles, ["b.swift"]) XCTAssertTrue(d.dependencies.contains(c)) XCTAssertTrue(d.dependencies.contains(b)) } } func testOneModuleWithNestedRedHerring() throws { try createFixture("a.swift", "b/b.foo") { root, paths in var modules: [Module]! XCTAssertNoThrow(modules = try modelize(root: root)) XCTAssertEqual(modules.count, 1) XCTAssertEqual(modules.flattened.count, 1) let base = try modules.get("Base") XCTAssertEqual(base.path, root) XCTAssertEqual(base.relativeFiles, ["a.swift"]) XCTAssertEqual(base.dependencies.count, 0) } } func testThrowsIfNoModules() throws { for fixture in [["foo"], ["a/b/c/d/foo"], ["a/b/c/d/foo", "e/f/goo"]] { try createFixture(files: fixture) { root, paths in XCTAssertThrowsError(try modelize(root: root)) { error in do { throw error } catch ModelizerError.noSwiftFiles(let path) { XCTAssertEqual(root, path) } catch { XCTFail() } } } } } } private enum E: LocalizedError { case moduleNotFound(desired: String, searching: [String]) case dependencyNotFound(desired: String, module: String) var errorDescription: String? { switch self { case .moduleNotFound(let desired, let searching): return "Could not find `\(desired)` in \(searching)" case .dependencyNotFound(let desired, let module): return "Dependency `\(desired)` not found in `\(module)`" } } } private extension Array where Element == Module { var mapped: [String: Module] { return Dictionary(uniqueKeysWithValues: map{ ($0.name, $0) }) } func get(_ name: String) throws -> Module { guard let module = first(where: { $0.name == name}) else { throw E.moduleNotFound(desired: name, searching: map(\.name)) } return module } } private extension Module { func dep(_ name: String) throws -> Module { do { return try dependencies.get(name) } catch E.moduleNotFound(let name, _) { throw E.dependencyNotFound(desired: name, module: self.name) } } } private func modelize(root: Path) throws -> [Module] { return try modelize(root: root, basename: "Base") } ================================================ FILE: Tests/Utility.swift ================================================ import Foundation import Base import Path func createFixture(_ files: String..., body: (Path, [Path]) throws -> Void) throws { try createFixture(files: files, body: body) } func createFixture(files: [String], body: (Path, [Path]) throws -> Void) throws { try Path.mktemp { root in let paths = files.map{ root/$0 } for path in paths { try path.parent.mkdir(.p) try path.touch() } try body(root, paths) } } ================================================ FILE: Tests/XcakeprojTests.swift ================================================ @testable import XcakeProject import CakefileDescription import Foundation import Modelizer import XCTest import Base class XcakeprojTests: XCTestCase { func test() throws { struct Output: Decodable { let project: Project struct Project: Decodable { let targets: [String] } } let basename = "Floobles" try createFixture("Sources/Model/a.swift", "Sources/Model/b/b.swift", "Sources/Model/b/c/c.swift", "Sources/Model/b/d/d.swift") { root, paths in var opts = Options() opts.baseModuleName = basename try XcakeProject(prefix: root, platforms: [.macOS ~> 10.14], swift: .v4_2, options: opts).write() let task = Process() task.currentDirectoryPath = root.join(".cake").string task.launchPath = "/usr/bin/xcodebuild" task.arguments = ["-list", "-json"] let data = try task.runSync().stdout.data let json = try JSONDecoder().decode(Output.self, from: data) XCTAssertEqual(Set(json.project.targets), ["Batter·\(basename)", "Batter·b", "Batter·c", "Batter·d", "Cakefile", "Cakefile·Completion", "Batter", "Cake", "Versionator"]) // or cannot delete fixture dir and test fails for entry in try root.join(".cake").ls() where entry.kind == .file && entry.path.extension == "swift" { try entry.path.unlock() } } } }