@theia/filesystem 1.77.0-next.99 → 1.78.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/breadcrumbs/filepath-breadcrumb.js +4 -8
- package/lib/browser/breadcrumbs/filepath-breadcrumb.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js +18 -25
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts +5 -5
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js +27 -33
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js.map +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser/download/file-download-command-contribution.js +28 -33
- package/lib/browser/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser/download/file-download-frontend-module.js +8 -10
- package/lib/browser/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser/download/file-download-service.d.ts +1 -1
- package/lib/browser/download/file-download-service.d.ts.map +1 -1
- package/lib/browser/download/file-download-service.js +19 -24
- package/lib/browser/download/file-download-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.js +25 -30
- package/lib/browser/file-dialog/file-dialog-container.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js +13 -21
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-model.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.js +20 -27
- package/lib/browser/file-dialog/file-dialog-model.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-module.js +21 -23
- package/lib/browser/file-dialog/file-dialog-module.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.d.ts +4 -4
- package/lib/browser/file-dialog/file-dialog-service.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.js +29 -38
- package/lib/browser/file-dialog/file-dialog-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js +16 -21
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js +9 -11
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-tree.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree.js +8 -11
- package/lib/browser/file-dialog/file-dialog-tree.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-widget.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.js +18 -23
- package/lib/browser/file-dialog/file-dialog-widget.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog.d.ts +6 -6
- package/lib/browser/file-dialog/file-dialog.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog.js +114 -132
- package/lib/browser/file-dialog/file-dialog.js.map +1 -1
- package/lib/browser/file-dialog/index.d.ts +4 -4
- package/lib/browser/file-dialog/index.d.ts.map +1 -1
- package/lib/browser/file-dialog/index.js +4 -7
- package/lib/browser/file-dialog/index.js.map +1 -1
- package/lib/browser/file-resource.d.ts +2 -2
- package/lib/browser/file-resource.d.ts.map +1 -1
- package/lib/browser/file-resource.js +64 -71
- package/lib/browser/file-resource.js.map +1 -1
- package/lib/browser/file-resource.spec.js +39 -42
- package/lib/browser/file-resource.spec.js.map +1 -1
- package/lib/browser/file-selection.d.ts +1 -1
- package/lib/browser/file-selection.d.ts.map +1 -1
- package/lib/browser/file-selection.js +7 -10
- package/lib/browser/file-selection.js.map +1 -1
- package/lib/browser/file-service-activation.spec.js +14 -16
- package/lib/browser/file-service-activation.spec.js.map +1 -1
- package/lib/browser/file-service-copy.spec.js +44 -47
- package/lib/browser/file-service-copy.spec.js.map +1 -1
- package/lib/browser/file-service-watcher.spec.js +199 -202
- package/lib/browser/file-service-watcher.spec.js.map +1 -1
- package/lib/browser/file-service.d.ts +3 -3
- package/lib/browser/file-service.d.ts.map +1 -1
- package/lib/browser/file-service.js +166 -181
- package/lib/browser/file-service.js.map +1 -1
- package/lib/browser/file-tree/file-tree-container.js +12 -15
- package/lib/browser/file-tree/file-tree-container.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.js +23 -31
- package/lib/browser/file-tree/file-tree-decorator-adapter.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js +26 -29
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.js +13 -18
- package/lib/browser/file-tree/file-tree-label-provider.js.map +1 -1
- package/lib/browser/file-tree/file-tree-model.d.ts +5 -5
- package/lib/browser/file-tree/file-tree-model.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-model.js +48 -52
- package/lib/browser/file-tree/file-tree-model.js.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts +3 -3
- package/lib/browser/file-tree/file-tree-widget.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.js +66 -72
- package/lib/browser/file-tree/file-tree-widget.js.map +1 -1
- package/lib/browser/file-tree/file-tree.d.ts +3 -3
- package/lib/browser/file-tree/file-tree.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree.js +26 -31
- package/lib/browser/file-tree/file-tree.js.map +1 -1
- package/lib/browser/file-tree/index.d.ts +6 -6
- package/lib/browser/file-tree/index.d.ts.map +1 -1
- package/lib/browser/file-tree/index.js +6 -9
- package/lib/browser/file-tree/index.js.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.d.ts +6 -6
- package/lib/browser/filesystem-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.js +75 -90
- package/lib/browser/filesystem-frontend-contribution.js.map +1 -1
- package/lib/browser/filesystem-frontend-module.js +47 -50
- package/lib/browser/filesystem-frontend-module.js.map +1 -1
- package/lib/browser/filesystem-saveable-service.d.ts +2 -2
- package/lib/browser/filesystem-saveable-service.d.ts.map +1 -1
- package/lib/browser/filesystem-saveable-service.js +35 -44
- package/lib/browser/filesystem-saveable-service.js.map +1 -1
- package/lib/browser/filesystem-watcher-error-handler.js +13 -18
- package/lib/browser/filesystem-watcher-error-handler.js.map +1 -1
- package/lib/browser/index.d.ts +4 -4
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +4 -7
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/location/index.d.ts +2 -2
- package/lib/browser/location/index.d.ts.map +1 -1
- package/lib/browser/location/index.js +2 -5
- package/lib/browser/location/index.js.map +1 -1
- package/lib/browser/location/location-renderer.d.ts +3 -3
- package/lib/browser/location/location-renderer.d.ts.map +1 -1
- package/lib/browser/location/location-renderer.js +42 -51
- package/lib/browser/location/location-renderer.js.map +1 -1
- package/lib/browser/location/location-renderer.spec.js +61 -64
- package/lib/browser/location/location-renderer.spec.js.map +1 -1
- package/lib/browser/location/location-service.js +1 -2
- package/lib/browser/location/location-service.js.map +1 -1
- package/lib/browser/remote-file-service-contribution.d.ts +2 -2
- package/lib/browser/remote-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/remote-file-service-contribution.js +8 -12
- package/lib/browser/remote-file-service-contribution.js.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.js +55 -64
- package/lib/browser/upload/file-upload-service-impl.js.map +1 -1
- package/lib/browser/vscode-file-service-contribution.d.ts +2 -2
- package/lib/browser/vscode-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/vscode-file-service-contribution.js +23 -28
- package/lib/browser/vscode-file-service-contribution.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +21 -23
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.js +10 -13
- package/lib/browser-only/browser-only-filesystem-provider-server.js.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.js +14 -19
- package/lib/browser-only/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser-only/download/file-download-frontend-module.js +8 -10
- package/lib/browser-only/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser-only/download/file-download-service.d.ts +3 -3
- package/lib/browser-only/download/file-download-service.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-service.js +26 -33
- package/lib/browser-only/download/file-download-service.js.map +1 -1
- package/lib/browser-only/file-search.d.ts.map +1 -1
- package/lib/browser-only/file-search.js +9 -15
- package/lib/browser-only/file-search.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.js +6 -9
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.d.ts +2 -2
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.js +60 -68
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser-only/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.js +51 -60
- package/lib/browser-only/upload/file-upload-service-impl.js.map +1 -1
- package/lib/common/delegating-file-system-provider.d.ts +1 -1
- package/lib/common/delegating-file-system-provider.d.ts.map +1 -1
- package/lib/common/delegating-file-system-provider.js +18 -22
- package/lib/common/delegating-file-system-provider.js.map +1 -1
- package/lib/common/download/file-download.js +5 -8
- package/lib/common/download/file-download.js.map +1 -1
- package/lib/common/file-upload.js +1 -4
- package/lib/common/file-upload.js.map +1 -1
- package/lib/common/files.js +38 -59
- package/lib/common/files.js.map +1 -1
- package/lib/common/files.spec.js +22 -25
- package/lib/common/files.spec.js.map +1 -1
- package/lib/common/filesystem-preferences.js +39 -44
- package/lib/common/filesystem-preferences.js.map +1 -1
- package/lib/common/filesystem-utils.d.ts +1 -1
- package/lib/common/filesystem-utils.d.ts.map +1 -1
- package/lib/common/filesystem-utils.js +2 -5
- package/lib/common/filesystem-utils.js.map +1 -1
- package/lib/common/filesystem-utils.spec.js +227 -229
- package/lib/common/filesystem-utils.spec.js.map +1 -1
- package/lib/common/filesystem-watcher-protocol.d.ts +1 -1
- package/lib/common/filesystem-watcher-protocol.d.ts.map +1 -1
- package/lib/common/filesystem-watcher-protocol.js +2 -5
- package/lib/common/filesystem-watcher-protocol.js.map +1 -1
- package/lib/common/filesystem.js +2 -5
- package/lib/common/filesystem.js.map +1 -1
- package/lib/common/index.d.ts +3 -3
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -6
- package/lib/common/index.js.map +1 -1
- package/lib/common/io.d.ts +2 -2
- package/lib/common/io.d.ts.map +1 -1
- package/lib/common/io.js +10 -13
- package/lib/common/io.js.map +1 -1
- package/lib/common/remote-file-system-provider.d.ts +5 -5
- package/lib/common/remote-file-system-provider.d.ts.map +1 -1
- package/lib/common/remote-file-system-provider.js +81 -93
- package/lib/common/remote-file-system-provider.js.map +1 -1
- package/lib/common/upload/file-upload.js +1 -4
- package/lib/common/upload/file-upload.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js +6 -8
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts +3 -3
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js +21 -23
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js +33 -12
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js.map +1 -1
- package/lib/electron-browser/preload.js +6 -9
- package/lib/electron-browser/preload.js.map +1 -1
- package/lib/electron-common/electron-api.d.ts +4 -0
- package/lib/electron-common/electron-api.d.ts.map +1 -1
- package/lib/electron-common/electron-api.js +2 -5
- package/lib/electron-common/electron-api.js.map +1 -1
- package/lib/electron-main/electron-api-main.d.ts.map +1 -1
- package/lib/electron-main/electron-api-main.js +19 -18
- package/lib/electron-main/electron-api-main.js.map +1 -1
- package/lib/electron-main/electron-main-module.js +6 -8
- package/lib/electron-main/electron-main-module.js.map +1 -1
- package/lib/node/archive/archive-extractor.d.ts +86 -0
- package/lib/node/archive/archive-extractor.d.ts.map +1 -0
- package/lib/node/archive/archive-extractor.js +290 -0
- package/lib/node/archive/archive-extractor.js.map +1 -0
- package/lib/node/archive/archive-extractor.spec.d.ts +2 -0
- package/lib/node/archive/archive-extractor.spec.d.ts.map +1 -0
- package/lib/node/archive/archive-extractor.spec.js +317 -0
- package/lib/node/archive/archive-extractor.spec.js.map +1 -0
- package/lib/node/archive/test/test-archives.d.ts +20 -0
- package/lib/node/archive/test/test-archives.d.ts.map +1 -0
- package/lib/node/archive/test/test-archives.js +97 -0
- package/lib/node/archive/test/test-archives.js.map +1 -0
- package/lib/node/disk-file-system-provider.d.ts +2 -2
- package/lib/node/disk-file-system-provider.d.ts.map +1 -1
- package/lib/node/disk-file-system-provider.js +111 -119
- package/lib/node/disk-file-system-provider.js.map +1 -1
- package/lib/node/disk-file-system-provider.spec.js +53 -56
- package/lib/node/disk-file-system-provider.spec.js.map +1 -1
- package/lib/node/download/directory-archiver.js +13 -16
- package/lib/node/download/directory-archiver.js.map +1 -1
- package/lib/node/download/directory-archiver.spec.js +20 -23
- package/lib/node/download/directory-archiver.spec.js.map +1 -1
- package/lib/node/download/file-download-backend-module.js +14 -16
- package/lib/node/download/file-download-backend-module.js.map +1 -1
- package/lib/node/download/file-download-cache.js +11 -15
- package/lib/node/download/file-download-cache.js.map +1 -1
- package/lib/node/download/file-download-endpoint.d.ts +1 -1
- package/lib/node/download/file-download-endpoint.d.ts.map +1 -1
- package/lib/node/download/file-download-endpoint.js +25 -31
- package/lib/node/download/file-download-endpoint.js.map +1 -1
- package/lib/node/download/file-download-handler.d.ts +2 -2
- package/lib/node/download/file-download-handler.d.ts.map +1 -1
- package/lib/node/download/file-download-handler.js +70 -76
- package/lib/node/download/file-download-handler.js.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.js +2 -6
- package/lib/node/download/test/mock-directory-archiver.js.map +1 -1
- package/lib/node/file-change-collection.d.ts +1 -1
- package/lib/node/file-change-collection.d.ts.map +1 -1
- package/lib/node/file-change-collection.js +1 -5
- package/lib/node/file-change-collection.js.map +1 -1
- package/lib/node/file-change-collection.spec.js +5 -8
- package/lib/node/file-change-collection.spec.js.map +1 -1
- package/lib/node/filesystem-backend-module.d.ts +1 -1
- package/lib/node/filesystem-backend-module.d.ts.map +1 -1
- package/lib/node/filesystem-backend-module.js +60 -64
- package/lib/node/filesystem-backend-module.js.map +1 -1
- package/lib/node/filesystem-watcher-client.d.ts +2 -2
- package/lib/node/filesystem-watcher-client.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-client.js +11 -16
- package/lib/node/filesystem-watcher-client.js.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.js +9 -13
- package/lib/node/filesystem-watcher-dispatcher.js.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.d.ts +3 -3
- package/lib/node/filesystem-watcher-service-impl.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.js +7 -11
- package/lib/node/filesystem-watcher-service-impl.js.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.spec.js +23 -26
- package/lib/node/filesystem-watcher-service-impl.spec.js.map +1 -1
- package/lib/node/filesystem-watcher.d.ts +1 -1
- package/lib/node/filesystem-watcher.d.ts.map +1 -1
- package/lib/node/filesystem-watcher.js +6 -11
- package/lib/node/filesystem-watcher.js.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts +4 -4
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.js +20 -26
- package/lib/node/nodejs-watcher/node-directory-watcher.js.map +1 -1
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js +51 -54
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js.map +1 -1
- package/lib/node/nodejs-watcher/watch-request-router.d.ts +3 -3
- package/lib/node/nodejs-watcher/watch-request-router.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/watch-request-router.js +8 -13
- package/lib/node/nodejs-watcher/watch-request-router.js.map +1 -1
- package/lib/node/nodejs-watcher/watcher-host.d.ts +1 -1
- package/lib/node/nodejs-watcher/watcher-host.d.ts.map +1 -1
- package/lib/node/nodejs-watcher/watcher-host.js +7 -12
- package/lib/node/nodejs-watcher/watcher-host.js.map +1 -1
- package/lib/node/parcel-watcher/index.js +6 -9
- package/lib/node/parcel-watcher/index.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts +4 -4
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.js +4 -8
- package/lib/node/parcel-watcher/parcel-filesystem-service.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js +23 -26
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-options.js +1 -4
- package/lib/node/parcel-watcher/parcel-options.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js +11 -16
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js +11 -16
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher.d.ts +3 -3
- package/lib/node/parcel-watcher/parcel-watcher.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher.js +28 -32
- package/lib/node/parcel-watcher/parcel-watcher.js.map +1 -1
- package/lib/node/test/watcher-test-helper.d.ts +1 -1
- package/lib/node/test/watcher-test-helper.d.ts.map +1 -1
- package/lib/node/test/watcher-test-helper.js +5 -10
- package/lib/node/test/watcher-test-helper.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts.map +1 -1
- package/lib/node/upload/node-file-upload-service.js +20 -25
- package/lib/node/upload/node-file-upload-service.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.spec.js +21 -24
- package/lib/node/upload/node-file-upload-service.spec.js.map +1 -1
- package/package.json +21 -5
- package/src/browser/breadcrumbs/filepath-breadcrumb.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-container.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-contribution.ts +5 -5
- package/src/browser/download/file-download-command-contribution.ts +1 -1
- package/src/browser/download/file-download-frontend-module.ts +3 -3
- package/src/browser/download/file-download-service.ts +1 -1
- package/src/browser/file-dialog/file-dialog-container.ts +5 -5
- package/src/browser/file-dialog/file-dialog-hidden-files-renderer.tsx +1 -1
- package/src/browser/file-dialog/file-dialog-model.ts +2 -2
- package/src/browser/file-dialog/file-dialog-module.ts +5 -5
- package/src/browser/file-dialog/file-dialog-service.ts +4 -4
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.spec.ts +2 -2
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.tsx +1 -1
- package/src/browser/file-dialog/file-dialog-tree.ts +2 -2
- package/src/browser/file-dialog/file-dialog-widget.ts +2 -2
- package/src/browser/file-dialog/file-dialog.ts +16 -13
- package/src/browser/file-dialog/index.ts +4 -4
- package/src/browser/file-resource.spec.ts +3 -3
- package/src/browser/file-resource.ts +3 -3
- package/src/browser/file-selection.ts +1 -1
- package/src/browser/file-service-activation.spec.ts +2 -2
- package/src/browser/file-service-copy.spec.ts +2 -2
- package/src/browser/file-service-watcher.spec.ts +2 -2
- package/src/browser/file-service.ts +6 -6
- package/src/browser/file-tree/file-tree-container.ts +3 -3
- package/src/browser/file-tree/file-tree-decorator-adapter.spec.ts +1 -1
- package/src/browser/file-tree/file-tree-decorator-adapter.ts +1 -1
- package/src/browser/file-tree/file-tree-label-provider.ts +1 -1
- package/src/browser/file-tree/file-tree-model.ts +12 -6
- package/src/browser/file-tree/file-tree-widget.tsx +8 -5
- package/src/browser/file-tree/file-tree.ts +3 -3
- package/src/browser/file-tree/index.ts +6 -6
- package/src/browser/filesystem-frontend-contribution.ts +6 -6
- package/src/browser/filesystem-frontend-module.ts +14 -14
- package/src/browser/filesystem-saveable-service.ts +2 -2
- package/src/browser/index.ts +4 -4
- package/src/browser/location/index.ts +2 -2
- package/src/browser/location/location-renderer.spec.ts +3 -3
- package/src/browser/location/location-renderer.tsx +3 -3
- package/src/browser/remote-file-service-contribution.ts +2 -2
- package/src/browser/upload/file-upload-service-impl.ts +5 -5
- package/src/browser/vscode-file-service-contribution.ts +2 -2
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +7 -7
- package/src/browser-only/browser-only-filesystem-provider-server.ts +1 -1
- package/src/browser-only/download/file-download-command-contribution.ts +2 -2
- package/src/browser-only/download/file-download-frontend-module.ts +3 -3
- package/src/browser-only/download/file-download-service.ts +3 -3
- package/src/browser-only/file-search.ts +2 -1
- package/src/browser-only/opfs-filesystem-initialization.ts +1 -1
- package/src/browser-only/opfs-filesystem-provider.ts +3 -3
- package/src/browser-only/upload/file-upload-service-impl.ts +4 -4
- package/src/common/delegating-file-system-provider.ts +1 -1
- package/src/common/files.spec.ts +1 -1
- package/src/common/filesystem-utils.spec.ts +2 -2
- package/src/common/filesystem-utils.ts +1 -1
- package/src/common/filesystem-watcher-protocol.ts +1 -1
- package/src/common/index.ts +3 -3
- package/src/common/io.ts +2 -2
- package/src/common/remote-file-system-provider.ts +1 -1
- package/src/electron-browser/file-dialog/electron-file-dialog-module.ts +2 -2
- package/src/electron-browser/file-dialog/electron-file-dialog-service.spec.ts +30 -3
- package/src/electron-browser/file-dialog/electron-file-dialog-service.ts +8 -6
- package/src/electron-browser/preload.ts +1 -1
- package/src/electron-common/electron-api.ts +4 -0
- package/src/electron-main/electron-api-main.ts +7 -3
- package/src/electron-main/electron-main-module.ts +1 -1
- package/src/node/archive/archive-extractor.spec.ts +359 -0
- package/src/node/archive/archive-extractor.ts +350 -0
- package/src/node/archive/test/test-archives.ts +117 -0
- package/src/node/disk-file-system-provider.spec.ts +3 -3
- package/src/node/disk-file-system-provider.ts +7 -6
- package/src/node/download/directory-archiver.spec.ts +1 -1
- package/src/node/download/file-download-backend-module.ts +4 -4
- package/src/node/download/file-download-endpoint.ts +4 -3
- package/src/node/download/file-download-handler.ts +3 -3
- package/src/node/download/test/mock-directory-archiver.ts +1 -1
- package/src/node/file-change-collection.spec.ts +2 -2
- package/src/node/file-change-collection.ts +1 -1
- package/src/node/filesystem-backend-module.ts +15 -12
- package/src/node/filesystem-watcher-client.ts +2 -2
- package/src/node/filesystem-watcher-dispatcher.ts +1 -1
- package/src/node/filesystem-watcher-service-impl.spec.ts +5 -5
- package/src/node/filesystem-watcher-service-impl.ts +4 -4
- package/src/node/filesystem-watcher.ts +1 -1
- package/src/node/nodejs-watcher/node-directory-watcher.spec.ts +5 -5
- package/src/node/nodejs-watcher/node-directory-watcher.ts +5 -5
- package/src/node/nodejs-watcher/watch-request-router.ts +4 -4
- package/src/node/nodejs-watcher/watcher-host.ts +1 -1
- package/src/node/parcel-watcher/index.ts +2 -2
- package/src/node/parcel-watcher/parcel-filesystem-service.ts +4 -4
- package/src/node/parcel-watcher/parcel-filesystem-watcher.spec.ts +2 -2
- package/src/node/parcel-watcher/parcel-watcher-exclude.spec.ts +4 -8
- package/src/node/parcel-watcher/parcel-watcher-retry.spec.ts +4 -6
- package/src/node/parcel-watcher/parcel-watcher.ts +7 -6
- package/src/node/test/watcher-test-helper.ts +1 -1
- package/src/node/upload/node-file-upload-service.spec.ts +1 -1
- package/src/node/upload/node-file-upload-service.ts +6 -6
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// *****************************************************************************
|
|
3
2
|
// Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
|
|
4
3
|
//
|
|
@@ -14,31 +13,29 @@
|
|
|
14
13
|
//
|
|
15
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
15
|
// *****************************************************************************
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const sinon = tslib_1.__importStar(require("sinon"));
|
|
26
|
-
const file_service_1 = require("./file-service");
|
|
16
|
+
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
|
|
17
|
+
let disableJSDOM = enableJSDOM();
|
|
18
|
+
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
|
19
|
+
FrontendApplicationConfigProvider.set({});
|
|
20
|
+
import { Disposable, Emitter, URI } from '@theia/core';
|
|
21
|
+
import { expect } from 'chai';
|
|
22
|
+
import * as sinon from 'sinon';
|
|
23
|
+
import { FileService } from './file-service.js';
|
|
27
24
|
disableJSDOM();
|
|
28
25
|
function createMockProvider(caseSensitive = true) {
|
|
29
26
|
const watchers = [];
|
|
30
27
|
return {
|
|
31
28
|
watchers,
|
|
32
29
|
capabilities: caseSensitive ? 1024 /* FileSystemProviderCapabilities.PathCaseSensitive */ : 0,
|
|
33
|
-
onDidChangeCapabilities: () =>
|
|
34
|
-
onDidChangeFile: () =>
|
|
35
|
-
onFileWatchError: () =>
|
|
30
|
+
onDidChangeCapabilities: () => Disposable.NULL,
|
|
31
|
+
onDidChangeFile: () => Disposable.NULL,
|
|
32
|
+
onFileWatchError: () => Disposable.NULL,
|
|
36
33
|
watch(resource, options) {
|
|
37
34
|
const watcher = {
|
|
38
35
|
resource,
|
|
39
36
|
options,
|
|
40
37
|
disposed: false,
|
|
41
|
-
disposable:
|
|
38
|
+
disposable: Disposable.create(() => { watcher.disposed = true; }),
|
|
42
39
|
};
|
|
43
40
|
watchers.push(watcher);
|
|
44
41
|
return watcher.disposable;
|
|
@@ -61,14 +58,14 @@ describe('FileService watcher deduplication', () => {
|
|
|
61
58
|
let fileService;
|
|
62
59
|
let mockProvider;
|
|
63
60
|
before(() => {
|
|
64
|
-
disableJSDOM =
|
|
61
|
+
disableJSDOM = enableJSDOM();
|
|
65
62
|
});
|
|
66
63
|
after(() => {
|
|
67
64
|
disableJSDOM();
|
|
68
65
|
});
|
|
69
66
|
beforeEach(() => {
|
|
70
67
|
sandbox.restore();
|
|
71
|
-
fileService = new
|
|
68
|
+
fileService = new FileService();
|
|
72
69
|
mockProvider = createMockProvider();
|
|
73
70
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
74
71
|
sandbox.stub(fileService, 'withProvider').resolves(mockProvider);
|
|
@@ -79,22 +76,22 @@ describe('FileService watcher deduplication', () => {
|
|
|
79
76
|
// ── (A) Exact-match dedup ──────────────────────────────────────────
|
|
80
77
|
describe('exact-match dedup', () => {
|
|
81
78
|
it('should reuse an existing watcher for the same resource and options', async () => {
|
|
82
|
-
const uri = new
|
|
79
|
+
const uri = new URI('file:///project/src');
|
|
83
80
|
const opts = { recursive: true, excludes: [] };
|
|
84
81
|
const d1 = await fileService.doWatch(uri, opts);
|
|
85
82
|
const d2 = await fileService.doWatch(uri, opts);
|
|
86
83
|
// Only one real OS watcher should have been created
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
85
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
89
86
|
// Disposing one handle should NOT dispose the real watcher
|
|
90
87
|
d2.dispose();
|
|
91
|
-
|
|
88
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
92
89
|
// Disposing the last handle should dispose it
|
|
93
90
|
d1.dispose();
|
|
94
|
-
|
|
91
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
95
92
|
});
|
|
96
93
|
it('should not let a restrictive parent subsume a permissive child at the same URI', async () => {
|
|
97
|
-
const uri = new
|
|
94
|
+
const uri = new URI('file:///project/src');
|
|
98
95
|
const opts1 = { recursive: true, excludes: ['**/node_modules'] };
|
|
99
96
|
const opts2 = { recursive: true, excludes: [] };
|
|
100
97
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
@@ -102,164 +99,164 @@ describe('FileService watcher deduplication', () => {
|
|
|
102
99
|
// The first watcher (with excludes) cannot subsume the second (no excludes),
|
|
103
100
|
// but the second (watching everything) CAN subsume the first via subsumeExistingChildren.
|
|
104
101
|
// Two real watchers were created, but only the permissive one (d2) remains live.
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
103
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
107
104
|
// Disposing d1 (already subsumed, no real watcher) should have no OS-level effect
|
|
108
105
|
d1.dispose();
|
|
109
|
-
|
|
106
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
110
107
|
d2.dispose();
|
|
111
|
-
|
|
108
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
112
109
|
});
|
|
113
110
|
it('should subsume a watcher with matching excludes on the same URI', async () => {
|
|
114
|
-
const uri = new
|
|
111
|
+
const uri = new URI('file:///project/src');
|
|
115
112
|
const opts1 = { recursive: true, excludes: ['**/node_modules'] };
|
|
116
113
|
const opts2 = { recursive: true, excludes: ['**/node_modules'] };
|
|
117
114
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
118
115
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
119
116
|
// Same excludes — exact-match dedup applies
|
|
120
|
-
|
|
117
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
121
118
|
d2.dispose();
|
|
122
|
-
|
|
119
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
123
120
|
d1.dispose();
|
|
124
|
-
|
|
121
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
125
122
|
});
|
|
126
123
|
it('should subsume a watcher with more excludes (superset) on the same URI', async () => {
|
|
127
|
-
const uri = new
|
|
124
|
+
const uri = new URI('file:///project/src');
|
|
128
125
|
const opts1 = { recursive: true, excludes: [] };
|
|
129
126
|
const opts2 = { recursive: true, excludes: ['**/node_modules'] };
|
|
130
127
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
131
128
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
132
129
|
// Parent has no excludes, so it watches everything the child needs — subsumption is safe
|
|
133
|
-
|
|
130
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
134
131
|
d2.dispose();
|
|
135
|
-
|
|
132
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
136
133
|
d1.dispose();
|
|
137
|
-
|
|
134
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
138
135
|
});
|
|
139
136
|
it('should subsume a non-recursive watcher on the same URI as a recursive watcher', async () => {
|
|
140
|
-
const uri = new
|
|
137
|
+
const uri = new URI('file:///project/src');
|
|
141
138
|
const opts1 = { recursive: true, excludes: [] };
|
|
142
139
|
const opts2 = { recursive: false, excludes: [] };
|
|
143
140
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
144
141
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
145
142
|
// The recursive watcher subsumes the non-recursive one on the same URI
|
|
146
|
-
|
|
143
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
147
144
|
d2.dispose();
|
|
148
|
-
|
|
145
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
149
146
|
d1.dispose();
|
|
150
|
-
|
|
147
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
151
148
|
});
|
|
152
149
|
it('should support three refs and only dispose when all are gone', async () => {
|
|
153
|
-
const uri = new
|
|
150
|
+
const uri = new URI('file:///project/src');
|
|
154
151
|
const opts = { recursive: false, excludes: [] };
|
|
155
152
|
const d1 = await fileService.doWatch(uri, opts);
|
|
156
153
|
const d2 = await fileService.doWatch(uri, opts);
|
|
157
154
|
const d3 = await fileService.doWatch(uri, opts);
|
|
158
|
-
|
|
155
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
159
156
|
d1.dispose();
|
|
160
|
-
|
|
157
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
161
158
|
d2.dispose();
|
|
162
|
-
|
|
159
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
163
160
|
d3.dispose();
|
|
164
|
-
|
|
161
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
165
162
|
});
|
|
166
163
|
});
|
|
167
164
|
// ── (B) Parent subsumption of new child ────────────────────────────
|
|
168
165
|
describe('parent subsumption', () => {
|
|
169
166
|
it('should not create an OS watcher when a recursive parent already covers the child', async () => {
|
|
170
|
-
const parentUri = new
|
|
171
|
-
const childUri = new
|
|
167
|
+
const parentUri = new URI('file:///project');
|
|
168
|
+
const childUri = new URI('file:///project/src');
|
|
172
169
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
173
170
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
174
171
|
// Only the parent's OS watcher should exist
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
173
|
+
expect(mockProvider.watchers[0].resource.toString()).to.equal(parentUri.toString());
|
|
177
174
|
});
|
|
178
175
|
it('should not subsume a child that is excluded by the parent', async () => {
|
|
179
|
-
const parentUri = new
|
|
180
|
-
const childUri = new
|
|
176
|
+
const parentUri = new URI('file:///project');
|
|
177
|
+
const childUri = new URI('file:///project/node_modules/foo');
|
|
181
178
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
182
179
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
183
180
|
// The child should get its own real watcher
|
|
184
|
-
|
|
181
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
185
182
|
});
|
|
186
183
|
it('should not subsume when the parent is non-recursive', async () => {
|
|
187
|
-
const parentUri = new
|
|
188
|
-
const childUri = new
|
|
184
|
+
const parentUri = new URI('file:///project');
|
|
185
|
+
const childUri = new URI('file:///project/src');
|
|
189
186
|
await fileService.doWatch(parentUri, { recursive: false, excludes: [] });
|
|
190
187
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
191
|
-
|
|
188
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
192
189
|
});
|
|
193
190
|
it('should subsume a deeply nested child', async () => {
|
|
194
|
-
const parentUri = new
|
|
195
|
-
const childUri = new
|
|
191
|
+
const parentUri = new URI('file:///project');
|
|
192
|
+
const childUri = new URI('file:///project/src/main/java/com/example');
|
|
196
193
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
197
194
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
198
|
-
|
|
195
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
199
196
|
});
|
|
200
197
|
it('should not subsume a sibling directory', async () => {
|
|
201
|
-
const parentUri = new
|
|
202
|
-
const siblingUri = new
|
|
198
|
+
const parentUri = new URI('file:///project/src');
|
|
199
|
+
const siblingUri = new URI('file:///project/test');
|
|
203
200
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
204
201
|
await fileService.doWatch(siblingUri, { recursive: false, excludes: [] });
|
|
205
|
-
|
|
202
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
206
203
|
});
|
|
207
204
|
it('should not subsume a child when it is under an excluded ancestor directory', async () => {
|
|
208
|
-
const parentUri = new
|
|
205
|
+
const parentUri = new URI('file:///project');
|
|
209
206
|
// node_modules is excluded, so anything under it should not be subsumed
|
|
210
|
-
const childUri = new
|
|
207
|
+
const childUri = new URI('file:///project/node_modules/pkg/lib');
|
|
211
208
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
212
209
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
213
210
|
// Child needs its own watcher since it's under an excluded directory
|
|
214
|
-
|
|
211
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
215
212
|
});
|
|
216
213
|
});
|
|
217
214
|
// ── (D) New recursive parent subsumes existing children ────────────
|
|
218
215
|
describe('child subsumption by new parent', () => {
|
|
219
216
|
it('should subsume existing non-recursive children when a new recursive parent is created', async () => {
|
|
220
|
-
const childUri1 = new
|
|
221
|
-
const childUri2 = new
|
|
222
|
-
const parentUri = new
|
|
217
|
+
const childUri1 = new URI('file:///project/src');
|
|
218
|
+
const childUri2 = new URI('file:///project/test');
|
|
219
|
+
const parentUri = new URI('file:///project');
|
|
223
220
|
await fileService.doWatch(childUri1, { recursive: false, excludes: [] });
|
|
224
221
|
await fileService.doWatch(childUri2, { recursive: false, excludes: [] });
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
223
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
227
224
|
// Adding a recursive parent should subsume both children
|
|
228
225
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
229
226
|
// Three watchers created total, but only the parent should remain live
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
227
|
+
expect(mockProvider.watchers).to.have.lengthOf(3);
|
|
228
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
229
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // child1 real watcher disposed
|
|
230
|
+
expect(mockProvider.watchers[1].disposed).to.be.true; // child2 real watcher disposed
|
|
231
|
+
expect(mockProvider.watchers[2].disposed).to.be.false; // parent alive
|
|
235
232
|
});
|
|
236
233
|
it('should subsume existing recursive children and re-parent grandchildren', async () => {
|
|
237
|
-
const grandchildUri = new
|
|
238
|
-
const childUri = new
|
|
239
|
-
const parentUri = new
|
|
234
|
+
const grandchildUri = new URI('file:///project/src/deep');
|
|
235
|
+
const childUri = new URI('file:///project/src');
|
|
236
|
+
const parentUri = new URI('file:///project');
|
|
240
237
|
// Create a recursive child first, then a grandchild under it
|
|
241
238
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
242
239
|
await fileService.doWatch(grandchildUri, { recursive: false, excludes: [] });
|
|
243
240
|
// Grandchild should already be subsumed by the child
|
|
244
|
-
|
|
241
|
+
expect(mockProvider.watchers).to.have.lengthOf(1); // only child has a real watcher
|
|
245
242
|
// Now create a parent that covers everything
|
|
246
243
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
247
244
|
// Child's real watcher gets disposed, parent takes over
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
245
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
246
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // child disposed
|
|
247
|
+
expect(mockProvider.watchers[1].disposed).to.be.false; // parent alive
|
|
251
248
|
});
|
|
252
249
|
it('should promote and re-index a recursive grandchild excluded by the new parent', async () => {
|
|
253
|
-
const childUri = new
|
|
254
|
-
const grandchildUri = new
|
|
255
|
-
const parentUri = new
|
|
250
|
+
const childUri = new URI('file:///project/src');
|
|
251
|
+
const grandchildUri = new URI('file:///project/src/vendor');
|
|
252
|
+
const parentUri = new URI('file:///project');
|
|
256
253
|
// Child and grandchild share the same excludes — grandchild is compatible with child.
|
|
257
254
|
// The pattern '**/src/vendor' does NOT match the relative path from child to grandchild
|
|
258
255
|
// ('vendor'), so isExcludedByParent(child, grandchild) is false — grandchild is subsumed.
|
|
259
256
|
await fileService.doWatch(childUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
260
257
|
await fileService.doWatch(grandchildUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
expect(mockProvider.watchers).to.have.lengthOf(1); // only child has a real watcher
|
|
259
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
263
260
|
// Create a parent with the same excludes. The parent subsumes the child
|
|
264
261
|
// (areExcludesCompatible passes). But the grandchild at /project/src/vendor has
|
|
265
262
|
// relative path 'src/vendor' from /project, which DOES match '**/src/vendor'.
|
|
@@ -267,20 +264,20 @@ describe('FileService watcher deduplication', () => {
|
|
|
267
264
|
// with its own real watcher and re-indexed.
|
|
268
265
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
269
266
|
// Parent is live (subsumes child). Grandchild is promoted with its own real watcher.
|
|
270
|
-
|
|
267
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
271
268
|
// A new watcher under the promoted grandchild should be subsumed by it,
|
|
272
269
|
// which only works if the grandchild was re-indexed after promotion.
|
|
273
|
-
const deepUri = new
|
|
270
|
+
const deepUri = new URI('file:///project/src/vendor/utils');
|
|
274
271
|
await fileService.doWatch(deepUri, { recursive: false, excludes: [] });
|
|
275
272
|
// No new OS watcher — the promoted grandchild covers it
|
|
276
|
-
|
|
273
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
277
274
|
});
|
|
278
275
|
it('should not delete parent index when subsuming a recursive child at the same URI', async () => {
|
|
279
|
-
const uri = new
|
|
280
|
-
const childUri = new
|
|
276
|
+
const uri = new URI('file:///project');
|
|
277
|
+
const childUri = new URI('file:///project/src');
|
|
281
278
|
// Create a recursive watcher with excludes
|
|
282
279
|
await fileService.doWatch(uri, { recursive: true, excludes: ['**/node_modules'] });
|
|
283
|
-
|
|
280
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
284
281
|
// Create a new recursive watcher at the SAME URI with no excludes.
|
|
285
282
|
// Different key (different excludes), so it's a new entry. The new watcher
|
|
286
283
|
// subsumes the old one via subsumeExistingChildren. The old watcher is recursive,
|
|
@@ -288,193 +285,193 @@ describe('FileService watcher deduplication', () => {
|
|
|
288
285
|
// index entry (they share the same URI).
|
|
289
286
|
await fileService.doWatch(uri, { recursive: true, excludes: [] });
|
|
290
287
|
// Old watcher's OS watcher is disposed; new parent is live
|
|
291
|
-
|
|
288
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
292
289
|
// A child watcher should be subsumed by the new parent. Without the fix,
|
|
293
290
|
// the parent's index entry was deleted, causing unnecessary OS watchers.
|
|
294
291
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
295
292
|
// No new OS watcher — parent's index entry is intact
|
|
296
|
-
|
|
293
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
297
294
|
});
|
|
298
295
|
it('should not subsume excluded children when creating a new parent', async () => {
|
|
299
|
-
const childUri = new
|
|
300
|
-
const parentUri = new
|
|
296
|
+
const childUri = new URI('file:///project/node_modules/pkg');
|
|
297
|
+
const parentUri = new URI('file:///project');
|
|
301
298
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
302
|
-
|
|
299
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
303
300
|
// Parent excludes node_modules
|
|
304
301
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
305
302
|
// Child should NOT be subsumed — both watchers should remain live
|
|
306
|
-
|
|
303
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
307
304
|
});
|
|
308
305
|
});
|
|
309
306
|
// ── Disposal and promotion ─────────────────────────────────────────
|
|
310
307
|
describe('disposal and promotion', () => {
|
|
311
308
|
it('should promote subsumed children by creating real watchers when the parent is disposed', async () => {
|
|
312
|
-
const parentUri = new
|
|
313
|
-
const childUri = new
|
|
309
|
+
const parentUri = new URI('file:///project');
|
|
310
|
+
const childUri = new URI('file:///project/src');
|
|
314
311
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
315
312
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
316
313
|
// Only parent watcher is real
|
|
317
|
-
|
|
314
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
318
315
|
// Dispose the parent
|
|
319
316
|
parentDisposable.dispose();
|
|
320
317
|
// Child should now have its own real watcher
|
|
321
|
-
|
|
318
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
322
319
|
// The new watcher (index 1) should be for the child
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
320
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
321
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // parent
|
|
322
|
+
expect(mockProvider.watchers[1].disposed).to.be.false; // child promoted
|
|
323
|
+
expect(mockProvider.watchers[1].resource.toString()).to.equal(childUri.toString());
|
|
327
324
|
});
|
|
328
325
|
it('should re-parent children to another existing parent on disposal', async () => {
|
|
329
|
-
const grandparentUri = new
|
|
330
|
-
const parentUri = new
|
|
331
|
-
const childUri = new
|
|
326
|
+
const grandparentUri = new URI('file:///project');
|
|
327
|
+
const parentUri = new URI('file:///project/src');
|
|
328
|
+
const childUri = new URI('file:///project/src/components');
|
|
332
329
|
// Create grandparent, then parent, then child
|
|
333
330
|
await fileService.doWatch(grandparentUri, { recursive: true, excludes: [] });
|
|
334
331
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
335
332
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
336
333
|
// Grandparent subsumed parent; parent did not get a real watcher.
|
|
337
334
|
// Child was also subsumed (by grandparent after re-parenting).
|
|
338
|
-
|
|
335
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
339
336
|
// Dispose the parent
|
|
340
337
|
parentDisposable.dispose();
|
|
341
338
|
// Grandparent still covers the child — no new OS watcher needed
|
|
342
|
-
|
|
339
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
343
340
|
});
|
|
344
341
|
it('should promote multiple children when a parent is disposed', async () => {
|
|
345
|
-
const parentUri = new
|
|
346
|
-
const child1Uri = new
|
|
347
|
-
const child2Uri = new
|
|
348
|
-
const child3Uri = new
|
|
342
|
+
const parentUri = new URI('file:///project');
|
|
343
|
+
const child1Uri = new URI('file:///project/src');
|
|
344
|
+
const child2Uri = new URI('file:///project/test');
|
|
345
|
+
const child3Uri = new URI('file:///project/docs');
|
|
349
346
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
350
347
|
await fileService.doWatch(child1Uri, { recursive: false, excludes: [] });
|
|
351
348
|
await fileService.doWatch(child2Uri, { recursive: false, excludes: [] });
|
|
352
349
|
await fileService.doWatch(child3Uri, { recursive: false, excludes: [] });
|
|
353
|
-
|
|
350
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
354
351
|
parentDisposable.dispose();
|
|
355
352
|
// All three children should now have their own real watchers
|
|
356
|
-
|
|
353
|
+
expect(liveWatcherCount(mockProvider)).to.equal(3);
|
|
357
354
|
});
|
|
358
355
|
it('should not corrupt index when disposing a subsumed recursive watcher at the same URI', async () => {
|
|
359
|
-
const uri = new
|
|
360
|
-
const childUri = new
|
|
356
|
+
const uri = new URI('file:///project');
|
|
357
|
+
const childUri = new URI('file:///project/src');
|
|
361
358
|
// Watcher A: recursive, no excludes — gets indexed
|
|
362
359
|
await fileService.doWatch(uri, { recursive: true, excludes: [] });
|
|
363
360
|
// Watcher B: recursive, with excludes at the same URI — subsumed by A (not indexed)
|
|
364
361
|
const bDisposable = await fileService.doWatch(uri, { recursive: true, excludes: ['**/node_modules'] });
|
|
365
|
-
|
|
362
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
366
363
|
// Disposing B must NOT remove A's index entry.
|
|
367
364
|
// Without the fix, removeFromRecursiveIndex would delete /project from
|
|
368
365
|
// the tree, causing subsequent child watchers to miss A as a parent.
|
|
369
366
|
bDisposable.dispose();
|
|
370
367
|
// A child watcher should still be subsumed by A
|
|
371
368
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
372
|
-
|
|
369
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
373
370
|
});
|
|
374
371
|
it('should handle disposing a subsumed child cleanly', async () => {
|
|
375
|
-
const parentUri = new
|
|
376
|
-
const childUri = new
|
|
372
|
+
const parentUri = new URI('file:///project');
|
|
373
|
+
const childUri = new URI('file:///project/src');
|
|
377
374
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
378
375
|
const childDisposable = await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
379
|
-
|
|
376
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
380
377
|
// Disposing the subsumed child should not affect the parent's watcher
|
|
381
378
|
childDisposable.dispose();
|
|
382
|
-
|
|
379
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
383
380
|
});
|
|
384
381
|
it('should handle dispose-then-rewatch correctly', async () => {
|
|
385
|
-
const parentUri = new
|
|
386
|
-
const childUri = new
|
|
382
|
+
const parentUri = new URI('file:///project');
|
|
383
|
+
const childUri = new URI('file:///project/src');
|
|
387
384
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
388
385
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
389
386
|
parentDisposable.dispose();
|
|
390
387
|
// Child is promoted, now re-create the parent
|
|
391
388
|
const parentDisposable2 = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
392
389
|
// The child should be subsumed again — its promoted watcher should be disposed
|
|
393
|
-
|
|
390
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
394
391
|
parentDisposable2.dispose();
|
|
395
392
|
// Child promoted again
|
|
396
|
-
|
|
393
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
397
394
|
});
|
|
398
395
|
});
|
|
399
396
|
// ── Exclude pattern matching ───────────────────────────────────────
|
|
400
397
|
describe('exclude pattern matching', () => {
|
|
401
398
|
it('should exclude with glob patterns using **', async () => {
|
|
402
|
-
const parentUri = new
|
|
403
|
-
const excludedChild = new
|
|
399
|
+
const parentUri = new URI('file:///project');
|
|
400
|
+
const excludedChild = new URI('file:///project/dist/bundle.js');
|
|
404
401
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/dist'] });
|
|
405
402
|
await fileService.doWatch(excludedChild, { recursive: false, excludes: [] });
|
|
406
403
|
// Should not be subsumed because dist is excluded
|
|
407
|
-
|
|
404
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
408
405
|
});
|
|
409
406
|
it('should handle multiple exclude patterns', async () => {
|
|
410
|
-
const parentUri = new
|
|
411
|
-
const nmChild = new
|
|
412
|
-
const distChild = new
|
|
413
|
-
const srcChild = new
|
|
407
|
+
const parentUri = new URI('file:///project');
|
|
408
|
+
const nmChild = new URI('file:///project/node_modules/pkg');
|
|
409
|
+
const distChild = new URI('file:///project/dist/out');
|
|
410
|
+
const srcChild = new URI('file:///project/src/main');
|
|
414
411
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules', '**/dist'] });
|
|
415
412
|
await fileService.doWatch(nmChild, { recursive: false, excludes: [] });
|
|
416
413
|
await fileService.doWatch(distChild, { recursive: false, excludes: [] });
|
|
417
414
|
await fileService.doWatch(srcChild, { recursive: false, excludes: [] });
|
|
418
415
|
// nm and dist children need their own watchers; src is subsumed
|
|
419
|
-
|
|
416
|
+
expect(mockProvider.watchers).to.have.lengthOf(3); // parent + nm + dist
|
|
420
417
|
});
|
|
421
418
|
it('should exclude based on ancestor directory matching', async () => {
|
|
422
|
-
const parentUri = new
|
|
419
|
+
const parentUri = new URI('file:///project');
|
|
423
420
|
// The exclude is for node_modules — anything under it should also be excluded
|
|
424
|
-
const deepChild = new
|
|
421
|
+
const deepChild = new URI('file:///project/node_modules/pkg/lib/index.js');
|
|
425
422
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
426
423
|
await fileService.doWatch(deepChild, { recursive: false, excludes: [] });
|
|
427
|
-
|
|
424
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
428
425
|
});
|
|
429
426
|
it('should not exclude a non-matching path', async () => {
|
|
430
|
-
const parentUri = new
|
|
431
|
-
const childUri = new
|
|
427
|
+
const parentUri = new URI('file:///project');
|
|
428
|
+
const childUri = new URI('file:///project/src/node_modules_backup/file.ts');
|
|
432
429
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
433
430
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
434
431
|
// 'node_modules_backup' does not match '**/node_modules', so child should be subsumed
|
|
435
|
-
|
|
432
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
436
433
|
});
|
|
437
434
|
});
|
|
438
435
|
// ── Edge cases ─────────────────────────────────────────────────────
|
|
439
436
|
describe('edge cases', () => {
|
|
440
437
|
it('should promote a non-recursive watcher when its recursive same-URI subsumer is disposed', async () => {
|
|
441
|
-
const uri = new
|
|
438
|
+
const uri = new URI('file:///project/src');
|
|
442
439
|
const recursiveOpts = { recursive: true, excludes: [] };
|
|
443
440
|
const nonRecursiveOpts = { recursive: false, excludes: [] };
|
|
444
441
|
const d1 = await fileService.doWatch(uri, recursiveOpts);
|
|
445
442
|
const d2 = await fileService.doWatch(uri, nonRecursiveOpts);
|
|
446
443
|
// findSubstr matches exact URIs, so the recursive watcher subsumes the non-recursive one
|
|
447
|
-
|
|
444
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
448
445
|
// Disposing the recursive watcher promotes the non-recursive one
|
|
449
446
|
d1.dispose();
|
|
450
|
-
|
|
447
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
451
448
|
d2.dispose();
|
|
452
|
-
|
|
449
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
453
450
|
});
|
|
454
451
|
it('should handle double dispose gracefully', async () => {
|
|
455
|
-
const uri = new
|
|
452
|
+
const uri = new URI('file:///project/src');
|
|
456
453
|
const d1 = await fileService.doWatch(uri, { recursive: false, excludes: [] });
|
|
457
454
|
d1.dispose();
|
|
458
455
|
// Double dispose should not throw
|
|
459
456
|
d1.dispose();
|
|
460
|
-
|
|
457
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
461
458
|
});
|
|
462
459
|
it('should handle many watchers under one parent', async () => {
|
|
463
|
-
const parentUri = new
|
|
460
|
+
const parentUri = new URI('file:///project');
|
|
464
461
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
465
462
|
const childDisposables = [];
|
|
466
463
|
for (let i = 0; i < 20; i++) {
|
|
467
|
-
const d = await fileService.doWatch(new
|
|
464
|
+
const d = await fileService.doWatch(new URI(`file:///project/dir${i}`), { recursive: false, excludes: [] });
|
|
468
465
|
childDisposables.push(d);
|
|
469
466
|
}
|
|
470
467
|
// Only the parent's real watcher exists
|
|
471
|
-
|
|
472
|
-
|
|
468
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
469
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
473
470
|
// Dispose all children — parent still alive
|
|
474
471
|
for (const d of childDisposables) {
|
|
475
472
|
d.dispose();
|
|
476
473
|
}
|
|
477
|
-
|
|
474
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
478
475
|
});
|
|
479
476
|
});
|
|
480
477
|
});
|
|
@@ -484,18 +481,18 @@ describe('FileService watcher deduplication', () => {
|
|
|
484
481
|
*/
|
|
485
482
|
function createEventMockProvider(caseSensitive = true) {
|
|
486
483
|
const watchers = [];
|
|
487
|
-
const fileChangeEmitter = new
|
|
484
|
+
const fileChangeEmitter = new Emitter();
|
|
488
485
|
const provider = {
|
|
489
486
|
watchers,
|
|
490
487
|
fileChangeEmitter,
|
|
491
488
|
capabilities: caseSensitive ? 1024 /* FileSystemProviderCapabilities.PathCaseSensitive */ : 0,
|
|
492
|
-
onDidChangeCapabilities: () =>
|
|
489
|
+
onDidChangeCapabilities: () => Disposable.NULL,
|
|
493
490
|
onDidChangeFile: fileChangeEmitter.event,
|
|
494
|
-
onFileWatchError: () =>
|
|
491
|
+
onFileWatchError: () => Disposable.NULL,
|
|
495
492
|
watch(resource, options) {
|
|
496
493
|
const watcher = {
|
|
497
494
|
resource, options, disposed: false,
|
|
498
|
-
disposable:
|
|
495
|
+
disposable: Disposable.create(() => { watcher.disposed = true; }),
|
|
499
496
|
};
|
|
500
497
|
watchers.push(watcher);
|
|
501
498
|
return watcher.disposable;
|
|
@@ -518,13 +515,13 @@ describe('FileService watcher event delivery', () => {
|
|
|
518
515
|
let provider;
|
|
519
516
|
let disJSDOM;
|
|
520
517
|
before(() => {
|
|
521
|
-
disJSDOM =
|
|
518
|
+
disJSDOM = enableJSDOM();
|
|
522
519
|
});
|
|
523
520
|
after(() => {
|
|
524
521
|
disJSDOM();
|
|
525
522
|
});
|
|
526
523
|
beforeEach(() => {
|
|
527
|
-
fileService = new
|
|
524
|
+
fileService = new FileService();
|
|
528
525
|
provider = createEventMockProvider();
|
|
529
526
|
fileService.registerProvider('file', provider);
|
|
530
527
|
});
|
|
@@ -535,17 +532,17 @@ describe('FileService watcher event delivery', () => {
|
|
|
535
532
|
received.push(change.resource);
|
|
536
533
|
}
|
|
537
534
|
});
|
|
538
|
-
const parentUri = new
|
|
539
|
-
const childUri = new
|
|
535
|
+
const parentUri = new URI('file:///project');
|
|
536
|
+
const childUri = new URI('file:///project/src');
|
|
540
537
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
541
538
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
542
539
|
// Child is subsumed — only parent has a real watcher
|
|
543
|
-
|
|
540
|
+
expect(liveWatcherCount(provider)).to.equal(1);
|
|
544
541
|
// Simulate a change under the child path — should be delivered through the parent
|
|
545
|
-
const changedFile = new
|
|
542
|
+
const changedFile = new URI('file:///project/src/index.ts');
|
|
546
543
|
provider.simulateChange(changedFile);
|
|
547
|
-
|
|
548
|
-
|
|
544
|
+
expect(received).to.have.lengthOf(1);
|
|
545
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
549
546
|
});
|
|
550
547
|
it('should deliver events after a child is promoted due to parent disposal', async () => {
|
|
551
548
|
const received = [];
|
|
@@ -554,18 +551,18 @@ describe('FileService watcher event delivery', () => {
|
|
|
554
551
|
received.push(change.resource);
|
|
555
552
|
}
|
|
556
553
|
});
|
|
557
|
-
const parentUri = new
|
|
558
|
-
const childUri = new
|
|
554
|
+
const parentUri = new URI('file:///project');
|
|
555
|
+
const childUri = new URI('file:///project/src');
|
|
559
556
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
560
557
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
561
558
|
// Dispose parent — child gets promoted with its own real watcher
|
|
562
559
|
parentDisposable.dispose();
|
|
563
|
-
|
|
560
|
+
expect(liveWatcherCount(provider)).to.equal(1);
|
|
564
561
|
// Simulate a change — should still be delivered
|
|
565
|
-
const changedFile = new
|
|
562
|
+
const changedFile = new URI('file:///project/src/index.ts');
|
|
566
563
|
provider.simulateChange(changedFile);
|
|
567
|
-
|
|
568
|
-
|
|
564
|
+
expect(received).to.have.lengthOf(1);
|
|
565
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
569
566
|
});
|
|
570
567
|
it('should not let a parent with excludes suppress events for a child that needs them', async () => {
|
|
571
568
|
const received = [];
|
|
@@ -574,18 +571,18 @@ describe('FileService watcher event delivery', () => {
|
|
|
574
571
|
received.push(change.resource);
|
|
575
572
|
}
|
|
576
573
|
});
|
|
577
|
-
const parentUri = new
|
|
578
|
-
const childUri = new
|
|
574
|
+
const parentUri = new URI('file:///project');
|
|
575
|
+
const childUri = new URI('file:///project/src');
|
|
579
576
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
580
577
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
581
578
|
// Child is recursive with no excludes, parent has excludes — child should NOT be subsumed
|
|
582
579
|
// Both should have their own real watchers
|
|
583
|
-
|
|
580
|
+
expect(liveWatcherCount(provider)).to.equal(2);
|
|
584
581
|
// Simulate a change inside node_modules under the child — only the child's watcher would catch it
|
|
585
|
-
const changedFile = new
|
|
582
|
+
const changedFile = new URI('file:///project/src/node_modules/pkg/index.js');
|
|
586
583
|
provider.simulateChange(changedFile);
|
|
587
|
-
|
|
588
|
-
|
|
584
|
+
expect(received).to.have.lengthOf(1);
|
|
585
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
589
586
|
});
|
|
590
587
|
it('should preserve recursive watcher state through subsumption and promotion', async () => {
|
|
591
588
|
const received = [];
|
|
@@ -594,24 +591,24 @@ describe('FileService watcher event delivery', () => {
|
|
|
594
591
|
received.push(change.resource);
|
|
595
592
|
}
|
|
596
593
|
});
|
|
597
|
-
const grandparentUri = new
|
|
598
|
-
const parentUri = new
|
|
599
|
-
const childUri = new
|
|
594
|
+
const grandparentUri = new URI('file:///project');
|
|
595
|
+
const parentUri = new URI('file:///project/src');
|
|
596
|
+
const childUri = new URI('file:///project/src/lib');
|
|
600
597
|
// Create parent (recursive), then child under it
|
|
601
598
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
602
599
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
603
|
-
|
|
600
|
+
expect(liveWatcherCount(provider)).to.equal(1); // only parent has real watcher
|
|
604
601
|
// Now create a grandparent that subsumes the parent
|
|
605
602
|
const gpDisposable = await fileService.doWatch(grandparentUri, { recursive: true, excludes: [] });
|
|
606
|
-
|
|
603
|
+
expect(liveWatcherCount(provider)).to.equal(1); // only grandparent is live
|
|
607
604
|
// Dispose the grandparent — parent should be promoted, child should re-parent to parent
|
|
608
605
|
gpDisposable.dispose();
|
|
609
|
-
|
|
606
|
+
expect(liveWatcherCount(provider)).to.equal(1); // promoted parent is live
|
|
610
607
|
// Simulate a change under the child — should still be delivered
|
|
611
|
-
const changedFile = new
|
|
608
|
+
const changedFile = new URI('file:///project/src/lib/utils.ts');
|
|
612
609
|
provider.simulateChange(changedFile);
|
|
613
|
-
|
|
614
|
-
|
|
610
|
+
expect(received).to.have.lengthOf(1);
|
|
611
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
615
612
|
});
|
|
616
613
|
});
|
|
617
614
|
// ── files.watcherExclude applied to every watcher (#17247, #10794) ──────────
|
|
@@ -630,11 +627,11 @@ describe('FileService applies files.watcherExclude to all watchers', () => {
|
|
|
630
627
|
get: (name) => (name === 'files.watcherExclude' ? value : undefined)
|
|
631
628
|
};
|
|
632
629
|
}
|
|
633
|
-
before(() => { disJSDOM =
|
|
630
|
+
before(() => { disJSDOM = enableJSDOM(); });
|
|
634
631
|
after(() => { disJSDOM(); });
|
|
635
632
|
beforeEach(() => {
|
|
636
633
|
sandbox.restore();
|
|
637
|
-
fileService = new
|
|
634
|
+
fileService = new FileService();
|
|
638
635
|
mockProvider = createMockProvider();
|
|
639
636
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
640
637
|
sandbox.stub(fileService, 'withProvider').resolves(mockProvider);
|
|
@@ -646,42 +643,42 @@ describe('FileService applies files.watcherExclude to all watchers', () => {
|
|
|
646
643
|
'**/.git/objects/**': true,
|
|
647
644
|
'**/disabled/**': false
|
|
648
645
|
});
|
|
649
|
-
fileService.watch(new
|
|
646
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: [] });
|
|
650
647
|
await flush();
|
|
651
|
-
|
|
648
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
652
649
|
const excludes = mockProvider.watchers[0].options.excludes;
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
650
|
+
expect(excludes).to.include('**/node_modules/**');
|
|
651
|
+
expect(excludes).to.include('**/.git/objects/**');
|
|
652
|
+
expect(excludes).to.not.include('**/disabled/**');
|
|
656
653
|
// the temporary-upload exclude is still always applied
|
|
657
|
-
|
|
654
|
+
expect(excludes).to.include('**/theia_upload_*');
|
|
658
655
|
});
|
|
659
656
|
it('keeps the caller-supplied excludes alongside the configured ones', async () => {
|
|
660
657
|
stubWatcherExclude({ '**/node_modules/**': true });
|
|
661
|
-
fileService.watch(new
|
|
658
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: ['**/custom/**'] });
|
|
662
659
|
await flush();
|
|
663
660
|
const excludes = mockProvider.watchers[0].options.excludes;
|
|
664
|
-
|
|
665
|
-
|
|
661
|
+
expect(excludes).to.include('**/custom/**');
|
|
662
|
+
expect(excludes).to.include('**/node_modules/**');
|
|
666
663
|
});
|
|
667
664
|
it('still applies the temporary-upload exclude when no files.watcherExclude is configured', async () => {
|
|
668
665
|
stubWatcherExclude(undefined);
|
|
669
|
-
fileService.watch(new
|
|
666
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: [] });
|
|
670
667
|
await flush();
|
|
671
|
-
|
|
668
|
+
expect(mockProvider.watchers[0].options.excludes).to.deep.equal(['**/theia_upload_*']);
|
|
672
669
|
});
|
|
673
670
|
it('lets the workspace root watcher subsume an internal child watcher once excludes are consistent', async () => {
|
|
674
671
|
stubWatcherExclude({ '**/node_modules/**': true });
|
|
675
672
|
// The workspace root watcher already carries the configured excludes...
|
|
676
|
-
fileService.watch(new
|
|
673
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: ['**/node_modules/**'] });
|
|
677
674
|
// ...while an internal recursive watcher (e.g. @theia/ai-core) requests a child directory
|
|
678
675
|
// with empty excludes. Previously their exclude lists differed, so the child was not
|
|
679
676
|
// subsumed and produced a second OS watcher (and duplicate change events, see #17247).
|
|
680
|
-
fileService.watch(new
|
|
677
|
+
fileService.watch(new URI('file:///project/.prompts'), { recursive: true, excludes: [] });
|
|
681
678
|
await flush();
|
|
682
679
|
// With files.watcherExclude applied uniformly, the child's excludes now match the parent's,
|
|
683
680
|
// so the root watcher subsumes it — a single OS watcher instead of two.
|
|
684
|
-
|
|
681
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
685
682
|
});
|
|
686
683
|
});
|
|
687
684
|
//# sourceMappingURL=file-service-watcher.spec.js.map
|