1/* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16const fs = require('fs'); 17const path = require('path'); 18const { JSDOM } = require('jsdom'); 19const os = require('os'); 20const unzipper = require('unzipper'); 21const { 22 clearDir, deleteDir, existDir, mkdir, moveDir, readDir, renameDir, isExistFile, copyFile 23} = require('../utils/file.js'); 24const http = require("http"); 25 26module.exports = { prepareHostEnv }; 27 28async function getPullsNumberComments(url) { 29 const response = await fetch(url); 30 if (response.ok) { 31 const data = await response.json(); 32 for (let i = 0; i < data.length; i++) { 33 if (data[i].body.includes("代码门禁通过")) { 34 const dom = new JSDOM(data[i].body); 35 const document = dom.window.document; 36 const anchors = document.getElementsByTagName('a'); 37 for (let j = 0; j < anchors.length; j++) { 38 const anchor = anchors[j]; 39 const hrefValue = anchor.href; 40 if (hrefValue.includes("ohos-sdk") && hrefValue.includes(".zip")) { 41 return { status: response.status, data, hrefValue }; 42 } 43 } 44 } 45 } 46 } else { 47 throw new Error(`HTTP状态码${response.status},请求URL为${url}`); 48 } 49 return null; 50} 51 52async function downloadFile(url, destinationPath) { 53 return new Promise(async (resolve, reject) => { 54 const fileStream = fs.createWriteStream(destinationPath); 55 const request = await http.get(url, (response) => { 56 if (response.statusCode === 404) { 57 console.error("当前PR地址已失效,请更换可用的PR地址后重试"); 58 reject(false); 59 return; 60 } 61 if (response.statusCode !== 200) { 62 console.error("下载失败"); 63 reject(false); 64 return; 65 } 66 response.pipe(fileStream); 67 fileStream.on('finish', () => { 68 fileStream.close(() => resolve(true)); 69 }); 70 fileStream.on('error', (error) => { 71 console.error("下载文件错误", error); 72 reject(false); 73 }); 74 }); 75 request.on('error', (error) => { 76 console.error("请求出错", error); 77 reject(false); 78 }); 79 }); 80} 81 82async function extractLargeZip(zipFilePath, outputDir) { 83 return new Promise((resolve, reject) => { 84 const readStream = fs.createReadStream(zipFilePath); 85 readStream.pipe(unzipper.Parse()) 86 .on('entry', (entry) => { 87 const fileName = entry.path; 88 const type = entry.type; 89 90 if (type === 'File') { 91 const outputPath = path.join(outputDir, fileName); 92 entry.pipe(fs.createWriteStream(outputPath)); 93 } else if (type === 'Directory') { 94 fs.mkdirSync(path.join(outputDir, fileName), { recursive: true }); 95 entry.autodrain(); 96 } 97 }) 98 .on('error', (error) => { 99 throw error; 100 }) 101 .on('close', () => { 102 resolve(); 103 }); 104 }); 105} 106 107function judgePlatform() { 108 return os.platform() === 'win32'; 109} 110 111async function extractZipFile(zipFilePath, outputDirectory) { 112 try { 113 await new Promise((resolve, reject) => { 114 fs.createReadStream(zipFilePath) 115 .pipe(unzipper.Extract({ path: outputDirectory })) 116 .on('error', reject) 117 .on('finish', () => { 118 resolve(); 119 }); 120 }); 121 } catch (err) { 122 throw err; 123 } 124 if (!fs.existsSync(outputDirectory)) { 125 fs.mkdirSync(outputDirectory, { recursive: true }); 126 } 127} 128 129async function downloadSdk(url, downloadPath) { 130 return new Promise(async (resolve, reject) => { 131 try { 132 const pullsNumberCommentsResponse = await getPullsNumberComments(url); 133 if (pullsNumberCommentsResponse !== null && pullsNumberCommentsResponse.hrefValue !== "") { 134 await downloadFile(pullsNumberCommentsResponse.hrefValue, 135 path.join(downloadPath, "ohos-sdk.zip")).then((res, rej) => { 136 if (res) { 137 resolve(true); 138 } else { 139 reject(false); 140 } 141 }) 142 } else { 143 console.error("暂无可用sdk"); 144 reject(false); 145 } 146 } catch (error) { 147 console.error("下载过程中发生错误"); 148 reject(false); 149 } 150 }); 151} 152 153async function prepareHostEnv(url, downloadPath, sdkPath) { 154 try { 155 let ohosSdkPath; 156 let etsPath = path.join(sdkPath, "ets\\api"); 157 const existSdk = await existDir(downloadPath); 158 if (existSdk) { 159 await clearDir(downloadPath); 160 } else { 161 await mkdir(downloadPath); 162 } 163 164 const existSdkPath = await existDir(sdkPath); 165 const existBackUpSdkPath = await existDir(`${sdkPath}-backup`); 166 if (existBackUpSdkPath) { 167 await deleteDir(`${sdkPath}-backup`); 168 } 169 if (existSdkPath) { 170 await renameDir(sdkPath, `${sdkPath}-backup`); 171 await mkdir(sdkPath); 172 } else { 173 await mkdir(sdkPath); 174 } 175 await downloadSdk(url, downloadPath); 176 await extractLargeZip(path.join(downloadPath, "ohos-sdk.zip"), downloadPath); 177 178 if (judgePlatform) { 179 ohosSdkPath = path.join(downloadPath, 'windows'); 180 } else { 181 ohosSdkPath = path.join(downloadPath, 'linux'); 182 } 183 184 let zipFiles = await readDir(ohosSdkPath); 185 for (let i = 0; i < zipFiles.length; i++) { 186 await extractZipFile(zipFiles[i], ohosSdkPath); 187 } 188 189 let sdks = await readDir(ohosSdkPath); 190 for (let i = 0; i < sdks.length; i++) { 191 if (sdks[i].includes(".zip") !== true) { 192 await moveDir(sdks[i], sdkPath); 193 } 194 } 195 let etsFile = path.join(etsPath, "@ohos.arkui.componentTest.d.ts"); 196 if (await isExistFile(etsFile)) { 197 await copyFile("previewer_host\\resource\\componentTest.ts", etsFile) 198 } 199 } catch (error) { 200 console.log("准备环境过程出错,恢复初始状态"); 201 202 if (await isExistFile(downloadPath)) { 203 await clearDir(downloadPath); 204 } 205 206 if (await isExistFile(sdkPath)) { 207 await deleteDir(sdkPath); 208 } 209 210 if (await isExistFile(`${sdkPath}-backup`)) { 211 await renameDir(`${sdkPath}-backup`, sdkPath); 212 } 213 console.log("环境清理完成"); 214 throw error; 215 } 216}