Skip to content

Commit 3fdf644

Browse files
author
Benjamin Pasero
committed
fix tests
1 parent d2e4503 commit 3fdf644

2 files changed

Lines changed: 93 additions & 66 deletions

File tree

src/vs/base/node/pfs.ts

Lines changed: 84 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -731,88 +731,107 @@ function doWatchNonRecursive(file: { path: string, isDirectory: boolean }, onCha
731731
// File path: use path directly for files and join with changed file name otherwise
732732
const changedFilePath = file.isDirectory ? join(file.path, changedFileName) : file.path;
733733

734-
// File: rename/delete
735-
if (!file.isDirectory && (type === 'rename' || changedFileName !== originalFileName)) {
736-
// The file was either deleted or renamed. Many tools apply changes to files in an
737-
// atomic way ("Atomic Save") by first renaming the file to a temporary name and then
738-
// renaming it back to the original name. Our watcher will detect this as a rename
739-
// and then stops to work on Mac and Linux because the watcher is applied to the
740-
// inode and not the name. The fix is to detect this case and trying to watch the file
741-
// again after a certain delay.
742-
// In addition, we send out a delete event if after a timeout we detect that the file
743-
// does indeed not exist anymore.
744-
745-
// Wait a bit and try to install watcher again, assuming that the file was renamed quickly ("Atomic Save")
746-
const timeoutHandle = setTimeout(async () => {
747-
const fileExists = await exists(changedFilePath);
748-
749-
if (disposed) {
750-
return; // ignore if disposed by now
751-
}
734+
// File
735+
if (!file.isDirectory) {
736+
if (type === 'rename' || changedFileName !== originalFileName) {
737+
// The file was either deleted or renamed. Many tools apply changes to files in an
738+
// atomic way ("Atomic Save") by first renaming the file to a temporary name and then
739+
// renaming it back to the original name. Our watcher will detect this as a rename
740+
// and then stops to work on Mac and Linux because the watcher is applied to the
741+
// inode and not the name. The fix is to detect this case and trying to watch the file
742+
// again after a certain delay.
743+
// In addition, we send out a delete event if after a timeout we detect that the file
744+
// does indeed not exist anymore.
745+
746+
// Wait a bit and try to install watcher again, assuming that the file was renamed quickly ("Atomic Save")
747+
const timeoutHandle = setTimeout(async () => {
748+
const fileExists = await exists(changedFilePath);
749+
750+
if (disposed) {
751+
return; // ignore if disposed by now
752+
}
752753

753-
// File still exists, so emit as change event and reapply the watcher
754-
if (fileExists) {
755-
onChange('changed', changedFilePath);
754+
// File still exists, so emit as change event and reapply the watcher
755+
if (fileExists) {
756+
onChange('changed', changedFilePath);
756757

757-
watcherDisposables = [doWatchNonRecursive(file, onChange, onError)];
758-
}
758+
watcherDisposables = [doWatchNonRecursive(file, onChange, onError)];
759+
}
759760

760-
// File seems to be really gone, so emit a deleted event
761-
else {
762-
onChange('deleted', changedFilePath);
763-
}
764-
}, 300);
761+
// File seems to be really gone, so emit a deleted event
762+
else {
763+
onChange('deleted', changedFilePath);
764+
}
765+
}, 300);
765766

766-
// Very important to dispose the watcher which now points to a stale inode
767-
// and wire in a new disposable that tracks our timeout that is installed
768-
dispose(watcherDisposables);
769-
watcherDisposables = [toDisposable(() => clearTimeout(timeoutHandle))];
767+
// Very important to dispose the watcher which now points to a stale inode
768+
// and wire in a new disposable that tracks our timeout that is installed
769+
dispose(watcherDisposables);
770+
watcherDisposables = [toDisposable(() => clearTimeout(timeoutHandle))];
771+
} else {
772+
onChange('changed', changedFilePath);
773+
}
770774
}
771775

772-
// Folder: add/delete
773-
else if (file.isDirectory && type === 'rename') {
776+
// Folder
777+
else {
774778

775-
// Cancel any previous stats for this file path if existing
776-
const statDisposable = mapPathToStatDisposable.get(changedFilePath);
777-
if (statDisposable) {
778-
dispose(statDisposable);
779-
}
779+
// Children add/delete
780+
if (type === 'rename') {
780781

781-
// Wait a bit and try see if the file still exists on disk to decide on the resulting event
782-
const timeoutHandle = setTimeout(async () => {
783-
mapPathToStatDisposable.delete(changedFilePath);
782+
// Cancel any previous stats for this file path if existing
783+
const statDisposable = mapPathToStatDisposable.get(changedFilePath);
784+
if (statDisposable) {
785+
dispose(statDisposable);
786+
}
784787

785-
const fileExists = await exists(changedFilePath);
788+
// Wait a bit and try see if the file still exists on disk to decide on the resulting event
789+
const timeoutHandle = setTimeout(async () => {
790+
mapPathToStatDisposable.delete(changedFilePath);
786791

787-
if (disposed) {
788-
return; // ignore if disposed by now
789-
}
792+
const fileExists = await exists(changedFilePath);
790793

791-
// Figure out the correct event type:
792-
// File Exists: either 'added' or 'changed' if known before
793-
// File Does not Exist: always 'deleted'
794-
let type: 'added' | 'deleted' | 'changed';
795-
if (fileExists) {
796-
if (folderChildren.has(changedFileName)) {
797-
type = 'changed';
794+
if (disposed) {
795+
return; // ignore if disposed by now
796+
}
797+
798+
// Figure out the correct event type:
799+
// File Exists: either 'added' or 'changed' if known before
800+
// File Does not Exist: always 'deleted'
801+
let type: 'added' | 'deleted' | 'changed';
802+
if (fileExists) {
803+
if (folderChildren.has(changedFileName)) {
804+
type = 'changed';
805+
} else {
806+
type = 'added';
807+
folderChildren.add(changedFileName);
808+
}
798809
} else {
799-
type = 'added';
800-
folderChildren.add(changedFileName);
810+
folderChildren.delete(changedFileName);
811+
type = 'deleted';
801812
}
813+
814+
onChange(type, changedFilePath);
815+
}, 100);
816+
817+
mapPathToStatDisposable.set(changedFilePath, toDisposable(() => clearTimeout(timeoutHandle)));
818+
}
819+
820+
// Other events
821+
else {
822+
823+
// Figure out the correct event type: if this is the
824+
// first time we see this child, it can only be added
825+
let type: 'added' | 'changed';
826+
if (folderChildren.has(changedFileName)) {
827+
type = 'changed';
802828
} else {
803-
folderChildren.delete(changedFileName);
804-
type = 'deleted';
829+
type = 'added';
830+
folderChildren.add(changedFileName);
805831
}
806832

807833
onChange(type, changedFilePath);
808-
}, 100);
809-
810-
mapPathToStatDisposable.set(changedFilePath, toDisposable(() => clearTimeout(timeoutHandle)));
811-
}
812-
813-
// Other events
814-
else {
815-
onChange('changed', changedFilePath);
834+
}
816835
}
817836
});
818837
} catch (error) {

src/vs/workbench/services/files2/test/node/diskFileService.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,13 +862,21 @@ suite('Disk File Service', () => {
862862
function assertWatch(toWatch: URI, expectedType: FileChangeType, expectedPath: URI, done: MochaDone): void {
863863
const watcherDisposable = service.watch(toWatch);
864864

865+
function toString(type: FileChangeType): string {
866+
switch (type) {
867+
case FileChangeType.ADDED: return 'added';
868+
case FileChangeType.DELETED: return 'deleted';
869+
case FileChangeType.UPDATED: return 'updated';
870+
}
871+
}
872+
865873
const listenerDisposable = service.onFileChanges(event => {
866874
watcherDisposable.dispose();
867875
listenerDisposable.dispose();
868876

869877
try {
870878
assert.equal(event.changes.length, 1);
871-
assert.equal(event.changes[0].type, expectedType);
879+
assert.equal(event.changes[0].type, expectedType, `Expected ${toString(expectedType)} but got ${toString(event.changes[0].type)}`);
872880
assert.equal(event.changes[0].resource.fsPath, expectedPath.fsPath);
873881

874882
done();

0 commit comments

Comments
 (0)