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

Commit1925567

Browse files
committed
preserve existing mode on config file if present
1 parentf9943cb commit1925567

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
})
@@ -491,6 +498,7 @@ Host afterconfig
491498

492499
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
493500
mockFileSystem.readFile.mockResolvedValueOnce(existentSSHConfig)
501+
mockFileSystem.stat.mockResolvedValueOnce({mode:0o644})
494502
awaitsshConfig.load()
495503

496504
constexpectedOutput=`Host beforeconfig
@@ -534,13 +542,15 @@ Host afterconfig
534542

535543
expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath),expectedOutput,{
536544
encoding:"utf-8",
537-
mode:384,
545+
mode:0o644,
538546
})
539547
expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath+"."),sshFilePath)
540548
})
541549

542550
it("override values",async()=>{
543551
mockFileSystem.readFile.mockRejectedValueOnce("No file found")
552+
mockFileSystem.stat.mockRejectedValueOnce({code:"ENOENT"})
553+
544554
constsshConfig=newSSHConfig(sshFilePath,mockFileSystem)
545555
awaitsshConfig.load()
546556
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
@@ -222,14 +224,24 @@ export class SSHConfig {
222224
}
223225

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp