@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
296 lines (294 loc) • 11.2 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const FileSystemFile_1 = require("./FileSystemFile");
const FileSystemStorage_1 = require("./FileSystemStorage");
const StorageUtilities_1 = require("./StorageUtilities");
const Utilities_1 = require("./../core/Utilities");
const Log_1 = require("./../core/Log");
const FolderBase_1 = require("./FolderBase");
class FileSystemFolder extends FolderBase_1.default {
get handle() {
return this._handle;
}
set handle(newHandle) {
this._handle = newHandle;
}
get writeHandle() {
return this._writeHandle;
}
set writeHandle(newHandle) {
this._writeHandle = newHandle;
}
get storage() {
return this._storage;
}
get parentFolder() {
return this._parentFolder;
}
get name() {
return this._name;
}
get fullPath() {
return (this._parentPath + FileSystemStorage_1.default.fileSystemFolderDelimiter + StorageUtilities_1.default.canonicalizeName(this.name));
}
constructor(storage, parentFolder, parentPath, folderName, handle) {
super();
this._storage = storage;
this._parentFolder = parentFolder;
this._handle = handle;
this._writeHandle = handle;
this._parentPath = parentPath;
this._name = folderName;
this._lastSavedContent = "";
this.lastSavedFileCount = 0;
this.folders = {};
this.files = {};
}
async getIsEmptyError(depth, processedFolders) {
if (depth && depth > 10) {
return "Folder hierarchy is too deep.";
}
await this.load(false);
for (const fileName in this.files) {
return "Folder '" + this.fullPath + "' is not empty.";
}
const folderCount = this.folderCount;
processedFolders = processedFolders === undefined ? folderCount : processedFolders + this.folderCount;
if (folderCount > 1000) {
return "Folder hierarchy is too complex. (" + folderCount + " folders)";
}
if (processedFolders > 4000) {
return "Too many folders to process in this folder.";
}
for (const folderName in this.folders) {
const folder = this.folders[folderName];
if (folder) {
const result = await folder.getFirstUnsafeError(depth === undefined ? 1 : depth + 1, processedFolders);
if (result !== undefined) {
return result;
}
}
}
return undefined;
}
async getFirstUnsafeError(depth, processedFolders) {
if (depth && depth > 10) {
return "Folder hierarchy is too deep.";
}
await this.load(false);
for (const fileName in this.files) {
if (!StorageUtilities_1.default.isUsableFile(fileName)) {
return "Cannot work with '" + this.fullPath + fileName + "'";
}
}
const folderCount = this.folderCount;
processedFolders = processedFolders === undefined ? folderCount : processedFolders + this.folderCount;
if (folderCount > 1000) {
return "Folder hierarchy is too complex. (" + folderCount + " folders)";
}
if (processedFolders > 4000) {
return "Too many folders to process in this folder.";
}
for (const folderName in this.folders) {
const folder = this.folders[folderName];
if (folder) {
const result = await folder.getFirstUnsafeError(depth === undefined ? 1 : depth + 1, processedFolders);
if (result !== undefined) {
return result;
}
}
}
return undefined;
}
ensureFile(name, file) {
const nameCanon = StorageUtilities_1.default.canonicalizeName(name);
let candFile = this.files[nameCanon];
if (candFile == null) {
candFile = new FileSystemFile_1.default(this, name);
this.files[nameCanon] = candFile;
this.storage.notifyFileAdded(candFile);
}
if (file) {
candFile.handle = file;
candFile.writeHandle = file;
}
return candFile;
}
async exists() {
return true;
}
async ensureExists() {
return true;
}
ensureFolder(name, handle) {
const nameCanon = StorageUtilities_1.default.canonicalizeName(name);
let candFolder = this.folders[nameCanon];
if (!candFolder) {
candFolder = new FileSystemFolder(this._storage, this, this.fullPath, name);
this.folders[nameCanon] = candFolder;
}
if (handle) {
candFolder.handle = handle;
}
return candFolder;
}
_removeFile(file) {
const nameCanon = StorageUtilities_1.default.canonicalizeName(file.name);
const candFile = this.files[nameCanon];
Log_1.default.assert(candFile === file, "Files don't match.");
this.files[nameCanon] = undefined;
this.storage.notifyFileRemoved(this.storageRelativePath + file.name);
}
async deleteThisFolder() {
throw new Error("Deletion of this folder " + this.fullPath + " is not supported.");
}
async deleteAllFolderContents() {
throw new Error("Deletion of all folder contents at " + this.fullPath + " is not supported.");
}
async _removeFileExistence(fileName) {
const handle = await this.getHandle();
await handle?.removeEntry(fileName, {
recursive: false,
});
}
_addExistingFile(file) {
const nameCanon = StorageUtilities_1.default.canonicalizeName(file.name);
this.files[nameCanon] = file;
}
_addExistingFolder(folder) {
const nameCanon = StorageUtilities_1.default.canonicalizeName(folder.name);
this.folders[nameCanon] = folder;
}
async moveTo(newStorageRelativePath) {
const newFolderPath = StorageUtilities_1.default.getFolderPath(newStorageRelativePath);
const newFolderName = StorageUtilities_1.default.getLeafName(newStorageRelativePath);
if (newFolderName.length < 2) {
throw new Error("New path is not correct.");
}
if (this.isSameFolder(newStorageRelativePath)) {
return false;
}
if (this._parentFolder !== null) {
const newParentFolder = await this._parentFolder.storage.ensureFolderFromStorageRelativePath(newFolderPath);
if (newParentFolder.folders[newFolderName] !== undefined) {
throw new Error("Folder exists at specified path.");
}
this._parentFolder._clearExistingFolder(this);
this._parentFolder = newParentFolder;
this._name = newFolderName;
newParentFolder._addExistingFolder(this);
}
this._name = newFolderName;
if (this._parentFolder !== null) {
await this._parentFolder.save(true);
}
throw new Error("Not implemented.");
//return true;
}
async createFile(name) {
const file = this.ensureFile(name);
this.storage.notifyFileAdded(file);
return file;
}
async getHandle() {
if (!this._handle) {
if (this._writeHandle) {
return this._writeHandle;
}
if (this.parentFolder) {
const parentFolderHandle = await this.parentFolder.getHandle();
if (parentFolderHandle) {
try {
this._handle = await parentFolderHandle.getDirectoryHandle(this.name, {
create: false,
});
}
catch (e) {
// Log.debugAlert("Folder r/o retrieval: " + e);
return undefined;
}
}
}
}
return this._handle;
}
async ensureWriteHandle() {
if (!this._writeHandle) {
if (this.parentFolder) {
await this.parentFolder.ensureWriteHandle();
if (this.parentFolder.writeHandle) {
try {
this._writeHandle = await this.parentFolder.writeHandle.getDirectoryHandle(this.name, {
create: true,
});
}
catch (e) {
Log_1.default.debugAlert("Folder r/w retrieval: " + e);
}
}
}
}
Log_1.default.assert(this._writeHandle !== undefined, "No folder handle.");
return this._writeHandle;
}
async load(force) {
if (this.lastLoadedOrSaved != null && !force) {
return this.lastLoadedOrSaved;
}
const handle = await this.getHandle();
if (handle) {
for await (const [key, value] of handle.entries()) {
if (value.kind === "file") {
this.ensureFile(key, value);
}
else if (value.kind === "directory") {
const keyLower = key.toLowerCase();
if (keyLower !== ".git" && keyLower !== "node_modules") {
this.ensureFolder(key, value);
}
}
}
}
this.updateLastLoadedOrSaved();
return this.lastLoadedOrSaved;
}
async save(force) {
this.updateLastLoadedOrSaved();
const folderState = {
updated: this.lastLoadedOrSaved,
files: [],
folders: [],
};
for (const fileName in this.files) {
const file = this.files[fileName];
if (file !== undefined) {
const fileState = {
name: file.name,
size: file.size,
modified: file.latestModified == null ? new Date() : file.latestModified,
};
folderState.files.push(fileState);
}
}
for (const folderName in this.folders) {
const childFolder = this.folders[folderName];
if (childFolder !== undefined && !childFolder.errorStatus) {
const childFolderState = {
name: childFolder.name,
fileCount: Utilities_1.default.lengthOfDictionary(childFolder.files),
modified: childFolder.modifiedAtLoad == null ? new Date() : childFolder.modifiedAtLoad,
};
folderState.folders.push(childFolderState);
}
}
const saveContent = JSON.stringify(folderState);
if (this._lastSavedContent !== saveContent || force) {
// await localforage.setItem<string>(this.fullPath + FileSystemStorage.folderDelimiter, saveContent);
}
return this.lastLoadedOrSaved;
}
}
exports.default = FileSystemFolder;
//# sourceMappingURL=../maps/storage/FileSystemFolder.js.map