Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/deploying.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ jobs:
with:
path: go
key: ${{ runner.os }}-gopenpgp-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/gopenpgp_build.sh') }}
- uses: actions/cache@v4
id: libgit2-cache
with:
path: libgit2/dist
key: ${{ runner.os }}-libgit2-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/libgit2_build.sh') }}
- name: Bundle Install
run: |
bundle config path vendor/bundle
Expand All @@ -39,8 +44,18 @@ jobs:
run: |
export PATH="/usr/local/opt/go/bin:$PATH"
./scripts/gopenpgp_build.sh
- name: libgit2
if: ${{ steps.libgit2-cache.outputs.cache-hit == false }}
run: ./scripts/libgit2_build.sh
- name: Start git servers
run: |
./scripts/git_servers.sh start
cat .git-servers/env >> "$GITHUB_ENV"
- name: Test
run: bundle exec fastlane test
- name: Stop git servers
if: always()
run: ./scripts/git_servers.sh stop
- name: Deploy
run: bundle exec fastlane ${{ matrix.channel }}
env:
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,27 @@ jobs:
with:
path: go
key: ${{ runner.os }}-gopenpgp-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/gopenpgp_build.sh') }}
- uses: actions/cache@v4
id: libgit2-cache
with:
path: libgit2/dist
key: ${{ runner.os }}-libgit2-${{ secrets.CACHE_VERSION }}-${{ hashFiles('**/libgit2_build.sh') }}
- name: Bundle Install
run: |
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
- name: GopenPGP
if: ${{ steps.gopenpgp-cache.outputs.cache-hit == false }}
run: ./scripts/gopenpgp_build.sh
- name: libgit2
if: ${{ steps.libgit2-cache.outputs.cache-hit == false }}
run: ./scripts/libgit2_build.sh
- name: Start git servers
run: |
./scripts/git_servers.sh start
cat .git-servers/env >> "$GITHUB_ENV"
- name: Testing
run: bundle exec fastlane test
- name: Stop git servers
if: always()
run: ./scripts/git_servers.sh stop
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Podfile.lock

# Go Mobile Build results and dependency sources
go/
libgit2/

# fastlane
#
Expand All @@ -67,3 +68,6 @@ fastlane/test_output
#
# The Continuous Integration environment will create this file. It avoids specific "Run Script" phases while building.
.ci-env

# Local git servers for the transport tests
.git-servers/
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,25 @@ For more, please read the [wiki page](https://github.com/mssun/passforios/wiki).

## Building Pass for iOS

1. Install Go: `brew install go`.
1. Install Go and CMake: `brew install go cmake`.
1. Run `./scripts/gopenpgp_build.sh` to build GopenPGP.
1. Run `./scripts/libgit2_build.sh` to build libgit2. This also builds libssh2
and OpenSSL and takes a while, but only has to be done once.
1. Open the `pass.xcodeproj` file in Xcode.
1. Build & Run.

## Running the tests

The tests of the SSH and HTTPS transports need local git servers. Without them
those tests are skipped and everything else still runs.

```sh
./scripts/git_servers.sh start
set -a; source .git-servers/env; set +a
bundle exec fastlane test
./scripts/git_servers.sh stop
```

## License

MIT
11 changes: 10 additions & 1 deletion fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ default_platform :ios
lane :prepare do
carthage(cache_builds: true, platform: "iOS")
sh "./scripts/gopenpgp_build.sh"
sh "./scripts/libgit2_build.sh"
end

lane :reset_build_number do
Expand Down Expand Up @@ -63,7 +64,15 @@ end
platform :ios do
desc "Runs all tests"
lane :test do
run_tests(scheme: "pass")
# scripts/git_servers.sh trusts its certificate authority on one simulator
# and records which, because a device name can match several runtimes and
# the tests would otherwise run on one that never saw the certificate.
udid = ENV["GIT_SERVERS_DEVICE_UDID"]
if udid
run_tests(scheme: "pass", destination: "platform=iOS Simulator,id=#{udid}")
else
run_tests(scheme: "pass")
end
end

desc "Submit a new Beta Build to Apple TestFlight"
Expand Down
53 changes: 36 additions & 17 deletions pass.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pass/Controllers/AdvancedSettingsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class AdvancedSettingsTableViewController: UITableViewController {
}

private func setGitSignatureText() {
let gitSignatureName = passwordStore.gitSignatureForNow?.name ?? ""
let gitSignatureEmail = passwordStore.gitSignatureForNow?.email ?? ""
let gitSignatureName = passwordStore.gitSignatureForNow.name
let gitSignatureEmail = passwordStore.gitSignatureForNow.email
gitSignatureTableViewCell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
gitSignatureTableViewCell.detailTextLabel?.text = "\(gitSignatureName) <\(gitSignatureEmail)>"
if Defaults.gitSignatureName == nil, Defaults.gitSignatureEmail == nil {
Expand Down
7 changes: 3 additions & 4 deletions pass/Controllers/CommitLogsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
// Copyright © 2017 Bob Sun. All rights reserved.
//

import ObjectiveGit
import passKit
import UIKit

class CommitLogsTableViewController: UITableViewController {
var commits: [GTCommit] = []
var commits: [GitCommit] = []
let passwordStore = PasswordStore.shared

override func viewDidLoad() {
Expand All @@ -31,7 +30,7 @@ class CommitLogsTableViewController: UITableViewController {
let formatter = DateFormatter()
formatter.dateStyle = DateFormatter.Style.medium
formatter.timeStyle = .medium
let dateString = formatter.string(from: commits[indexPath.row].commitDate)
let dateString = formatter.string(from: commits[indexPath.row].date)

let author = cell.contentView.viewWithTag(200) as? UILabel
let dateLabel = cell.contentView.viewWithTag(201) as? UILabel
Expand All @@ -48,7 +47,7 @@ class CommitLogsTableViewController: UITableViewController {
tableView.reloadData()
}

private func getCommitLogs() -> [GTCommit] {
private func getCommitLogs() -> [GitCommit] {
do {
return try passwordStore.getRecentCommits(count: 20)
} catch {
Expand Down
8 changes: 4 additions & 4 deletions pass/Controllers/GitConfigSettingsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ class GitConfigSettingsTableViewController: UITableViewController {
tableView.rowHeight = UITableView.automaticDimension

let signature = passwordStore.gitSignatureForNow
nameTextField.placeholder = signature?.name ?? ""
emailTextField.placeholder = signature?.email ?? ""
nameTextField.placeholder = signature.name
emailTextField.placeholder = signature.email
nameTextField.text = Defaults.gitSignatureName
emailTextField.text = Defaults.gitSignatureEmail
}

override func shouldPerformSegue(withIdentifier identifier: String, sender _: Any?) -> Bool {
if identifier == "saveGitConfigSettingSegue" {
let name = nameTextField.text!.isEmpty ? Globals.gitSignatureDefaultName : nameTextField.text!
let email = emailTextField.text!.isEmpty ? Globals.gitSignatureDefaultEmail : nameTextField.text!
guard GTSignature(name: name, email: email, time: nil) != nil else {
let email = emailTextField.text!.isEmpty ? Globals.gitSignatureDefaultEmail : emailTextField.text!
guard GitSignature(name: name, email: email).isValid else {
Utils.alert(title: "Error".localize(), message: "InvalidNameOrEmail".localize(), controller: self, completion: nil)
return false
}
Expand Down
11 changes: 4 additions & 7 deletions pass/Controllers/GitRepositorySettingsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,12 @@ class GitRepositorySettingsTableViewController: UITableViewController, PasswordA
// swiftlint:disable:next closure_body_length
DispatchQueue.global(qos: .userInitiated).async {
do {
let transferProgressBlock: (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void = { git_transfer_progress, _ in
let gitTransferProgress = git_transfer_progress.pointee
let progress = Float(gitTransferProgress.received_objects) / Float(gitTransferProgress.total_objects)
SVProgressHUD.showProgress(progress, status: "Cloning Remote Repository")
let transferProgressBlock: TransferProgressHandler = { progress, _ in
SVProgressHUD.showProgress(progress.fractionCompleted, status: "Cloning Remote Repository")
}

let checkoutProgressBlock: (String, UInt, UInt) -> Void = { _, completedSteps, totalSteps in
let progress = Float(completedSteps) / Float(totalSteps)
SVProgressHUD.showProgress(progress, status: "CheckingOutBranch".localize(self.gitBranchName))
let checkoutProgressBlock: CheckoutProgressHandler = { progress in
SVProgressHUD.showProgress(progress.fractionCompleted, status: "CheckingOutBranch".localize(self.gitBranchName))
}

let options = self.gitCredential.getCredentialOptions(passwordProvider: self.present)
Expand Down
16 changes: 13 additions & 3 deletions pass/Controllers/OpenSourceComponentsTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ class OpenSourceComponentsTableViewController: BasicStaticTableViewController {
"https://github.com/kishikawakatsumi/KeychainAccess/blob/master/LICENSE",
],
[
"ObjectiveGit",
"https://github.com/libgit2/objective-git",
"https://github.com/libgit2/objective-git/blob/master/LICENSE",
"libgit2",
"https://libgit2.org",
"https://github.com/libgit2/libgit2/blob/main/COPYING",
],
[
"libssh2",
"https://libssh2.org",
"https://github.com/libssh2/libssh2/blob/master/COPYING",
],
[
"ObjectivePGP",
Expand All @@ -41,6 +46,11 @@ class OpenSourceComponentsTableViewController: BasicStaticTableViewController {
"https://github.com/mattrubin/OneTimePassword",
"https://github.com/mattrubin/OneTimePassword/blob/develop/LICENSE.md",
],
[
"OpenSSL",
"https://www.openssl.org",
"https://github.com/openssl/openssl/blob/master/LICENSE.txt",
],
[
"SVProgressHUD",
"https://github.com/SVProgressHUD/SVProgressHUD",
Expand Down
30 changes: 15 additions & 15 deletions pass/Controllers/PasswordNavigationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -510,16 +510,16 @@ extension PasswordNavigationViewController: PasswordAlertPresenter {
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
do {
let pullOptions = gitCredential.getCredentialOptions(passwordProvider: present)
try PasswordStore.shared.pullRepository(options: pullOptions) { git_transfer_progress, _ in
try PasswordStore.shared.pullRepository(options: pullOptions) { progress, _ in
DispatchQueue.main.async {
SVProgressHUD.showProgress(Float(git_transfer_progress.pointee.received_objects) / Float(git_transfer_progress.pointee.total_objects), status: "PullingFromRemoteRepository".localize())
SVProgressHUD.showProgress(progress.fractionCompleted, status: "PullingFromRemoteRepository".localize())
}
}
if PasswordStore.shared.numberOfLocalCommits > 0 {
let pushOptions = gitCredential.getCredentialOptions(passwordProvider: present)
try PasswordStore.shared.pushRepository(options: pushOptions) { current, total, _, _ in
try PasswordStore.shared.pushRepository(options: pushOptions) { progress, _ in
DispatchQueue.main.async {
SVProgressHUD.showProgress(Float(current) / Float(total), status: "PushingToRemoteRepository".localize())
SVProgressHUD.showProgress(progress.fractionCompleted, status: "PushingToRemoteRepository".localize())
}
}
}
Expand All @@ -528,20 +528,20 @@ extension PasswordNavigationViewController: PasswordAlertPresenter {
SVProgressHUD.showSuccess(withStatus: "Done".localize())
SVProgressHUD.dismiss(withDelay: 1)
}
} catch let error as NSError {
gitCredential.delete()
} catch {
// Only forget the stored password when it might be the reason for
// the failure. A refused push or a conflicting merge happens long
// after the remote has accepted the credential.
if error.mightBeAuthenticationFailure {
gitCredential.delete()
}
DispatchQueue.main.async {
SVProgressHUD.dismiss()
// libgit2 reports the message of the underlying library, so a
// wrong SSH passphrase is recognised by what libssh2 wrote.
var message = error.localizedDescription
if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? NSError {
message = message | "UnderlyingError".localize(underlyingError.localizedDescription)
if underlyingError.localizedDescription.contains("WrongPassphrase".localize()) {
message = message | "RecoverySuggestion.".localize()
}
}
if let mergeConflictFiles = error.userInfo[GTPullMergeConflictedFiles] as? NSArray {
let mergeConflictFilesString = mergeConflictFiles.componentsJoined(by: ", ")
message = message | "MergeConflictError".localize(mergeConflictFilesString)
if message.contains("WrongPassphrase".localize()) {
message = message | "RecoverySuggestion.".localize()
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(800)) {
Utils.alert(title: "Error".localize(), message: message, controller: self, completion: nil)
Expand Down
2 changes: 0 additions & 2 deletions pass/Helpers/Objective-CBridgingHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@
#ifndef Objective_CBridgingHeader_h
#define Objective_CBridgingHeader_h

@import ObjectiveGit;

#endif /* Objective_CBridgingHeader_h */
2 changes: 2 additions & 0 deletions pass/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
"SpecifyBranchName." = "Der Name des zu verwendenden Branches muss angegeben werden.";

// SSH
"AuthenticationRequired." = "Das entfernte Repository erfordert eine Authentifizierung.";
"AuthenticationCancelled." = "Die Authentifizierung wurde abgebrochen.";
"FillInSshKeyPassphrase." = "Bitte gib das Passwort des SSH-Schlüssels ein.";
"CannotSelectSshKey" = "SSH-Schlüssel kann nicht selektiert werden";
"PleaseSetupSshKeyFirst." = "Bitte richte erst den SSH-Schlüssel ein.";
Expand Down
2 changes: 2 additions & 0 deletions pass/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@
"SpecifyBranchName." = "Please specify the name of the branch to be used.";

// SSH
"AuthenticationRequired." = "The remote repository requires authentication.";
"AuthenticationCancelled." = "Authentication was cancelled.";
"FillInSshKeyPassphrase." = "Please fill in the passphrase of your SSH key.";
"CannotSelectSshKey" = "Cannot Select SSH Key";
"PleaseSetupSshKeyFirst." = "Please setup SSH key first.";
Expand Down
2 changes: 2 additions & 0 deletions pass/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
"SpecifyBranchName." = "Specificare il nome del branch da usare.";

// SSH
"AuthenticationRequired." = "Il repository remoto richiede l'autenticazione.";
"AuthenticationCancelled." = "Autenticazione annullata.";
"FillInSshKeyPassphrase." = "Inserire la password della chiave SSH.";
"CannotSelectSshKey" = "Impossibile selezionare la chiave SSH";
"PleaseSetupSshKeyFirst." = "Impostare la chiave SSH.";
Expand Down
Loading
Loading