@@ -42,10 +42,17 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
42
42
argParser.addOption (_androidDependency,
43
43
help: 'An Android dependency to update.' ,
44
44
allowed: < String > [
45
- 'gradle' ,
45
+ _AndroidDepdencyType .gradle,
46
+ _AndroidDepdencyType .compileSdk,
47
+ _AndroidDepdencyType .compileSdkForExamples,
46
48
],
47
49
allowedHelp: < String , String > {
48
- 'gradle' : 'Updates Gradle version used in plugin example apps.' ,
50
+ _AndroidDepdencyType .gradle:
51
+ 'Updates Gradle version used in plugin example apps.' ,
52
+ _AndroidDepdencyType .compileSdk:
53
+ 'Updates compileSdk version used to compile plugins.' ,
54
+ _AndroidDepdencyType .compileSdkForExamples:
55
+ 'Updates compileSdk version used to compile plugin examples.' ,
49
56
});
50
57
argParser.addOption (
51
58
_versionFlag,
@@ -130,7 +137,7 @@ ${response.httpResponse.body}
130
137
if (version == null ) {
131
138
printError ('A version must be provided to update this dependency.' );
132
139
throw ToolExit (_exitNoTargetVersion);
133
- } else if (_targetAndroidDependency == ' gradle' ) {
140
+ } else if (_targetAndroidDependency == _AndroidDepdencyType . gradle) {
134
141
final RegExp validGradleVersionPattern = RegExp (r'^\d+(?:\.\d+){1,2}$' );
135
142
final bool isValidGradleVersion =
136
143
validGradleVersionPattern.stringMatch (version) == version;
@@ -139,14 +146,24 @@ ${response.httpResponse.body}
139
146
'A version with a valid format (maximum 2-3 numbers separated by period) must be provided.' );
140
147
throw ToolExit (_exitInvalidTargetVersion);
141
148
}
142
- _targetVersion = version;
143
- return ;
149
+ } else if (_targetAndroidDependency == _AndroidDepdencyType .compileSdk ||
150
+ _targetAndroidDependency ==
151
+ _AndroidDepdencyType .compileSdkForExamples) {
152
+ final RegExp validSdkVersion = RegExp (r'^\d{1,2}$' );
153
+ final bool isValidSdkVersion =
154
+ validSdkVersion.stringMatch (version) == version;
155
+ if (! isValidSdkVersion) {
156
+ printError (
157
+ 'A valid Android SDK version number (1-2 digit numbers) must be provided.' );
158
+ throw ToolExit (_exitInvalidTargetVersion);
159
+ }
144
160
} else {
145
- // TODO(camsim99): Add other supported Android dependencies like the Android SDK and AGP.
161
+ // TODO(camsim99): Add other supported Android dependencies like the min/target Android SDK and AGP.
146
162
printError (
147
163
'Target Android dependency $_targetAndroidDependency is unrecognized.' );
148
164
throw ToolExit (_exitIncorrectTargetDependency);
149
165
}
166
+ _targetVersion = version;
150
167
}
151
168
}
152
169
@@ -233,59 +250,114 @@ ${response.httpResponse.body}
233
250
/// an Android dependency.
234
251
Future <PackageResult > _runForAndroidDependency (
235
252
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
- }
253
+ if (_targetAndroidDependency == _AndroidDepdencyType .compileSdk ) {
254
+ return _runForCompileSdkVersion (package );
255
+ } else if (_targetAndroidDependency == _AndroidDepdencyType .gradle ||
256
+ _targetAndroidDependency ==
257
+ _AndroidDepdencyType .compileSdkForExamples ) {
258
+ return _runForAndroidDependencyOnExamples (package) ;
259
+ }
243
260
244
- updateRanForExamples = true ;
245
- Directory gradleWrapperPropertiesDirectory =
246
- example.platformDirectory (FlutterPlatform .android);
247
- if (gradleWrapperPropertiesDirectory
261
+ return PackageResult .fail (< String > [
262
+ 'Target Android dependency $_androidDependency is unrecognized.'
263
+ ]);
264
+ }
265
+
266
+ Future <PackageResult > _runForAndroidDependencyOnExamples (
267
+ RepositoryPackage package) async {
268
+ final Iterable <RepositoryPackage > packageExamples = package.getExamples ();
269
+ bool updateRanForExamples = false ;
270
+ for (final RepositoryPackage example in packageExamples) {
271
+ if (! example.platformDirectory (FlutterPlatform .android).existsSync ()) {
272
+ continue ;
273
+ }
274
+
275
+ updateRanForExamples = true ;
276
+ Directory androidDirectory =
277
+ example.platformDirectory (FlutterPlatform .android);
278
+ final File fileToUpdate;
279
+ final RegExp dependencyVersionPattern;
280
+ final String newDependencyVersionEntry;
281
+
282
+ if (_targetAndroidDependency == _AndroidDepdencyType .gradle) {
283
+ if (androidDirectory
248
284
.childDirectory ('app' )
249
285
.childDirectory ('gradle' )
250
286
.existsSync ()) {
251
- gradleWrapperPropertiesDirectory =
252
- gradleWrapperPropertiesDirectory.childDirectory ('app' );
287
+ androidDirectory = androidDirectory.childDirectory ('app' );
253
288
}
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 =
289
+ fileToUpdate = androidDirectory
290
+ .childDirectory ('gradle' )
291
+ .childDirectory ('wrapper' )
292
+ .childFile ('gradle-wrapper.properties' );
293
+ dependencyVersionPattern =
263
294
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
295
// TODO(camsim99): Validate current AGP version against target Gradle
278
296
// version: https://github.com/flutter/flutter/issues/133887.
279
- gradleWrapperPropertiesFile
280
- .writeAsStringSync (newGradleWrapperPropertiesContents);
297
+ newDependencyVersionEntry =
298
+ 'distributionUrl=https\\ ://services.gradle.org/distributions/gradle-$_targetVersion -all.zip' ;
299
+ } else if (_targetAndroidDependency ==
300
+ _AndroidDepdencyType .compileSdkForExamples) {
301
+ fileToUpdate =
302
+ androidDirectory.childDirectory ('app' ).childFile ('build.gradle' );
303
+ dependencyVersionPattern = RegExp (
304
+ r'(compileSdk|compileSdkVersion) (\d{1,2}|flutter.compileSdkVersion)' );
305
+ newDependencyVersionEntry = 'compileSdk $_targetVersion ' ;
306
+ } else {
307
+ printError (
308
+ 'Target Android dependency $_targetAndroidDependency is unrecognized.' );
309
+ throw ToolExit (_exitIncorrectTargetDependency);
310
+ }
311
+
312
+ final String oldFileToUpdateContents = fileToUpdate.readAsStringSync ();
313
+
314
+ if (! dependencyVersionPattern.hasMatch (oldFileToUpdateContents)) {
315
+ return PackageResult .fail (< String > [
316
+ 'Unable to find a $_targetAndroidDependency version entry to update for ${example .displayName }.'
317
+ ]);
281
318
}
282
- return updateRanForExamples
283
- ? PackageResult .success ()
284
- : PackageResult .skip ('No example apps run on Android.' );
319
+
320
+ print (
321
+ '${indentation }Updating ${getRelativePosixPath (example .directory , from : package .directory )} to "$_targetVersion "' );
322
+ final String newGradleWrapperPropertiesContents = oldFileToUpdateContents
323
+ .replaceFirst (dependencyVersionPattern, newDependencyVersionEntry);
324
+
325
+ fileToUpdate.writeAsStringSync (newGradleWrapperPropertiesContents);
285
326
}
286
- return PackageResult .fail (< String > [
287
- 'Target Android dependency $_androidDependency is unrecognized.'
288
- ]);
327
+ return updateRanForExamples
328
+ ? PackageResult .success ()
329
+ : PackageResult .skip ('No example apps run on Android.' );
330
+ }
331
+
332
+ Future <PackageResult > _runForCompileSdkVersion (
333
+ RepositoryPackage package) async {
334
+ if (! package.platformDirectory (FlutterPlatform .android).existsSync ()) {
335
+ return PackageResult .skip (
336
+ 'Package ${package .displayName } does not run on Android.' );
337
+ } else if (package.isExample) {
338
+ // We skip examples for this command.
339
+ return PackageResult .skip (
340
+ 'Package ${package .displayName } is not a top-level package; run with "compileSdkForExamples" to update.' );
341
+ }
342
+ final File buildConfigurationFile = package
343
+ .platformDirectory (FlutterPlatform .android)
344
+ .childFile ('build.gradle' );
345
+ final String buildConfigurationContents =
346
+ buildConfigurationFile.readAsStringSync ();
347
+ final RegExp validCompileSdkVersion =
348
+ RegExp (r'(compileSdk|compileSdkVersion) \d{1,2}' );
349
+
350
+ if (! validCompileSdkVersion.hasMatch (buildConfigurationContents)) {
351
+ return PackageResult .fail (< String > [
352
+ 'Unable to find a compileSdk version entry to update for ${package .displayName }.'
353
+ ]);
354
+ }
355
+ print ('${indentation }Updating ${package .directory } to "$_targetVersion "' );
356
+ final String newBuildConfigurationContents = buildConfigurationContents
357
+ .replaceFirst (validCompileSdkVersion, 'compileSdk $_targetVersion ' );
358
+ buildConfigurationFile.writeAsStringSync (newBuildConfigurationContents);
359
+
360
+ return PackageResult .success ();
289
361
}
290
362
291
363
/// Returns information about the current dependency of [package] on
@@ -414,3 +486,9 @@ class _PubDependencyInfo {
414
486
}
415
487
416
488
enum _PubDependencyType { normal, dev }
489
+
490
+ class _AndroidDepdencyType {
491
+ static const String gradle = 'gradle' ;
492
+ static const String compileSdk = 'compileSdk' ;
493
+ static const String compileSdkForExamples = 'compileSdkForExamples' ;
494
+ }
0 commit comments