Skip to content

Commit

Permalink
feat(shorebird_cli): add cache (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel committed Apr 6, 2023
1 parent 9641707 commit 82b2931
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 3 deletions.
117 changes: 117 additions & 0 deletions packages/shorebird_cli/lib/src/cache.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import 'dart:io' hide Platform;
import 'dart:isolate';

import 'package:archive/archive_io.dart';
import 'package:http/http.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:shorebird_cli/src/engine_revision.dart';
import 'package:shorebird_cli/src/shorebird_paths.dart';

class Cache {
Cache({Platform platform = const LocalPlatform()}) {
registerArtifact(PatchArtifact(cache: this, platform: platform));
}

void registerArtifact(CachedArtifact artifact) => _artifacts.add(artifact);

Future<void> updateAll() async {
for (final artifact in _artifacts) {
if (await artifact.isUpToDate()) {
continue;
}

await artifact.download();
}
}

/// Get a named directory from with the cache's artifact directory;
/// for example, `foo` would return `bin/cache/artifacts/foo`.
Directory getArtifactDirectory(String name) {
return Directory(p.join(shorebirdArtifactsDirectory.path, name));
}

/// The Shorebird cached artifacts directory.
static Directory get shorebirdArtifactsDirectory => Directory(
p.join(
ShorebirdPaths.shorebirdCacheDirectory.path,
'artifacts',
),
);

final List<CachedArtifact> _artifacts = [];

String get storageBaseUrl => 'https://storage.googleapis.com';

String get storageBucket => 'download.shorebird.dev';
}

abstract class CachedArtifact {
const CachedArtifact({required this.cache});

final Cache cache;

String get name;

String get storagePath;

List<String> get executables => [];

Directory get location => cache.getArtifactDirectory(name);

Future<bool> isUpToDate() async => location.existsSync();

Future<void> download() async {
final url = '${cache.storageBaseUrl}/${cache.storageBucket}/$storagePath';
final client = Client();
final request = Request('GET', Uri.parse(url));
final response = await client.send(request);
client.close();

final tempDir = Directory.systemTemp.createTempSync();
final archivePath = p.join(tempDir.path, '$name.zip');
await response.stream.pipe(File(archivePath).openWrite());

await Isolate.run(
() async {
final inputStream = InputFileStream(archivePath);
final archive = ZipDecoder().decodeBuffer(inputStream);
extractArchiveToDisk(archive, location.path);
},
);

for (final executable in executables) {
final process = await Process.start(
'chmod',
['+x', p.join(location.path, executable)],
);
await process.exitCode;
}
}
}

class PatchArtifact extends CachedArtifact {
PatchArtifact({required super.cache, required this.platform});

final Platform platform;

@override
String get name => 'patch';

@override
List<String> get executables => ['patch'];

@override
String get storagePath {
var artifactName = 'patch-';
if (platform.isMacOS) {
artifactName += 'darwin-x64.zip';
} else if (platform.isLinux) {
artifactName += 'linux-x64.zip';
} else if (platform.isWindows) {
artifactName += 'windows-x64.zip';
}

return 'shorebird/$shorebirdEngineRevision/$artifactName';
}
}
4 changes: 4 additions & 0 deletions packages/shorebird_cli/lib/src/command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:http/http.dart' as http;
import 'package:mason_logger/mason_logger.dart';
import 'package:meta/meta.dart';
import 'package:shorebird_cli/src/auth/auth.dart';
import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/shorebird_process.dart';
import 'package:shorebird_cli/src/validators/validators.dart';
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
Expand All @@ -28,11 +29,13 @@ abstract class ShorebirdCommand extends Command<int> {
ShorebirdCommand({
required this.logger,
Auth? auth,
Cache? cache,
CodePushClientBuilder? buildCodePushClient,
RunProcess? runProcess,
StartProcess? startProcess,
ShorebirdFlutterValidator? flutterValidator,
}) : auth = auth ?? Auth(),
cache = cache ?? Cache(),
buildCodePushClient = buildCodePushClient ?? CodePushClient.new,
runProcess = runProcess ?? ShorebirdProcess.run,
startProcess = startProcess ?? ShorebirdProcess.start {
Expand All @@ -41,6 +44,7 @@ abstract class ShorebirdCommand extends Command<int> {
}

final Auth auth;
final Cache cache;
final CodePushClientBuilder buildCodePushClient;
final Logger logger;
final RunProcess runProcess;
Expand Down
8 changes: 6 additions & 2 deletions packages/shorebird_cli/lib/src/commands/patch_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class PatchCommand extends ShorebirdCommand
return ExitCode.usage.code;
}

await cache.updateAll();

final buildProgress = logger.progress('Building patch');
try {
await buildRelease();
Expand Down Expand Up @@ -377,8 +379,10 @@ Please create a release using "shorebird release" and try again.
}) async {
final tempDir = await Directory.systemTemp.createTemp();
final diffPath = p.join(tempDir.path, 'diff.patch');

final diffExecutable = p.join('patch');
final diffExecutable = p.join(
cache.getArtifactDirectory('patch').path,
'patch',
);
final diffArguments = [
releaseArtifactPath,
patchArtifactPath,
Expand Down
5 changes: 5 additions & 0 deletions packages/shorebird_cli/lib/src/shorebird_environment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ abstract class ShorebirdEnvironment {
),
);

/// The Shorebird cache directory.
static Directory get shorebirdCacheDirectory => Directory(
p.join(shorebirdRoot.path, 'bin', 'cache'),
);

/// The Shorebird-vended Flutter binary.
static File get flutterBinaryFile => File(
p.join(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:http/http.dart' as http;
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
Expand Down

0 comments on commit 82b2931

Please sign in to comment.