实现下载
This commit is contained in:
parent
ba126f651d
commit
2bf0d54f9b
@ -8,6 +8,9 @@
|
|||||||
"progress.initialization": "Initialization",
|
"progress.initialization": "Initialization",
|
||||||
"progress.build-module-tree": "Build Module Tree",
|
"progress.build-module-tree": "Build Module Tree",
|
||||||
"progress.download-digital-lsp": "Download Digital LSP",
|
"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",
|
"fail.save-file": "fail to save file",
|
||||||
"click.join-qq-group": "Click the link to join the QQ group"
|
"click.join-qq-group": "Click the link to join the QQ group"
|
||||||
}
|
}
|
@ -3,11 +3,14 @@
|
|||||||
"welcome.title": "感谢使用 Digital-IDE ❤️。您的支持将是我们最大的动力!😊",
|
"welcome.title": "感谢使用 Digital-IDE ❤️。您的支持将是我们最大的动力!😊",
|
||||||
"welcome.star": "支持",
|
"welcome.star": "支持",
|
||||||
"welcome.refuse": "拒绝",
|
"welcome.refuse": "拒绝",
|
||||||
"progress.register-command": "(Digital IDE) 注册命令",
|
"progress.register-command": "Digital IDE 注册命令",
|
||||||
"progress.active-lsp-server": "Activate LSP Server",
|
"progress.active-lsp-server": "Digital IDE 激活语言服务器",
|
||||||
"progress.initialization": "(Digital IDE) 初始化",
|
"progress.initialization": "Digital IDE 初始化",
|
||||||
"progress.build-module-tree": "构建模块树",
|
"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": "保存文件失败",
|
"fail.save-file": "保存文件失败",
|
||||||
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
||||||
}
|
}
|
@ -8,6 +8,9 @@
|
|||||||
"progress.initialization": "(Digital IDE) 初始化",
|
"progress.initialization": "(Digital IDE) 初始化",
|
||||||
"progress.build-module-tree": "構建模塊樹",
|
"progress.build-module-tree": "構建模塊樹",
|
||||||
"progress.download-digital-lsp": "Download Digital LSP",
|
"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": "保存文件失敗",
|
"fail.save-file": "保存文件失敗",
|
||||||
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
"click.join-qq-group": "点击链接加入QQ群一起讨论"
|
||||||
}
|
}
|
@ -12,7 +12,6 @@ import * as lspClient from './function/lsp-client';
|
|||||||
import { refreshArchTree } from './function/treeView';
|
import { refreshArchTree } from './function/treeView';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function registerCommand(context: vscode.ExtensionContext) {
|
async function registerCommand(context: vscode.ExtensionContext) {
|
||||||
func.registerFunctionCommands(context);
|
func.registerFunctionCommands(context);
|
||||||
func.registerLsp(context);
|
func.registerLsp(context);
|
||||||
@ -44,7 +43,6 @@ async function launch(context: vscode.ExtensionContext) {
|
|||||||
title: t('progress.register-command')
|
title: t('progress.register-command')
|
||||||
}, async () => {
|
}, async () => {
|
||||||
await registerCommand(context);
|
await registerCommand(context);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await lspClient.activate(context, versionString);
|
await lspClient.activate(context, versionString);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { performance } from 'perf_hooks';
|
||||||
|
|
||||||
enum IPlatformSignature {
|
enum IPlatformSignature {
|
||||||
x86Windows = 'windows_amd64',
|
x86Windows = 'windows_amd64',
|
||||||
@ -50,4 +51,59 @@ export function getGithubDownloadLink(signature: string, version: string): strin
|
|||||||
|
|
||||||
export function getGiteeDownloadLink(signature: string, version: string): string {
|
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`;
|
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 vscode from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as zlib from 'zlib';
|
||||||
|
import * as tar from 'tar';
|
||||||
import { platform } from "os";
|
import { platform } from "os";
|
||||||
import { IProgress, LspClient } from '../../global';
|
import { IProgress, LspClient } from '../../global';
|
||||||
import axios, { AxiosResponse } from "axios";
|
import axios, { AxiosResponse } from "axios";
|
||||||
import { getGiteeDownloadLink, getPlatformPlatformSignature } from "./cdn";
|
import { chooseBestDownloadSource, getGiteeDownloadLink, getGithubDownloadLink, getPlatformPlatformSignature } from "./cdn";
|
||||||
|
import { hdlDir } from "../../hdlFs";
|
||||||
|
|
||||||
function getLspServerExecutionName() {
|
function getLspServerExecutionName() {
|
||||||
const osname = platform();
|
const osname = platform();
|
||||||
@ -23,9 +25,54 @@ function getLspServerExecutionName() {
|
|||||||
return 'digital-lsp';
|
return 'digital-lsp';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkAndDownload(context: vscode.ExtensionContext, version: string): boolean {
|
function extractTarGz(filePath: string, outputDir: string): Promise<void> {
|
||||||
const { t } = vscode.l10n;
|
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(
|
const versionFolderPath = context.asAbsolutePath(
|
||||||
path.join('resources', 'dide-lsp', 'server', version)
|
path.join('resources', 'dide-lsp', 'server', version)
|
||||||
);
|
);
|
||||||
@ -35,41 +82,53 @@ async function checkAndDownload(context: vscode.ExtensionContext, version: strin
|
|||||||
return true;
|
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,
|
location: vscode.ProgressLocation.Notification,
|
||||||
title: t('progress.download-digital-lsp')
|
title: t('progress.download-digital-lsp')
|
||||||
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||||
progress.report({ increment: 0 });
|
progress.report({ increment: 0 });
|
||||||
const signature = getPlatformPlatformSignature().toString();
|
|
||||||
const downloadLink = getGiteeDownloadLink(signature, version);
|
|
||||||
const response = await axios.get(downloadLink, { responseType: 'stream' });
|
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> {
|
await vscode.window.withProgress({
|
||||||
const totalLength = response.headers['content-length'];
|
location: vscode.ProgressLocation.Notification,
|
||||||
const totalSize = parseInt(totalLength);
|
title: t('progress.extract-digital-lsp')
|
||||||
let downloadSize = 0;
|
}, async (progress: vscode.Progress<IProgress>, token: vscode.CancellationToken) => {
|
||||||
const savePath = context.asAbsolutePath(
|
if (fs.existsSync(tarGzFilePath)) {
|
||||||
path.join('resources', 'dide-lsp', 'server', 'tmp.tar.gz')
|
console.log('check finish, begin to extract');
|
||||||
);
|
await extractTarGz(tarGzFilePath, versionFolderPath);
|
||||||
const fileStream = fs.createWriteStream(savePath);
|
} else {
|
||||||
|
vscode.window.showErrorMessage(t('error.download-digital-lsp') + version);
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -77,10 +136,9 @@ async function checkAndDownload(context: vscode.ExtensionContext, version: strin
|
|||||||
export async function activate(context: vscode.ExtensionContext, version: string) {
|
export async function activate(context: vscode.ExtensionContext, version: string) {
|
||||||
await checkAndDownload(context, version);
|
await checkAndDownload(context, version);
|
||||||
|
|
||||||
|
|
||||||
const lspServerName = getLspServerExecutionName();
|
const lspServerName = getLspServerExecutionName();
|
||||||
const lspServerPath = context.asAbsolutePath(
|
const lspServerPath = context.asAbsolutePath(
|
||||||
path.join('resources', 'dide-lsp', 'server', lspServerName)
|
path.join('resources', 'dide-lsp', 'server', version, lspServerName)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fs.existsSync(lspServerPath)) {
|
if (fs.existsSync(lspServerPath)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user