// Copyright (c) 2012, 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.

library git_source;

import 'git.dart' as git;
import 'io.dart';
import 'package.dart';
import 'source.dart';
import 'source_registry.dart';
import 'utils.dart';

/**
 * A package source that installs packages from Git repos.
 */
class GitSource extends Source {
  final String name = "git";

  final bool shouldCache = true;

  GitSource();

  /**
   * Clones a Git repo to the local filesystem.
   *
   * The Git cache directory is a little idiosyncratic. At the top level, it
   * contains a directory for each commit of each repository, named `<package
   * name>-<commit hash>`. These are the canonical package directories that are
   * linked to from the `packages/` directory.
   *
   * In addition, the Git system cache contains a subdirectory named `cache/`
   * which contains a directory for each separate repository URL, named
   * `<package name>-<url hash>`. These are used to check out the repository
   * itself; each of the commit-specific directories are clones of a directory
   * in `cache/`.
   */
  Future<Package> installToSystemCache(PackageId id) {
    var revisionCachePath;

    return git.isInstalled.chain((installed) {
      if (!installed) {
        throw new Exception(
            "Cannot install '${id.name}' from Git (${_getUrl(id)}).\n"
            "Please ensure Git is correctly installed.");
      }

      return ensureDir(join(systemCacheRoot, 'cache'));
    }).chain((_) => _ensureRepoCache(id))
      .chain((_) => _revisionCachePath(id))
      .chain((path) {
      revisionCachePath = path;
      return exists(revisionCachePath);
    }).chain((exists) {
      if (exists) return new Future.immediate(null);
      return _clone(_repoCachePath(id), revisionCachePath, mirror: false);
    }).chain((_) {
      var ref = _getEffectiveRef(id);
      if (ref == 'HEAD') return new Future.immediate(null);
      return _checkOut(revisionCachePath, ref);
    }).chain((_) {
      return Package.load(id.name, revisionCachePath, systemCache.sources);
    });
  }

  /**
   * Ensures [description] is a Git URL.
   */
  void validateDescription(description, [bool fromLockFile = false]) {
    // A single string is assumed to be a Git URL.
    if (description is String) return;
    if (description is! Map || !description.containsKey('url')) {
      throw new FormatException("The description must be a Git URL or a map "
          "with a 'url' key.");
    }
    description = new Map.from(description);
    description.remove('url');
    description.remove('ref');
    if (fromLockFile) description.remove('resolved-ref');

    if (!description.isEmpty()) {
      var plural = description.length > 1;
      var keys = Strings.join(description.getKeys(), ', ');
      throw new FormatException("Invalid key${plural ? 's' : ''}: $keys.");
    }
  }

  /**
   * Two Git descriptions are equal if both their URLs and their refs are equal.
   */
  bool descriptionsEqual(description1, description2) {
    // TODO(nweiz): Do we really want to throw an error if you have two
    // dependencies on some repo, one of which specifies a ref and one of which
    // doesn't? If not, how do we handle that case in the version solver?
    return _getUrl(description1) == _getUrl(description2) &&
      _getRef(description1) == _getRef(description2);
  }

  /**
   * Attaches a specific commit to [id] to disambiguate it.
   */
  Future<PackageId> resolveId(PackageId id) {
    return _revisionAt(id).transform((revision) {
      var description = {'url': _getUrl(id), 'ref': _getRef(id)};
      description['resolved-ref'] = revision;
      return new PackageId(id.name, this, id.version, description);
    });
  }

  /**
   * Ensure that the canonical clone of the repository referred to by [id] (the
   * one in `<system cache>/git/cache`) exists and is up-to-date. Returns a
   * future that completes once this is finished and throws an exception if it
   * fails.
   */
  Future _ensureRepoCache(PackageId id) {
    var path = _repoCachePath(id);
    return exists(path).chain((exists) {
      if (!exists) return _clone(_getUrl(id), path, mirror: true);

      return git.run(["fetch"], workingDir: path).transform((result) => null);
    });
  }

  /**
   * Returns a future that completes to the revision hash of [id].
   */
  Future<String> _revisionAt(PackageId id) {
    return git.run(["rev-parse", _getEffectiveRef(id)],
        workingDir: _repoCachePath(id)).transform((result) => result[0]);
  }

  /**
   * Returns the path to the revision-specific cache of [id].
   */
  Future<String> _revisionCachePath(PackageId id) {
    return _revisionAt(id).transform((rev) {
      var revisionCacheName = '${id.name}-$rev';
      return join(systemCacheRoot, revisionCacheName);
    });
  }

  /**
   * Clones the repo at the URI [from] to the path [to] on the local filesystem.
   *
   * If [mirror] is true, create a bare, mirrored clone. This doesn't check out
   * the working tree, but instead makes the repository a local mirror of the
   * remote repository. See the manpage for `git clone` for more information.
   */
  Future _clone(String from, String to, [bool mirror=false]) {
    // Git on Windows does not seem to automatically create the destination
    // directory.
    return ensureDir(to).chain((_) {
      var args = ["clone", from, to];
      if (mirror) args.insertRange(1, 1, "--mirror");
      return git.run(args);
    }).transform((result) => null);
  }

  /**
   * Checks out the reference [ref] in [repoPath].
   */
  Future _checkOut(String repoPath, String ref) {
    return git.run(["checkout", ref], workingDir: repoPath).transform(
        (result) => null);
  }

  /**
   * Returns the path to the canonical clone of the repository referred to by
   * [id] (the one in `<system cache>/git/cache`).
   */
  String _repoCachePath(PackageId id) {
    var repoCacheName = '${id.name}-${sha1(_getUrl(id))}';
    return join(systemCacheRoot, 'cache', repoCacheName);
  }

  /**
   * Returns the repository URL for [id].
   *
   * [description] may be a description or a [PackageId].
   */
  String _getUrl(description) {
    description = _getDescription(description);
    if (description is String) return description;
    return description['url'];
  }

  /**
   * Returns the commit ref that should be checked out for [description].
   *
   * This differs from [_getRef] in that it doesn't just return the ref in
   * [description]. It will return a sensible default if that ref doesn't exist,
   * and it will respect the "resolved-ref" parameter set by [resolveId].
   *
   * [description] may be a description or a [PackageId].
   */
  String _getEffectiveRef(description) {
    description = _getDescription(description);
    if (description is Map && description.containsKey('resolved-ref')) {
      return description['resolved-ref'];
    }

    var ref = _getRef(description);
    return ref == null ? 'HEAD' : ref;
  }

  /**
   * Returns the commit ref for [description], or null if none is given.
   *
   * [description] may be a description or a [PackageId].
   */
  String _getRef(description) {
    description = _getDescription(description);
    if (description is String) return null;
    return description['ref'];
  }

  /**
   * Returns [description] if it's a description, or [PackageId.description] if
   * it's a [PackageId].
   */
  _getDescription(description) {
    if (description is PackageId) return description.description;
    return description;
  }
}
