diff --git a/pass/Controllers/GitSSHKeyArmorSettingTableViewController.swift b/pass/Controllers/GitSSHKeyArmorSettingTableViewController.swift index 035f73a..b21adb7 100644 --- a/pass/Controllers/GitSSHKeyArmorSettingTableViewController.swift +++ b/pass/Controllers/GitSSHKeyArmorSettingTableViewController.swift @@ -21,28 +21,10 @@ class GitSSHKeyArmorSettingTableViewController: UITableViewController, UITextVie super.viewDidLoad() armorPublicKeyTextView.text = Defaults[.gitSSHPublicKeyArmor] armorPrivateKeyTextView.text = Defaults[.gitSSHPrivateKeyArmor] - gitSSHPrivateKeyPassphrase = passwordStore.gitSSHPrivateKeyPassphrase - armorPublicKeyTextView.delegate = self armorPrivateKeyTextView.delegate = self } - private func createSavePassphraseAlert() -> UIAlertController { - let savePassphraseAlert = UIAlertController(title: "Passphrase", message: "Do you want to save the passphrase for later sync?", preferredStyle: UIAlertControllerStyle.alert) - savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in - Defaults[.isRememberPassphraseOn] = false - Defaults[.gitSSHKeySource] = "armor" - self.navigationController!.popViewController(animated: true) - }) - savePassphraseAlert.addAction(UIAlertAction(title: "Save", style: UIAlertActionStyle.destructive) {_ in - Defaults[.isRememberPassphraseOn] = true - self.passwordStore.gitSSHPrivateKeyPassphrase = self.gitSSHPrivateKeyPassphrase - Defaults[.gitSSHKeySource] = "armor" - self.navigationController!.popViewController(animated: true) - }) - return savePassphraseAlert - } - @IBAction func doneButtonTapped(_ sender: Any) { Defaults[.gitSSHPublicKeyArmor] = armorPublicKeyTextView.text Defaults[.gitSSHPrivateKeyArmor] = armorPrivateKeyTextView.text @@ -52,22 +34,13 @@ class GitSSHKeyArmorSettingTableViewController: UITableViewController, UITextVie } catch { Utils.alert(title: "Cannot Save", message: "Cannot Save SSH Key", controller: self, completion: nil) } - let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your SSH secret key.", preferredStyle: UIAlertControllerStyle.alert) - alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in - self.gitSSHPrivateKeyPassphrase = alert.textFields?.first?.text - let savePassphraseAlert = self.createSavePassphraseAlert() - self.present(savePassphraseAlert, animated: true, completion: nil) - })) - alert.addTextField(configurationHandler: {(textField: UITextField!) in - textField.text = self.gitSSHPrivateKeyPassphrase - textField.isSecureTextEntry = true - }) - self.present(alert, animated: true, completion: nil) + Defaults[.gitSSHKeySource] = "armor" + self.navigationController!.popViewController(animated: true) } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == UIPasteboard.general.string { - // user pastes somethint, get ready to clear in 10s + // user pastes something, get ready to clear in 10s recentPastedText = text DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime.now() + 10) { [weak weakSelf = self] in if let pasteboardString = UIPasteboard.general.string, diff --git a/pass/Controllers/GitServerSettingTableViewController.swift b/pass/Controllers/GitServerSettingTableViewController.swift index 4e680b9..8843ce7 100644 --- a/pass/Controllers/GitServerSettingTableViewController.swift +++ b/pass/Controllers/GitServerSettingTableViewController.swift @@ -17,8 +17,8 @@ class GitServerSettingTableViewController: UITableViewController { @IBOutlet weak var authSSHKeyCell: UITableViewCell! @IBOutlet weak var authPasswordCell: UITableViewCell! let passwordStore = PasswordStore.shared - var password: String? - + var sshLabel: UILabel? = nil + var authenticationMethod = Defaults[.gitAuthenticationMethod] private func checkAuthenticationMethod(method: String) { @@ -37,24 +37,22 @@ class GitServerSettingTableViewController: UITableViewController { sshKeyCheckView.isHidden = true } } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + // Grey out ssh option if ssh_key and ssh_key.pub are not present + sshLabel = authSSHKeyCell.subviews[0].subviews[0] as? UILabel + sshLabel!.isEnabled = gitSSHKeyExists() + + } override func viewDidLoad() { super.viewDidLoad() if let url = Defaults[.gitURL] { gitURLTextField.text = url.absoluteString } usernameTextField.text = Defaults[.gitUsername] - password = passwordStore.gitPassword authenticationMethod = Defaults[.gitAuthenticationMethod] - // Grey out ssh option if ssh_key and ssh_key.pub are not present - let sshLabel = authSSHKeyCell.subviews[0].subviews[0] as! UILabel - - sshLabel.isEnabled = gitSSHKeyExists() - - if authenticationMethod == nil || !sshLabel.isEnabled { - authenticationMethod = "Password" - } - checkAuthenticationMethod(method: authenticationMethod!) authSSHKeyCell.accessoryType = .detailButton } @@ -108,24 +106,8 @@ class GitServerSettingTableViewController: UITableViewController { } private func doClone() { - if authenticationMethod == "Password" { - let alert = UIAlertController(title: "Password", message: "Please fill in the password of your Git account.", preferredStyle: UIAlertControllerStyle.alert) - alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in - self.password = alert.textFields!.first!.text - self.passwordStore.gitPassword = self.password - if self.shouldPerformSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) { - self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) - } - })) - alert.addTextField(configurationHandler: {(textField: UITextField!) in - textField.text = self.password - textField.isSecureTextEntry = true - }) - self.present(alert, animated: true, completion: nil) - } else { - if self.shouldPerformSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) { - self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) - } + if self.shouldPerformSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) { + self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self) } } @@ -172,30 +154,8 @@ class GitServerSettingTableViewController: UITableViewController { if (gitSSHKeyExists()) { let fileAction = UIAlertAction(title: fileActionTitle, style: .default) { _ in - let alert = UIAlertController( - title: "SSH Key Passphrase", - message: "Please fill in the passphrase for your Git Repository SSH key.", - preferredStyle: UIAlertControllerStyle.alert - ) - - alert.addAction( - UIAlertAction( - title: "OK", - style: UIAlertActionStyle.default, - handler: {_ in - self.passwordStore.gitSSHPrivateKeyPassphrase = alert.textFields!.first!.text! - } - ) - ) - - alert.addTextField( - configurationHandler: {(textField: UITextField!) in - textField.text = self.passwordStore.gitSSHPrivateKeyPassphrase - textField.isSecureTextEntry = true - } - ) + Defaults[.gitSSHKeySource] = "file" } - Defaults[.gitSSHKeySource] = "file" optionMenu.addAction(fileAction) } @@ -203,6 +163,7 @@ class GitServerSettingTableViewController: UITableViewController { let deleteAction = UIAlertAction(title: "Remove Git SSH Keys", style: .destructive) { _ in Utils.removeGitSSHKeys() Defaults[.gitSSHKeySource] = nil + self.sshLabel!.isEnabled = false } optionMenu.addAction(deleteAction) } diff --git a/pass/Controllers/PasswordsViewController.swift b/pass/Controllers/PasswordsViewController.swift index aee47a7..b0707e4 100644 --- a/pass/Controllers/PasswordsViewController.swift +++ b/pass/Controllers/PasswordsViewController.swift @@ -128,19 +128,38 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV } private func syncPasswords() { + guard passwordStore.repositoryExisted() else { + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800)) { + Utils.alert(title: "Error", message: "There is no password store right now.", controller: self, completion: nil) + } + return + } SVProgressHUD.setDefaultMaskType(.black) SVProgressHUD.setDefaultStyle(.light) SVProgressHUD.show(withStatus: "Sync Password Store") let numberOfLocalCommits = self.passwordStore.numberOfLocalCommits() + var gitCredential: GitCredential + if Defaults[.gitAuthenticationMethod] == "Password" { + gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitUsername]!, controller: self)) + } else { + gitCredential = GitCredential( + credential: GitCredential.Credential.ssh( + userName: Defaults[.gitUsername]!, + publicKeyFile: Globals.gitSSHPublicKeyURL, + privateKeyFile: Globals.gitSSHPrivateKeyURL, + controller: self + ) + ) + } DispatchQueue.global(qos: .userInitiated).async { [unowned self] in do { - try self.passwordStore.pullRepository(transferProgressBlock: {(git_transfer_progress, stop) in + try self.passwordStore.pullRepository(credential: gitCredential, transferProgressBlock: {(git_transfer_progress, stop) in DispatchQueue.main.async { SVProgressHUD.showProgress(Float(git_transfer_progress.pointee.received_objects)/Float(git_transfer_progress.pointee.total_objects), status: "Pull Remote Repository") } }) if numberOfLocalCommits > 0 { - try self.passwordStore.pushRepository(transferProgressBlock: {(current, total, bytes, stop) in + try self.passwordStore.pushRepository(credential: gitCredential, transferProgressBlock: {(current, total, bytes, stop) in DispatchQueue.main.async { SVProgressHUD.showProgress(Float(current)/Float(total), status: "Push Remote Repository") } @@ -148,7 +167,6 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV } DispatchQueue.main.async { self.reloadTableView(parent: nil) - Defaults[.gitPasswordAttempts] = 0 SVProgressHUD.showSuccess(withStatus: "Done") SVProgressHUD.dismiss(withDelay: 1) } diff --git a/pass/Controllers/SSHKeySettingTableViewController.swift b/pass/Controllers/SSHKeySettingTableViewController.swift index 23f0c5c..615ef6c 100644 --- a/pass/Controllers/SSHKeySettingTableViewController.swift +++ b/pass/Controllers/SSHKeySettingTableViewController.swift @@ -43,32 +43,7 @@ class SSHKeySettingTableViewController: UITableViewController { Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil) } Defaults[.gitSSHKeySource] = "url" - let alert = UIAlertController( - title: "PGP Passphrase", - message: "Please fill in the passphrase for your Git Repository SSH key.", - preferredStyle: UIAlertControllerStyle.alert - ) - - alert.addAction( - UIAlertAction( - title: "OK", - style: UIAlertActionStyle.default, - handler: {_ in - Utils.addPasswordToKeychain( - name: "gitSSHPrivateKeyPassphrase", - password: alert.textFields!.first!.text! - ) - self.navigationController!.popViewController(animated: true) - } - ) - ) - - alert.addTextField( - configurationHandler: {(textField: UITextField!) in - textField.text = self.passwordStore.gitSSHPrivateKeyPassphrase - textField.isSecureTextEntry = true - }) - self.present(alert, animated: true, completion: nil) + self.navigationController!.popViewController(animated: true) } } diff --git a/pass/Controllers/SettingsTableViewController.swift b/pass/Controllers/SettingsTableViewController.swift index a05ce5a..8c0b38d 100644 --- a/pass/Controllers/SettingsTableViewController.swift +++ b/pass/Controllers/SettingsTableViewController.swift @@ -98,7 +98,6 @@ class SettingsTableViewController: UITableViewController { if let controller = segue.source as? GitServerSettingTableViewController { let gitRepostiroyURL = controller.gitURLTextField.text! let username = controller.usernameTextField.text! - let password = controller.password let auth = controller.authenticationMethod SVProgressHUD.setDefaultMaskType(.black) @@ -106,15 +105,14 @@ class SettingsTableViewController: UITableViewController { SVProgressHUD.show(withStatus: "Prepare Repository") var gitCredential: GitCredential if auth == "Password" { - gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: username, password: password!, requestGitPassword: requestGitPassword)) + gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: username, controller: self)) } else { gitCredential = GitCredential( credential: GitCredential.Credential.ssh( userName: username, - password: Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") ?? "", publicKeyFile: Globals.gitSSHPublicKeyURL, privateKeyFile: Globals.gitSSHPrivateKeyURL, - requestSSHKeyPassword: self.requestGitPassword + controller: self ) ) } @@ -137,7 +135,6 @@ class SettingsTableViewController: UITableViewController { Defaults[.gitURL] = URL(string: gitRepostiroyURL) Defaults[.gitUsername] = username Defaults[.gitAuthenticationMethod] = auth - Defaults[.gitPasswordAttempts] = 0 self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitURL]?.host SVProgressHUD.showSuccess(withStatus: "Done") SVProgressHUD.dismiss(withDelay: 1) @@ -196,32 +193,6 @@ class SettingsTableViewController: UITableViewController { touchIDSwitch.isOn = false } } - - private func requestGitPassword(message: String) -> String? { - let sem = DispatchSemaphore(value: 0) - var password: String? - - DispatchQueue.main.async { - SVProgressHUD.dismiss() - let alert = UIAlertController(title: "Password", message: message, preferredStyle: UIAlertControllerStyle.alert) - alert.addTextField(configurationHandler: {(textField: UITextField!) in - textField.text = self.passwordStore.gitPassword - textField.isSecureTextEntry = true - }) - alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in - password = alert.textFields!.first!.text - sem.signal() - })) - alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in - password = nil - sem.signal() - }) - self.present(alert, animated: true, completion: nil) - } - - let _ = sem.wait(timeout: .distantFuture) - return password - } func actOnPasswordStoreErasedNotification() { setPGPKeyTableViewCellDetailText() diff --git a/pass/Helpers/DefaultsKeys.swift b/pass/Helpers/DefaultsKeys.swift index 3de6fdf..8ea41a9 100644 --- a/pass/Helpers/DefaultsKeys.swift +++ b/pass/Helpers/DefaultsKeys.swift @@ -20,7 +20,6 @@ extension DefaultsKeys { static let gitURL = DefaultsKey("gitURL") static let gitAuthenticationMethod = DefaultsKey("gitAuthenticationMethod") static let gitUsername = DefaultsKey("gitUsername") - static let gitPasswordAttempts = DefaultsKey("gitPasswordAttempts") static let gitSSHPublicKeyURL = DefaultsKey("gitSSHPublicKeyURL") static let gitSSHPrivateKeyURL = DefaultsKey("gitSSHPrivateKeyURL") static let gitSSHKeySource = DefaultsKey("gitSSHKeySource") diff --git a/pass/Models/PasswordStore.swift b/pass/Models/PasswordStore.swift index a91c6fb..7a24b79 100644 --- a/pass/Models/PasswordStore.swift +++ b/pass/Models/PasswordStore.swift @@ -17,50 +17,91 @@ struct GitCredential { var credential: Credential enum Credential { - case http(userName: String, password: String, requestGitPassword: ((_ message: String) -> String?)?) - case ssh(userName: String, password: String, publicKeyFile: URL, privateKeyFile: URL, requestSSHKeyPassword: ((_ message: String) -> String?)? ) + case http(userName: String, controller: UIViewController) + case ssh(userName: String, publicKeyFile: URL, privateKeyFile: URL, controller: UIViewController) } init(credential: Credential) { self.credential = credential - Defaults[.gitPasswordAttempts] = 0 } func credentialProvider() throws -> GTCredentialProvider { + var attempts = 0 + var lastPassword: String? = nil return GTCredentialProvider { (_, _, _) -> (GTCredential?) in var credential: GTCredential? = nil switch self.credential { - case let .http(userName, password, requestGitPassword): - var newPassword = password - if Defaults[.gitPasswordAttempts] != 0 { - if let requestGitPasswordCallback = requestGitPassword, - let requestedPassword = requestGitPasswordCallback("Please fill in the password of your Git account.") { + case let .http(userName, controller): + var newPassword = Utils.getPasswordFromKeychain(name: "gitPassword") + if newPassword == nil || attempts != 0 { + if let requestedPassword = self.requestGitPassword(controller, lastPassword) { newPassword = requestedPassword + Utils.addPasswordToKeychain(name: "gitPassword", password: newPassword) } else { return nil - } } - Defaults[.gitPasswordAttempts] += 1 - credential = try? GTCredential(userName: userName, password: newPassword) - case let .ssh(userName, password, publicKeyFile, privateKeyFile, requestSSHKeyPassword): - var newPassword = password - if Defaults[.gitPasswordAttempts] != 0 { - if let requestSSHKeyPasswordCallback = requestSSHKeyPassword, - let requestedPassword = requestSSHKeyPasswordCallback("Please fill in the password of your SSH key.") { + attempts += 1 + lastPassword = newPassword + credential = try? GTCredential(userName: userName, password: newPassword!) + case let .ssh(userName, publicKeyFile, privateKeyFile, controller): + var newPassword = Utils.getPasswordFromKeychain(name: "gitSSHKeyPassphrase") + if newPassword == nil { + if let requestedPassword = self.requestGitPassword(controller, nil) { newPassword = requestedPassword + Utils.addPasswordToKeychain(name: "gitSSHKeyPassphrase", password: newPassword) } else { return nil - } } - Defaults[.gitPasswordAttempts] += 1 - credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword) + credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword!) } return credential } } + + func delete() { + switch credential { + case .http: + Utils.removeKeychain(name: "gitPassword") + case .ssh: + Utils.removeKeychain(name: "gitSSHKeyPassphrase") + } + } + + private func requestGitPassword(_ controller: UIViewController, _ lastPassword: String?) -> String? { + let sem = DispatchSemaphore(value: 0) + var password: String? + var message = "" + switch credential { + case .http: + message = "Please fill in the password of your Git account." + case .ssh: + message = "Please fill in the password of your SSH key." + } + + DispatchQueue.main.async { + SVProgressHUD.dismiss() + let alert = UIAlertController(title: "Password", message: message, preferredStyle: UIAlertControllerStyle.alert) + alert.addTextField(configurationHandler: {(textField: UITextField!) in + textField.text = lastPassword ?? "" + textField.isSecureTextEntry = true + }) + alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in + password = alert.textFields!.first!.text + sem.signal() + })) + alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in + password = nil + sem.signal() + }) + controller.present(alert, animated: true, completion: nil) + } + + let _ = sem.wait(timeout: .distantFuture) + return password + } } class PasswordStore { @@ -69,7 +110,6 @@ class PasswordStore { let tempStoreURL = URL(fileURLWithPath: "\(Globals.repositoryPath)-temp") var storeRepository: GTRepository? - var gitCredential: GitCredential? var pgpKeyID: String? var publicKey: PGPKey? { didSet { @@ -100,6 +140,7 @@ class PasswordStore { return Utils.getPasswordFromKeychain(name: "pgpKeyPassphrase") } } + var gitPassword: String? { set { Utils.addPasswordToKeychain(name: "gitPassword", password: newValue) @@ -114,7 +155,7 @@ class PasswordStore { Utils.addPasswordToKeychain(name: "gitSSHPrivateKeyPassphrase", password: newValue) } get { - return Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") ?? "" + return Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") } } @@ -147,32 +188,12 @@ class PasswordStore { print(error) } initPGPKeys() - initGitCredential() } enum SSHKeyType { case `public`, secret } - public func initGitCredential() { - if Defaults[.gitAuthenticationMethod] == "Password" { - let httpCredential = GitCredential.Credential.http(userName: Defaults[.gitUsername] ?? "", password: Utils.getPasswordFromKeychain(name: "gitPassword") ?? "", requestGitPassword: nil) - gitCredential = GitCredential(credential: httpCredential) - } else if Defaults[.gitAuthenticationMethod] == "SSH Key"{ - gitCredential = GitCredential( - credential: GitCredential.Credential.ssh( - userName: Defaults[.gitUsername] ?? "", - password: gitSSHPrivateKeyPassphrase ?? "", - publicKeyFile: Globals.gitSSHPublicKeyURL, - privateKeyFile: Globals.gitSSHPrivateKeyURL, - requestSSHKeyPassword: nil - ) - ) - } else { - gitCredential = nil - } - } - public func initGitSSHKey(with armorKey: String, _ keyType: SSHKeyType) throws { var keyPath = "" switch keyType { @@ -304,43 +325,47 @@ class PasswordStore { checkoutProgressBlock: @escaping (String?, UInt, UInt) -> Void) throws { Utils.removeFileIfExists(at: storeURL) Utils.removeFileIfExists(at: tempStoreURL) - - let credentialProvider = try credential.credentialProvider() - let options: [String: Any] = [ - GTRepositoryCloneOptionsCredentialProvider: credentialProvider, - ] - storeRepository = try GTRepository.clone(from: remoteRepoURL, toWorkingDirectory: tempStoreURL, options: options, transferProgressBlock:transferProgressBlock) - let fm = FileManager.default do { + let credentialProvider = try credential.credentialProvider() + let options: [String: Any] = [ + GTRepositoryCloneOptionsCredentialProvider: credentialProvider, + ] + storeRepository = try GTRepository.clone(from: remoteRepoURL, toWorkingDirectory: tempStoreURL, options: options, transferProgressBlock:transferProgressBlock) + let fm = FileManager.default if fm.fileExists(atPath: storeURL.path) { try fm.removeItem(at: storeURL) } try fm.copyItem(at: tempStoreURL, to: storeURL) try fm.removeItem(at: tempStoreURL) + storeRepository = try GTRepository(url: storeURL) } catch { - print(error) + credential.delete() + throw(error) } - storeRepository = try GTRepository(url: storeURL) - gitCredential = credential - Defaults[.lastSyncedTime] = Date() DispatchQueue.main.async { + Defaults[.lastSyncedTime] = Date() self.updatePasswordEntityCoreData() NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil) } } - func pullRepository(transferProgressBlock: @escaping (UnsafePointer, UnsafeMutablePointer) -> Void) throws { - if gitCredential == nil { + func pullRepository(credential: GitCredential, transferProgressBlock: @escaping (UnsafePointer, UnsafeMutablePointer) -> Void) throws { + if storeRepository == nil { throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Git Repository is not set."]) } - let credentialProvider = try gitCredential!.credentialProvider() - let options: [String: Any] = [ - GTRepositoryRemoteOptionsCredentialProvider: credentialProvider - ] - let remote = try GTRemote(name: "origin", in: storeRepository!) - try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock) - Defaults[.lastSyncedTime] = Date() + do { + let credentialProvider = try credential.credentialProvider() + let options: [String: Any] = [ + GTRepositoryRemoteOptionsCredentialProvider: credentialProvider + ] + let remote = try GTRemote(name: "origin", in: storeRepository!) + try storeRepository!.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock) + } catch { + credential.delete() + throw(error) + } DispatchQueue.main.async { + Defaults[.lastSyncedTime] = Date() self.setAllSynced() self.updatePasswordEntityCoreData() NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil) @@ -583,14 +608,19 @@ class PasswordStore { return nil } - func pushRepository(transferProgressBlock: @escaping (UInt32, UInt32, Int, UnsafeMutablePointer) -> Void) throws { - let credentialProvider = try gitCredential!.credentialProvider() - let options: [String: Any] = [ - GTRepositoryRemoteOptionsCredentialProvider: credentialProvider, - ] - let masterBranch = getLocalBranch(withName: "master")! - let remote = try GTRemote(name: "origin", in: storeRepository!) - try storeRepository?.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock) + func pushRepository(credential: GitCredential, transferProgressBlock: @escaping (UInt32, UInt32, Int, UnsafeMutablePointer) -> Void) throws { + do { + let credentialProvider = try credential.credentialProvider() + let options: [String: Any] = [ + GTRepositoryRemoteOptionsCredentialProvider: credentialProvider, + ] + let masterBranch = getLocalBranch(withName: "master")! + let remote = try GTRemote(name: "origin", in: storeRepository!) + try storeRepository?.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock) + } catch { + credential.delete() + throw(error) + } } private func addPasswordEntities(password: Password) throws -> PasswordEntity? {