@@ -19,6 +19,7 @@ import 'common/repository_package.dart';
19
19
20
20
const int _exitIncorrectTargetDependency = 3 ;
21
21
const int _exitNoTargetVersion = 4 ;
22
+ const int _exitInvalidTargetVersion = 5 ;
22
23
23
24
/// A command to update a dependency in packages.
24
25
///
@@ -38,23 +39,34 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
38
39
_pubPackageFlag,
39
40
help: 'A pub package to update.' ,
40
41
);
42
+ argParser.addOption (_androidDependency,
43
+ help: 'An Android dependency to update.' ,
44
+ allowed: < String > [
45
+ 'gradle' ,
46
+ ],
47
+ allowedHelp: < String , String > {
48
+ 'gradle' : 'Updates Gradle version used in plugin example apps.' ,
49
+ });
41
50
argParser.addOption (
42
51
_versionFlag,
43
52
help: 'The version to update to.\n\n '
44
53
'- For pub, defaults to the latest published version if not '
45
54
'provided. This can be any constraint that pubspec.yaml allows; a '
46
55
'specific version will be treated as the exact version for '
47
56
'dependencies that are alread pinned, or a ^ range for those that '
48
- 'are unpinned.' ,
57
+ 'are unpinned.\n '
58
+ '- For Android dependencies, a version must be provided.' ,
49
59
);
50
60
}
51
61
52
62
static const String _pubPackageFlag = 'pub-package' ;
63
+ static const String _androidDependency = 'android-dependency' ;
53
64
static const String _versionFlag = 'version' ;
54
65
55
66
final PubVersionFinder _pubVersionFinder;
56
67
57
68
late final String ? _targetPubPackage;
69
+ late final String ? _targetAndroidDependency;
58
70
late final String _targetVersion;
59
71
60
72
@override
@@ -72,14 +84,19 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
72
84
73
85
@override
74
86
Future <void > initializeRun () async {
75
- const Set <String > targetFlags = < String > {_pubPackageFlag};
87
+ const Set <String > targetFlags = < String > {
88
+ _pubPackageFlag,
89
+ _androidDependency
90
+ };
76
91
final Set <String > passedTargetFlags =
77
92
targetFlags.where ((String flag) => argResults! [flag] != null ).toSet ();
78
93
if (passedTargetFlags.length != 1 ) {
79
94
printError (
80
95
'Exactly one of the target flags must be provided: (${targetFlags .join (', ' )})' );
81
96
throw ToolExit (_exitIncorrectTargetDependency);
82
97
}
98
+
99
+ // Setup for updating pub dependency.
83
100
_targetPubPackage = getNullableStringArg (_pubPackageFlag);
84
101
if (_targetPubPackage != null ) {
85
102
final String ? version = getNullableStringArg (_versionFlag);
@@ -102,6 +119,33 @@ ${response.httpResponse.body}
102
119
}
103
120
} else {
104
121
_targetVersion = version;
122
+ return ;
123
+ }
124
+ }
125
+
126
+ // Setup for updating Android dependency.
127
+ _targetAndroidDependency = getNullableStringArg (_androidDependency);
128
+ if (_targetAndroidDependency != null ) {
129
+ final String ? version = getNullableStringArg (_versionFlag);
130
+ if (version == null ) {
131
+ printError ('A version must be provided to update this dependency.' );
132
+ throw ToolExit (_exitNoTargetVersion);
133
+ } else if (_targetAndroidDependency == 'gradle' ) {
134
+ final RegExp validGradleVersionPattern = RegExp (r'^\d+(?:\.\d+){1,2}$' );
135
+ final bool isValidGradleVersion =
136
+ validGradleVersionPattern.stringMatch (version) == version;
137
+ if (! isValidGradleVersion) {
138
+ printError (
139
+ 'A version with a valid format (maximum 2-3 numbers separated by period) must be provided.' );
140
+ throw ToolExit (_exitInvalidTargetVersion);
141
+ }
142
+ _targetVersion = version;
143
+ return ;
144
+ } else {
145
+ // TODO(camsim99): Add other supported Android dependencies like the Android SDK and AGP.
146
+ printError (
147
+ 'Target Android dependency $_targetAndroidDependency is unrecognized.' );
148
+ throw ToolExit (_exitIncorrectTargetDependency);
105
149
}
106
150
}
107
151
}
@@ -116,7 +160,11 @@ ${response.httpResponse.body}
116
160
if (_targetPubPackage != null ) {
117
161
return _runForPubDependency (package, _targetPubPackage! );
118
162
}
119
- // TODO(stuartmorgan): Add othe dependency types here (e.g., maven).
163
+ if (_targetAndroidDependency != null ) {
164
+ return _runForAndroidDependency (package);
165
+ }
166
+
167
+ // TODO(stuartmorgan): Add other dependency types here (e.g., maven).
120
168
121
169
return PackageResult .fail ();
122
170
}
@@ -181,6 +229,65 @@ ${response.httpResponse.body}
181
229
return PackageResult .success ();
182
230
}
183
231
232
+ /// Handles all of the updates for [package] when the target dependency is
233
+ /// an Android dependency.
234
+ Future <PackageResult > _runForAndroidDependency (
235
+ RepositoryPackage package) async {
236
+ if (_targetAndroidDependency == 'gradle' ) {
237
+ final Iterable <RepositoryPackage > packageExamples = package.getExamples ();
238
+ bool updateRanForExamples = false ;
239
+ for (final RepositoryPackage example in packageExamples) {
240
+ if (! example.platformDirectory (FlutterPlatform .android).existsSync ()) {
241
+ continue ;
242
+ }
243
+
244
+ updateRanForExamples = true ;
245
+ Directory gradleWrapperPropertiesDirectory =
246
+ example.platformDirectory (FlutterPlatform .android);
247
+ if (gradleWrapperPropertiesDirectory
248
+ .childDirectory ('app' )
249
+ .childDirectory ('gradle' )
250
+ .existsSync ()) {
251
+ gradleWrapperPropertiesDirectory =
252
+ gradleWrapperPropertiesDirectory.childDirectory ('app' );
253
+ }
254
+ final File gradleWrapperPropertiesFile =
255
+ gradleWrapperPropertiesDirectory
256
+ .childDirectory ('gradle' )
257
+ .childDirectory ('wrapper' )
258
+ .childFile ('gradle-wrapper.properties' );
259
+
260
+ final String gradleWrapperPropertiesContents =
261
+ gradleWrapperPropertiesFile.readAsStringSync ();
262
+ final RegExp validGradleDistributionUrl =
263
+ RegExp (r'^\s*distributionUrl\s*=\s*.*\.zip' , multiLine: true );
264
+ if (! validGradleDistributionUrl
265
+ .hasMatch (gradleWrapperPropertiesContents)) {
266
+ return PackageResult .fail (< String > [
267
+ 'Unable to find a "distributionUrl" entry to update for ${package .displayName }.'
268
+ ]);
269
+ }
270
+
271
+ print (
272
+ '${indentation }Updating ${getRelativePosixPath (example .directory , from : package .directory )} to "$_targetVersion "' );
273
+ final String newGradleWrapperPropertiesContents =
274
+ gradleWrapperPropertiesContents.replaceFirst (
275
+ validGradleDistributionUrl,
276
+ 'distributionUrl=https\\ ://services.gradle.org/distributions/gradle-$_targetVersion -all.zip' );
277
+ // TODO(camsim99): Validate current AGP version against target Gradle
278
+ // version: https://github.com/flutter/flutter/issues/133887.
279
+ gradleWrapperPropertiesFile
280
+ .writeAsStringSync (newGradleWrapperPropertiesContents);
281
+ }
282
+ return updateRanForExamples
283
+ ? PackageResult .success ()
284
+ : PackageResult .skip ('No example apps run on Android.' );
285
+ }
286
+ return PackageResult .fail (< String > [
287
+ 'Target Android dependency $_androidDependency is unrecognized.'
288
+ ]);
289
+ }
290
+
184
291
/// Returns information about the current dependency of [package] on
185
292
/// the package named [dependencyName] , or null if there is no dependency.
186
293
_PubDependencyInfo ? _getPubDependencyInfo (
0 commit comments