// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/publish_command.dart';
import 'package:git/git.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';

import 'mocks.dart';
import 'util.dart';

void main() {
  late MockPlatform platform;
  late Directory packagesDir;
  late TestProcessRunner processRunner;
  late PublishCommand command;
  late CommandRunner<void> commandRunner;
  late MockStdin mockStdin;
  // Map of package name to mock response.
  late Map<String, Map<String, dynamic>> mockHttpResponses;

  void createMockCredentialFile() {
    packagesDir.fileSystem.file(command.credentialsPath)
      ..createSync(recursive: true)
      ..writeAsStringSync('some credential');
  }

  setUp(() async {
    platform = MockPlatform(isLinux: true);
    processRunner = TestProcessRunner();
    final GitDir gitDir;
    (:packagesDir, processRunner: _, gitProcessRunner: _, :gitDir) =
        configureBaseCommandMocks(
      platform: platform,
      customProcessRunner: processRunner,
      customGitProcessRunner: processRunner,
    );
    platform.environment['HOME'] = '/home';

    mockHttpResponses = <String, Map<String, dynamic>>{};
    final MockClient mockClient = MockClient((http.Request request) async {
      final String packageName =
          request.url.pathSegments.last.replaceAll('.json', '');
      final Map<String, dynamic>? response = mockHttpResponses[packageName];
      if (response != null) {
        return http.Response(json.encode(response), 200);
      }
      // Default to simulating the plugin never having been published.
      return http.Response('', 404);
    });

    mockStdin = MockStdin();
    command = PublishCommand(
      packagesDir,
      platform: platform,
      processRunner: processRunner,
      stdinput: mockStdin,
      gitDir: gitDir,
      httpClient: mockClient,
    );
    commandRunner = CommandRunner<void>('tester', '')..addCommand(command);
  });

  group('Initial validation', () {
    test('refuses to proceed with dirty files', () async {
      final RepositoryPackage plugin =
          createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['git-status'] =
          <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '?? ${plugin.directory.childFile('tmp').path}\n'))
      ];

      Error? commandError;
      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains("There are files in the package directory that haven't "
                'been saved in git. Refusing to publish these files:\n\n'
                '?? /packages/foo/tmp\n\n'
                'If the directory should be clean, you can run `git clean -xdf && '
                'git reset --hard HEAD` to wipe all local changes.'),
            contains('foo:\n'
                '    uncommitted changes'),
          ]));
    });

    test("fails immediately if the remote doesn't exist", () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['git-remote'] =
          <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(exitCode: 1)),
      ];

      Error? commandError;
      final List<String> output = await runCapturingPrint(
          commandRunner, <String>['publish', '--packages=foo'],
          errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'Unable to find URL for remote upstream; cannot push tags'),
          ]));
    });
  });

  group('pre-publish script', () {
    test('runs if present', () async {
      final RepositoryPackage package =
          createFakePackage('foo', packagesDir, examples: <String>[]);
      package.prePublishScript.createSync(recursive: true);

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ]);

      expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Running pre-publish hook tool/pre_publish.dart...'),
        ]),
      );
      expect(
          processRunner.recordedCalls,
          containsAllInOrder(<ProcessCall>[
            ProcessCall(
                'dart',
                const <String>[
                  'pub',
                  'get',
                ],
                package.directory.path),
            ProcessCall(
                'dart',
                const <String>[
                  'run',
                  'tool/pre_publish.dart',
                ],
                package.directory.path),
          ]));
    });

    test('causes command failure if it fails', () async {
      final RepositoryPackage package = createFakePackage('foo', packagesDir,
          isFlutter: true, examples: <String>[]);
      package.prePublishScript.createSync(recursive: true);

      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(exitCode: 1),
            <String>['run']), // run tool/pre_publish.dart
      ];

      Error? commandError;
      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Pre-publish script failed.'),
        ]),
      );
      expect(
          processRunner.recordedCalls,
          containsAllInOrder(<ProcessCall>[
            ProcessCall(
                getFlutterCommand(platform),
                const <String>[
                  'pub',
                  'get',
                ],
                package.directory.path),
            ProcessCall(
                'dart',
                const <String>[
                  'run',
                  'tool/pre_publish.dart',
                ],
                package.directory.path),
          ]));
    });
  });

  group('Publishes package', () {
    test('while showing all output from pub publish to the user', () async {
      createFakePlugin('plugin1', packagesDir, examples: <String>[]);
      createFakePlugin('plugin2', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
        FakeProcessInfo(
            MockProcess(
                stdout: 'Foo',
                stderr: 'Bar',
                stdoutEncoding: utf8,
                stderrEncoding: utf8),
            <String>['pub', 'publish']), // publish for plugin1
        FakeProcessInfo(
            MockProcess(
                stdout: 'Baz', stdoutEncoding: utf8, stderrEncoding: utf8),
            <String>['pub', 'publish']), // publish for plugin2
      ];

      final List<String> output = await runCapturingPrint(
          commandRunner, <String>['publish', '--packages=plugin1,plugin2']);

      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Running `pub publish ` in /packages/plugin1...'),
            contains('Foo'),
            contains('Bar'),
            contains('Package published!'),
            contains('Running `pub publish ` in /packages/plugin2...'),
            contains('Baz'),
            contains('Package published!'),
          ]));
    });

    test('forwards input from the user to `pub publish`', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      mockStdin.mockUserInputs.add(utf8.encode('user input'));

      await runCapturingPrint(
          commandRunner, <String>['publish', '--packages=foo']);

      expect(processRunner.mockPublishProcess.stdinMock.lines,
          contains('user input'));
    });

    test('forwards --pub-publish-flags to pub publish', () async {
      final RepositoryPackage plugin =
          createFakePlugin('foo', packagesDir, examples: <String>[]);

      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--pub-publish-flags',
        '--dry-run,--server=bar'
      ]);

      expect(
          processRunner.recordedCalls,
          contains(ProcessCall(
              'flutter',
              const <String>['pub', 'publish', '--dry-run', '--server=bar'],
              plugin.path)));
    });

    test(
        '--skip-confirmation flag automatically adds --force to --pub-publish-flags',
        () async {
      createMockCredentialFile();
      final RepositoryPackage plugin =
          createFakePlugin('foo', packagesDir, examples: <String>[]);

      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--skip-confirmation',
        '--pub-publish-flags',
        '--server=bar'
      ]);

      expect(
          processRunner.recordedCalls,
          contains(ProcessCall(
              'flutter',
              const <String>['pub', 'publish', '--server=bar', '--force'],
              plugin.path)));
    });

    test('--force is only added once, regardless of plugin count', () async {
      createMockCredentialFile();
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin_a', packagesDir, examples: <String>[]);
      final RepositoryPackage plugin2 =
          createFakePlugin('plugin_b', packagesDir, examples: <String>[]);

      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=plugin_a,plugin_b',
        '--skip-confirmation',
        '--pub-publish-flags',
        '--server=bar'
      ]);

      expect(
          processRunner.recordedCalls,
          containsAllInOrder(<ProcessCall>[
            ProcessCall(
                'flutter',
                const <String>['pub', 'publish', '--server=bar', '--force'],
                plugin1.path),
            ProcessCall(
                'flutter',
                const <String>['pub', 'publish', '--server=bar', '--force'],
                plugin2.path),
          ]));
    });

    test('creates credential file from envirnoment variable if necessary',
        () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);
      const String credentials = 'some credential';
      platform.environment['PUB_CREDENTIALS'] = credentials;

      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--skip-confirmation',
        '--pub-publish-flags',
        '--server=bar'
      ]);

      final File credentialFile =
          packagesDir.fileSystem.file(command.credentialsPath);
      expect(credentialFile.existsSync(), true);
      expect(credentialFile.readAsStringSync(), credentials);
    });

    test('throws if pub publish fails', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(exitCode: 128), <String>['pub', 'publish'])
      ];

      Error? commandError;
      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Publishing foo failed.'),
          ]));
    });

    test('publish, dry run', () async {
      final RepositoryPackage plugin =
          createFakePlugin('foo', packagesDir, examples: <String>[]);

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--dry-run',
      ]);

      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('=============== DRY RUN ==============='),
            contains('Running for foo'),
            contains('Running `pub publish ` in ${plugin.path}...'),
            contains('Tagging release foo-v0.0.1...'),
            contains('Pushing tag to upstream...'),
            contains('Published foo successfully!'),
          ]));
    });

    test('can publish non-flutter package', () async {
      const String packageName = 'a_package';
      createFakePackage(packageName, packagesDir);

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=$packageName',
      ]);

      expect(
        output,
        containsAllInOrder(
          <Matcher>[
            contains('Running `pub publish ` in /packages/a_package...'),
            contains('Package published!'),
          ],
        ),
      );
    });

    test('skips publish with --tag-for-auto-publish', () async {
      const String packageName = 'a_package';
      createFakePackage(packageName, packagesDir);

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=$packageName',
        '--tag-for-auto-publish',
      ]);

      // There should be no variant of any command containing "publish".
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.toString()),
          isNot(contains(contains('publish'))));
      // The output should indicate that it was tagged, not published.
      expect(
        output,
        containsAllInOrder(
          <Matcher>[
            contains('Tagged a_package successfully!'),
          ],
        ),
      );
    });
  });

  group('Tags release', () {
    test('with the version and name from the pubspec.yaml', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);
      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ]);

      expect(processRunner.recordedCalls,
          contains(const ProcessCall('git-tag', <String>['foo-v0.0.1'], null)));
    });

    test('only if publishing succeeded', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(exitCode: 128), <String>['pub', 'publish']),
      ];

      Error? commandError;
      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Publishing foo failed.'),
          ]));
      expect(
          processRunner.recordedCalls,
          isNot(contains(
              const ProcessCall('git-tag', <String>['foo-v0.0.1'], null))));
    });

    test('when passed --tag-for-auto-publish', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);
      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--tag-for-auto-publish',
      ]);

      expect(processRunner.recordedCalls,
          contains(const ProcessCall('git-tag', <String>['foo-v0.0.1'], null)));
    });
  });

  group('Pushes tags', () {
    test('to upstream by default', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      mockStdin.readLineOutput = 'y';

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
      ]);

      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'foo-v0.0.1'], null)));
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Pushing tag to upstream...'),
            contains('Published foo successfully!'),
          ]));
    });

    test('does not ask for user input if the --skip-confirmation flag is on',
        () async {
      createMockCredentialFile();
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--skip-confirmation',
        '--packages=foo',
      ]);

      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'foo-v0.0.1'], null)));
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Published foo successfully!'),
          ]));
    });

    test('when passed --tag-for-auto-publish', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);
      await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--skip-confirmation',
        '--tag-for-auto-publish',
      ]);

      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'foo-v0.0.1'], null)));
    });

    test('to upstream by default, dry run', () async {
      final RepositoryPackage plugin =
          createFakePlugin('foo', packagesDir, examples: <String>[]);

      mockStdin.readLineOutput = 'y';

      final List<String> output = await runCapturingPrint(
          commandRunner, <String>['publish', '--packages=foo', '--dry-run']);

      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('=============== DRY RUN ==============='),
            contains('Running `pub publish ` in ${plugin.path}...'),
            contains('Tagging release foo-v0.0.1...'),
            contains('Pushing tag to upstream...'),
            contains('Published foo successfully!'),
          ]));
    });

    test('to different remotes based on a flag', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      mockStdin.readLineOutput = 'y';

      final List<String> output =
          await runCapturingPrint(commandRunner, <String>[
        'publish',
        '--packages=foo',
        '--remote',
        'origin',
      ]);

      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['origin', 'foo-v0.0.1'], null)));
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Published foo successfully!'),
          ]));
    });
  });

  group('--already-tagged', () {
    test('passes when HEAD has the expected tag', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess()), // Skip the initializeRun call.
        FakeProcessInfo(MockProcess(stdout: 'foo-v0.0.1\n'),
            <String>['--points-at', 'HEAD'])
      ];

      await runCapturingPrint(commandRunner,
          <String>['publish', '--packages=foo', '--already-tagged']);
    });

    test('fails if HEAD does not have the expected tag', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      Error? commandError;
      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--packages=foo', '--already-tagged'],
          errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('The current checkout is not already tagged "foo-v0.0.1"'),
            contains('missing tag'),
          ]));
    });

    test('does not create or push tags', () async {
      createFakePlugin('foo', packagesDir, examples: <String>[]);

      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess()), // Skip the initializeRun call.
        FakeProcessInfo(MockProcess(stdout: 'foo-v0.0.1\n'),
            <String>['--points-at', 'HEAD'])
      ];

      await runCapturingPrint(commandRunner,
          <String>['publish', '--packages=foo', '--already-tagged']);

      expect(
          processRunner.recordedCalls,
          isNot(contains(
              const ProcessCall('git-tag', <String>['foo-v0.0.1'], null))));
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });
  });

  group('Auto release (all-changed flag)', () {
    test('can release newly created plugins', () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>[],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>[],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir);
      // federated
      final RepositoryPackage plugin2 = createFakePlugin(
        'plugin2',
        packagesDir.childDirectory('plugin2'),
      );
      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];
      mockStdin.readLineOutput = 'y';

      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);

      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'Publishing all packages that have changed relative to "HEAD~"'),
            contains('Running `pub publish ` in ${plugin1.path}...'),
            contains('Running `pub publish ` in ${plugin2.path}...'),
            contains('plugin1 - published'),
            contains('plugin2/plugin2 - published'),
          ]));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin1-v0.0.1'], null)));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin2-v0.0.1'], null)));
    });

    test('can release newly created plugins, while there are existing plugins',
        () async {
      mockHttpResponses['plugin0'] = <String, dynamic>{
        'name': 'plugin0',
        'versions': <String>['0.0.1'],
      };

      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>[],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>[],
      };

      // The existing plugin.
      createFakePlugin('plugin0', packagesDir);
      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir);
      // federated
      final RepositoryPackage plugin2 =
          createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));

      // Git results for plugin0 having been released already, and plugin1 and
      // plugin2 being new.
      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(stdout: 'plugin0-v0.0.1\n'))
      ];
      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];

      mockStdin.readLineOutput = 'y';

      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);

      expect(
          output,
          containsAllInOrder(<String>[
            'Running `pub publish ` in ${plugin1.path}...\n',
            'Running `pub publish ` in ${plugin2.path}...\n',
          ]));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin1-v0.0.1'], null)));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin2-v0.0.1'], null)));
    });

    test('can release newly created plugins, dry run', () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>[],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>[],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir);
      // federated
      final RepositoryPackage plugin2 =
          createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];
      mockStdin.readLineOutput = 'y';

      final List<String> output = await runCapturingPrint(
          commandRunner, <String>[
        'publish',
        '--all-changed',
        '--base-sha=HEAD~',
        '--dry-run'
      ]);

      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('=============== DRY RUN ==============='),
            contains('Running `pub publish ` in ${plugin1.path}...'),
            contains('Tagging release plugin1-v0.0.1...'),
            contains('Pushing tag to upstream...'),
            contains('Published plugin1 successfully!'),
            contains('Running `pub publish ` in ${plugin2.path}...'),
            contains('Tagging release plugin2-v0.0.1...'),
            contains('Pushing tag to upstream...'),
            contains('Published plugin2 successfully!'),
          ]));
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });

    test('version change triggers releases.', () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>['0.0.1'],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>['0.0.1'],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir, version: '0.0.2');
      // federated
      final RepositoryPackage plugin2 = createFakePlugin(
          'plugin2', packagesDir.childDirectory('plugin2'),
          version: '0.0.2');

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];

      mockStdin.readLineOutput = 'y';

      final List<String> output2 = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);
      expect(
          output2,
          containsAllInOrder(<Matcher>[
            contains('Running `pub publish ` in ${plugin1.path}...'),
            contains('Published plugin1 successfully!'),
            contains('Running `pub publish ` in ${plugin2.path}...'),
            contains('Published plugin2 successfully!'),
          ]));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin1-v0.0.2'], null)));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin2-v0.0.2'], null)));
    });

    test(
        'delete package will not trigger publish but exit the command successfully!',
        () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>['0.0.1'],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>['0.0.1'],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir, version: '0.0.2');
      // federated
      final RepositoryPackage plugin2 =
          createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));
      plugin2.directory.deleteSync(recursive: true);

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];

      mockStdin.readLineOutput = 'y';

      final List<String> output2 = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);
      expect(
          output2,
          containsAllInOrder(<Matcher>[
            contains('Running `pub publish ` in ${plugin1.path}...'),
            contains('Published plugin1 successfully!'),
            contains(
                'The pubspec file for plugin2/plugin2 does not exist, so no publishing will happen.\nSafe to ignore if the package is deleted in this commit.\n'),
            contains('SKIPPING: package deleted'),
            contains('skipped (with warning)'),
          ]));
      expect(
          processRunner.recordedCalls,
          contains(const ProcessCall(
              'git-push', <String>['upstream', 'plugin1-v0.0.2'], null)));
    });

    test('Existing versions do not trigger release, also prints out message.',
        () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>['0.0.2'],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>['0.0.2'],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir, version: '0.0.2');
      // federated
      final RepositoryPackage plugin2 = createFakePlugin(
          'plugin2', packagesDir.childDirectory('plugin2'),
          version: '0.0.2');

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];
      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: 'plugin1-v0.0.2\n'
                'plugin2-v0.0.2\n'))
      ];

      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);

      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('plugin1 0.0.2 has already been published'),
            contains('SKIPPING: already published'),
            contains('plugin2 0.0.2 has already been published'),
            contains('SKIPPING: already published'),
          ]));

      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });

    test(
        'Existing versions do not trigger release, but fail if the tags do not exist.',
        () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'plugin1',
        'versions': <String>['0.0.2'],
      };

      mockHttpResponses['plugin2'] = <String, dynamic>{
        'name': 'plugin2',
        'versions': <String>['0.0.2'],
      };

      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir, version: '0.0.2');
      // federated
      final RepositoryPackage plugin2 = createFakePlugin(
          'plugin2', packagesDir.childDirectory('plugin2'),
          version: '0.0.2');

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.pubspecFile.path}\n'
                '${plugin2.pubspecFile.path}\n'))
      ];

      Error? commandError;
      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~'],
          errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('plugin1 0.0.2 has already been published, '
                'however the git release tag (plugin1-v0.0.2) was not found.'),
            contains('plugin2 0.0.2 has already been published, '
                'however the git release tag (plugin2-v0.0.2) was not found.'),
          ]));
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });

    test('No version change does not release any plugins', () async {
      // Non-federated
      final RepositoryPackage plugin1 =
          createFakePlugin('plugin1', packagesDir);
      // federated
      final RepositoryPackage plugin2 =
          createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));

      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(
            stdout: '${plugin1.libDirectory.childFile('plugin1.dart').path}\n'
                '${plugin2.libDirectory.childFile('plugin2.dart').path}\n'))
      ];

      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);

      expect(output, containsAllInOrder(<String>['Ran for 0 package(s)']));
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });

    test('Do not release flutter_plugin_tools', () async {
      mockHttpResponses['plugin1'] = <String, dynamic>{
        'name': 'flutter_plugin_tools',
        'versions': <String>[],
      };

      final RepositoryPackage flutterPluginTools =
          createFakePlugin('flutter_plugin_tools', packagesDir);
      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
        FakeProcessInfo(
            MockProcess(stdout: flutterPluginTools.pubspecFile.path))
      ];

      final List<String> output = await runCapturingPrint(commandRunner,
          <String>['publish', '--all-changed', '--base-sha=HEAD~']);

      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'SKIPPING: publishing flutter_plugin_tools via the tool is not supported')
          ]));
      expect(
          output.contains(
            'Running `pub publish ` in ${flutterPluginTools.path}...',
          ),
          isFalse);
      expect(
          processRunner.recordedCalls
              .map((ProcessCall call) => call.executable),
          isNot(contains('git-push')));
    });
  });

  group('credential location', () {
    test('Linux with XDG', () async {
      platform = MockPlatform(isLinux: true);
      platform.environment['XDG_CONFIG_HOME'] = '/xdghome/config';
      command = PublishCommand(packagesDir, platform: platform);

      expect(
          command.credentialsPath, '/xdghome/config/dart/pub-credentials.json');
    });

    test('Linux without XDG', () async {
      platform = MockPlatform(isLinux: true);
      platform.environment['HOME'] = '/home';
      command = PublishCommand(packagesDir, platform: platform);

      expect(
          command.credentialsPath, '/home/.config/dart/pub-credentials.json');
    });

    test('macOS', () async {
      platform = MockPlatform(isMacOS: true);
      platform.environment['HOME'] = '/Users/someuser';
      command = PublishCommand(packagesDir, platform: platform);

      expect(command.credentialsPath,
          '/Users/someuser/Library/Application Support/dart/pub-credentials.json');
    });

    test('Windows', () async {
      platform = MockPlatform(isWindows: true);
      platform.environment['APPDATA'] = r'C:\Users\SomeUser\AppData';
      command = PublishCommand(packagesDir, platform: platform);

      expect(command.credentialsPath,
          r'C:\Users\SomeUser\AppData\dart\pub-credentials.json');
    });
  });
}

/// An extension of [RecordingProcessRunner] that stores 'flutter pub publish'
/// calls so that their input streams can be checked in tests.
class TestProcessRunner extends RecordingProcessRunner {
  // Most recent returned publish process.
  late MockProcess mockPublishProcess;

  @override
  Future<io.Process> start(String executable, List<String> args,
      {Directory? workingDirectory}) async {
    final io.Process process =
        await super.start(executable, args, workingDirectory: workingDirectory);
    if (executable == 'flutter' &&
        args.isNotEmpty &&
        args[0] == 'pub' &&
        args[1] == 'publish') {
      mockPublishProcess = process as MockProcess;
    }
    return process;
  }
}

class MockStdin extends Mock implements io.Stdin {
  List<List<int>> mockUserInputs = <List<int>>[];
  final StreamController<List<int>> _controller = StreamController<List<int>>();
  String? readLineOutput;

  @override
  Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
    mockUserInputs.forEach(_addUserInputsToSteam);
    return _controller.stream.transform(streamTransformer);
  }

  @override
  StreamSubscription<List<int>> listen(void Function(List<int> event)? onData,
      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
    return _controller.stream.listen(onData,
        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  String? readLineSync(
          {Encoding encoding = io.systemEncoding,
          bool retainNewlines = false}) =>
      readLineOutput;

  void _addUserInputsToSteam(List<int> input) => _controller.add(input);
}
