<commit_before>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * This file contains a collection of functions that call the Google Drive APIs, and are
 * wrapped in the ApiManager class.
 */

class DriveFile extends DatalabFile {
}

/**
 * An Google Drive specific file manager.
 */
class DriveFileManager implements FileManager {

  private static readonly _directoryMimeType = 'application/vnd.google-apps.folder';
  private static readonly _notebookMimeType = 'application/json';

  private static _upstreamToDriveFile(file: gapi.client.drive.File) {
    const datalabFile: DriveFile = new DriveFile({
      icon: file.iconLink,
      id: new DatalabFileId(file.id, FileManagerType.DRIVE),
      name: file.name,
      status: DatalabFileStatus.IDLE,
      type: file.mimeType === DriveFileManager._directoryMimeType ?
                              DatalabFileType.DIRECTORY :
                              DatalabFileType.FILE,
    } as DatalabFile);
    if (datalabFile.name.endsWith('.ipynb')) {
      datalabFile.type = DatalabFileType.NOTEBOOK;
    }
    return datalabFile;
  }
  public async get(fileId: DatalabFileId): Promise<DatalabFile> {
    const upstreamFile = await GapiManager.drive.getFile(fileId.path);
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public async getStringContent(fileId: DatalabFileId, _asText?: boolean): Promise<string> {
    const [, content] = await GapiManager.drive.getFileWithContent(fileId.path);
    if (content === null) {
      throw new Error('Could not download file: ' + fileId.toQueryString());
    }
    return content;
  }

  public async getRootFile(): Promise<DatalabFile> {
    const upstreamFile = await GapiManager.drive.getRoot();
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public saveText(file: DatalabFile, text: string): Promise<DatalabFile> {
    return GapiManager.drive.patchContent(file.id.path, text)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public async list(fileId: DatalabFileId): Promise<DatalabFile[]> {
    const whitelistFilePredicates = [
      'name contains \'.ipynb\'',
      'name contains \'.txt\'',
      'mimeType = \'' + DriveFileManager._directoryMimeType + '\'',
    ];
    const queryPredicates = [
      '"' + fileId.path + '" in parents',
      'trashed = false',
      '(' + whitelistFilePredicates.join(' or ') + ')',
    ];
    const fileFields = [
      'createdTime',
      'iconLink',
      'id',
      'mimeType',
      'modifiedTime',
      'name',
      'parents',
    ];
    const orderModifiers = [
      'folder',
      'modifiedTime',
      'name',
    ];
    const upstreamFiles =
        await GapiManager.drive.listFiles(fileFields, queryPredicates, orderModifiers);
    // TODO: Check which files are running from the SessionsManager and modify
    // their status accordingly.
    return upstreamFiles.map((file) => DriveFileManager._upstreamToDriveFile(file));
  }

  public async create(fileType: DatalabFileType, containerId?: DatalabFileId, name?: string)
      : Promise<DatalabFile> {
    let mimeType: string;
    switch (fileType) {
      case DatalabFileType.DIRECTORY:
        mimeType = DriveFileManager._directoryMimeType; break;
      case DatalabFileType.NOTEBOOK:
        mimeType = DriveFileManager._notebookMimeType; break;
      default:
        mimeType = 'text/plain';
    }
    const content = fileType === DatalabFileType.NOTEBOOK ?
        NotebookContent.EMPTY_NOTEBOOK_CONTENT : '';
    const upstreamFile = await GapiManager.drive.create(mimeType,
                                                        containerId ? containerId.path : 'root',
                                                        name || 'New Item',
                                                        content);
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public rename(oldFileId: DatalabFileId, newName: string, newContainerId?: DatalabFileId)
      : Promise<DatalabFile> {
    const newContainerPath = newContainerId ? newContainerId.path : undefined;
    return GapiManager.drive.renameFile(oldFileId.path, newName, newContainerPath)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public delete(fileId: DatalabFileId): Promise<boolean> {
    return GapiManager.drive.deleteFile(fileId.path)
      .then(() => true, () => false);
  }

  public copy(file: DatalabFileId, destinationDirectoryId: DatalabFileId): Promise<DatalabFile> {
    return GapiManager.drive.copy(file.path, destinationDirectoryId.path)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public async getEditorUrl(fileId: DatalabFileId) {
    return location.protocol + '//' + location.host +
        '/editor?file=' + fileId.toQueryString();
  }

  public async getNotebookUrl(fileId: DatalabFileId): Promise<string> {
    return location.protocol + '//' + location.host +
        '/notebook#fileId=' + fileId.toQueryString();
  }<commit_msg>use ?file querystring for file id (#1638)<commit_after>/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

/**
 * This file contains a collection of functions that call the Google Drive APIs, and are
 * wrapped in the ApiManager class.
 */

class DriveFile extends DatalabFile {
}

/**
 * An Google Drive specific file manager.
 */
class DriveFileManager implements FileManager {

  private static readonly _directoryMimeType = 'application/vnd.google-apps.folder';
  private static readonly _notebookMimeType = 'application/json';

  private static _upstreamToDriveFile(file: gapi.client.drive.File) {
    const datalabFile: DriveFile = new DriveFile({
      icon: file.iconLink,
      id: new DatalabFileId(file.id, FileManagerType.DRIVE),
      name: file.name,
      status: DatalabFileStatus.IDLE,
      type: file.mimeType === DriveFileManager._directoryMimeType ?
                              DatalabFileType.DIRECTORY :
                              DatalabFileType.FILE,
    } as DatalabFile);
    if (datalabFile.name.endsWith('.ipynb')) {
      datalabFile.type = DatalabFileType.NOTEBOOK;
    }
    return datalabFile;
  }
  public async get(fileId: DatalabFileId): Promise<DatalabFile> {
    const upstreamFile = await GapiManager.drive.getFile(fileId.path);
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public async getStringContent(fileId: DatalabFileId, _asText?: boolean): Promise<string> {
    const [, content] = await GapiManager.drive.getFileWithContent(fileId.path);
    if (content === null) {
      throw new Error('Could not download file: ' + fileId.toQueryString());
    }
    return content;
  }

  public async getRootFile(): Promise<DatalabFile> {
    const upstreamFile = await GapiManager.drive.getRoot();
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public saveText(file: DatalabFile, text: string): Promise<DatalabFile> {
    return GapiManager.drive.patchContent(file.id.path, text)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public async list(fileId: DatalabFileId): Promise<DatalabFile[]> {
    const whitelistFilePredicates = [
      'name contains \'.ipynb\'',
      'name contains \'.txt\'',
      'mimeType = \'' + DriveFileManager._directoryMimeType + '\'',
    ];
    const queryPredicates = [
      '"' + fileId.path + '" in parents',
      'trashed = false',
      '(' + whitelistFilePredicates.join(' or ') + ')',
    ];
    const fileFields = [
      'createdTime',
      'iconLink',
      'id',
      'mimeType',
      'modifiedTime',
      'name',
      'parents',
    ];
    const orderModifiers = [
      'folder',
      'modifiedTime',
      'name',
    ];
    const upstreamFiles =
        await GapiManager.drive.listFiles(fileFields, queryPredicates, orderModifiers);
    // TODO: Check which files are running from the SessionsManager and modify
    // their status accordingly.
    return upstreamFiles.map((file) => DriveFileManager._upstreamToDriveFile(file));
  }

  public async create(fileType: DatalabFileType, containerId?: DatalabFileId, name?: string)
      : Promise<DatalabFile> {
    let mimeType: string;
    switch (fileType) {
      case DatalabFileType.DIRECTORY:
        mimeType = DriveFileManager._directoryMimeType; break;
      case DatalabFileType.NOTEBOOK:
        mimeType = DriveFileManager._notebookMimeType; break;
      default:
        mimeType = 'text/plain';
    }
    const content = fileType === DatalabFileType.NOTEBOOK ?
        NotebookContent.EMPTY_NOTEBOOK_CONTENT : '';
    const upstreamFile = await GapiManager.drive.create(mimeType,
                                                        containerId ? containerId.path : 'root',
                                                        name || 'New Item',
                                                        content);
    return DriveFileManager._upstreamToDriveFile(upstreamFile);
  }

  public rename(oldFileId: DatalabFileId, newName: string, newContainerId?: DatalabFileId)
      : Promise<DatalabFile> {
    const newContainerPath = newContainerId ? newContainerId.path : undefined;
    return GapiManager.drive.renameFile(oldFileId.path, newName, newContainerPath)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public delete(fileId: DatalabFileId): Promise<boolean> {
    return GapiManager.drive.deleteFile(fileId.path)
      .then(() => true, () => false);
  }

  public copy(file: DatalabFileId, destinationDirectoryId: DatalabFileId): Promise<DatalabFile> {
    return GapiManager.drive.copy(file.path, destinationDirectoryId.path)
      .then((upstreamFile) => DriveFileManager._upstreamToDriveFile(upstreamFile));
  }

  public async getEditorUrl(fileId: DatalabFileId) {
    return location.protocol + '//' + location.host +
        '/editor?file=' + fileId.toQueryString();
  }

  public async getNotebookUrl(fileId: DatalabFileId): Promise<string> {
    return location.protocol + '//' + location.host +
        '/notebook?file=' + fileId.toQueryString();
  }
{'fraction_non_alphanumeric': 0.10489759572573464, 'fraction_numerical': 0.0017809439002671415, 'mean_word_length': 3.1704418863720756, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2279411', 'n_tokens_mistral': 3287, 'n_tokens_neox': 3184, 'n_words': 768}