From 0ed06c42298869fe8b010ababb3adb5823b711f8 Mon Sep 17 00:00:00 2001 From: Alexandre Roux Date: Wed, 22 Jan 2025 16:39:33 +0100 Subject: [PATCH] fix pub get/upgrade with cache for workspace --- lib/bin/pubget.dart | 23 ++++++----- lib/bin/pubupgrade.dart | 21 +++++----- lib/bin/src/pub_workspace_cache.dart | 60 ++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 lib/bin/src/pub_workspace_cache.dart diff --git a/lib/bin/pubget.dart b/lib/bin/pubget.dart index 8056bf1..abc83bb 100755 --- a/lib/bin/pubget.dart +++ b/lib/bin/pubget.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:args/args.dart'; import 'package:dev_build/menu/menu_run_ci.dart'; import 'package:process_run/stdio.dart'; +import 'package:tekartik_pub/bin/src/pub_workspace_cache.dart'; import 'package:tekartik_pub/bin/src/pubbin_utils.dart'; import 'package:tekartik_pub/io.dart'; @@ -57,6 +58,7 @@ Future main(List arguments) async { rest = ['.']; } + initPubWorkspacesCache(); await pubGet( rest, PubGetOptions() @@ -75,28 +77,27 @@ Future pubGet(List directories, PubGetOptions options) async { if (options.verbose == true) { print('found package(s): $pkgPaths'); } + var offline = options.offline ?? false; var futures = []; for (final dir in pkgPaths) { var pubIoPackage = PubIoPackage(dir); await pubIoPackage.ready; - var isFlutterPub = pubIoPackage.dofPub == 'flutter pub'; - final pkg = PubPackage(dir); - ProcessCmd cmd; - if (isFlutterPub) { - if (!isFlutterSupported) { + + if (pubWorkspacesCache != null && + (pubIoPackage.hasWorkspaceResolution || pubIoPackage.isWorkspace)) { + var root = await pubIoPackage.getWorkspaceRootPath(); + var cache = PubWorkspaceCache(root, PubWorkspaceCacheAction.get, offline); + if (!pubWorkspacesCache!.cacheIfNeeded(cache)) { continue; } - cmd = FlutterCmd(['pub', 'get'])..workingDirectory = dir; - } else { - cmd = pkg.pubCmd(pubGetArgs( - offline: options.offline, packagesDir: options.packagesDir)); } + var future = () async { await shellStdioLinesGrouper.runZoned(() async { try { - await runCmd(cmd, options: options); + await pubIoPackage.pubGet(offline: offline); } catch (e) { - stderr.writeln('Error in $pkg: $e'); + stderr.writeln('Error in $pubIoPackage: $e'); if (options.ignoreErrors ?? false) { // ok } else { diff --git a/lib/bin/pubupgrade.dart b/lib/bin/pubupgrade.dart index 74341d4..dce6daa 100755 --- a/lib/bin/pubupgrade.dart +++ b/lib/bin/pubupgrade.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:args/args.dart'; import 'package:dev_build/menu/menu_run_ci.dart'; import 'package:process_run/stdio.dart'; +import 'package:tekartik_pub/bin/src/pub_workspace_cache.dart'; import 'package:tekartik_pub/bin/src/pubbin_utils.dart'; import 'package:tekartik_pub/io.dart'; @@ -50,7 +51,7 @@ Future main(List arguments) async { if (rest.isEmpty) { rest = ['.']; } - + initPubWorkspacesCache(); await pubUpgrade( rest, PubGetOptions() @@ -64,28 +65,26 @@ Future main(List arguments) async { } Future pubUpgrade(List directories, PubGetOptions options) async { + var offline = options.offline ?? false; final pkgPaths = await recursivePubPath(directories); var futures = []; for (final dir in pkgPaths) { final pkg = PubPackage(dir); - ProcessCmd cmd; var pubIoPackage = PubIoPackage(dir); await pubIoPackage.ready; - var isFlutterPub = pubIoPackage.dofPub == 'flutter pub'; - if (isFlutterPub) { - if (!isFlutterSupported) { + + if (pubWorkspacesCache != null && + (pubIoPackage.hasWorkspaceResolution || pubIoPackage.isWorkspace)) { + var root = await pubIoPackage.getWorkspaceRootPath(); + var cache = PubWorkspaceCache(root, PubWorkspaceCacheAction.get, offline); + if (!pubWorkspacesCache!.cacheIfNeeded(cache)) { continue; } - cmd = FlutterCmd(['pub', 'upgrade'])..workingDirectory = dir; - } else { - cmd = pkg.pubCmd(pubUpgradeArgs( - offline: options.offline, packagesDir: options.packagesDir)); } - var future = () async { await shellStdioLinesGrouper.runZoned(() async { try { - await runCmd(cmd, options: options); + await pubIoPackage.pubUpgrade(offline: offline); } catch (e) { stderr.writeln('Error in $pkg: $e'); if (options.ignoreErrors ?? false) { diff --git a/lib/bin/src/pub_workspace_cache.dart b/lib/bin/src/pub_workspace_cache.dart new file mode 100644 index 0000000..452dbdc --- /dev/null +++ b/lib/bin/src/pub_workspace_cache.dart @@ -0,0 +1,60 @@ +enum PubWorkspaceCacheAction { get, upgrade, downgrade } + +/// Last action done on a workspace, invalide others. +class PubWorkspaceCache { + final String workspaceRoot; + final bool offline; + final PubWorkspaceCacheAction action; + + PubWorkspaceCache(this.workspaceRoot, this.action, this.offline); + + @override + int get hashCode => workspaceRoot.hashCode; + + @override + bool operator ==(Object other) { + if (other is PubWorkspaceCache) { + return workspaceRoot == other.workspaceRoot && + offline == other.offline && + action == other.action; + } + return false; + } +} + +/// Workspace cache +abstract class PubWorkspacesCache { + factory PubWorkspacesCache() => _PubWorkspacesCache(); + + /// Returns true if the cache was updated (i.e. must run, next call will return false) + bool cacheIfNeeded(PubWorkspaceCache cache); + PubWorkspaceCache? getWorkspaceCache(String workspaceRoot); +} + +class _PubWorkspacesCache implements PubWorkspacesCache { + final _map = {}; + + _PubWorkspacesCache(); + + @override + PubWorkspaceCache? getWorkspaceCache(String workspaceRoot) { + return _map[workspaceRoot]; + } + + @override + bool cacheIfNeeded(PubWorkspaceCache cache) { + var existing = _map[cache.workspaceRoot]; + if (existing != cache) { + _map[cache.workspaceRoot] = cache; + return true; + } + return false; + } +} + +PubWorkspacesCache? pubWorkspacesCache; + +/// Internal only use for run_ci binary for now +void initPubWorkspacesCache() { + pubWorkspacesCache = PubWorkspacesCache(); +}