Skip to content

Commit

Permalink
Merge pull request #1714 from posit-dev/dotnomad/watcher-manager
Browse files Browse the repository at this point in the history
Create watcher manager to handle file watching
  • Loading branch information
dotNomad authored May 24, 2024
2 parents 4c872ec + dc970e7 commit 0d1c0b0
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 135 deletions.
6 changes: 6 additions & 0 deletions extensions/vscode/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const POSIT_FOLDER = ".posit";
export const PUBLISH_FOLDER = ".posit/publish";
export const PUBLISH_DEPLOYMENTS_FOLDER = ".posit/publish/deployments";

export const CONFIGURATIONS_PATTERN = ".posit/publish/*.toml";
export const DEPLOYMENTS_PATTERN = ".posit/publish/deployments/*.toml";
12 changes: 8 additions & 4 deletions extensions/vscode/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (C) 2024 by Posit Software, PBC.

import { ExtensionContext, commands } from "vscode";
import { ExtensionContext, commands, workspace } from "vscode";

import * as ports from "src/ports";
import { Service } from "src/services";
Expand All @@ -12,6 +12,7 @@ import { HelpAndFeedbackTreeDataProvider } from "src/views/helpAndFeedback";
import { LogsTreeDataProvider } from "src/views/logs";
import { EventStream } from "src/events";
import { HomeViewProvider } from "src/views/homeView";
import { WatcherManager } from "./watchers";

const STATE_CONTEXT = "posit.publish.state";

Expand Down Expand Up @@ -50,6 +51,9 @@ export async function activate(context: ExtensionContext) {

service = new Service(context, port);

const watchers = new WatcherManager(workspace.workspaceFolders?.[0]);
context.subscriptions.push(watchers);

// First the construction of the data providers
const projectTreeDataProvider = new ProjectTreeDataProvider(context);

Expand All @@ -74,12 +78,12 @@ export async function activate(context: ExtensionContext) {

// Then the registration of the data providers with the VSCode framework
projectTreeDataProvider.register();
deploymentsTreeDataProvider.register();
configurationsTreeDataProvider.register();
deploymentsTreeDataProvider.register(watchers);
configurationsTreeDataProvider.register(watchers);
credentialsTreeDataProvider.register();
helpAndFeedbackTreeDataProvider.register();
logsTreeDataProvider.register();
homeViewProvider.register();
homeViewProvider.register(watchers);

await service.start();

Expand Down
37 changes: 7 additions & 30 deletions extensions/vscode/src/views/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
EventEmitter,
ExtensionContext,
InputBoxValidationSeverity,
RelativePattern,
ThemeIcon,
TreeDataProvider,
TreeItem,
Expand All @@ -28,6 +27,7 @@ import { getSummaryStringFromError } from "src/utils/errors";
import { ensureSuffix, fileExists, isValidFilename } from "src/utils/files";
import { untitledConfigurationName } from "src/utils/names";
import { newConfig } from "src/multiStepInputs/newConfig";
import { WatcherManager } from "src/watchers";

const viewName = "posit.publisher.configurations";
const refreshCommand = viewName + ".refresh";
Expand All @@ -36,7 +36,6 @@ const editCommand = viewName + ".edit";
const cloneCommand = viewName + ".clone";
const renameCommand = viewName + ".rename";
const deleteCommand = viewName + ".delete";
const fileStore = ".posit/publish/*.toml";

type ConfigurationEventEmitter = EventEmitter<
ConfigurationTreeItem | undefined | void
Expand Down Expand Up @@ -94,7 +93,7 @@ export class ConfigurationsTreeDataProvider
}
}

public register() {
public register(watchers: WatcherManager) {
const treeView = window.createTreeView(viewName, {
treeDataProvider: this,
});
Expand All @@ -108,35 +107,13 @@ export class ConfigurationsTreeDataProvider
commands.registerCommand(cloneCommand, this.clone),
commands.registerCommand(deleteCommand, this.delete),
);
if (this.root !== undefined) {
const positDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit"),
true,
true,
false,
);
positDirWatcher.onDidDelete(this.refresh, this);
const publishDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit/publish"),
true,
true,
false,
);
publishDirWatcher.onDidDelete(this.refresh, this);

const watcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, fileStore),
);
watcher.onDidCreate(this.refresh);
watcher.onDidDelete(this.refresh);
watcher.onDidChange(this.refresh);
watchers.positDir?.onDidDelete(this.refresh, this);
watchers.publishDir?.onDidDelete(this.refresh, this);

this._context.subscriptions.push(
positDirWatcher,
publishDirWatcher,
watcher,
);
}
watchers.configurations?.onDidCreate(this.refresh, this);
watchers.configurations?.onDidDelete(this.refresh, this);
watchers.configurations?.onDidChange(this.refresh, this);
}

private refresh = () => {
Expand Down
48 changes: 8 additions & 40 deletions extensions/vscode/src/views/deployments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
Event,
EventEmitter,
ExtensionContext,
RelativePattern,
ThemeIcon,
TreeDataProvider,
TreeItem,
Expand Down Expand Up @@ -34,6 +33,7 @@ import { formatDateString } from "src/utils/date";
import { getSummaryStringFromError } from "src/utils/errors";
import { ensureSuffix } from "src/utils/files";
import { deploymentNameValidator } from "src/utils/names";
import { WatcherManager } from "src/watchers";

const viewName = "posit.publisher.deployments";
const refreshCommand = viewName + ".refresh";
Expand All @@ -44,8 +44,6 @@ const visitCommand = viewName + ".visit";
const addDeploymentCommand = viewName + ".addDeployment";
const createNewDeploymentFileCommand = viewName + ".createNewDeploymentFile";

const fileStore = ".posit/publish/deployments/*.toml";

type DeploymentsEventEmitter = EventEmitter<
DeploymentsTreeItem | undefined | void
>;
Expand Down Expand Up @@ -113,7 +111,7 @@ export class DeploymentsTreeDataProvider
}
}

public register() {
public register(watchers: WatcherManager) {
const treeView = window.createTreeView(viewName, {
treeDataProvider: this,
});
Expand Down Expand Up @@ -232,43 +230,13 @@ export class DeploymentsTreeDataProvider
),
);

if (this.root !== undefined) {
const positDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit"),
true,
true,
false,
);
positDirWatcher.onDidDelete(this.refresh, this);
const publishDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit/publish"),
true,
true,
false,
);
publishDirWatcher.onDidDelete(this.refresh, this);
const deploymentsDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit/publish/deployments"),
true,
true,
false,
);
deploymentsDirWatcher.onDidDelete(this.refresh, this);

const watcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, fileStore),
);
watcher.onDidCreate(this.refresh);
watcher.onDidDelete(this.refresh);
watcher.onDidChange(this.refresh);
watchers.positDir?.onDidDelete(this.refresh, this);
watchers.publishDir?.onDidDelete(this.refresh, this);
watchers.deploymentsDir?.onDidDelete(this.refresh, this);

this._context.subscriptions.push(
positDirWatcher,
publishDirWatcher,
deploymentsDirWatcher,
watcher,
);
}
watchers.deployments?.onDidCreate(this.refresh, this);
watchers.deployments?.onDidDelete(this.refresh, this);
watchers.deployments?.onDidChange(this.refresh, this);
}
}

Expand Down
83 changes: 22 additions & 61 deletions extensions/vscode/src/views/homeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ import { DestinationQuickPick } from "src/types/quickPicks";
import { normalizeURL } from "src/utils/url";
import { selectConfig } from "src/multiStepInputs/selectConfig";
import { RPackage, RVersionConfig } from "src/api/types/packages";

const deploymentFiles = ".posit/publish/deployments/*.toml";
const configFiles = ".posit/publish/*.toml";
import { WatcherManager } from "src/watchers";

const viewName = "posit.publisher.homeView";
const refreshCommand = viewName + ".refresh";
Expand Down Expand Up @@ -1130,7 +1128,7 @@ export class HomeViewProvider implements WebviewViewProvider {
this._context.subscriptions.push(watcher);
}

public register() {
public register(watchers: WatcherManager) {
this._stream.register("publish/start", () => {
this._onPublishStart();
});
Expand Down Expand Up @@ -1171,62 +1169,25 @@ export class HomeViewProvider implements WebviewViewProvider {
),
);

if (this.root !== undefined) {
const positDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit"),
true,
true,
false,
);
positDirWatcher.onDidDelete(() => {
this.refreshDeployments();
this.refreshConfigurations();
}, this);
const publishDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit/publish"),
true,
true,
false,
);
publishDirWatcher.onDidDelete(() => {
this.refreshDeployments();
this.refreshConfigurations();
}, this);
const deploymentsDirWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, ".posit/publish/deployments"),
true,
true,
false,
);
deploymentsDirWatcher.onDidDelete(this.refreshDeployments, this);
this._context.subscriptions.push(
positDirWatcher,
publishDirWatcher,
deploymentsDirWatcher,
);

const configFileWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, configFiles),
);
configFileWatcher.onDidCreate(this.refreshConfigurations);
configFileWatcher.onDidDelete(this.refreshConfigurations);
configFileWatcher.onDidChange(this.refreshConfigurations);
this._context.subscriptions.push(configFileWatcher);

const deploymentFileWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, deploymentFiles),
);
deploymentFileWatcher.onDidCreate(this.refreshDeployments);
deploymentFileWatcher.onDidDelete(this.refreshDeployments);
deploymentFileWatcher.onDidChange(this.refreshDeployments);
this._context.subscriptions.push(deploymentFileWatcher);

const allFileWatcher = workspace.createFileSystemWatcher(
new RelativePattern(this.root, "**"),
);
allFileWatcher.onDidCreate(this.sendRefreshedFilesLists);
allFileWatcher.onDidDelete(this.sendRefreshedFilesLists);
this._context.subscriptions.push(allFileWatcher);
}
watchers.positDir?.onDidDelete(() => {
this.refreshDeployments();
this.refreshConfigurations();
}, this);
watchers.publishDir?.onDidDelete(() => {
this.refreshDeployments();
this.refreshConfigurations();
}, this);
watchers.deploymentsDir?.onDidDelete(this.refreshDeployments, this);

watchers.configurations?.onDidCreate(this.refreshConfigurations, this);
watchers.configurations?.onDidDelete(this.refreshConfigurations, this);
watchers.configurations?.onDidChange(this.refreshConfigurations, this);

watchers.deployments?.onDidCreate(this.refreshDeployments, this);
watchers.deployments?.onDidDelete(this.refreshDeployments, this);
watchers.deployments?.onDidChange(this.refreshDeployments, this);

watchers.allFiles?.onDidCreate(this.sendRefreshedFilesLists, this);
watchers.allFiles?.onDidDelete(this.sendRefreshedFilesLists, this);
}
}
77 changes: 77 additions & 0 deletions extensions/vscode/src/watchers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {
Disposable,
RelativePattern,
WorkspaceFolder,
FileSystemWatcher,
workspace,
} from "vscode";

import {
PUBLISH_DEPLOYMENTS_FOLDER,
POSIT_FOLDER,
PUBLISH_FOLDER,
CONFIGURATIONS_PATTERN,
DEPLOYMENTS_PATTERN,
} from "src/constants";

/**
* Manages all the file system watchers for the extension.
*
* The directory watchers only watch for onDidDelete events.
*/
export class WatcherManager implements Disposable {
positDir: FileSystemWatcher | undefined;
publishDir: FileSystemWatcher | undefined;
configurations: FileSystemWatcher | undefined;
deploymentsDir: FileSystemWatcher | undefined;
deployments: FileSystemWatcher | undefined;
allFiles: FileSystemWatcher | undefined;

constructor(root?: WorkspaceFolder) {
if (root === undefined) {
return;
}

this.positDir = workspace.createFileSystemWatcher(
new RelativePattern(root, POSIT_FOLDER),
true,
true,
false,
);

this.publishDir = workspace.createFileSystemWatcher(
new RelativePattern(root, PUBLISH_FOLDER),
true,
true,
false,
);

this.configurations = workspace.createFileSystemWatcher(
new RelativePattern(root, CONFIGURATIONS_PATTERN),
);

this.deploymentsDir = workspace.createFileSystemWatcher(
new RelativePattern(root, PUBLISH_DEPLOYMENTS_FOLDER),
true,
true,
false,
);

this.deployments = workspace.createFileSystemWatcher(
new RelativePattern(root, DEPLOYMENTS_PATTERN),
);

this.allFiles = workspace.createFileSystemWatcher(
new RelativePattern(root, "**"),
);
}

dispose() {
this.positDir?.dispose();
this.publishDir?.dispose();
this.configurations?.dispose();
this.deploymentsDir?.dispose();
this.deployments?.dispose();
this.allFiles?.dispose();
}
}

0 comments on commit 0d1c0b0

Please sign in to comment.