<commit_before>library devops.project.group.impl;

import 'dart:async';
import 'project.dart';
import 'dart:io';
import 'package:git/git.dart';
import 'package:devops/src/git/git.dart';
import 'package:quiver/iterables.dart';
import 'package:quiver/streams.dart' as streamz;
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'dependency_graph.dart';
import 'package:devops/src/spec/JefeSpec.dart' as spec;
import 'package:devops/src/project_impl.dart';
import 'package:devops/src/spec/JefeSpec.dart';

Logger _log = new Logger('devops.project.group.impl');

class ProjectGroupReferenceImpl implements ProjectGroupReference {
  final ProjectGroupImpl parent;
  final spec.ProjectGroupIdentifier ref;
  ProjectGroupReferenceImpl(this.parent, this.ref);

  @override
  Future<ProjectGroup> get() => parent._getChildGroup(name, gitUri);

  @override
  String get gitUri => ref.gitUri;

  @override
  String get name => ref.name;
}

abstract class ProjectEntityReferenceFactory {
  ProjectGroupReference createGroupReference(
      ProjectGroupImpl group, ProjectGroupIdentifier id);
  ProjectReference createProjectReference(
      ProjectGroupImpl group, ProjectIdentifier id);
}

class DefaultProjectEntityReferenceFactory
    implements ProjectEntityReferenceFactory {
  const DefaultProjectEntityReferenceFactory();

  @override
  ProjectGroupReference createGroupReference(
          ProjectGroupImpl group, spec.ProjectGroupIdentifier id) =>
      new ProjectGroupReferenceImpl(group, id);

  @override
  ProjectReference createProjectReference(
          ProjectGroupImpl group, spec.ProjectIdentifier id) =>
      new ProjectReferenceImpl(group, id);
}

class ProjectGroupImpl extends ProjectEntityImpl implements ProjectGroup {
  // TODO: we need to hide the project group refs here etc as
  // it complicates encapsulating loading from the right directory

  final ProjectEntityReferenceFactory _referenceFactory;

  final spec.ProjectGroupMetaData metaData;
  String get name => metaData.name;

  final GroupDirectoryLayout directoryLayout;
  Directory get containerDirectory => directoryLayout.containerDirectory;

  ProjectGroupIdentifier get id => new ProjectGroupIdentifier(name, gitUri);

  Iterable<ProjectGroupReference> get _childGroups => metaData.childGroups
      .toSet()
      .map((gr) => _referenceFactory.createGroupReference(this, gr));

  Iterable<ProjectReference> get _projects => metaData.projects
      .toSet()
      .map((pr) => _referenceFactory.createProjectReference(this, pr));

  ProjectGroupImpl(
      String gitUri, this.metaData, GroupDirectoryLayout directoryLayout,
      {ProjectEntityReferenceFactory referenceFactory: const DefaultProjectEntityReferenceFactory()})
      : this.directoryLayout = directoryLayout,
        this._referenceFactory = referenceFactory,
        super(gitUri, directoryLayout.groupDirectory);

  static Future<ProjectGroup> install(Directory parentDir, String gitUri,
      {String name}) async {
    final workspaceName = name != null ? name : gitWorkspaceName(gitUri);
    _log.info('installing group $workspaceName from $gitUri into $parentDir');

    final GroupDirectoryLayout directoryLayout =
        new GroupDirectoryLayout.fromParent(parentDir, workspaceName);

    final Directory projectGroupRoot =
        await directoryLayout.containerDirectory.create(recursive: true);

    final GitDir gitDir = await clone(gitUri, projectGroupRoot);

    final spec.ProjectGroupMetaData metaData = await spec.ProjectGroupMetaData
        .fromDefaultProjectGroupYamlFile(gitDir.path);

    final projectGroup =
        new ProjectGroupImpl(gitUri, metaData, directoryLayout);

    final projectGroupInstallFutures = projectGroup._childGroups
        .map((ref) => projectGroup._installChildGroup(ref.name, ref.gitUri));
    final projectInstallFutures = projectGroup._projects
        .map((ref) => projectGroup._installChildProject(ref.name, ref.gitUri));
    await Future
        .wait(concat([projectGroupInstallFutures, projectInstallFutures]));

    return projectGroup;
  }

  static Future<ProjectGroup> load(Directory groupContainerDirectory) async {
    _log.info(
        'loading group from group container directory $groupContainerDirectory');
//  print('========= $installDirectory');
//    _childGr
    final directoryLayout =
        new GroupDirectoryLayout.withDefaultName(groupContainerDirectory);
    final groupDirectoryPath = directoryLayout.groupDirectory.path;

    print('--- loading git dir from $groupDirectoryPath');
    final gitDirFuture = GitDir.fromExisting(groupDirectoryPath);
    final metaDataFuture = spec.ProjectGroupMetaData
        .fromDefaultProjectGroupYamlFile(groupDirectoryPath);
    final results = await Future.wait([gitDirFuture, metaDataFuture]);

    final GitDir gitDir = results.first;

    final String gitUri = await getFirstRemote(gitDir);
    return new ProjectGroupImpl(gitUri, results.elementAt(1), directoryLayout);
  }

  Future<ProjectGroupImpl> _getChildGroup(String childName, String gitUri) {
    final childContainer =
        directoryLayout.childGroup(childName).containerDirectory;
    _log.finer('loading child group $childName of $name contained in '
        '$childContainer. Parent container is $containerDirectory');

    return load(childContainer);
  }

  Future<ProjectImpl> getChildProject(String name, String gitUri) =>
      ProjectImpl.load(directoryLayout.projectDirectory(name));

  Future<ProjectGroupImpl> _installChildGroup(String name, String gitUri) =>
      install(directoryLayout.containerDirectory, name, gitUri);

  Future<ProjectImpl> _installChildProject(String name, String gitUri) =>
      ProjectImpl.install(directoryLayout.containerDirectory, name, gitUri);

  // parent is group container??
//  @deprecated
//  Directory _childGroupDirectory(String name, String gitUri) {
//    final container = _containerDirectory(gitUri, installDirectory.parent);
//    return new Directory(p.join(container.path, name));
//  }
//
//  Directory _childGroupDirectory2(String name) => _childDirectory(name);
//
//  Directory _childGroupContainerDirectory(String name, String gitUri) =>
//      _containerDirectory(gitUri, containerDirectory);

//  // parent is group container
//  Directory _childProjectDirectory(String name) => _childDirectory(name);<commit_msg>creating jefe command<commit_after>library devops.project.group.impl;

import 'dart:async';
import 'project.dart';
import 'dart:io';
import 'package:git/git.dart';
import 'package:devops/src/git/git.dart';
import 'package:quiver/iterables.dart';
import 'package:quiver/streams.dart' as streamz;
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'dependency_graph.dart';
import 'package:devops/src/spec/JefeSpec.dart' as spec;
import 'package:devops/src/project_impl.dart';
import 'package:devops/src/spec/JefeSpec.dart';

Logger _log = new Logger('devops.project.group.impl');

class ProjectGroupReferenceImpl implements ProjectGroupReference {
  final ProjectGroupImpl parent;
  final spec.ProjectGroupIdentifier ref;
  ProjectGroupReferenceImpl(this.parent, this.ref);

  @override
  Future<ProjectGroup> get() => parent._getChildGroup(name, gitUri);

  @override
  String get gitUri => ref.gitUri;

  @override
  String get name => ref.name;
}

abstract class ProjectEntityReferenceFactory {
  ProjectGroupReference createGroupReference(
      ProjectGroupImpl group, ProjectGroupIdentifier id);
  ProjectReference createProjectReference(
      ProjectGroupImpl group, ProjectIdentifier id);
}

class DefaultProjectEntityReferenceFactory
    implements ProjectEntityReferenceFactory {
  const DefaultProjectEntityReferenceFactory();

  @override
  ProjectGroupReference createGroupReference(
          ProjectGroupImpl group, spec.ProjectGroupIdentifier id) =>
      new ProjectGroupReferenceImpl(group, id);

  @override
  ProjectReference createProjectReference(
          ProjectGroupImpl group, spec.ProjectIdentifier id) =>
      new ProjectReferenceImpl(group, id);
}

class ProjectGroupImpl extends ProjectEntityImpl implements ProjectGroup {
  // TODO: we need to hide the project group refs here etc as
  // it complicates encapsulating loading from the right directory

  final ProjectEntityReferenceFactory _referenceFactory;

  final spec.ProjectGroupMetaData metaData;
  String get name => metaData.name;

  final GroupDirectoryLayout directoryLayout;
  Directory get containerDirectory => directoryLayout.containerDirectory;

  ProjectGroupIdentifier get id => new ProjectGroupIdentifier(name, gitUri);

  Iterable<ProjectGroupReference> get _childGroups => metaData.childGroups
      .toSet()
      .map((gr) => _referenceFactory.createGroupReference(this, gr));

  Iterable<ProjectReference> get _projects => metaData.projects
      .toSet()
      .map((pr) => _referenceFactory.createProjectReference(this, pr));

  ProjectGroupImpl(
      String gitUri, this.metaData, GroupDirectoryLayout directoryLayout,
      {ProjectEntityReferenceFactory referenceFactory: const DefaultProjectEntityReferenceFactory()})
      : this.directoryLayout = directoryLayout,
        this._referenceFactory = referenceFactory,
        super(gitUri, directoryLayout.groupDirectory);

  static Future<ProjectGroup> install(Directory parentDir, String gitUri,
      {String name}) async {
    final workspaceName = name != null ? name : gitWorkspaceName(gitUri);
    _log.info('installing group $workspaceName from $gitUri into $parentDir');

    final GroupDirectoryLayout directoryLayout =
        new GroupDirectoryLayout.fromParent(parentDir, workspaceName);

    final Directory projectGroupRoot =
        await directoryLayout.containerDirectory.create(recursive: true);

    final GitDir gitDir = await clone(gitUri, projectGroupRoot);

    final spec.ProjectGroupMetaData metaData = await spec.ProjectGroupMetaData
        .fromDefaultProjectGroupYamlFile(gitDir.path);

    final projectGroup =
        new ProjectGroupImpl(gitUri, metaData, directoryLayout);

    final projectGroupInstallFutures = projectGroup._childGroups
        .map((ref) => projectGroup._installChildGroup(ref.name, ref.gitUri));
    final projectInstallFutures = projectGroup._projects
        .map((ref) => projectGroup._installChildProject(ref.name, ref.gitUri));
    await Future
        .wait(concat([projectGroupInstallFutures, projectInstallFutures]));

    return projectGroup;
  }

  static Future<ProjectGroup> load(Directory groupContainerDirectory) async {
    _log.info(
        'loading group from group container directory $groupContainerDirectory');
//  print('========= $installDirectory');
//    _childGr
    final directoryLayout =
        new GroupDirectoryLayout.withDefaultName(groupContainerDirectory);
    final groupDirectoryPath = directoryLayout.groupDirectory.path;

    print('--- loading git dir from $groupDirectoryPath');
    final gitDirFuture = GitDir.fromExisting(groupDirectoryPath);
    final metaDataFuture = spec.ProjectGroupMetaData
        .fromDefaultProjectGroupYamlFile(groupDirectoryPath);
    final results = await Future.wait([gitDirFuture, metaDataFuture]);

    final GitDir gitDir = results.first;

    final String gitUri = await getFirstRemote(gitDir);
    return new ProjectGroupImpl(gitUri, results.elementAt(1), directoryLayout);
  }

  Future<ProjectGroupImpl> _getChildGroup(String childName, String gitUri) {
    final childContainer =
        directoryLayout.childGroup(childName).containerDirectory;
    _log.finer('loading child group $childName of $name contained in '
        '$childContainer. Parent container is $containerDirectory');

    return load(childContainer);
  }

  Future<ProjectImpl> getChildProject(String name, String gitUri) =>
      ProjectImpl.load(directoryLayout.projectDirectory(name));

  Future<ProjectGroupImpl> _installChildGroup(String name, String gitUri) =>
      install(directoryLayout.containerDirectory, gitUri, name: name);

  Future<ProjectImpl> _installChildProject(String name, String gitUri) =>
      ProjectImpl.install(directoryLayout.containerDirectory, name, gitUri);

  // parent is group container??
//  @deprecated
//  Directory _childGroupDirectory(String name, String gitUri) {
//    final container = _containerDirectory(gitUri, installDirectory.parent);
//    return new Directory(p.join(container.path, name));
//  }
//
//  Directory _childGroupDirectory2(String name) => _childDirectory(name);
//
//  Directory _childGroupContainerDirectory(String name, String gitUri) =>
//      _containerDirectory(gitUri, containerDirectory);

//  // parent is group container
//  Directory _childProjectDirectory(String name) => _childDirectory(name);
{'fraction_non_alphanumeric': 0.09094481999685584, 'fraction_numerical': 0.00031441597233139445, 'mean_word_length': 4.978853383458647, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '644675', 'n_tokens_mistral': 3321, 'n_tokens_neox': 3256, 'n_words': 790}