@@ -14,7 +14,7 @@ import { WrapError } from '../common/utils';
14
14
15
15
const systemSSHConfig = isWindows ? path . resolve ( process . env . ALLUSERSPROFILE || 'C:\\ProgramData' , 'ssh\\ssh_config' ) : '/etc/ssh/ssh_config' ;
16
16
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' ) ;
18
18
19
19
export function getSSHConfigPath ( ) {
20
20
const sshConfigPath = vscode . workspace . getConfiguration ( 'remote.SSH' ) . get < string > ( 'configFile' ) ;
@@ -57,6 +57,29 @@ function normalizeSSHConfig(config: SSHConfig) {
57
57
}
58
58
}
59
59
60
+ // TODO: Delete me
61
+ async function tryDeleteOldMatch ( matchContent : string , gitpodHeader : string ) {
62
+ try {
63
+ const match = matchContent . match ( / I n c l u d e " (?< 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
+
60
83
export default class SSHConfiguration {
61
84
62
85
static async loadFromFS ( ) : Promise < SSHConfiguration > {
@@ -97,14 +120,11 @@ export default class SSHConfiguration {
97
120
}
98
121
}
99
122
100
- static async ensureIncludeGitpodSSHConfig ( ) : Promise < void > {
123
+ private static async addIncludeToUserSSHConfig ( gitpodHeader : string ) : Promise < void > {
101
124
const gitpodIncludeSection = `## START GITPOD INTEGRATION
102
125
## This section is managed by Gitpod. Any manual changes will be lost.
103
- Include "gitpod /config"
126
+ Include "code_gitpod.d /config"
104
127
## END GITPOD INTEGRATION` ;
105
-
106
- const gitpodHeader = `### This file is managed by Gitpod. Any manual changes will be lost.` ;
107
-
108
128
const configPath = getSSHConfigPath ( ) ;
109
129
let content = '' ;
110
130
if ( await exists ( configPath ) ) {
@@ -114,11 +134,25 @@ Include "gitpod/config"
114
134
throw new WrapError ( `Could not read ssh config file at ${ configPath } ` , e ) ;
115
135
}
116
136
}
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 ) {
120
153
content = `${ gitpodIncludeSection } \n\n${ content } ` ;
121
-
154
+ }
155
+ if ( content !== oldContent ) {
122
156
const configFileDir = path . dirname ( configPath ) ;
123
157
// must be dir
124
158
if ( ! ( await exists ( configFileDir ) ) ) {
@@ -138,7 +172,9 @@ Include "gitpod/config"
138
172
throw new WrapError ( `Could not write ssh config file ${ configPath } ` , e ) ;
139
173
}
140
174
}
175
+ }
141
176
177
+ private static async createGitpodSSHConfig ( gitpodHeader : string ) : Promise < void > {
142
178
const gitpodConfigFileDir = path . dirname ( gitpodSSHConfigPath ) ;
143
179
// must be dir
144
180
if ( ! ( await exists ( gitpodConfigFileDir ) ) ) {
@@ -166,6 +202,22 @@ Include "gitpod/config"
166
202
}
167
203
}
168
204
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
+
169
221
constructor ( private sshConfig : SSHConfig ) {
170
222
// Normalize config property names
171
223
normalizeSSHConfig ( sshConfig ) ;
0 commit comments