diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewModel.ts b/src/vs/workbench/parts/files/browser/views/explorerViewModel.ts index b3a15cc0dd1bb5150ffd4b9a837f058123cbaa86..8826ec024dfa29dfa4ce4475886574e85d930191 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewModel.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewModel.ts @@ -6,6 +6,7 @@ import assert = require('vs/base/common/assert'); import types = require('vs/base/common/types'); import URI from 'vs/base/common/uri'; +import {isLinux} from 'vs/base/common/platform'; import paths = require('vs/base/common/paths'); import {guessMimeTypes} from 'vs/base/common/mime'; import {IFileStat} from 'vs/platform/files/common/files'; @@ -273,7 +274,7 @@ export class FileStat implements IFileStat { public find(resource: URI): FileStat { // Return if path found - if (resource.toString() === this.resource.toString()) { + if (this.fileResourceEquals(resource, this.resource)) { return this; } @@ -285,7 +286,7 @@ export class FileStat implements IFileStat { for (let i = 0; i < this.children.length; i++) { let child = this.children[i]; - if (resource.toString() === child.resource.toString()) { + if (this.fileResourceEquals(resource, child.resource)) { return child; } @@ -296,6 +297,15 @@ export class FileStat implements IFileStat { return null; //Unable to find } + + private fileResourceEquals(r1: URI, r2: URI) { + const identityEquals = (r1.toString() === r2.toString()); + if (isLinux || identityEquals) { + return identityEquals; + } + + return r1.toString().toLowerCase() === r2.toString().toLowerCase(); + } } /* A helper that can be used to show a placeholder when creating a new stat */ diff --git a/src/vs/workbench/parts/files/test/browser/viewModel.test.ts b/src/vs/workbench/parts/files/test/browser/viewModel.test.ts index 0b28a8e1774c7b1dae799a315088686278592a85..53899fe072e24625c2b36f69768aec8283ec946c 100644 --- a/src/vs/workbench/parts/files/test/browser/viewModel.test.ts +++ b/src/vs/workbench/parts/files/test/browser/viewModel.test.ts @@ -216,6 +216,32 @@ suite('Files - View Model', () => { assert.strictEqual(s1.find(toResource('/')), s1); }); + test("Find with mixed case", function() { + let d = new Date().getTime(); + + let s1 = createStat("/", "/", true, false, 8096, d, "text/plain"); + let s2 = createStat("/path", "path", true, false, 8096, d, "text/plain"); + let s3 = createStat("/path/to", "to", true, false, 8096, d, "text/plain"); + let s4 = createStat("/path/to/stat", "stat", true, false, 8096, d, "text/plain"); + + let child1 = createStat("/path/to/stat/foo", "foo", true, false, 8096, d, "text/plain"); + let child2 = createStat("/path/to/stat/foo/bar.html", "bar.html", false, false, 8096, d, "text/html"); + + s1.addChild(s2); + s2.addChild(s3); + s3.addChild(s4); + s4.addChild(child1); + child1.addChild(child2); + + if (isLinux) { // linux is case sensitive + assert.ok(!s1.find(toResource('/path/to/stat/Foo'))); + assert.ok(!s1.find(toResource('/Path/to/stat/foo/bar.html'))); + } else { + assert.ok(s1.find(toResource('/path/to/stat/Foo'))); + assert.ok(s1.find(toResource('/Path/to/stat/foo/bar.html'))); + } + }); + test("Validate File Name (For Create)", function() { let d = new Date().getTime(); let s = createStat("/path/to/stat", "sName", true, true, 8096, d, "text/plain"); diff --git a/src/vs/workbench/services/files/node/fileService.ts b/src/vs/workbench/services/files/node/fileService.ts index fa104c65a4c505614d52af0f13870bc59fa26a30..ef3be5934bce99d85e3de85921b58bdfbd63381d 100644 --- a/src/vs/workbench/services/files/node/fileService.ts +++ b/src/vs/workbench/services/files/node/fileService.ts @@ -636,6 +636,7 @@ export class StatResolver { } return new TPromise((c, e) => { + // Load children this.resolveChildren(this.resource.fsPath, absoluteTargetPaths, options && options.resolveSingleChildDescendants, (children) => { children = arrays.coalesce(children); // we dont want those null childs (could be permission denied when reading a child) @@ -706,7 +707,7 @@ export class StatResolver { let resolveFolderChildren = false; if (files.length === 1 && resolveSingleChildDescendants) { resolveFolderChildren = true; - } else if (childCount > 0 && absoluteTargetPaths && absoluteTargetPaths.some((targetPath) => targetPath.indexOf(fileResource.fsPath) === 0)) { + } else if (childCount > 0 && absoluteTargetPaths && absoluteTargetPaths.some((targetPath) => basePaths.isEqualOrParent(targetPath, fileResource.fsPath))) { resolveFolderChildren = true; } diff --git a/src/vs/workbench/services/files/test/node/resolver.test.ts b/src/vs/workbench/services/files/test/node/resolver.test.ts index e54f31475ff788eea6cde588a7bc63ddf8ee2bc1..d20d009f19fc219a2fced21df66ee4534f92ea0e 100644 --- a/src/vs/workbench/services/files/test/node/resolver.test.ts +++ b/src/vs/workbench/services/files/test/node/resolver.test.ts @@ -11,6 +11,7 @@ import assert = require('assert'); import {StatResolver} from 'vs/workbench/services/files/node/fileService'; import uri from 'vs/base/common/uri'; +import {isLinux} from 'vs/base/common/platform'; import utils = require('vs/workbench/services/files/test/node/utils'); function create(relativePath: string): StatResolver { @@ -106,6 +107,36 @@ suite('Stat Resolver', () => { .done(() => done(), done); }); + test('resolve directory - resolveTo single directory - mixed casing', function(done: () => void) { + let resolver = create('/'); + + resolver.resolve({ resolveTo: [toResource('other/Deep')] }).then(result => { + assert.ok(result); + assert.ok(result.children); + assert.ok(result.hasChildren); + assert.ok(result.isDirectory); + + let children = result.children; + assert.equal(children.length, 4); + + let other = utils.getByName(result, 'other'); + assert.ok(other); + assert.ok(other.hasChildren); + + let deep = utils.getByName(other, 'deep'); + if (isLinux) { // Linux has case sensitive file system + assert.ok(deep); + assert.ok(deep.hasChildren); + assert.ok(!deep.children); // not resolved because we got instructed to resolve other/Deep with capital D + } else { + assert.ok(deep); + assert.ok(deep.hasChildren); + assert.equal(deep.children.length, 4); + } + }) + .done(() => done(), done); + }); + test('resolve directory - resolveTo multiple directories', function(done: () => void) { let resolver = create('/');