Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 107fd9d

Browse files
author
Akos Kitta
committed
fix: workaround for # in the app path
Closes eclipse-theia/theia#12064 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 26d3963 commit 107fd9d

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

‎arduino-ide-extension/src/node/arduino-ide-backend-module.ts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ import { MessagingContribution } from './theia/core/messaging-contribution';
113113
import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service';
114114
import { HostedPluginReader } from './theia/plugin-ext/plugin-reader';
115115
import { HostedPluginReader as TheiaHostedPluginReader } from '@theia/plugin-ext/lib/hosted/node/plugin-reader';
116+
import { PluginDeployer } from '@theia/plugin-ext/lib/common/plugin-protocol';
117+
import {
118+
LocalDirectoryPluginDeployerResolverWithFallback,
119+
PluginDeployer_GH_12064,
120+
} from './theia/plugin-ext/plugin-deployer';
116121

117122
export default new ContainerModule((bind, unbind, isBound, rebind) => {
118123
bind(BackendApplication).toSelf().inSingletonScope();
@@ -392,6 +397,12 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
392397
// https://github.com/arduino/arduino-ide/pull/1706#pullrequestreview-1195595080
393398
bind(HostedPluginReader).toSelf().inSingletonScope();
394399
rebind(TheiaHostedPluginReader).toService(HostedPluginReader);
400+
401+
// https://github.com/eclipse-theia/theia/issues/12064
402+
bind(LocalDirectoryPluginDeployerResolverWithFallback)
403+
.toSelf()
404+
.inSingletonScope();
405+
rebind(PluginDeployer).to(PluginDeployer_GH_12064).inSingletonScope();
395406
});
396407

397408
function bindChildLogger(bind: interfaces.Bind, name: string): void {
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { URI } from '@theia/core/lib/common/uri';
2+
import {
3+
inject,
4+
injectable,
5+
postConstruct,
6+
} from '@theia/core/shared/inversify';
7+
import {
8+
PluginDeployerResolver,
9+
PluginDeployerResolverContext,
10+
} from '@theia/plugin-ext/lib/common/plugin-protocol';
11+
import { PluginDeployerImpl } from '@theia/plugin-ext/lib/main/node/plugin-deployer-impl';
12+
import { LocalDirectoryPluginDeployerResolver } from '@theia/plugin-ext/lib/main/node/resolvers/local-directory-plugin-deployer-resolver';
13+
import { constants, promises as fs } from 'fs';
14+
import { isAbsolute, resolve } from 'path';
15+
16+
@injectable()
17+
export class LocalDirectoryPluginDeployerResolverWithFallback extends LocalDirectoryPluginDeployerResolver {
18+
override async resolve(
19+
pluginResolverContext: PluginDeployerResolverContext
20+
): Promise<void> {
21+
const origin = pluginResolverContext.getOriginId();
22+
// The original implementation must not run when there is a hash in the path. Otherwise, it can resolve an undesired directory.
23+
// Consider app under c:\Users\username\Desktop\# here is my app\
24+
// Then the flawed logic will incorrectly find c:\Users\username\Desktop location after stripping the rest of the path after the hash.
25+
// The implementation which provides a workaround for the hash in the path assumes that the original Theia logic is correct, when no hash present in the URI path.
26+
let localPath: string | null;
27+
if (origin.includes('#')) {
28+
localPath = await resolveLocalPluginPathFallback(
29+
pluginResolverContext,
30+
this.supportedScheme
31+
);
32+
} else {
33+
localPath = await this.originalResolveLocalPluginPath(
34+
pluginResolverContext,
35+
this.supportedScheme
36+
);
37+
}
38+
if (localPath) {
39+
await this.resolveFromLocalPath(pluginResolverContext, localPath);
40+
}
41+
}
42+
43+
private async originalResolveLocalPluginPath(
44+
context: PluginDeployerResolverContext,
45+
scheme: string
46+
): Promise<string | null> {
47+
const object = <Record<string, unknown>>this;
48+
if (
49+
'resolveLocalPluginPath' in object &&
50+
typeof object['resolveLocalPluginPath'] === 'function'
51+
) {
52+
return object['resolveLocalPluginPath'](context, scheme);
53+
}
54+
return null;
55+
}
56+
}
57+
58+
async function resolveLocalPluginPathFallback(
59+
context: PluginDeployerResolverContext,
60+
scheme: string
61+
): Promise<string | null> {
62+
const uri = new URI(context.getOriginId());
63+
if (uri.scheme === scheme) {
64+
const unencodedRawUri = uri.toString(true);
65+
let fsPath = unencodedRawUri.substring(`${scheme}:`.length);
66+
if (!isAbsolute(fsPath)) {
67+
fsPath = resolve(process.cwd(), fsPath);
68+
}
69+
try {
70+
await fs.access(fsPath, constants.R_OK);
71+
return fsPath;
72+
} catch {
73+
console.warn(
74+
`The local plugin referenced by ${context.getOriginId()} does not exist.`
75+
);
76+
}
77+
}
78+
return null;
79+
}
80+
81+
@injectable()
82+
export class PluginDeployer_GH_12064 extends PluginDeployerImpl {
83+
@inject(LocalDirectoryPluginDeployerResolverWithFallback)
84+
private readonly pluginResolver: LocalDirectoryPluginDeployerResolverWithFallback;
85+
86+
@postConstruct()
87+
protected adjustPluginResolvers(): void {
88+
const pluginResolvers = <PluginDeployerResolver[]>(
89+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
90+
(this as any).pluginResolvers
91+
);
92+
const index = pluginResolvers.findIndex(
93+
(pluginResolver) =>
94+
pluginResolver instanceof LocalDirectoryPluginDeployerResolver
95+
);
96+
if (index >= 0) {
97+
pluginResolvers.splice(index, 1, this.pluginResolver);
98+
}
99+
}
100+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /