Skip to content

Commit

Permalink
refactor(shorebird_cli): ShorebirdFlutterManager use Git wrapper (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel authored Aug 7, 2023
1 parent 50650b1 commit 1ec6af9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 115 deletions.
2 changes: 2 additions & 0 deletions packages/shorebird_cli/bin/shorebird.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:shorebird_cli/src/cache.dart';
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
import 'package:shorebird_cli/src/command_runner.dart';
import 'package:shorebird_cli/src/doctor.dart';
import 'package:shorebird_cli/src/git.dart';
import 'package:shorebird_cli/src/gradlew.dart';
import 'package:shorebird_cli/src/ios_deploy.dart';
import 'package:shorebird_cli/src/java.dart';
Expand Down Expand Up @@ -37,6 +38,7 @@ Future<void> main(List<String> args) async {
codePushClientWrapperRef,
doctorRef,
engineConfigRef,
gitRef,
gradlewRef,
iosDeployRef,
javaRef,
Expand Down
7 changes: 7 additions & 0 deletions packages/shorebird_cli/lib/src/git.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import 'dart:io';

import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/process.dart';

/// A reference to a [Git] instance.
final gitRef = create(Git.new);

/// The [Git] instance available in the current zone.
Git get git => read(gitRef);

/// A wrapper around all git related functionality.
class Git {
static const executable = 'git';
Expand Down
52 changes: 11 additions & 41 deletions packages/shorebird_cli/lib/src/shorebird_flutter_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/git.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';

/// A reference to a [ShorebirdFlutterManager] instance.
Expand All @@ -28,51 +28,21 @@ class ShorebirdFlutterManager {
p.join(shorebirdEnv.flutterDirectory.parent.path, revision),
);
if (targetDirectory.existsSync()) return;
const executable = 'git';

// Clone the Shorebird Flutter repo into the target directory.
final cloneArgs = [
'clone',
'--filter=tree:0',
flutterGitUrl,
'--no-checkout',
targetDirectory.path,
];
final cloneResult = await process.run(
executable,
cloneArgs,
runInShell: true,
await git.clone(
url: flutterGitUrl,
outputDirectory: targetDirectory.path,
args: [
'--filter=tree:0',
'--no-checkout',
],
);
if (cloneResult.exitCode != 0) {
throw ProcessException(
executable,
cloneArgs,
'${cloneResult.stderr}',
cloneResult.exitCode,
);
}

// Checkout the correct revision.
final checkoutArgs = [
'-C',
targetDirectory.path,
'-c',
'advice.detachedHead=false',
'checkout',
revision,
];
final checkoutResult = await process.run(
executable,
checkoutArgs,
runInShell: true,
await git.checkout(
directory: targetDirectory.path,
revision: revision,
);
if (checkoutResult.exitCode != 0) {
throw ProcessException(
executable,
checkoutArgs,
'${checkoutResult.stderr}',
checkoutResult.exitCode,
);
}
}
}
126 changes: 52 additions & 74 deletions packages/shorebird_cli/test/src/shorebird_flutter_manager_test.dart
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
import 'dart:io';

import 'package:mason_logger/mason_logger.dart';
import 'package:mocktail/mocktail.dart';
import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/process.dart';
import 'package:shorebird_cli/src/git.dart';
import 'package:shorebird_cli/src/shorebird_env.dart';
import 'package:shorebird_cli/src/shorebird_flutter_manager.dart';
import 'package:test/test.dart';

class _MockShorebirdEnv extends Mock implements ShorebirdEnv {}

class _MockShorebirdProcess extends Mock implements ShorebirdProcess {}
class _MockGit extends Mock implements Git {}

class _MockShorebirdProcessResult extends Mock
implements ShorebirdProcessResult {}
class _MockShorebirdEnv extends Mock implements ShorebirdEnv {}

void main() {
group(ShorebirdFlutterManager, () {
late Directory shorebirdRoot;
late Directory flutterDirectory;
late Git git;
late ShorebirdEnv shorebirdEnv;
late ShorebirdProcessResult cloneProcessResult;
late ShorebirdProcessResult checkoutProcessResult;
late ShorebirdProcess shorebirdProcess;
late ShorebirdFlutterManager shorebirdFlutterManager;

R runWithOverrides<R>(R Function() body) {
return runScoped(
body,
values: {
processRef.overrideWith(() => shorebirdProcess),
gitRef.overrideWith(() => git),
shorebirdEnvRef.overrideWith(() => shorebirdEnv),
},
);
Expand All @@ -39,34 +33,24 @@ void main() {
setUp(() {
shorebirdRoot = Directory.systemTemp.createTempSync();
flutterDirectory = Directory(p.join(shorebirdRoot.path, 'flutter'));
git = _MockGit();
shorebirdEnv = _MockShorebirdEnv();
cloneProcessResult = _MockShorebirdProcessResult();
checkoutProcessResult = _MockShorebirdProcessResult();
shorebirdProcess = _MockShorebirdProcess();
shorebirdFlutterManager = runWithOverrides(ShorebirdFlutterManager.new);

when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
when(
() => shorebirdProcess.run(
any(),
any(),
runInShell: any(named: 'runInShell'),
() => git.clone(
url: any(named: 'url'),
outputDirectory: any(named: 'outputDirectory'),
args: any(named: 'args'),
),
).thenAnswer((invocation) async {
final executable = invocation.positionalArguments[0] as String;
final args = invocation.positionalArguments[1] as List<String>;
if (executable == 'git' && args[0] == 'clone') {
return cloneProcessResult;
} else if (executable == 'git' && args[4] == 'checkout') {
return checkoutProcessResult;
} else {
throw UnimplementedError();
}
});
when(() => cloneProcessResult.exitCode).thenReturn(ExitCode.success.code);
).thenAnswer((_) async => {});
when(
() => checkoutProcessResult.exitCode,
).thenReturn(ExitCode.success.code);
() => git.checkout(
directory: any(named: 'directory'),
revision: any(named: 'revision'),
),
).thenAnswer((_) async => {});
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
});

group('installRevision', () {
Expand All @@ -80,73 +64,67 @@ void main() {
() => shorebirdFlutterManager.installRevision(revision: revision),
);

verifyNever(() => shorebirdProcess.run(any(), any()));
verifyNever(
() => git.clone(
url: any(named: 'url'),
outputDirectory: any(named: 'outputDirectory'),
args: any(named: 'args'),
),
);
});

test('throws ProcessException if unable to clone', () async {
test('throws exception if unable to clone', () async {
final exception = Exception('oops');
when(
() => cloneProcessResult.exitCode,
).thenReturn(ExitCode.software.code);
() => git.clone(
url: any(named: 'url'),
outputDirectory: any(named: 'outputDirectory'),
args: any(named: 'args'),
),
).thenThrow(exception);

await expectLater(
runWithOverrides(
() => shorebirdFlutterManager.installRevision(revision: revision),
),
throwsA(isA<ProcessException>()),
throwsA(exception),
);

verify(
() => shorebirdProcess.run(
'git',
[
'clone',
'--filter=tree:0',
ShorebirdFlutterManager.flutterGitUrl,
'--no-checkout',
p.join(flutterDirectory.parent.path, revision)
],
runInShell: true,
() => git.clone(
url: ShorebirdFlutterManager.flutterGitUrl,
outputDirectory: p.join(flutterDirectory.parent.path, revision),
args: ['--filter=tree:0', '--no-checkout'],
),
).called(1);
});

test('throws ProcessException if unable to checkout revision', () async {
test('throws exception if unable to checkout revision', () async {
final exception = Exception('oops');
when(
() => checkoutProcessResult.exitCode,
).thenReturn(ExitCode.software.code);
() => git.checkout(
directory: any(named: 'directory'),
revision: any(named: 'revision'),
),
).thenThrow(exception);

await expectLater(
runWithOverrides(
() => shorebirdFlutterManager.installRevision(revision: revision),
),
throwsA(isA<ProcessException>()),
throwsA(exception),
);

verify(
() => shorebirdProcess.run(
'git',
[
'clone',
'--filter=tree:0',
ShorebirdFlutterManager.flutterGitUrl,
'--no-checkout',
p.join(flutterDirectory.parent.path, revision)
],
runInShell: true,
() => git.clone(
url: ShorebirdFlutterManager.flutterGitUrl,
outputDirectory: p.join(flutterDirectory.parent.path, revision),
args: ['--filter=tree:0', '--no-checkout'],
),
).called(1);
verify(
() => shorebirdProcess.run(
'git',
[
'-C',
p.join(flutterDirectory.parent.path, revision),
'-c',
'advice.detachedHead=false',
'checkout',
revision,
],
runInShell: true,
() => git.checkout(
directory: p.join(flutterDirectory.parent.path, revision),
revision: revision,
),
).called(1);
});
Expand Down

0 comments on commit 1ec6af9

Please sign in to comment.