[tool] refactor publish plugin command (#3779)

diff --git a/script/tool/lib/src/publish_plugin_command.dart b/script/tool/lib/src/publish_plugin_command.dart
index eb59091..d004002 100644
--- a/script/tool/lib/src/publish_plugin_command.dart
+++ b/script/tool/lib/src/publish_plugin_command.dart
@@ -85,15 +85,24 @@
   final Print _print;
   final Stdin _stdin;
   // The directory of the actual package that we are publishing.
-  Directory _packageDir;
   StreamSubscription<String> _stdinSubscription;
 
   @override
   Future<Null> run() async {
     checkSharding();
+    final String package = argResults[_packageOption];
+    if (package == null) {
+      _print(
+          'Must specify a package to publish. See `plugin_tools help publish-plugin`.');
+      throw ToolExit(1);
+    }
+
     _print('Checking local repo...');
-    _packageDir = _checkPackageDir();
-    await _checkGitStatus();
+    if (!await GitDir.isGitDir(packagesDir.path)) {
+      _print('$packagesDir is not a valid Git repository.');
+      throw ToolExit(1);
+    }
+
     final bool shouldPushTag = argResults[_pushTagsOption];
     final String remote = argResults[_remoteOption];
     String remoteUrl;
@@ -102,23 +111,39 @@
     }
     _print('Local repo is ready!');
 
-    await _publish();
-    _print('Package published!');
-    if (!argResults[_tagReleaseOption]) {
-      return await _finishSuccesfully();
+    final Directory packageDir = _getPackageDir(package);
+    await _publishPlugin(packageDir: packageDir);
+    if (argResults[_tagReleaseOption] as bool) {
+      await _tagRelease(
+          packageDir: packageDir,
+          remote: remote,
+          remoteUrl: remoteUrl,
+          shouldPushTag: shouldPushTag);
     }
+    await _finishSuccesfully();
+  }
 
-    _print('Tagging release...');
-    final String tag = _getTag();
+  Future<void> _publishPlugin({@required Directory packageDir}) async {
+    await _checkGitStatus(packageDir);
+    await _publish(packageDir);
+    _print('Package published!');
+  }
+
+  Future<void> _tagRelease(
+      {@required Directory packageDir,
+      @required String remote,
+      @required String remoteUrl,
+      @required bool shouldPushTag}) async {
+    final String tag = _getTag(packageDir);
+    _print('Tagging release $tag...');
     await processRunner.runAndExitOnError('git', <String>['tag', tag],
-        workingDir: _packageDir);
+        workingDir: packageDir);
     if (!shouldPushTag) {
-      return await _finishSuccesfully();
+      return;
     }
 
     _print('Pushing tag to $remote...');
     await _pushTagToRemote(remote: remote, tag: tag, remoteUrl: remoteUrl);
-    await _finishSuccesfully();
   }
 
   Future<void> _finishSuccesfully() async {
@@ -126,36 +151,28 @@
     _print('Done!');
   }
 
-  Directory _checkPackageDir() {
-    final String package = argResults[_packageOption];
-    if (package == null) {
-      _print(
-          'Must specify a package to publish. See `plugin_tools help publish-plugin`.');
+  // Returns the packageDirectory based on the package name.
+  // Throws ToolExit if the `package` doesn't exist.
+  Directory _getPackageDir(String package) {
+    final Directory packageDir = packagesDir.childDirectory(package);
+    if (!packageDir.existsSync()) {
+      _print('${packageDir.absolute.path} does not exist.');
       throw ToolExit(1);
     }
-    final Directory _packageDir = packagesDir.childDirectory(package);
-    if (!_packageDir.existsSync()) {
-      _print('${_packageDir.absolute.path} does not exist.');
-      throw ToolExit(1);
-    }
-    return _packageDir;
+    return packageDir;
   }
 
-  Future<void> _checkGitStatus() async {
-    if (!await GitDir.isGitDir(packagesDir.path)) {
-      _print('$packagesDir is not a valid Git repository.');
-      throw ToolExit(1);
-    }
-
+  Future<void> _checkGitStatus(Directory packageDir) async {
     final ProcessResult statusResult = await processRunner.runAndExitOnError(
         'git',
         <String>[
           'status',
           '--porcelain',
           '--ignored',
-          _packageDir.absolute.path
+          packageDir.absolute.path
         ],
-        workingDir: _packageDir);
+        workingDir: packageDir);
+
     final String statusOutput = statusResult.stdout;
     if (statusOutput.isNotEmpty) {
       _print(
@@ -169,17 +186,17 @@
   Future<String> _verifyRemote(String remote) async {
     final ProcessResult remoteInfo = await processRunner.runAndExitOnError(
         'git', <String>['remote', 'get-url', remote],
-        workingDir: _packageDir);
+        workingDir: packagesDir);
     return remoteInfo.stdout;
   }
 
-  Future<void> _publish() async {
+  Future<void> _publish(Directory packageDir) async {
     final List<String> publishFlags = argResults[_pubFlagsOption];
     _print(
-        'Running `pub publish ${publishFlags.join(' ')}` in ${_packageDir.absolute.path}...\n');
+        'Running `pub publish ${publishFlags.join(' ')}` in ${packageDir.absolute.path}...\n');
     final Process publish = await processRunner.start(
         'flutter', <String>['pub', 'publish'] + publishFlags,
-        workingDirectory: _packageDir);
+        workingDirectory: packageDir);
     publish.stdout
         .transform(utf8.decoder)
         .listen((String data) => _print(data));
@@ -196,9 +213,9 @@
     }
   }
 
-  String _getTag() {
+  String _getTag(Directory packageDir) {
     final File pubspecFile =
-        fileSystem.file(p.join(_packageDir.path, 'pubspec.yaml'));
+        fileSystem.file(p.join(packageDir.path, 'pubspec.yaml'));
     final YamlMap pubspecYaml = loadYaml(pubspecFile.readAsStringSync());
     final String name = pubspecYaml['name'];
     final String version = pubspecYaml['version'];
@@ -220,7 +237,6 @@
       _print('Tag push canceled.');
       throw ToolExit(1);
     }
-
     await processRunner.runAndExitOnError('git', <String>['push', remote, tag],
         workingDir: packagesDir);
   }
diff --git a/script/tool/test/publish_plugin_command_test.dart b/script/tool/test/publish_plugin_command_test.dart
index 9a0f1d6..cfa40b9 100644
--- a/script/tool/test/publish_plugin_command_test.dart
+++ b/script/tool/test/publish_plugin_command_test.dart
@@ -50,7 +50,7 @@
     mockStdin = MockStdin();
     commandRunner = CommandRunner<Null>('tester', '')
       ..addCommand(PublishPluginCommand(
-          mockPackagesDir, const LocalFileSystem(),
+          mockPackagesDir, mockPackagesDir.fileSystem,
           processRunner: processRunner,
           print: (Object message) => printedMessages.add(message.toString()),
           stdinput: mockStdin));
@@ -65,7 +65,6 @@
     test('requires a package flag', () async {
       await expectLater(() => commandRunner.run(<String>['publish-plugin']),
           throwsA(const TypeMatcher<ToolExit>()));
-
       expect(
           printedMessages.last, contains("Must specify a package to publish."));
     });
@@ -73,7 +72,7 @@
     test('requires an existing flag', () async {
       await expectLater(
           () => commandRunner
-              .run(<String>['publish-plugin', '--package', 'iamerror']),
+              .run(<String>['publish-plugin', '--package', 'iamerror', '--no-push-tags']),
           throwsA(const TypeMatcher<ToolExit>()));
 
       expect(printedMessages.last, contains('iamerror does not exist'));
@@ -84,7 +83,7 @@
 
       await expectLater(
           () => commandRunner
-              .run(<String>['publish-plugin', '--package', testPluginName]),
+              .run(<String>['publish-plugin', '--package', testPluginName, '--no-push-tags']),
           throwsA(const TypeMatcher<ToolExit>()));
 
       expect(
@@ -98,7 +97,6 @@
           () => commandRunner
               .run(<String>['publish-plugin', '--package', testPluginName]),
           throwsA(const TypeMatcher<ToolExit>()));
-
       expect(processRunner.results.last.stderr, contains("No such remote"));
     });