Merge from vscode 63d257f78a
(#5240)
This commit is contained in:
Родитель
8cda364210
Коммит
9b90400abd
|
@ -400,6 +400,7 @@
|
|||
"statusBar.noFolderBackground": "#10192c",
|
||||
"statusBar.debuggingBackground": "#10192c",
|
||||
// "statusBar.foreground": "",
|
||||
"statusBarItem.hostBackground": "#0063a5",
|
||||
"statusBarItem.prominentBackground": "#0063a5",
|
||||
"statusBarItem.prominentHoverBackground": "#0063a5dd",
|
||||
// "statusBarItem.activeBackground": "",
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
"include": "./hc_black_defaults.json",
|
||||
"colors": {
|
||||
"selection.background": "#008000",
|
||||
"editor.selectionBackground": "#FFFFFF"
|
||||
"editor.selectionBackground": "#FFFFFF",
|
||||
"statusBarItem.hostBackground": "#00000000"
|
||||
},
|
||||
"tokenColors": [
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"editor.foreground": "#FFFFFF",
|
||||
"editorIndentGuide.background": "#FFFFFF",
|
||||
"editorIndentGuide.activeBackground": "#FFFFFF",
|
||||
"statusBarItem.hostBackground": "#00000000",
|
||||
"sideBarTitle.foreground": "#FFFFFF"
|
||||
},
|
||||
"settings": [
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"statusBar.background": "#423523",
|
||||
"statusBar.debuggingBackground": "#423523",
|
||||
"statusBar.noFolderBackground": "#423523",
|
||||
"statusBarItem.hostBackground": "#6e583b",
|
||||
"activityBar.background": "#221a0f",
|
||||
"activityBar.foreground": "#d3af86",
|
||||
"sideBar.background": "#362712",
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"statusBar.debuggingBackground": "#505050",
|
||||
"statusBar.noFolderBackground": "#505050",
|
||||
"titleBar.activeBackground": "#505050",
|
||||
"statusBarItem.hostBackground": "#3655b5",
|
||||
"activityBar.background": "#353535",
|
||||
"activityBar.foreground": "#ffffff",
|
||||
"activityBarBadge.background": "#3655b5",
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
"statusBar.background": "#414339",
|
||||
"statusBar.noFolderBackground": "#414339",
|
||||
"statusBar.debuggingBackground": "#75715E",
|
||||
"statusBarItem.hostBackground": "#AC6218",
|
||||
"activityBar.background": "#272822",
|
||||
"activityBar.foreground": "#f8f8f2",
|
||||
"activityBar.dropBackground": "#414339",
|
||||
|
|
|
@ -516,6 +516,7 @@
|
|||
"statusBar.background": "#705697",
|
||||
"statusBar.noFolderBackground": "#705697",
|
||||
"statusBar.debuggingBackground": "#705697",
|
||||
"statusBarItem.hostBackground": "#4e3c69",
|
||||
"activityBar.background": "#EDEDF5",
|
||||
"activityBar.foreground": "#705697",
|
||||
"activityBarBadge.background": "#705697",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"sideBar.background": "#330000",
|
||||
"statusBar.background": "#700000",
|
||||
"statusBar.noFolderBackground": "#700000",
|
||||
"statusBarItem.hostBackground": "#c33",
|
||||
"editorGroupHeader.tabsBackground": "#330000",
|
||||
"titleBar.activeBackground": "#770000",
|
||||
"titleBar.inactiveBackground": "#772222",
|
||||
|
|
|
@ -448,6 +448,7 @@
|
|||
"statusBar.background": "#00212B",
|
||||
"statusBar.debuggingBackground": "#00212B",
|
||||
"statusBar.noFolderBackground": "#00212B",
|
||||
"statusBarItem.hostBackground": "#2AA19899",
|
||||
"statusBarItem.prominentBackground": "#003847",
|
||||
"statusBarItem.prominentHoverBackground": "#003847",
|
||||
// "statusBarItem.activeBackground": "",
|
||||
|
|
|
@ -447,6 +447,7 @@
|
|||
"statusBar.debuggingBackground": "#EEE8D5",
|
||||
"statusBar.noFolderBackground": "#EEE8D5",
|
||||
// "statusBar.foreground": "",
|
||||
"statusBarItem.hostBackground": "#AC9D57",
|
||||
"statusBarItem.prominentBackground": "#DDD6C1",
|
||||
"statusBarItem.prominentHoverBackground": "#DDD6C199",
|
||||
// "statusBarItem.activeBackground": "",
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"debugToolBar.background": "#001c40",
|
||||
"titleBar.activeBackground": "#001126",
|
||||
"statusBar.background": "#001126",
|
||||
"statusBarItem.hostBackground": "#0e639c",
|
||||
"statusBar.noFolderBackground": "#001126",
|
||||
"statusBar.debuggingBackground": "#001126",
|
||||
"activityBar.background": "#001733",
|
||||
|
|
|
@ -141,13 +141,13 @@ export const enum ProtocolConstants {
|
|||
*/
|
||||
AcknowledgeTimeoutTime = 10000, // 10 seconds
|
||||
/**
|
||||
* Send at least a message every 30s for keep alive reasons.
|
||||
* Send at least a message every 5s for keep alive reasons.
|
||||
*/
|
||||
KeepAliveTime = 30000, // 30 seconds
|
||||
KeepAliveTime = 5000, // 5 seconds
|
||||
/**
|
||||
* If there is no message received for 60 seconds, consider the connection closed...
|
||||
* If there is no message received for 10 seconds, consider the connection closed...
|
||||
*/
|
||||
KeepAliveTimeoutTime = 60000, // 60 seconds
|
||||
KeepAliveTimeoutTime = 10000, // 10 seconds
|
||||
/**
|
||||
* If there is no reconnection within this time-frame, consider the connection permanently closed...
|
||||
*/
|
||||
|
|
|
@ -1770,7 +1770,9 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
|
|||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IOpenerService private readonly openerService: IOpenerService,
|
||||
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService
|
||||
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
|
||||
) {
|
||||
super(id, label, 'extension-action');
|
||||
this.recommendations = recommendations;
|
||||
|
@ -1787,17 +1789,30 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
|
|||
let installPromises: Promise<any>[] = [];
|
||||
let model = new PagedModel(pager);
|
||||
for (let i = 0; i < pager.total; i++) {
|
||||
installPromises.push(model.resolve(i, CancellationToken.None).then(e => {
|
||||
return this.extensionWorkbenchService.install(e).then(undefined, err => {
|
||||
console.error(err);
|
||||
return promptDownloadManually(e.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", e.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
|
||||
});
|
||||
}));
|
||||
installPromises.push(model.resolve(i, CancellationToken.None).then(e => this.installExtension(e)));
|
||||
}
|
||||
return Promise.all(installPromises);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async installExtension(extension: IExtension): Promise<void> {
|
||||
try {
|
||||
if (extension.local && extension.gallery) {
|
||||
if (isUIExtension(extension.local.manifest, this.configurationService)) {
|
||||
await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(extension.gallery);
|
||||
return;
|
||||
} else if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
await this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(extension.gallery);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await this.extensionWorkbenchService.install(extension);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class InstallRecommendedExtensionAction extends Action {
|
||||
|
|
|
@ -274,22 +274,26 @@ export class RemoteFileDialog {
|
|||
});
|
||||
|
||||
this.filePickBox.onDidChangeValue(async value => {
|
||||
// onDidChangeValue can also be triggered by the auto complete, so if it looks like the auto complete, don't do anything
|
||||
if (this.isChangeFromUser()) {
|
||||
// If the user has just entered more bad path, don't change anything
|
||||
if (!equalsIgnoreCase(value, this.constructFullUserPath()) && !this.isBadSubpath(value)) {
|
||||
this.filePickBox.validationMessage = undefined;
|
||||
const valueUri = this.remoteUriFrom(this.trimTrailingSlash(this.filePickBox.value));
|
||||
let updated: UpdateResult = UpdateResult.NotUpdated;
|
||||
if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), valueUri, true)) {
|
||||
updated = await this.tryUpdateItems(value, this.remoteUriFrom(this.filePickBox.value));
|
||||
try {
|
||||
// onDidChangeValue can also be triggered by the auto complete, so if it looks like the auto complete, don't do anything
|
||||
if (this.isChangeFromUser()) {
|
||||
// If the user has just entered more bad path, don't change anything
|
||||
if (!equalsIgnoreCase(value, this.constructFullUserPath()) && !this.isBadSubpath(value)) {
|
||||
this.filePickBox.validationMessage = undefined;
|
||||
const valueUri = this.remoteUriFrom(this.trimTrailingSlash(this.filePickBox.value));
|
||||
let updated: UpdateResult = UpdateResult.NotUpdated;
|
||||
if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), valueUri, true)) {
|
||||
updated = await this.tryUpdateItems(value, this.remoteUriFrom(this.filePickBox.value));
|
||||
}
|
||||
if (updated === UpdateResult.NotUpdated) {
|
||||
this.setActiveItems(value);
|
||||
}
|
||||
} else {
|
||||
this.filePickBox.activeItems = [];
|
||||
}
|
||||
if (updated === UpdateResult.NotUpdated) {
|
||||
this.setActiveItems(value);
|
||||
}
|
||||
} else {
|
||||
this.filePickBox.activeItems = [];
|
||||
}
|
||||
} catch {
|
||||
// Since any text can be entered in the input box, there is potential for error causing input. If this happens, do nothing.
|
||||
}
|
||||
});
|
||||
this.filePickBox.onDidHide(() => {
|
||||
|
@ -331,12 +335,13 @@ export class RemoteFileDialog {
|
|||
this.filePickBox.busy = true;
|
||||
let resolveValue: URI | undefined;
|
||||
let navigateValue: URI | undefined;
|
||||
const trimmedPickBoxValue = ((this.filePickBox.value.length > 1) && this.endsWithSlash(this.filePickBox.value)) ? this.filePickBox.value.substr(0, this.filePickBox.value.length - 1) : this.filePickBox.value;
|
||||
const inputUri = this.remoteUriFrom(trimmedPickBoxValue);
|
||||
const inputUriDirname = resources.dirname(inputUri);
|
||||
let inputUri: URI | undefined;
|
||||
let inputUriDirname: URI | undefined;
|
||||
let stat: IFileStat | undefined;
|
||||
let statDirname: IFileStat | undefined;
|
||||
try {
|
||||
inputUri = resources.removeTrailingPathSeparator(this.remoteUriFrom(this.filePickBox.value));
|
||||
inputUriDirname = resources.dirname(inputUri);
|
||||
statDirname = await this.fileService.resolve(inputUriDirname);
|
||||
stat = await this.fileService.resolve(inputUri);
|
||||
} catch (e) {
|
||||
|
@ -363,17 +368,18 @@ export class RemoteFileDialog {
|
|||
}
|
||||
}
|
||||
|
||||
if (resolveValue) {
|
||||
resolveValue = this.addPostfix(resolveValue);
|
||||
|
||||
if (navigateValue) {
|
||||
// Try to navigate into the folder.
|
||||
await this.updateItems(navigateValue, true, this.trailing);
|
||||
} else {
|
||||
if (resolveValue) {
|
||||
resolveValue = this.addPostfix(resolveValue);
|
||||
}
|
||||
if (await this.validate(resolveValue)) {
|
||||
this.filePickBox.busy = false;
|
||||
return resolveValue;
|
||||
}
|
||||
} else if (navigateValue) {
|
||||
// Try to navigate into the folder.
|
||||
await this.updateItems(navigateValue, true, this.trailing);
|
||||
} else {
|
||||
// validation error. Path does not exist.
|
||||
}
|
||||
this.filePickBox.busy = false;
|
||||
return undefined;
|
||||
|
@ -575,7 +581,12 @@ export class RemoteFileDialog {
|
|||
});
|
||||
}
|
||||
|
||||
private async validate(uri: URI): Promise<boolean> {
|
||||
private async validate(uri: URI | undefined): Promise<boolean> {
|
||||
if (uri === undefined) {
|
||||
this.filePickBox.validationMessage = nls.localize('remoteFileDialog.invalidPath', 'Please enter a valid path.');
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
let stat: IFileStat | undefined;
|
||||
let statDirname: IFileStat | undefined;
|
||||
try {
|
||||
|
|
|
@ -9,6 +9,7 @@ import { realpathSync } from 'vs/base/node/extpath';
|
|||
import { IExtensionHostProfile, IExtensionService, ProfileSegmentId, ProfileSession } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export class ExtensionHostProfiler {
|
||||
|
||||
|
@ -30,7 +31,9 @@ export class ExtensionHostProfiler {
|
|||
private distill(profile: Profile, extensions: IExtensionDescription[]): IExtensionHostProfile {
|
||||
let searchTree = TernarySearchTree.forPaths<IExtensionDescription>();
|
||||
for (let extension of extensions) {
|
||||
searchTree.set(realpathSync(extension.extensionLocation.fsPath), extension);
|
||||
if (extension.extensionLocation.scheme === Schemas.file) {
|
||||
searchTree.set(realpathSync(extension.extensionLocation.fsPath), extension);
|
||||
}
|
||||
}
|
||||
|
||||
let nodes = profile.nodes;
|
||||
|
|
|
@ -338,8 +338,9 @@ export class FileService extends Disposable implements IFileService {
|
|||
// but to the same length. This is a compromise we take to avoid having to produce checksums of
|
||||
// the file content for comparison which would be much slower to compute.
|
||||
if (
|
||||
options && typeof options.mtime === 'number' && typeof options.etag === 'string' &&
|
||||
options.etag !== ETAG_DISABLED && options.mtime < stat.mtime && options.etag !== etag({ mtime: options.mtime /* not using stat.mtime for a reason, see above */, size: stat.size })
|
||||
options && typeof options.mtime === 'number' && typeof options.etag === 'string' && options.etag !== ETAG_DISABLED &&
|
||||
typeof stat.mtime === 'number' && typeof stat.size === 'number' &&
|
||||
options.mtime < stat.mtime && options.etag !== etag({ mtime: options.mtime /* not using stat.mtime for a reason, see above */, size: stat.size })
|
||||
) {
|
||||
throw new FileOperationError(localize('fileModifiedError', "File Modified Since"), FileOperationResult.FILE_MODIFIED_SINCE, options);
|
||||
}
|
||||
|
@ -496,7 +497,7 @@ export class FileService extends Disposable implements IFileService {
|
|||
}
|
||||
|
||||
// Return early if file not modified since (unless disabled)
|
||||
if (options && options.etag !== ETAG_DISABLED && options.etag === stat.etag) {
|
||||
if (options && typeof options.etag === 'string' && options.etag !== ETAG_DISABLED && options.etag === stat.etag) {
|
||||
throw new FileOperationError(localize('fileNotModifiedError', "File not modified since"), FileOperationResult.FILE_NOT_MODIFIED_SINCE, options);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { getPathFromAmdModule } from 'vs/base/common/amd';
|
|||
import { copy, rimraf, symlink, RimRafMode, rimrafSync } from 'vs/base/node/pfs';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { existsSync, statSync, readdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, mkdirSync } from 'fs';
|
||||
import { FileOperation, FileOperationEvent, IFileStat, FileOperationResult, FileSystemProviderCapabilities, FileChangeType, IFileChange, FileChangesEvent, FileOperationError, etag } from 'vs/platform/files/common/files';
|
||||
import { FileOperation, FileOperationEvent, IFileStat, FileOperationResult, FileSystemProviderCapabilities, FileChangeType, IFileChange, FileChangesEvent, FileOperationError, etag, IStat } from 'vs/platform/files/common/files';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
|
@ -62,6 +62,8 @@ export class TestDiskFileSystemProvider extends DiskFileSystemProvider {
|
|||
|
||||
totalBytesRead: number = 0;
|
||||
|
||||
private invalidStatSize: boolean;
|
||||
|
||||
private _testCapabilities: FileSystemProviderCapabilities;
|
||||
get capabilities(): FileSystemProviderCapabilities {
|
||||
if (!this._testCapabilities) {
|
||||
|
@ -82,6 +84,20 @@ export class TestDiskFileSystemProvider extends DiskFileSystemProvider {
|
|||
this._testCapabilities = capabilities;
|
||||
}
|
||||
|
||||
setInvalidStatSize(disabled: boolean): void {
|
||||
this.invalidStatSize = disabled;
|
||||
}
|
||||
|
||||
async stat(resource: URI): Promise<IStat> {
|
||||
const res = await super.stat(resource);
|
||||
|
||||
if (this.invalidStatSize) {
|
||||
res.size = String(res.size) as any; // for https://github.com/Microsoft/vscode/issues/72909
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number> {
|
||||
const bytesRead = await super.read(fd, pos, data, offset, length);
|
||||
|
||||
|
@ -1049,6 +1065,24 @@ suite('Disk File Service', () => {
|
|||
assert.equal(fileProvider.totalBytesRead, 0);
|
||||
});
|
||||
|
||||
test('readFile - FILE_NOT_MODIFIED_SINCE does not fire wrongly - https://github.com/Microsoft/vscode/issues/72909', async () => {
|
||||
setCapabilities(fileProvider, FileSystemProviderCapabilities.FileOpenReadWriteClose);
|
||||
fileProvider.setInvalidStatSize(true);
|
||||
|
||||
const resource = URI.file(join(testDir, 'index.html'));
|
||||
|
||||
await service.readFile(resource);
|
||||
|
||||
let error: FileOperationError | undefined = undefined;
|
||||
try {
|
||||
await service.readFile(resource, { etag: undefined });
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
assert.ok(!error);
|
||||
});
|
||||
|
||||
test('readFile - FILE_NOT_MODIFIED_SINCE - unbuffered', async () => {
|
||||
setCapabilities(fileProvider, FileSystemProviderCapabilities.FileReadWrite);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче