mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-16 13:49:28 +00:00
Avoid deleting the workspace when it's still in use.
- From now on, NSFW service disposes after last reference is removed. No more 10sec delay. - Moved the temp workspace deletion to a startup task. - Can set initial task for the window from electron-main. - Removed the `browser-app`. Closes #39 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { ContainerModule } from '@theia/core/shared/inversify';
|
||||
import { ContainerModule, interfaces } from '@theia/core/shared/inversify';
|
||||
import { ArduinoDaemonImpl } from './arduino-daemon-impl';
|
||||
import {
|
||||
ArduinoFirmwareUploader,
|
||||
@@ -110,6 +110,7 @@ import {
|
||||
SurveyNotificationServicePath,
|
||||
} from '../common/protocol/survey-service';
|
||||
import { IsTempSketch } from './is-temp-sketch';
|
||||
import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-watcher/nsfw-bindings';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(BackendApplication).toSelf().inSingletonScope();
|
||||
@@ -288,6 +289,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
rebindNsfwFileSystemWatcher(rebind);
|
||||
|
||||
// Output service per connection.
|
||||
bind(ConnectionContainerModule).toConstantValue(
|
||||
@@ -325,58 +327,14 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
})
|
||||
);
|
||||
|
||||
// Logger for the Arduino daemon
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child('daemon');
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed('daemon');
|
||||
|
||||
// Logger for the Arduino daemon
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child('fwuploader');
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed('fwuploader');
|
||||
|
||||
// Logger for the "serial discovery".
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child('discovery-log'); // TODO: revert
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed('discovery-log'); // TODO: revert
|
||||
|
||||
// Logger for the CLI config service. From the CLI config (FS path aware), we make a URI-aware app config.
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child('config');
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed('config');
|
||||
|
||||
// Logger for the monitor manager and its services
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child(MonitorManagerName);
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(MonitorManagerName);
|
||||
|
||||
bind(ILogger)
|
||||
.toDynamicValue((ctx) => {
|
||||
const parentLogger = ctx.container.get<ILogger>(ILogger);
|
||||
return parentLogger.child(MonitorServiceName);
|
||||
})
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(MonitorServiceName);
|
||||
[
|
||||
'daemon', // Logger for the Arduino daemon
|
||||
'fwuploader', // Arduino Firmware uploader
|
||||
'discovery-log', // Boards discovery
|
||||
'config', // Logger for the CLI config reading and manipulation
|
||||
MonitorManagerName, // Logger for the monitor manager and its services
|
||||
MonitorServiceName,
|
||||
].forEach((name) => bindChildLogger(bind, name));
|
||||
|
||||
// Remote sketchbook bindings
|
||||
bind(AuthenticationServiceImpl).toSelf().inSingletonScope();
|
||||
@@ -423,3 +381,12 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
|
||||
bind(IsTempSketch).toSelf().inSingletonScope();
|
||||
});
|
||||
|
||||
function bindChildLogger(bind: interfaces.Bind, name: string): void {
|
||||
bind(ILogger)
|
||||
.toDynamicValue(({ container }) =>
|
||||
container.get<ILogger>(ILogger).child(name)
|
||||
)
|
||||
.inSingletonScope()
|
||||
.whenTargetNamed(name);
|
||||
}
|
||||
|
||||
@@ -561,14 +561,18 @@ void loop() {
|
||||
return path.join(os.tmpdir(), `arduino-ide2-${suffix}`);
|
||||
}
|
||||
|
||||
notifyDeleteSketch(sketch: Sketch): void {
|
||||
const sketchPath = FileUri.fsPath(sketch.uri);
|
||||
fs.rm(sketchPath, { recursive: true, maxRetries: 5 }, (error) => {
|
||||
if (error) {
|
||||
console.error(`Failed to delete sketch at ${sketchPath}.`, error);
|
||||
} else {
|
||||
console.error(`Successfully delete sketch at ${sketchPath}.`);
|
||||
}
|
||||
async deleteSketch(sketch: Sketch): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const sketchPath = FileUri.fsPath(sketch.uri);
|
||||
fs.rm(sketchPath, { recursive: true, maxRetries: 5 }, (error) => {
|
||||
if (error) {
|
||||
console.error(`Failed to delete sketch at ${sketchPath}.`, error);
|
||||
reject(error);
|
||||
} else {
|
||||
console.log(`Successfully deleted sketch at ${sketchPath}.`);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as yargs from '@theia/core/shared/yargs';
|
||||
import { JsonRpcProxyFactory } from '@theia/core';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service';
|
||||
import type { IPCEntryPoint } from '@theia/core/lib/node/messaging/ipc-protocol';
|
||||
import type { FileSystemWatcherServiceClient } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
|
||||
const options: {
|
||||
verbose: boolean;
|
||||
} = yargs
|
||||
.option('verbose', {
|
||||
default: false,
|
||||
alias: 'v',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('nsfwOptions', {
|
||||
alias: 'o',
|
||||
type: 'string',
|
||||
coerce: JSON.parse,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}).argv as any;
|
||||
|
||||
export default <IPCEntryPoint>((connection) => {
|
||||
const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService(
|
||||
options
|
||||
);
|
||||
const factory = new JsonRpcProxyFactory<FileSystemWatcherServiceClient>(
|
||||
server
|
||||
);
|
||||
server.setClient(factory.createProxy());
|
||||
factory.listen(connection);
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { join } from 'path';
|
||||
import { interfaces } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
NsfwFileSystemWatcherServiceProcessOptions,
|
||||
NSFW_SINGLE_THREADED,
|
||||
spawnNsfwFileSystemWatcherServiceProcess,
|
||||
} from '@theia/filesystem/lib/node/filesystem-backend-module';
|
||||
import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import { NsfwFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service';
|
||||
import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service';
|
||||
|
||||
export function rebindNsfwFileSystemWatcher(rebind: interfaces.Rebind): void {
|
||||
rebind<NsfwFileSystemWatcherServiceProcessOptions>(
|
||||
NsfwFileSystemWatcherServiceProcessOptions
|
||||
).toConstantValue({
|
||||
entryPoint: join(__dirname, 'index.js'),
|
||||
});
|
||||
rebind<FileSystemWatcherService>(FileSystemWatcherService)
|
||||
.toDynamicValue((context) =>
|
||||
NSFW_SINGLE_THREADED
|
||||
? createNsfwFileSystemWatcherService(context)
|
||||
: spawnNsfwFileSystemWatcherServiceProcess(context)
|
||||
)
|
||||
.inSingletonScope();
|
||||
}
|
||||
|
||||
function createNsfwFileSystemWatcherService({
|
||||
container,
|
||||
}: interfaces.Context): FileSystemWatcherService {
|
||||
const options = container.get<NsfwFileSystemWatcherServerOptions>(
|
||||
NsfwFileSystemWatcherServerOptions
|
||||
);
|
||||
const dispatcher = container.get<FileSystemWatcherServiceDispatcher>(
|
||||
FileSystemWatcherServiceDispatcher
|
||||
);
|
||||
const server = new NoDelayDisposalTimeoutNsfwFileSystemWatcherService(
|
||||
options
|
||||
);
|
||||
server.setClient(dispatcher);
|
||||
return server;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Minimatch } from 'minimatch';
|
||||
import type { WatchOptions } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import {
|
||||
NsfwFileSystemWatcherService,
|
||||
NsfwWatcher,
|
||||
} from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service';
|
||||
|
||||
// Dispose the watcher immediately when the last reference is removed. By default, Theia waits 10 sec.
|
||||
// https://github.com/eclipse-theia/theia/issues/11639#issuecomment-1238980708
|
||||
const NoDelay = 0;
|
||||
|
||||
export class NoDelayDisposalTimeoutNsfwFileSystemWatcherService extends NsfwFileSystemWatcherService {
|
||||
protected override createWatcher(
|
||||
clientId: number,
|
||||
fsPath: string,
|
||||
options: WatchOptions
|
||||
): NsfwWatcher {
|
||||
const watcherOptions = {
|
||||
ignored: options.ignored.map(
|
||||
(pattern) => new Minimatch(pattern, { dot: true })
|
||||
),
|
||||
};
|
||||
return new NsfwWatcher(
|
||||
clientId,
|
||||
fsPath,
|
||||
watcherOptions,
|
||||
this.options,
|
||||
this.maybeClient,
|
||||
NoDelay
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user