Movatterモバイル変換


[0]ホーム

URL:


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

Commit698b334

Browse files
committed
preserve existing mode on config file if present
1 parent685101a commit698b334

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

‎src/sshConfig.test.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { SSHConfig } from "./sshConfig"
55
constsshFilePath="~/.config/ssh"
66

77
constmockFileSystem={
8-
readFile:vi.fn(),
98
mkdir:vi.fn(),
10-
writeFile:vi.fn(),
9+
readFile:vi.fn(),
1110
rename:vi.fn(),
11+
stat:vi.fn(),
12+
writeFile:vi.fn(),
1213
}
1314

1415
afterEach(()=>{
@@ -17,6 +18,7 @@ afterEach(() => {
1718

1819
it("creates a new file and adds config with empty label",async()=>{
1920
mockFileSystem.readFile.mockRejectedValueOnce("No file found")
21+
mockFileSystem.stat.mockRejectedValueOnce({code:"ENOENT"})
2022

2123
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
2224
awaitsshConfig.load()
@@ -49,6 +51,7 @@ Host coder-vscode--*
4951

5052
it("creates a new file and adds the config",async()=>{
5153
mockFileSystem.readFile.mockRejectedValueOnce("No file found")
54+
mockFileSystem.stat.mockRejectedValueOnce({code:"ENOENT"})
5255

5356
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
5457
awaitsshConfig.load()
@@ -88,6 +91,7 @@ it("adds a new coder config in an existent SSH configuration", async () => {
8891
StrictHostKeyChecking=no
8992
UserKnownHostsFile=/dev/null`
9093
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
94+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
9195

9296
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
9397
awaitsshConfig.load()
@@ -113,7 +117,7 @@ Host coder-vscode.dev.coder.com--*
113117

114118
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
115119
encoding:"utf-8",
116-
mode:384,
120+
mode:0o644,
117121
})
118122
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
119123
})
@@ -150,6 +154,7 @@ Host coder-vscode.dev.coder.com--*
150154
Host *
151155
SetEnv TEST=1`
152156
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
157+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
153158

154159
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
155160
awaitsshConfig.load()
@@ -178,7 +183,7 @@ Host *
178183

179184
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
180185
encoding:"utf-8",
181-
mode:384,
186+
mode:0o644,
182187
})
183188
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
184189
})
@@ -199,6 +204,7 @@ Host coder-vscode--*
199204
UserKnownHostsFile=/dev/null
200205
# --- END CODER VSCODE ---`
201206
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
207+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
202208

203209
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
204210
awaitsshConfig.load()
@@ -224,7 +230,7 @@ Host coder-vscode.dev.coder.com--*
224230

225231
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
226232
encoding:"utf-8",
227-
mode:384,
233+
mode:0o644,
228234
})
229235
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
230236
})
@@ -233,6 +239,7 @@ it("it does not remove a user-added block that only matches the host of an old c
233239
constexistentSSHConfig=`Host coder-vscode--*
234240
ForwardAgent=yes`
235241
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
242+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
236243

237244
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
238245
awaitsshConfig.load()
@@ -259,7 +266,7 @@ Host coder-vscode.dev.coder.com--*
259266

260267
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
261268
encoding:"utf-8",
262-
mode:384,
269+
mode:0o644,
263270
})
264271
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
265272
})
@@ -451,6 +458,7 @@ Host afterconfig
451458

452459
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
453460
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
461+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
454462
awaitsshConfig.load()
455463

456464
constexpectedOutput=`Host beforeconfig
@@ -494,13 +502,15 @@ Host afterconfig
494502

495503
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
496504
encoding:"utf-8",
497-
mode:384,
505+
mode:0o644,
498506
})
499507
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
500508
})
501509

502510
it("override values",async()=>{
503511
mockFileSystem.readFile.mockRejectedValueOnce("No file found")
512+
mockFileSystem.stat.mockRejectedValueOnce({code:"ENOENT"})
513+
504514
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
505515
awaitsshConfig.load()
506516
awaitsshConfig.update(

‎src/sshConfig.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{mkdir,readFile,writeFile,rename}from"fs/promises"
1+
import{mkdir,readFile,rename,stat,writeFile}from"fs/promises"
22
importpathfrom"path"
33
import{countSubstring}from"./util"
44

@@ -20,17 +20,19 @@ export interface SSHValues {
2020

2121
// Interface for the file system to make it easier to test
2222
exportinterfaceFileSystem{
23-
readFile:typeofreadFile
2423
mkdir:typeofmkdir
25-
writeFile:typeofwriteFile
24+
readFile:typeofreadFile
2625
rename:typeofrename
26+
stat:typeofstat
27+
writeFile:typeofwriteFile
2728
}
2829

2930
constdefaultFileSystem:FileSystem={
30-
readFile,
3131
mkdir,
32-
writeFile,
32+
readFile,
3333
rename,
34+
stat,
35+
writeFile,
3436
}
3537

3638
// mergeSSHConfigValues will take a given ssh config and merge it with the overrides
@@ -221,14 +223,24 @@ export class SSHConfig {
221223
}
222224

223225
privateasyncsave(){
226+
// We want to preserve the original file mode.
227+
constexistingMode=awaitthis.fileSystem
228+
.stat(this.filePath)
229+
.then((stat)=>stat.mode)
230+
.catch((ex)=>{
231+
if(ex.code&&ex.code==="ENOENT"){
232+
return0o600// default to 0600 if file does not exist
233+
}
234+
throwex// Any other error is unexpected
235+
})
224236
awaitthis.fileSystem.mkdir(path.dirname(this.filePath),{
225237
mode:0o700,// only owner has rwx permission, not group or everyone.
226238
recursive:true,
227239
})
228240
constrandSuffix=Math.random().toString(36).substring(8)
229241
consttempFilePath=`${this.filePath}.${randSuffix}`
230242
awaitthis.fileSystem.writeFile(tempFilePath,this.getRaw(),{
231-
mode:0o600,// owner rw
243+
mode:existingMode,
232244
encoding:"utf-8",
233245
})
234246
awaitthis.fileSystem.rename(tempFilePath,this.filePath)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp