blob: 41a1c38c8a7a26424ee9c5ab21782af4838c026d [file] [log] [blame]
// Copyright 2023 The Chromium 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:io';
import 'package:args/command_runner.dart';
import 'package:cli_util/cli_logging.dart';
import 'package:devtools_tool/model.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as path;
import '../utils.dart';
const _fromPathFlag = 'from-path';
const _useCacheFlag = 'use-cache';
/// This command updates the the Flutter SDK contained in the 'tool/' directory
/// to the latest Flutter candidate branch.
///
/// When the '--from-path' flag is passed, the Flutter SDK that is on PATH (your
/// local flutter/flutter git checkout) will be updated as well.
///
/// This command will use the Flutter version from the 'flutter-candidate.txt'
/// file in the repository root, unless the '--no-use-cache' flag is passed,
/// in which case it will run the 'tool/latest_flutter_candidate.sh' script to
/// fetch the latest version from upstream.
///
/// The version from 'flutter-candidate.txt' should be identical most of the
/// time since the GitHub workflow that updates this file runs twice per day.
///
/// To run this script:
/// `devtools_tool update-flutter-sdk [--from-path] [--no-use-cache]`
class UpdateFlutterSdkCommand extends Command {
UpdateFlutterSdkCommand() {
argParser
..addFlag(
_fromPathFlag,
abbr: 'p',
negatable: false,
help: 'Update the Flutter SDK that is on PATH (your local '
'flutter/flutter git checkout)',
)
..addFlag(
_useCacheFlag,
negatable: true,
defaultsTo: true,
help: 'Update the Flutter SDK(s) to the cached Flutter version stored '
'in "flutter-candidate.txt" instead of the latest version at '
'"https://flutter.googlesource.com/mirrors/flutter/"',
);
}
@override
String get name => 'update-flutter-sdk';
@override
String get description =>
'Updates the the Flutter SDK contained in the \'tool/\' directory to the '
'latest Flutter candidate branch. Optionally, can also update the Flutter'
'SDK that is on PATH (your local flutter/flutter git checkout).';
@override
Future run() async {
final updateFlutterFromPath = argResults![_fromPathFlag];
final useCachedVersion = argResults![_useCacheFlag];
final log = Logger.standard();
// TODO(kenz): we can remove this if we can rewrite the
// 'latest_flutter_candidate.sh' script as a Dart script, or if we instead
// duplicate it as a Windows script (we may need this to be a non-Dart
// script for execution on the bots before we have a Dart SDK available).
if (Platform.isWindows && !useCachedVersion) {
log.stderr(
'On windows, you can only use the cached Flutter version from '
'"flutter-candidate.txt". Please remove the "--no-use-cache" flag and '
'try again.',
);
return 1;
}
final repo = DevToolsRepo.getInstance();
final processManager = ProcessManager();
late String flutterTag;
if (useCachedVersion) {
flutterTag =
'tags/${repo.readFile(Uri.parse('flutter-candidate.txt')).trim()}';
} else {
flutterTag = (await processManager.runProcess(
CliCommand('sh latest_flutter_candidate.sh'),
workingDirectory: repo.toolDirectoryPath,
))
.stdout
.replaceFirst('refs/', '')
.trim();
}
log.stdout(
'Updating to Flutter version '
'${useCachedVersion ? 'from cache' : 'from upstream'}: $flutterTag ',
);
if (updateFlutterFromPath) {
final sdk = FlutterSdk.current;
log.stdout('Updating local flutter/flutter repository...');
// Verify we have an upstream remote to pull from.
await findRemote(
processManager,
remoteId: 'flutter/flutter.git',
workingDirectory: sdk.sdkPath,
);
await processManager.runAll(
commands: [
CliCommand.git(cmd: 'stash'),
CliCommand.git(cmd: 'fetch upstream'),
CliCommand.git(cmd: 'checkout upstream/master'),
CliCommand.git(cmd: 'reset --hard upstream/master'),
CliCommand.git(cmd: 'checkout $flutterTag -f'),
CliCommand.flutter('--version'),
],
workingDirectory: sdk.sdkPath,
);
log.stdout('Finished updating local flutter/flutter repository.');
}
final flutterSdkDirName = 'flutter-sdk';
final toolSdkPath = path.join(
repo.toolDirectoryPath,
flutterSdkDirName,
);
final toolFlutterSdkDirectory = Directory(toolSdkPath);
log.stdout('Updating "$toolSdkPath" to branch $flutterTag');
if (toolFlutterSdkDirectory.existsSync()) {
log.stdout(
'"$toolSdkPath" directory already exists. Fetching $flutterTag from GitHub.',
);
await processManager.runAll(
commands: [
CliCommand.git(cmd: 'fetch'),
CliCommand.git(cmd: 'checkout $flutterTag -f'),
CliCommand.flutter('--version'),
],
workingDirectory: toolFlutterSdkDirectory.path,
);
} else {
log.stdout('Cloning flutter/flutter into "$toolSdkPath" directory.');
await processManager.runProcess(
CliCommand.git(
cmd: 'clone https://github.com/flutter/flutter $flutterSdkDirName',
),
workingDirectory: repo.toolDirectoryPath,
);
await processManager.runAll(
commands: [
CliCommand.git(cmd: 'checkout $flutterTag -f'),
CliCommand.flutter('--version'),
],
workingDirectory: toolFlutterSdkDirectory.path,
);
}
log.stdout('Finished updating $toolSdkPath.');
}
}