-
Notifications
You must be signed in to change notification settings - Fork 30.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use r+ with truncation when saving existing files #31733
Changes from 2 commits
cc8b380
8dbd3e0
5517b03
e27c8ca
bdbfeac
c7d4931
ab03fee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,6 +109,10 @@ export function touch(path: string): TPromise<void> { | |
return nfcall(fs.utimes, path, now, now); | ||
} | ||
|
||
export function truncate(path: string, len: number): TPromise<void> { | ||
return nfcall(fs.truncate, path, len); | ||
} | ||
|
||
export function readFile(path: string): TPromise<Buffer>; | ||
export function readFile(path: string, encoding: string): TPromise<string>; | ||
export function readFile(path: string, encoding?: string): TPromise<Buffer | string> { | ||
|
@@ -120,12 +124,12 @@ export function readFile(path: string, encoding?: string): TPromise<Buffer | str | |
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly. | ||
const writeFilePathQueue: { [path: string]: Queue<void> } = Object.create(null); | ||
|
||
export function writeFile(path: string, data: string, encoding?: string): TPromise<void>; | ||
export function writeFile(path: string, data: NodeBuffer, encoding?: string): TPromise<void>; | ||
export function writeFile(path: string, data: any, encoding: string = 'utf8'): TPromise<void> { | ||
export function writeFile(path: string, data: string, options?: string | { encoding?: string; mode?: number; flag?: string; }): TPromise<void>; | ||
export function writeFile(path: string, data: NodeBuffer, options?: string | { encoding?: string; mode?: number; flag?: string; }): TPromise<void>; | ||
export function writeFile(path: string, data: any, options?: string | { encoding?: string; mode?: number; flag?: string; }): TPromise<void> { | ||
let queueKey = toQueueKey(path); | ||
|
||
return ensureWriteFileQueue(queueKey).queue(() => nfcall(extfs.writeFileAndFlush, path, data, encoding)); | ||
return ensureWriteFileQueue(queueKey).queue(() => nfcall(extfs.writeFileAndFlush, path, data, options)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this change, can we update |
||
} | ||
|
||
function toQueueKey(path: string): string { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -366,6 +366,34 @@ export class FileService implements IFileService { | |
|
||
// 5.) resolve | ||
return this.resolve(resource); | ||
}, error => { | ||
// Can't use 'w' for hidden files, so truncate and use 'r+' if the file exists | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to reference the issue here in the comment: #931 |
||
if (!exists || error.code !== 'EPERM') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @seishun should we add a check for windows here? as far as I know, hidden files (and this issue) only manifest on windows |
||
throw error; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer to use |
||
} | ||
|
||
// 5.) truncate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest to add a little bit more comment here why the trick of |
||
return pfs.truncate(absolutePath, 0).then(() => { | ||
let writeFilePromise: TPromise<void>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @seishun I still suggest to extract those lines which are now duplicate to a separate method that can be called then once from the normal path and once from the error path. that should make the change much smaller and easier to understand 👍 |
||
|
||
// Write fast if we do UTF 8 without BOM | ||
if (!addBom && encodingToWrite === encoding.UTF8) { | ||
writeFilePromise = pfs.writeFile(absolutePath, value, { encoding: encoding.UTF8, mode: 0o666, flag: 'r+' }); | ||
} | ||
|
||
// Otherwise use encoding lib | ||
else { | ||
const encoded = encoding.encode(value, encodingToWrite, { addBOM: addBom }); | ||
writeFilePromise = pfs.writeFile(absolutePath, encoded, { mode: 0o666, flag: 'r+' }); | ||
} | ||
|
||
// 6.) set contents | ||
return writeFilePromise.then(() => { | ||
|
||
// 7.) resolve | ||
return this.resolve(resource); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can safely remove the
encoding
option because it was always UTF-8 being used. The reason why an explicit encoding field is dangerous is because not all encodings the VS Code supports are supported by node (that is why we use a third party library for encoding conversion). Let's remove this option and use UTF-8 always in the method.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean the
string
option or theencoding
property?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seishun the encoding property within the options bag. I think it is good that you removed the previous string property and replaced with a more explicit option bag 👍