Ian Hickson 449f4a6673
License update (#45373)
* Update project.pbxproj files to say Flutter rather than Chromium

Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright.

* Update the copyright notice checker to require a standard notice on all files

* Update copyrights on Dart files. (This was a mechanical commit.)

* Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine.

Some were already marked "The Flutter Authors", not clear why. Their
dates have been normalized. Some were missing the blank line after the
license. Some were randomly different in trivial ways for no apparent
reason (e.g. missing the trailing period).

* Clean up the copyrights in non-Dart files. (Manual edits.)

Also, make sure templates don't have copyrights.

* Fix some more ORGANIZATIONNAMEs
2019-11-27 15:04:02 -08:00

255 lines
8.4 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 '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../build_info.dart';
import '../cache.dart';
import '../globals.dart';
import '../runner/flutter_command.dart';
/// The directory in the Flutter cache for each platform's artifacts.
const Map<TargetPlatform, String> flutterArtifactPlatformDirectory = <TargetPlatform, String>{
TargetPlatform.windows_x64: 'windows-x64',
TargetPlatform.linux_x64: 'linux-x64',
};
// TODO(jonahwilliams): this should come from a configuration in each build
// directory.
const Map<TargetPlatform, List<String>> artifactFilesByPlatform = <TargetPlatform, List<String>>{
TargetPlatform.windows_x64: <String>[
'flutter_windows.dll',
'flutter_windows.dll.exp',
'flutter_windows.dll.lib',
'flutter_windows.dll.pdb',
'flutter_export.h',
'flutter_messenger.h',
'flutter_plugin_registrar.h',
'flutter_windows.h',
'icudtl.dat',
'cpp_client_wrapper/',
],
};
/// Copies desktop artifacts to local cache directories.
class UnpackCommand extends FlutterCommand {
UnpackCommand() {
argParser.addOption(
'target-platform',
allowed: <String>['windows-x64', 'linux-x64'],
);
argParser.addOption('cache-dir',
help: 'Location to output platform specific artifacts.');
}
@override
String get description => '(DEPRECATED) unpack desktop artifacts';
@override
String get name => 'unpack';
@override
bool get hidden => true;
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
final Set<DevelopmentArtifact> result = <DevelopmentArtifact>{};
final TargetPlatform targetPlatform = getTargetPlatformForName(stringArg('target-platform'));
switch (targetPlatform) {
case TargetPlatform.windows_x64:
result.add(DevelopmentArtifact.windows);
break;
case TargetPlatform.linux_x64:
result.add(DevelopmentArtifact.linux);
break;
default:
}
return result;
}
@override
Future<FlutterCommandResult> runCommand() async {
final String targetName = stringArg('target-platform');
final String targetDirectory = stringArg('cache-dir');
if (!fs.directory(targetDirectory).existsSync()) {
fs.directory(targetDirectory).createSync(recursive: true);
}
final TargetPlatform targetPlatform = getTargetPlatformForName(targetName);
final ArtifactUnpacker flutterArtifactFetcher = ArtifactUnpacker(targetPlatform);
bool success = true;
if (artifacts is LocalEngineArtifacts) {
final LocalEngineArtifacts localEngineArtifacts = artifacts as LocalEngineArtifacts;
success = flutterArtifactFetcher.copyLocalBuildArtifacts(
localEngineArtifacts.engineOutPath,
targetDirectory,
);
} else {
success = flutterArtifactFetcher.copyCachedArtifacts(
targetDirectory,
);
}
if (!success) {
throwToolExit('Failed to unpack desktop artifacts.');
}
return null;
}
}
/// Manages the copying of cached or locally built Flutter artifacts, including
/// tracking the last-copied versions and updating only if necessary.
class ArtifactUnpacker {
/// Creates a new fetcher for the given configuration.
const ArtifactUnpacker(this.platform);
/// The platform to copy artifacts for.
final TargetPlatform platform;
/// Checks [targetDirectory] to see if artifacts have already been copied for
/// the current hash, and if not, copies the artifacts for [platform] from the
/// Flutter cache (after ensuring that the cache is present).
///
/// Returns true if the artifacts were successfully copied, or were already
/// present with the correct hash.
bool copyCachedArtifacts(String targetDirectory) {
String cacheStamp;
switch (platform) {
case TargetPlatform.windows_x64:
cacheStamp = 'windows-sdk';
break;
case TargetPlatform.linux_x64:
return true;
default:
throwToolExit('Unsupported target platform: $platform');
}
final String targetHash =
readHashFileIfPossible(Cache.instance.getStampFileFor(cacheStamp));
if (targetHash == null) {
printError('Failed to find engine stamp file');
return false;
}
try {
final String currentHash = _lastCopiedHash(targetDirectory);
if (currentHash == null || targetHash != currentHash) {
// Copy them to the target directory.
final String flutterCacheDirectory = fs.path.join(
Cache.flutterRoot,
'bin',
'cache',
'artifacts',
'engine',
flutterArtifactPlatformDirectory[platform],
);
if (!_copyArtifactFiles(flutterCacheDirectory, targetDirectory)) {
return false;
}
_setLastCopiedHash(targetDirectory, targetHash);
printTrace('Copied artifacts for version $targetHash.');
} else {
printTrace('Artifacts for version $targetHash already present.');
}
} catch (error, stackTrace) {
printError(stackTrace.toString());
printError(error.toString());
return false;
}
return true;
}
/// Acts like [copyCachedArtifacts], replacing the artifacts and updating
/// the version stamp, except that it pulls the artifact from a local engine
/// build with the given [buildConfiguration] (e.g., host_debug_unopt) whose
/// checkout is rooted at [engineRoot].
bool copyLocalBuildArtifacts(String buildOutput, String targetDirectory) {
if (!_copyArtifactFiles(buildOutput, targetDirectory)) {
return false;
}
// Update the hash file to indicate that it's a local build, so that it's
// obvious where it came from.
_setLastCopiedHash(targetDirectory, 'local build: $buildOutput');
return true;
}
/// Copies the artifact files for [platform] from [sourceDirectory] to
/// [targetDirectory].
bool _copyArtifactFiles(String sourceDirectory, String targetDirectory) {
final List<String> artifactFiles = artifactFilesByPlatform[platform];
if (artifactFiles == null) {
printError('Unsupported platform: $platform.');
return false;
}
try {
fs.directory(targetDirectory).createSync(recursive: true);
for (final String entityName in artifactFiles) {
final String sourcePath = fs.path.join(sourceDirectory, entityName);
final String targetPath = fs.path.join(targetDirectory, entityName);
if (entityName.endsWith('/')) {
copyDirectorySync(
fs.directory(sourcePath),
fs.directory(targetPath),
);
} else {
fs.file(sourcePath)
.copySync(fs.path.join(targetDirectory, entityName));
}
}
printTrace('Copied artifacts from $sourceDirectory.');
} catch (e, stackTrace) {
printError(e.message as String);
printError(stackTrace.toString());
return false;
}
return true;
}
/// Returns a File object for the file containing the last copied hash
/// in [directory].
File _lastCopiedHashFile(String directory) {
return fs.file(fs.path.join(directory, '.last_artifact_version'));
}
/// Returns the hash of the artifacts last copied to [directory], or null if
/// they haven't been copied.
String _lastCopiedHash(String directory) {
// Sanity check that at least one file is present; this won't catch every
// case, but handles someone deleting all the non-hidden cached files to
// force fresh copy.
final String artifactFilePath = fs.path.join(
directory,
artifactFilesByPlatform[platform].first,
);
if (!fs.file(artifactFilePath).existsSync()) {
return null;
}
final File hashFile = _lastCopiedHashFile(directory);
return readHashFileIfPossible(hashFile);
}
/// Writes [hash] to the file that stores the last copied hash for
/// in [directory].
void _setLastCopiedHash(String directory, String hash) {
_lastCopiedHashFile(directory).writeAsStringSync(hash);
}
/// Returns the engine hash from [file] as a String, or null.
///
/// If the file is missing, or cannot be read, returns null.
String readHashFileIfPossible(File file) {
if (!file.existsSync()) {
return null;
}
try {
return file.readAsStringSync().trim();
} on FileSystemException {
// If the file can't be read for any reason, just treat it as missing.
return null;
}
}
}