Support custom branches (#236)

This commit is contained in:
Danny Moesch 2019-01-06 20:10:47 +01:00 committed by Mingshen Sun
parent 744b46adc2
commit 6b4dbd50a9
6 changed files with 81 additions and 15 deletions

View file

@ -10,7 +10,8 @@ import Foundation
public enum AppError: Error {
case RepositoryNotSetError
case RepositoryRemoteMasterNotFoundError
case RepositoryRemoteBranchNotFoundError(_: String)
case RepositoryBranchNotFound(_: String)
case KeyImportError
case PasswordDuplicatedError
case GitResetError
@ -25,8 +26,10 @@ extension AppError: LocalizedError {
switch self {
case .RepositoryNotSetError:
return "Git repository is not set."
case .RepositoryRemoteMasterNotFoundError:
return "Cannot find remote branch origin/master."
case let .RepositoryRemoteBranchNotFoundError(remoteBranchName):
return "Cannot find remote branch 'origin/\(remoteBranchName)'."
case let .RepositoryBranchNotFound(branchName):
return "Branch with name '\(branchName)' not found in repository."
case .KeyImportError:
return "Cannot import the key."
case .PasswordDuplicatedError:

View file

@ -22,6 +22,7 @@ public extension DefaultsKeys {
static let gitURL = DefaultsKey<URL?>("gitURL")
static let gitAuthenticationMethod = DefaultsKey<String?>("gitAuthenticationMethod")
static let gitUsername = DefaultsKey<String?>("gitUsername")
static let gitBranchName = DefaultsKey<String?>("gitBranchName")
static let gitSSHPrivateKeyURL = DefaultsKey<URL?>("gitSSHPrivateKeyURL")
static let gitSSHKeySource = DefaultsKey<String?>("gitSSHKeySource")
static let gitSSHPrivateKeyArmor = DefaultsKey<String?>("gitSSHPrivateKeyArmor")

View file

@ -299,6 +299,7 @@ public class PasswordStore {
public func cloneRepository(remoteRepoURL: URL,
credential: GitCredential,
branchName: String,
requestGitPassword: @escaping (GitCredential.Credential, String?) -> String?,
transferProgressBlock: @escaping (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void,
checkoutProgressBlock: @escaping (String?, UInt, UInt) -> Void) throws {
@ -312,6 +313,7 @@ public class PasswordStore {
storeRepository = try GTRepository.clone(from: remoteRepoURL, toWorkingDirectory: tempStoreURL, options: options, transferProgressBlock:transferProgressBlock)
try fm.moveItem(at: tempStoreURL, to: storeURL)
storeRepository = try GTRepository(url: storeURL)
try checkoutAndChangeBranch(withName: branchName)
} catch {
credential.delete()
DispatchQueue.main.async {
@ -328,6 +330,27 @@ public class PasswordStore {
}
}
private func checkoutAndChangeBranch(withName localBranchName: String) throws {
if (localBranchName == "master") {
return
}
guard let storeRepository = storeRepository else {
throw AppError.RepositoryNotSetError
}
let remoteBranchName = "origin/\(localBranchName)"
guard let remoteBranch = try? storeRepository.lookUpBranch(withName: remoteBranchName, type: .remote, success: nil) else {
throw AppError.RepositoryRemoteBranchNotFoundError(remoteBranchName)
}
guard let remoteBranchOid = remoteBranch.oid else {
throw AppError.RepositoryRemoteBranchNotFoundError(remoteBranchName)
}
let localBranch = try storeRepository.createBranchNamed(localBranchName, from: remoteBranchOid, message: nil)
try localBranch.updateTrackingBranch(remoteBranch)
let checkoutOptions = GTCheckoutOptions.init(strategy: .force)
try storeRepository.checkoutReference(localBranch.reference, options: checkoutOptions)
try storeRepository.moveHEAD(to: localBranch.reference)
}
public func pullRepository(credential: GitCredential, requestGitPassword: @escaping (GitCredential.Credential, String?) -> String?, transferProgressBlock: @escaping (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
guard let storeRepository = storeRepository else {
throw AppError.RepositoryNotSetError
@ -567,9 +590,9 @@ public class PasswordStore {
do {
let credentialProvider = try credential.credentialProvider(requestGitPassword: requestGitPassword)
let options = [GTRepositoryRemoteOptionsCredentialProvider: credentialProvider]
if let masterBranch = try getLocalBranch(withName: "master") {
if let branch = try getLocalBranch(withName: SharedDefaults[.gitBranchName]!) {
let remote = try GTRemote(name: "origin", in: storeRepository)
try storeRepository.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock)
try storeRepository.push(branch, to: remote, withOptions: options, progress: transferProgressBlock)
}
} catch {
throw(error)
@ -790,19 +813,18 @@ public class PasswordStore {
guard let storeRepository = storeRepository else {
throw AppError.RepositoryNotSetError
}
// get the remote origin/master branch
guard let index = try storeRepository.remoteBranches().index(where: { $0.shortName == "master" }) else {
throw AppError.RepositoryRemoteMasterNotFoundError
// get the remote branch
let remoteBranchName = SharedDefaults[.gitBranchName]!
guard let remoteBranch = try storeRepository.remoteBranches().first(where: { $0.shortName == remoteBranchName }) else {
throw AppError.RepositoryRemoteBranchNotFoundError(remoteBranchName)
}
let remoteMasterBranch = try storeRepository.remoteBranches()[index]
// check oid before calling localCommitsRelative
guard remoteMasterBranch.oid != nil else {
throw AppError.RepositoryRemoteMasterNotFoundError
guard remoteBranch.oid != nil else {
throw AppError.RepositoryRemoteBranchNotFoundError(remoteBranchName)
}
// get a list of local commits
return try storeRepository.localCommitsRelative(toRemoteBranch: remoteMasterBranch)
return try storeRepository.localCommitsRelative(toRemoteBranch: remoteBranch)
}