From 6b4dbd50a97ebe6703173178096dab352452d1db Mon Sep 17 00:00:00 2001 From: Danny Moesch Date: Sun, 6 Jan 2019 20:10:47 +0100 Subject: [PATCH] Support custom branches (#236) --- pass/AppDelegate.swift | 5 +++ pass/Base.lproj/Main.storyboard | 34 ++++++++++++++- .../GitServerSettingTableViewController.swift | 5 +++ passKit/Helpers/AppError.swift | 9 ++-- passKit/Helpers/DefaultsKeys.swift | 1 + passKit/Models/PasswordStore.swift | 42 ++++++++++++++----- 6 files changed, 81 insertions(+), 15 deletions(-) diff --git a/pass/AppDelegate.swift b/pass/AppDelegate.swift index c12fd6e..a09a02c 100644 --- a/pass/AppDelegate.swift +++ b/pass/AppDelegate.swift @@ -10,6 +10,7 @@ import UIKit import CoreData import SVProgressHUD import passKit +import SwiftyUserDefaults @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -33,6 +34,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { self.perform(#selector(postSearchNotification), with: nil, afterDelay: 0.4) } } + + // Assign default values to global settings. + SharedDefaults.register(defaults: [DefaultsKeys.gitBranchName._key: "master"]) + return true } diff --git a/pass/Base.lproj/Main.storyboard b/pass/Base.lproj/Main.storyboard index 03dbfe5..08afe1e 100644 --- a/pass/Base.lproj/Main.storyboard +++ b/pass/Base.lproj/Main.storyboard @@ -381,10 +381,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -416,7 +445,7 @@ - + @@ -466,6 +495,7 @@ + diff --git a/pass/Controllers/GitServerSettingTableViewController.swift b/pass/Controllers/GitServerSettingTableViewController.swift index 7c322b4..0410a55 100644 --- a/pass/Controllers/GitServerSettingTableViewController.swift +++ b/pass/Controllers/GitServerSettingTableViewController.swift @@ -14,6 +14,7 @@ class GitServerSettingTableViewController: UITableViewController { @IBOutlet weak var gitURLTextField: UITextField! @IBOutlet weak var usernameTextField: UITextField! + @IBOutlet weak var branchNameTextField: UITextField! @IBOutlet weak var authSSHKeyCell: UITableViewCell! @IBOutlet weak var authPasswordCell: UITableViewCell! let passwordStore = PasswordStore.shared @@ -51,6 +52,7 @@ class GitServerSettingTableViewController: UITableViewController { gitURLTextField.text = url.absoluteString } usernameTextField.text = SharedDefaults[.gitUsername] + branchNameTextField.text = SharedDefaults[.gitBranchName] sshLabel = authSSHKeyCell.subviews[0].subviews[0] as? UILabel checkAuthenticationMethod(method: authenticationMethod) authSSHKeyCell.accessoryType = .detailButton @@ -77,6 +79,7 @@ class GitServerSettingTableViewController: UITableViewController { // try to clone let gitRepostiroyURL = gitURLTextField.text!.trimmed let username = usernameTextField.text! + let branchName = branchNameTextField.text! let auth = authenticationMethod SVProgressHUD.setDefaultMaskType(.black) @@ -100,6 +103,7 @@ class GitServerSettingTableViewController: UITableViewController { do { try self.passwordStore.cloneRepository(remoteRepoURL: URL(string: gitRepostiroyURL)!, credential: gitCredential, + branchName: branchName, requestGitPassword: self.requestGitPassword, transferProgressBlock: { (git_transfer_progress, stop) in DispatchQueue.main.async { @@ -114,6 +118,7 @@ class GitServerSettingTableViewController: UITableViewController { DispatchQueue.main.async { SharedDefaults[.gitURL] = URL(string: gitRepostiroyURL) SharedDefaults[.gitUsername] = username + SharedDefaults[.gitBranchName] = branchName SharedDefaults[.gitAuthenticationMethod] = auth SVProgressHUD.dismiss() let savePassphraseAlert = UIAlertController(title: "Done", message: "Do you want to save the Git credential password/passphrase?", preferredStyle: UIAlertControllerStyle.alert) diff --git a/passKit/Helpers/AppError.swift b/passKit/Helpers/AppError.swift index 2a96877..c185ea8 100644 --- a/passKit/Helpers/AppError.swift +++ b/passKit/Helpers/AppError.swift @@ -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: diff --git a/passKit/Helpers/DefaultsKeys.swift b/passKit/Helpers/DefaultsKeys.swift index 8f5c47e..e5b08f5 100644 --- a/passKit/Helpers/DefaultsKeys.swift +++ b/passKit/Helpers/DefaultsKeys.swift @@ -22,6 +22,7 @@ public extension DefaultsKeys { static let gitURL = DefaultsKey("gitURL") static let gitAuthenticationMethod = DefaultsKey("gitAuthenticationMethod") static let gitUsername = DefaultsKey("gitUsername") + static let gitBranchName = DefaultsKey("gitBranchName") static let gitSSHPrivateKeyURL = DefaultsKey("gitSSHPrivateKeyURL") static let gitSSHKeySource = DefaultsKey("gitSSHKeySource") static let gitSSHPrivateKeyArmor = DefaultsKey("gitSSHPrivateKeyArmor") diff --git a/passKit/Models/PasswordStore.swift b/passKit/Models/PasswordStore.swift index 7035303..5f9e381 100644 --- a/passKit/Models/PasswordStore.swift +++ b/passKit/Models/PasswordStore.swift @@ -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, UnsafeMutablePointer) -> 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, UnsafeMutablePointer) -> 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) }