feat(update-center): 统一使用下载包文件进行安装

- 移除 buildLegacySparkUpgradeCommand,所有更新现在需要先下载 deb 包
- 为 APTSS 添加元数据查询功能
- 优化 aria2c 下载参数,使用 metalink URL
- 版本号更新至 5.0.0beta4
This commit is contained in:
2026-04-12 16:44:55 +08:00
parent fa2689c753
commit 6fcfa438d9
4 changed files with 114 additions and 74 deletions

View File

@@ -33,13 +33,22 @@ export const runAria2Download = async ({
const filePath = join(downloadDir, item.fileName); const filePath = join(downloadDir, item.fileName);
// Use .metalink URL for download (same as Qt version)
const metalinkUrl = `${item.downloadUrl}.metalink`;
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
const child = spawn("aria2c", [ const child = spawn("aria2c", [
"--dir", "--dir",
downloadDir, downloadDir,
"--out", "--out",
item.fileName, item.fileName,
item.downloadUrl, "--enable-rpc=false",
"--console-log-level=warn",
"--summary-interval=1",
"--allow-overwrite=true",
"--connect-timeout=30",
"--max-tries=3",
metalinkUrl,
]); ]);
const abortDownload = () => { const abortDownload = () => {

View File

@@ -66,6 +66,14 @@ const getApmPrintUrisCommand = (pkgname: string) => ({
], ],
}); });
const getAptssPrintUrisCommand = (pkgname: string) => ({
command: "bash",
args: [
"-lc",
`/usr/bin/apt download ${pkgname} --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf -o Dir::Etc::sourcelist=/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list -o Dir::Etc::sourceparts=/dev/null`,
],
});
const runCommandCapture: UpdateCenterCommandRunner = async ( const runCommandCapture: UpdateCenterCommandRunner = async (
command, command,
args, args,
@@ -140,6 +148,42 @@ const loadApmItemMetadata = async (
}; };
}; };
const loadAptssItemMetadata = async (
item: UpdateCenterItem,
runCommand: UpdateCenterCommandRunner,
): Promise<
| { item: UpdateCenterItem; warning?: undefined }
| { item: null; warning: string }
> => {
const printUrisCommand = getAptssPrintUrisCommand(item.pkgname);
const metadataResult = await runCommand(
printUrisCommand.command,
printUrisCommand.args,
);
const commandError = getCommandError(
`aptss metadata query for ${item.pkgname}`,
metadataResult,
);
if (commandError) {
return { item: null, warning: commandError };
}
const metadata = parsePrintUrisOutput(metadataResult.stdout);
if (!metadata) {
return {
item: null,
warning: `aptss metadata query for ${item.pkgname} returned no package metadata`,
};
}
return {
item: {
...item,
...metadata,
},
};
};
const enrichApmItems = async ( const enrichApmItems = async (
items: UpdateCenterItem[], items: UpdateCenterItem[],
runCommand: UpdateCenterCommandRunner, runCommand: UpdateCenterCommandRunner,
@@ -156,6 +200,22 @@ const enrichApmItems = async (
}; };
}; };
const enrichAptssItems = async (
items: UpdateCenterItem[],
runCommand: UpdateCenterCommandRunner,
): Promise<UpdateCenterLoadItemsResult> => {
const results = await Promise.all(
items.map((item) => loadAptssItemMetadata(item, runCommand)),
);
return {
items: results.flatMap((result) => (result.item ? [result.item] : [])),
warnings: results.flatMap((result) =>
result.warning ? [result.warning] : [],
),
};
};
const getStoreArch = ( const getStoreArch = (
item: Pick<UpdateCenterItem, "source" | "arch">, item: Pick<UpdateCenterItem, "source" | "arch">,
): string => { ): string => {
@@ -299,18 +359,22 @@ export const loadUpdateCenterItems = async (
enrichItemCategories(aptssItems), enrichItemCategories(aptssItems),
enrichItemCategories(apmItems), enrichItemCategories(apmItems),
]); ]);
const enrichedApmItems = await enrichApmItems( const [enrichedAptssItems, enrichedApmItems] = await Promise.all([
categorizedApmItems, enrichAptssItems(categorizedAptssItems, runCommand),
runCommand, enrichApmItems(categorizedApmItems, runCommand),
); ]);
return { return {
items: mergeUpdateSources( items: mergeUpdateSources(
enrichItemIcons(categorizedAptssItems), enrichItemIcons(enrichedAptssItems.items),
enrichItemIcons(enrichedApmItems.items), enrichItemIcons(enrichedApmItems.items),
installedSources, installedSources,
), ),
warnings: [...warnings, ...enrichedApmItems.warnings], warnings: [
...warnings,
...enrichedAptssItems.warnings,
...enrichedApmItems.warnings,
],
}; };
}; };

View File

@@ -119,29 +119,8 @@ const buildPrivilegedCommand = (
}; };
}; };
export const buildLegacySparkUpgradeCommand = ( // Removed buildLegacySparkUpgradeCommand - all updates now require downloading the deb package first
pkgname: string, // to avoid aptss install popup. Use ssinstall with downloaded deb file instead.
superUserCmd = "",
): UpdateCommand => {
if (superUserCmd) {
return {
execCommand: superUserCmd,
execParams: [
SHELL_CALLER_PATH,
"aptss",
"install",
"-y",
pkgname,
"--only-upgrade",
],
};
}
return {
execCommand: SHELL_CALLER_PATH,
execParams: ["aptss", "install", "-y", pkgname, "--only-upgrade"],
};
};
export const installUpdateItem = async ({ export const installUpdateItem = async ({
item, item,
@@ -150,11 +129,13 @@ export const installUpdateItem = async ({
onLog, onLog,
signal, signal,
}: InstallUpdateItemOptions): Promise<void> => { }: InstallUpdateItemOptions): Promise<void> => {
if (item.source === "apm" && !filePath) { if (!filePath) {
throw new Error("APM update task requires downloaded package metadata"); throw new Error(
`Update task for ${item.pkgname} requires downloaded package file`,
);
} }
if (item.source === "apm" && filePath) { if (item.source === "apm") {
const installCommand = buildPrivilegedCommand( const installCommand = buildPrivilegedCommand(
SHELL_CALLER_PATH, SHELL_CALLER_PATH,
["apm", "ssinstall", filePath], ["apm", "ssinstall", filePath],
@@ -169,26 +150,18 @@ export const installUpdateItem = async ({
return; return;
} }
if (filePath) { // APTSS (Spark Store) packages use ssinstall
const installCommand = buildPrivilegedCommand( const installCommand = buildPrivilegedCommand(
SSINSTALL_PATH, SSINSTALL_PATH,
[filePath, "--delete-after-install"], [filePath, "--delete-after-install", "--no-create-desktop-entry", "--native"],
superUserCmd, superUserCmd,
); );
await runCommand( await runCommand(
installCommand.execCommand, installCommand.execCommand,
installCommand.execParams, installCommand.execParams,
onLog, onLog,
signal, signal,
);
return;
}
const command = buildLegacySparkUpgradeCommand(
item.pkgname,
superUserCmd ?? "",
); );
await runCommand(command.execCommand, command.execParams, onLog, signal);
}; };
export const createTaskRunner = ( export const createTaskRunner = (
@@ -246,30 +219,24 @@ export const createTaskRunner = (
}; };
try { try {
let filePath: string | undefined; // All updates require download metadata
if (!task.item.downloadUrl || !task.item.fileName) {
if (
task.item.source === "apm" &&
(!task.item.downloadUrl || !task.item.fileName)
) {
throw new Error( throw new Error(
"APM update task requires downloaded package metadata", `Update task for ${task.item.pkgname} requires download metadata (URL and filename)`,
); );
} }
if (task.item.downloadUrl && task.item.fileName) { queue.markActiveTask(task.id, "downloading");
queue.markActiveTask(task.id, "downloading"); const result = await runDownload({
const result = await runDownload({ item: task.item,
item: task.item, task,
task, onLog,
onLog, signal: activeAbortController.signal,
signal: activeAbortController.signal, onProgress: (progress) => {
onProgress: (progress) => { queue.updateTaskProgress(task.id, progress);
queue.updateTaskProgress(task.id, progress); },
}, });
}); const filePath = result.filePath;
filePath = result.filePath;
}
queue.markActiveTask(task.id, "installing"); queue.markActiveTask(task.id, "installing");
await installItem({ await installItem({

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "spark-store", "name": "spark-store",
"version": "5.0.0beta3", "version": "5.0.0beta4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "spark-store", "name": "spark-store",
"version": "5.0.0beta3", "version": "5.0.0beta4",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",