mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-22 03:03:56 +00:00
fix(installer): address standalone review feedback
This commit is contained in:
parent
40ac124927
commit
bae933332e
6 changed files with 169 additions and 27 deletions
|
|
@ -241,7 +241,7 @@ if /i "!METHOD!"=="standalone" (
|
|||
call :InstallStandalone
|
||||
if !ERRORLEVEL! NEQ 0 exit /b !ERRORLEVEL!
|
||||
call :PrintFinalInstructions "!INSTALL_BIN_DIR!"
|
||||
endlocal & set "PATH=!INSTALL_BIN_DIR!;%PATH%"
|
||||
endlocal & set "PATH=%INSTALL_BIN_DIR%;%PATH%"
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ call :InstallStandalone
|
|||
set "STANDALONE_STATUS=!ERRORLEVEL!"
|
||||
if !STANDALONE_STATUS! EQU 0 (
|
||||
call :PrintFinalInstructions "!INSTALL_BIN_DIR!"
|
||||
endlocal & set "PATH=!INSTALL_BIN_DIR!;%PATH%"
|
||||
endlocal & set "PATH=%INSTALL_BIN_DIR%;%PATH%"
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
|
|
@ -906,6 +906,12 @@ if !ERRORLEVEL! NEQ 0 (
|
|||
exit /b 1
|
||||
)
|
||||
|
||||
call :RestoreStaleInstallBackup
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
if exist "!TEMP_DIR!" rmdir /S /Q "!TEMP_DIR!" >nul 2>&1
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if exist "!NEW_INSTALL_DIR!" (
|
||||
rmdir /S /Q "!NEW_INSTALL_DIR!" >nul 2>&1
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
|
|
@ -918,7 +924,7 @@ if exist "!OLD_INSTALL_DIR!" (
|
|||
rmdir /S /Q "!OLD_INSTALL_DIR!" >nul 2>&1
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
if exist "!TEMP_DIR!" rmdir /S /Q "!TEMP_DIR!" >nul 2>&1
|
||||
echo ERROR: Failed to remove stale backup directory: !OLD_INSTALL_DIR!.
|
||||
echo ERROR: Failed to remove stale install backup: !OLD_INSTALL_DIR!.
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
|
@ -1057,6 +1063,18 @@ if !ERRORLEVEL! NEQ 0 (
|
|||
)
|
||||
exit /b 0
|
||||
|
||||
:RestoreStaleInstallBackup
|
||||
if exist "!INSTALL_DIR!" exit /b 0
|
||||
if not exist "!OLD_INSTALL_DIR!" exit /b 0
|
||||
echo WARNING: Found previous install backup without an active install: !OLD_INSTALL_DIR!
|
||||
echo WARNING: Restoring backup to !INSTALL_DIR! before continuing.
|
||||
move /Y "!OLD_INSTALL_DIR!" "!INSTALL_DIR!" >nul
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
echo ERROR: Failed to restore previous install from !OLD_INSTALL_DIR!.
|
||||
exit /b 1
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:RejectArchiveLinks
|
||||
set "QWEN_EXTRACT_DIR=%~1"
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -Command "$item = Get-ChildItem -LiteralPath $env:QWEN_EXTRACT_DIR -Recurse -Force | Where-Object { ($_.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 } | Select-Object -First 1; if ($item) { exit 1 }"
|
||||
|
|
|
|||
|
|
@ -811,6 +811,7 @@ verify_checksum() {
|
|||
|
||||
validate_archive_entry_path() {
|
||||
local entry="$1"
|
||||
entry="${entry//\\//}"
|
||||
|
||||
while [[ "${entry}" == ./* ]]; do
|
||||
entry="${entry#./}"
|
||||
|
|
@ -826,7 +827,7 @@ validate_archive_entry_path() {
|
|||
esac
|
||||
|
||||
case "${entry}" in
|
||||
""|/*|..|../*|*/..|*/../*|*\\*)
|
||||
""|/*|..|../*|*/..|*/../*)
|
||||
log_error "Archive contains unsafe path: ${entry:-<empty>}"
|
||||
return 1
|
||||
;;
|
||||
|
|
@ -923,6 +924,24 @@ ensure_managed_install_dir() {
|
|||
return 1
|
||||
}
|
||||
|
||||
restore_stale_install_backup() {
|
||||
local old_install_dir="$1"
|
||||
local current_install_dir="$2"
|
||||
|
||||
if [[ -e "${current_install_dir}" || ! -e "${old_install_dir}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_warning "Found previous install backup without an active install: ${old_install_dir}"
|
||||
log_warning "Restoring backup to ${current_install_dir} before continuing."
|
||||
if mv "${old_install_dir}" "${current_install_dir}"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_error "Failed to restore previous install from ${old_install_dir}."
|
||||
return 1
|
||||
}
|
||||
|
||||
is_qwen_standalone_install_dir() {
|
||||
local install_dir="$1"
|
||||
local manifest_path="${install_dir}/manifest.json"
|
||||
|
|
@ -1113,7 +1132,18 @@ install_standalone() {
|
|||
rm -rf "${temp_dir}"
|
||||
return 1
|
||||
fi
|
||||
rm -rf "${new_install_dir}" "${old_install_dir}" "${wrapper_tmp}"
|
||||
if ! restore_stale_install_backup "${old_install_dir}" "${INSTALL_LIB_DIR}"; then
|
||||
rm -rf "${temp_dir}"
|
||||
return 1
|
||||
fi
|
||||
if [[ -e "${old_install_dir}" ]]; then
|
||||
rm -rf "${old_install_dir}" || {
|
||||
rm -rf "${temp_dir}"
|
||||
log_error "Failed to remove stale install backup: ${old_install_dir}"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
rm -rf "${new_install_dir}" "${wrapper_tmp}"
|
||||
mv "${extract_dir}/qwen-code" "${new_install_dir}"
|
||||
|
||||
if ! write_unix_wrapper "${wrapper_tmp}" "${INSTALL_LIB_DIR}/bin/qwen"; then
|
||||
|
|
|
|||
|
|
@ -320,9 +320,8 @@ $installDir = Get-QwenInstallDir
|
|||
$installBinDir = Get-QwenInstallBinDir
|
||||
$installWasManaged = Test-QwenStandaloneInstallDir -InstallDir $installDir
|
||||
|
||||
Remove-CurrentCmdPathShim
|
||||
|
||||
if ($installWasManaged) {
|
||||
Remove-CurrentCmdPathShim
|
||||
Remove-Item -LiteralPath $installDir -Recurse -Force
|
||||
Write-Success "Removed $installDir"
|
||||
} elseif (Test-Path -LiteralPath $installDir) {
|
||||
|
|
|
|||
|
|
@ -193,8 +193,14 @@ remove_shell_path_entry() {
|
|||
}
|
||||
|
||||
awk -v marker="${marker}" '
|
||||
$0 == marker { skip_next = 1; next }
|
||||
skip_next == 1 { skip_next = 0; next }
|
||||
index($0, marker) { check_next = 1; next }
|
||||
check_next == 1 {
|
||||
check_next = 0
|
||||
if ($0 ~ /^[[:space:]]*export PATH=/ ||
|
||||
$0 ~ /^[[:space:]]*set -gx PATH /) {
|
||||
next
|
||||
}
|
||||
}
|
||||
{ print }
|
||||
' "${rc_file}" > "${temp_file}" && mv "${temp_file}" "${rc_file}" || {
|
||||
rm -f "${temp_file}"
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ describe('installation scripts', () => {
|
|||
expect(script).toContain('/latest/VERSION');
|
||||
expect(script).toContain('resolve_aliyun_version_path()');
|
||||
expect(script).toContain('retrying GitHub mirror');
|
||||
expect(script).toContain('entry="${entry//\\\\//}"');
|
||||
expect(script).toContain('restore_stale_install_backup()');
|
||||
expect(script).toContain(
|
||||
'restore_stale_install_backup "${old_install_dir}" "${INSTALL_LIB_DIR}"',
|
||||
);
|
||||
expect(script).not.toContain(
|
||||
'rm -rf "${new_install_dir}" "${old_install_dir}" "${wrapper_tmp}"',
|
||||
);
|
||||
expect(script).not.toContain('-print -quit');
|
||||
});
|
||||
|
||||
|
|
@ -252,6 +260,15 @@ describe('installation scripts', () => {
|
|||
expect(script).toContain(':ResolveAliyunVersionPath');
|
||||
expect(script).toContain(':UseGithubFallbackBaseUrl');
|
||||
expect(script).toContain('retrying GitHub mirror');
|
||||
expect(script).toContain('endlocal & set "PATH=%INSTALL_BIN_DIR%;%PATH%"');
|
||||
expect(script).not.toContain(
|
||||
'endlocal & set "PATH=!INSTALL_BIN_DIR!;%PATH%"',
|
||||
);
|
||||
expect(script).toContain(':RestoreStaleInstallBackup');
|
||||
expect(script).toContain('call :RestoreStaleInstallBackup');
|
||||
expect(script).not.toContain(
|
||||
'ERROR: Failed to remove stale backup directory',
|
||||
);
|
||||
expect(script).not.toContain('%RANDOM%');
|
||||
});
|
||||
|
||||
|
|
@ -1341,6 +1358,14 @@ describe('standalone release packaging', () => {
|
|||
expect(workflow.slice(publishLatestStepIndex)).toContain(
|
||||
'releases/qwen-code/latest/VERSION',
|
||||
);
|
||||
const syncStep = workflow.slice(syncStepIndex, verifyStepIndex);
|
||||
expect(syncStep).toContain('IS_STABLE_RELEASE');
|
||||
expect(syncStep).toContain(
|
||||
'if [[ "${IS_STABLE_RELEASE}" == "true" ]]; then',
|
||||
);
|
||||
expect(syncStep).toContain(
|
||||
'Skipping hosted installation asset upload for prerelease',
|
||||
);
|
||||
expect(workflow).toContain('installation/install-qwen-standalone.sh');
|
||||
expect(workflow).toContain('installation/install-qwen-standalone.bat');
|
||||
expect(workflow).toContain('installation/install-qwen-standalone.ps1');
|
||||
|
|
@ -1356,6 +1381,14 @@ describe('standalone release packaging', () => {
|
|||
expect(workflow).not.toContain(
|
||||
'npm run verify:installation-release -- --base-url "${ALIYUN_OSS_PUBLIC_BASE_URL}/releases/qwen-code/latest"',
|
||||
);
|
||||
const verifyStep = workflow.slice(verifyStepIndex, publishLatestStepIndex);
|
||||
expect(verifyStep).toContain('IS_STABLE_RELEASE');
|
||||
expect(verifyStep).toContain(
|
||||
'if [[ "${IS_STABLE_RELEASE}" == "true" ]]; then',
|
||||
);
|
||||
expect(verifyStep).toContain(
|
||||
'Skipping hosted installation asset verification for prerelease',
|
||||
);
|
||||
expect(workflow).toContain('hosted_tmp_dir="$(mktemp -d)"');
|
||||
expect(workflow).toContain(
|
||||
'cmp -s "dist/installation/SHA256SUMS" "${hosted_tmp_dir}/SHA256SUMS"',
|
||||
|
|
@ -1421,6 +1454,12 @@ describe('standalone release packaging', () => {
|
|||
);
|
||||
expect(uninstallPowerShellSource).toContain('QWEN_UNINSTALL_PURGE');
|
||||
expect(uninstallPowerShellSource).toContain('Preserving');
|
||||
expect(uninstallPowerShellSource).toMatch(
|
||||
/if \(\$installWasManaged\) \{\n\s+Remove-CurrentCmdPathShim\n\s+Remove-Item/,
|
||||
);
|
||||
expect(uninstallPowerShellSource).not.toMatch(
|
||||
/\$installWasManaged = Test-QwenStandaloneInstallDir[^\n]*\n\nRemove-CurrentCmdPathShim\n\nif \(\$installWasManaged\)/,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1748,6 +1787,46 @@ describe('Linux/macOS installer end-to-end', () => {
|
|||
}
|
||||
});
|
||||
|
||||
itOnUnix(
|
||||
'removes only installer-owned shell rc PATH lines during uninstall',
|
||||
() => {
|
||||
const createdDist = ensureMinimalDist();
|
||||
const tmpDir = mkdtempSync(path.join(tmpdir(), 'qwen-uninstall-test-'));
|
||||
|
||||
try {
|
||||
const archive = packageFakeStandalone(tmpDir);
|
||||
const installRoot = path.join(tmpDir, 'install');
|
||||
const home = path.join(tmpDir, 'home');
|
||||
runUnixInstaller(archive, installRoot, home);
|
||||
|
||||
const rcFile = path.join(home, '.zshrc');
|
||||
writeFileSync(
|
||||
rcFile,
|
||||
[
|
||||
'before',
|
||||
'# Added by qwen-code installer (multi-qwen shadow fix) ',
|
||||
`export PATH='${installRoot}/bin':$PATH`,
|
||||
'middle',
|
||||
'# Added by qwen-code installer (multi-qwen shadow fix)',
|
||||
'echo keep-me',
|
||||
'after',
|
||||
].join('\n') + '\n',
|
||||
);
|
||||
|
||||
runUnixUninstaller(installRoot, home);
|
||||
|
||||
expect(readScript(rcFile)).toBe(
|
||||
['before', 'middle', 'echo keep-me', 'after'].join('\n') + '\n',
|
||||
);
|
||||
} finally {
|
||||
rmSync(tmpDir, { recursive: true, force: true });
|
||||
if (createdDist) {
|
||||
rmSync('dist', { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
itOnUnix('shell-quotes custom install paths in the generated wrapper', () => {
|
||||
const createdDist = ensureMinimalDist();
|
||||
const tmpDir = mkdtempSync(path.join(tmpdir(), 'qwen-install-test-'));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue