From cca40de70648a2c847b85a0b288d8eabc29623a5 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Sat, 5 Jun 2021 13:39:46 +0200 Subject: [PATCH] Bump dart-git Since dart-git's API has completely changed, this is a huge change. And it's now obvious where all the code can fail. This needs a massive re-write. --- lib/core/git_repo.dart | 41 ++++++++++++++++--------------- lib/repository.dart | 55 ++++++++++++++++++++++++------------------ lib/setup/clone.dart | 51 ++++++++++++++++++++++++--------------- lib/setup/screens.dart | 4 +-- pubspec.lock | 9 ++++++- pubspec.yaml | 2 +- 6 files changed, 95 insertions(+), 67 deletions(-) diff --git a/lib/core/git_repo.dart b/lib/core/git_repo.dart index 2d426606..6204aed6 100644 --- a/lib/core/git_repo.dart +++ b/lib/core/git_repo.dart @@ -40,8 +40,8 @@ class GitNoteRepository { Future _add(String pathSpec) async { if (useDartGit) { - var repo = await git.GitRepository.load(gitDirPath); - await repo.add(pathSpec); + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); + await repo.add(pathSpec).throwOnError(); } else { await _gitRepo.add(pathSpec); } @@ -49,8 +49,8 @@ class GitNoteRepository { Future _rm(String pathSpec) async { if (useDartGit) { - var repo = await git.GitRepository.load(gitDirPath); - await repo.rm(pathSpec); + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); + await repo.rm(pathSpec).throwOnError(); } else { await _gitRepo.rm(pathSpec); } @@ -61,9 +61,9 @@ class GitNoteRepository { required String authorEmail, required String authorName}) async { if (useDartGit) { - var repo = await git.GitRepository.load(gitDirPath); + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); var author = git.GitAuthor(name: authorName, email: authorEmail); - await repo.commit(message: message, author: author); + await repo.commit(message: message, author: author).throwOnError(); } else { await _gitRepo.commit( message: message, @@ -222,11 +222,9 @@ class GitNoteRepository { } Future merge() async { - var repo = await git.GitRepository.load(gitDirPath); - var branch = await repo.currentBranch(); - if (branch == null) { - throw Exception('No current branch found'); - } + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); + var branch = await repo.currentBranch().getOrThrow(); + var branchConfig = repo.config.branch(branch); if (branchConfig == null) { logExceptionWarning( @@ -234,13 +232,13 @@ class GitNoteRepository { return; } - var remoteRef = await repo.remoteBranch( + var result = await repo.remoteBranch( branchConfig.remote!, branchConfig.trackingBranch()!, ); - if (remoteRef == null) { - Log.i('Remote has no refs'); - return; + if (result.isFailure) { + Log.e("Failed to get remote refs", + ex: result.error, stacktrace: result.stackTrace); } try { @@ -257,11 +255,14 @@ class GitNoteRepository { Future push() async { // Only push if we have something we need to push try { - var repo = await git.GitRepository.load(gitDirPath); - if ((await repo.canPush()) == false) { + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); + var canPush = await repo.canPush().getOrThrow(); + if (!canPush) { return; } - } catch (_) {} + } catch (ex, st) { + Log.e("Can Push", ex: ex, stacktrace: st); + } try { await _gitRepo.push( @@ -283,8 +284,8 @@ class GitNoteRepository { Future numChanges() async { try { - var repo = await git.GitRepository.load(gitDirPath); - var n = await repo.numChangesToPush(); + var repo = await git.GitRepository.load(gitDirPath).getOrThrow(); + var n = await repo.numChangesToPush().getOrThrow(); return n; } catch (ex, st) { Log.e("numChanges", ex: ex, stacktrace: st); diff --git a/lib/repository.dart b/lib/repository.dart index 9d3cd77e..ebfa8bf4 100644 --- a/lib/repository.dart +++ b/lib/repository.dart @@ -23,7 +23,6 @@ import 'package:gitjournal/error_reporting.dart'; import 'package:gitjournal/features.dart'; import 'package:gitjournal/settings/settings.dart'; import 'package:gitjournal/settings/settings_migrations.dart'; -import 'package:gitjournal/setup/clone.dart'; import 'package:gitjournal/utils/logger.dart'; enum SyncStatus { @@ -96,19 +95,20 @@ class GitJournalRepo with ChangeNotifier { // has disappeared? } - var repo = await GitRepository.load(repoPath); + var repo = await GitRepository.load(repoPath).getOrThrow(); var remoteConfigured = repo.config.remotes.isNotEmpty; + /* if (remoteConfigured) { // Code path for 'branch is null' exception - var branch = await repo.currentBranch(); - var head = await repo.head(); + var branchR = await repo.currentBranch(); + var headR = await repo.head(); BranchConfig? branchConfig; if (branch != null) { branchConfig = repo.config.branch(branch); } - if (branch == null || head == null || branchConfig == null) { + if (branchR.isFailure || headR.isFailure || branchConfig == null) { var remoteConfig = repo.config.remotes[0]; await cloneRemote( repoPath: repoPath, @@ -122,6 +122,7 @@ class GitJournalRepo with ChangeNotifier { ); } } + */ return GitJournalRepo._internal( repoPath: repoPath, @@ -130,7 +131,7 @@ class GitJournalRepo with ChangeNotifier { remoteGitRepoConfigured: remoteConfigured, settings: settings, id: id, - currentBranch: await repo.currentBranch(), + currentBranch: await repo.currentBranch().getOrThrow(), ); } @@ -485,22 +486,22 @@ class GitJournalRepo with ChangeNotifier { } Future discardChanges(Note note) async { - var repo = await GitRepository.load(repoPath); - await repo.checkout(note.filePath); + var repo = await GitRepository.load(repoPath).getOrThrow(); + await repo.checkout(note.filePath).throwOnError(); await note.load(); } Future> remoteConfigs() async { - var repo = await GitRepository.load(repoPath); + var repo = await GitRepository.load(repoPath).getOrThrow(); return repo.config.remotes; } Future> branches() async { - var repo = await GitRepository.load(repoPath); - var branches = Set.from(await repo.branches()); + var repo = await GitRepository.load(repoPath).getOrThrow(); + var branches = Set.from(await repo.branches().getOrThrow()); if (repo.config.remotes.isNotEmpty) { var remoteName = repo.config.remotes.first.name; - var remoteBranches = await repo.remoteBranches(remoteName); + var remoteBranches = await repo.remoteBranches(remoteName).getOrThrow(); branches.addAll(remoteBranches.map((e) { return e.name.branchName()!; })); @@ -512,15 +513,19 @@ class GitJournalRepo with ChangeNotifier { Future checkoutBranch(String branchName) async { Log.i("Changing branch to $branchName"); - var repo = await GitRepository.load(repoPath); + var repo = await GitRepository.load(repoPath).getOrThrow(); - var created = await createBranchIfRequired(repo, branchName); - if (created.isEmpty) { - return ""; + try { + var created = await createBranchIfRequired(repo, branchName); + if (created.isEmpty) { + return ""; + } + } catch (ex, st) { + Log.e("createBranch", ex: ex, stacktrace: st); } try { - await repo.checkoutBranch(branchName); + await repo.checkoutBranch(branchName).getOrThrow(); _currentBranch = branchName; print("Done checking out $branchName"); @@ -537,8 +542,10 @@ class GitJournalRepo with ChangeNotifier { return branchName; } + // FIXME: Why does this need to return a string? + /// throws exceptions Future createBranchIfRequired(GitRepository repo, String name) async { - var localBranches = await repo.branches(); + var localBranches = await repo.branches().getOrThrow(); if (localBranches.contains(name)) { return name; } @@ -547,15 +554,17 @@ class GitJournalRepo with ChangeNotifier { return ""; } var remoteConfig = repo.config.remotes.first; - var remoteBranches = await repo.remoteBranches(remoteConfig.name); - var remoteBranchRef = - remoteBranches.firstWhereOrNull((ref) => ref.name.branchName() == name); + var remoteBranches = + await repo.remoteBranches(remoteConfig.name).getOrThrow(); + var remoteBranchRef = remoteBranches.firstWhereOrNull( + (ref) => ref.name.branchName() == name, + ); if (remoteBranchRef == null) { return ""; } - await repo.createBranch(name, hash: remoteBranchRef.hash); - await repo.setBranchUpstreamTo(name, remoteConfig, name); + await repo.createBranch(name, hash: remoteBranchRef.hash).throwOnError(); + await repo.setBranchUpstreamTo(name, remoteConfig, name).throwOnError(); Log.i("Created branch $name"); return name; diff --git a/lib/setup/clone.dart b/lib/setup/clone.dart index 584c5ec6..23aec6bc 100644 --- a/lib/setup/clone.dart +++ b/lib/setup/clone.dart @@ -1,10 +1,11 @@ import 'package:dart_git/dart_git.dart'; +import 'package:dart_git/exceptions.dart'; import 'package:git_bindings/git_bindings.dart' as git_bindings; import 'package:path/path.dart' as p; import 'package:gitjournal/utils/logger.dart'; -Future cloneRemote({ +Future> cloneRemote({ required String repoPath, required String cloneUrl, required String remoteName, @@ -14,9 +15,8 @@ Future cloneRemote({ required String authorName, required String authorEmail, }) async { - var repo = await GitRepository.load(repoPath); - - var remote = await repo.addOrUpdateRemote(remoteName, cloneUrl); + var repo = await GitRepository.load(repoPath).getOrThrow(); + var remote = await repo.addOrUpdateRemote(remoteName, cloneUrl).getOrThrow(); var _gitRepo = git_bindings.GitRepo(folderPath: repoPath); await _gitRepo.fetch( @@ -36,18 +36,25 @@ Future cloneRemote({ ); Log.i("Using remote branch: $remoteBranchName"); - var branches = await repo.branches(); + var branches = await repo.branches().getOrThrow(); if (branches.isEmpty) { Log.i("Completing - no local branch"); - var remoteBranch = await repo.remoteBranch(remoteName, remoteBranchName!); + var remoteBranchR = await repo.remoteBranch(remoteName, remoteBranchName); + if (remoteBranchR.isFailure) { + if (remoteBranchR.error is! GitNotFound) { + return fail(remoteBranchR); + } - // FIXME: This logic doesn't seem right. What if the remoteBranchName is empty - if (/*remoteBranchName != null &&*/ - remoteBranchName.isNotEmpty && remoteBranch != null) { + // remoteBranch doesn't exist - do nothing? Are you sure? + } else { + // remote branch exists + var remoteBranch = remoteBranchR.getOrThrow(); await repo.createBranch(remoteBranchName, hash: remoteBranch.hash); await repo.checkoutBranch(remoteBranchName); } - await repo.setUpstreamTo(remote, remoteBranchName); + + // FIXME: This will fail if the currentBranch doesn't exist!! + await repo.setUpstreamTo(remote, remoteBranchName).getOrThrow(); } else { Log.i("Local branches $branches"); var branch = branches[0]; @@ -55,7 +62,7 @@ Future cloneRemote({ if (branch == remoteBranchName) { Log.i("Completing - localBranch: $branch"); - var currentBranch = await repo.currentBranch(); + var currentBranch = await repo.currentBranch().getOrThrow(); if (currentBranch != branch) { // Shit happens sometimes // There is only one local branch, and that branch is not the current @@ -63,9 +70,9 @@ Future cloneRemote({ await repo.checkoutBranch(branch); } - await repo.setUpstreamTo(remote, remoteBranchName!); - var remoteBranch = await repo.remoteBranch(remoteName, remoteBranchName); - if (remoteBranch != null) { + await repo.setUpstreamTo(remote, remoteBranchName).getOrThrow(); + var remoteBranchR = await repo.remoteBranch(remoteName, remoteBranchName); + if (remoteBranchR.isSuccess) { Log.i("Merging '$remoteName/$remoteBranchName'"); await _gitRepo.merge( branch: '$remoteName/$remoteBranchName', @@ -75,11 +82,11 @@ Future cloneRemote({ } } else { Log.i("Completing - localBranch diff remote: $branch $remoteBranchName"); - await repo.createBranch(remoteBranchName!); - await repo.checkoutBranch(remoteBranchName); + await repo.createBranch(remoteBranchName).getOrThrow(); + await repo.checkoutBranch(remoteBranchName).getOrThrow(); - await repo.deleteBranch(branch); - await repo.setUpstreamTo(remote, remoteBranchName); + await repo.deleteBranch(branch).getOrThrow(); + await repo.setUpstreamTo(remote, remoteBranchName).getOrThrow(); Log.i("Merging '$remoteName/$remoteBranchName'"); await _gitRepo.merge( @@ -97,9 +104,11 @@ Future cloneRemote({ // https://sentry.io/organizations/gitjournal/issues/2254310735/?project=5168082&query=is%3Aunresolved // await repo.checkout("."); + + return Result(null); } -Future _remoteDefaultBranch({ +Future _remoteDefaultBranch({ required GitRepository repo, required git_bindings.GitRepo libGit2Repo, required String remoteName, @@ -126,7 +135,7 @@ Future _remoteDefaultBranch({ if (remoteBranch == null) { return 'master'; } - return remoteBranch.target!.branchName(); + return remoteBranch.target!.branchName()!; } String folderNameFromCloneUrl(String cloneUrl) { @@ -143,3 +152,5 @@ String folderNameFromCloneUrl(String cloneUrl) { // * Existing Repo (master default), No Local Changes // * Existing Repo (master default), Local changes in 'master' branch // * Existing Repo (main default), Local changes in 'master' branch + +// GIT_SSH_COMMAND='ssh -i private_key_file -o IdentitiesOnly=yes' git clone user@host:repo.git diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index f816929e..1a05660e 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -436,8 +436,8 @@ class GitHostSetupScreenState extends State { if (!await GitRepository.isValidRepo(repoPath)) { await GitRepository.init(repoPath); } - var repo = await GitRepository.load(repoPath); - await repo.removeRemote(widget.remoteName); + var repo = await GitRepository.load(repoPath).getOrThrow(); + await repo.removeRemote(widget.remoteName).throwOnError(); } on Exception catch (e, stacktrace) { Log.e("Failed to remove remote", ex: e, stacktrace: stacktrace); logExceptionWarning(e, stacktrace); diff --git a/pubspec.lock b/pubspec.lock index c3347cb8..0ec59771 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -272,7 +272,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: "51e16c02aba0628211ee29b42a5d45b3a7d596df" + resolved-ref: "445f7a3fcb0c06cf957f3f300a5930a61f7611cb" url: "https://github.com/GitJournal/dart-git.git" source: git version: "0.0.2" @@ -304,6 +304,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + diff_match_patch: + dependency: transitive + description: + name: diff_match_patch + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1" dots_indicator: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 3f313e4a..1d58e0d2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: sdk: flutter dart_git: git: https://github.com/GitJournal/dart-git.git - #path: /Users/vishesh/src/gitjournal/dart-git + # path: /Users/vishesh/src/gitjournal/dart-git git_bindings: #path: /Users/vishesh/src/gitjournal/git_bindings git: https://github.com/GitJournal/git_bindings.git