Unverified Commit 126c58ef authored by Danny Tuppeny's avatar Danny Tuppeny Committed by GitHub

Add a `flutter create --list-samples` command (#28938)

* Add a `flutter create --list-samples` command

* Add some comments/docs

* Tweak text
parent 748c95f3
...@@ -95,6 +95,12 @@ class CreateCommand extends FlutterCommand { ...@@ -95,6 +95,12 @@ class CreateCommand extends FlutterCommand {
defaultsTo: null, defaultsTo: null,
valueHelp: 'id', valueHelp: 'id',
); );
argParser.addOption(
'list-samples',
help: 'Specifies a JSON output file for a listing of Flutter code samples '
'that can created with --sample.',
valueHelp: 'path',
);
argParser.addFlag( argParser.addFlag(
'overwrite', 'overwrite',
negatable: true, negatable: true,
...@@ -179,6 +185,11 @@ class CreateCommand extends FlutterCommand { ...@@ -179,6 +185,11 @@ class CreateCommand extends FlutterCommand {
return null; return null;
} }
/// The hostname for the Flutter docs for the current channel.
String get _snippetsHost => FlutterVersion.instance.channel == 'stable'
? 'docs.flutter.io'
: 'master-docs.flutter.io';
Future<String> _fetchSampleFromServer(String sampleId) async { Future<String> _fetchSampleFromServer(String sampleId) async {
// Sanity check the sampleId // Sanity check the sampleId
if (sampleId.contains(RegExp(r'[^-\w\.]'))) { if (sampleId.contains(RegExp(r'[^-\w\.]'))) {
...@@ -186,14 +197,36 @@ class CreateCommand extends FlutterCommand { ...@@ -186,14 +197,36 @@ class CreateCommand extends FlutterCommand {
'documentation and try again.'); 'documentation and try again.');
} }
final String host = FlutterVersion.instance.channel == 'stable' return utf8.decode(await fetchUrl(Uri.https(_snippetsHost, 'snippets/$sampleId.dart')));
? 'docs.flutter.io' }
: 'master-docs.flutter.io';
return utf8.decode(await fetchUrl(Uri.https(host, 'snippets/$sampleId.dart'))); /// Fetches the samples index file from the Flutter docs website.
Future<String> _fetchSamplesIndexFromServer() async {
return utf8.decode(await fetchUrl(Uri.https(_snippetsHost, 'snippets/index.json')));
}
/// Fetches the samples index file from the server and writes it to
/// [outputFilePath].
Future<void> _writeSamplesJson(String outputFilePath) async {
try {
final File outputFile = fs.file(outputFilePath);
if (outputFile.existsSync()) {
throwToolExit('File "$outputFilePath" already exists', exitCode: 1);
}
outputFile.writeAsStringSync(await _fetchSamplesIndexFromServer());
printStatus('Wrote samples JSON to "$outputFilePath"');
} catch (e) {
throwToolExit('Failed to write samples JSON to "$outputFilePath": $e', exitCode: 2);
}
} }
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
if (argResults['list-samples'] != null) {
await _writeSamplesJson(argResults['list-samples']);
return null;
}
if (argResults.rest.isEmpty) if (argResults.rest.isEmpty)
throwToolExit('No option specified for the output directory.\n$usage', exitCode: 2); throwToolExit('No option specified for the output directory.\n$usage', exitCode: 2);
......
...@@ -27,6 +27,10 @@ final Generator _kNoColorTerminalPlatform = () => FakePlatform.fromPlatform(cons ...@@ -27,6 +27,10 @@ final Generator _kNoColorTerminalPlatform = () => FakePlatform.fromPlatform(cons
final Map<Type, Generator> noColorTerminalOverride = <Type, Generator> { final Map<Type, Generator> noColorTerminalOverride = <Type, Generator> {
Platform: _kNoColorTerminalPlatform, Platform: _kNoColorTerminalPlatform,
}; };
const String samplesIndexJson = '''[
{ "id": "sample1" },
{ "id": "sample2" }
]''';
void main() { void main() {
Directory tempDir; Directory tempDir;
...@@ -888,6 +892,41 @@ void main() { ...@@ -888,6 +892,41 @@ void main() {
}, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{ }, timeout: allowForRemotePubInvocation, overrides: <Type, Generator>{
HttpClientFactory: () => () => MockHttpClient(200, result: 'void main() {}'), HttpClientFactory: () => () => MockHttpClient(200, result: 'void main() {}'),
}); });
testUsingContext('can write samples index to disk', () async {
final String outputFile = fs.path.join(tempDir.path, 'flutter_samples.json');
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
final List<String> args = <String>[
'create',
'--list-samples',
outputFile
];
await runner.run(args);
final File expectedFile = fs.file(outputFile);
expect(expectedFile.existsSync(), isTrue);
expect(expectedFile.readAsStringSync(), equals(samplesIndexJson));
}, overrides: <Type, Generator>{
HttpClientFactory: () =>
() => MockHttpClient(200, result: samplesIndexJson),
});
testUsingContext('provides an error to the user if samples json download fails', () async {
final String outputFile = fs.path.join(tempDir.path, 'flutter_samples.json');
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
final List<String> args = <String>[
'create',
'--list-samples',
outputFile
];
await expectLater(runner.run(args), throwsToolExit(exitCode: 2, message: 'Failed to write samples'));
expect(fs.file(outputFile).existsSync(), isFalse);
}, overrides: <Type, Generator>{
HttpClientFactory: () =>
() => MockHttpClient(404, result: 'not found'),
});
} }
Future<void> _createProject( Future<void> _createProject(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment