Skip to content

Commit 3211128

Browse files
authored
watcher - remove trailing path separators for watching (microsoft#210561)
1 parent 0ec62ea commit 3211128

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/vs/base/common/extpath.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ export function sanitizeFilePath(candidate: string, cwd: string): string {
282282
candidate = normalize(candidate);
283283

284284
// Ensure no trailing slash/backslash
285+
return removeTrailingPathSeparator(candidate);
286+
}
287+
288+
export function removeTrailingPathSeparator(candidate: string): string {
285289
if (isWindows) {
286290
candidate = rtrim(candidate, sep);
287291

src/vs/platform/files/common/diskFileSystemProvider.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { insert } from 'vs/base/common/arrays';
77
import { ThrottledDelayer } from 'vs/base/common/async';
88
import { onUnexpectedError } from 'vs/base/common/errors';
99
import { Emitter } from 'vs/base/common/event';
10+
import { removeTrailingPathSeparator } from 'vs/base/common/extpath';
1011
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
1112
import { normalize } from 'vs/base/common/path';
1213
import { URI } from 'vs/base/common/uri';
@@ -66,14 +67,21 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
6667

6768
private universalWatcher: AbstractUniversalWatcherClient | undefined;
6869

69-
private readonly universalPathsToWatch: IUniversalWatchRequest[] = [];
70+
private readonly universalWatchRequests: IUniversalWatchRequest[] = [];
7071
private readonly universalWatchRequestDelayer = this._register(new ThrottledDelayer<void>(0));
7172

7273
private watchUniversal(resource: URI, opts: IWatchOptions): IDisposable {
7374

7475
// Add to list of paths to watch universally
75-
const pathToWatch: IUniversalWatchRequest = { path: this.toFilePath(resource), excludes: opts.excludes, includes: opts.includes, recursive: opts.recursive, filter: opts.filter, correlationId: opts.correlationId };
76-
const remove = insert(this.universalPathsToWatch, pathToWatch);
76+
const request: IUniversalWatchRequest = {
77+
path: this.toWatchPath(resource),
78+
excludes: opts.excludes,
79+
includes: opts.includes,
80+
recursive: opts.recursive,
81+
filter: opts.filter,
82+
correlationId: opts.correlationId
83+
};
84+
const remove = insert(this.universalWatchRequests, request);
7785

7886
// Trigger update
7987
this.refreshUniversalWatchers();
@@ -116,13 +124,13 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
116124
// Adjust for polling
117125
const usePolling = this.options?.watcher?.recursive?.usePolling;
118126
if (usePolling === true) {
119-
for (const request of this.universalPathsToWatch) {
127+
for (const request of this.universalWatchRequests) {
120128
if (isRecursiveWatchRequest(request)) {
121129
request.pollingInterval = this.options?.watcher?.recursive?.pollingInterval ?? 5000;
122130
}
123131
}
124132
} else if (Array.isArray(usePolling)) {
125-
for (const request of this.universalPathsToWatch) {
133+
for (const request of this.universalWatchRequests) {
126134
if (isRecursiveWatchRequest(request)) {
127135
if (usePolling.includes(request.path)) {
128136
request.pollingInterval = this.options?.watcher?.recursive?.pollingInterval ?? 5000;
@@ -132,7 +140,7 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
132140
}
133141

134142
// Ask to watch the provided paths
135-
return this.universalWatcher.watch(this.universalPathsToWatch);
143+
return this.universalWatcher.watch(this.universalWatchRequests);
136144
}
137145

138146
protected abstract createUniversalWatcher(
@@ -147,14 +155,21 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
147155

148156
private nonRecursiveWatcher: AbstractNonRecursiveWatcherClient | undefined;
149157

150-
private readonly nonRecursivePathsToWatch: INonRecursiveWatchRequest[] = [];
158+
private readonly nonRecursiveWatchRequests: INonRecursiveWatchRequest[] = [];
151159
private readonly nonRecursiveWatchRequestDelayer = this._register(new ThrottledDelayer<void>(0));
152160

153161
private watchNonRecursive(resource: URI, opts: IWatchOptions): IDisposable {
154162

155163
// Add to list of paths to watch non-recursively
156-
const pathToWatch: INonRecursiveWatchRequest = { path: this.toFilePath(resource), excludes: opts.excludes, includes: opts.includes, recursive: false, filter: opts.filter, correlationId: opts.correlationId };
157-
const remove = insert(this.nonRecursivePathsToWatch, pathToWatch);
164+
const request: INonRecursiveWatchRequest = {
165+
path: this.toWatchPath(resource),
166+
excludes: opts.excludes,
167+
includes: opts.includes,
168+
recursive: false,
169+
filter: opts.filter,
170+
correlationId: opts.correlationId
171+
};
172+
const remove = insert(this.nonRecursiveWatchRequests, request);
158173

159174
// Trigger update
160175
this.refreshNonRecursiveWatchers();
@@ -195,7 +210,7 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
195210
}
196211

197212
// Ask to watch the provided paths
198-
return this.nonRecursiveWatcher.watch(this.nonRecursivePathsToWatch);
213+
return this.nonRecursiveWatcher.watch(this.nonRecursiveWatchRequests);
199214
}
200215

201216
protected abstract createNonRecursiveWatcher(
@@ -221,4 +236,14 @@ export abstract class AbstractDiskFileSystemProvider extends Disposable implemen
221236
protected toFilePath(resource: URI): string {
222237
return normalize(resource.fsPath);
223238
}
239+
240+
private toWatchPath(resource: URI): string {
241+
const filePath = this.toFilePath(resource);
242+
243+
// Ensure to have any trailing path separators removed, otherwise
244+
// we may believe the path is not "real" and will convert every
245+
// event back to this form, which is not warranted.
246+
// See also https://github.com/microsoft/vscode/issues/210517
247+
return removeTrailingPathSeparator(filePath);
248+
}
224249
}

0 commit comments

Comments
 (0)