mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-19 18:14:50 +01:00
Merge remote-tracking branch 'origin/master' into alex/node-modules-webpack
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
2020-12-15T15:34:44.634Z
|
||||
2020-12-17T07:59:24.060Z
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||
echo -n $VSCODE_QUALITY > .build/quality
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
exit 1
|
||||
displayName: Check RestoreCache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -34,9 +13,19 @@ steps:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: Compilation
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Download compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
displayName: Extract compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
cat << EOF > ~/.netrc
|
||||
machine github.com
|
||||
login vscode
|
||||
@@ -66,6 +55,7 @@ steps:
|
||||
|
||||
- script: |
|
||||
echo -n $(VSCODE_ARCH) > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||
echo -n $VSCODE_QUALITY > .build/quality
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
exit 1
|
||||
displayName: Check RestoreCache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -34,6 +13,17 @@ steps:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: Compilation
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Download compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
displayName: Extract compilation output
|
||||
|
||||
- task: Docker@1
|
||||
displayName: "Pull image"
|
||||
inputs:
|
||||
@@ -45,7 +35,6 @@ steps:
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
|
||||
cat << EOF > ~/.netrc
|
||||
machine github.com
|
||||
login vscode
|
||||
@@ -69,6 +58,7 @@ steps:
|
||||
|
||||
- script: |
|
||||
echo -n "alpine" > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||
echo -n $VSCODE_QUALITY > .build/quality
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
exit 1
|
||||
displayName: Check RestoreCache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -34,6 +13,17 @@ steps:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: Compilation
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Download compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
displayName: Extract compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
cat << EOF > ~/.netrc
|
||||
@@ -59,6 +49,7 @@ steps:
|
||||
|
||||
- script: |
|
||||
echo -n $(VSCODE_ARCH) > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
@@ -76,12 +67,19 @@ steps:
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
if [ -z "$CC" ] || [ -z "$CXX" ]
|
||||
then
|
||||
export npm_config_arch=$(NPM_ARCH)
|
||||
|
||||
if [ -z "$CC" ] || [ -z "$CXX" ]; then
|
||||
export CC=$(which gcc-5)
|
||||
export CXX=$(which g++-5)
|
||||
fi
|
||||
export npm_config_arch=$(NPM_ARCH)
|
||||
|
||||
if [ "$VSCODE_ARCH" == "x64" ]; then
|
||||
export VSCODE_REMOTE_CC=$(which gcc-4.8)
|
||||
export VSCODE_REMOTE_CXX=$(which g++-4.8)
|
||||
export VSCODE_REMOTE_NODE_GYP=$(which node-gyp)
|
||||
fi
|
||||
|
||||
for i in {1..3}; do # try 3 times, for Terrapin
|
||||
yarn --frozen-lockfile && break
|
||||
if [ $i -eq 3 ]; then
|
||||
@@ -103,16 +101,6 @@ steps:
|
||||
vstsFeed: "npm-vscode"
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
export CC=$(which gcc-4.8)
|
||||
export CXX=$(which g++-4.8)
|
||||
export npm_config_node_gyp=$(which node-gyp)
|
||||
cd remote && rm -rf node_modules/
|
||||
yarn
|
||||
displayName: Rebuild remote modules with gcc-4.8
|
||||
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/mixin
|
||||
|
||||
@@ -8,8 +8,8 @@ schedules:
|
||||
- master
|
||||
|
||||
variables:
|
||||
? ${{ if and(eq(variables['VSCODE_PUBLISH'], ''), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'BatchedCI'))) }}
|
||||
: VSCODE_PUBLISH: "false"
|
||||
${{ if and(eq(variables['VSCODE_PUBLISH'], ''), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'BatchedCI'))) }}:
|
||||
VSCODE_PUBLISH: "false"
|
||||
|
||||
resources:
|
||||
containers:
|
||||
|
||||
@@ -1,36 +1,17 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||
echo -n $VSCODE_QUALITY > .build/quality
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flag
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
dryRun: true
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: AzureKeyVault@1
|
||||
displayName: "Azure Key Vault: Get Secrets"
|
||||
inputs:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -43,22 +24,22 @@ steps:
|
||||
git config user.email "vscode@microsoft.com"
|
||||
git config user.name "VSCode"
|
||||
displayName: Prepare tooling
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
git pull --no-rebase https://github.com/$(VSCODE_MIXIN_REPO).git $(node -p "require('./package.json').distro")
|
||||
displayName: Merge distro
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
npx https://aka.ms/enablesecurefeed standAlone
|
||||
displayName: Switch to Terrapin packages
|
||||
timeoutInMinutes: 5
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
condition: and(succeeded(), eq(variables['ENABLE_TERRAPIN'], 'true'))
|
||||
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $(VSCODE_ARCH) > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
@@ -66,15 +47,22 @@ steps:
|
||||
keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock"
|
||||
targetfolder: "**/node_modules, !**/node_modules/**/node_modules"
|
||||
vstsFeed: "npm-vscode"
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
if [ -z "$CC" ] || [ -z "$CXX" ]
|
||||
then
|
||||
export npm_config_arch=$(NPM_ARCH)
|
||||
|
||||
if [ -z "$CC" ] || [ -z "$CXX" ]; then
|
||||
export CC=$(which gcc-5)
|
||||
export CXX=$(which g++-5)
|
||||
fi
|
||||
|
||||
if [ "$VSCODE_ARCH" == "x64" ]; then
|
||||
export VSCODE_REMOTE_CC=$(which gcc-4.8)
|
||||
export VSCODE_REMOTE_CXX=$(which g++-4.8)
|
||||
export VSCODE_REMOTE_NODE_GYP=$(which node-gyp)
|
||||
fi
|
||||
|
||||
for i in {1..3}; do # try 3 times, for Terrapin
|
||||
yarn --frozen-lockfile && break
|
||||
if [ $i -eq 3 ]; then
|
||||
@@ -87,21 +75,20 @@ steps:
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: ".build/arch, .build/terrapin, build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock"
|
||||
targetfolder: "**/node_modules, !**/node_modules/**/node_modules"
|
||||
vstsFeed: "npm-vscode"
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
# Mixin must run before optimize, because the CSS loader will inline small SVGs
|
||||
- script: |
|
||||
set -e
|
||||
node build/azure-pipelines/mixin
|
||||
displayName: Mix in quality
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -111,14 +98,13 @@ steps:
|
||||
yarn gulp minify-vscode-reh
|
||||
yarn gulp minify-vscode-reh-web
|
||||
displayName: Compile
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
|
||||
node build/azure-pipelines/upload-sourcemaps
|
||||
displayName: Upload sourcemaps
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -126,13 +112,16 @@ steps:
|
||||
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
|
||||
node build/azure-pipelines/common/createBuild.js $VERSION
|
||||
displayName: Create build
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
# we gotta tarball everything in order to preserve file permissions
|
||||
- script: |
|
||||
set -e
|
||||
tar -czf $(Build.ArtifactStagingDirectory)/compilation.tar.gz .build out-*
|
||||
displayName: Compress compilation artifact
|
||||
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
targetPath: $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
artifactName: Compilation
|
||||
displayName: Publish compilation artifact
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flag
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -36,7 +31,9 @@ steps:
|
||||
displayName: Merge distro
|
||||
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $(VSCODE_ARCH) > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
steps:
|
||||
- script: |
|
||||
mkdir -p .build
|
||||
echo -n $BUILD_SOURCEVERSION > .build/commit
|
||||
echo -n $VSCODE_QUALITY > .build/quality
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare compilation cache flag
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
exit 1
|
||||
displayName: Check RestoreCache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -34,6 +13,17 @@ steps:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: Compilation
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Download compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz
|
||||
displayName: Extract compilation output
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
cat << EOF > ~/.netrc
|
||||
@@ -59,6 +49,7 @@ steps:
|
||||
|
||||
- script: |
|
||||
echo -n "web" > .build/arch
|
||||
echo -n $ENABLE_TERRAPIN > .build/terrapin
|
||||
displayName: Prepare yarn cache flag
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
|
||||
@@ -1,25 +1,4 @@
|
||||
steps:
|
||||
- powershell: |
|
||||
mkdir .build -ea 0
|
||||
"$env:BUILD_SOURCEVERSION" | Out-File -Encoding ascii -NoNewLine .build\commit
|
||||
"$env:VSCODE_QUALITY" | Out-File -Encoding ascii -NoNewLine .build\quality
|
||||
"$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin
|
||||
displayName: Prepare compilation cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: "build/.cachesalt, .build/commit, .build/quality, .build/terrapin"
|
||||
targetfolder: ".build, out-build, out-vscode-min, out-vscode-reh-min, out-vscode-reh-web-min"
|
||||
vstsFeed: "npm-vscode"
|
||||
platformIndependent: true
|
||||
alias: "Compilation"
|
||||
|
||||
- powershell: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
exit 1
|
||||
displayName: Check RestoreCache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.18.3"
|
||||
@@ -39,6 +18,18 @@ steps:
|
||||
azureSubscription: "vscode-builds-subscription"
|
||||
KeyVaultName: vscode
|
||||
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: Compilation
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
displayName: Download compilation output
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
exec { tar --force-local -xzf $(Build.ArtifactStagingDirectory)/compilation.tar.gz }
|
||||
displayName: Extract compilation output
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -62,6 +53,7 @@ steps:
|
||||
|
||||
- powershell: |
|
||||
"$(VSCODE_ARCH)" | Out-File -Encoding ascii -NoNewLine .build\arch
|
||||
"$env:ENABLE_TERRAPIN" | Out-File -Encoding ascii -NoNewLine .build\terrapin
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
|
||||
@@ -34,7 +34,14 @@ function yarnInstall(location, opts) {
|
||||
yarnInstall('extensions'); // node modules shared by all extensions
|
||||
|
||||
if (!(process.platform === 'win32' && (process.arch === 'arm64' || process.env['npm_config_arch'] === 'arm64'))) {
|
||||
yarnInstall('remote'); // node modules used by vscode server
|
||||
const env = { ...process.env };
|
||||
if (process.env['VSCODE_REMOTE_CC']) { env['CC'] = process.env['VSCODE_REMOTE_CC']; }
|
||||
if (process.env['VSCODE_REMOTE_CXX']) { env['CXX'] = process.env['VSCODE_REMOTE_CXX']; }
|
||||
if (process.env['VSCODE_REMOTE_NODE_GYP']) { env['npm_config_node_gyp'] = process.env['VSCODE_REMOTE_NODE_GYP']; }
|
||||
|
||||
console.log('remote yarn install env', JSON.stringify(env, undefined, ' '));
|
||||
|
||||
yarnInstall('remote', { env }); // node modules used by vscode server
|
||||
yarnInstall('remote/web'); // node modules used by vscode web
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { localize } from 'vs/nls';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { IStateService } from 'vs/platform/state/node/state';
|
||||
import { app, JumpListCategory } from 'electron';
|
||||
import { app, JumpListCategory, JumpListItem } from 'electron';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { getBaseLabel, getPathLabel, splitName } from 'vs/base/common/labels';
|
||||
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
|
||||
@@ -350,34 +350,40 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
|
||||
this.removeRecentlyOpened(toRemove);
|
||||
|
||||
// Add entries
|
||||
jumpList.push({
|
||||
type: 'custom',
|
||||
name: localize('recentFolders', "Recent Workspaces"),
|
||||
items: coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => {
|
||||
const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri;
|
||||
const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome);
|
||||
let hasWorkspaces = false;
|
||||
const items: JumpListItem[] = coalesce(this.getRecentlyOpened().workspaces.slice(0, 7 /* limit number of entries here */).map(recent => {
|
||||
const workspace = isRecentWorkspace(recent) ? recent.workspace : recent.folderUri;
|
||||
const title = recent.label ? splitName(recent.label).name : this.getSimpleWorkspaceLabel(workspace, this.environmentService.untitledWorkspacesHome);
|
||||
|
||||
let description;
|
||||
let args;
|
||||
if (isSingleFolderWorkspaceIdentifier(workspace)) {
|
||||
description = localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService));
|
||||
args = `--folder-uri "${workspace.toString()}"`;
|
||||
} else {
|
||||
description = localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService));
|
||||
args = `--file-uri "${workspace.configPath.toString()}"`;
|
||||
}
|
||||
let description;
|
||||
let args;
|
||||
if (isSingleFolderWorkspaceIdentifier(workspace)) {
|
||||
description = localize('folderDesc', "{0} {1}", getBaseLabel(workspace), getPathLabel(dirname(workspace), this.environmentService));
|
||||
args = `--folder-uri "${workspace.toString()}"`;
|
||||
} else {
|
||||
hasWorkspaces = true;
|
||||
description = localize('workspaceDesc', "{0} {1}", getBaseLabel(workspace.configPath), getPathLabel(dirname(workspace.configPath), this.environmentService));
|
||||
args = `--file-uri "${workspace.configPath.toString()}"`;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'task',
|
||||
title: title.substr(0, 255), // Windows seems to be picky around the length of entries
|
||||
description: description.substr(0, 255), // (see https://github.com/microsoft/vscode/issues/111177)
|
||||
program: process.execPath,
|
||||
args,
|
||||
iconPath: 'explorer.exe', // simulate folder icon
|
||||
iconIndex: 0
|
||||
};
|
||||
}))
|
||||
});
|
||||
return {
|
||||
type: 'task',
|
||||
title: title.substr(0, 255), // Windows seems to be picky around the length of entries
|
||||
description: description.substr(0, 255), // (see https://github.com/microsoft/vscode/issues/111177)
|
||||
program: process.execPath,
|
||||
args,
|
||||
iconPath: 'explorer.exe', // simulate folder icon
|
||||
iconIndex: 0
|
||||
};
|
||||
}));
|
||||
|
||||
if (items.length > 0) {
|
||||
jumpList.push({
|
||||
type: 'custom',
|
||||
name: hasWorkspaces ? localize('recentFoldersAndWorkspaces', "Recent Folders & Workspaces") : localize('recentFolders', "Recent Folders"),
|
||||
items
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Recent
|
||||
|
||||
@@ -16,10 +16,19 @@ import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { raceCancellation } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
@extHostCustomer
|
||||
export class MainThreadFileSystemEventService {
|
||||
|
||||
static readonly MementoKeyAdditionalEdits = `file.particpants.additionalEdits`;
|
||||
|
||||
private readonly _listener = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
@@ -27,7 +36,11 @@ export class MainThreadFileSystemEventService {
|
||||
@IFileService fileService: IFileService,
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
|
||||
@IBulkEditService bulkEditService: IBulkEditService,
|
||||
@IProgressService progressService: IProgressService
|
||||
@IProgressService progressService: IProgressService,
|
||||
@IDialogService dialogService: IDialogService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ILogService logService: ILogService,
|
||||
@IEnvironmentService envService: IEnvironmentService
|
||||
) {
|
||||
|
||||
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService);
|
||||
@@ -92,9 +105,60 @@ export class MainThreadFileSystemEventService {
|
||||
return;
|
||||
}
|
||||
|
||||
const edit = reviveWorkspaceEditDto2(data);
|
||||
await bulkEditService.apply(edit, { undoRedoGroupId });
|
||||
const needsConfirmation = data.edit.edits.some(edit => edit.metadata?.needsConfirmation);
|
||||
let showPreview = storageService.getBoolean(MainThreadFileSystemEventService.MementoKeyAdditionalEdits, StorageScope.GLOBAL);
|
||||
|
||||
if (envService.extensionTestsLocationURI) {
|
||||
// don't show dialog in tests
|
||||
showPreview = false;
|
||||
}
|
||||
|
||||
if (showPreview === undefined) {
|
||||
// show a user facing message
|
||||
|
||||
let message: string;
|
||||
if (data.extensionNames.length === 1) {
|
||||
message = localize('ask.1', "Extension '{0}' wants to make additional edits for this file operation.", data.extensionNames[0]);
|
||||
} else {
|
||||
message = localize('ask.N', "{0} extensions want to make additional edits for this file operation.", data.extensionNames.length);
|
||||
}
|
||||
|
||||
if (needsConfirmation) {
|
||||
// edit which needs confirmation -> always show dialog
|
||||
const answer = await dialogService.show(Severity.Info, message, [localize('preview', "Show Preview"), localize('cancel', "Skip additional edits")], { cancelId: 1 });
|
||||
showPreview = true;
|
||||
if (answer.choice === 1) {
|
||||
// no additional edits wanted
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// choice
|
||||
const answer = await dialogService.show(Severity.Info, message,
|
||||
[localize('ok', "OK"), localize('preview', "Show Preview"), localize('cancel', "Skip additional edits")],
|
||||
{
|
||||
cancelId: 2,
|
||||
checkbox: { label: localize('again', "Don't ask again") }
|
||||
}
|
||||
);
|
||||
if (answer.choice === 2) {
|
||||
// no additional edits wanted, don't persist cancel option
|
||||
return;
|
||||
}
|
||||
showPreview = answer.choice === 1;
|
||||
if (answer.checkboxChecked /* && answer.choice !== 2 */) {
|
||||
storageService.store(MainThreadFileSystemEventService.MementoKeyAdditionalEdits, showPreview, StorageScope.GLOBAL, StorageTarget.USER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logService.info('[onWill-handler] applying additional workspace edit from extensions', data.extensionNames);
|
||||
|
||||
await bulkEditService.apply(
|
||||
reviveWorkspaceEditDto2(data.edit),
|
||||
{ undoRedoGroupId, showPreview }
|
||||
);
|
||||
}
|
||||
|
||||
private _progressLabel(operation: FileOperation): string {
|
||||
switch (operation) {
|
||||
case FileOperation.CREATE:
|
||||
@@ -119,10 +183,21 @@ export class MainThreadFileSystemEventService {
|
||||
dispose(): void {
|
||||
this._listener.dispose();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
registerAction2(class ResetMemento extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'files.participants.resetChoice',
|
||||
title: localize('label', "Reset choice for 'File operation needs preview'"),
|
||||
f1: true
|
||||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor) {
|
||||
accessor.get(IStorageService).remove(MainThreadFileSystemEventService.MementoKeyAdditionalEdits, StorageScope.GLOBAL);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
|
||||
id: 'files',
|
||||
|
||||
@@ -1157,9 +1157,14 @@ export interface SourceTargetPair {
|
||||
target: UriComponents;
|
||||
}
|
||||
|
||||
export interface IWillRunFileOperationParticipation {
|
||||
edit: IWorkspaceEditDto;
|
||||
extensionNames: string[]
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemEventServiceShape {
|
||||
$onFileEvent(events: FileSystemEvents): void;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<IWorkspaceEditDto | undefined>;
|
||||
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<IWillRunFileOperationParticipation | undefined>;
|
||||
$onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IRelativePattern, parse } from 'vs/base/common/glob';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import type * as vscode from 'vscode';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, SourceTargetPair, IWorkspaceEditDto } from './extHost.protocol';
|
||||
import { ExtHostFileSystemEventServiceShape, FileSystemEvents, IMainContext, SourceTargetPair, IWorkspaceEditDto, IWillRunFileOperationParticipation } from './extHost.protocol';
|
||||
import * as typeConverter from './extHostTypeConverters';
|
||||
import { Disposable, WorkspaceEdit } from './extHostTypes';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -177,7 +177,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
};
|
||||
}
|
||||
|
||||
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<IWorkspaceEditDto | undefined> {
|
||||
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<IWillRunFileOperationParticipation | undefined> {
|
||||
switch (operation) {
|
||||
case FileOperation.MOVE:
|
||||
return await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token);
|
||||
@@ -189,8 +189,9 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async _fireWillEvent<E extends IWaitUntil>(emitter: AsyncEmitter<E>, data: Omit<E, 'waitUntil'>, timeout: number, token: CancellationToken): Promise<IWorkspaceEditDto | undefined> {
|
||||
private async _fireWillEvent<E extends IWaitUntil>(emitter: AsyncEmitter<E>, data: Omit<E, 'waitUntil'>, timeout: number, token: CancellationToken): Promise<IWillRunFileOperationParticipation | undefined> {
|
||||
|
||||
const extensionNames = new Set<string>();
|
||||
const edits: WorkspaceEdit[] = [];
|
||||
|
||||
await emitter.fireAsync(data, token, async (thenable, listener) => {
|
||||
@@ -199,10 +200,11 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
const result = await Promise.resolve(thenable);
|
||||
if (result instanceof WorkspaceEdit) {
|
||||
edits.push(result);
|
||||
extensionNames.add((<IExtensionListener<E>>listener).extension.displayName ?? (<IExtensionListener<E>>listener).extension.identifier.value);
|
||||
}
|
||||
|
||||
if (Date.now() - now > timeout) {
|
||||
this._logService.warn('SLOW file-participant', (<IExtensionListener<E>>listener).extension?.identifier);
|
||||
this._logService.warn('SLOW file-participant', (<IExtensionListener<E>>listener).extension.identifier);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -220,6 +222,6 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
|
||||
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
|
||||
dto.edits = dto.edits.concat(edits);
|
||||
}
|
||||
return dto;
|
||||
return { edit: dto, extensionNames: Array.from(extensionNames) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +49,17 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
tooltip: nls.localize('remove', "Remove from Recently Opened")
|
||||
};
|
||||
|
||||
private readonly dirtyRecentlyOpened: IQuickInputButton = {
|
||||
private readonly dirtyRecentlyOpenedFolder: IQuickInputButton = {
|
||||
iconClass: 'dirty-workspace ' + Codicon.closeDirty.classNames,
|
||||
tooltip: nls.localize('dirtyRecentlyOpened', "Workspace With Dirty Files"),
|
||||
tooltip: nls.localize('dirtyRecentlyOpenedFolder', "Folder With Unsaved Files"),
|
||||
alwaysVisible: true
|
||||
};
|
||||
|
||||
private readonly dirtyRecentlyOpenedWorkspace: IQuickInputButton = {
|
||||
...this.dirtyRecentlyOpenedFolder,
|
||||
tooltip: nls.localize('dirtyRecentlyOpenedWorkspace', "Workspace With Unsaved Files"),
|
||||
};
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@@ -77,7 +82,9 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
const recentlyOpened = await this.workspacesService.getRecentlyOpened();
|
||||
const dirtyWorkspacesAndFolders = await this.workspacesService.getDirtyWorkspaces();
|
||||
|
||||
// Identify all folders and workspaces with dirty files
|
||||
let hasWorkspaces = false;
|
||||
|
||||
// Identify all folders and workspaces with unsaved files
|
||||
const dirtyFolders = new ResourceMap<boolean>();
|
||||
const dirtyWorkspaces = new ResourceMap<IWorkspaceIdentifier>();
|
||||
for (const dirtyWorkspace of dirtyWorkspacesAndFolders) {
|
||||
@@ -85,6 +92,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
dirtyFolders.set(dirtyWorkspace, true);
|
||||
} else {
|
||||
dirtyWorkspaces.set(dirtyWorkspace.configPath, dirtyWorkspace);
|
||||
hasWorkspaces = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +104,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
recentFolders.set(recent.folderUri, true);
|
||||
} else {
|
||||
recentWorkspaces.set(recent.workspace.configPath, recent.workspace);
|
||||
hasWorkspaces = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +133,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
|
||||
let keyMods: IKeyMods | undefined;
|
||||
|
||||
const workspaceSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('workspaces', "workspaces") };
|
||||
const workspaceSeparator: IQuickPickSeparator = { type: 'separator', label: hasWorkspaces ? nls.localize('workspacesAndFolders', "folders & workspaces") : nls.localize('folders', "folders") };
|
||||
const fileSeparator: IQuickPickSeparator = { type: 'separator', label: nls.localize('files', "files") };
|
||||
const picks = [workspaceSeparator, ...workspacePicks, fileSeparator, ...filePicks];
|
||||
|
||||
@@ -143,13 +152,14 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
context.removeItem();
|
||||
}
|
||||
|
||||
// Dirty Workspace
|
||||
else if (context.button === this.dirtyRecentlyOpened) {
|
||||
// Dirty Folder/Workspace
|
||||
else if (context.button === this.dirtyRecentlyOpenedFolder || context.button === this.dirtyRecentlyOpenedWorkspace) {
|
||||
const isDirtyWorkspace = context.button === this.dirtyRecentlyOpenedWorkspace;
|
||||
const result = await this.dialogService.confirm({
|
||||
type: 'question',
|
||||
title: nls.localize('dirtyWorkspace', "Workspace with Dirty Files"),
|
||||
message: nls.localize('dirtyWorkspaceConfirm', "Do you want to open the workspace to review the dirty files?"),
|
||||
detail: nls.localize('dirtyWorkspaceConfirmDetail', "Workspaces with dirty files cannot be removed until all dirty files have been saved or reverted.")
|
||||
title: isDirtyWorkspace ? nls.localize('dirtyWorkspace', "Workspace with Unsaved Files") : nls.localize('dirtyFolder', "Folder with Unsaved Files"),
|
||||
message: isDirtyWorkspace ? nls.localize('dirtyWorkspaceConfirm', "Do you want to open the workspace to review the unsaved files?") : nls.localize('dirtyFolderConfirm', "Do you want to open the folder to review the unsaved files?"),
|
||||
detail: isDirtyWorkspace ? nls.localize('dirtyWorkspaceConfirmDetail', "Workspaces with unsaved files cannot be removed until all unsaved files have been saved or reverted.") : nls.localize('dirtyFolderConfirmDetail', "Folders with unsaved files cannot be removed until all unsaved files have been saved or reverted.")
|
||||
});
|
||||
|
||||
if (result.confirmed) {
|
||||
@@ -170,6 +180,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
let iconClasses: string[];
|
||||
let fullLabel: string | undefined;
|
||||
let resource: URI | undefined;
|
||||
let isWorkspace = false;
|
||||
|
||||
// Folder
|
||||
if (isRecentFolder(recent)) {
|
||||
@@ -185,6 +196,7 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
iconClasses = getIconClasses(this.modelService, this.modeService, resource, FileKind.ROOT_FOLDER);
|
||||
openable = { workspaceUri: resource };
|
||||
fullLabel = recent.label || this.labelService.getWorkspaceLabel(recent.workspace, { verbose: true });
|
||||
isWorkspace = true;
|
||||
}
|
||||
|
||||
// File
|
||||
@@ -200,9 +212,9 @@ abstract class BaseOpenRecentAction extends Action {
|
||||
return {
|
||||
iconClasses,
|
||||
label: name,
|
||||
ariaLabel: isDirty ? nls.localize('recentDirtyAriaLabel', "{0}, dirty workspace", name) : name,
|
||||
ariaLabel: isDirty ? isWorkspace ? nls.localize('recentDirtyWorkspaceAriaLabel', "{0}, workspace with unsaved changes", name) : nls.localize('recentDirtyFolderAriaLabel', "{0}, folder with unsaved changes", name) : name,
|
||||
description: parentPath,
|
||||
buttons: isDirty ? [this.dirtyRecentlyOpened] : [this.removeFromRecentlyOpened],
|
||||
buttons: isDirty ? [isWorkspace ? this.dirtyRecentlyOpenedWorkspace : this.dirtyRecentlyOpenedFolder] : [this.removeFromRecentlyOpened],
|
||||
openable,
|
||||
resource
|
||||
};
|
||||
|
||||
@@ -114,7 +114,7 @@ export class CloseWorkspaceAction extends Action {
|
||||
|
||||
async run(): Promise<void> {
|
||||
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
this.notificationService.info(nls.localize('noWorkspaceOpened', "There is currently no workspace opened in this instance to close."));
|
||||
this.notificationService.info(nls.localize('noWorkspaceOrFolderOpened', "There is currently no workspace or folder opened in this instance to close."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ export class SaveWorkspaceAsAction extends Action {
|
||||
export class DuplicateWorkspaceInNewWindowAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.duplicateWorkspaceInNewWindow';
|
||||
static readonly LABEL = nls.localize('duplicateWorkspaceInNewWindow', "Duplicate Workspace in New Window");
|
||||
static readonly LABEL = nls.localize('duplicateWorkspaceInNewWindow', "Duplicate As Workspace in New Window");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -259,7 +259,7 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(AddRootFolderAction),
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(GlobalRemoveRootFolderAction), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseWorkspaceAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory, EmptyWorkspaceSupportContext);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(SaveWorkspaceAsAction), 'Workspaces: Save Workspace As...', workspacesCategory, EmptyWorkspaceSupportContext);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateWorkspaceInNewWindowAction), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateWorkspaceInNewWindowAction), 'Workspaces: Duplicate As Workspace in New Window', workspacesCategory);
|
||||
|
||||
// --- Menu Registration
|
||||
|
||||
|
||||
@@ -330,8 +330,8 @@ import { isStandalone } from 'vs/base/browser/browser';
|
||||
nls.localize('activeFolderLong', "`\${activeFolderLong}`: the full path of the folder the file is contained in (e.g. /Users/Development/myFolder/myFileFolder)."),
|
||||
nls.localize('folderName', "`\${folderName}`: name of the workspace folder the file is contained in (e.g. myFolder)."),
|
||||
nls.localize('folderPath', "`\${folderPath}`: file path of the workspace folder the file is contained in (e.g. /Users/Development/myFolder)."),
|
||||
nls.localize('rootName', "`\${rootName}`: name of the workspace (e.g. myFolder or myWorkspace)."),
|
||||
nls.localize('rootPath', "`\${rootPath}`: file path of the workspace (e.g. /Users/Development/myWorkspace)."),
|
||||
nls.localize('rootName', "`\${rootName}`: name of the opened workspace or folder (e.g. myFolder or myWorkspace)."),
|
||||
nls.localize('rootPath', "`\${rootPath}`: file path of the opened workspace or folder (e.g. /Users/Development/myWorkspace)."),
|
||||
nls.localize('appName', "`\${appName}`: e.g. VS Code."),
|
||||
nls.localize('remoteName', "`\${remoteName}`: e.g. SSH"),
|
||||
nls.localize('dirty', "`\${dirty}`: a dirty indicator if the active editor is dirty."),
|
||||
|
||||
@@ -339,7 +339,7 @@ export const STATUS_BAR_FOREGROUND = registerColor('statusBar.foreground', {
|
||||
dark: '#FFFFFF',
|
||||
light: '#FFFFFF',
|
||||
hc: '#FFFFFF'
|
||||
}, nls.localize('statusBarForeground', "Status bar foreground color when a workspace is opened. The status bar is shown in the bottom of the window."));
|
||||
}, nls.localize('statusBarForeground', "Status bar foreground color when a workspace or folder is opened. The status bar is shown in the bottom of the window."));
|
||||
|
||||
export const STATUS_BAR_NO_FOLDER_FOREGROUND = registerColor('statusBar.noFolderForeground', {
|
||||
dark: STATUS_BAR_FOREGROUND,
|
||||
@@ -351,7 +351,7 @@ export const STATUS_BAR_BACKGROUND = registerColor('statusBar.background', {
|
||||
dark: '#007ACC',
|
||||
light: '#007ACC',
|
||||
hc: null
|
||||
}, nls.localize('statusBarBackground', "Status bar background color when a workspace is opened. The status bar is shown in the bottom of the window."));
|
||||
}, nls.localize('statusBarBackground', "Status bar background color when a workspace or folder is opened. The status bar is shown in the bottom of the window."));
|
||||
|
||||
export const STATUS_BAR_NO_FOLDER_BACKGROUND = registerColor('statusBar.noFolderBackground', {
|
||||
dark: '#68217A',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import 'vs/css!./media/repl';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { IAction, IActionViewItem, Action, Separator } from 'vs/base/common/actions';
|
||||
import { IAction, IActionViewItem } from 'vs/base/common/actions';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -26,7 +26,7 @@ import { memoize } from 'vs/base/common/decorators';
|
||||
import { dispose, IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { IDebugService, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL, IDebugSession, State, IReplElement, IDebugConfiguration, REPL_VIEW_ID, CONTEXT_MULTI_SESSION_REPL } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, DEBUG_SCHEME, CONTEXT_IN_DEBUG_REPL, IDebugSession, State, IReplElement, IDebugConfiguration, REPL_VIEW_ID, CONTEXT_MULTI_SESSION_REPL, CONTEXT_DEBUG_STATE, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { HistoryNavigator } from 'vs/base/common/history';
|
||||
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
|
||||
import { createAndBindHistoryNavigationWidgetScopedContextKeyService } from 'vs/platform/browser/contextScopedHistoryWidget';
|
||||
@@ -60,7 +60,8 @@ import { EDITOR_FONT_DEFAULTS, EditorOption } from 'vs/editor/common/config/edit
|
||||
import { MOUSE_CURSOR_TEXT_CSS_CLASS_NAME } from 'vs/base/browser/ui/mouseCursor/mouseCursor';
|
||||
import { ReplFilter, ReplFilterState, ReplFilterActionViewItem } from 'vs/workbench/contrib/debug/browser/replFilter';
|
||||
import { debugConsoleClearAll, debugConsoleEvaluationPrompt } from 'vs/workbench/contrib/debug/browser/debugIcons';
|
||||
import { registerAction2, MenuId, MenuItemAction, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { registerAction2, MenuId, Action2, IMenuService, IMenu } from 'vs/platform/actions/common/actions';
|
||||
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -100,6 +101,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
private filterState: ReplFilterState;
|
||||
private filterActionViewItem: ReplFilterActionViewItem | undefined;
|
||||
private multiSessionRepl: IContextKey<boolean>;
|
||||
private menu: IMenu;
|
||||
|
||||
constructor(
|
||||
options: IViewPaneOptions,
|
||||
@@ -114,14 +116,16 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService private readonly textResourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IClipboardService private readonly clipboardService: IClipboardService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IMenuService menuService: IMenuService
|
||||
) {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
|
||||
this.menu = menuService.createMenu(MenuId.DebugConsoleContext, contextKeyService);
|
||||
this._register(this.menu);
|
||||
this.history = new HistoryNavigator(JSON.parse(this.storageService.get(HISTORY_STORAGE_KEY, StorageScope.WORKSPACE, '[]')), 50);
|
||||
this.filter = new ReplFilter();
|
||||
this.filterState = new ReplFilterState(this);
|
||||
@@ -459,6 +463,14 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
this.replInput.layout({ width: width - 30, height: replInputHeight });
|
||||
}
|
||||
|
||||
collapseAll(): void {
|
||||
this.tree.collapseAll();
|
||||
}
|
||||
|
||||
getReplInput(): CodeEditorWidget {
|
||||
return this.replInput;
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
setTimeout(() => this.replInput.focus(), 0);
|
||||
}
|
||||
@@ -615,44 +627,12 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
|
||||
private onContextMenu(e: ITreeContextMenuEvent<IReplElement>): void {
|
||||
const actions: IAction[] = [];
|
||||
actions.push(new Action('debug.replCopy', localize('copy', "Copy"), undefined, true, async () => {
|
||||
const nativeSelection = window.getSelection();
|
||||
if (nativeSelection) {
|
||||
await this.clipboardService.writeText(nativeSelection.toString());
|
||||
}
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Action('workbench.debug.action.copyAll', localize('copyAll', "Copy All"), undefined, true, async () => {
|
||||
await this.clipboardService.writeText(this.getVisibleContent());
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Action('debug.replPaste', localize('paste', "Paste"), undefined, this.debugService.state !== State.Inactive, async () => {
|
||||
const clipboardText = await this.clipboardService.readText();
|
||||
if (clipboardText) {
|
||||
this.replInput.setValue(this.replInput.getValue().concat(clipboardText));
|
||||
this.replInput.focus();
|
||||
const model = this.replInput.getModel();
|
||||
const lineNumber = model ? model.getLineCount() : 0;
|
||||
const column = model?.getLineMaxColumn(lineNumber);
|
||||
if (typeof lineNumber === 'number' && typeof column === 'number') {
|
||||
this.replInput.setPosition({ lineNumber, column });
|
||||
}
|
||||
}
|
||||
}));
|
||||
actions.push(new Separator());
|
||||
actions.push(new Action('debug.collapseRepl', localize('collapse', "Collapse All"), undefined, true, () => {
|
||||
this.tree.collapseAll();
|
||||
this.replInput.focus();
|
||||
return Promise.resolve();
|
||||
}));
|
||||
actions.push(new Separator());
|
||||
actions.push(this.instantiationService.createInstance(MenuItemAction, clearReplCommand, undefined, {}));
|
||||
|
||||
const actionsDisposable = createAndFillInContextMenuActions(this.menu, { arg: e.element, shouldForwardArgs: false }, actions);
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => e.anchor,
|
||||
getActions: () => actions,
|
||||
getActionsContext: () => e.element,
|
||||
onHide: () => dispose(actions)
|
||||
onHide: () => dispose(actionsDisposable)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -864,26 +844,123 @@ registerAction2(class extends ViewAction<Repl> {
|
||||
}
|
||||
});
|
||||
|
||||
const clearReplCommand = {
|
||||
id: 'workbench.debug.panel.action.clearReplAction',
|
||||
viewId: REPL_VIEW_ID,
|
||||
title: localize('clearRepl', "Clear Console"),
|
||||
f1: true,
|
||||
icon: debugConsoleClearAll,
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
when: ContextKeyEqualsExpr.create('view', REPL_VIEW_ID),
|
||||
order: 30
|
||||
}
|
||||
};
|
||||
registerAction2(class extends ViewAction<Repl> {
|
||||
constructor() {
|
||||
super(clearReplCommand);
|
||||
super({
|
||||
id: 'workbench.debug.panel.action.clearReplAction',
|
||||
viewId: REPL_VIEW_ID,
|
||||
title: localize('clearRepl', "Clear Console"),
|
||||
f1: true,
|
||||
icon: debugConsoleClearAll,
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
when: ContextKeyEqualsExpr.create('view', REPL_VIEW_ID),
|
||||
order: 30
|
||||
}, {
|
||||
id: MenuId.DebugConsoleContext,
|
||||
group: 'z_commands',
|
||||
order: 20
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
runInView(_accessor: ServicesAccessor, view: Repl) {
|
||||
runInView(_accessor: ServicesAccessor, view: Repl): void {
|
||||
view.clearRepl();
|
||||
aria.status(localize('debugConsoleCleared', "Debug console was cleared"));
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends ViewAction<Repl> {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'debug.collapseRepl',
|
||||
title: localize('collapse', "Collapse All"),
|
||||
viewId: REPL_VIEW_ID,
|
||||
menu: {
|
||||
id: MenuId.DebugConsoleContext,
|
||||
group: 'z_commands',
|
||||
order: 10
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
runInView(_accessor: ServicesAccessor, view: Repl): void {
|
||||
view.collapseAll();
|
||||
view.focus();
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends ViewAction<Repl> {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'debug.replPaste',
|
||||
title: localize('paste', "Paste"),
|
||||
viewId: REPL_VIEW_ID,
|
||||
precondition: CONTEXT_DEBUG_STATE.notEqualsTo(getStateLabel(State.Inactive)),
|
||||
menu: {
|
||||
id: MenuId.DebugConsoleContext,
|
||||
group: '2_cutcopypaste',
|
||||
order: 30
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async runInView(accessor: ServicesAccessor, view: Repl): Promise<void> {
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const clipboardText = await clipboardService.readText();
|
||||
if (clipboardText) {
|
||||
const replInput = view.getReplInput();
|
||||
replInput.setValue(replInput.getValue().concat(clipboardText));
|
||||
view.focus();
|
||||
const model = replInput.getModel();
|
||||
const lineNumber = model ? model.getLineCount() : 0;
|
||||
const column = model?.getLineMaxColumn(lineNumber);
|
||||
if (typeof lineNumber === 'number' && typeof column === 'number') {
|
||||
replInput.setPosition({ lineNumber, column });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends ViewAction<Repl> {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.debug.action.copyAll',
|
||||
title: localize('copyAll', "Copy All"),
|
||||
viewId: REPL_VIEW_ID,
|
||||
menu: {
|
||||
id: MenuId.DebugConsoleContext,
|
||||
group: '2_cutcopypaste',
|
||||
order: 20
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async runInView(accessor: ServicesAccessor, view: Repl): Promise<void> {
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
await clipboardService.writeText(view.getVisibleContent());
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'debug.replCopy',
|
||||
title: localize('copy', "Copy"),
|
||||
menu: {
|
||||
id: MenuId.DebugConsoleContext,
|
||||
group: '2_cutcopypaste',
|
||||
order: 10
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const nativeSelection = window.getSelection();
|
||||
if (nativeSelection) {
|
||||
await clipboardService.writeText(nativeSelection.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -198,8 +198,8 @@ const hotExitConfiguration: IConfigurationPropertySchema = platform.isNative ?
|
||||
'default': HotExitConfiguration.ON_EXIT,
|
||||
'markdownEnumDescriptions': [
|
||||
nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with dirty files.'),
|
||||
nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of workspaces with unsaved files can be accessed via `File > Open Recent > More...`'),
|
||||
nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of workspaces with unsaved files can be accessed via `File > Open Recent > More...`')
|
||||
nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`'),
|
||||
nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`')
|
||||
],
|
||||
'description': nls.localize('hotExit', "Controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE)
|
||||
} : {
|
||||
|
||||
@@ -89,7 +89,7 @@ export class WorkspaceWatcher extends Disposable {
|
||||
if (msg.indexOf('ENOSPC') >= 0) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('enospcError', "Unable to watch for file changes in this large workspace. Please follow the instructions link to resolve this issue."),
|
||||
localize('enospcError', "Unable to watch for file changes in this large workspace folder. Please follow the instructions link to resolve this issue."),
|
||||
[{
|
||||
label: localize('learnMore', "Instructions"),
|
||||
run: () => this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=867693'))
|
||||
|
||||
@@ -164,8 +164,6 @@ export class SCMStatusController implements IWorkbenchContribution {
|
||||
}
|
||||
|
||||
private renderActivityCount(): void {
|
||||
this.badgeDisposable.clear();
|
||||
|
||||
const countBadgeType = this.configurationService.getValue<'all' | 'focused' | 'off'>('scm.countBadge');
|
||||
|
||||
let count = 0;
|
||||
@@ -180,7 +178,7 @@ export class SCMStatusController implements IWorkbenchContribution {
|
||||
const badge = new NumberBadge(count, num => localize('scmPendingChangesBadge', '{0} pending changes', num));
|
||||
this.badgeDisposable.value = this.activityService.showViewActivity(VIEW_PANE_ID, { badge, clazz: 'scm-viewlet-label' });
|
||||
} else {
|
||||
this.badgeDisposable.clear();
|
||||
this.badgeDisposable.value = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -840,7 +840,7 @@ configurationRegistry.registerConfiguration({
|
||||
'search.seedOnFocus': {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: nls.localize('search.seedOnFocus', "Update workspace search query to the editor's selected text when focusing the search view. This happens either on click or when triggering the `workbench.views.search.focus` command.")
|
||||
description: nls.localize('search.seedOnFocus', "Update the search query to the editor's selected text when focusing the search view. This happens either on click or when triggering the `workbench.views.search.focus` command.")
|
||||
},
|
||||
'search.searchOnTypeDebouncePeriod': {
|
||||
type: 'number',
|
||||
|
||||
@@ -378,7 +378,7 @@ export class QueryBuilder {
|
||||
});
|
||||
} else {
|
||||
// No root folder with name
|
||||
const searchPathNotFoundError = nls.localize('search.noWorkspaceWithName', "No folder in workspace with name: {0}", searchPathRoot);
|
||||
const searchPathNotFoundError = nls.localize('search.noWorkspaceWithName', "Workspace folder does not exist: {0}", searchPathRoot);
|
||||
throw new Error(searchPathNotFoundError);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1977,7 +1977,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
||||
await this.computeTasksForSingleConfig(workspaceFolder, configuration.config, runSource, custom, customizedTasks.byIdentifier, TaskConfig.TaskConfigSource.WorkspaceFile);
|
||||
const engine = configuration.config ? TaskConfig.ExecutionEngine.from(configuration.config) : ExecutionEngine.Terminal;
|
||||
if (engine === ExecutionEngine.Process) {
|
||||
this.notificationService.warn(nls.localize('TaskSystem.versionWorkspaceFile', 'Only tasks version 2.0.0 permitted in .codeworkspace.'));
|
||||
this.notificationService.warn(nls.localize('TaskSystem.versionWorkspaceFile', 'Only tasks version 2.0.0 permitted in workspace configuration files.'));
|
||||
return this.emptyWorkspaceTaskResults(workspaceFolder);
|
||||
}
|
||||
return { workspaceFolder, set: { tasks: custom }, configurations: customizedTasks, hasErrors: configuration.hasParseErrors };
|
||||
|
||||
@@ -32,7 +32,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.none' }, "Start without an editor."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePage' }, "Open the Welcome page (default)."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.readme' }, "Open the README when opening a folder that contains one, fallback to 'welcomePage' otherwise."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.newUntitledFile' }, "Open a new untitled file (only applies when opening an empty workspace)."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.newUntitledFile' }, "Open a new untitled file (only applies when opening an empty window)."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePageInEmptyWorkbench' }, "Open the Welcome page when opening an empty workbench."),],
|
||||
...(product.quality !== 'stable'
|
||||
? [localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.gettingStarted' }, "Open the Getting Started page (experimental).")]
|
||||
|
||||
@@ -246,7 +246,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
|
||||
jsonEditor;
|
||||
|
||||
if (!this.workspaceSettingsResource) {
|
||||
this.notificationService.info(nls.localize('openFolderFirst', "Open a folder first to create workspace settings"));
|
||||
this.notificationService.info(nls.localize('openFolderFirst', "Open a folder or workspace first to create workspace or folder settings."));
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user