// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';

import '../../descriptor.dart' as d;
import '../../test_pub.dart';

void main() {
  group('root-level packages', () {
    setUp(() async {
      // Create two cached revisions of foo.
      await d.git('foo.git', [
        d.libDir('foo'),
        d.libPubspec('foo', '1.0.0'),
      ]).create();

      await d
          .appDir(
            dependencies: {
              'foo': {'git': '../foo.git'},
            },
          )
          .create();
      await pubGet();

      await d.git('foo.git', [
        d.libDir('foo'),
        d.libPubspec('foo', '1.0.1'),
      ]).commit();

      await pubUpgrade();
    });

    test('reinstalls previously cached git packages', () async {
      // Find the cached foo packages for each revision.
      final gitCacheDir = p.join(d.sandbox, cachePath, 'git');
      final fooDirs =
          listDir(
            gitCacheDir,
          ).where((dir) => p.basename(dir).startsWith('foo-')).toList();

      // Delete "foo.dart" from them.
      for (var dir in fooDirs) {
        deleteEntry(p.join(dir, 'lib', 'foo.dart'));
      }

      // Repair them.
      await runPub(
        args: ['cache', 'repair'],
        output: '''
          Resetting Git repository for foo 1.0.0...
          Resetting Git repository for foo 1.0.1...
          Reinstalled 2 packages.''',
      );

      // The missing libraries should have been replaced.
      final fooLibs =
          fooDirs.map((dir) {
            final fooDirName = p.basename(dir);
            return d.dir(fooDirName, [
              d.dir('lib', [d.file('foo.dart', 'main() => "foo";')]),
            ]);
          }).toList();

      await d.dir(cachePath, [d.dir('git', fooLibs)]).validate();
    });

    test('deletes packages without pubspecs', () async {
      final gitCacheDir = p.join(d.sandbox, cachePath, 'git');
      final fooDirs =
          listDir(
            gitCacheDir,
          ).where((dir) => p.basename(dir).startsWith('foo-')).toList();

      for (var dir in fooDirs) {
        deleteEntry(p.join(dir, 'pubspec.yaml'));
      }

      await runPub(
        args: ['cache', 'repair'],
        error: allOf([
          contains('Failed to load package:'),
          contains('Could not find a file named "pubspec.yaml" in '),
          contains('foo-'),
        ]),
        output: allOf([
          startsWith('Failed to reinstall 2 packages:'),
          contains('- foo 0.0.0 from git'),
          contains('- foo 0.0.0 from git'),
        ]),
        exitCode: exit_codes.UNAVAILABLE,
      );

      await d.dir(cachePath, [
        d.dir('git', fooDirs.map((dir) => d.nothing(p.basename(dir)))),
      ]).validate();
    });

    test('deletes packages with invalid pubspecs', () async {
      final gitCacheDir = p.join(d.sandbox, cachePath, 'git');
      final fooDirs =
          listDir(
            gitCacheDir,
          ).where((dir) => p.basename(dir).startsWith('foo-')).toList();

      for (var dir in fooDirs) {
        writeTextFile(p.join(dir, 'pubspec.yaml'), '{');
      }

      await runPub(
        args: ['cache', 'repair'],
        error: allOf([
          contains('Failed to load package:'),
          contains('Error on line 1, column 2 of '),
          contains('foo-'),
        ]),
        output: allOf([
          startsWith('Failed to reinstall 2 packages:'),
          contains('- foo 0.0.0 from git'),
          contains('- foo 0.0.0 from git'),
        ]),
        exitCode: exit_codes.UNAVAILABLE,
      );

      await d.dir(cachePath, [
        d.dir('git', fooDirs.map((dir) => d.nothing(p.basename(dir)))),
      ]).validate();
    });
  });

  group('subdirectory packages', () {
    setUp(() async {
      // Create two cached revisions of foo.
      await d.git('foo.git', [
        d.dir('subdir', [d.libDir('sub'), d.libPubspec('sub', '1.0.0')]),
      ]).create();

      await d
          .appDir(
            dependencies: {
              'sub': {
                'git': {'url': '../foo.git', 'path': 'subdir'},
              },
            },
          )
          .create();
      await pubGet();

      await d.git('foo.git', [
        d.dir('subdir', [d.libDir('sub'), d.libPubspec('sub', '1.0.1')]),
      ]).commit();

      await pubUpgrade();
    });

    test('reinstalls previously cached git packages', () async {
      // Find the cached foo packages for each revision.
      final gitCacheDir = p.join(d.sandbox, cachePath, 'git');
      final fooDirs =
          listDir(
            gitCacheDir,
          ).where((dir) => p.basename(dir).startsWith('foo-')).toList();

      // Delete "sub.dart" from them.
      for (var dir in fooDirs) {
        deleteEntry(p.join(dir, 'subdir/lib/sub.dart'));
      }

      // Repair them.
      await runPub(
        args: ['cache', 'repair'],
        output: '''
          Resetting Git repository for sub 1.0.0...
          Resetting Git repository for sub 1.0.1...
          Reinstalled 2 packages.''',
      );

      // The missing libraries should have been replaced.
      final fooLibs =
          fooDirs.map((dir) {
            final fooDirName = p.basename(dir);
            return d.dir(fooDirName, [
              d.dir('subdir', [
                d.dir('lib', [d.file('sub.dart', 'main() => "sub";')]),
              ]),
            ]);
          }).toList();

      await d.dir(cachePath, [d.dir('git', fooLibs)]).validate();
    });

    test('deletes packages without pubspecs', () async {
      final gitCacheDir = p.join(d.sandbox, cachePath, 'git');
      final fooDirs =
          listDir(
            gitCacheDir,
          ).where((dir) => p.basename(dir).startsWith('foo-')).toList();

      for (var dir in fooDirs) {
        deleteEntry(p.join(dir, 'subdir', 'pubspec.yaml'));
      }

      await runPub(
        args: ['cache', 'repair'],
        error: allOf([
          contains('Failed to load package:'),
          contains('Could not find a file named "pubspec.yaml" in '),
          contains('foo-'),
          contains('${p.separator}subdir'),
        ]),
        output: allOf([
          startsWith('Failed to reinstall 2 packages:'),
          contains('- foo 0.0.0 from git'),
          contains('- foo 0.0.0 from git'),
        ]),
        exitCode: exit_codes.UNAVAILABLE,
      );

      await d.dir(cachePath, [
        d.dir('git', fooDirs.map((dir) => d.nothing(p.basename(dir)))),
      ]).validate();
    });
  });
}
