实现下载
This commit is contained in:
parent
ba126f651d
commit
2bf0d54f9b
@ -8,6 +8,9 @@
|
||||
"progress.initialization": "Initialization",
|
||||
"progress.build-module-tree": "Build Module Tree",
|
||||
"progress.download-digital-lsp": "Download Digital LSP",
|
||||
"progress.choose-best-download-source": "Choose Best Download Source",
|
||||
"progress.extract-digital-lsp": "Extract Digital LSP",
|
||||
"error.download-digital-lsp": "Fail to download digital lsp server, check your network and reload vscode. You can also visit following site and download manually: https://github.com/Digital-EDA/Digital-IDE/releases/tag/",
|
||||
"fail.save-file": "fail to save file",
|
||||
"click.join-qq-group": "Click the link to join the QQ group"
|
||||
}
|
@ -3,11 +3,14 @@
|
||||
"welcome.title": "感谢使用 Digital-IDE ❤️。您的支持将是我们最大的动力!😊",
|
||||
"welcome.star": "支持",
|
||||
"welcome.refuse": "拒绝",
|
||||
"progress.register-command": "(Digital IDE) 注册命令",
|
||||
"progress.active-lsp-server": "Activate LSP Server",
|
||||
"progress.initialization": "(Digital IDE) 初始化",
|
||||
"progress.register-command": "Digital IDE 注册命令",
|
||||
"progress.active-lsp-server": "Digital IDE 激活语言服务器",
|
||||
"progress.initialization": "Digital IDE 初始化",
|
||||
"progress.build-module-tree": "构建模块树",
|
||||
"progress.download-digital-lsp": "Download Digital LSP",
|
||||
"progress.download-digital-lsp": "下载 Digital IDE 语言服务器",
|
||||
"progress.choose-best-download-source": "选择最佳下载源",
|
||||
"progress.extract-digital-lsp": "解压 Digital LSP 语言服务器",
|
||||
"error.download-digital-lsp": "无法下载 Digital LSP 语言服务器,检查你的网络后重启 vscode,或者请手动去下方地址下载 https://github.com/Digital-EDA/Digital-IDE/releases/tag/",
|
||||
"fail.save-file": "保存文件失败",
|
||||
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
||||
}
|
@ -8,6 +8,9 @@
|
||||
"progress.initialization": "(Digital IDE) 初始化",
|
||||
"progress.build-module-tree": "構建模塊樹",
|
||||
"progress.download-digital-lsp": "Download Digital LSP",
|
||||
"progress.choose-best-download-source": "Choose Best Download Source",
|
||||
"progress.extract-digital-lsp": "Extract Digital LSP",
|
||||
"error.download-digital-lsp": "Fail to download digital lsp server, check your network and reload vscode",
|
||||
"fail.save-file": "保存文件失敗",
|
||||
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
||||
}
|
@ -12,7 +12,6 @@ import * as lspClient from './function/lsp-client';
|
||||
import { refreshArchTree } from './function/treeView';
|
||||
|
||||
|
||||
|
||||
async function registerCommand(context: vscode.ExtensionContext) {
|
||||
func.registerFunctionCommands(context);
|
||||
func.registerLsp(context);
|
||||
@ -44,7 +43,6 @@ async function launch(context: vscode.ExtensionContext) {
|
||||
title: t('progress.register-command')
|
||||
}, async () => {
|
||||
await registerCommand(context);
|
||||
|
||||
});
|
||||
|
||||
await lspClient.activate(context, versionString);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as os from 'os';
|
||||
import axios from 'axios';
|
||||
import { performance } from 'perf_hooks';
|
||||
|
||||
enum IPlatformSignature {
|
||||
x86Windows = 'windows_amd64',
|
||||
@ -51,3 +52,58 @@ export function getGithubDownloadLink(signature: string, version: string): strin
|
||||
export function getGiteeDownloadLink(signature: string, version: string): string {
|
||||
return `https://gitee.com/Digital-IDE/Digital-IDE/releases/download/${version}/digital-lsp_${version}_${signature}.tar.gz`;
|
||||
}
|
||||
|
||||
function measureRequestTimecost(url: string, timeout: number = 5): Promise<number> {
|
||||
let s = performance.now();
|
||||
|
||||
let timer: NodeJS.Timeout;
|
||||
|
||||
const responseP = axios.get(url, { responseType: 'stream' });
|
||||
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
// 设置超时计时器
|
||||
timer = setTimeout(() => {
|
||||
resolve(Infinity);
|
||||
}, timeout);
|
||||
|
||||
responseP.then(response => {
|
||||
// 清除超时计时器
|
||||
clearTimeout(timer);
|
||||
|
||||
const totalLength = response.headers['content-length'];
|
||||
if (totalLength > 0) {
|
||||
resolve(performance.now() - s);
|
||||
} else {
|
||||
resolve(Infinity);
|
||||
}
|
||||
}).catch(error => {
|
||||
// 清除超时计时器
|
||||
clearTimeout(timer);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function chooseBestDownloadSource(signature: string, version: string, timeout: number = 3000) {
|
||||
const links = [
|
||||
getGiteeDownloadLink(signature, version),
|
||||
getGithubDownloadLink(signature, version)
|
||||
];
|
||||
const pools: Promise<number>[] = [];
|
||||
for (const link of links) {
|
||||
pools.push(measureRequestTimecost(link, timeout));
|
||||
}
|
||||
let fastTc = Infinity;
|
||||
let fastTcIndex = -1;
|
||||
for (let i = 0; i < pools.length; ++ i) {
|
||||
const tc = await pools[i];
|
||||
if (tc < fastTc) {
|
||||
fastTc = tc;
|
||||
fastTcIndex = i;
|
||||
}
|
||||
}
|
||||
if (fastTcIndex == -1) {
|
||||
return links[0];
|
||||
}
|
||||
return links[fastTcIndex];
|
||||
}
|
@ -8,11 +8,13 @@ import {
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as zlib from 'zlib';
|
||||
import * as tar from 'tar';
|
||||
import { platform } from "os";
|
||||
import { IProgress, LspClient } from '../../global';
|
||||
import axios, { AxiosResponse } from "axios";
|
||||
import { getGiteeDownloadLink, getPlatformPlatformSignature } from "./cdn";
|
||||
|
||||
import { chooseBestDownloadSource, getGiteeDownloadLink, getGithubDownloadLink, getPlatformPlatformSignature } from "./cdn";
|
||||
import { hdlDir } from "../../hdlFs";
|
||||
|
||||
function getLspServerExecutionName() {
|
||||
const osname = platform();
|
||||
@ -23,9 +25,54 @@ function getLspServerExecutionName() {
|
||||
return 'digital-lsp';
|
||||
}
|
||||
|
||||
async function checkAndDownload(context: vscode.ExtensionContext, version: string): boolean {
|
||||
const { t } = vscode.l10n;
|
||||
function extractTarGz(filePath: string, outputDir: string): Promise<void> {
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
const inputStream = fs.createReadStream(filePath);
|
||||
const gunzip = zlib.createGunzip();
|
||||
const extract = tar.extract({
|
||||
cwd: outputDir, // 解压到指定目录
|
||||
});
|
||||
|
||||
inputStream.pipe(gunzip).pipe(extract);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
extract.on('finish', resolve);
|
||||
extract.on('error', reject);
|
||||
})
|
||||
}
|
||||
|
||||
function streamDownload(context: vscode.ExtensionContext, progress: vscode.Progress<IProgress>, response: AxiosResponse<any, any>): Promise<string> {
|
||||
const totalLength = response.headers['content-length'];
|
||||
const totalSize = parseInt(totalLength);
|
||||
let downloadSize = 0;
|
||||
const savePath = context.asAbsolutePath(
|
||||
path.join('resources', 'dide-lsp', 'server', 'tmp.tar.gz')
|
||||
);
|
||||
const fileStream = fs.createWriteStream(savePath);
|
||||
response.data.pipe(fileStream);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
response.data.on('data', (chunk: Buffer) => {
|
||||
downloadSize += chunk.length;
|
||||
let precent = Math.ceil(downloadSize / totalSize * 100);
|
||||
let increment = chunk.length / totalSize * 100;
|
||||
progress.report({ message: `${precent}%`, increment });
|
||||
});
|
||||
|
||||
fileStream.on('finish', () => {
|
||||
console.log('finish download');
|
||||
fileStream.close();
|
||||
resolve(savePath);
|
||||
});
|
||||
|
||||
fileStream.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
async function checkAndDownload(context: vscode.ExtensionContext, version: string): Promise<boolean> {
|
||||
const versionFolderPath = context.asAbsolutePath(
|
||||
path.join('resources', 'dide-lsp', 'server', version)
|
||||
);
|
||||
@ -35,41 +82,53 @@ async function checkAndDownload(context: vscode.ExtensionContext, version: strin
|
||||
return true;
|
||||
}
|
||||
|
||||
await vscode.window.withProgress({
|
||||
const serverFolder = context.asAbsolutePath(
|
||||
path.join('resources', 'dide-lsp', 'server')
|
||||
);
|
||||
hdlDir.mkdir(serverFolder);
|
||||
|
||||
return await downloadLsp(context, version, versionFolderPath);
|
||||
}
|
||||
|
||||
export async function downloadLsp(context: vscode.ExtensionContext, version: string, versionFolderPath: string): Promise<boolean> {
|
||||
const { t } = vscode.l10n;
|
||||
|
||||
const downloadLink = await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: t('progress.choose-best-download-source')
|
||||
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||
let timeout = 3000;
|
||||
let reportInterval = 500;
|
||||
const intervalHandler = setInterval(() => {
|
||||
progress.report({ increment: reportInterval / timeout * 100 });
|
||||
}, reportInterval);
|
||||
|
||||
const signature = getPlatformPlatformSignature().toString();
|
||||
const downloadLink = await chooseBestDownloadSource(signature, version, timeout);
|
||||
clearInterval(intervalHandler);
|
||||
return downloadLink
|
||||
});
|
||||
|
||||
const tarGzFilePath = await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: t('progress.download-digital-lsp')
|
||||
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||
progress.report({ increment: 0 });
|
||||
const signature = getPlatformPlatformSignature().toString();
|
||||
const downloadLink = getGiteeDownloadLink(signature, version);
|
||||
const response = await axios.get(downloadLink, { responseType: 'stream' });
|
||||
|
||||
return await streamDownload(context, progress, response);
|
||||
});
|
||||
|
||||
function streamDownload(progress: vscode.Progress<IProgress>, response: AxiosResponse<any, any>): Promise<void> {
|
||||
const totalLength = response.headers['content-length'];
|
||||
const totalSize = parseInt(totalLength);
|
||||
let downloadSize = 0;
|
||||
const savePath = context.asAbsolutePath(
|
||||
path.join('resources', 'dide-lsp', 'server', 'tmp.tar.gz')
|
||||
);
|
||||
const fileStream = fs.createWriteStream(savePath);
|
||||
|
||||
response.data.on('data', (chunk: Buffer) => {
|
||||
downloadSize += chunk.length;
|
||||
let increment = Math.ceil(downloadSize / totalSize * 100);
|
||||
progress.report({ message: t('progress.download-digital-lsp'), increment });
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
fileStream.on('finish', () => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
fileStream.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: t('progress.extract-digital-lsp')
|
||||
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||
if (fs.existsSync(tarGzFilePath)) {
|
||||
console.log('check finish, begin to extract');
|
||||
await extractTarGz(tarGzFilePath, versionFolderPath);
|
||||
} else {
|
||||
vscode.window.showErrorMessage(t('error.download-digital-lsp') + version);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -77,10 +136,9 @@ async function checkAndDownload(context: vscode.ExtensionContext, version: strin
|
||||
export async function activate(context: vscode.ExtensionContext, version: string) {
|
||||
await checkAndDownload(context, version);
|
||||
|
||||
|
||||
const lspServerName = getLspServerExecutionName();
|
||||
const lspServerPath = context.asAbsolutePath(
|
||||
path.join('resources', 'dide-lsp', 'server', lspServerName)
|
||||
path.join('resources', 'dide-lsp', 'server', version, lspServerName)
|
||||
);
|
||||
|
||||
if (fs.existsSync(lspServerPath)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user