From f9271edad3ebe6d03ae59c3414e7ccb36f5bd4ad Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Thu, 13 Jan 2022 18:14:01 +0100 Subject: [PATCH] Upgrade to latest dart-git Most of dart-git's operations are synchronous by default now. The async functions run on another isolate. --- lib/core/file/file_storage.dart | 121 +++++++++++++----- lib/core/file/file_storage_cache.dart | 6 +- lib/core/git_repo.dart | 17 ++- lib/history/commit_data_widget.dart | 13 +- lib/history/history_screen.dart | 17 ++- lib/repository.dart | 68 ++++------ lib/settings/settings.dart | 2 + lib/settings/settings_git_remote.dart | 2 +- lib/setup/clone.dart | 12 +- lib/setup/clone_git_exec.dart | 4 +- lib/setup/clone_libgit2.dart | 4 +- lib/setup/screens.dart | 14 +- lib/utils/git_desktop.dart | 8 +- pubspec.lock | 2 +- test/core/file/file_storage_cache_test.dart | 15 ++- .../flattened_filtered_notes_folder_test.dart | 4 +- test/flattened_notes_folder_large_test.dart | 8 +- test/flattened_notes_folder_test.dart | 4 +- test/link_resolver_test.dart | 4 +- test/note_storage_test.dart | 4 +- test_driver/main.dart | 2 +- 21 files changed, 197 insertions(+), 134 deletions(-) diff --git a/lib/core/file/file_storage.dart b/lib/core/file/file_storage.dart index 1dc85f7f..e069f611 100644 --- a/lib/core/file/file_storage.dart +++ b/lib/core/file/file_storage.dart @@ -4,15 +4,20 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import 'dart:isolate'; + import 'package:flutter/foundation.dart'; import 'package:dart_git/blob_ctime_builder.dart'; import 'package:dart_git/dart_git.dart'; +import 'package:dart_git/exceptions.dart'; import 'package:dart_git/file_mtime_builder.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; +import 'package:tuple/tuple.dart'; import 'package:universal_io/io.dart' as io; +import 'package:gitjournal/error_reporting.dart'; import 'package:gitjournal/logger/logger.dart'; import 'file.dart'; @@ -25,21 +30,7 @@ class FileStorage with ChangeNotifier { var _dateTime = DateTime.now(); DateTime get dateTime => _dateTime; - TreeEntryVisitor get visitor { - return MultiTreeEntryVisitor( - [ - blobCTimeBuilder, - fileMTimeBuilder, - ], - afterCommitCallback: (commit) { - var commitDt = commit.author.date; - if (commitDt.isBefore(_dateTime)) { - _dateTime = commitDt; - } - notifyListeners(); - }, - ); - } + var head = GitHash.zero(); FileStorage({ required String repoPath, @@ -96,20 +87,50 @@ class FileStorage with ChangeNotifier { )); } + Future fill() async { + var rp = ReceivePort(); + rp.listen((d) { + if (d is DateTime) { + _dateTime = d; + notifyListeners(); + } + }); + + var resp = await compute( + _fillFileStorage, + _FillFileStorageParams( + rp.sendPort, + repoPath, + blobCTimeBuilder, + fileMTimeBuilder, + ), + ); + rp.close(); + + // FIXME: Handle this case of having an error! + assert(resp != null); + if (resp == null) return; + + blobCTimeBuilder.update(resp.item1); + fileMTimeBuilder.update(resp.item2); + head = resp.item3; + notifyListeners(); + } + @visibleForTesting static Future fake(String rootFolder) async { assert(rootFolder.startsWith(p.separator)); - await GitRepository.init(rootFolder).throwOnError(); + GitRepository.init(rootFolder).throwOnError(); var blobVisitor = BlobCTimeBuilder(); var mTimeBuilder = FileMTimeBuilder(); - var repo = await GitRepository.load(rootFolder).getOrThrow(); - var result = await repo.headHash(); + var repo = GitRepository.load(rootFolder).getOrThrow(); + var result = repo.headHash(); if (result.isSuccess) { var multi = MultiTreeEntryVisitor([blobVisitor, mTimeBuilder]); - await repo + repo .visitTree(fromCommitHash: result.getOrThrow(), visitor: multi) .throwOnError(); } @@ -128,17 +149,7 @@ class FileStorage with ChangeNotifier { @visibleForTesting Future> reload() async { - var gitRepo = await GitRepository.load(repoPath).getOrThrow(); - var result = await gitRepo.headHash(); - if (result.isFailure) { - return fail(result); - } - var headHash = result.getOrThrow(); - - var multi = MultiTreeEntryVisitor([blobCTimeBuilder, fileMTimeBuilder]); - await gitRepo - .visitTree(fromCommitHash: headHash, visitor: multi) - .throwOnError(); + await fill(); return Result(null); } } @@ -147,3 +158,53 @@ class FileStorageCacheIncomplete implements Exception { final String path; FileStorageCacheIncomplete(this.path); } + +typedef _FillFileStorageParams + = Tuple4; + +typedef _FillFileStorageOutput + = Tuple3; + +_FillFileStorageOutput? _fillFileStorage(_FillFileStorageParams params) { + var sendPort = params.item1; + var repoPath = params.item2; + var blobCTimeBuilder = params.item3; + var fileMTimeBuilder = params.item4; + + var dateTime = DateTime.now(); + var visitor = MultiTreeEntryVisitor( + [blobCTimeBuilder, fileMTimeBuilder], + afterCommitCallback: (commit) { + var commitDt = commit.author.date; + if (commitDt.isBefore(dateTime)) { + dateTime = commitDt; + sendPort.send(dateTime); + } + }, + ); + + var gitRepo = GitRepository.load(repoPath).getOrThrow(); + var headR = gitRepo.headHash(); + if (headR.isFailure) { + if (headR.error is GitRefNotFound) { + // No commits + // fileStorageCacheReady = true; + // notifyListeners(); + // FIXME: Send a signal saying its done + return _FillFileStorageOutput( + blobCTimeBuilder, fileMTimeBuilder, GitHash.zero()); + } + Log.e("Failed to fetch HEAD", result: headR); + return null; + } + var head = headR.getOrThrow(); + Log.d("Got HEAD: $head"); + + var result = gitRepo.visitTree(fromCommitHash: head, visitor: visitor); + if (result.isFailure) { + Log.e("Failed to build FileStorage cache", result: result); + logException(result.exception!, result.stackTrace!); + } + + return _FillFileStorageOutput(blobCTimeBuilder, fileMTimeBuilder, head); +} diff --git a/lib/core/file/file_storage_cache.dart b/lib/core/file/file_storage_cache.dart index 810baeca..e07a4326 100644 --- a/lib/core/file/file_storage_cache.dart +++ b/lib/core/file/file_storage_cache.dart @@ -66,9 +66,7 @@ class FileStorageCache { Future> save(FileStorage fileStorage) async { return catchAll(() async { - var repo = await GitRepository.load(fileStorage.repoPath).getOrThrow(); - var headR = await repo.headHash(); - lastProcessedHead = headR.isFailure ? GitHash.zero() : headR.getOrThrow(); + lastProcessedHead = fileStorage.head; var blobCTimeBuilder = fileStorage.blobCTimeBuilder; var fileMTimeBUilder = fileStorage.fileMTimeBuilder; @@ -83,7 +81,7 @@ class FileStorageCache { } String get _cTimeFilePath => p.join(cacheFolderPath, 'blob_ctime_v1'); - String get _mTimeFilePath => p.join(cacheFolderPath, 'file_mtime_v1'); + String get _mTimeFilePath => p.join(cacheFolderPath, 'file_mtime_v2'); Future> _buildCTimeBuilder() async { var file = io.File(_cTimeFilePath); diff --git a/lib/core/git_repo.dart b/lib/core/git_repo.dart index 6316f2ab..5ace7e9c 100644 --- a/lib/core/git_repo.dart +++ b/lib/core/git_repo.dart @@ -24,6 +24,9 @@ import 'package:gitjournal/utils/git_desktop.dart'; bool useDartGit = false; +// FIXME: Remember to close all the opened repos!! +// FIXME: Micro optimization? Avoid re-creating the GitAsyncRepository! + class GitNoteRepository { final String gitRepoPath; final gb.GitRepo _gitRepo; @@ -43,7 +46,7 @@ class GitNoteRepository { Future> _add(String pathSpec) async { if (useDartGit || AppConfig.instance.experimentalGitOps) { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); await repo.add(pathSpec).throwOnError(); return Result(null); } else { @@ -59,7 +62,7 @@ class GitNoteRepository { Future> _rm(String pathSpec) async { if (useDartGit || AppConfig.instance.experimentalGitOps) { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); return await repo.rm(pathSpec); } else { try { @@ -78,7 +81,7 @@ class GitNoteRepository { required String authorName, }) async { if (useDartGit || AppConfig.instance.experimentalGitOps) { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); var author = GitAuthor(name: authorName, email: authorEmail); var r = await repo.commit(message: message, author: author); if (r.isFailure) { @@ -209,7 +212,7 @@ class GitNoteRepository { Future> resetLastCommit() async { if (useDartGit || AppConfig.instance.experimentalGitOps) { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); var headCommitR = await repo.headCommit(); if (headCommitR.isFailure) { return fail(headCommitR); @@ -268,7 +271,7 @@ class GitNoteRepository { Future> merge() => catchAll(_merge); Future> _merge() async { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); var branch = await repo.currentBranch().getOrThrow(); var branchConfig = repo.config.branch(branch); @@ -316,7 +319,7 @@ class GitNoteRepository { Future> push() async { // Only push if we have something we need to push try { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); var canPush = await repo.canPush().getOrThrow(); if (!canPush) { return Result(null); @@ -365,7 +368,7 @@ class GitNoteRepository { Future numChanges() async { try { - var repo = await GitRepository.load(gitRepoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(gitRepoPath).getOrThrow(); var nResult = await repo.numChangesToPush(); if (nResult.isSuccess) { return nResult.getOrThrow(); diff --git a/lib/history/commit_data_widget.dart b/lib/history/commit_data_widget.dart index e935c55f..bbe102d8 100644 --- a/lib/history/commit_data_widget.dart +++ b/lib/history/commit_data_widget.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:dart_git/dart_git.dart'; import 'package:dart_git/diff_commit.dart'; @@ -43,10 +44,10 @@ class _CommitDataWidgetState extends State { _initStateAsync(); } - Future _initStateAsync() async { + void _initStateAsync() { // FIXME: Run all of this in another worker thread! - var r = await diffCommits( + var r = diffCommits( fromCommit: widget.parentCommit, toCommit: widget.commit, objStore: widget.gitRepo.objStorage, @@ -54,7 +55,7 @@ class _CommitDataWidgetState extends State { if (r.isFailure) { Log.e("Got exception in diffCommits", ex: r.error, stacktrace: r.stackTrace); - return setState(() { + setState(() { _exception = r.exception; }); } @@ -131,11 +132,11 @@ class __BlobLoaderState extends State<_BlobLoader> { void initState() { super.initState(); - _initStateAsync(); + SchedulerBinding.instance!.addPostFrameCallback((_) => _initStateAsync); } - Future _initStateAsync() async { - var result = await widget.gitRepo.objStorage.readBlob(widget.blobHash); + void _initStateAsync() { + var result = widget.gitRepo.objStorage.readBlob(widget.blobHash); setState(() { _exception = result.exception; _blob = result.data; diff --git a/lib/history/history_screen.dart b/lib/history/history_screen.dart index a193399d..64357b7e 100644 --- a/lib/history/history_screen.dart +++ b/lib/history/history_screen.dart @@ -8,7 +8,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:dart_git/git.dart'; +import 'package:dart_git/dart_git.dart'; import 'package:dart_git/plumbing/commit_iterator.dart'; import 'package:dart_git/plumbing/objects/commit.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -59,7 +59,7 @@ class _HistoryWidgetState extends State { List> commits = []; List commitsAndSyncAttempts = []; - Stream>? _stream; + Iterable>? _stream; final _scrollController = ScrollController(); final _lock = Lock(); @@ -109,7 +109,7 @@ class _HistoryWidgetState extends State { var stream = _stream!; var list = >[]; - await for (var commit in stream.take(20)) { + for (var commit in stream.take(20)) { list.add(commit); } @@ -120,20 +120,19 @@ class _HistoryWidgetState extends State { }); } - Future>> _initStream() async { + Future>> _initStream() async { try { - _gitRepo = await GitRepository.load(widget.repoPath).getOrThrow(); - var head = await _gitRepo!.headHash().getOrThrow(); + _gitRepo = GitRepository.load(widget.repoPath).getOrThrow(); + var head = _gitRepo!.headHash().getOrThrow(); return commitPreOrderIterator( - objStorage: _gitRepo!.objStorage, from: head) - .asBroadcastStream(); + objStorage: _gitRepo!.objStorage, from: head); } on Exception catch (ex) { setState(() { _exception = ex; }); } - return const Stream.empty(); + return []; } void _rebuildCombined() { diff --git a/lib/repository.dart b/lib/repository.dart index 5c75f49a..4bffa588 100644 --- a/lib/repository.dart +++ b/lib/repository.dart @@ -135,7 +135,7 @@ class GitJournalRepo with ChangeNotifier { if (!repoDir.existsSync()) { Log.i("Calling GitInit for ${storageConfig.folderName} at: $repoPath"); - var r = await GitRepository.init(repoPath, defaultBranch: 'main'); + var r = GitRepository.init(repoPath, defaultBranch: DEFAULT_BRANCH); if (r.isFailure) { Log.e("GitInit Failed", result: r); return fail(r); @@ -144,7 +144,7 @@ class GitJournalRepo with ChangeNotifier { storageConfig.save(); } - var valid = await GitRepository.isValidRepo(repoPath); + var valid = GitRepository.isValidRepo(repoPath); if (!valid) { // What happened that the directory still exists but the .git folder // has disappeared? @@ -154,7 +154,7 @@ class GitJournalRepo with ChangeNotifier { return Result.fail(ex); } - var repoR = await GitRepository.load(repoPath); + var repoR = await GitAsyncRepository.load(repoPath); if (repoR.isFailure) { return fail(repoR); } @@ -164,6 +164,7 @@ class GitJournalRepo with ChangeNotifier { if (!storageConfig.storeInternally) { var r = await _commitUnTrackedChanges(repo, gitConfig); if (r.isFailure) { + repo.close(); return fail(r); } } @@ -192,6 +193,8 @@ class GitJournalRepo with ChangeNotifier { currentBranch: await repo.currentBranch().getOrThrow(), headHash: head, ); + + repo.close(); return Result(gjRepo); } @@ -268,7 +271,7 @@ class GitJournalRepo with ChangeNotifier { var r = await rootFolder.loadRecursively(); if (r.isFailure) { if (r.error is FileStorageCacheIncomplete) { - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(repoPath).getOrThrow(); await _commitUnTrackedChanges(repo, gitConfig); await _resetFileStorage(); return; @@ -287,33 +290,11 @@ class GitJournalRepo with ChangeNotifier { } Future __fillFileStorageCache() async { - var gitRepo = await GitRepository.load(repoPath).getOrThrow(); - var headR = await gitRepo.headHash(); - if (headR.isFailure) { - if (headR.error is GitRefNotFound) { - // No commits - fileStorageCacheReady = true; - notifyListeners(); - return; - } - Log.e("Failed to fetch HEAD", result: headR); - return; - } - var head = headR.getOrThrow(); - Log.d("Got HEAD: $head"); - var startTime = DateTime.now(); - var result = await gitRepo.visitTree( - fromCommitHash: head, - visitor: fileStorage.visitor, - ); + await fileStorage.fill(); var endTime = DateTime.now().difference(startTime); Log.i("Built Git Time Cache - $endTime"); - if (result.isFailure) { - Log.e("Failed to build FileStorage cache", result: result); - logException(result.exception!, result.stackTrace!); - } var r = await fileStorageCache.save(fileStorage); if (r.isFailure) { @@ -321,10 +302,7 @@ class GitJournalRepo with ChangeNotifier { logException(r.exception!, r.stackTrace!); } - if (fileStorageCache.lastProcessedHead != head) { - Log.e( - "FileStorageCache Head different ${fileStorageCache.lastProcessedHead}"); - } + assert(fileStorageCache.lastProcessedHead == fileStorage.head); // Notify that the cache is ready fileStorageCacheReady = true; @@ -342,7 +320,7 @@ class GitJournalRepo with ChangeNotifier { Future syncNotes({bool doNotThrow = false}) async { // This is extremely slow with dart-git, can take over a second! if (_shouldCheckForChanges()) { - var repoR = await GitRepository.load(repoPath); + var repoR = await GitAsyncRepository.load(repoPath); if (repoR.isFailure) { Log.e("SyncNotes Failed to Load Repo", result: repoR); return; @@ -747,7 +725,7 @@ class GitJournalRepo with ChangeNotifier { Future discardChanges(Note note) async { // FIXME: Add the checkout method to GJRepo - var gitRepo = await GitRepository.load(repoPath).getOrThrow(); + var gitRepo = await GitAsyncRepository.load(repoPath).getOrThrow(); await gitRepo.checkout(note.filePath).throwOnError(); // FIXME: Instead of this just reload that specific file @@ -756,12 +734,12 @@ class GitJournalRepo with ChangeNotifier { } Future> remoteConfigs() async { - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(repoPath).getOrThrow(); return repo.config.remotes; } Future> branches() async { - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(repoPath).getOrThrow(); var branches = Set.from(await repo.branches().getOrThrow()); if (repo.config.remotes.isNotEmpty) { var remoteName = repo.config.remotes.first.name; @@ -777,11 +755,12 @@ class GitJournalRepo with ChangeNotifier { Future checkoutBranch(String branchName) async { Log.i("Changing branch to $branchName"); - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(repoPath).getOrThrow(); try { var created = await createBranchIfRequired(repo, branchName); if (created.isEmpty) { + repo.close(); return ""; } } catch (ex, st) { @@ -800,12 +779,15 @@ class GitJournalRepo with ChangeNotifier { } catch (e, st) { Log.e("Checkout Branch Failed", ex: e, stacktrace: st); } + + repo.close(); return branchName; } // FIXME: Why does this need to return a string? /// throws exceptions - Future createBranchIfRequired(GitRepository repo, String name) async { + Future createBranchIfRequired( + GitAsyncRepository repo, String name) async { var localBranches = await repo.branches().getOrThrow(); if (localBranches.contains(name)) { return name; @@ -824,8 +806,8 @@ class GitJournalRepo with ChangeNotifier { return ""; } - await repo.createBranch(name, hash: remoteBranchRef.hash).throwOnError(); - await repo.setBranchUpstreamTo(name, remoteConfig, name).throwOnError(); + repo.createBranch(name, hash: remoteBranchRef.hash).throwOnError(); + repo.setBranchUpstreamTo(name, remoteConfig, name).throwOnError(); Log.i("Created branch $name"); return name; @@ -840,7 +822,8 @@ class GitJournalRepo with ChangeNotifier { /// reset --hard the current branch to its remote branch Future> resetHard() { return catchAll(() async { - var repo = await GitRepository.load(_gitRepo.gitRepoPath).getOrThrow(); + var repo = + await GitAsyncRepository.load(_gitRepo.gitRepoPath).getOrThrow(); var branchName = await repo.currentBranch().getOrThrow(); var branchConfig = repo.config.branch(branchName); if (branchConfig == null) { @@ -866,7 +849,8 @@ class GitJournalRepo with ChangeNotifier { Future> canResetHard() { return catchAll(() async { - var repo = await GitRepository.load(_gitRepo.gitRepoPath).getOrThrow(); + var repo = + await GitAsyncRepository.load(_gitRepo.gitRepoPath).getOrThrow(); var branchName = await repo.currentBranch().getOrThrow(); var branchConfig = repo.config.branch(branchName); if (branchConfig == null) { @@ -930,7 +914,7 @@ Future _ensureOneCommitInRepo({ } Future> _commitUnTrackedChanges( - GitRepository repo, GitConfig gitConfig) async { + GitAsyncRepository repo, GitConfig gitConfig) async { var timer = Stopwatch()..start(); // // Check for un-committed files and save them diff --git a/lib/settings/settings.dart b/lib/settings/settings.dart index df90f43a..254a771c 100644 --- a/lib/settings/settings.dart +++ b/lib/settings/settings.dart @@ -23,6 +23,8 @@ const SETTINGS_VERSION = 3; const DEFAULT_LIGHT_THEME_NAME = "LightDefault"; const DEFAULT_DARK_THEME_NAME = "DarkDefault"; +const DEFAULT_BRANCH = 'main'; + class Settings extends ChangeNotifier with SettingsSharedPref { Settings(this.id, this.pref); diff --git a/lib/settings/settings_git_remote.dart b/lib/settings/settings_git_remote.dart index badae7b1..76e20a9b 100644 --- a/lib/settings/settings_git_remote.dart +++ b/lib/settings/settings_git_remote.dart @@ -246,7 +246,7 @@ class _GitRemoteSettingsScreenState extends State { while (true) { var repoFolderPath = p.join(gitDir, "$repoFolderName$num"); if (!Directory(repoFolderPath).existsSync()) { - var r = await GitRepository.init(repoFolderPath, defaultBranch: 'main'); + var r = GitRepository.init(repoFolderPath, defaultBranch: 'main'); showResultError(context, r); break; } diff --git a/lib/setup/clone.dart b/lib/setup/clone.dart index 7a05562d..f761f387 100644 --- a/lib/setup/clone.dart +++ b/lib/setup/clone.dart @@ -13,9 +13,10 @@ import 'package:path/path.dart' as p; import 'package:universal_io/io.dart' show Directory; import 'package:gitjournal/logger/logger.dart'; +import 'package:gitjournal/settings/settings.dart'; import 'git_transfer_progress.dart'; -const DefaultBranchName = 'main'; +const DefaultBranchName = DEFAULT_BRANCH; typedef GitFetchFunction = Future> Function( String repoPath, @@ -56,7 +57,7 @@ Future> cloneRemotePluggable({ required GitDefaultBranchFunction defaultBranchFn, required GitMergeFn gitMergeFn, }) async { - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = await GitAsyncRepository.load(repoPath).getOrThrow(); var remote = await repo.addOrUpdateRemote(remoteName, cloneUrl).getOrThrow(); var statusFile = p.join(Directory.systemTemp.path, 'gj'); @@ -73,12 +74,14 @@ Future> cloneRemotePluggable({ timer.cancel(); if (fetchR.isFailure) { // FIXME: Give a better error? + repo.close(); return fail(fetchR); } var branchNameR = await defaultBranchFn( repoPath, remoteName, sshPublicKey, sshPrivateKey, sshPassword); if (branchNameR.isFailure) { + repo.close(); return fail(branchNameR); } var remoteBranchName = branchNameR.getOrThrow(); @@ -101,6 +104,7 @@ Future> cloneRemotePluggable({ var remoteBranchR = await repo.remoteBranch(remoteName, remoteBranchName); if (remoteBranchR.isFailure) { if (remoteBranchR.error is! GitNotFound) { + repo.close(); return fail(remoteBranchR); } @@ -144,6 +148,7 @@ Future> cloneRemotePluggable({ var r = await gitMergeFn( repoPath, remoteName, remoteBranchName, authorName, authorEmail); if (r.isFailure) { + repo.close(); return fail(r); } } @@ -159,6 +164,7 @@ Future> cloneRemotePluggable({ var r = await gitMergeFn( repoPath, remoteName, remoteBranchName, authorName, authorEmail); if (r.isFailure) { + repo.close(); return fail(r); } } @@ -173,10 +179,12 @@ Future> cloneRemotePluggable({ if (!skipCheckout) { var r = await repo.checkout("."); if (r.isFailure) { + repo.close(); return fail(r); } } + repo.close(); return Result(null); } diff --git a/lib/setup/clone_git_exec.dart b/lib/setup/clone_git_exec.dart index f83496e6..c9fefdce 100644 --- a/lib/setup/clone_git_exec.dart +++ b/lib/setup/clone_git_exec.dart @@ -81,9 +81,9 @@ Future> _merge( String authorEmail, ) { return catchAll(() async { - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = GitRepository.load(repoPath).getOrThrow(); var author = GitAuthor(name: authorName, email: authorEmail); - await repo.mergeCurrentTrackingBranch(author: author).throwOnError(); + repo.mergeCurrentTrackingBranch(author: author).throwOnError(); return Result(null); }); } diff --git a/lib/setup/clone_libgit2.dart b/lib/setup/clone_libgit2.dart index a3d7771e..e44a52eb 100644 --- a/lib/setup/clone_libgit2.dart +++ b/lib/setup/clone_libgit2.dart @@ -89,8 +89,8 @@ Future> _defaultBranch( Log.w("Could not fetch git Default Branch", ex: ex); } - var repo = await GitRepository.load(repoPath).getOrThrow(); - var remoteBranch = await repo.guessRemoteHead(remoteName); + var repo = GitRepository.load(repoPath).getOrThrow(); + var remoteBranch = repo.guessRemoteHead(remoteName); if (remoteBranch == null) { return Result(null); } diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index e4c1b3b2..6dbf86a2 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:dart_git/git.dart'; +import 'package:dart_git/dart_git.dart'; import 'package:dots_indicator/dots_indicator.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:function_types/function_types.dart'; @@ -426,20 +426,20 @@ class GitHostSetupScreenState extends State { ); } - Future _removeRemote() async { + void _removeRemote() { var repo = context.read(); var basePath = repo.gitBaseDirectory; var repoPath = p.join(basePath, widget.repoFolderName); try { - if (!await GitRepository.isValidRepo(repoPath)) { - var r = await GitRepository.init(repoPath, defaultBranch: 'main'); + if (!GitRepository.isValidRepo(repoPath)) { + var r = GitRepository.init(repoPath, defaultBranch: 'main'); showResultError(context, r); } - var repo = await GitRepository.load(repoPath).getOrThrow(); + var repo = GitRepository.load(repoPath).getOrThrow(); if (repo.config.remote(widget.remoteName) != null) { - await repo.removeRemote(widget.remoteName).throwOnError(); + repo.removeRemote(widget.remoteName).throwOnError(); } } catch (e, stacktrace) { Log.e("Failed to remove remote", ex: e, stacktrace: stacktrace); @@ -571,7 +571,7 @@ class GitHostSetupScreenState extends State { if (cloneR.isFailure) { Log.e("Failed to clone", ex: cloneR.error, stacktrace: cloneR.stackTrace); var error = cloneR.error.toString(); - await _removeRemote(); + _removeRemote(); setState(() { logEvent(Event.GitHostSetupGitCloneError, parameters: { diff --git a/lib/utils/git_desktop.dart b/lib/utils/git_desktop.dart index 685259fd..82ccae3e 100644 --- a/lib/utils/git_desktop.dart +++ b/lib/utils/git_desktop.dart @@ -13,6 +13,7 @@ import 'package:dart_git/utils/result.dart'; import 'package:universal_io/io.dart'; import 'package:gitjournal/logger/logger.dart'; +import 'package:gitjournal/settings/settings.dart'; Future> gitFetchViaExecutable({ required String repoPath, @@ -60,7 +61,7 @@ Future> _gitCommandViaExecutable({ var dir = Directory.systemTemp.createTempSync(); var temp = File("${dir.path}/key"); _ = await temp.writeAsString(privateKey); - await temp.chmod(int.parse('0600', radix: 8)); + temp.chmodSync(int.parse('0600', radix: 8)); Log.i("Running git $command $remoteName"); var process = await Process.start( @@ -113,7 +114,7 @@ Future> gitDefaultBranchViaExecutable({ var dir = Directory.systemTemp.createTempSync(); var temp = File("${dir.path}/key"); _ = await temp.writeAsString(privateKey); - await temp.chmod(int.parse('0600', radix: 8)); + temp.chmodSync(int.parse('0600', radix: 8)); var process = await Process.start( 'git', @@ -147,9 +148,8 @@ Future> gitDefaultBranchViaExecutable({ for (var line in LineSplitter.split(stdout)) { if (line.contains('HEAD branch:')) { var branch = line.split(':')[1].trim(); - // Everyone seems to default to 'main' these days if (branch == '(unknown)') { - return Result('main'); + return Result(DEFAULT_BRANCH); } return Result(branch); } diff --git a/pubspec.lock b/pubspec.lock index 689e14e0..21e5a470 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -346,7 +346,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: f1cb3b0376a2f3222a84b034906f156b237766d3 + resolved-ref: d02e1ea8712a31d1e51211091de7b56e6f2158b8 url: "https://github.com/GitJournal/dart-git.git" source: git version: "0.0.2" diff --git a/test/core/file/file_storage_cache_test.dart b/test/core/file/file_storage_cache_test.dart index 55620a05..269f0cd9 100644 --- a/test/core/file/file_storage_cache_test.dart +++ b/test/core/file/file_storage_cache_test.dart @@ -58,7 +58,7 @@ void main() { var tempDir = await io.Directory.systemTemp.createTemp('__fnft__'); var repoPath = tempDir.path; - await GitRepository.init(repoPath).throwOnError(); + GitRepository.init(repoPath).throwOnError(); var fileStorage = FileStorage( repoPath: repoPath, @@ -74,12 +74,19 @@ void main() { var deepEq = const DeepCollectionEquality().equals; expect( - deepEq(fileStorage2.blobCTimeBuilder.processedCommits, commits), true); - expect(deepEq(fileStorage2.blobCTimeBuilder.processedTrees, trees), true); + deepEq(fileStorage2.blobCTimeBuilder.processedCommits.set, commits), + true, + ); + expect( + deepEq(fileStorage2.blobCTimeBuilder.processedTrees.set, trees), + true, + ); expect(deepEq(fileStorage2.blobCTimeBuilder.map, cMap), true); expect( - deepEq(fileStorage2.fileMTimeBuilder.processedCommits, commits), true); + deepEq(fileStorage2.fileMTimeBuilder.processedCommits.set, commits), + true, + ); expect(deepEq(fileStorage2.fileMTimeBuilder.map, mMap), true); }); } diff --git a/test/core/flattened_filtered_notes_folder_test.dart b/test/core/flattened_filtered_notes_folder_test.dart index 925ba9fa..c743bc2b 100644 --- a/test/core/flattened_filtered_notes_folder_test.dart +++ b/test/core/flattened_filtered_notes_folder_test.dart @@ -108,8 +108,8 @@ void main() { await storage.save(note).throwOnError(); } - var repo = await GitRepository.load(repoPath).getOrThrow(); - await repo + var repo = GitRepository.load(repoPath).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), diff --git a/test/flattened_notes_folder_large_test.dart b/test/flattened_notes_folder_large_test.dart index 292afe6c..dc5eb795 100644 --- a/test/flattened_notes_folder_large_test.dart +++ b/test/flattened_notes_folder_large_test.dart @@ -42,8 +42,8 @@ void main() { await _writeRandomNote(random, repoPath, config, fileStorage); } - var repo = await GitRepository.load(repoPath).getOrThrow(); - await repo + var repo = GitRepository.load(repoPath).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), @@ -72,8 +72,8 @@ void main() { var newFileStorage = await FileStorage.fake(newRepoPath); await _writeRandomNote(Random(), newRepoPath, config, newFileStorage); - var repo = await GitRepository.load(newRepoPath).getOrThrow(); - await repo + var repo = GitRepository.load(newRepoPath).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), diff --git a/test/flattened_notes_folder_test.dart b/test/flattened_notes_folder_test.dart index 97f386b6..620c0684 100644 --- a/test/flattened_notes_folder_test.dart +++ b/test/flattened_notes_folder_test.dart @@ -109,8 +109,8 @@ void main() { await storage.save(note).throwOnError(); } - var repo = await GitRepository.load(repoPath).getOrThrow(); - await repo + var repo = GitRepository.load(repoPath).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), diff --git a/test/link_resolver_test.dart b/test/link_resolver_test.dart index 35e78a46..884ea2de 100644 --- a/test/link_resolver_test.dart +++ b/test/link_resolver_test.dart @@ -46,8 +46,8 @@ void main() { await generateNote(repoPath, "zeplin.txt"); await generateNote(repoPath, "Goat Sim.md"); - var repo = await GitRepository.load(repoPath).getOrThrow(); - await repo + var repo = GitRepository.load(repoPath).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), diff --git a/test/note_storage_test.dart b/test/note_storage_test.dart index 0a20a10c..52d9fac4 100644 --- a/test/note_storage_test.dart +++ b/test/note_storage_test.dart @@ -67,8 +67,8 @@ void main() { notes = [n1, n2]; - var repo = await GitRepository.load(tempDir.path).getOrThrow(); - await repo + var repo = GitRepository.load(tempDir.path).getOrThrow(); + repo .commit( message: "Prepare Test Env", author: GitAuthor(name: 'Name', email: "name@example.com"), diff --git a/test_driver/main.dart b/test_driver/main.dart index 27587015..637180f0 100644 --- a/test_driver/main.dart +++ b/test_driver/main.dart @@ -28,7 +28,7 @@ Future populateWithData(SharedPreferences pref) async { var dir = await getApplicationDocumentsDirectory(); var repoPath = p.join(dir.path, "journal_local"); - await GitRepository.init(repoPath); + GitRepository.init(repoPath); stderr.writeln("Filling fake data in $repoPath");