@@ -99,14 +99,25 @@ class UpdatePackagesCommand extends FlutterCommand {
9999 abbr: 'j' ,
100100 help: 'Causes the "pub get" runs to happen concurrently on this many '
101101 'CPUs. Defaults to the number of CPUs that this machine has.' ,
102+ )
103+ ..addOption (
104+ 'synthetic-package-path' ,
105+ help: 'Write the synthetic monolithic pub package generated to do '
106+ 'version solving to a persistent path. By default, a temporary '
107+ 'directory that is deleted before the command exits. By '
108+ 'providing this path, a Flutter maintainer can inspect further '
109+ 'exactly how version solving was achieved.' ,
102110 );
103111 }
104112
105113 @override
106114 final String name = 'update-packages' ;
107115
108116 @override
109- final String description = 'Update the packages inside the Flutter repo.' ;
117+ final String description = 'Update the packages inside the Flutter repo. '
118+ 'This is intended for CI and repo maintainers. '
119+ 'Normal Flutter developers should not have to '
120+ 'use this command.' ;
110121
111122 @override
112123 final List <String > aliases = < String > ['upgrade-packages' ];
@@ -144,6 +155,22 @@ class UpdatePackagesCommand extends FlutterCommand {
144155 ..writeAsBytesSync (data, flush: true );
145156 }
146157
158+ late final Directory _syntheticPackageDir = (() {
159+ final String ? optionPath = stringArg ('synthetic-package-path' );
160+ if (optionPath == null ) {
161+ return globals.fs.systemTempDirectory.createTempSync ('flutter_update_packages.' );
162+ }
163+ final Directory syntheticPackageDir = globals.fs.directory (optionPath);
164+ if (! syntheticPackageDir.existsSync ()) {
165+ syntheticPackageDir.createSync (recursive: true );
166+ }
167+ globals.printStatus (
168+ 'The synthetic package with all pub dependencies across the repo will '
169+ 'be written to ${syntheticPackageDir .absolute .path }.' ,
170+ );
171+ return syntheticPackageDir;
172+ })();
173+
147174 @override
148175 Future <FlutterCommandResult > runCommand () async {
149176 final List <Directory > packages = runner! .getRepoPackages ();
@@ -218,15 +245,19 @@ class UpdatePackagesCommand extends FlutterCommand {
218245 // attempt to download any necessary package versions to the pub cache to
219246 // warm the cache.
220247 final PubDependencyTree tree = PubDependencyTree (); // object to collect results
221- final Directory tempDir = globals.fs.systemTempDirectory.createTempSync ('flutter_update_packages.' );
222248 await _generateFakePackage (
223- tempDir: tempDir ,
249+ tempDir: _syntheticPackageDir ,
224250 dependencies: doUpgrade ? explicitDependencies.values : allDependencies.values,
225251 pubspecs: pubspecs,
226252 tree: tree,
227253 doUpgrade: doUpgrade,
228254 );
229255
256+ // Only delete the synthetic package if it was done in a temp directory
257+ if (stringArg ('synthetic-package-path' ) == null ) {
258+ _syntheticPackageDir.deleteSync (recursive: true );
259+ }
260+
230261 if (doUpgrade) {
231262 final bool done = _upgradePubspecs (
232263 tree: tree,
@@ -380,57 +411,49 @@ class UpdatePackagesCommand extends FlutterCommand {
380411 required bool doUpgrade,
381412 }) async {
382413 Directory ? temporaryFlutterSdk;
383- try {
384- final File fakePackage = _pubspecFor (tempDir);
385- fakePackage.createSync ();
386- fakePackage.writeAsStringSync (
387- generateFakePubspec (
388- dependencies,
389- doUpgrade: doUpgrade,
390- ),
414+ final Directory syntheticPackageDir = tempDir.childDirectory ('synthetic_package' );
415+ final File fakePackage = _pubspecFor (syntheticPackageDir);
416+ fakePackage.createSync (recursive: true );
417+ fakePackage.writeAsStringSync (
418+ generateFakePubspec (
419+ dependencies,
420+ doUpgrade: doUpgrade,
421+ ),
422+ );
423+ // Create a synthetic flutter SDK so that transitive flutter SDK
424+ // constraints are not affected by this upgrade.
425+ if (doUpgrade) {
426+ temporaryFlutterSdk = createTemporaryFlutterSdk (
427+ globals.logger,
428+ globals.fs,
429+ globals.fs.directory (Cache .flutterRoot),
430+ pubspecs,
431+ tempDir,
391432 );
392- // Create a synthetic flutter SDK so that transitive flutter SDK
393- // constraints are not affected by this upgrade.
394- if (doUpgrade) {
395- temporaryFlutterSdk = createTemporaryFlutterSdk (
396- globals.logger,
397- globals.fs,
398- globals.fs.directory (Cache .flutterRoot),
399- pubspecs,
400- );
401- }
433+ }
402434
403- // Next we run "pub get" on it in order to force the download of any
404- // needed packages to the pub cache, upgrading if requested.
405- await pub.get (
435+ // Next we run "pub get" on it in order to force the download of any
436+ // needed packages to the pub cache, upgrading if requested.
437+ await pub.get (
438+ context: PubContext .updatePackages,
439+ project: FlutterProject .fromDirectory (syntheticPackageDir),
440+ upgrade: doUpgrade,
441+ offline: boolArgDeprecated ('offline' ),
442+ flutterRootOverride: temporaryFlutterSdk? .path,
443+ );
444+
445+ if (doUpgrade) {
446+ // If upgrading, we run "pub deps --style=compact" on the result. We
447+ // pipe all the output to tree.fill(), which parses it so that it can
448+ // create a graph of all the dependencies so that we can figure out the
449+ // transitive dependencies later. It also remembers which version was
450+ // selected for each package.
451+ await pub.batch (
452+ < String > ['deps' , '--style=compact' ],
406453 context: PubContext .updatePackages,
407- project: FlutterProject .fromDirectory (tempDir),
408- upgrade: doUpgrade,
409- offline: boolArgDeprecated ('offline' ),
410- flutterRootOverride: temporaryFlutterSdk? .path,
454+ directory: syntheticPackageDir.path,
455+ filter: tree.fill,
411456 );
412-
413- if (doUpgrade) {
414- // If upgrading, we run "pub deps --style=compact" on the result. We
415- // pipe all the output to tree.fill(), which parses it so that it can
416- // create a graph of all the dependencies so that we can figure out the
417- // transitive dependencies later. It also remembers which version was
418- // selected for each package.
419- await pub.batch (
420- < String > ['deps' , '--style=compact' ],
421- context: PubContext .updatePackages,
422- directory: tempDir.path,
423- filter: tree.fill,
424- );
425- }
426- } finally {
427- // Cleanup the temporary SDK
428- try {
429- temporaryFlutterSdk? .deleteSync (recursive: true );
430- } on FileSystemException {
431- // Failed to delete temporary SDK.
432- }
433- tempDir.deleteSync (recursive: true );
434457 }
435458 }
436459
@@ -1577,6 +1600,7 @@ Directory createTemporaryFlutterSdk(
15771600 FileSystem fileSystem,
15781601 Directory realFlutter,
15791602 List <PubspecYaml > pubspecs,
1603+ Directory tempDir,
15801604) {
15811605 final Set <String > currentPackages = < String > {};
15821606 for (final FileSystemEntity entity in realFlutter.childDirectory ('packages' ).listSync ()) {
@@ -1591,8 +1615,7 @@ Directory createTemporaryFlutterSdk(
15911615 pubspecsByName[pubspec.name] = pubspec;
15921616 }
15931617
1594- final Directory directory = fileSystem.systemTempDirectory
1595- .createTempSync ('flutter_upgrade_sdk.' )
1618+ final Directory directory = tempDir.childDirectory ('flutter_upgrade_sdk' )
15961619 ..createSync ();
15971620 // Fill in version info.
15981621 realFlutter.childFile ('version' )
0 commit comments