Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/commands/apps/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default class extends Command {
}

async run(task: TaskData, item: UserAppTreeItem) {
const workspaceAvailable = this.core.workspaceAvailable;
const workspaceAvailable = FileSystem.workspaceAvailable;
let workspaceFolder: Uri | undefined;
if (workspaceAvailable) workspaceFolder = await FileSystem.getWorkspaceFolder({ token: task.token });
if (!workspaceFolder) {
workspaceFolder = await this.core.getFolderDialog(task);
workspaceFolder = await FileSystem.getFolderDialog(task);
if (!workspaceFolder) throw Error(t("no.folder.found"));
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/apps/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default class extends Command {
}

async run(task: TaskData, item: UserAppTreeItem) {
const workspaceAvailable = this.core.workspaceAvailable;
const workspaceAvailable = FileSystem.workspaceAvailable;
let workspaceFolder: Uri | undefined;
if (workspaceAvailable) workspaceFolder = await FileSystem.getWorkspaceFolder();
if (!workspaceFolder) {
workspaceFolder = await this.core.getFolderDialog(task);
workspaceFolder = await FileSystem.getFolderDialog(task);
if (!workspaceFolder) throw Error(t("no.folder.found"));
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/team/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default class extends Command {
}

async run(task: TaskData, item: TeamAppTreeItem) {
const workspaceAvailable = this.core.workspaceAvailable;
const workspaceAvailable = FileSystem.workspaceAvailable;
let workspaceFolder: Uri | undefined;
if (workspaceAvailable) workspaceFolder = await FileSystem.getWorkspaceFolder();
if (!workspaceFolder) {
workspaceFolder = await this.core.getFolderDialog(task);
workspaceFolder = await FileSystem.getFolderDialog(task);
if (!workspaceFolder) throw Error(t("no.folder.found"));
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/team/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default class extends Command {
}

async run(task: TaskData, item: TeamAppTreeItem) {
const workspaceAvailable = this.core.workspaceAvailable;
const workspaceAvailable = FileSystem.workspaceAvailable;
let workspaceFolder: Uri | undefined;
if (workspaceAvailable) workspaceFolder = await FileSystem.getWorkspaceFolder();
if (!workspaceFolder) {
workspaceFolder = await this.core.getFolderDialog(task);
workspaceFolder = await FileSystem.getFolderDialog(task);
if (!workspaceFolder) throw Error(t("no.folder.found"));
}

Expand Down
33 changes: 5 additions & 28 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { t } from "@vscode/l10n";
import { EventEmitter } from "events";
import { normalize } from "path";
import { commands, type Disposable, type ExtensionContext, type LogOutputChannel, type SecretStorage, window, workspace } from "vscode";
import { commands, type Disposable, type ExtensionContext, type LogOutputChannel, type SecretStorage, workspace } from "vscode";
import { type ExtensionContextId } from "./@enum";
import type { Events, IGlobalStateStorage, TaskData } from "./@types";
import type { Events, IGlobalStateStorage } from "./@types";
import DiscloudAuthenticationProvider from "./authentication/provider";
import { commandsRegister } from "./commands";
import { loadEvents } from "./events";
Expand Down Expand Up @@ -86,19 +85,11 @@ export default class ExtensionCore extends EventEmitter<Events> implements Dispo
return this.getLogOutputChannel("Discloud");
}

get singleWorkspaceFolder() {
const folders = workspace.workspaceFolders;
if (folders?.length === 1) return folders[0].uri;
}

get workspaceAvailable() {
return Boolean(workspace.workspaceFolders?.length);
}

get workspaceIgnoreList() {
const config = this.config;
return _workspaceIgnoreConfigKeys
.reduce<string[]>((acc, config) => {
const data = this.config.get<string>(config);
.reduce<string[]>((acc, configName) => {
const data = config.get<string>(configName);
if (data) return acc.concat(normalize(data));
return acc;
}, [])
Expand All @@ -118,20 +109,6 @@ export default class ExtensionCore extends EventEmitter<Events> implements Dispo
this.timers.dispose();
}

async getFolderDialog(task?: TaskData | null, title?: string, openLabel?: string) {
task?.progress.report({ increment: -1, message: t("folder.get.one") });

const uris = await window.showOpenDialog({
canSelectFolders: true,
title,
openLabel,
});

if (uris?.length) task?.progress.report({ message: t("folder.selected") });

return uris?.at(0);
}

getLogOutputChannel(name: string) {
return DiscloudLogOutputChannel.getInstance(this.context, name);
}
Expand Down
158 changes: 91 additions & 67 deletions src/utils/FileSystem.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { t } from "@vscode/l10n";
import { dirname, join } from "path";
import { commands, env, FileType, Uri, window, workspace, type CancellationToken } from "vscode";
import type { GetWorkspaceFolderOptions } from "../@types";
import type { GetWorkspaceFolderOptions, TaskData } from "../@types";
import { BLOCKED_FILES } from "./constants";
import lazy from "./lazy";

Expand All @@ -23,6 +24,95 @@ export interface FileSystemOptions {
}

export default class FileSystem {
static get singleWorkspaceFolder() {
const folders = workspace.workspaceFolders;
if (folders?.length === 1) return folders[0].uri;
}

static get workspaceAvailable() {
return Boolean(workspace.workspaceFolders?.length);
}

static async getFolderDialog(task?: TaskData | null, title?: string, openLabel?: string) {
task?.progress.report({ increment: -1, message: t("folder.get.one") });

const uris = await window.showOpenDialog({
canSelectFolders: true,
title,
openLabel,
});

if (uris?.length) task?.progress.report({ message: t("folder.selected") });

return uris?.at(0);
}

static async findIgnoreFile(filename: string, ignoreList?: string | string[] | Set<string>, token?: CancellationToken) {
if (!ignoreList) ignoreList = lazyDefaultBlockedFilesPattern();

if (ignoreList instanceof Set) ignoreList = Array.from(ignoreList);

if (Array.isArray(ignoreList)) ignoreList = `{${ignoreList}}`;

const files = await workspace.findFiles(join(_glob, filename), ignoreList, undefined, token);

const result = new Set<string>();

for (const file of files) {
const stat = await workspace.fs.stat(file);

if (stat.type !== FileType.File || !stat.size) return [];

const relativeFolder = dirname(workspace.asRelativePath(file, false));

const fileBuffer = await workspace.fs.readFile(file);

const patterns = fileBuffer.toString()
.replace(_commentRegexp, _emptyString)
.split(_lineBreakRegexp);

for (const pattern of patterns) {
result.add(join(relativeFolder, pattern));
}
}

return Array.from(result);
}

static async getWorkspaceFolder(options?: GetWorkspaceFolderOptions | null): Promise<Uri | undefined> {
options ??= {};

if (options.uri instanceof Uri) {
const folder = workspace.getWorkspaceFolder(options.uri);
if (folder) return folder.uri;
}

const folders = workspace.workspaceFolders;
if (!folders?.length) return;
if (folders.length === _one) return folders[_zero].uri;

options.allowReadSelectedPath ??= true;

if (options.allowReadSelectedPath) {
const [filePath] = await FileSystem.readSelectedPath(false);
if (filePath && filePath !== _dot)
return workspace.getWorkspaceFolder(Uri.file(filePath))?.uri;
}

if (options.silent || options.token?.isCancellationRequested) return;

const picked = await window.showWorkspaceFolderPick();
if (picked) return picked.uri;
}

static readSelectedPath(relative?: true): Promise<string[]>
static readSelectedPath(relative: boolean): Promise<string[]>
static async readSelectedPath(relative: boolean = true) {
await commands.executeCommand(relative ? "copyRelativeFilePath" : "copyFilePath");
const copied = await env.clipboard.readText();
return copied.split(_lineBreakRegexp);
}

constructor(readonly options: FileSystemOptions = {}) {
if (!options) options = {};

Expand Down Expand Up @@ -100,70 +190,4 @@ export default class FileSystem {
this.patterns.add(file);
}
}

static async findIgnoreFile(filename: string, ignoreList?: string | string[] | Set<string>, token?: CancellationToken) {
if (!ignoreList) ignoreList = lazyDefaultBlockedFilesPattern();

if (ignoreList instanceof Set) ignoreList = Array.from(ignoreList);

if (Array.isArray(ignoreList)) ignoreList = `{${ignoreList}}`;

const files = await workspace.findFiles(join(_glob, filename), ignoreList, undefined, token);

const result = new Set<string>();

for (const file of files) {
const stat = await workspace.fs.stat(file);

if (stat.type !== FileType.File || !stat.size) return [];

const relativeFolder = dirname(workspace.asRelativePath(file, false));

const fileBuffer = await workspace.fs.readFile(file);

const patterns = fileBuffer.toString()
.replace(_commentRegexp, _emptyString)
.split(_lineBreakRegexp);

for (const pattern of patterns) {
result.add(join(relativeFolder, pattern));
}
}

return Array.from(result);
}

static async getWorkspaceFolder(options?: GetWorkspaceFolderOptions | null): Promise<Uri | undefined> {
options ??= {};

if (options.uri instanceof Uri) {
const folder = workspace.getWorkspaceFolder(options.uri);
if (folder) return folder.uri;
}

const folders = workspace.workspaceFolders;
if (!folders?.length) return;
if (folders.length === _one) return folders[_zero].uri;

options.allowReadSelectedPath ??= true;

if (options.allowReadSelectedPath) {
const [filePath] = await FileSystem.readSelectedPath(false);
if (filePath && filePath !== _dot)
return workspace.getWorkspaceFolder(Uri.file(filePath))?.uri;
}

if (options.silent || options.token?.isCancellationRequested) return;

const picked = await window.showWorkspaceFolderPick();
if (picked) return picked.uri;
}

static readSelectedPath(relative?: true): Promise<string[]>
static readSelectedPath(relative: boolean): Promise<string[]>
static async readSelectedPath(relative: boolean = true) {
await commands.executeCommand(relative ? "copyRelativeFilePath" : "copyFilePath");
const copied = await env.clipboard.readText();
return copied.split(_lineBreakRegexp);
}
}
Loading