1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:args/args.dart' ; |
6 | import 'package:args/command_runner.dart' ; |
7 | import 'package:file/file.dart' ; |
8 | |
9 | import './git.dart'; |
10 | import './globals.dart' show releaseCandidateBranchRegex; |
11 | import './repository.dart'; |
12 | import './stdio.dart'; |
13 | import './version.dart'; |
14 | |
15 | const String kRemote = 'remote' ; |
16 | |
17 | class CandidatesCommand extends Command<void> { |
18 | CandidatesCommand({required this.flutterRoot, required this.checkouts}) |
19 | : git = Git(checkouts.processManager), |
20 | stdio = checkouts.stdio { |
21 | argParser.addOption( |
22 | kRemote, |
23 | help: 'Which remote name to query for branches.' , |
24 | defaultsTo: 'upstream' , |
25 | ); |
26 | } |
27 | |
28 | final Checkouts checkouts; |
29 | final Directory flutterRoot; |
30 | final Git git; |
31 | final Stdio stdio; |
32 | |
33 | @override |
34 | String get name => 'candidates' ; |
35 | |
36 | @override |
37 | String get description => 'List release candidates.' ; |
38 | |
39 | @override |
40 | Future<void> run() async { |
41 | final ArgResults results = argResults!; |
42 | await git.run( |
43 | <String>['fetch' , results[kRemote] as String], |
44 | 'Fetch from remote ${results[kRemote]}' , |
45 | workingDirectory: flutterRoot.path, |
46 | ); |
47 | |
48 | final FrameworkRepository framework = HostFrameworkRepository( |
49 | checkouts: checkouts, |
50 | name: 'framework-for-candidates' , |
51 | upstreamPath: flutterRoot.path, |
52 | ); |
53 | |
54 | final Version currentVersion = await framework.flutterVersion(); |
55 | stdio.printStatus('currentVersion = $currentVersion' ); |
56 | |
57 | final List<String> branches = (await git.getOutput( |
58 | <String>['branch' , '--no-color' , '--remotes' , '--list' , ' ${results[kRemote]}/*'], |
59 | 'List all remote branches', |
60 | workingDirectory: flutterRoot.path, |
61 | )).split('\n'); |
62 | |
63 | // Pattern for extracting only the branch name via sub-group 1 |
64 | final RegExp remotePattern = RegExp('${results[kRemote]}\\/(.*)'); |
65 | for (final String branchName in branches) { |
66 | final RegExpMatch? candidateMatch = releaseCandidateBranchRegex.firstMatch(branchName); |
67 | if (candidateMatch == null) { |
68 | continue; |
69 | } |
70 | final int currentX = currentVersion.x; |
71 | final int currentY = currentVersion.y; |
72 | final int currentZ = currentVersion.z; |
73 | final int currentM = currentVersion.m ?? 0; |
74 | final int x = int.parse(candidateMatch.group(1)!); |
75 | final int y = int.parse(candidateMatch.group(2)!); |
76 | final int m = int.parse(candidateMatch.group(3)!); |
77 | |
78 | final RegExpMatch? match = remotePattern.firstMatch(branchName); |
79 | // If this is not the correct remote |
80 | if (match == null) { |
81 | continue; |
82 | } |
83 | if (x < currentVersion.x) { |
84 | continue; |
85 | } |
86 | if (x == currentVersion.x && y < currentVersion.y) { |
87 | continue; |
88 | } |
89 | if (x == currentX && y == currentY && currentZ == 0 && m <= currentM) { |
90 | continue; |
91 | } |
92 | stdio.printStatus(match.group(1)!); |
93 | } |
94 | } |
95 | } |
96 | |