Skip to content

Commit e04ab2b

Browse files
authored
Change gitpod config location IDE-165 (#79)
* Change gitpod config location * Write gitpod config file first then change ssh config * Wrap error again * Avoid downgrade
1 parent ea70782 commit e04ab2b

File tree

1 file changed

+62
-10
lines changed

1 file changed

+62
-10
lines changed

src/ssh/sshConfig.ts

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { WrapError } from '../common/utils';
1414

1515
const systemSSHConfig = isWindows ? path.resolve(process.env.ALLUSERSPROFILE || 'C:\\ProgramData', 'ssh\\ssh_config') : '/etc/ssh/ssh_config';
1616
const defaultSSHConfigPath = path.resolve(os.homedir(), '.ssh/config');
17-
const gitpodSSHConfigPath = path.resolve(os.homedir(), '.ssh/gitpod/config');
17+
const gitpodSSHConfigPath = path.resolve(os.homedir(), '.ssh/code_gitpod.d/config');
1818

1919
export function getSSHConfigPath() {
2020
const sshConfigPath = vscode.workspace.getConfiguration('remote.SSH').get<string>('configFile');
@@ -57,6 +57,29 @@ function normalizeSSHConfig(config: SSHConfig) {
5757
}
5858
}
5959

60+
// TODO: Delete me
61+
async function tryDeleteOldMatch(matchContent: string, gitpodHeader: string) {
62+
try {
63+
const match = matchContent.match(/Include "(?<oldTarget>.*?)"/);
64+
if (!match) {
65+
return;
66+
}
67+
const location = path.resolve(os.homedir(), '.ssh/' + match.groups!.oldTarget);
68+
const content = (await fs.promises.readFile(location, 'utf8')).trim();
69+
if (content.includes(gitpodHeader)) {
70+
await fs.promises.unlink(location);
71+
// check if folder is empty if so delete it
72+
const folder = path.dirname(location);
73+
const files = await fs.promises.readdir(folder);
74+
if (files.length === 0) {
75+
await fs.promises.rmdir(folder);
76+
}
77+
}
78+
} catch (e) {
79+
// ignore
80+
}
81+
}
82+
6083
export default class SSHConfiguration {
6184

6285
static async loadFromFS(): Promise<SSHConfiguration> {
@@ -97,14 +120,11 @@ export default class SSHConfiguration {
97120
}
98121
}
99122

100-
static async ensureIncludeGitpodSSHConfig(): Promise<void> {
123+
private static async addIncludeToUserSSHConfig(gitpodHeader: string): Promise<void> {
101124
const gitpodIncludeSection = `## START GITPOD INTEGRATION
102125
## This section is managed by Gitpod. Any manual changes will be lost.
103-
Include "gitpod/config"
126+
Include "code_gitpod.d/config"
104127
## END GITPOD INTEGRATION`;
105-
106-
const gitpodHeader = `### This file is managed by Gitpod. Any manual changes will be lost.`;
107-
108128
const configPath = getSSHConfigPath();
109129
let content = '';
110130
if (await exists(configPath)) {
@@ -114,11 +134,25 @@ Include "gitpod/config"
114134
throw new WrapError(`Could not read ssh config file at ${configPath}`, e);
115135
}
116136
}
117-
118-
const scopeRegex = new RegExp(`START GITPOD INTEGRATION.+Include "gitpod/config".+END GITPOD INTEGRATION`, 's');
119-
if (!scopeRegex.test(content)) {
137+
let hasIncludeTarget = false;
138+
const oldContent = content;
139+
const scopeRegex = new RegExp(`## START GITPOD INTEGRATION.+END GITPOD INTEGRATION`, 'sg');
140+
const matchResult = content.match(scopeRegex);
141+
if (matchResult) {
142+
for (const matchContent of matchResult) {
143+
if (matchContent !== gitpodIncludeSection) {
144+
content = content.replace(matchContent, '');
145+
// try to check and delete old file
146+
tryDeleteOldMatch(matchContent, gitpodHeader);
147+
} else {
148+
hasIncludeTarget = true;
149+
}
150+
}
151+
}
152+
if (!hasIncludeTarget) {
120153
content = `${gitpodIncludeSection}\n\n${content}`;
121-
154+
}
155+
if (content !== oldContent) {
122156
const configFileDir = path.dirname(configPath);
123157
// must be dir
124158
if (!(await exists(configFileDir))) {
@@ -138,7 +172,9 @@ Include "gitpod/config"
138172
throw new WrapError(`Could not write ssh config file ${configPath}`, e);
139173
}
140174
}
175+
}
141176

177+
private static async createGitpodSSHConfig(gitpodHeader: string): Promise<void> {
142178
const gitpodConfigFileDir = path.dirname(gitpodSSHConfigPath);
143179
// must be dir
144180
if (!(await exists(gitpodConfigFileDir))) {
@@ -166,6 +202,22 @@ Include "gitpod/config"
166202
}
167203
}
168204

205+
static async ensureIncludeGitpodSSHConfig(): Promise<void> {
206+
const gitpodHeader = `### This file is managed by Gitpod. Any manual changes will be lost.`;
207+
try {
208+
await this.createGitpodSSHConfig(gitpodHeader);
209+
} catch (e) {
210+
const code = e?.code ?? 'Unknown';
211+
throw new WrapError('Failed to create gitpod ssh config', e, 'GitpodSSHConfig:' + code);
212+
}
213+
try {
214+
await this.addIncludeToUserSSHConfig(gitpodHeader);
215+
} catch (e) {
216+
const code = e?.code ?? 'Unknown';
217+
throw new WrapError('Failed to add include to user ssh config', e, 'UserSSHConfig:' + code);
218+
}
219+
}
220+
169221
constructor(private sshConfig: SSHConfig) {
170222
// Normalize config property names
171223
normalizeSSHConfig(sshConfig);

0 commit comments

Comments
 (0)