From 4c7efdb2dc1b544fc30276cbe5b05d8f98942646 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Tue, 19 Jan 2021 14:05:51 +0100 Subject: [PATCH] Move cloning logic to its own file This has gotten very complex and needs to be properly tested. It's the number 1 bug. --- lib/core/git_repo.dart | 14 -------- lib/repository.dart | 48 ------------------------- lib/setup/clone.dart | 82 ++++++++++++++++++++++++++++++++++++++++++ lib/setup/screens.dart | 19 +++++----- pubspec.lock | 8 ++--- 5 files changed, 94 insertions(+), 77 deletions(-) create mode 100644 lib/setup/clone.dart diff --git a/lib/core/git_repo.dart b/lib/core/git_repo.dart index db5edfbf..def2eb51 100644 --- a/lib/core/git_repo.dart +++ b/lib/core/git_repo.dart @@ -241,20 +241,6 @@ class GitNoteRepository { } } - Future defaultBranch(String remoteName) async { - try { - return await _gitRepo.defaultBranch( - remote: remoteName, - publicKey: settings.sshPublicKey, - privateKey: settings.sshPrivateKey, - password: settings.sshPassword, - ); - } on GitException catch (ex, stackTrace) { - Log.e("GitDefaultBranch Failed", ex: ex, stacktrace: stackTrace); - rethrow; - } - } - Future numChanges() async { try { var repo = await git.GitRepository.load(gitDirPath); diff --git a/lib/repository.dart b/lib/repository.dart index d8f1e034..86c0efb3 100644 --- a/lib/repository.dart +++ b/lib/repository.dart @@ -403,54 +403,6 @@ class Repository with ChangeNotifier { _gitRepo = GitNoteRepository(gitDirPath: repoPath, settings: settings); - var repo = await GitRepository.load(repoPath); - var remote = repo.config.remote(remoteName); - var remoteBranchName = "master"; - try { - remoteBranchName = await _gitRepo.defaultBranch(remoteName); - } catch (ex) { - Log.w("Could not get git main branch - assuming master", ex: ex); - } - - var remoteBranch = await repo.remoteBranch(remoteName, remoteBranchName); - Log.i("Using remote branch: $remoteBranchName"); - - var branches = await repo.branches(); - if (branches.isEmpty) { - Log.i("Completing - no local branch"); - if (remoteBranchName != null && - remoteBranchName.isNotEmpty && - remoteBranch != null) { - await repo.checkoutBranch(remoteBranchName, remoteBranch.hash); - } - await repo.setUpstreamTo(remote, remoteBranchName); - } else { - var branch = branches[0]; - - if (branch == remoteBranchName) { - Log.i("Completing - localBranch: $branch"); - - await repo.setUpstreamTo(remote, remoteBranchName); - await _gitRepo.merge(); - } else { - Log.i( - "Completing - localBranch diff remote: $branch $remoteBranchName"); - - var headRef = await repo.resolveReference(await repo.head()); - await repo.checkoutBranch(remoteBranchName, headRef.hash); - await repo.deleteBranch(branch); - await repo.setUpstreamTo(remote, remoteBranchName); - await _gitRepo.merge(); - } - - // if more than one branch - // TODO: Check if one of the branches matches the remote branch name - // and use that - // if not, then just create a new branch with the remoteBranchName - // and merge .. - - } - await _addFileInRepo(repo: this, settings: settings); this.repoPath = repoPath; diff --git a/lib/setup/clone.dart b/lib/setup/clone.dart new file mode 100644 index 00000000..bbe2ce61 --- /dev/null +++ b/lib/setup/clone.dart @@ -0,0 +1,82 @@ +import 'package:dart_git/dart_git.dart'; +import 'package:git_bindings/git_bindings.dart' as git_bindings; +import 'package:meta/meta.dart'; + +import 'package:gitjournal/utils/logger.dart'; + +Future cloneRemote({ + @required String repoPath, + @required String cloneUrl, + @required String remoteName, + @required String sshPublicKey, + @required String sshPrivateKey, + @required String sshPassword, +}) async { + var repo = await GitRepository.load(repoPath); + + // FIXME: In the case of no remotes and no commits, revert to clone? + + var remote = await repo.addOrUpdateRemote(remoteName, cloneUrl); + + var _gitRepo = git_bindings.GitRepo(folderPath: repoPath); + await _gitRepo.fetch( + remote: remoteName, + publicKey: sshPublicKey, + privateKey: sshPrivateKey, + password: sshPassword, + ); + + var remoteBranchName = "master"; + try { + var branch = await _gitRepo.defaultBranch( + remote: remoteName, + publicKey: sshPublicKey, + privateKey: sshPrivateKey, + password: sshPassword, + ); + if (branch != null && branch.isNotEmpty) { + Log.i("Got default branch: $branch"); + remoteBranchName = branch; + } + } catch (ex) { + Log.w("Could not get git main branch - assuming master", ex: ex); + } + + var remoteBranch = await repo.remoteBranch(remoteName, remoteBranchName); + Log.i("Using remote branch: $remoteBranchName"); + + var branches = await repo.branches(); + if (branches.isEmpty) { + Log.i("Completing - no local branch"); + if (remoteBranchName != null && + remoteBranchName.isNotEmpty && + remoteBranch != null) { + await repo.checkoutBranch(remoteBranchName, remoteBranch.hash); + } + await repo.setUpstreamTo(remote, remoteBranchName); + } else { + var branch = branches[0]; + + if (branch == remoteBranchName) { + Log.i("Completing - localBranch: $branch"); + + await repo.setUpstreamTo(remote, remoteBranchName); + await _gitRepo.merge(); + } else { + Log.i("Completing - localBranch diff remote: $branch $remoteBranchName"); + + var headRef = await repo.resolveReference(await repo.head()); + await repo.checkoutBranch(remoteBranchName, headRef.hash); + await repo.deleteBranch(branch); + await repo.setUpstreamTo(remote, remoteBranchName); + await _gitRepo.merge(); + } + + // if more than one branch + // TODO: Check if one of the branches matches the remote branch name + // and use that + // if not, then just create a new branch with the remoteBranchName + // and merge .. + + } +} diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index de2f9663..af68e4e9 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -20,6 +20,7 @@ import 'package:gitjournal/repository.dart'; import 'package:gitjournal/settings.dart'; import 'package:gitjournal/setup/autoconfigure.dart'; import 'package:gitjournal/setup/button.dart'; +import 'package:gitjournal/setup/clone.dart'; import 'package:gitjournal/setup/clone_url.dart'; import 'package:gitjournal/setup/loading_error.dart'; import 'package:gitjournal/setup/repo_selector.dart'; @@ -525,18 +526,16 @@ class GitHostSetupScreenState extends State { String error; try { - var repo = await GitRepository.load(repoPath); - await repo.addOrUpdateRemote(widget.remoteName, _gitCloneUrl); - - var repoN = git_bindings.GitRepo(folderPath: repoPath); - await repoN.fetch( - remote: widget.remoteName, - publicKey: settings.sshPublicKey, - privateKey: settings.sshPrivateKey, - password: settings.sshPassword, + await cloneRemote( + cloneUrl: _gitCloneUrl, + remoteName: widget.remoteName, + repoPath: repoPath, + sshPassword: settings.sshPassword, + sshPrivateKey: settings.sshPrivateKey, + sshPublicKey: settings.sshPublicKey, ); } on Exception catch (e, stacktrace) { - Log.e("Failed to add remote", ex: e, stacktrace: stacktrace); + Log.e("Failed to clone", ex: e, stacktrace: stacktrace); error = e.toString(); } diff --git a/pubspec.lock b/pubspec.lock index 355f08a7..fb010a78 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -477,11 +477,9 @@ packages: git_bindings: dependency: "direct main" description: - path: "." - ref: HEAD - resolved-ref: "89c587037dd4d9d9270b09b51df40e537d7263c5" - url: "https://github.com/GitJournal/git_bindings.git" - source: git + path: "/Users/vishesh/src/gitjournal/git_bindings" + relative: false + source: path version: "0.0.18" git_url_parse2: dependency: "direct main"