// Copyright 2013 The Flutter Authors
// 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:platform/platform.dart';
import 'package:test/test.dart';

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

void main() {
  late NativePlatform 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 = createMockPlatform(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((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('uses dart rather than flutter for non-Flutter packages', () async {
      final RepositoryPackage package = createFakePackage('foo', packagesDir, examples: <String>[]);

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

      expect(
        processRunner.recordedCalls,
        contains(ProcessCall('dart', const <String>['pub', 'publish'], package.directory.path)),
      );
    });

    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 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 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 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')),
      );
    });

    group('--batch-release-branch flag', () {
      test('filters packages based on the existence of ci_config.yaml', () async {
        // Mock pub.dev responses.
        mockHttpResponses['package1'] = <String, dynamic>{
          'name': 'package1',
          'versions': <String>['0.0.1'],
        };
        mockHttpResponses['package2'] = <String, dynamic>{
          'name': 'package2',
          'versions': <String>['0.0.1'],
        };

        // Mock packages.
        final RepositoryPackage package1 = createFakePackage(
          'package1',
          packagesDir,
          version: '0.0.2',
        );
        createFakeCiConfig(package: package1, batchRelease: true);

        final RepositoryPackage package2 = createFakePackage(
          'package2',
          packagesDir,
          version: '0.0.2',
        );

        expect(package1.ciConfigFile.existsSync(), true);
        expect(package2.ciConfigFile.existsSync(), false);

        // Mock git diff to show both packages have changed.
        processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
          FakeProcessInfo(
            MockProcess(stdout: '${package1.pubspecFile.path}\n${package2.pubspecFile.path}'),
          ),
        ];

        mockStdin.readLineOutput = 'y';

        final List<String> output = await runCapturingPrint(commandRunner, <String>[
          'publish',
          '--all-changed',
          '--base-sha=HEAD~',
          '--batch-release-branch=release-package1-1.0.0',
        ]);
        // Package1 is published in batch realease, pacakge2 is not.
        expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Running `pub publish ` in ${package1.path}...'),
            contains('Published package1 successfully!'),
          ]),
        );

        expect(output, isNot(contains(contains('Running `pub publish ` in ${package2.path}...!'))));
        expect(output, isNot(contains(contains('Published package2 successfully!'))));
      });

      test('filters packages based on the batch release flag value in ci_config.yaml', () async {
        // Mock pub.dev responses.
        mockHttpResponses['package1'] = <String, dynamic>{
          'name': 'package1',
          'versions': <String>['0.0.1'],
        };
        mockHttpResponses['package2'] = <String, dynamic>{
          'name': 'package2',
          'versions': <String>['0.0.1'],
        };

        // Mock packages.
        final RepositoryPackage package1 = createFakePackage(
          'package1',
          packagesDir,
          version: '0.0.2',
        );
        createFakeCiConfig(package: package1, batchRelease: true);
        final RepositoryPackage package2 = createFakePackage(
          'package2',
          packagesDir,
          version: '0.0.2',
        );
        createFakeCiConfig(package: package2, batchRelease: false);

        // Mock git diff to show both packages have changed.
        processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
          FakeProcessInfo(
            MockProcess(stdout: '${package1.pubspecFile.path}\n${package2.pubspecFile.path}'),
          ),
        ];

        mockStdin.readLineOutput = 'y';

        final List<String> output = await runCapturingPrint(commandRunner, <String>[
          'publish',
          '--all-changed',
          '--base-sha=HEAD~',
          '--batch-release-branch=release-package1-1.0.0',
        ]);
        // Package1 is published in batch realease, pacakge2 is not.
        expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Running `pub publish ` in ${package1.path}...'),
            contains('Published package1 successfully!'),
          ]),
        );

        expect(output, isNot(contains(contains('Running `pub publish ` in ${package2.path}...!'))));
        expect(output, isNot(contains(contains('Published package2 successfully!'))));
      });

      test(
        'when --batch-release-branch flag value is empty, batch release packages are filtered out',
        () async {
          // Mock pub.dev responses.
          mockHttpResponses['package1'] = <String, dynamic>{
            'name': 'package1',
            'versions': <String>['0.0.1'],
          };
          mockHttpResponses['package2'] = <String, dynamic>{
            'name': 'package2',
            'versions': <String>['0.0.1'],
          };

          // Mock packages.
          final RepositoryPackage package1 = createFakePackage(
            'package1',
            packagesDir,
            version: '0.0.2',
          );

          final RepositoryPackage package2 = createFakePackage(
            'package2',
            packagesDir,
            version: '0.0.2',
          );
          createFakeCiConfig(package: package2, batchRelease: true);

          // Mock git diff to show both packages have changed.
          processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
            FakeProcessInfo(
              MockProcess(stdout: '${package1.pubspecFile.path}\n${package2.pubspecFile.path}'),
            ),
          ];

          mockStdin.readLineOutput = 'y';

          final List<String> output = await runCapturingPrint(commandRunner, <String>[
            'publish',
            '--all-changed',
            '--base-sha=HEAD~',
          ]);
          // Package1 is published in batch realease, pacakge2 is not.
          expect(
            output,
            containsAllInOrder(<Matcher>[
              contains('Running `pub publish ` in ${package1.path}...'),
              contains('Published package1 successfully!'),
            ]),
          );

          expect(
            output,
            isNot(contains(contains('Running `pub publish ` in ${package2.path}...!'))),
          );
          expect(output, isNot(contains(contains('Published package2 successfully!'))));
        },
      );
      test(' throw tool exit when could not parse ci config file', () async {
        // Mock pub.dev responses.
        mockHttpResponses['package1'] = <String, dynamic>{
          'name': 'package1',
          'versions': <String>['0.0.1'],
        };

        // Mock packages.
        final RepositoryPackage package1 = createFakePackage(
          'package1',
          packagesDir,
          version: '0.0.2',
        );
        createFakeCiConfig(package: package1, batchRelease: false);
        package1.ciConfigFile.writeAsStringSync('wrong format of ci config file');

        // Mock git diff to show both packages have changed.
        processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
          FakeProcessInfo(MockProcess(stdout: '${package1.pubspecFile.path}\n')),
        ];

        mockStdin.readLineOutput = 'y';

        Error? commandError;
        // Package1 is published in batch realease, pacakge2 is not.
        final List<String> output = await runCapturingPrint(
          commandRunner,
          <String>[
            'publish',
            '--all-changed',
            '--base-sha=HEAD~',
            '--batch-release-branch=release-package1-1.0.0',
          ],
          errorHandler: (Error e) {
            commandError = e;
          },
        );

        expect(commandError, isA<ToolExit>());
        expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
              'Could not parse ci_config.yaml for package1: FormatException: Root of ci_config.yaml must be a map.',
            ),
          ]),
        );
      });
    });

    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 = createMockPlatform(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 = createMockPlatform(isLinux: true);
      platform.environment['HOME'] = '/home';
      command = PublishCommand(packagesDir, platform: platform);

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

    test('macOS', () async {
      platform = createMockPlatform(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 = createMockPlatform(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);
}
