forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathServerInstaller.js
More file actions
1 lines (1 loc) · 8.35 KB
/
Copy pathServerInstaller.js
File metadata and controls
1 lines (1 loc) · 8.35 KB
1
define(function(require,exports,module){const NodeUtils=brackets.getModule("utils/NodeUtils"),NotificationUI=brackets.getModule("widgets/NotificationUI"),TaskManager=brackets.getModule("features/TaskManager"),PreferencesManager=brackets.getModule("preferences/PreferencesManager"),Metrics=brackets.getModule("utils/Metrics"),StringUtils=brackets.getModule("utils/StringUtils"),Strings=brackets.getModule("strings"),_PINS=brackets.config&&brackets.config.lsp_server_pins||{};_PINS.pyrefly&&_PINS.ruff||window.alert("[PythonSupport] lsp_server_pins missing from AppConfig - stale build? Run npm run build.");const PYREFLY_VERSION=_PINS.pyrefly||"1.1.1",RUFF_VERSION=_PINS.ruff||"0.15.20",PREF_PYTHON_CODE_INTELLIGENCE="codeIntelligence.python",UNITS={pyrefly:{pkg:"pyrefly",version:PYREFLY_VERSION},ruff:{pkg:"ruff",version:RUFF_VERSION}};let _onInstalled=null,_inFlight=null,_cancelledThisSession=!1,_cancelRequested=!1,_activeDownload=null,_onlineRetryArmed=!1;function _installDirVfs(unit){return Phoenix.VFS.getAppSupportDir()+"lspServers/"+unit.pkg+"/"}function _binaryRelPath(unit){const exe="win"===brackets.platform?".exe":"";return unit.pkg+"-"+unit.version+".data/scripts/"+unit.pkg+exe}function _binaryVfs(unit){return _installDirVfs(unit)+_binaryRelPath(unit)}function _markerVfs(unit){return _installDirVfs(unit)+"installed.json"}function _binaryPlatformPath(unit){return Phoenix.fs.getTauriPlatformPath(_binaryVfs(unit))}function getBinaryPlatformPath(){return _binaryPlatformPath(UNITS.pyrefly)}function getRuffBinaryPlatformPath(){return _binaryPlatformPath(UNITS.ruff)}async function _unitState(unit){const binExists=await Phoenix.VFS.existsAsync(_binaryVfs(unit));if(binExists)try{const marker=JSON.parse(await Phoenix.VFS.readFileAsync(_markerVfs(unit),"utf8"));return{installed:!0,pinMatches:marker.version===unit.version}}catch(e){return{installed:!0,pinMatches:!1}}const markerExists=await Phoenix.VFS.existsAsync(_markerVfs(unit));return{installed:markerExists,pinMatches:!1}}async function installedState(){const pyrefly=await _unitState(UNITS.pyrefly),ruff=await _unitState(UNITS.ruff);return{installed:pyrefly.installed,pinMatches:pyrefly.pinMatches&&ruff.installed&&ruff.pinMatches}}async function _wheelTag(){const platform=brackets.platform,arch=String(await Phoenix.app.getPlatformArch()||"").toLowerCase(),isX64="x86_64"===arch||"x64"===arch||"amd64"===arch,isArm64="aarch64"===arch||"arm64"===arch;if("win"===platform){if(isX64)return"win_amd64";if(isArm64)return"win_arm64"}else if("mac"===platform){if(isArm64)return"macosx_11_0_arm64";if(isX64)return"macosx_10_12_x86_64"}else if("linux"===platform){if(isX64)return"manylinux_2_17_x86_64.manylinux2014_x86_64";if(isArm64)return"manylinux_2_17_aarch64.manylinux2014_aarch64"}throw new Error("no "+Object.keys(UNITS).join("/")+" build for "+platform+"/"+arch)}async function _resolveWheel(unit,tag){const metaUrl="https://pypi.org/pypi/"+unit.pkg+"/"+unit.version+"/json",response=await fetch(metaUrl);if(!response.ok)throw new Error("PyPI metadata fetch failed with HTTP "+response.status);const meta=await response.json(),wheel=(meta.urls||[]).find(function(u){return u.filename&&u.filename.endsWith(".whl")&&-1!==u.filename.indexOf(tag)});if(!wheel)throw new Error("no "+unit.pkg+" "+unit.version+" wheel for "+tag);return{url:wheel.url,sha256:wheel.digests&&wheel.digests.sha256}}const NETWORK_ERROR_RE=new RegExp("failed to fetch|fetch failed|load failed|ENOTFOUND|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|ENETUNREACH|getaddrinfo|network","i");function _isNetworkError(err){return NETWORK_ERROR_RE.test(err&&err.message||String(err))}function _armOnlineRetry(){_onlineRetryArmed||(_onlineRetryArmed=!0,window.addEventListener("online",function(){_onlineRetryArmed=!1,autoInstall()},{once:!0}))}function _showFailureToast(message){const $tpl=$("<div>").text(message);NotificationUI.createToastFromTemplate(Strings.PYTHON_INSTALL_TITLE,$tpl,{dismissOnClick:!0,toastStyle:NotificationUI.NOTIFICATION_STYLES_CSS_CLASS.SUBTLE,autoCloseTimeS:30,instantOpen:!0})}async function _installUnit(unit,tag,task,pctFrom,pctTo){const wheel=await _resolveWheel(unit,tag);if(_cancelRequested){const cancelErr=new Error("install cancelled");throw cancelErr.cancelled=!0,cancelErr}await Phoenix.VFS.unlinkAsync(_installDirVfs(unit)).catch(function(){});const destDir=Phoenix.fs.getTauriPlatformPath(_installDirVfs(unit)),wheelFile=Phoenix.fs.getTauriPlatformPath(_installDirVfs(unit)+"download.whl"),downloadShare=.85*(pctTo-pctFrom);_activeDownload=NodeUtils.downloadFile(wheel.url,wheelFile,{sha256:wheel.sha256,progress:function(transferred,total){total>0&&task.setProgressPercent(Math.round(pctFrom+transferred/total*downloadShare))}});try{await _activeDownload}finally{_activeDownload=null}await NodeUtils.extractZipFile(wheelFile,destDir),await NodeUtils.setExecutableBits(_binaryPlatformPath(unit)),await Phoenix.VFS.unlinkAsync(_installDirVfs(unit)+"download.whl").catch(function(){});const ok=await Phoenix.VFS.existsAsync(_binaryVfs(unit));if(!ok)throw new Error(unit.pkg+" binary missing after wheel extraction");await Phoenix.VFS.writeFileAsync(_markerVfs(unit),JSON.stringify({version:unit.version},null,4),"utf8"),task.setProgressPercent(pctTo)}async function _doInstall(){const state=await installedState();if(state.installed&&state.pinMatches)return{binaryPath:getBinaryPlatformPath(),upgraded:!1};const upgrading=state.installed;_cancelRequested=!1;let currentUnit=null;const task=TaskManager.addNewTask(Strings.PYTHON_INSTALL_TITLE,Strings.PYTHON_INSTALLING,"<i class='fa-brands fa-python'></i>",{progressPercent:2,onStopClick:function(){_cancelledThisSession=!0,_cancelRequested=!0,_activeDownload&&_activeDownload.cancel().catch(function(){})},onRetryClick:function(){task.close(),installNow()}});task.showStopIcon(Strings.PYTHON_INSTALL_STOP),task.show();try{const tag=await _wheelTag(),pending=[];for(const key of Object.keys(UNITS)){const unitState=await _unitState(UNITS[key]);unitState.installed&&unitState.pinMatches||pending.push(UNITS[key])}task.setProgressPercent(5);const span=90/(pending.length||1);for(let i=0;i<pending.length;i++)currentUnit=pending[i],await _installUnit(pending[i],tag,task,Math.round(5+i*span),Math.round(5+(i+1)*span));return currentUnit=null,task.setProgressPercent(100),task.setMessage(Strings.PYTHON_INSTALL_DONE),task.setSucceeded(),setTimeout(task.close,4e3),Metrics.countEvent("lsp","pyInst",upgrading?"upOk":"ok"),{binaryPath:getBinaryPlatformPath(),upgraded:upgrading}}catch(err){const message=err&&err.message||String(err);currentUnit&&await Phoenix.VFS.unlinkAsync(_installDirVfs(currentUnit)).catch(function(){});const cancelled=_cancelRequested||err&&err.cancelled||/cancelled/i.test(message);return cancelled?(Metrics.countEvent("lsp","pyInst","cancel"),task.close(),null):_isNetworkError(err)||!navigator.onLine?(Metrics.countEvent("lsp","pyInst","waitNet"),task.setMessage(Strings.PYTHON_INSTALL_WAITING_NETWORK),setTimeout(task.close,4e3),_armOnlineRetry(),null):(console.error("[PythonSupport] install failed",err),Metrics.countEvent("lsp","pyInst","fail"),window.logger&&window.logger.reportError(err,"[PythonSupport] LSP install failed"),task.setFailed(),task.setMessage(StringUtils.format(Strings.PYTHON_INSTALL_FAILED,message)),task.showRestartIcon(),task.show(),_showFailureToast(StringUtils.format(Strings.PYTHON_INSTALL_FAILED,message)),setTimeout(task.close,3e4),null)}finally{_activeDownload=null}}function installNow(){return _inFlight||(_inFlight=_doInstall().then(function(result){return result&&_onInstalled&&_onInstalled(result),result}).finally(function(){_inFlight=null}))}function autoInstall(){return"undefined"!=typeof Phoenix&&Phoenix.isTestWindow?Promise.resolve(null):_cancelledThisSession||!1===PreferencesManager.get(PREF_PYTHON_CODE_INTELLIGENCE)?Promise.resolve(null):navigator.onLine?installNow():(_armOnlineRetry(),Promise.resolve(null))}async function repairInstall(){for(const key of Object.keys(UNITS))await Phoenix.VFS.unlinkAsync(_installDirVfs(UNITS[key])).catch(function(){});return installNow()}function init(options){_onInstalled=options&&options.onInstalled||null}exports.init=init,exports.installedState=installedState,exports.installNow=installNow,exports.autoInstall=autoInstall,exports.repairInstall=repairInstall,exports.getBinaryPlatformPath=getBinaryPlatformPath,exports.getRuffBinaryPlatformPath=getRuffBinaryPlatformPath,exports.PYREFLY_VERSION=PYREFLY_VERSION,exports.RUFF_VERSION=RUFF_VERSION,exports.PREF_PYTHON_CODE_INTELLIGENCE=PREF_PYTHON_CODE_INTELLIGENCE});