import Foundation import Tagged public enum RemoteNameTag {} public typealias RemoteName = Tagged public enum RemoteURLTag {} public typealias RemoteURL = Tagged public enum BranchNameTag {} public typealias BranchName = Tagged public enum RefNameTag {} public typealias RefName = Tagged public enum CommitIDTag {} public typealias CommitID = Tagged public enum CommitMessageTag {} public typealias CommitMessage = Tagged public enum PersonNameTag {} public typealias PersonName = Tagged public enum EmailAddressTag {} public typealias EmailAddress = Tagged public enum SSHUsernameTag {} public typealias SSHUsername = Tagged public enum SSHPrivateKeyTag {} public typealias SSHPrivateKey = Tagged public enum SSHPublicKeyTag {} public typealias SSHPublicKey = Tagged public enum SSHKeyPassphraseTag {} public typealias SSHKeyPassphrase = Tagged public enum HostKeySHA256Tag {} public typealias HostKeySHA256 = Tagged public enum RepositoryPathTag {} public typealias RepositoryPath = Tagged public struct Repository: Equatable, Sendable { public var url: URL public init(url: URL) { self.url = url.standardizedFileURL } } public struct Remote: Equatable, Sendable { public var name: RemoteName public var url: RemoteURL public init(name: RemoteName = "origin", url: RemoteURL) { self.name = name self.url = url } } public struct Branch: Equatable, Sendable { public var name: BranchName public init(name: BranchName) { self.name = name } } public struct Commit: Equatable, Sendable { public var id: CommitID public init(id: CommitID) { self.id = id } } public struct Author: Equatable, Sendable { public var name: PersonName public var email: EmailAddress public init(name: PersonName, email: EmailAddress) { self.name = name self.email = email } } public enum SSHCredentialSource: Equatable, Sendable { case agent case memory( publicKey: SSHPublicKey?, privateKey: SSHPrivateKey, passphrase: SSHKeyPassphrase? ) } public struct SSHCredentials: Equatable, Sendable { public var username: SSHUsername public var source: SSHCredentialSource public init( username: SSHUsername = "git", publicKey: SSHPublicKey? = nil, privateKey: SSHPrivateKey, passphrase: SSHKeyPassphrase? = nil ) { self.username = username self.source = .memory( publicKey: publicKey, privateKey: privateKey, passphrase: passphrase ) } public init( username: SSHUsername = "git", source: SSHCredentialSource ) { self.username = username self.source = source } } public enum HostKeyPolicy: Equatable, Sendable { case defaultValidation case pinnedSHA256(HostKeySHA256) case acceptForTesting } public struct Credentials: Equatable, Sendable { public var ssh: SSHCredentials public var hostKeyPolicy: HostKeyPolicy public init( ssh: SSHCredentials, hostKeyPolicy: HostKeyPolicy = .defaultValidation ) { self.ssh = ssh self.hostKeyPolicy = hostKeyPolicy } } public extension Credentials { static func sshAgent( username: SSHUsername = "git", hostKeyPolicy: HostKeyPolicy = .defaultValidation ) -> Self { Self( ssh: SSHCredentials(username: username, source: .agent), hostKeyPolicy: hostKeyPolicy ) } } public struct CloneRequest: Equatable, Sendable { public var remote: Remote public var destinationURL: URL public var checkout: RefName? public var depth: Int? public var credentials: Credentials? public init( remote: Remote, destinationURL: URL, checkout: RefName? = nil, depth: Int? = nil, credentials: Credentials? = nil ) { if let depth { precondition(depth > 0, "Clone depth must be positive.") } self.remote = remote self.destinationURL = destinationURL.standardizedFileURL self.checkout = checkout self.depth = depth self.credentials = credentials } } public struct FetchRequest: Equatable, Sendable { public var repository: Repository public var remote: RemoteName public var credentials: Credentials? public init( repository: Repository, remote: RemoteName = "origin", credentials: Credentials? = nil ) { self.repository = repository self.remote = remote self.credentials = credentials } } public struct CheckoutRequest: Equatable, Sendable { public var repository: Repository public var ref: RefName public init(repository: Repository, ref: RefName) { self.repository = repository self.ref = ref } } public struct ResolveRevisionRequest: Equatable, Sendable { public var repository: Repository public var ref: RefName public init(repository: Repository, ref: RefName = "HEAD") { self.repository = repository self.ref = ref } } public struct CreateBranchRequest: Equatable, Sendable { public var repository: Repository public var name: BranchName public var startPoint: RefName public var checkout: Bool public init( repository: Repository, name: BranchName, startPoint: RefName = "HEAD", checkout: Bool = true ) { self.repository = repository self.name = name self.startPoint = startPoint self.checkout = checkout } } public struct StageRequest: Equatable, Sendable { public var repository: Repository public var paths: [RepositoryPath] public init(repository: Repository, paths: [RepositoryPath]) { self.repository = repository self.paths = paths } } public struct CommitRequest: Equatable, Sendable { public var repository: Repository public var message: CommitMessage public var author: Author public init( repository: Repository, message: CommitMessage, author: Author ) { self.repository = repository self.message = message self.author = author } } public struct FormatPatchRequest: Equatable, Sendable { public var repository: Repository public var commit: CommitID public init(repository: Repository, commit: CommitID) { self.repository = repository self.commit = commit } } public struct EmailPatchRequest: Equatable, Sendable { public var repository: Repository public var commit: CommitID public var baseCommit: CommitID public init( repository: Repository, commit: CommitID, baseCommit: CommitID ) { self.repository = repository self.commit = commit self.baseCommit = baseCommit } } public struct PushRequest: Equatable, Sendable { public var repository: Repository public var remote: RemoteName public var localBranch: BranchName public var remoteBranch: BranchName public var credentials: Credentials? public init( repository: Repository, remote: RemoteName = "origin", localBranch: BranchName, remoteBranch: BranchName, credentials: Credentials? = nil ) { self.repository = repository self.remote = remote self.localBranch = localBranch self.remoteBranch = remoteBranch self.credentials = credentials } } public struct StatusEntry: Equatable, Sendable { public enum Kind: Equatable, Sendable { case added case modified case deleted case renamed case untracked case conflicted } public var path: RepositoryPath public var kind: Kind public init(path: RepositoryPath, kind: Kind) { self.path = path self.kind = kind } } public struct SourceControlRemoteFailure: Equatable, Sendable { public enum Kind: Equatable, Sendable { case authentication case connection case timedOut case unknown } public var kind: Kind public var message: String public init(kind: Kind, message: String) { self.kind = kind self.message = message } } public enum SourceControlError: Equatable, Error, Sendable { case notConfigured case operationFailed(String) case remoteOperationFailed(SourceControlRemoteFailure) } extension SourceControlError: LocalizedError { public var errorDescription: String? { switch self { case .notConfigured: "Source control is not configured." case let .operationFailed(message): message case let .remoteOperationFailed(failure): failure.message } } }