mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
![Devon Carew](/assets/img/avatar_default.png)
Also rev package:csslib and package:html. csslib (7054945..f33d632
): f33d632 2023-01-28 Devon Carew switch to using package:dart_flutter_team_lints (#161) c0097a0 2023-01-28 Devon Carew Update README.md (#158) 0d985fb 2023-01-28 dependabot[bot] Bump dart-lang/setup-dart from 1.3 to 1.4 (#164) 56d1152 2023-01-28 dependabot[bot] Bump actions/checkout from 3.2.0 to 3.3.0 (#163) 46d2c57 2023-01-28 Devon Carew Update test-package.yml (#165) a7d17bc 2023-01-26 Kevin Moore all the cleanup (#155) html (3dd00b0..f118e00
): f118e00 2023-01-30 Devon Carew lint with dart_flutter_team_lints (#201) 52d9185 2023-01-30 Devon Carew updates from #158 (#202) 71d3e71 2023-01-30 Ron Booth fixed issue #157 (querySelector fails), and added test for it (#158) 9ab8b28 2023-01-30 dependabot[bot] Bump actions/checkout from 3.2.0 to 3.3.0 (#200) fe3fbf6 2023-01-30 dependabot[bot] Bump dart-lang/setup-dart from 1.3 to 1.4 (#199) 776daf5 2023-01-30 Devon Carew Update test-package.yml (#198) a5be27f 2023-01-27 Devon Carew finish work for avoid_dynamic_calls (#196) Change-Id: If03552028f30b8dfd6a227674aa161e43a05e11f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280129 Reviewed-by: William Hesse <whesse@google.com> Reviewed-by: Sigurd Meldgaard <sigurdm@google.com> Commit-Queue: Devon Carew <devoncarew@google.com>
284 lines
8.1 KiB
Dart
Executable file
284 lines
8.1 KiB
Dart
Executable file
#!tools/sdks/dart-sdk/bin/dart
|
|
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
/// Helps rolling dependency to the newest version available
|
|
/// (or a target version).
|
|
///
|
|
/// Usage: ./tools/manage_deps.dart bump <dependency> [--branch <branch>] [--target <ref>]
|
|
///
|
|
/// This will:
|
|
/// 0. Check that git is clean
|
|
/// 1. Create branch `<branch> ?? bump_<dependency>`
|
|
/// 2. Update `DEPS` for `<dependency>`
|
|
/// 3. Create a commit with `git log` of imported commits in the message.
|
|
/// 4. Prompt to create a CL
|
|
|
|
// @dart = 2.13
|
|
library bump;
|
|
|
|
import 'dart:io';
|
|
|
|
import 'package:args/command_runner.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
class BumpCommand extends Command<int> {
|
|
@override
|
|
String get description => '''
|
|
Bump a dependency in DEPS and create a CL
|
|
|
|
This will:
|
|
0. Check that git is clean
|
|
1. Create branch `<branch> ?? bump_<dependency>`
|
|
2. Update `DEPS` for `<dependency>`
|
|
3. Create a commit with `git log` of imported commits in the message.
|
|
4. Prompt to create a CL
|
|
''';
|
|
|
|
@override
|
|
String get invocation =>
|
|
'./tools/manage_deps.dart bump <path/to/dependency> <options>';
|
|
|
|
BumpCommand() {
|
|
argParser.addOption(
|
|
'branch',
|
|
help: 'The name of the branch where the update is created.',
|
|
valueHelp: 'branch-name',
|
|
);
|
|
argParser.addOption(
|
|
'target',
|
|
help: 'The git ref to update to.',
|
|
valueHelp: 'ref',
|
|
);
|
|
}
|
|
|
|
@override
|
|
String get name => 'bump';
|
|
|
|
@override
|
|
Future<int> run() async {
|
|
final argResults = this.argResults!;
|
|
if (argResults.rest.length != 1) {
|
|
usageException('No dependency directory given');
|
|
}
|
|
final status = runProcessForLines(['git', 'status', '--porcelain'],
|
|
explanation: 'Checking if your git checkout is clean');
|
|
if (status.isNotEmpty) {
|
|
print('Note your git checkout is dirty!');
|
|
}
|
|
|
|
final pkgDir = argResults.rest.first;
|
|
if (!Directory(pkgDir).existsSync()) {
|
|
usageException('No directory $pkgDir');
|
|
}
|
|
final toUpdate = p.split(pkgDir).last;
|
|
final branchName = argResults['branch'] ?? 'bump_$toUpdate';
|
|
|
|
final exists = runProcessForExitCode(
|
|
['git', 'rev-parse', '--verify', branchName],
|
|
explanation: 'Checking if branch-name exists');
|
|
if (exists == 0) {
|
|
print('Branch $branchName already exist - delete it?');
|
|
if (!prompt()) {
|
|
print('Ok - exiting');
|
|
exit(-1);
|
|
}
|
|
runProcessAssumingSuccess(
|
|
['git', 'branch', '-D', branchName],
|
|
explanation: 'Deleting existing branch',
|
|
);
|
|
}
|
|
runProcessAssumingSuccess(
|
|
['git', 'checkout', '-b', branchName],
|
|
explanation: 'Creating branch',
|
|
);
|
|
|
|
final currentRev = runProcessForLines(
|
|
['gclient', 'getdep', '-r', p.join('sdk', pkgDir)],
|
|
explanation: 'Finding current revision',
|
|
).first;
|
|
|
|
final originUrl = runProcessForLines(
|
|
['git', 'config', '--get', 'remote.origin.url'],
|
|
workingDirectory: pkgDir,
|
|
explanation: 'Finding origin url',
|
|
).first;
|
|
|
|
runProcessAssumingSuccess(
|
|
['git', 'fetch', 'origin'],
|
|
workingDirectory: pkgDir,
|
|
explanation: 'Retrieving updates to $toUpdate',
|
|
);
|
|
|
|
final gitRevParseResult = runProcessForLines([
|
|
'git',
|
|
'rev-parse',
|
|
if (argResults.wasParsed('target'))
|
|
argResults['target']
|
|
else
|
|
'origin/${defaultBranchTarget(pkgDir)}',
|
|
], workingDirectory: pkgDir, explanation: 'Finding sha-id');
|
|
|
|
final target = gitRevParseResult.first;
|
|
if (currentRev == target) {
|
|
print('Already at $target - nothing to do');
|
|
return -1;
|
|
}
|
|
runProcessAssumingSuccess(
|
|
['gclient', 'setdep', '-r', '${p.join('sdk', pkgDir)}@$target'],
|
|
explanation: 'Updating $toUpdate',
|
|
);
|
|
runProcessAssumingSuccess(
|
|
['gclient', 'sync', '-D'],
|
|
explanation: 'Syncing your deps',
|
|
);
|
|
runProcessAssumingSuccess(
|
|
[
|
|
Platform.resolvedExecutable,
|
|
'tools/generate_package_config.dart',
|
|
],
|
|
explanation: 'Updating package config',
|
|
);
|
|
final gitLogResult = runProcessForLines([
|
|
'git',
|
|
'log',
|
|
'--format=%C(auto) $originUrl/+/%h %s ',
|
|
'$currentRev..$target',
|
|
], workingDirectory: pkgDir, explanation: 'Listing new commits');
|
|
// To avoid github notifying issues in the sdk when it sees #issueid
|
|
// we remove all '#' characters.
|
|
final cleanedGitLogResult =
|
|
gitLogResult.map((x) => x.replaceAll('#', '')).join('\n');
|
|
final commitMessage = '''
|
|
Bump $toUpdate to $target
|
|
|
|
Changes:
|
|
```
|
|
> git log --format="%C(auto) %h %s" ${currentRev.substring(0, 7)}..${target.substring(0, 7)}
|
|
$cleanedGitLogResult
|
|
```
|
|
Diff: $originUrl/+/$currentRev..$target/
|
|
''';
|
|
runProcessAssumingSuccess(['git', 'commit', '-am', commitMessage],
|
|
explanation: 'Committing');
|
|
print('Consider updating CHANGELOG.md');
|
|
print('Do you want to create a CL?');
|
|
if (prompt()) {
|
|
await runProcessInteractively(
|
|
['git', 'cl', 'upload', '-m', commitMessage],
|
|
explanation: 'Creating CL',
|
|
);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
Future<void> main(List<String> args) async {
|
|
final runner = CommandRunner<int>(
|
|
'manage_deps.dart', 'helps managing the DEPS file',
|
|
usageLineLength: 80)
|
|
..addCommand(BumpCommand());
|
|
try {
|
|
exit(await runner.run(args) ?? -1);
|
|
} on UsageException catch (e) {
|
|
print(e.message);
|
|
print(e.usage);
|
|
}
|
|
}
|
|
|
|
bool prompt() {
|
|
stdout.write('(y/N):');
|
|
final answer = stdin.readLineSync() ?? '';
|
|
return answer.trim().toLowerCase() == 'y';
|
|
}
|
|
|
|
void printRunningLine(
|
|
List<String> cmd, String? explanation, String? workingDirectory) {
|
|
stdout.write(
|
|
"${explanation ?? 'Running'}: `${cmd.join(' ')}` ${workingDirectory == null ? '' : 'in $workingDirectory'}");
|
|
}
|
|
|
|
void printSuccessTrailer(ProcessResult result, String? onFailure) {
|
|
if (result.exitCode == 0) {
|
|
stdout.writeln(' ✓');
|
|
} else {
|
|
stdout.writeln(' X');
|
|
stderr.write(result.stdout);
|
|
stderr.write(result.stderr);
|
|
if (onFailure != null) {
|
|
print(onFailure);
|
|
}
|
|
throw Exception();
|
|
}
|
|
}
|
|
|
|
void runProcessAssumingSuccess(List<String> cmd,
|
|
{String? explanation,
|
|
String? workingDirectory,
|
|
Map<String, String> environment = const {},
|
|
String? onFailure}) {
|
|
printRunningLine(cmd, explanation, workingDirectory);
|
|
final result = Process.runSync(
|
|
cmd[0],
|
|
cmd.skip(1).toList(),
|
|
workingDirectory: workingDirectory,
|
|
environment: environment,
|
|
);
|
|
printSuccessTrailer(result, onFailure);
|
|
}
|
|
|
|
List<String> runProcessForLines(List<String> cmd,
|
|
{String? explanation, String? workingDirectory, String? onFailure}) {
|
|
printRunningLine(cmd, explanation, workingDirectory);
|
|
final result = Process.runSync(
|
|
cmd[0],
|
|
cmd.skip(1).toList(),
|
|
workingDirectory: workingDirectory,
|
|
environment: {'DEPOT_TOOLS_UPDATE': '0'},
|
|
);
|
|
printSuccessTrailer(result, onFailure);
|
|
final output = (result.stdout as String);
|
|
return output == '' ? <String>[] : output.split('\n');
|
|
}
|
|
|
|
Future<void> runProcessInteractively(List<String> cmd,
|
|
{String? explanation, String? workingDirectory}) async {
|
|
printRunningLine(cmd, explanation, workingDirectory);
|
|
stdout.writeln('');
|
|
final process = await Process.start(cmd[0], cmd.skip(1).toList(),
|
|
workingDirectory: workingDirectory, mode: ProcessStartMode.inheritStdio);
|
|
final exitCode = await process.exitCode;
|
|
if (exitCode != 0) {
|
|
throw Exception();
|
|
}
|
|
}
|
|
|
|
int runProcessForExitCode(List<String> cmd,
|
|
{String? explanation, String? workingDirectory}) {
|
|
printRunningLine(cmd, explanation, workingDirectory);
|
|
final result = Process.runSync(
|
|
cmd[0],
|
|
cmd.skip(1).toList(),
|
|
workingDirectory: workingDirectory,
|
|
);
|
|
stdout.writeln(' => ${result.exitCode}');
|
|
return result.exitCode;
|
|
}
|
|
|
|
String defaultBranchTarget(String dir) {
|
|
var branchNames = Directory(p.join(dir, '.git', 'refs', 'heads'))
|
|
.listSync()
|
|
.whereType<File>()
|
|
.map((f) => p.basename(f.path))
|
|
.toSet();
|
|
|
|
for (var name in ['main', 'master']) {
|
|
if (branchNames.contains(name)) {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
return 'HEAD';
|
|
}
|