diff --git a/CHANGELOG.md b/CHANGELOG.md index 8479242..78b639e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,3 @@ -## 1.2.2 - -- fix: lookup package in correct location of Dart/Flutter cached packages - -## 1.2.1 - -- fix: use default location of Flutter's '.pub_cache' folder - -- docs: update README with troubleshooting instructions for Windows - -- chore: bump minimum dart and flutter versions - -- chore: Lookup library in system path (thanks @dnys1) - ## 1.2.0 - feat: upgrade libgit2 to 1.5.0 diff --git a/README.md b/README.md index e1c6679..8c17eb4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # libgit2dart +![Coverage](coverage_badge.svg) + **Dart bindings to libgit2** libgit2dart package provides ability to use [libgit2](https://github.com/libgit2/libgit2) in Dart/Flutter. @@ -663,8 +665,6 @@ Fork libgit2dart, improve libgit2dart, send a pull request. ### Troubleshooting -#### Linux: - If you are developing on Linux using non-Debian based distrib you might encounter these errors: - Failed to load dynamic library: libpcre.so.3: cannot open shared object file: No such file or directory @@ -679,16 +679,6 @@ sudo ln -s /usr/lib64/libpcre.so /usr/lib64/libpcre.so.3 sudo ln -s /usr/lib64/libpcreposix.so /usr/lib64/libpcreposix.so.3 ``` -#### Windows: - -If you are developing on Windows you might encounter: - -- Failed to load dynamic library: error code 126 - -That happens because libgit2 dynamic library bundled with libgit2dart package is precompiled with ssh support, and it fails to find the `libssh2.dll`. - -To fix that error you should [build](https://github.com/libssh2/libssh2/blob/master/docs/INSTALL_CMAKE.md) libssh2, and place resulting `libssh2.dll` somewhere in system path (e.g. "Windows\System32"). - ### Ffigen To generate bindings with ffigen use (adjust paths to yours): @@ -703,6 +693,7 @@ To run all tests and generate coverage report make sure to have activated packag ```sh $ dart pub global activate coverage +$ dart pub global activate flutter_coverage_badge ``` And run: diff --git a/bin/setup.dart b/bin/setup.dart index 74bce74..a71be0d 100644 --- a/bin/setup.dart +++ b/bin/setup.dart @@ -5,6 +5,7 @@ import 'package:libgit2dart/libgit2dart.dart'; import 'package:libgit2dart/src/libgit2.dart'; import 'package:libgit2dart/src/util.dart'; import 'package:path/path.dart' as path; +import 'package:pub_cache/pub_cache.dart'; /// Copies prebuilt libgit2 library from package in '.pub_cache' into correct /// directory for [platform]. @@ -22,24 +23,27 @@ Future copyLibrary(String platform) async { ); } } else { - final libPath = checkCache(); + String? checkCache(PubCache pubCache) => + pubCache.getLatestVersion('libgit2dart')?.resolve()?.location.path; + + final libPath = checkCache(PubCache()) ?? + checkCache( + PubCache( + Directory( + path.join(Platform.environment['FLUTTER_ROOT']!, '.pub-cache'), + ), + ), + ); final libName = getLibName(); stdout.writeln('Copying libgit2 for $platform'); - if (libPath == null) { - stdout.writeln( - "Couldn't find libgit2dart package.\n" - "Make sure to run 'dart pub get' to resolve dependencies.", - ); - } else { - final destination = path.join(libDir, platform); - Directory(destination).createSync(recursive: true); - File(path.join(libPath, platform, libName)).copySync( - path.join(destination, libName), - ); + final destination = path.join(libDir, platform); + Directory(destination).createSync(recursive: true); + File(path.join(libPath!, platform, libName)).copySync( + path.join(destination, libName), + ); - stdout.writeln('Done! libgit2 for $platform is now available!'); - } + stdout.writeln('Done! libgit2 for $platform is now available!'); } } @@ -53,9 +57,7 @@ class CleanCommand extends Command { @override void run() { stdout.writeln('Cleaning...'); - if (Directory(libDir).existsSync()) { - Directory(libDir).deleteSync(recursive: true); - } + Directory(libDir).deleteSync(recursive: true); } } diff --git a/coverage.sh b/coverage.sh index 1ea3ef2..79f52cb 100755 --- a/coverage.sh +++ b/coverage.sh @@ -1,2 +1,2 @@ #!/bin/bash -dart test --coverage=coverage --test-randomize-ordering-seed random && dart pub global run coverage:format_coverage --lcov --check-ignore --in=coverage --out=coverage/lcov.info --report-on=lib && genhtml coverage/lcov.info -o coverage/ \ No newline at end of file +dart test --coverage=coverage --test-randomize-ordering-seed random && dart pub global run coverage:format_coverage --lcov --check-ignore --in=coverage --out=coverage/lcov.info --report-on=lib && genhtml coverage/lcov.info -o coverage/ && dart pub global run flutter_coverage_badge \ No newline at end of file diff --git a/coverage_badge.svg b/coverage_badge.svg new file mode 100644 index 0000000..0c4efc0 --- /dev/null +++ b/coverage_badge.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + coverage + coverage + 100% + 100% + + diff --git a/lib/src/util.dart b/lib/src/util.dart index 3ba855c..8ce2caf 100644 --- a/lib/src/util.dart +++ b/lib/src/util.dart @@ -1,13 +1,12 @@ // coverage:ignore-file -import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; import 'package:libgit2dart/src/bindings/libgit2_bindings.dart'; import 'package:libgit2dart/src/bindings/libgit2_opts_bindings.dart'; import 'package:path/path.dart' as path; -import 'package:pub_semver/pub_semver.dart'; +import 'package:pub_cache/pub_cache.dart'; const libgit2Version = '1.5.0'; final libDir = path.join('.dart_tool', 'libgit2'); @@ -26,20 +25,6 @@ String getLibName() { return 'libgit2-$libgit2Version.$ext'; } -/// Returns location of the most recent verison of the libgit2dart package -/// contained in the cache. -String? checkCache() { - final cache = json.decode( - Process.runSync('dart', ['pub', 'cache', 'list']).stdout as String, - ) as Map; - final packages = cache['packages'] as Map; - final libPackages = packages['libgit2dart'] as Map?; - final versions = libPackages?.keys.map((e) => Version.parse(e)).toList(); - final latestVersion = libPackages?[Version.primary(versions!).toString()] - as Map?; - return latestVersion?['location'] as String?; -} - /// Checks if [File]/[Link] exists for [path]. bool _doesFileExist(String path) { return File(path).existsSync() || Link(path).existsSync(); @@ -68,22 +53,18 @@ String? _resolveLibPath(String name) { libPath = path.join(path.dirname(Platform.resolvedExecutable), 'lib', name); if (_doesFileExist(libPath)) return libPath; - // If lib is installed in system dir. - if (Platform.isMacOS || Platform.isLinux) { - final paths = [ - '/usr/local/lib/libgit2.$libgit2Version.dylib', - '/usr/local/lib/libgit2.so.$libgit2Version', - '/usr/lib64/libgit2.so.$libgit2Version' - ]; - for (final path in paths) { - if (_doesFileExist(path)) return path; - } + String checkCache(PubCache pubCache) { + final pubCacheDir = + pubCache.getLatestVersion('libgit2dart')!.resolve()!.location; + return path.join(pubCacheDir.path, Platform.operatingSystem, name); } - // If lib is in '.pub_cache' folder. - final cachedLocation = checkCache(); - if (cachedLocation != null) { - libPath = path.join(cachedLocation, Platform.operatingSystem, name); + // If lib is in Flutter's '.pub_cache' folder. + final env = Platform.environment; + if (env.containsKey('FLUTTER_ROOT')) { + final flutterPubCache = + PubCache(Directory(path.join(env['FLUTTER_ROOT']!, '.pub-cache'))); + libPath = checkCache(flutterPubCache); if (_doesFileExist(libPath)) return libPath; } diff --git a/macos/libgit2dart.podspec b/macos/libgit2dart.podspec index 5ccfc67..c9c9408 100644 --- a/macos/libgit2dart.podspec +++ b/macos/libgit2dart.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'libgit2dart' - s.version = '1.2.2' + s.version = '1.2.0' s.summary = 'Dart bindings to libgit2.' s.description = <<-DESC Dart bindings to libgit2. diff --git a/pubspec.yaml b/pubspec.yaml index d0c47a5..f868cae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,13 +2,13 @@ name: libgit2dart description: Dart bindings to libgit2, provides ability to use libgit2 library in Dart and Flutter. -version: 1.2.2 +version: 1.2.0 homepage: https://github.com/SkinnyMind/libgit2dart environment: - sdk: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + sdk: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" dependencies: args: ^2.3.0 @@ -16,7 +16,7 @@ dependencies: ffi: ^2.0.0 meta: ^1.7.0 path: ^1.8.1 - pub_semver: ^2.1.3 + pub_cache: ^0.3.1 dev_dependencies: ffigen: ^6.0.1 diff --git a/test/credentials_test.dart b/test/credentials_test.dart index f198093..cdfaa1c 100644 --- a/test/credentials_test.dart +++ b/test/credentials_test.dart @@ -83,28 +83,32 @@ void main() { cloneDir.deleteSync(recursive: true); }); - test('clones repository with provided keypair', () { - final cloneDir = Directory.systemTemp.createTempSync('clone'); - final keypair = Keypair( - username: 'git', - pubKey: p.join('test', 'assets', 'keys', 'id_rsa.pub'), - privateKey: p.join('test', 'assets', 'keys', 'id_rsa'), - passPhrase: 'empty', - ); - final callbacks = Callbacks(credentials: keypair); + test( + testOn: '!linux', + 'clones repository with provided keypair', + () { + final cloneDir = Directory.systemTemp.createTempSync('clone'); + final keypair = Keypair( + username: 'git', + pubKey: p.join('test', 'assets', 'keys', 'id_rsa.pub'), + privateKey: p.join('test', 'assets', 'keys', 'id_rsa'), + passPhrase: 'empty', + ); + final callbacks = Callbacks(credentials: keypair); - final repo = Repository.clone( - url: 'ssh://git@github.com/libgit2/TestGitRepository', - localPath: cloneDir.path, - callbacks: callbacks, - ); + final repo = Repository.clone( + url: 'ssh://git@github.com/libgit2/TestGitRepository', + localPath: cloneDir.path, + callbacks: callbacks, + ); - expect(repo.isEmpty, false); + expect(repo.isEmpty, false); - if (Platform.isLinux || Platform.isMacOS) { - cloneDir.deleteSync(recursive: true); - } - }); + if (Platform.isLinux || Platform.isMacOS) { + cloneDir.deleteSync(recursive: true); + } + }, + ); test('throws when no credentials is provided', () { final cloneDir = Directory.systemTemp.createTempSync('clone'); @@ -185,32 +189,36 @@ void main() { cloneDir.deleteSync(recursive: true); }); - test('clones repository with provided keypair from memory', () { - final cloneDir = Directory.systemTemp.createTempSync('clone'); - final pubKey = File(p.join('test', 'assets', 'keys', 'id_rsa.pub')) - .readAsStringSync(); - final privateKey = - File(p.join('test', 'assets', 'keys', 'id_rsa')).readAsStringSync(); - final keypair = KeypairFromMemory( - username: 'git', - pubKey: pubKey, - privateKey: privateKey, - passPhrase: 'empty', - ); - final callbacks = Callbacks(credentials: keypair); + test( + testOn: '!linux', + 'clones repository with provided keypair from memory', + () { + final cloneDir = Directory.systemTemp.createTempSync('clone'); + final pubKey = File(p.join('test', 'assets', 'keys', 'id_rsa.pub')) + .readAsStringSync(); + final privateKey = + File(p.join('test', 'assets', 'keys', 'id_rsa')).readAsStringSync(); + final keypair = KeypairFromMemory( + username: 'git', + pubKey: pubKey, + privateKey: privateKey, + passPhrase: 'empty', + ); + final callbacks = Callbacks(credentials: keypair); - final repo = Repository.clone( - url: 'ssh://git@github.com/libgit2/TestGitRepository', - localPath: cloneDir.path, - callbacks: callbacks, - ); + final repo = Repository.clone( + url: 'ssh://git@github.com/libgit2/TestGitRepository', + localPath: cloneDir.path, + callbacks: callbacks, + ); - expect(repo.isEmpty, false); + expect(repo.isEmpty, false); - if (Platform.isLinux || Platform.isMacOS) { - cloneDir.deleteSync(recursive: true); - } - }); + if (Platform.isLinux || Platform.isMacOS) { + cloneDir.deleteSync(recursive: true); + } + }, + ); test('throws when provided keypair from memory is incorrect', () { final cloneDir = Directory.systemTemp.createTempSync('clone'); diff --git a/test/remote_test.dart b/test/remote_test.dart index caa3a63..126f317 100644 --- a/test/remote_test.dart +++ b/test/remote_test.dart @@ -278,7 +278,7 @@ void main() { expect(refs.first.localId, null); expect(refs.first.name, 'HEAD'); expect(refs.first.symRef, 'refs/heads/master'); - expect(refs.first.oid.sha, '49322bb17d3acc9146f98c97d078513228bbf3c0'); + expect((refs.first.oid).sha, '49322bb17d3acc9146f98c97d078513228bbf3c0'); expect(refs.first.toString(), contains('RemoteReference{')); expect(refs.first, remote.ls().first); });