mirror of
https://github.com/flutter/flutter
synced 2024-08-25 02:46:31 +00:00
![Christopher Fujino](/assets/img/avatar_default.png)
I plan to extend the prepare_package.dart script to upload the flutter preview device ([design doc](https://docs.google.com/document/d/1AzI-_Uk2v1LA2kKKFJ7gVD4xcakXJ6yVZiS5Ek6RHtg/edit#heading=h.byp03plw7mg9)). However, given that that script is one large >1k line file, I decided to organize it into smaller libraries in this PR. There should be no behavioral change in this PR, this is a cleanup only. I made the following changes: 1. Created a //dev/bots/prepare_package/ directory to contain helper libraries 2. Moved everything but the `main()` function in //dev/bots/prepare_package.dart into one of 4 helper libraries under the new directory from step 1: a. archive_creator.dart which contains the code that creates archive directory locally on disk b. archive_publisher.dart which contains the code that uploads the archive to cloud storage c. common.dart for shared constants and definitions d. process_runner.dart for an abstraction over running sub-processes 3. Changed all definitions to `File` and `Directory` from `dart:io` to use the testable versions from `package:file`. This allowed me to use the `MemoryFileSystem` in the unit tests, rather than creating real temp file system directories.
165 lines
5.1 KiB
Dart
165 lines
5.1 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:io' show exit, stderr;
|
|
|
|
import 'package:args/args.dart';
|
|
import 'package:file/file.dart';
|
|
import 'package:file/local.dart';
|
|
|
|
import 'prepare_package/archive_creator.dart';
|
|
import 'prepare_package/archive_publisher.dart';
|
|
import 'prepare_package/common.dart';
|
|
|
|
const FileSystem fs = LocalFileSystem();
|
|
|
|
/// Prepares a flutter git repo to be packaged up for distribution. It mainly
|
|
/// serves to populate the .pub-preload-cache with any appropriate Dart
|
|
/// packages, and the flutter cache in bin/cache with the appropriate
|
|
/// dependencies and snapshots.
|
|
///
|
|
/// Archives contain the executables and customizations for the platform that
|
|
/// they are created on.
|
|
Future<void> main(List<String> rawArguments) async {
|
|
final ArgParser argParser = ArgParser();
|
|
argParser.addOption(
|
|
'temp_dir',
|
|
help: 'A location where temporary files may be written. Defaults to a '
|
|
'directory in the system temp folder. Will write a few GiB of data, '
|
|
'so it should have sufficient free space. If a temp_dir is not '
|
|
'specified, then the default temp_dir will be created, used, and '
|
|
'removed automatically.',
|
|
);
|
|
argParser.addOption('revision',
|
|
help: 'The Flutter git repo revision to build the '
|
|
'archive with. Must be the full 40-character hash. Required.');
|
|
argParser.addOption(
|
|
'branch',
|
|
allowed: Branch.values.map<String>((Branch branch) => branch.name),
|
|
help: 'The Flutter branch to build the archive with. Required.',
|
|
);
|
|
argParser.addOption(
|
|
'output',
|
|
help: 'The path to the directory where the output archive should be '
|
|
'written. If --output is not specified, the archive will be written to '
|
|
"the current directory. If the output directory doesn't exist, it, and "
|
|
'the path to it, will be created.',
|
|
);
|
|
argParser.addFlag(
|
|
'publish',
|
|
help: 'If set, will publish the archive to Google Cloud Storage upon '
|
|
'successful creation of the archive. Will publish under this '
|
|
'directory: $baseUrl$releaseFolder',
|
|
);
|
|
argParser.addFlag(
|
|
'force',
|
|
abbr: 'f',
|
|
help: 'Overwrite a previously uploaded package.',
|
|
);
|
|
argParser.addFlag(
|
|
'dry_run',
|
|
negatable: false,
|
|
help: 'Prints gsutil commands instead of executing them.',
|
|
);
|
|
argParser.addFlag(
|
|
'help',
|
|
negatable: false,
|
|
help: 'Print help for this command.',
|
|
);
|
|
|
|
final ArgResults parsedArguments = argParser.parse(rawArguments);
|
|
|
|
if (parsedArguments['help'] as bool) {
|
|
print(argParser.usage);
|
|
exit(0);
|
|
}
|
|
|
|
void errorExit(String message, {int exitCode = -1}) {
|
|
stderr.write('Error: $message\n\n');
|
|
stderr.write('${argParser.usage}\n');
|
|
exit(exitCode);
|
|
}
|
|
|
|
if (!parsedArguments.wasParsed('revision')) {
|
|
errorExit('Invalid argument: --revision must be specified.');
|
|
}
|
|
final String revision = parsedArguments['revision'] as String;
|
|
if (revision.length != 40) {
|
|
errorExit('Invalid argument: --revision must be the entire hash, not just a prefix.');
|
|
}
|
|
|
|
if (!parsedArguments.wasParsed('branch')) {
|
|
errorExit('Invalid argument: --branch must be specified.');
|
|
}
|
|
|
|
final String? tempDirArg = parsedArguments['temp_dir'] as String?;
|
|
final Directory tempDir;
|
|
bool removeTempDir = false;
|
|
if (tempDirArg == null || tempDirArg.isEmpty) {
|
|
tempDir = fs.systemTempDirectory.createTempSync('flutter_package.');
|
|
removeTempDir = true;
|
|
} else {
|
|
tempDir = fs.directory(tempDirArg);
|
|
if (!tempDir.existsSync()) {
|
|
errorExit("Temporary directory $tempDirArg doesn't exist.");
|
|
}
|
|
}
|
|
|
|
final Directory outputDir;
|
|
if (parsedArguments['output'] == null) {
|
|
outputDir = tempDir;
|
|
} else {
|
|
outputDir = fs.directory(parsedArguments['output'] as String);
|
|
if (!outputDir.existsSync()) {
|
|
outputDir.createSync(recursive: true);
|
|
}
|
|
}
|
|
|
|
final bool publish = parsedArguments['publish'] as bool;
|
|
final bool dryRun = parsedArguments['dry_run'] as bool;
|
|
final Branch branch = Branch.values.byName(parsedArguments['branch'] as String);
|
|
final ArchiveCreator creator = ArchiveCreator(
|
|
tempDir,
|
|
outputDir,
|
|
revision,
|
|
branch,
|
|
fs: fs,
|
|
strict: publish && !dryRun,
|
|
);
|
|
int exitCode = 0;
|
|
late String message;
|
|
try {
|
|
final Map<String, String> version = await creator.initializeRepo();
|
|
final File outputFile = await creator.createArchive();
|
|
final ArchivePublisher publisher = ArchivePublisher(
|
|
tempDir,
|
|
revision,
|
|
branch,
|
|
version,
|
|
outputFile,
|
|
dryRun,
|
|
fs: fs,
|
|
);
|
|
await publisher.generateLocalMetadata();
|
|
if (parsedArguments['publish'] as bool) {
|
|
await publisher.publishArchive(parsedArguments['force'] as bool);
|
|
}
|
|
} on PreparePackageException catch (e) {
|
|
exitCode = e.exitCode;
|
|
message = e.message;
|
|
} catch (e) {
|
|
exitCode = -1;
|
|
message = e.toString();
|
|
} finally {
|
|
if (removeTempDir) {
|
|
tempDir.deleteSync(recursive: true);
|
|
}
|
|
if (exitCode != 0) {
|
|
errorExit(message, exitCode: exitCode);
|
|
}
|
|
exit(0);
|
|
}
|
|
}
|