@@ -7,6 +7,7 @@ import 'dart:convert';
77import 'dart:io' as io;
88
99import 'package:file/file.dart' ;
10+ import 'package:flutter_plugin_tools/src/common/repository_package.dart' ;
1011import 'package:git/git.dart' ;
1112import 'package:http/http.dart' as http;
1213import 'package:meta/meta.dart' ;
@@ -58,11 +59,6 @@ class PublishPluginCommand extends PluginCommand {
5859 _stdin = stdinput ?? io.stdin,
5960 super (packagesDir,
6061 platform: platform, processRunner: processRunner, gitDir: gitDir) {
61- argParser.addOption (
62- _packageOption,
63- help: 'The package to publish.'
64- 'If the package directory name is different than its pubspec.yaml name, then this should specify the directory.' ,
65- );
6662 argParser.addMultiOption (_pubFlagsOption,
6763 help:
6864 'A list of options that will be forwarded on to pub. Separate multiple flags with commas.' );
@@ -75,8 +71,8 @@ class PublishPluginCommand extends PluginCommand {
7571 argParser.addFlag (
7672 _allChangedFlag,
7773 help:
78- 'Release all plugins that contains pubspec changes at the current commit compares to the base-sha.\n '
79- 'The $ _packageOption option is ignored if this is on.' ,
74+ 'Release all packages that contains pubspec changes at the current commit compares to the base-sha.\n '
75+ 'The --packages option is ignored if this is on.' ,
8076 defaultsTo: false ,
8177 );
8278 argParser.addFlag (
@@ -95,7 +91,6 @@ class PublishPluginCommand extends PluginCommand {
9591 negatable: true );
9692 }
9793
98- static const String _packageOption = 'package' ;
9994 static const String _pubFlagsOption = 'pub-publish-flags' ;
10095 static const String _remoteOption = 'remote' ;
10196 static const String _allChangedFlag = 'all-changed' ;
@@ -113,7 +108,7 @@ class PublishPluginCommand extends PluginCommand {
113108
114109 @override
115110 final String description =
116- 'Attempts to publish the given plugin and tag its release on GitHub.\n '
111+ 'Attempts to publish the given packages and tag the release(s) on GitHub.\n '
117112 'If running this on CI, an environment variable named $_pubCredentialName must be set to a String that represents the pub credential JSON.\n '
118113 'WARNING: Do not check in the content of pub credential JSON, it should only come from secure sources.' ;
119114
@@ -123,14 +118,6 @@ class PublishPluginCommand extends PluginCommand {
123118
124119 @override
125120 Future <void > run () async {
126- final String packageName = getStringArg (_packageOption);
127- final bool publishAllChanged = getBoolArg (_allChangedFlag);
128- if (packageName.isEmpty && ! publishAllChanged) {
129- printError (
130- 'Must specify a package to publish. See `plugin_tools help publish-plugin`.' );
131- throw ToolExit (1 );
132- }
133-
134121 print ('Checking local repo...' );
135122 final GitDir repository = await gitDir;
136123 final String remoteName = getStringArg (_remoteOption);
@@ -146,36 +133,52 @@ class PublishPluginCommand extends PluginCommand {
146133 print ('=============== DRY RUN ===============' );
147134 }
148135
149- bool successful;
150- if (publishAllChanged) {
151- successful = await _publishAllChangedPackages (
152- baseGitDir: repository,
153- remoteForTagPush: remote,
154- );
155- } else {
156- successful = await _publishAndTagPackage (
157- packageDir: _getPackageDir (packageName),
158- remoteForTagPush: remote,
159- );
160- }
136+ final List <PackageEnumerationEntry > packages = await _getPackagesToProcess ()
137+ .where ((PackageEnumerationEntry entry) => ! entry.excluded)
138+ .toList ();
139+ bool successful = true ;
140+
141+ successful = await _publishPackages (
142+ packages,
143+ baseGitDir: repository,
144+ remoteForTagPush: remote,
145+ );
161146
162- _pubVersionFinder.httpClient.close ();
163147 await _finish (successful);
164148 }
165149
166- Future <bool > _publishAllChangedPackages ({
150+ Stream <PackageEnumerationEntry > _getPackagesToProcess () async * {
151+ if (getBoolArg (_allChangedFlag)) {
152+ final GitVersionFinder gitVersionFinder = await retrieveVersionFinder ();
153+ final List <String > changedPubspecs =
154+ await gitVersionFinder.getChangedPubSpecs ();
155+
156+ for (final String pubspecPath in changedPubspecs) {
157+ // Convert git's Posix-style paths to a path that matches the current
158+ // filesystem.
159+ final String localStylePubspecPath =
160+ path.joinAll (p.posix.split (pubspecPath));
161+ final File pubspecFile = packagesDir.fileSystem
162+ .directory ((await gitDir).path)
163+ .childFile (localStylePubspecPath);
164+ yield PackageEnumerationEntry (RepositoryPackage (pubspecFile.parent),
165+ excluded: false );
166+ }
167+ } else {
168+ yield * getTargetPackages (filterExcluded: false );
169+ }
170+ }
171+
172+ Future <bool > _publishPackages (
173+ List <PackageEnumerationEntry > packages, {
167174 required GitDir baseGitDir,
168175 required _RemoteInfo remoteForTagPush,
169176 }) async {
170- final GitVersionFinder gitVersionFinder = await retrieveVersionFinder ();
171- final List <String > changedPubspecs =
172- await gitVersionFinder.getChangedPubSpecs ();
173- if (changedPubspecs.isEmpty) {
177+ if (packages.isEmpty) {
174178 print ('No version updates in this commit.' );
175179 return true ;
176180 }
177181
178- print ('Getting existing tags...' );
179182 final io.ProcessResult existingTagsResult =
180183 await baseGitDir.runCommand (< String > ['tag' , '--sort=-committerdate' ]);
181184 final List <String > existingTags = (existingTagsResult.stdout as String )
@@ -185,16 +188,11 @@ class PublishPluginCommand extends PluginCommand {
185188 final List <String > packagesReleased = < String > [];
186189 final List <String > packagesFailed = < String > [];
187190
188- for (final String pubspecPath in changedPubspecs) {
189- // Convert git's Posix-style paths to a path that matches the current
190- // filesystem.
191- final String localStylePubspecPath =
192- path.joinAll (p.posix.split (pubspecPath));
193- final File pubspecFile = packagesDir.fileSystem
194- .directory (baseGitDir.path)
195- .childFile (localStylePubspecPath);
191+ for (final PackageEnumerationEntry entry in packages) {
192+ final RepositoryPackage package = entry.package;
193+
196194 final _CheckNeedsReleaseResult result = await _checkNeedsRelease (
197- pubspecFile : pubspecFile ,
195+ package : package ,
198196 existingTags: existingTags,
199197 );
200198 switch (result) {
@@ -203,17 +201,15 @@ class PublishPluginCommand extends PluginCommand {
203201 case _CheckNeedsReleaseResult .noRelease:
204202 continue ;
205203 case _CheckNeedsReleaseResult .failure:
206- packagesFailed.add (pubspecFile.parent.basename );
204+ packagesFailed.add (package.displayName );
207205 continue ;
208206 }
209207 print ('\n ' );
210- if (await _publishAndTagPackage (
211- packageDir: pubspecFile.parent,
212- remoteForTagPush: remoteForTagPush,
213- )) {
214- packagesReleased.add (pubspecFile.parent.basename);
208+ if (await _publishAndTagPackage (package,
209+ remoteForTagPush: remoteForTagPush)) {
210+ packagesReleased.add (package.displayName);
215211 } else {
216- packagesFailed.add (pubspecFile.parent.basename );
212+ packagesFailed.add (package.displayName );
217213 }
218214 print ('\n ' );
219215 }
@@ -230,31 +226,32 @@ class PublishPluginCommand extends PluginCommand {
230226 // Publish the package to pub with `pub publish`, then git tag the release
231227 // and push the tag to [remoteForTagPush].
232228 // Returns `true` if publishing and tagging are successful.
233- Future <bool > _publishAndTagPackage ({
234- required Directory packageDir,
235- required _RemoteInfo remoteForTagPush,
229+ Future <bool > _publishAndTagPackage (
230+ RepositoryPackage package, {
231+ _RemoteInfo ? remoteForTagPush,
236232 }) async {
237- if (! await _publishPlugin (packageDir : packageDir )) {
233+ if (! await _publishPackage (package )) {
238234 return false ;
239235 }
240236 if (! await _tagRelease (
241- packageDir : packageDir ,
237+ package ,
242238 remoteForPush: remoteForTagPush,
243239 )) {
244240 return false ;
245241 }
246- print ('Released [${ packageDir . basename }] successfully.' );
242+ print ('Published ${ package . directory . basename } successfully.' );
247243 return true ;
248244 }
249245
250246 // Returns a [_CheckNeedsReleaseResult] that indicates the result.
251247 Future <_CheckNeedsReleaseResult > _checkNeedsRelease ({
252- required File pubspecFile ,
248+ required RepositoryPackage package ,
253249 required List <String > existingTags,
254250 }) async {
251+ final File pubspecFile = package.pubspecFile;
255252 if (! pubspecFile.existsSync ()) {
256253 print ('''
257- The file at The pubspec file at ${pubspecFile .path } does not exist. Publishing will not happen for ${pubspecFile .parent .basename }.
254+ The pubspec file at ${pubspecFile .path } does not exist. Publishing will not happen for ${pubspecFile .parent .basename }.
258255Safe to ignore if the package is deleted in this commit.
259256''' );
260257 return _CheckNeedsReleaseResult .noRelease;
@@ -279,7 +276,8 @@ Safe to ignore if the package is deleted in this commit.
279276 return _CheckNeedsReleaseResult .failure;
280277 }
281278
282- // Check if the package named `packageName` with `version` has already published.
279+ // Check if the package named `packageName` with `version` has already
280+ // been published.
283281 final Version version = pubspec.version! ;
284282 final PubVersionFinderResponse pubVersionFinderResponse =
285283 await _pubVersionFinder.getPackageVersion (packageName: pubspec.name);
@@ -303,31 +301,31 @@ Safe to ignore if the package is deleted in this commit.
303301 return _CheckNeedsReleaseResult .release;
304302 }
305303
306- // Publish the plugin .
304+ // Publish the package .
307305 //
308306 // Returns `true` if successful, `false` otherwise.
309- Future <bool > _publishPlugin ({ required Directory packageDir} ) async {
310- final bool gitStatusOK = await _checkGitStatus (packageDir );
307+ Future <bool > _publishPackage ( RepositoryPackage package ) async {
308+ final bool gitStatusOK = await _checkGitStatus (package );
311309 if (! gitStatusOK) {
312310 return false ;
313311 }
314- final bool publishOK = await _publish (packageDir );
312+ final bool publishOK = await _publish (package );
315313 if (! publishOK) {
316314 return false ;
317315 }
318316 print ('Package published!' );
319317 return true ;
320318 }
321319
322- // Tag the release with <plugin -name>-v<version>, and, if [remoteForTagPush]
320+ // Tag the release with <package -name>-v<version>, and, if [remoteForTagPush]
323321 // is provided, push it to that remote.
324322 //
325323 // Return `true` if successful, `false` otherwise.
326- Future <bool > _tagRelease ({
327- required Directory packageDir,
324+ Future <bool > _tagRelease (
325+ RepositoryPackage package, {
328326 _RemoteInfo ? remoteForPush,
329327 }) async {
330- final String tag = _getTag (packageDir );
328+ final String tag = _getTag (package );
331329 print ('Tagging release $tag ...' );
332330 if (! getBoolArg (_dryRunFlag)) {
333331 final io.ProcessResult result = await (await gitDir).runCommand (
@@ -351,6 +349,7 @@ Safe to ignore if the package is deleted in this commit.
351349 }
352350
353351 Future <void > _finish (bool successful) async {
352+ _pubVersionFinder.httpClient.close ();
354353 await _stdinSubscription? .cancel ();
355354 _stdinSubscription = null ;
356355 if (successful) {
@@ -361,20 +360,14 @@ Safe to ignore if the package is deleted in this commit.
361360 }
362361 }
363362
364- // Returns the packageDirectory based on the package name.
365- // Throws ToolExit if the `package` doesn't exist.
366- Directory _getPackageDir (String packageName) {
367- final Directory packageDir = packagesDir.childDirectory (packageName);
368- if (! packageDir.existsSync ()) {
369- printError ('${packageDir .absolute .path } does not exist.' );
370- throw ToolExit (1 );
371- }
372- return packageDir;
373- }
374-
375- Future <bool > _checkGitStatus (Directory packageDir) async {
363+ Future <bool > _checkGitStatus (RepositoryPackage package) async {
376364 final io.ProcessResult statusResult = await (await gitDir).runCommand (
377- < String > ['status' , '--porcelain' , '--ignored' , packageDir.absolute.path],
365+ < String > [
366+ 'status' ,
367+ '--porcelain' ,
368+ '--ignored' ,
369+ package.directory.absolute.path
370+ ],
378371 throwOnError: false ,
379372 );
380373 if (statusResult.exitCode != 0 ) {
@@ -402,10 +395,10 @@ Safe to ignore if the package is deleted in this commit.
402395 return getRemoteUrlResult.stdout as String ? ;
403396 }
404397
405- Future <bool > _publish (Directory packageDir ) async {
398+ Future <bool > _publish (RepositoryPackage package ) async {
406399 final List <String > publishFlags = getStringListArg (_pubFlagsOption);
407- print (
408- 'Running `pub publish ${ publishFlags . join ( ' ' )}` in ${ packageDir .absolute .path }...\n ' );
400+ print ('Running `pub publish ${ publishFlags . join ( ' ' )}` in '
401+ '${ package . directory .absolute .path }...\n ' );
409402 if (getBoolArg (_dryRunFlag)) {
410403 return true ;
411404 }
@@ -419,22 +412,22 @@ Safe to ignore if the package is deleted in this commit.
419412
420413 final io.Process publish = await processRunner.start (
421414 flutterCommand, < String > ['pub' , 'publish' ] + publishFlags,
422- workingDirectory: packageDir );
415+ workingDirectory: package.directory );
423416 publish.stdout.transform (utf8.decoder).listen ((String data) => print (data));
424417 publish.stderr.transform (utf8.decoder).listen ((String data) => print (data));
425418 _stdinSubscription ?? = _stdin
426419 .transform (utf8.decoder)
427420 .listen ((String data) => publish.stdin.writeln (data));
428421 final int result = await publish.exitCode;
429422 if (result != 0 ) {
430- printError ('Publish ${packageDir .basename } failed.' );
423+ printError ('Publishing ${package . directory .basename } failed.' );
431424 return false ;
432425 }
433426 return true ;
434427 }
435428
436- String _getTag (Directory packageDir ) {
437- final File pubspecFile = packageDir. childFile ( 'pubspec.yaml' ) ;
429+ String _getTag (RepositoryPackage package ) {
430+ final File pubspecFile = package.pubspecFile ;
438431 final YamlMap pubspecYaml =
439432 loadYaml (pubspecFile.readAsStringSync ()) as YamlMap ;
440433 final String name = pubspecYaml['name' ] as String ;
0 commit comments