mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-09-15 08:50:57 +00:00
Merge branch 'xpc_updater' into xpc_services
This commit is contained in:
commit
06a10d57ce
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -24,6 +24,8 @@ jobs:
|
|||||||
- name: Set Environment
|
- name: Set Environment
|
||||||
run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app
|
run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app
|
||||||
- name: Test
|
- name: Test
|
||||||
|
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test
|
||||||
|
# SPM doesn't seem to pick up on the tests currently?
|
||||||
run: swift test --build-system swiftbuild --package-path Sources/Packages
|
run: swift test --build-system swiftbuild --package-path Sources/Packages
|
||||||
build:
|
build:
|
||||||
permissions:
|
permissions:
|
||||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -12,6 +12,8 @@ jobs:
|
|||||||
- name: Set Environment
|
- name: Set Environment
|
||||||
run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app
|
run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app
|
||||||
- name: Test Main Packages
|
- name: Test Main Packages
|
||||||
run: swift test --build-system swiftbuild --package-path Sources/Packages
|
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test
|
||||||
|
# SPM doesn't seem to pick up on the tests currently?
|
||||||
|
# run: swift test --build-system swiftbuild --package-path Sources/Packages
|
||||||
- name: Test SecretKit Packages
|
- name: Test SecretKit Packages
|
||||||
run: swift test --build-system swiftbuild
|
run: swift test --build-system swiftbuild
|
||||||
|
@ -13,12 +13,24 @@
|
|||||||
},
|
},
|
||||||
"testTargets" : [
|
"testTargets" : [
|
||||||
{
|
{
|
||||||
"enabled" : false,
|
|
||||||
"parallelizable" : true,
|
|
||||||
"target" : {
|
"target" : {
|
||||||
"containerPath" : "container:Secretive.xcodeproj",
|
"containerPath" : "container:Packages",
|
||||||
"identifier" : "50617D9323FCE48E0099B055",
|
"identifier" : "BriefTests",
|
||||||
"name" : "SecretiveTests"
|
"name" : "BriefTests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target" : {
|
||||||
|
"containerPath" : "container:Packages",
|
||||||
|
"identifier" : "SecretKitTests",
|
||||||
|
"name" : "SecretKitTests"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target" : {
|
||||||
|
"containerPath" : "container:Packages",
|
||||||
|
"identifier" : "SecretAgentKitTests",
|
||||||
|
"name" : "SecretAgentKitTests"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objc public protocol ReleaseProtocol: Sendable {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A release is a representation of a downloadable update.
|
/// A release is a representation of a downloadable update.
|
||||||
public struct Release: Codable, Sendable {
|
public struct Release: Codable, Sendable {
|
||||||
|
|
||||||
|
@ -32,9 +32,12 @@ final class OpenSSHReader {
|
|||||||
return lengthChunk.bytes.unsafeLoad(as: T.self)
|
return lengthChunk.bytes.unsafeLoad(as: T.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readNextChunkAsString(convertEndianness: Bool = true) throws(OpenSSHReaderError) -> String {
|
||||||
|
try String(decoding: readNextChunk(convertEndianness: convertEndianness), as: UTF8.self)
|
||||||
|
}
|
||||||
|
|
||||||
func readNextChunkAsString() throws(OpenSSHReaderError) -> String {
|
func readNextChunkAsSubReader(convertEndianness: Bool = true) throws(OpenSSHReaderError) -> OpenSSHReader {
|
||||||
try String(decoding: readNextChunk(), as: UTF8.self)
|
OpenSSHReader(data: try readNextChunk(convertEndianness: convertEndianness))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,19 +8,22 @@ import CryptoKit
|
|||||||
|
|
||||||
// MARK: Identity Listing
|
// MARK: Identity Listing
|
||||||
|
|
||||||
|
|
||||||
// let testProvenance = SigningRequestProvenance(root: .init(pid: 0, processName: "Test", appName: "Test", iconURL: nil, path: /, validSignature: true, parentPID: nil))
|
|
||||||
|
|
||||||
@Test func emptyStores() async throws {
|
@Test func emptyStores() async throws {
|
||||||
let agent = Agent(storeList: SecretStoreList())
|
let agent = Agent(storeList: SecretStoreList())
|
||||||
let response = try await agent.handle(data: Constants.Requests.requestIdentities, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities)
|
||||||
|
let response = await agent.handle(request: request, provenance: .test)
|
||||||
#expect(response == Constants.Responses.requestIdentitiesEmpty)
|
#expect(response == Constants.Responses.requestIdentitiesEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test func identitiesList() async throws {
|
@Test func identitiesList() async throws {
|
||||||
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
||||||
let agent = Agent(storeList: list)
|
let agent = Agent(storeList: list)
|
||||||
let response = try await agent.handle(data: Constants.Requests.requestIdentities, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities)
|
||||||
|
let response = await agent.handle(request: request, provenance: .test)
|
||||||
|
|
||||||
|
let actual = OpenSSHReader(data: response)
|
||||||
|
let expected = OpenSSHReader(data: Constants.Responses.requestIdentitiesMultiple)
|
||||||
|
print(actual, expected)
|
||||||
#expect(response == Constants.Responses.requestIdentitiesMultiple)
|
#expect(response == Constants.Responses.requestIdentitiesMultiple)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,40 +32,42 @@ import CryptoKit
|
|||||||
@Test func noMatchingIdentities() async throws {
|
@Test func noMatchingIdentities() async throws {
|
||||||
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
||||||
let agent = Agent(storeList: list)
|
let agent = Agent(storeList: list)
|
||||||
let response = try await agent.handle(data: Constants.Requests.requestSignatureWithNoneMatching, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignatureWithNoneMatching)
|
||||||
|
let response = await agent.handle(request: request, provenance: .test)
|
||||||
#expect(response == Constants.Responses.requestFailure)
|
#expect(response == Constants.Responses.requestFailure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test func ecdsaSignature() async throws {
|
@Test func ecdsaSignature() async throws {
|
||||||
// let stubReader = StubFileHandleReader(availableData: Constants.Requests.requestSignature)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
|
||||||
// let requestReader = OpenSSHReader(data: Constants.Requests.requestSignature[5...])
|
guard case SSHAgent.Request.signRequest(let context) = request else { return }
|
||||||
// _ = requestReader.readNextChunk()
|
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
||||||
// let dataToSign = requestReader.readNextChunk()
|
let agent = Agent(storeList: list)
|
||||||
// let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
|
let response = await agent.handle(request: request, provenance: .test)
|
||||||
// let agent = Agent(storeList: list)
|
let responseReader = OpenSSHReader(data: response)
|
||||||
// await agent.handle(reader: stubReader, writer: stubWriter)
|
let length = try responseReader.readNextBytes(as: UInt32.self).bigEndian
|
||||||
// let outer = OpenSSHReader(data: stubWriter.data[5...])
|
let type = try responseReader.readNextBytes(as: UInt8.self).bigEndian
|
||||||
// let payload = outer.readNextChunk()
|
#expect(length == response.count - MemoryLayout<UInt32>.size)
|
||||||
// let inner = OpenSSHReader(data: payload)
|
#expect(type == SSHAgent.Response.agentSignResponse.rawValue)
|
||||||
// _ = inner.readNextChunk()
|
let outer = OpenSSHReader(data: responseReader.remaining)
|
||||||
// let signedData = inner.readNextChunk()
|
let inner = try outer.readNextChunkAsSubReader()
|
||||||
// let rsData = OpenSSHReader(data: signedData)
|
_ = try inner.readNextChunk()
|
||||||
// var r = rsData.readNextChunk()
|
let rsData = try inner.readNextChunkAsSubReader()
|
||||||
// var s = rsData.readNextChunk()
|
var r = try rsData.readNextChunk()
|
||||||
// // This is fine IRL, but it freaks out CryptoKit
|
var s = try rsData.readNextChunk()
|
||||||
// if r[0] == 0 {
|
// This is fine IRL, but it freaks out CryptoKit
|
||||||
// r.removeFirst()
|
if r[0] == 0 {
|
||||||
// }
|
r.removeFirst()
|
||||||
// if s[0] == 0 {
|
}
|
||||||
// s.removeFirst()
|
if s[0] == 0 {
|
||||||
// }
|
s.removeFirst()
|
||||||
// var rs = r
|
}
|
||||||
// rs.append(s)
|
var rs = r
|
||||||
// let signature = try P256.Signing.ECDSASignature(rawRepresentation: rs)
|
rs.append(s)
|
||||||
// // Correct signature
|
let signature = try P256.Signing.ECDSASignature(rawRepresentation: rs)
|
||||||
// #expect(try P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey)
|
// Correct signature
|
||||||
// .isValidSignature(signature, for: dataToSign))
|
#expect(try P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey)
|
||||||
// }
|
.isValidSignature(signature, for: context.dataToSign))
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Witness protocol
|
// MARK: Witness protocol
|
||||||
|
|
||||||
@ -72,7 +77,7 @@ import CryptoKit
|
|||||||
return true
|
return true
|
||||||
}, witness: { _, _ in })
|
}, witness: { _, _ in })
|
||||||
let agent = Agent(storeList: list, witness: witness)
|
let agent = Agent(storeList: list, witness: witness)
|
||||||
let response = try await agent.handle(data: Constants.Requests.requestSignature, provenance: .test)
|
let response = await agent.handle(request: .signRequest(.empty), provenance: .test)
|
||||||
#expect(response == Constants.Responses.requestFailure)
|
#expect(response == Constants.Responses.requestFailure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +90,8 @@ import CryptoKit
|
|||||||
witnessed = true
|
witnessed = true
|
||||||
})
|
})
|
||||||
let agent = Agent(storeList: list, witness: witness)
|
let agent = Agent(storeList: list, witness: witness)
|
||||||
_ = try await agent.handle(data: Constants.Requests.requestSignature, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
|
||||||
|
_ = await agent.handle(request: request, provenance: .test)
|
||||||
#expect(witnessed)
|
#expect(witnessed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +106,8 @@ import CryptoKit
|
|||||||
witnessTrace = trace
|
witnessTrace = trace
|
||||||
})
|
})
|
||||||
let agent = Agent(storeList: list, witness: witness)
|
let agent = Agent(storeList: list, witness: witness)
|
||||||
_ = try await agent.handle(data: Constants.Requests.requestSignature, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
|
||||||
|
_ = await agent.handle(request: request, provenance: .test)
|
||||||
#expect(witnessTrace == speakNowTrace)
|
#expect(witnessTrace == speakNowTrace)
|
||||||
#expect(witnessTrace == .test)
|
#expect(witnessTrace == .test)
|
||||||
}
|
}
|
||||||
@ -112,7 +119,8 @@ import CryptoKit
|
|||||||
let store = await list.stores.first?.base as! Stub.Store
|
let store = await list.stores.first?.base as! Stub.Store
|
||||||
store.shouldThrow = true
|
store.shouldThrow = true
|
||||||
let agent = Agent(storeList: list)
|
let agent = Agent(storeList: list)
|
||||||
let response = try await agent.handle(data: Constants.Requests.requestSignature, provenance: .test)
|
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
|
||||||
|
let response = await agent.handle(request: request, provenance: .test)
|
||||||
#expect(response == Constants.Responses.requestFailure)
|
#expect(response == Constants.Responses.requestFailure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +128,7 @@ import CryptoKit
|
|||||||
|
|
||||||
@Test func unhandledAdd() async throws {
|
@Test func unhandledAdd() async throws {
|
||||||
let agent = Agent(storeList: SecretStoreList())
|
let agent = Agent(storeList: SecretStoreList())
|
||||||
let response = try await agent.handle(data: Constants.Requests.addIdentity, provenance: .test)
|
let response = await agent.handle(request: .addIdentity, provenance: .test)
|
||||||
#expect(response == Constants.Responses.requestFailure)
|
#expect(response == Constants.Responses.requestFailure)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,14 +154,13 @@ extension AgentTests {
|
|||||||
|
|
||||||
enum Requests {
|
enum Requests {
|
||||||
static let requestIdentities = Data(base64Encoded: "AAAAAQs=")!
|
static let requestIdentities = Data(base64Encoded: "AAAAAQs=")!
|
||||||
static let addIdentity = Data(base64Encoded: "AAAAARE=")!
|
|
||||||
static let requestSignatureWithNoneMatching = Data(base64Encoded: "AAABhA0AAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBEqCbkJbOHy5S1wVCaJoKPmpS0egM4frMqllgnlRRQ/Uvnn6EVS8oV03cPA2Bz0EdESyRKA/sbmn0aBtgjIwGELxu45UXEW1TEz6TxyS0u3vuIqR3Wo1CrQWRDnkrG/pBQAAAO8AAAAgbqmrqPUtJ8mmrtaSVexjMYyXWNqjHSnoto7zgv86xvcyAAAAA2dpdAAAAA5zc2gtY29ubmVjdGlvbgAAAAlwdWJsaWNrZXkBAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBEqCbkJbOHy5S1wVCaJoKPmpS0egM4frMqllgnlRRQ/Uvnn6EVS8oV03cPA2Bz0EdESyRKA/sbmn0aBtgjIwGELxu45UXEW1TEz6TxyS0u3vuIqR3Wo1CrQWRDnkrG/pBQAAAAA=")!
|
static let requestSignatureWithNoneMatching = Data(base64Encoded: "AAABhA0AAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBEqCbkJbOHy5S1wVCaJoKPmpS0egM4frMqllgnlRRQ/Uvnn6EVS8oV03cPA2Bz0EdESyRKA/sbmn0aBtgjIwGELxu45UXEW1TEz6TxyS0u3vuIqR3Wo1CrQWRDnkrG/pBQAAAO8AAAAgbqmrqPUtJ8mmrtaSVexjMYyXWNqjHSnoto7zgv86xvcyAAAAA2dpdAAAAA5zc2gtY29ubmVjdGlvbgAAAAlwdWJsaWNrZXkBAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBEqCbkJbOHy5S1wVCaJoKPmpS0egM4frMqllgnlRRQ/Uvnn6EVS8oV03cPA2Bz0EdESyRKA/sbmn0aBtgjIwGELxu45UXEW1TEz6TxyS0u3vuIqR3Wo1CrQWRDnkrG/pBQAAAAA=")!
|
||||||
static let requestSignature = Data(base64Encoded: "AAABRA0AAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKzOkUiVJEcACMtAd9X7xalbc0FYZyhbmv2dsWl4IP2GWIi+RcsaHQNw+nAIQ8CKEYmLnl0VLDp5Ef8KMhgIy08AAADPAAAAIBIFsbCZ4/dhBmLNGHm0GKj7EJ4N8k/jXRxlyg+LFIYzMgAAAANnaXQAAAAOc3NoLWNvbm5lY3Rpb24AAAAJcHVibGlja2V5AQAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAAaAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSszpFIlSRHAAjLQHfV+8WpW3NBWGcoW5r9nbFpeCD9hliIvkXLGh0DcPpwCEPAihGJi55dFSw6eRH/CjIYCMtPAAAAAA==")!
|
static let requestSignature = Data(base64Encoded: "AAABRA0AAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKzOkUiVJEcACMtAd9X7xalbc0FYZyhbmv2dsWl4IP2GWIi+RcsaHQNw+nAIQ8CKEYmLnl0VLDp5Ef8KMhgIy08AAADPAAAAIBIFsbCZ4/dhBmLNGHm0GKj7EJ4N8k/jXRxlyg+LFIYzMgAAAANnaXQAAAAOc3NoLWNvbm5lY3Rpb24AAAAJcHVibGlja2V5AQAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAAaAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSszpFIlSRHAAjLQHfV+8WpW3NBWGcoW5r9nbFpeCD9hliIvkXLGh0DcPpwCEPAihGJi55dFSw6eRH/CjIYCMtPAAAAAA==")!
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Responses {
|
enum Responses {
|
||||||
static let requestIdentitiesEmpty = Data(base64Encoded: "AAAABQwAAAAA")!
|
static let requestIdentitiesEmpty = Data(base64Encoded: "AAAABQwAAAAA")!
|
||||||
static let requestIdentitiesMultiple = Data(base64Encoded: "AAABKwwAAAACAAAAaAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSszpFIlSRHAAjLQHfV+8WpW3NBWGcoW5r9nbFpeCD9hliIvkXLGh0DcPpwCEPAihGJi55dFSw6eRH/CjIYCMtPAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBLKSzA5q3jCb3q0JKigvcxfWVGrJ+bklpG0Zc9YzUwrbsh9SipvlSJi+sHQI+O0m88DOpRBAtuAHX60euD/Yv250tovN7/+MEFbXGZ/hLdd0BoFpWbLfJcQj806KJGlcDAAAABNlY2RzYS1zaGEyLW5pc3RwMzg0")!
|
static let requestIdentitiesMultiple = Data(base64Encoded: "AAABLwwAAAACAAAAaAAAABNlY2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSszpFIlSRHAAjLQHfV+8WpW3NBWGcoW5r9nbFpeCD9hliIvkXLGh0DcPpwCEPAihGJi55dFSw6eRH/CjIYCMtPAAAAFWVjZHNhLTI1NkBleGFtcGxlLmNvbQAAAIgAAAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAAhuaXN0cDM4NAAAAGEEspLMDmreMJverQkqKC9zF9ZUasn5uSWkbRlz1jNTCtuyH1KKm+VImL6wdAj47SbzwM6lEEC24AdfrR64P9i/bnS2i83v/4wQVtcZn+Et13QGgWlZst8lxCPzTookaVwMAAAAFWVjZHNhLTM4NEBleGFtcGxlLmNvbQ==")!
|
||||||
static let requestFailure = Data(base64Encoded: "AAAAAQU=")!
|
static let requestFailure = Data(base64Encoded: "AAAAAQU=")!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Testing
|
import Testing
|
||||||
@testable import SecretKit
|
@testable import SecretAgentKit
|
||||||
@testable import SecureEnclaveSecretKit
|
@testable import SecureEnclaveSecretKit
|
||||||
@testable import SmartCardSecretKit
|
@testable import SmartCardSecretKit
|
||||||
|
|
@ -82,7 +82,7 @@ extension Stub {
|
|||||||
let privateKey: Data
|
let privateKey: Data
|
||||||
|
|
||||||
init(keySize: Int, publicKey: Data, privateKey: Data) {
|
init(keySize: Int, publicKey: Data, privateKey: Data) {
|
||||||
self.attributes = Attributes(keyType: .init(algorithm: .ecdsa, size: keySize), authentication: .notRequired)
|
self.attributes = Attributes(keyType: .init(algorithm: .ecdsa, size: keySize), authentication: .notRequired, publicKeyAttribution: "ecdsa-\(keySize)@example.com")
|
||||||
self.publicKey = publicKey
|
self.publicKey = publicKey
|
||||||
self.privateKey = privateKey
|
self.privateKey = privateKey
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "2600"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<TestPlans>
|
||||||
|
<TestPlanReference
|
||||||
|
reference = "container:Config/Secretive.xctestplan">
|
||||||
|
</TestPlanReference>
|
||||||
|
</TestPlans>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
Loading…
Reference in New Issue
Block a user