@@ -14,7 +14,7 @@ import { WrapError } from '../common/utils';
1414
1515const systemSSHConfig = isWindows ? path . resolve ( process . env . ALLUSERSPROFILE || 'C:\\ProgramData' , 'ssh\\ssh_config' ) : '/etc/ssh/ssh_config' ;
1616const 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
1919export 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 ( / 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+
6083export 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