22// Use of this source code is governed by a BSD-style license that can be 
33// found in the LICENSE file. 
44
5+ import  'dart:io'  as  io;
6+ 
57import  'package:file/file.dart' ;
68import  'package:http/http.dart'  as  http;
79import  'package:pub_semver/pub_semver.dart' ;
@@ -10,6 +12,7 @@ import 'package:yaml_edit/yaml_edit.dart';
1012
1113import  'common/core.dart' ;
1214import  'common/package_looping_command.dart' ;
15+ import  'common/process_runner.dart' ;
1316import  'common/pub_version_finder.dart' ;
1417import  'common/repository_package.dart' ;
1518
@@ -26,10 +29,11 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
2629  /// Creates an instance of the version check command. 
2730UpdateDependencyCommand (
2831    Directory  packagesDir, {
32+     ProcessRunner  processRunner =  const  ProcessRunner (),
2933    http.Client ?  httpClient,
3034  })  :  _pubVersionFinder = 
3135            PubVersionFinder (httpClient:  httpClient ??  http.Client ()),
32-         super (packagesDir) {
36+         super (packagesDir, processRunner :  processRunner ) {
3337    argParser.addOption (
3438      _pubPackageFlag,
3539      help:  'A pub package to update.' ,
@@ -129,6 +133,7 @@ ${response.httpResponse.body}
129133      return  PackageResult .skip ('$dependency  in not a hosted dependency' );
130134    }
131135
136+     // Determine the target version constraint. 
132137    final  String  sectionKey =  dependencyInfo.type ==  _PubDependencyType .dev
133138        ?  'dev_dependencies' 
134139        :  'dependencies' ;
@@ -147,6 +152,7 @@ ${response.httpResponse.body}
147152      versionString =  '^$minVersion ' ;
148153    }
149154
155+     // Update pubspec.yaml with the new version. 
150156    print ('${indentation }Updating to "$versionString "' );
151157    if  (versionString ==  dependencyInfo.constraintString) {
152158      return  PackageResult .skip ('Already depends on $versionString ' );
@@ -159,8 +165,14 @@ ${response.httpResponse.body}
159165    );
160166    package.pubspecFile.writeAsStringSync (editablePubspec.toString ());
161167
162-     // TODO(stuartmorgan): Add additionally handling of known packages that 
163-     // do file generation (mockito, pigeon, etc.). 
168+     // Do any dependency-specific extra processing. 
169+     if  (dependency ==  'pigeon' ) {
170+       if  (! await  _regeneratePigeonFiles (package)) {
171+         return  PackageResult .fail (< String > ['Failed to update pigeon files' ]);
172+       }
173+     }
174+     // TODO(stuartmorgan): Add additional handling of known packages that 
175+     // do file generation (mockito, etc.). 
164176
165177    return  PackageResult .success ();
166178  }
@@ -193,6 +205,59 @@ ${response.httpResponse.body}
193205    }
194206    return  _PubDependencyInfo (type, pinned:  false , hosted:  false );
195207  }
208+ 
209+   /// Returns all of the files in [package]  that are, according to repository 
210+   /// convention, Pigeon input files. 
211+ Iterable <File > _getPigeonInputFiles (RepositoryPackage  package) {
212+     // Repo convention is that the Pigeon input files are the Dart files in a 
213+     // top-level "pigeons" directory. 
214+     final  Directory  pigeonsDir =  package.directory.childDirectory ('pigeons' );
215+     if  (! pigeonsDir.existsSync ()) {
216+       return  < File > [];
217+     }
218+     return  pigeonsDir
219+         .listSync ()
220+         .whereType <File >()
221+         .where ((File  file) =>  file.basename.endsWith ('.dart' ));
222+   }
223+ 
224+   /// Re-runs Pigeon generation for [package] . 
225+   /// 
226+   /// This assumes that all output configuration is set in the input files, so 
227+   /// no additional arguments are needed. If that assumption stops holding true, 
228+   /// the tooling will need a way for packages to control the generation (e.g., 
229+   /// with a script file with a known name in the pigeons/ directory.) 
230+ Future <bool > _regeneratePigeonFiles (RepositoryPackage  package) async  {
231+     final  Iterable <File > inputs =  _getPigeonInputFiles (package);
232+     if  (inputs.isEmpty) {
233+       logWarning ('No pigeon input files found.' );
234+       return  true ;
235+     }
236+ 
237+     print ('${indentation }Running pub get...' );
238+     final  io.ProcessResult  getResult =  await  processRunner
239+         .run ('dart' , < String > ['pub' , 'get' ], workingDir:  package.directory);
240+     if  (getResult.exitCode !=  0 ) {
241+       printError ('dart pub get failed (${getResult .exitCode }):\n ' 
242+           '${getResult .stdout }\n ${getResult .stderr }\n ' );
243+       return  false ;
244+     }
245+ 
246+     print ('${indentation }Updating Pigeon files...' );
247+     for  (final  File  input in  inputs) {
248+       final  String  relativePath = 
249+           getRelativePosixPath (input, from:  package.directory);
250+       final  io.ProcessResult  pigeonResult =  await  processRunner.run (
251+           'dart' , < String > ['run' , 'pigeon' , '--input' , relativePath],
252+           workingDir:  package.directory);
253+       if  (pigeonResult.exitCode !=  0 ) {
254+         printError ('dart run pigeon failed (${pigeonResult .exitCode }):\n ' 
255+             '${pigeonResult .stdout }\n ${pigeonResult .stderr }\n ' );
256+         return  false ;
257+       }
258+     }
259+     return  true ;
260+   }
196261}
197262
198263class  _PubDependencyInfo  {
0 commit comments