<commit_before>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */

import { existsSync } from 'fs';
import * as path from 'path';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, first, map, tap } from 'rxjs/operators';
import { BaseException } from '../../exception';
import {
  JsonObject,
  JsonParseMode,
  parseJson,
  schema,
} from '../../json';
import {
  Path,
  basename,
  dirname,
  isAbsolute,
  join,
  normalize,
  relative,
  resolve,
  virtualFs,
} from '../../virtual-fs';
import { WorkspaceProject, WorkspaceSchema, WorkspaceTool } from './workspace-schema';


export class WorkspaceFileNotFoundException extends BaseException {
  constructor(path: Path) {
    super(`Workspace could not be found from path ${path}.`);
  }
}

export class ProjectNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Project '${name}' could not be found in workspace.`);
  }
}

export class WorkspaceToolNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Tool ${name} could not be found in workspace.`);
  }
}

export class ProjectToolNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Tool ${name} could not be found in project.`);
  }
}

export class WorkspaceNotYetLoadedException extends BaseException {
  constructor() { super(`Workspace needs to be loaded before it is used.`); }
}

export class AmbiguousProjectPathException extends BaseException {
  constructor(public readonly path: Path, public readonly projects: ReadonlyArray<string>) {
    super(`Current active project is ambiguous (${projects.join(',')}) using path: '${path}'`);
  }
}

async function _findUp(host: virtualFs.Host, names: string[], from: Path): Promise<Path | null> {
  if (!Array.isArray(names)) {
    names = [names];
  }

  do {
    for (const name of names) {
      const p = join(from, name);
      if (await host.exists(p)) {
        return p;
      }
    }

    from = dirname(from);
  } while (from && from !== dirname(from));

  return null;
}

export class Workspace {
  protected static _workspaceFileNames = [
    'angular.json',
    '.angular.json',
    'workspace.json',
    '.workspace.json',
  ];

  private readonly _workspaceSchemaPath = normalize(require.resolve('./workspace-schema.json'));
  private _workspaceSchema: JsonObject;
  private _workspace: WorkspaceSchema;
  private _registry: schema.CoreSchemaRegistry;

  constructor(
    private _root: Path,
    private _host: virtualFs.Host<{}>,
    registry?: schema.CoreSchemaRegistry,
  ) {
    if (registry) {
      this._registry = registry;
    } else {
      this._registry = new schema.CoreSchemaRegistry();
      this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
    }
  }

  static async findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null> {<commit_msg>fix(@angular-devkit/core): correct workspace discovery<commit_after>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */

import { existsSync } from 'fs';
import * as path from 'path';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, first, map, tap } from 'rxjs/operators';
import { BaseException } from '../../exception';
import {
  JsonObject,
  JsonParseMode,
  parseJson,
  schema,
} from '../../json';
import {
  Path,
  basename,
  dirname,
  isAbsolute,
  join,
  normalize,
  relative,
  resolve,
  virtualFs,
} from '../../virtual-fs';
import { WorkspaceProject, WorkspaceSchema, WorkspaceTool } from './workspace-schema';


export class WorkspaceFileNotFoundException extends BaseException {
  constructor(path: Path) {
    super(`Workspace could not be found from path ${path}.`);
  }
}

export class ProjectNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Project '${name}' could not be found in workspace.`);
  }
}

export class WorkspaceToolNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Tool ${name} could not be found in workspace.`);
  }
}

export class ProjectToolNotFoundException extends BaseException {
  constructor(name: string) {
    super(`Tool ${name} could not be found in project.`);
  }
}

export class WorkspaceNotYetLoadedException extends BaseException {
  constructor() { super(`Workspace needs to be loaded before it is used.`); }
}

export class AmbiguousProjectPathException extends BaseException {
  constructor(public readonly path: Path, public readonly projects: ReadonlyArray<string>) {
    super(`Current active project is ambiguous (${projects.join(',')}) using path: '${path}'`);
  }
}

async function _findUp(host: virtualFs.Host, names: string[], from: Path): Promise<Path | null> {
  if (!Array.isArray(names)) {
    names = [names];
  }

  do {
    for (const name of names) {
      const p = join(from, name);
      if (await host.exists(p).toPromise()) {
        return p;
      }
    }

    from = dirname(from);
  } while (from && from !== dirname(from));

  return null;
}

export class Workspace {
  protected static _workspaceFileNames = [
    'angular.json',
    '.angular.json',
  ];

  private readonly _workspaceSchemaPath = normalize(require.resolve('./workspace-schema.json'));
  private _workspaceSchema: JsonObject;
  private _workspace: WorkspaceSchema;
  private _registry: schema.CoreSchemaRegistry;

  constructor(
    private _root: Path,
    private _host: virtualFs.Host<{}>,
    registry?: schema.CoreSchemaRegistry,
  ) {
    if (registry) {
      this._registry = registry;
    } else {
      this._registry = new schema.CoreSchemaRegistry();
      this._registry.addPostTransform(schema.transforms.addUndefinedDefaults);
    }
  }

  static async findWorkspaceFile(host: virtualFs.Host<{}>, path: Path): Promise<Path | null> {
{'fraction_non_alphanumeric': 0.12306679828891083, 'fraction_numerical': 0.0, 'mean_word_length': 3.9103392568659125, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 2, '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': '5147238', 'n_tokens_mistral': 1753, 'n_tokens_neox': 1750, 'n_words': 527}