-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathpathResolver.ts
More file actions
187 lines (169 loc) · 5.67 KB
/
Copy pathpathResolver.ts
File metadata and controls
187 lines (169 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import * as os from "node:os";
import * as path from "node:path";
import * as vscode from "vscode";
import { expandPath } from "../util";
import { currentEditorId } from "../util/authority";
/** Extension of generated SSH config files; the include glob matches on it. */
export const SSH_CONFIG_EXT = ".conf";
/** The per-user data dir of the platform, shared by every editor. */
function platformDataDir(): string {
switch (process.platform) {
case "win32":
return (
process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming")
);
case "darwin":
return path.join(os.homedir(), "Library", "Application Support");
default:
return (
process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share")
);
}
}
export class PathResolver {
constructor(
private readonly basePath: string,
private readonly codeLogPath: string,
) {}
/**
* Per-deployment directory for the extension's Coder configs. A user
* `--global-config` in `coder.globalFlags` redirects the CLI; this stays the
* default. Caller must ensure it exists.
*/
public getGlobalConfigDir(safeHostname: string): string {
return path.join(this.basePath, safeHostname);
}
/**
* Return the directory for a deployment with the provided hostname to where
* its binary is cached.
*
* The caller must ensure this directory exists before use.
*/
public getBinaryCachePath(safeHostname: string): string {
return (
PathResolver.resolveOverride(
"coder.binaryDestination",
"CODER_BINARY_DESTINATION",
) || path.join(this.getGlobalConfigDir(safeHostname), "bin")
);
}
/**
* Return the path where network information for SSH hosts are stored.
*
* The CLI will write files here named after the process PID.
*/
public getNetworkInfoPath(): string {
return path.join(this.basePath, "net");
}
/**
* Directory of generated SSH configs, glob-included from the user's config.
* Lives in the platform data dir so every editor emits the same include.
*/
public getSshConfigDir(): string {
return path.join(platformDataDir(), "coder.coder-remote", "ssh");
}
/**
* Generated SSH config for one deployment, named after the editor in the
* host prefix rather than the one writing it: two files declaring the same
* host pattern would leave glob order to decide which one ssh reads.
*/
public getSshConfigPath(
safeHostname: string,
editorId: string = currentEditorId(),
): string {
return path.join(
this.getSshConfigDir(),
`${editorId}--${safeHostname}${SSH_CONFIG_EXT}`,
);
}
/** The deployment hostname if `editorId` named the file, else undefined. */
public parseSshConfigFile(
fileName: string,
editorId: string = currentEditorId(),
): string | undefined {
const prefix = `${editorId}--`;
return fileName.startsWith(prefix) && fileName.endsWith(SSH_CONFIG_EXT)
? fileName.slice(prefix.length, -SSH_CONFIG_EXT.length)
: undefined;
}
/**
* Return the directory where telemetry files are written.
*/
public getTelemetryPath(): string {
return path.join(this.basePath, "telemetry");
}
/**
* Return the proxy log directory from the `coder.proxyLogDirectory` setting
* or the `CODER_SSH_LOG_DIR` environment variable, falling back to the `log`
* subdirectory inside the extension's global storage path.
*
* The CLI will write files here named after the process PID.
*/
public getProxyLogPath(): string {
return (
PathResolver.resolveOverride(
"coder.proxyLogDirectory",
"CODER_SSH_LOG_DIR",
) || path.join(this.basePath, "log")
);
}
/**
* Get the path to the user's settings.json file.
*
* Going through VSCode's API should be preferred when modifying settings.
*/
public getUserSettingsPath(): string {
return path.join(this.basePath, "..", "..", "..", "User", "settings.json");
}
/**
* Return the directory for the deployment with the provided hostname to
* where its session token is stored.
*
* The caller must ensure this directory exists before use.
*/
public getSessionTokenPath(safeHostname: string): string {
return path.join(this.getGlobalConfigDir(safeHostname), "session");
}
/**
* Return the directory for the deployment with the provided hostname to
* where its session token was stored by older code.
*
* The caller must ensure this directory exists before use.
*/
public getLegacySessionTokenPath(safeHostname: string): string {
return path.join(this.getGlobalConfigDir(safeHostname), "session_token");
}
/**
* Return the directory for the deployment with the provided hostname to
* where its url is stored.
*
* The caller must ensure this directory exists before use.
*/
public getUrlPath(safeHostname: string): string {
return path.join(this.getGlobalConfigDir(safeHostname), "url");
}
/**
* The URI of a directory in which the extension can create log files.
*
* The directory might not exist on disk and creation is up to the extension.
* However, the parent directory is guaranteed to be existent.
*
* This directory is provided by VS Code and may not be the same as the directory where the Coder CLI writes its log files.
*/
public getCodeLogDir(): string {
return this.codeLogPath;
}
/**
* Read a path from a VS Code setting then an environment variable, returning
* the first non-empty value after trimming, tilde/variable expansion, and
* normalization. Returns an empty string when neither source provides a path.
*/
private static resolveOverride(setting: string, envVar: string): string {
const fromSetting = expandPath(
vscode.workspace.getConfiguration().get<string>(setting)?.trim() ?? "",
);
const resolved =
fromSetting || expandPath(process.env[envVar]?.trim() ?? "");
return resolved ? path.normalize(resolved) : "";
}
}